diff options
Diffstat (limited to 'fpga/usrp3/top/n3xx/sim')
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 | 
