eth: Add 100G configuration to HTG-ZRF8 example design

Signed-off-by: Alex Forencich <alex@alexforencich.com>
This commit is contained in:
Alex Forencich
2026-08-11 14:38:29 -07:00
parent 1d741faa1c
commit fa0cd921a3
19 changed files with 755 additions and 288 deletions

View File

@@ -8,7 +8,7 @@
set params [dict create]
# 10G MAC configuration
# MAC configuration
dict set params CFG_LOW_LATENCY "1"
dict set params COMBINED_MAC_PCS "1"
dict set params MAC_DATA_W "32"

View File

@@ -8,7 +8,7 @@
set params [dict create]
# 10G MAC configuration
# MAC configuration
dict set params CFG_LOW_LATENCY "1"
dict set params COMBINED_MAC_PCS "1"
dict set params MAC_DATA_W "32"

View File

@@ -0,0 +1,65 @@
# SPDX-License-Identifier: MIT
#
# Copyright (c) 2025 FPGA Ninja, LLC
#
# Authors:
# - Alex Forencich
#
# FPGA settings
FPGA_PART = xczu48dr-ffvg1517-2-e
FPGA_TOP = fpga
FPGA_ARCH = zynquplusRFSOC
RTL_DIR = ../rtl
LIB_DIR = ../lib
TAXI_SRC_DIR = $(LIB_DIR)/taxi/src
# Files for synthesis
SYN_FILES = $(RTL_DIR)/fpga_em.sv
SYN_FILES += $(RTL_DIR)/fpga_core.sv
SYN_FILES += $(RTL_DIR)/../pll/pll_i2c_init_em.sv
SYN_FILES += $(TAXI_SRC_DIR)/eth/rtl/us/taxi_eth_mac_25g_us.f
SYN_FILES += $(TAXI_SRC_DIR)/xfcp/rtl/taxi_xfcp_if_uart.f
SYN_FILES += $(TAXI_SRC_DIR)/xfcp/rtl/taxi_xfcp_switch.sv
SYN_FILES += $(TAXI_SRC_DIR)/xfcp/rtl/taxi_xfcp_mod_apb.f
SYN_FILES += $(TAXI_SRC_DIR)/xfcp/rtl/taxi_xfcp_mod_i2c_master.f
SYN_FILES += $(TAXI_SRC_DIR)/xfcp/rtl/taxi_xfcp_mod_stats.f
SYN_FILES += $(TAXI_SRC_DIR)/axis/rtl/taxi_axis_async_fifo.f
SYN_FILES += $(TAXI_SRC_DIR)/sync/rtl/taxi_sync_reset.sv
SYN_FILES += $(TAXI_SRC_DIR)/sync/rtl/taxi_sync_signal.sv
SYN_FILES += $(TAXI_SRC_DIR)/io/rtl/taxi_debounce_switch.sv
# XDC files
XDC_FILES += ../syn/EM/fpga.xdc
XDC_FILES += ../syn/EM/pll.xdc
XDC_FILES += ../syn/EM/lmk.xdc
XDC_FILES += ../syn/EM/gpio.xdc
XDC_FILES += ../syn/EM/i2c.xdc
XDC_FILES += ../syn/EM/fmc_htg_qsfp28_deg90.xdc
XDC_FILES += ../syn/EM/rfdc.xdc
XDC_FILES += ../syn/cfgmclk.xdc
XDC_FILES += $(TAXI_SRC_DIR)/eth/syn/vivado/taxi_eth_mac_fifo.tcl
XDC_FILES += $(TAXI_SRC_DIR)/axis/syn/vivado/taxi_axis_async_fifo.tcl
XDC_FILES += $(TAXI_SRC_DIR)/sync/syn/vivado/taxi_sync_reset.tcl
XDC_FILES += $(TAXI_SRC_DIR)/sync/syn/vivado/taxi_sync_signal.tcl
# IP
IP_TCL_FILES = $(TAXI_SRC_DIR)/eth/rtl/us/taxi_eth_phy_25g_us_gty_25g_161.tcl
IP_TCL_FILES += ../ip/usp_rfdc_1ghz_1gsps.tcl
# Configuration
CONFIG_TCL_FILES = ./config.tcl
include ../common/vivado.mk
program: $(FPGA_TOP).bit
echo "open_hw" > program.tcl
echo "connect_hw_server" >> program.tcl
echo "open_hw_target" >> program.tcl
echo "current_hw_device [lindex [get_hw_devices] 0]" >> program.tcl
echo "refresh_hw_device -update_hw_probes false [current_hw_device]" >> program.tcl
echo "set_property PROGRAM.FILE {$(FPGA_TOP).bit} [current_hw_device]" >> program.tcl
echo "program_hw_devices [current_hw_device]" >> program.tcl
echo "exit" >> program.tcl
vivado -nojournal -nolog -mode batch -source program.tcl

View File

@@ -0,0 +1,22 @@
# SPDX-License-Identifier: MIT
#
# Copyright (c) 2025 FPGA Ninja, LLC
#
# Authors:
# - Alex Forencich
#
set params [dict create]
# MAC configuration
dict set params CFG_LOW_LATENCY "1"
dict set params COMBINED_MAC_PCS "1"
dict set params MAC_DATA_W "64"
# apply parameters to top-level
set param_list {}
dict for {name value} $params {
lappend param_list $name=$value
}
set_property generic $param_list [get_filesets sources_1]

View File

@@ -0,0 +1,65 @@
# SPDX-License-Identifier: MIT
#
# Copyright (c) 2025 FPGA Ninja, LLC
#
# Authors:
# - Alex Forencich
#
# FPGA settings
FPGA_PART = xczu48dr-ffvg1517-2-e
FPGA_TOP = fpga
FPGA_ARCH = zynquplusRFSOC
RTL_DIR = ../rtl
LIB_DIR = ../lib
TAXI_SRC_DIR = $(LIB_DIR)/taxi/src
# Files for synthesis
SYN_FILES = $(RTL_DIR)/fpga_r2.sv
SYN_FILES += $(RTL_DIR)/fpga_core.sv
SYN_FILES += $(RTL_DIR)/../pll/pll_i2c_init_r2.sv
SYN_FILES += $(TAXI_SRC_DIR)/eth/rtl/us/taxi_eth_mac_25g_us.f
SYN_FILES += $(TAXI_SRC_DIR)/xfcp/rtl/taxi_xfcp_if_uart.f
SYN_FILES += $(TAXI_SRC_DIR)/xfcp/rtl/taxi_xfcp_switch.sv
SYN_FILES += $(TAXI_SRC_DIR)/xfcp/rtl/taxi_xfcp_mod_apb.f
SYN_FILES += $(TAXI_SRC_DIR)/xfcp/rtl/taxi_xfcp_mod_i2c_master.f
SYN_FILES += $(TAXI_SRC_DIR)/xfcp/rtl/taxi_xfcp_mod_stats.f
SYN_FILES += $(TAXI_SRC_DIR)/axis/rtl/taxi_axis_async_fifo.f
SYN_FILES += $(TAXI_SRC_DIR)/sync/rtl/taxi_sync_reset.sv
SYN_FILES += $(TAXI_SRC_DIR)/sync/rtl/taxi_sync_signal.sv
SYN_FILES += $(TAXI_SRC_DIR)/io/rtl/taxi_debounce_switch.sv
# XDC files
XDC_FILES += ../syn/R2/fpga.xdc
XDC_FILES += ../syn/R2/pll.xdc
XDC_FILES += ../syn/R2/lmk.xdc
XDC_FILES += ../syn/R2/gpio.xdc
XDC_FILES += ../syn/R2/i2c.xdc
XDC_FILES += ../syn/R2/fmc_htg_qsfp28_deg90.xdc
XDC_FILES += ../syn/R2/rfdc.xdc
XDC_FILES += ../syn/cfgmclk.xdc
XDC_FILES += $(TAXI_SRC_DIR)/eth/syn/vivado/taxi_eth_mac_fifo.tcl
XDC_FILES += $(TAXI_SRC_DIR)/axis/syn/vivado/taxi_axis_async_fifo.tcl
XDC_FILES += $(TAXI_SRC_DIR)/sync/syn/vivado/taxi_sync_reset.tcl
XDC_FILES += $(TAXI_SRC_DIR)/sync/syn/vivado/taxi_sync_signal.tcl
# IP
IP_TCL_FILES = $(TAXI_SRC_DIR)/eth/rtl/us/taxi_eth_phy_25g_us_gty_25g_161.tcl
IP_TCL_FILES += ../ip/usp_rfdc_1ghz_1gsps.tcl
# Configuration
CONFIG_TCL_FILES = ./config.tcl
include ../common/vivado.mk
program: $(FPGA_TOP).bit
echo "open_hw" > program.tcl
echo "connect_hw_server" >> program.tcl
echo "open_hw_target" >> program.tcl
echo "current_hw_device [lindex [get_hw_devices] 0]" >> program.tcl
echo "refresh_hw_device -update_hw_probes false [current_hw_device]" >> program.tcl
echo "set_property PROGRAM.FILE {$(FPGA_TOP).bit} [current_hw_device]" >> program.tcl
echo "program_hw_devices [current_hw_device]" >> program.tcl
echo "exit" >> program.tcl
vivado -nojournal -nolog -mode batch -source program.tcl

