.. _shortfifo_source: shortfifo Source File ===================== .. code-block:: verilog :linenos: // Short (2-32 long) FIFO meant to be efficiently implemented with // Xilinx SRL16E or similar // Except for the unified clock and the count output port, // this is pin-compatible with ordinary fifo.v // max. elements: 2**aw `timescale 1ns / 1ns module shortfifo #( parameter dw=8, parameter aw=3 ) ( // require single clock domain input clk, // input port input [dw-1:0] din, input we, // output port output [dw-1:0] dout, input re, // status output full, output empty, output last, output [aw:0] count // -1: empty, 0: single element, 2**aw - 1: full ); localparam len = 1 << aw; // Need 1 extra bit to distinguish between full and empty reg [aw:0] raddr = ~0; wire re_ = re && !empty; wire we_ = we && (!full || re); genvar ix; generate for (ix=0; ix 0)) assert($stable(f_fill)); // Show 2 values entering and exiting the FIFO: // cover(f_past_valid && $past(f_state) == 3 && f_state == 0); end // Fill up the FIFO and empty it again reg f_was_full = 0; reg f_both = 0; // show what happens when both are high always @(posedge clk) begin // assume(din == $past(din) + 8'h1); if (full) f_was_full <= 1; if (we && re && !empty) f_both <= 1; cover(f_was_full && empty && f_both); end always @(*) begin assert(f_fill >= 0); assert(raddr == f_fill - (aw'd1)); assert(empty == (f_fill == 0)); assert(last == (f_fill == 1)); assert(full == (f_fill == len)); // Can't have more items than the memory holds assert(f_fill <= len); // Can't be full and empty at the same time assert(!(full && empty)); end `endif endmodule // should infer as a single SRL16E, SRL32E, ... // See "Dynamic Shift Registers Verilog Coding Example" in UG687 /* verilator lint_save */ /* verilator lint_off DECLFILENAME */ module abstract_dsr #( parameter aw=4 ) ( input clk, input ce, input din, input [aw-1:0] addr, output dout ); localparam len = 1 << aw; reg [len-1:0] sr=0; always @(posedge clk) if (ce) sr <= {sr[len-2:0],din}; assign dout = sr[addr]; endmodule /* verilator lint_restore */