source: PROJECT_CORE_MPI/CORE_MPI/BRANCHES/v0.03/DMA_ARBITER.vhd @ 44

Last change on this file since 44 was 41, checked in by rolagamo, 12 years ago

Ceci est la version stable avant optimisation

File size: 13.3 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-- 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----------------------------------------------------------------------------------
23library IEEE;
24library NocLib;
25use IEEE.STD_LOGIC_1164.ALL;
26use IEEE.STD_LOGIC_ARITH.ALL;
27use IEEE.STD_LOGIC_UNSIGNED.ALL;
28use IEEE.numeric_std.all; 
29use 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
35entity 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
54end DMA_ARBITER;
55
56architecture Behavioral of DMA_ARBITER is
57type fsm_states is (idle,wait_ack,arbiter_ack, writing,ReadWrite,reading);-- definition du type etat pour le codage des etats des fsm
58signal dmac_state : fsm_states;
59
60signal prio_rd,prio_wr:std_logic_vector(3 downto 0);--vecteur de bits de priorité
61signal pri_rd,pri_wr : natural range 0 to 3; -- stocke le numéro du module qui a la priorité
62signal dma_rd_logic : std_logic_vector(3 downto 0):=(others=>'0');
63signal dma_wr_logic : std_logic_vector(3 downto 0):=(others=>'0');
64signal dma_req_wr, dma_req_rd : std_logic;
65signal tmp :std_logic_vector(3 downto 0):="0000";
66
67begin
68--==========================================================================
69---le MUX qui contrôle les adresses est géré à l'extérieur du contrôleur DMA
70data_rd_out<=data_rd_mem ;
71data_wr_mem <= data_wr_in;
72address_out_rd <= address_rd;
73address_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
78tmp<=(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;
87hold_req<=dma_req_rd or dma_req_wr; --envoyer un Hold vers l'application
88
89
90-- machine à etat du DMAC
91dmac_process : process(clk)
92--variable tmp : natural range 0 to 15;
93variable tmp_rd,tmp_wr: std_logic_vector(3 downto 0);
94variable  req_rd,req_wr : std_logic:='0' ;
95
96begin 
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 => 
132                                                                        if req_rd='1' then
133                                                                       
134                                                                                if dma_rd_request(pri_rd)='1'  then
135                                                                                                pri_wr<=pri_rd;
136                                                                                                req_wr:='1';
137                                                                                                for i in 0 to 3 loop
138                                                                                                 if i=pri_rd then
139                                                                                                  prio_wr(i)<='1';
140                                                                                                  dma_wr_logic(i)<='1';
141                                                                                                 else
142                                                                                                        prio_wr(i)<='0';
143                                                                                                   dma_wr_logic(i)<='0';
144                                                                                                 end if;
145                                                                                                end loop;
146                                                                                               
147                                                                                               
148                                                                                end if;
149                                                                               
150                                                                        else
151                                                                                tmp_wr:= (dma_wr_request and prio_wr) ;
152                                                                                dma_wr_logic <=tmp_wr;
153                                                                               
154                                                                                req_wr:= not(All_zeros(tmp_wr)); 
155                                                                                dma_req_wr<= not(All_zeros(tmp_wr)); 
156                                                                        end if;
157                                                                        -- la priorité est circulaire et décale à chaque coup d'horloge
158                                                                        if req_wr='0' then
159                                                                                prio_wr<=rol_vec(prio_wr); 
160                                                                                if pri_wr=3 then
161                                                                                        pri_wr<=0;
162                                                                                        Prio_wr<="0001";
163                                                                                else
164                                                                                        pri_wr<=pri_wr+1;
165                                                                                end if;
166                                                                 end if;
167                                end case;
168                                       
169                                end if;
170                               
171                                if req_rd='0' or dma_rd_request="0000" then --tant que le Ctrl DMA est libre alors faire bouger la priorité
172                                case dma_rd_request is
173                                when "0001" => pri_rd<=0;
174                                                                        prio_rd<="0001";
175                                                                        req_rd:='1';
176                                                                        dma_req_rd<= '1';
177                                                                        dma_rd_logic<="0001";
178                                when "0010" => pri_rd<=1;
179                                                                        prio_rd<="0010";
180                                                                        req_rd:='1';
181                                                                        dma_req_rd<= '1';
182                                                                        dma_rd_logic<="0010";
183                                                                       
184                                when "0100" => pri_rd<=2;
185                                                                        prio_rd<="0100";
186                                                                        req_rd:='1';
187                                                                        dma_req_rd<= '1';
188                                                                        dma_rd_logic<="0100";
189                                                                       
190                                when "1000" => pri_rd<=3;
191                                                                        prio_rd<="1000";
192                                                                        req_rd:='1';
193                                                                        dma_req_rd<= '1';
194                                                                        dma_rd_logic<="1000";
195                                                                       
196                                when others => 
197                                                                        --si une demande survient de la part d'un composant déjà acquitté alors celui-ci est prioritaire
198                                                                        if req_wr='1' then
199                                                                       
200                                                                                if dma_rd_request(pri_wr)='1'  then
201                                                                                                pri_rd<=pri_wr;
202                                                                                                req_rd:='1';
203                                                                                                for i in 0 to 3 loop
204                                                                                                 if i=pri_wr then
205                                                                                                  prio_rd(i)<='1';
206                                                                                                  dma_rd_logic(i)<='1';
207                                                                                                 else
208                                                                                                        prio_rd(i)<='0';
209                                                                                                   dma_rd_logic(i)<='0';
210                                                                                                 end if;
211                                                                                                end loop;
212                                                                                               
213                                                                                               
214                                                                                end if;
215                                                                               
216                                                                        else
217                                                                                tmp_rd:= (dma_rd_request and prio_rd) ; 
218                                                                                dma_rd_logic<=tmp_rd;
219                                                                                dma_req_rd<= not (All_Zeros(tmp_rd));
220                                                                                req_rd:= not (All_Zeros(tmp_rd));
221                                                                        end if;
222                                                                -- la priorité est circulaire et décale à chaque coup d'horloge
223                                                                        if req_rd='0' then
224                                                                                prio_rd<=rol_vec(prio_rd);
225                                                                                if pri_rd =3 then
226                                                                                        pri_rd<=0;
227                                                                                        prio_rd<="0001";
228                                                                                else
229                                                                                       
230                                                                                        pri_rd<=pri_rd+1;
231                                                                                end if;
232                                                                        end if;
233                                end case;
234                               
235                           end if;
236           
237                  case dmac_state is
238                   when idle => if req_rd='1' or req_wr='1' then
239                                                                        dmac_state<=wait_ack; 
240                                                        else -- initialiser la priorité
241                                                                       
242                                                                       
243                                                                        req_rd:='0';
244                                                                        dma_req_rd<= '0';
245                                                                        dma_rd_logic <="0000";
246                                                                       
247                                                                       
248                                                                        req_wr:='0';
249                                                                        dma_req_wr<= '0';
250                                                                        dma_wr_logic <="0000";
251                                                                                       
252                                                        end if;
253                        when wait_ack =>  -- l'application doit autoriser l'utilisation de la RAM par le Core
254                                                if dma_wr_request(pri_wr) ='1' or dma_rd_request(pri_rd) ='1' then
255                                                        if hold_ack='1' then
256                                                                dmac_state<=arbiter_ack;
257                                                        end if;
258                                                else
259                                                       
260                                                        if dma_wr_request(pri_wr) ='0' then
261                                                        req_wr:='0';-- forcer une nouvelle recherche de priorité
262                                                        end if;
263                                                       
264                                                        if dma_rd_request(pri_rd) ='0' then
265                                                                req_rd:='0';
266                                                        end if;
267                                                        dmac_state<=Idle;
268                                                end if;
269                                               
270                               
271                        when arbiter_ack => if dma_wr_request(pri_wr) ='1' and dma_rd_request(pri_rd) ='1' then --
272                                                                        dmac_state <= Readwrite;
273                                                                 elsif dma_wr_request(pri_wr) ='0' and dma_rd_request(pri_rd) ='1' then
274                                                                                        dmac_state <= Reading;
275                                                                elsif dma_wr_request(pri_wr) ='1' and dma_rd_request(pri_rd) ='0' then
276                                                                                        dmac_state <= Writing;
277                                                                else
278                                                                                        dmac_state<=Idle;
279                                                                end if;
280                                                               
281                        when Writing => if dma_wr_request(pri_wr) ='1' then
282                                                                                if hold_ack='1' then 
283                                                                                    -- on reste dans cet état
284                                                                                 if dma_rd_request(pri_rd)='1' then
285                                                                                                dmac_state<=ReadWrite;
286                                                                                 else
287                                                                                                req_rd:='0';
288                                                                                 end if;
289                                                                                else
290                                                                                        dmac_state<=wait_ack; 
291                                                                                end if;
292                                                                 elsif dma_rd_request(pri_rd) ='1' then
293                                                                                dmac_state <= Reading;
294                                                                 else
295                                                                                dmac_state <= idle;
296                                                                end if;
297                       
298                       
299                        when ReadWrite => if hold_ack='1' then
300                                                                                  if dma_wr_request(pri_wr)='1' and dma_rd_request(pri_rd)='1' then
301                                                                                                dmac_state <= ReadWrite;
302                                                                                        elsif dma_wr_request(pri_wr)='1' and dma_rd_request(pri_rd)='0' then 
303                                                                                                dmac_state <= Writing;
304                                                                                                req_rd:='0';
305                                                                                        elsif dma_wr_request(pri_wr)='0' and dma_rd_request(pri_rd)='1' then
306                                                                                                dmac_state <= Reading;
307                                                                                                req_wr:='0';
308                                                                                        else
309                                                                                                dmac_state <= Idle;
310                                                                                                req_rd:='0';req_wr:='0';
311                                                                                        end if;
312                                                                         else 
313                                                                                        if (dma_wr_request(pri_wr)='1') or (dma_rd_request(pri_rd)='1') then
314                                                                                                        dmac_state <= Wait_ack;
315                                                                                        else
316                                                                                                dmac_state <= Idle;
317                                                                                        end if;
318                                                                        end if;
319                        when Reading => 
320                                                                 if dma_rd_request(pri_rd) ='1' then
321                                                                                if hold_ack='1' then 
322                                                                                    -- on reste dans cet état
323                                                                                         if dma_wr_request(pri_wr)='1' then
324                                                                                                dmac_state<=ReadWrite;
325                                                                                        else
326                                                                                                req_wr:='0';
327                                                                                        end if;
328                                                                                else
329                                                                                        dmac_state<=wait_ack; 
330                                                                                end if;
331                                                                 elsif dma_wr_request(pri_wr) ='1' then
332                                                                                dmac_state<=writing;
333                                                                 else
334                                                                                dmac_state <= idle;
335                                                                end if;
336                        when others => dmac_state <= idle;
337                   end case;
338         end if;
339        end if;
340end process;
341-- action_asociées
342ol: process(dmac_state, address_rd, address_wr,pri_wr,pri_rd,prio_wr,prio_rd,dma_wr_request,dma_rd_request)
343
344begin
345--tester les requêtes DMA en lecture ou en écriture
346
347case dmac_state is
348                when idle => 
349                                                        ram_en <='0';
350                                                        ram_we <='0';
351                                                        dma_wr_grant <=(others=>'0');
352                                                        dma_rd_grant <=(others=>'0');
353                                                        --address_out_rd <= address_rd;
354                                                        --hold_req<='0';
355                when wait_ack =>
356                                                        ram_en <='0';
357                                                        ram_we <='0';
358                                                        dma_wr_grant<=(others=>'0');
359                                                        dma_rd_grant<=(others=>'0');
360                                                        --address_out_rd <= (others=>'Z');
361                                                        --address_out_wr <= (others=>'Z');
362                                                        --hold_req<='1';
363                when arbiter_ack =>  --à optimiser pour gagner un cycle
364                                                        ram_en <='1';
365                                                        ram_we <='0';
366                                                        dma_wr_grant<=(others=>'0');
367                                                        dma_rd_grant<=(others=>'0');
368                                                        --address_out_rd <= (others=>'Z');
369                                                        --address_out_wr <= (others=>'Z');
370                when writing => -- ecriture dans la ram
371                                                        ram_en <='1';
372                                                        ram_we <='1';
373                                                        dma_wr_grant<=(others=>'0');
374                                                        dma_wr_grant(pri_wr) <='1';
375                                                        dma_rd_grant <=(others=>'0');
376                                                        --address_out_rd <= (others=>'Z');
377                                                        --address_out_wr <= address_wr;
378                                                        --hold_req<='1';                                                       
379                                                       
380                when ReadWrite => -- Lecture et écriture simultannée dans la Dual Port RAM
381                                                        ram_en <='1';
382                                                        ram_we <='1';
383                                                        dma_wr_grant<=(others=>'0');
384                                                        dma_wr_grant(pri_wr) <='1';
385                                                        dma_rd_grant<=(others=>'0');
386                                                        dma_rd_grant(pri_rd)<='1';
387                                                       
388                                                        --address_out_rd <= address_rd;
389                                                        --address_out_wr <= address_wr;
390                                                        --hold_req<='1';                                                       
391                when Reading => -- lecture dans la ram
392                                                        ram_en <='1';
393                                                        ram_we <='0';
394                                                        dma_wr_grant<=(others=>'0');
395                                                        dma_rd_grant<=(others=>'0');
396                                                        dma_rd_grant(pri_rd)<='1';
397                                                       
398                                                        --address_out_rd <= address_rd;
399                                                        --address_out_wr <= (others=>'Z');
400                                                        --hold_req<='1';
401                when others => 
402                                                   ram_en <='0';
403                                                        ram_we <='0';
404                                                        dma_wr_grant <=(others=>'0');
405                                                        dma_rd_grant <=(others=>'0');
406                                                        --address_out_rd <= (others=>'Z');
407                                                        --address_out_wr <= (others=>'Z');
408                                                        --hold_req<='0';
409                end case;
410end process;
411
412
413end Behavioral;
414
Note: See TracBrowser for help on using the repository browser.