aboutsummaryrefslogtreecommitdiffstats
path: root/fpga/usrp3/lib/fifo/axi_fifo_tb.v
diff options
context:
space:
mode:
Diffstat (limited to 'fpga/usrp3/lib/fifo/axi_fifo_tb.v')
-rw-r--r--fpga/usrp3/lib/fifo/axi_fifo_tb.v328
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