View File

@@ -0,0 +1,22 @@
# SPDX-License-Identifier: MIT
#
# Copyright (c) 2025 FPGA Ninja, LLC
#
# Authors:
# - Alex Forencich
#
set params [dict create]
# MAC configuration
dict set params CFG_LOW_LATENCY "1"
dict set params COMBINED_MAC_PCS "1"
dict set params MAC_DATA_W "64"
# apply parameters to top-level
set param_list {}
dict for {name value} $params {
lappend param_list $name=$value
}
set_property generic $param_list [get_filesets sources_1]

View File

@@ -19,7 +19,7 @@ TAXI_SRC_DIR = $(LIB_DIR)/taxi/src
SYN_FILES = $(RTL_DIR)/fpga_em.sv
SYN_FILES += $(RTL_DIR)/fpga_core.sv
SYN_FILES += $(RTL_DIR)/../pll/pll_i2c_init_em.sv
SYN_FILES += $(TAXI_SRC_DIR)/eth/rtl/us/taxi_eth_mac_25g_us.f
SYN_FILES += $(TAXI_SRC_DIR)/eth/rtl/us/taxi_eth_mac_100g_us.f
SYN_FILES += $(TAXI_SRC_DIR)/xfcp/rtl/taxi_xfcp_if_uart.f
SYN_FILES += $(TAXI_SRC_DIR)/xfcp/rtl/taxi_xfcp_switch.sv
SYN_FILES += $(TAXI_SRC_DIR)/xfcp/rtl/taxi_xfcp_mod_apb.f
@@ -38,6 +38,7 @@ XDC_FILES += ../syn/EM/gpio.xdc
XDC_FILES += ../syn/EM/i2c.xdc
XDC_FILES += ../syn/EM/fmc_htg_qsfp28_deg90.xdc
XDC_FILES += ../syn/EM/rfdc.xdc
XDC_FILES += ../syn/EM/eth_cmac.xdc
XDC_FILES += ../syn/cfgmclk.xdc
XDC_FILES += $(TAXI_SRC_DIR)/eth/syn/vivado/taxi_eth_mac_fifo.tcl
XDC_FILES += $(TAXI_SRC_DIR)/axis/syn/vivado/taxi_axis_async_fifo.tcl
@@ -45,7 +46,8 @@ XDC_FILES += $(TAXI_SRC_DIR)/sync/syn/vivado/taxi_sync_reset.tcl
XDC_FILES += $(TAXI_SRC_DIR)/sync/syn/vivado/taxi_sync_signal.tcl
# IP
IP_TCL_FILES = $(TAXI_SRC_DIR)/eth/rtl/us/taxi_eth_phy_25g_us_gty_25g_161.tcl
IP_TCL_FILES += $(TAXI_SRC_DIR)/eth/rtl/us/taxi_eth_mac_100g_us_cmace4.tcl
IP_TCL_FILES += $(TAXI_SRC_DIR)/eth/rtl/us/taxi_eth_mac_100g_us_gty_161.tcl
IP_TCL_FILES += ../ip/usp_rfdc_1ghz_1gsps.tcl
# Configuration

View File

@@ -8,10 +8,10 @@
set params [dict create]
# 10G MAC configuration
# MAC configuration
dict set params CFG_LOW_LATENCY "1"
dict set params COMBINED_MAC_PCS "1"
dict set params MAC_DATA_W "64"
dict set params MAC_DATA_W "512"
# apply parameters to top-level
set param_list {}

View File

@@ -19,7 +19,7 @@ TAXI_SRC_DIR = $(LIB_DIR)/taxi/src
SYN_FILES = $(RTL_DIR)/fpga_r2.sv
SYN_FILES += $(RTL_DIR)/fpga_core.sv
SYN_FILES += $(RTL_DIR)/../pll/pll_i2c_init_r2.sv
SYN_FILES += $(TAXI_SRC_DIR)/eth/rtl/us/taxi_eth_mac_25g_us.f
SYN_FILES += $(TAXI_SRC_DIR)/eth/rtl/us/taxi_eth_mac_100g_us.f
SYN_FILES += $(TAXI_SRC_DIR)/xfcp/rtl/taxi_xfcp_if_uart.f
SYN_FILES += $(TAXI_SRC_DIR)/xfcp/rtl/taxi_xfcp_switch.sv
SYN_FILES += $(TAXI_SRC_DIR)/xfcp/rtl/taxi_xfcp_mod_apb.f
@@ -38,6 +38,7 @@ XDC_FILES += ../syn/R2/gpio.xdc
XDC_FILES += ../syn/R2/i2c.xdc
XDC_FILES += ../syn/R2/fmc_htg_qsfp28_deg90.xdc
XDC_FILES += ../syn/R2/rfdc.xdc
XDC_FILES += ../syn/R2/eth_cmac.xdc
XDC_FILES += ../syn/cfgmclk.xdc
XDC_FILES += $(TAXI_SRC_DIR)/eth/syn/vivado/taxi_eth_mac_fifo.tcl
XDC_FILES += $(TAXI_SRC_DIR)/axis/syn/vivado/taxi_axis_async_fifo.tcl
@@ -45,7 +46,8 @@ XDC_FILES += $(TAXI_SRC_DIR)/sync/syn/vivado/taxi_sync_reset.tcl
XDC_FILES += $(TAXI_SRC_DIR)/sync/syn/vivado/taxi_sync_signal.tcl
# IP
IP_TCL_FILES = $(TAXI_SRC_DIR)/eth/rtl/us/taxi_eth_phy_25g_us_gty_25g_161.tcl
IP_TCL_FILES += $(TAXI_SRC_DIR)/eth/rtl/us/taxi_eth_mac_100g_us_cmace4.tcl
IP_TCL_FILES += $(TAXI_SRC_DIR)/eth/rtl/us/taxi_eth_mac_100g_us_gty_161.tcl
IP_TCL_FILES += ../ip/usp_rfdc_1ghz_1gsps.tcl
# Configuration

View File

