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