OpenCores
URL https://opencores.org/ocsvn/w11/w11/trunk

Subversion Repositories w11

[/] [w11/] [tags/] [w11a_V0.74/] [rtl/] [vlib/] [memlib/] [fifo_2c_dram.vhd] - Blame information for rev 40

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
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;

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.