| 1 | ---------------------------------------------------------------------------------- |
|---|
| 2 | -- Company: |
|---|
| 3 | -- Engineer: KIEGAING EMMANUEL |
|---|
| 4 | -- GAMOM ROLAND CHRISTIAN |
|---|
| 5 | -- |
|---|
| 6 | -- Create Date: 04:39:43 05/21/2011 |
|---|
| 7 | -- Design Name: |
|---|
| 8 | -- Module Name: DMA_ARBITER - Behavioral |
|---|
| 9 | -- Project Name: |
|---|
| 10 | -- Target Devices: |
|---|
| 11 | -- Tool versions: |
|---|
| 12 | -- Description: |
|---|
| 13 | -- gestionnaire DMA pour le port secodaire de la RAM true dual port des mémoire |
|---|
| 14 | -- privée de chaque noeud |
|---|
| 15 | -- Dependencies: |
|---|
| 16 | -- |
|---|
| 17 | -- Revision: 09/07/2012 |
|---|
| 18 | -- Revision 1.01 - File Created |
|---|
| 19 | -- Additional Comments: Ce module pourra être optimisé pour générer les adresses automatiquement |
|---|
| 20 | -- par le controleur DMA lorsqu'il est sollicité par la périphérie |
|---|
| 21 | -- |
|---|
| 22 | ---------------------------------------------------------------------------------- |
|---|
| 23 | library IEEE; |
|---|
| 24 | library NocLib; |
|---|
| 25 | use IEEE.STD_LOGIC_1164.ALL; |
|---|
| 26 | use IEEE.STD_LOGIC_ARITH.ALL; |
|---|
| 27 | use IEEE.STD_LOGIC_UNSIGNED.ALL; |
|---|
| 28 | use IEEE.numeric_std.all; |
|---|
| 29 | use NocLib.CoreTypes.all; |
|---|
| 30 | ---- Uncomment the following library declaration if instantiating |
|---|
| 31 | ---- any Xilinx primitives in this code. |
|---|
| 32 | --library UNISIM; |
|---|
| 33 | --use UNISIM.VComponents.all; |
|---|
| 34 | |
|---|
| 35 | entity DMA_ARBITER is |
|---|
| 36 | Port ( dma_rd_request : in STD_LOGIC_VEctor (3 downto 0):=(others=>'0'); |
|---|
| 37 | data_wr_in : in STD_LOGIC_VECTOR (Word-1 downto 0); |
|---|
| 38 | data_rd_out : out STD_LOGIC_VECTOR (Word-1 downto 0); |
|---|
| 39 | address_rd : in STD_LOGIC_VECTOR (ADRLEN-1 downto 0); --adresse pour lecture |
|---|
| 40 | address_wr : in STD_LOGIC_VECTOR (ADRLEN-1 downto 0); -- adresse pour écriture |
|---|
| 41 | address_out_wr : out STD_LOGIC_VECTOR (ADRLEN-1 downto 0); -- adresse de sortie du DMA Arbiter |
|---|
| 42 | address_out_rd : out STD_LOGIC_VECTOR (ADRLEN-1 downto 0); |
|---|
| 43 | ram_en : out STD_LOGIC; -- |
|---|
| 44 | ram_we : out STD_LOGIC; |
|---|
| 45 | data_wr_mem : out STD_LOGIC_VECTOR (Word-1 downto 0); -- donnée en sortie écriture |
|---|
| 46 | data_rd_mem : in STD_LOGIC_VECTOR (Word-1 downto 0); -- données en sortie lecture |
|---|
| 47 | dma_wr_grant : out STD_LOGIC_vector(3 downto 0):=(others=>'0'); -- autorisation d'écriture |
|---|
| 48 | hold_req : out STD_Logic; --requete vers application |
|---|
| 49 | hold_ack : in STD_Logic; --autorisation par l'application |
|---|
| 50 | clk : in std_logic; |
|---|
| 51 | reset : in std_logic; |
|---|
| 52 | dma_rd_grant : out STD_LOGIC_vector(3 downto 0):=(others=>'0'); -- autorisation de lecture |
|---|
| 53 | dma_wr_request : in STD_LOGIC_vector(3 downto 0):=(others=>'0')); -- demande de lecture |
|---|
| 54 | end DMA_ARBITER; |
|---|
| 55 | |
|---|
| 56 | architecture Behavioral of DMA_ARBITER is |
|---|
| 57 | type fsm_states is (idle,wait_ack,arbiter_ack, writing,ReadWrite,reading);-- definition du type etat pour le codage des etats des fsm |
|---|
| 58 | signal dmac_state : fsm_states; |
|---|
| 59 | |
|---|
| 60 | signal prio_rd,prio_wr:std_logic_vector(3 downto 0);--vecteur de bits de priorité |
|---|
| 61 | signal pri_rd,pri_wr : natural range 0 to 3; -- stocke le numéro du module qui a la priorité |
|---|
| 62 | signal dma_rd_logic : std_logic_vector(3 downto 0):=(others=>'0'); |
|---|
| 63 | signal dma_wr_logic : std_logic_vector(3 downto 0):=(others=>'0'); |
|---|
| 64 | signal dma_req_wr, dma_req_rd : std_logic; |
|---|
| 65 | signal tmp :std_logic_vector(3 downto 0):="0000"; |
|---|
| 66 | |
|---|
| 67 | begin |
|---|
| 68 | --========================================================================== |
|---|
| 69 | ---le MUX qui contrôle les adresses est géré à l'extérieur du contrôleur DMA |
|---|
| 70 | data_rd_out<=data_rd_mem ; |
|---|
| 71 | data_wr_mem <= data_wr_in; |
|---|
| 72 | address_out_rd <= address_rd; |
|---|
| 73 | address_out_wr <= address_wr; |
|---|
| 74 | --========================================================================== |
|---|
| 75 | |
|---|
| 76 | --Déterminer si une requête HOLD doit être émise vers l'application pour la libération du |
|---|
| 77 | --bus mémoire |
|---|
| 78 | tmp<=(others =>'0'); |
|---|
| 79 | |
|---|
| 80 | --for i in 0 to 3 loop |
|---|
| 81 | --dma_req_wr<=dma_req_wr or dma_wr_request(i); |
|---|
| 82 | --loop; |
|---|
| 83 | |
|---|
| 84 | --for i in 0 to 3 loop |
|---|
| 85 | -- dma_req_rd<=dma_req_rd or dma_rd_request(i); -- construire le signal request vers l'extérieur |
|---|
| 86 | --loop; |
|---|
| 87 | hold_req<=dma_req_rd or dma_req_wr; --envoyer un Hold vers l'application |
|---|
| 88 | |
|---|
| 89 | |
|---|
| 90 | -- machine à etat du DMAC |
|---|
| 91 | dmac_process : process(clk) |
|---|
| 92 | --variable tmp : natural range 0 to 15; |
|---|
| 93 | variable tmp_rd,tmp_wr: std_logic_vector(3 downto 0); |
|---|
| 94 | variable req_rd,req_wr : std_logic:='0' ; |
|---|
| 95 | |
|---|
| 96 | begin |
|---|
| 97 | if rising_edge(clk) then |
|---|
| 98 | if reset = '1' then |
|---|
| 99 | dmac_state<= idle; |
|---|
| 100 | |
|---|
| 101 | prio_rd <="0001"; -- au debut priorité lecture au premier module |
|---|
| 102 | prio_wr <="0010"; -- au debut priorité ecriture au deuxième module |
|---|
| 103 | pri_rd<=0;--index de la priorité |
|---|
| 104 | pri_wr<=1; |
|---|
| 105 | req_rd:='0'; |
|---|
| 106 | req_wr:='0'; |
|---|
| 107 | else |
|---|
| 108 | if req_wr='0' or dma_wr_request="0000" then --tant que le Ctrl DMA est libre alors faire bouger la priorité en écriture |
|---|
| 109 | case dma_wr_request is |
|---|
| 110 | when "0001" => pri_wr<=0; |
|---|
| 111 | prio_wr<="0001"; |
|---|
| 112 | req_wr:='1'; |
|---|
| 113 | dma_req_wr<= '1'; |
|---|
| 114 | dma_wr_logic <="0001"; |
|---|
| 115 | when "0010" => pri_wr<=1; |
|---|
| 116 | prio_wr<="0010"; |
|---|
| 117 | req_wr:='1'; |
|---|
| 118 | dma_req_wr<= '1'; |
|---|
| 119 | dma_wr_logic <="0010"; |
|---|
| 120 | when "0100" => pri_wr<=2; |
|---|
| 121 | prio_wr<="0100"; |
|---|
| 122 | req_wr:='1'; |
|---|
| 123 | dma_req_wr<= '1'; |
|---|
| 124 | dma_wr_logic <="0100"; |
|---|
| 125 | when "1000" => pri_wr<=3; |
|---|
| 126 | prio_wr<="1000"; |
|---|
| 127 | req_wr:='1'; |
|---|
| 128 | dma_req_wr<= '1'; |
|---|
| 129 | dma_wr_logic <="1000"; |
|---|
| 130 | |
|---|
| 131 | when others => tmp_wr:= (dma_wr_request and prio_wr) ; |
|---|
| 132 | dma_wr_logic <=tmp_wr; |
|---|
| 133 | req_wr:= not(All_zeros(tmp_wr)); |
|---|
| 134 | dma_req_wr<= not(All_zeros(tmp_wr)); |
|---|
| 135 | -- la priorité est circulaire et décale à chaque coup d'horloge |
|---|
| 136 | prio_wr<=rol_vec(prio_wr); |
|---|
| 137 | if pri_wr=3 then |
|---|
| 138 | pri_wr<=0; |
|---|
| 139 | Prio_wr<="0001"; |
|---|
| 140 | else |
|---|
| 141 | pri_wr<=pri_wr+1; |
|---|
| 142 | end if; |
|---|
| 143 | end case; |
|---|
| 144 | |
|---|
| 145 | end if; |
|---|
| 146 | |
|---|
| 147 | if req_rd='0' or dma_rd_request="0000" then --tant que le Ctrl DMA est libre alors faire bouger la priorité |
|---|
| 148 | case dma_rd_request is |
|---|
| 149 | when "0001" => pri_rd<=0; |
|---|
| 150 | prio_rd<="0001"; |
|---|
| 151 | req_rd:='1'; |
|---|
| 152 | dma_req_rd<= '1'; |
|---|
| 153 | dma_rd_logic<="0001"; |
|---|
| 154 | when "0010" => pri_rd<=1; |
|---|
| 155 | prio_rd<="0010"; |
|---|
| 156 | req_rd:='1'; |
|---|
| 157 | dma_req_rd<= '1'; |
|---|
| 158 | dma_rd_logic<="0010"; |
|---|
| 159 | |
|---|
| 160 | when "0100" => pri_rd<=2; |
|---|
| 161 | prio_rd<="0100"; |
|---|
| 162 | req_rd:='1'; |
|---|
| 163 | dma_req_rd<= '1'; |
|---|
| 164 | dma_rd_logic<="0100"; |
|---|
| 165 | |
|---|
| 166 | when "1000" => pri_rd<=3; |
|---|
| 167 | prio_rd<="1000"; |
|---|
| 168 | req_rd:='1'; |
|---|
| 169 | dma_req_rd<= '1'; |
|---|
| 170 | dma_rd_logic<="1000"; |
|---|
| 171 | |
|---|
| 172 | when others => |
|---|
| 173 | |
|---|
| 174 | tmp_rd:= (dma_rd_request and prio_rd) ; |
|---|
| 175 | dma_rd_logic<=tmp_rd; |
|---|
| 176 | dma_req_rd<= not (All_Zeros(tmp_rd)); |
|---|
| 177 | req_rd:= not (All_Zeros(tmp_rd)); |
|---|
| 178 | |
|---|
| 179 | -- la priorité est circulaire et décale à chaque coup d'horloge |
|---|
| 180 | prio_rd<=rol_vec(prio_rd); |
|---|
| 181 | if pri_rd =3 then |
|---|
| 182 | pri_rd<=0; |
|---|
| 183 | prio_rd<="0001"; |
|---|
| 184 | else |
|---|
| 185 | |
|---|
| 186 | pri_rd<=pri_rd+1; |
|---|
| 187 | end if; |
|---|
| 188 | end case; |
|---|
| 189 | |
|---|
| 190 | end if; |
|---|
| 191 | |
|---|
| 192 | case dmac_state is |
|---|
| 193 | when idle => if req_rd='1' or req_wr='1' then |
|---|
| 194 | dmac_state<=wait_ack; |
|---|
| 195 | else -- initialiser la priorité |
|---|
| 196 | |
|---|
| 197 | |
|---|
| 198 | req_rd:='0'; |
|---|
| 199 | dma_req_rd<= '0'; |
|---|
| 200 | dma_rd_logic <="0000"; |
|---|
| 201 | |
|---|
| 202 | |
|---|
| 203 | req_wr:='0'; |
|---|
| 204 | dma_req_wr<= '0'; |
|---|
| 205 | dma_wr_logic <="0000"; |
|---|
| 206 | |
|---|
| 207 | end if; |
|---|
| 208 | when wait_ack => -- l'application doit autoriser l'utilisation de la RAM par le Core |
|---|
| 209 | if dma_wr_request(pri_wr) ='1' or dma_rd_request(pri_rd) ='1' then |
|---|
| 210 | if hold_ack='1' then |
|---|
| 211 | dmac_state<=arbiter_ack; |
|---|
| 212 | end if; |
|---|
| 213 | else |
|---|
| 214 | |
|---|
| 215 | if dma_wr_request(pri_wr) ='0' then |
|---|
| 216 | req_wr:='0';-- forcer une nouvelle recherche de priorité |
|---|
| 217 | end if; |
|---|
| 218 | |
|---|
| 219 | if dma_rd_request(pri_rd) ='0' then |
|---|
| 220 | req_rd:='0'; |
|---|
| 221 | end if; |
|---|
| 222 | dmac_state<=Idle; |
|---|
| 223 | end if; |
|---|
| 224 | |
|---|
| 225 | |
|---|
| 226 | when arbiter_ack => if dma_wr_request(pri_wr) ='1' and dma_rd_request(pri_rd) ='1' then -- |
|---|
| 227 | dmac_state <= Readwrite; |
|---|
| 228 | elsif dma_wr_request(pri_wr) ='0' and dma_rd_request(pri_rd) ='1' then |
|---|
| 229 | dmac_state <= Reading; |
|---|
| 230 | elsif dma_wr_request(pri_wr) ='1' and dma_rd_request(pri_rd) ='0' then |
|---|
| 231 | dmac_state <= Writing; |
|---|
| 232 | else |
|---|
| 233 | dmac_state<=Idle; |
|---|
| 234 | end if; |
|---|
| 235 | |
|---|
| 236 | when Writing => if dma_wr_request(pri_wr) ='1' then |
|---|
| 237 | if hold_ack='1' then |
|---|
| 238 | -- on reste dans cet état |
|---|
| 239 | if dma_rd_request(pri_rd)='1' then |
|---|
| 240 | dmac_state<=ReadWrite; |
|---|
| 241 | else |
|---|
| 242 | req_rd:='0'; |
|---|
| 243 | end if; |
|---|
| 244 | else |
|---|
| 245 | dmac_state<=wait_ack; |
|---|
| 246 | end if; |
|---|
| 247 | elsif dma_rd_request(pri_rd) ='1' then |
|---|
| 248 | dmac_state <= Reading; |
|---|
| 249 | else |
|---|
| 250 | dmac_state <= idle; |
|---|
| 251 | end if; |
|---|
| 252 | |
|---|
| 253 | |
|---|
| 254 | when ReadWrite => if hold_ack='1' then |
|---|
| 255 | if dma_wr_request(pri_wr)='1' and dma_rd_request(pri_rd)='1' then |
|---|
| 256 | dmac_state <= ReadWrite; |
|---|
| 257 | elsif dma_wr_request(pri_wr)='1' and dma_rd_request(pri_rd)='0' then |
|---|
| 258 | dmac_state <= Writing; |
|---|
| 259 | req_rd:='0'; |
|---|
| 260 | elsif dma_wr_request(pri_wr)='0' and dma_rd_request(pri_rd)='1' then |
|---|
| 261 | dmac_state <= Reading; |
|---|
| 262 | req_wr:='0'; |
|---|
| 263 | else |
|---|
| 264 | dmac_state <= Idle; |
|---|
| 265 | req_rd:='0';req_wr:='0'; |
|---|
| 266 | end if; |
|---|
| 267 | else |
|---|
| 268 | if (dma_wr_request(pri_wr)='1') or (dma_rd_request(pri_rd)='1') then |
|---|
| 269 | dmac_state <= Wait_ack; |
|---|
| 270 | else |
|---|
| 271 | dmac_state <= Idle; |
|---|
| 272 | end if; |
|---|
| 273 | end if; |
|---|
| 274 | when Reading => |
|---|
| 275 | if dma_rd_request(pri_rd) ='1' then |
|---|
| 276 | if hold_ack='1' then |
|---|
| 277 | -- on reste dans cet état |
|---|
| 278 | if dma_wr_request(pri_wr)='1' then |
|---|
| 279 | dmac_state<=ReadWrite; |
|---|
| 280 | else |
|---|
| 281 | req_wr:='0'; |
|---|
| 282 | end if; |
|---|
| 283 | else |
|---|
| 284 | dmac_state<=wait_ack; |
|---|
| 285 | end if; |
|---|
| 286 | elsif dma_wr_request(pri_wr) ='1' then |
|---|
| 287 | dmac_state<=writing; |
|---|
| 288 | else |
|---|
| 289 | dmac_state <= idle; |
|---|
| 290 | end if; |
|---|
| 291 | when others => dmac_state <= idle; |
|---|
| 292 | end case; |
|---|
| 293 | end if; |
|---|
| 294 | end if; |
|---|
| 295 | end process; |
|---|
| 296 | -- action_asociées |
|---|
| 297 | ol: process(dmac_state, address_rd, address_wr,pri_wr,pri_rd,prio_wr,prio_rd,dma_wr_request,dma_rd_request) |
|---|
| 298 | |
|---|
| 299 | begin |
|---|
| 300 | --tester les requêtes DMA en lecture ou en écriture |
|---|
| 301 | |
|---|
| 302 | case dmac_state is |
|---|
| 303 | when idle => |
|---|
| 304 | ram_en <='0'; |
|---|
| 305 | ram_we <='0'; |
|---|
| 306 | dma_wr_grant <=(others=>'0'); |
|---|
| 307 | dma_rd_grant <=(others=>'0'); |
|---|
| 308 | --address_out_rd <= address_rd; |
|---|
| 309 | --hold_req<='0'; |
|---|
| 310 | when wait_ack => |
|---|
| 311 | ram_en <='0'; |
|---|
| 312 | ram_we <='0'; |
|---|
| 313 | dma_wr_grant<=(others=>'0'); |
|---|
| 314 | dma_rd_grant<=(others=>'0'); |
|---|
| 315 | --address_out_rd <= (others=>'Z'); |
|---|
| 316 | --address_out_wr <= (others=>'Z'); |
|---|
| 317 | --hold_req<='1'; |
|---|
| 318 | when arbiter_ack => --à optimiser pour gagner un cycle |
|---|
| 319 | ram_en <='1'; |
|---|
| 320 | ram_we <='0'; |
|---|
| 321 | dma_wr_grant<=(others=>'0'); |
|---|
| 322 | dma_rd_grant<=(others=>'0'); |
|---|
| 323 | --address_out_rd <= (others=>'Z'); |
|---|
| 324 | --address_out_wr <= (others=>'Z'); |
|---|
| 325 | when writing => -- ecriture dans la ram |
|---|
| 326 | ram_en <='1'; |
|---|
| 327 | ram_we <='1'; |
|---|
| 328 | dma_wr_grant<=(others=>'0'); |
|---|
| 329 | dma_wr_grant(pri_wr) <='1'; |
|---|
| 330 | dma_rd_grant <=(others=>'0'); |
|---|
| 331 | --address_out_rd <= (others=>'Z'); |
|---|
| 332 | --address_out_wr <= address_wr; |
|---|
| 333 | --hold_req<='1'; |
|---|
| 334 | |
|---|
| 335 | when ReadWrite => -- Lecture et écriture simultannée dans la Dual Port RAM |
|---|
| 336 | ram_en <='1'; |
|---|
| 337 | ram_we <='1'; |
|---|
| 338 | dma_wr_grant<=(others=>'0'); |
|---|
| 339 | dma_wr_grant(pri_wr) <='1'; |
|---|
| 340 | dma_rd_grant<=(others=>'0'); |
|---|
| 341 | dma_rd_grant(pri_rd)<='1'; |
|---|
| 342 | |
|---|
| 343 | --address_out_rd <= address_rd; |
|---|
| 344 | --address_out_wr <= address_wr; |
|---|
| 345 | --hold_req<='1'; |
|---|
| 346 | when Reading => -- lecture dans la ram |
|---|
| 347 | ram_en <='1'; |
|---|
| 348 | ram_we <='0'; |
|---|
| 349 | dma_wr_grant<=(others=>'0'); |
|---|
| 350 | dma_rd_grant<=(others=>'0'); |
|---|
| 351 | dma_rd_grant(pri_rd)<='1'; |
|---|
| 352 | |
|---|
| 353 | --address_out_rd <= address_rd; |
|---|
| 354 | --address_out_wr <= (others=>'Z'); |
|---|
| 355 | --hold_req<='1'; |
|---|
| 356 | when others => |
|---|
| 357 | ram_en <='0'; |
|---|
| 358 | ram_we <='0'; |
|---|
| 359 | dma_wr_grant <=(others=>'0'); |
|---|
| 360 | dma_rd_grant <=(others=>'0'); |
|---|
| 361 | --address_out_rd <= (others=>'Z'); |
|---|
| 362 | --address_out_wr <= (others=>'Z'); |
|---|
| 363 | --hold_req<='0'; |
|---|
| 364 | end case; |
|---|
| 365 | end process; |
|---|
| 366 | |
|---|
| 367 | |
|---|
| 368 | end Behavioral; |
|---|
| 369 | |
|---|