fpga: x400: Add support for X410 motherboard FPGA
Co-authored-by: Andrew Moch <Andrew.Moch@ni.com> Co-authored-by: Daniel Jepson <daniel.jepson@ni.com> Co-authored-by: Javier Valenzuela <javier.valenzuela@ni.com> Co-authored-by: Joerg Hofrichter <joerg.hofrichter@ni.com> Co-authored-by: Kumaran Subramoniam <kumaran.subramoniam@ni.com> Co-authored-by: Max Köhler <max.koehler@ni.com> Co-authored-by: Michael Auchter <michael.auchter@ni.com> Co-authored-by: Paul Butler <paul.butler@ni.com> Co-authored-by: Wade Fife <wade.fife@ettus.com> Co-authored-by: Hector Rubio <hrubio@ni.com> Original-commit: 6d3765605262016a80f71e36357f749ea35cbe5a
This commit is contained in:
committed by
Aaron Rossetto
co-authored by
Andrew Moch
Daniel Jepson
Javier Valenzuela
Joerg Hofrichter
Kumaran Subramoniam
Max Köhler
Michael Auchter
Paul Butler
Hector Rubio
parent
bfef20ea45
commit
61782b02d7
@@ -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)))
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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)
|
||||
> //------------------------------------------------------------------------
|
||||
Reference in New Issue
Block a user