Tiny FIFO

A synchronous FIFO, depth 4, width 8, show-ahead (FWFT) style:

Port Dir Width
clk, rst, wr_en, rd_en in 1
wr_data in 8
rd_data out 8
full, empty out 1

Related: FIFO depth calculator, and the async version lives in the library's roadmap.

Show the testbench (the grader)
tb.v — locked
`timescale 1ns/1ps
module tb;
    reg clk=0, rst=1, wr_en=0, rd_en=0; reg [7:0] wr_data=0;
    wire [7:0] rd_data; wire full, empty;
    reg [7:0] model [0:15]; integer head=0, tail=0, count=0;
    integer i, errors=0; reg [31:0] lfsr = 32'hCAFE;
    reg do_push, do_pop;
    challenge dut (.clk(clk), .rst(rst), .wr_en(wr_en), .wr_data(wr_data),
                   .rd_en(rd_en), .rd_data(rd_data), .full(full), .empty(empty));
    always #5 clk = ~clk;
    initial begin
        $dumpfile("wave.vcd"); $dumpvars(0, tb);
        repeat (2) @(negedge clk); rst = 0;
        for (i = 0; i < 500; i = i + 1) begin
            @(negedge clk);
            lfsr = {lfsr[30:0], lfsr[31]^lfsr[21]^lfsr[1]^lfsr[0]};
            wr_en = lfsr[0]; rd_en = lfsr[1]; wr_data = lfsr[15:8];
            // flags BEFORE the edge decide what happens at the edge
            #1;
            if (full !== (count == 4)) begin
                errors = errors + 1;
                if (errors < 6) $display("FAIL @%0t: full=%b count=%0d", $time, full, count);
            end
            if (empty !== (count == 0)) begin
                errors = errors + 1;
                if (errors < 6) $display("FAIL @%0t: empty=%b count=%0d", $time, empty, count);
            end
            if (count > 0 && rd_data !== model[head % 16]) begin
                errors = errors + 1;
                if (errors < 6) $display("FAIL @%0t: rd_data=%h want=%h",
                                         $time, rd_data, model[head % 16]);
            end
            do_push = wr_en && (count < 4);
            do_pop  = rd_en && (count > 0);
            @(posedge clk);
            if (do_push) begin model[tail % 16] = wr_data; tail = tail + 1; end
            if (do_pop)  head = head + 1;
            count = tail - head;
        end
        if (errors == 0) $display("TB PASS");
        else $display("TB FAIL (%0d errors)", errors);
        $finish;
    end
endmodule