@@ -8,10 +8,10 @@
set params [dict create]
# 10G MAC configuration
# MAC configuration
dict set params CFG_LOW_LATENCY "1"
dict set params COMBINED_MAC_PCS "1"
dict set params MAC_DATA_W "64"
dict set params MAC_DATA_W "512"
# apply parameters to top-level
set param_list {}

View File

@@ -1,7 +1,7 @@
// SPDX-License-Identifier: MIT
/*
Copyright (c) 2021-2025 FPGA Ninja, LLC
Copyright (c) 2021-2026 FPGA Ninja, LLC
Authors:
- Alex Forencich
@@ -30,10 +30,10 @@ module fpga_core #
parameter GTY_CLK_CNT = GTY_QUAD_CNT,
parameter ADC_CNT = 8,
parameter DAC_CNT = ADC_CNT,
// 10G/25G MAC configuration
// MAC configuration
parameter logic CFG_LOW_LATENCY = 1'b1,
parameter logic COMBINED_MAC_PCS = 1'b1,
parameter MAC_DATA_W = 64
parameter MAC_DATA_W = 512
)
(
/*
@@ -253,19 +253,21 @@ xfcp_mod_axil_inst (
);
// Ethernet
localparam MAC_CNT = MAC_DATA_W > 64 ? GTY_QUAD_CNT : GTY_CNT;
wire eth_reset = SIM ? 1'b0 : rst_125mhz;
assign eth_port_resetl = {PORT_CNT{~eth_reset}};
wire eth_gty_tx_clk[GTY_CNT];
wire eth_gty_tx_rst[GTY_CNT];
taxi_axis_if #(.DATA_W(MAC_DATA_W), .ID_W(8), .USER_EN(1), .USER_W(1)) eth_gty_axis_tx[GTY_CNT]();
taxi_axis_if #(.DATA_W(96), .KEEP_W(1), .ID_W(8)) eth_gty_axis_tx_cpl[GTY_CNT]();
wire eth_gty_tx_clk[MAC_CNT];
wire eth_gty_tx_rst[MAC_CNT];
taxi_axis_if #(.DATA_W(MAC_DATA_W), .ID_W(8), .USER_EN(1), .USER_W(1)) eth_gty_axis_tx[MAC_CNT]();
taxi_axis_if #(.DATA_W(96), .KEEP_W(1), .ID_W(8)) eth_gty_axis_tx_cpl[MAC_CNT]();
wire eth_gty_rx_clk[GTY_CNT];
wire eth_gty_rx_rst[GTY_CNT];
taxi_axis_if #(.DATA_W(MAC_DATA_W), .ID_W(8), .USER_EN(1), .USER_W(1)) eth_gty_axis_rx[GTY_CNT]();
wire eth_gty_rx_clk[MAC_CNT];
wire eth_gty_rx_rst[MAC_CNT];
taxi_axis_if #(.DATA_W(MAC_DATA_W), .ID_W(8), .USER_EN(1), .USER_W(1)) eth_gty_axis_rx[MAC_CNT]();
wire eth_gty_rx_status[GTY_CNT];
wire eth_gty_rx_status[MAC_CNT];
wire [GTY_QUAD_CNT-1:0] eth_gty_gtpowergood;
@@ -352,273 +354,513 @@ for (genvar n = 0; n < GTY_QUAD_CNT; n = n + 1) begin : gty_quad
.m_apb(gt_apb_ctrl)
);
taxi_eth_mac_25g_us #(
.SIM(SIM),
.VENDOR(VENDOR),
.FAMILY(FAMILY),
if (MAC_DATA_W == 512) begin: mac
.CNT(CNT),
taxi_eth_mac_100g_us #(
.SIM(SIM),
.VENDOR(VENDOR),
.FAMILY(FAMILY),
// GT config
.CFG_LOW_LATENCY(CFG_LOW_LATENCY),
.GT_CNT(CNT),
// GT type
.GT_TYPE("GTY"),
// GT config
.CFG_LOW_LATENCY(CFG_LOW_LATENCY),
// MAC/PHY config
.COMBINED_MAC_PCS(COMBINED_MAC_PCS),
.DATA_W(eth_gty_axis_tx[0].DATA_W),
.USXGMII_EN(COMBINED_MAC_PCS),
.DIC_EN(1'b1),
.PTP_TS_EN(1'b0),
.PTP_TD_EN(1'b0),
.PTP_TS_FMT_TOD(1'b1),
.PTP_TS_W(96),
.PTP_TD_SDI_PIPELINE(2),
.PRBS31_EN(1'b0),
.TX_SERDES_PIPELINE(1),
.RX_SERDES_PIPELINE(1),
.COUNT_125US(125000/6.4),
.STAT_EN(1),
.STAT_TX_LEVEL(1),
.STAT_RX_LEVEL(1),
.STAT_ID_BASE(n*CNT*(16+16)),
.STAT_UPDATE_PERIOD(1024),
.STAT_STR_EN(1),
.STAT_PREFIX_STR(
n == 0 ? STAT_PREFIX_STR_QSFP1 :
STAT_PREFIX_STR_QSFP2
// GT type
.GT_TYPE("GTY"),
// MAC/PHY config
.PTP_TS_EN(1'b0),
.PTP_TD_EN(1'b0),
.PTP_TS_FMT_TOD(1'b1),
.PTP_TS_W(96),
.PTP_TD_SDI_PIPELINE(2),
.TX_SERDES_PIPELINE(1),
.RX_SERDES_PIPELINE(1),
.STAT_EN(1),
.STAT_TX_LEVEL(1),
.STAT_RX_LEVEL(1),
.STAT_ID_BASE(n*CNT*(16+16)),
.STAT_UPDATE_PERIOD(1024),
.STAT_STR_EN(1),
.STAT_PREFIX_STR(
n == 0 ? "QSFP1" :
"QSFP2"
)
)
)
mac_inst (
.xcvr_ctrl_clk(clk_125mhz),
.xcvr_ctrl_rst(eth_gty_rst[CLK]),
mac_inst (
.xcvr_ctrl_clk(clk_125mhz),
.xcvr_ctrl_rst(eth_gty_rst[CLK]),
/*
* Transceiver control
*/
.s_apb_ctrl(gt_apb_ctrl),
/*
* Transceiver control
*/
.s_apb_ctrl(gt_apb_ctrl),
/*
* Common
*/
.xcvr_gtpowergood_out(eth_gty_gtpowergood[n]),
.xcvr_gtrefclk00_in(eth_gty_mgt_refclk[CLK]),
.xcvr_qpll0pd_in(1'b0),
.xcvr_qpll0reset_in(1'b0),
.xcvr_qpll0pcierate_in(3'd0),
.xcvr_qpll0lock_out(),
.xcvr_qpll0clk_out(),
.xcvr_qpll0refclk_out(),
.xcvr_gtrefclk01_in(eth_gty_mgt_refclk[CLK]),
.xcvr_qpll1pd_in(1'b0),
.xcvr_qpll1reset_in(1'b0),
.xcvr_qpll1pcierate_in(3'd0),
.xcvr_qpll1lock_out(),
.xcvr_qpll1clk_out(),
.xcvr_qpll1refclk_out(),
/*
* Common
*/
.xcvr_gtpowergood_out(eth_gty_gtpowergood[n]),
.xcvr_gtrefclk00_in(eth_gty_mgt_refclk[CLK]),
.xcvr_qpll0pd_in(1'b0),
.xcvr_qpll0lock_out(),
.xcvr_qpll0clk_out(),
.xcvr_qpll0refclk_out(),
.xcvr_gtrefclk01_in(eth_gty_mgt_refclk[CLK]),
.xcvr_qpll1pd_in(1'b0),
.xcvr_qpll1lock_out(),
.xcvr_qpll1clk_out(),
.xcvr_qpll1refclk_out(),
/*
* Serial data
*/
.xcvr_txp(eth_gty_tx_p[n*CNT +: CNT]),
.xcvr_txn(eth_gty_tx_n[n*CNT +: CNT]),
.xcvr_rxp(eth_gty_rx_p[n*CNT +: CNT]),
.xcvr_rxn(eth_gty_rx_n[n*CNT +: CNT]),
/*
* Serial data
*/
.xcvr_txp(eth_gty_tx_p[n*CNT +: CNT]),
.xcvr_txn(eth_gty_tx_n[n*CNT +: CNT]),
.xcvr_rxp(eth_gty_rx_p[n*CNT +: CNT]),
.xcvr_rxn(eth_gty_rx_n[n*CNT +: CNT]),
/*
* MAC clocks
*/
.rx_clk(eth_gty_rx_clk[n*CNT +: CNT]),
.rx_rst_in('{CNT{1'b0}}),
.rx_rst_out(eth_gty_rx_rst[n*CNT +: CNT]),
.tx_clk(eth_gty_tx_clk[n*CNT +: CNT]),
.tx_rst_in('{CNT{1'b0}}),
.tx_rst_out(eth_gty_tx_rst[n*CNT +: CNT]),
/*
* MAC clocks
*/
.rx_clk(eth_gty_rx_clk[n]),
.rx_rst_in(1'b0),
.rx_rst_out(eth_gty_rx_rst[n]),
.tx_clk(eth_gty_tx_clk[n]),
.tx_rst_in(1'b0),
.tx_rst_out(eth_gty_tx_rst[n]),
/*
* Transmit interface (AXI stream)
*/
.s_axis_tx(eth_gty_axis_tx[n*CNT +: CNT]),
.m_axis_tx_cpl(eth_gty_axis_tx_cpl[n*CNT +: CNT]),
/*
* Transmit interface (AXI stream)
*/
.s_axis_tx(eth_gty_axis_tx[n]),
.m_axis_tx_cpl(eth_gty_axis_tx_cpl[n]),
/*
* Receive interface (AXI stream)
*/
.m_axis_rx(eth_gty_axis_rx[n*CNT +: CNT]),
/*
* Receive interface (AXI stream)
*/
.m_axis_rx(eth_gty_axis_rx[n]),
/*
* USXGMII autonegotiation
*/
.an_en('{CNT{1'b1}}),
.an_restart('{CNT{1'b0}}),
.an_speedup('{CNT{1'b0}}),
.an_timeout_en('{CNT{1'b1}}),
.an_usxgmii_en('{CNT{1'b0}}),
.an_usxgmii_auto('{CNT{1'b1}}),
.an_intr(),
.an_running(),
.an_complete(),
.an_timeout(),
.an_usxgmii_mode(),
.an_adv_ability_usxgmii('{CNT{16'h1601}}),
.an_lp_adv_ability(),
.an_lp_usxgmii_link(),
.an_lp_usxgmii_speed(),
.an_res_full_duplex(),
/*
* PTP clock
*/
.ptp_clk(1'b0),
.ptp_rst(1'b0),
.ptp_sample_clk(1'b0),
.ptp_td_sdi(1'b0),
.tx_ptp_ts_in('0),
.tx_ptp_ts_out(),
.tx_ptp_ts_step_out(),
.tx_ptp_locked(),
.rx_ptp_ts_in('0),
.rx_ptp_ts_out(),
.rx_ptp_ts_step_out(),
.rx_ptp_locked(),
/*
* PTP clock
*/
.ptp_clk(1'b0),
.ptp_rst(1'b0),
.ptp_sample_clk(1'b0),
.ptp_td_sdi(1'b0),
.tx_ptp_ts_in('{CNT{'0}}),
.tx_ptp_ts_out(),
.tx_ptp_ts_step_out(),
.tx_ptp_locked(),
.rx_ptp_ts_in('{CNT{'0}}),
.rx_ptp_ts_out(),
.rx_ptp_ts_step_out(),
.rx_ptp_locked(),
/*
* Link-level Flow Control (LFC) (IEEE 802.3 annex 31B PAUSE)
*/
.tx_lfc_req(1'b0),
.tx_lfc_resend(1'b0),
.rx_lfc_en(1'b0),
.rx_lfc_req(),
.rx_lfc_ack(1'b0),
/*
* Link-level Flow Control (LFC) (IEEE 802.3 annex 31B PAUSE)
*/
.tx_lfc_req('{CNT{1'b0}}),
.tx_lfc_resend('{CNT{1'b0}}),
.rx_lfc_en('{CNT{1'b0}}),
.rx_lfc_req(),
.rx_lfc_ack('{CNT{1'b0}}),
/*
* Priority Flow Control (PFC) (IEEE 802.3 annex 31D PFC)
*/
.tx_pfc_req('0),
.tx_pfc_resend(1'b0),
.rx_pfc_en('0),
.rx_pfc_req(),
.rx_pfc_ack('0),
/*
* Priority Flow Control (PFC) (IEEE 802.3 annex 31D PFC)
*/
.tx_pfc_req('{CNT{'0}}),
.tx_pfc_resend('{CNT{1'b0}}),
.rx_pfc_en('{CNT{'0}}),
.rx_pfc_req(),
.rx_pfc_ack('{CNT{'0}}),
/*
* Pause interface
*/
.tx_lfc_pause_en(1'b0),
.tx_pause_req(1'b0),
.tx_pause_ack(),
/*
* Pause interface
*/
.tx_lfc_pause_en('{CNT{1'b0}}),
.tx_pause_req('{CNT{1'b0}}),
.tx_pause_ack(),
/*
* Statistics
*/
.stat_clk(clk_125mhz),
.stat_rst(rst_125mhz),
.m_axis_stat(axis_eth_stat[n]),
/*
* Statistics
*/
.stat_clk(clk_125mhz),
.stat_rst(rst_125mhz),
.m_axis_stat(axis_eth_stat[n]),
/*
* Status
*/
.tx_start_packet(),
.stat_tx_byte(),
.stat_tx_pkt_len(),
.stat_tx_pkt_ucast(),
.stat_tx_pkt_mcast(),
.stat_tx_pkt_bcast(),
.stat_tx_pkt_vlan(),
.stat_tx_pkt_good(),
.stat_tx_pkt_bad(),
.stat_tx_pad_frame(),
.stat_tx_err_oversize(),
.stat_tx_err_user(),
.stat_tx_err_underflow(),
.rx_start_packet(),
.rx_error_count(),
.rx_block_lock(),
.rx_high_ber(),
.rx_status(eth_gty_rx_status[n]),
.stat_rx_byte(),
.stat_rx_pkt_len(),
.stat_rx_pkt_fragment(),
.stat_rx_pkt_jabber(),
.stat_rx_pkt_ucast(),
.stat_rx_pkt_mcast(),
.stat_rx_pkt_bcast(),
.stat_rx_pkt_vlan(),
.stat_rx_pkt_good(),
.stat_rx_pkt_bad(),
.stat_rx_err_oversize(),
.stat_rx_err_bad_fcs(),
.stat_rx_err_bad_block(),
.stat_rx_err_framing(),
.stat_rx_err_preamble(),
.stat_rx_fifo_drop(1'b0),
.stat_tx_mcf(),
.stat_rx_mcf(),
.stat_tx_lfc_pkt(),
.stat_tx_lfc_xon(),
.stat_tx_lfc_xoff(),
.stat_tx_lfc_paused(),
.stat_tx_pfc_pkt(),
.stat_tx_pfc_xon(),
.stat_tx_pfc_xoff(),
.stat_tx_pfc_paused(),
.stat_rx_lfc_pkt(),
.stat_rx_lfc_xon(),
.stat_rx_lfc_xoff(),
.stat_rx_lfc_paused(),
.stat_rx_pfc_pkt(),
.stat_rx_pfc_xon(),
.stat_rx_pfc_xoff(),
.stat_rx_pfc_paused(),
/*
* Status
*/
.tx_start_packet(),
.stat_tx_byte(),
.stat_tx_pkt_len(),
.stat_tx_pkt_ucast(),
.stat_tx_pkt_mcast(),
.stat_tx_pkt_bcast(),
.stat_tx_pkt_vlan(),
.stat_tx_pkt_good(),
.stat_tx_pkt_bad(),
.stat_tx_pad_frame(),
.stat_tx_err_oversize(),
.stat_tx_err_user(),
.stat_tx_err_underflow(),
.rx_start_packet(),
.rx_error_count(),
.rx_block_lock(),
.rx_high_ber(),
.rx_status(eth_gty_rx_status[n*CNT +: CNT]),
.stat_rx_byte(),
.stat_rx_pkt_len(),
.stat_rx_pkt_fragment(),
.stat_rx_pkt_jabber(),
.stat_rx_pkt_ucast(),
.stat_rx_pkt_mcast(),
.stat_rx_pkt_bcast(),
.stat_rx_pkt_vlan(),
.stat_rx_pkt_good(),
.stat_rx_pkt_bad(),
.stat_rx_err_oversize(),
.stat_rx_err_bad_fcs(),
.stat_rx_err_bad_block(),
.stat_rx_err_framing(),
.stat_rx_err_preamble(),
.stat_rx_fifo_drop('{CNT{1'b0}}),
.stat_tx_mcf(),
.stat_rx_mcf(),
.stat_tx_lfc_pkt(),
.stat_tx_lfc_xon(),
.stat_tx_lfc_xoff(),
.stat_tx_lfc_paused(),
.stat_tx_pfc_pkt(),
.stat_tx_pfc_xon(),
.stat_tx_pfc_xoff(),
.stat_tx_pfc_paused(),
.stat_rx_lfc_pkt(),
.stat_rx_lfc_xon(),
.stat_rx_lfc_xoff(),
.stat_rx_lfc_paused(),
.stat_rx_pfc_pkt(),
.stat_rx_pfc_xon(),
.stat_rx_pfc_xoff(),
.stat_rx_pfc_paused(),
/*
* Configuration
*/
.cfg_tx_pad_en(1'b1),
.cfg_tx_min_pkt_len(8'd60-1),
.cfg_tx_max_pkt_len(16'd9218-1),
.cfg_tx_ifg(8'd12),
.cfg_tx_enable(1'b1),
.cfg_rx_max_pkt_len(16'd9218-1),
.cfg_rx_enable(1'b1),
.cfg_tx_prbs31_enable(1'b0),
.cfg_rx_prbs31_enable(1'b0),
.cfg_mcf_rx_eth_dst_mcast(48'h01_80_C2_00_00_01),
.cfg_mcf_rx_check_eth_dst_mcast(1'b1),
.cfg_mcf_rx_eth_dst_ucast(48'd0),
.cfg_mcf_rx_check_eth_dst_ucast(1'b0),
.cfg_mcf_rx_eth_src(48'd0),
.cfg_mcf_rx_check_eth_src(1'b0),
.cfg_mcf_rx_eth_type(16'h8808),
.cfg_mcf_rx_opcode_lfc(16'h0001),
.cfg_mcf_rx_check_opcode_lfc(1'b1),
.cfg_mcf_rx_opcode_pfc(16'h0101),
.cfg_mcf_rx_check_opcode_pfc(1'b1),
.cfg_mcf_rx_forward(1'b0),
.cfg_mcf_rx_enable(1'b0),
.cfg_tx_lfc_eth_dst(48'h01_80_C2_00_00_01),
.cfg_tx_lfc_eth_src(48'h80_23_31_43_54_4C),
.cfg_tx_lfc_eth_type(16'h8808),
.cfg_tx_lfc_opcode(16'h0001),
.cfg_tx_lfc_en(1'b0),
.cfg_tx_lfc_quanta(16'hffff),
.cfg_tx_lfc_refresh(16'h7fff),
.cfg_tx_pfc_eth_dst(48'h01_80_C2_00_00_01),
.cfg_tx_pfc_eth_src(48'h80_23_31_43_54_4C),
.cfg_tx_pfc_eth_type(16'h8808),
.cfg_tx_pfc_opcode(16'h0101),
.cfg_tx_pfc_en(1'b0),
.cfg_tx_pfc_quanta('{8{16'hffff}}),
.cfg_tx_pfc_refresh('{8{16'h7fff}}),
.cfg_rx_lfc_opcode(16'h0001),
.cfg_rx_lfc_en(1'b0),
.cfg_rx_pfc_opcode(16'h0101),
.cfg_rx_pfc_en(1'b0)
);
/*
* Configuration
*/
.cfg_tx_pad_en('{CNT{1'b1}}),
.cfg_tx_min_pkt_len('{CNT{8'd60-1}}),
.cfg_tx_max_pkt_len('{CNT{16'd9218-1}}),
.cfg_tx_ifg('{CNT{8'd12}}),
.cfg_tx_enable('{CNT{1'b1}}),
.cfg_rx_max_pkt_len('{CNT{16'd9218-1}}),
.cfg_rx_enable('{CNT{1'b1}}),
.cfg_tx_prbs31_enable('{CNT{1'b0}}),
.cfg_rx_prbs31_enable('{CNT{1'b0}}),
.cfg_mcf_rx_eth_dst_mcast('{CNT{48'h01_80_C2_00_00_01}}),
.cfg_mcf_rx_check_eth_dst_mcast('{CNT{1'b1}}),
.cfg_mcf_rx_eth_dst_ucast('{CNT{48'd0}}),
.cfg_mcf_rx_check_eth_dst_ucast('{CNT{1'b0}}),
.cfg_mcf_rx_eth_src('{CNT{48'd0}}),
.cfg_mcf_rx_check_eth_src('{CNT{1'b0}}),
.cfg_mcf_rx_eth_type('{CNT{16'h8808}}),
.cfg_mcf_rx_opcode_lfc('{CNT{16'h0001}}),
.cfg_mcf_rx_check_opcode_lfc('{CNT{1'b1}}),
.cfg_mcf_rx_opcode_pfc('{CNT{16'h0101}}),
.cfg_mcf_rx_check_opcode_pfc('{CNT{1'b1}}),
.cfg_mcf_rx_forward('{CNT{1'b0}}),
.cfg_mcf_rx_enable('{CNT{1'b0}}),
.cfg_tx_lfc_eth_dst('{CNT{48'h01_80_C2_00_00_01}}),
.cfg_tx_lfc_eth_src('{CNT{48'h80_23_31_43_54_4C}}),
.cfg_tx_lfc_eth_type('{CNT{16'h8808}}),
.cfg_tx_lfc_opcode('{CNT{16'h0001}}),
.cfg_tx_lfc_en('{CNT{1'b0}}),
.cfg_tx_lfc_quanta('{CNT{16'hffff}}),
.cfg_tx_lfc_refresh('{CNT{16'h7fff}}),
.cfg_tx_pfc_eth_dst('{CNT{48'h01_80_C2_00_00_01}}),
.cfg_tx_pfc_eth_src('{CNT{48'h80_23_31_43_54_4C}}),
.cfg_tx_pfc_eth_type('{CNT{16'h8808}}),
.cfg_tx_pfc_opcode('{CNT{16'h0101}}),
.cfg_tx_pfc_en('{CNT{1'b0}}),
.cfg_tx_pfc_quanta('{CNT{'{8{16'hffff}}}}),
.cfg_tx_pfc_refresh('{CNT{'{8{16'h7fff}}}}),
.cfg_rx_lfc_opcode('{CNT{16'h0001}}),
.cfg_rx_lfc_en('{CNT{1'b0}}),
.cfg_rx_pfc_opcode('{CNT{16'h0101}}),
.cfg_rx_pfc_en('{CNT{1'b0}})
);
end else begin: mac
taxi_eth_mac_25g_us #(
.SIM(SIM),
.VENDOR(VENDOR),
.FAMILY(FAMILY),
.CNT(CNT),
// GT config
.CFG_LOW_LATENCY(CFG_LOW_LATENCY),
// GT type
.GT_TYPE("GTY"),
// MAC/PHY config
.COMBINED_MAC_PCS(COMBINED_MAC_PCS),
.DATA_W(eth_gty_axis_tx[0].DATA_W),
.USXGMII_EN(COMBINED_MAC_PCS),
.DIC_EN(1'b1),
.PTP_TS_EN(1'b0),
.PTP_TD_EN(1'b0),
.PTP_TS_FMT_TOD(1'b1),
.PTP_TS_W(96),
.PTP_TD_SDI_PIPELINE(2),
.PRBS31_EN(1'b0),
.TX_SERDES_PIPELINE(1),
.RX_SERDES_PIPELINE(1),
.COUNT_125US(125000/6.4),
.STAT_EN(1),
.STAT_TX_LEVEL(1),
.STAT_RX_LEVEL(1),
.STAT_ID_BASE(n*CNT*(16+16)),
.STAT_UPDATE_PERIOD(1024),
.STAT_STR_EN(1),
.STAT_PREFIX_STR(
n == 0 ? STAT_PREFIX_STR_QSFP1 :
STAT_PREFIX_STR_QSFP2
)
)
mac_inst (
.xcvr_ctrl_clk(clk_125mhz),
.xcvr_ctrl_rst(eth_gty_rst[CLK]),
/*
* Transceiver control
*/
.s_apb_ctrl(gt_apb_ctrl),
/*
* Common
*/
.xcvr_gtpowergood_out(eth_gty_gtpowergood[n]),
.xcvr_gtrefclk00_in(eth_gty_mgt_refclk[CLK]),
.xcvr_qpll0pd_in(1'b0),
.xcvr_qpll0reset_in(1'b0),
.xcvr_qpll0pcierate_in(3'd0),
.xcvr_qpll0lock_out(),
.xcvr_qpll0clk_out(),
.xcvr_qpll0refclk_out(),
.xcvr_gtrefclk01_in(eth_gty_mgt_refclk[CLK]),
.xcvr_qpll1pd_in(1'b0),
.xcvr_qpll1reset_in(1'b0),
.xcvr_qpll1pcierate_in(3'd0),
.xcvr_qpll1lock_out(),
.xcvr_qpll1clk_out(),
.xcvr_qpll1refclk_out(),
/*
* Serial data
*/
.xcvr_txp(eth_gty_tx_p[n*CNT +: CNT]),
.xcvr_txn(eth_gty_tx_n[n*CNT +: CNT]),
.xcvr_rxp(eth_gty_rx_p[n*CNT +: CNT]),
.xcvr_rxn(eth_gty_rx_n[n*CNT +: CNT]),
/*
* MAC clocks
*/
.rx_clk(eth_gty_rx_clk[n*CNT +: CNT]),
.rx_rst_in('{CNT{1'b0}}),
.rx_rst_out(eth_gty_rx_rst[n*CNT +: CNT]),
.tx_clk(eth_gty_tx_clk[n*CNT +: CNT]),
.tx_rst_in('{CNT{1'b0}}),
.tx_rst_out(eth_gty_tx_rst[n*CNT +: CNT]),
/*
* Transmit interface (AXI stream)
*/
.s_axis_tx(eth_gty_axis_tx[n*CNT +: CNT]),
.m_axis_tx_cpl(eth_gty_axis_tx_cpl[n*CNT +: CNT]),
/*
* Receive interface (AXI stream)
*/
.m_axis_rx(eth_gty_axis_rx[n*CNT +: CNT]),
/*
* USXGMII autonegotiation
*/
.an_en('{CNT{1'b1}}),
.an_restart('{CNT{1'b0}}),
.an_speedup('{CNT{1'b0}}),
.an_timeout_en('{CNT{1'b1}}),
.an_usxgmii_en('{CNT{1'b0}}),
.an_usxgmii_auto('{CNT{1'b1}}),
.an_intr(),
.an_running(),
.an_complete(),
.an_timeout(),
.an_usxgmii_mode(),
.an_adv_ability_usxgmii('{CNT{16'h1601}}),
.an_lp_adv_ability(),
.an_lp_usxgmii_link(),
.an_lp_usxgmii_speed(),
.an_res_full_duplex(),
/*
* PTP clock
*/
.ptp_clk(1'b0),
.ptp_rst(1'b0),
.ptp_sample_clk(1'b0),
.ptp_td_sdi(1'b0),
.tx_ptp_ts_in('{CNT{'0}}),
.tx_ptp_ts_out(),
.tx_ptp_ts_step_out(),
.tx_ptp_locked(),
.rx_ptp_ts_in('{CNT{'0}}),
.rx_ptp_ts_out(),
.rx_ptp_ts_step_out(),
.rx_ptp_locked(),
/*
* Link-level Flow Control (LFC) (IEEE 802.3 annex 31B PAUSE)
*/
.tx_lfc_req('{CNT{1'b0}}),
.tx_lfc_resend('{CNT{1'b0}}),
.rx_lfc_en('{CNT{1'b0}}),
.rx_lfc_req(),
.rx_lfc_ack('{CNT{1'b0}}),
/*
* Priority Flow Control (PFC) (IEEE 802.3 annex 31D PFC)
*/
.tx_pfc_req('{CNT{'0}}),
.tx_pfc_resend('{CNT{1'b0}}),
.rx_pfc_en('{CNT{'0}}),
.rx_pfc_req(),
.rx_pfc_ack('{CNT{'0}}),
/*
* Pause interface
*/
.tx_lfc_pause_en('{CNT{1'b0}}),
.tx_pause_req('{CNT{1'b0}}),
.tx_pause_ack(),
/*
* Statistics
*/
.stat_clk(clk_125mhz),
.stat_rst(rst_125mhz),
.m_axis_stat(axis_eth_stat[n]),
/*
* Status
*/
.tx_start_packet(),
.stat_tx_byte(),
.stat_tx_pkt_len(),
.stat_tx_pkt_ucast(),
.stat_tx_pkt_mcast(),
.stat_tx_pkt_bcast(),
.stat_tx_pkt_vlan(),
.stat_tx_pkt_good(),
.stat_tx_pkt_bad(),
.stat_tx_pad_frame(),
.stat_tx_err_oversize(),
.stat_tx_err_user(),
.stat_tx_err_underflow(),
.rx_start_packet(),
.rx_error_count(),
.rx_block_lock(),
.rx_high_ber(),
.rx_status(eth_gty_rx_status[n*CNT +: CNT]),
.stat_rx_byte(),
.stat_rx_pkt_len(),
.stat_rx_pkt_fragment(),
.stat_rx_pkt_jabber(),
.stat_rx_pkt_ucast(),
.stat_rx_pkt_mcast(),
.stat_rx_pkt_bcast(),
.stat_rx_pkt_vlan(),
.stat_rx_pkt_good(),
.stat_rx_pkt_bad(),
.stat_rx_err_oversize(),
.stat_rx_err_bad_fcs(),
.stat_rx_err_bad_block(),
.stat_rx_err_framing(),
.stat_rx_err_preamble(),
.stat_rx_fifo_drop('{CNT{1'b0}}),
.stat_tx_mcf(),
.stat_rx_mcf(),
.stat_tx_lfc_pkt(),
.stat_tx_lfc_xon(),
.stat_tx_lfc_xoff(),
.stat_tx_lfc_paused(),
.stat_tx_pfc_pkt(),
.stat_tx_pfc_xon(),
.stat_tx_pfc_xoff(),
.stat_tx_pfc_paused(),
.stat_rx_lfc_pkt(),
.stat_rx_lfc_xon(),
.stat_rx_lfc_xoff(),
.stat_rx_lfc_paused(),
.stat_rx_pfc_pkt(),
.stat_rx_pfc_xon(),
.stat_rx_pfc_xoff(),
.stat_rx_pfc_paused(),
/*
* Configuration
*/
.cfg_tx_pad_en('{CNT{1'b1}}),
.cfg_tx_min_pkt_len('{CNT{8'd60-1}}),
.cfg_tx_max_pkt_len('{CNT{16'd9218-1}}),
.cfg_tx_ifg('{CNT{8'd12}}),
.cfg_tx_enable('{CNT{1'b1}}),
.cfg_rx_max_pkt_len('{CNT{16'd9218-1}}),
.cfg_rx_enable('{CNT{1'b1}}),
.cfg_tx_prbs31_enable('{CNT{1'b0}}),
.cfg_rx_prbs31_enable('{CNT{1'b0}}),
.cfg_mcf_rx_eth_dst_mcast('{CNT{48'h01_80_C2_00_00_01}}),
.cfg_mcf_rx_check_eth_dst_mcast('{CNT{1'b1}}),
.cfg_mcf_rx_eth_dst_ucast('{CNT{48'd0}}),
.cfg_mcf_rx_check_eth_dst_ucast('{CNT{1'b0}}),
.cfg_mcf_rx_eth_src('{CNT{48'd0}}),
.cfg_mcf_rx_check_eth_src('{CNT{1'b0}}),
.cfg_mcf_rx_eth_type('{CNT{16'h8808}}),
.cfg_mcf_rx_opcode_lfc('{CNT{16'h0001}}),
.cfg_mcf_rx_check_opcode_lfc('{CNT{1'b1}}),
.cfg_mcf_rx_opcode_pfc('{CNT{16'h0101}}),
.cfg_mcf_rx_check_opcode_pfc('{CNT{1'b1}}),
.cfg_mcf_rx_forward('{CNT{1'b0}}),
.cfg_mcf_rx_enable('{CNT{1'b0}}),
.cfg_tx_lfc_eth_dst('{CNT{48'h01_80_C2_00_00_01}}),
.cfg_tx_lfc_eth_src('{CNT{48'h80_23_31_43_54_4C}}),
.cfg_tx_lfc_eth_type('{CNT{16'h8808}}),
.cfg_tx_lfc_opcode('{CNT{16'h0001}}),
.cfg_tx_lfc_en('{CNT{1'b0}}),
.cfg_tx_lfc_quanta('{CNT{16'hffff}}),
.cfg_tx_lfc_refresh('{CNT{16'h7fff}}),
.cfg_tx_pfc_eth_dst('{CNT{48'h01_80_C2_00_00_01}}),
.cfg_tx_pfc_eth_src('{CNT{48'h80_23_31_43_54_4C}}),
.cfg_tx_pfc_eth_type('{CNT{16'h8808}}),
.cfg_tx_pfc_opcode('{CNT{16'h0101}}),
.cfg_tx_pfc_en('{CNT{1'b0}}),
.cfg_tx_pfc_quanta('{CNT{'{8{16'hffff}}}}),
.cfg_tx_pfc_refresh('{CNT{'{8{16'h7fff}}}}),
.cfg_rx_lfc_opcode('{CNT{16'h0001}}),
.cfg_rx_lfc_en('{CNT{1'b0}}),
.cfg_rx_pfc_opcode('{CNT{16'h0101}}),
.cfg_rx_pfc_en('{CNT{1'b0}})
);
end
end
for (genvar n = 0; n < GTY_CNT; n = n + 1) begin : gty_ch
for (genvar n = 0; n < $size(eth_gty_axis_tx); n = n + 1) begin : gty_ch
taxi_axis_async_fifo #(
.DEPTH(16384),

