No Description
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

Etage1_LectureInstruction_NS.vhd 15KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  1. ----------------------------------------------------------------------------------
  2. -- Company: INSA-Toulouse
  3. -- Engineer: Paul Faure
  4. --
  5. -- Create Date: 18.04.2021 21:19:41
  6. -- Module Name: Etage1_LectureInstruction_NS - Behavioral
  7. -- Project Name: Processeur sécurisé
  8. -- Target Devices: Basys 3 ARTIX7
  9. -- Tool Versions: Vivado 2016.4
  10. -- Description: Etage 1 du processeur
  11. -- - Gestion des instructions, lecture en mémoire
  12. -- - Gestion des aléas sur les registres
  13. -- - Gestion des sauts et appels de fonction
  14. --
  15. -- Dependencies:
  16. -- - MemoireInstruction
  17. -- - MemoireAdressesRetour
  18. ----------------------------------------------------------------------------------
  19. library IEEE;
  20. use IEEE.STD_LOGIC_1164.ALL;
  21. use IEEE.STD_LOGIC_UNSIGNED.ALL;
  22. use IEEE.NUMERIC_STD.ALL;
  23. entity Etage1_LectureInstruction_NS is
  24. Generic (Instruction_size_in_memory : Natural; -- Taille d'une instruction en mémoire (Taille d'un code instruction + 3*Taille d'un mot binaire)
  25. Addr_size_mem_instruction : Natural; -- Nombre de bits pour adresser la mémoire d'instruction
  26. Mem_instruction_size : Natural; -- Taille de la mémoire d'instruction (nombre d'instructions stockées)
  27. Nb_bits : Natural; -- Taille d'un mot binaire
  28. Instruction_bus_size : Natural; -- Nombre de bits du bus d'instruction (Taille d'un code instruction)
  29. Nb_registres : Natural; -- Nombre de registres du processeurs
  30. Instructions_critiques_lecture_A : STD_LOGIC_VECTOR; -- Vecteur de bit représentant les instruction critiques sur l'opérande A (si le bit i est a un, l'instruction i lit une valeur dans le registre n°opérandeA)
  31. Instructions_critiques_lecture_B : STD_LOGIC_VECTOR; -- Vecteur de bit représentant les instruction critiques sur l'opérande B (si le bit i est a un, l'instruction i lit une valeur dans le registre n°opérandeB)
  32. Instructions_critiques_lecture_C : STD_LOGIC_VECTOR; -- Vecteur de bit représentant les instruction critiques sur l'opérande C (si le bit i est a un, l'instruction i lit une valeur dans le registre n°opérandeC)
  33. Instructions_critiques_ecriture : STD_LOGIC_VECTOR; -- Vecteur de bit représentant les instruction critiques en écriture (toujours sur l'opérande A) (si le bit i est a un, l'instruction i ecrit une valeur dans le registre n°opérandeA)
  34. -- Exemple 1 : Soit MUL i j k avec pour numéro d'instruction 7 avec le comportement Ri <- Rj*Rk
  35. -- Instructions_critiques_lecture_A(7) = '0' --> MUL ne lit pas dans le registre de l'opérande A
  36. -- Instructions_critiques_lecture_B(7) = '1' --> MUL lit dans le registre de l'opérande B
  37. -- Instructions_critiques_lecture_C(7) = '1' --> MUL lit dans le registre de l'opérande C
  38. -- Instructions_critiques_ecriture(7) = '1' --> MUL ecrit dans le registre de l'opérande A
  39. -- Exemple 2 : Soit AFC i val avec pour numéro d'instruction 5 avec le comportement Ri <- val
  40. -- Instructions_critiques_lecture_A(5) = '0' --> AFC ne lit pas dans le registre de l'opérande A
  41. -- Instructions_critiques_lecture_B(5) = '0' --> AFC ne lit pas dans le registre de l'opérande B (pour AFC, B est directement la valeur, pas un numero de registre, il n'y a donc pas de lecture)
  42. -- Instructions_critiques_lecture_C(5) = '0' --> AFC ne lit pas dans le registre de l'opérande C
  43. -- Instructions_critiques_ecriture(5) = '1' --> AFC ecrit dans le registre de l'opérande A
  44. Code_Instruction_JMP : STD_LOGIC_VECTOR; -- Numéro de l'instruction JMP
  45. Code_Instruction_JMZ : STD_LOGIC_VECTOR; -- Numéro de l'instruction JMZ
  46. Code_Instruction_CALL : STD_LOGIC_VECTOR; -- Numéro de l'instruction CALL
  47. Code_Instruction_RET : STD_LOGIC_VECTOR; -- Numéro de l'instruction RET
  48. Code_Instruction_STOP : STD_LOGIC_VECTOR); -- Numéro de l'instruction STOP
  49. Port ( CLK : in STD_LOGIC; -- Clock
  50. RST : in STD_LOGIC; -- Reset
  51. Z : in STD_LOGIC; -- Flag Zero de l'ALU (utile pour le JMZ)
  52. Addr_Retour : in STD_LOGIC_VECTOR (Nb_bits - 1 downto 0); -- Entrée de l'adresse de retour depuis l'étage 4
  53. A : out STD_LOGIC_VECTOR (Nb_bits - 1 downto 0); -- Sortie de l'opérande A
  54. B : out STD_LOGIC_VECTOR (Nb_bits - 1 downto 0); -- Sortie de l'opérande B
  55. C : out STD_LOGIC_VECTOR (Nb_bits - 1 downto 0); -- Sortie de l'opérande C
  56. Instruction : out STD_LOGIC_VECTOR (Instruction_bus_size - 1 downto 0)); -- Sortie du code de l'instruction
  57. end Etage1_LectureInstruction_NS;
  58. architecture Behavioral of Etage1_LectureInstruction_NS is
  59. component MemoireInstructions is
  60. Generic (Nb_bits : Natural;
  61. Addr_size : Natural;
  62. Mem_size : Natural);
  63. Port ( Addr : in STD_LOGIC_VECTOR (Addr_size-1 downto 0);
  64. D_OUT : out STD_LOGIC_VECTOR (Nb_bits-1 downto 0) := (others => '0'));
  65. end component;
  66. -- Signaux pour récuperer l'instruction de la mémoire
  67. signal Pointeur_instruction : STD_LOGIC_VECTOR (Addr_size_mem_instruction - 1 downto 0) := (others => '0');
  68. signal Instruction_courante : STD_LOGIC_VECTOR (Instruction_size_in_memory - 1 downto 0) := (others => '0');
  69. -- Tableau pour gérer les aléas des registres (lecture en étage 2 avant écriture en étage 5)
  70. subtype Registre is integer range -1 to Nb_registres - 1;
  71. type Tab_registres is array (1 to 3) of Registre;
  72. signal Tableau : Tab_registres := (others => - 1);
  73. -- constantes pour injecter des bulles dans le pipeline
  74. constant Instruction_nulle : STD_LOGIC_VECTOR (Instruction_bus_size - 1 downto 0) := (others => '0');
  75. constant Argument_nul : STD_LOGIC_VECTOR (Nb_bits - 1 downto 0) := (others => '0');
  76. -- condition pour detecter si une bulle doit être injectée
  77. signal bulles : boolean := false;
  78. -- Compteur pour attendre lors d'un JMZ que l'instruction d'avant soit a l'ALU, ou lors d'un STOP k
  79. signal compteur : integer := 0;
  80. -- Signal d'arret (STOP 0)
  81. signal locked : boolean := false;
  82. begin
  83. instance : MemoireInstructions
  84. generic map (Nb_bits => Instruction_size_in_memory,
  85. Addr_size => Addr_size_mem_instruction,
  86. Mem_size => Mem_instruction_size)
  87. port map (Addr => Pointeur_Instruction,
  88. D_OUT => Instruction_courante);
  89. process
  90. begin
  91. -- Synchronisation
  92. wait until CLK'event and CLK = '1';
  93. if (RST = '0') then
  94. -- Reset de l'étage
  95. Tableau <= (others => -1);
  96. Pointeur_Instruction <= (others => '0');
  97. compteur <= 0;
  98. locked <= false;
  99. C <= Argument_nul;
  100. B <= Argument_nul;
  101. A <= Argument_nul;
  102. Instruction <= Instruction_nulle;
  103. else
  104. -- Avancement des instructions en écritures dans le pipeline
  105. Tableau(3) <= Tableau(2);
  106. Tableau(2) <= Tableau(1);
  107. Tableau(1) <= -1;
  108. if (not bulles) then
  109. -- S'il ne faut pas injecter de bulles ont traite l'instruction (Possible code factorisable sur ce if)
  110. if ((Instruction_courante (Instruction_bus_size + 3 * Nb_bits - 1 downto 3 * Nb_bits) = Code_Instruction_CALL) or (Instruction_courante (Instruction_bus_size + 3 * Nb_bits - 1 downto 3 * Nb_bits) = Code_Instruction_JMP)) then
  111. -- CAS PARTICULIER : CALL ou JMP, on transmet (en modifiant le paramètre A pour le CALL (addr de retour à stocker))et on saute
  112. C <= Instruction_courante (1 * Nb_bits - 1 downto 0 * Nb_bits); -- STOCKER
  113. B <= Instruction_courante (2 * Nb_bits - 1 downto 1 * Nb_bits);
  114. A <= ((Nb_bits - 1 downto Addr_size_mem_instruction => '0') & Pointeur_Instruction) + 1;
  115. Instruction <= Instruction_courante (Instruction_bus_size + 3 * Nb_bits - 1 downto 3 * Nb_bits);
  116. Pointeur_Instruction <= Instruction_courante (2 * Nb_bits + Addr_size_mem_instruction - 1 downto 2 * Nb_bits);
  117. elsif (Instruction_courante (Instruction_bus_size + 3 * Nb_bits - 1 downto 3 * Nb_bits) = Code_Instruction_RET) then
  118. -- CAS PARTICULIER : RET, on transmet une seule fois, on attend et on revient
  119. compteur <= compteur + 1;
  120. if (compteur = 1) then
  121. C <= Instruction_courante (1 * Nb_bits - 1 downto 0 * Nb_bits);
  122. B <= Instruction_courante (2 * Nb_bits - 1 downto 1 * Nb_bits);
  123. A <= Instruction_courante (3 * Nb_bits - 1 downto 2 * Nb_bits);
  124. Instruction <= Instruction_courante (Instruction_bus_size + 3 * Nb_bits - 1 downto 3 * Nb_bits);
  125. elsif (compteur = 5) then
  126. Pointeur_Instruction <= Addr_Retour (Addr_size_mem_instruction - 1 downto 0);
  127. compteur <= 0;
  128. else
  129. C <= Argument_nul;
  130. B <= Argument_nul;
  131. A <= Argument_nul;
  132. Instruction <= Instruction_nulle;
  133. end if;
  134. elsif (Instruction_courante (Instruction_bus_size + 3 * Nb_bits - 1 downto 3 * Nb_bits) = Code_Instruction_JMZ) then
  135. -- CAS PARTICULIER : JMZ, on attends que l'instruction précedente arrive sur l'ALU, si le flag Zero est a un on saute, sinon on continue normalement
  136. compteur <= compteur + 1;
  137. C <= Instruction_courante (1 * Nb_bits - 1 downto 0 * Nb_bits);
  138. B <= Instruction_courante (2 * Nb_bits - 1 downto 1 * Nb_bits);
  139. A <= Instruction_courante (3 * Nb_bits - 1 downto 2 * Nb_bits);
  140. Instruction <= Instruction_courante (Instruction_bus_size + 3 * Nb_bits - 1 downto 3 * Nb_bits);
  141. if (compteur = 2) then
  142. if (Z = '1') then
  143. Pointeur_Instruction <= Instruction_courante (2 * Nb_bits + Addr_size_mem_instruction - 1 downto 2 * Nb_bits);
  144. else
  145. Pointeur_Instruction <= Pointeur_Instruction + 1;
  146. end if;
  147. compteur <= 0;
  148. end if;
  149. elsif (Instruction_courante (Instruction_bus_size + 3 * Nb_bits - 1 downto 3 * Nb_bits) = Code_Instruction_STOP) then
  150. -- CAS PARTICULIER : STOP, si on est bloqué, on ne fait rien, programme arrété
  151. -- sinon, on regarde si l'on doit se bloquer
  152. -- sinon, on incremente le compteur et on attends
  153. if (not locked) then
  154. if (Instruction_courante (3 * Nb_bits - 1 downto 2 * Nb_bits) = Argument_nul) then
  155. locked <= true;
  156. end if;
  157. compteur <= compteur + 1;
  158. if (compteur + 1 = to_integer(unsigned(Instruction_courante (3 * Nb_bits - 1 downto 2 * Nb_bits))) * 1000) then
  159. Pointeur_Instruction <= Pointeur_Instruction + 1;
  160. compteur <= 0;
  161. end if;
  162. end if;
  163. C <= Instruction_courante (1 * Nb_bits - 1 downto 0 * Nb_bits);
  164. B <= Instruction_courante (2 * Nb_bits - 1 downto 1 * Nb_bits);
  165. A <= Instruction_courante (3 * Nb_bits - 1 downto 2 * Nb_bits);
  166. Instruction <= Instruction_courante (Instruction_bus_size + 3 * Nb_bits - 1 downto 3 * Nb_bits);
  167. else
  168. -- CAS GENERAL : On transmet l'instruction et les opérandes, si elle est critique en ecriture, on enregistre le registre associé dans le tableau
  169. C <= Instruction_courante (1 * Nb_bits - 1 downto 0 * Nb_bits);
  170. B <= Instruction_courante (2 * Nb_bits - 1 downto 1 * Nb_bits);
  171. A <= Instruction_courante (3 * Nb_bits - 1 downto 2 * Nb_bits);
  172. Instruction <= Instruction_courante (Instruction_bus_size + 3 * Nb_bits - 1 downto 3 * Nb_bits);
  173. if (Instructions_critiques_ecriture(to_integer(unsigned(Instruction_courante (Instruction_bus_size + 3 * Nb_bits - 1 downto 3 * Nb_bits)))) = '1') then
  174. Tableau(1) <= to_integer(unsigned(Instruction_courante (3 * Nb_bits - 1 downto 2 * Nb_bits)));
  175. end if;
  176. Pointeur_Instruction <= Pointeur_Instruction + 1;
  177. end if;
  178. else
  179. -- Si besoin de bulle, on l'injecte
  180. C <= Argument_nul;
  181. B <= Argument_nul;
  182. A <= Argument_nul;
  183. Instruction <= Instruction_nulle;
  184. end if;
  185. end if;
  186. end process;
  187. -- Condition horrible -> Instruction critique en lecture sur A qui lit dans A=i et Ri dans tableau ou instruction critique en lecture sur B qui lit dans B=j et Rj dans tableau ou instruction critique en lecture sur C qui lit dans C=k et Rk dans tableau
  188. bulles <=
  189. (
  190. (
  191. Instructions_critiques_lecture_A(to_integer(unsigned(Instruction_courante (Instruction_bus_size + 3 * Nb_bits - 1 downto 3 * Nb_bits)))) = '1' -- Intruction critique sur A
  192. )
  193. and
  194. (
  195. (to_integer(unsigned(Instruction_courante (3 * Nb_bits - 1 downto 2 * Nb_bits))) = Tableau(1)) -- A est
  196. or
  197. (to_integer(unsigned(Instruction_courante (3 * Nb_bits - 1 downto 2 * Nb_bits))) = Tableau(2)) -- dans le
  198. or
  199. (to_integer(unsigned(Instruction_courante (3 * Nb_bits - 1 downto 2 * Nb_bits))) = Tableau(3)) -- tableau
  200. )
  201. )
  202. or
  203. (
  204. (
  205. Instructions_critiques_lecture_B(to_integer(unsigned(Instruction_courante (Instruction_bus_size + 3 * Nb_bits - 1 downto 3 * Nb_bits)))) = '1'
  206. )
  207. and
  208. (
  209. (to_integer(unsigned(Instruction_courante (2 * Nb_bits - 1 downto 1 * Nb_bits))) = Tableau(1))
  210. or
  211. (to_integer(unsigned(Instruction_courante (2 * Nb_bits - 1 downto 1 * Nb_bits))) = Tableau(2))
  212. or
  213. (to_integer(unsigned(Instruction_courante (2 * Nb_bits - 1 downto 1 * Nb_bits))) = Tableau(3))
  214. )
  215. )
  216. or
  217. (
  218. (
  219. Instructions_critiques_lecture_C(to_integer(unsigned(Instruction_courante (Instruction_bus_size + 3 * Nb_bits - 1 downto 3 * Nb_bits)))) = '1'
  220. )
  221. and
  222. (
  223. (to_integer(unsigned(Instruction_courante (1 * Nb_bits - 1 downto 0 * Nb_bits))) = Tableau(1))
  224. or
  225. (to_integer(unsigned(Instruction_courante (1 * Nb_bits - 1 downto 0 * Nb_bits))) = Tableau(2))
  226. or
  227. (to_integer(unsigned(Instruction_courante (1 * Nb_bits - 1 downto 0 * Nb_bits))) = Tableau(3))
  228. )
  229. );
  230. end Behavioral;