source: PROJECT_CORE_MPI/CORE_MPI/BRANCHES/v0.01/DMA_ARBITER.vhd @ 35

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

Version stable pour les tests

File size: 12.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                                                                       
133                                                                        tmp_wr:= (dma_wr_request and prio_wr) ;
134                                                                        dma_wr_logic <=tmp_wr;
135                                                                       
136                                                                        req_wr:= not(All_zeros(tmp_wr)); 
137                                                                        dma_req_wr<= not(All_zeros(tmp_wr));                                   
138                                                                        -- la priorité est circulaire et décale à chaque coup d'horloge
139                                                                        if req_wr='0' then
140                                                                                prio_wr<=rol_vec(prio_wr); 
141                                                                                if pri_wr=3 then
142                                                                                        pri_wr<=0;
143                                                                                        Prio_wr<="0001";
144                                                                                else
145                                                                                        pri_wr<=pri_wr+1;
146                                                                                end if;
147                                                                 end if;
148                                end case;
149                                       
150                                end if;
151                               
152                                if req_rd='0' or dma_rd_request="0000" then --tant que le Ctrl DMA est libre alors faire bouger la priorité
153                                case dma_rd_request is
154                                when "0001" => pri_rd<=0;
155                                                                        prio_rd<="0001";
156                                                                        req_rd:='1';
157                                                                        dma_req_rd<= '1';
158                                                                        dma_rd_logic<="0001";
159                                when "0010" => pri_rd<=1;
160                                                                        prio_rd<="0010";
161                                                                        req_rd:='1';
162                                                                        dma_req_rd<= '1';
163                                                                        dma_rd_logic<="0010";
164                                                                       
165                                when "0100" => pri_rd<=2;
166                                                                        prio_rd<="0100";
167                                                                        req_rd:='1';
168                                                                        dma_req_rd<= '1';
169                                                                        dma_rd_logic<="0100";
170                                                                       
171                                when "1000" => pri_rd<=3;
172                                                                        prio_rd<="1000";
173                                                                        req_rd:='1';
174                                                                        dma_req_rd<= '1';
175                                                                        dma_rd_logic<="1000";
176                                                                       
177                                when others => 
178                                                                       
179                                                                        tmp_rd:= (dma_rd_request and prio_rd) ; 
180                                                                        dma_rd_logic<=tmp_rd;
181                                                                        dma_req_rd<= not (All_Zeros(tmp_rd));
182                                                                        req_rd:= not (All_Zeros(tmp_rd));
183                                                                       
184                                                                -- la priorité est circulaire et décale à chaque coup d'horloge
185                                                                        if req_rd='0' then
186                                                                                prio_rd<=rol_vec(prio_rd);
187                                                                                if pri_rd =3 then
188                                                                                        pri_rd<=0;
189                                                                                        prio_rd<="0001";
190                                                                                else
191                                                                                       
192                                                                                        pri_rd<=pri_rd+1;
193                                                                                end if;
194                                                                        end if;
195                                end case;
196                               
197                           end if;
198           
199                  case dmac_state is
200                   when idle => if req_rd='1' or req_wr='1' then
201                                                                        dmac_state<=wait_ack; 
202                                                        else -- initialiser la priorité
203                                                                       
204                                                                       
205                                                                        req_rd:='0';
206                                                                        dma_req_rd<= '0';
207                                                                        dma_rd_logic <="0000";
208                                                                       
209                                                                       
210                                                                        req_wr:='0';
211                                                                        dma_req_wr<= '0';
212                                                                        dma_wr_logic <="0000";
213                                                                                       
214                                                        end if;
215                        when wait_ack =>  -- l'application doit autoriser l'utilisation de la RAM par le Core
216                                                if dma_wr_request(pri_wr) ='1' or dma_rd_request(pri_rd) ='1' then
217                                                        if hold_ack='1' then
218                                                                dmac_state<=arbiter_ack;
219                                                        end if;
220                                                else
221                                                       
222                                                        if dma_wr_request(pri_wr) ='0' then
223                                                        req_wr:='0';-- forcer une nouvelle recherche de priorité
224                                                        end if;
225                                                       
226                                                        if dma_rd_request(pri_rd) ='0' then
227                                                                req_rd:='0';
228                                                        end if;
229                                                        dmac_state<=Idle;
230                                                end if;
231                                               
232                               
233                        when arbiter_ack => if dma_wr_request(pri_wr) ='1' and dma_rd_request(pri_rd) ='1' then --
234                                                                        dmac_state <= Readwrite;
235                                                                 elsif dma_wr_request(pri_wr) ='0' and dma_rd_request(pri_rd) ='1' then
236                                                                                        dmac_state <= Reading;
237                                                                elsif dma_wr_request(pri_wr) ='1' and dma_rd_request(pri_rd) ='0' then
238                                                                                        dmac_state <= Writing;
239                                                                else
240                                                                                        dmac_state<=Idle;
241                                                                end if;
242                                                               
243                        when Writing => if dma_wr_request(pri_wr) ='1' then
244                                                                                if hold_ack='1' then 
245                                                                                    -- on reste dans cet état
246                                                                                 if dma_rd_request(pri_rd)='1' then
247                                                                                                dmac_state<=ReadWrite;
248                                                                                 else
249                                                                                                req_rd:='0';
250                                                                                 end if;
251                                                                                else
252                                                                                        dmac_state<=wait_ack; 
253                                                                                end if;
254                                                                 elsif dma_rd_request(pri_rd) ='1' then
255                                                                                dmac_state <= Reading;
256                                                                 else
257                                                                                dmac_state <= idle;
258                                                                end if;
259                       
260                       
261                        when ReadWrite => if hold_ack='1' then
262                                                                                  if dma_wr_request(pri_wr)='1' and dma_rd_request(pri_rd)='1' then
263                                                                                                dmac_state <= ReadWrite;
264                                                                                        elsif dma_wr_request(pri_wr)='1' and dma_rd_request(pri_rd)='0' then 
265                                                                                                dmac_state <= Writing;
266                                                                                                req_rd:='0';
267                                                                                        elsif dma_wr_request(pri_wr)='0' and dma_rd_request(pri_rd)='1' then
268                                                                                                dmac_state <= Reading;
269                                                                                                req_wr:='0';
270                                                                                        else
271                                                                                                dmac_state <= Idle;
272                                                                                                req_rd:='0';req_wr:='0';
273                                                                                        end if;
274                                                                         else 
275                                                                                        if (dma_wr_request(pri_wr)='1') or (dma_rd_request(pri_rd)='1') then
276                                                                                                        dmac_state <= Wait_ack;
277                                                                                        else
278                                                                                                dmac_state <= Idle;
279                                                                                        end if;
280                                                                        end if;
281                        when Reading => 
282                                                                 if dma_rd_request(pri_rd) ='1' then
283                                                                                if hold_ack='1' then 
284                                                                                    -- on reste dans cet état
285                                                                                         if dma_wr_request(pri_wr)='1' then
286                                                                                                dmac_state<=ReadWrite;
287                                                                                        else
288                                                                                                req_wr:='0';
289                                                                                        end if;
290                                                                                else
291                                                                                        dmac_state<=wait_ack; 
292                                                                                end if;
293                                                                 elsif dma_wr_request(pri_wr) ='1' then
294                                                                                dmac_state<=writing;
295                                                                 else
296                                                                                dmac_state <= idle;
297                                                                end if;
298                        when others => dmac_state <= idle;
299                   end case;
300         end if;
301        end if;
302end process;
303-- action_asociées
304ol: process(dmac_state, address_rd, address_wr,pri_wr,pri_rd,prio_wr,prio_rd,dma_wr_request,dma_rd_request)
305
306begin
307--tester les requêtes DMA en lecture ou en écriture
308
309case dmac_state is
310                when idle => 
311                                                        ram_en <='0';
312                                                        ram_we <='0';
313                                                        dma_wr_grant <=(others=>'0');
314                                                        dma_rd_grant <=(others=>'0');
315                                                        --address_out_rd <= address_rd;
316                                                        --hold_req<='0';
317                when wait_ack =>
318                                                        ram_en <='0';
319                                                        ram_we <='0';
320                                                        dma_wr_grant<=(others=>'0');
321                                                        dma_rd_grant<=(others=>'0');
322                                                        --address_out_rd <= (others=>'Z');
323                                                        --address_out_wr <= (others=>'Z');
324                                                        --hold_req<='1';
325                when arbiter_ack =>  --à optimiser pour gagner un cycle
326                                                        ram_en <='1';
327                                                        ram_we <='0';
328                                                        dma_wr_grant<=(others=>'0');
329                                                        dma_rd_grant<=(others=>'0');
330                                                        --address_out_rd <= (others=>'Z');
331                                                        --address_out_wr <= (others=>'Z');
332                when writing => -- ecriture dans la ram
333                                                        ram_en <='1';
334                                                        ram_we <='1';
335                                                        dma_wr_grant<=(others=>'0');
336                                                        dma_wr_grant(pri_wr) <='1';
337                                                        dma_rd_grant <=(others=>'0');
338                                                        --address_out_rd <= (others=>'Z');
339                                                        --address_out_wr <= address_wr;
340                                                        --hold_req<='1';                                                       
341                                                       
342                when ReadWrite => -- Lecture et écriture simultannée dans la Dual Port RAM
343                                                        ram_en <='1';
344                                                        ram_we <='1';
345                                                        dma_wr_grant<=(others=>'0');
346                                                        dma_wr_grant(pri_wr) <='1';
347                                                        dma_rd_grant<=(others=>'0');
348                                                        dma_rd_grant(pri_rd)<='1';
349                                                       
350                                                        --address_out_rd <= address_rd;
351                                                        --address_out_wr <= address_wr;
352                                                        --hold_req<='1';                                                       
353                when Reading => -- lecture dans la ram
354                                                        ram_en <='1';
355                                                        ram_we <='0';
356                                                        dma_wr_grant<=(others=>'0');
357                                                        dma_rd_grant<=(others=>'0');
358                                                        dma_rd_grant(pri_rd)<='1';
359                                                       
360                                                        --address_out_rd <= address_rd;
361                                                        --address_out_wr <= (others=>'Z');
362                                                        --hold_req<='1';
363                when others => 
364                                                   ram_en <='0';
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                                                        --hold_req<='0';
371                end case;
372end process;
373
374
375end Behavioral;
376
Note: See TracBrowser for help on using the repository browser.