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 17KB

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