Skip to content

Instantly share code, notes, and snippets.

@C47D
Last active December 6, 2023 07:52
Show Gist options
  • Save C47D/e299230c65b82a87d7fc83579d78b168 to your computer and use it in GitHub Desktop.
Save C47D/e299230c65b82a87d7fc83579d78b168 to your computer and use it in GitHub Desktop.
Generic FIFO implemented in verilog.
/**
* Generic FIFO.
* Author: Carlos Diaz (2017)
*
* DISCLAIMER (2021): This implementation was done when I had a few days of
* experience using verilog, I was at school and not really sure what
* I was doing. I choose to make it public in case of me needing it
* in the future, but that was not the case, it's been a long time
* since I tried to learn any HDL.
*
* Parameters:
* WIDTH: Width of the data on the FIFO, default to 4.
* DEPTH: Depth of the FIFO, default to 4.
*
* Input signals:
* data_in: Data input, width controlled with WIDTH parameter.
* clk: Clock input.
* write: Enable writing into the FIFO.
* read: Enable reading from the FIFO.
*
* Output signals:
* data_out: Data output, witdh controlled with WIDTH parameter.
* fifo_full: 1bit signal, indicate when the FIFO is full.
* fifo_empty: 1bit signal, indicate when the FIFO is empty.
* fifo_not_empty: 1bit signal, indicate when the FIFO is not empty.
* fifo_not_full: 1bit signal, indicate when the FIFO is not full.
*
**/
`timescale 1ns / 1ps
`default_nettype none
module fifo #(
parameter WIDTH = 4,
parameter DEPTH = 4
)(
input [WIDTH-1:0] data_in,
input wire clk,
input wire write,
input wire read,
output reg [WIDTH-1:0] data_out,
output wire fifo_full,
output wire fifo_empty,
output wire fifo_not_empty,
output wire fifo_not_full
);
// memory will contain the FIFO data.
reg [WIDTH-1:0] memory [0:DEPTH-1];
// $clog2(DEPTH+1)-2 to count from 0 to DEPTH
reg [$clog2(DEPTH)-1:0] write_ptr;
reg [$clog2(DEPTH)-1:0] read_ptr;
// Initialization
initial begin
// Init both write_cnt and read_cnt to 0
write_ptr = 0;
read_ptr = 0;
// Display error if WIDTH is 0 or less.
if ( WIDTH <= 0 ) begin
$error("%m ** Illegal condition **, you used %d WIDTH", WIDTH);
end
// Display error if DEPTH is 0 or less.
if ( DEPTH <= 0) begin
$error("%m ** Illegal condition **, you used %d DEPTH", DEPTH);
end
end // end initial
assign fifo_empty = ( write_ptr == read_ptr ) ? 1'b1 : 1'b0;
assign fifo_full = ( write_ptr == (DEPTH-1) ) ? 1'b1 : 1'b0;
assign fifo_not_empty = ~fifo_empty;
assign fifo_not_full = ~fifo_full;
always @ (posedge clk) begin
if ( write ) begin
memory[write_ptr] <= data_in;
end
if ( read ) begin
data_out <= memory[read_ptr];
end
end
always @ ( posedge clk ) begin
if ( write ) begin
write_ptr <= write_ptr + 1;
end
if ( read && fifo_not_empty ) begin
read_ptr <= read_ptr + 1;
end
end
endmodule
@C47D
Copy link
Author

C47D commented Nov 3, 2021

It's nice to know it's been useful for others, but I did it at school when I didn't knew much, so it's been good to receive feedback to improve it.

@clint-lemire
Copy link

clint-lemire commented Jun 29, 2022

Since this is one of the top google results for verilog fifo I'll post my hdl.

module RXFIFO #(
  parameter PACKET_WIDTH = 248,
  parameter FIFO_DEPTH   = 256, 
  parameter PTR_MSB      = 8,
  parameter ADDR_MSB     = 7
  )
  (
  input                           zedClk100MHz_i,
  input                           reset_ni,
  input                           read_i,
  input                           write_i,
  input        [PACKET_WIDTH-1:0] packet_i,
  output logic [PACKET_WIDTH-1:0] packet_o,
  output logic                    fifoFull_o,
  output logic                    fifoEmpty_o
  );
  
  logic [PACKET_WIDTH-1:0] memory [0:FIFO_DEPTH-1];
  logic [       PTR_MSB:0] readPtr, writePtr;
  wire  [      ADDR_MSB:0] writeAddr = writePtr[ADDR_MSB:0];
  wire  [      ADDR_MSB:0] readAddr = readPtr[ADDR_MSB:0]; 
  
  always_ff@(posedge zedClk100MHz_i or negedge reset_ni)begin
    if(~reset_ni)begin
      readPtr     <= '0;
      writePtr    <= '0;
    end
    else begin
      if(write_i && ~fifoFull_o)begin
        memory[writeAddr] <= packet_i;
        writePtr         <= writePtr + 1;
      end
      if(read_i && ~fifoEmpty_o)begin
        packet_o <= memory[readAddr];
        readPtr <= readPtr + 1;
      end
    end
  end
  
    assign fifoEmpty_o = (writePtr == readPtr) ? 1'b1: 1'b0;
    assign fifoFull_o  = ((writePtr[ADDR_MSB:0] == readPtr[ADDR_MSB:0])&(writePtr[PTR_MSB] != readPtr[PTR_MSB])) ? 1'b1 : 1'b0;

endmodule

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment