From 6d3765605262016a80f71e36357f749ea35cbe5a Mon Sep 17 00:00:00 2001 From: Wade Fife Date: Tue, 8 Jun 2021 19:40:46 -0500 Subject: fpga: x400: Add support for X410 motherboard FPGA MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Andrew Moch Co-authored-by: Daniel Jepson Co-authored-by: Javier Valenzuela Co-authored-by: Joerg Hofrichter Co-authored-by: Kumaran Subramoniam Co-authored-by: Max Köhler Co-authored-by: Michael Auchter Co-authored-by: Paul Butler Co-authored-by: Wade Fife Co-authored-by: Hector Rubio --- fpga/usrp3/top/x400/ip/xge_pcs_pma/Makefile.inc | 47 + fpga/usrp3/top/x400/ip/xge_pcs_pma/eth_10g.sv | 173 +++ fpga/usrp3/top/x400/ip/xge_pcs_pma/model_10gbe.sv | 174 +++ fpga/usrp3/top/x400/ip/xge_pcs_pma/ten_gige_phy.v | 274 +++++ fpga/usrp3/top/x400/ip/xge_pcs_pma/xge_pcs_pma.xci | 1184 ++++++++++++++++++++ .../ip/xge_pcs_pma/xge_pcs_pma_wrapper.v.patch | 30 + 6 files changed, 1882 insertions(+) create mode 100644 fpga/usrp3/top/x400/ip/xge_pcs_pma/Makefile.inc create mode 100644 fpga/usrp3/top/x400/ip/xge_pcs_pma/eth_10g.sv create mode 100644 fpga/usrp3/top/x400/ip/xge_pcs_pma/model_10gbe.sv create mode 100644 fpga/usrp3/top/x400/ip/xge_pcs_pma/ten_gige_phy.v create mode 100644 fpga/usrp3/top/x400/ip/xge_pcs_pma/xge_pcs_pma.xci create mode 100644 fpga/usrp3/top/x400/ip/xge_pcs_pma/xge_pcs_pma_wrapper.v.patch (limited to 'fpga/usrp3/top/x400/ip/xge_pcs_pma') diff --git a/fpga/usrp3/top/x400/ip/xge_pcs_pma/Makefile.inc b/fpga/usrp3/top/x400/ip/xge_pcs_pma/Makefile.inc new file mode 100644 index 000000000..4df9bcc5f --- /dev/null +++ b/fpga/usrp3/top/x400/ip/xge_pcs_pma/Makefile.inc @@ -0,0 +1,47 @@ +# +# Copyright 2021 Ettus Research, a National Instruments Brand +# +# SPDX-License-Identifier: LGPL-3.0-or-later +# + +include $(TOOLS_DIR)/make/viv_ip_builder.mak + +XGE_PCS_PMA_SRCS = \ +$(IP_DIR)/xge_pcs_pma/ten_gige_phy.v \ +$(IP_DIR)/xge_pcs_pma/eth_10g.sv \ +$(IP_XGE_PCS_PMA_EXAMPLE_SRCS) + +IP_XGE_PCS_PMA_HDL_SIM_SRCS = $(IP_DIR)/xge_pcs_pma/model_10gbe.sv \ +$(wildcard $(addprefix $(IP_BUILD_DIR)/xge_pcs_pma/, \ +xge_pcs_pma.v \ +hdl/xxv_ethernet_v3_0_vl_rfs.sv \ +ip_0/hdl/*.v \ +ip_0/sim/*.v \ +xxv_ethernet_v3_0_1/*.v \ +)) + +IP_XGE_PCS_PMA_EXAMPLE_SRCS = \ +$(IP_BUILD_DIR)/xge_pcs_pma_ex/imports/xge_pcs_pma_common_wrapper.v \ +$(IP_BUILD_DIR)/xge_pcs_pma_ex/imports/xge_pcs_pma_gt_gtye4_common_wrapper.v \ +$(IP_BUILD_DIR)/xge_pcs_pma_ex/imports/gtwizard_ultrascale_v1_7_gtye4_common.v \ + +# Describe the paths for the patch file, the file to be patched, and the +# patched copy of the file. +IP_XGE_FILE_PATCH = $(IP_DIR)/xge_pcs_pma/xge_pcs_pma_wrapper.v.patch +IP_XGE_FILE_TO_PATCH = $(IP_BUILD_DIR)/xge_pcs_pma/xxv_ethernet_v3_0_1/xge_pcs_pma_wrapper.v +IP_XGE_PATCHED_FILE = $(IP_BUILD_DIR)/xge_pcs_pma_wrapper.v.patched + +IP_XGE_PCS_PMA_SRCS = $(IP_BUILD_DIR)/xge_pcs_pma/xge_pcs_pma.xci $(IP_XGE_PATCHED_FILE) + +IP_XGE_PCS_PMA_OUTS = \ +$(IP_BUILD_DIR)/xge_pcs_pma/xge_pcs_pma.xci.out \ +$(IP_BUILD_DIR)/xge_pcs_pma/xge_pcs_pma.v \ + +$(IP_XGE_PCS_PMA_EXAMPLE_SRCS) : $(IP_XGE_PCS_PMA_OUTS) + +$(IP_XGE_PCS_PMA_SRCS) $(IP_XGE_PCS_PMA_OUTS) : $(IP_DIR)/xge_pcs_pma/xge_pcs_pma.xci $(IP_XGE_FILE_PATCH) + $(call BUILD_VIVADO_IP,xge_pcs_pma,$(ARCH),$(PART_ID),$(IP_DIR),$(IP_BUILD_DIR),1) + cp $(IP_XGE_FILE_TO_PATCH) $(IP_XGE_FILE_TO_PATCH).orig + cp $(IP_XGE_FILE_TO_PATCH) $(IP_XGE_PATCHED_FILE) + patch $(IP_XGE_PATCHED_FILE) $(IP_XGE_FILE_PATCH) + $(call REBUILD_VIVADO_IP_WITH_PATCH,xge_pcs_pma,$(ARCH),$(PART_ID),$(IP_DIR),$(IP_BUILD_DIR),0,$(call RESOLVE_PATH,$(IP_XGE_PATCHED_FILE)),$(call RESOLVE_PATH,$(IP_XGE_FILE_TO_PATCH))) diff --git a/fpga/usrp3/top/x400/ip/xge_pcs_pma/eth_10g.sv b/fpga/usrp3/top/x400/ip/xge_pcs_pma/eth_10g.sv new file mode 100644 index 000000000..41e60e789 --- /dev/null +++ b/fpga/usrp3/top/x400/ip/xge_pcs_pma/eth_10g.sv @@ -0,0 +1,173 @@ +// +// Copyright 2021 Ettus Research, A National Instruments Brand +// +// SPDX-License-Identifier: LGPL-3.0-or-later +// +// Module: eth_10g +// +// Description: Wrapper for the 10G mac and phy + + +module eth_10g ( + + // Resets + input logic areset, + // Clock for misc stuff + input logic clk100, + // Shared Quad signals + output logic[0:0] qpll0_reset, + input logic[0:0] qpll0_lock, + input logic[0:0] qpll0_clk, + input logic[0:0] qpll0_refclk, + output logic[0:0] qpll1_reset, + input logic[0:0] qpll1_lock, + input logic[0:0] qpll1_clk, + input logic[0:0] qpll1_refclk, + // RX Clk for output + output logic rx_rec_clk_out, + // MGT high-speed IO + output logic tx_p, + output logic tx_n, + input logic rx_p, + input logic rx_n, + + // Data port + output logic mgt_clk, + output logic mgt_rst, + // Interface clocks for mgt_tx and mgt_rx are NOT used (logic uses using mgt_clk) + AxiStreamIf.slave mgt_tx, + AxiStreamIf.master mgt_rx, + // Axi port + AxiLiteIf.slave mgt_axil, + // Misc + output logic [31:0] phy_status, + input logic [31:0] mac_ctrl, + output logic [31:0] mac_status, + output logic phy_reset, + output logic link_up +); + + import PkgAxiLite::*; + + assign phy_status[31:8] = 24'h0; + assign mac_status[31:9] = 23'h0; + assign link_up = phy_status[0]; + + // respond with error if anyone reads this memory region + always_comb begin + mgt_axil.awready = 1'b1; + mgt_axil.wready = 1'b1; + mgt_axil.bresp= SLVERR; + mgt_axil.bvalid = 1'b1; + mgt_axil.arready = 1'b1; + mgt_axil.rdata = 'b0; + mgt_axil.rresp = SLVERR; + mgt_axil.rvalid = 1'b1; + end + + logic xgmii_clk; + logic [63:0] xgmii_txd; + logic [7:0] xgmii_txc; + logic [63:0] xgmii_rxd; + logic [7:0] xgmii_rxc; + logic xge_phy_resetdone; + + assign phy_reset = !xge_phy_resetdone; + assign mgt_clk = xgmii_clk; + + // This is a heavily replicated signal, add some pipeline + // to it to make it easier to spread out + logic mgt_rst_0; + + always_ff @(posedge mgt_clk,posedge areset) begin : reset_timing_dff + if (areset) begin + mgt_rst_0 = 1'b1; + mgt_rst = 1'b1; + end else begin + mgt_rst_0 = !link_up; + mgt_rst = mgt_rst_0; + end + end + + // areset pin notes - reset is used asynchronously + ten_gige_phy ten_gige_phy_i ( + .areset (areset), + .dclk (clk100), + .xgmii_clk (xgmii_clk), + .txp (tx_p), + .txn (tx_n), + .rxp (rx_p), + .rxn (rx_n), + .xgmii_txd (xgmii_txd), + .xgmii_txc (xgmii_txc), + .xgmii_rxd (xgmii_rxd), + .xgmii_rxc (xgmii_rxc), + .qpll0_refclk (qpll0_refclk), + .qpll0_clk (qpll0_clk), + .qpll0_lock (qpll0_lock), + .qpll0_reset (qpll0_reset), + .qpll1_refclk (qpll1_refclk), + .qpll1_clk (qpll1_clk), + .qpll1_lock (qpll1_lock), + .qpll1_reset (qpll1_reset), + .rxrecclkout (rx_rec_clk_out), + .core_status (phy_status[7:0]), + .reset_done (xge_phy_resetdone) + ); + + xge_mac_wrapper #( + .PORTNUM(0), + .WISHBONE(0), + .ADD_PREAMBLE(0), + .CROSS_TO_SYSCLK(0), + .CUT_THROUGH(15) + ) xge_mac_wrapper_i ( + // XGMII + .xgmii_clk(xgmii_clk), + .xgmii_txd(xgmii_txd), + .xgmii_txc(xgmii_txc), + .xgmii_rxd(xgmii_rxd), + .xgmii_rxc(xgmii_rxc), + // Client FIFO Interfaces + .sys_clk(1'b0), + .sys_rst(1'b0), + .rx_tdata(mgt_rx.tdata), + .rx_tuser(mgt_rx.tuser), + .rx_tlast(mgt_rx.tlast), + .rx_tvalid(mgt_rx.tvalid), + .rx_tready(mgt_rx.tready), + .tx_tdata(mgt_tx.tdata), + .tx_tuser(mgt_tx.tuser), // Bit[3] (error) is ignored for now. + .tx_tlast(mgt_tx.tlast), + .tx_tvalid(mgt_tx.tvalid), + .tx_tready(mgt_tx.tready), + // Control and Status + .phy_ready(xge_phy_resetdone), + .ctrl_tx_enable(mac_ctrl[0]), + .status_crc_error(mac_status[0]), + .status_fragment_error(mac_status[1]), + .status_txdfifo_ovflow(mac_status[2]), + .status_txdfifo_udflow(mac_status[3]), + .status_rxdfifo_ovflow(mac_status[4]), + .status_rxdfifo_udflow(mac_status[5]), + .status_pause_frame_rx(mac_status[6]), + .status_local_fault(mac_status[7]), + .status_remote_fault(mac_status[8]), + // MDIO + .mdc(), + .mdio_in(), + .mdio_out(1'b0), + // Wishbone + .wb_ack_o(), + .wb_dat_o(), + .wb_adr_i(8'b0), + .wb_clk_i(1'b0), + .wb_cyc_i(1'b0), + .wb_dat_i(32'b0), + .wb_rst_i(1'b0), + .wb_stb_i(1'b0), + .wb_we_i (1'b0), + .wb_int_o() + ); + +endmodule diff --git a/fpga/usrp3/top/x400/ip/xge_pcs_pma/model_10gbe.sv b/fpga/usrp3/top/x400/ip/xge_pcs_pma/model_10gbe.sv new file mode 100644 index 000000000..bda0c2c64 --- /dev/null +++ b/fpga/usrp3/top/x400/ip/xge_pcs_pma/model_10gbe.sv @@ -0,0 +1,174 @@ +// +// Copyright 2021 Ettus Research, A National Instruments Brand +// +// SPDX-License-Identifier: LGPL-3.0-or-later +// +// Module: model_10gbe +// +// Description: +// +// A wrapper of the 10gbe core to axistream interface. this model can be used +// drive packets into the x400 translated to serial ethernet. This is far +// slower than just driving things in at the output of the mac with force's +// + +module model_10gbe #( + parameter [7:0] PORTNUM = 8'd0 +)( + input logic areset, + // 156.25 Mhz refclk + input logic ref_clk, + + // QSFP high-speed IO + output logic tx_p, + output logic tx_n, + input logic rx_p, + input logic rx_n, + + // CLK and RESET - 156.25 + output logic mgt_clk, + output logic mgt_rst, + output logic link_up, + + + // Data port + AxiStreamIf.slave mgt_tx, + AxiStreamIf.master mgt_rx + +); + + // Include macros and time declarations for use with PkgTestExec + `define TEST_EXEC_OBJ test + `include "test_exec.svh" + import PkgAxiLiteBfm::*; + import PkgTestExec::*; + + logic clk40,clk40_rst; + logic clk100,clk100_rst; + logic phy_reset; + + //interface + AxiLiteIf #(32,32) + mgt_axil (clk40, clk40_rst); + //bfm + AxiLiteBfm #(32, 32) axi = new(.master(mgt_axil)); + TestExec mac_test = new(); + + sim_clock_gen #(.PERIOD(25.0), .AUTOSTART(1)) + clk40_gen (.clk(clk40), .rst(clk40_rst)); + sim_clock_gen #(.PERIOD(100.0), .AUTOSTART(1)) + clk100_gen (.clk(clk100), .rst(clk100_rst)); + + // Register Docs for init_model + // MAC CTRL REG Bit positions + // ctrl_tx_enable = mac_ctrl[0] + // MAC STATUS REG Bit positions + // status_crc_error = mac_status[0] 1 + // status_fragment_error = mac_status[1] 2 + // status_txdfifo_ovflow = mac_status[2] 4 + // status_txdfifo_udflow = mac_status[3] 8 + // status_rxdfifo_ovflow = mac_status[4] 10 + // status_rxdfifo_udflow = mac_status[5] 20 + // status_pause_frame_rx = mac_status[6] 40 + // status_local_fault = mac_status[7] 80 + // status_remote_fault = mac_status[8] 100 + + logic [31:0] phy_status; + logic [31:0] mac_status; + logic [31:0] mac_ctrl; + + initial begin : init_model + mac_ctrl = 0; + + clk40_gen.reset(); + axi.run(); + wait(!clk40_rst); + repeat (10) @(posedge clk40); + + mac_test.start_test("model_10gbe::Wait for phy reset done", 150us); + wait(phy_reset===1'b0); + mac_test.end_test(); + + mac_test.start_test("model_10gbe::Wait for MAC link_up", 150us); + mac_ctrl[0] = 1; // turn on TX + wait(link_up===1'b1); + mac_test.end_test(); + end + + logic [0:0] qpll0_reset; + logic [0:0] qpll0_lock; + logic [0:0] qpll0_clk; + logic [0:0] qpll0_refclk; + logic [0:0] qpll1_reset; + logic [0:0] qpll1_lock; + logic [0:0] qpll1_clk; + logic [0:0] qpll1_refclk; + + xge_pcs_pma_common_wrapper xge_pcs_pma_common_wrapperx ( + .refclk (ref_clk), + .qpll0reset (qpll0_reset), + .qpll0lock (qpll0_lock), + .qpll0outclk (qpll0_clk), + .qpll0outrefclk (qpll0_refclk), + .qpll1reset (qpll1_reset), + .qpll1lock (qpll1_lock), + .qpll1outclk (qpll1_clk), + .qpll1outrefclk (qpll1_refclk) + ); + + AxiStreamIf #(.DATA_WIDTH(64),.USER_WIDTH(4)) + eth10g_rx(mgt_clk,mgt_rst); + + always_comb begin + mgt_rx.tdata = eth10g_rx.tdata; + mgt_rx.tuser = eth10g_rx.tuser; + mgt_rx.tkeep = eth10g_rx.trailing2keep(eth10g_rx.tuser); + mgt_rx.tvalid = eth10g_rx.tvalid; + mgt_rx.tlast = eth10g_rx.tlast; + // The MAC ignores hold off. Data must be consumed every clock it is valid. + if (!mgt_rst) begin + if (!mgt_rx.tready && mgt_rx.tvalid) begin + $error("Model 100Gbe : can't hold off the MAC"); + end + end + end + + eth_10g eth_10g_i ( + .areset(areset), + //-- Free running 100 MHz clock used for InitClk and AxiLite to mac + .clk100(clk100), + // Quad Info + .qpll0_refclk (qpll0_refclk), + .qpll0_clk (qpll0_clk), + .qpll0_lock (qpll0_lock), + .qpll0_reset (qpll0_reset), + .qpll1_refclk (qpll1_refclk), + .qpll1_clk (qpll1_clk), + .qpll1_lock (qpll1_lock), + .qpll1_reset (qpll1_reset), + // MGT TX/RX differential signals + .tx_p(tx_p), + .tx_n(tx_n), + .rx_p(rx_p), + .rx_n(rx_n), + // MAC system_clock + .mgt_clk(mgt_clk), + .mgt_rst(mgt_rst), + //------------------------ AXI Stream TX Interface ------------------------ + .mgt_tx(mgt_tx), + //---------------------- AXI Stream RX Interface ------------------------ + // There is no RxTReady signal support by the Ethernet100G IP. Received data has to + // be read immediately or it is lost. + // tUser indicates an error on rcvd packet + .mgt_rx(eth10g_rx), + // Axi-Lite bus for tie off + .mgt_axil(mgt_axil), + // LEDs of QSFP28 port + .phy_status(phy_status), + .mac_ctrl(mac_ctrl), + .mac_status(mac_status), + .phy_reset(phy_reset), + .link_up(link_up) + ); + +endmodule diff --git a/fpga/usrp3/top/x400/ip/xge_pcs_pma/ten_gige_phy.v b/fpga/usrp3/top/x400/ip/xge_pcs_pma/ten_gige_phy.v new file mode 100644 index 000000000..b419c45da --- /dev/null +++ b/fpga/usrp3/top/x400/ip/xge_pcs_pma/ten_gige_phy.v @@ -0,0 +1,274 @@ +// +// Copyright 2021 Ettus Research, A National Instruments Brand +// +// SPDX-License-Identifier: LGPL-3.0-or-later +// +// Module: ten_gige_phy +// +// Description: +// +// Wrapper for the Xilinx xxv_ethernet IP (10G/25G Ethernet Subsystem). +// + + +module ten_gige_phy ( + input wire areset, + input wire dclk, + output wire xgmii_clk, + + // Transceiver IO + output wire txp, + output wire txn, + input wire rxp, + input wire rxn, + + // XGMII Interface + input wire [63:0] xgmii_txd, + input wire [ 7:0] xgmii_txc, + output wire [63:0] xgmii_rxd, + output wire [ 7:0] xgmii_rxc, + + // GTYE4_COMMON + input wire qpll0_refclk, + input wire qpll0_clk, + input wire qpll0_lock, + output wire qpll0_reset, + input wire qpll1_refclk, + input wire qpll1_clk, + input wire qpll1_lock, + output wire qpll1_reset, + + output wire rxrecclkout, + output wire [7:0] core_status, + output reg reset_done +); + + localparam XGMII_FREQ = 125_000_000; // xgmii_clk frequency in Hz + localparam RX_RST_WAIT = XGMII_FREQ/2; // Cycles to wait before resetting + localparam RX_RST_DURATION = 100; // Duration of reset in cycles + localparam RX_RST_COUNT_W = $clog2(RX_RST_WAIT); + + wire rx_serdes_reset; + wire tx_reset; + wire rx_reset; + + wire a_gt_reset_tx_done, gt_reset_tx_done; + wire a_gt_reset_rx_done, gt_reset_rx_done; + + wire stat_rx_status_tmp; + reg stat_rx_status; + + reg [RX_RST_COUNT_W-1:0] rst_count; + reg gt_rx_reset_in; + + //--------------------------------------------------------------------------- + // Xilinx 10G/25G IP High Speed Ethernet Subsystem Instance + //--------------------------------------------------------------------------- + + // All connections below follow the Xilinx IP example design, except that + // rx_core_clk is driven by tx_mii_clk instead of rx_clk_out. This puts the + // RX and TX interfaces on the same clock domain. + + // gtwiz_reset_qpll1reset_out is not connected to qpll1reset in the example + // design. Instead, qpll1reset is connected to 0. + assign qpll1_reset = 1'b0; + + xge_pcs_pma xge_pcs_pma_i ( + .gt_rxp_in_0 (rxp), + .gt_rxn_in_0 (rxn), + .gt_txp_out_0 (txp), + .gt_txn_out_0 (txn), + .rx_core_clk_0 (xgmii_clk), + .rx_serdes_reset_0 (rx_serdes_reset), + .txoutclksel_in_0 (3'b101), + .rxoutclksel_in_0 (3'b101), + .gt_dmonitorout_0 (), + .gt_eyescandataerror_0 (), + .gt_eyescanreset_0 (1'b0), + .gt_eyescantrigger_0 (1'b0), + .gt_pcsrsvdin_0 (16'b0), + .gt_rxbufreset_0 (1'b0), + .gt_rxbufstatus_0 (), + .gt_rxcdrhold_0 (1'b0), + .gt_rxcommadeten_0 (1'b0), + .gt_rxdfeagchold_0 (1'b0), + .gt_rxdfelpmreset_0 (1'b0), + .gt_rxlatclk_0 (1'b0), + .gt_rxlpmen_0 (1'b0), + .gt_rxpcsreset_0 (1'b0), + .gt_rxpmareset_0 (1'b0), + .gt_rxpolarity_0 (1'b0), + .gt_rxprbscntreset_0 (1'b0), + .gt_rxprbserr_0 (), + .gt_rxprbssel_0 (4'b0), + .gt_rxrate_0 (3'b0), + .gt_rxslide_in_0 (1'b0), + .gt_rxstartofseq_0 (), + .gt_txbufstatus_0 (), + .gt_txdiffctrl_0 (5'h18), + .gt_txinhibit_0 (1'b0), + .gt_txlatclk_0 (1'b0), + .gt_txmaincursor_0 (7'h50), + .gt_txpcsreset_0 (1'b0), + .gt_txpmareset_0 (1'b0), + .gt_txpolarity_0 (1'b0), + .gt_txpostcursor_0 (5'b0), + .gt_txprbsforceerr_0 (1'b0), + .gt_txprbssel_0 (4'b0), + .gt_txprecursor_0 (5'b0), + .rxrecclkout_0 (rxrecclkout), + .gt_drpclk_0 (dclk), + .gt_drpdo_0 (), + .gt_drprdy_0 (), + .gt_drpen_0 (1'b0), + .gt_drpwe_0 (1'b0), + .gt_drpaddr_0 (10'b0), + .gt_drpdi_0 (16'b0), + .sys_reset (areset), + .dclk (dclk), + .tx_mii_clk_0 (xgmii_clk), + .rx_clk_out_0 (), + .gtpowergood_out_0 (), + .qpll0clk_in (qpll0_clk), + .qpll0refclk_in (qpll0_refclk), + .qpll1clk_in (qpll1_clk), + .qpll1refclk_in (qpll1_refclk), + .gtwiz_reset_qpll0lock_in (qpll0_lock), + .gtwiz_reset_qpll1lock_in (qpll1_lock), + .gtwiz_reset_qpll0reset_out (qpll0_reset), + .gtwiz_reset_qpll1reset_out (), + .gt_reset_tx_done_out_0 (a_gt_reset_tx_done), + .gt_reset_rx_done_out_0 (a_gt_reset_rx_done), + .gt_reset_all_in_0 (areset), + .gt_tx_reset_in_0 (1'b0), + .gt_rx_reset_in_0 (gt_rx_reset_in), + .rx_reset_0 (rx_reset), + .rx_mii_d_0 (xgmii_rxd), + .rx_mii_c_0 (xgmii_rxc), + .ctl_rx_test_pattern_0 (1'b0), + .ctl_rx_test_pattern_enable_0 (1'b0), + .ctl_rx_data_pattern_select_0 (1'b0), + .ctl_rx_prbs31_test_pattern_enable_0 (1'b0), + .stat_rx_framing_err_0 (), + .stat_rx_framing_err_valid_0 (), + .stat_rx_local_fault_0 (), + .stat_rx_block_lock_0 (), + .stat_rx_valid_ctrl_code_0 (), + .stat_rx_status_0 (stat_rx_status_tmp), // rx_core_clk_0 domain + .stat_rx_hi_ber_0 (), + .stat_rx_bad_code_0 (), + .stat_rx_bad_code_valid_0 (), + .stat_rx_error_0 (), + .stat_rx_error_valid_0 (), + .stat_rx_fifo_error_0 (), + .tx_reset_0 (tx_reset), + .tx_mii_d_0 (xgmii_txd), + .tx_mii_c_0 (xgmii_txc), + .stat_tx_local_fault_0 (), + .ctl_tx_test_pattern_0 (1'b0), + .ctl_tx_test_pattern_enable_0 (1'b0), + .ctl_tx_test_pattern_select_0 (1'b0), + .ctl_tx_data_pattern_select_0 (1'b0), + .ctl_tx_test_pattern_seed_a_0 (58'b0), + .ctl_tx_test_pattern_seed_b_0 (58'b0), + .ctl_tx_prbs31_test_pattern_enable_0 (1'b0), + .gt_loopback_in_0 (3'b0) + ); + + + //--------------------------------------------------------------------------- + // Status + //--------------------------------------------------------------------------- + + assign core_status[7:1] = 0; // Unused + assign core_status[0] = stat_rx_status; // Link status + + // Safely combine the RX and TX reset done signals into a single glitch-free + // signal. + + synchronizer sync_reset_tx_done ( + .clk (xgmii_clk), + .rst (1'b0), + .in (a_gt_reset_tx_done), + .out (gt_reset_tx_done) + ); + + synchronizer sync_reset_rx_done ( + .clk (xgmii_clk), + .rst (1'b0), + .in (a_gt_reset_rx_done), + .out (gt_reset_rx_done) + ); + + always @(posedge xgmii_clk) begin : ResetDoneProc + reset_done <= gt_reset_tx_done & gt_reset_rx_done; + end + + + //--------------------------------------------------------------------------- + // Reset Logic + //--------------------------------------------------------------------------- + + // The reset synchronization below is taken from the example design, except + // that rx_clk_out was replaced by tx_mii_clk (xgmii_clk). + + synchronizer sync_rx_serdes_reset ( + .clk (xgmii_clk), + .rst (1'b0), + .in (~a_gt_reset_rx_done), + .out (rx_serdes_reset) + ); + + synchronizer sync_tx_reset ( + .clk (xgmii_clk), + .rst (1'b0), + .in (~a_gt_reset_tx_done), + .out (tx_reset) + ); + + synchronizer sync_rx_reset ( + .clk (xgmii_clk), + .rst (1'b0), + .in (~a_gt_reset_rx_done), + .out (rx_reset) + ); + + // This state machine resets the RX GT part of the core periodically when + // the link is down. This is necessary due to a bug in the Xilinx IP. + always @(posedge xgmii_clk, posedge areset) begin + if (areset) begin + gt_rx_reset_in <= 0; + rst_count <= 0; + stat_rx_status <= 0; + end else begin + stat_rx_status <= stat_rx_status_tmp; + + // Periodically reset until link is up + if (!stat_rx_status) begin + rst_count <= rst_count + 1; + + if (!gt_rx_reset_in) begin + // We're not in reset. Wait until RX_RST_WAIT cycles have elapsed, + // then reset. + if (rst_count == RX_RST_WAIT-1) begin + rst_count <= 0; + gt_rx_reset_in <= 1; + end + end else begin + // We're in reset. Wait until RX_RST_DURATION cycles have elapsed + // before deasserting reset. + if (rst_count == RX_RST_DURATION-1) begin + rst_count <= 0; + gt_rx_reset_in <= 0; + end + end + + // Currently linked, so all is well + end else begin + rst_count <= 0; + gt_rx_reset_in <= 0; + end + end + end + +endmodule diff --git a/fpga/usrp3/top/x400/ip/xge_pcs_pma/xge_pcs_pma.xci b/fpga/usrp3/top/x400/ip/xge_pcs_pma/xge_pcs_pma.xci new file mode 100644 index 000000000..aeda24d44 --- /dev/null +++ b/fpga/usrp3/top/x400/ip/xge_pcs_pma/xge_pcs_pma.xci @@ -0,0 +1,1184 @@ + + + xilinx.com + xci + unknown + 1.0 + + + xge_pcs_pma + + + + 100000000 + 0 + 0.000 + + 100000000 + 0 + 0.000 + + 100000000 + 0 + 0.000 + + 100000000 + 0 + 0.000 + 0 + 0 + 0 + 0 + + 100000000 + 0 + 0 + 0 + 0 + 0 + undef + 0.000 + 0 + 0 + 0 + 0 + + 100000000 + 0 + 0 + 0 + 0 + 0 + undef + 0.000 + 0 + 0 + 0 + 0 + + 100000000 + 0 + 0 + 0 + 0 + 0 + undef + 0.000 + 0 + 0 + 0 + 0 + + 100000000 + 0 + 0 + 0 + 0 + 0 + undef + 0.000 + 0 + 0 + 0 + 0 + + 100000000 + 0 + 0 + 0 + 0 + 0 + undef + 0.000 + 0 + 0 + 0 + 0 + + 100000000 + 0 + 0 + 0 + 0 + 0 + undef + 0.000 + 0 + 0 + 0 + 0 + + 100000000 + 0 + 0 + 0 + 0 + 0 + undef + 0.000 + 0 + 0 + 0 + 0 + + 100000000 + 0 + 0 + 0 + 0 + 0 + undef + 0.000 + 0 + 0 + 0 + 0 + + 100000000 + 0 + 0 + 0 + 0 + 0 + undef + 0.000 + 0 + 0 + 0 + 0 + + 100000000 + 0 + 0 + 0 + 0 + 0 + undef + 0.000 + 0 + 0 + 0 + 0 + + 100000000 + 0 + 0 + 0 + 0 + 0 + undef + 0.000 + 0 + 0 + 0 + 0 + + 100000000 + 0 + 0 + 0 + 0 + 0 + undef + 0.000 + 0 + 0 + 0 + 0 + + 100000000 + 0 + 0 + 0 + 0 + 0 + undef + 0.000 + 0 + 0 + 0 + 0 + + 100000000 + 0 + 0 + 0 + 0 + 0 + undef + 0.000 + 0 + 0 + 0 + 0 + + 100000000 + 0 + 0 + 0 + 0 + 0 + undef + 0.000 + 0 + 0 + 0 + 0 + + 100000000 + 0 + 0 + 0 + 0 + 0 + undef + 0.000 + 0 + 0 + 0 + 0 + + 100000000 + 0 + 0 + 0 + 0 + 0 + undef + 0.000 + 0 + 0 + 0 + 0 + + 100000000 + 0 + 0 + 0 + 0 + 0 + undef + 0.000 + 0 + 0 + 0 + 0 + + 100000000 + 0 + 0 + 0 + 0 + 0 + undef + 0.000 + 0 + 0 + 0 + 0 + + 100000000 + 0 + 0 + 0 + 0 + 0 + undef + 0.000 + 0 + 0 + 0 + 0 + + 100000000 + 0 + 0 + 0 + 0 + 0 + undef + 0.000 + 0 + 0 + 0 + 0 + + 100000000 + 0 + 0 + 0 + 0 + 0 + undef + 0.000 + 0 + 0 + 0 + 0 + + 100000000 + 0 + 0 + 0 + 0 + 0 + undef + 0.000 + 0 + 0 + 0 + 0 + + 100000000 + 0 + 0 + 0 + 0 + 0 + undef + 0.000 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + 100000000 + 0 + 0.000 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + 100000000 + 0 + 0.000 + + + + 100000000 + 0 + 0.000 + + + + 100000000 + 0 + 0.000 + + + + 100000000 + 0 + 0.000 + 0 + 0 + 0 + 0 + + + + 0 + 0.000 + false + 100000000 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + undef + undef + undef + undef + undef + undef + undef + undef + undef + undef + undef + undef + undef + undef + undef + undef + undef + undef + undef + undef + false + 0 + 0 + 0 + 0 + undef + undef + undef + undef + undef + undef + undef + undef + undef + undef + undef + undef + undef + undef + undef + undef + undef + undef + undef + undef + + + + 0 + 0.000 + + + + 0 + 0.000 + + + + 0 + 0.000 + + + + 0 + 0.000 + + + + 100000000 + 0 + 0.000 + + + + 100000000 + 0 + 0.000 + 0 + + + + 100000000 + 0 + 0.000 + + + + 100000000 + 0 + 0.000 + 0 + + + + 100000000 + 0 + 0.000 + + + + 100000000 + 0 + 0.000 + + + + 100000000 + 0 + 0.000 + + + + 100000000 + 0 + 0.000 + + 0 + 0.000 + + 0 + 0.000 + + 0 + 0.000 + + 0 + 0.000 + + 100000000 + 0 + 0.000 + + 100000000 + 0 + 0.000 + + 100000000 + 0 + 0.000 + + 100000000 + 0 + 0.000 + + 0 + 0.000 + + 0 + 0.000 + + 0 + 0.000 + + 0 + 0.000 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 156.25 + undef + 156.25 + undef + 156.25 + undef + 156.25 + undef + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + + 1 + 100000000 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 1 + 1 + 1 + 1 + 0.000 + AXI4LITE + READ_WRITE + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + + 1 + 100000000 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 1 + 1 + 1 + 1 + 0.000 + AXI4LITE + READ_WRITE + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + + 1 + 100000000 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 1 + 1 + 1 + 1 + 0.000 + AXI4LITE + READ_WRITE + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + + 1 + 100000000 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 1 + 1 + 1 + 1 + 0.000 + AXI4LITE + READ_WRITE + 0 + 0 + 0 + 0 + 0 + + 100000000 + 0 + 0.000 + + 100000000 + 0 + 0.000 + + 100000000 + 0 + 0.000 + + 100000000 + 0 + 0.000 + 0 + 0 + 0 + 0 + + 0 + 0.000 + + 0 + 0.000 + + 0 + 0.000 + + 0 + 0.000 + + 100000000 + 0 + 0.000 + + 100000000 + 0 + 0.000 + + 100000000 + 0 + 0.000 + + 100000000 + 0 + 0.000 + + + + 0 + 0.000 + + + + 0 + 0.000 + + + + 0 + 0.000 + + + + 0 + 0.000 + + + + 0 + 0.000 + + + + 0 + 0.000 + + + + 0 + 0.000 + + + + 0 + 0.000 + + 0 + 0.000 + + 0 + 0.000 + + 0 + 0.000 + + 0 + 0.000 + 0 + 0 + 0 + 0 + + + 0 + 0.000 + + + 0 + 0.000 + + + 0 + 0.000 + + + 0 + 0.000 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 100 + 64 + 7 + BASE-R + Asynchronous + Ethernet PCS/PMA 64-bit + MII + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + zynquplus + 0 + 4 + 100.00 + Quad X0Y0 + 1 + 156.25 + GTY + None + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 10 + X0Y16 + NA + NA + NA + 10 + 8 + 64 + 1 + 0 + 2 + 0 + AUTO + 0 + 0 + 0 + 4 + 1 + 0 + 1 + 100 + BASE-R + Asynchronous + Ethernet PCS/PMA 64-bit + xge_pcs_pma + MII + Custom + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + Custom + 0 + 100.00 + Quad_X0Y4 + 1 + 156.25 + GTY + None + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 30 + X0Y16 + NA + NA + NA + 10 + 1 + 0 + 2 + 0 + AUTO + 0 + 0 + 4000 + 0 + false + 1 + zynquplusRFSOC + + + xczu28dr + ffvg1517 + VERILOG + + MIXED + -1 + + E + TRUE + TRUE + IP_Flow + 1 + TRUE + . + + . + 2019.1.1 + OUT_OF_CONTEXT + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/fpga/usrp3/top/x400/ip/xge_pcs_pma/xge_pcs_pma_wrapper.v.patch b/fpga/usrp3/top/x400/ip/xge_pcs_pma/xge_pcs_pma_wrapper.v.patch new file mode 100644 index 000000000..ba059bc44 --- /dev/null +++ b/fpga/usrp3/top/x400/ip/xge_pcs_pma/xge_pcs_pma_wrapper.v.patch @@ -0,0 +1,30 @@ +692a693,712 +> +> //--------------------------------------------------------------------------- +> // Workaround for link status bug. See SR 10471238 for details. +> //--------------------------------------------------------------------------- +> +> reg [13:0] rx_clk_noctrlcode_count; +> +> always @(posedge rx_core_clk_0) begin +> if (rx_reset_done_0 == 1'b1) begin +> rx_clk_noctrlcode_count <= 14'h270F; +> end else begin +> if (stat_rx_valid_ctrl_code_0 == 1'b1) begin +> rx_clk_noctrlcode_count <= 14'h270F; +> end else begin +> rx_clk_noctrlcode_count <= rx_clk_noctrlcode_count - 1; +> end +> end +> end +> +> //--------------------------------------------------------------------------- +700c720,725 +< if(stat_rx_block_lock_0 == 1'b0) +--- +> //------------------------------------------------------------------------ +> // Workaround for link status bug. See SR 10471238 for details. +> // Original code: if(stat_rx_block_lock_0 == 1'b0) +> // New code: +> if(stat_rx_block_lock_0 == 1'b0 || rx_clk_noctrlcode_count ==14'h0) +> //------------------------------------------------------------------------ -- cgit v1.2.3