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