source: PROJECT_CORE_MPI/CORE_MPI/TRUNK/DMA_ARBITER.vhd

Last change on this file was 15, checked in by rolagamo, 14 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.