Files
max2771-raw-ethernet-recorder/tb/common/tb_async_fifo_gray.sv
T

104 lines
3.4 KiB
Systemverilog

`timescale 1ns/1ps
`default_nettype none
module tb_async_fifo_gray;
localparam int DEPTH = 16;
logic w_clk=0, r_clk=0, w_rst=1, r_rst=1;
logic w_en=0, r_en=0;
logic [15:0] w_data=0, r_data;
logic w_full, r_empty, r_valid;
logic [$clog2(DEPTH):0] w_level, r_level;
logic [63:0] overflow_count, underflow_count;
logic [15:0] expected [0:20000];
integer writes=0, reads=0, errors=0;
integer cycles;
always #3.5 w_clk = ~w_clk;
always #5.5 r_clk = ~r_clk;
async_fifo_gray #(.DATA_WIDTH(16), .DEPTH(DEPTH)) dut (
.w_clk(w_clk), .w_rst(w_rst), .w_en(w_en), .w_data(w_data),
.w_full(w_full), .w_level(w_level), .overflow_attempt_count(overflow_count),
.r_clk(r_clk), .r_rst(r_rst), .r_en(r_en), .r_data(r_data),
.r_valid(r_valid), .r_empty(r_empty), .r_level(r_level),
.underflow_attempt_count(underflow_count)
);
always @(posedge w_clk) begin
if (!w_rst && w_en && !w_full) begin
expected[writes] = w_data;
writes = writes + 1;
end
end
always @(posedge r_clk) begin
if (!r_rst && r_valid) begin
if (r_data !== expected[reads]) begin
$error("FIFO mismatch at read %0d: got %04x expected %04x", reads, r_data, expected[reads]);
errors = errors + 1;
end
reads = reads + 1;
end
end
initial begin
repeat (4) @(posedge w_clk);
w_rst = 0;
repeat (3) @(posedge r_clk);
r_rst = 0;
// Fill through the full boundary and intentionally attempt overflow.
@(negedge w_clk); w_en=1;
repeat (DEPTH+8) begin
@(negedge w_clk); w_data = w_data + 16'd1;
end
@(negedge w_clk); w_en=0;
if (!w_full) $fatal(1, "FIFO did not assert full");
// Drain through empty and intentionally attempt underflow.
@(negedge r_clk); r_en=1;
repeat (DEPTH+12) @(negedge r_clk);
@(negedge r_clk); r_en=0;
repeat (4) @(posedge r_clk);
if (!r_empty) $fatal(1, "FIFO did not assert empty");
// Random unrelated-clock traffic for wrap-around and simultaneous use.
fork
begin
for (cycles=0; cycles<5000; cycles=cycles+1) begin
@(negedge w_clk);
w_en = ($urandom_range(0,99) < 68);
w_data = w_data + 16'd1;
end
@(negedge w_clk); w_en=0;
end
begin
repeat (5000) begin
@(negedge r_clk);
r_en = ($urandom_range(0,99) < 54);
end
@(negedge r_clk); r_en=0;
end
join
// Final drain.
r_en=1;
while (reads < writes) @(negedge r_clk);
r_en=0;
repeat (4) @(posedge r_clk);
if (errors != 0) $fatal(1, "FIFO scoreboard saw %0d errors", errors);
if (overflow_count == 0) $fatal(1, "overflow attempt counter stayed zero");
if (underflow_count == 0) $fatal(1, "underflow attempt counter stayed zero");
if (reads != writes) $fatal(1, "writes=%0d reads=%0d", writes, reads);
$display("PASS tb_async_fifo_gray: %0d ordered words, overflow=%0d underflow=%0d",
reads, overflow_count, underflow_count);
$finish;
end
initial begin
#500000;
$fatal(1, "FIFO test timeout");
end
endmodule
`default_nettype wire