diff options
Diffstat (limited to 'fpga/usrp3/top/x300/sim')
-rw-r--r-- | fpga/usrp3/top/x300/sim/aurora_loopback/Makefile | 77 | ||||
-rw-r--r-- | fpga/usrp3/top/x300/sim/aurora_loopback/aurora_loopback_tb.sv | 310 | ||||
-rw-r--r-- | fpga/usrp3/top/x300/sim/dram_fifo/Makefile | 72 | ||||
-rw-r--r-- | fpga/usrp3/top/x300/sim/dram_fifo/axis_dram_fifo_single.sv | 589 | ||||
-rw-r--r-- | fpga/usrp3/top/x300/sim/dram_fifo/dram_fifo_tb.sv | 184 | ||||
-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 | ||||
-rw-r--r-- | fpga/usrp3/top/x300/sim/x300_pcie_int/Makefile | 66 | ||||
-rw-r--r-- | fpga/usrp3/top/x300/sim/x300_pcie_int/x300_pcie_int_tb.sv | 596 |
9 files changed, 2315 insertions, 0 deletions
diff --git a/fpga/usrp3/top/x300/sim/aurora_loopback/Makefile b/fpga/usrp3/top/x300/sim/aurora_loopback/Makefile new file mode 100644 index 000000000..eb135ef4e --- /dev/null +++ b/fpga/usrp3/top/x300/sim/aurora_loopback/Makefile @@ -0,0 +1,77 @@ +# +# 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 +include $(BASE_DIR)/../lib/rfnoc/Makefile.srcs + +DESIGN_SRCS = $(abspath \ +$(FIFO_SRCS) \ +$(AXI_SRCS) \ +$(CONTROL_LIB_SRCS) \ +$(RFNOC_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)/aurora_64b66b_pcs_pma/Makefile.inc +include $(IP_DIR)/fifo_short_2clk/Makefile.inc +include $(IP_DIR)/axi64_4k_2clk_fifo/Makefile.inc + +DESIGN_SRCS += $(abspath \ +$(IP_AURORA_64B66B_PCS_PMA_SRCS) \ +$(IP_AXI64_4K_2CLK_FIFO_SRCS) \ +$(IP_FIFO_SHORT_2CLK_SRCS) \ +$(AURORA_PHY_SRCS) \ +) + +#------------------------------------------------- +# Testbench Specific +#------------------------------------------------- +include $(BASE_DIR)/../sim/general/Makefile.srcs +include $(BASE_DIR)/../sim/control/Makefile.srcs +include $(BASE_DIR)/../sim/axi/Makefile.srcs + +# Define only one toplevel module +SIM_TOP = aurora_loopback_tb +# Simulation runtime in microseconds +SIM_RUNTIME_US = 70 + +SIM_SRCS = \ +$(abspath aurora_loopback_tb.sv) \ +$(SIM_GENERAL_SRCS) \ +$(SIM_CONTROL_SRCS) \ +$(SIM_AXI_SRCS) + +#------------------------------------------------- +# 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/aurora_loopback/aurora_loopback_tb.sv b/fpga/usrp3/top/x300/sim/aurora_loopback/aurora_loopback_tb.sv new file mode 100644 index 000000000..75c07dd09 --- /dev/null +++ b/fpga/usrp3/top/x300/sim/aurora_loopback/aurora_loopback_tb.sv @@ -0,0 +1,310 @@ +// +// Copyright 2016 Ettus Research LLC +// + + +`timescale 1ns/1ps +`define NS_PER_TICK 1 +`define NUM_TEST_CASES 13 + +`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" + +module aurora_loopback_tb(); + `TEST_BENCH_INIT("aurora_loopback_tb",`NUM_TEST_CASES,`NS_PER_TICK) + + // Define all clocks and resets + `DEFINE_CLK(XG_CLK_P, 1000/156.25, 50) //156.25MHz GT transceiver clock + `DEFINE_RESET(GSR, 0, 100) //100ns for GSR to deassert + + wire XG_CLK_N = ~XG_CLK_P; + wire SFP_LN0_P, SFP_LN0_N, SFP_LN1_P, SFP_LN1_N; + + localparam PACKET_MODE = 1; + + // Aurora Loopback Topology: + // + // TB Simulus ====> |------------| |----------------| + // | Aurora MAC | <===> | Aurora PCS/PMA | <====>|| + // TB Checker <==== |------------| |----------------| || Loopback through + // || + // ====> |------------| |----------------| || perfect serial channel + // Loopback | | Aurora MAC | <===> | Aurora PCS/PMA | <====>|| + // <==== |------------| |----------------| + + // Initialize DUT + wire aurora_refclk, aurora_init_clk; + wire m_user_clk, s_user_clk; + wire m_user_rst, s_user_rst; + wire m_channel_up, s_channel_up; + wire m_hard_err, s_hard_err; + wire m_soft_err, s_soft_err; + + aurora_phy_clk_gen aurora_clk_gen_i ( + .areset(GSR), + .refclk_p(XG_CLK_P), + .refclk_n(XG_CLK_N), + .refclk(aurora_refclk), + .clk156(), + .init_clk(aurora_init_clk) + ); + + wire [63:0] m_i_tdata, m_o_tdata; + wire m_i_tvalid, m_i_tready, m_o_tvalid; + wire [63:0] s_i_tdata, s_o_tdata; + wire s_i_tvalid, s_i_tready, s_o_tvalid; + wire [63:0] loop_tdata; + wire loop_tlast, loop_tvalid, loop_tready; + wire [31:0] m_overruns, s_overruns; + wire [31:0] m_soft_errors, s_soft_errors; + reg m_bist_gen, m_bist_check, s_bist_loopback; + reg [5:0] m_bist_rate; + wire m_bist_locked; + wire [47:0] m_bist_samps, m_bist_errors; + + + cvita_master m_tx_chdr (.clk(m_user_clk)); + cvita_slave m_rx_chdr (.clk(s_user_clk)); + + aurora_phy_x1 #(.SIMULATION(1)) aurora_phy_master_i ( + // Resets + .areset(GSR), + // Clocks + .refclk(aurora_refclk), + .user_clk(m_user_clk), + .init_clk(aurora_init_clk), + .user_rst(m_user_rst), + // GTX Serial I/O + .tx_p(SFP_LN0_P), .tx_n(SFP_LN0_N), + .rx_p(SFP_LN1_P), .rx_n(SFP_LN1_N), + // AXI4-Stream TX Interface + .s_axis_tdata(m_i_tdata), .s_axis_tvalid(m_i_tvalid), .s_axis_tready(m_i_tready), + // AXI4-Stream RX Interface + .m_axis_tdata(m_o_tdata), .m_axis_tvalid(m_o_tvalid), + // AXI4-Lite Config Interface + .s_axi_awaddr(32'h0), .s_axi_araddr(32'h0), .s_axi_awvalid(1'b0), .s_axi_awready(), + .s_axi_wdata(32'h0), .s_axi_wvalid(1'b0), .s_axi_wstrb(1'b0), .s_axi_wready(), + .s_axi_bvalid(), .s_axi_bresp(), .s_axi_bready(1'b1), + .s_axi_arready(), .s_axi_arvalid(1'b0), + .s_axi_rdata(), .s_axi_rvalid(), .s_axi_rresp(), .s_axi_rready(1'b1), + // Status and Error Reporting Interface + .channel_up(m_channel_up), .hard_err(m_hard_err), .soft_err(m_soft_err) + ); + + aurora_axis_mac #(.PACKET_MODE(PACKET_MODE), .BIST_ENABLED(1)) aurora_mac_master_i ( + // Clocks and resets + .phy_clk(m_user_clk), .phy_rst(m_user_rst), + .sys_clk(m_user_clk), .sys_rst(m_user_rst), + .clear(1'b0), + // PHY Interface + .phy_s_axis_tdata(m_o_tdata), .phy_s_axis_tvalid(m_o_tvalid), + .phy_m_axis_tdata(m_i_tdata), .phy_m_axis_tvalid(m_i_tvalid), .phy_m_axis_tready(m_i_tready), + // User Interface + .s_axis_tdata(m_tx_chdr.axis.tdata), .s_axis_tlast(m_tx_chdr.axis.tlast), + .s_axis_tvalid(m_tx_chdr.axis.tvalid), .s_axis_tready(m_tx_chdr.axis.tready), + .m_axis_tdata(m_rx_chdr.axis.tdata), .m_axis_tlast(m_rx_chdr.axis.tlast), + .m_axis_tvalid(m_rx_chdr.axis.tvalid), .m_axis_tready(m_rx_chdr.axis.tready), + // Misc PHY + .channel_up(m_channel_up), .hard_err(m_hard_err), .soft_err(m_soft_err), + .overruns(m_overruns), .soft_errors(m_soft_errors), + //BIST + .bist_gen_en(m_bist_gen), .bist_checker_en(m_bist_check), .bist_loopback_en(1'b0), .bist_gen_rate(m_bist_rate), + .bist_checker_locked(m_bist_locked), .bist_checker_samps(m_bist_samps), .bist_checker_errors(m_bist_errors) + ); + + aurora_phy_x1 #(.SIMULATION(1)) aurora_phy_slave_i ( + // Resets + .areset(GSR), + // Clocks + .refclk(aurora_refclk), + .user_clk(s_user_clk), + .init_clk(aurora_init_clk), + .user_rst(s_user_rst), + // GTX Serial I/O + .tx_p(SFP_LN1_P), .tx_n(SFP_LN1_N), + .rx_p(SFP_LN0_P), .rx_n(SFP_LN0_N), + // AXI4-Stream TX Interface + .s_axis_tdata(s_i_tdata), .s_axis_tvalid(s_i_tvalid), .s_axis_tready(s_i_tready), + // AXI4-Stream RX Interface + .m_axis_tdata(s_o_tdata), .m_axis_tvalid(s_o_tvalid), + // AXI4-Lite Config Interface + // AXI4-Lite Config Interface + .s_axi_awaddr(32'h0), .s_axi_araddr(32'h0), .s_axi_awvalid(1'b0), .s_axi_awready(), + .s_axi_wdata(32'h0), .s_axi_wvalid(1'b0), .s_axi_wstrb(1'b0), .s_axi_wready(), + .s_axi_bvalid(), .s_axi_bresp(), .s_axi_bready(1'b1), + .s_axi_arready(), .s_axi_arvalid(1'b0), + .s_axi_rdata(), .s_axi_rvalid(), .s_axi_rresp(), .s_axi_rready(1'b1), + // Status and Error Reporting Interface + .channel_up(s_channel_up), .hard_err(s_hard_err), .soft_err(s_soft_err) + ); + + aurora_axis_mac #(.PACKET_MODE(PACKET_MODE), .BIST_ENABLED(1)) aurora_mac_slave_i ( + // Clocks and resets + .phy_clk(s_user_clk), .phy_rst(s_user_rst), + .sys_clk(s_user_clk), .sys_rst(s_user_rst), + .clear(1'b0), + // PHY Interface + .phy_s_axis_tdata(s_o_tdata), .phy_s_axis_tvalid(s_o_tvalid), + .phy_m_axis_tdata(s_i_tdata), .phy_m_axis_tvalid(s_i_tvalid), .phy_m_axis_tready(s_i_tready), + // User Interface + .s_axis_tdata(loop_tdata), .s_axis_tlast(loop_tlast), + .s_axis_tvalid(~s_bist_loopback & loop_tvalid), .s_axis_tready(loop_tready), + .m_axis_tdata(loop_tdata), .m_axis_tlast(loop_tlast), + .m_axis_tvalid(loop_tvalid), .m_axis_tready(~s_bist_loopback & loop_tready), + // Misc PHY + .channel_up(s_channel_up), .hard_err(s_hard_err), .soft_err(s_soft_err), + .overruns(s_overruns), .soft_errors(s_soft_errors), + //BIST + .bist_gen_en(1'b0), .bist_checker_en(1'b0), .bist_loopback_en(s_bist_loopback), .bist_gen_rate(6'd0), + .bist_checker_locked(), .bist_checker_samps(), .bist_checker_errors() + ); + + //Testbench variables + cvita_hdr_t header, header_out; + cvita_stats_t stats; + logic [63:0] crc_cache; + + //------------------------------------------ + //Main thread for testbench execution + //------------------------------------------ + initial begin : tb_main + string s; + `TEST_CASE_START("Wait for reset"); + while (GSR) @(posedge XG_CLK_P); + `TEST_CASE_DONE((~GSR)); + + m_bist_gen <= 1'b0; + m_bist_rate <= 6'd0; + m_bist_check <= 1'b0; + s_bist_loopback <= 1'b0; + + m_tx_chdr.push_bubble(); + + `TEST_CASE_START("Wait for master channel to come up"); + while (m_channel_up !== 1'b1) @(posedge m_user_clk); + `TEST_CASE_DONE(1'b1); + + `TEST_CASE_START("Wait for slave channel to come up"); + while (s_channel_up !== 1'b1) @(posedge s_user_clk); + `TEST_CASE_DONE(1'b1); + + `TEST_CASE_START("Run PRBS BIST"); + s_bist_loopback <= PACKET_MODE; + @(posedge m_user_clk); + m_bist_rate <= 6'd60; + m_bist_gen <= 1'b1; + m_bist_check <= 1'b1; + @(posedge m_user_clk); + while (m_bist_locked !== 1'b1) @(posedge m_user_clk); + repeat (512) @(posedge m_user_clk); + `ASSERT_ERROR(m_bist_samps>256, "BIST: Num samples incorrect"); + `ASSERT_ERROR(m_bist_errors===36'd0, "BIST: Errors!"); + @(posedge m_user_clk); + m_bist_gen <= 1'b0; + repeat (256) @(posedge m_user_clk); + m_bist_check <= 1'b0; + `TEST_CASE_DONE(1'b1); + + 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 (short packet)"); + m_rx_chdr.axis.tready = 0; + m_tx_chdr.push_ramp_pkt(16, 64'd0, 64'h100, header); + m_rx_chdr.axis.tready = 1; + m_rx_chdr.wait_for_pkt_get_info(header_out, stats); + `ASSERT_ERROR(stats.count==16, "Bad packet: Length mismatch"); + $sformat(s, "Bad packet: Wrong SID. Expected: %08x, Actual: %08x", + {header.src_sid,header.dst_sid},{header_out.src_sid,header_out.dst_sid}); + `ASSERT_ERROR({header.src_sid,header.dst_sid}=={header_out.src_sid,header_out.dst_sid}, s); + `TEST_CASE_DONE(1); + + `TEST_CASE_START("Fill up empty FIFO then drain (long packet)"); + m_rx_chdr.axis.tready = 0; + m_tx_chdr.push_ramp_pkt(256, 64'd0, 64'h100, header); + m_rx_chdr.axis.tready = 1; + m_rx_chdr.wait_for_pkt_get_info(header_out, stats); + `ASSERT_ERROR(stats.count==256, "Bad packet: Length mismatch"); + $sformat(s, "Bad packet: Wrong SID. Expected: %08x, Actual: %08x", + {header.src_sid,header.dst_sid},{header_out.src_sid,header_out.dst_sid}); + `ASSERT_ERROR({header.src_sid,header.dst_sid}=={header_out.src_sid,header_out.dst_sid}, s); + `TEST_CASE_DONE(1); + + header = '{ + pkt_type:DATA, has_time:1, eob:0, seqnum:12'h666, + length:0, src_sid:$random, dst_sid:$random, timestamp:64'h0}; + + `TEST_CASE_START("Concurrent read and write (single packet)"); + repeat (10) @(posedge m_user_clk); //Wait for clear to go low + m_rx_chdr.axis.tready = 1; + fork + begin + m_tx_chdr.push_ramp_pkt(200, 64'd0, 64'h100, header); + end + begin + m_rx_chdr.wait_for_pkt_get_info(header_out, stats); + end + join + crc_cache = stats.crc; //Cache CRC for future test cases + `ASSERT_ERROR(stats.count==200, "Bad packet: Length mismatch"); + `TEST_CASE_DONE(1); + + `TEST_CASE_START("Concurrent read and write (multiple packets)"); + m_rx_chdr.axis.tready = 1; + fork + begin + repeat (20) begin + m_tx_chdr.push_ramp_pkt(20, 64'd0, 64'h100, header); + m_tx_chdr.push_bubble(); + end + end + begin + repeat (20) begin + m_rx_chdr.wait_for_pkt_get_info(header_out, stats); + `ASSERT_ERROR(stats.count==20, "Bad packet: Length mismatch"); + `ASSERT_ERROR(crc_cache==stats.crc, "Bad packet: Wrong CRC"); + end + end + join + `TEST_CASE_DONE(1); + + `TEST_CASE_START("Validate no drops (master)"); + `TEST_CASE_DONE((m_overruns === 32'd0)); + + `TEST_CASE_START("Validate no drops (slave)"); + `TEST_CASE_DONE((s_overruns === 32'd0)); + + s_bist_loopback <= 1'b1; + + `TEST_CASE_START("Run PRBS BIST (Loopback Mode)"); + @(posedge m_user_clk); + m_bist_gen <= 1'b1; + m_bist_rate <= 6'd60; + m_bist_check <= 1'b1; + @(posedge m_user_clk); + while (m_bist_locked !== 1'b1) @(posedge m_user_clk); + repeat (512) @(posedge m_user_clk); + `ASSERT_ERROR(m_bist_samps>256, "BIST: Num samples incorrect"); + `ASSERT_ERROR(m_bist_errors===36'd0, "BIST: Errors!"); + @(posedge m_user_clk); + m_bist_gen <= 1'b0; + repeat (256) @(posedge m_user_clk); + m_bist_check <= 1'b0; + `TEST_CASE_DONE(1'b1); + + s_bist_loopback <= 1'b0; + + `TEST_CASE_START("Validate no drops (master)"); + `TEST_CASE_DONE((m_overruns === 32'd0)); + + `TEST_CASE_START("Validate no drops (slave)"); + `TEST_CASE_DONE((s_overruns === 32'd0)); + + `TEST_BENCH_DONE; + end + +endmodule diff --git a/fpga/usrp3/top/x300/sim/dram_fifo/Makefile b/fpga/usrp3/top/x300/sim/dram_fifo/Makefile new file mode 100644 index 000000000..8cc56331c --- /dev/null +++ b/fpga/usrp3/top/x300/sim/dram_fifo/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_tb + +SIM_SRCS = \ +$(abspath dram_fifo_tb.sv) \ +$(abspath 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/axis_dram_fifo_single.sv b/fpga/usrp3/top/x300/sim/dram_fifo/axis_dram_fifo_single.sv new file mode 100644 index 000000000..d4aae6dd0 --- /dev/null +++ b/fpga/usrp3/top/x300/sim/dram_fifo/axis_dram_fifo_single.sv @@ -0,0 +1,589 @@ +// +// Copyright 2015 Ettus Research LLC +// + +`timescale 1ns/1ps + +module axis_dram_fifo_single +#( + parameter USE_SRAM_MEMORY = 0, + parameter USE_BD_INTERCON = 0, + parameter SR_BASE = 0 +) ( + input bus_clk, + input bus_rst, + input sys_clk, + input sys_rst, + + input [63:0] i_tdata, + input i_tlast, + input i_tvalid, + output i_tready, + + output [63:0] o_tdata, + output o_tlast, + output o_tvalid, + input o_tready, + + input set_stb, + input [7:0] set_addr, + input [31:0] set_data, + output [31:0] rb_data, + + input [63:0] forced_bit_err, + + output init_calib_complete +); + + // Misc declarations + axi4_rd_t #(.DWIDTH(64), .AWIDTH(32), .IDWIDTH(1)) dma_axi_rd(.clk(sys_clk)); + axi4_wr_t #(.DWIDTH(64), .AWIDTH(32), .IDWIDTH(1)) dma_axi_wr(.clk(sys_clk)); + axi4_rd_t #(.DWIDTH(256), .AWIDTH(32), .IDWIDTH(1)) mig_axi_rd(.clk(sys_clk)); + axi4_wr_t #(.DWIDTH(256), .AWIDTH(32), .IDWIDTH(1)) mig_axi_wr(.clk(sys_clk)); + + wire [31:0] ddr3_dq; // Data pins. Input for Reads; Output for Writes. + wire [3:0] ddr3_dqs_n; // Data Strobes. Input for Reads; Output for Writes. + wire [3:0] ddr3_dqs_p; + wire [14:0] ddr3_addr; // Address + wire [2:0] ddr3_ba; // Bank Address + wire ddr3_ras_n; // Row Address Strobe. + wire ddr3_cas_n; // Column address select + wire ddr3_we_n; // Write Enable + wire ddr3_reset_n; // SDRAM reset pin. + wire [0:0] ddr3_ck_p; // Differential clock + wire [0:0] ddr3_ck_n; + wire [0:0] ddr3_cke; // Clock Enable + wire [0:0] ddr3_cs_n; // Chip Select + wire [3:0] ddr3_dm; // Data Mask [3] = UDM.U26; [2] = LDM.U26; ... + wire [0:0] ddr3_odt; // On-Die termination enable. + + wire ddr3_axi_clk; // 1/4 DDR external clock rate (250MHz) + wire ddr3_axi_rst; // Synchronized to ddr_sys_clk + reg ddr3_axi_rst_reg_n; // Synchronized to ddr_sys_clk + wire ddr3_axi_clk_x2; + + always @(posedge ddr3_axi_clk) + ddr3_axi_rst_reg_n <= ~ddr3_axi_rst; + + axi_dma_fifo #( + .DEFAULT_BASE(30'h00010000), + .DEFAULT_MASK(30'hFFFF0000), + .DEFAULT_TIMEOUT(280), + .SR_BASE(SR_BASE), + .EXT_BIST(1), + .SIMULATION(1) + ) axi_dma_fifo_i0 ( + // + // Clocks and reset + .bus_clk (bus_clk), + .bus_reset (bus_rst), + .dram_clk (ddr3_axi_clk_x2), + .dram_reset (ddr3_axi_rst), + // + // AXI Write address channel + .m_axi_awid (dma_axi_wr.addr.id), + .m_axi_awaddr (dma_axi_wr.addr.addr), + .m_axi_awlen (dma_axi_wr.addr.len), + .m_axi_awsize (dma_axi_wr.addr.size), + .m_axi_awburst (dma_axi_wr.addr.burst), + .m_axi_awlock (dma_axi_wr.addr.lock), + .m_axi_awcache (dma_axi_wr.addr.cache), + .m_axi_awprot (dma_axi_wr.addr.prot), + .m_axi_awqos (dma_axi_wr.addr.qos), + .m_axi_awregion (dma_axi_wr.addr.region), + .m_axi_awuser (dma_axi_wr.addr.user), + .m_axi_awvalid (dma_axi_wr.addr.valid), + .m_axi_awready (dma_axi_wr.addr.ready), + // + // AXI Write data channel. + .m_axi_wdata (dma_axi_wr.data.data), + .m_axi_wstrb (dma_axi_wr.data.strb), + .m_axi_wlast (dma_axi_wr.data.last), + .m_axi_wuser (dma_axi_wr.data.user), + .m_axi_wvalid (dma_axi_wr.data.valid), + .m_axi_wready (dma_axi_wr.data.ready), + // + // AXI Write response channel signals + .m_axi_bid (dma_axi_wr.resp.id), + .m_axi_bresp (dma_axi_wr.resp.resp), + .m_axi_buser (dma_axi_wr.resp.user), + .m_axi_bvalid (dma_axi_wr.resp.valid), + .m_axi_bready (dma_axi_wr.resp.ready), + // + // AXI Read address channel + .m_axi_arid (dma_axi_rd.addr.id), + .m_axi_araddr (dma_axi_rd.addr.addr), + .m_axi_arlen (dma_axi_rd.addr.len), + .m_axi_arsize (dma_axi_rd.addr.size), + .m_axi_arburst (dma_axi_rd.addr.burst), + .m_axi_arlock (dma_axi_rd.addr.lock), + .m_axi_arcache (dma_axi_rd.addr.cache), + .m_axi_arprot (dma_axi_rd.addr.prot), + .m_axi_arqos (dma_axi_rd.addr.qos), + .m_axi_arregion (dma_axi_rd.addr.region), + .m_axi_aruser (dma_axi_rd.addr.user), + .m_axi_arvalid (dma_axi_rd.addr.valid), + .m_axi_arready (dma_axi_rd.addr.ready), + // + // AXI Read data channel + .m_axi_rid (dma_axi_rd.data.id), + .m_axi_rdata (dma_axi_rd.data.data), + .m_axi_rresp (dma_axi_rd.data.resp), + .m_axi_rlast (dma_axi_rd.data.last), + .m_axi_ruser (dma_axi_rd.data.user), + .m_axi_rvalid (dma_axi_rd.data.valid), + .m_axi_rready (dma_axi_rd.data.ready), + // + // CHDR friendly AXI stream input + .i_tdata (i_tdata), + .i_tlast (i_tlast), + .i_tvalid (i_tvalid), + .i_tready (i_tready), + // + // CHDR friendly AXI Stream output + .o_tdata (o_tdata), + .o_tlast (o_tlast), + .o_tvalid (o_tvalid), + .o_tready (o_tready), + // + // Settings + .set_stb (set_stb), + .set_addr (set_addr), + .set_data (set_data), + .rb_data (rb_data), + + .debug() + ); + + generate if (USE_SRAM_MEMORY) begin + assign init_calib_complete = 1; + assign ddr3_axi_clk = bus_clk; + assign ddr3_axi_clk_x2 = bus_clk; + assign ddr3_axi_rst = bus_rst; + + axi4_dualport_sram axi4_dualport_sram_i1 ( + .s_aclk (ddr3_axi_clk_x2), // input s_aclk + .s_aresetn (~ddr3_axi_rst), // input s_aresetn + .s_axi_awid (dma_axi_wr.addr.id), // input [0 : 0] s_axi_awid + .s_axi_awaddr (dma_axi_wr.addr.addr), // input [31 : 0] s_axi_awaddr + .s_axi_awlen (dma_axi_wr.addr.len), // input [7 : 0] s_axi_awlen + .s_axi_awsize (dma_axi_wr.addr.size), // input [2 : 0] s_axi_awsize + .s_axi_awburst (dma_axi_wr.addr.burst), // input [1 : 0] s_axi_awburst + .s_axi_awvalid (dma_axi_wr.addr.valid), // input s_axi_awvalid + .s_axi_awready (dma_axi_wr.addr.ready), // output s_axi_awready + .s_axi_wdata (dma_axi_wr.data.data ^ forced_bit_err), // input [63 : 0] s_axi_wdata + .s_axi_wstrb (dma_axi_wr.data.strb), // input [7 : 0] s_axi_wstrb + .s_axi_wlast (dma_axi_wr.data.last), // input s_axi_wlast + .s_axi_wvalid (dma_axi_wr.data.valid), // input s_axi_wvalid + .s_axi_wready (dma_axi_wr.data.ready), // output s_axi_wready + .s_axi_bid (dma_axi_wr.resp.id), // output [0 : 0] s_axi_bid + .s_axi_bresp (dma_axi_wr.resp.resp), // output [1 : 0] s_axi_bresp + .s_axi_bvalid (dma_axi_wr.resp.valid), // output s_axi_bvalid + .s_axi_bready (dma_axi_wr.resp.ready), // input s_axi_bready + .s_axi_arid (dma_axi_rd.addr.id), // input [0 : 0] s_axi_arid + .s_axi_araddr (dma_axi_rd.addr.addr), // input [31 : 0] s_axi_araddr + .s_axi_arlen (dma_axi_rd.addr.len), // input [7 : 0] s_axi_arlen + .s_axi_arsize (dma_axi_rd.addr.size), // input [2 : 0] s_axi_arsize + .s_axi_arburst (dma_axi_rd.addr.burst), // input [1 : 0] s_axi_arburst + .s_axi_arvalid (dma_axi_rd.addr.valid), // input s_axi_arvalid + .s_axi_arready (dma_axi_rd.addr.ready), // output s_axi_arready + .s_axi_rid (dma_axi_rd.data.id), // output [0 : 0] s_axi_rid + .s_axi_rdata (dma_axi_rd.data.data), // output [63 : 0] s_axi_rdata + .s_axi_rresp (dma_axi_rd.data.resp), // output [1 : 0] s_axi_rresp + .s_axi_rlast (dma_axi_rd.data.last), // output s_axi_rlast + .s_axi_rvalid (dma_axi_rd.data.valid), // output s_axi_rvalid + .s_axi_rready (dma_axi_rd.data.ready) // input s_axi_rready + ); + + end else begin //generate if (USE_SRAM_MEMORY) begin + //--------------------------------------------------- + // We use an interconnect to connect to FIFOs. + //--------------------------------------------------- + if (USE_BD_INTERCON) begin + // Vivado Block Diagram interconnect. + axi_intercon_2x64_128_bd_wrapper axi_intercon_2x64_128_i ( + .S00_AXI_ACLK (ddr3_axi_clk_x2), // input S00_AXI_ACLK + .S00_AXI_ARESETN (~ddr3_axi_rst), // input S00_AXI_ARESETN + .S00_AXI_AWID (dma_axi_wr.addr.id), // input [0 : 0] S00_AXI_AWID + .S00_AXI_AWADDR (dma_axi_wr.addr.addr), // input [31 : 0] S00_AXI_AWADDR + .S00_AXI_AWLEN (dma_axi_wr.addr.len), // input [7 : 0] S00_AXI_AWLEN + .S00_AXI_AWSIZE (dma_axi_wr.addr.size), // input [2 : 0] S00_AXI_AWSIZE + .S00_AXI_AWBURST (dma_axi_wr.addr.burst), // input [1 : 0] S00_AXI_AWBURST + .S00_AXI_AWLOCK (dma_axi_wr.addr.lock), // input S00_AXI_AWLOCK + .S00_AXI_AWCACHE (dma_axi_wr.addr.cache), // input [3 : 0] S00_AXI_AWCACHE + .S00_AXI_AWPROT (dma_axi_wr.addr.prot), // input [2 : 0] S00_AXI_AWPROT + .S00_AXI_AWQOS (dma_axi_wr.addr.qos), // input [3 : 0] S00_AXI_AWQOS + .S00_AXI_AWVALID (dma_axi_wr.addr.valid), // input S00_AXI_AWVALID + .S00_AXI_AWREADY (dma_axi_wr.addr.ready), // output S00_AXI_AWREADY + .S00_AXI_WDATA (dma_axi_wr.data.data ^ forced_bit_err), // input [63 : 0] S00_AXI_WDATA + .S00_AXI_WSTRB (dma_axi_wr.data.strb), // input [7 : 0] S00_AXI_WSTRB + .S00_AXI_WLAST (dma_axi_wr.data.last), // input S00_AXI_WLAST + .S00_AXI_WVALID (dma_axi_wr.data.valid), // input S00_AXI_WVALID + .S00_AXI_WREADY (dma_axi_wr.data.ready), // output S00_AXI_WREADY + .S00_AXI_BID (dma_axi_wr.resp.id), // output [0 : 0] S00_AXI_BID + .S00_AXI_BRESP (dma_axi_wr.resp.resp), // output [1 : 0] S00_AXI_BRESP + .S00_AXI_BVALID (dma_axi_wr.resp.valid), // output S00_AXI_BVALID + .S00_AXI_BREADY (dma_axi_wr.resp.ready), // input S00_AXI_BREADY + .S00_AXI_ARID (dma_axi_rd.addr.id), // input [0 : 0] S00_AXI_ARID + .S00_AXI_ARADDR (dma_axi_rd.addr.addr), // input [31 : 0] S00_AXI_ARADDR + .S00_AXI_ARLEN (dma_axi_rd.addr.len), // input [7 : 0] S00_AXI_ARLEN + .S00_AXI_ARSIZE (dma_axi_rd.addr.size), // input [2 : 0] S00_AXI_ARSIZE + .S00_AXI_ARBURST (dma_axi_rd.addr.burst), // input [1 : 0] S00_AXI_ARBURST + .S00_AXI_ARLOCK (dma_axi_rd.addr.lock), // input S00_AXI_ARLOCK + .S00_AXI_ARCACHE (dma_axi_rd.addr.cache), // input [3 : 0] S00_AXI_ARCACHE + .S00_AXI_ARPROT (dma_axi_rd.addr.prot), // input [2 : 0] S00_AXI_ARPROT + .S00_AXI_ARQOS (dma_axi_rd.addr.qos), // input [3 : 0] S00_AXI_ARQOS + .S00_AXI_ARVALID (dma_axi_rd.addr.valid), // input S00_AXI_ARVALID + .S00_AXI_ARREADY (dma_axi_rd.addr.ready), // output S00_AXI_ARREADY + .S00_AXI_RID (dma_axi_rd.data.id), // output [0 : 0] S00_AXI_RID + .S00_AXI_RDATA (dma_axi_rd.data.data), // output [63 : 0] S00_AXI_RDATA + .S00_AXI_RRESP (dma_axi_rd.data.resp), // output [1 : 0] S00_AXI_RRESP + .S00_AXI_RLAST (dma_axi_rd.data.last), // output S00_AXI_RLAST + .S00_AXI_RVALID (dma_axi_rd.data.valid), // output S00_AXI_RVALID + .S00_AXI_RREADY (dma_axi_rd.data.ready), // input S00_AXI_RREADY + // + //.S01_AXI_ARESET_OUT_N (), // output S01_AXI_ARESET_OUT_N + .S01_AXI_ACLK (ddr3_axi_clk_x2), // input S01_AXI_ACLK + .S01_AXI_ARESETN (~ddr3_axi_rst), // input S01_AXI_ARESETN + .S01_AXI_AWID (0), // input [0 : 0] S01_AXI_AWID + .S01_AXI_AWADDR (0), // input [31 : 0] S01_AXI_AWADDR + .S01_AXI_AWLEN (0), // input [7 : 0] S01_AXI_AWLEN + .S01_AXI_AWSIZE (0), // input [2 : 0] S01_AXI_AWSIZE + .S01_AXI_AWBURST (0), // input [1 : 0] S01_AXI_AWBURST + .S01_AXI_AWLOCK (0), // input S01_AXI_AWLOCK + .S01_AXI_AWCACHE (0), // input [3 : 0] S01_AXI_AWCACHE + .S01_AXI_AWPROT (0), // input [2 : 0] S01_AXI_AWPROT + .S01_AXI_AWQOS (0), // input [3 : 0] S01_AXI_AWQOS + .S01_AXI_AWVALID (0), // input S01_AXI_AWVALID + .S01_AXI_AWREADY (), // output S01_AXI_AWREADY + .S01_AXI_WDATA (0), // input [63 : 0] S01_AXI_WDATA + .S01_AXI_WSTRB (0), // input [7 : 0] S01_AXI_WSTRB + .S01_AXI_WLAST (0), // input S01_AXI_WLAST + .S01_AXI_WVALID (0), // input S01_AXI_WVALID + .S01_AXI_WREADY (), // output S01_AXI_WREADY + .S01_AXI_BID (), // output [0 : 0] S01_AXI_BID + .S01_AXI_BRESP (), // output [1 : 0] S01_AXI_BRESP + .S01_AXI_BVALID (), // output S01_AXI_BVALID + .S01_AXI_BREADY (0), // input S01_AXI_BREADY + .S01_AXI_ARID (0), // input [0 : 0] S01_AXI_ARID + .S01_AXI_ARADDR (0), // input [31 : 0] S01_AXI_ARADDR + .S01_AXI_ARLEN (0), // input [7 : 0] S01_AXI_ARLEN + .S01_AXI_ARSIZE (0), // input [2 : 0] S01_AXI_ARSIZE + .S01_AXI_ARBURST (0), // input [1 : 0] S01_AXI_ARBURST + .S01_AXI_ARLOCK (0), // input S01_AXI_ARLOCK + .S01_AXI_ARCACHE (0), // input [3 : 0] S01_AXI_ARCACHE + .S01_AXI_ARPROT (0), // input [2 : 0] S01_AXI_ARPROT + .S01_AXI_ARQOS (0), // input [3 : 0] S01_AXI_ARQOS + .S01_AXI_ARVALID (0), // input S01_AXI_ARVALID + .S01_AXI_ARREADY (), // output S01_AXI_ARREADY + .S01_AXI_RID (), // output [0 : 0] S01_AXI_RID + .S01_AXI_RDATA (), // output [63 : 0] S01_AXI_RDATA + .S01_AXI_RRESP (), // output [1 : 0] S01_AXI_RRESP + .S01_AXI_RLAST (), // output S01_AXI_RLAST + .S01_AXI_RVALID (), // output S01_AXI_RVALID + .S01_AXI_RREADY (0), // input S01_AXI_RREADY + // + //.M00_AXI_ARESET_OUT_N (), // output M00_AXI_ARESET_OUT_N + .M00_AXI_ACLK (ddr3_axi_clk), // input M00_AXI_ACLK + .M00_AXI_ARESETN (~ddr3_axi_rst), // input M00_AXI_ARESETN + .M00_AXI_AWID (mig_axi_wr.addr.id), // output [3 : 0] M00_AXI_AWID + .M00_AXI_AWADDR (mig_axi_wr.addr.addr), // output [31 : 0] M00_AXI_AWADDR + .M00_AXI_AWLEN (mig_axi_wr.addr.len), // output [7 : 0] M00_AXI_AWLEN + .M00_AXI_AWSIZE (mig_axi_wr.addr.size), // output [2 : 0] M00_AXI_AWSIZE + .M00_AXI_AWBURST (mig_axi_wr.addr.burst), // output [1 : 0] M00_AXI_AWBURST + .M00_AXI_AWLOCK (mig_axi_wr.addr.lock), // output M00_AXI_AWLOCK + .M00_AXI_AWCACHE (mig_axi_wr.addr.cache), // output [3 : 0] M00_AXI_AWCACHE + .M00_AXI_AWPROT (mig_axi_wr.addr.prot), // output [2 : 0] M00_AXI_AWPROT + .M00_AXI_AWQOS (mig_axi_wr.addr.qos), // output [3 : 0] M00_AXI_AWQOS + .M00_AXI_AWVALID (mig_axi_wr.addr.valid), // output M00_AXI_AWVALID + .M00_AXI_AWREADY (mig_axi_wr.addr.ready), // input M00_AXI_AWREADY + .M00_AXI_WDATA (mig_axi_wr.data.data), // output [127 : 0] M00_AXI_WDATA + .M00_AXI_WSTRB (mig_axi_wr.data.strb), // output [15 : 0] M00_AXI_WSTRB + .M00_AXI_WLAST (mig_axi_wr.data.last), // output M00_AXI_WLAST + .M00_AXI_WVALID (mig_axi_wr.data.valid), // output M00_AXI_WVALID + .M00_AXI_WREADY (mig_axi_wr.data.ready), // input M00_AXI_WREADY + .M00_AXI_BID (mig_axi_wr.resp.id), // input [3 : 0] M00_AXI_BID + .M00_AXI_BRESP (mig_axi_wr.resp.resp), // input [1 : 0] M00_AXI_BRESP + .M00_AXI_BVALID (mig_axi_wr.resp.valid), // input M00_AXI_BVALID + .M00_AXI_BREADY (mig_axi_wr.resp.ready), // output M00_AXI_BREADY + .M00_AXI_ARID (mig_axi_rd.addr.id), // output [3 : 0] M00_AXI_ARID + .M00_AXI_ARADDR (mig_axi_rd.addr.addr), // output [31 : 0] M00_AXI_ARADDR + .M00_AXI_ARLEN (mig_axi_rd.addr.len), // output [7 : 0] M00_AXI_ARLEN + .M00_AXI_ARSIZE (mig_axi_rd.addr.size), // output [2 : 0] M00_AXI_ARSIZE + .M00_AXI_ARBURST (mig_axi_rd.addr.burst), // output [1 : 0] M00_AXI_ARBURST + .M00_AXI_ARLOCK (mig_axi_rd.addr.lock), // output M00_AXI_ARLOCK + .M00_AXI_ARCACHE (mig_axi_rd.addr.cache), // output [3 : 0] M00_AXI_ARCACHE + .M00_AXI_ARPROT (mig_axi_rd.addr.prot), // output [2 : 0] M00_AXI_ARPROT + .M00_AXI_ARQOS (mig_axi_rd.addr.qos), // output [3 : 0] M00_AXI_ARQOS + .M00_AXI_ARVALID (mig_axi_rd.addr.valid), // output M00_AXI_ARVALID + .M00_AXI_ARREADY (mig_axi_rd.addr.ready), // input M00_AXI_ARREADY + .M00_AXI_RID (mig_axi_rd.data.id), // input [3 : 0] M00_AXI_RID + .M00_AXI_RDATA (mig_axi_rd.data.data), // input [127 : 0] M00_AXI_RDATA + .M00_AXI_RRESP (mig_axi_rd.data.resp), // input [1 : 0] M00_AXI_RRESP + .M00_AXI_RLAST (mig_axi_rd.data.last), // input M00_AXI_RLAST + .M00_AXI_RVALID (mig_axi_rd.data.valid), // input M00_AXI_RVALID + .M00_AXI_RREADY (mig_axi_rd.data.ready) // output M00_AXI_RREADY + ); + end else begin + //Original IP interconnect + axi_intercon_2x64_128 axi_intercon_2x64_128_i ( + .INTERCONNECT_ACLK(ddr3_axi_clk_x2), // input INTERCONNECT_ACLK + .INTERCONNECT_ARESETN(~ddr3_axi_rst), // input INTERCONNECT_ARESETN + // + .S00_AXI_ARESET_OUT_N (), // output S00_AXI_ARESET_OUT_N + .S00_AXI_ACLK (ddr3_axi_clk_x2), // input S00_AXI_ACLK + .S00_AXI_AWID (dma_axi_wr.addr.id), // input [0 : 0] S00_AXI_AWID + .S00_AXI_AWADDR (dma_axi_wr.addr.addr), // input [31 : 0] S00_AXI_AWADDR + .S00_AXI_AWLEN (dma_axi_wr.addr.len), // input [7 : 0] S00_AXI_AWLEN + .S00_AXI_AWSIZE (dma_axi_wr.addr.size), // input [2 : 0] S00_AXI_AWSIZE + .S00_AXI_AWBURST (dma_axi_wr.addr.burst), // input [1 : 0] S00_AXI_AWBURST + .S00_AXI_AWLOCK (dma_axi_wr.addr.lock), // input S00_AXI_AWLOCK + .S00_AXI_AWCACHE (dma_axi_wr.addr.cache), // input [3 : 0] S00_AXI_AWCACHE + .S00_AXI_AWPROT (dma_axi_wr.addr.prot), // input [2 : 0] S00_AXI_AWPROT + .S00_AXI_AWQOS (dma_axi_wr.addr.qos), // input [3 : 0] S00_AXI_AWQOS + .S00_AXI_AWVALID (dma_axi_wr.addr.valid), // input S00_AXI_AWVALID + .S00_AXI_AWREADY (dma_axi_wr.addr.ready), // output S00_AXI_AWREADY + .S00_AXI_WDATA (dma_axi_wr.data.data ^ forced_bit_err), // input [63 : 0] S00_AXI_WDATA + .S00_AXI_WSTRB (dma_axi_wr.data.strb), // input [7 : 0] S00_AXI_WSTRB + .S00_AXI_WLAST (dma_axi_wr.data.last), // input S00_AXI_WLAST + .S00_AXI_WVALID (dma_axi_wr.data.valid), // input S00_AXI_WVALID + .S00_AXI_WREADY (dma_axi_wr.data.ready), // output S00_AXI_WREADY + .S00_AXI_BID (dma_axi_wr.resp.id), // output [0 : 0] S00_AXI_BID + .S00_AXI_BRESP (dma_axi_wr.resp.resp), // output [1 : 0] S00_AXI_BRESP + .S00_AXI_BVALID (dma_axi_wr.resp.valid), // output S00_AXI_BVALID + .S00_AXI_BREADY (dma_axi_wr.resp.ready), // input S00_AXI_BREADY + .S00_AXI_ARID (dma_axi_rd.addr.id), // input [0 : 0] S00_AXI_ARID + .S00_AXI_ARADDR (dma_axi_rd.addr.addr), // input [31 : 0] S00_AXI_ARADDR + .S00_AXI_ARLEN (dma_axi_rd.addr.len), // input [7 : 0] S00_AXI_ARLEN + .S00_AXI_ARSIZE (dma_axi_rd.addr.size), // input [2 : 0] S00_AXI_ARSIZE + .S00_AXI_ARBURST (dma_axi_rd.addr.burst), // input [1 : 0] S00_AXI_ARBURST + .S00_AXI_ARLOCK (dma_axi_rd.addr.lock), // input S00_AXI_ARLOCK + .S00_AXI_ARCACHE (dma_axi_rd.addr.cache), // input [3 : 0] S00_AXI_ARCACHE + .S00_AXI_ARPROT (dma_axi_rd.addr.prot), // input [2 : 0] S00_AXI_ARPROT + .S00_AXI_ARQOS (dma_axi_rd.addr.qos), // input [3 : 0] S00_AXI_ARQOS + .S00_AXI_ARVALID (dma_axi_rd.addr.valid), // input S00_AXI_ARVALID + .S00_AXI_ARREADY (dma_axi_rd.addr.ready), // output S00_AXI_ARREADY + .S00_AXI_RID (dma_axi_rd.data.id), // output [0 : 0] S00_AXI_RID + .S00_AXI_RDATA (dma_axi_rd.data.data), // output [63 : 0] S00_AXI_RDATA + .S00_AXI_RRESP (dma_axi_rd.data.resp), // output [1 : 0] S00_AXI_RRESP + .S00_AXI_RLAST (dma_axi_rd.data.last), // output S00_AXI_RLAST + .S00_AXI_RVALID (dma_axi_rd.data.valid), // output S00_AXI_RVALID + .S00_AXI_RREADY (dma_axi_rd.data.ready), // input S00_AXI_RREADY + // + .S01_AXI_ARESET_OUT_N (), // output S01_AXI_ARESET_OUT_N + .S01_AXI_ACLK (ddr3_axi_clk_x2), // input S01_AXI_ACLK + .S01_AXI_AWID (0), // input [0 : 0] S01_AXI_AWID + .S01_AXI_AWADDR (0), // input [31 : 0] S01_AXI_AWADDR + .S01_AXI_AWLEN (0), // input [7 : 0] S01_AXI_AWLEN + .S01_AXI_AWSIZE (0), // input [2 : 0] S01_AXI_AWSIZE + .S01_AXI_AWBURST (0), // input [1 : 0] S01_AXI_AWBURST + .S01_AXI_AWLOCK (0), // input S01_AXI_AWLOCK + .S01_AXI_AWCACHE (0), // input [3 : 0] S01_AXI_AWCACHE + .S01_AXI_AWPROT (0), // input [2 : 0] S01_AXI_AWPROT + .S01_AXI_AWQOS (0), // input [3 : 0] S01_AXI_AWQOS + .S01_AXI_AWVALID (0), // input S01_AXI_AWVALID + .S01_AXI_AWREADY (), // output S01_AXI_AWREADY + .S01_AXI_WDATA (0), // input [63 : 0] S01_AXI_WDATA + .S01_AXI_WSTRB (0), // input [7 : 0] S01_AXI_WSTRB + .S01_AXI_WLAST (0), // input S01_AXI_WLAST + .S01_AXI_WVALID (0), // input S01_AXI_WVALID + .S01_AXI_WREADY (), // output S01_AXI_WREADY + .S01_AXI_BID (), // output [0 : 0] S01_AXI_BID + .S01_AXI_BRESP (), // output [1 : 0] S01_AXI_BRESP + .S01_AXI_BVALID (), // output S01_AXI_BVALID + .S01_AXI_BREADY (0), // input S01_AXI_BREADY + .S01_AXI_ARID (0), // input [0 : 0] S01_AXI_ARID + .S01_AXI_ARADDR (0), // input [31 : 0] S01_AXI_ARADDR + .S01_AXI_ARLEN (0), // input [7 : 0] S01_AXI_ARLEN + .S01_AXI_ARSIZE (0), // input [2 : 0] S01_AXI_ARSIZE + .S01_AXI_ARBURST (0), // input [1 : 0] S01_AXI_ARBURST + .S01_AXI_ARLOCK (0), // input S01_AXI_ARLOCK + .S01_AXI_ARCACHE (0), // input [3 : 0] S01_AXI_ARCACHE + .S01_AXI_ARPROT (0), // input [2 : 0] S01_AXI_ARPROT + .S01_AXI_ARQOS (0), // input [3 : 0] S01_AXI_ARQOS + .S01_AXI_ARVALID (0), // input S01_AXI_ARVALID + .S01_AXI_ARREADY (), // output S01_AXI_ARREADY + .S01_AXI_RID (), // output [0 : 0] S01_AXI_RID + .S01_AXI_RDATA (), // output [63 : 0] S01_AXI_RDATA + .S01_AXI_RRESP (), // output [1 : 0] S01_AXI_RRESP + .S01_AXI_RLAST (), // output S01_AXI_RLAST + .S01_AXI_RVALID (), // output S01_AXI_RVALID + .S01_AXI_RREADY (0), // input S01_AXI_RREADY + // + .M00_AXI_ARESET_OUT_N (), // output M00_AXI_ARESET_OUT_N + .M00_AXI_ACLK (ddr3_axi_clk), // input M00_AXI_ACLK + .M00_AXI_AWID (mig_axi_wr.addr.id), // output [3 : 0] M00_AXI_AWID + .M00_AXI_AWADDR (mig_axi_wr.addr.addr), // output [31 : 0] M00_AXI_AWADDR + .M00_AXI_AWLEN (mig_axi_wr.addr.len), // output [7 : 0] M00_AXI_AWLEN + .M00_AXI_AWSIZE (mig_axi_wr.addr.size), // output [2 : 0] M00_AXI_AWSIZE + .M00_AXI_AWBURST (mig_axi_wr.addr.burst), // output [1 : 0] M00_AXI_AWBURST + .M00_AXI_AWLOCK (mig_axi_wr.addr.lock), // output M00_AXI_AWLOCK + .M00_AXI_AWCACHE (mig_axi_wr.addr.cache), // output [3 : 0] M00_AXI_AWCACHE + .M00_AXI_AWPROT (mig_axi_wr.addr.prot), // output [2 : 0] M00_AXI_AWPROT + .M00_AXI_AWQOS (mig_axi_wr.addr.qos), // output [3 : 0] M00_AXI_AWQOS + .M00_AXI_AWVALID (mig_axi_wr.addr.valid), // output M00_AXI_AWVALID + .M00_AXI_AWREADY (mig_axi_wr.addr.ready), // input M00_AXI_AWREADY + .M00_AXI_WDATA (mig_axi_wr.data.data), // output [127 : 0] M00_AXI_WDATA + .M00_AXI_WSTRB (mig_axi_wr.data.strb), // output [15 : 0] M00_AXI_WSTRB + .M00_AXI_WLAST (mig_axi_wr.data.last), // output M00_AXI_WLAST + .M00_AXI_WVALID (mig_axi_wr.data.valid), // output M00_AXI_WVALID + .M00_AXI_WREADY (mig_axi_wr.data.ready), // input M00_AXI_WREADY + .M00_AXI_BID (mig_axi_wr.resp.id), // input [3 : 0] M00_AXI_BID + .M00_AXI_BRESP (mig_axi_wr.resp.resp), // input [1 : 0] M00_AXI_BRESP + .M00_AXI_BVALID (mig_axi_wr.resp.valid), // input M00_AXI_BVALID + .M00_AXI_BREADY (mig_axi_wr.resp.ready), // output M00_AXI_BREADY + .M00_AXI_ARID (mig_axi_rd.addr.id), // output [3 : 0] M00_AXI_ARID + .M00_AXI_ARADDR (mig_axi_rd.addr.addr), // output [31 : 0] M00_AXI_ARADDR + .M00_AXI_ARLEN (mig_axi_rd.addr.len), // output [7 : 0] M00_AXI_ARLEN + .M00_AXI_ARSIZE (mig_axi_rd.addr.size), // output [2 : 0] M00_AXI_ARSIZE + .M00_AXI_ARBURST (mig_axi_rd.addr.burst), // output [1 : 0] M00_AXI_ARBURST + .M00_AXI_ARLOCK (mig_axi_rd.addr.lock), // output M00_AXI_ARLOCK + .M00_AXI_ARCACHE (mig_axi_rd.addr.cache), // output [3 : 0] M00_AXI_ARCACHE + .M00_AXI_ARPROT (mig_axi_rd.addr.prot), // output [2 : 0] M00_AXI_ARPROT + .M00_AXI_ARQOS (mig_axi_rd.addr.qos), // output [3 : 0] M00_AXI_ARQOS + .M00_AXI_ARVALID (mig_axi_rd.addr.valid), // output M00_AXI_ARVALID + .M00_AXI_ARREADY (mig_axi_rd.addr.ready), // input M00_AXI_ARREADY + .M00_AXI_RID (mig_axi_rd.data.id), // input [3 : 0] M00_AXI_RID + .M00_AXI_RDATA (mig_axi_rd.data.data), // input [127 : 0] M00_AXI_RDATA + .M00_AXI_RRESP (mig_axi_rd.data.resp), // input [1 : 0] M00_AXI_RRESP + .M00_AXI_RLAST (mig_axi_rd.data.last), // input M00_AXI_RLAST + .M00_AXI_RVALID (mig_axi_rd.data.valid), // input M00_AXI_RVALID + .M00_AXI_RREADY (mig_axi_rd.data.ready) // output M00_AXI_RREADY + ); + end + + //--------------------------------------------------- + // MIG + //--------------------------------------------------- + wire ddr3_idelay_refclk; + + ddr3_32bit ddr_mig_i ( + // Memory interface ports + .ddr3_addr (ddr3_addr), + .ddr3_ba (ddr3_ba), + .ddr3_cas_n (ddr3_cas_n), + .ddr3_ck_n (ddr3_ck_n), + .ddr3_ck_p (ddr3_ck_p), + .ddr3_cke (ddr3_cke), + .ddr3_ras_n (ddr3_ras_n), + .ddr3_reset_n (ddr3_reset_n), + .ddr3_we_n (ddr3_we_n), + .ddr3_dq (ddr3_dq), + .ddr3_dqs_n (ddr3_dqs_n), + .ddr3_dqs_p (ddr3_dqs_p), + .init_calib_complete (init_calib_complete), + + .ddr3_cs_n (ddr3_cs_n), + .ddr3_dm (ddr3_dm), + .ddr3_odt (ddr3_odt), + // Application interface ports + .ui_clk (ddr3_axi_clk), // 150MHz clock out + .ui_addn_clk_0 (ddr3_axi_clk_x2), // 300MHz clock out + .ui_addn_clk_1 (ddr3_idelay_refclk), + .ui_addn_clk_2 (), + .ui_addn_clk_3 (), + .ui_addn_clk_4 (), + .clk_ref_i (ddr3_idelay_refclk), + .ui_clk_sync_rst (ddr3_axi_rst), // Active high Reset signal synchronised to 150MHz + .aresetn (ddr3_axi_rst_reg_n), + .app_sr_req (1'b0), + .app_sr_active (), + .app_ref_req (1'b0), + .app_ref_ack (), + .app_zq_req (1'b0), + .app_zq_ack (), + .device_temp_i (12'd0), + // Slave Interface Write Address Ports + .s_axi_awid (mig_axi_wr.addr.id), + .s_axi_awaddr (mig_axi_wr.addr.addr), + .s_axi_awlen (mig_axi_wr.addr.len), + .s_axi_awsize (mig_axi_wr.addr.size), + .s_axi_awburst (mig_axi_wr.addr.burst), + .s_axi_awlock (mig_axi_wr.addr.lock), + .s_axi_awcache (mig_axi_wr.addr.cache), + .s_axi_awprot (mig_axi_wr.addr.prot), + .s_axi_awqos (mig_axi_wr.addr.qos), + .s_axi_awvalid (mig_axi_wr.addr.valid), + .s_axi_awready (mig_axi_wr.addr.ready), + // Slave Interface Write Data Ports + .s_axi_wdata (mig_axi_wr.data.data), + .s_axi_wstrb (mig_axi_wr.data.strb), + .s_axi_wlast (mig_axi_wr.data.last), + .s_axi_wvalid (mig_axi_wr.data.valid), + .s_axi_wready (mig_axi_wr.data.ready), + // Slave Interface Write Response Ports + .s_axi_bid (mig_axi_wr.resp.id), + .s_axi_bresp (mig_axi_wr.resp.resp), + .s_axi_bvalid (mig_axi_wr.resp.valid), + .s_axi_bready (mig_axi_wr.resp.ready), + // Slave Interface Read Address Ports + .s_axi_arid (mig_axi_rd.addr.id), + .s_axi_araddr (mig_axi_rd.addr.addr), + .s_axi_arlen (mig_axi_rd.addr.len), + .s_axi_arsize (mig_axi_rd.addr.size), + .s_axi_arburst (mig_axi_rd.addr.burst), + .s_axi_arlock (mig_axi_rd.addr.lock), + .s_axi_arcache (mig_axi_rd.addr.cache), + .s_axi_arprot (mig_axi_rd.addr.prot), + .s_axi_arqos (mig_axi_rd.addr.qos), + .s_axi_arvalid (mig_axi_rd.addr.valid), + .s_axi_arready (mig_axi_rd.addr.ready), + // Slave Interface Read Data Ports + .s_axi_rid (mig_axi_rd.data.id), + .s_axi_rdata (mig_axi_rd.data.data), + .s_axi_rresp (mig_axi_rd.data.resp), + .s_axi_rlast (mig_axi_rd.data.last), + .s_axi_rvalid (mig_axi_rd.data.valid), + .s_axi_rready (mig_axi_rd.data.ready), + // System Clock Ports + .sys_clk_i (sys_clk), // From external 100MHz source. + .sys_rst (sys_rst) + ); + + //--------------------------------------------------- + // DDR3 SDRAM Models + //--------------------------------------------------- + ddr3_model #( + .DEBUG(0) //Disable verbose prints + ) sdram_i0 ( + .rst_n (ddr3_reset_n), + .ck (ddr3_ck_p), + .ck_n (ddr3_ck_n), + .cke (ddr3_cke), + .cs_n (ddr3_cs_n), + .ras_n (ddr3_ras_n), + .cas_n (ddr3_cas_n), + .we_n (ddr3_we_n), + .dm_tdqs (ddr3_dm[1:0]), + .ba (ddr3_ba), + .addr (ddr3_addr), + .dq (ddr3_dq[15:0]), + .dqs (ddr3_dqs_p[1:0]), + .dqs_n (ddr3_dqs_n[1:0]), + .tdqs_n (), // Unused on x16 + .odt (ddr3_odt) + ); + + ddr3_model #( + .DEBUG(0) //Disable verbose prints + ) sdram_i1 ( + .rst_n (ddr3_reset_n), + .ck (ddr3_ck_p), + .ck_n (ddr3_ck_n), + .cke (ddr3_cke), + .cs_n (ddr3_cs_n), + .ras_n (ddr3_ras_n), + .cas_n (ddr3_cas_n), + .we_n (ddr3_we_n), + .dm_tdqs (ddr3_dm[3:2]), + .ba (ddr3_ba), + .addr (ddr3_addr), + .dq (ddr3_dq[31:16]), + .dqs (ddr3_dqs_p[3:2]), + .dqs_n (ddr3_dqs_n[3:2]), + .tdqs_n (), // Unused on x16 + .odt (ddr3_odt) + ); + end endgenerate + +endmodule diff --git a/fpga/usrp3/top/x300/sim/dram_fifo/dram_fifo_tb.sv b/fpga/usrp3/top/x300/sim/dram_fifo/dram_fifo_tb.sv new file mode 100644 index 000000000..0be9dc9dd --- /dev/null +++ b/fpga/usrp3/top/x300/sim/dram_fifo/dram_fifo_tb.sv @@ -0,0 +1,184 @@ +// +// Copyright 2016 Ettus Research +// + + +`timescale 1ns/1ps +`define SIM_TIMEOUT_US 120 +`define NS_PER_TICK 1 +`define NUM_TEST_CASES 7 + +`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 0 //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_tb(); + `TEST_BENCH_INIT("dram_fifo_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 + + settings_bus_master #(.SR_AWIDTH(8),.SR_DWIDTH(32)) tst_set (.clk(bus_clk)); + cvita_master chdr_i (.clk(bus_clk)); + cvita_slave chdr_o (.clk(bus_clk)); + + // Initialize DUT + wire calib_complete; +`ifdef USE_SRAM_FIFO + + axi_fifo #(.WIDTH(65), .SIZE(18)) dut_single ( + .clk(bus_clk), + .reset(bus_rst), + .clear(1'b0), + + .i_tdata({chdr_i.axis.tlast, chdr_i.axis.tdata}), + .i_tvalid(chdr_i.axis.tvalid), + .i_tready(chdr_i.axis.tready), + + .o_tdata({chdr_o.axis.tlast, chdr_o.axis.tdata}), + .o_tvalid(chdr_o.axis.tvalid), + .o_tready(chdr_o.axis.tready), + + .space(), + .occupied() + ); + assign calib_complete = 1; + +`else + + axis_dram_fifo_single #( + .USE_SRAM_MEMORY(`USE_SRAM_MIG), + .USE_BD_INTERCON(`USE_BD_INTERCON) + ) dut_single + ( + .bus_clk(bus_clk), + .bus_rst(bus_rst), + .sys_clk(sys_clk), + .sys_rst(sys_rst), + + .i_tdata(chdr_i.axis.tdata), + .i_tlast(chdr_i.axis.tlast), + .i_tvalid(chdr_i.axis.tvalid), + .i_tready(chdr_i.axis.tready), + + .o_tdata(chdr_o.axis.tdata), + .o_tlast(chdr_o.axis.tlast), + .o_tvalid(chdr_o.axis.tvalid), + .o_tready(chdr_o.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(), + + .forced_bit_err(64'h0), + .init_calib_complete(calib_complete) + ); +`endif + + //Testbench variables + cvita_hdr_t header; + cvita_pkt_t pkt_out; + integer i; + + //------------------------------------------ + //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)); + + `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(1, {16'h0, 12'd280, 2'b00, 1'b0, 1'b1}); + repeat (200) @(posedge bus_clk); + tst_set.write(1, {16'h0, 12'd280, 2'b00, 1'b0, 1'b0}); + repeat (200) @(posedge bus_clk); + `TEST_CASE_DONE(1); + + 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 (short packet)"); + chdr_i.push_ramp_pkt(16, 64'd0, 64'h100, header); + chdr_o.pull_pkt(pkt_out); + $sformat(s, "Bad packet: Length mismatch. Expected: %0d, Actual: %0d",16,pkt_out.payload.size()); + `ASSERT_ERROR(pkt_out.payload.size()==16, 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); + `TEST_CASE_DONE(1); + + `TEST_CASE_START("Fill up empty FIFO then drain (long packet)"); + chdr_i.push_ramp_pkt(1024, 64'd0, 64'h100, header); + chdr_o.pull_pkt(pkt_out); + $sformat(s, "Bad packet: Length mismatch. Expected: %0d, Actual: %0d",1024,pkt_out.payload.size()); + `ASSERT_ERROR(pkt_out.payload.size()==1024, 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); + `TEST_CASE_DONE(1); + + 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("Concurrent read and write (single packet)"); + fork + begin + chdr_i.push_ramp_pkt(20, 64'd0, 64'h100, header); + end + begin + chdr_o.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); + i = 0; + repeat (20) 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("Concurrent read and write (multiple packets)"); + fork + begin + repeat (10) begin + chdr_i.push_ramp_pkt(20, 64'd0, 64'h100, header); + repeat (30) @(posedge bus_clk); + end + end + begin + repeat (10) begin + chdr_o.pull_pkt(pkt_out); + $sformat(s, "Bad packet: Length mismatch. Expected: %0d, Actual: %0d",20,pkt_out.payload.size()); + `ASSERT_ERROR(pkt_out.payload.size()==20, s); + end + end + join + `TEST_CASE_DONE(1); + + `TEST_BENCH_DONE; + + end + +endmodule 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 diff --git a/fpga/usrp3/top/x300/sim/x300_pcie_int/Makefile b/fpga/usrp3/top/x300/sim/x300_pcie_int/Makefile new file mode 100644 index 000000000..02aaef59c --- /dev/null +++ b/fpga/usrp3/top/x300/sim/x300_pcie_int/Makefile @@ -0,0 +1,66 @@ +# +# 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/control/Makefile.srcs +include $(BASE_DIR)/../lib/packet_proc/Makefile.srcs +include $(BASE_DIR)/../lib/fifo/Makefile.srcs +include $(BASE_DIR)/../lib/io_port2/Makefile.srcs + +DESIGN_SRCS = $(abspath \ +$(FIFO_SRCS) \ +$(CONTROL_LIB_SRCS) \ +$(PACKET_PROC_SRCS) \ +$(IOPORT2_SRCS) \ +../../x300_pcie_int.v \ +) + +#------------------------------------------------- +# 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)/fifo_short_2clk/Makefile.inc +include $(IP_DIR)/fifo_4k_2clk/Makefile.inc + +DESIGN_SRCS += $(abspath \ +$(IP_FIFO_4K_2CLK_SRCS) \ +$(IP_FIFO_SHORT_2CLK_SRCS) \ +) + +#------------------------------------------------- +# Testbench Specific +#------------------------------------------------- +# Define only one toplevel module +SIM_TOP = x300_pcie_int_tb + +SIM_SRCS = \ +$(abspath x300_pcie_int_tb.sv) + +#------------------------------------------------- +# 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/x300_pcie_int/x300_pcie_int_tb.sv b/fpga/usrp3/top/x300/sim/x300_pcie_int/x300_pcie_int_tb.sv new file mode 100644 index 000000000..0093e4315 --- /dev/null +++ b/fpga/usrp3/top/x300/sim/x300_pcie_int/x300_pcie_int_tb.sv @@ -0,0 +1,596 @@ +// +// Copyright 2013 Ettus Research LLC +// + + +`timescale 1ns/1ps +`define NS_PER_TICK 1 +`define NUM_TEST_CASES 23 + +`define SIM_TIMEOUT_US 1000 // 1ms + +`include "sim_clks_rsts.vh" +`include "sim_exec_report.vh" + +module x300_pcie_int_tb(); + `DEFINE_CLK(clk, 8.000, 50) + `DEFINE_RESET(reset, 0, 10) + + `TEST_BENCH_INIT("x300_pcie_int_tb",`NUM_TEST_CASES,`NS_PER_TICK) + + reg temp_pass = 0; + reg pkt_swap = 0; + reg [15:0] it = 0; + reg [15:0] tx_ch, rx_ch = 0; + + reg [31:0] dma_sample_cnt = 0; + reg [31:0] dma_packet_cnt = 0; + reg [31:0] dma_out_sample_cnt[0:5]; + reg [63:0] dma_out_last_sample[0:5]; + + reg pcie_usr_reg_wr, pcie_usr_reg_rd; + reg [1:0] pcie_usr_reg_len; + reg [19:0] pcie_usr_reg_addr; + reg [31:0] pcie_usr_reg_data_in, pcie_usr_data; + wire pcie_usr_reg_rc, pcie_usr_reg_rdy; + wire [31:0] pcie_usr_reg_data_out; + + wire chinch_reg_wr, chinch_reg_rd; + wire [1:0] chinch_reg_len; + wire [19:0] chinch_reg_addr; + wire [31:0] chinch_reg_data_out; + reg chinch_reg_rc, chinch_reg_rdy; + reg [31:0] chinch_reg_data_in; + + reg [2:0] i_chan, o_chan; + reg [383:0] i_tdata_par; + reg [5:0] i_tvalid_par = 6'b000000, o_tready_par = 6'b111111; + wire [383:0] o_tdata_par; + wire [5:0] o_tvalid_par, i_tready_par; + + reg i_tvalid, i_tready, o_tvalid, o_tready; + reg [63:0] i_tdata, o_tdata; + + localparam READ = 2'b01; + localparam WRITE = 2'b10; + + task usr_regport_request; + input [1:0] operation; + input [19:0] address; + input [31:0] data; + begin + pcie_usr_reg_data_in <= data; + pcie_usr_reg_addr <= address; + pcie_usr_reg_wr <= operation[1]; + pcie_usr_reg_rd <= operation[0]; + pcie_usr_reg_len <= 2'b10; + + @(posedge clk); + while (~pcie_usr_reg_rdy) @(posedge clk); + + pcie_usr_reg_wr <= 1'b0; + pcie_usr_reg_rd <= 1'b0; + @(posedge clk); + end + endtask // usr_regport_request + + task usr_regport_response; + begin + @(posedge clk); + while (~pcie_usr_reg_rc) @(posedge clk); + pcie_usr_data <= pcie_usr_reg_data_out; + @(posedge clk); + end + endtask // usr_regport_response + + task chinch_regport_request; + input [1:0] operation; + input [19:0] address; + input [31:0] data; + begin + @(posedge clk); + while (~(chinch_reg_rdy && + chinch_reg_addr == address && + {chinch_reg_wr,chinch_reg_rd} == operation && + chinch_reg_len == 2'b10 && + (operation == WRITE || chinch_reg_data_out == data) + )) @(posedge clk); + + @(posedge clk); + end + endtask // chinch_regport_request + + task chinch_regport_response; + input [31:0] data; + begin + @(posedge clk); + chinch_reg_data_in <= data; + chinch_reg_rc <= 1'b1; + @(posedge clk); + chinch_reg_rc <= 1'b0; + end + endtask // chinch_regport_response + + task send_packet; + input [63:0] sid; + input [31:0] len; + input [31:0] quant; + begin + if(quant < 2) begin + i_tdata <= { sid[63:32],len[15:0], sid[15:0] }; + i_tvalid <= 1; + @(posedge clk); + i_tvalid <= 0; + @(posedge clk); + end else begin + i_tdata <= { sid[63:32],len[15:0], sid[15:0] }; + i_tvalid <= 1; + @(posedge clk); + i_tdata <= 64'h0000_0001_0000_0000; + repeat(quant - 2) begin + i_tdata <= i_tdata + 64'h0000_0002_0000_0002; + @(posedge clk); + end + i_tdata <= i_tdata + 64'h0000_0002_0000_0002; + @(posedge clk); + i_tvalid <= 1'b0; + @(posedge clk); + end // else: !if(len < 3) + end + endtask // send_packet + + task reset_dma_counts; + begin + dma_sample_cnt <= 32'd0; + dma_packet_cnt <= 32'd0; + dma_out_sample_cnt[0] <= 32'd0; + dma_out_sample_cnt[1] <= 32'd0; + dma_out_sample_cnt[2] <= 32'd0; + dma_out_sample_cnt[3] <= 32'd0; + dma_out_sample_cnt[4] <= 32'd0; + dma_out_sample_cnt[5] <= 32'd0; + dma_out_last_sample[0] <= 64'd0; + dma_out_last_sample[1] <= 64'd0; + dma_out_last_sample[2] <= 64'd0; + dma_out_last_sample[3] <= 64'd0; + dma_out_last_sample[4] <= 64'd0; + dma_out_last_sample[5] <= 64'd0; + @(posedge clk); + end + endtask // reset_dma_counts + + task select_channels; + input [2:0] tx_ch; + input [2:0] rx_ch; + begin + i_chan <= tx_ch; + o_chan <= rx_ch; + @(posedge clk); + end + endtask // select_channels + + task wait_for_pkt_loopback; + begin + while (i_tvalid & i_tready) @(posedge clk); //Wait for outbound pkt to pad and send + while (~o_tvalid) @(posedge clk); //Wait for inbound pkt to arrive + while (o_tvalid & o_tready) @(posedge clk); //Wait for inbound pkt to finish + end + endtask // wait_for_pkt_loopback + + wire [63:0] dma_loop_tdata ; + wire [ 2:0] dma_loop_tuser ; + wire dma_loop_tvalid, dma_loop_tlast, dma_loop_tready; + + wire [63:0] iop2_msg_tdata ; + wire iop2_msg_tvalid, iop2_msg_tlast, iop2_msg_tready; + + + initial begin : tb_main + while (reset) @(posedge clk); + + chinch_reg_rdy <= 1'b1; + chinch_reg_rc <= 1'b0; + + `TEST_CASE_START("Verify signature register"); + usr_regport_request(READ, 20'h40000, 32'h0); + usr_regport_response(); + `TEST_CASE_DONE((pcie_usr_data == "X300")) + + `TEST_CASE_START("Verify counter frequency register"); + usr_regport_request(READ, 20'h4000C, 32'h0); + usr_regport_response(); + `TEST_CASE_DONE((pcie_usr_data == 166666667)); + + `TEST_CASE_START("Verify scratch registers"); + usr_regport_request(WRITE, 20'h40010, 32'hDEAD); + usr_regport_request(WRITE, 20'h40014, 32'hBEEF); + usr_regport_request(READ, 20'h40014, 32'h0); + usr_regport_response(); + temp_pass <= (pcie_usr_data == 32'hBEEF); + usr_regport_request(READ, 20'h40010, 32'h0); + usr_regport_response(); + `TEST_CASE_DONE((pcie_usr_data == 32'hDEAD) & temp_pass); + + `TEST_CASE_START("Client register port write 1"); + usr_regport_request(WRITE, 20'h60000, 32'h12345678); + chinch_regport_request(WRITE, 20'h60000, 32'h12345678); + + usr_regport_request(WRITE, 20'h7FFFC, 32'h1357); + chinch_regport_request(WRITE, 20'h7FFFC, 32'h1357); + + usr_regport_request(WRITE, 20'h70000, 32'h2468); + chinch_regport_request(WRITE, 20'h70000, 32'h2468); + `TEST_CASE_DONE(1); + + `TEST_CASE_START("Client register port read 1"); + usr_regport_request(READ, 20'h60000, 32'h0); + chinch_regport_request(READ, 20'h60000, 32'h0); + chinch_regport_response(32'hACE0BA51); + usr_regport_response(); + `ASSERT_ERROR((pcie_usr_data == 32'hACE0BA51),""); + + usr_regport_request(READ, 20'h7FFFC, 32'h0); + chinch_regport_request(READ, 20'h7FFFC, 32'h0); + chinch_regport_response(32'hACE0BA52); + usr_regport_response(); + `ASSERT_ERROR((pcie_usr_data == 32'hACE0BA52),""); + + usr_regport_request(READ, 20'h70000, 32'h0); + chinch_regport_request(READ, 20'h70000, 32'h0); + chinch_regport_response(32'hACE0BA53); + usr_regport_response(); + `TEST_CASE_DONE((pcie_usr_data == 32'hACE0BA53)); + + `TEST_CASE_START("Configure RX DMA routing table"); + usr_regport_request(WRITE, 20'h40500, 32'h0000_0000); + usr_regport_request(WRITE, 20'h40500, 32'h0001_0001); + usr_regport_request(WRITE, 20'h40500, 32'h0002_0002); + usr_regport_request(WRITE, 20'h40500, 32'h0003_0003); + usr_regport_request(WRITE, 20'h40500, 32'h00D3_0000); + usr_regport_request(WRITE, 20'h40500, 32'h00D2_0001); + usr_regport_request(WRITE, 20'h40500, 32'h00D1_0002); + usr_regport_request(WRITE, 20'h40500, 32'h00D0_0003); + `TEST_CASE_DONE(1); + + `TEST_CASE_START("Frame size register read"); + usr_regport_request(READ, 20'h40204, 32'h0); + usr_regport_response(); + `ASSERT_ERROR((pcie_usr_data == 32), "Frame size register read (Default) [TX0]."); + usr_regport_request(READ, 20'h40214, 32'h0); + usr_regport_response(); + `ASSERT_ERROR((pcie_usr_data == 32), "Frame size register read (Default) [TX1]."); + usr_regport_request(READ, 20'h40404, 32'h0); + usr_regport_response(); + `ASSERT_ERROR((pcie_usr_data == 32), "Frame size register read (Default) [RX0]."); + usr_regport_request(READ, 20'h40414, 32'h0); + usr_regport_response(); + `ASSERT_ERROR((pcie_usr_data == 32), "Frame size register read (Default) [RX1]."); + `TEST_CASE_DONE(1); + + o_tready <= 1'b1; + + `TEST_CASE_START("Loopback packet"); + reset_dma_counts(); + usr_regport_request(WRITE, 20'h40200, 32'h0000_0012); + usr_regport_request(WRITE, 20'h40400, 32'h0000_0012); + select_channels(0,0); + send_packet(16'h00D2, 80, 32); + wait_for_pkt_loopback(); + `TEST_CASE_DONE((dma_sample_cnt==10 && dma_packet_cnt==1 && dma_out_sample_cnt[0]==32)); + + reset_dma_counts(); + select_channels(1,0); + send_packet(16'h00D3, 80, 32); + wait_for_pkt_loopback(); + `TEST_CASE_DONE(dma_sample_cnt==10 && dma_packet_cnt==1 && dma_out_sample_cnt[0]==32); + + `TEST_CASE_START("Frame size register write."); + usr_regport_request(WRITE, 20'h40224, 32'd16); + usr_regport_request(WRITE, 20'h40234, 32'd16); + usr_regport_request(WRITE, 20'h40424, 32'd16); + usr_regport_request(WRITE, 20'h40434, 32'd16); + `TEST_CASE_DONE(1); + + `TEST_CASE_START("Frame size register read"); + usr_regport_request(READ, 20'h40224, 32'h0); + usr_regport_response(); + `ASSERT_ERROR((pcie_usr_data == 16), "Frame size register read [TX2]."); + usr_regport_request(READ, 20'h40234, 32'h0); + usr_regport_response(); + `ASSERT_ERROR((pcie_usr_data == 16), "Frame size register read [TX3]."); + usr_regport_request(READ, 20'h40424, 32'h0); + usr_regport_response(); + `ASSERT_ERROR((pcie_usr_data == 16), "Frame size register read [RX2]."); + usr_regport_request(READ, 20'h40434, 32'h0); + usr_regport_response(); + `ASSERT_ERROR((pcie_usr_data == 16), "Frame size register read [RX3]."); + `TEST_CASE_DONE(1); + + `TEST_CASE_START("Loopback packet"); + reset_dma_counts(); + select_channels(2,2); + send_packet(16'h0002, 32, 16); + wait_for_pkt_loopback(); + `TEST_CASE_DONE(dma_sample_cnt==4 && dma_packet_cnt==1 && dma_out_sample_cnt[2]==16); + + reset_dma_counts(); + select_channels(3,3); + send_packet(16'h0003, 32, 16); + wait_for_pkt_loopback(); + `TEST_CASE_DONE((dma_sample_cnt==4 && dma_packet_cnt==1 && dma_out_sample_cnt[3]==16)); + + `TEST_CASE_START("Loopback multiple packets"); + reset_dma_counts(); + select_channels(3,2); + send_packet(16'h0002, 128, 16); + send_packet(16'h0002, 128, 16); + send_packet(16'h0002, 128, 16); + send_packet(16'h0002, 128, 16); + wait_for_pkt_loopback(); + repeat(64) @(posedge clk); + `TEST_CASE_DONE(dma_sample_cnt==64 && dma_packet_cnt==4 && dma_out_sample_cnt[2]==64 && o_tdata==64'h0000009e00000020); + + `TEST_CASE_START("Loopback multiple packets (RX Swapped)"); + reset_dma_counts(); + select_channels(3,2); + + usr_regport_request(WRITE, 20'h40230, 32'h10); + usr_regport_request(WRITE, 20'h40420, 32'h00); + repeat(16) @(posedge clk); + + send_packet(16'h0002, 128, 16); + send_packet(16'h0002, 128, 16); + wait_for_pkt_loopback(); + repeat(64) @(posedge clk); + `TEST_CASE_DONE(dma_sample_cnt==32 && dma_packet_cnt==2 && dma_out_sample_cnt[2]==32 && o_tdata==64'h000000200000009e); + + /* @TODO: Need to implement data swapping in TB + `TEST_CASE_START(); + reset_dma_counts(); + select_channels(3,2); + + usr_regport_request(WRITE, 20'h40230, 32'h00); + usr_regport_request(WRITE, 20'h40420, 32'h10); + repeat(16) @(posedge clk); + + send_packet(16'h0002, 128, 16); + send_packet(16'h0002, 128, 16); + wait_for_pkt_loopback(); + repeat(64) @(posedge clk); + `TEST_CASE_DONE(dma_sample_cnt==32 && dma_packet_cnt==2 && dma_out_sample_cnt[2]==32 && o_tdata[7:0]==32, + "Loopback multiple packets (TX Swapped)."); + */ + + `TEST_CASE_START("Good DMA status."); + reset_dma_counts(); + select_channels(3,2); + usr_regport_request(READ, 20'h40230, 32'h0); + usr_regport_response(); + temp_pass <= (pcie_usr_data == 32'h0); + usr_regport_request(READ, 20'h40420, 32'h0); + usr_regport_response(); + `TEST_CASE_DONE(temp_pass && (pcie_usr_data == 32'h0)); + + `TEST_CASE_START("Bad DMA status."); + send_packet(16'h0002, 160, 20); + repeat(64) @(posedge clk); + usr_regport_request(READ, 20'h40230, 32'h0); + usr_regport_response(); + temp_pass <= (pcie_usr_data == 32'h1); + usr_regport_request(READ, 20'h40420, 32'h0); + usr_regport_response(); + `TEST_CASE_DONE(temp_pass || (pcie_usr_data == 32'h1)); + + `TEST_CASE_START("DMA Status reset."); + usr_regport_request(WRITE, 20'h40230, 32'h1); + usr_regport_request(READ, 20'h40230, 32'h0); + usr_regport_response(); + temp_pass <= (pcie_usr_data == 32'h0); + usr_regport_request(WRITE, 20'h40420, 32'h1); + usr_regport_request(READ, 20'h40420, 32'h0); + usr_regport_response(); + `TEST_CASE_DONE(temp_pass && (pcie_usr_data == 32'h0)); + + `TEST_CASE_START("Packet count register reset"); + select_channels(2,1); + reset_dma_counts(); + usr_regport_request(WRITE, 20'h4022C, 32'h0); + usr_regport_request(READ, 20'h4022C, 32'h0); + usr_regport_response(); + `ASSERT_ERROR((pcie_usr_data == 0), "TX Packet count register reset."); + usr_regport_request(WRITE, 20'h4041C, 32'h0); + usr_regport_request(READ, 20'h4041C, 32'h0); + usr_regport_response(); + `ASSERT_ERROR((pcie_usr_data == 0), "RX Packet count register reset."); + `TEST_CASE_DONE(1); + + `TEST_CASE_START("TX Packet count register read"); + send_packet(16'h0001, 80, 16); + send_packet(16'h0001, 24, 16); + send_packet(16'h0001, 48, 16); + repeat(64) @(posedge clk); + usr_regport_request(READ, 20'h4022C, 32'h0); + usr_regport_response(); + `ASSERT_ERROR((pcie_usr_data == 3), "TX Packet count register read."); + usr_regport_request(READ, 20'h4041C, 32'h0); + usr_regport_response(); + `ASSERT_ERROR((pcie_usr_data == 3), "RX Packet count register read."); + `TEST_CASE_DONE(1); + + `TEST_CASE_START("TX Sample count register reset"); + select_channels(1,2); + reset_dma_counts(); + usr_regport_request(WRITE, 20'h40218, 32'h0); + usr_regport_request(READ, 20'h40218, 32'h0); + usr_regport_response(); + `ASSERT_ERROR((pcie_usr_data == 0), "TX Sample count register reset."); + usr_regport_request(WRITE, 20'h40428, 32'h0); + usr_regport_request(READ, 20'h40428, 32'h0); + usr_regport_response(); + `ASSERT_ERROR((pcie_usr_data == 0), "RX Sample count register reset."); + `TEST_CASE_DONE(1'b1); + + `TEST_CASE_START("TX Sample count register read"); + send_packet(16'h0002, 28, 16); + wait_for_pkt_loopback(); + usr_regport_request(READ, 20'h40218, 32'h0); + usr_regport_response(); + `ASSERT_ERROR((pcie_usr_data == 4), "TX Sample count register read."); + usr_regport_request(READ, 20'h40428, 32'h0); + usr_regport_response(); + `ASSERT_ERROR((pcie_usr_data == 4), "RX Sample count register read."); + `TEST_CASE_DONE(1'b1); + + `TEST_CASE_START("Setup for NxN DMA test"); + for (it = 0; it < 16'd6; it = it + 16'd1) begin + usr_regport_request(WRITE, 20'h40204 + (it * 16), 32'h4); + usr_regport_request(WRITE, 20'h40404 + (it * 16), 32'h4); + usr_regport_request(WRITE, 20'h40500, {it, it}); + end + `TEST_CASE_DONE(1'b1); + + `TEST_CASE_START("Setup for NxN DMA test"); + for (tx_ch = 0; tx_ch < 6; tx_ch = tx_ch + 16'd2) begin + for (rx_ch = 1; rx_ch < 6; rx_ch = rx_ch + 16'd1) begin + select_channels(tx_ch,rx_ch); + reset_dma_counts(); + @(posedge clk); + send_packet(rx_ch, 16, 4); + wait_for_pkt_loopback(); + if (dma_sample_cnt==2 && dma_packet_cnt==1 && dma_out_sample_cnt[rx_ch]==4) begin + $display("[TEST%d]: NxN DMA Test [TX=%d, RX=%d]...Passed",tc_run_count,tx_ch[3:0],rx_ch[3:0]); + end else begin + $display("[TEST%d]: NxN DMA Test [TX=%d, RX=%d]...FAILED!!!",tc_run_count,tx_ch[3:0],rx_ch[3:0]); + end + @(posedge clk); + end + end + `TEST_CASE_DONE(1'b1); + end // initial begin + + + x300_pcie_int #( + .DMA_STREAM_WIDTH (64), + .NUM_TX_STREAMS (6 ), + .NUM_RX_STREAMS (6 ), + .REGPORT_ADDR_WIDTH(20), + .REGPORT_DATA_WIDTH(32), + .IOP2_MSG_WIDTH (64) + ) x300_pcie_int ( + .ioport2_clk (clk ), + .bus_clk (clk ), + .bus_rst (reset ), + + //DMA TX FIFOs (IoPort2 Clock Domain) + .dmatx_tdata_iop2 (i_tdata_par ), + .dmatx_tvalid_iop2 (i_tvalid_par ), + .dmatx_tready_iop2 (i_tready_par ), + + //DMA TX FIFOs (IoPort2 Clock Domain) + .dmarx_tdata_iop2 (o_tdata_par ), + .dmarx_tvalid_iop2 (o_tvalid_par ), + .dmarx_tready_iop2 (o_tready_par ), + + //PCIe User Regport + .pcie_usr_reg_wr (pcie_usr_reg_wr ), + .pcie_usr_reg_rd (pcie_usr_reg_rd ), + .pcie_usr_reg_addr (pcie_usr_reg_addr ), + .pcie_usr_reg_data_in (pcie_usr_reg_data_in ), + .pcie_usr_reg_len (pcie_usr_reg_len ), + .pcie_usr_reg_data_out(pcie_usr_reg_data_out), + .pcie_usr_reg_rc (pcie_usr_reg_rc ), + .pcie_usr_reg_rdy (pcie_usr_reg_rdy ), + + //Chinch Regport + .chinch_reg_wr (chinch_reg_wr ), + .chinch_reg_rd (chinch_reg_rd ), + .chinch_reg_addr (chinch_reg_addr ), + .chinch_reg_data_out (chinch_reg_data_out ), + .chinch_reg_len (chinch_reg_len ), + .chinch_reg_data_in (chinch_reg_data_in ), + .chinch_reg_rc (chinch_reg_rc ), + .chinch_reg_rdy (chinch_reg_rdy ), + + //DMA TX FIFO (Bus Clock Domain) + .dmatx_tdata (dma_loop_tdata ), + .dmatx_tuser (dma_loop_tuser ), + .dmatx_tlast (dma_loop_tlast ), + .dmatx_tvalid (dma_loop_tvalid ), + .dmatx_tready (dma_loop_tready ), + + //DMA RX FIFO (Bus Clock Domain) + .dmarx_tdata (dma_loop_tdata ), + .dmarx_tuser (dma_loop_tuser ), + .dmarx_tlast (dma_loop_tlast ), + .dmarx_tvalid (dma_loop_tvalid ), + .dmarx_tready (dma_loop_tready ), + + //Message FIFO Out (Bus Clock Domain) + .rego_tdata (iop2_msg_tdata ), + .rego_tvalid (iop2_msg_tvalid ), + .rego_tlast (iop2_msg_tlast ), + .rego_tready (iop2_msg_tready ), + + //Message FIFO In (Bus Clock Domain) + .regi_tdata (iop2_msg_tdata ), + .regi_tvalid (iop2_msg_tvalid ), + .regi_tlast (iop2_msg_tlast ), + .regi_tready (iop2_msg_tready ), + + .debug ( ) + ); + + always @(posedge clk) begin + if (dma_loop_tvalid & dma_loop_tready) begin + dma_sample_cnt <= dma_sample_cnt + 32'd1; + if (dma_loop_tlast) dma_packet_cnt <= dma_packet_cnt + 32'd1; + end + end + + always @(posedge clk) begin + case (i_chan) + 3'd5: + {i_tdata_par[383:320], i_tvalid_par[5], i_tready} <= {i_tdata, i_tvalid, i_tready_par[5]}; + 3'd4: + {i_tdata_par[319:256], i_tvalid_par[4], i_tready} <= {i_tdata, i_tvalid, i_tready_par[4]}; + 3'd3: + {i_tdata_par[255:192], i_tvalid_par[3], i_tready} <= {i_tdata, i_tvalid, i_tready_par[3]}; + 3'd2: + {i_tdata_par[191:128], i_tvalid_par[2], i_tready} <= {i_tdata, i_tvalid, i_tready_par[2]}; + 3'd1: + {i_tdata_par[127:64], i_tvalid_par[1], i_tready} <= {i_tdata, i_tvalid, i_tready_par[1]}; + default: + {i_tdata_par[63:0], i_tvalid_par[0], i_tready} <= {i_tdata, i_tvalid, i_tready_par[0]}; + endcase + end + + always @(posedge clk) begin + case (o_chan) + 3'd5: + {o_tdata, o_tvalid, o_tready_par[5]} <= {o_tdata_par[383:320], o_tvalid_par[5], o_tready}; + 3'd4: + {o_tdata, o_tvalid, o_tready_par[4]} <= {o_tdata_par[319:256], o_tvalid_par[4], o_tready}; + 3'd3: + {o_tdata, o_tvalid, o_tready_par[3]} <= {o_tdata_par[255:192], o_tvalid_par[3], o_tready}; + 3'd2: + {o_tdata, o_tvalid, o_tready_par[2]} <= {o_tdata_par[191:128], o_tvalid_par[2], o_tready}; + 3'd1: + {o_tdata, o_tvalid, o_tready_par[1]} <= {o_tdata_par[127:64], o_tvalid_par[1], o_tready}; + default: + {o_tdata, o_tvalid, o_tready_par[0]} <= {o_tdata_par[63:0], o_tvalid_par[0], o_tready}; + endcase + end + + genvar i; + generate + for (i=0; i<6; i=i+1) begin: dma_counter_generator + always @(posedge clk) begin + if (o_tvalid_par[i] & o_tready_par[i]) begin + dma_out_sample_cnt[i] <= dma_out_sample_cnt[i] + 32'd1; + dma_out_last_sample[i] <= o_tdata_par[(64*i)+63:64*i]; + end + end + end + endgenerate + +endmodule |