1 |
2 |
DavidRAMBA |
--=============================================================================
|
2 |
|
|
-- TITRE : MANAGE DMA
|
3 |
|
|
-- DESCRIPTION :
|
4 |
|
|
-- Gère les transferts DMA vers la passerelle
|
5 |
|
|
-- Les transferts DMA sont envoyés à partir de l'adresse dma_base_pa
|
6 |
|
|
-- Ils sont répartis sur 3 zones (Rx1, Rx2, Tx)
|
7 |
|
|
-- Chaque zone contient 32 buffers de 256 octets
|
8 |
|
|
-- Un transfert DMA peut faire au maximum 128 octets (32 mots). Si une trame
|
9 |
|
|
-- fait plus, il faut la transférer en 2 fois
|
10 |
|
|
-- FICHIER : manage_dma.vhd
|
11 |
|
|
--=============================================================================
|
12 |
|
|
-- CREATION
|
13 |
|
|
-- DATE AUTEUR PROJET REVISION
|
14 |
|
|
-- 10/04/2014 DRA SATURN V1.0
|
15 |
|
|
--=============================================================================
|
16 |
|
|
-- HISTORIQUE DES MODIFICATIONS :
|
17 |
|
|
-- DATE AUTEUR PROJET REVISION
|
18 |
|
|
--=============================================================================
|
19 |
|
|
|
20 |
|
|
LIBRARY IEEE;
|
21 |
|
|
USE IEEE.STD_LOGIC_1164.ALL;
|
22 |
|
|
USE IEEE.STD_LOGIC_ARITH.ALL;
|
23 |
|
|
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
|
24 |
|
|
|
25 |
|
|
ENTITY manage_dma IS
|
26 |
|
|
PORT (
|
27 |
|
|
-- Ports système
|
28 |
|
|
clk_sys : IN STD_LOGIC; -- Clock système à 62.5MHz
|
29 |
|
|
rst_n : IN STD_LOGIC; -- Reset général système
|
30 |
|
|
store_enable : IN STD_LOGIC; -- Autorise le stockage et la transmission par DMA des trames incidentes
|
31 |
|
|
|
32 |
|
|
-- Interfaces de réception des trames Rx1
|
33 |
|
|
data_storerx1 : IN STD_LOGIC_VECTOR(7 DOWNTO 0); -- Données à stocker.
|
34 |
|
|
val_storerx1 : IN STD_LOGIC; -- Validant du bus data_store(signal write)
|
35 |
|
|
sof_storerx1 : IN STD_LOGIC; -- Indique un début de trame (nouvelle trame). Synchrone du 1er octet envoyé
|
36 |
|
|
eof_storerx1 : IN STD_LOGIC; -- Indique que la trame est finie
|
37 |
|
|
crcok_storerx1 : IN STD_LOGIC; -- Indique que le CRC est bon ou pas
|
38 |
|
|
|
39 |
|
|
-- Interfaces de réception des trames Rx2
|
40 |
|
|
data_storerx2 : IN STD_LOGIC_VECTOR(7 DOWNTO 0); -- Données à stocker.
|
41 |
|
|
val_storerx2 : IN STD_LOGIC; -- Validant du bus data_store(signal write)
|
42 |
|
|
sof_storerx2 : IN STD_LOGIC; -- Indique un début de trame (nouvelle trame). Synchrone du 1er octet envoyé
|
43 |
|
|
eof_storerx2 : IN STD_LOGIC; -- Indique que la trame est finie
|
44 |
|
|
crcok_storerx2 : IN STD_LOGIC; -- Indique que le CRC est bon ou pas
|
45 |
|
|
|
46 |
|
|
-- Interfaces de réception des trames Tx
|
47 |
|
|
data_storetx : IN STD_LOGIC_VECTOR(7 DOWNTO 0); -- Données à stocker.
|
48 |
|
|
val_storetx : IN STD_LOGIC; -- Validant du bus data_store(signal write)
|
49 |
|
|
sof_storetx : IN STD_LOGIC; -- Indique un début de trame (nouvelle trame). Synchrone du 1er octet envoyé
|
50 |
|
|
eof_storetx : IN STD_LOGIC; -- Indique que la trame est finie
|
51 |
|
|
|
52 |
|
|
-- Signaux de gestion des buffers d'enregistrement des trames RX
|
53 |
|
|
newframe_rx1 : OUT STD_LOGIC_VECTOR(31 DOWNTO 0);-- Un '1' pour un nouveau buffer DMA remplit avec Rx1
|
54 |
|
|
newframe_rx2 : OUT STD_LOGIC_VECTOR(31 DOWNTO 0);-- Un '1' pour un nouveau buffer DMA remplit avec Rx2
|
55 |
|
|
newframe_tx : OUT STD_LOGIC_VECTOR(31 DOWNTO 0);-- Un '1' pour un nouveau buffer DMA remplit avec Tx
|
56 |
|
|
bufferrx1_full : IN STD_LOGIC_VECTOR(31 DOWNTO 0);-- Un '1' pour un nouveau buffer DMA libre pour Rx1
|
57 |
|
|
bufferrx2_full : IN STD_LOGIC_VECTOR(31 DOWNTO 0);-- Un '1' pour un nouveau buffer DMA libre pour Rx2
|
58 |
|
|
buffertx_full : IN STD_LOGIC_VECTOR(31 DOWNTO 0);-- Un '1' pour un nouveau buffer DMA libre pour Tx
|
59 |
|
|
rx1_overflow : OUT STD_LOGIC; -- Indique qu'une trame Rx1 n'a pas pu être stockée
|
60 |
|
|
rx2_overflow : OUT STD_LOGIC; -- Indique qu'une trame Rx2 n'a pas pu être stockée
|
61 |
|
|
tx_overflow : OUT STD_LOGIC; -- Indique qu'une trame Tx n'a pas pu être stockée
|
62 |
|
|
rx1_badformat : OUT STD_LOGIC; -- Indique une erreur CRC sur une trame reçue sur Rx1
|
63 |
|
|
rx2_badformat : OUT STD_LOGIC; -- Indique une erreur CRC sur une trame reçue sur Rx2
|
64 |
|
|
|
65 |
|
|
-- Interface vers le DMA du module PCIe
|
66 |
|
|
dma_inprogress : OUT STD_LOGIC; -- Signale qu'un transfert DMA est en cours
|
67 |
|
|
dma_req : OUT STD_LOGIC; -- Demande de pourvoir faire une transfert DMA
|
68 |
|
|
dma_size : OUT STD_LOGIC_VECTOR(7 DOWNTO 0); -- Taille du DMA en mots de 32 bits
|
69 |
|
|
dma_ack : IN STD_LOGIC; -- Acquittement à la demande de DMA
|
70 |
|
|
dma_compl : IN STD_LOGIC; -- Indique que le transfert DMA précédent est fini
|
71 |
|
|
dma_read : IN STD_LOGIC; -- Signal de lecture pour fetcher une donéne de plus vers le DMA
|
72 |
|
|
dma_data : OUT STD_LOGIC_VECTOR(31 DOWNTO 0);-- Donnée envoyée par DMA
|
73 |
|
|
dma_add_dest : OUT STD_LOGIC_VECTOR(31 DOWNTO 0);-- Adresse de destination coté PC pour le DMA
|
74 |
|
|
dma_base_pa : IN STD_LOGIC_VECTOR(31 DOWNTO 0);-- Adresse de base coté PC pour les transferts DMA
|
75 |
|
|
dma_timestamp : IN STD_LOGIC_VECTOR(7 DOWNTO 0) -- Numéro de cycle en cours MOD 256 pour dater les trames reçues
|
76 |
|
|
);
|
77 |
|
|
|
78 |
|
|
END manage_dma;
|
79 |
|
|
|
80 |
|
|
ARCHITECTURE rtl of manage_dma is
|
81 |
|
|
-- Signaux de gestion des trames Rx
|
82 |
|
|
SIGNAL frame_disporx1: STD_LOGIC; -- Indique qu'une trame Rx1 est dipos pour un transfert DMA
|
83 |
|
|
SIGNAL frame_datarx1 : STD_LOGIC_VECTOR(31 DOWNTO 0); -- Donnée lue dans la DPRA pour transfert DMA Rx1
|
84 |
|
|
SIGNAL frame_rdrx1 : STD_LOGIC; -- Lit une donnée de plus dans la DPRAM Rx1
|
85 |
|
|
SIGNAL frame_disporx2: STD_LOGIC; -- Indique qu'une trame Rx2 est dipos pour un transfert DMA
|
86 |
|
|
SIGNAL frame_datarx2 : STD_LOGIC_VECTOR(31 DOWNTO 0); -- Donnée lue dans la DPRA pour transfert DMA Rx2
|
87 |
|
|
SIGNAL frame_rdrx2 : STD_LOGIC; -- Lit une donnée de plus dans la DPRAM Rx2
|
88 |
|
|
SIGNAL frame_dispotx : STD_LOGIC; -- Indique qu'une trame Tx est dipos pour un transfert DMA
|
89 |
|
|
SIGNAL frame_datatx : STD_LOGIC_VECTOR(31 DOWNTO 0); -- Donnée lue dans la DPRA pour transfert DMA Tx
|
90 |
|
|
SIGNAL frame_rdtx : STD_LOGIC; -- Lit une donnée de plus dans la DPRAM Tx
|
91 |
|
|
|
92 |
|
|
SIGNAL sel_voierx : STD_LOGIC_VECTOR(1 DOWNTO 0); -- Sélecteur de voie 0:Rx1, 1:Rx2, 2:Tx
|
93 |
|
|
SIGNAL dma_datamux : STD_LOGIC_VECTOR(31 DOWNTO 0); -- Multiplexage des données à transférer selon la voie
|
94 |
|
|
SIGNAL dma_rest : STD_LOGIC_VECTOR(7 DOWNTO 0); -- Nombre de mots de 32 bits restant à transférer
|
95 |
|
|
SIGNAL new_frame : STD_LOGIC_VECTOR(31 DOWNTO 0); -- Un '1' signale le numéro de buffer qui veint d'être rempli par DMA
|
96 |
|
|
SIGNAL buf_selected : STD_LOGIC_VECTOR(4 DOWNTO 0); -- Numéro du 1er buffer disponible en fonction de la voie traitée
|
97 |
|
|
SIGNAL buf_selectmem : STD_LOGIC_VECTOR(4 DOWNTO 0); -- Mémorisation du numéro de buffer sélectionné à un instant donné
|
98 |
|
|
-- Machine d'état de gestion des DMA
|
99 |
|
|
TYPE fsm_dma_type IS (idledma_st, calc_dma_size_st, wait_dma_ack_st, wait_dma_compl_st, update_flag_st);
|
100 |
|
|
SIGNAL fsm_dma : fsm_dma_type;
|
101 |
|
|
|
102 |
|
|
SIGNAL rx1_tobeproc : STD_LOGIC; -- A 1 lorsque la voie Rx1 demande un transfert DMA
|
103 |
|
|
SIGNAL rx2_tobeproc : STD_LOGIC; -- A 1 lorsque la voie Rx2 demande un transfert DMA
|
104 |
|
|
SIGNAL tx_tobeproc : STD_LOGIC; -- A 1 lorsque la voie Tx demande un transfert DMA
|
105 |
|
|
|
106 |
|
|
COMPONENT store_framerxdma
|
107 |
|
|
PORT(
|
108 |
|
|
clk_sys : IN STD_LOGIC;
|
109 |
|
|
rst_n : IN STD_LOGIC;
|
110 |
|
|
store_enable: IN STD_LOGIC;
|
111 |
|
|
data_store : IN STD_LOGIC_VECTOR(7 downto 0);
|
112 |
|
|
val_store : IN STD_LOGIC;
|
113 |
|
|
sof_store : IN STD_LOGIC;
|
114 |
|
|
eof_store : IN STD_LOGIC;
|
115 |
|
|
crcok_store : IN STD_LOGIC;
|
116 |
|
|
frame_dispo : OUT STD_LOGIC;
|
117 |
|
|
frame_data : OUT STD_LOGIC_VECTOR(31 downto 0);
|
118 |
|
|
frame_rd : IN STD_LOGIC;
|
119 |
|
|
overflow : OUT STD_LOGIC;
|
120 |
|
|
bad_format : OUT STD_LOGIC;
|
121 |
|
|
timestamp : IN STD_LOGIC_VECTOR(7 DOWNTO 0)
|
122 |
|
|
);
|
123 |
|
|
END COMPONENT;
|
124 |
|
|
|
125 |
|
|
COMPONENT store_frametxdma
|
126 |
|
|
PORT(
|
127 |
|
|
clk_sys : IN STD_LOGIC;
|
128 |
|
|
rst_n : IN STD_LOGIC;
|
129 |
|
|
store_enable: IN STD_LOGIC;
|
130 |
|
|
data_store : IN STD_LOGIC_VECTOR(7 downto 0);
|
131 |
|
|
val_store : IN STD_LOGIC;
|
132 |
|
|
sof_store : IN STD_LOGIC;
|
133 |
|
|
eof_store : IN STD_LOGIC;
|
134 |
|
|
frame_dispo : OUT STD_LOGIC;
|
135 |
|
|
frame_data : OUT STD_LOGIC_VECTOR(31 downto 0);
|
136 |
|
|
frame_rd : IN STD_LOGIC;
|
137 |
|
|
overflow : OUT STD_LOGIC;
|
138 |
|
|
timestamp : IN STD_LOGIC_VECTOR(7 DOWNTO 0)
|
139 |
|
|
);
|
140 |
|
|
END COMPONENT;
|
141 |
|
|
|
142 |
|
|
BEGIN
|
143 |
|
|
--------------------------------
|
144 |
|
|
-- Module de stockage des trames reçues sur Rx1
|
145 |
|
|
--------------------------------
|
146 |
|
|
storerx1 : store_framerxdma
|
147 |
|
|
PORT MAP (
|
148 |
|
|
clk_sys => clk_sys,
|
149 |
|
|
rst_n => rst_n,
|
150 |
|
|
store_enable => store_enable,
|
151 |
|
|
data_store => data_storerx1,
|
152 |
|
|
val_store => val_storerx1,
|
153 |
|
|
sof_store => sof_storerx1,
|
154 |
|
|
eof_store => eof_storerx1,
|
155 |
|
|
crcok_store => crcok_storerx1,
|
156 |
|
|
frame_dispo => frame_disporx1,
|
157 |
|
|
frame_data => frame_datarx1,
|
158 |
|
|
frame_rd => frame_rdrx1,
|
159 |
|
|
overflow => rx1_overflow,
|
160 |
|
|
bad_format => rx1_badformat,
|
161 |
|
|
timestamp => dma_timestamp
|
162 |
|
|
);
|
163 |
|
|
|
164 |
|
|
--------------------------------
|
165 |
|
|
-- Module de stockage des trames reçues sur Rx2
|
166 |
|
|
--------------------------------
|
167 |
|
|
storerx2 : store_framerxdma
|
168 |
|
|
PORT MAP (
|
169 |
|
|
clk_sys => clk_sys,
|
170 |
|
|
rst_n => rst_n,
|
171 |
|
|
store_enable => store_enable,
|
172 |
|
|
data_store => data_storerx2,
|
173 |
|
|
val_store => val_storerx2,
|
174 |
|
|
sof_store => sof_storerx2,
|
175 |
|
|
eof_store => eof_storerx2,
|
176 |
|
|
crcok_store => crcok_storerx2,
|
177 |
|
|
frame_dispo => frame_disporx2,
|
178 |
|
|
frame_data => frame_datarx2,
|
179 |
|
|
frame_rd => frame_rdrx2,
|
180 |
|
|
overflow => rx2_overflow,
|
181 |
|
|
bad_format => rx2_badformat,
|
182 |
|
|
timestamp => dma_timestamp
|
183 |
|
|
);
|
184 |
|
|
|
185 |
|
|
--------------------------------
|
186 |
|
|
-- Module de stockage des trames reçues sur Tx
|
187 |
|
|
--------------------------------
|
188 |
|
|
storetx : store_frametxdma
|
189 |
|
|
PORT MAP (
|
190 |
|
|
clk_sys => clk_sys,
|
191 |
|
|
rst_n => rst_n,
|
192 |
|
|
store_enable => store_enable,
|
193 |
|
|
data_store => data_storetx,
|
194 |
|
|
val_store => val_storetx,
|
195 |
|
|
sof_store => sof_storetx,
|
196 |
|
|
eof_store => eof_storetx,
|
197 |
|
|
frame_dispo => frame_dispotx,
|
198 |
|
|
frame_data => frame_datatx,
|
199 |
|
|
frame_rd => frame_rdtx,
|
200 |
|
|
overflow => tx_overflow,
|
201 |
|
|
timestamp => dma_timestamp
|
202 |
|
|
);
|
203 |
|
|
|
204 |
|
|
----------------------------------------------
|
205 |
|
|
-- Multiplexage des signaux selon al voie en cours de traitement
|
206 |
|
|
----------------------------------------------
|
207 |
|
|
-- Donnée envoyée vers le DMA
|
208 |
|
|
dma_datamux <= frame_datarx1 WHEN (sel_voierx = "00") ELSE
|
209 |
|
|
frame_datarx2 WHEN (sel_voierx = "01") ELSE
|
210 |
|
|
frame_datatx;
|
211 |
|
|
|
212 |
|
|
-- Pour les DMA, il faut inverser l'ordre little / big endian.
|
213 |
|
|
dma_data <= dma_datamux(7 DOWNTO 0) & dma_datamux(15 DOWNTO 8) &
|
214 |
|
|
dma_datamux(23 DOWNTO 16) & dma_datamux(31 DOWNTO 24); --dma_datamux;
|
215 |
|
|
|
216 |
|
|
-- On lit le bon buffer selon la voie sélectionnée
|
217 |
|
|
frame_rdrx1 <= dma_read WHEN (sel_voierx = "00") ELSE '0';
|
218 |
|
|
frame_rdrx2 <= dma_read WHEN (sel_voierx = "01") ELSE '0';
|
219 |
|
|
frame_rdtx <= dma_read WHEN (sel_voierx = "10") ELSE '0';
|
220 |
|
|
|
221 |
|
|
-- Indique au module mémroy map quel bufefr de quelle zone a été rempli
|
222 |
|
|
newframe_rx1 <= new_frame WHEN (sel_voierx = "00") ELSE x"00000000";
|
223 |
|
|
newframe_rx2 <= new_frame WHEN (sel_voierx = "01") ELSE x"00000000";
|
224 |
|
|
newframe_tx <= new_frame WHEN (sel_voierx = "10") ELSE x"00000000";
|
225 |
|
|
|
226 |
|
|
-- demande de transfert DMA = au moins une trame stockée et au moins 1 buffer de libre dans la zone concernée
|
227 |
|
|
rx1_tobeproc <= '1' WHEN (frame_disporx1 = '1' AND bufferrx1_full /= x"FFFFFFFF") ELSE '0';
|
228 |
|
|
rx2_tobeproc <= '1' WHEN (frame_disporx2 = '1' AND bufferrx2_full /= x"FFFFFFFF") ELSE '0';
|
229 |
|
|
tx_tobeproc <= '1' WHEN (frame_dispotx = '1' AND buffertx_full /= x"FFFFFFFF") ELSE '0';
|
230 |
|
|
|
231 |
|
|
------------------------------------------
|
232 |
|
|
-- Machine d'état de gestion du transfert DMA
|
233 |
|
|
------------------------------------------
|
234 |
|
|
man_dma : PROCESS(clk_sys, rst_n)
|
235 |
|
|
VARIABLE temp : STD_LOGIC_VECTOR(5 DOWNTO 0); -- Pour les calculs de taille intermédiaires
|
236 |
|
|
BEGIN
|
237 |
|
|
IF (rst_n = '0') THEN
|
238 |
|
|
sel_voierx <= "00";
|
239 |
|
|
dma_req <= '0';
|
240 |
|
|
dma_size <= (OTHERS => '0');
|
241 |
|
|
dma_rest <= (OTHERS => '0');
|
242 |
|
|
buf_selectmem <= (OTHERS => '0');
|
243 |
|
|
new_frame <= (OTHERS => '0');
|
244 |
|
|
dma_inprogress <= '0';
|
245 |
|
|
fsm_dma <= idledma_st;
|
246 |
|
|
ELSIF (clk_sys'event AND clk_sys = '1') THEN
|
247 |
|
|
CASE fsm_dma IS
|
248 |
|
|
WHEN idledma_st =>
|
249 |
|
|
-- Etat d'attente de demande d'un transfert. Gestion des 3 zones en Round Robin
|
250 |
|
|
dma_req <= '0'; -- Pas de demande pour l'instant
|
251 |
|
|
new_frame <= (OTHERS => '0'); -- Pour s'assurer que le signal ne dure qu'un clk
|
252 |
|
|
IF ((rx1_tobeproc = '1') AND
|
253 |
|
|
((rx2_tobeproc = '0' AND tx_tobeproc = '0') OR sel_voierx /= "00")) THEN
|
254 |
|
|
-- On s'assure qu'on traite par alternance une voie et puis l'autre. On traite la voie 1 que si y'a
|
255 |
|
|
-- des données a traiter et que : soit les autres voies sont vides soit on a traité une autre voie au coup d'avant
|
256 |
|
|
sel_voierx <= "00"; -- On sélectionne la voie 0 (Rx1)
|
257 |
|
|
dma_inprogress <= '1'; -- On indique que le DMA est en cours
|
258 |
|
|
fsm_dma <= calc_dma_size_st; -- On va calculer la tailel du DMA
|
259 |
|
|
ELSIF ((rx2_tobeproc = '1') AND (tx_tobeproc = '0' OR sel_voierx /= "01")) THEN
|
260 |
|
|
-- On va traiter Rx2 si y'a une demande et qu'on a pas traité du Rx2 au coup d'avant
|
261 |
|
|
sel_voierx <= "01";
|
262 |
|
|
dma_inprogress <= '1';
|
263 |
|
|
fsm_dma <= calc_dma_size_st;
|
264 |
|
|
ELSIF (tx_tobeproc = '1') THEN
|
265 |
|
|
-- On va traiter du Tx si y'a une demande
|
266 |
|
|
sel_voierx <= "10";
|
267 |
|
|
dma_inprogress <= '1';
|
268 |
|
|
fsm_dma <= calc_dma_size_st;
|
269 |
|
|
ELSE
|
270 |
|
|
dma_inprogress <= '0';
|
271 |
|
|
END IF;
|
272 |
|
|
|
273 |
|
|
WHEN calc_dma_size_st =>
|
274 |
|
|
-- Le premier mot contient la longueur utile de la trame. On rajoute 4 octets
|
275 |
|
|
-- à la taille à transmettre pour tenir compte du premier mot qu'il faut aussi transmettre
|
276 |
|
|
-- temp ne peut pas déborder car la trame utile ne peut pas excéder 250 octets
|
277 |
|
|
IF (dma_datamux(1 DOWNTO 0) = "00") THEN
|
278 |
|
|
-- Si le nombre d'octets à transmettre est multiple de 4
|
279 |
|
|
temp := dma_datamux(7 DOWNTO 2) + 1; -- On rajoute que le premier mot
|
280 |
|
|
ELSE
|
281 |
|
|
-- Vu qu'on transmet par groupe de 4 octets, on arrondi au nombre de mots supérieur
|
282 |
|
|
temp := dma_datamux(7 DOWNTO 2) + 1 + 1; --
|
283 |
|
|
END IF;
|
284 |
|
|
IF (temp > "100000") THEN
|
285 |
|
|
-- Si le bloc à transmettre fait plus de 128 octets (32 mots)
|
286 |
|
|
dma_size <= x"20"; -- on envoie 128 octets
|
287 |
|
|
dma_rest <= "000" & temp(4 DOWNTO 0); -- Et on mémorise le nombre de mots à transmettre au coup suivant
|
288 |
|
|
ELSE
|
289 |
|
|
dma_size <= "00" & temp; -- Sinon on fait un seul DMA
|
290 |
|
|
dma_rest <= (OTHERS => '0'); -- Le reste est donc nul
|
291 |
|
|
END IF;
|
292 |
|
|
dma_req <= '1'; -- On demande un transfert
|
293 |
|
|
-- L'adresse du transfert = @ de base + zone * 8Ko + buffer * 256
|
294 |
|
|
dma_add_dest <= dma_base_pa(31 DOWNTO 15) & sel_voierx & buf_selected & "00000000";
|
295 |
|
|
buf_selectmem <= buf_selected; -- On mémorise le 1er buffer dispo au moment du transfert
|
296 |
|
|
fsm_dma <= wait_dma_ack_st;
|
297 |
|
|
|
298 |
|
|
WHEN wait_dma_ack_st =>
|
299 |
|
|
-- Etat d'attente de l'acquittement envoyé parl e module PCIe
|
300 |
|
|
IF (dma_ack = '1') THEN
|
301 |
|
|
dma_req <= '0';
|
302 |
|
|
fsm_dma <= wait_dma_compl_st;
|
303 |
|
|
END IF;
|
304 |
|
|
|
305 |
|
|
WHEN wait_dma_compl_st =>
|
306 |
|
|
-- Etat d'attente que le dma soit fini
|
307 |
|
|
IF (dma_compl = '1') THEN
|
308 |
|
|
-- Si le transfert DMA est fini
|
309 |
|
|
IF (dma_rest /= "00000000") THEN
|
310 |
|
|
-- Si on a un deuxième bloc à transférer
|
311 |
|
|
dma_size <= dma_rest;
|
312 |
|
|
dma_rest <= (OTHERS => '0');
|
313 |
|
|
dma_req <= '1';
|
314 |
|
|
dma_add_dest <= dma_base_pa(31 DOWNTO 15) & sel_voierx & buf_selectmem & "10000000";
|
315 |
|
|
fsm_dma <= wait_dma_ack_st;
|
316 |
|
|
ELSE
|
317 |
|
|
-- Si on a fini
|
318 |
|
|
dma_inprogress <= '0'; -- On indique que le DMA est dispo
|
319 |
|
|
fsm_dma <= update_flag_st;
|
320 |
|
|
new_frame(CONV_INTEGER(buf_selectmem)) <= '1'; -- On signale quel buffer a été rempli
|
321 |
|
|
END IF;
|
322 |
|
|
END IF;
|
323 |
|
|
|
324 |
|
|
WHEN update_flag_st =>
|
325 |
|
|
-- Etat d'attente (1 cycle) que les flags bufferrx1_full, bufferrx2_full ou buffertx_full soit mis à jour.
|
326 |
|
|
new_frame <= (OTHERS => '0');
|
327 |
|
|
fsm_dma <= idledma_st;
|
328 |
|
|
|
329 |
|
|
WHEN OTHERS =>
|
330 |
|
|
fsm_dma <= idledma_st;
|
331 |
|
|
END CASE;
|
332 |
|
|
END IF;
|
333 |
|
|
END PROCESS;
|
334 |
|
|
|
335 |
|
|
-------------------------------------------------
|
336 |
|
|
-- Calcul du premier buffer vide et de l'indice associé
|
337 |
|
|
-------------------------------------------------
|
338 |
|
|
sel_buffree : PROCESS(bufferrx1_full, bufferrx2_full, buffertx_full, sel_voierx)
|
339 |
|
|
VARIABLE mux_buf : STD_LOGIC_VECTOR(31 DOWNTO 0);
|
340 |
|
|
BEGIN
|
341 |
|
|
-- En fonction de la voie choisie, on regarde le bon statut de bufefr
|
342 |
|
|
IF (sel_voierx = "00") THEN
|
343 |
|
|
mux_buf := bufferrx1_full;
|
344 |
|
|
ELSIF (sel_voierx = "01") THEN
|
345 |
|
|
mux_buf := bufferrx2_full;
|
346 |
|
|
ELSE
|
347 |
|
|
mux_buf := buffertx_full;
|
348 |
|
|
END IF;
|
349 |
|
|
IF (mux_buf(0) = '0') THEN
|
350 |
|
|
-- On cherche le 1er bit à '0' (i.e. 1er buffer vide) dans le vecteur sélectionné
|
351 |
|
|
buf_selected <= CONV_STD_LOGIC_VECTOR(0, 5);
|
352 |
|
|
ELSIF (mux_buf(1) = '0') THEN
|
353 |
|
|
buf_selected <= CONV_STD_LOGIC_VECTOR(1, 5);
|
354 |
|
|
ELSIF (mux_buf(2) = '0') THEN
|
355 |
|
|
buf_selected <= CONV_STD_LOGIC_VECTOR(2, 5);
|
356 |
|
|
ELSIF (mux_buf(3) = '0') THEN
|
357 |
|
|
buf_selected <= CONV_STD_LOGIC_VECTOR(3, 5);
|
358 |
|
|
ELSIF (mux_buf(4) = '0') THEN
|
359 |
|
|
buf_selected <= CONV_STD_LOGIC_VECTOR(4, 5);
|
360 |
|
|
ELSIF (mux_buf(5) = '0') THEN
|
361 |
|
|
buf_selected <= CONV_STD_LOGIC_VECTOR(5, 5);
|
362 |
|
|
ELSIF (mux_buf(6) = '0') THEN
|
363 |
|
|
buf_selected <= CONV_STD_LOGIC_VECTOR(6, 5);
|
364 |
|
|
ELSIF (mux_buf(7) = '0') THEN
|
365 |
|
|
buf_selected <= CONV_STD_LOGIC_VECTOR(7, 5);
|
366 |
|
|
ELSIF (mux_buf(8) = '0') THEN
|
367 |
|
|
buf_selected <= CONV_STD_LOGIC_VECTOR(8, 5);
|
368 |
|
|
ELSIF (mux_buf(9) = '0') THEN
|
369 |
|
|
buf_selected <= CONV_STD_LOGIC_VECTOR(9, 5);
|
370 |
|
|
ELSIF (mux_buf(10) = '0') THEN
|
371 |
|
|
buf_selected <= CONV_STD_LOGIC_VECTOR(10, 5);
|
372 |
|
|
ELSIF (mux_buf(11) = '0') THEN
|
373 |
|
|
buf_selected <= CONV_STD_LOGIC_VECTOR(11, 5);
|
374 |
|
|
ELSIF (mux_buf(12) = '0') THEN
|
375 |
|
|
buf_selected <= CONV_STD_LOGIC_VECTOR(12, 5);
|
376 |
|
|
ELSIF (mux_buf(13) = '0') THEN
|
377 |
|
|
buf_selected <= CONV_STD_LOGIC_VECTOR(13, 5);
|
378 |
|
|
ELSIF (mux_buf(14) = '0') THEN
|
379 |
|
|
buf_selected <= CONV_STD_LOGIC_VECTOR(14, 5);
|
380 |
|
|
ELSIF (mux_buf(15) = '0') THEN
|
381 |
|
|
buf_selected <= CONV_STD_LOGIC_VECTOR(15, 5);
|
382 |
|
|
ELSIF (mux_buf(16) = '0') THEN
|
383 |
|
|
buf_selected <= CONV_STD_LOGIC_VECTOR(16, 5);
|
384 |
|
|
ELSIF (mux_buf(17) = '0') THEN
|
385 |
|
|
buf_selected <= CONV_STD_LOGIC_VECTOR(17, 5);
|
386 |
|
|
ELSIF (mux_buf(18) = '0') THEN
|
387 |
|
|
buf_selected <= CONV_STD_LOGIC_VECTOR(18, 5);
|
388 |
|
|
ELSIF (mux_buf(19) = '0') THEN
|
389 |
|
|
buf_selected <= CONV_STD_LOGIC_VECTOR(19, 5);
|
390 |
|
|
ELSIF (mux_buf(20) = '0') THEN
|
391 |
|
|
buf_selected <= CONV_STD_LOGIC_VECTOR(20, 5);
|
392 |
|
|
ELSIF (mux_buf(21) = '0') THEN
|
393 |
|
|
buf_selected <= CONV_STD_LOGIC_VECTOR(21, 5);
|
394 |
|
|
ELSIF (mux_buf(22) = '0') THEN
|
395 |
|
|
buf_selected <= CONV_STD_LOGIC_VECTOR(22, 5);
|
396 |
|
|
ELSIF (mux_buf(23) = '0') THEN
|
397 |
|
|
buf_selected <= CONV_STD_LOGIC_VECTOR(23, 5);
|
398 |
|
|
ELSIF (mux_buf(24) = '0') THEN
|
399 |
|
|
buf_selected <= CONV_STD_LOGIC_VECTOR(24, 5);
|
400 |
|
|
ELSIF (mux_buf(25) = '0') THEN
|
401 |
|
|
buf_selected <= CONV_STD_LOGIC_VECTOR(25, 5);
|
402 |
|
|
ELSIF (mux_buf(26) = '0') THEN
|
403 |
|
|
buf_selected <= CONV_STD_LOGIC_VECTOR(26, 5);
|
404 |
|
|
ELSIF (mux_buf(27) = '0') THEN
|
405 |
|
|
buf_selected <= CONV_STD_LOGIC_VECTOR(27, 5);
|
406 |
|
|
ELSIF (mux_buf(28) = '0') THEN
|
407 |
|
|
buf_selected <= CONV_STD_LOGIC_VECTOR(28, 5);
|
408 |
|
|
ELSIF (mux_buf(29) = '0') THEN
|
409 |
|
|
buf_selected <= CONV_STD_LOGIC_VECTOR(29, 5);
|
410 |
|
|
ELSIF (mux_buf(30) = '0') THEN
|
411 |
|
|
buf_selected <= CONV_STD_LOGIC_VECTOR(30, 5);
|
412 |
|
|
ELSIF (mux_buf(31) = '0') THEN
|
413 |
|
|
buf_selected <= CONV_STD_LOGIC_VECTOR(31, 5);
|
414 |
|
|
ELSE
|
415 |
|
|
-- En cas d'overflow (i.e. pas de buffer libre, on sélectionne le dernier)
|
416 |
|
|
-- Mais ce cas ne doit pas arrivé car dans ce cas, la mahcine reste en ideldma_st
|
417 |
|
|
buf_selected <= CONV_STD_LOGIC_VECTOR(31, 5);
|
418 |
|
|
END IF;
|
419 |
|
|
END PROCESS;
|
420 |
|
|
|
421 |
|
|
|
422 |
|
|
END rtl;
|
423 |
|
|
|