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