|
- `timescale 1ns / 1ps
-
-
- //////////////////////////////////////////////////////////////////////////////////
- // Company: BITSILICA PVT LTD
- // Design Name:
- // Module Name: FIFO
- // Project Name:
- //////////////////////////////////////////////////////////////////////////////////
-
- /*
-
- Description
- ===========
-
- I/Os
- ----
- rst low active, either sync. or async. master reset (see below how to select)
- clr synchronous clear (just like reset but always synchronous), high active
- re read enable, synchronous, high active
- we read enable, synchronous, high active
- din Data Input
- dout Data Output
-
- full Indicates the FIFO is full (combinatorial output)
- full_r same as above, but registered output (see note below)
- empty Indicates the FIFO is empty
- empty_r same as above, but registered output (see note below)
-
- full_n Indicates if the FIFO has space for N entries (combinatorial output)
- full_n_r same as above, but registered output (see note below)
- empty_n Indicates the FIFO has at least N entries (combinatorial output)
- empty_n_r same as above, but registered output (see note below)
-
- level indicates the FIFO level:
- 2'b00 0-25% full
- 2'b01 25-50% full
- 2'b10 50-75% full
- 2'b11 %75-100% full
-
- combinatorial vs. registered status outputs
- -------------------------------------------
- Both the combinatorial and registered status outputs have exactly the same
- synchronous timing. Meaning they are being asserted immediately at the clock
- edge after the last read or write. The combinatorial outputs however, pass
- through several levels of logic before they are output. The registered status
- outputs are direct outputs of a flip-flop. The reason both are provided, is
- that the registered outputs require quite a bit of additional logic inside
- the FIFO. If you can meet timing of your device with the combinatorial
- outputs, use them ! The FIFO will be smaller. If the status signals are
- in the critical pass, use the registered outputs, they have a much smaller
- output delay (actually only Tcq).
-
- Parameters
- ----------
- The FIFO takes 3 parameters:
- dw Data bus width
- aw Address bus width (Determines the FIFO size by evaluating 2^aw)
- n N is a second status threshold constant for full_n and empty_n
-
- */
-
- // Selecting Sync. or Async Reset
- // ------------------------------
- // Uncomment one of the two lines below. The first line for
- // synchronous reset, the second for asynchronous reset
-
- `define SC_FIFO_ASYNC_RESET //Uncomment for Syncr. reset
- //`define SC_FIFO_ASYNC_RESET or negedge rst // Uncomment for Async. reset
-
-
- module fifo#(parameter dw=32,aw=5,n=32)(clk, rst, din, we, dout, re,
- full, empty, full_r, empty_r,
- full_n, empty_n, full_n_r, empty_n_r,
- level,count);
-
-
- parameter max_size = 1<<aw;
-
- input clk, rst;
- input [dw-1:0] din;
- input we;
- output [dw-1:0] dout;
- input re;
- output full, full_r;
- output empty, empty_r;
- output full_n, full_n_r;
- output empty_n, empty_n_r;
- output [1:0] level;
- output [aw:0] count;
-
-
- ////////////////////////////////////////////////////////////////////
- //
- // Local Wires
- //
- wire wen; // Write Enable
- wire ren; // Read Enable
- reg [aw-1:0] wp;
- wire [aw-1:0] wp_pl1;
- wire [aw-1:0] wp_pl2;
- reg [aw-1:0] rp;
- wire [aw-1:0] rp_pl1;
- reg full_r;
- reg empty_r;
- reg gb;
- reg gb2;
- reg [aw:0] cnt;
- wire full_n, empty_n;
- reg full_n_r, empty_n_r;
-
-
-
- // Write Only when FIFO isn't full & write enable is there
- assign wen = (!full && we) ? 1'b1 : 1'b0;
- assign ren = (!empty && re) ? 1'b1 : 1'b0;
- assign count = cnt;
-
- ////////////////////////////////////////////////////////////////////
- // Memory Block
- ////////////////////////////////////////////////////////////////////
- simple_dual_port_ram #(.WIDTH(dw),.DEPTH(n),.AW(aw))u0(.clk(clk),.wea(wen),.enb(ren),.addra(wp),.addrb(rp),.dia(din),.dob(dout));
-
- ////////////////////////////////////////////////////////////////////
- // Misc Logic
-
- always @(posedge clk `SC_FIFO_ASYNC_RESET)
- if(!rst) wp <= #1 {aw{1'b0}};
- else
- if(we) wp <= #1 wp_pl1;
-
- assign wp_pl1 = wp + { {aw-1{1'b0}}, 1'b1};
- assign wp_pl2 = wp + { {aw-2{1'b0}}, 2'b10};
-
- always @(posedge clk `SC_FIFO_ASYNC_RESET)
- if(!rst) rp <= #1 {aw{1'b0}};
- else
- if(re) rp <= #1 rp_pl1;
-
- assign rp_pl1 = rp + { {aw-1{1'b0}}, 1'b1};
-
- ////////////////////////////////////////////////////////////////////
- // Combinatorial Full & Empty Flags
- //
-
- assign empty = ((wp == rp) & !gb);
- assign full = ((wp == rp) & gb);
-
- // Guard Bit ...
- always @(posedge clk `SC_FIFO_ASYNC_RESET)
- if(!rst) gb <= #1 1'b0;
- else
- if((wp_pl1 == rp) & we) gb <= #1 1'b1;
- else
- if(re) gb <= #1 1'b0;
-
- ////////////////////////////////////////////////////////////////////
- // Registered Full & Empty Flags
- //
-
- // Guard Bit ...
- always @(posedge clk `SC_FIFO_ASYNC_RESET)
- if(!rst) gb2 <= #1 1'b0;
- else
- if((wp_pl2 == rp) & we) gb2 <= #1 1'b1;
- else
- if((wp != rp) & re) gb2 <= #1 1'b0;
-
- always @(posedge clk `SC_FIFO_ASYNC_RESET)
- if(!rst) full_r <= #1 1'b0;
- else
- if(we & ((wp_pl1 == rp) & gb2) & !re) full_r <= #1 1'b1;
- else
- if(re & ((wp_pl1 != rp) | !gb2) & !we) full_r <= #1 1'b0;
-
- always @(posedge clk `SC_FIFO_ASYNC_RESET)
- if(!rst) empty_r <= #1 1'b1;
- else
- if(we & ((wp != rp_pl1) | gb2) & !re) empty_r <= #1 1'b0;
- else
- if(re & ((wp == rp_pl1) & !gb2) & !we) empty_r <= #1 1'b1;
-
- ////////////////////////////////////////////////////////////////////
- // Combinatorial Full_n & Empty_n Flags
-
- assign empty_n = cnt < n;
- assign full_n = !(cnt < (max_size-n+1));
- assign level = {2{cnt[aw]}} | cnt[aw-1:aw-2];
-
- // N entries status
- always @(posedge clk `SC_FIFO_ASYNC_RESET)
- if(!rst) cnt <= #1 {aw+1{1'b0}};
- else
- if( re & !we) cnt <= #1 cnt + { {aw{1'b1}}, 1'b1};
- else
- if(!re & we) cnt <= #1 cnt + { {aw{1'b0}}, 1'b1};
-
- ////////////////////////////////////////////////////////////////////
- // Registered Full_n & Empty_n Flags
-
- always @(posedge clk `SC_FIFO_ASYNC_RESET)
- if(!rst) empty_n_r <= #1 1'b1;
- else
- if(we & (cnt >= (n-1) ) & !re) empty_n_r <= #1 1'b0;
- else
- if(re & (cnt <= n ) & !we) empty_n_r <= #1 1'b1;
-
- always @(posedge clk `SC_FIFO_ASYNC_RESET)
- if(!rst) full_n_r <= #1 1'b0;
- else
- if(we & (cnt >= (max_size-n) ) & !re) full_n_r <= #1 1'b1;
- else
- if(re & (cnt <= (max_size-n+1)) & !we) full_n_r <= #1 1'b0;
-
- ////////////////////////////////////////////////////////////////////
- // Sanity Check
- always @(posedge clk)
- if(we & full)
- $display("%m WARNING: Writing while fifo is FULL (%t)",$time);
-
- always @(posedge clk)
- if(re & empty)
- $display("%m WARNING: Reading while fifo is EMPTY (%t)",$time);
-
- endmodule
|