diff options
Diffstat (limited to 'fpga/usrp3/lib/fifo/axi_fifo_tb.v')
-rw-r--r-- | fpga/usrp3/lib/fifo/axi_fifo_tb.v | 328 |
1 files changed, 328 insertions, 0 deletions
diff --git a/fpga/usrp3/lib/fifo/axi_fifo_tb.v b/fpga/usrp3/lib/fifo/axi_fifo_tb.v new file mode 100644 index 000000000..69529c7af --- /dev/null +++ b/fpga/usrp3/lib/fifo/axi_fifo_tb.v @@ -0,0 +1,328 @@ +// +// Copyright 2015 Ettus Research LLC +// Copyright 2018 Ettus Research, a National Instruments Company +// +// SPDX-License-Identifier: LGPL-3.0-or-later +// + +module axi_fifo_tb(); + + /********************************************* + ** User variables + *********************************************/ + localparam FIFO_SIZE = 1; + localparam TEST_VECTOR_SIZE = 10; + + /********************************************* + ** Clocks & Reset + *********************************************/ + `define CLOCK_FREQ 200e6 + `define RESET_TIME 100 + + reg clk; + initial clk = 1'b0; + localparam CLOCK_PERIOD = 1e9/`CLOCK_FREQ; + always + #(CLOCK_PERIOD) clk = ~clk; + + reg reset; + initial begin + reset = 1'b1; + #(`RESET_TIME); + @(posedge clk); + reset = 1'b0; + end + + /********************************************* + ** DUT + *********************************************/ + reg [31:0] i_tdata; + reg i_tvalid, o_tready; + wire i_tready, o_tvalid; + wire [31:0] o_tdata; + reg clear; + + axi_fifo #( + .SIZE(FIFO_SIZE), + .WIDTH(32)) + dut_axi_fifo ( + .clk(clk), .reset(reset), .clear(clear), + .i_tdata(i_tdata), .i_tvalid(i_tvalid), .i_tready(i_tready), + .o_tdata(o_tdata), .o_tvalid(o_tvalid), .o_tready(o_tready), + .space(), .occupied()); + + /********************************************* + ** Testbench + *********************************************/ + reg [TEST_VECTOR_SIZE-1:0] i_tvalid_sequence; + reg [TEST_VECTOR_SIZE-1:0] o_tready_sequence; + integer i,k,n,i_tready_timeout; + reg [31:0] o_tdata_check; + + initial begin + i_tdata = {32{1'b1}}; + i_tvalid = 1'b0; + o_tready = 1'b0; + i_tready_timeout = 0; + clear = 1'b0; + @(negedge reset); + #(10*CLOCK_PERIOD) + @(posedge clk); + $display("*****************************************************"); + $display("** Begin Assertion Tests **"); + $display("*****************************************************"); + $display("Test 1 -- Check filling FIFO"); + // Note, if REG_OUTPUT is enabled, the FIFO has space for 1 extra entry + for (i = 0; i < 2**FIFO_SIZE; i = i + 1) begin + if (~i_tready) begin + $display("Test 1 FAILED!"); + $error("FIFO size should be %d entries, but detected %d!",2**FIFO_SIZE,i); + $stop; + end + i_tvalid = 1'b1; + i_tdata = i_tdata + 32'd1; + @(posedge clk); + end + i_tvalid = 1'b0; + @(posedge clk); + if (i_tready) begin + $display("Test 1 warning!"); + $warning("i_tready still asserted after filling FIFO with %d entries! Might be due to output registering.",i); + //$stop; + end + $display("Test 1 Passed!"); + ////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////// + $display("Test 2 -- Check emptying FIFO"); + for (i = 0; i < 2**FIFO_SIZE; i = i + 1) begin + if (~o_tvalid) begin + $display("Test 2 FAILED!"); + $error("FIFO o_tvalid not asserted! Occured at entry %d",2**FIFO_SIZE-i+1); + $stop; + end + o_tready = 1'b1; + @(posedge clk); + end + o_tready = 1'b0; + @(posedge clk); + if (o_tvalid) begin + $display("Test 1 FAILED!"); + $error("o_tvalid still asserted after emptying FIFO!"); + $stop; + end + $display("Test 2 Passed!"); + ////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////// + $display("Test 3 -- Check for o_tready / i_tready dropping unexpectantly"); + clear = 1'b1; + i_tdata = {32{1'b1}}; + i_tvalid = 1'b0; + o_tready = 1'b0; + @(posedge clk); + clear = 1'b0; + @(posedge clk); + for (i = 0; i < 2**FIFO_SIZE-1; i = i + 1) begin + i_tvalid = 1'b1; + i_tdata = i_tdata + 32'd1; + @(posedge clk); + i_tvalid = 1'b0; + // Give some time to propogate + @(posedge clk); + @(posedge clk); + @(posedge clk); + if (~i_tready) begin + $display("Test 3 FAILED!"); + $error("i_tready deasserted unexpectantly after writing %d entries!",i+1); + $stop; + end + if (~o_tvalid) begin + $display("Test 3 FAILED!"); + $error("o_tvalid deasserted unexpectantly after writing %d entries!",i+1); + $stop; + end + end + // Write final entry + i_tvalid = 1'b1; + i_tdata = i_tdata + 32'd1; + @(posedge clk); + i_tvalid = 1'b0; + @(posedge clk); + if (i_tready) begin + $display("Test 3 warning!"); + $warning("i_tready still asserted after writing %d entries! Might be due to output registering.",i+1); + //$stop; + end + @(posedge clk); + for (i = 0; i < 2**FIFO_SIZE-1; i = i + 1) begin + o_tready = 1'b1; + @(posedge clk); + o_tready = 1'b0; + // Give some time to propogate + @(posedge clk); + @(posedge clk); + @(posedge clk); + if (~i_tready) begin + $display("Test 3 FAILED!"); + $error("i_tready deasserted unexpectantly after reading %d entries!",i+1); + $stop; + end + if (~o_tvalid) begin + $display("Test 3 FAILED!"); + $error("o_tvalid deasserted unexpectantly after reading %d entries!",i+1); + $stop; + end + end + // Read final entry + o_tready = 1'b1; + @(posedge clk); + o_tready = 1'b0; + @(posedge clk); + if (o_tvalid) begin + $display("Test 3 FAILED!"); + $error("o_tvalid still asserted after reading %d entries!",i+1); + $stop; + end + @(posedge clk); + ////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////// + $display("Test 4 -- Check for bubble states"); + clear = 1'b1; + i_tdata = {32{1'b1}}; + i_tvalid = 1'b0; + o_tready = 1'b0; + @(posedge clk); + clear = 1'b0; + @(posedge clk); + // Fill up half way + for (i = 0; i < (2**FIFO_SIZE + 1)/2; i = i + 1) begin + i_tvalid = 1'b1; + i_tdata = i_tdata + 32'd1; + @(posedge clk); + end + // Start reading + o_tready = 1'b1; + i_tdata = i_tdata + 32'd1; + @(posedge clk); + // Give a clock cycle for latency, but no bubbles should occur after this + i_tdata = i_tdata + 32'd1; + @(posedge clk); + // Continue to write and read at full rate + for (i = 0; i < (2**FIFO_SIZE + 1)/2; i = i + 1) begin + if (~i_tready) begin + $display("Test 4 FAILED!"); + $error("FIFO bubble state detected when writing & reading at full rate!"); + $stop; + end + i_tvalid = 1'b1; + i_tdata = i_tdata + 32'd1; + @(posedge clk); + end + // Read at full, write at half rate + for (i = 0; i < (2**FIFO_SIZE + 1)/2; i = i + 1) begin + if (~i_tready | ~o_tvalid) begin + $display("Test 4 FAILED!"); + $error("FIFO bubble state detected when write at half rate, reading at full rate!"); + $stop; + end + i_tvalid = ~i_tvalid; + if (i_tvalid) i_tdata = i_tdata + 32'd1; + @(posedge clk); + end + // Read at half rate, write at full rate + for (i = 0; i < (2**FIFO_SIZE + 1)/2; i = i + 1) begin + if (~i_tready | ~o_tvalid) begin + $display("Test 4 FAILED!"); + $error("FIFO bubble state detected when write at half rate, reading at full rate!"); + $stop; + end + o_tready = ~o_tready; + i_tvalid = 1'b1; + i_tdata = i_tdata + 32'd1; + @(posedge clk); + end + $display("Test 4 Passed!"); + ////////////////////////////////////////////////////////////////////////////// + // Tests combinations of i_tvalid / o_tready sequences. + // Test space depends on TEST_VECTOR_SIZE. + // Example: TEST_VECTOR_SIZE = 10 => 1024*1024 number of test sequences, + // which is every possible 10 bit sequence of i_tvalid / o_tready. + $display("Test 5 -- Check combinations of i_tvalid / o_tready"); + clear = 1'b1; + i_tdata = {32{1'b1}}; + i_tvalid = 1'b0; + o_tready = 1'b0; + i_tready_timeout = 0; + i_tvalid_sequence = {TEST_VECTOR_SIZE{1'd0}}; + o_tready_sequence = {TEST_VECTOR_SIZE{1'd0}}; + @(posedge clk); + clear = 1'b0; + @(posedge clk); + for (i = 0; i < 2**TEST_VECTOR_SIZE; i = i + 1) begin + i_tvalid_sequence = i_tvalid_sequence + 1; + for (k = 0; k < 2**TEST_VECTOR_SIZE; k = k + 1) begin + o_tready_sequence = o_tready_sequence + 1; + for (n = 0; n < TEST_VECTOR_SIZE; n = n + 1) begin + if (o_tready_sequence[n]) begin + o_tready = 1'b1; + end else begin + o_tready = 1'b0; + end + // Special Case: If i_tready timed out, then i_tvalid is still asserted and we cannot + // deassert i_tvalid until we see a corresponding i_tready. This is a basic + // AXI stream requirement, so we will continue to assert i_tvalid regardless + // of what i_tvalid_sequence would have set i_tvalid for this loop. + if (i_tvalid_sequence[n] | (i_tready_timeout == TEST_VECTOR_SIZE)) begin + i_tvalid = 1'b1; + if (i_tready_timeout < TEST_VECTOR_SIZE) begin + i_tdata = i_tdata + 32'd1; + end + @(posedge clk); + i_tready_timeout = 0; + // Wait for i_tready until timeout. Timeouts may occur when o_tready_sequence + // has o_tready not asserted for several clock cycles. + while(~i_tready & (i_tready_timeout < TEST_VECTOR_SIZE)) begin + @(posedge clk) + i_tready_timeout = i_tready_timeout + 1; + end + end else begin + i_tvalid = 1'b0; + @(posedge clk); + end + end + end + // Reset starting conditions for the test sequences + clear = 1'b1; + i_tdata = {32{1'b1}}; + i_tvalid = 1'b0; + o_tready = 1'b0; + i_tready_timeout = 0; + @(posedge clk); + clear = 1'b0; + @(posedge clk); + end + $display("Test 5 Passed!"); + $display("All tests PASSED!"); + $stop; + end + + // Check the input counting sequence independent of + // i_tvalid / o_tready sequences. + always @(posedge clk) begin + if (reset) begin + o_tdata_check <= 32'd0; + end else begin + if (clear) begin + o_tdata_check <= 32'd0; + end + if (o_tready & o_tvalid) begin + o_tdata_check <= o_tdata_check + 32'd1; + if (o_tdata != o_tdata_check) begin + $display("Test FAILED!"); + $error("Incorrect output!"); + $stop; + end + end + end + end + +endmodule |