Files
b210-k7-fpga/top/e320/e320_mgt_io_core.v
T
Wade Fife 5f4d53eacb fpga: e320: Support advanced transport adapter
- Fix NODE_INST
- Fix RFNOC_PROTOVER
- Add option to use SystemVerilog transport adapter for raw UDP


Original-commit: 0114e108af63d9ac785649c8099a042299624943
2022-08-29 17:01:45 -05:00

655 lines
23 KiB
Verilog

///////////////////////////////////////////////////////////////////
//
// Copyright 2018 Ettus Research, A National Instruments Company
//
// SPDX-License-Identifier: LGPL-3.0
//
// Module: e320_mgt_io_core
// Description:
// Encapsulates the PSC/PMA, the MAC layer and the control interface
// for 1GbE, 10GbE and Aurora
//
//////////////////////////////////////////////////////////////////////
module e320_mgt_io_core #(
parameter PROTOCOL = "10GbE", // Must be {10GbE, 1GbE, Aurora, Disabled}
parameter [13:0] REG_BASE = 14'h0,
parameter REG_DWIDTH = 32,
parameter REG_AWIDTH = 14,
parameter [7:0] PORTNUM = 8'd0,
parameter MDIO_EN = 0,
parameter [4:0] MDIO_PHYADDR = 5'd0
)(
// Resets
input areset,
input bus_rst,
// Clocks
input gt_refclk,
input gb_refclk,
input misc_clk,
input bus_clk,
// SFP high-speed IO
output txp,
output txn,
input rxp,
input rxn,
// SFP low-speed IO
input sfpp_rxlos,
input sfpp_tx_fault,
output sfpp_tx_disable,
// Data port: Ethernet TX
input [63:0] s_axis_tdata,
input [3:0] s_axis_tuser,
input s_axis_tlast,
input s_axis_tvalid,
output s_axis_tready,
// Data port: Ethernet RX
output [63:0] m_axis_tdata,
output [3:0] m_axis_tuser,
output m_axis_tlast,
output m_axis_tvalid,
input m_axis_tready,
// Register port
input reg_wr_req,
input [REG_AWIDTH-1:0] reg_wr_addr,
input [REG_DWIDTH-1:0] reg_wr_data,
input reg_rd_req,
input [REG_AWIDTH-1:0] reg_rd_addr,
output reg_rd_resp,
output [REG_DWIDTH-1:0] reg_rd_data,
// Misc
output [31:0] port_info,
output link_up,
output reg activity
);
//-----------------------------------------------------------------
// Registers
//-----------------------------------------------------------------
localparam [7:0] COMPAT_NUM = 8'd2;
// Common registers
localparam REG_PORT_INFO = REG_BASE + 'h0;
localparam REG_MAC_CTRL_STATUS = REG_BASE + 'h4;
localparam REG_PHY_CTRL_STATUS = REG_BASE + 'h8;
localparam REG_MAC_LED_CTL = REG_BASE + 'hC;
// Ethernet specific
localparam REG_ETH_MDIO_BASE = REG_BASE + 'h10;
// Aurora specific
localparam REG_AURORA_OVERRUNS = REG_BASE + 'h20;
localparam REG_CHECKSUM_ERRORS = REG_BASE + 'h24;
localparam REG_BIST_CHECKER_SAMPS = REG_BASE + 'h28;
localparam REG_BIST_CHECKER_ERRORS = REG_BASE + 'h2C;
wire reg_rd_resp_mdio;
reg reg_rd_resp_glob = 1'b0;
wire [REG_DWIDTH-1:0] reg_rd_data_mdio;
reg [REG_DWIDTH-1:0] reg_rd_data_glob = 32'h0;
// Protocol specific constants
wire [7:0] mgt_protocol;
wire [31:0] mac_ctrl_rst_val, phy_ctrl_rst_val;
wire [1:0] mac_led_ctl_rst_val = 2'h0;
// 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+3), // 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 == "Aurora") begin
assign mgt_protocol = 8'd3;
assign mac_ctrl_rst_val = 32'h0;
assign phy_ctrl_rst_val = 32'h0;
end else if (PROTOCOL == "10GbE") begin
assign mgt_protocol = 8'd2;
assign mac_ctrl_rst_val = {31'h0, 1'b1}; // tx_enable on reset
assign phy_ctrl_rst_val = 32'h0;
end else if (PROTOCOL == "1GbE") begin
assign mgt_protocol = 8'd1;
assign mac_ctrl_rst_val = {31'h0, 1'b1}; // tx_enable on reset
assign phy_ctrl_rst_val = 32'h0;
end else begin
assign mgt_protocol = 8'd0;
assign mac_ctrl_rst_val = 32'h0;
assign phy_ctrl_rst_val = 32'h0;
end
endgenerate
// Writable registers
reg [31:0] mac_ctrl_reg = 32'h0;
reg [31:0] phy_ctrl_reg = 32'h0;
reg [1:0] mac_led_ctl = 2'h0;
always @(posedge bus_clk) begin
if (bus_rst) begin
mac_ctrl_reg <= mac_ctrl_rst_val;
phy_ctrl_reg <= phy_ctrl_rst_val;
mac_led_ctl <= mac_led_ctl_rst_val;
end else if (reg_wr_req) begin
case(reg_wr_addr)
REG_MAC_CTRL_STATUS:
mac_ctrl_reg <= reg_wr_data;
REG_PHY_CTRL_STATUS:
phy_ctrl_reg <= reg_wr_data;
REG_MAC_LED_CTL:
mac_led_ctl <= reg_wr_data[1:0];
endcase
end
end
// Readable registers
wire [31:0] overruns;
wire [31:0] checksum_errors;
wire [47:0] bist_checker_samps;
wire [47:0] bist_checker_errors;
wire [31:0] mac_status, phy_status;
wire [31:0] mac_status_bclk, phy_status_bclk;
assign port_info = {COMPAT_NUM, 6'h0, activity, link_up, mgt_protocol, PORTNUM};
always @(posedge bus_clk) begin
// No reset handling needed for readback
if (reg_rd_req) begin
reg_rd_resp_glob <= 1'b1;
case(reg_rd_addr)
REG_PORT_INFO:
reg_rd_data_glob <= port_info;
REG_MAC_CTRL_STATUS:
reg_rd_data_glob <= mac_status_bclk;
REG_PHY_CTRL_STATUS:
reg_rd_data_glob <= phy_status_bclk;
REG_MAC_LED_CTL:
reg_rd_data_glob <= {30'd0, mac_led_ctl};
REG_AURORA_OVERRUNS:
reg_rd_data_glob <= overruns;
REG_CHECKSUM_ERRORS:
reg_rd_data_glob <= checksum_errors;
REG_BIST_CHECKER_SAMPS:
reg_rd_data_glob <= bist_checker_samps[47:16]; //Scale num samples by 2^16
REG_BIST_CHECKER_ERRORS:
reg_rd_data_glob <= bist_checker_errors[31:0]; //Don't scale errors
default:
reg_rd_resp_glob <= 1'b0;
endcase
end if (reg_rd_resp_glob) begin
reg_rd_resp_glob <= 1'b0;
end
end
synchronizer #( .STAGES(2), .WIDTH(32), .INITIAL_VAL(32'h0) ) mac_status_sync_i (
.clk(bus_clk), .rst(1'b0), .in(mac_status), .out(mac_status_bclk)
);
synchronizer #( .STAGES(2), .WIDTH(32), .INITIAL_VAL(32'h0) ) phy_status_sync_i (
.clk(bus_clk), .rst(1'b0), .in(phy_status), .out(phy_status_bclk)
);
// Regport Mux for response
regport_resp_mux #(
.WIDTH (REG_DWIDTH),
.NUM_SLAVES (2)
) reg_resp_mux_i (
.clk(bus_clk), .reset(bus_rst),
.sla_rd_resp({reg_rd_resp_mdio, reg_rd_resp_glob}),
.sla_rd_data({reg_rd_data_mdio, reg_rd_data_glob}),
.mst_rd_resp(reg_rd_resp), .mst_rd_data(reg_rd_data)
);
//-----------------------------------------------------------------
// Ethernet Specific: MDIO
//-----------------------------------------------------------------
wire mdc, mdio_m2s, mdio_s2m, mdio_s2m_sync;
generate
if ((PROTOCOL == "10GbE" || PROTOCOL == "1GbE") && (MDIO_EN == 1)) begin
mdio_master #(
.REG_BASE (REG_ETH_MDIO_BASE),
.REG_AWIDTH (REG_AWIDTH),
.MDC_DIVIDER (8'd200)
) mdio_master_i (
.clk (bus_clk),
.rst (bus_rst),
.mdc (mdc),
.mdio_in (mdio_s2m_sync),
.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_mdio),
.reg_rd_resp (reg_rd_resp_mdio)
);
// We can cross mdio_s2m into the bus_clk domain. A synchronizer is safe
// here because the bit is inherently async
synchronizer #(.INITIAL_VAL(1'b0)) mdio_s2m_sync_i (
.clk(bus_clk), .rst(1'b0 /* no reset */), .in(mdio_s2m), .out(mdio_s2m_sync)
);
end else begin
assign mdc = 1'b0;
assign mdio_m2s = 1'b0;
assign reg_rd_resp_mdio = 1'b0;
assign reg_rd_data_mdio = 32'h0;
end
endgenerate
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 xge_phy_resetdone;
ten_gige_phy ten_gige_phy_i
(
// Clocks and Reset
.areset(areset | phy_ctrl_reg[0]), // 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_m2s), // Management Data In
.mdio_out(mdio_s2m), // Management Data Out
.mdio_tri(), // Management Data Tristate
.prtad(MDIO_PHYADDR), // MDIO address
// General IO's
.core_status(phy_status[7:0]), // 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(0)
) 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),
// 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),
.ctrl_tx_enable(mac_ctrl_reg[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]),
.wb_ack_o(),
.wb_dat_o(),
.wb_adr_i(1'b0),
.wb_clk_i(1'b0),
.wb_cyc_i(1'b0),
.wb_dat_i(1'b0),
.wb_rst_i(1'b0),
.wb_stb_i(1'b0),
.wb_we_i (1'b0),
.wb_int_o()
);
assign phy_status[31:8] = 24'h0;
assign mac_status[31:9] = 23'h0;
assign link_up = phy_status_bclk[0];
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;
wire gt0_qplloutclk, gt0_qplloutrefclk; //unused in 7-series Zynq
assign gt0_qplloutclk = 1'b0;
assign gt0_qplloutrefclk = 1'b0;
assign sfpp_tx_disable = 1'b0; // Always on.
one_gige_phy one_gige_phy_i
(
.reset(areset | phy_ctrl_reg[0]), // 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_m2s), // Management Data In
.mdio_o(mdio_s2m), // Management Data Out
.mdio_t(), // Management Data Tristate
.phyaddr(MDIO_PHYADDR), // MDIO address
.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[15:0]), // 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),
.wb_clk_i(1'b0),
.wb_rst_i(1'b0),
.wb_adr_i(8'h0),
.wb_dat_i(32'h0),
.wb_we_i(1'b0),
.wb_stb_i(1'b0),
.wb_cyc_i(1'b0),
.wb_dat_o(),
.wb_ack_o(),
.wb_int_o(),
.mdc(),
.mdio_out(1'b0),
.mdio_tri(),
.mdio_in(),
.debug_tx(),
.debug_rx()
);
assign phy_status[31:16] = 16'h0;
assign mac_status[31:0] = 32'h0;
assign link_up = phy_status_bclk[0];
assign gt_tx_out_clk_unbuf = 1'b0;
end else if (PROTOCOL == "Aurora") begin
//-----------------------------------------------------------------
// Aurora
//-----------------------------------------------------------------
wire user_clk, user_rst;
wire [63:0] m2p_tdata, p2m_tdata;
wire m2p_tvalid, m2p_tready, p2m_tvalid;
wire channel_up, hard_err, soft_err, mac_crit_err;
wire bist_checker_en = mac_ctrl_reg[0];
wire bist_gen_en = mac_ctrl_reg[1];
wire bist_loopback_en = mac_ctrl_reg[2];
wire [5:0] bist_gen_rate = mac_ctrl_reg[8:3];
wire phy_areset = mac_ctrl_reg[9];
wire mac_clear = mac_ctrl_reg[10];
wire bist_checker_locked;
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(user_clk),
.user_rst(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(m2p_tdata),
.s_axis_tvalid(m2p_tvalid),
.s_axis_tready(m2p_tready),
// AXI4-Stream RX Interface
.m_axis_tdata(p2m_tdata),
.m_axis_tvalid(p2m_tvalid),
// AXI4-Lite Config Interface (unused)
.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)
);
aurora_axis_mac #(
.PHY_ENDIANNESS ("LITTLE"),
.PACKET_MODE (1),
.MAX_PACKET_SIZE(1024),
.BIST_ENABLED (1)
) aurora_mac_i (
// Clocks and resets
.phy_clk(user_clk), .phy_rst(user_rst),
.sys_clk(bus_clk), .sys_rst(bus_rst),
.clear(mac_clear),
// PHY Interface (Synchronous to phy_clk)
.phy_s_axis_tdata(p2m_tdata),
.phy_s_axis_tvalid(p2m_tvalid),
.phy_m_axis_tdata(m2p_tdata),
.phy_m_axis_tvalid(m2p_tvalid),
.phy_m_axis_tready(m2p_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 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
assign phy_status = {30'd0, hard_err, channel_up};
assign mac_status = {
6'h0, //[31:26]
mac_crit_err_latch, //[25]
1'b1, //[24]
1'b0, //[23]
1'b0, //[22]
1'b0, //[21]
1'b0, //[20]
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;
end else begin
//-----------------------------------------------------------------
// Disabled
//-----------------------------------------------------------------
assign phy_status = 'h0;
assign mac_status = 'h0;
assign link_up = 1'b0;
assign sfpp_tx_disable = 1'b0; // Always on.
assign c2mac_tready = 1'b1;
assign m_axis_tdata = 64'h0;
assign m_axis_tuser = 4'h0;
assign m_axis_tlast = 1'b0;
assign m_axis_tvalid = 1'b0;
end
endgenerate
wire identify_enable = mac_led_ctl[0];
wire identify_value = mac_led_ctl[1];
//-----------------------------------------------------------------
// Activity detector
//-----------------------------------------------------------------
wire activity_int;
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_int)
);
always @ (posedge bus_clk) activity <= identify_enable ? identify_value : activity_int;
endmodule