source: PROJECT_CORE_MPI/CORE_MPI/TRUNK/DMA_ARBITER.vhd

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