`timescale 1ns/1ps `default_nettype none module tb_sync_fifo; parameter integer DATA_WIDTH = 8; parameter integer DEPTH = 4; reg clk=0; always #5 clk = ~clk; reg rst_n=0, wr_en=0, rd_en=0; reg [DATA_WIDTH-1:0] wr_data=0; wire [DATA_WIDTH-1:0] rd_data; wire full, empty; wire [$clog2(DEPTH+1)-1:0] count; sync_fifo #(.DATA_WIDTH(DATA_WIDTH), .DEPTH(DEPTH)) dut ( .clk(clk), .rst_n(rst_n), .wr_en(wr_en), .wr_data(wr_data), .rd_en(rd_en), .rd_data(rd_data), .full(full), .empty(empty), .count(count) ); // Independent scoreboard: shift an array, rather than reusing DUT pointers. reg [DATA_WIDTH-1:0] reference [0:DEPTH-1]; reg [DATA_WIDTH-1:0] last_read=0; integer occupancy=0, cycles=0, accepted_writes=0, accepted_reads=0; integer blocked_writes=0, blocked_reads=0, i; reg [31:0] seed=32'h7A1E_F00D; function automatic [31:0] rand32(input [31:0] old); reg [31:0] x; begin x = old ^ (old << 13); x = x ^ (x >> 17); rand32 = x ^ (x << 5); end endfunction task automatic verify; begin if (count !== occupancy || full !== (occupancy == DEPTH) || empty !== (occupancy == 0) || rd_data !== last_read) $fatal(1, "cycle=%0d DEPTH=%0d expected count/full/empty/data=%0d/%0b/%0b/%0h actual=%0d/%0b/%0b/%0h", cycles,DEPTH,occupancy,(occupancy==DEPTH),(occupancy==0),last_read, count,full,empty,rd_data); end endtask task automatic reset_fifo; begin @(negedge clk); rst_n = 0; wr_en = 0; rd_en = 0; occupancy = 0; last_read = 0; // Check async clearing *before* any next rising edge. #1; verify(); repeat (2) @(posedge clk); #1; verify(); @(negedge clk); rst_n = 1; #1; verify(); end endtask task automatic step(input reg push, input reg [DATA_WIDTH-1:0] data_in, input reg pop); reg do_read, do_write; begin @(negedge clk); wr_en = push; wr_data = data_in; rd_en = pop; do_read = pop && (occupancy > 0); do_write = push && (occupancy < DEPTH || do_read); if (push && !do_write) blocked_writes = blocked_writes + 1; if (pop && !do_read) blocked_reads = blocked_reads + 1; if (do_read) begin last_read = reference[0]; for (i=0; i> 8),candidate[1]); end // Guarantee the final state is checked after draining. for (integer k=0; k