1 |
29 |
wfjm |
-- $Id: fx2_3fifoctl_ic.vhd 649 2015-02-21 21:10:16Z mueller $
|
2 |
17 |
wfjm |
--
|
3 |
18 |
wfjm |
-- Copyright 2012-2013 by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
|
4 |
17 |
wfjm |
--
|
5 |
|
|
-- This program is free software; you may redistribute and/or modify it under
|
6 |
|
|
-- the terms of the GNU General Public License as published by the Free
|
7 |
|
|
-- Software Foundation, either version 2, or at your option any later version.
|
8 |
|
|
--
|
9 |
|
|
-- This program is distributed in the hope that it will be useful, but
|
10 |
|
|
-- WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
|
11 |
|
|
-- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
12 |
|
|
-- for complete details.
|
13 |
|
|
--
|
14 |
|
|
------------------------------------------------------------------------------
|
15 |
|
|
-- Module Name: fx2_3fifoctl_ic - syn
|
16 |
|
|
-- Description: Cypress EZ-USB FX2 driver (3 fifo; int clk)
|
17 |
|
|
--
|
18 |
|
|
-- Dependencies: vlib/xlib/iob_reg_o
|
19 |
|
|
-- vlib/xlib/iob_reg_i_gen
|
20 |
|
|
-- vlib/xlib/iob_reg_o_gen
|
21 |
|
|
-- vlib/xlib/iob_reg_io_gen
|
22 |
|
|
-- memlib/fifo_2c_dram
|
23 |
|
|
--
|
24 |
|
|
-- Test bench: -
|
25 |
|
|
-- Target Devices: generic
|
26 |
29 |
wfjm |
-- Tool versions: xst 13.3-14.7; ghdl 0.29-0.31
|
27 |
17 |
wfjm |
--
|
28 |
|
|
-- Synthesized (xst):
|
29 |
|
|
-- Date Rev ise Target flop lutl lutm slic t peri
|
30 |
18 |
wfjm |
-- 2012-01-15 453 13.3 O76x xc3s1200e-4 157 265 96 243 s 7.7/7.4
|
31 |
17 |
wfjm |
-- 2012-01-15 453 13.3 O76x xc3s1200e-4 156 259 96 238 s 7.9/7.5
|
32 |
|
|
--
|
33 |
|
|
-- Revision History:
|
34 |
|
|
-- Date Rev Version Comment
|
35 |
18 |
wfjm |
-- 2013-01-04 469 1.1 BUGFIX: redo rx logic, now properly pipelined
|
36 |
17 |
wfjm |
-- 2012-01-09 453 1.0 Initial version (derived from 2fifo_ic)
|
37 |
|
|
--
|
38 |
|
|
------------------------------------------------------------------------------
|
39 |
|
|
|
40 |
|
|
library ieee;
|
41 |
|
|
use ieee.std_logic_1164.all;
|
42 |
|
|
use ieee.numeric_std.all;
|
43 |
|
|
|
44 |
|
|
use work.slvtypes.all;
|
45 |
|
|
use work.xlib.all;
|
46 |
|
|
use work.memlib.all;
|
47 |
|
|
use work.fx2lib.all;
|
48 |
|
|
|
49 |
|
|
entity fx2_3fifoctl_ic is -- EZ-USB FX2 driver (3 fifo; int clk)
|
50 |
|
|
generic (
|
51 |
|
|
RXFAWIDTH : positive := 5; -- receive fifo address width
|
52 |
|
|
TXFAWIDTH : positive := 5; -- transmit fifo address width
|
53 |
|
|
PETOWIDTH : positive := 7; -- packet end time-out counter width
|
54 |
|
|
CCWIDTH : positive := 5; -- chunk counter width
|
55 |
|
|
RXAEMPTY_THRES : natural := 1; -- threshold for rx aempty flag
|
56 |
|
|
TXAFULL_THRES : natural := 1; -- threshold for tx afull flag
|
57 |
|
|
TX2AFULL_THRES : natural := 1); -- threshold for tx2 afull flag
|
58 |
|
|
port (
|
59 |
|
|
CLK : in slbit; -- clock
|
60 |
|
|
RESET : in slbit := '0'; -- reset
|
61 |
|
|
RXDATA : out slv8; -- receive data out
|
62 |
|
|
RXVAL : out slbit; -- receive data valid
|
63 |
|
|
RXHOLD : in slbit; -- receive data hold
|
64 |
|
|
RXAEMPTY : out slbit; -- receive almost empty flag
|
65 |
|
|
TXDATA : in slv8; -- transmit 1 data in
|
66 |
|
|
TXENA : in slbit; -- transmit 1 data enable
|
67 |
|
|
TXBUSY : out slbit; -- transmit 1 data busy
|
68 |
|
|
TXAFULL : out slbit; -- transmit 1 almost full flag
|
69 |
|
|
TX2DATA : in slv8; -- transmit 2 data in
|
70 |
|
|
TX2ENA : in slbit; -- transmit 2 data enable
|
71 |
|
|
TX2BUSY : out slbit; -- transmit 2 data busy
|
72 |
|
|
TX2AFULL : out slbit; -- transmit 2 almost full flag
|
73 |
|
|
MONI : out fx2ctl_moni_type; -- monitor port data
|
74 |
|
|
I_FX2_IFCLK : in slbit; -- fx2: interface clock
|
75 |
|
|
O_FX2_FIFO : out slv2; -- fx2: fifo address
|
76 |
|
|
I_FX2_FLAG : in slv4; -- fx2: fifo flags
|
77 |
|
|
O_FX2_SLRD_N : out slbit; -- fx2: read enable (act.low)
|
78 |
|
|
O_FX2_SLWR_N : out slbit; -- fx2: write enable (act.low)
|
79 |
|
|
O_FX2_SLOE_N : out slbit; -- fx2: output enable (act.low)
|
80 |
|
|
O_FX2_PKTEND_N : out slbit; -- fx2: packet end (act.low)
|
81 |
|
|
IO_FX2_DATA : inout slv8 -- fx2: data lines
|
82 |
|
|
);
|
83 |
|
|
end fx2_3fifoctl_ic;
|
84 |
|
|
|
85 |
|
|
|
86 |
|
|
architecture syn of fx2_3fifoctl_ic is
|
87 |
|
|
|
88 |
|
|
constant c_rxfifo : slv2 := c_fifo_ep4;
|
89 |
|
|
constant c_txfifo : slv2 := c_fifo_ep6;
|
90 |
|
|
constant c_tx2fifo: slv2 := c_fifo_ep8;
|
91 |
|
|
|
92 |
|
|
constant c_flag_prog : integer := 0;
|
93 |
|
|
constant c_flag_tx_ff : integer := 1;
|
94 |
|
|
constant c_flag_rx_ef : integer := 2;
|
95 |
|
|
constant c_flag_tx2_ff : integer := 3;
|
96 |
|
|
|
97 |
|
|
type state_type is (
|
98 |
|
|
s_idle, -- s_idle: idle state
|
99 |
|
|
s_rxprep0, -- s_rxprep0: switch to rx-fifo
|
100 |
|
|
s_rxprep1, -- s_rxprep1: fifo addr setup
|
101 |
|
|
s_rxprep2, -- s_rxprep2: wait for flags
|
102 |
|
|
s_rxdisp, -- s_rxdisp: read, dispatch
|
103 |
18 |
wfjm |
s_rxpipe, -- s_rxpipe: read, pipe wait
|
104 |
17 |
wfjm |
s_txprep0, -- s_txprep0: switch to tx-fifo
|
105 |
|
|
s_txprep1, -- s_txprep1: fifo addr setup
|
106 |
|
|
s_txprep2, -- s_txprep2: wait for flags
|
107 |
|
|
s_txdisp, -- s_txdisp: write, dispatch
|
108 |
|
|
s_tx2prep0, -- s_tx2prep0: switch to tx2-fifo
|
109 |
|
|
s_tx2prep1, -- s_tx2prep1: fifo addr setup
|
110 |
|
|
s_tx2prep2, -- s_tx2prep2: wait for flags
|
111 |
|
|
s_tx2disp -- s_tx2disp: write, dispatch
|
112 |
|
|
);
|
113 |
|
|
|
114 |
|
|
type regs_type is record
|
115 |
|
|
state : state_type; -- state
|
116 |
|
|
petocnt : slv(PETOWIDTH-1 downto 0); -- pktend 1 time out counter
|
117 |
|
|
pe2tocnt : slv(PETOWIDTH-1 downto 0); -- pktend 2 time out counter
|
118 |
|
|
pepend : slbit; -- pktend 1 pending
|
119 |
|
|
pe2pend : slbit; -- pktend 2 pending
|
120 |
18 |
wfjm |
rxpipe1 : slbit; -- read pipe 1: iob capture stage
|
121 |
|
|
rxpipe2 : slbit; -- read pipe 2: fifo write stage
|
122 |
17 |
wfjm |
ccnt : slv(CCWIDTH-1 downto 0); -- chunk counter
|
123 |
|
|
moni_ep4_sel : slbit; -- ep4 (rx) select
|
124 |
|
|
moni_ep6_sel : slbit; -- ep6 (tx) select
|
125 |
|
|
moni_ep8_sel : slbit; -- ep8 (tx2) select
|
126 |
|
|
moni_ep4_pf : slbit; -- ep4 (rx) prog flag
|
127 |
|
|
moni_ep6_pf : slbit; -- ep6 (tx) prog flag
|
128 |
|
|
moni_ep8_pf : slbit; -- ep8 (tx2) prog flag
|
129 |
|
|
end record regs_type;
|
130 |
|
|
|
131 |
|
|
constant petocnt_init : slv(PETOWIDTH-1 downto 0) := (others=>'0');
|
132 |
|
|
constant ccnt_init : slv(CCWIDTH-1 downto 0) := (others=>'0');
|
133 |
|
|
|
134 |
|
|
constant regs_init : regs_type := (
|
135 |
|
|
s_idle, -- state
|
136 |
|
|
petocnt_init, -- petocnt
|
137 |
|
|
petocnt_init, -- pe2tocnt
|
138 |
18 |
wfjm |
'0','0', -- pepend,pe2pend
|
139 |
|
|
'0','0', -- rxpipe1, rxpipe2
|
140 |
17 |
wfjm |
ccnt_init, -- ccnt
|
141 |
|
|
'0','0','0', -- moni_ep(4|6|8)_sel
|
142 |
|
|
'0','0','0' -- moni_ep(4|6|8)_pf
|
143 |
|
|
);
|
144 |
|
|
|
145 |
|
|
signal R_REGS : regs_type := regs_init; -- state registers
|
146 |
|
|
signal N_REGS : regs_type := regs_init; -- next value state regs
|
147 |
|
|
|
148 |
|
|
signal FX2_FIFO : slv2 := (others=>'0');
|
149 |
|
|
signal FX2_FIFO_CE : slbit := '0';
|
150 |
|
|
signal FX2_FLAG_N : slv4 := (others=>'0');
|
151 |
|
|
signal FX2_SLRD_N : slbit := '1';
|
152 |
|
|
signal FX2_SLWR_N : slbit := '1';
|
153 |
|
|
signal FX2_SLOE_N : slbit := '1';
|
154 |
|
|
signal FX2_PKTEND_N : slbit := '1';
|
155 |
|
|
signal FX2_DATA_CEI : slbit := '0';
|
156 |
|
|
signal FX2_DATA_CEO : slbit := '0';
|
157 |
|
|
signal FX2_DATA_OE : slbit := '0';
|
158 |
|
|
signal FX2_DATA_DO : slv8 := (others=>'0');
|
159 |
|
|
|
160 |
|
|
signal RXFIFO_DI : slv8 := (others=>'0');
|
161 |
|
|
signal RXFIFO_ENA : slbit := '0';
|
162 |
|
|
signal RXFIFO_BUSY : slbit := '0';
|
163 |
|
|
signal RXSIZE_FX2 : slv(RXFAWIDTH-1 downto 0) := (others=>'0');
|
164 |
|
|
signal RXSIZE_USR : slv(RXFAWIDTH-1 downto 0) := (others=>'0');
|
165 |
|
|
signal TXFIFO_DO : slv8 := (others=>'0');
|
166 |
|
|
signal TXFIFO_VAL : slbit := '0';
|
167 |
|
|
signal TXFIFO_HOLD : slbit := '0';
|
168 |
|
|
signal TXSIZE_FX2 : slv(TXFAWIDTH-1 downto 0) := (others=>'0');
|
169 |
|
|
signal TXSIZE_USR : slv(TXFAWIDTH-1 downto 0) := (others=>'0');
|
170 |
|
|
signal TX2FIFO_DO : slv8 := (others=>'0');
|
171 |
|
|
signal TX2FIFO_VAL : slbit := '0';
|
172 |
|
|
signal TX2FIFO_HOLD : slbit := '0';
|
173 |
|
|
signal TX2SIZE_FX2 : slv(TXFAWIDTH-1 downto 0) := (others=>'0');
|
174 |
|
|
signal TX2SIZE_USR : slv(TXFAWIDTH-1 downto 0) := (others=>'0');
|
175 |
|
|
|
176 |
|
|
signal TXBUSY_L : slbit := '0';
|
177 |
|
|
signal TX2BUSY_L : slbit := '0';
|
178 |
|
|
|
179 |
|
|
signal R_MONI_C : fx2ctl_moni_type := fx2ctl_moni_init;
|
180 |
|
|
signal R_MONI_S : fx2ctl_moni_type := fx2ctl_moni_init;
|
181 |
|
|
|
182 |
|
|
begin
|
183 |
|
|
|
184 |
|
|
assert RXAEMPTY_THRES<=2**RXFAWIDTH-1 and
|
185 |
|
|
TXAFULL_THRES<=2**TXFAWIDTH-1 and
|
186 |
|
|
TX2AFULL_THRES<=2**TXFAWIDTH-1
|
187 |
|
|
report "assert((RXAEMPTY|TXAFULL|TX2AFULL)_THRES <= 2**(RX|TX)FAWIDTH)-1"
|
188 |
|
|
severity failure;
|
189 |
|
|
|
190 |
|
|
|
191 |
|
|
IOB_FX2_FIFO : iob_reg_o_gen
|
192 |
|
|
generic map (
|
193 |
|
|
DWIDTH => 2,
|
194 |
|
|
INIT => '0')
|
195 |
|
|
port map (
|
196 |
|
|
CLK => I_FX2_IFCLK,
|
197 |
|
|
CE => FX2_FIFO_CE,
|
198 |
|
|
DO => FX2_FIFO,
|
199 |
|
|
PAD => O_FX2_FIFO
|
200 |
|
|
);
|
201 |
|
|
|
202 |
|
|
IOB_FX2_FLAG : iob_reg_i_gen
|
203 |
|
|
generic map (
|
204 |
|
|
DWIDTH => 4,
|
205 |
|
|
INIT => '0')
|
206 |
|
|
port map (
|
207 |
|
|
CLK => I_FX2_IFCLK,
|
208 |
|
|
CE => '1',
|
209 |
|
|
DI => FX2_FLAG_N,
|
210 |
|
|
PAD => I_FX2_FLAG
|
211 |
|
|
);
|
212 |
|
|
|
213 |
|
|
IOB_FX2_SLRD : iob_reg_o
|
214 |
|
|
generic map (
|
215 |
|
|
INIT => '1')
|
216 |
|
|
port map (
|
217 |
|
|
CLK => I_FX2_IFCLK,
|
218 |
|
|
CE => '1',
|
219 |
|
|
DO => FX2_SLRD_N,
|
220 |
|
|
PAD => O_FX2_SLRD_N
|
221 |
|
|
);
|
222 |
|
|
|
223 |
|
|
IOB_FX2_SLWR : iob_reg_o
|
224 |
|
|
generic map (
|
225 |
|
|
INIT => '1')
|
226 |
|
|
port map (
|
227 |
|
|
CLK => I_FX2_IFCLK,
|
228 |
|
|
CE => '1',
|
229 |
|
|
DO => FX2_SLWR_N,
|
230 |
|
|
PAD => O_FX2_SLWR_N
|
231 |
|
|
);
|
232 |
|
|
|
233 |
|
|
IOB_FX2_SLOE : iob_reg_o
|
234 |
|
|
generic map (
|
235 |
|
|
INIT => '1')
|
236 |
|
|
port map (
|
237 |
|
|
CLK => I_FX2_IFCLK,
|
238 |
|
|
CE => '1',
|
239 |
|
|
DO => FX2_SLOE_N,
|
240 |
|
|
PAD => O_FX2_SLOE_N
|
241 |
|
|
);
|
242 |
|
|
|
243 |
|
|
IOB_FX2_PKTEND : iob_reg_o
|
244 |
|
|
generic map (
|
245 |
|
|
INIT => '1')
|
246 |
|
|
port map (
|
247 |
|
|
CLK => I_FX2_IFCLK,
|
248 |
|
|
CE => '1',
|
249 |
|
|
DO => FX2_PKTEND_N,
|
250 |
|
|
PAD => O_FX2_PKTEND_N
|
251 |
|
|
);
|
252 |
|
|
|
253 |
|
|
IOB_FX2_DATA : iob_reg_io_gen
|
254 |
|
|
generic map (
|
255 |
|
|
DWIDTH => 8,
|
256 |
|
|
PULL => "KEEP")
|
257 |
|
|
port map (
|
258 |
|
|
CLK => I_FX2_IFCLK,
|
259 |
|
|
CEI => FX2_DATA_CEI,
|
260 |
|
|
CEO => FX2_DATA_CEO,
|
261 |
|
|
OE => FX2_DATA_OE,
|
262 |
|
|
DI => RXFIFO_DI, -- input data (read from pad)
|
263 |
|
|
DO => FX2_DATA_DO, -- output data (write to pad)
|
264 |
|
|
PAD => IO_FX2_DATA
|
265 |
|
|
);
|
266 |
|
|
|
267 |
|
|
RXFIFO : fifo_2c_dram -- input fifo, 2 clock, dram based
|
268 |
|
|
generic map (
|
269 |
|
|
AWIDTH => RXFAWIDTH,
|
270 |
|
|
DWIDTH => 8)
|
271 |
|
|
port map (
|
272 |
|
|
CLKW => I_FX2_IFCLK,
|
273 |
|
|
CLKR => CLK,
|
274 |
|
|
RESETW => '0',
|
275 |
|
|
RESETR => RESET,
|
276 |
|
|
DI => RXFIFO_DI,
|
277 |
|
|
ENA => RXFIFO_ENA,
|
278 |
|
|
BUSY => RXFIFO_BUSY,
|
279 |
|
|
DO => RXDATA,
|
280 |
|
|
VAL => RXVAL,
|
281 |
|
|
HOLD => RXHOLD,
|
282 |
|
|
SIZEW => RXSIZE_FX2,
|
283 |
|
|
SIZER => RXSIZE_USR
|
284 |
|
|
);
|
285 |
|
|
|
286 |
|
|
TXFIFO : fifo_2c_dram -- output fifo, 2 clock, dram based
|
287 |
|
|
generic map (
|
288 |
|
|
AWIDTH => TXFAWIDTH,
|
289 |
|
|
DWIDTH => 8)
|
290 |
|
|
port map (
|
291 |
|
|
CLKW => CLK,
|
292 |
|
|
CLKR => I_FX2_IFCLK,
|
293 |
|
|
RESETW => RESET,
|
294 |
|
|
RESETR => '0',
|
295 |
|
|
DI => TXDATA,
|
296 |
|
|
ENA => TXENA,
|
297 |
|
|
BUSY => TXBUSY_L,
|
298 |
|
|
DO => TXFIFO_DO,
|
299 |
|
|
VAL => TXFIFO_VAL,
|
300 |
|
|
HOLD => TXFIFO_HOLD,
|
301 |
|
|
SIZEW => TXSIZE_USR,
|
302 |
|
|
SIZER => TXSIZE_FX2
|
303 |
|
|
);
|
304 |
|
|
|
305 |
|
|
TX2FIFO : fifo_2c_dram -- output 2 fifo, 2 clock, dram based
|
306 |
|
|
generic map (
|
307 |
|
|
AWIDTH => TXFAWIDTH,
|
308 |
|
|
DWIDTH => 8)
|
309 |
|
|
port map (
|
310 |
|
|
CLKW => CLK,
|
311 |
|
|
CLKR => I_FX2_IFCLK,
|
312 |
|
|
RESETW => RESET,
|
313 |
|
|
RESETR => '0',
|
314 |
|
|
DI => TX2DATA,
|
315 |
|
|
ENA => TX2ENA,
|
316 |
|
|
BUSY => TX2BUSY_L,
|
317 |
|
|
DO => TX2FIFO_DO,
|
318 |
|
|
VAL => TX2FIFO_VAL,
|
319 |
|
|
HOLD => TX2FIFO_HOLD,
|
320 |
|
|
SIZEW => TX2SIZE_USR,
|
321 |
|
|
SIZER => TX2SIZE_FX2
|
322 |
|
|
);
|
323 |
|
|
|
324 |
|
|
proc_regs: process (I_FX2_IFCLK)
|
325 |
|
|
begin
|
326 |
|
|
|
327 |
|
|
if rising_edge(I_FX2_IFCLK) then
|
328 |
|
|
if RESET = '1' then
|
329 |
|
|
R_REGS <= regs_init;
|
330 |
|
|
else
|
331 |
|
|
R_REGS <= N_REGS;
|
332 |
|
|
end if;
|
333 |
|
|
end if;
|
334 |
|
|
|
335 |
|
|
end process proc_regs;
|
336 |
|
|
|
337 |
|
|
proc_next: process (R_REGS,
|
338 |
|
|
FX2_FLAG_N, TXFIFO_VAL, TX2FIFO_VAL,
|
339 |
|
|
TXFIFO_DO, TX2FIFO_DO,
|
340 |
|
|
RXSIZE_FX2, RXFIFO_BUSY, TXBUSY_L, TX2BUSY_L)
|
341 |
|
|
|
342 |
|
|
variable r : regs_type := regs_init;
|
343 |
|
|
variable n : regs_type := regs_init;
|
344 |
|
|
|
345 |
|
|
variable ififo_ce : slbit := '0';
|
346 |
|
|
variable ififo : slv2 := "00";
|
347 |
|
|
|
348 |
|
|
variable irxfifo_ena : slbit := '0';
|
349 |
|
|
variable itxfifo_hold : slbit := '0';
|
350 |
|
|
variable itx2fifo_hold : slbit := '0';
|
351 |
|
|
|
352 |
|
|
variable islrd : slbit := '0';
|
353 |
|
|
variable islwr : slbit := '0';
|
354 |
|
|
variable isloe : slbit := '0';
|
355 |
|
|
variable ipktend : slbit := '0';
|
356 |
|
|
|
357 |
|
|
variable idata_cei : slbit := '0';
|
358 |
|
|
variable idata_ceo : slbit := '0';
|
359 |
|
|
variable idata_oe : slbit := '0';
|
360 |
|
|
variable idata_do : slv8 := (others=>'0');
|
361 |
|
|
|
362 |
|
|
variable slrxok : slbit := '0';
|
363 |
|
|
variable sltxok : slbit := '0';
|
364 |
|
|
variable sltx2ok : slbit := '0';
|
365 |
|
|
variable pipeok : slbit := '0';
|
366 |
|
|
|
367 |
|
|
variable cc_clr : slbit := '0';
|
368 |
|
|
variable cc_cnt : slbit := '0';
|
369 |
|
|
variable cc_done : slbit := '0';
|
370 |
|
|
|
371 |
|
|
begin
|
372 |
|
|
|
373 |
|
|
r := R_REGS;
|
374 |
|
|
n := R_REGS;
|
375 |
|
|
|
376 |
|
|
ififo_ce := '0';
|
377 |
|
|
ififo := "00";
|
378 |
|
|
|
379 |
|
|
irxfifo_ena := '0';
|
380 |
|
|
itxfifo_hold := '1';
|
381 |
|
|
itx2fifo_hold := '1';
|
382 |
|
|
|
383 |
|
|
islrd := '0';
|
384 |
|
|
islwr := '0';
|
385 |
|
|
isloe := '0';
|
386 |
|
|
ipktend := '0';
|
387 |
|
|
|
388 |
|
|
idata_cei := '0';
|
389 |
|
|
idata_ceo := '0';
|
390 |
|
|
idata_oe := '0';
|
391 |
|
|
idata_do := TXFIFO_DO;
|
392 |
|
|
|
393 |
|
|
slrxok := FX2_FLAG_N(c_flag_rx_ef); -- empty flag is act.low!
|
394 |
|
|
sltxok := FX2_FLAG_N(c_flag_tx_ff); -- full flag is act.low!
|
395 |
|
|
sltx2ok := FX2_FLAG_N(c_flag_tx2_ff); -- full flag is act.low!
|
396 |
|
|
pipeok := FX2_FLAG_N(c_flag_prog); -- almost flag is act.low!
|
397 |
|
|
|
398 |
|
|
cc_clr := '0';
|
399 |
|
|
cc_cnt := '0';
|
400 |
|
|
if unsigned(r.ccnt) = 0 then
|
401 |
|
|
cc_done := '1';
|
402 |
|
|
else
|
403 |
|
|
cc_done := '0';
|
404 |
|
|
end if;
|
405 |
18 |
wfjm |
|
406 |
|
|
n.rxpipe1 := '0';
|
407 |
17 |
wfjm |
|
408 |
|
|
case r.state is
|
409 |
|
|
when s_idle => -- s_idle:
|
410 |
|
|
if slrxok='1' and RXFIFO_BUSY='0' then
|
411 |
|
|
ififo_ce := '1';
|
412 |
|
|
ififo := c_rxfifo;
|
413 |
|
|
n.state := s_rxprep1;
|
414 |
|
|
elsif sltxok='1' and (TXFIFO_VAL='1' or r.pepend='1')then
|
415 |
|
|
ififo_ce := '1';
|
416 |
|
|
ififo := c_txfifo;
|
417 |
|
|
n.state := s_txprep1;
|
418 |
|
|
elsif sltx2ok='1' and (TX2FIFO_VAL='1' or r.pe2pend='1')then
|
419 |
|
|
ififo_ce := '1';
|
420 |
|
|
ififo := c_tx2fifo;
|
421 |
|
|
n.state := s_tx2prep1;
|
422 |
|
|
end if;
|
423 |
|
|
|
424 |
|
|
when s_rxprep0 => -- s_rxprep0: switch to rx-fifo
|
425 |
|
|
ififo_ce := '1';
|
426 |
|
|
ififo := c_rxfifo;
|
427 |
|
|
n.state := s_rxprep1;
|
428 |
|
|
|
429 |
|
|
when s_rxprep1 => -- s_rxprep1: fifo addr setup
|
430 |
|
|
cc_clr := '1';
|
431 |
|
|
n.state := s_rxprep2;
|
432 |
|
|
|
433 |
|
|
when s_rxprep2 => -- s_rxprep2: wait for flags
|
434 |
|
|
isloe := '1';
|
435 |
|
|
n.state := s_rxdisp;
|
436 |
|
|
|
437 |
|
|
when s_rxdisp => -- s_rxdisp: read, dispatch
|
438 |
|
|
isloe := '1';
|
439 |
|
|
-- if chunk done and tx or pe pending and possible
|
440 |
|
|
if cc_done='1' and sltxok='1' and (TXFIFO_VAL='1' or r.pepend='1') then
|
441 |
18 |
wfjm |
if r.rxpipe1='1' or r.rxpipe2='1' then -- rx pipe busy ?
|
442 |
|
|
n.state := s_rxdisp; -- wait
|
443 |
|
|
else
|
444 |
|
|
n.state := s_txprep0; -- otherwise switch to tx flow
|
445 |
|
|
end if;
|
446 |
17 |
wfjm |
-- if chunk done and tx2 or pe2 pending and possible
|
447 |
|
|
elsif cc_done='1' and sltx2ok='1' and (TX2FIFO_VAL='1' or r.pe2pend='1')
|
448 |
|
|
then
|
449 |
18 |
wfjm |
if r.rxpipe1='1' or r.rxpipe2='1' then -- rx pipe busy ?
|
450 |
|
|
n.state := s_rxdisp; -- wait
|
451 |
|
|
else
|
452 |
|
|
n.state := s_tx2prep0;
|
453 |
|
|
end if;
|
454 |
17 |
wfjm |
-- if more rx to do and possible
|
455 |
18 |
wfjm |
elsif slrxok='1' and unsigned(RXSIZE_FX2)>3 then -- !thres must be >3!
|
456 |
|
|
islrd := '1';
|
457 |
17 |
wfjm |
cc_cnt := '1';
|
458 |
18 |
wfjm |
n.rxpipe1 := '1';
|
459 |
|
|
if pipeok='1' then
|
460 |
|
|
n.state := s_rxdisp; -- 1 cycle read
|
461 |
|
|
--n.state := s_rxprep2; -- 2 cycle read
|
462 |
17 |
wfjm |
else
|
463 |
|
|
n.state := s_rxpipe;
|
464 |
18 |
wfjm |
end if;
|
465 |
17 |
wfjm |
-- otherwise back to idle
|
466 |
|
|
else
|
467 |
18 |
wfjm |
if r.rxpipe1='1' or r.rxpipe2='1' then -- rx pipe busy ?
|
468 |
|
|
n.state := s_rxdisp; -- wait
|
469 |
|
|
else
|
470 |
|
|
n.state := s_idle; -- to idle
|
471 |
|
|
end if;
|
472 |
17 |
wfjm |
end if;
|
473 |
|
|
|
474 |
18 |
wfjm |
when s_rxpipe => -- s_rxpipe: read, pipe wait
|
475 |
17 |
wfjm |
isloe := '1';
|
476 |
18 |
wfjm |
n.state := s_rxprep2;
|
477 |
17 |
wfjm |
|
478 |
|
|
when s_txprep0 => -- s_txprep0: switch to tx-fifo
|
479 |
|
|
ififo_ce := '1';
|
480 |
|
|
ififo := c_txfifo;
|
481 |
|
|
n.state := s_txprep1;
|
482 |
|
|
|
483 |
|
|
when s_txprep1 => -- s_txprep1: fifo addr setup
|
484 |
|
|
cc_clr := '1';
|
485 |
|
|
n.state := s_txprep2;
|
486 |
|
|
|
487 |
|
|
when s_txprep2 => -- s_txprep2: wait for flags
|
488 |
|
|
n.state := s_txdisp;
|
489 |
|
|
|
490 |
|
|
when s_txdisp => -- s_txdisp: write, dispatch
|
491 |
|
|
-- if chunk done and tx2 or pe2 pending and possible
|
492 |
|
|
if cc_done='1' and sltx2ok='1' and (TX2FIFO_VAL='1' or r.pe2pend='1')
|
493 |
|
|
then
|
494 |
|
|
n.state := s_tx2prep0;
|
495 |
|
|
-- if chunk done and rx pending and possible
|
496 |
|
|
elsif cc_done='1' and slrxok='1' and RXFIFO_BUSY='0' then
|
497 |
|
|
n.state := s_rxprep0;
|
498 |
|
|
-- if pktend to do and possible
|
499 |
|
|
elsif sltxok = '1' and r.pepend = '1' then
|
500 |
|
|
ipktend := '1';
|
501 |
|
|
n.pepend := '0';
|
502 |
|
|
n.state := s_idle;
|
503 |
|
|
-- if more tx to do and possible
|
504 |
|
|
elsif sltxok = '1' and TXFIFO_VAL = '1' then
|
505 |
|
|
cc_cnt := '1'; -- inc chunk count
|
506 |
|
|
n.pepend := '0'; -- cancel pe (avoid back-2-back tx+pe)
|
507 |
|
|
itxfifo_hold := '0';
|
508 |
|
|
idata_do := TXFIFO_DO;
|
509 |
|
|
idata_ceo := '1';
|
510 |
|
|
idata_oe := '1';
|
511 |
|
|
islwr := '1';
|
512 |
|
|
if pipeok = '1' then -- if not almost full
|
513 |
|
|
n.state := s_txdisp; -- stream
|
514 |
|
|
else
|
515 |
|
|
n.state := s_txprep1; -- wait for full flag
|
516 |
|
|
end if;
|
517 |
|
|
-- otherwise back to idle
|
518 |
|
|
else
|
519 |
|
|
n.state := s_idle;
|
520 |
|
|
end if;
|
521 |
|
|
|
522 |
|
|
when s_tx2prep0 => -- s_tx2prep0: switch to tx2-fifo
|
523 |
|
|
ififo_ce := '1';
|
524 |
|
|
ififo := c_tx2fifo;
|
525 |
|
|
n.state := s_tx2prep1;
|
526 |
|
|
|
527 |
|
|
when s_tx2prep1 => -- s_tx2prep1: fifo addr setup
|
528 |
|
|
cc_clr := '1';
|
529 |
|
|
n.state := s_tx2prep2;
|
530 |
|
|
|
531 |
|
|
when s_tx2prep2 => -- s_tx2prep2: wait for flags
|
532 |
|
|
n.state := s_tx2disp;
|
533 |
|
|
|
534 |
|
|
when s_tx2disp => -- s_tx2disp: write, dispatch
|
535 |
|
|
-- if chunk done and rx pending and possible
|
536 |
|
|
if cc_done='1' and slrxok='1' and RXFIFO_BUSY='0' then
|
537 |
|
|
n.state := s_rxprep0;
|
538 |
|
|
-- if chunk done and tx or pe pending and possible
|
539 |
|
|
elsif cc_done='1' and sltxok='1' and (TXFIFO_VAL='1' or r.pepend='1')
|
540 |
|
|
then
|
541 |
|
|
n.state := s_txprep0;
|
542 |
|
|
-- if pktend 2 to do and possible
|
543 |
|
|
elsif sltx2ok = '1' and r.pe2pend = '1' then
|
544 |
|
|
ipktend := '1';
|
545 |
|
|
n.pe2pend := '0';
|
546 |
|
|
n.state := s_idle;
|
547 |
|
|
-- if more tx2 to do and possible
|
548 |
|
|
elsif sltx2ok = '1' and TX2FIFO_VAL = '1' then
|
549 |
|
|
cc_cnt := '1'; -- inc chunk count
|
550 |
|
|
n.pe2pend := '0'; -- cancel pe (avoid back-2-back tx+pe)
|
551 |
|
|
itx2fifo_hold := '0';
|
552 |
|
|
idata_do := TX2FIFO_DO;
|
553 |
|
|
idata_ceo := '1';
|
554 |
|
|
idata_oe := '1';
|
555 |
|
|
islwr := '1';
|
556 |
|
|
if pipeok = '1' then -- if not almost full
|
557 |
|
|
n.state := s_tx2disp; -- stream
|
558 |
|
|
else
|
559 |
|
|
n.state := s_tx2prep1; -- wait for full flag
|
560 |
|
|
end if;
|
561 |
|
|
-- otherwise back to idle
|
562 |
|
|
else
|
563 |
|
|
n.state := s_idle;
|
564 |
|
|
end if;
|
565 |
|
|
|
566 |
|
|
when others => null;
|
567 |
|
|
end case;
|
568 |
|
|
|
569 |
18 |
wfjm |
-- rx pipe handling
|
570 |
|
|
idata_cei := r.rxpipe1;
|
571 |
|
|
n.rxpipe2 := r.rxpipe1;
|
572 |
|
|
irxfifo_ena := r.rxpipe2;
|
573 |
|
|
|
574 |
17 |
wfjm |
-- chunk counter handling
|
575 |
|
|
if cc_clr = '1' then
|
576 |
|
|
n.ccnt := (others=>'1');
|
577 |
|
|
elsif cc_cnt='1' and unsigned(r.ccnt) > 0 then
|
578 |
|
|
n.ccnt := slv(unsigned(r.ccnt) - 1);
|
579 |
|
|
end if;
|
580 |
|
|
|
581 |
|
|
-- pktend time-out handling:
|
582 |
|
|
-- if tx fifo is non-empty, set counter to max
|
583 |
|
|
-- if tx fifo is empty, count down every usec
|
584 |
|
|
-- on 1->0 transition queue pktend request
|
585 |
|
|
if TXFIFO_VAL = '1' then
|
586 |
|
|
n.petocnt := (others=>'1');
|
587 |
|
|
else
|
588 |
|
|
if unsigned(r.petocnt) /= 0 then
|
589 |
|
|
n.petocnt := slv(unsigned(r.petocnt) - 1);
|
590 |
|
|
if unsigned(r.petocnt) = 1 then
|
591 |
|
|
n.pepend := '1';
|
592 |
|
|
end if;
|
593 |
|
|
end if;
|
594 |
|
|
end if;
|
595 |
|
|
if TX2FIFO_VAL = '1' then
|
596 |
|
|
n.pe2tocnt := (others=>'1');
|
597 |
|
|
else
|
598 |
|
|
if unsigned(r.pe2tocnt) /= 0 then
|
599 |
|
|
n.pe2tocnt := slv(unsigned(r.pe2tocnt) - 1);
|
600 |
|
|
if unsigned(r.pe2tocnt) = 1 then
|
601 |
|
|
n.pe2pend := '1';
|
602 |
|
|
end if;
|
603 |
|
|
end if;
|
604 |
|
|
end if;
|
605 |
|
|
|
606 |
|
|
n.moni_ep4_sel := '0';
|
607 |
|
|
n.moni_ep6_sel := '0';
|
608 |
|
|
n.moni_ep8_sel := '0';
|
609 |
|
|
if r.state = s_rxdisp or r.state = s_rxpipe then
|
610 |
|
|
n.moni_ep4_sel := '1';
|
611 |
|
|
n.moni_ep4_pf := not FX2_FLAG_N(c_flag_prog);
|
612 |
|
|
elsif r.state = s_txdisp then
|
613 |
|
|
n.moni_ep6_sel := '1';
|
614 |
|
|
n.moni_ep6_pf := not FX2_FLAG_N(c_flag_prog);
|
615 |
|
|
elsif r.state = s_tx2disp then
|
616 |
|
|
n.moni_ep8_sel := '1';
|
617 |
|
|
n.moni_ep8_pf := not FX2_FLAG_N(c_flag_prog);
|
618 |
|
|
end if;
|
619 |
|
|
|
620 |
|
|
N_REGS <= n;
|
621 |
|
|
|
622 |
|
|
FX2_FIFO_CE <= ififo_ce;
|
623 |
|
|
FX2_FIFO <= ififo;
|
624 |
|
|
|
625 |
|
|
FX2_SLRD_N <= not islrd;
|
626 |
|
|
FX2_SLWR_N <= not islwr;
|
627 |
|
|
FX2_SLOE_N <= not isloe;
|
628 |
|
|
FX2_PKTEND_N <= not ipktend;
|
629 |
|
|
|
630 |
|
|
FX2_DATA_CEI <= idata_cei;
|
631 |
|
|
FX2_DATA_CEO <= idata_ceo;
|
632 |
|
|
FX2_DATA_OE <= idata_oe;
|
633 |
|
|
FX2_DATA_DO <= idata_do;
|
634 |
|
|
|
635 |
|
|
RXFIFO_ENA <= irxfifo_ena;
|
636 |
|
|
TXFIFO_HOLD <= itxfifo_hold;
|
637 |
|
|
TX2FIFO_HOLD <= itx2fifo_hold;
|
638 |
|
|
|
639 |
|
|
end process proc_next;
|
640 |
|
|
|
641 |
|
|
proc_moni: process (CLK)
|
642 |
|
|
begin
|
643 |
|
|
|
644 |
|
|
if rising_edge(CLK) then
|
645 |
|
|
if RESET = '1' then
|
646 |
|
|
R_MONI_C <= fx2ctl_moni_init;
|
647 |
|
|
R_MONI_S <= fx2ctl_moni_init;
|
648 |
|
|
else
|
649 |
|
|
R_MONI_C <= fx2ctl_moni_init;
|
650 |
|
|
R_MONI_C.fifo_ep4 <= R_REGS.moni_ep4_sel;
|
651 |
|
|
R_MONI_C.fifo_ep6 <= R_REGS.moni_ep6_sel;
|
652 |
|
|
R_MONI_C.fifo_ep8 <= R_REGS.moni_ep8_sel;
|
653 |
|
|
R_MONI_C.flag_ep4_empty <= not FX2_FLAG_N(c_flag_rx_ef);
|
654 |
|
|
R_MONI_C.flag_ep4_almost <= R_REGS.moni_ep4_pf;
|
655 |
|
|
R_MONI_C.flag_ep6_full <= not FX2_FLAG_N(c_flag_tx_ff);
|
656 |
|
|
R_MONI_C.flag_ep6_almost <= R_REGS.moni_ep6_pf;
|
657 |
|
|
R_MONI_C.flag_ep8_full <= not FX2_FLAG_N(c_flag_tx2_ff);
|
658 |
|
|
R_MONI_C.flag_ep8_almost <= R_REGS.moni_ep8_pf;
|
659 |
|
|
R_MONI_C.slrd <= not FX2_SLRD_N;
|
660 |
|
|
R_MONI_C.slwr <= not FX2_SLWR_N;
|
661 |
|
|
R_MONI_C.pktend <= not FX2_PKTEND_N;
|
662 |
|
|
R_MONI_S <= R_MONI_C;
|
663 |
|
|
end if;
|
664 |
|
|
end if;
|
665 |
|
|
|
666 |
|
|
end process proc_moni;
|
667 |
|
|
|
668 |
|
|
proc_almost: process (RXSIZE_USR, TXSIZE_USR, TX2SIZE_USR)
|
669 |
|
|
begin
|
670 |
|
|
|
671 |
|
|
-- rxsize_usr is the number of bytes to read
|
672 |
|
|
-- txsize_usr is the number of bytes to write
|
673 |
|
|
|
674 |
|
|
if unsigned(RXSIZE_USR) <= RXAEMPTY_THRES then
|
675 |
|
|
RXAEMPTY <= '1';
|
676 |
|
|
else
|
677 |
|
|
RXAEMPTY <= '0';
|
678 |
|
|
end if;
|
679 |
|
|
|
680 |
|
|
if unsigned(TXSIZE_USR) <= TXAFULL_THRES then
|
681 |
|
|
TXAFULL <= '1';
|
682 |
|
|
else
|
683 |
|
|
TXAFULL <= '0';
|
684 |
|
|
end if;
|
685 |
|
|
|
686 |
|
|
if unsigned(TX2SIZE_USR) <= TX2AFULL_THRES then
|
687 |
|
|
TX2AFULL <= '1';
|
688 |
|
|
else
|
689 |
|
|
TX2AFULL <= '0';
|
690 |
|
|
end if;
|
691 |
|
|
|
692 |
|
|
end process proc_almost;
|
693 |
|
|
|
694 |
|
|
TXBUSY <= TXBUSY_L;
|
695 |
|
|
TX2BUSY <= TX2BUSY_L;
|
696 |
|
|
|
697 |
|
|
MONI <= R_MONI_S;
|
698 |
|
|
|
699 |
|
|
end syn;
|