Verilog FIFO

Simple FIFO with some absolutely basic test bench. You may use iverilog and
gtkwave to simulate it. All files including makefile are on the bottom of this
article.

Code for FIFO does is pretty dense and does not explicitly show combinatorial
logic. Code could be broken down into two pieces: - combinatorial logic with
registers such as ptr_next, ptr, etc and separate state machine that loads
vaues of "next" registers.

module fifo
  (input wire clk,
   input wire reset,
   input wire [23:0] w_data,
   input wire wr,
   input wire rd,
   output reg [23:0] r_data,
   output wire full,
   output wire empty,
   output reg [8:0] full_indicator); // N
 
  reg [7:0] wr_ptr; // N-1
  reg [7:0] rd_ptr; // N-1
 
  reg[23:0] fifo_mem[2**8-1:0];
 
  assign full = (full_indicator == 2**8);
  assign empty = (full_indicator == 8'b0);
 
  always @(posedge clk)
    if (reset) 
      begin
        wr_ptr <= 8'b0;
        rd_ptr <= 8'b0;
        full_indicator <= 8'b0;
      end
    else
      begin
        case ({rd, wr})
          2'b00: // nothing
            begin
              full_indicator <= full_indicator;
            end
          2'b01: // write
            begin
              if  (full_indicator < 2**8)
                begin
                  full_indicator <= full_indicator + 1;
                  fifo_mem[wr_ptr] <= w_data;
                  wr_ptr <= wr_ptr + 1;
                end
            end
          2'b10: // read
            begin
              if (full_indicator > 0)
                begin
                  r_data <= fifo_mem[rd_ptr];
                  full_indicator <= full_indicator - 1;
                  rd_ptr <= rd_ptr + 1;
                end
            end
          2'b11: // read+write
            begin
              wr_ptr <= wr_ptr + 1;
              rd_ptr <= rd_ptr + 1;
              r_data <= fifo_mem[rd_ptr];
              fifo_mem[wr_ptr] <= w_data;
              full_indicator <= full_indicator;
            end
        endcase
      end
endmodule

Simple test bench:

`timescale 1ns/100ps 
module fifo_vito_tb;
  parameter B=8; // bit width
 
  reg [20:0] i;
  reg clk;
  reg reset;
  reg rd;
  reg wr;
  reg [B-1:0] w_data;
  wire [B-1:0] r_data;
  wire full;
  wire empty;
  reg [20:0] n;
 
  task WRITE(input [B-1:0] value);
    begin
      clk <= 1'b0;
      wr <= 1;
      rd <= 0;
      w_data <= value;
      #5 clk = 1'b1;
      #5 clk = 1'b0;
      wr<=0;
    end
  endtask
 
  task READ();
    begin
      clk <= 1'b0;
      rd <= 1;
      wr <= 0;
      #5 clk <= 1'b1;
      #5 clk <= 1'b0;
         rd  <= 0;
    end
  endtask
 
  task WRITEREAD(input [B-1:0] value);
    begin
      clk <= 1'b0;
      wr <= 1;
      rd <= 1;
      w_data <= value;
      #5 clk = 1'b1;
      #5 clk = 1'b0;
         rd <= 0;
         wr <= 0;
    end
  endtask
 
  task IDLE();
    begin
      #5 clk = 1'b1;
      #5 clk = 1'b0;
    end
  endtask
 
  fifo fifo_unit(.clk(clk), .reset(reset), .rd(rd), .wr(wr), .w_data(w_data), .r_data(r_data), .full(full), .empty(empty));
 
  /* FSM1 */
  initial begin
    clk=0;
    reset=1;
    rd=0;
    wr=0;
    w_data=0;
    //r_data=0;
    $dumpfile("fifo_vito_tb");
    $dumpvars;
 
    #5 clk<=1'b1;
    #5 clk<=1'b0;
       reset<=1'b0;
    #10000 $finish;
  end
 
  /* CASE 1: OVERFLOW: */
  initial begin // WRITING
    #10
    for (i=0; i<260; i=i+1)
    begin
      WRITE(i);
    end
 
    for (i=15; i<255; i=i+1)
    begin
      WRITEREAD(i);
    end
 
    for (i=32; i<64; i=i+1)
    begin
      READ();
    end
  end
endmodule