104 lines
3.4 KiB
Systemverilog
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
|