source: PROJECT_CORE_MPI/MPI_HCL/BRANCHES/v2.1/CORE_MPI/DMA_ARBITER.vhd @ 155

Last change on this file since 155 was 142, checked in by rolagamo, 10 years ago
File size: 14.9 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,data_rd_mem,data_wr_in,address_rd,address_wr)
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;
100req_process:process(reset,dma_req_rd,dma_req_wr)
101begin
102  if reset='1' then
103    hold_req<='0';
104else
105  if dma_req_rd='1' or dma_req_wr='1' then
106    hold_req<='1';
107else
108    hold_req<='0';
109end if;
110end if;
111 
112end process;
113--hold_req<='1' when dma_req_rd='1' or dma_req_wr='1' else '0'; --envoyer un Hold vers l'application
114
115
116-- machine à etat du DMAC
117dmac_process : process(clk,reset)
118--variable tmp : natural range 0 to 15;
119variable tmp_rd,tmp_wr: std_logic_vector(3 downto 0);
120variable  req_rd,req_wr : std_logic:='0' ;
121
122begin 
123        if rising_edge(clk) then 
124         if reset = '1' then
125                                dmac_state<= idle;
126                                dma_wr_logic <="0000";
127                                dma_rd_logic <="0000";
128                                prio_rd <="0001"; -- au debut priorité lecture au premier module
129                                prio_wr <="0010"; -- au debut priorité ecriture au deuxième module
130                                pri_rd<=0;--index de la priorité
131                                pri_wr<=1;
132                                req_rd:='0';
133                                req_wr:='0';
134                                dma_req_wr<= '0';
135                                dma_req_rd<= '0';
136          else 
137                                if req_wr='0'  then --tant que le Ctrl DMA est libre alors faire bouger la priorité en écriture
138                                case dma_wr_request is
139                                when "0001" => pri_wr<=0;
140                                                                        prio_wr<="0001";
141                                                                        req_wr:='1';
142                                                                        dma_req_wr<= '1';
143                                                                        dma_wr_logic <="0001";
144                                when "0010" => pri_wr<=1;
145                                                                        prio_wr<="0010";
146                                                                        req_wr:='1';
147                                                                        dma_req_wr<= '1';
148                                                                        dma_wr_logic <="0010";
149                                when "0100" => pri_wr<=2;
150                                                                        prio_wr<="0100";
151                                                                        req_wr:='1';
152                                                                        dma_req_wr<= '1';
153                                                                        dma_wr_logic <="0100";
154                                when "1000" => pri_wr<=3;
155                                                                        prio_wr<="1000";
156                                                                        req_wr:='1';
157                                                                        dma_req_wr<= '1';
158                                                                        dma_wr_logic <="1000";
159                                                                       
160                                when others => 
161                                                                        if req_rd='1' then --demande simultané de lecture et d'écriture
162                                                                       
163                                                                                if dma_rd_request(pri_rd)='1'  then
164                                                                                                pri_wr<=pri_rd;
165                                                                                                req_wr:='1';
166                                                                                                for i in 0 to 3 loop
167                                                                                                 if i=pri_rd then
168                                                                                                  prio_wr(i)<='1';
169                                                                                                  dma_wr_logic(i)<='1';
170                                                                                                 else
171                                                                                                        prio_wr(i)<='0';
172                                                                                                   dma_wr_logic(i)<='0';
173                                                                                                 end if;
174                                                                                                end loop;
175                                                                                               
176                                                                                               
177                                                                                end if;
178                                                                               
179                                                                        else --on affecte l'accè à la mémoire suivant le round robbin
180                                                                                tmp_wr:= (dma_wr_request and prio_wr) ;
181                                                                                dma_wr_logic <=tmp_wr;
182                                                                               
183                                                                                req_wr:= not(All_zeros(tmp_wr)); 
184                                                                                dma_req_wr<= not(All_zeros(tmp_wr)); 
185                                                                        end if;
186                                                                        -- la priorité est circulaire et décale à chaque coup d'horloge
187                                                                        if req_wr='0' then
188                                                                                prio_wr<=rol_vec(prio_wr); 
189                                                                                if pri_wr=3 then
190                                                                                        pri_wr<=0;
191                                                                                        Prio_wr<="0001";
192                                                                                else
193                                                                                        pri_wr<=pri_wr+1;
194                                                                                end if;
195                                                                 end if;
196                                end case;
197                                else   --req_wr='1'
198                               
199                                 --demande simultané de lecture et d'écriture
200                                                                       
201                                                                                if dma_rd_request(pri_wr)='1'  then
202                                                                                                pri_rd<=pri_wr;
203                                                                                                req_rd:='1';
204                                                                                                prio_rd<=prio_wr;
205--                                                                                              for i in 0 to 3 loop
206--                                                                                               if i=pri_rd then
207--                                                                                                prio_wr(i)<='1';
208--                                                                                                dma_wr_logic(i)<='1';
209--                                                                                               else
210--                                                                                                      prio_wr(i)<='0';
211--                                                                                                 dma_wr_logic(i)<='0';
212--                                                                                               end if;
213--                                                                                              end loop;                                       
214                                                                                               
215                                                                                end if;
216
217                                end if;
218                               
219                                if req_rd='0'  then --tant que le Ctrl DMA est libre alors faire bouger la priorité
220                                case dma_rd_request is
221                                when "0001" => pri_rd<=0;
222                                                                        prio_rd<="0001";
223                                                                        req_rd:='1';
224                                                                        dma_req_rd<= '1';
225                                                                        dma_rd_logic<="0001";
226                                when "0010" => pri_rd<=1;
227                                                                        prio_rd<="0010";
228                                                                        req_rd:='1';
229                                                                        dma_req_rd<= '1';
230                                                                        dma_rd_logic<="0010";
231                                                                       
232                                when "0100" => pri_rd<=2;
233                                                                        prio_rd<="0100";
234                                                                        req_rd:='1';
235                                                                        dma_req_rd<= '1';
236                                                                        dma_rd_logic<="0100";
237                                                                       
238                                when "1000" => pri_rd<=3;
239                                                                        prio_rd<="1000";
240                                                                        req_rd:='1';
241                                                                        dma_req_rd<= '1';
242                                                                        dma_rd_logic<="1000";
243                                                                       
244                                when others => 
245                                                                        --si une demande survient de la part d'un composant déjà acquitté alors celui-ci est prioritaire
246                                                                        if req_wr='1' then
247                                                                       
248                                                                                if dma_rd_request(pri_wr)='1'  then
249                                                                                                pri_rd<=pri_wr;
250                                                                                                req_rd:='1';
251                                                                                                for i in 0 to 3 loop
252                                                                                                 if i=pri_wr then
253                                                                                                  prio_rd(i)<='1';
254                                                                                                  dma_rd_logic(i)<='1';
255                                                                                                 else
256                                                                                                        prio_rd(i)<='0';
257                                                                                                   dma_rd_logic(i)<='0';
258                                                                                                 end if;
259                                                                                                end loop;
260                                                                                               
261                                                                                               
262                                                                                end if;
263                                                                               
264                                                                        else
265                                                                                tmp_rd:= (dma_rd_request and prio_rd) ; 
266                                                                                dma_rd_logic<=tmp_rd;
267                                                                                dma_req_rd<= not (All_Zeros(tmp_rd));
268                                                                                req_rd:= not (All_Zeros(tmp_rd));
269                                                                        end if;
270                                                                -- la priorité est circulaire et décale à chaque coup d'horloge
271                                                                        if req_rd='0' then
272                                                                                prio_rd<=rol_vec(prio_rd);
273                                                                                if pri_rd =3 then
274                                                                                        pri_rd<=0;
275                                                                                        prio_rd<="0001";
276                                                                                else
277                                                                                       
278                                                                                        pri_rd<=pri_rd+1;
279                                                                                end if;
280                                                                        end if;
281                                end case;
282                               
283                           end if;
284           
285                  case dmac_state is
286                   when idle => if req_rd='1' or req_wr='1' then
287                                                                        dmac_state<=wait_ack; 
288                                                        else -- initialiser la priorité
289                                                                       
290                                                                       
291                                                                        req_rd:='0';
292                                                                        dma_req_rd<= '0';
293                                                                       
294                                                                       
295                                                                       
296                                                                        req_wr:='0';
297                                                                        dma_req_wr<= '0';
298                                                                       
299                                                                        dma_wr_logic <="0000"; --aucun accès mémoire n'est accrédité
300                                                                        dma_rd_logic <="0000";
301                                                                                       
302                                                        end if;
303                                                       
304                        when wait_ack =>  -- l'application doit autoriser l'utilisation de la RAM par le Core
305                                                if dma_wr_request(pri_wr) ='1' or dma_rd_request(pri_rd) ='1' then
306                                                        if hold_ack='1' then
307                                                                --dmac_state<=arbiter_ack;
308                                                                if dma_wr_request(pri_wr) ='1' and dma_rd_request(pri_rd) ='1' then --
309                                                                        dmac_state <= Readwrite;
310                                                                 elsif dma_wr_request(pri_wr) ='0' and dma_rd_request(pri_rd) ='1' then
311                                                                                        dmac_state <= Reading;
312                                                                elsif dma_wr_request(pri_wr) ='1' and dma_rd_request(pri_rd) ='0' then
313                                                                                        dmac_state <= Writing;
314                                                                else
315                                                                                        dmac_state<=Idle;
316                                                                end if;
317                                                        end if;
318                                                else
319                                                       
320                                                        if dma_wr_request(pri_wr) ='0' then
321                                                        req_wr:='0';-- forcer une nouvelle recherche de priorité
322                                                        end if;
323                                                       
324                                                        if dma_rd_request(pri_rd) ='0' then
325                                                                req_rd:='0';
326                                                        end if;
327                                                        dmac_state<=Idle;
328                                                end if;
329                                               
330                               
331                        when arbiter_ack => 
332--                                                      if dma_wr_request(pri_wr) ='1' and dma_rd_request(pri_rd) ='1' then --
333--                                                                      dmac_state <= Readwrite;
334--                                                               elsif dma_wr_request(pri_wr) ='0' and dma_rd_request(pri_rd) ='1' then
335--                                                                                      dmac_state <= Reading;
336--                                                              elsif dma_wr_request(pri_wr) ='1' and dma_rd_request(pri_rd) ='0' then
337--                                                                                      dmac_state <= Writing;
338--                                                              else
339                                                                                        dmac_state<=Idle;
340--                                                              end if;
341                                                                -- cet état a été combiné au précédent pour gagner un cycle
342                        when Writing => if dma_wr_request(pri_wr) ='1' then
343                                                                                if hold_ack='1' then 
344                                                                                    -- on reste dans cet état
345                                                                                 if dma_rd_request(pri_rd)='1' then
346                                                                                                dmac_state<=ReadWrite;
347                                                                                 else
348                                                                                                req_rd:='0';
349                                                                                 end if;
350                                                                                else
351                                                                                        dmac_state<=wait_ack; 
352                                                                                end if;
353                                                                 elsif dma_rd_request(pri_rd) ='1' then
354                                                                                dmac_state <= Reading;
355                                                                                req_wr:='0';
356                                                                 else
357                                                                                dmac_state <= idle;
358                                                                                req_wr:='0';
359                                                                end if;
360                       
361                       
362                        when ReadWrite => if hold_ack='1' then
363                                                                                  if dma_wr_request(pri_wr)='1' and dma_rd_request(pri_rd)='1' then
364                                                                                                dmac_state <= ReadWrite;
365                                                                                        elsif dma_wr_request(pri_wr)='1' and dma_rd_request(pri_rd)='0' then 
366                                                                                                dmac_state <= Writing;
367                                                                                                req_rd:='0';
368                                                                                        elsif dma_wr_request(pri_wr)='0' and dma_rd_request(pri_rd)='1' then
369                                                                                                dmac_state <= Reading;
370                                                                                                req_wr:='0';
371                                                                                        else
372                                                                                                dmac_state <= Idle;
373                                                                                                req_rd:='0';req_wr:='0';
374                                                                                        end if;
375                                                                         else 
376                                                                                        if (dma_wr_request(pri_wr)='1') or (dma_rd_request(pri_rd)='1') then
377                                                                                                        dmac_state <= Wait_ack;
378                                                                                        else
379                                                                                                dmac_state <= Idle;
380                                                                                        end if;
381                                                                        end if;
382                        when Reading => 
383                                                                 if dma_rd_request(pri_rd) ='1' then
384                                                                                if hold_ack='1' then 
385                                                                                    -- on reste dans cet état
386                                                                                         if dma_wr_request(pri_wr)='1' then
387                                                                                                dmac_state<=ReadWrite;
388                                                                                        else
389                                                                                                req_wr:='0';
390                                                                                        end if;
391                                                                                else
392                                                                                        dmac_state<=wait_ack; 
393                                                                                end if;
394                                                                 elsif dma_wr_request(pri_wr) ='1' then
395                                                                                dmac_state<=writing;
396                                                                                req_rd:='0';
397                                                                 else
398                                                                                dmac_state <= idle;
399                                                                                req_rd:='0';
400                                                                end if;
401                        when others => dmac_state <= idle;
402                   end case;
403         end if;
404        end if;
405end process;
406-- action_asociées
407ol: process(dmac_state, address_rd, address_wr,pri_wr,pri_rd,prio_wr,prio_rd,dma_wr_request,dma_rd_request)
408
409begin
410--tester les requêtes DMA en lecture ou en écriture
411
412case dmac_state is
413                when idle => 
414                                                        ram_en <='0';
415                                                        ram_we <='0';
416                                                        dma_wr_latch <=(others=>'0');
417                                                        dma_rd_latch <=(others=>'0');
418                                                        --address_out_rd <= address_rd;
419                                                        --hold_req<='0';
420                when wait_ack =>
421                                                        ram_en <='0';
422                                                        ram_we <='0';
423                                                        dma_wr_latch<=(others=>'0');
424                                                        dma_rd_latch<=(others=>'0');
425                                                        --address_out_rd <= (others=>'Z');
426                                                        --address_out_wr <= (others=>'Z');
427                                                        --hold_req<='1';
428                when arbiter_ack =>  --à optimiser pour gagner un cycle
429                                                        ram_en <='0';
430                                                        ram_we <='0';
431                                                        dma_wr_latch<=(others=>'0');
432                                                        dma_rd_latch<=(others=>'0');
433                                                        --address_out_rd <= (others=>'Z');
434                                                        --address_out_wr <= (others=>'Z');
435                when writing => -- ecriture dans la ram
436                                                        ram_en <='1';
437                                                        ram_we <='1';
438                                                        dma_wr_latch<=(others=>'0');
439                                                        dma_wr_latch(pri_wr) <='1';
440                                                        dma_rd_latch <=(others=>'0');
441                                                        --address_out_rd <= (others=>'Z');
442                                                        --address_out_wr <= address_wr;
443                                                        --hold_req<='1';                                                       
444                                                       
445                when ReadWrite => -- Lecture et écriture simultannée dans la Dual Port RAM
446                                                        ram_en <='1';
447                                                        ram_we <='1';
448                                                        dma_wr_latch<=(others=>'0');
449                                                        dma_wr_latch(pri_wr) <='1';
450                                                        dma_rd_latch<=(others=>'0');
451                                                        dma_rd_latch(pri_rd)<='1';
452                                                       
453                                                        --address_out_rd <= address_rd;
454                                                        --address_out_wr <= address_wr;
455                                                        --hold_req<='1';                                                       
456                when Reading => -- lecture dans la ram
457                                                        ram_en <='1';
458                                                        ram_we <='0';
459                                                        dma_wr_latch<=(others=>'0');
460                                                        dma_rd_latch<=(others=>'0');
461                                                        dma_rd_latch(pri_rd)<='1';
462                                                       
463                                                        --address_out_rd <= address_rd;
464                                                        --address_out_wr <= (others=>'Z');
465                                                        --hold_req<='1';
466                when others => 
467                                                   ram_en <='0';
468                                                        ram_we <='0';
469                                                        dma_wr_latch <=(others=>'0');
470                                                        dma_rd_latch <=(others=>'0');
471                                                        --address_out_rd <= (others=>'Z');
472                                                        --address_out_wr <= (others=>'Z');
473                                                        --hold_req<='0';
474                end case;
475end process;
476
477
478end Behavioral;
479
Note: See TracBrowser for help on using the repository browser.