View File

@@ -1,7 +1,7 @@
// SPDX-License-Identifier: MIT
/*
Copyright (c) 2021-2025 FPGA Ninja, LLC
Copyright (c) 2021-2026 FPGA Ninja, LLC
Authors:
- Alex Forencich
@@ -23,10 +23,10 @@ module fpga #
parameter string VENDOR = "XILINX",
// device family
parameter string FAMILY = "zynquplusRFSOC",
// 10G/25G MAC configuration
// MAC configuration
parameter logic CFG_LOW_LATENCY = 1'b1,
parameter logic COMBINED_MAC_PCS = 1'b1,
parameter MAC_DATA_W = 64
parameter MAC_DATA_W = 512
)
(
/*

View File

@@ -1,7 +1,7 @@
// SPDX-License-Identifier: MIT
/*
Copyright (c) 2021-2025 FPGA Ninja, LLC
Copyright (c) 2021-2026 FPGA Ninja, LLC
Authors:
- Alex Forencich
@@ -23,10 +23,10 @@ module fpga #
parameter string VENDOR = "XILINX",
// device family
parameter string FAMILY = "zynquplusRFSOC",
// 10G/25G MAC configuration
// MAC configuration
parameter logic CFG_LOW_LATENCY = 1'b1,
parameter logic COMBINED_MAC_PCS = 1'b1,
parameter MAC_DATA_W = 64
parameter MAC_DATA_W = 512
)
(
/*

View File

@@ -0,0 +1,4 @@
# CMACs
set_property LOC CMACE4_X0Y0 [get_cells -hierarchical -filter {NAME =~ core_inst/gty_quad[0].mac.* && REF_NAME==CMACE4}]
set_property LOC CMACE4_X0Y1 [get_cells -hierarchical -filter {NAME =~ core_inst/gty_quad[1].mac.* && REF_NAME==CMACE4}]

View File

@@ -16,7 +16,7 @@ set_property -dict {LOC AU3 IOSTANDARD LVDS_25} [get_ports fpga_refclk_n] ;# U2
create_clock -period 4.000 -name fpga_refclk [get_ports fpga_refclk_p]
# Source pin is in an HDIO bank, so it must be routed to an MMCM via a BUFG
set_property CLOCK_DEDICATED_ROUTE ANY_CMT_COLUMN [get_nets fpga_refclk_int fpga_refclk_bufg_inst_n_0]
set_property CLOCK_DEDICATED_ROUTE ANY_CMT_COLUMN [get_nets {fpga_refclk_int fpga_refclk_bufg_inst_n_0}]
# PLL sysref from U2
set_property -dict {LOC AT5 IOSTANDARD LVDS_25} [get_ports fpga_sysref_p] ;# U2.62 CLKout12_P

View File

@@ -0,0 +1,4 @@
# CMACs
set_property LOC CMACE4_X0Y0 [get_cells -hierarchical -filter {NAME =~ core_inst/gty_quad[0].mac.* && REF_NAME==CMACE4}]
set_property LOC CMACE4_X0Y1 [get_cells -hierarchical -filter {NAME =~ core_inst/gty_quad[1].mac.* && REF_NAME==CMACE4}]

View File

@@ -16,7 +16,7 @@ set_property -dict {LOC AV5 IOSTANDARD LVDS_25} [get_ports fpga_refclk_n] ;# U7
create_clock -period 4.000 -name fpga_refclk [get_ports fpga_refclk_p]
# Source pin is in an HDIO bank, so it must be routed to an MMCM via a BUFG
set_property CLOCK_DEDICATED_ROUTE ANY_CMT_COLUMN [get_nets fpga_refclk_int fpga_refclk_bufg_inst_n_0]
set_property CLOCK_DEDICATED_ROUTE ANY_CMT_COLUMN [get_nets {fpga_refclk_int fpga_refclk_bufg_inst_n_0}]
# PLL sysref from U78
set_property -dict {LOC AP20 IOSTANDARD LVDS} [get_ports fpga_sysref_p] ;# U78.22 CLKout5_P

View File

@@ -25,6 +25,7 @@ TOPLEVEL = $(COCOTB_TOPLEVEL)
VERILOG_SOURCES += $(COCOTB_TOPLEVEL).sv
VERILOG_SOURCES += $(RTL_DIR)/$(DUT).sv
VERILOG_SOURCES += $(TAXI_SRC_DIR)/eth/rtl/us/taxi_eth_mac_25g_us.f
VERILOG_SOURCES += $(TAXI_SRC_DIR)/eth/rtl/us/taxi_eth_mac_100g_us.f
VERILOG_SOURCES += $(TAXI_SRC_DIR)/xfcp/rtl/taxi_xfcp_if_uart.f
VERILOG_SOURCES += $(TAXI_SRC_DIR)/xfcp/rtl/taxi_xfcp_switch.sv
VERILOG_SOURCES += $(TAXI_SRC_DIR)/xfcp/rtl/taxi_xfcp_mod_apb.f
@@ -51,7 +52,7 @@ export PARAM_GTY_CNT := $(shell echo $$(( 4 * $(PARAM_GTY_QUAD_CNT) )))
export PARAM_GTY_CLK_CNT := $(PARAM_GTY_QUAD_CNT)
export PARAM_CFG_LOW_LATENCY := "1'b1"
export PARAM_COMBINED_MAC_PCS := "1'b1"
export PARAM_MAC_DATA_W := "64"
export PARAM_MAC_DATA_W := "512"
ifeq ($(SIM), icarus)
PLUSARGS += -fst

View File

@@ -2,7 +2,7 @@
# SPDX-License-Identifier: MIT
"""
Copyright (c) 2020-2025 FPGA Ninja, LLC
Copyright (c) 2020-2026 FPGA Ninja, LLC
Authors:
- Alex Forencich
@@ -20,7 +20,10 @@ import cocotb
from cocotb.clock import Clock
from cocotb.triggers import RisingEdge, Combine
from cocotbext.eth import EthMacFrame, EthMac
from cocotbext.eth import GmiiFrame
from cocotbext.eth import XgmiiFrame
from cocotbext.axi import AxiStreamBus
from cocotbext.uart import UartSource, UartSink
try:
@@ -52,11 +55,41 @@ class TB:
for clk in dut.eth_gty_mgt_refclk_p:
cocotb.start_soon(Clock(clk, 6.206, units="ns").start())
for inst in dut.uut.gty_quad:
for ch in inst.mac_inst.ch:
has_cmac = False
for quad in dut.uut.gty_quad:
if dut.MAC_DATA_W.value == 512:
inst = quad.mac.mac_inst
has_cmac = True
mac = EthMac(
tx_clk=inst.ch[0].ch_inst.gt.gt_inst.gt_txoutclk,
tx_rst=inst.tx_rst_out,
tx_bus=AxiStreamBus.from_entity(inst.cmac.cmac_axis_tx),
# tx_ptp_time=inst.tx_ptp_ts_out,
# tx_ptp_ts=inst.tx_ptp_ts,
# tx_ptp_ts_tag=inst.tx_ptp_ts_tag,
# tx_ptp_ts_valid=inst.tx_ptp_ts_valid,
rx_clk=inst.ch[0].ch_inst.gt.gt_inst.gt_rxoutclk,
rx_rst=inst.rx_rst_out,
rx_bus=AxiStreamBus.from_entity(inst.cmac.cmac_axis_rx),
# rx_ptp_time=inst.rx_ptp_ts_out,
ifg=12, speed=100e9
)
self.qsfp_sources.append(mac.rx)
self.qsfp_sinks.append(mac.tx)
for ch in quad.mac.mac_inst.ch:
gt_inst = ch.ch_inst.gt.gt_inst
if ch.ch_inst.DATA_W.value == 64:
if has_cmac:
clk = 3.102
cocotb.start_soon(Clock(gt_inst.gt_txoutclk, clk, units="ns").start())
cocotb.start_soon(Clock(gt_inst.gt_rxoutclk, clk, units="ns").start())
continue
elif ch.ch_inst.DATA_W.value == 64:
if ch.ch_inst.CFG_LOW_LATENCY.value:
clk = 2.482
gbx_cfg = (66, [64, 65])
@@ -126,13 +159,9 @@ class TB:
await RisingEdge(self.dut.clk_125mhz)
async def mac_test(tb, source, sink):
async def mac_test(tb, source, sink, frame_type=GmiiFrame):
tb.log.info("Test MAC")
tb.log.info("Wait for block lock")
for k in range(1200):
await RisingEdge(tb.dut.clk_125mhz)
sink.clear()
tb.log.info("Multiple small packets")
@@ -142,7 +171,7 @@ async def mac_test(tb, source, sink):
pkts = [bytearray([(x+k) % 256 for x in range(60)]) for k in range(count)]
for p in pkts:
await source.send(XgmiiFrame.from_payload(p))
await source.send(frame_type.from_payload(p))
for k in range(count):
rx_frame = await sink.recv()
@@ -159,7 +188,7 @@ async def mac_test(tb, source, sink):
pkts = [bytearray([(x+k) % 256 for x in range(1514)]) for k in range(count)]
for p in pkts:
await source.send(XgmiiFrame.from_payload(p))
await source.send(frame_type.from_payload(p))
for k in range(count):
rx_frame = await sink.recv()
@@ -181,10 +210,18 @@ async def run_test(dut):
tests = []
tb.log.info("Wait for block lock")
for k in range(1200):
await RisingEdge(dut.clk_125mhz)
ft = XgmiiFrame
if dut.MAC_DATA_W.value == 512:
ft = EthMacFrame
for k in range(len(tb.qsfp_sources)):
tb.log.info("Start QSFP %d MAC loopback test", k)
tests.append(cocotb.start_soon(mac_test(tb, tb.qsfp_sources[k], tb.qsfp_sinks[k])))
tests.append(cocotb.start_soon(mac_test(tb, tb.qsfp_sources[k], tb.qsfp_sinks[k], ft)))
await Combine(*tests)
@@ -213,7 +250,7 @@ def process_f_files(files):
return list(lst.values())
@pytest.mark.parametrize("mac_data_w", [32, 64])
@pytest.mark.parametrize("mac_data_w", [32, 64, 512])
def test_fpga_core(request, mac_data_w):
dut = "fpga_core"
module = os.path.splitext(os.path.basename(__file__))[0]
@@ -223,6 +260,7 @@ def test_fpga_core(request, mac_data_w):
os.path.join(tests_dir, f"{toplevel}.sv"),
os.path.join(rtl_dir, f"{dut}.sv"),
os.path.join(taxi_src_dir, "eth", "rtl", "us", "taxi_eth_mac_25g_us.f"),
os.path.join(taxi_src_dir, "eth", "rtl", "us", "taxi_eth_mac_100g_us.f"),
os.path.join(taxi_src_dir, "xfcp", "rtl", "taxi_xfcp_if_uart.f"),
os.path.join(taxi_src_dir, "xfcp", "rtl", "taxi_xfcp_switch.sv"),
os.path.join(taxi_src_dir, "xfcp", "rtl", "taxi_xfcp_mod_apb.f"),