1 /////////////////////////////////////////////////////////////////////
 
   3 ////  Universal FIFO Single Clock                                ////
 
   6 ////  Author: Rudolf Usselmann                                   ////
 
   7 ////          rudi@asics.ws                                      ////
 
  10 ////  D/L from: http://www.opencores.org/cores/generic_fifos/    ////
 
  12 /////////////////////////////////////////////////////////////////////
 
  14 //// Copyright (C) 2000-2002 Rudolf Usselmann                    ////
 
  15 ////                         www.asics.ws                        ////
 
  16 ////                         rudi@asics.ws                       ////
 
  18 //// This source file may be used and distributed without        ////
 
  19 //// restriction provided that this copyright statement is not   ////
 
  20 //// removed from the file and that any derivative work contains ////
 
  21 //// the original copyright notice and the associated disclaimer.////
 
  23 ////     THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY     ////
 
  24 //// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED   ////
 
  25 //// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS   ////
 
  26 //// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR      ////
 
  27 //// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,         ////
 
  28 //// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES    ////
 
  29 //// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE   ////
 
  30 //// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR        ////
 
  31 //// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF  ////
 
  32 //// LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT  ////
 
  33 //// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT  ////
 
  34 //// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE         ////
 
  35 //// POSSIBILITY OF SUCH DAMAGE.                                 ////
 
  37 /////////////////////////////////////////////////////////////////////
 
  41 //  $Id: generic_fifo_sc_a.v,v 1.1 2007-02-11 21:58:30 sithglan Exp $
 
  43 //  $Date: 2007-02-11 21:58:30 $
 
  45 //  $Author: sithglan $
 
  50 //               $Log: generic_fifo_sc_a.v,v $
 
  51 //               Revision 1.1  2007-02-11 21:58:30  sithglan
 
  54 //               Revision 1.1.1.1  2002/09/25 05:42:06  rudi
 
  68 `include "timescale.v"
 
  77 rst     low active, either sync. or async. master reset (see below how to select)
 
  78 clr     synchronous clear (just like reset but always synchronous), high active
 
  79 re      read enable, synchronous, high active
 
  80 we      read enable, synchronous, high active
 
  84 full    Indicates the FIFO is full (combinatorial output)
 
  85 full_r  same as above, but registered output (see note below)
 
  86 empty   Indicates the FIFO is empty
 
  87 empty_r same as above, but registered output (see note below)
 
  89 full_n          Indicates if the FIFO has space for N entries (combinatorial output)
 
  90 full_n_r        same as above, but registered output (see note below)
 
  91 empty_n         Indicates the FIFO has at least N entries (combinatorial output)
 
  92 empty_n_r       same as above, but registered output (see note below)
 
  94 level           indicates the FIFO level:
 
 100 combinatorial vs. registered status outputs
 
 101 -------------------------------------------
 
 102 Both the combinatorial and registered status outputs have exactly the same
 
 103 synchronous timing. Meaning they are being asserted immediately at the clock
 
 104 edge after the last read or write. The combinatorial outputs however, pass
 
 105 through several levels of logic before they are output. The registered status
 
 106 outputs are direct outputs of a flip-flop. The reason both are provided, is
 
 107 that the registered outputs require quite a bit of additional logic inside
 
 108 the FIFO. If you can meet timing of your device with the combinatorial
 
 109 outputs, use them ! The FIFO will be smaller. If the status signals are
 
 110 in the critical pass, use the registered outputs, they have a much smaller
 
 111 output delay (actually only Tcq).
 
 115 The FIFO takes 3 parameters:
 
 117 aw      Address bus width (Determines the FIFO size by evaluating 2^aw)
 
 118 n       N is a second status threshold constant for full_n and empty_n
 
 119         If you have no need for the second status threshold, do not
 
 120         connect the outputs and the logic should be removed by your
 
 125 In a Spartan 2e a 8 bit wide, 8 entries deep FIFO, takes 85 LUTs and runs
 
 126 at about 116 MHz (IO insertion disabled). The registered status outputs
 
 127 are valid after 2.1NS, the combinatorial once take out to 6.5 NS to be
 
 133 This design assumes you will do appropriate status checking externally.
 
 135 IMPORTANT ! writing while the FIFO is full or reading while the FIFO is
 
 136 empty will place the FIFO in an undefined state.
 
 141 // Selecting Sync. or Async Reset
 
 142 // ------------------------------
 
 143 // Uncomment one of the two lines below. The first line for
 
 144 // synchronous reset, the second for asynchronous reset
 
 146 `define SC_FIFO_ASYNC_RESET                             // Uncomment for Syncr. reset
 
 147 //`define SC_FIFO_ASYNC_RESET   or negedge rst          // Uncomment for Async. reset
 
 150 module generic_fifo_sc_a(clk, rst, clr, din, we, dout, re,
 
 151                         full, empty, full_r, empty_r,
 
 152                         full_n, empty_n, full_n_r, empty_n_r,
 
 158 parameter max_size = 1<<aw;
 
 163 output  [dw-1:0]        dout;
 
 166 output                  empty, empty_r;
 
 167 output                  full_n, full_n_r;
 
 168 output                  empty_n, empty_n_r;
 
 171 ////////////////////////////////////////////////////////////////////
 
 177 wire    [aw-1:0]        wp_pl1;
 
 178 wire    [aw-1:0]        wp_pl2;
 
 180 wire    [aw-1:0]        rp_pl1;
 
 186 wire                    full_n, empty_n;
 
 187 reg                     full_n_r, empty_n_r;
 
 189 ////////////////////////////////////////////////////////////////////
 
 194 generic_dpram  #(aw,dw) u0(
 
 209 ////////////////////////////////////////////////////////////////////
 
 214 always @(posedge clk `SC_FIFO_ASYNC_RESET)
 
 215         if(!rst)        wp <= #1 {aw{1'b0}};
 
 217         if(clr)         wp <= #1 {aw{1'b0}};
 
 219         if(we)          wp <= #1 wp_pl1;
 
 221 assign wp_pl1 = wp + { {aw-1{1'b0}}, 1'b1};
 
 222 assign wp_pl2 = wp + { {aw-2{1'b0}}, 2'b10};
 
 224 always @(posedge clk `SC_FIFO_ASYNC_RESET)
 
 225         if(!rst)        rp <= #1 {aw{1'b0}};
 
 227         if(clr)         rp <= #1 {aw{1'b0}};
 
 229         if(re)          rp <= #1 rp_pl1;
 
 231 assign rp_pl1 = rp + { {aw-1{1'b0}}, 1'b1};
 
 233 ////////////////////////////////////////////////////////////////////
 
 235 // Combinatorial Full & Empty Flags
 
 238 assign empty = ((wp == rp) & !gb);
 
 239 assign full  = ((wp == rp) &  gb);
 
 242 always @(posedge clk `SC_FIFO_ASYNC_RESET)
 
 243         if(!rst)                        gb <= #1 1'b0;
 
 245         if(clr)                         gb <= #1 1'b0;
 
 247         if((wp_pl1 == rp) & we)         gb <= #1 1'b1;
 
 249         if(re)                          gb <= #1 1'b0;
 
 251 ////////////////////////////////////////////////////////////////////
 
 253 // Registered Full & Empty Flags
 
 257 always @(posedge clk `SC_FIFO_ASYNC_RESET)
 
 258         if(!rst)                        gb2 <= #1 1'b0;
 
 260         if(clr)                         gb2 <= #1 1'b0;
 
 262         if((wp_pl2 == rp) & we)         gb2 <= #1 1'b1;
 
 264         if((wp != rp) & re)             gb2 <= #1 1'b0;
 
 266 always @(posedge clk `SC_FIFO_ASYNC_RESET)
 
 267         if(!rst)                                full_r <= #1 1'b0;
 
 269         if(clr)                                 full_r <= #1 1'b0;
 
 271         if(we & ((wp_pl1 == rp) & gb2) & !re)   full_r <= #1 1'b1;
 
 273         if(re & ((wp_pl1 != rp) | !gb2) & !we)  full_r <= #1 1'b0;
 
 275 always @(posedge clk `SC_FIFO_ASYNC_RESET)
 
 276         if(!rst)                                empty_r <= #1 1'b1;
 
 278         if(clr)                                 empty_r <= #1 1'b1;
 
 280         if(we & ((wp != rp_pl1) | gb2) & !re)   empty_r <= #1 1'b0;
 
 282         if(re & ((wp == rp_pl1) & !gb2) & !we)  empty_r <= #1 1'b1;
 
 284 ////////////////////////////////////////////////////////////////////
 
 286 // Combinatorial Full_n & Empty_n Flags
 
 289 assign empty_n = cnt < n;
 
 290 assign full_n  = !(cnt < (max_size-n+1));
 
 291 assign level = {2{cnt[aw]}} | cnt[aw-1:aw-2];
 
 294 always @(posedge clk `SC_FIFO_ASYNC_RESET)
 
 295         if(!rst)        cnt <= #1 {aw+1{1'b0}};
 
 297         if(clr)         cnt <= #1 {aw+1{1'b0}};
 
 299         if( re & !we)   cnt <= #1 cnt + { {aw{1'b1}}, 1'b1};
 
 301         if(!re &  we)   cnt <= #1 cnt + { {aw{1'b0}}, 1'b1};
 
 303 ////////////////////////////////////////////////////////////////////
 
 305 // Registered Full_n & Empty_n Flags
 
 308 always @(posedge clk `SC_FIFO_ASYNC_RESET)
 
 309         if(!rst)                                empty_n_r <= #1 1'b1;
 
 311         if(clr)                                 empty_n_r <= #1 1'b1;
 
 313         if(we & (cnt >= (n-1) ) & !re)          empty_n_r <= #1 1'b0;
 
 315         if(re & (cnt <= n ) & !we)              empty_n_r <= #1 1'b1;
 
 317 always @(posedge clk `SC_FIFO_ASYNC_RESET)
 
 318         if(!rst)                                full_n_r <= #1 1'b0;
 
 320         if(clr)                                 full_n_r <= #1 1'b0;
 
 322         if(we & (cnt >= (max_size-n) ) & !re)   full_n_r <= #1 1'b1;
 
 324         if(re & (cnt <= (max_size-n+1)) & !we)  full_n_r <= #1 1'b0;
 
 326 ////////////////////////////////////////////////////////////////////
 
 331 // synopsys translate_off
 
 332 always @(posedge clk)
 
 334                 $display("%m WARNING: Writing while fifo is FULL (%t)",$time);
 
 336 always @(posedge clk)
 
 338                 $display("%m WARNING: Reading while fifo is EMPTY (%t)",$time);
 
 339 // synopsys translate_on