[15] | 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 | |
---|