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

Subversion Repositories w11

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

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

Line No. Rev Author Line
1 16 wfjm
-- $Id: fifo_2c_dram.vhd 424 2011-11-13 16:38:23Z mueller $
2
--
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
-- Tool versions:  xst 8.2, 9.1, 9.2, 13.1; ghdl 0.18-0.29
26
-- 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
  G2B_RW : gray2bin_gen                 -- gray->bin for raddr on write side
179
    generic map (DWIDTH => AWIDTH)
180
    port map (DI => RADDR, DO => RADDR_BIN);
181
  G2B_RR : gray2bin_gen                 -- gray->bin for raddr on read  side
182
    generic map (DWIDTH => AWIDTH)
183
    port map (DI => R_REGW.raddr_s, DO => RADDR_S_BIN);
184
 
185
  proc_regw: process (CLKW)
186
  begin
187
    if rising_edge(CLKW) then
188
      R_REGW <= N_REGW;
189
    end if;
190
  end process proc_regw;
191
 
192
  proc_nextw: process (R_REGW, RESETW, ENA, R_REGR,
193
                       RADDR, RADDR_S_BIN, WADDR_BIN)
194
 
195
    variable r : regw_type := regw_init;
196
    variable n : regw_type := regw_init;
197
    variable ibusy : slbit := '0';
198
    variable igcw_ce  : slbit := '0';
199
    variable igcw_rst : slbit := '0';
200
    variable isizew : slv(AWIDTH-1 downto 0) := (others=>'0');
201
  begin
202
 
203
    r := R_REGW;
204
    n := R_REGW;
205
 
206
    isizew := slv(unsigned(RADDR_S_BIN) + unsigned(not WADDR_BIN));
207
    ibusy  := '0';
208
    igcw_ce  := '0';
209
    igcw_rst := '0';
210
 
211
    if unsigned(isizew) = 0 then        -- if no free slots
212
      ibusy := '1';                       -- next cycle busy=1
213
    end if;
214
 
215
    if ENA='1' and r.busy='0' then      -- if ena=1 and this cycle busy=0
216
      igcw_ce := '1';                     -- write this value
217
      if unsigned(isizew) = 1 then        -- if this last free slot
218
        ibusy := '1';                       -- next cycle busy=1
219
      end if;
220
    end if;
221
 
222
    if RESETW = '1' then                -- reset(write side) request
223
      n.rstw := '1';                      -- set RSTW flag
224
    elsif r.rstw_ss = '1' then          -- request gone and return seen
225
      n.rstw := '0';                      -- clear RSTW flag
226
    end if;
227
 
228
    if r.rstw='1' and r.rstw_ss='1' then -- RSTW seen on write and read side
229
      igcw_rst := '1';                     -- clear write address counter
230
    end if;
231
    if r.rstr_s = '1' then              -- RSTR active
232
      igcw_rst := '1';                    -- clear write address counter
233
    end if;
234
 
235
    if RESETW='1' or r.rstw='1' or r.rstw_ss='1' or r.rstr_s='1'
236
    then             -- RESETW or RESETR active
237
      ibusy  := '1';                      -- signal write side busy
238
      isizew := (others=>'1');
239
    end if;
240
 
241
    n.busy  := ibusy;
242
    n.sizew := isizew;
243
 
244
    n.raddr_c := RADDR;                 -- data captuture from CLKR
245
    n.raddr_s := r.raddr_c;
246
    n.rstw_sc := R_REGR.rstw_s;
247
    n.rstw_ss := r.rstw_sc;
248
    n.rstr_c  := R_REGR.rstr;
249
    n.rstr_s  := r.rstr_c;
250
 
251
    N_REGW  <= n;
252
 
253
    GCW_CE  <= igcw_ce;
254
    GCW_RST <= igcw_rst;
255
    BUSY    <= r.busy;
256
    SIZEW   <= r.sizew;
257
 
258
  end process proc_nextw;
259
 
260
  proc_regr: process (CLKR)
261
  begin
262
    if rising_edge(CLKR) then
263
      R_REGR <= N_REGR;
264
    end if;
265
  end process proc_regr;
266
 
267
  proc_nextr: process (R_REGR, RESETR, HOLD, R_REGW,
268
                       WADDR, WADDR_S_BIN, RADDR_BIN)
269
 
270
    variable r : regr_type := regr_init;
271
    variable n : regr_type := regr_init;
272
    variable ival : slbit := '0';
273
    variable igcr_ce  : slbit := '0';
274
    variable igcr_rst : slbit := '0';
275
    variable isizer : slv(AWIDTH-1 downto 0) := (others=>'0');
276
 
277
  begin
278
 
279
    r := R_REGR;
280
    n := R_REGR;
281
 
282
    isizer := slv(unsigned(WADDR_S_BIN) - unsigned(RADDR_BIN));
283
    ival  := '1';
284
    igcr_ce  := '0';
285
    igcr_rst := '0';
286
 
287
    if unsigned(isizer) = 0 then        -- if nothing to read
288
      ival := '0';                        -- next cycle val=0
289
    end if;
290
 
291
    if r.val='1' and HOLD='0' then      -- this cycle val=1 and no hold
292
      igcr_ce := '1';                     -- retire this value
293
      if unsigned(isizer) = 1  then       -- if this is last one
294
        ival := '0';                        -- next cycle val=0
295
      end if;
296
    end if;
297
 
298
    if RESETR = '1' then                -- reset(read side) request
299
      n.rstr := '1';                      -- set RSTR flag
300
    elsif r.rstr_ss = '1' then          -- request gone and return seen
301
      n.rstr := '0';                      -- clear RSTR flag
302
    end if;
303
 
304
    if r.rstr='1' and r.rstr_ss='1' then -- RSTR seen on read and write side
305
      igcr_rst := '1';                     -- clear read address counter
306
    end if;
307
    if r.rstw_s = '1' then              -- RSTW active
308
      igcr_rst := '1';                    -- clear read address counter
309
    end if;
310
 
311
    if RESETR='1' or r.rstr='1' or r.rstr_ss='1' or r.rstw_s='1'
312
    then                                -- RESETR or RESETW active 
313
      ival   := '0';                       -- signal read side empty
314
      isizer := (others=>'0');
315
    end if;
316
 
317
    n.val   := ival;
318
    n.sizer := isizer;
319
 
320
    n.waddr_c := WADDR;                 -- data captuture from CLKW
321
    n.waddr_s := r.waddr_c;
322
    n.rstr_sc := R_REGW.rstr_s;
323
    n.rstr_ss := r.rstr_sc;
324
    n.rstw_c  := R_REGW.rstw;
325
    n.rstw_s  := r.rstw_c;
326
 
327
    N_REGR <= n;
328
 
329
    GCR_CE  <= igcr_ce;
330
    GCR_RST <= igcr_rst;
331
    VAL     <= r.val;
332
    SIZER   <= r.sizer;
333
 
334
  end process proc_nextr;
335
 
336
end syn;

powered by: WebSVN 2.1.0

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