Files
b210-k7-fpga/top/x300/x300_sfpp_io_core.v
T
Martin Braun df0b86f432 fpga: x300: sfpp: Fix warning about duplicate reg
This removes a duplicate code section that causes build warnings. It
also references a wire that gets declared further down and the removed
and remaining code sections were incorrectly indented.


Original-commit: e8084eb4cb4ec6ff6476feb6e77ab3ea45dd969e
2024-01-04 10:24:05 -06:00

499 lines
18 KiB
Verilog

//
// Copyright 2016-2017 Ettus Research LLC
// Copyright 2017 Ettus Research, a National Instruments Company
//
// SPDX-License-Identifier: LGPL-3.0-or-later
//
// sfpp_io_core
// - mdio_master
// - One Gige phy + MAC
// - Ten Gige phy + MAC
// - Aurora phy + MAC
//
//////////////////////////////////////////////////////////////////////
module x300_sfpp_io_core #(
parameter PROTOCOL = "10GbE", // Must be {10GbE, 1GbE, Aurora}
parameter PORTNUM = 8'd0
)(
input areset,
input bus_rst,
input bus_rst_div2,
input gt_refclk,
input gb_refclk,
input misc_clk,
input bus_clk,
input bus_clk_div2,
output txp,
output txn,
input rxp,
input rxn,
input sfpp_rxlos,
input sfpp_tx_fault,
output sfpp_tx_disable,
input [63:0] s_axis_tdata,
input [3:0] s_axis_tuser,
input s_axis_tlast,
input s_axis_tvalid,
output s_axis_tready,
output [63:0] m_axis_tdata,
output [3:0] m_axis_tuser,
output m_axis_tlast,
output m_axis_tvalid,
input m_axis_tready,
input [7:0] wb_adr_i,
input wb_cyc_i,
input [31:0] wb_dat_i,
input wb_stb_i,
input wb_we_i,
output wb_ack_o,
output [31:0] wb_dat_o,
output wb_int_o,
output [15:0] phy_status,
output link_up,
output activity
);
wire mdc, mdio_in, mdio_out;
// Flush logic: If the link is not up, we will flush all packets coming from
// the device. This avoids the MAC backpressuring when the PHY is down.
// The device will always send discovery packets to the transports during
// initialization, and they have no way of knowing if it's safe to travel
// down this route. c2mac == "CHDR to MAC"
wire [63:0] c2mac_tdata;
wire [3:0] c2mac_tuser;
wire c2mac_tlast;
wire c2mac_tvalid;
wire c2mac_tready;
axis_packet_flush #(
.WIDTH(64+4), // tdata + tuser
.TIMEOUT_W(1), // Not using timeout
.FLUSH_PARTIAL_PKTS(0),
.PIPELINE("NONE")
) linkup_flush (
.clk(bus_clk),
.reset(bus_rst),
.enable(~link_up), // enable flushing when link down
.timeout(1'b0),
.flushing(/* not required */),
.done(/* not required */),
// Input from device/crossbar
.s_axis_tdata ({s_axis_tuser, s_axis_tdata}),
.s_axis_tlast (s_axis_tlast),
.s_axis_tvalid (s_axis_tvalid),
.s_axis_tready (s_axis_tready),
// Output to MAC
.m_axis_tdata ({c2mac_tuser, c2mac_tdata}),
.m_axis_tlast (c2mac_tlast),
.m_axis_tvalid (c2mac_tvalid),
.m_axis_tready (c2mac_tready)
);
generate
if (PROTOCOL == "10GbE") begin
//-----------------------------------------------------------------
// 10 Gigabit Ethernet
//-----------------------------------------------------------------
wire [63:0] xgmii_txd;
wire [7:0] xgmii_txc;
wire [63:0] xgmii_rxd;
wire [7:0] xgmii_rxc;
wire [7:0] xgmii_status;
wire xge_phy_resetdone;
ten_gige_phy ten_gige_phy_i
(
// Clocks and Reset
.areset(areset), // Asynchronous reset for entire core.
.refclk(gt_refclk), // Transciever reference clock: 156.25MHz
.clk156(gb_refclk), // Globally buffered core clock: 156.25MHz
.dclk(misc_clk), // Management/DRP clock: 78.125MHz
.sim_speedup_control(1'b0),
// GMII Interface (client MAC <=> PCS)
.xgmii_txd(xgmii_txd), // Transmit data from client MAC.
.xgmii_txc(xgmii_txc), // Transmit control signal from client MAC.
.xgmii_rxd(xgmii_rxd), // Received Data to client MAC.
.xgmii_rxc(xgmii_rxc), // Received control signal to client MAC.
// Tranceiver Interface
.txp(txp), // Differential +ve of serial transmission from PMA to PMD.
.txn(txn), // Differential -ve of serial transmission from PMA to PMD.
.rxp(rxp), // Differential +ve for serial reception from PMD to PMA.
.rxn(rxn), // Differential -ve for serial reception from PMD to PMA.
// Management: MDIO Interface
.mdc(mdc), // Management Data Clock
.mdio_in(mdio_in), // Management Data In
.mdio_out(mdio_out), // Management Data Out
.mdio_tri(), // Management Data Tristate
.prtad(5'd4), // MDIO address is 4
// General IO's
.core_status(xgmii_status), // Core status
.resetdone(xge_phy_resetdone),
.signal_detect(~sfpp_rxlos), // Input from PMD to indicate presence of optical input. (Undocumented, but it seems Xilinx expect this to be inverted.)
.tx_fault(sfpp_tx_fault),
.tx_disable(sfpp_tx_disable)
);
xge_mac_wrapper #(
.PORTNUM(PORTNUM),
.WISHBONE(1)
) xge_mac_wrapper_i (
// XGMII
.xgmii_clk(gb_refclk),
.xgmii_txd(xgmii_txd),
.xgmii_txc(xgmii_txc),
.xgmii_rxd(xgmii_rxd),
.xgmii_rxc(xgmii_rxc),
// MDIO
.mdc(mdc),
.mdio_in(mdio_in),
.mdio_out(mdio_out),
// Wishbone I/F
.wb_clk_i(bus_clk_div2),
.wb_rst_i(bus_rst_div2),
.wb_adr_i(wb_adr_i),
.wb_cyc_i(wb_cyc_i),
.wb_dat_i(wb_dat_i),
.wb_stb_i(wb_stb_i),
.wb_we_i(wb_we_i),
.wb_ack_o(wb_ack_o),
.wb_dat_o(wb_dat_o),
.wb_int_o(wb_int_o),
// Client FIFO Interfaces
.sys_clk(bus_clk),
.sys_rst(bus_rst),
.rx_tdata(m_axis_tdata),
.rx_tuser(m_axis_tuser),
.rx_tlast(m_axis_tlast),
.rx_tvalid(m_axis_tvalid),
.rx_tready(m_axis_tready),
.tx_tdata(c2mac_tdata),
.tx_tuser(c2mac_tuser), // Bit[3] (error) is ignored for now.
.tx_tlast(c2mac_tlast),
.tx_tvalid(c2mac_tvalid),
.tx_tready(c2mac_tready),
// Other
.phy_ready(xge_phy_resetdone)
);
assign phy_status = {8'h00, xgmii_status};
// Use the PCS Block Lock signal to drive the link_up LED on the FP.
// For further details, see Xilinx' PG068, Table 2-11 (core_status[0] signal).
synchronizer #(.INITIAL_VAL(1'b0)) link_up_sync (
.clk(bus_clk), .rst(1'b0 /* no reset */), .in(xgmii_status[0]), .out(link_up));
end else if (PROTOCOL == "1GbE") begin
//-----------------------------------------------------------------
// 1 Gigabit Ethernet
//-----------------------------------------------------------------
wire [7:0] gmii_txd, gmii_rxd;
wire gmii_tx_en, gmii_tx_er, gmii_rx_dv, gmii_rx_er;
wire gmii_clk;
assign sfpp_tx_disable = 1'b0; // Always on.
one_gige_phy one_gige_phy_i
(
.reset(areset), // Asynchronous reset for entire core.
.independent_clock(bus_clk),
// Tranceiver Interface
.gtrefclk(gt_refclk), // Reference clock for MGT: 125MHz, very high quality.
.gtrefclk_bufg(gb_refclk), // Reference clock routed through a BUFG
.txp(txp), // Differential +ve of serial transmission from PMA to PMD.
.txn(txn), // Differential -ve of serial transmission from PMA to PMD.
.rxp(rxp), // Differential +ve for serial reception from PMD to PMA.
.rxn(rxn), // Differential -ve for serial reception from PMD to PMA.
// GMII Interface (client MAC <=> PCS)
.gmii_clk(gmii_clk), // Clock to client MAC.
.gmii_txd(gmii_txd), // Transmit data from client MAC.
.gmii_tx_en(gmii_tx_en), // Transmit control signal from client MAC.
.gmii_tx_er(gmii_tx_er), // Transmit control signal from client MAC.
.gmii_rxd(gmii_rxd), // Received Data to client MAC.
.gmii_rx_dv(gmii_rx_dv), // Received control signal to client MAC.
.gmii_rx_er(gmii_rx_er), // Received control signal to client MAC.
// Management: MDIO Interface
.mdc(mdc), // Management Data Clock
.mdio_i(mdio_in), // Management Data In
.mdio_o(mdio_out), // 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(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_i
(
.clk125(gmii_clk),
.reset(areset),
.GMII_GTX_CLK(),
.GMII_TX_EN(gmii_tx_en),
.GMII_TX_ER(gmii_tx_er),
.GMII_TXD(gmii_txd),
.GMII_RX_CLK(gmii_clk),
.GMII_RX_DV(gmii_rx_dv),
.GMII_RX_ER(gmii_rx_er),
.GMII_RXD(gmii_rxd),
.sys_clk(bus_clk),
.rx_tdata(m_axis_tdata),
.rx_tuser(m_axis_tuser),
.rx_tlast(m_axis_tlast),
.rx_tvalid(m_axis_tvalid),
.rx_tready(m_axis_tready),
.tx_tdata(c2mac_tdata),
.tx_tuser(c2mac_tuser),
.tx_tlast(c2mac_tlast),
.tx_tvalid(c2mac_tvalid),
.tx_tready(c2mac_tready),
// MDIO
.mdc(mdc),
.mdio_in(mdio_in),
.mdio_out(mdio_out),
.mdio_tri(),
// Wishbone I/F
.wb_clk_i(bus_clk_div2),
.wb_rst_i(bus_rst_div2),
.wb_adr_i(wb_adr_i),
.wb_cyc_i(wb_cyc_i),
.wb_dat_i(wb_dat_o),
.wb_stb_i(wb_stb_i),
.wb_we_i(wb_we_i),
.wb_ack_o(wb_ack_o),
.wb_dat_o(wb_dat_i),
.wb_int_o(wb_int_o),
// Debug
.debug_tx(), .debug_rx()
);
// Use the Link Status signal to drive the link_up LED on the FP.
// For further details, see Xilinx' PG047, Table 2-76 (status_vector[0]).
synchronizer #(.INITIAL_VAL(1'b0)) link_up_sync (
.clk(bus_clk), .rst(1'b0 /* no reset */), .in(phy_status[0]), .out(link_up));
end else if (PROTOCOL == "Aurora") begin
//-----------------------------------------------------------------
// Aurora
//-----------------------------------------------------------------
wire au_user_clk, au_user_rst, phy_areset;
wire [63:0] i_tdata, o_tdata;
wire i_tvalid, i_tready, o_tvalid;
wire channel_up, hard_err, soft_err;
wire mac_clear;
assign sfpp_tx_disable = 1'b0; // Always on.
aurora_phy_x1 aurora_phy_i (
// Resets
.areset(areset | phy_areset),
// Clocks
.refclk(gt_refclk),
.init_clk(misc_clk),
.user_clk(au_user_clk),
.user_rst(au_user_rst),
// GTX Serial I/O
.tx_p(txp),
.tx_n(txn),
.rx_p(rxp),
.rx_n(rxn),
// AXI4-Stream TX Interface
.s_axis_tdata(i_tdata),
.s_axis_tvalid(i_tvalid),
.s_axis_tready(i_tready),
// AXI4-Stream RX Interface
.m_axis_tdata(o_tdata),
.m_axis_tvalid(o_tvalid),
// AXI4-Lite Config Interface: TODO: Hook up to WB->AXI4Lite converter
.s_axi_awaddr(32'h0),
.s_axi_araddr(32'h0),
.s_axi_awvalid(1'b0),
.s_axi_awready(),
.s_axi_wdata(32'h0),
.s_axi_wvalid(1'b0),
.s_axi_wstrb(1'b0),
.s_axi_wready(),
.s_axi_bvalid(),
.s_axi_bresp(),
.s_axi_bready(1'b1),
.s_axi_arready(),
.s_axi_arvalid(1'b0),
.s_axi_rdata(),
.s_axi_rvalid(),
.s_axi_rresp(),
.s_axi_rready(1'b1),
// Status and Error Reporting Interface
.channel_up(channel_up),
.hard_err(hard_err),
.soft_err(soft_err)
);
assign phy_status = {14'd0, hard_err, channel_up};
wire bist_gen_en, bist_checker_en, bist_loopback_en;
wire bist_checker_locked;
wire [5:0] bist_gen_rate;
wire [47:0] bist_checker_samps, bist_checker_errors;
wire [31:0] overruns, checksum_errors;
aurora_axis_mac #(
.PHY_ENDIANNESS ("LITTLE"),
.PACKET_MODE (1),
.MAX_PACKET_SIZE(1024),
.BIST_ENABLED (1)
) aurora_mac_i (
// Clocks and resets
.phy_clk(au_user_clk), .phy_rst(au_user_rst),
.sys_clk(bus_clk), .sys_rst(bus_rst),
.clear(mac_clear),
// PHY Interface (Synchronous to phy_clk)
.phy_s_axis_tdata(o_tdata),
.phy_s_axis_tvalid(o_tvalid),
.phy_m_axis_tdata(i_tdata),
.phy_m_axis_tvalid(i_tvalid),
.phy_m_axis_tready(i_tready),
// User Interface (Synchronous to sys_clk)
.s_axis_tdata(c2mac_tdata),
.s_axis_tlast(c2mac_tlast),
.s_axis_tvalid(c2mac_tvalid),
.s_axis_tready(c2mac_tready),
.m_axis_tdata(m_axis_tdata),
.m_axis_tlast(m_axis_tlast),
.m_axis_tvalid(m_axis_tvalid),
.m_axis_tready(m_axis_tready),
// PHY Status Inputs (Synchronous to phy_clk)
.channel_up(channel_up),
.hard_err(hard_err),
.soft_err(soft_err),
// Status and Error Outputs (Synchronous to sys_clk)
.overruns(overruns),
.soft_errors(),
.checksum_errors(checksum_errors),
.critical_err(mac_crit_err),
// BIST Interface (Synchronous to sys_clk)
.bist_gen_en(bist_gen_en),
.bist_gen_rate(bist_gen_rate),
.bist_checker_en(bist_checker_en),
.bist_loopback_en(bist_loopback_en),
.bist_checker_locked(bist_checker_locked),
.bist_checker_samps(bist_checker_samps),
.bist_checker_errors(bist_checker_errors)
);
assign m_axis_tuser = 4'd0;
wire set_stb;
wire [3:0] set_addr, rb_addr;
wire [31:0] set_data;
reg [31:0] rb_data;
settings_bus #(.AWIDTH(8), .DWIDTH(32), .SWIDTH(4)) settings_bus_i (
.wb_clk(bus_clk), .wb_rst(bus_rst),
.wb_adr_i(wb_adr_i), .wb_dat_i(wb_dat_i),
.wb_stb_i(wb_stb_i), .wb_we_i(wb_we_i), .wb_ack_o(wb_ack_o),
.strobe(set_stb), .addr(set_addr), .data(set_data)
);
settings_readback #(.AWIDTH(8),.DWIDTH(32), .RB_ADDRW(4)) settings_readback_i (
.wb_clk(bus_clk), .wb_rst(bus_rst),
.wb_adr_i(wb_adr_i), .wb_stb_i(wb_stb_i), .wb_we_i(wb_we_i), .wb_dat_o(wb_dat_o),
.rb_data(rb_data), .rb_addr(rb_addr), .rb_rd_stb()
);
setting_reg #(.my_addr(4'd0), .awidth(4), .width(11), .at_reset(11'h000)) set_core_control_i (
.clk(bus_clk), .rst(bus_rst),
.strobe(set_stb), .addr(set_addr), .in(set_data),
.out({mac_clear, phy_areset, bist_gen_rate, bist_loopback_en, bist_gen_en, bist_checker_en}), .changed()
);
wire channel_up_bclk, hard_err_bclk, soft_err_bclk, mac_crit_err_bclk;
synchronizer #(.INITIAL_VAL(1'b0)) channel_up_sync (
.clk(bus_clk), .rst(1'b0 /* no reset */), .in(channel_up), .out(channel_up_bclk));
synchronizer #(.INITIAL_VAL(1'b0)) hard_err_sync (
.clk(bus_clk), .rst(1'b0 /* no reset */), .in(hard_err), .out(hard_err_bclk));
synchronizer #(.INITIAL_VAL(1'b0)) soft_err_sync (
.clk(bus_clk), .rst(1'b0 /* no reset */), .in(soft_err), .out(soft_err_bclk));
synchronizer #(.INITIAL_VAL(1'b0)) mac_crit_err_sync (
.clk(bus_clk), .rst(1'b0 /* no reset */), .in(mac_crit_err), .out(mac_crit_err_bclk));
reg [19:0] bist_lock_latency;
always @(posedge bus_clk) begin
if (!bist_checker_en && !bist_checker_locked)
bist_lock_latency <= 20'd0;
else if (bist_checker_en && !bist_checker_locked)
bist_lock_latency <= bist_lock_latency + 20'd1;
end
reg mac_crit_err_latch;
always @(posedge bus_clk) begin
if (bus_rst | mac_clear) begin
mac_crit_err_latch <= 1'b0;
end else begin
if (mac_crit_err_bclk)
mac_crit_err_latch <= 1'b1;
end
end
wire [31:0] core_status = {
6'h0, //[31:26]
mac_crit_err_latch, //[25]
1, //[24] mmcm_locked_bclk
1, //[23] gt_pll_locked_bclk
0, //[22] qpll_refclklost_bclk
1, //[21] qpll_lock_bclk
0, //[20] qpll_reset_bclk
bist_lock_latency[19:4], //[19:4]
bist_checker_locked, //[3]
soft_err_bclk, //[2]
hard_err_bclk, //[1]
channel_up_bclk //[0]
};
assign link_up = channel_up_bclk;
always @(*)
case (rb_addr)
4'd0: rb_data = core_status;
4'd1: rb_data = overruns;
4'd2: rb_data = checksum_errors;
4'd3: rb_data = bist_checker_samps[47:16]; //Scale num sample by 2^16
4'd4: rb_data = bist_checker_errors[31:0]; //Dont scale errors
default: rb_data = 32'h0;
endcase // case (rb_addr)
end else begin
//Invalid protocol
end
endgenerate
//-----------------------------------------------------------------
// Activity detector
//-----------------------------------------------------------------
pulse_stretch act_pulse_str_i (
.clk(bus_clk),
.rst(bus_rst | ~link_up),
.pulse((s_axis_tvalid & s_axis_tready) | (m_axis_tvalid & m_axis_tready)),
.pulse_stretched(activity)
);
endmodule