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.vhd 18KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  1. ----------------------------------------------------------------------------------
  2. -- Company: INSA-Toulouse
  3. -- Engineer: Paul Faure
  4. --
  5. -- Create Date: 18.04.2021 21:19:41
  6. -- Module Name: Etage1_LectureInstruction - 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 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. Mem_adresse_retour_size : Natural; -- Taille de la mémoire des adresses de retour (nombre d'adresse maximum) (profondeur d'appel maximale)
  31. Adresse_size_mem_adresse_retour : Natural; -- Nombre de bits pour adresser la mémoire des adresses de retour
  32. 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)
  33. 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)
  34. 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)
  35. 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)
  36. -- Exemple 1 : Soit MUL i j k avec pour numéro d'instruction 7 avec le comportement Ri <- Rj*Rk
  37. -- Instructions_critiques_lecture_A(7) = '0' --> MUL ne lit pas dans le registre de l'opérande A
  38. -- Instructions_critiques_lecture_B(7) = '1' --> MUL lit dans le registre de l'opérande B
  39. -- Instructions_critiques_lecture_C(7) = '1' --> MUL lit dans le registre de l'opérande C
  40. -- Instructions_critiques_ecriture(7) = '1' --> MUL ecrit dans le registre de l'opérande A
  41. -- Exemple 2 : Soit AFC i val avec pour numéro d'instruction 5 avec le comportement Ri <- val
  42. -- Instructions_critiques_lecture_A(5) = '0' --> AFC ne lit pas dans le registre de l'opérande A
  43. -- 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)
  44. -- Instructions_critiques_lecture_C(5) = '0' --> AFC ne lit pas dans le registre de l'opérande C
  45. -- Instructions_critiques_ecriture(5) = '1' --> AFC ecrit dans le registre de l'opérande A
  46. Code_Instruction_JMP : STD_LOGIC_VECTOR; -- Numéro de l'instruction JMP
  47. Code_Instruction_JMZ : STD_LOGIC_VECTOR; -- Numéro de l'instruction JMZ
  48. Code_Instruction_CALL : STD_LOGIC_VECTOR; -- Numéro de l'instruction CALL
  49. Code_Instruction_RET : STD_LOGIC_VECTOR; -- Numéro de l'instruction RET
  50. Code_Instruction_STOP : STD_LOGIC_VECTOR); -- Numéro de l'instruction STOP
  51. Port ( CLK : in STD_LOGIC; -- Clock
  52. RST : in STD_LOGIC; -- Reset
  53. Z : in STD_LOGIC; -- Flag Zero de l'ALU (utile pour le JMZ)
  54. A : out STD_LOGIC_VECTOR (Nb_bits - 1 downto 0); -- Sortie de l'opérande A
  55. B : out STD_LOGIC_VECTOR (Nb_bits - 1 downto 0); -- Sortie de l'opérande B
  56. C : out STD_LOGIC_VECTOR (Nb_bits - 1 downto 0); -- Sortie de l'opérande C
  57. Instruction : out STD_LOGIC_VECTOR (Instruction_bus_size - 1 downto 0)); -- Sortie du code de l'instruction
  58. end Etage1_LectureInstruction;
  59. architecture Behavioral of Etage1_LectureInstruction is
  60. component MemoireInstructions is
  61. Generic (Nb_bits : Natural;
  62. Addr_size : Natural;
  63. Mem_size : Natural);
  64. Port ( Addr : in STD_LOGIC_VECTOR (Addr_size-1 downto 0);
  65. D_OUT : out STD_LOGIC_VECTOR (Nb_bits-1 downto 0) := (others => '0'));
  66. end component;
  67. component MemoireAdressesRetour is
  68. Generic (Nb_bits : Natural;
  69. Addr_size : Natural;
  70. Mem_size : Natural);
  71. Port ( R : in STD_LOGIC;
  72. W : in STD_LOGIC;
  73. D_IN : in STD_LOGIC_VECTOR (Nb_bits-1 downto 0);
  74. RST : in STD_LOGIC;
  75. CLK : in STD_LOGIC;
  76. D_OUT : out STD_LOGIC_VECTOR (Nb_bits-1 downto 0) := (others => '0');
  77. E : out STD_LOGIC;
  78. F : out STD_LOGIC);
  79. end component;
  80. -- Signaux pour récuperer l'instruction de la mémoire
  81. signal Pointeur_instruction : STD_LOGIC_VECTOR (Addr_size_mem_instruction - 1 downto 0) := (others => '0');
  82. signal Pointeur_instruction_next : STD_LOGIC_VECTOR (Addr_size_mem_instruction - 1 downto 0) := (0 => '1', others => '0');
  83. signal Instruction_courante : STD_LOGIC_VECTOR (Instruction_size_in_memory - 1 downto 0) := (others => '0');
  84. -- Tableau pour gérer les aléas des registres (lecture en étage 2 avant écriture en étage 5)
  85. subtype Registre is integer range -1 to Nb_registres - 1;
  86. type Tab_registres is array (1 to 3) of Registre;
  87. signal Tableau : Tab_registres := (others => - 1);
  88. -- Signaux de gestion pour la mémoire des adresses de retour
  89. signal Adresse_Retour : STD_LOGIC_VECTOR (Addr_size_mem_instruction - 1 downto 0) := (others => '0');
  90. signal E : STD_LOGIC;
  91. signal F : STD_LOGIC;
  92. signal R_Aux : STD_LOGIC := '0';
  93. signal W_Aux : STD_LOGIC := '0';
  94. -- constantes pour injecter des bulles dans le pipeline
  95. constant Instruction_nulle : STD_LOGIC_VECTOR (Instruction_bus_size - 1 downto 0) := (others => '0');
  96. constant Argument_nul : STD_LOGIC_VECTOR (Nb_bits - 1 downto 0) := (others => '0');
  97. -- condition pour detecter si une bulle doit être injectée
  98. signal bulles : boolean := false;
  99. -- Compteur pour attendre lors d'un JMZ que l'instruction d'avant soit a l'ALU, ou lors d'un STOP k
  100. signal compteur : integer := 0;
  101. -- Signal d'arret (STOP 0)
  102. signal locked : boolean := false;
  103. begin
  104. instance : MemoireInstructions
  105. generic map (Nb_bits => Instruction_size_in_memory,
  106. Addr_size => Addr_size_mem_instruction,
  107. Mem_size => Mem_instruction_size)
  108. port map (Addr => Pointeur_Instruction,
  109. D_OUT => Instruction_courante);
  110. instance_MemoireAdressesRetour : MemoireAdressesRetour
  111. generic map (Nb_bits => Addr_size_mem_instruction,
  112. Addr_size => Adresse_size_mem_adresse_retour,
  113. Mem_size => Mem_adresse_retour_size
  114. )
  115. port map ( R => R_Aux,
  116. W => W_Aux,
  117. D_IN => Pointeur_instruction_next,
  118. RST => RST,
  119. CLK => CLK,
  120. D_OUT => Adresse_Retour,
  121. E => E,
  122. F => F
  123. );
  124. process
  125. begin
  126. -- Synchronisation
  127. wait until CLK'event and CLK = '1';
  128. if (RST = '0') then
  129. -- Reset de l'étage
  130. Tableau <= (others => -1);
  131. Pointeur_Instruction <= (others => '0');
  132. compteur <= 0;
  133. locked <= false;
  134. C <= Argument_nul;
  135. B <= Argument_nul;
  136. A <= Argument_nul;
  137. Instruction <= Instruction_nulle;
  138. else
  139. -- Avancement des instructions en écritures dans le pipeline
  140. Tableau(3) <= Tableau(2);
  141. Tableau(2) <= Tableau(1);
  142. Tableau(1) <= -1;
  143. if (not bulles) then
  144. -- S'il ne faut pas injecter de bulles ont traite l'instruction (Possible code factorisable sur ce if)
  145. 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
  146. -- CAS PARTICULIER : CALL ou JMP, on transmet et on saute
  147. C <= Instruction_courante (1 * Nb_bits - 1 downto 0 * Nb_bits);
  148. B <= Instruction_courante (2 * Nb_bits - 1 downto 1 * Nb_bits);
  149. A <= Instruction_courante (3 * Nb_bits - 1 downto 2 * Nb_bits);
  150. Instruction <= Instruction_courante (Instruction_bus_size + 3 * Nb_bits - 1 downto 3 * Nb_bits);
  151. Pointeur_Instruction <= Instruction_courante (2 * Nb_bits + Addr_size_mem_instruction - 1 downto 2 * Nb_bits);
  152. elsif (Instruction_courante (Instruction_bus_size + 3 * Nb_bits - 1 downto 3 * Nb_bits) = Code_Instruction_RET) then
  153. -- CAS PARTICULIER : RET, on transmet et on revient
  154. C <= Instruction_courante (1 * Nb_bits - 1 downto 0 * Nb_bits);
  155. B <= Instruction_courante (2 * Nb_bits - 1 downto 1 * Nb_bits);
  156. A <= Instruction_courante (3 * Nb_bits - 1 downto 2 * Nb_bits);
  157. Instruction <= Instruction_courante (Instruction_bus_size + 3 * Nb_bits - 1 downto 3 * Nb_bits);
  158. Pointeur_Instruction <= Adresse_Retour;
  159. elsif (Instruction_courante (Instruction_bus_size + 3 * Nb_bits - 1 downto 3 * Nb_bits) = Code_Instruction_JMZ) then
  160. -- 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
  161. compteur <= compteur + 1;
  162. C <= Instruction_courante (1 * Nb_bits - 1 downto 0 * Nb_bits);
  163. B <= Instruction_courante (2 * Nb_bits - 1 downto 1 * Nb_bits);
  164. A <= Instruction_courante (3 * Nb_bits - 1 downto 2 * Nb_bits);
  165. Instruction <= Instruction_courante (Instruction_bus_size + 3 * Nb_bits - 1 downto 3 * Nb_bits);
  166. if (compteur = 2) then
  167. if (Z = '1') then
  168. Pointeur_Instruction <= Instruction_courante (2 * Nb_bits + Addr_size_mem_instruction - 1 downto 2 * Nb_bits);
  169. else
  170. Pointeur_Instruction <= Pointeur_Instruction + 1;
  171. end if;
  172. compteur <= 0;
  173. end if;
  174. elsif (Instruction_courante (Instruction_bus_size + 3 * Nb_bits - 1 downto 3 * Nb_bits) = Code_Instruction_STOP) then
  175. -- CAS PARTICULIER : STOP, si on est bloqué, on ne fait rien, programme arrété
  176. -- sinon, on regarde si l'on doit se bloquer
  177. -- sinon, on incremente le compteur et on attends
  178. if (not locked) then
  179. if (Instruction_courante (3 * Nb_bits - 1 downto 2 * Nb_bits) = Argument_nul) then
  180. locked <= true;
  181. end if;
  182. compteur <= compteur + 1;
  183. if (compteur + 1 = to_integer(unsigned(Instruction_courante (3 * Nb_bits - 1 downto 2 * Nb_bits))) * 1000) then
  184. Pointeur_Instruction <= Pointeur_Instruction + 1;
  185. compteur <= 0;
  186. end if;
  187. end if;
  188. C <= Instruction_courante (1 * Nb_bits - 1 downto 0 * Nb_bits);
  189. B <= Instruction_courante (2 * Nb_bits - 1 downto 1 * Nb_bits);
  190. A <= Instruction_courante (3 * Nb_bits - 1 downto 2 * Nb_bits);
  191. Instruction <= Instruction_courante (Instruction_bus_size + 3 * Nb_bits - 1 downto 3 * Nb_bits);
  192. else
  193. -- CAS GENERAL : On transmet l'instruction et les opérandes, si elle est critique en ecriture, on enregistre le registre associé dans le tableau
  194. C <= Instruction_courante (1 * Nb_bits - 1 downto 0 * Nb_bits);
  195. B <= Instruction_courante (2 * Nb_bits - 1 downto 1 * Nb_bits);
  196. A <= Instruction_courante (3 * Nb_bits - 1 downto 2 * Nb_bits);
  197. Instruction <= Instruction_courante (Instruction_bus_size + 3 * Nb_bits - 1 downto 3 * Nb_bits);
  198. if (Instructions_critiques_ecriture(to_integer(unsigned(Instruction_courante (Instruction_bus_size + 3 * Nb_bits - 1 downto 3 * Nb_bits)))) = '1') then
  199. Tableau(1) <= to_integer(unsigned(Instruction_courante (3 * Nb_bits - 1 downto 2 * Nb_bits)));
  200. end if;
  201. Pointeur_Instruction <= Pointeur_Instruction + 1;
  202. end if;
  203. else
  204. -- Si besoin de bulle, on l'injecte
  205. C <= Argument_nul;
  206. B <= Argument_nul;
  207. A <= Argument_nul;
  208. Instruction <= Instruction_nulle;
  209. end if;
  210. end if;
  211. end process;
  212. -- 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
  213. bulles <=
  214. (
  215. (
  216. 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
  217. )
  218. and
  219. (
  220. (to_integer(unsigned(Instruction_courante (3 * Nb_bits - 1 downto 2 * Nb_bits))) = Tableau(1)) -- A est
  221. or
  222. (to_integer(unsigned(Instruction_courante (3 * Nb_bits - 1 downto 2 * Nb_bits))) = Tableau(2)) -- dans le
  223. or
  224. (to_integer(unsigned(Instruction_courante (3 * Nb_bits - 1 downto 2 * Nb_bits))) = Tableau(3)) -- tableau
  225. )
  226. )
  227. or
  228. (
  229. (
  230. Instructions_critiques_lecture_B(to_integer(unsigned(Instruction_courante (Instruction_bus_size + 3 * Nb_bits - 1 downto 3 * Nb_bits)))) = '1'
  231. )
  232. and
  233. (
  234. (to_integer(unsigned(Instruction_courante (2 * Nb_bits - 1 downto 1 * Nb_bits))) = Tableau(1))
  235. or
  236. (to_integer(unsigned(Instruction_courante (2 * Nb_bits - 1 downto 1 * Nb_bits))) = Tableau(2))
  237. or
  238. (to_integer(unsigned(Instruction_courante (2 * Nb_bits - 1 downto 1 * Nb_bits))) = Tableau(3))
  239. )
  240. )
  241. or
  242. (
  243. (
  244. Instructions_critiques_lecture_C(to_integer(unsigned(Instruction_courante (Instruction_bus_size + 3 * Nb_bits - 1 downto 3 * Nb_bits)))) = '1'
  245. )
  246. and
  247. (
  248. (to_integer(unsigned(Instruction_courante (1 * Nb_bits - 1 downto 0 * Nb_bits))) = Tableau(1))
  249. or
  250. (to_integer(unsigned(Instruction_courante (1 * Nb_bits - 1 downto 0 * Nb_bits))) = Tableau(2))
  251. or
  252. (to_integer(unsigned(Instruction_courante (1 * Nb_bits - 1 downto 0 * Nb_bits))) = Tableau(3))
  253. )
  254. );
  255. -- Gestion de l'écriture/lecture dans la mémoire des adresses de retour
  256. R_Aux <= '1' when Instruction_courante (Instruction_bus_size + 3 * Nb_bits - 1 downto 3 * Nb_bits) = Code_Instruction_RET else
  257. '0';
  258. W_Aux <= '1' when Instruction_courante (Instruction_bus_size + 3 * Nb_bits - 1 downto 3 * Nb_bits) = Code_instruction_CALL else
  259. '0';
  260. Pointeur_instruction_next <= Pointeur_instruction + 1;
  261. end Behavioral;