1 |
36 |
wfjm |
-- $Id: fifo_2c_dram.vhd 751 2016-03-25 19:46:11Z mueller $
|
2 |
16 |
wfjm |
--
|
3 |
|
|
-- Copyright 2007-2011 by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
|
4 |
|
|
--
|
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: fifo_2c_dram - syn
|
16 |
|
|
-- Description: FIFO, two clock domain, distributed RAM based, with
|
17 |
|
|
-- enable/busy/valid/hold interface.
|
18 |
|
|
--
|
19 |
|
|
-- Dependencies: ram_1swar_1ar_gen
|
20 |
|
|
-- genlib/gray_cnt_n
|
21 |
|
|
-- genlib/gray2bin_gen
|
22 |
|
|
--
|
23 |
|
|
-- Test bench: tb/tb_fifo_2c_dram
|
24 |
|
|
-- Target Devices: generic Spartan, Virtex
|
25 |
36 |
wfjm |
-- Tool versions: xst 8.2-14.7; ghdl 0.18-0.33
|
26 |
16 |
wfjm |
-- Revision History:
|
27 |
|
|
-- Date Rev Version Comment
|
28 |
|
|
-- 2011-11-13 424 1.1 use capture+sync flops; reset now glitch free
|
29 |
|
|
-- 2011-11-07 421 1.0.2 now numeric_std clean
|
30 |
|
|
-- 2007-12-28 107 1.0.1 VAL=0 in cycle after RESETR=1
|
31 |
|
|
-- 2007-12-28 106 1.0 Initial version
|
32 |
|
|
--
|
33 |
|
|
-- Some synthesis results:
|
34 |
|
|
-- - 2011-11-13 Rev 424: ise 13.1 for xc3s1000-ft256-4:
|
35 |
|
|
-- AWIDTH DWIDTH LUT.l LUT.m LUT.s Flop Slice CLKW CLKR (xst est.)
|
36 |
|
|
-- 4 16 41 32 12 38 54 135MHz 115MHz ( 16 words)
|
37 |
|
|
-- 5 16 65 64 14 40 80 113MHz 116MHz ( 32 words)
|
38 |
|
|
-- - 2007-12-28 Rev 106: ise 8.2.03 for xc3s1000-ft256-4:
|
39 |
|
|
-- AWIDTH DWIDTH LUT.l LUT.m Flop CLKW CLKR (xst est.)
|
40 |
|
|
-- 4 16 40 32 42 141MHz 165MHz ( 16 words)
|
41 |
|
|
-- 5 16 65 64 52 108MHz 108MHz ( 32 words)
|
42 |
|
|
-- 6 16 95 128 61 111MHz 113MHz ( 64 words)
|
43 |
|
|
-- 7 16 149 256 74 100MHz 96MHz (128 words)
|
44 |
|
|
------------------------------------------------------------------------------
|
45 |
|
|
|
46 |
|
|
library ieee;
|
47 |
|
|
use ieee.std_logic_1164.all;
|
48 |
|
|
use ieee.numeric_std.all;
|
49 |
|
|
|
50 |
|
|
use work.slvtypes.all;
|
51 |
|
|
use work.genlib.all;
|
52 |
|
|
use work.memlib.all;
|
53 |
|
|
|
54 |
|
|
entity fifo_2c_dram is -- fifo, 2 clock, dram based
|
55 |
|
|
generic (
|
56 |
|
|
AWIDTH : positive := 5; -- address width (sets size)
|
57 |
|
|
DWIDTH : positive := 16); -- data width
|
58 |
|
|
port (
|
59 |
|
|
CLKW : in slbit; -- clock (write side)
|
60 |
|
|
CLKR : in slbit; -- clock (read side)
|
61 |
|
|
RESETW : in slbit; -- W|reset from write side
|
62 |
|
|
RESETR : in slbit; -- R|reset from read side
|
63 |
|
|
DI : in slv(DWIDTH-1 downto 0); -- W|input data
|
64 |
|
|
ENA : in slbit; -- W|write enable
|
65 |
|
|
BUSY : out slbit; -- W|write port hold
|
66 |
|
|
DO : out slv(DWIDTH-1 downto 0); -- R|output data
|
67 |
|
|
VAL : out slbit; -- R|read valid
|
68 |
|
|
HOLD : in slbit; -- R|read hold
|
69 |
|
|
SIZEW : out slv(AWIDTH-1 downto 0); -- W|number slots to write
|
70 |
|
|
SIZER : out slv(AWIDTH-1 downto 0) -- R|number slots to read
|
71 |
|
|
);
|
72 |
|
|
end fifo_2c_dram;
|
73 |
|
|
|
74 |
|
|
|
75 |
|
|
architecture syn of fifo_2c_dram is
|
76 |
|
|
|
77 |
|
|
type regw_type is record
|
78 |
|
|
raddr_c : slv(AWIDTH-1 downto 0); -- read address (capt from CLKR)
|
79 |
|
|
raddr_s : slv(AWIDTH-1 downto 0); -- read address (sync in CLKW)
|
80 |
|
|
sizew : slv(AWIDTH-1 downto 0); -- slots to write
|
81 |
|
|
busy : slbit; -- busy flag
|
82 |
|
|
rstw : slbit; -- resetw active
|
83 |
|
|
rstw_sc : slbit; -- resetw (sync-capt from CLKR-CLKW)
|
84 |
|
|
rstw_ss : slbit; -- resetw (sync-sync from CLKR-CLKW)
|
85 |
|
|
rstr_c : slbit; -- resetr (capt from CLKR)
|
86 |
|
|
rstr_s : slbit; -- resetr (sync from CLKR)
|
87 |
|
|
end record regw_type;
|
88 |
|
|
|
89 |
|
|
constant regw_init : regw_type := (
|
90 |
|
|
slv(to_unsigned(0,AWIDTH)), -- raddr_c
|
91 |
|
|
slv(to_unsigned(0,AWIDTH)), -- raddr_s
|
92 |
|
|
slv(to_unsigned(0,AWIDTH)), -- sizew
|
93 |
|
|
'0', -- busy
|
94 |
|
|
'0','0','0', -- rstw,rstw_sc,rstw_ss
|
95 |
|
|
'0','0' -- rstr_c,rstr_s
|
96 |
|
|
);
|
97 |
|
|
|
98 |
|
|
type regr_type is record
|
99 |
|
|
waddr_c : slv(AWIDTH-1 downto 0); -- write address (capt from CLKW)
|
100 |
|
|
waddr_s : slv(AWIDTH-1 downto 0); -- write address (sync in CLKR)
|
101 |
|
|
sizer : slv(AWIDTH-1 downto 0); -- slots to read
|
102 |
|
|
val : slbit; -- valid flag
|
103 |
|
|
rstr : slbit; -- resetr active
|
104 |
|
|
rstr_sc : slbit; -- resetr (sync-capt from CLKW-CLKR)
|
105 |
|
|
rstr_ss : slbit; -- resetr (sync-sync from CLKW-CLKR)
|
106 |
|
|
rstw_c : slbit; -- resetw (capt from CLKW)
|
107 |
|
|
rstw_s : slbit; -- resetw (sync from CLKW)
|
108 |
|
|
end record regr_type;
|
109 |
|
|
|
110 |
|
|
constant regr_init : regr_type := (
|
111 |
|
|
slv(to_unsigned(0,AWIDTH)), -- waddr_c
|
112 |
|
|
slv(to_unsigned(0,AWIDTH)), -- waddr_s
|
113 |
|
|
slv(to_unsigned(0,AWIDTH)), -- sizer
|
114 |
|
|
'0', -- val
|
115 |
|
|
'0','0','0', -- rstr,rstr_sc,rstr_ss
|
116 |
|
|
'0','0' -- rstw_c,rstw_s
|
117 |
|
|
);
|
118 |
|
|
|
119 |
|
|
signal R_REGW : regw_type := regw_init; -- write side state registers
|
120 |
|
|
signal N_REGW : regw_type := regw_init; -- next values write side
|
121 |
|
|
signal R_REGR : regr_type := regr_init; -- read side state registers
|
122 |
|
|
signal N_REGR : regr_type := regr_init; -- next values read side
|
123 |
|
|
|
124 |
|
|
signal WADDR : slv(AWIDTH-1 downto 0) := (others=>'0');
|
125 |
|
|
signal RADDR : slv(AWIDTH-1 downto 0) := (others=>'0');
|
126 |
|
|
signal WADDR_BIN : slv(AWIDTH-1 downto 0) := (others=>'0');
|
127 |
|
|
signal RADDR_BIN : slv(AWIDTH-1 downto 0) := (others=>'0');
|
128 |
|
|
signal WADDR_S_BIN : slv(AWIDTH-1 downto 0) := (others=>'0');
|
129 |
|
|
signal RADDR_S_BIN : slv(AWIDTH-1 downto 0) := (others=>'0');
|
130 |
|
|
|
131 |
|
|
signal GCW_RST : slbit := '0';
|
132 |
|
|
signal GCW_CE : slbit := '0';
|
133 |
|
|
signal GCR_RST : slbit := '0';
|
134 |
|
|
signal GCR_CE : slbit := '0';
|
135 |
|
|
|
136 |
|
|
begin
|
137 |
|
|
|
138 |
|
|
RAM : ram_1swar_1ar_gen -- dual ported memory
|
139 |
|
|
generic map (
|
140 |
|
|
AWIDTH => AWIDTH,
|
141 |
|
|
DWIDTH => DWIDTH)
|
142 |
|
|
port map (
|
143 |
|
|
CLK => CLKW,
|
144 |
|
|
WE => GCW_CE,
|
145 |
|
|
ADDRA => WADDR,
|
146 |
|
|
ADDRB => RADDR,
|
147 |
|
|
DI => DI,
|
148 |
|
|
DOA => open,
|
149 |
|
|
DOB => DO
|
150 |
|
|
);
|
151 |
|
|
|
152 |
|
|
GCW : gray_cnt_gen -- gray counter for write address
|
153 |
|
|
generic map (
|
154 |
|
|
DWIDTH => AWIDTH)
|
155 |
|
|
port map (
|
156 |
|
|
CLK => CLKW,
|
157 |
|
|
RESET => GCW_RST,
|
158 |
|
|
CE => GCW_CE,
|
159 |
|
|
DATA => WADDR
|
160 |
|
|
);
|
161 |
|
|
|
162 |
|
|
GCR : gray_cnt_gen -- gray counter for read address
|
163 |
|
|
generic map (
|
164 |
|
|
DWIDTH => AWIDTH)
|
165 |
|
|
port map (
|
166 |
|
|
CLK => CLKR,
|
167 |
|
|
RESET => GCR_RST,
|
168 |
|
|
CE => GCR_CE,
|
169 |
|
|
DATA => RADDR
|
170 |
|
|
);
|
171 |
|
|
|
172 |
|
|
G2B_WW : gray2bin_gen -- gray->bin for waddr on write side
|
173 |
|
|
generic map (DWIDTH => AWIDTH)
|
174 |
|
|
port map (DI => WADDR, DO => WADDR_BIN);
|
175 |
|
|
G2B_WR : gray2bin_gen -- gray->bin for waddr on read side
|
176 |
|
|
generic map (DWIDTH => AWIDTH)
|
177 |
|
|
port map (DI => R_REGR.waddr_s, DO => WADDR_S_BIN);
|
178 |
36 |
wfjm |
G2B_RR : gray2bin_gen -- gray->bin for raddr on read side
|
179 |
16 |
wfjm |
generic map (DWIDTH => AWIDTH)
|
180 |
|
|
port map (DI => RADDR, DO => RADDR_BIN);
|
181 |
36 |
wfjm |
G2B_RW : gray2bin_gen -- gray->bin for raddr on write side
|
182 |
16 |
wfjm |
generic map (DWIDTH => AWIDTH)
|
183 |
|
|
port map (DI => R_REGW.raddr_s, DO => RADDR_S_BIN);
|
184 |
|
|
|
185 |
36 |
wfjm |
--
|
186 |
|
|
-- write side --------------------------------------------------------------
|
187 |
|
|
--
|
188 |
16 |
wfjm |
proc_regw: process (CLKW)
|
189 |
|
|
begin
|
190 |
|
|
if rising_edge(CLKW) then
|
191 |
|
|
R_REGW <= N_REGW;
|
192 |
|
|
end if;
|
193 |
|
|
end process proc_regw;
|
194 |
|
|
|
195 |
|
|
proc_nextw: process (R_REGW, RESETW, ENA, R_REGR,
|
196 |
|
|
RADDR, RADDR_S_BIN, WADDR_BIN)
|
197 |
|
|
|
198 |
|
|
variable r : regw_type := regw_init;
|
199 |
|
|
variable n : regw_type := regw_init;
|
200 |
|
|
variable ibusy : slbit := '0';
|
201 |
|
|
variable igcw_ce : slbit := '0';
|
202 |
|
|
variable igcw_rst : slbit := '0';
|
203 |
|
|
variable isizew : slv(AWIDTH-1 downto 0) := (others=>'0');
|
204 |
|
|
begin
|
205 |
|
|
|
206 |
|
|
r := R_REGW;
|
207 |
|
|
n := R_REGW;
|
208 |
|
|
|
209 |
|
|
isizew := slv(unsigned(RADDR_S_BIN) + unsigned(not WADDR_BIN));
|
210 |
|
|
ibusy := '0';
|
211 |
|
|
igcw_ce := '0';
|
212 |
|
|
igcw_rst := '0';
|
213 |
|
|
|
214 |
|
|
if unsigned(isizew) = 0 then -- if no free slots
|
215 |
|
|
ibusy := '1'; -- next cycle busy=1
|
216 |
|
|
end if;
|
217 |
|
|
|
218 |
|
|
if ENA='1' and r.busy='0' then -- if ena=1 and this cycle busy=0
|
219 |
|
|
igcw_ce := '1'; -- write this value
|
220 |
|
|
if unsigned(isizew) = 1 then -- if this last free slot
|
221 |
|
|
ibusy := '1'; -- next cycle busy=1
|
222 |
|
|
end if;
|
223 |
|
|
end if;
|
224 |
|
|
|
225 |
|
|
if RESETW = '1' then -- reset(write side) request
|
226 |
|
|
n.rstw := '1'; -- set RSTW flag
|
227 |
|
|
elsif r.rstw_ss = '1' then -- request gone and return seen
|
228 |
|
|
n.rstw := '0'; -- clear RSTW flag
|
229 |
|
|
end if;
|
230 |
|
|
|
231 |
|
|
if r.rstw='1' and r.rstw_ss='1' then -- RSTW seen on write and read side
|
232 |
|
|
igcw_rst := '1'; -- clear write address counter
|
233 |
|
|
end if;
|
234 |
|
|
if r.rstr_s = '1' then -- RSTR active
|
235 |
|
|
igcw_rst := '1'; -- clear write address counter
|
236 |
|
|
end if;
|
237 |
|
|
|
238 |
|
|
if RESETW='1' or r.rstw='1' or r.rstw_ss='1' or r.rstr_s='1'
|
239 |
|
|
then -- RESETW or RESETR active
|
240 |
|
|
ibusy := '1'; -- signal write side busy
|
241 |
|
|
isizew := (others=>'1');
|
242 |
|
|
end if;
|
243 |
|
|
|
244 |
|
|
n.busy := ibusy;
|
245 |
|
|
n.sizew := isizew;
|
246 |
|
|
|
247 |
|
|
n.raddr_c := RADDR; -- data captuture from CLKR
|
248 |
|
|
n.raddr_s := r.raddr_c;
|
249 |
|
|
n.rstw_sc := R_REGR.rstw_s;
|
250 |
|
|
n.rstw_ss := r.rstw_sc;
|
251 |
|
|
n.rstr_c := R_REGR.rstr;
|
252 |
|
|
n.rstr_s := r.rstr_c;
|
253 |
|
|
|
254 |
|
|
N_REGW <= n;
|
255 |
|
|
|
256 |
|
|
GCW_CE <= igcw_ce;
|
257 |
|
|
GCW_RST <= igcw_rst;
|
258 |
|
|
BUSY <= r.busy;
|
259 |
|
|
SIZEW <= r.sizew;
|
260 |
|
|
|
261 |
|
|
end process proc_nextw;
|
262 |
|
|
|
263 |
36 |
wfjm |
--
|
264 |
|
|
-- read side ---------------------------------------------------------------
|
265 |
|
|
--
|
266 |
16 |
wfjm |
proc_regr: process (CLKR)
|
267 |
|
|
begin
|
268 |
|
|
if rising_edge(CLKR) then
|
269 |
|
|
R_REGR <= N_REGR;
|
270 |
|
|
end if;
|
271 |
|
|
end process proc_regr;
|
272 |
|
|
|
273 |
|
|
proc_nextr: process (R_REGR, RESETR, HOLD, R_REGW,
|
274 |
|
|
WADDR, WADDR_S_BIN, RADDR_BIN)
|
275 |
|
|
|
276 |
|
|
variable r : regr_type := regr_init;
|
277 |
|
|
variable n : regr_type := regr_init;
|
278 |
|
|
variable ival : slbit := '0';
|
279 |
|
|
variable igcr_ce : slbit := '0';
|
280 |
|
|
variable igcr_rst : slbit := '0';
|
281 |
|
|
variable isizer : slv(AWIDTH-1 downto 0) := (others=>'0');
|
282 |
|
|
|
283 |
|
|
begin
|
284 |
|
|
|
285 |
|
|
r := R_REGR;
|
286 |
|
|
n := R_REGR;
|
287 |
|
|
|
288 |
|
|
isizer := slv(unsigned(WADDR_S_BIN) - unsigned(RADDR_BIN));
|
289 |
|
|
ival := '1';
|
290 |
|
|
igcr_ce := '0';
|
291 |
|
|
igcr_rst := '0';
|
292 |
|
|
|
293 |
|
|
if unsigned(isizer) = 0 then -- if nothing to read
|
294 |
|
|
ival := '0'; -- next cycle val=0
|
295 |
|
|
end if;
|
296 |
|
|
|
297 |
|
|
if r.val='1' and HOLD='0' then -- this cycle val=1 and no hold
|
298 |
|
|
igcr_ce := '1'; -- retire this value
|
299 |
|
|
if unsigned(isizer) = 1 then -- if this is last one
|
300 |
|
|
ival := '0'; -- next cycle val=0
|
301 |
|
|
end if;
|
302 |
|
|
end if;
|
303 |
|
|
|
304 |
|
|
if RESETR = '1' then -- reset(read side) request
|
305 |
|
|
n.rstr := '1'; -- set RSTR flag
|
306 |
|
|
elsif r.rstr_ss = '1' then -- request gone and return seen
|
307 |
|
|
n.rstr := '0'; -- clear RSTR flag
|
308 |
|
|
end if;
|
309 |
|
|
|
310 |
|
|
if r.rstr='1' and r.rstr_ss='1' then -- RSTR seen on read and write side
|
311 |
|
|
igcr_rst := '1'; -- clear read address counter
|
312 |
|
|
end if;
|
313 |
|
|
if r.rstw_s = '1' then -- RSTW active
|
314 |
|
|
igcr_rst := '1'; -- clear read address counter
|
315 |
|
|
end if;
|
316 |
|
|
|
317 |
|
|
if RESETR='1' or r.rstr='1' or r.rstr_ss='1' or r.rstw_s='1'
|
318 |
|
|
then -- RESETR or RESETW active
|
319 |
|
|
ival := '0'; -- signal read side empty
|
320 |
|
|
isizer := (others=>'0');
|
321 |
|
|
end if;
|
322 |
|
|
|
323 |
|
|
n.val := ival;
|
324 |
|
|
n.sizer := isizer;
|
325 |
|
|
|
326 |
|
|
n.waddr_c := WADDR; -- data captuture from CLKW
|
327 |
|
|
n.waddr_s := r.waddr_c;
|
328 |
|
|
n.rstr_sc := R_REGW.rstr_s;
|
329 |
|
|
n.rstr_ss := r.rstr_sc;
|
330 |
|
|
n.rstw_c := R_REGW.rstw;
|
331 |
|
|
n.rstw_s := r.rstw_c;
|
332 |
|
|
|
333 |
|
|
N_REGR <= n;
|
334 |
|
|
|
335 |
|
|
GCR_CE <= igcr_ce;
|
336 |
|
|
GCR_RST <= igcr_rst;
|
337 |
|
|
VAL <= r.val;
|
338 |
|
|
SIZER <= r.sizer;
|
339 |
|
|
|
340 |
|
|
end process proc_nextr;
|
341 |
|
|
|
342 |
|
|
end syn;
|