aboutsummaryrefslogtreecommitdiffstats
path: root/fpga/usrp3/top/n3xx/sim/one_gig_eth_loopback
diff options
context:
space:
mode:
Diffstat (limited to 'fpga/usrp3/top/n3xx/sim/one_gig_eth_loopback')
-rw-r--r--fpga/usrp3/top/n3xx/sim/one_gig_eth_loopback/Makefile78
-rw-r--r--fpga/usrp3/top/n3xx/sim/one_gig_eth_loopback/demo_one_gig_pcs_pma_mdio.v489
-rw-r--r--fpga/usrp3/top/n3xx/sim/one_gig_eth_loopback/one_gig_eth_loopback_tb.sv381
3 files changed, 948 insertions, 0 deletions
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