1 |
36 |
wfjm |
-- $Id: fifo_2c_dram2.vhd 752 2016-03-27 17:57:18Z mueller $
|
2 |
16 |
wfjm |
--
|
3 |
36 |
wfjm |
-- Copyright 2016- by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
|
4 |
16 |
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 |
36 |
wfjm |
-- Module Name: fifo_2c_dram2 - syn
|
16 |
16 |
wfjm |
-- 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 |
36 |
wfjm |
-- Target Devices: generic
|
25 |
|
|
-- Tool versions: viv 2015.4; ghdl 0.33
|
26 |
16 |
wfjm |
-- Revision History:
|
27 |
|
|
-- Date Rev Version Comment
|
28 |
36 |
wfjm |
-- 2016-03-24 751 1.0 Initial version (derived from fifo_2c_dram, is
|
29 |
|
|
-- exactly same logic, re-written to allow proper
|
30 |
|
|
-- usage of vivado constraints)
|
31 |
16 |
wfjm |
------------------------------------------------------------------------------
|
32 |
|
|
|
33 |
|
|
library ieee;
|
34 |
|
|
use ieee.std_logic_1164.all;
|
35 |
|
|
use ieee.numeric_std.all;
|
36 |
|
|
|
37 |
|
|
use work.slvtypes.all;
|
38 |
|
|
use work.genlib.all;
|
39 |
|
|
use work.memlib.all;
|
40 |
|
|
|
41 |
36 |
wfjm |
entity fifo_2c_dram2 is -- fifo, 2 clock, dram based (v2)
|
42 |
16 |
wfjm |
generic (
|
43 |
|
|
AWIDTH : positive := 5; -- address width (sets size)
|
44 |
|
|
DWIDTH : positive := 16); -- data width
|
45 |
|
|
port (
|
46 |
|
|
CLKW : in slbit; -- clock (write side)
|
47 |
|
|
CLKR : in slbit; -- clock (read side)
|
48 |
|
|
RESETW : in slbit; -- W|reset from write side
|
49 |
|
|
RESETR : in slbit; -- R|reset from read side
|
50 |
|
|
DI : in slv(DWIDTH-1 downto 0); -- W|input data
|
51 |
|
|
ENA : in slbit; -- W|write enable
|
52 |
|
|
BUSY : out slbit; -- W|write port hold
|
53 |
|
|
DO : out slv(DWIDTH-1 downto 0); -- R|output data
|
54 |
|
|
VAL : out slbit; -- R|read valid
|
55 |
|
|
HOLD : in slbit; -- R|read hold
|
56 |
|
|
SIZEW : out slv(AWIDTH-1 downto 0); -- W|number slots to write
|
57 |
|
|
SIZER : out slv(AWIDTH-1 downto 0) -- R|number slots to read
|
58 |
|
|
);
|
59 |
36 |
wfjm |
end fifo_2c_dram2;
|
60 |
16 |
wfjm |
|
61 |
|
|
|
62 |
36 |
wfjm |
architecture syn of fifo_2c_dram2 is
|
63 |
16 |
wfjm |
|
64 |
36 |
wfjm |
subtype a_range is integer range AWIDTH-1 downto 0; -- addr value regs
|
65 |
16 |
wfjm |
|
66 |
36 |
wfjm |
signal RW_RADDR_S0 : slv(a_range) := (others=>'0'); -- read addr: CLKR->CLKW
|
67 |
|
|
signal RW_RADDR_S1 : slv(a_range) := (others=>'0'); -- read addr: CLKW->CLKW
|
68 |
|
|
signal RW_SIZEW : slv(a_range) := (others=>'0'); -- slots to write
|
69 |
|
|
signal RW_BUSY : slbit := '0'; -- busy flag
|
70 |
|
|
signal RW_RSTW : slbit := '0'; -- resetw active
|
71 |
|
|
signal RW_RSTW_E_S0 : slbit := '0'; -- rstw-echo: CLKR->CLKW
|
72 |
|
|
signal RW_RSTW_E_S1 : slbit := '0'; -- rstw-echo: CLKW->CLKW
|
73 |
|
|
signal RW_RSTR_S0 : slbit := '0'; -- resetr: CLKR->CLKW
|
74 |
|
|
signal RW_RSTR_S1 : slbit := '0'; -- resetr: CLKW->CLKW
|
75 |
|
|
|
76 |
|
|
signal NW_SIZEW : slv(a_range) := (others=>'0'); -- slots to write
|
77 |
|
|
signal NW_BUSY : slbit := '0'; -- busy flag
|
78 |
|
|
signal NW_RSTW : slbit := '0'; -- resetw active
|
79 |
16 |
wfjm |
|
80 |
36 |
wfjm |
signal RR_WADDR_S0 : slv(a_range) := (others=>'0'); -- write addr: CLKW->CLKR
|
81 |
|
|
signal RR_WADDR_S1 : slv(a_range) := (others=>'0'); -- write addr: CLKR->CLKR
|
82 |
|
|
signal RR_SIZER : slv(a_range) := (others=>'0'); -- slots to read
|
83 |
|
|
signal RR_VAL: slbit := '0'; -- valid flag
|
84 |
|
|
signal RR_RSTR : slbit := '0'; -- resetr active
|
85 |
|
|
signal RR_RSTR_E_S0 : slbit := '0'; -- rstr-echo: CLKW->CLKR
|
86 |
|
|
signal RR_RSTR_E_S1 : slbit := '0'; -- rstr-echo: CLKR->CLKR
|
87 |
|
|
signal RR_RSTW_S0 : slbit := '0'; -- resetw: CLKW->CLKR
|
88 |
|
|
signal RR_RSTW_S1 : slbit := '0'; -- resetw: CLKR->CLKR
|
89 |
16 |
wfjm |
|
90 |
36 |
wfjm |
signal NR_SIZER : slv(a_range) := (others=>'0'); -- slots to read
|
91 |
|
|
signal NR_VAL: slbit := '0'; -- valid flag
|
92 |
|
|
signal NR_RSTR : slbit := '0'; -- resetr active
|
93 |
16 |
wfjm |
|
94 |
|
|
signal WADDR : slv(AWIDTH-1 downto 0) := (others=>'0');
|
95 |
|
|
signal RADDR : slv(AWIDTH-1 downto 0) := (others=>'0');
|
96 |
36 |
wfjm |
signal WADDR_BIN_W : slv(AWIDTH-1 downto 0) := (others=>'0');
|
97 |
|
|
signal RADDR_BIN_R : slv(AWIDTH-1 downto 0) := (others=>'0');
|
98 |
|
|
signal WADDR_BIN_R : slv(AWIDTH-1 downto 0) := (others=>'0');
|
99 |
|
|
signal RADDR_BIN_W : slv(AWIDTH-1 downto 0) := (others=>'0');
|
100 |
16 |
wfjm |
|
101 |
|
|
signal GCW_RST : slbit := '0';
|
102 |
36 |
wfjm |
signal GCW_CE : slbit := '0';
|
103 |
16 |
wfjm |
signal GCR_RST : slbit := '0';
|
104 |
36 |
wfjm |
signal GCR_CE : slbit := '0';
|
105 |
16 |
wfjm |
|
106 |
36 |
wfjm |
attribute ASYNC_REG: string;
|
107 |
|
|
|
108 |
|
|
attribute ASYNC_REG of RW_RADDR_S0 : signal is "true";
|
109 |
|
|
attribute ASYNC_REG of RW_RADDR_S1 : signal is "true";
|
110 |
|
|
attribute ASYNC_REG of RW_RSTW_E_S0 : signal is "true";
|
111 |
|
|
attribute ASYNC_REG of RW_RSTW_E_S1 : signal is "true";
|
112 |
|
|
attribute ASYNC_REG of RW_RSTR_S0 : signal is "true";
|
113 |
|
|
attribute ASYNC_REG of RW_RSTR_S1 : signal is "true";
|
114 |
|
|
|
115 |
|
|
attribute ASYNC_REG of RR_WADDR_S0 : signal is "true";
|
116 |
|
|
attribute ASYNC_REG of RR_WADDR_S1 : signal is "true";
|
117 |
|
|
attribute ASYNC_REG of RR_RSTR_E_S0 : signal is "true";
|
118 |
|
|
attribute ASYNC_REG of RR_RSTR_E_S1 : signal is "true";
|
119 |
|
|
attribute ASYNC_REG of RR_RSTW_S0 : signal is "true";
|
120 |
|
|
attribute ASYNC_REG of RR_RSTW_S1 : signal is "true";
|
121 |
|
|
|
122 |
16 |
wfjm |
begin
|
123 |
|
|
|
124 |
|
|
RAM : ram_1swar_1ar_gen -- dual ported memory
|
125 |
|
|
generic map (
|
126 |
|
|
AWIDTH => AWIDTH,
|
127 |
|
|
DWIDTH => DWIDTH)
|
128 |
|
|
port map (
|
129 |
|
|
CLK => CLKW,
|
130 |
|
|
WE => GCW_CE,
|
131 |
|
|
ADDRA => WADDR,
|
132 |
|
|
ADDRB => RADDR,
|
133 |
|
|
DI => DI,
|
134 |
|
|
DOA => open,
|
135 |
|
|
DOB => DO
|
136 |
|
|
);
|
137 |
|
|
|
138 |
|
|
GCW : gray_cnt_gen -- gray counter for write address
|
139 |
|
|
generic map (
|
140 |
|
|
DWIDTH => AWIDTH)
|
141 |
|
|
port map (
|
142 |
|
|
CLK => CLKW,
|
143 |
|
|
RESET => GCW_RST,
|
144 |
|
|
CE => GCW_CE,
|
145 |
|
|
DATA => WADDR
|
146 |
|
|
);
|
147 |
|
|
|
148 |
|
|
GCR : gray_cnt_gen -- gray counter for read address
|
149 |
|
|
generic map (
|
150 |
|
|
DWIDTH => AWIDTH)
|
151 |
|
|
port map (
|
152 |
|
|
CLK => CLKR,
|
153 |
|
|
RESET => GCR_RST,
|
154 |
|
|
CE => GCR_CE,
|
155 |
|
|
DATA => RADDR
|
156 |
|
|
);
|
157 |
|
|
|
158 |
|
|
G2B_WW : gray2bin_gen -- gray->bin for waddr on write side
|
159 |
|
|
generic map (DWIDTH => AWIDTH)
|
160 |
36 |
wfjm |
port map (DI => WADDR, DO => WADDR_BIN_W);
|
161 |
16 |
wfjm |
G2B_WR : gray2bin_gen -- gray->bin for waddr on read side
|
162 |
|
|
generic map (DWIDTH => AWIDTH)
|
163 |
36 |
wfjm |
port map (DI => RR_WADDR_S1, DO => WADDR_BIN_R);
|
164 |
|
|
G2B_RR : gray2bin_gen -- gray->bin for raddr on read side
|
165 |
|
|
generic map (DWIDTH => AWIDTH)
|
166 |
|
|
port map (DI => RADDR, DO => RADDR_BIN_R);
|
167 |
16 |
wfjm |
G2B_RW : gray2bin_gen -- gray->bin for raddr on write side
|
168 |
|
|
generic map (DWIDTH => AWIDTH)
|
169 |
36 |
wfjm |
port map (DI => RW_RADDR_S1, DO => RADDR_BIN_W);
|
170 |
|
|
|
171 |
|
|
--
|
172 |
|
|
-- write side --------------------------------------------------------------
|
173 |
|
|
--
|
174 |
16 |
wfjm |
proc_regw: process (CLKW)
|
175 |
|
|
begin
|
176 |
|
|
if rising_edge(CLKW) then
|
177 |
36 |
wfjm |
RW_RADDR_S0 <= RADDR; -- sync 0: CLKR->CLKW
|
178 |
|
|
RW_RADDR_S1 <= RW_RADDR_S0; -- sync 1: CLKW
|
179 |
|
|
RW_SIZEW <= NW_SIZEW;
|
180 |
|
|
RW_BUSY <= NW_BUSY;
|
181 |
|
|
RW_RSTW <= NW_RSTW;
|
182 |
|
|
RW_RSTW_E_S0 <= RR_RSTW_S1; -- sync 0: CLKR->CLKW
|
183 |
|
|
RW_RSTW_E_S1 <= RW_RSTW_E_S0; -- sync 1: CLKW
|
184 |
|
|
RW_RSTR_S0 <= RR_RSTR; -- sync 0: CLKR->CLKW
|
185 |
|
|
RW_RSTR_S1 <= RW_RSTR_S0; -- sync 1: CLKW
|
186 |
|
|
end if;
|
187 |
16 |
wfjm |
end process proc_regw;
|
188 |
|
|
|
189 |
36 |
wfjm |
proc_nextw: process (RW_BUSY, RW_SIZEW, RW_RSTW, RW_RSTW_E_S1, RW_RSTR_S1,
|
190 |
|
|
ENA, RESETW, RADDR_BIN_W, WADDR_BIN_W)
|
191 |
16 |
wfjm |
|
192 |
|
|
variable ibusy : slbit := '0';
|
193 |
36 |
wfjm |
variable irstw : slbit := '0';
|
194 |
16 |
wfjm |
variable igcw_ce : slbit := '0';
|
195 |
|
|
variable igcw_rst : slbit := '0';
|
196 |
36 |
wfjm |
variable isizew : slv(a_range) := (others=>'0');
|
197 |
16 |
wfjm |
begin
|
198 |
|
|
|
199 |
36 |
wfjm |
isizew := slv(unsigned(RADDR_BIN_W) + unsigned(not WADDR_BIN_W));
|
200 |
16 |
wfjm |
ibusy := '0';
|
201 |
|
|
igcw_ce := '0';
|
202 |
|
|
igcw_rst := '0';
|
203 |
|
|
|
204 |
|
|
if unsigned(isizew) = 0 then -- if no free slots
|
205 |
|
|
ibusy := '1'; -- next cycle busy=1
|
206 |
|
|
end if;
|
207 |
|
|
|
208 |
36 |
wfjm |
if ENA='1' and RW_BUSY='0' then -- if ena=1 and this cycle busy=0
|
209 |
16 |
wfjm |
igcw_ce := '1'; -- write this value
|
210 |
|
|
if unsigned(isizew) = 1 then -- if this last free slot
|
211 |
|
|
ibusy := '1'; -- next cycle busy=1
|
212 |
|
|
end if;
|
213 |
|
|
end if;
|
214 |
36 |
wfjm |
|
215 |
|
|
irstw := RW_RSTW;
|
216 |
16 |
wfjm |
if RESETW = '1' then -- reset(write side) request
|
217 |
36 |
wfjm |
irstw := '1'; -- set RSTW flag
|
218 |
|
|
elsif RW_RSTW_E_S1 = '1' then -- request gone and return seen
|
219 |
|
|
irstw := '0'; -- clear RSTW flag
|
220 |
16 |
wfjm |
end if;
|
221 |
|
|
|
222 |
36 |
wfjm |
if RW_RSTW='1' and RW_RSTW_E_S1='1' then -- RSTW seen on write and read side
|
223 |
16 |
wfjm |
igcw_rst := '1'; -- clear write address counter
|
224 |
|
|
end if;
|
225 |
36 |
wfjm |
if RW_RSTR_S1 = '1' then -- RSTR active
|
226 |
16 |
wfjm |
igcw_rst := '1'; -- clear write address counter
|
227 |
|
|
end if;
|
228 |
|
|
|
229 |
36 |
wfjm |
if RESETW='1' or RW_RSTW='1' or RW_RSTW_E_S1='1' or RW_RSTR_S1='1'
|
230 |
16 |
wfjm |
then -- RESETW or RESETR active
|
231 |
|
|
ibusy := '1'; -- signal write side busy
|
232 |
|
|
isizew := (others=>'1');
|
233 |
|
|
end if;
|
234 |
|
|
|
235 |
36 |
wfjm |
NW_BUSY <= ibusy;
|
236 |
|
|
NW_RSTW <= irstw;
|
237 |
|
|
NW_SIZEW <= isizew;
|
238 |
16 |
wfjm |
|
239 |
|
|
GCW_CE <= igcw_ce;
|
240 |
|
|
GCW_RST <= igcw_rst;
|
241 |
36 |
wfjm |
BUSY <= RW_BUSY;
|
242 |
|
|
SIZEW <= RW_SIZEW;
|
243 |
16 |
wfjm |
|
244 |
|
|
end process proc_nextw;
|
245 |
|
|
|
246 |
36 |
wfjm |
--
|
247 |
|
|
-- read side ---------------------------------------------------------------
|
248 |
|
|
--
|
249 |
16 |
wfjm |
proc_regr: process (CLKR)
|
250 |
|
|
begin
|
251 |
|
|
if rising_edge(CLKR) then
|
252 |
36 |
wfjm |
RR_WADDR_S0 <= WADDR; -- sync 0: CLKW->CLKR
|
253 |
|
|
RR_WADDR_S1 <= RR_WADDR_S0; -- sync 1: CLKW
|
254 |
|
|
RR_SIZER <= NR_SIZER;
|
255 |
|
|
RR_VAL <= NR_VAL;
|
256 |
|
|
RR_RSTR <= NR_RSTR;
|
257 |
|
|
RR_RSTR_E_S0 <= RW_RSTR_S1; -- sync 0: CLKW->CLKR
|
258 |
|
|
RR_RSTR_E_S1 <= RR_RSTR_E_S0; -- sync 1: CLKW
|
259 |
|
|
RR_RSTW_S0 <= RW_RSTW; -- sync 0: CLKW->CLKR
|
260 |
|
|
RR_RSTW_S1 <= RR_RSTW_S0; -- sync 1: CLKW
|
261 |
16 |
wfjm |
end if;
|
262 |
|
|
end process proc_regr;
|
263 |
|
|
|
264 |
36 |
wfjm |
proc_nextr: process (RR_VAL, RR_SIZER, RR_RSTR, RR_RSTR_E_S1, RR_RSTW_S1,
|
265 |
|
|
HOLD, RESETR, RADDR_BIN_R, WADDR_BIN_R)
|
266 |
16 |
wfjm |
|
267 |
|
|
variable ival : slbit := '0';
|
268 |
36 |
wfjm |
variable irstr : slbit := '0';
|
269 |
16 |
wfjm |
variable igcr_ce : slbit := '0';
|
270 |
|
|
variable igcr_rst : slbit := '0';
|
271 |
36 |
wfjm |
variable isizer : slv(a_range) := (others=>'0');
|
272 |
16 |
wfjm |
|
273 |
|
|
begin
|
274 |
|
|
|
275 |
36 |
wfjm |
isizer := slv(unsigned(WADDR_BIN_R) - unsigned(RADDR_BIN_R));
|
276 |
16 |
wfjm |
ival := '1';
|
277 |
|
|
igcr_ce := '0';
|
278 |
|
|
igcr_rst := '0';
|
279 |
|
|
|
280 |
|
|
if unsigned(isizer) = 0 then -- if nothing to read
|
281 |
|
|
ival := '0'; -- next cycle val=0
|
282 |
|
|
end if;
|
283 |
|
|
|
284 |
36 |
wfjm |
if RR_VAL='1' and HOLD='0' then -- this cycle val=1 and no hold
|
285 |
16 |
wfjm |
igcr_ce := '1'; -- retire this value
|
286 |
|
|
if unsigned(isizer) = 1 then -- if this is last one
|
287 |
|
|
ival := '0'; -- next cycle val=0
|
288 |
|
|
end if;
|
289 |
|
|
end if;
|
290 |
|
|
|
291 |
36 |
wfjm |
irstr := RR_RSTR;
|
292 |
16 |
wfjm |
if RESETR = '1' then -- reset(read side) request
|
293 |
36 |
wfjm |
irstr := '1'; -- set RSTR flag
|
294 |
|
|
elsif RR_RSTR_E_S1 = '1' then -- request gone and return seen
|
295 |
|
|
irstr := '0'; -- clear RSTR flag
|
296 |
16 |
wfjm |
end if;
|
297 |
|
|
|
298 |
36 |
wfjm |
if RR_RSTR='1' and RR_RSTR_E_S1='1' then -- RSTR seen on read and write side
|
299 |
16 |
wfjm |
igcr_rst := '1'; -- clear read address counter
|
300 |
|
|
end if;
|
301 |
36 |
wfjm |
if RR_RSTW_S1 = '1' then -- RSTW active
|
302 |
16 |
wfjm |
igcr_rst := '1'; -- clear read address counter
|
303 |
|
|
end if;
|
304 |
|
|
|
305 |
36 |
wfjm |
if RESETR='1' or RR_RSTR='1' or RR_RSTR_E_S1='1' or RR_RSTW_S1='1'
|
306 |
16 |
wfjm |
then -- RESETR or RESETW active
|
307 |
|
|
ival := '0'; -- signal read side empty
|
308 |
|
|
isizer := (others=>'0');
|
309 |
|
|
end if;
|
310 |
|
|
|
311 |
36 |
wfjm |
NR_VAL <= ival;
|
312 |
|
|
NR_RSTR <= irstr;
|
313 |
|
|
NR_SIZER <= isizer;
|
314 |
16 |
wfjm |
|
315 |
|
|
GCR_CE <= igcr_ce;
|
316 |
|
|
GCR_RST <= igcr_rst;
|
317 |
36 |
wfjm |
VAL <= RR_VAL;
|
318 |
|
|
SIZER <= RR_SIZER;
|
319 |
16 |
wfjm |
|
320 |
|
|
end process proc_nextr;
|
321 |
|
|
|
322 |
|
|
end syn;
|