aboutsummaryrefslogtreecommitdiffstats
path: root/fpga/usrp3/top/n3xx/sim
diff options
context:
space:
mode:
Diffstat (limited to 'fpga/usrp3/top/n3xx/sim')
-rw-r--r--fpga/usrp3/top/n3xx/sim/arm_to_sfp_loopback/Makefile84
-rw-r--r--fpga/usrp3/top/n3xx/sim/arm_to_sfp_loopback/arm_to_sfp_tb.sv528
-rw-r--r--fpga/usrp3/top/n3xx/sim/aurora_loopback/Makefile80
-rw-r--r--fpga/usrp3/top/n3xx/sim/aurora_loopback/aurora_loopback_tb.sv395
-rw-r--r--fpga/usrp3/top/n3xx/sim/dram_fifo/Makefile70
-rw-r--r--fpga/usrp3/top/n3xx/sim/dram_fifo/axis_dram_fifo_single.sv493
-rw-r--r--fpga/usrp3/top/n3xx/sim/dram_fifo/dram_fifo_tb.sv163
-rw-r--r--fpga/usrp3/top/n3xx/sim/dram_fifo_bist/Makefile70
-rw-r--r--fpga/usrp3/top/n3xx/sim/dram_fifo_bist/dram_fifo_bist_tb.sv348
-rw-r--r--fpga/usrp3/top/n3xx/sim/one_gig_eth_loopback/Makefile78
-rw-r--r--fpga/usrp3/top/n3xx/sim/one_gig_eth_loopback/demo_one_gig_pcs_pma_mdio.v489
-rw-r--r--fpga/usrp3/top/n3xx/sim/one_gig_eth_loopback/one_gig_eth_loopback_tb.sv381
-rw-r--r--fpga/usrp3/top/n3xx/sim/ten_gig_eth_loopback/Makefile84
-rw-r--r--fpga/usrp3/top/n3xx/sim/ten_gig_eth_loopback/ten_gig_eth_loopback_tb.sv527
14 files changed, 3790 insertions, 0 deletions
diff --git a/fpga/usrp3/top/n3xx/sim/arm_to_sfp_loopback/Makefile b/fpga/usrp3/top/n3xx/sim/arm_to_sfp_loopback/Makefile
new file mode 100644
index 000000000..1e783b2de
--- /dev/null
+++ b/fpga/usrp3/top/n3xx/sim/arm_to_sfp_loopback/Makefile
@@ -0,0 +1,84 @@
+#
+# 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 = zynq
+PART_ID = xc7z100/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/xge_interface/Makefile.srcs
+include $(BASE_DIR)/../lib/xge/Makefile.srcs
+include $(BASE_DIR)/../lib/packet_proc/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)/ten_gig_eth_pcs_pma/Makefile.inc
+include $(IP_DIR)/axi64_8k_2clk_fifo/Makefile.inc
+include $(IP_DIR)/axi64_4k_2clk_fifo/Makefile.inc
+
+DESIGN_SRCS += $(abspath \
+$(XGE_SRCS) \
+$(XGE_INTERFACE_SRCS) \
+$(IP_TEN_GIG_ETH_PCS_PMA_SRCS) \
+$(IP_TEN_GIGE_PHY_XCI_SRCS) \
+$(TEN_GIGE_PHY_SRCS) \
+$(IP_AXI64_8K_2CLK_FIFO_SRCS) \
+$(IP_AXI64_4K_2CLK_FIFO_SRCS) \
+$(PACKET_PROC_SRCS) \
+)
+#$(IP_FIFO_SHORT_2CLK_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 = arm_to_sfp_tb
+# Simulation runtime in microseconds
+SIM_RUNTIME_US = 30000
+
+SIM_SRCS = \
+$(abspath arm_to_sfp_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/n3xx/sim/arm_to_sfp_loopback/arm_to_sfp_tb.sv b/fpga/usrp3/top/n3xx/sim/arm_to_sfp_loopback/arm_to_sfp_tb.sv
new file mode 100644
index 000000000..46005a13a
--- /dev/null
+++ b/fpga/usrp3/top/n3xx/sim/arm_to_sfp_loopback/arm_to_sfp_tb.sv
@@ -0,0 +1,528 @@
+//
+// Copyright 2017 Ettus Research
+//
+
+
+`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_axis_lib.svh"
+`include "sim_axi4_lib.svh"
+`include "sim_set_rb_lib.svh"
+
+module arm_to_sfp_tb();
+ `TEST_BENCH_INIT("arm_to_sfp_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 = 0;
+ localparam PORTNUM = 8'd0;
+
+ // ARM to SFP Loopback Topology:
+ //
+ // TB Simulus ====> |------------| |----------------|
+ // | XgigE MAC | <===> | XgigE PCS/PMA | <====>||
+ // TB Checker <==== |------------| |----------------| || Loopback through
+ // ||
+ // ====> |------------| |----------------| || perfect serial channel
+ // Loopback | | XgigE MAC | <===> | XgigE PCS/PMA | <====>||
+ // <==== |------------| |----------------|
+
+ // Initialize DUT
+ wire xgige_refclk, xgige_clk156, xgige_dclk;
+ wire m_user_clk, s_user_clk;
+ wire m_channel_up, s_channel_up;
+
+ wire [63:0] m_xgmii_txd;
+ wire [7:0] m_xgmii_txc;
+ wire [63:0] m_xgmii_rxd;
+ wire [7:0] m_xgmii_rxc;
+ wire [63:0] s_xgmii_txd;
+ wire [7:0] s_xgmii_txc;
+ wire [63:0] s_xgmii_rxd;
+ wire [7:0] s_xgmii_rxc;
+ wire [7:0] m_xgmii_status;
+ wire [7:0] s_xgmii_status;
+ wire m_xge_phy_resetdone;
+ wire s_xge_phy_resetdone;
+ wire m_mdc, m_mdio_in, m_mdio_out;
+ wire s_mdc, s_mdio_in, s_mdio_out;
+ wire sfpp_rxlos,sfpp_tx_fault,sfpp_tx_disable;
+
+
+ wire [15:0] m_phy_status;
+ wire [15:0] s_phy_status;
+ wire [63:0] loop_tdata;
+ wire [3:0] loop_tuser;
+ wire loop_tlast, loop_tvalid, loop_tready;
+
+ wire [7:0] wb_adr_i;
+ wire wb_cyc_i;
+ wire [31:0] wb_dat_i;
+ wire wb_stb_i;
+ wire wb_we_i;
+ wire wb_ack_o;
+ wire [31:0] wb_dat_o;
+ wire wb_int_o;
+ wire [63:0] c2e_tdata_int;
+ wire [3:0] c2e_tuser_int;
+ wire c2e_tlast_int;
+ wire c2e_tvalid_int;
+ wire c2e_tready_int;
+ wire [63:0] c2e_tdata;
+ wire [3:0] c2e_tuser;
+ wire c2e_tlast;
+ wire c2e_tvalid;
+ wire c2e_tready;
+ wire m_axis_tvalid;
+ wire m_axis_tlast;
+ wire [63:0] m_axis_tdata;
+ wire m_axis_tready;
+ wire [3:0] m_axis_tuser;
+
+ reg independent_clock;
+ assign m_channel_up = m_phy_status[0];
+ assign s_channel_up = s_phy_status[0];
+ //assign m_user_clk = xgige_refclk;
+ //assign s_user_clk = xgige_refclk;
+ assign m_user_clk = independent_clock;
+ assign s_user_clk = independent_clock;
+
+ ten_gige_phy_clk_gen xgige_clk_gen_i (
+ .areset(GSR),
+ .refclk_p(XG_CLK_P),
+ .refclk_n(XG_CLK_N),
+ .refclk(xgige_refclk),
+ .clk156(xgige_clk156),
+ .dclk(xgige_dclk)
+ );
+
+ axis_master #(.DWIDTH(34)) m_axis (.clk(m_user_clk));
+ axis_slave #(.DWIDTH(68)) s_axis (.clk(s_user_clk));
+
+ initial
+ begin
+ independent_clock <= 1'b0;
+ forever
+ begin
+ independent_clock <= 1'b0;
+ #2.5;
+ independent_clock <= 1'b1;
+ #2.5;
+ end
+ end
+
+ assign sfpp_rxlos = 1'b0;
+ assign sfpp_tx_fault = 1'b0;
+
+ // Instantiate the 10GBASER/KR GT Common block
+ ten_gig_eth_pcs_pma_gt_common # (
+ .WRAPPER_SIM_GTRESET_SPEEDUP("TRUE") ) //Does not affect hardware
+ ten_gig_eth_pcs_pma_gt_common_block
+ (
+ .refclk(xgige_refclk),
+ .qpllreset(qpllreset),
+ .qplllock(qplllock),
+ .qplloutclk(qplloutclk),
+ .qplloutrefclk(qplloutrefclk),
+ .qpllrefclksel(3'b001 /*3'b101*GTSOUTHREFCLK0*/)
+ );
+
+ ten_gige_phy ten_gige_phy_master_i
+ (
+ // Clocks and Reset
+ .areset(GSR), // Asynchronous reset for entire core.
+ .refclk(xgige_refclk), // Transciever reference clock: 156.25MHz
+ .clk156(xgige_clk156), // Globally buffered core clock: 156.25MHz
+ .dclk(xgige_dclk), // Management/DRP clock: 78.125MHz
+ .sim_speedup_control(~GSR),
+ // GMII Interface (client MAC <=> PCS)
+ .xgmii_txd(m_xgmii_txd), // Transmit data from client MAC.
+ .xgmii_txc(m_xgmii_txc), // Transmit control signal from client MAC.
+ .xgmii_rxd(m_xgmii_rxd), // Received Data to client MAC.
+ .xgmii_rxc(m_xgmii_rxc), // Received control signal to client MAC.
+ // Tranceiver Interface
+ .txp(SFP_LN0_P), // Differential +ve of serial transmission from PMA to PMD.
+ .txn(SFP_LN0_N), // Differential -ve of serial transmission from PMA to PMD.
+ .rxp(SFP_LN1_P), // Differential +ve for serial reception from PMD to PMA.
+ .rxn(SFP_LN1_N), // Differential -ve for serial reception from PMD to PMA.
+ // Management: MDIO Interface
+ .mdc(m_mdc), // Management Data Clock
+ .mdio_in(m_mdio_in), // Management Data In
+ .mdio_out(m_mdio_out), // Management Data Out
+ .mdio_tri(), // Management Data Tristate
+ .prtad(5'd4), // MDIO address is 4
+ // General IO's
+ .core_status(m_xgmii_status), // Core status
+ .resetdone(m_xge_phy_resetdone),
+ .signal_detect(~sfpp_rxlos), //FIXME // Input from PMD to indicate presence of optical input. (Undocumented, but it seems Xilinx expect this to be inverted.)
+ .tx_fault(sfpp_tx_fault), //FIXME
+ .tx_disable(/*sfpp_tx_disable*/), //FIXME
+ .qpllreset(qpllreset1),
+ .qplllock(qplllock),
+ .qplloutclk(qplloutclk),
+ .qplloutrefclk(qplloutrefclk)
+
+ );
+
+ n310_xge_mac_wrapper #(.PORTNUM(PORTNUM)) xge_mac_wrapper_master_i
+ (
+ // XGMII
+ .xgmii_clk(xgige_clk156),
+ .xgmii_txd(m_xgmii_txd),
+ .xgmii_txc(m_xgmii_txc),
+ .xgmii_rxd(m_xgmii_rxd),
+ .xgmii_rxc(m_xgmii_rxc),
+ // Client FIFO Interfaces
+ .sys_clk(m_user_clk),
+ .sys_rst(GSR),
+ .rx_tdata(s_axis.axis.tdata[63:0]),
+ .rx_tuser(s_axis.axis.tdata[67:64]),
+ .rx_tlast(s_axis.axis.tlast),
+ .rx_tvalid(s_axis.axis.tvalid),
+ .rx_tready(/*s_axis.axis.tready*/1'b1),
+ .tx_tdata(c2e_tdata),
+ .tx_tuser(c2e_tuser), // Bit[3] (error) is ignored for now.
+ .tx_tlast(c2e_tlast),
+ .tx_tvalid(c2e_tvalid),
+ .tx_tready(c2e_tready),
+ // Other
+ .phy_ready(m_xge_phy_resetdone),
+ .ctrl_tx_enable (/*mac_ctrl_reg[0]*/1'b1), //FIXME: Remove hardcoded value
+ .status_crc_error (),
+ .status_fragment_error (),
+ .status_txdfifo_ovflow (),
+ .status_txdfifo_udflow (),
+ .status_rxdfifo_ovflow (),
+ .status_rxdfifo_udflow (),
+ .status_pause_frame_rx (),
+ .status_local_fault (),
+ .status_remote_fault ()
+ );
+
+ assign m_phy_status = {8'h00, m_xgmii_status};
+
+ axi_fifo32_to_fifo64 inst_axi_fifo32_to_fifo64
+ (
+ .clk(m_user_clk),
+ .reset(GSR),
+ .i_tdata({m_axis.axis.tdata[31:0]}), // endian swap
+ .i_tuser(m_axis.axis.tdata[33:32]),
+ .i_tlast(m_axis.axis.tlast),
+ .i_tvalid(m_axis.axis.tvalid),
+ .i_tready(m_axis.axis.tready),
+ .o_tdata(m_axis_tdata),
+ .o_tuser(m_axis_tuser),
+ .o_tlast(m_axis_tlast),
+ .o_tvalid(m_axis_tvalid),
+ .o_tready(m_axis_tready)
+ );
+
+ arm_framer inst_arm_framer (
+ .clk (m_user_clk),
+ .reset (GSR),
+ .clear (clear),
+ .s_axis_tdata (m_axis_tdata),
+ .s_axis_tuser (m_axis_tuser),
+ .s_axis_tlast (m_axis_tlast),
+ .s_axis_tvalid (m_axis_tvalid),
+ .s_axis_tready (m_axis_tready),
+ .m_axis_tdata (c2e_tdata_int),
+ .m_axis_tuser (c2e_tuser_int),
+ .m_axis_tlast (c2e_tlast_int),
+ .m_axis_tvalid (c2e_tvalid_int),
+ .m_axis_tready (c2e_tready_int)
+ );
+
+ axi_mux4 #(.PRIO(0), .WIDTH(68)) eth_mux
+ (.clk(m_user_clk), .reset(GSR), .clear(clear),
+ .i0_tdata({c2e_tuser_int,c2e_tdata_int}), .i0_tlast(c2e_tlast_int), .i0_tvalid(c2e_tvalid_int), .i0_tready(c2e_tready_int),
+ .i1_tdata(), .i1_tlast(), .i1_tvalid(), .i1_tready(),
+ .i2_tdata(), .i2_tlast(), .i2_tvalid(), .i2_tready(),
+ .i3_tdata(), .i3_tlast(), .i3_tvalid(1'b0), .i3_tready(),
+ .o_tdata({c2e_tuser,c2e_tdata}), .o_tlast(c2e_tlast), .o_tvalid(c2e_tvalid), .o_tready(c2e_tready));
+
+ ten_gige_phy ten_gige_phy_slave_i
+ (
+ // Clocks and Reset
+ .areset(GSR), // Asynchronous reset for entire core.
+ .refclk(xgige_refclk), // Transciever reference clock: 156.25MHz
+ .clk156(xgige_clk156), // Globally buffered core clock: 156.25MHz
+ .dclk(xgige_dclk), // Management/DRP clock: 78.125MHz
+ .sim_speedup_control(~GSR),
+ // GMII Interface (client MAC <=> PCS)
+ .xgmii_txd(s_xgmii_txd), // Transmit data from client MAC.
+ .xgmii_txc(s_xgmii_txc), // Transmit control signal from client MAC.
+ .xgmii_rxd(s_xgmii_rxd), // Received Data to client MAC.
+ .xgmii_rxc(s_xgmii_rxc), // Received control signal to client MAC.
+ // Tranceiver Interface
+ .txp(SFP_LN1_P), // Differential +ve of serial transmission from PMA to PMD.
+ .txn(SFP_LN1_N), // Differential -ve of serial transmission from PMA to PMD.
+ .rxp(SFP_LN0_P), // Differential +ve for serial reception from PMD to PMA.
+ .rxn(SFP_LN0_N), // Differential -ve for serial reception from PMD to PMA.
+ // Management: MDIO Interface
+ .mdc(s_mdc), // Management Data Clock
+ .mdio_in(s_mdio_in), // Management Data In
+ .mdio_out(s_mdio_out), // Management Data Out
+ .mdio_tri(), // Management Data Tristate
+ .prtad(5'd4), // MDIO address is 4
+ // General IO's
+ .core_status(s_xgmii_status), // Core status
+ .resetdone(s_xge_phy_resetdone),
+ .signal_detect(~sfpp_rxlos), //FIXME // Input from PMD to indicate presence of optical input. (Undocumented, but it seems Xilinx expect this to be inverted.)
+ .tx_fault(sfpp_tx_fault), //FIXME
+ .tx_disable(/*sfpp_tx_disable*/), //FIXME
+ .qpllreset(qpllreset2),
+ .qplllock(qplllock),
+ .qplloutclk(qplloutclk),
+ .qplloutrefclk(qplloutrefclk)
+ );
+
+ n310_xge_mac_wrapper #(.PORTNUM(PORTNUM)) xge_mac_wrapper_slave_i
+ (
+ // XGMII
+ .xgmii_clk(xgige_clk156),
+ .xgmii_txd(s_xgmii_txd),
+ .xgmii_txc(s_xgmii_txc),
+ .xgmii_rxd(s_xgmii_rxd),
+ .xgmii_rxc(s_xgmii_rxc),
+ // Client FIFO Interfaces
+ .sys_clk(s_user_clk),
+ .sys_rst(GSR),
+ .rx_tdata(loop_tdata),
+ .rx_tuser(loop_tuser),
+ .rx_tlast(loop_tlast),
+ .rx_tvalid(loop_tvalid),
+ .rx_tready(loop_tready),
+ .tx_tdata(loop_tdata),
+ .tx_tuser(loop_tuser), // Bit[3] (error) is ignored for now.
+ .tx_tlast(loop_tlast),
+ .tx_tvalid(loop_tvalid),
+ .tx_tready(loop_tready),
+ // Other
+ .phy_ready(s_xge_phy_resetdone),
+ .ctrl_tx_enable (/*mac_ctrl_reg[0]*/1'b1), //FIXME: Remove hardcoded value
+ .status_crc_error (),
+ .status_fragment_error (),
+ .status_txdfifo_ovflow (),
+ .status_txdfifo_udflow (),
+ .status_rxdfifo_ovflow (),
+ .status_rxdfifo_udflow (),
+ .status_pause_frame_rx (),
+ .status_local_fault (),
+ .status_remote_fault ()
+ );
+
+ assign s_phy_status = {8'h00, s_xgmii_status};
+
+ //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
+ `TEST_CASE_START("Wait for reset");
+ m_axis.reset;
+ while (GSR) @(posedge XG_CLK_P);
+ `TEST_CASE_DONE((~GSR));
+
+ m_axis.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);
+
+ repeat(2000) @(posedge m_user_clk);
+
+ //`TEST_CASE_START("Test Ethernet packet");
+ // s_axis.axis.tready = 0;
+ // m_axis.push_word({4'b0, 64'h0000_0000_0000_ffff}, 1'b0);
+ // s_axis.axis.tready = 1;
+ // m_axis.push_word({4'b0, 64'hffff_ffff_ce20_ad1b}, 1'b0);
+ // m_axis.push_word({4'b0, 64'hc57a_0806_0001_0800}, 1'b0);
+ // m_axis.push_word({4'b0, 64'h0604_0001_ce20_ad1b}, 1'b0);
+ // m_axis.push_word({4'b0, 64'hc57a_c0a8_0a64_0000}, 1'b0);
+ // m_axis.push_word({4'b0, 64'h0000_0000_c0a8_0a0a}, 1'b1);
+ //`TEST_CASE_DONE(1'b1);
+ //`TEST_CASE_START("Test Ethernet packet");
+ // s_axis.axis.tready = 0;
+ // m_axis.push_word({4'b0, 64'hffff_ffff_ffff_ce20}, 1'b0);
+ // s_axis.axis.tready = 1;
+ // m_axis.push_word({4'b0, 64'had1b_c57a_0806_0001}, 1'b0);
+ // m_axis.push_word({4'b0, 64'h0800_0604_0001_ce20}, 1'b0);
+ // m_axis.push_word({4'b0, 64'had1b_c57a_c0a8_0a64}, 1'b0);
+ // m_axis.push_word({4'b0, 64'h0000_0000_0000_c0a8}, 1'b0);
+ // m_axis.push_word({4'd2, 64'h0a0a_1111_1111_1111}, 1'b1);
+ //`TEST_CASE_DONE(1'b1);
+ // repeat(2000) @(posedge m_user_clk);
+ `TEST_CASE_START("Test Ethernet packet");
+ s_axis.axis.tready = 0;
+ m_axis.push_word({2'b0, 32'hffff_ffff}, 1'b0);
+ s_axis.axis.tready = 1;
+ m_axis.push_word({2'b0, 32'hffff_9aa9}, 1'b0);
+ m_axis.push_word({2'b0, 32'h6400_e341}, 1'b0);
+ m_axis.push_word({2'b0, 32'h0800_4500}, 1'b0);
+ m_axis.push_word({2'b0, 32'h0148_0000}, 1'b0);
+ m_axis.push_word({2'b0, 32'h0000_4011}, 1'b0);
+ m_axis.push_word({2'b0, 32'h79a6_0000}, 1'b0);
+ m_axis.push_word({2'b0, 32'h0000_ffff}, 1'b0);
+ m_axis.push_word({2'b0, 32'hffff_0044}, 1'b0);
+ m_axis.push_word({2'b0, 32'h0043_0134}, 1'b0);
+ m_axis.push_word({2'b0, 32'h90be_0101}, 1'b0);
+ m_axis.push_word({2'b0, 32'h0600_d2ab}, 1'b0);
+ m_axis.push_word({2'b0, 32'h9f01_0007}, 1'b0);
+ m_axis.push_word({2'b0, 32'h0000_0000}, 1'b0);
+ m_axis.push_word({2'b0, 32'h0000_0000}, 1'b0);
+ m_axis.push_word({2'b0, 32'h0000_0000}, 1'b0);
+ m_axis.push_word({2'b0, 32'h0000_0000}, 1'b0);
+ m_axis.push_word({2'b0, 32'h0000_9aa9}, 1'b0);
+ m_axis.push_word({2'b0, 32'h6400_e341}, 1'b0);
+ m_axis.push_word({2'b0, 32'h0000_0000}, 1'b0);
+ m_axis.push_word({2'b0, 32'h0000_0000}, 1'b0);
+ m_axis.push_word({2'b0, 32'h0000_0000}, 1'b0);
+ m_axis.push_word({2'b0, 32'h0000_0000}, 1'b0);
+ m_axis.push_word({2'b0, 32'h0000_0000}, 1'b0);
+ m_axis.push_word({2'b0, 32'h0000_0000}, 1'b0);
+ m_axis.push_word({2'b0, 32'h0000_0000}, 1'b0);
+ m_axis.push_word({2'b0, 32'h0000_0000}, 1'b0);
+ m_axis.push_word({2'b0, 32'h0000_0000}, 1'b0);
+ m_axis.push_word({2'b0, 32'h0000_0000}, 1'b0);
+ m_axis.push_word({2'b0, 32'h0000_0000}, 1'b0);
+ m_axis.push_word({2'b0, 32'h0000_0000}, 1'b0);
+ m_axis.push_word({2'b0, 32'h0000_0000}, 1'b0);
+ m_axis.push_word({2'b0, 32'h0000_0000}, 1'b0);
+ m_axis.push_word({2'b0, 32'h0000_0000}, 1'b0);
+ m_axis.push_word({2'b0, 32'h0000_0000}, 1'b0);
+ m_axis.push_word({2'b0, 32'h0000_0000}, 1'b0);
+ m_axis.push_word({2'b0, 32'h0000_0000}, 1'b0);
+ m_axis.push_word({2'b0, 32'h0000_0000}, 1'b0);
+ m_axis.push_word({2'b0, 32'h0000_0000}, 1'b0);
+ m_axis.push_word({2'b0, 32'h0000_0000}, 1'b0);
+ m_axis.push_word({2'b0, 32'h0000_0000}, 1'b0);
+ m_axis.push_word({2'b0, 32'h0000_0000}, 1'b0);
+ m_axis.push_word({2'b0, 32'h0000_0000}, 1'b0);
+ m_axis.push_word({2'b0, 32'h0000_0000}, 1'b0);
+ m_axis.push_word({2'b0, 32'h0000_0000}, 1'b0);
+ m_axis.push_word({2'b0, 32'h0000_0000}, 1'b0);
+ m_axis.push_word({2'b0, 32'h0000_0000}, 1'b0);
+ m_axis.push_word({2'b0, 32'h0000_0000}, 1'b0);
+ m_axis.push_word({2'b0, 32'h0000_0000}, 1'b0);
+ m_axis.push_word({2'b0, 32'h0000_0000}, 1'b0);
+ m_axis.push_word({2'b0, 32'h0000_0000}, 1'b0);
+ m_axis.push_word({2'b0, 32'h0000_0000}, 1'b0);
+ m_axis.push_word({2'b0, 32'h0000_0000}, 1'b0);
+ m_axis.push_word({2'b0, 32'h0000_0000}, 1'b0);
+ m_axis.push_word({2'b0, 32'h0000_0000}, 1'b0);
+ m_axis.push_word({2'b0, 32'h0000_0000}, 1'b0);
+ m_axis.push_word({2'b0, 32'h0000_0000}, 1'b0);
+ m_axis.push_word({2'b0, 32'h0000_0000}, 1'b0);
+ m_axis.push_word({2'b0, 32'h0000_0000}, 1'b0);
+ m_axis.push_word({2'b0, 32'h0000_0000}, 1'b0);
+ m_axis.push_word({2'b0, 32'h0000_0000}, 1'b0);
+ m_axis.push_word({2'b0, 32'h0000_0000}, 1'b0);
+ m_axis.push_word({2'b0, 32'h0000_0000}, 1'b0);
+ m_axis.push_word({2'b0, 32'h0000_0000}, 1'b0);
+ m_axis.push_word({2'b0, 32'h0000_0000}, 1'b0);
+ m_axis.push_word({2'b0, 32'h0000_0000}, 1'b0);
+ m_axis.push_word({2'b0, 32'h0000_0000}, 1'b0);
+ m_axis.push_word({2'b0, 32'h0000_0000}, 1'b0);
+ m_axis.push_word({2'b0, 32'h0000_0000}, 1'b0);
+ m_axis.push_word({2'b0, 32'h0000_6382}, 1'b0);
+ m_axis.push_word({2'b0, 32'h5363_3501}, 1'b0);
+ m_axis.push_word({2'b0, 32'h013d_0701}, 1'b0);
+ m_axis.push_word({2'b0, 32'h9aa9_6400}, 1'b0);
+ m_axis.push_word({2'b0, 32'he341_3902}, 1'b0);
+ m_axis.push_word({2'b0, 32'h0240_3707}, 1'b0);
+ m_axis.push_word({2'b0, 32'h0103_060c}, 1'b0);
+ m_axis.push_word({2'b0, 32'h0f1c_2a3c}, 1'b0);
+ m_axis.push_word({2'b0, 32'h0c75_6468}, 1'b0);
+ m_axis.push_word({2'b0, 32'h6370_2031}, 1'b0);
+ m_axis.push_word({2'b0, 32'h2e32_342e}, 1'b0);
+ m_axis.push_word({2'b0, 32'h31ff_0000}, 1'b0);
+ m_axis.push_word({2'b0, 32'h0000_0000}, 1'b0);
+ m_axis.push_word({2'b0, 32'h0000_0000}, 1'b0);
+ m_axis.push_word({2'b0, 32'h0000_0000}, 1'b0);
+ m_axis.push_word({2'b0, 32'h0000_0000}, 1'b0);
+ m_axis.push_word({2'd2, 32'h0000_0000}, 1'b1);
+
+ `TEST_CASE_DONE(1'b1);
+
+ repeat(2000) @(posedge m_user_clk);
+
+ `TEST_CASE_START("Test Ethernet packet");
+ s_axis.axis.tready = 0;
+ m_axis.push_word({2'b0, 32'h01005e7f }, 1'b0);
+ s_axis.axis.tready = 1;
+ m_axis.push_word({2'b0, 32'hfffa90e2 }, 1'b0);
+ m_axis.push_word({2'b0, 32'hba3aa7e8 }, 1'b0);
+ m_axis.push_word({2'b0, 32'h08004500 }, 1'b0);
+ m_axis.push_word({2'b0, 32'h00c7515e }, 1'b0);
+ m_axis.push_word({2'b0, 32'h40000111 }, 1'b0);
+ m_axis.push_word({2'b0, 32'h6d1bc0a8 }, 1'b0);
+ m_axis.push_word({2'b0, 32'h0a0aefff }, 1'b0);
+ m_axis.push_word({2'b0, 32'hfffad40f }, 1'b0);
+ m_axis.push_word({2'b0, 32'h076c00b3 }, 1'b0);
+ m_axis.push_word({2'b0, 32'hbb714d2d }, 1'b0);
+ m_axis.push_word({2'b0, 32'h53454152 }, 1'b0);
+ m_axis.push_word({2'b0, 32'h4348202a }, 1'b0);
+ m_axis.push_word({2'b0, 32'h20485454 }, 1'b0);
+ m_axis.push_word({2'b0, 32'h502f312e }, 1'b0);
+ m_axis.push_word({2'b0, 32'h310d0a48 }, 1'b0);
+ m_axis.push_word({2'b0, 32'h4f53543a }, 1'b0);
+ m_axis.push_word({2'b0, 32'h20323339 }, 1'b0);
+ m_axis.push_word({2'b0, 32'h2e323535 }, 1'b0);
+ m_axis.push_word({2'b0, 32'h2e323535 }, 1'b0);
+ m_axis.push_word({2'b0, 32'h2e323530 }, 1'b0);
+ m_axis.push_word({2'b0, 32'h3a313930 }, 1'b0);
+ m_axis.push_word({2'b0, 32'h300d0a4d }, 1'b0);
+ m_axis.push_word({2'b0, 32'h414e3a20 }, 1'b0);
+ m_axis.push_word({2'b0, 32'h22737364 }, 1'b0);
+ m_axis.push_word({2'b0, 32'h703a6469 }, 1'b0);
+ m_axis.push_word({2'b0, 32'h73636f76 }, 1'b0);
+ m_axis.push_word({2'b0, 32'h6572220d }, 1'b0);
+ m_axis.push_word({2'b0, 32'h0a4d583a }, 1'b0);
+ m_axis.push_word({2'b0, 32'h20310d0a }, 1'b0);
+ m_axis.push_word({2'b0, 32'h53543a20 }, 1'b0);
+ m_axis.push_word({2'b0, 32'h75726e3a }, 1'b0);
+ m_axis.push_word({2'b0, 32'h6469616c }, 1'b0);
+ m_axis.push_word({2'b0, 32'h2d6d756c }, 1'b0);
+ m_axis.push_word({2'b0, 32'h74697363 }, 1'b0);
+ m_axis.push_word({2'b0, 32'h7265656e }, 1'b0);
+ m_axis.push_word({2'b0, 32'h2d6f7267 }, 1'b0);
+ m_axis.push_word({2'b0, 32'h3a736572 }, 1'b0);
+ m_axis.push_word({2'b0, 32'h76696365 }, 1'b0);
+ m_axis.push_word({2'b0, 32'h3a646961 }, 1'b0);
+ m_axis.push_word({2'b0, 32'h6c3a310d }, 1'b0);
+ m_axis.push_word({2'b0, 32'h0a555345 }, 1'b0);
+ m_axis.push_word({2'b0, 32'h522d4147 }, 1'b0);
+ m_axis.push_word({2'b0, 32'h454e543a }, 1'b0);
+ m_axis.push_word({2'b0, 32'h20476f6f }, 1'b0);
+ m_axis.push_word({2'b0, 32'h676c6520 }, 1'b0);
+ m_axis.push_word({2'b0, 32'h4368726f }, 1'b0);
+ m_axis.push_word({2'b0, 32'h6d652f35 }, 1'b0);
+ m_axis.push_word({2'b0, 32'h342e302e }, 1'b0);
+ m_axis.push_word({2'b0, 32'h32383430 }, 1'b0);
+ m_axis.push_word({2'b0, 32'h2e353920 }, 1'b0);
+ m_axis.push_word({2'b0, 32'h4c696e75 }, 1'b0);
+ m_axis.push_word({2'b1, 32'h78111111 }, 1'b1);
+
+ `TEST_CASE_DONE(1'b1);
+ end
+
+endmodule
diff --git a/fpga/usrp3/top/n3xx/sim/aurora_loopback/Makefile b/fpga/usrp3/top/n3xx/sim/aurora_loopback/Makefile
new file mode 100644
index 000000000..c4cdf38dd
--- /dev/null
+++ b/fpga/usrp3/top/n3xx/sim/aurora_loopback/Makefile
@@ -0,0 +1,80 @@
+#
+# 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 = zynq
+PART_ID = xc7z100/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) \
+../../n3xx_npio_qsfp_wrapper.v \
+../../n3xx_mgt_io_core.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)/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) \
+$(AURORA_PHY_1_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/n3xx/sim/aurora_loopback/aurora_loopback_tb.sv b/fpga/usrp3/top/n3xx/sim/aurora_loopback/aurora_loopback_tb.sv
new file mode 100644
index 000000000..ed328f153
--- /dev/null
+++ b/fpga/usrp3/top/n3xx/sim/aurora_loopback/aurora_loopback_tb.sv
@@ -0,0 +1,395 @@
+/////////////////////////////////////////////////////////////////
+//
+// Copyright 2018 Ettus Research, A National Instruments Company
+//
+// SPDX-License-Identifier: LGPL-3.0-or-later
+//
+/////////////////////////////////////////////////////////////////
+
+
+
+`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_CLK(bus_clk, 1000/200, 50) //define 200 MHz bus clk
+ `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
+ // ||
+ //
+ // |-------------------------------------|
+ // | n3xx_npio_qsfp_wrapper |
+ // ====> |------------| |----------------| || perfect serial channel
+ // Loopback | | Aurora MAC | <===> | Aurora PCS/PMA | <====>||
+ // <==== |------------| |----------------|
+ // |-------------------------------------|
+
+ // Initialize DUT
+ wire aurora_refclk, aurora_init_clk;
+ wire aurora_clk156;
+ 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;
+ wire s_link_up;
+
+(* dont_touch = "true" *) IBUFDS_GTE2 aurora_refclk_ibuf (
+ .ODIV2(),
+ .CEB (1'b0),
+ .I (XG_CLK_P),
+ .IB(XG_CLK_N),
+ .O (aurora_refclk)
+ );
+
+ aurora_phy_clk_gen aurora_clk_gen_i (
+ .refclk_ibuf(aurora_refclk),
+ .clk156(aurora_clk156),
+ .init_clk(aurora_init_clk)
+ );
+ wire qpllreset, qpllreset_slave;
+ wire qplllock, qplllock_slave;
+ wire qplloutclk, qplloutclk_slave;
+ wire qplloutrefclk, qplloutrefclk_slave;
+ wire qpllrefclklost, qpllrefclklost_slave;
+ wire [7:0] qpll_drpaddr_in_i = 8'h0;
+ wire [15:0] qpll_drpdi_in_i = 16'h0;
+ wire qpll_drpen_in_i = 1'b0;
+ wire qpll_drpwe_in_i = 1'b0;
+ wire [15:0] qpll_drpdo_out_i, qpll_drpdo_out_s_i;
+ wire qpll_drprdy_out_i, qpll_drprdy_out_s_i;
+
+ aurora_64b66b_pcs_pma_gt_common_wrapper gt_common_support (
+ .gt_qpllclk_quad1_out (qplloutclk), //to sfp
+ .gt_qpllrefclk_quad1_out (qplloutrefclk), // to sfp
+ .GT0_GTREFCLK0_COMMON_IN (aurora_refclk),
+//----------------------- Common Block - QPLL Ports ------------------------
+ .GT0_QPLLLOCK_OUT (qplllock), //from 1st sfp
+ .GT0_QPLLRESET_IN (qpllreset), //from 1st sfp
+ .GT0_QPLLLOCKDETCLK_IN (aurora_init_clk),
+ .GT0_QPLLREFCLKLOST_OUT (qpllrefclklost), //from 1st sfp
+//---------------------- Common DRP Ports ---------------------- //not really used???
+ .qpll_drpaddr_in (qpll_drpaddr_in_i),
+ .qpll_drpdi_in (qpll_drpdi_in_i),
+ .qpll_drpclk_in (aurora_init_clk),
+ .qpll_drpdo_out (qpll_drpdo_out_i),
+ .qpll_drprdy_out (qpll_drprdy_out_i),
+ .qpll_drpen_in (qpll_drpen_in_i),
+ .qpll_drpwe_in (qpll_drpwe_in_i)
+ );
+
+ wire au_master_tx_out_clk, au_slave_tx_out_clk;
+ wire au_master_gt_pll_lock, au_slave_gt_pll_lock;
+ wire au_user_clk, au_sync_clk, au_mmcm_locked;
+ wire au_s_user_clk, au_s_sync_clk, au_s_mmcm_locked;
+ wire au_master_phy_reset;
+
+ aurora_phy_mmcm aurora_phy_mmcm_0 (
+ .aurora_tx_clk_unbuf(au_master_tx_out_clk),
+ .mmcm_reset(!au_master_gt_pll_lock),
+ .user_clk(au_user_clk),
+ .sync_clk(au_sync_clk),
+ .mmcm_locked(au_mmcm_locked)
+ );
+
+ 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;
+ reg [31:0] 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(au_user_clk));
+ cvita_slave m_rx_chdr (.clk(au_user_clk));
+
+ aurora_phy_x1 #(.SIMULATION(1)) aurora_phy_master_i (
+ // Resets
+ .areset(GSR),
+ // Clocks
+ .refclk(aurora_refclk),
+ .qpllclk(qplloutclk),
+ .qpllrefclk(qplloutrefclk),
+ .user_clk(au_user_clk),
+ .sync_clk(au_sync_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),
+ .qplllock(qplllock),
+ .qpllreset(qpllreset),
+ .qpllrefclklost(qpllrefclklost),
+ .tx_out_clk(au_master_tx_out_clk),
+ .gt_pll_lock(au_master_gt_pll_lock),
+ .mmcm_locked(au_mmcm_locked)
+ );
+
+ aurora_axis_mac #(.PACKET_MODE(PACKET_MODE), .BIST_ENABLED(1)) aurora_mac_master_i (
+ // Clocks and resets
+ .phy_clk(au_user_clk), .phy_rst(m_user_rst),
+ .sys_clk(au_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)
+ );
+
+reg reg_wr_req_s;
+reg [13:0] reg_wr_addr_s;
+reg [31:0] reg_wr_data_s;
+reg reg_rd_req_s;
+reg [13:0] reg_rd_addr_s;
+wire reg_rd_resp_s;
+wire [31:0] reg_rd_data_s;
+
+n3xx_npio_qsfp_wrapper #(
+ .LANES(1), // Number of lanes of Aurora to instantiate (Supported = {1,2,3,4})
+ .REG_BASE(32'h0), // Base register address
+ .PORTNUM_BASE(4), // Base port number for discovery
+ .REG_DWIDTH(32), // Width of regport address bus
+ .REG_AWIDTH(14) // Width of regport data bus
+) qsfp_wrapper_inst (
+ // Clocks and Resets
+ .areset(GSR),
+ .bus_clk(bus_clk),
+ .misc_clk(aurora_init_clk),
+ .bus_rst(GSR),
+ .gt_refclk(aurora_refclk),
+ .gt_clk156(aurora_clk156),
+ // Serial lanes
+ .txp(SFP_LN1_P),
+ .txn(SFP_LN1_N),
+ .rxp(SFP_LN0_P),
+ .rxn(SFP_LN0_N),
+ // AXIS input interface
+ .s_axis_tdata(loop_tdata),
+ .s_axis_tlast(loop_tlast),
+ .s_axis_tvalid(~s_bist_loopback & loop_tvalid),
+ .s_axis_tready(loop_tready),
+ // AXIS output interface
+ .m_axis_tdata(loop_tdata),
+ .m_axis_tlast(loop_tlast),
+ .m_axis_tvalid(loop_tvalid),
+ .m_axis_tready(~s_bist_loopback & loop_tready),
+ // Register ports
+ .reg_wr_req(reg_wr_req_s), //input reg_wr_req,
+ .reg_wr_addr(reg_wr_addr_s), //input [REG_AWIDTH-1:0] reg_wr_addr,
+ .reg_wr_data(reg_wr_data_s), //input [REG_DWIDTH-1:0] reg_wr_data,
+ .reg_rd_req(reg_rd_req_s), //input reg_rd_req,
+ .reg_rd_addr(reg_rd_addr_s), //input [REG_AWIDTH-1:0] reg_rd_addr,
+ .reg_rd_resp(reg_rd_resp_s), //output reg_rd_resp,
+ .reg_rd_data(reg_rd_data_s), //output [REG_DWIDTH-1:0] reg_rd_data,
+
+ .link_up(s_link_up),
+ .activity()
+);
+
+ //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
+ `TEST_CASE_START("Wait for reset");
+ while (GSR) @(posedge aurora_refclk);
+ `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 au_user_clk);
+ `TEST_CASE_DONE(1'b1);
+
+ `TEST_CASE_START("Wait for slave channel to come up. Uses QSFP Wrapper");
+ while (s_link_up !== 1'b1) @(posedge bus_clk);
+ `TEST_CASE_DONE(1'b1);
+
+ `TEST_CASE_START("Run PRBS BIST");
+ s_bist_loopback <= PACKET_MODE;
+ $display("Need to interact with regport to set s_bist_loopback.");
+ reg_wr_req_s <= 1;
+ reg_wr_addr_s <= 4;
+ reg_wr_data_s <= 4;
+ @(posedge bus_clk);
+ repeat (3) @(posedge au_user_clk);
+ reg_wr_req_s <= 0;
+ m_bist_rate <= 6'd60;
+ m_bist_gen <= 1'b1;
+ m_bist_check <= 1'b1;
+ @(posedge au_user_clk);
+ while (m_bist_locked !== 1'b1) @(posedge au_user_clk);
+ repeat (512) @(posedge au_user_clk);
+ `ASSERT_ERROR(m_bist_samps>256, "BIST: Num samples incorrect");
+ `ASSERT_ERROR(m_bist_errors===36'd0, "BIST: Errors!");
+ @(posedge au_user_clk);
+ m_bist_gen <= 1'b0;
+ repeat (256) @(posedge au_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");
+ `ASSERT_ERROR(header.src_sid==header_out.src_sid, "Bad packet: Wrong Src SID");
+ `ASSERT_ERROR(header.dst_sid==header_out.dst_sid, "Bad packet: Wrong Dst SID");
+ `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");
+ `ASSERT_ERROR(header.src_sid==header_out.src_sid, "Bad packet: Wrong Src SID");
+ `ASSERT_ERROR(header.dst_sid==header_out.dst_sid, "Bad packet: Wrong Dst SID");
+ `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 au_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==201, "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==21, "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)");
+ reg_rd_req_s <= 1;
+ reg_rd_addr_s <= 'h20;
+ @(posedge reg_rd_resp_s)
+ reg_rd_req_s <= 0;
+ s_overruns <= reg_rd_data_s;
+ `TEST_CASE_DONE((s_overruns === 32'd0));
+
+ s_bist_loopback <= 1'b1;
+
+ `TEST_CASE_START("Run PRBS BIST (Loopback Mode)");
+ @(posedge au_user_clk);
+ m_bist_gen <= 1'b1;
+ m_bist_rate <= 6'd60;
+ m_bist_check <= 1'b1;
+ @(posedge au_user_clk);
+ while (m_bist_locked !== 1'b1) @(posedge au_user_clk);
+ repeat (512) @(posedge au_user_clk);
+ `ASSERT_ERROR(m_bist_samps>256, "BIST: Num samples incorrect");
+ `ASSERT_ERROR(m_bist_errors===36'd0, "BIST: Errors!");
+ @(posedge au_user_clk);
+ m_bist_gen <= 1'b0;
+ repeat (256) @(posedge au_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)");
+ reg_rd_req_s <= 1;
+ reg_rd_addr_s <= 'h20;
+ @(posedge reg_rd_resp_s)
+ reg_rd_req_s <= 0;
+ s_overruns <= reg_rd_data_s;
+ `TEST_CASE_DONE((s_overruns === 32'd0));
+
+ `TEST_BENCH_DONE;
+ end
+
+endmodule
diff --git a/fpga/usrp3/top/n3xx/sim/dram_fifo/Makefile b/fpga/usrp3/top/n3xx/sim/dram_fifo/Makefile
new file mode 100644
index 000000000..738cb12dc
--- /dev/null
+++ b/fpga/usrp3/top/n3xx/sim/dram_fifo/Makefile
@@ -0,0 +1,70 @@
+#
+# 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 = zynq
+PART_ID = xc7z100/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_4x64_256_bd/Makefile.inc
+include $(IP_DIR)/fifo_short_2clk/Makefile.inc
+include $(IP_DIR)/fifo_4k_2clk/Makefile.inc
+
+DESIGN_SRCS += $(abspath \
+$(IP_DDR3_32BIT_SRCS) \
+$(IP_AXI_INTERCON_4X64_256_SRCS) \
+$(IP_AXI_INTERCON_4X64_256_BD_SRCS) \
+$(IP_FIFO_4K_2CLK_SRCS) \
+$(IP_FIFO_SHORT_2CLK_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/n3xx/sim/dram_fifo/axis_dram_fifo_single.sv b/fpga/usrp3/top/n3xx/sim/dram_fifo/axis_dram_fifo_single.sv
new file mode 100644
index 000000000..63bea218e
--- /dev/null
+++ b/fpga/usrp3/top/n3xx/sim/dram_fifo/axis_dram_fifo_single.sv
@@ -0,0 +1,493 @@
+//
+// Copyright 2015 Ettus Research LLC
+//
+
+`timescale 1ns/1ps
+
+module axis_dram_fifo_single
+#(
+ parameter DIFF_CLK = 0,
+ parameter SR_BASE = 0
+) (
+ input bus_clk,
+ input bus_rst,
+ input sys_clk_p,
+ input sys_clk_n,
+ input sys_rst_n,
+ input dma_engine_clk,
+
+ 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
+);
+
+ 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
+
+ // Misc declarations
+ axi4_rd_t #(.DWIDTH(64), .AWIDTH(32), .IDWIDTH(1)) dma_axi_rd(.clk(dma_engine_clk));
+ axi4_wr_t #(.DWIDTH(64), .AWIDTH(32), .IDWIDTH(1)) dma_axi_wr(.clk(dma_engine_clk));
+ axi4_rd_t #(.DWIDTH(256), .AWIDTH(32), .IDWIDTH(4)) mig_axi_rd(.clk(ddr3_axi_clk));
+ axi4_wr_t #(.DWIDTH(256), .AWIDTH(32), .IDWIDTH(4)) mig_axi_wr(.clk(ddr3_axi_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 [15: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.
+
+ always @(posedge ddr3_axi_clk)
+ ddr3_axi_rst_reg_n <= ~ddr3_axi_rst;
+
+ axi_dma_fifo #(
+ .DEFAULT_BASE(30'h02000000),
+ .DEFAULT_MASK(30'hFF000000),
+ .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 (dma_engine_clk),
+ .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()
+ );
+
+ //---------------------------------------------------
+ // We use an interconnect to connect to FIFOs.
+ //---------------------------------------------------
+ // Attach to third slave just to validate proper ID handling in interconnect
+
+ axi_intercon_4x64_256_bd_wrapper axi_intercon_i (
+ //
+ .S00_AXI_ACLK (dma_engine_clk), // input S01_AXI_ACLK
+ .S00_AXI_ARESETN (~ddr3_axi_rst), // input S01_AXI_ARESETN
+ .S00_AXI_AWID (0), // input [0 : 0] S01_AXI_AWID
+ .S00_AXI_AWADDR (0), // input [31 : 0] S01_AXI_AWADDR
+ .S00_AXI_AWLEN (0), // input [7 : 0] S01_AXI_AWLEN
+ .S00_AXI_AWSIZE (0), // input [2 : 0] S01_AXI_AWSIZE
+ .S00_AXI_AWBURST (0), // input [1 : 0] S01_AXI_AWBURST
+ .S00_AXI_AWLOCK (0), // input S01_AXI_AWLOCK
+ .S00_AXI_AWCACHE (0), // input [3 : 0] S01_AXI_AWCACHE
+ .S00_AXI_AWPROT (0), // input [2 : 0] S01_AXI_AWPROT
+ .S00_AXI_AWQOS (0), // input [3 : 0] S01_AXI_AWQOS
+ .S00_AXI_AWVALID (0), // input S01_AXI_AWVALID
+ .S00_AXI_AWREADY (), // output S01_AXI_AWREADY
+ .S00_AXI_WDATA (0), // input [63 : 0] S01_AXI_WDATA
+ .S00_AXI_WSTRB (0), // input [7 : 0] S01_AXI_WSTRB
+ .S00_AXI_WLAST (0), // input S01_AXI_WLAST
+ .S00_AXI_WVALID (0), // input S01_AXI_WVALID
+ .S00_AXI_WREADY (), // output S01_AXI_WREADY
+ .S00_AXI_BID (), // output [0 : 0] S01_AXI_BID
+ .S00_AXI_BRESP (), // output [1 : 0] S01_AXI_BRESP
+ .S00_AXI_BVALID (), // output S01_AXI_BVALID
+ .S00_AXI_BREADY (1), // input S01_AXI_BREADY
+ .S00_AXI_ARID (0), // input [0 : 0] S01_AXI_ARID
+ .S00_AXI_ARADDR (0), // input [31 : 0] S01_AXI_ARADDR
+ .S00_AXI_ARLEN (0), // input [7 : 0] S01_AXI_ARLEN
+ .S00_AXI_ARSIZE (0), // input [2 : 0] S01_AXI_ARSIZE
+ .S00_AXI_ARBURST (0), // input [1 : 0] S01_AXI_ARBURST
+ .S00_AXI_ARLOCK (0), // input S01_AXI_ARLOCK
+ .S00_AXI_ARCACHE (0), // input [3 : 0] S01_AXI_ARCACHE
+ .S00_AXI_ARPROT (0), // input [2 : 0] S01_AXI_ARPROT
+ .S00_AXI_ARQOS (0), // input [3 : 0] S01_AXI_ARQOS
+ .S00_AXI_ARVALID (0), // input S01_AXI_ARVALID
+ .S00_AXI_ARREADY (), // output S01_AXI_ARREADY
+ .S00_AXI_RID (), // output [0 : 0] S01_AXI_RID
+ .S00_AXI_RDATA (), // output [63 : 0] S01_AXI_RDATA
+ .S00_AXI_RRESP (), // output [1 : 0] S01_AXI_RRESP
+ .S00_AXI_RLAST (), // output S01_AXI_RLAST
+ .S00_AXI_RVALID (), // output S01_AXI_RVALID
+ .S00_AXI_RREADY (1), // input S01_AXI_RREADY
+ //
+ .S01_AXI_ACLK (dma_engine_clk), // 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 (1), // 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 (1), // input S01_AXI_RREADY
+ //
+ .S02_AXI_ACLK (dma_engine_clk), // input S01_AXI_ACLK
+ .S02_AXI_ARESETN (~ddr3_axi_rst), // input S01_AXI_ARESETN
+ .S02_AXI_AWID (0), // input [0 : 0] S01_AXI_AWID
+ .S02_AXI_AWADDR (0), // input [31 : 0] S01_AXI_AWADDR
+ .S02_AXI_AWLEN (0), // input [7 : 0] S01_AXI_AWLEN
+ .S02_AXI_AWSIZE (0), // input [2 : 0] S01_AXI_AWSIZE
+ .S02_AXI_AWBURST (0), // input [1 : 0] S01_AXI_AWBURST
+ .S02_AXI_AWLOCK (0), // input S01_AXI_AWLOCK
+ .S02_AXI_AWCACHE (0), // input [3 : 0] S01_AXI_AWCACHE
+ .S02_AXI_AWPROT (0), // input [2 : 0] S01_AXI_AWPROT
+ .S02_AXI_AWQOS (0), // input [3 : 0] S01_AXI_AWQOS
+ .S02_AXI_AWVALID (0), // input S01_AXI_AWVALID
+ .S02_AXI_AWREADY (), // output S01_AXI_AWREADY
+ .S02_AXI_WDATA (0), // input [63 : 0] S01_AXI_WDATA
+ .S02_AXI_WSTRB (0), // input [7 : 0] S01_AXI_WSTRB
+ .S02_AXI_WLAST (0), // input S01_AXI_WLAST
+ .S02_AXI_WVALID (0), // input S01_AXI_WVALID
+ .S02_AXI_WREADY (), // output S01_AXI_WREADY
+ .S02_AXI_BID (), // output [0 : 0] S01_AXI_BID
+ .S02_AXI_BRESP (), // output [1 : 0] S01_AXI_BRESP
+ .S02_AXI_BVALID (), // output S01_AXI_BVALID
+ .S02_AXI_BREADY (1), // input S01_AXI_BREADY
+ .S02_AXI_ARID (0), // input [0 : 0] S01_AXI_ARID
+ .S02_AXI_ARADDR (0), // input [31 : 0] S01_AXI_ARADDR
+ .S02_AXI_ARLEN (0), // input [7 : 0] S01_AXI_ARLEN
+ .S02_AXI_ARSIZE (0), // input [2 : 0] S01_AXI_ARSIZE
+ .S02_AXI_ARBURST (0), // input [1 : 0] S01_AXI_ARBURST
+ .S02_AXI_ARLOCK (0), // input S01_AXI_ARLOCK
+ .S02_AXI_ARCACHE (0), // input [3 : 0] S01_AXI_ARCACHE
+ .S02_AXI_ARPROT (0), // input [2 : 0] S01_AXI_ARPROT
+ .S02_AXI_ARQOS (0), // input [3 : 0] S01_AXI_ARQOS
+ .S02_AXI_ARVALID (0), // input S01_AXI_ARVALID
+ .S02_AXI_ARREADY (), // output S01_AXI_ARREADY
+ .S02_AXI_RID (), // output [0 : 0] S01_AXI_RID
+ .S02_AXI_RDATA (), // output [63 : 0] S01_AXI_RDATA
+ .S02_AXI_RRESP (), // output [1 : 0] S01_AXI_RRESP
+ .S02_AXI_RLAST (), // output S01_AXI_RLAST
+ .S02_AXI_RVALID (), // output S01_AXI_RVALID
+ .S02_AXI_RREADY (1), // input S01_AXI_RREADY
+ //
+ .S03_AXI_ACLK (dma_engine_clk), // input S00_AXI_ACLK
+ .S03_AXI_ARESETN (~ddr3_axi_rst), // input S00_AXI_ARESETN
+ .S03_AXI_AWID (dma_axi_wr.addr.id), // input [0 : 0] S00_AXI_AWID
+ .S03_AXI_AWADDR (dma_axi_wr.addr.addr), // input [31 : 0] S00_AXI_AWADDR
+ .S03_AXI_AWLEN (dma_axi_wr.addr.len), // input [7 : 0] S00_AXI_AWLEN
+ .S03_AXI_AWSIZE (dma_axi_wr.addr.size), // input [2 : 0] S00_AXI_AWSIZE
+ .S03_AXI_AWBURST (dma_axi_wr.addr.burst), // input [1 : 0] S00_AXI_AWBURST
+ .S03_AXI_AWLOCK (dma_axi_wr.addr.lock), // input S00_AXI_AWLOCK
+ .S03_AXI_AWCACHE (dma_axi_wr.addr.cache), // input [3 : 0] S00_AXI_AWCACHE
+ .S03_AXI_AWPROT (dma_axi_wr.addr.prot), // input [2 : 0] S00_AXI_AWPROT
+ .S03_AXI_AWQOS (dma_axi_wr.addr.qos), // input [3 : 0] S00_AXI_AWQOS
+ .S03_AXI_AWVALID (dma_axi_wr.addr.valid), // input S00_AXI_AWVALID
+ .S03_AXI_AWREADY (dma_axi_wr.addr.ready), // output S00_AXI_AWREADY
+ .S03_AXI_WDATA (dma_axi_wr.data.data ^ forced_bit_err), // input [63 : 0] S00_AXI_WDATA
+ .S03_AXI_WSTRB (dma_axi_wr.data.strb), // input [7 : 0] S00_AXI_WSTRB
+ .S03_AXI_WLAST (dma_axi_wr.data.last), // input S00_AXI_WLAST
+ .S03_AXI_WVALID (dma_axi_wr.data.valid), // input S00_AXI_WVALID
+ .S03_AXI_WREADY (dma_axi_wr.data.ready), // output S00_AXI_WREADY
+ .S03_AXI_BID (dma_axi_wr.resp.id), // output [0 : 0] S00_AXI_BID
+ .S03_AXI_BRESP (dma_axi_wr.resp.resp), // output [1 : 0] S00_AXI_BRESP
+ .S03_AXI_BVALID (dma_axi_wr.resp.valid), // output S00_AXI_BVALID
+ .S03_AXI_BREADY (dma_axi_wr.resp.ready), // input S00_AXI_BREADY
+ .S03_AXI_ARID (dma_axi_rd.addr.id), // input [0 : 0] S00_AXI_ARID
+ .S03_AXI_ARADDR (dma_axi_rd.addr.addr), // input [31 : 0] S00_AXI_ARADDR
+ .S03_AXI_ARLEN (dma_axi_rd.addr.len), // input [7 : 0] S00_AXI_ARLEN
+ .S03_AXI_ARSIZE (dma_axi_rd.addr.size), // input [2 : 0] S00_AXI_ARSIZE
+ .S03_AXI_ARBURST (dma_axi_rd.addr.burst), // input [1 : 0] S00_AXI_ARBURST
+ .S03_AXI_ARLOCK (dma_axi_rd.addr.lock), // input S00_AXI_ARLOCK
+ .S03_AXI_ARCACHE (dma_axi_rd.addr.cache), // input [3 : 0] S00_AXI_ARCACHE
+ .S03_AXI_ARPROT (dma_axi_rd.addr.prot), // input [2 : 0] S00_AXI_ARPROT
+ .S03_AXI_ARQOS (dma_axi_rd.addr.qos), // input [3 : 0] S00_AXI_ARQOS
+ .S03_AXI_ARVALID (dma_axi_rd.addr.valid), // input S00_AXI_ARVALID
+ .S03_AXI_ARREADY (dma_axi_rd.addr.ready), // output S00_AXI_ARREADY
+ .S03_AXI_RID (dma_axi_rd.data.id), // output [0 : 0] S00_AXI_RID
+ .S03_AXI_RDATA (dma_axi_rd.data.data), // output [63 : 0] S00_AXI_RDATA
+ .S03_AXI_RRESP (dma_axi_rd.data.resp), // output [1 : 0] S00_AXI_RRESP
+ .S03_AXI_RLAST (dma_axi_rd.data.last), // output S00_AXI_RLAST
+ .S03_AXI_RVALID (dma_axi_rd.data.valid), // output S00_AXI_RVALID
+ .S03_AXI_RREADY (dma_axi_rd.data.ready), // input S00_AXI_RREADY
+ //
+ .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
+ );
+
+ //---------------------------------------------------
+ // MIG
+ //---------------------------------------------------
+ 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_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 (),
+
+ // 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_p (sys_clk_p), // From external 100MHz source.
+ .sys_clk_n (sys_clk_n), // From external 100MHz source.
+ .clk_ref_i (bus_clk),
+ .sys_rst (sys_rst_n) // IJB. Poorly named active low. Should change RST_ACT_LOW.
+ );
+
+ //---------------------------------------------------
+ // 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)
+ );
+
+endmodule
diff --git a/fpga/usrp3/top/n3xx/sim/dram_fifo/dram_fifo_tb.sv b/fpga/usrp3/top/n3xx/sim/dram_fifo/dram_fifo_tb.sv
new file mode 100644
index 000000000..2979aefb7
--- /dev/null
+++ b/fpga/usrp3/top/n3xx/sim/dram_fifo/dram_fifo_tb.sv
@@ -0,0 +1,163 @@
+//
+// 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"
+
+module dram_fifo_tb();
+ `TEST_BENCH_INIT("dram_fifo_tb",`NUM_TEST_CASES,`NS_PER_TICK)
+
+ // Define all clocks and resets
+ `DEFINE_DIFF_CLK(sys_clk_p, sys_clk_n, 10, 50) //100MHz differential sys_clk to generate DDR3 clocking
+ `DEFINE_CLK(bus_clk, 1000/200, 50) //200MHz bus_clk
+ `DEFINE_CLK(dma_engine_clk, 1000.0/305.0, 50) //305MHz dma_engine_clk
+ `DEFINE_RESET(bus_rst, 0, 100) //100ns for GSR to deassert
+ `DEFINE_RESET_N(sys_rst_n, 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;
+
+ axis_dram_fifo_single dut_single (
+ .bus_clk(bus_clk),
+ .bus_rst(bus_rst),
+ .sys_clk_p(sys_clk_p),//use differential clock on N310
+ .sys_clk_n(sys_clk_n),
+ .sys_rst_n(sys_rst_n),
+ .dma_engine_clk(dma_engine_clk),
+
+ .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)
+ );
+
+ //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_n) @(posedge sys_clk_p);
+ `TEST_CASE_DONE((~bus_rst & sys_rst_n));
+
+ `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);
+ 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
+ end
+ end
+ join
+ `TEST_CASE_DONE(1);
+
+ `TEST_BENCH_DONE;
+
+ end
+
+endmodule
diff --git a/fpga/usrp3/top/n3xx/sim/dram_fifo_bist/Makefile b/fpga/usrp3/top/n3xx/sim/dram_fifo_bist/Makefile
new file mode 100644
index 000000000..49e673dc4
--- /dev/null
+++ b/fpga/usrp3/top/n3xx/sim/dram_fifo_bist/Makefile
@@ -0,0 +1,70 @@
+#
+# 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 = zynq
+PART_ID = xc7z100/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_4x64_256_bd/Makefile.inc
+include $(IP_DIR)/fifo_short_2clk/Makefile.inc
+include $(IP_DIR)/fifo_4k_2clk/Makefile.inc
+
+DESIGN_SRCS += $(abspath \
+$(IP_DDR3_32BIT_SRCS) \
+$(IP_AXI_INTERCON_4X64_256_SRCS) \
+$(IP_AXI_INTERCON_4X64_256_BD_SRCS) \
+$(IP_FIFO_4K_2CLK_SRCS) \
+$(IP_FIFO_SHORT_2CLK_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/n3xx/sim/dram_fifo_bist/dram_fifo_bist_tb.sv b/fpga/usrp3/top/n3xx/sim/dram_fifo_bist/dram_fifo_bist_tb.sv
new file mode 100644
index 000000000..96a60de6e
--- /dev/null
+++ b/fpga/usrp3/top/n3xx/sim/dram_fifo_bist/dram_fifo_bist_tb.sv
@@ -0,0 +1,348 @@
+//
+// Copyright 2015 Ettus Research LLC
+//
+
+
+`timescale 1ns/1ps
+`define SIM_RUNTIME_US 3000
+`define NS_PER_TICK 1
+`define NUM_TEST_CASES 8
+
+`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 dram_fifo_bist_tb();
+ `TEST_BENCH_INIT("dram_fifo_bist_tb",`NUM_TEST_CASES,`NS_PER_TICK)
+
+ // Define all clocks and resets
+ `DEFINE_DIFF_CLK(sys_clk_p, sys_clk_n, 10, 50) //100MHz differential sys_clk to generate DDR3 clocking
+ `DEFINE_CLK(bus_clk, 1000/200, 50) //200MHz bus_clk
+ `DEFINE_CLK(dma_engine_clk, 1000/300, 50) //300MHz dma_engine_clk
+ `DEFINE_RESET(bus_rst, 0, 100) //100ns for GSR to deassert
+ `DEFINE_RESET_N(sys_rst_n, 0, 100) //100ns for GSR to deassert
+
+ localparam EXTENDED_TEST = 0;
+
+ // 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 dut_single (
+ .bus_clk(bus_clk),
+ .bus_rst(bus_rst),
+ .sys_clk_p(sys_clk_p),//use differential clock on N310
+ .sys_clk_n(sys_clk_n),
+ .sys_rst_n(sys_rst_n),
+ .dma_engine_clk(dma_engine_clk),
+
+ .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_n) @(posedge sys_clk_p);
+ `TEST_CASE_DONE(~bus_rst & sys_rst_n);
+
+ forced_bit_err <= 64'h0;
+ repeat (200) @(posedge sys_clk_p);
+
+ `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);
+
+ if (EXTENDED_TEST) begin // Extended test mode
+ `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);
+ end
+
+ `TEST_BENCH_DONE;
+
+ end
+endmodule
diff --git a/fpga/usrp3/top/n3xx/sim/one_gig_eth_loopback/Makefile b/fpga/usrp3/top/n3xx/sim/one_gig_eth_loopback/Makefile
new file mode 100644
index 000000000..77c7c58c5
--- /dev/null
+++ b/fpga/usrp3/top/n3xx/sim/one_gig_eth_loopback/Makefile
@@ -0,0 +1,78 @@
+#
+# 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 = zynq
+PART_ID = xc7z100/ffg900/-2
+
+# Include makefiles and sources for the DUT and its dependencies
+include $(BASE_DIR)/../lib/simple_gemac/Makefile.srcs
+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) \
+$(SIMPLE_GEMAC_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)/one_gig_eth_pcs_pma/Makefile.inc
+#include $(IP_DIR)/fifo_short_2clk/Makefile.inc
+include $(IP_DIR)/axi64_8k_2clk_fifo/Makefile.inc
+
+DESIGN_SRCS += $(abspath \
+$(IP_ONE_GIG_ETH_PCS_PMA_SRCS) \
+$(IP_ONE_GIGE_PHY_XCI_SRCS) \
+$(ONE_GIGE_PHY_SRCS) \
+$(IP_AXI64_8K_2CLK_FIFO_SRCS) \
+$(IP_FIFO_SHORT_2CLK_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 = one_gig_eth_loopback_tb
+# Simulation runtime in microseconds
+SIM_RUNTIME_US = 30000
+
+SIM_SRCS = \
+$(abspath one_gig_eth_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/n3xx/sim/one_gig_eth_loopback/demo_one_gig_pcs_pma_mdio.v b/fpga/usrp3/top/n3xx/sim/one_gig_eth_loopback/demo_one_gig_pcs_pma_mdio.v
new file mode 100644
index 000000000..cd24e14a8
--- /dev/null
+++ b/fpga/usrp3/top/n3xx/sim/one_gig_eth_loopback/demo_one_gig_pcs_pma_mdio.v
@@ -0,0 +1,489 @@
+//------------------------------------------------------------------------------
+// File : demo_tb.v
+// Author : Xilinx Inc.
+//------------------------------------------------------------------------------
+// (c) Copyright 2009 Xilinx, Inc. All rights reserved.
+//
+// This file contains confidential and proprietary information
+// of Xilinx, Inc. and is protected under U.S. and
+// international copyright and other intellectual property
+// laws.
+//
+// DISCLAIMER
+// This disclaimer is not a license and does not grant any
+// rights to the materials distributed herewith. Except as
+// otherwise provided in a valid license issued to you by
+// Xilinx, and to the maximum extent permitted by applicable
+// law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND
+// WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES
+// AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING
+// BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON-
+// INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; and
+// (2) Xilinx shall not be liable (whether in contract or tort,
+// including negligence, or under any other theory of
+// liability) for any loss or damage of any kind or nature
+// related to, arising under or in connection with these
+// materials, including for any direct, or any indirect,
+// special, incidental, or consequential loss or damage
+// (including loss of data, profits, goodwill, or any type of
+// loss or damage suffered as a result of any action brought
+// by a third party) even if such damage or loss was
+// reasonably foreseeable or Xilinx had been advised of the
+// possibility of the same.
+//
+// CRITICAL APPLICATIONS
+// Xilinx products are not designed or intended to be fail-
+// safe, or for use in any application requiring fail-safe
+// performance, such as life-support or safety devices or
+// systems, Class III medical devices, nuclear facilities,
+// applications related to the deployment of airbags, or any
+// other applications that could lead to death, personal
+// injury, or severe property or environmental damage
+// (individually and collectively, "Critical
+// Applications"). Customer assumes the sole risk and
+// liability of any use of Xilinx products in Critical
+// Applications, subject only to applicable laws and
+// regulations governing limitations on product liability.
+//
+// THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS
+// PART OF THIS FILE AT ALL TIMES.
+//
+//
+//------------------------------------------------------------------------------
+// Description: This testbench will exercise the ports of the Ethernet
+// 1000BASE-X PCS/PMA core's example design to perform the following
+// operations:
+//
+//----------------
+// Configuration
+//----------------
+// The core will be reset, then Auto-Negotiation (if present) will
+// be disabled and and the core will be taken out of the Isolate
+// state.
+//
+//----------------
+// Transmitter
+//----------------
+// Four frames are generated by the Tx Stimulus and pushed into the
+// GMII transmitter.
+//
+// The PHY side transmitter interface data is captured, 8B10B decoded
+// and the Tx Monitor checks that the captured data matches that
+// injected.
+//
+//----------------
+// Receiver
+//----------------
+// Four frames are generated by the Rx Stimulus, 8B10B encoded and
+// pushed into the PHY side receiver interface.
+//
+// The GMII side receiver interface data is captured and the
+// Rx Monitor checks that the captured data matches that injected.
+//
+//
+//----------------------------------------------------------------------
+// Demonstration Test Fixture |
+// |
+// |
+// -------------------------- |
+// | Example Design | |
+// | (DUT) | |
+// | | |
+// | | |
+// | | |
+// Tx | | 8B10B decode, Tx |
+// Generate -------> --------> Monitor |
+// Frames | | Frames |
+// |GMII PHY | |
+// | I/F I/F | |
+// | | |
+// | | |
+// | | |
+// Rx | | 8B10B encode, Rx |
+// Monitor <-------- <-------- Generate |
+// Frames | | Frames |
+// | | |
+// ------------^------------- |
+// | |
+// | |
+// Stimulate |
+// MDIO I/F |
+// (if present) |
+// |
+//----------------------------------------------------------------------
+
+`timescale 1 ps/1 ps
+
+
+// To use this testbench copy it over the demo_tb.v in the example testbench
+// provided by xilinx
+
+// This module is a modified version of the demonstration testbench provided
+// by Xilinx. It has the mdio_master along with the one_gig dut.
+// It uses the configuration vector to control the phy
+// Can be used to debug mdio_master
+module demo_tb;
+
+
+ //----------------------------------------------------------------------------
+ // Stimulus - Management Frame data
+ //----------------------------------------------------------------------------
+ // Create management frame
+ reg [0:63] mdio_data;
+
+ initial
+ begin
+
+ mdio_data[0:31] = 32'hffffffff; // preamble field
+ mdio_data[32:33] = 2'h1; // start opcode
+ mdio_data[34:35] = 2'h1; // write opcode
+ mdio_data[36:40] = 5'd1; // phyad (write to this device)
+ mdio_data[41:45] = 5'h0; // regad (write to Configuration Register)
+ mdio_data[46:47] = 2'h2; // Turn-around cycles
+
+ // DATA FIELD
+
+ mdio_data[48] = 1'b0; // Do not assert Reset
+ mdio_data[49] = 1'b0; // No loopback
+ mdio_data[50] = 1'b0; // Speed selection
+ mdio_data[51] = 1'b0; // Disable Auto-Negotiation
+ mdio_data[52] = 1'b0; // Disable Power Down
+ mdio_data[53] = 1'b0; // Disable Isolate GMII
+ mdio_data[54] = 1'b0; // Disable Auto-Negotiation Restart
+ mdio_data[55] = 1'b1; // Full Duplex Mode
+ mdio_data[56] = 1'b0; // Disable Collision Test
+ mdio_data[57] = 1'b0; // Speed selection
+ mdio_data[58:63] = 6'h0; // Reserved
+
+ end
+
+
+
+ //----------------------------------------------------------------------------
+ // testbench signals
+ //----------------------------------------------------------------------------
+
+ // testbench control semaphores
+ reg configuration_finished;
+ wire tx_monitor_finished;
+ wire rx_monitor_finished;
+ wire simulation_finished;
+
+
+ //----------------------------------------------------------------------------
+ // DUT signals
+ //----------------------------------------------------------------------------
+
+ // An independent clock source used as the reference clock for an
+ // IDELAYCTRL (if present) and for the main GT transceiver reset logic.
+ // This example design assumes that this is of frequency 200MHz.
+ reg independent_clock;
+
+ // System Reset
+ reg reset;
+
+ // Transceiver Interface
+ //----------------------
+ reg gtrefclk_p;
+ reg gtrefclk_n;
+ wire rxuserclk2;
+ wire txp;
+ wire txn;
+ wire rxp;
+ wire rxn;
+
+ // GMII Interface
+ //---------------
+ wire gmii_tx_clk;
+ wire gmii_rx_clk;
+ wire [7:0] gmii_txd;
+ wire gmii_tx_en;
+ wire gmii_tx_er;
+ wire [7:0] gmii_rxd;
+ wire gmii_rx_dv;
+ wire gmii_rx_er;
+
+ // Management: MDIO Interface
+ //---------------------------
+ wire mdc;
+ wire mdio_i;
+ wire mdio_o;
+ wire mdio_t;
+ reg [4:0] configuration_vector;
+ reg configuration_valid;
+ wire signal_detect;
+ wire [15:0] status_vector;
+
+ parameter [13:0] REG_BASE = 14'h0;
+ parameter REG_DWIDTH = 32;
+ parameter REG_AWIDTH = 14;
+
+ reg reg_wr_req;
+ reg [REG_AWIDTH-1:0] reg_wr_addr;
+ reg [31:0] reg_wr_data;
+ reg reg_rd_req;
+ reg [REG_AWIDTH-1:0] reg_rd_addr;
+ wire reg_rd_resp;
+ wire [31:0] reg_rd_data;
+
+ //----------------------------------------------------------------------------
+ // Create clock sources
+ //----------------------------------------------------------------------------
+
+ // An independent clock source used as the reference clock for an
+ // IDELAYCTRL (if present) and for the main GT transceiver reset logic.
+ // This testbench uses the frequency of 200MHz.
+ initial
+ begin
+ independent_clock <= 1'b0;
+ forever
+ begin
+ independent_clock <= 1'b0;
+ #2500;
+ independent_clock <= 1'b1;
+ #2500;
+ end
+ end
+
+
+
+ // Create the transceiver Reference clock (125 MHz)
+ initial
+ begin
+ gtrefclk_p <= 1'b0;
+ gtrefclk_n <= 1'b1;
+ forever
+ begin
+ gtrefclk_p <= 1'b0;
+ gtrefclk_n <= 1'b1;
+ #4000;
+ gtrefclk_p <= 1'b1;
+ gtrefclk_n <= 1'b0;
+ #4000;
+ end
+ end
+
+ // MDIO Master
+ mdio_master #(
+ .REG_BASE (REG_BASE + 32'h10),
+ .REG_AWIDTH (REG_AWIDTH),
+ .MDC_DIVIDER (8'd200)
+ ) mdio_master_i (
+ .clk (independent_clock),
+ .rst (reset),
+ .mdc (mdc),
+ .mdio_in (mdio_o),
+ .mdio_out (mdio_i),
+ .mdio_tri (mdio_t),
+ .reg_wr_req (reg_wr_req),
+ .reg_wr_addr(reg_wr_addr),
+ .reg_wr_data(reg_wr_data),
+ .reg_rd_req (reg_rd_req),
+ .reg_rd_addr(reg_rd_addr),
+ .reg_rd_data(reg_rd_data),
+ .reg_rd_resp(reg_rd_resp)
+ );
+
+ //----------------------------------------------------------------------------
+ // Wire up Device Under Test
+ //----------------------------------------------------------------------------
+ one_gig_eth_pcs_pma_example_design dut
+ (
+ .independent_clock (independent_clock),
+ .gtrefclk_p (gtrefclk_p),
+ .gtrefclk_n (gtrefclk_n),
+ .rxuserclk2 (rxuserclk2),
+ .txp (txp),
+ .txn (txn),
+ .rxp (rxp),
+ .rxn (rxn),
+ .gmii_tx_clk (gmii_tx_clk),
+ .gmii_rx_clk (gmii_rx_clk),
+ .gmii_txd (gmii_txd),
+ .gmii_tx_en (gmii_tx_en),
+ .gmii_tx_er (gmii_tx_er),
+ .gmii_rxd (gmii_rxd),
+ .gmii_rx_dv (gmii_rx_dv),
+ .gmii_rx_er (gmii_rx_er),
+ .mdc (mdc),
+ .mdio_i (mdio_i),
+ .mdio_o (mdio_o),
+ .mdio_t (mdio_t),
+ .configuration_vector (configuration_vector),
+ .configuration_valid (configuration_valid),
+ .status_vector (status_vector),
+ .reset (reset),
+ .signal_detect (signal_detect)
+ );
+
+
+
+ //----------------------------------------------------------------------------
+ // Instantiate a Stimulus module for the core
+ //----------------------------------------------------------------------------
+ stimulus_tb stimulus
+ (
+ .txp (txp),
+ .txn (txn),
+ .rxp (rxp),
+ .rxn (rxn),
+
+ .gmii_tx_clk (gmii_tx_clk),
+ .gmii_rx_clk (gmii_rx_clk),
+ .gmii_txd (gmii_txd),
+ .gmii_tx_en (gmii_tx_en),
+ .gmii_tx_er (gmii_tx_er),
+ .gmii_rxd (gmii_rxd),
+ .gmii_rx_dv (gmii_rx_dv),
+ .gmii_rx_er (gmii_rx_er),
+
+ .configuration_finished (configuration_finished),
+ .tx_monitor_finished (tx_monitor_finished),
+ .rx_monitor_finished (rx_monitor_finished)
+ );
+
+
+
+ //----------------------------------------------------------------------------
+ // Simulate that PMD sublayer has detected and optical input.
+ //----------------------------------------------------------------------------
+ assign signal_detect = 1'b1;
+
+
+
+
+ //----------------------------------------------------------------------------
+ // Set the PHYAD for the core
+ //----------------------------------------------------------------------------
+
+
+ //----------------------------------------------------------------------------
+ // Configuration process. This process will reset the core, then write
+ // to configuration register 0 to turn off autonegotiation and take
+ // the core out of the isolate state.
+ //----------------------------------------------------------------------------
+
+ // drives MDC at 2.5 MHz
+ //initial
+ //begin
+ // mdc <= 1'b0;
+ // forever
+ // begin
+ // mdc <= 1'b0;
+ // #200000;
+ // mdc <= 1'b1;
+ // #200000;
+ // end
+ //end
+
+
+ // Main configuration process
+ initial
+ begin : p_configuration
+ integer MDIO_BIT; // Bit counter within MDIO frame
+
+ $display("** Note: Timing checks are not valid");
+
+ configuration_finished <= 0;
+ configuration_vector <= 5'b00000;
+ // Not doing any MDIO write, so configure the Register 0 using
+ // Configuration Vector
+ configuration_valid <= 1'b1;
+ //mdio_i <= 1'b1;
+
+ // reset the core
+ $display("Resetting core...");
+ reset <= 1'b1;
+ #1000000
+ @(posedge gtrefclk_p)
+ reset <= 1'b0;
+ // wait for core to obtain synchronisation
+
+ #2000000000
+ #1000000000
+
+ #250000000
+
+ // Write to PCS Management configuration register 0.
+ $display("Writing to Control Register in PCS sublayer....");
+
+ // Write REG_MDIO_OP to Read MDIO Phy Addr 1, Reg Addr 1
+ @(posedge independent_clock)
+ reg_wr_addr <= 14'h18;
+ reg_wr_data <= 16'h822;
+ reg_wr_req <= 1'b1;
+ @(posedge independent_clock)
+ reg_wr_req <= 1'b0;
+ #4000000
+
+ // Write REG_MDIO_CTRL_STATUS to turn on mdio_running
+ @(posedge independent_clock)
+ reg_wr_addr <= 14'h1c;
+ reg_wr_data <= 32'h1;
+ reg_wr_req <= 1'b1;
+ @(posedge independent_clock)
+ reg_wr_req <= 1'b0;
+ #4000000
+
+ // Write REG_MDIO_OP to Read MDIO Phy Addr 1, Reg Addr 0
+ @(posedge independent_clock)
+ reg_wr_addr <= 14'h18;
+ reg_wr_data <= 32'h820;
+ reg_wr_req <= 1'b1;
+ @(posedge independent_clock)
+ reg_wr_req <= 1'b0;
+ #4000000
+ //@(negedge mdc) // centre MDIO around MDC rising edge
+
+ //MDIO_BIT = 0;
+
+ //// transmit serial management frame
+ //while(MDIO_BIT !== 64)
+ //begin
+ // @(negedge mdc);
+ // mdio_i <= mdio_data[MDIO_BIT];
+ // MDIO_BIT = MDIO_BIT + 1;
+ //end
+
+ //@(negedge mdc)
+ //mdio_i <= 1'b1; // simulate tri-state with pullup
+ #10000000
+ // wait for core to obtain synchronisation
+ wait (status_vector[1] == 1);
+ #8000000
+
+ configuration_finished <= 1;
+ end // p_configuration
+
+
+
+ //----------------------------------------------------------------------------
+ // End the simulation.
+ //----------------------------------------------------------------------------
+
+ assign simulation_finished = tx_monitor_finished & rx_monitor_finished;
+
+
+ initial
+ begin : p_end_simulation
+ fork: sim_in_progress
+ @(posedge simulation_finished) disable sim_in_progress;
+ #2000000000
+ #2000000000
+ #500000000
+ disable sim_in_progress;
+
+ join
+ if (simulation_finished) begin
+ #1000000
+ $display("Test completed successfully");
+ $display("Simulation Complete.");
+ end
+ else
+ $display("** Error: Testbench timed out");
+ $stop;
+ end // p_end_simulation
+
+
+endmodule
+
diff --git a/fpga/usrp3/top/n3xx/sim/one_gig_eth_loopback/one_gig_eth_loopback_tb.sv b/fpga/usrp3/top/n3xx/sim/one_gig_eth_loopback/one_gig_eth_loopback_tb.sv
new file mode 100644
index 000000000..759ea2872
--- /dev/null
+++ b/fpga/usrp3/top/n3xx/sim/one_gig_eth_loopback/one_gig_eth_loopback_tb.sv
@@ -0,0 +1,381 @@
+//
+// 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 one_gig_eth_loopback_tb();
+ `TEST_BENCH_INIT("one_gig_eth_loopback_tb",`NUM_TEST_CASES,`NS_PER_TICK)
+
+ // Define all clocks and resets
+ `DEFINE_CLK(ETH_CLK_P, 1000/125, 50) //125MHz GT transceiver clock
+ `DEFINE_RESET(GSR, 0, 100) //100ns for GSR to deassert
+
+ wire ETH_CLK_N = ~ETH_CLK_P;
+ wire SFP_LN0_P, SFP_LN0_N, SFP_LN1_P, SFP_LN1_N;
+
+ //localparam PACKET_MODE = 0;
+ localparam PORTNUM = 8'd0;
+
+ // One_gigE Loopback Topology:
+ //
+ // TB Simulus ====> |------------| |----------------|
+ // | gigE MAC | <===> | gigE PCS/PMA | <====>||
+ // TB Checker <==== |------------| |----------------| || Loopback through
+ // ||
+ // ====> |------------| |----------------| || perfect serial channel
+ // Loopback | | gigE MAC | <===> | gigE PCS/PMA | <====>||
+ // <==== |------------| |----------------|
+
+ // Initialize DUT
+ wire gige_refclk, gige_refclk_bufg;
+ wire m_user_clk, s_user_clk;
+ wire m_channel_up, s_channel_up;
+ wire [7:0] m_gmii_txd, m_gmii_rxd;
+ wire m_gmii_tx_en, m_gmii_tx_er, m_gmii_rx_dv, m_gmii_rx_er;
+ wire m_gmii_clk;
+ wire [7:0] s_gmii_txd, s_gmii_rxd;
+ wire s_gmii_tx_en, s_gmii_tx_er, s_gmii_rx_dv, s_gmii_rx_er;
+ wire s_gmii_clk;
+ wire [15:0] m_phy_status;
+ wire [15:0] s_phy_status;
+ wire [63:0] loop_tdata;
+ wire loop_tlast, loop_tvalid, loop_tready;
+
+
+ reg independent_clock;
+ assign m_channel_up = m_phy_status[0];
+ assign s_channel_up = s_phy_status[0];
+ //assign m_user_clk = gmii_clk;
+ //assign s_user_clk = gmii_clk;
+ assign m_user_clk = independent_clock;
+ assign s_user_clk = independent_clock;
+ wire gt0_qplloutclk, gt0_qplloutrefclk, pma_reset;
+
+ one_gige_phy_clk_gen gige_clk_gen_i (
+ .areset(GSR),
+ .refclk_p(ETH_CLK_P),
+ .refclk_n(ETH_CLK_N),
+ .refclk(gige_refclk),
+ .refclk_bufg(gige_refclk_bufg)
+ );
+
+ cvita_master m_tx_chdr (.clk(m_user_clk));
+ cvita_slave s_rx_chdr (.clk(s_user_clk));
+ initial
+ begin
+ independent_clock <= 1'b0;
+ forever
+ begin
+ independent_clock <= 1'b0;
+ #0.5;
+ independent_clock <= 1'b1;
+ #0.5;
+ end
+ end
+
+ //-----------------------------------------------------------------
+ // MDIO Master
+ //-----------------------------------------------------------------
+ wire mdc, mdio_m2s, mdio_s2m;
+
+ mdio_master #(
+ .MDC_DIVIDER (8'd200)
+ ) mdio_master_i (
+ .clk (m_user_clk),
+ .rst (GSR),
+ .mdc (mdc),
+ .mdio_in (mdio_s2m),
+ .mdio_out (mdio_m2s),
+ .mdio_tri (),
+ .reg_wr_req (/*reg_wr_req*/),
+ .reg_wr_addr(/*reg_wr_addr*/),
+ .reg_wr_data(/*reg_wr_data*/),
+ .reg_rd_req (/*reg_rd_req*/),
+ .reg_rd_addr(/*reg_rd_addr*/),
+ .reg_rd_data(/*reg_rd_data*/),
+ .reg_rd_resp(/*reg_rd_resp*/)
+ );
+
+ //GT COMMON
+ one_gig_eth_pcs_pma_gt_common core_gt_common_i
+ (
+ .GTREFCLK0_IN (gige_refclk) ,
+ .QPLLLOCK_OUT (),
+ .QPLLLOCKDETCLK_IN (independent_clock),
+ .QPLLOUTCLK_OUT (gt0_qplloutclk),
+ .QPLLOUTREFCLK_OUT (gt0_qplloutrefclk),
+ .QPLLREFCLKLOST_OUT (),
+ .QPLLRESET_IN (pma_reset)
+ );
+
+ one_gige_phy one_gige_phy_master_i
+ (
+ .reset(GSR), // Asynchronous reset for entire core.
+ .independent_clock(independent_clock),
+ .pma_reset_out(pma_reset),
+ .gt0_qplloutclk_in(gt0_qplloutclk),
+ .gt0_qplloutrefclk_in(gt0_qplloutrefclk),
+ // Tranceiver Interface
+ .gtrefclk(gige_refclk), // Reference clock for MGT: 125MHz, very high quality.
+ .gtrefclk_bufg(gige_refclk_bufg), // Reference clock routed through a BUFG
+ .txp(SFP_LN1_P), // Differential +ve of serial transmission from PMA to PMD.
+ .txn(SFP_LN1_N), // Differential -ve of serial transmission from PMA to PMD.
+ .rxp(SFP_LN0_P), // Differential +ve for serial reception from PMD to PMA.
+ .rxn(SFP_LN0_N), // Differential -ve for serial reception from PMD to PMA.
+ // GMII Interface (client MAC <=> PCS)
+ .gmii_clk(m_gmii_clk), // Clock to client MAC.
+ .gmii_txd(m_gmii_txd), // Transmit data from client MAC.
+ .gmii_tx_en(m_gmii_tx_en), // Transmit control signal from client MAC.
+ .gmii_tx_er(m_gmii_tx_er), // Transmit control signal from client MAC.
+ .gmii_rxd(m_gmii_rxd), // Received Data to client MAC.
+ .gmii_rx_dv(m_gmii_rx_dv), // Received control signal to client MAC.
+ .gmii_rx_er(m_gmii_rx_er), // Received control signal to client MAC.
+ // Management: MDIO Interface
+ .mdc(mdc), // Management Data Clock
+ .mdio_i(mdio_m2s), // Management Data In
+ .mdio_o(mdio_s2m), // Management Data Out
+ .mdio_t(), // Management Data Tristate
+ .configuration_vector(5'd0), // Alternative to MDIO interface.
+ .configuration_valid(1'b1), // Validation signal for Config vector (MUST be 1 for proper functionality...undocumented)
+ // General IO's
+ .status_vector(m_phy_status), // Core status.
+ .signal_detect(1'b1 /*Optical module not supported*/) // Input from PMD to indicate presence of optical input.
+ );
+
+ simple_gemac_wrapper #(.RX_FLOW_CTRL(0), .PORTNUM(PORTNUM)) simple_gemac_wrapper_master_i
+ (
+ .clk125(m_gmii_clk),
+ .reset(GSR),
+
+ .GMII_GTX_CLK(),
+ .GMII_TX_EN(m_gmii_tx_en),
+ .GMII_TX_ER(m_gmii_tx_er),
+ .GMII_TXD(m_gmii_txd),
+ .GMII_RX_CLK(m_gmii_clk),
+ .GMII_RX_DV(m_gmii_rx_dv),
+ .GMII_RX_ER(m_gmii_rx_er),
+ .GMII_RXD(m_gmii_rxd),
+
+ .sys_clk(m_user_clk),
+ .rx_tdata(s_rx_chdr.axis.tdata),
+ .rx_tuser(/*s_rx_chdr.axis.tuser*/),
+ .rx_tlast(s_rx_chdr.axis.tlast),
+ .rx_tvalid(s_rx_chdr.axis.tvalid),
+ .rx_tready(s_rx_chdr.axis.tready),
+ .tx_tdata(m_tx_chdr.axis.tdata),
+ .tx_tuser(/*m_tx_chdr.axis_tuser*/),
+ .tx_tlast(m_tx_chdr.axis.tlast),
+ .tx_tvalid(m_tx_chdr.axis.tvalid),
+ .tx_tready(m_tx_chdr.axis.tready),
+ // Debug
+ .debug_tx(), .debug_rx()
+ );
+
+ one_gige_phy one_gige_phy_slave_i
+ (
+ .reset(GSR), // Asynchronous reset for entire core.
+ .independent_clock(independent_clock),
+ .pma_reset_out(),
+ .gt0_qplloutclk_in(gt0_qplloutclk),
+ .gt0_qplloutrefclk_in(gt0_qplloutrefclk),
+ // Tranceiver Interface
+ .gtrefclk(gige_refclk), // Reference clock for MGT: 125MHz, very high quality.
+ .gtrefclk_bufg(gige_refclk_bufg), // Reference clock routed through a BUFG
+ .txp(SFP_LN0_P), // Differential +ve of serial transmission from PMA to PMD.
+ .txn(SFP_LN0_N), // Differential -ve of serial transmission from PMA to PMD.
+ .rxp(SFP_LN1_P), // Differential +ve for serial reception from PMD to PMA.
+ .rxn(SFP_LN1_N), // Differential -ve for serial reception from PMD to PMA.
+ // GMII Interface (client MAC <=> PCS)
+ .gmii_clk(s_gmii_clk), // Clock to client MAC.
+ .gmii_txd(s_gmii_txd), // Transmit data from client MAC.
+ .gmii_tx_en(s_gmii_tx_en), // Transmit control signal from client MAC.
+ .gmii_tx_er(s_gmii_tx_er), // Transmit control signal from client MAC.
+ .gmii_rxd(s_gmii_rxd), // Received Data to client MAC.
+ .gmii_rx_dv(s_gmii_rx_dv), // Received control signal to client MAC.
+ .gmii_rx_er(s_gmii_rx_er), // Received control signal to client MAC.
+ // Management: MDIO Interface
+ .mdc(mdc), // Management Data Clock
+ .mdio_i(mdio_m2s), // Management Data In
+ .mdio_o(mdio_s2m), // Management Data Out
+ .mdio_t(), // Management Data Tristate
+ .configuration_vector(5'd0), // Alternative to MDIO interface.
+ .configuration_valid(1'b1), // Validation signal for Config vector (MUST be 1 for proper functionality...undocumented)
+ // General IO's
+ .status_vector(s_phy_status), // Core status.
+ .signal_detect(1'b1 /*Optical module not supported*/) // Input from PMD to indicate presence of optical input.
+ );
+
+ simple_gemac_wrapper #(.RX_FLOW_CTRL(0), .PORTNUM(PORTNUM)) simple_gemac_wrapper_slave_i
+ (
+ .clk125(s_gmii_clk),
+ .reset(GSR),
+
+ .GMII_GTX_CLK(),
+ .GMII_TX_EN(s_gmii_tx_en),
+ .GMII_TX_ER(s_gmii_tx_er),
+ .GMII_TXD(s_gmii_txd),
+ .GMII_RX_CLK(s_gmii_clk),
+ .GMII_RX_DV(s_gmii_rx_dv),
+ .GMII_RX_ER(s_gmii_rx_er),
+ .GMII_RXD(s_gmii_rxd),
+
+ .sys_clk(s_user_clk),
+ .rx_tdata(loop_tdata),
+ .rx_tuser(),
+ .rx_tlast(loop_tlast),
+ .rx_tvalid(loop_tvalid),
+ .rx_tready(loop_tready),
+ .tx_tdata(loop_tdata),
+ .tx_tuser(),
+ .tx_tlast(loop_tlast),
+ .tx_tvalid(loop_tvalid),
+ .tx_tready(loop_tready),
+ // Debug
+ .debug_tx(), .debug_rx()
+ );
+
+ //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
+ `TEST_CASE_START("Wait for reset");
+ while (GSR) @(posedge ETH_CLK_P);
+ `TEST_CASE_DONE((~GSR));
+
+ 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 PRBS15 BIST");
+ // s_bist_loopback <= PACKET_MODE;
+ // @(posedge m_user_clk);
+ // 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);
+
+ repeat(1000) @(posedge m_user_clk);
+
+ 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)");
+ s_rx_chdr.axis.tready = 0;
+ m_tx_chdr.push_ramp_pkt(16, 64'd0, 64'h100, header);
+ s_rx_chdr.axis.tready = 1;
+ s_rx_chdr.wait_for_pkt_get_info(header_out, stats);
+ `ASSERT_ERROR(stats.count==16, "Bad packet: Length mismatch");
+ `ASSERT_ERROR(header.dst_sid==header_out.dst_sid, "Bad packet: Wrong SID");
+ `TEST_CASE_DONE(1);
+
+ `TEST_CASE_START("Fill up empty FIFO then drain (long packet)");
+ s_rx_chdr.axis.tready = 0;
+ m_tx_chdr.push_ramp_pkt(256, 64'd0, 64'h100, header);
+ s_rx_chdr.axis.tready = 1;
+ s_rx_chdr.wait_for_pkt_get_info(header_out, stats);
+ `ASSERT_ERROR(stats.count==256, "Bad packet: Length mismatch");
+ `ASSERT_ERROR(header.dst_sid==header_out.dst_sid, "Bad packet: Wrong SID");
+ `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)");
+ s_rx_chdr.axis.tready = 1;
+ fork
+ begin
+ m_tx_chdr.push_ramp_pkt(1000, 64'd0, 64'h100, header);
+ end
+ begin
+ s_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==1000, "Bad packet: Length mismatch");
+ `TEST_CASE_DONE(1);
+
+ `TEST_CASE_START("Concurrent read and write (multiple packets)");
+ s_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
+ s_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 PRBS15 BIST (Loopback Mode)");
+ //@(posedge m_user_clk);
+ //m_bist_gen <= 1'b1;
+ //m_bist_rate <= 5'd4;
+ //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));
+
+ end
+
+endmodule
diff --git a/fpga/usrp3/top/n3xx/sim/ten_gig_eth_loopback/Makefile b/fpga/usrp3/top/n3xx/sim/ten_gig_eth_loopback/Makefile
new file mode 100644
index 000000000..c1271a40b
--- /dev/null
+++ b/fpga/usrp3/top/n3xx/sim/ten_gig_eth_loopback/Makefile
@@ -0,0 +1,84 @@
+#
+# 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 = zynq
+PART_ID = xc7z100/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/xge_interface/Makefile.srcs
+include $(BASE_DIR)/../lib/xge/Makefile.srcs
+include $(BASE_DIR)/../lib/packet_proc/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)/ten_gig_eth_pcs_pma/Makefile.inc
+include $(IP_DIR)/axi64_8k_2clk_fifo/Makefile.inc
+include $(IP_DIR)/axi64_4k_2clk_fifo/Makefile.inc
+
+DESIGN_SRCS += $(abspath \
+$(XGE_SRCS) \
+$(XGE_INTERFACE_SRCS) \
+$(IP_TEN_GIG_ETH_PCS_PMA_SRCS) \
+$(IP_TEN_GIGE_PHY_XCI_SRCS) \
+$(TEN_GIGE_PHY_SRCS) \
+$(IP_AXI64_8K_2CLK_FIFO_SRCS) \
+$(IP_AXI64_4K_2CLK_FIFO_SRCS) \
+$(PACKET_PROC_SRCS) \
+)
+#$(IP_FIFO_SHORT_2CLK_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 = ten_gig_eth_loopback_tb
+# Simulation runtime in microseconds
+SIM_RUNTIME_US = 30000
+
+SIM_SRCS = \
+$(abspath ten_gig_eth_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/n3xx/sim/ten_gig_eth_loopback/ten_gig_eth_loopback_tb.sv b/fpga/usrp3/top/n3xx/sim/ten_gig_eth_loopback/ten_gig_eth_loopback_tb.sv
new file mode 100644
index 000000000..b0233a339
--- /dev/null
+++ b/fpga/usrp3/top/n3xx/sim/ten_gig_eth_loopback/ten_gig_eth_loopback_tb.sv
@@ -0,0 +1,527 @@
+//
+// 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_axis_lib.svh"
+`include "sim_axi4_lib.svh"
+`include "sim_set_rb_lib.svh"
+
+module ten_gig_eth_loopback_tb();
+ `TEST_BENCH_INIT("ten_gig_eth_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 = 0;
+ localparam PORTNUM = 8'd0;
+
+ // Ten_gigE Loopback Topology:
+ //
+ // TB Simulus ====> |------------| |----------------|
+ // | XgigE MAC | <===> | XgigE PCS/PMA | <====>||
+ // TB Checker <==== |------------| |----------------| || Loopback through
+ // ||
+ // ====> |------------| |----------------| || perfect serial channel
+ // Loopback | | XgigE MAC | <===> | XgigE PCS/PMA | <====>||
+ // <==== |------------| |----------------|
+
+ // Initialize DUT
+ wire xgige_refclk, xgige_clk156, xgige_dclk;
+ wire m_user_clk, s_user_clk;
+ wire m_channel_up, s_channel_up;
+
+ wire [63:0] m_xgmii_txd;
+ wire [7:0] m_xgmii_txc;
+ wire [63:0] m_xgmii_rxd;
+ wire [7:0] m_xgmii_rxc;
+ wire [63:0] s_xgmii_txd;
+ wire [7:0] s_xgmii_txc;
+ wire [63:0] s_xgmii_rxd;
+ wire [7:0] s_xgmii_rxc;
+ wire [7:0] m_xgmii_status;
+ wire [7:0] s_xgmii_status;
+ wire m_xge_phy_resetdone;
+ wire s_xge_phy_resetdone;
+ wire m_mdc, m_mdio_in, m_mdio_out;
+ wire s_mdc, s_mdio_in, s_mdio_out;
+ wire sfpp_rxlos,sfpp_tx_fault,sfpp_tx_disable;
+
+
+ wire [15:0] m_phy_status;
+ wire [15:0] s_phy_status;
+ wire [63:0] loop_tdata;
+ wire [3:0] loop_tuser;
+ wire loop_tlast, loop_tvalid, loop_tready;
+
+ wire [7:0] wb_adr_i;
+ wire wb_cyc_i;
+ wire [31:0] wb_dat_i;
+ wire wb_stb_i;
+ wire wb_we_i;
+ wire wb_ack_o;
+ wire [31:0] wb_dat_o;
+ wire wb_int_o;
+ //`ifdef USE_ARM_FRAMER
+ //wire [63:0] c2e_tdata_int;
+ //wire [3:0] c2e_tuser_int;
+ //wire c2e_tlast_int;
+ //wire c2e_tvalid_int;
+ //wire c2e_tready_int;
+ //wire [63:0] c2e_tdata;
+ //wire [3:0] c2e_tuser;
+ //wire c2e_tlast;
+ //wire c2e_tvalid;
+ //wire c2e_tready;
+ //`endif
+
+ reg independent_clock;
+ assign m_channel_up = m_phy_status[0];
+ assign s_channel_up = s_phy_status[0];
+ //assign m_user_clk = xgige_refclk;
+ //assign s_user_clk = xgige_refclk;
+ assign m_user_clk = independent_clock;
+ assign s_user_clk = independent_clock;
+
+ ten_gige_phy_clk_gen xgige_clk_gen_i (
+ .areset(GSR),
+ .refclk_p(XG_CLK_P),
+ .refclk_n(XG_CLK_N),
+ .refclk(xgige_refclk),
+ .clk156(xgige_clk156),
+ .dclk(xgige_dclk)
+ );
+
+ cvita_master m_tx_chdr (.clk(m_user_clk));
+ cvita_slave s_rx_chdr (.clk(s_user_clk));
+ // Use this to send axi-stream with arm_framer
+ //`ifdef USE_ARM_FRAMER
+ //axis_master #(.DWIDTH(68)) m_axis (.clk(m_user_clk));
+ //axis_slave #(.DWIDTH(68)) s_axis (.clk(s_user_clk));
+ //`endif
+ initial
+ begin
+ independent_clock <= 1'b0;
+ forever
+ begin
+ independent_clock <= 1'b0;
+ #2.5;
+ independent_clock <= 1'b1;
+ #2.5;
+ end
+ end
+
+ assign sfpp_rxlos = 1'b0;
+ assign sfpp_tx_fault = 1'b0;
+
+ // Instantiate the 10GBASER/KR GT Common block
+ ten_gig_eth_pcs_pma_gt_common # (
+ .WRAPPER_SIM_GTRESET_SPEEDUP("TRUE") ) //Does not affect hardware
+ ten_gig_eth_pcs_pma_gt_common_block
+ (
+ .refclk(xgige_refclk),
+ .qpllreset(qpllreset),
+ .qplllock(qplllock),
+ .qplloutclk(qplloutclk),
+ .qplloutrefclk(qplloutrefclk),
+ .qpllrefclksel(3'b001 /*3'b101*GTSOUTHREFCLK0*/)
+ );
+
+ ten_gige_phy ten_gige_phy_master_i
+ (
+ // Clocks and Reset
+ .areset(GSR), // Asynchronous reset for entire core.
+ .refclk(xgige_refclk), // Transciever reference clock: 156.25MHz
+ .clk156(xgige_clk156), // Globally buffered core clock: 156.25MHz
+ .dclk(xgige_dclk), // Management/DRP clock: 78.125MHz
+ .sim_speedup_control(~GSR),
+ // GMII Interface (client MAC <=> PCS)
+ .xgmii_txd(m_xgmii_txd), // Transmit data from client MAC.
+ .xgmii_txc(m_xgmii_txc), // Transmit control signal from client MAC.
+ .xgmii_rxd(m_xgmii_rxd), // Received Data to client MAC.
+ .xgmii_rxc(m_xgmii_rxc), // Received control signal to client MAC.
+ // Tranceiver Interface
+ .txp(SFP_LN0_P), // Differential +ve of serial transmission from PMA to PMD.
+ .txn(SFP_LN0_N), // Differential -ve of serial transmission from PMA to PMD.
+ .rxp(SFP_LN1_P), // Differential +ve for serial reception from PMD to PMA.
+ .rxn(SFP_LN1_N), // Differential -ve for serial reception from PMD to PMA.
+ // Management: MDIO Interface
+ .mdc(m_mdc), // Management Data Clock
+ .mdio_in(m_mdio_in), // Management Data In
+ .mdio_out(m_mdio_out), // Management Data Out
+ .mdio_tri(), // Management Data Tristate
+ .prtad(5'd4), // MDIO address is 4
+ // General IO's
+ .core_status(m_xgmii_status), // Core status
+ .resetdone(m_xge_phy_resetdone),
+ .signal_detect(~sfpp_rxlos), //FIXME // Input from PMD to indicate presence of optical input. (Undocumented, but it seems Xilinx expect this to be inverted.)
+ .tx_fault(sfpp_tx_fault), //FIXME
+ .tx_disable(/*sfpp_tx_disable*/), //FIXME
+ .qpllreset(qpllreset1),
+ .qplllock(qplllock),
+ .qplloutclk(qplloutclk),
+ .qplloutrefclk(qplloutrefclk)
+
+ );
+
+ n310_xge_mac_wrapper #(.PORTNUM(PORTNUM)) xge_mac_wrapper_master_i
+ (
+ // XGMII
+ .xgmii_clk(xgige_clk156),
+ .xgmii_txd(m_xgmii_txd),
+ .xgmii_txc(m_xgmii_txc),
+ .xgmii_rxd(m_xgmii_rxd),
+ .xgmii_rxc(m_xgmii_rxc),
+ // Client FIFO Interfaces
+ .sys_clk(m_user_clk),
+ .sys_rst(GSR),
+ //`ifdef USE_ARM_FRAMER
+ //.rx_tdata(s_axis.axis.tdata[63:0]),
+ //.rx_tuser(s_axis.axis.tdata[67:64]),
+ //.rx_tlast(s_axis.axis.tlast),
+ //.rx_tvalid(s_axis.axis.tvalid),
+ //.rx_tready(/*s_axis.axis.tready*/1'b1),
+ //.tx_tdata(c2e_tdata),
+ //.tx_tuser(c2e_tuser),
+ //.tx_tlast(c2e_tlast),
+ //.tx_tvalid(c2e_tvalid),
+ //.tx_tready(c2e_tready),
+ //`endif
+ .rx_tdata(s_rx_chdr.axis.tdata),
+ .rx_tuser(),
+ .rx_tlast(s_rx_chdr.axis.tlast),
+ .rx_tvalid(s_rx_chdr.axis.tvalid),
+ .rx_tready(s_rx_chdr.axis.tready),
+ .tx_tdata(m_tx_chdr.axis.tdata),
+ .tx_tuser(4'd4), // Bit[3] (error) is ignored for now.
+ .tx_tlast(m_tx_chdr.axis.tlast),
+ .tx_tvalid(m_tx_chdr.axis.tvalid),
+ .tx_tready(m_tx_chdr.axis.tready),
+ // Other
+ .phy_ready(m_xge_phy_resetdone),
+ .ctrl_tx_enable (/*mac_ctrl_reg[0]*/1'b1), //FIXME: Remove hardcoded value
+ .status_crc_error (),
+ .status_fragment_error (),
+ .status_txdfifo_ovflow (),
+ .status_txdfifo_udflow (),
+ .status_rxdfifo_ovflow (),
+ .status_rxdfifo_udflow (),
+ .status_pause_frame_rx (),
+ .status_local_fault (),
+ .status_remote_fault ()
+ );
+
+ assign m_phy_status = {8'h00, m_xgmii_status};
+
+ //`ifdef USE_ARM_FRAMER
+ // arm_framer inst_arm_framer (
+ // .clk (m_user_clk),
+ // .reset (GSR),
+ // .clear (clear),
+ // .s_axis_tdata (m_axis.axis.tdata[63:0]),
+ // .s_axis_tuser (m_axis.axis.tdata[67:64]),
+ // .s_axis_tlast (m_axis.axis.tlast),
+ // .s_axis_tvalid (m_axis.axis.tvalid),
+ // .s_axis_tready (m_axis.axis.tready),
+ // .m_axis_tdata (c2e_tdata_int),
+ // .m_axis_tuser (c2e_tuser_int),
+ // .m_axis_tlast (c2e_tlast_int),
+ // .m_axis_tvalid (c2e_tvalid_int),
+ // .m_axis_tready (c2e_tready_int)
+ // );
+
+ // axi_mux4 #(.PRIO(0), .WIDTH(68)) eth_mux
+ // (.clk(m_user_clk), .reset(GSR), .clear(clear),
+ // .i0_tdata({c2e_tuser_int,c2e_tdata_int}), .i0_tlast(c2e_tlast_int), .i0_tvalid(c2e_tvalid_int), .i0_tready(c2e_tready_int),
+ // .i1_tdata(), .i1_tlast(), .i1_tvalid(), .i1_tready(),
+ // .i2_tdata(), .i2_tlast(), .i2_tvalid(), .i2_tready(),
+ // .i3_tdata(), .i3_tlast(), .i3_tvalid(1'b0), .i3_tready(),
+ // .o_tdata({c2e_tuser,c2e_tdata}), .o_tlast(c2e_tlast), .o_tvalid(c2e_tvalid), .o_tready(c2e_tready));
+ //`endif
+
+ ten_gige_phy ten_gige_phy_slave_i
+ (
+ // Clocks and Reset
+ .areset(GSR), // Asynchronous reset for entire core.
+ .refclk(xgige_refclk), // Transciever reference clock: 156.25MHz
+ .clk156(xgige_clk156), // Globally buffered core clock: 156.25MHz
+ .dclk(xgige_dclk), // Management/DRP clock: 78.125MHz
+ .sim_speedup_control(~GSR),
+ // GMII Interface (client MAC <=> PCS)
+ .xgmii_txd(s_xgmii_txd), // Transmit data from client MAC.
+ .xgmii_txc(s_xgmii_txc), // Transmit control signal from client MAC.
+ .xgmii_rxd(s_xgmii_rxd), // Received Data to client MAC.
+ .xgmii_rxc(s_xgmii_rxc), // Received control signal to client MAC.
+ // Tranceiver Interface
+ .txp(SFP_LN1_P), // Differential +ve of serial transmission from PMA to PMD.
+ .txn(SFP_LN1_N), // Differential -ve of serial transmission from PMA to PMD.
+ .rxp(SFP_LN0_P), // Differential +ve for serial reception from PMD to PMA.
+ .rxn(SFP_LN0_N), // Differential -ve for serial reception from PMD to PMA.
+ // Management: MDIO Interface
+ .mdc(s_mdc), // Management Data Clock
+ .mdio_in(s_mdio_in), // Management Data In
+ .mdio_out(s_mdio_out), // Management Data Out
+ .mdio_tri(), // Management Data Tristate
+ .prtad(5'd4), // MDIO address is 4
+ // General IO's
+ .core_status(s_xgmii_status), // Core status
+ .resetdone(s_xge_phy_resetdone),
+ .signal_detect(~sfpp_rxlos), //FIXME // Input from PMD to indicate presence of optical input. (Undocumented, but it seems Xilinx expect this to be inverted.)
+ .tx_fault(sfpp_tx_fault), //FIXME
+ .tx_disable(/*sfpp_tx_disable*/), //FIXME
+ .qpllreset(qpllreset2),
+ .qplllock(qplllock),
+ .qplloutclk(qplloutclk),
+ .qplloutrefclk(qplloutrefclk)
+ );
+
+ n310_xge_mac_wrapper #(.PORTNUM(PORTNUM)) xge_mac_wrapper_slave_i
+ (
+ // XGMII
+ .xgmii_clk(xgige_clk156),
+ .xgmii_txd(s_xgmii_txd),
+ .xgmii_txc(s_xgmii_txc),
+ .xgmii_rxd(s_xgmii_rxd),
+ .xgmii_rxc(s_xgmii_rxc),
+ // Client FIFO Interfaces
+ .sys_clk(s_user_clk),
+ .sys_rst(GSR),
+ .rx_tdata(loop_tdata),
+ .rx_tuser(loop_tuser),
+ .rx_tlast(loop_tlast),
+ .rx_tvalid(loop_tvalid),
+ .rx_tready(loop_tready),
+ .tx_tdata(loop_tdata),
+ .tx_tuser(loop_tuser), // Bit[3] (error) is ignored for now.
+ .tx_tlast(loop_tlast),
+ .tx_tvalid(loop_tvalid),
+ .tx_tready(loop_tready),
+ // Other
+ .phy_ready(s_xge_phy_resetdone),
+ .ctrl_tx_enable (/*mac_ctrl_reg[0]*/1'b1), //FIXME: Remove hardcoded value
+ .status_crc_error (),
+ .status_fragment_error (),
+ .status_txdfifo_ovflow (),
+ .status_txdfifo_udflow (),
+ .status_rxdfifo_ovflow (),
+ .status_rxdfifo_udflow (),
+ .status_pause_frame_rx (),
+ .status_local_fault (),
+ .status_remote_fault ()
+ );
+
+ assign s_phy_status = {8'h00, s_xgmii_status};
+
+ //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
+ `TEST_CASE_START("Wait for reset");
+ // `ifdef USE_ARM_FRAMER
+ // m_axis.reset;
+ // `endif
+ while (GSR) @(posedge XG_CLK_P);
+ `TEST_CASE_DONE((~GSR));
+
+ m_tx_chdr.push_bubble();
+ // `ifdef USE_ARM_FRAMER
+ //m_axis.push_bubble();
+ // `endif
+
+ `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 PRBS15 BIST");
+ // s_bist_loopback <= PACKET_MODE;
+ // @(posedge m_user_clk);
+ // 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);
+
+ repeat(2000) @(posedge m_user_clk);
+
+ //`TEST_CASE_START("Test Ethernet packet");
+ // s_axis.axis.tready = 0;
+ // m_axis.push_word({4'b0, 64'h0000_0000_0000_ffff}, 1'b0);
+ // s_axis.axis.tready = 1;
+ // m_axis.push_word({4'b0, 64'hffff_ffff_ce20_ad1b}, 1'b0);
+ // m_axis.push_word({4'b0, 64'hc57a_0806_0001_0800}, 1'b0);
+ // m_axis.push_word({4'b0, 64'h0604_0001_ce20_ad1b}, 1'b0);
+ // m_axis.push_word({4'b0, 64'hc57a_c0a8_0a64_0000}, 1'b0);
+ // m_axis.push_word({4'b0, 64'h0000_0000_c0a8_0a0a}, 1'b1);
+ //`TEST_CASE_DONE(1'b1);
+
+ // repeat(2000) @(posedge m_user_clk);
+ //`TEST_CASE_START("Test Ethernet packet");
+ // s_axis.axis.tready = 0;
+ // m_axis.push_word({4'b0, 64'hffff_ffff_ffff_9aa9}, 1'b0);
+ // s_axis.axis.tready = 1;
+ // m_axis.push_word({4'b0, 64'h6400_e341_0800_4500}, 1'b0);
+ // m_axis.push_word({4'b0, 64'h0148_0000_0000_4011}, 1'b0);
+ // m_axis.push_word({4'b0, 64'h79a6_0000_0000_ffff}, 1'b0);
+ // m_axis.push_word({4'b0, 64'hffff_0044_0043_0134}, 1'b0);
+ // m_axis.push_word({4'b0, 64'h90be_0101_0600_d2ab}, 1'b0);
+ // m_axis.push_word({4'b0, 64'h9f01_0007_0000_0000}, 1'b0);
+ // m_axis.push_word({4'b0, 64'h0000_0000_0000_0000}, 1'b0);
+ // m_axis.push_word({4'b0, 64'h0000_0000_0000_9aa9}, 1'b0);
+ // m_axis.push_word({4'b0, 64'h6400_e341_0000_0000}, 1'b0);
+ // m_axis.push_word({4'b0, 64'h0000_0000_0000_0000}, 1'b0);
+ // m_axis.push_word({4'b0, 64'h0000_0000_0000_0000}, 1'b0);
+ // m_axis.push_word({4'b0, 64'h0000_0000_0000_0000}, 1'b0);
+ // m_axis.push_word({4'b0, 64'h0000_0000_0000_0000}, 1'b0);
+ // m_axis.push_word({4'b0, 64'h0000_0000_0000_0000}, 1'b0);
+ // m_axis.push_word({4'b0, 64'h0000_0000_0000_0000}, 1'b0);
+ // m_axis.push_word({4'b0, 64'h0000_0000_0000_0000}, 1'b0);
+ // m_axis.push_word({4'b0, 64'h0000_0000_0000_0000}, 1'b0);
+ // m_axis.push_word({4'b0, 64'h0000_0000_0000_0000}, 1'b0);
+ // m_axis.push_word({4'b0, 64'h0000_0000_0000_0000}, 1'b0);
+ // m_axis.push_word({4'b0, 64'h0000_0000_0000_0000}, 1'b0);
+ // m_axis.push_word({4'b0, 64'h0000_0000_0000_0000}, 1'b0);
+ // m_axis.push_word({4'b0, 64'h0000_0000_0000_0000}, 1'b0);
+ // m_axis.push_word({4'b0, 64'h0000_0000_0000_0000}, 1'b0);
+ // m_axis.push_word({4'b0, 64'h0000_0000_0000_0000}, 1'b0);
+ // m_axis.push_word({4'b0, 64'h0000_0000_0000_0000}, 1'b0);
+ // m_axis.push_word({4'b0, 64'h0000_0000_0000_0000}, 1'b0);
+ // m_axis.push_word({4'b0, 64'h0000_0000_0000_0000}, 1'b0);
+ // m_axis.push_word({4'b0, 64'h0000_0000_0000_0000}, 1'b0);
+ // m_axis.push_word({4'b0, 64'h0000_0000_0000_0000}, 1'b0);
+ // m_axis.push_word({4'b0, 64'h0000_0000_0000_0000}, 1'b0);
+ // m_axis.push_word({4'b0, 64'h0000_0000_0000_0000}, 1'b0);
+ // m_axis.push_word({4'b0, 64'h0000_0000_0000_0000}, 1'b0);
+ // m_axis.push_word({4'b0, 64'h0000_0000_0000_0000}, 1'b0);
+ // m_axis.push_word({4'b0, 64'h0000_0000_0000_6382}, 1'b0);
+ // m_axis.push_word({4'b0, 64'h5363_3501_013d_0701}, 1'b0);
+ // m_axis.push_word({4'b0, 64'h9aa9_6400_e341_3902}, 1'b0);
+ // m_axis.push_word({4'b0, 64'h0240_3707_0103_060c}, 1'b0);
+ // m_axis.push_word({4'b0, 64'h0f1c_2a3c_0c75_6468}, 1'b0);
+ // m_axis.push_word({4'b0, 64'h6370_2031_2e32_342e}, 1'b0);
+ // m_axis.push_word({4'b0, 64'h31ff_0000_0000_0000}, 1'b0);
+ // m_axis.push_word({5'b0, 64'h0000_0000_0000_0000}, 1'b0);
+ // m_axis.push_word({4'd6, 64'h0000_0000_1234_0000}, 1'b1);
+
+ //`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)");
+ s_rx_chdr.axis.tready = 0;
+ m_tx_chdr.push_ramp_pkt(16, 64'd0, 64'h100, header);
+ s_rx_chdr.axis.tready = 1;
+ s_rx_chdr.wait_for_pkt_get_info(header_out, stats);
+ `ASSERT_ERROR(stats.count==16, "Bad packet: Length mismatch");
+ `ASSERT_ERROR(header.dst_sid==header_out.dst_sid, "Bad packet: Wrong SID");
+ `TEST_CASE_DONE(1);
+
+ `TEST_CASE_START("Fill up empty FIFO then drain (long packet)");
+ s_rx_chdr.axis.tready = 0;
+ m_tx_chdr.push_ramp_pkt(256, 64'd0, 64'h100, header);
+ s_rx_chdr.axis.tready = 1;
+ s_rx_chdr.wait_for_pkt_get_info(header_out, stats);
+ `ASSERT_ERROR(stats.count==256, "Bad packet: Length mismatch");
+ `ASSERT_ERROR(header.dst_sid==header_out.dst_sid, "Bad packet: Wrong SID");
+ `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)");
+ s_rx_chdr.axis.tready = 1;
+ fork
+ begin
+ m_tx_chdr.push_ramp_pkt(1000, 64'd0, 64'h100, header);
+ end
+ begin
+ s_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==1000, "Bad packet: Length mismatch");
+ `TEST_CASE_DONE(1);
+
+ `TEST_CASE_START("Concurrent read and write (multiple packets)");
+ s_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
+ s_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 PRBS15 BIST (Loopback Mode)");
+ //@(posedge m_user_clk);
+ //m_bist_gen <= 1'b1;
+ //m_bist_rate <= 5'd4;
+ //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));
+
+ end
+
+endmodule