diff options
Diffstat (limited to 'fpga/usrp3/lib/sim/axi_packet_gate')
-rw-r--r-- | fpga/usrp3/lib/sim/axi_packet_gate/Makefile | 46 | ||||
-rw-r--r-- | fpga/usrp3/lib/sim/axi_packet_gate/axi_packet_gate_tb.sv | 347 |
2 files changed, 393 insertions, 0 deletions
diff --git a/fpga/usrp3/lib/sim/axi_packet_gate/Makefile b/fpga/usrp3/lib/sim/axi_packet_gate/Makefile new file mode 100644 index 000000000..625a02877 --- /dev/null +++ b/fpga/usrp3/lib/sim/axi_packet_gate/Makefile @@ -0,0 +1,46 @@ +# +# Copyright 2016 Ettus Research +# + +#------------------------------------------------- +# Top-of-Makefile +#------------------------------------------------- +# Define BASE_DIR to point to the "top" dir +BASE_DIR = $(abspath ../../../top) +# Include viv_sim_preamble after defining BASE_DIR +include $(BASE_DIR)/../tools/make/viv_sim_preamble.mak + +#------------------------------------------------- +# Design Specific +#------------------------------------------------- +# Include makefiles and sources for the DUT and its dependencies +include $(BASE_DIR)/../lib/control/Makefile.srcs +include $(BASE_DIR)/../lib/fifo/Makefile.srcs + +DESIGN_SRCS = $(abspath \ +$(CONTROL_LIB_SRCS) \ +$(FIFO_SRCS) \ +$(LIB_DIR)/fifo/axi_packet_gate.v \ +) + +#------------------------------------------------- +# Testbench Specific +#------------------------------------------------- +# Define only one toplevel module +SIM_TOP = axi_packet_gate_tb + +# Add test bench, user design under test, and +# additional user created files +SIM_SRCS = $(abspath \ +axi_packet_gate_tb.sv \ +) + +# MODELSIM_USER_DO = $(abspath wave.do) + +#------------------------------------------------- +# Bottom-of-Makefile +#------------------------------------------------- +# Include all simulator specific makefiles here +# Each should define a unique target to simulate +# e.g. xsim, vsim, etc and a common "clean" target +include $(BASE_DIR)/../tools/make/viv_simulator.mak diff --git a/fpga/usrp3/lib/sim/axi_packet_gate/axi_packet_gate_tb.sv b/fpga/usrp3/lib/sim/axi_packet_gate/axi_packet_gate_tb.sv new file mode 100644 index 000000000..0463a1e28 --- /dev/null +++ b/fpga/usrp3/lib/sim/axi_packet_gate/axi_packet_gate_tb.sv @@ -0,0 +1,347 @@ +`timescale 1ns/1ps +`define NS_PER_TICK 1 +`define NUM_TEST_CASES 7 + +`include "sim_exec_report.vh" +`include "sim_clks_rsts.vh" +`include "sim_axis_lib.svh" + +module axi_packet_gate_tb(); + `TEST_BENCH_INIT("axi_packet_gate_tb", `NUM_TEST_CASES, `NS_PER_TICK); + localparam CLK_PERIOD = $ceil(1e9/166.67e6); + `DEFINE_CLK(clk, CLK_PERIOD, 50); + `DEFINE_RESET(reset, 0, 100); + + localparam MAX_PKT_SIZE = 64; + + // +1 for terror + axis_master #(.DWIDTH(32+1)) m_axis (.clk(clk)); + axis_slave #(.DWIDTH(32)) s_axis (.clk(clk)); + + axi_packet_gate #( + .WIDTH(32), + .SIZE($clog2(MAX_PKT_SIZE)), + .USE_AS_BUFF(1) + ) dut ( + .clk(clk), .reset(reset), .clear(1'b0), + .i_tdata(m_axis.axis.tdata[31:0]), + .i_tvalid(m_axis.axis.tvalid), + .i_tlast(m_axis.axis.tlast), + .i_terror(m_axis.axis.tdata[32]), // Use MSB as terror + .i_tready(m_axis.axis.tready), + .o_tdata(s_axis.axis.tdata), + .o_tvalid(s_axis.axis.tvalid), + .o_tlast(s_axis.axis.tlast), + .o_tready(s_axis.axis.tready) + ); + + /******************************************************** + ** Verification + ********************************************************/ + task random_wait(int unsigned min_cycles, int unsigned max_cycles); + begin + int unsigned num_cycles; + do begin + num_cycles = $random() & (2**($clog2(max_cycles))-1); + end while ((num_cycles < min_cycles) || (num_cycles > max_cycles)); + + if (num_cycles != 0) begin + for (int unsigned i = 0; i < num_cycles; i++) begin + @(posedge clk); + end + @(negedge clk); // Realign with negedge + end + end + endtask + + initial begin : tb_main + string s; + logic error, last; + int cnt, check; + + /******************************************************** + ** Test 1 -- Reset + ********************************************************/ + `TEST_CASE_START("Wait for Reset"); + m_axis.reset(); + s_axis.reset(); + while (reset) @(posedge clk); + `TEST_CASE_DONE(~reset); + + /******************************************************** + ** Test 2 -- Fill / Empty FIFO + ********************************************************/ + `TEST_CASE_START("Fill and empty FIFO"); + error = 0; + last = 0; + cnt = 0; + $display("Write %0d words to FIFO", MAX_PKT_SIZE); + for (int i = 0; i < MAX_PKT_SIZE; i++) begin + $sformat(s, "FIFO prematurely full at %0d (tready not asserted!)", i); + `ASSERT_FATAL(m_axis.axis.tready, s); + m_axis.push_word({error,cnt}, i == MAX_PKT_SIZE-1); + cnt++; + end + $display("Done writing to FIFO"); + if (m_axis.axis.tready) begin + $display("FIFO not full, fill remaining space"); + // Continue filling until FIFO is full + while (m_axis.axis.tready) begin + m_axis.push_word({error,cnt}, 0); + cnt++; + end + $display("Done filling remaining space"); + $display("Expected FIFO size: %0d, Actual: %0d",MAX_PKT_SIZE,cnt); + end + // On the first packet, output is held off until a full packet is received + repeat(MAX_PKT_SIZE) @(posedge clk); + $display("Empty FIFO and check output"); + for (int i = 0; i < cnt; i++) begin + $sformat(s, "FIFO prematurely empty at %0d (tvalid not asserted!)", i); + `ASSERT_FATAL(s_axis.axis.tvalid, s); + s_axis.pull_word(check, last); + $sformat(s, "FIFO output incorrect! Expected: %0d, Actual: %0d", i, check); + `ASSERT_FATAL(check == i, s); + if (i == cnt-1) begin + `ASSERT_FATAL(last, "tlast not asserted on final word!"); + end else begin + `ASSERT_FATAL(~last, "tlast asserted prematurely!"); + end + end + `TEST_CASE_DONE(1); + + /******************************************************** + ** Test 3 -- Check gating + ********************************************************/ + `TEST_CASE_START("Check gating"); + error = 0; + last = 0; + cnt = 0; + + $display("Write %0d words to FIFO and check out valid", MAX_PKT_SIZE); + for (int i = 0; i < MAX_PKT_SIZE/2; i++) begin + m_axis.push_word({error,cnt}, 0); + cnt++; + end + // On the first packet, output is held off until a full packet is received + repeat(10) @(posedge clk); + `ASSERT_FATAL(~s_axis.axis.tvalid, "Saw output before a full packet input"); + for (int i = MAX_PKT_SIZE/2; i < MAX_PKT_SIZE; i++) begin + m_axis.push_word({error,cnt}, i == MAX_PKT_SIZE-1); + cnt++; + end + repeat(10) @(posedge clk); + `ASSERT_FATAL(s_axis.axis.tvalid, "Did not see output even after full packet input"); + $display("Empty FIFO and check output"); + for (int i = 0; i < cnt; i++) begin + $sformat(s, "FIFO prematurely empty at %0d (tvalid not asserted!)", i); + `ASSERT_FATAL(s_axis.axis.tvalid, s); + s_axis.pull_word(check, last); + $sformat(s, "FIFO output incorrect! Expected: %0d, Actual: %0d", i, check); + `ASSERT_FATAL(check == i, s); + if (i == cnt-1) begin + `ASSERT_FATAL(last, "tlast not asserted on final word!"); + end else begin + `ASSERT_FATAL(~last, "tlast asserted prematurely!"); + end + end + `TEST_CASE_DONE(1); + + /******************************************************** + ** Test 4 -- Ensure no bleed + ********************************************************/ + `TEST_CASE_START("Ensure no bleed"); + error = 0; + last = 0; + cnt = 0; + + $display("Write %0d words to FIFO (full packet)", MAX_PKT_SIZE/2); + for (int i = 0; i < MAX_PKT_SIZE/2; i++) begin + m_axis.push_word({error,cnt}, i == (MAX_PKT_SIZE/2)-1); + cnt++; + end + $display("Write %0d words to FIFO (partial packet)", MAX_PKT_SIZE/4); + for (int i = 0; i < MAX_PKT_SIZE/4; i++) begin + m_axis.push_word({error,cnt}, 0); + cnt++; + end + // On the first packet, output is held off until a full packet is received + repeat(10) @(posedge clk); + for (int i = 0; i < MAX_PKT_SIZE/2; i++) begin + $sformat(s, "FIFO prematurely empty at %0d (tvalid not asserted!)", i); + `ASSERT_FATAL(s_axis.axis.tvalid, s); + s_axis.pull_word(check, last); + $sformat(s, "FIFO output incorrect! Expected: %0d, Actual: %0d", i, check); + `ASSERT_FATAL(check == i, s); + if (i == (MAX_PKT_SIZE/2)-1) begin + `ASSERT_FATAL(last, "tlast not asserted on final word!"); + end else begin + `ASSERT_FATAL(~last, "tlast asserted prematurely!"); + end + end + repeat(10) @(posedge clk); + `ASSERT_FATAL(~s_axis.axis.tvalid, "Partial packet bled through with full packet"); + for (int i = MAX_PKT_SIZE/4; i < MAX_PKT_SIZE/2; i++) begin + m_axis.push_word({error,cnt}, i == (MAX_PKT_SIZE/2)-1); + cnt++; + end + repeat(10) @(posedge clk); + `ASSERT_FATAL(s_axis.axis.tvalid, "Did not see output even after full packet input"); + $display("Empty FIFO and check output"); + for (int i = MAX_PKT_SIZE/2; i < cnt; i++) begin + $sformat(s, "FIFO prematurely empty at %0d (tvalid not asserted!)", i); + `ASSERT_FATAL(s_axis.axis.tvalid, s); + s_axis.pull_word(check, last); + $sformat(s, "FIFO output incorrect! Expected: %0d, Actual: %0d", i, check); + `ASSERT_FATAL(check == i, s); + if (i == cnt-1) begin + `ASSERT_FATAL(last, "tlast not asserted on final word!"); + end else begin + `ASSERT_FATAL(~last, "tlast asserted prematurely!"); + end + end + `TEST_CASE_DONE(1); + + /******************************************************** + ** Test 5 -- Back to back small packets + ********************************************************/ + `TEST_CASE_START("Back to back small packets"); + error = 0; + last = 0; + cnt = 0; + for (int i = 0; i < MAX_PKT_SIZE/2; i++) begin + $sformat(s, "FIFO prematurely full at %0d (tready not asserted!)", i); + `ASSERT_FATAL(m_axis.axis.tready, s); + m_axis.push_word({error,cnt}, i == MAX_PKT_SIZE/2-1); + cnt++; + end + for (int i = 0; i < MAX_PKT_SIZE/2; i++) begin + $sformat(s, "FIFO prematurely full at %0d (tready not asserted!)", i); + `ASSERT_FATAL(m_axis.axis.tready, s); + m_axis.push_word({error,cnt}, i == MAX_PKT_SIZE/2-1); + cnt++; + end + fork + begin + for (int k = 0; k < 8; k++) begin + for (int i = 0; i < MAX_PKT_SIZE/2; i++) begin + m_axis.push_word({error,cnt}, i == MAX_PKT_SIZE/2-1); + cnt++; + end + end + end + begin + @(posedge clk); + @(posedge clk); + @(posedge clk); + for (int k = 0; k < 10; k++) begin + for (int i = 0; i < MAX_PKT_SIZE/2; i++) begin + `ASSERT_FATAL(s_axis.axis.tvalid, "tvalid not asserted!"); + s_axis.pull_word(check, last); + $sformat(s, "FIFO output incorrect! Expected: %0d, Actual: %0d", i, check); + `ASSERT_FATAL(check == (i+k*MAX_PKT_SIZE/2), s); + if (i == MAX_PKT_SIZE/2-1) begin + `ASSERT_FATAL(last, "tlast not asserted on final word!"); + end else begin + `ASSERT_FATAL(~last, "tlast asserted prematurely!"); + end + end + end + end + join + `TEST_CASE_DONE(1); + + #2000; // Delay to make the tests visually distinct in waveform viewer + + /******************************************************** + ** Test 6 -- Drop error packet + ** - Send packet, drop a packet, send another packet + ********************************************************/ + `TEST_CASE_START("Drop error packet"); + cnt = 0; + $display("Write packet with %0d words to FIFO", MAX_PKT_SIZE/4); + error = 0; + for (int i = 0; i < MAX_PKT_SIZE/4; i++) begin + $sformat(s, "FIFO prematurely full at %0d (tready not asserted!)", i); + `ASSERT_FATAL(m_axis.axis.tready, s); + m_axis.push_word({error,cnt}, i == MAX_PKT_SIZE/4-1); + cnt++; + end + $display("Write error packet with %0d words to FIFO", MAX_PKT_SIZE/4); + error = 1; + for (int i = 0; i < MAX_PKT_SIZE/4; i++) begin + $sformat(s, "FIFO prematurely full at %0d (tready not asserted!)", i); + `ASSERT_FATAL(m_axis.axis.tready, s); + m_axis.push_word({error,cnt}, i == MAX_PKT_SIZE/4-1); + cnt++; + end + $display("Write packet with %0d words to FIFO", MAX_PKT_SIZE/4); + error = 0; + for (int i = 0; i < MAX_PKT_SIZE/4; i++) begin + $sformat(s, "FIFO prematurely full at %0d (tready not asserted!)", i); + `ASSERT_FATAL(m_axis.axis.tready, s); + m_axis.push_word({error,cnt}, i == MAX_PKT_SIZE/4-1); + cnt++; + end + for (int i = 0; i < MAX_PKT_SIZE/4; i++) begin + $sformat(s, "FIFO prematurely empty at %0d (tvalid not asserted!)", i); + `ASSERT_FATAL(s_axis.axis.tvalid, s); + s_axis.pull_word(check, last); + $sformat(s, "FIFO output incorrect! Expected: %0d, Actual: %0d", i, check); + `ASSERT_FATAL(check == i, s); + if (i == MAX_PKT_SIZE/4-1) begin + `ASSERT_FATAL(last, "tlast not asserted on final word!"); + end else begin + `ASSERT_FATAL(~last, "tlast asserted prematurely!"); + end + end + for (int i = 0; i < MAX_PKT_SIZE/4; i++) begin + $sformat(s, "FIFO prematurely empty at %0d (tvalid not asserted!)", i); + `ASSERT_FATAL(s_axis.axis.tvalid, s); + s_axis.pull_word(check, last); + $sformat(s, "FIFO output incorrect! Expected: %0d, Actual: %0d", i, check); + `ASSERT_FATAL(check == (i+MAX_PKT_SIZE/2), s); + if (i == MAX_PKT_SIZE/4-1) begin + `ASSERT_FATAL(last, "tlast not asserted on final word!"); + end else begin + `ASSERT_FATAL(~last, "tlast asserted prematurely!"); + end + end + `TEST_CASE_DONE(1); + + #2000; + + /******************************************************** + ** Test 7 -- Random read / writes + ********************************************************/ + `TEST_CASE_START("Random read / writes"); + error = 0; + last = 0; + cnt = 0; + fork + begin + for (int k = 1; k <= 5000*MAX_PKT_SIZE; k++) begin + m_axis.push_word({error,k}, (k % 16) == 0); + random_wait(0,16); + end + end + begin + for (int k = 1; k <= 5000*MAX_PKT_SIZE; k++) begin + random_wait(0,16); + s_axis.pull_word(check, last); + $sformat(s, "FIFO output incorrect! Expected: %0d, Actual: %0d", k, check); + `ASSERT_FATAL(check == k, s); + if ((k % 16) == 0) begin + `ASSERT_FATAL(last, "tlast not asserted!"); + end else begin + `ASSERT_FATAL(~last, "tlast asserted prematurely!"); + end + end + end + join + `TEST_CASE_DONE(1); + + `TEST_BENCH_DONE; + + end +endmodule |