aboutsummaryrefslogtreecommitdiffstats
path: root/fpga/usrp3/top/x300/sim/dram_fifo_bist
diff options
context:
space:
mode:
Diffstat (limited to 'fpga/usrp3/top/x300/sim/dram_fifo_bist')
-rw-r--r--fpga/usrp3/top/x300/sim/dram_fifo_bist/Makefile72
-rw-r--r--fpga/usrp3/top/x300/sim/dram_fifo_bist/dram_fifo_bist_tb.sv349
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