diff options
Diffstat (limited to 'fpga/usrp3/top/x300/sim/dram_fifo_bist')
-rw-r--r-- | fpga/usrp3/top/x300/sim/dram_fifo_bist/Makefile | 72 | ||||
-rw-r--r-- | fpga/usrp3/top/x300/sim/dram_fifo_bist/dram_fifo_bist_tb.sv | 349 |
2 files changed, 421 insertions, 0 deletions
diff --git a/fpga/usrp3/top/x300/sim/dram_fifo_bist/Makefile b/fpga/usrp3/top/x300/sim/dram_fifo_bist/Makefile new file mode 100644 index 000000000..8e75817b1 --- /dev/null +++ b/fpga/usrp3/top/x300/sim/dram_fifo_bist/Makefile @@ -0,0 +1,72 @@ +# +# Copyright 2015 Ettus Research LLC +# + +#------------------------------------------------- +# Top-of-Makefile +#------------------------------------------------- +# Define BASE_DIR to point to the "top" dir +BASE_DIR = $(abspath ../../..) +# Include viv_sim_preample after defining BASE_DIR +include $(BASE_DIR)/../tools/make/viv_sim_preamble.mak + +#------------------------------------------------- +# Design Specific +#------------------------------------------------- +# Define part using PART_ID (<device>/<package>/<speedgrade>) +ARCH = kintex7 +PART_ID = xc7k410t/ffg900/-2 + +# Include makefiles and sources for the DUT and its dependencies +include $(BASE_DIR)/../lib/fifo/Makefile.srcs +include $(BASE_DIR)/../lib/axi/Makefile.srcs +include $(BASE_DIR)/../lib/control/Makefile.srcs + +DESIGN_SRCS = $(abspath \ +$(FIFO_SRCS) \ +$(AXI_SRCS) \ +$(CONTROL_LIB_SRCS) \ +) + +#------------------------------------------------- +# IP Specific +#------------------------------------------------- +# If simulation contains IP, define the IP_DIR and point +# it to the base level IP directory +IP_DIR = ../../ip + +# Include makefiles and sources for all IP components +# *after* defining the IP_DIR +include $(IP_DIR)/ddr3_32bit/Makefile.inc +include $(IP_DIR)/axi_intercon_2x64_128_bd/Makefile.inc +include $(IP_DIR)/fifo_short_2clk/Makefile.inc +include $(IP_DIR)/fifo_4k_2clk/Makefile.inc +include $(IP_DIR)/axi4_dualport_sram/Makefile.inc + +DESIGN_SRCS += $(abspath \ +$(IP_DDR3_32BIT_SRCS) \ +$(IP_AXI_INTERCON_2X64_128_SRCS) \ +$(IP_AXI_INTERCON_2X64_128_BD_SRCS) \ +$(IP_FIFO_4K_2CLK_SRCS) \ +$(IP_FIFO_SHORT_2CLK_SRCS) \ +$(IP_AXI4_BRAM_SRCS) \ +) + +#------------------------------------------------- +# Testbench Specific +#------------------------------------------------- +# Define only one toplevel module +SIM_TOP = dram_fifo_bist_tb + +SIM_SRCS = \ +$(abspath dram_fifo_bist_tb.sv) \ +$(abspath ../dram_fifo/axis_dram_fifo_single.sv) \ +$(IP_DDR3_32BIT_SIM_OUTS) + +#------------------------------------------------- +# 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/top/x300/sim/dram_fifo_bist/dram_fifo_bist_tb.sv b/fpga/usrp3/top/x300/sim/dram_fifo_bist/dram_fifo_bist_tb.sv new file mode 100644 index 000000000..33fb93332 --- /dev/null +++ b/fpga/usrp3/top/x300/sim/dram_fifo_bist/dram_fifo_bist_tb.sv @@ -0,0 +1,349 @@ +// +// Copyright 2015 Ettus Research LLC +// + + +`timescale 1ns/1ps +`define SIM_RUNTIME_US 3000 +`define NS_PER_TICK 1 +`define NUM_TEST_CASES 25 + +`include "sim_clks_rsts.vh" +`include "sim_exec_report.vh" +`include "sim_cvita_lib.svh" +`include "sim_axi4_lib.svh" +`include "sim_set_rb_lib.svh" + +//`define USE_SRAM_FIFO //Use an AXI-Stream SRAM FIFO (for testing) +`define USE_SRAM_MIG 1 //Use the DMA engine from the DRAM FIFO but SRAM as the base memory +`define USE_BD_INTERCON 1 //Use the Block Design Axi Interconnect + + +module dram_fifo_bist_tb(); + `TEST_BENCH_INIT("dram_fifo_bist_tb",`NUM_TEST_CASES,`NS_PER_TICK) + + // Define all clocks and resets + `DEFINE_CLK(sys_clk, 10, 50) //100MHz sys_clk to generate DDR3 clocking + `DEFINE_CLK(bus_clk, 1000/166.6667, 50) //166MHz bus_clk + `DEFINE_RESET(bus_rst, 0, 100) //100ns for GSR to deassert + `DEFINE_RESET(sys_rst, 0, 100) //100ns for GSR to deassert + + // Initialize DUT + wire calib_complete; + wire running, done; + wire [1:0] error; + wire [31:0] rb_data; + reg [63:0] forced_bit_err; + + settings_bus_master #(.SR_AWIDTH(8),.SR_DWIDTH(32)) tst_set (.clk(bus_clk)); + cvita_master cvita_fifo_in (.clk(bus_clk)); + cvita_slave cvita_fifo_out (.clk(bus_clk)); + + // AXI DRAM FIFO Topology (Inline production BIST for DRAM FIFO): + // + // User Data ====> |---------| |---------------| |-----------| ====> User Data Out + // | AXI MUX | ====> | AXI DRAM FIFO | ====> | AXI DEMUX | + // BIST Data ====> |---------| |---------------| |-----------| ====> BIST Data Out + // || + // |--------------| + // | MIG (D/S)RAM | + // |--------------| + + localparam SR_FIFO_BASE = 0; + localparam SR_BIST_BASE = SR_FIFO_BASE + 4; + + axis_dram_fifo_single #( + .USE_SRAM_MEMORY(`USE_SRAM_MIG), + .USE_BD_INTERCON(`USE_BD_INTERCON), + .SR_BASE(SR_FIFO_BASE) + ) dut_single ( + .bus_clk(bus_clk), + .bus_rst(bus_rst), + .sys_clk(sys_clk), + .sys_rst(sys_rst), + + .i_tdata(cvita_fifo_in.axis.tdata), + .i_tlast(cvita_fifo_in.axis.tlast), + .i_tvalid(cvita_fifo_in.axis.tvalid), + .i_tready(cvita_fifo_in.axis.tready), + + .o_tdata(cvita_fifo_out.axis.tdata), + .o_tlast(cvita_fifo_out.axis.tlast), + .o_tvalid(cvita_fifo_out.axis.tvalid), + .o_tready(cvita_fifo_out.axis.tready), + + .set_stb(tst_set.settings_bus.set_stb), + .set_addr(tst_set.settings_bus.set_addr), + .set_data(tst_set.settings_bus.set_data), + .rb_data(rb_data), + + .forced_bit_err(forced_bit_err), + .init_calib_complete(calib_complete) + ); + + assign {error, done, running} = rb_data[3:0]; + + //Testbench variables + cvita_hdr_t header; + cvita_pkt_t pkt_out; + integer i; + integer single_run_time; + integer xfer_cnt, cyc_cnt; + + //------------------------------------------ + //Main thread for testbench execution + //------------------------------------------ + initial begin : tb_main + string s; + + `TEST_CASE_START("Wait for reset"); + while (bus_rst) @(posedge bus_clk); + while (sys_rst) @(posedge sys_clk); + `TEST_CASE_DONE(~bus_rst & ~sys_rst); + + forced_bit_err <= 64'h0; + repeat (200) @(posedge sys_clk); + + `TEST_CASE_START("Wait for initial calibration to complete"); + while (calib_complete !== 1'b1) @(posedge bus_clk); + `TEST_CASE_DONE(calib_complete); + + `TEST_CASE_START("Clear FIFO"); + tst_set.write(SR_FIFO_BASE + 1, {16'h0, 12'd280, 2'b00, 1'b0, 1'b1}); + repeat (200) @(posedge bus_clk); + tst_set.write(SR_FIFO_BASE + 1, {16'h0, 12'd280, 2'b00, 1'b0, 1'b0}); + repeat (200) @(posedge bus_clk); + `TEST_CASE_DONE(1); + + //Select BIST status as the readback output + tst_set.write(SR_FIFO_BASE + 0, 3'd1); + + header = '{ + pkt_type:DATA, has_time:0, eob:0, seqnum:12'h666, + length:0, src_sid:$random, dst_sid:$random, timestamp:64'h0}; + + `TEST_CASE_START("Fill up empty FIFO then drain (long packet)"); + cvita_fifo_in.push_ramp_pkt(100, 64'd0, 64'h100, header); + cvita_fifo_out.pull_pkt(pkt_out); + $sformat(s, "Bad packet: Length mismatch. Expected: %0d, Actual: %0d",100,pkt_out.payload.size()); + `ASSERT_ERROR(pkt_out.payload.size()==100, s); + $sformat(s, "Bad packet: Wrong SID. Expected: %08x, Actual: %08x", + {header.src_sid,header.dst_sid},{pkt_out.hdr.src_sid,pkt_out.hdr.dst_sid}); + `ASSERT_ERROR({header.src_sid,header.dst_sid}=={pkt_out.hdr.src_sid,pkt_out.hdr.dst_sid}, s); + i = 0; + repeat (100) begin + $sformat(s, "Bad packet: Wrong payload. Index: %d, Expected: %08x, Actual: %08x", + i,(i * 64'h100),pkt_out.payload[i]); + `ASSERT_ERROR(pkt_out.payload[i]==(i * 64'h100), s); + end + `TEST_CASE_DONE(1); + + `TEST_CASE_START("Setup BIST: 10 x 40byte packets"); + tst_set.write(SR_BIST_BASE + 0, {2'd0, 2'd0, 1'b0, 1'b0}); + tst_set.write(SR_BIST_BASE + 3, 32'h01234567); + tst_set.write(SR_BIST_BASE + 2, {8'd0, 16'd0}); + tst_set.write(SR_BIST_BASE + 1, {1'b0, 13'd40, 18'd10}); + `TEST_CASE_DONE(~done & ~running); + + `TEST_CASE_START("Run BIST"); + tst_set.write(SR_BIST_BASE + 0, {2'd3, 2'd0, 1'b0, 1'b1}); + while (~done) @(posedge bus_clk); + `ASSERT_ERROR(error==2'b00, "BIST failed!"); + @(posedge bus_clk); + `TEST_CASE_DONE(done & ~running); + + `TEST_CASE_START("Run BIST ... again (should fail)"); + forced_bit_err <= 64'h8000000000000000; + tst_set.write(SR_BIST_BASE + 0, {2'd0, 2'd0, 1'b0, 1'b0}); + tst_set.write(SR_BIST_BASE + 0, {2'd0, 2'd0, 1'b0, 1'b1}); + while (~done) @(posedge bus_clk); + `ASSERT_ERROR(error==2'b01, "BIST passed when it should have failed!"); + forced_bit_err <= 64'h0; + @(posedge bus_clk); + `TEST_CASE_DONE(done & ~running); + + `TEST_CASE_START("Run BIST ... and again (should pass)"); + tst_set.write(SR_BIST_BASE + 0, {2'd0, 2'd0, 1'b0, 1'b0}); + tst_set.write(SR_BIST_BASE + 0, {2'd2, 2'd0, 1'b0, 1'b1}); + while (~done) @(posedge bus_clk); + `ASSERT_ERROR(error==2'b00, "BIST failed!"); + @(posedge bus_clk); + `TEST_CASE_DONE(done & ~running); + + `TEST_CASE_START("Setup BIST: 8000 x 40byte ramping packets"); + tst_set.write(SR_BIST_BASE + 0, {2'd0, 2'd0, 1'b0, 1'b0}); + tst_set.write(SR_BIST_BASE + 3, 32'h01234567); + tst_set.write(SR_BIST_BASE + 2, {8'd0, 16'd0}); + tst_set.write(SR_BIST_BASE + 1, {1'b1, 13'd40, 18'd8000}); + `TEST_CASE_DONE(~done & ~running); + + `TEST_CASE_START("Run BIST"); + tst_set.write(SR_BIST_BASE + 0, {2'd3, 2'd0, 1'b0, 1'b1}); + while (~done) @(posedge bus_clk); + `ASSERT_ERROR(error==2'b00, "BIST failed!"); + @(posedge bus_clk); + `TEST_CASE_DONE(done & ~running); + + `TEST_CASE_START("Setup BIST: 256 x 1000byte packets"); + tst_set.write(SR_BIST_BASE + 0, {2'd0, 2'd0, 1'b0, 1'b0}); + tst_set.write(SR_BIST_BASE + 3, 32'h0ABCDEF0); + tst_set.write(SR_BIST_BASE + 2, {8'd4, 16'd256}); + tst_set.write(SR_BIST_BASE + 1, {1'b0, 13'd1000, 18'd256}); + `TEST_CASE_DONE(~done & ~running); + + `TEST_CASE_START("Run BIST"); + tst_set.write(SR_BIST_BASE + 0, {2'd1, 2'd0, 1'b0, 1'b1}); + while (~done) @(negedge bus_clk); + `ASSERT_ERROR(error==2'b00, "BIST failed!"); + @(posedge bus_clk); + `TEST_CASE_DONE(done & ~running); + + `TEST_CASE_START("User Data: Concurrent read and write"); + cvita_fifo_out.axis.tready = 1; + fork + begin + cvita_fifo_in.push_ramp_pkt(20, 64'd0, 64'h100, header); + end + begin + cvita_fifo_out.pull_pkt(pkt_out); + end + join + $sformat(s, "Bad packet: Length mismatch. Expected: %0d, Actual: %0d",20,pkt_out.payload.size()); + `ASSERT_ERROR(pkt_out.payload.size()==20, s); + `TEST_CASE_DONE(1); + + `TEST_CASE_START("Setup BIST: 256 x 600byte ramping packets"); + tst_set.write(SR_BIST_BASE + 0, {2'd0, 2'd0, 1'b0, 1'b0}); + tst_set.write(SR_BIST_BASE + 3, 32'h01234567); + tst_set.write(SR_BIST_BASE + 2, {8'd0, 16'd0}); + tst_set.write(SR_BIST_BASE + 1, {1'b1, 13'd600, 18'd256}); + `TEST_CASE_DONE(~done & ~running); + + `TEST_CASE_START("Run BIST"); + tst_set.write(SR_BIST_BASE + 0, {2'd0, 2'd0, 1'b0, 1'b1}); + while (~done) @(posedge bus_clk); + `ASSERT_ERROR(error==2'b00, "BIST failed!"); + @(posedge bus_clk); + `TEST_CASE_DONE(done & ~running); + + `TEST_CASE_START("Setup BIST: 30 x 8000byte packets"); + tst_set.write(SR_BIST_BASE + 0, {2'd0, 2'd0, 1'b0, 1'b0}); + tst_set.write(SR_BIST_BASE + 3, 32'h0ABCDEF0); + tst_set.write(SR_BIST_BASE + 2, {8'd0, 16'd0}); + tst_set.write(SR_BIST_BASE + 1, {1'b0, 13'd8000, 18'd30}); + `TEST_CASE_DONE(~done & ~running); + + `TEST_CASE_START("Run BIST"); + tst_set.write(SR_BIST_BASE + 0, {2'd1, 2'd0, 1'b0, 1'b1}); + while (~done) @(negedge bus_clk); + `ASSERT_ERROR(error==2'b00, "BIST failed!"); + @(posedge bus_clk); + `TEST_CASE_DONE(done & ~running); + + `TEST_CASE_START("Setup BIST: 100 x 8000byte ramping packets"); + tst_set.write(SR_BIST_BASE + 0, {2'd0, 2'd0, 1'b0, 1'b0}); + tst_set.write(SR_BIST_BASE + 3, 32'h0ABCDEF0); + tst_set.write(SR_BIST_BASE + 2, {8'd0, 16'd0}); + tst_set.write(SR_BIST_BASE + 1, {1'b1, 13'd8000, 18'd100}); + `TEST_CASE_DONE(~done & ~running); + + `TEST_CASE_START("Run BIST"); + tst_set.write(SR_BIST_BASE + 0, {2'd1, 2'd0, 1'b0, 1'b1}); + while (~done) @(negedge bus_clk); + `ASSERT_ERROR(error==2'b00, "BIST failed!"); + @(posedge bus_clk); + `TEST_CASE_DONE(done & ~running); + + `TEST_CASE_START("Validate Throughput"); + tst_set.write(SR_FIFO_BASE + 0, 3'd2); + xfer_cnt = rb_data; + tst_set.write(SR_FIFO_BASE + 0, 3'd3); + cyc_cnt = rb_data; + `ASSERT_ERROR(xfer_cnt>0, "Transfer count was not >0"); + `ASSERT_ERROR(cyc_cnt>0, "Cycle count was not >0"); + $display("Measured Throughput = %0d%% of bus_clk throughput", ((xfer_cnt*100)/cyc_cnt)); + `ASSERT_ERROR(((xfer_cnt*100)/cyc_cnt)>80, "Throughput was less than 80%%"); + tst_set.write(SR_FIFO_BASE + 0, 3'd1); //Restore + `TEST_CASE_DONE(done & ~running); + + `TEST_CASE_START("Setup BIST: 10 x 256byte packets"); + tst_set.write(SR_BIST_BASE + 0, {2'd0, 2'd0, 1'b0, 1'b0}); + tst_set.write(SR_BIST_BASE + 3, 32'hFFFFFFFF); + tst_set.write(SR_BIST_BASE + 2, {8'd0, 16'd0}); + tst_set.write(SR_BIST_BASE + 1, {1'b0, 13'd256, 18'd30}); + `TEST_CASE_DONE(~done & ~running); + + fork + begin + integer curr_time = $time; + `TEST_CASE_START("Run BIST Continuous (Early interrupt)"); + tst_set.write(SR_BIST_BASE + 0, {2'd0, 2'd0, 1'b0, 1'b0}); + tst_set.write(SR_BIST_BASE + 0, {2'd2, 2'd0, 1'b1, 1'b1}); + while (~done) @(negedge bus_clk); + `ASSERT_ERROR(error==2'b00, "BIST failed!"); + @(posedge bus_clk); + single_run_time = $time - curr_time; + `TEST_CASE_DONE(done & ~running); + end + begin + //Wait then clear + #2000; + tst_set.write(SR_BIST_BASE + 0, {2'd0, 2'd0, 1'b0, 1'b0}); + end + join + + fork + begin + `TEST_CASE_START("Run BIST Continuous (Force error)"); + tst_set.write(SR_BIST_BASE + 0, {2'd0, 2'd0, 1'b0, 1'b0}); + tst_set.write(SR_BIST_BASE + 0, {2'd2, 2'd0, 1'b1, 1'b1}); + while (~done) @(negedge bus_clk); + `ASSERT_ERROR(error==2'b01, "BIST passed when it should have failed!"); + @(posedge bus_clk); + `TEST_CASE_DONE(done & ~running); + end + begin + //Wait then force error + #10000; + forced_bit_err <= 64'h1; + end + join + //Recover from failure + forced_bit_err <= 64'h0; + tst_set.write(SR_BIST_BASE + 0, {2'd0, 2'd0, 1'b0, 1'b0}); + repeat (2000) @(posedge bus_clk); + + fork + begin + integer curr_time = $time; + `TEST_CASE_START("Run BIST Continuous"); + tst_set.write(SR_BIST_BASE + 0, {2'd0, 2'd0, 1'b0, 1'b0}); + tst_set.write(SR_BIST_BASE + 0, {2'd2, 2'd0, 1'b1, 1'b1}); + while (~done) @(negedge bus_clk); + `ASSERT_ERROR(error==2'b00, "BIST failed!"); + @(posedge bus_clk); + `ASSERT_ERROR((($time - curr_time) > 2 * single_run_time), "Continuous test most likely stopped early!"); + `TEST_CASE_DONE(done & ~running); + end + begin + //Wait then clear + #100000; + tst_set.write(SR_BIST_BASE + 0, {2'd0, 2'd0, 1'b0, 1'b0}); + end + join + + `TEST_CASE_START("Validate Throughput"); + tst_set.write(SR_FIFO_BASE + 0, 3'd2); + xfer_cnt = rb_data; + tst_set.write(SR_FIFO_BASE + 0, 3'd3); + cyc_cnt = rb_data; + `ASSERT_ERROR(xfer_cnt>0, "Transfer count was not >0"); + `ASSERT_ERROR(cyc_cnt>0, "Cycle count was not >0"); + $display("Measured Throughput = %0d%% of bus_clk throughput", ((xfer_cnt*100)/cyc_cnt)); + `ASSERT_ERROR(((xfer_cnt*100)/cyc_cnt)>80, "Throughput was less than 80%%"); + tst_set.write(SR_FIFO_BASE + 0, 3'd1); //Restore + `TEST_CASE_DONE(done & ~running); + `TEST_BENCH_DONE; + + end +endmodule |