source: PROJECT_CORE_MPI/CORE_MPI/BRANCHES/v0.04/DMA_ARBITER.vhd

Last change on this file was 64, checked in by rolagamo, 12 years ago
File size: 15.0 KB
Line 
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-- Revision 1.2 - 19/03/2013
20-- Correction de bugs et optimisation du nombre de cycles
21--      Création d'un testbench                                 
22-- Additional Comments: Ce module pourra être optimisé pour générer les adresses automatiquement
23-- par le controleur DMA lorsqu'il est sollicité par la périphérie
24--
25----------------------------------------------------------------------------------
26library IEEE;
27library NocLib;
28use IEEE.STD_LOGIC_1164.ALL;
29use IEEE.STD_LOGIC_ARITH.ALL;
30use IEEE.STD_LOGIC_UNSIGNED.ALL;
31use IEEE.numeric_std.all; 
32use NocLib.CoreTypes.all;
33---- Uncomment the following library declaration if instantiating
34---- any Xilinx primitives in this code.
35--library UNISIM;
36--use UNISIM.VComponents.all;
37
38entity DMA_ARBITER is
39    Port ( dma_rd_request : in  STD_LOGIC_VEctor (3 downto 0):=(others=>'0');
40           data_wr_in : in  STD_LOGIC_VECTOR (Word-1 downto 0);
41           data_rd_out : out  STD_LOGIC_VECTOR (Word-1 downto 0);
42           address_rd : in  STD_LOGIC_VECTOR (ADRLEN-1 downto 0); --adresse pour lecture
43           address_wr : in  STD_LOGIC_VECTOR (ADRLEN-1 downto 0); -- adresse pour écriture
44           address_out_wr : out  STD_LOGIC_VECTOR (ADRLEN-1 downto 0); -- adresse de sortie du DMA Arbiter
45                          address_out_rd : out  STD_LOGIC_VECTOR (ADRLEN-1 downto 0);
46           ram_en : out  STD_LOGIC; --
47           ram_we : out  STD_LOGIC;
48           data_wr_mem : out  STD_LOGIC_VECTOR (Word-1 downto 0); -- donnée en sortie écriture
49           data_rd_mem : in  STD_LOGIC_VECTOR (Word-1 downto 0); -- données en sortie lecture
50           dma_wr_grant : out  STD_LOGIC_vector(3 downto 0):=(others=>'0'); -- autorisation d'écriture
51                          hold_req       : out STD_Logic;  --requete vers application
52                          hold_ack       : in  STD_Logic;  --autorisation par l'application
53                          clk           : in std_logic;
54                          reset             : in std_logic;
55           dma_rd_grant : out  STD_LOGIC_vector(3 downto 0):=(others=>'0');  -- autorisation de lecture
56           dma_wr_request : in  STD_LOGIC_vector(3 downto 0):=(others=>'0')); -- demande de lecture
57end DMA_ARBITER;
58
59architecture Behavioral of DMA_ARBITER is
60type fsm_states is (idle,wait_ack,arbiter_ack, writing,ReadWrite,reading);-- definition du type etat pour le codage des etats des fsm
61signal dmac_state : fsm_states;
62
63signal prio_rd,prio_wr:std_logic_vector(3 downto 0);--vecteur de bits de priorité
64signal pri_rd,pri_wr : natural range 0 to 3; -- stocke le numéro du module qui a la priorité
65signal dma_rd_logic : std_logic_vector(3 downto 0):=(others=>'0');
66signal dma_wr_logic : std_logic_vector(3 downto 0):=(others=>'0');
67signal dma_rd_latch,dma_wr_latch: std_logic_vector(3 downto 0):=(others=>'0');
68signal dma_req_wr, dma_req_rd : std_logic;
69signal last_grant_rd,last_grant_wr : STD_LOGIC_vector(3 downto 0):=(others=>'0');
70signal tmp :std_logic_vector(3 downto 0):="0000";
71
72begin
73--==========================================================================
74---le MUX qui contrôle les adresses est géré à l'extérieur du contrôleur DMA
75dma_sync: process (clk)
76begin
77data_rd_out<=data_rd_mem ;
78data_wr_mem <= data_wr_in;
79address_out_rd <= address_rd;
80address_out_wr <= address_wr;
81
82end process;
83--dma_rd_grant<= dma_rd_logic;
84--dma_wr_grant<= dma_wr_logic;
85dma_rd_grant<= dma_rd_latch;
86dma_wr_grant<= dma_wr_latch;
87--==========================================================================
88
89--Déterminer si une requête HOLD doit être émise vers l'application pour la libération du
90--bus mémoire
91tmp<=(others =>'0');
92
93--for  i in 0 to 3 loop
94--dma_req_wr<=dma_req_wr or dma_wr_request(i);
95--loop;
96
97--for  i in 0 to 3 loop
98-- dma_req_rd<=dma_req_rd or dma_rd_request(i);  -- construire le signal request vers l'extérieur
99--loop;
100hold_req<='1' when dma_req_rd='1' or dma_req_wr='1' else '0'; --envoyer un Hold vers l'application
101
102
103-- machine à etat du DMAC
104dmac_process : process(clk,reset)
105--variable tmp : natural range 0 to 15;
106variable tmp_rd,tmp_wr: std_logic_vector(3 downto 0);
107variable  req_rd,req_wr : std_logic:='0' ;
108
109begin 
110        if rising_edge(clk) then 
111         if reset = '1' then
112                                dmac_state<= idle;
113                               
114                                prio_rd <="0001"; -- au debut priorité lecture au premier module
115                                prio_wr <="0010"; -- au debut priorité ecriture au deuxième module
116                                pri_rd<=0;--index de la priorité
117                                pri_wr<=1;
118                                req_rd:='0';
119                                req_wr:='0';
120          else 
121                                if req_wr='0'  then --tant que le Ctrl DMA est libre alors faire bouger la priorité en écriture
122                                case dma_wr_request is
123                                when "0001" => pri_wr<=0;
124                                                                        prio_wr<="0001";
125                                                                        req_wr:='1';
126                                                                        dma_req_wr<= '1';
127                                                                        dma_wr_logic <="0001";
128                                when "0010" => pri_wr<=1;
129                                                                        prio_wr<="0010";
130                                                                        req_wr:='1';
131                                                                        dma_req_wr<= '1';
132                                                                        dma_wr_logic <="0010";
133                                when "0100" => pri_wr<=2;
134                                                                        prio_wr<="0100";
135                                                                        req_wr:='1';
136                                                                        dma_req_wr<= '1';
137                                                                        dma_wr_logic <="0100";
138                                when "1000" => pri_wr<=3;
139                                                                        prio_wr<="1000";
140                                                                        req_wr:='1';
141                                                                        dma_req_wr<= '1';
142                                                                        dma_wr_logic <="1000";
143                                                                       
144                                when others => 
145                                                                        if req_rd='1' then --demande simultané de lecture et d'écriture
146                                                                       
147                                                                                if dma_rd_request(pri_rd)='1'  then
148                                                                                                pri_wr<=pri_rd;
149                                                                                                req_wr:='1';
150                                                                                                for i in 0 to 3 loop
151                                                                                                 if i=pri_rd then
152                                                                                                  prio_wr(i)<='1';
153                                                                                                  dma_wr_logic(i)<='1';
154                                                                                                 else
155                                                                                                        prio_wr(i)<='0';
156                                                                                                   dma_wr_logic(i)<='0';
157                                                                                                 end if;
158                                                                                                end loop;
159                                                                                               
160                                                                                               
161                                                                                end if;
162                                                                               
163                                                                        else --on affecte l'accè à la mémoire suivant le round robbin
164                                                                                tmp_wr:= (dma_wr_request and prio_wr) ;
165                                                                                dma_wr_logic <=tmp_wr;
166                                                                               
167                                                                                req_wr:= not(All_zeros(tmp_wr)); 
168                                                                                dma_req_wr<= not(All_zeros(tmp_wr)); 
169                                                                        end if;
170                                                                        -- la priorité est circulaire et décale à chaque coup d'horloge
171                                                                        if req_wr='0' then
172                                                                                prio_wr<=rol_vec(prio_wr); 
173                                                                                if pri_wr=3 then
174                                                                                        pri_wr<=0;
175                                                                                        Prio_wr<="0001";
176                                                                                else
177                                                                                        pri_wr<=pri_wr+1;
178                                                                                end if;
179                                                                 end if;
180                                end case;
181                                else   --req_wr='1'
182                               
183                                 --demande simultané de lecture et d'écriture
184                                                                       
185                                                                                if dma_rd_request(pri_wr)='1'  then
186                                                                                                pri_rd<=pri_wr;
187                                                                                                req_rd:='1';
188                                                                                                prio_rd<=prio_wr;
189--                                                                                              for i in 0 to 3 loop
190--                                                                                               if i=pri_rd then
191--                                                                                                prio_wr(i)<='1';
192--                                                                                                dma_wr_logic(i)<='1';
193--                                                                                               else
194--                                                                                                      prio_wr(i)<='0';
195--                                                                                                 dma_wr_logic(i)<='0';
196--                                                                                               end if;
197--                                                                                              end loop;                                       
198                                                                                               
199                                                                                end if;
200
201                                end if;
202                               
203                                if req_rd='0'  then --tant que le Ctrl DMA est libre alors faire bouger la priorité
204                                case dma_rd_request is
205                                when "0001" => pri_rd<=0;
206                                                                        prio_rd<="0001";
207                                                                        req_rd:='1';
208                                                                        dma_req_rd<= '1';
209                                                                        dma_rd_logic<="0001";
210                                when "0010" => pri_rd<=1;
211                                                                        prio_rd<="0010";
212                                                                        req_rd:='1';
213                                                                        dma_req_rd<= '1';
214                                                                        dma_rd_logic<="0010";
215                                                                       
216                                when "0100" => pri_rd<=2;
217                                                                        prio_rd<="0100";
218                                                                        req_rd:='1';
219                                                                        dma_req_rd<= '1';
220                                                                        dma_rd_logic<="0100";
221                                                                       
222                                when "1000" => pri_rd<=3;
223                                                                        prio_rd<="1000";
224                                                                        req_rd:='1';
225                                                                        dma_req_rd<= '1';
226                                                                        dma_rd_logic<="1000";
227                                                                       
228                                when others => 
229                                                                        --si une demande survient de la part d'un composant déjà acquitté alors celui-ci est prioritaire
230                                                                        if req_wr='1' then
231                                                                       
232                                                                                if dma_rd_request(pri_wr)='1'  then
233                                                                                                pri_rd<=pri_wr;
234                                                                                                req_rd:='1';
235                                                                                                for i in 0 to 3 loop
236                                                                                                 if i=pri_wr then
237                                                                                                  prio_rd(i)<='1';
238                                                                                                  dma_rd_logic(i)<='1';
239                                                                                                 else
240                                                                                                        prio_rd(i)<='0';
241                                                                                                   dma_rd_logic(i)<='0';
242                                                                                                 end if;
243                                                                                                end loop;
244                                                                                               
245                                                                                               
246                                                                                end if;
247                                                                               
248                                                                        else
249                                                                                tmp_rd:= (dma_rd_request and prio_rd) ; 
250                                                                                dma_rd_logic<=tmp_rd;
251                                                                                dma_req_rd<= not (All_Zeros(tmp_rd));
252                                                                                req_rd:= not (All_Zeros(tmp_rd));
253                                                                        end if;
254                                                                -- la priorité est circulaire et décale à chaque coup d'horloge
255                                                                        if req_rd='0' then
256                                                                                prio_rd<=rol_vec(prio_rd);
257                                                                                if pri_rd =3 then
258                                                                                        pri_rd<=0;
259                                                                                        prio_rd<="0001";
260                                                                                else
261                                                                                       
262                                                                                        pri_rd<=pri_rd+1;
263                                                                                end if;
264                                                                        end if;
265                                end case;
266                               
267                           end if;
268           
269                  case dmac_state is
270                   when idle => if req_rd='1' or req_wr='1' then
271                                                                        dmac_state<=wait_ack; 
272                                                        else -- initialiser la priorité
273                                                                       
274                                                                       
275                                                                        req_rd:='0';
276                                                                        dma_req_rd<= '0';
277                                                                       
278                                                                       
279                                                                       
280                                                                        req_wr:='0';
281                                                                        dma_req_wr<= '0';
282                                                                       
283                                                                        dma_wr_logic <="0000"; --aucun accès mémoire n'est accrédité
284                                                                        dma_rd_logic <="0000";
285                                                                                       
286                                                        end if;
287                                                       
288                        when wait_ack =>  -- l'application doit autoriser l'utilisation de la RAM par le Core
289                                                if dma_wr_request(pri_wr) ='1' or dma_rd_request(pri_rd) ='1' then
290                                                        if hold_ack='1' then
291                                                                --dmac_state<=arbiter_ack;
292                                                                if dma_wr_request(pri_wr) ='1' and dma_rd_request(pri_rd) ='1' then --
293                                                                        dmac_state <= Readwrite;
294                                                                 elsif dma_wr_request(pri_wr) ='0' and dma_rd_request(pri_rd) ='1' then
295                                                                                        dmac_state <= Reading;
296                                                                elsif dma_wr_request(pri_wr) ='1' and dma_rd_request(pri_rd) ='0' then
297                                                                                        dmac_state <= Writing;
298                                                                else
299                                                                                        dmac_state<=Idle;
300                                                                end if;
301                                                        end if;
302                                                else
303                                                       
304                                                        if dma_wr_request(pri_wr) ='0' then
305                                                        req_wr:='0';-- forcer une nouvelle recherche de priorité
306                                                        end if;
307                                                       
308                                                        if dma_rd_request(pri_rd) ='0' then
309                                                                req_rd:='0';
310                                                        end if;
311                                                        dmac_state<=Idle;
312                                                end if;
313                                               
314                               
315                        when arbiter_ack => 
316--                                                      if dma_wr_request(pri_wr) ='1' and dma_rd_request(pri_rd) ='1' then --
317--                                                                      dmac_state <= Readwrite;
318--                                                               elsif dma_wr_request(pri_wr) ='0' and dma_rd_request(pri_rd) ='1' then
319--                                                                                      dmac_state <= Reading;
320--                                                              elsif dma_wr_request(pri_wr) ='1' and dma_rd_request(pri_rd) ='0' then
321--                                                                                      dmac_state <= Writing;
322--                                                              else
323                                                                                        dmac_state<=Idle;
324--                                                              end if;
325                                                                -- cet état a été combiné au précédent pour gagner un cycle
326                        when Writing => if dma_wr_request(pri_wr) ='1' then
327                                                                                if hold_ack='1' then 
328                                                                                    -- on reste dans cet état
329                                                                                 if dma_rd_request(pri_rd)='1' then
330                                                                                                dmac_state<=ReadWrite;
331                                                                                 else
332                                                                                                req_rd:='0';
333                                                                                 end if;
334                                                                                else
335                                                                                        dmac_state<=wait_ack; 
336                                                                                end if;
337                                                                 elsif dma_rd_request(pri_rd) ='1' then
338                                                                                dmac_state <= Reading;
339                                                                                req_wr:='0';
340                                                                 else
341                                                                                dmac_state <= idle;
342                                                                                req_wr:='0';
343                                                                end if;
344                       
345                       
346                        when ReadWrite => if hold_ack='1' then
347                                                                                  if dma_wr_request(pri_wr)='1' and dma_rd_request(pri_rd)='1' then
348                                                                                                dmac_state <= ReadWrite;
349                                                                                        elsif dma_wr_request(pri_wr)='1' and dma_rd_request(pri_rd)='0' then 
350                                                                                                dmac_state <= Writing;
351                                                                                                req_rd:='0';
352                                                                                        elsif dma_wr_request(pri_wr)='0' and dma_rd_request(pri_rd)='1' then
353                                                                                                dmac_state <= Reading;
354                                                                                                req_wr:='0';
355                                                                                        else
356                                                                                                dmac_state <= Idle;
357                                                                                                req_rd:='0';req_wr:='0';
358                                                                                        end if;
359                                                                         else 
360                                                                                        if (dma_wr_request(pri_wr)='1') or (dma_rd_request(pri_rd)='1') then
361                                                                                                        dmac_state <= Wait_ack;
362                                                                                        else
363                                                                                                dmac_state <= Idle;
364                                                                                        end if;
365                                                                        end if;
366                        when Reading => 
367                                                                 if dma_rd_request(pri_rd) ='1' then
368                                                                                if hold_ack='1' then 
369                                                                                    -- on reste dans cet état
370                                                                                         if dma_wr_request(pri_wr)='1' then
371                                                                                                dmac_state<=ReadWrite;
372                                                                                        else
373                                                                                                req_wr:='0';
374                                                                                        end if;
375                                                                                else
376                                                                                        dmac_state<=wait_ack; 
377                                                                                end if;
378                                                                 elsif dma_wr_request(pri_wr) ='1' then
379                                                                                dmac_state<=writing;
380                                                                                req_rd:='0';
381                                                                 else
382                                                                                dmac_state <= idle;
383                                                                                req_rd:='0';
384                                                                end if;
385                        when others => dmac_state <= idle;
386                   end case;
387         end if;
388        end if;
389end process;
390-- action_asociées
391ol: process(dmac_state, address_rd, address_wr,pri_wr,pri_rd,prio_wr,prio_rd,dma_wr_request,dma_rd_request)
392
393begin
394--tester les requêtes DMA en lecture ou en écriture
395
396case dmac_state is
397                when idle => 
398                                                        ram_en <='0';
399                                                        ram_we <='0';
400                                                        dma_wr_latch <=(others=>'0');
401                                                        dma_rd_latch <=(others=>'0');
402                                                        --address_out_rd <= address_rd;
403                                                        --hold_req<='0';
404                when wait_ack =>
405                                                        ram_en <='0';
406                                                        ram_we <='0';
407                                                        dma_wr_latch<=(others=>'0');
408                                                        dma_rd_latch<=(others=>'0');
409                                                        --address_out_rd <= (others=>'Z');
410                                                        --address_out_wr <= (others=>'Z');
411                                                        --hold_req<='1';
412                when arbiter_ack =>  --à optimiser pour gagner un cycle
413                                                        ram_en <='0';
414                                                        ram_we <='0';
415                                                        dma_wr_latch<=(others=>'0');
416                                                        dma_rd_latch<=(others=>'0');
417                                                        --address_out_rd <= (others=>'Z');
418                                                        --address_out_wr <= (others=>'Z');
419                when writing => -- ecriture dans la ram
420                                                        ram_en <='1';
421                                                        ram_we <='1';
422                                                        dma_wr_latch<=(others=>'0');
423                                                        dma_wr_latch(pri_wr) <='1';
424                                                        dma_rd_latch <=(others=>'0');
425                                                        --address_out_rd <= (others=>'Z');
426                                                        --address_out_wr <= address_wr;
427                                                        --hold_req<='1';                                                       
428                                                       
429                when ReadWrite => -- Lecture et écriture simultannée dans la Dual Port RAM
430                                                        ram_en <='1';
431                                                        ram_we <='1';
432                                                        dma_wr_latch<=(others=>'0');
433                                                        dma_wr_latch(pri_wr) <='1';
434                                                        dma_rd_latch<=(others=>'0');
435                                                        dma_rd_latch(pri_rd)<='1';
436                                                       
437                                                        --address_out_rd <= address_rd;
438                                                        --address_out_wr <= address_wr;
439                                                        --hold_req<='1';                                                       
440                when Reading => -- lecture dans la ram
441                                                        ram_en <='1';
442                                                        ram_we <='0';
443                                                        dma_wr_latch<=(others=>'0');
444                                                        dma_rd_latch<=(others=>'0');
445                                                        dma_rd_latch(pri_rd)<='1';
446                                                       
447                                                        --address_out_rd <= address_rd;
448                                                        --address_out_wr <= (others=>'Z');
449                                                        --hold_req<='1';
450                when others => 
451                                                   ram_en <='0';
452                                                        ram_we <='0';
453                                                        dma_wr_latch <=(others=>'0');
454                                                        dma_rd_latch <=(others=>'0');
455                                                        --address_out_rd <= (others=>'Z');
456                                                        --address_out_wr <= (others=>'Z');
457                                                        --hold_req<='0';
458                end case;
459end process;
460
461
462end Behavioral;
463
Note: See TracBrowser for help on using the repository browser.