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 | 
