cndm_proto: Add 1000BASE-X support to AS02MC04 design

Signed-off-by: Alex Forencich <alex@alexforencich.com>
This commit is contained in:
Alex Forencich
2026-08-11 16:14:36 -07:00
parent 743ffa2f3e
commit 857425991d
10 changed files with 698 additions and 280 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 "64"

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,92 @@
# SPDX-License-Identifier: MIT
#
# Copyright (c) 2025 FPGA Ninja, LLC
#
# Authors:
# - Alex Forencich
#
# FPGA settings
FPGA_PART = xcku3p-ffvb676-1-e
FPGA_TOP = fpga
FPGA_ARCH = kintexuplus
RTL_DIR = ../rtl
LIB_DIR = ../lib
TAXI_SRC_DIR = $(LIB_DIR)/taxi/src
# Files for synthesis
SYN_FILES = $(RTL_DIR)/fpga.sv
SYN_FILES += $(RTL_DIR)/fpga_core.sv
SYN_FILES += $(TAXI_SRC_DIR)/cndm_proto/rtl/cndm_proto_pcie_us.f
SYN_FILES += $(TAXI_SRC_DIR)/eth/rtl/us/taxi_eth_mac_1g_basex_us.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
# XDC files
XDC_FILES += ../syn/fpga.xdc
XDC_FILES += ../syn/gpio.xdc
XDC_FILES += ../syn/sfp28.xdc
XDC_FILES += ../syn/pcie.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_1g_basex_us_gty_156.tcl
IP_TCL_FILES += ../ip/pcie4_uscale_plus_0.tcl
# Configuration
CONFIG_TCL_FILES = ./config.tcl
include ../common/vivado.mk
program: $(PROJECT).bit
echo "open_hw_manager" > 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 {$(PROJECT).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
$(PROJECT).mcs $(PROJECT).prm: $(PROJECT).bit
echo "write_cfgmem -force -format mcs -size 32 -interface SPIx4 -loadbit {up 0x0000000 $*.bit} -checksum -file $*.mcs" > generate_mcs.tcl
echo "exit" >> generate_mcs.tcl
vivado -nojournal -nolog -mode batch -source generate_mcs.tcl
mkdir -p rev
COUNT=100; \
while [ -e rev/$*_rev$$COUNT.bit ]; \
do COUNT=$$((COUNT+1)); done; \
COUNT=$$((COUNT-1)); \
for x in .mcs .prm; \
do cp $*$$x rev/$*_rev$$COUNT$$x; \
echo "Output: rev/$*_rev$$COUNT$$x"; done;
flash: $(PROJECT).mcs $(PROJECT).prm
echo "open_hw" > flash.tcl
echo "connect_hw_server" >> flash.tcl
echo "open_hw_target" >> flash.tcl
echo "current_hw_device [lindex [get_hw_devices] 0]" >> flash.tcl
echo "refresh_hw_device -update_hw_probes false [current_hw_device]" >> flash.tcl
echo "create_hw_cfgmem -hw_device [current_hw_device] [lindex [get_cfgmem_parts {mt25qu256-spi-x1_x2_x4}] 0]" >> flash.tcl
echo "current_hw_cfgmem -hw_device [current_hw_device] [get_property PROGRAM.HW_CFGMEM [current_hw_device]]" >> flash.tcl
echo "set_property PROGRAM.FILES [list \"$(PROJECT).mcs\"] [current_hw_cfgmem]" >> flash.tcl
echo "set_property PROGRAM.PRM_FILES [list \"$(PROJECT).prm\"] [current_hw_cfgmem]" >> flash.tcl
echo "set_property PROGRAM.ERASE 1 [current_hw_cfgmem]" >> flash.tcl
echo "set_property PROGRAM.CFG_PROGRAM 1 [current_hw_cfgmem]" >> flash.tcl
echo "set_property PROGRAM.VERIFY 1 [current_hw_cfgmem]" >> flash.tcl
echo "set_property PROGRAM.CHECKSUM 0 [current_hw_cfgmem]" >> flash.tcl
echo "set_property PROGRAM.ADDRESS_RANGE {use_file} [current_hw_cfgmem]" >> flash.tcl
echo "set_property PROGRAM.UNUSED_PIN_TERMINATION {pull-none} [current_hw_cfgmem]" >> flash.tcl
echo "create_hw_bitstream -hw_device [current_hw_device] [get_property PROGRAM.HW_CFGMEM_BITFILE [current_hw_device]]" >> flash.tcl
echo "program_hw_devices [current_hw_device]" >> flash.tcl
echo "refresh_hw_device [current_hw_device]" >> flash.tcl
echo "program_hw_cfgmem -hw_cfgmem [current_hw_cfgmem]" >> flash.tcl
echo "boot_hw_device [current_hw_device]" >> flash.tcl
echo "exit" >> flash.tcl
vivado -nojournal -nolog -mode batch -source flash.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 "16"
# 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

@@ -23,7 +23,7 @@ module fpga #
parameter string VENDOR = "XILINX",
// device family
parameter string FAMILY = "kintexuplus",
// 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

View File

@@ -24,7 +24,7 @@ module fpga_core #
// device family
parameter string FAMILY = "kintexuplus",
parameter RQ_SEQ_NUM_W = 6,
// 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
@@ -207,270 +207,539 @@ taxi_apb_if #(
)
gt_apb_ctrl();
taxi_eth_mac_25g_us #(
.SIM(SIM),
.VENDOR(VENDOR),
.FAMILY(FAMILY),
if (MAC_DATA_W == 16) begin : sfp_mac
.CNT(2),
taxi_eth_mac_1g_basex_us #(
.SIM(SIM),
.VENDOR(VENDOR),
.FAMILY(FAMILY),
// GT config
.CFG_LOW_LATENCY(CFG_LOW_LATENCY),
.CNT(2),
// GT type
.GT_TYPE("GTY"),
// GT config
.CFG_LOW_LATENCY(CFG_LOW_LATENCY),
// GT parameters
.GT_TX_POLARITY('0),
.GT_RX_POLARITY('0),
// GT type
.GT_TYPE("GTY"),
// MAC/PHY config
.COMBINED_MAC_PCS(COMBINED_MAC_PCS),
.DATA_W(axis_sfp_tx[0].DATA_W),
.USXGMII_EN(COMBINED_MAC_PCS && axis_sfp_tx[0].DATA_W == 32),
.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'b0)
)
sfp_mac_inst (
.xcvr_ctrl_clk(clk_125mhz),
.xcvr_ctrl_rst(sfp_rst),
// GT parameters
.GT_TX_POLARITY('0),
.GT_RX_POLARITY('0),
/*
* Transceiver control
*/
.s_apb_ctrl(gt_apb_ctrl),
// MAC/PHY config
.COMBINED_MAC_PCS(COMBINED_MAC_PCS),
.SGMII_EN(1'b1),
.AN_EN(1'b1),
.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'b0)
)
sfp_mac_inst (
.xcvr_ctrl_clk(clk_125mhz),
.xcvr_ctrl_rst(sfp_rst),
/*
* Common
*/
.xcvr_gtpowergood_out(sfp_gtpowergood),
.xcvr_gtrefclk00_in(sfp_mgt_refclk),
.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(sfp_mgt_refclk),
.xcvr_qpll1pd_in(1'b0),
.xcvr_qpll1reset_in(1'b0),
.xcvr_qpll1pcierate_in(3'd0),
.xcvr_qpll1lock_out(),
.xcvr_qpll1clk_out(),
.xcvr_qpll1refclk_out(),
/*
* Transceiver control
*/
.s_apb_ctrl(gt_apb_ctrl),
/*
* Serial data
*/
.xcvr_txp(sfp_tx_p),
.xcvr_txn(sfp_tx_n),
.xcvr_rxp(sfp_rx_p),
.xcvr_rxn(sfp_rx_n),
/*
* Common
*/
.xcvr_gtpowergood_out(sfp_gtpowergood),
.xcvr_gtrefclk00_in(sfp_mgt_refclk),
.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(sfp_mgt_refclk),
.xcvr_qpll1pd_in(1'b0),
.xcvr_qpll1reset_in(1'b0),
.xcvr_qpll1pcierate_in(3'd0),
.xcvr_qpll1lock_out(),
.xcvr_qpll1clk_out(),
.xcvr_qpll1refclk_out(),
/*
* MAC clocks
*/
.rx_clk(sfp_rx_clk),
.rx_rst_in('{2{1'b0}}),
.rx_rst_out(sfp_rx_rst),
.tx_clk(sfp_tx_clk),
.tx_rst_in('{2{1'b0}}),
.tx_rst_out(sfp_tx_rst),
/*
* Serial data
*/
.xcvr_txp(sfp_tx_p),
.xcvr_txn(sfp_tx_n),
.xcvr_rxp(sfp_rx_p),
.xcvr_rxn(sfp_rx_n),
/*
* Transmit interface (AXI stream)
*/
.s_axis_tx(axis_sfp_tx),
.m_axis_tx_cpl(axis_sfp_tx_cpl),
/*
* MAC clocks
*/
.rx_clk(sfp_rx_clk),
.rx_rst_in('{2{1'b0}}),
.rx_rst_out(sfp_rx_rst),
.tx_clk(sfp_tx_clk),
.tx_rst_in('{2{1'b0}}),
.tx_rst_out(sfp_tx_rst),
/*
* Receive interface (AXI stream)
*/
.m_axis_rx(axis_sfp_rx),
/*
* Transmit interface (AXI stream)
*/
.s_axis_tx(axis_sfp_tx),
.m_axis_tx_cpl(axis_sfp_tx_cpl),
/*
* USXGMII autonegotiation
*/
.an_en('{2{1'b1}}),
.an_restart('{2{1'b0}}),
.an_speedup('{2{1'b0}}),
.an_timeout_en('{2{1'b1}}),
.an_usxgmii_en('{2{1'b0}}),
.an_usxgmii_auto('{2{1'b1}}),
.an_intr(),
.an_running(),
.an_complete(),
.an_timeout(),
.an_usxgmii_mode(),
.an_adv_ability_usxgmii('{2{16'h1601}}),
.an_lp_adv_ability(),
.an_lp_usxgmii_link(),
.an_lp_usxgmii_speed(),
.an_res_full_duplex(),
/*
* Receive interface (AXI stream)
*/
.m_axis_rx(axis_sfp_rx),
/*
* PTP clock
*/
.ptp_clk(1'b0),
.ptp_rst(1'b0),
.ptp_sample_clk(1'b0),
.ptp_td_sdi(1'b0),
.tx_ptp_ts_in('{2{'0}}),
.tx_ptp_ts_out(),
.tx_ptp_ts_step_out(),
.tx_ptp_locked(),
.rx_ptp_ts_in('{2{'0}}),
.rx_ptp_ts_out(),
.rx_ptp_ts_step_out(),
.rx_ptp_locked(),
/*
* Autonegotiation
*/
.an_en('{2{1'b1}}),
.an_restart('{2{1'b0}}),
.an_speedup('{2{1'b0}}),
.an_timeout_en('{2{1'b1}}),
.an_sgmii_en('{2{1'b0}}),
.an_sgmii_auto('{2{1'b1}}),
.an_intr(),
.an_running(),
.an_complete(),
.an_timeout(),
.an_sgmii_mode(),
.an_adv_ability_basex('{2{16'h0020}}),
.an_adv_ability_sgmii('{2{16'h0001}}),
.an_lp_adv_ability(),
.an_lp_remote_fault(),
.an_lp_sgmii_link(),
.an_lp_sgmii_speed(),
.an_res_full_duplex(),
.an_res_tx_pause(),
.an_res_rx_pause(),
/*
* Link-level Flow Control (LFC) (IEEE 802.3 annex 31B PAUSE)
*/
.tx_lfc_req('{2{1'b0}}),
.tx_lfc_resend('{2{1'b0}}),
.rx_lfc_en('{2{1'b0}}),
.rx_lfc_req(),
.rx_lfc_ack('{2{1'b0}}),
/*
* PTP clock
*/
.ptp_clk(1'b0),
.ptp_rst(1'b0),
.ptp_sample_clk(1'b0),
.ptp_td_sdi(1'b0),
.tx_ptp_ts_in('{2{'0}}),
.tx_ptp_ts_out(),
.tx_ptp_ts_step_out(),
.tx_ptp_locked(),
.rx_ptp_ts_in('{2{'0}}),
.rx_ptp_ts_out(),
.rx_ptp_ts_step_out(),
.rx_ptp_locked(),
/*
* Priority Flow Control (PFC) (IEEE 802.3 annex 31D PFC)
*/
.tx_pfc_req('{2{'0}}),
.tx_pfc_resend('{2{1'b0}}),
.rx_pfc_en('{2{'0}}),
.rx_pfc_req(),
.rx_pfc_ack('{2{'0}}),
/*
* Link-level Flow Control (LFC) (IEEE 802.3 annex 31B PAUSE)
*/
.tx_lfc_req('{2{1'b0}}),
.tx_lfc_resend('{2{1'b0}}),
.rx_lfc_en('{2{1'b0}}),
.rx_lfc_req(),
.rx_lfc_ack('{2{1'b0}}),
/*
* Pause interface
*/
.tx_lfc_pause_en('{2{1'b0}}),
.tx_pause_req('{2{1'b0}}),
.tx_pause_ack(),
/*
* Priority Flow Control (PFC) (IEEE 802.3 annex 31D PFC)
*/
.tx_pfc_req('{2{'0}}),
.tx_pfc_resend('{2{1'b0}}),
.rx_pfc_en('{2{'0}}),
.rx_pfc_req(),
.rx_pfc_ack('{2{'0}}),
/*
* Statistics
*/
.stat_clk(clk_125mhz),
.stat_rst(rst_125mhz),
.m_axis_stat(axis_sfp_stat),
/*
* Pause interface
*/
.tx_lfc_pause_en('{2{1'b0}}),
.tx_pause_req('{2{1'b0}}),
.tx_pause_ack(),
/*
* 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(sfp_rx_status),
.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('{2{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(),
/*
* Statistics
*/
.stat_clk(clk_125mhz),
.stat_rst(rst_125mhz),
.m_axis_stat(axis_sfp_stat),
/*
* Configuration
*/
.cfg_tx_pad_en('{2{1'b1}}),
.cfg_tx_min_pkt_len('{2{8'd60-1}}),
.cfg_tx_max_pkt_len('{2{16'd9218-1}}),
.cfg_tx_ifg('{2{8'd12}}),
.cfg_tx_enable('{2{1'b1}}),
.cfg_rx_max_pkt_len('{2{16'd9218-1}}),
.cfg_rx_enable('{2{1'b1}}),
.cfg_tx_prbs31_enable('{2{1'b0}}),
.cfg_rx_prbs31_enable('{2{1'b0}}),
.cfg_mcf_rx_eth_dst_mcast('{2{48'h01_80_C2_00_00_01}}),
.cfg_mcf_rx_check_eth_dst_mcast('{2{1'b1}}),
.cfg_mcf_rx_eth_dst_ucast('{2{48'd0}}),
.cfg_mcf_rx_check_eth_dst_ucast('{2{1'b0}}),
.cfg_mcf_rx_eth_src('{2{48'd0}}),
.cfg_mcf_rx_check_eth_src('{2{1'b0}}),
.cfg_mcf_rx_eth_type('{2{16'h8808}}),
.cfg_mcf_rx_opcode_lfc('{2{16'h0001}}),
.cfg_mcf_rx_check_opcode_lfc('{2{1'b1}}),
.cfg_mcf_rx_opcode_pfc('{2{16'h0101}}),
.cfg_mcf_rx_check_opcode_pfc('{2{1'b1}}),
.cfg_mcf_rx_forward('{2{1'b0}}),
.cfg_mcf_rx_enable('{2{1'b0}}),
.cfg_tx_lfc_eth_dst('{2{48'h01_80_C2_00_00_01}}),
.cfg_tx_lfc_eth_src('{2{48'h80_23_31_43_54_4C}}),
.cfg_tx_lfc_eth_type('{2{16'h8808}}),
.cfg_tx_lfc_opcode('{2{16'h0001}}),
.cfg_tx_lfc_en('{2{1'b0}}),
.cfg_tx_lfc_quanta('{2{16'hffff}}),
.cfg_tx_lfc_refresh('{2{16'h7fff}}),
.cfg_tx_pfc_eth_dst('{2{48'h01_80_C2_00_00_01}}),
.cfg_tx_pfc_eth_src('{2{48'h80_23_31_43_54_4C}}),
.cfg_tx_pfc_eth_type('{2{16'h8808}}),
.cfg_tx_pfc_opcode('{2{16'h0101}}),
.cfg_tx_pfc_en('{2{1'b0}}),
.cfg_tx_pfc_quanta('{2{'{8{16'hffff}}}}),
.cfg_tx_pfc_refresh('{2{'{8{16'h7fff}}}}),
.cfg_rx_lfc_opcode('{2{16'h0001}}),
.cfg_rx_lfc_en('{2{1'b0}}),
.cfg_rx_pfc_opcode('{2{16'h0101}}),
.cfg_rx_pfc_en('{2{1'b0}})
);
/*
* 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(sfp_rx_status),
.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('{2{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('{2{1'b1}}),
.cfg_tx_min_pkt_len('{2{8'd60-1}}),
.cfg_tx_max_pkt_len('{2{16'd9218-1}}),
.cfg_tx_ifg('{2{8'd12}}),
.cfg_tx_enable('{2{1'b1}}),
.cfg_rx_max_pkt_len('{2{16'd9218-1}}),
.cfg_rx_enable('{2{1'b1}}),
.cfg_tx_prbs31_enable('{2{1'b0}}),
.cfg_rx_prbs31_enable('{2{1'b0}}),
.cfg_mcf_rx_eth_dst_mcast('{2{48'h01_80_C2_00_00_01}}),
.cfg_mcf_rx_check_eth_dst_mcast('{2{1'b1}}),
.cfg_mcf_rx_eth_dst_ucast('{2{48'd0}}),
.cfg_mcf_rx_check_eth_dst_ucast('{2{1'b0}}),
.cfg_mcf_rx_eth_src('{2{48'd0}}),
.cfg_mcf_rx_check_eth_src('{2{1'b0}}),
.cfg_mcf_rx_eth_type('{2{16'h8808}}),
.cfg_mcf_rx_opcode_lfc('{2{16'h0001}}),
.cfg_mcf_rx_check_opcode_lfc('{2{1'b1}}),
.cfg_mcf_rx_opcode_pfc('{2{16'h0101}}),
.cfg_mcf_rx_check_opcode_pfc('{2{1'b1}}),
.cfg_mcf_rx_forward('{2{1'b0}}),
.cfg_mcf_rx_enable('{2{1'b0}}),
.cfg_tx_lfc_eth_dst('{2{48'h01_80_C2_00_00_01}}),
.cfg_tx_lfc_eth_src('{2{48'h80_23_31_43_54_4C}}),
.cfg_tx_lfc_eth_type('{2{16'h8808}}),
.cfg_tx_lfc_opcode('{2{16'h0001}}),
.cfg_tx_lfc_en('{2{1'b0}}),
.cfg_tx_lfc_quanta('{2{16'hffff}}),
.cfg_tx_lfc_refresh('{2{16'h7fff}}),
.cfg_tx_pfc_eth_dst('{2{48'h01_80_C2_00_00_01}}),
.cfg_tx_pfc_eth_src('{2{48'h80_23_31_43_54_4C}}),
.cfg_tx_pfc_eth_type('{2{16'h8808}}),
.cfg_tx_pfc_opcode('{2{16'h0101}}),
.cfg_tx_pfc_en('{2{1'b0}}),
.cfg_tx_pfc_quanta('{2{'{8{16'hffff}}}}),
.cfg_tx_pfc_refresh('{2{'{8{16'h7fff}}}}),
.cfg_rx_lfc_opcode('{2{16'h0001}}),
.cfg_rx_lfc_en('{2{1'b0}}),
.cfg_rx_pfc_opcode('{2{16'h0101}}),
.cfg_rx_pfc_en('{2{1'b0}})
);
end else begin : sfp_mac
taxi_eth_mac_25g_us #(
.SIM(SIM),
.VENDOR(VENDOR),
.FAMILY(FAMILY),
.CNT(2),
// GT config
.CFG_LOW_LATENCY(CFG_LOW_LATENCY),
// GT type
.GT_TYPE("GTY"),
// GT parameters
.GT_TX_POLARITY('0),
.GT_RX_POLARITY('0),
// MAC/PHY config
.COMBINED_MAC_PCS(COMBINED_MAC_PCS),
.DATA_W(axis_sfp_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'b0)
)
sfp_mac_inst (
.xcvr_ctrl_clk(clk_125mhz),
.xcvr_ctrl_rst(sfp_rst),
/*
* Transceiver control
*/
.s_apb_ctrl(gt_apb_ctrl),
/*
* Common
*/
.xcvr_gtpowergood_out(sfp_gtpowergood),
.xcvr_gtrefclk00_in(sfp_mgt_refclk),
.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(sfp_mgt_refclk),
.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(sfp_tx_p),
.xcvr_txn(sfp_tx_n),
.xcvr_rxp(sfp_rx_p),
.xcvr_rxn(sfp_rx_n),
/*
* MAC clocks
*/
.rx_clk(sfp_rx_clk),
.rx_rst_in('{2{1'b0}}),
.rx_rst_out(sfp_rx_rst),
.tx_clk(sfp_tx_clk),
.tx_rst_in('{2{1'b0}}),
.tx_rst_out(sfp_tx_rst),
/*
* Transmit interface (AXI stream)
*/
.s_axis_tx(axis_sfp_tx),
.m_axis_tx_cpl(axis_sfp_tx_cpl),
/*
* Receive interface (AXI stream)
*/
.m_axis_rx(axis_sfp_rx),
/*
* USXGMII autonegotiation
*/
.an_en('{2{1'b1}}),
.an_restart('{2{1'b0}}),
.an_speedup('{2{1'b0}}),
.an_timeout_en('{2{1'b1}}),
.an_usxgmii_en('{2{1'b0}}),
.an_usxgmii_auto('{2{1'b1}}),
.an_intr(),
.an_running(),
.an_complete(),
.an_timeout(),
.an_usxgmii_mode(),
.an_adv_ability_usxgmii('{2{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('{2{'0}}),
.tx_ptp_ts_out(),
.tx_ptp_ts_step_out(),
.tx_ptp_locked(),
.rx_ptp_ts_in('{2{'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('{2{1'b0}}),
.tx_lfc_resend('{2{1'b0}}),
.rx_lfc_en('{2{1'b0}}),
.rx_lfc_req(),
.rx_lfc_ack('{2{1'b0}}),
/*
* Priority Flow Control (PFC) (IEEE 802.3 annex 31D PFC)
*/
.tx_pfc_req('{2{'0}}),
.tx_pfc_resend('{2{1'b0}}),
.rx_pfc_en('{2{'0}}),
.rx_pfc_req(),
.rx_pfc_ack('{2{'0}}),
/*
* Pause interface
*/
.tx_lfc_pause_en('{2{1'b0}}),
.tx_pause_req('{2{1'b0}}),
.tx_pause_ack(),
/*
* Statistics
*/
.stat_clk(clk_125mhz),
.stat_rst(rst_125mhz),
.m_axis_stat(axis_sfp_stat),
/*
* 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(sfp_rx_status),
.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('{2{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('{2{1'b1}}),
.cfg_tx_min_pkt_len('{2{8'd60-1}}),
.cfg_tx_max_pkt_len('{2{16'd9218-1}}),
.cfg_tx_ifg('{2{8'd12}}),
.cfg_tx_enable('{2{1'b1}}),
.cfg_rx_max_pkt_len('{2{16'd9218-1}}),
.cfg_rx_enable('{2{1'b1}}),
.cfg_tx_prbs31_enable('{2{1'b0}}),
.cfg_rx_prbs31_enable('{2{1'b0}}),
.cfg_mcf_rx_eth_dst_mcast('{2{48'h01_80_C2_00_00_01}}),
.cfg_mcf_rx_check_eth_dst_mcast('{2{1'b1}}),
.cfg_mcf_rx_eth_dst_ucast('{2{48'd0}}),
.cfg_mcf_rx_check_eth_dst_ucast('{2{1'b0}}),
.cfg_mcf_rx_eth_src('{2{48'd0}}),
.cfg_mcf_rx_check_eth_src('{2{1'b0}}),
.cfg_mcf_rx_eth_type('{2{16'h8808}}),
.cfg_mcf_rx_opcode_lfc('{2{16'h0001}}),
.cfg_mcf_rx_check_opcode_lfc('{2{1'b1}}),
.cfg_mcf_rx_opcode_pfc('{2{16'h0101}}),
.cfg_mcf_rx_check_opcode_pfc('{2{1'b1}}),
.cfg_mcf_rx_forward('{2{1'b0}}),
.cfg_mcf_rx_enable('{2{1'b0}}),
.cfg_tx_lfc_eth_dst('{2{48'h01_80_C2_00_00_01}}),
.cfg_tx_lfc_eth_src('{2{48'h80_23_31_43_54_4C}}),
.cfg_tx_lfc_eth_type('{2{16'h8808}}),
.cfg_tx_lfc_opcode('{2{16'h0001}}),
.cfg_tx_lfc_en('{2{1'b0}}),
.cfg_tx_lfc_quanta('{2{16'hffff}}),
.cfg_tx_lfc_refresh('{2{16'h7fff}}),
.cfg_tx_pfc_eth_dst('{2{48'h01_80_C2_00_00_01}}),
.cfg_tx_pfc_eth_src('{2{48'h80_23_31_43_54_4C}}),
.cfg_tx_pfc_eth_type('{2{16'h8808}}),
.cfg_tx_pfc_opcode('{2{16'h0101}}),
.cfg_tx_pfc_en('{2{1'b0}}),
.cfg_tx_pfc_quanta('{2{'{8{16'hffff}}}}),
.cfg_tx_pfc_refresh('{2{'{8{16'h7fff}}}}),
.cfg_rx_lfc_opcode('{2{16'h0001}}),
.cfg_rx_lfc_en('{2{1'b0}}),
.cfg_rx_pfc_opcode('{2{16'h0101}}),
.cfg_rx_pfc_en('{2{1'b0}})
);
end
cndm_proto_pcie_us #(
.SIM(SIM),
.VENDOR(VENDOR),
.FAMILY(FAMILY),
.PORTS(2),
.PORTS($size(axis_sfp_tx)),
.RQ_SEQ_NUM_W(RQ_SEQ_NUM_W),
.BAR0_APERTURE(24)
)

View File

@@ -26,6 +26,7 @@ VERILOG_SOURCES += $(COCOTB_TOPLEVEL).sv
VERILOG_SOURCES += $(RTL_DIR)/$(DUT).sv
VERILOG_SOURCES += $(TAXI_SRC_DIR)/cndm_proto/rtl/cndm_proto_pcie_us.f
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_1g_basex_us.f
VERILOG_SOURCES += $(TAXI_SRC_DIR)/axis/rtl/taxi_axis_async_fifo.f
VERILOG_SOURCES += $(TAXI_SRC_DIR)/sync/rtl/taxi_sync_reset.sv
VERILOG_SOURCES += $(TAXI_SRC_DIR)/sync/rtl/taxi_sync_signal.sv

View File

@@ -0,0 +1 @@
../../lib/taxi/src/eth/tb/basex.py

View File

@@ -27,12 +27,14 @@ from cocotbext.pcie.xilinx.us import UltraScalePlusPcieDevice
try:
from baser import BaseRSerdesSource, BaseRSerdesSink
from basex import BaseXSerdesSource, BaseXSerdesSink
import cndm_proto
except ImportError:
# attempt import from current directory
sys.path.insert(0, os.path.join(os.path.dirname(__file__)))
try:
from baser import BaseRSerdesSource, BaseRSerdesSink
from basex import BaseXSerdesSource, BaseXSerdesSink
import cndm_proto
finally:
del sys.path[0]
@@ -280,47 +282,77 @@ class TB:
self.sfp_sources = []
self.sfp_sinks = []
for ch in dut.uut.sfp_mac_inst.ch:
for ch in dut.uut.sfp_mac.sfp_mac_inst.ch:
gt_inst = ch.ch_inst.gt.gt_inst
if ch.ch_inst.DATA_W.value == 64:
if dut.MAC_DATA_W.value == 16:
if ch.ch_inst.CFG_LOW_LATENCY.value:
clk = 2.482
gbx_cfg = (66, [64, 65])
else:
clk = 2.56
clk = 16
gbx_cfg = None
else:
clk = 16
gbx_cfg = None
cocotb.start_soon(Clock(gt_inst.tx_clk, clk, units="ns").start())
cocotb.start_soon(Clock(gt_inst.rx_clk, clk, units="ns").start())
self.sfp_sources.append(BaseXSerdesSource(
data=gt_inst.serdes_rx_data,
data_k=gt_inst.serdes_rx_data_k,
data_valid=gt_inst.serdes_rx_data_valid,
clock=gt_inst.rx_clk,
enc_8b10b=False,
gbx_cfg=gbx_cfg
))
self.sfp_sinks.append(BaseXSerdesSink(
data=gt_inst.serdes_tx_data,
data_k=gt_inst.serdes_tx_data_k,
data_valid=gt_inst.serdes_tx_data_valid,
gbx_sync=gt_inst.serdes_tx_gbx_sync,
clock=gt_inst.tx_clk,
dec_8b10b=False,
gbx_cfg=gbx_cfg
))
else:
if ch.ch_inst.CFG_LOW_LATENCY.value:
clk = 3.102
gbx_cfg = (66, [64, 65])
if ch.ch_inst.DATA_W.value == 64:
if ch.ch_inst.CFG_LOW_LATENCY.value:
clk = 2.482
gbx_cfg = (66, [64, 65])
else:
clk = 2.56
gbx_cfg = None
else:
clk = 3.2
gbx_cfg = None
if ch.ch_inst.CFG_LOW_LATENCY.value:
clk = 3.102
gbx_cfg = (66, [64, 65])
else:
clk = 3.2
gbx_cfg = None
cocotb.start_soon(Clock(gt_inst.tx_clk, clk, units="ns").start())
cocotb.start_soon(Clock(gt_inst.rx_clk, clk, units="ns").start())
cocotb.start_soon(Clock(gt_inst.tx_clk, clk, units="ns").start())
cocotb.start_soon(Clock(gt_inst.rx_clk, clk, units="ns").start())
self.sfp_sources.append(BaseRSerdesSource(
data=gt_inst.serdes_rx_data,
data_valid=gt_inst.serdes_rx_data_valid,
hdr=gt_inst.serdes_rx_hdr,
hdr_valid=gt_inst.serdes_rx_hdr_valid,
clock=gt_inst.rx_clk,
slip=gt_inst.serdes_rx_bitslip,
reverse=True,
gbx_cfg=gbx_cfg
))
self.sfp_sinks.append(BaseRSerdesSink(
data=gt_inst.serdes_tx_data,
data_valid=gt_inst.serdes_tx_data_valid,
hdr=gt_inst.serdes_tx_hdr,
hdr_valid=gt_inst.serdes_tx_hdr_valid,
gbx_sync=gt_inst.serdes_tx_gbx_sync,
clock=gt_inst.tx_clk,
reverse=True,
gbx_cfg=gbx_cfg
))
self.sfp_sources.append(BaseRSerdesSource(
data=gt_inst.serdes_rx_data,
data_valid=gt_inst.serdes_rx_data_valid,
hdr=gt_inst.serdes_rx_hdr,
hdr_valid=gt_inst.serdes_rx_hdr_valid,
clock=gt_inst.rx_clk,
slip=gt_inst.serdes_rx_bitslip,
reverse=True,
gbx_cfg=gbx_cfg
))
self.sfp_sinks.append(BaseRSerdesSink(
data=gt_inst.serdes_tx_data,
data_valid=gt_inst.serdes_tx_data_valid,
hdr=gt_inst.serdes_tx_hdr,
hdr_valid=gt_inst.serdes_tx_hdr_valid,
gbx_sync=gt_inst.serdes_tx_gbx_sync,
clock=gt_inst.tx_clk,
reverse=True,
gbx_cfg=gbx_cfg
))
dut.sfp_npres.setimmediatevalue(0)
dut.sfp_tx_fault.setimmediatevalue(0)
@@ -463,7 +495,7 @@ def process_f_files(files):
return list(lst.values())
@pytest.mark.parametrize("mac_data_w", [32, 64])
@pytest.mark.parametrize("mac_data_w", [16, 32, 64])
def test_fpga_core(request, mac_data_w):
dut = "fpga_core"
module = os.path.splitext(os.path.basename(__file__))[0]
@@ -474,6 +506,7 @@ def test_fpga_core(request, mac_data_w):
os.path.join(rtl_dir, f"{dut}.sv"),
os.path.join(taxi_src_dir, "cndm_proto", "rtl", "cndm_proto_pcie_us.f"),
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_1g_basex_us.f"),
os.path.join(taxi_src_dir, "axis", "rtl", "taxi_axis_async_fifo.f"),
os.path.join(taxi_src_dir, "sync", "rtl", "taxi_sync_reset.sv"),
os.path.join(taxi_src_dir, "sync", "rtl", "taxi_sync_signal.sv"),

View File

@@ -26,7 +26,7 @@ module test_fpga_core #
parameter AXIS_PCIE_RQ_USER_W = AXIS_PCIE_DATA_W < 512 ? 62 : 137,
parameter AXIS_PCIE_CQ_USER_W = AXIS_PCIE_DATA_W < 512 ? 85 : 183,
parameter AXIS_PCIE_CC_USER_W = AXIS_PCIE_DATA_W < 512 ? 33 : 81,
// 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
@@ -137,7 +137,7 @@ fpga_core #(
.VENDOR(VENDOR),
.FAMILY(FAMILY),
.RQ_SEQ_NUM_W(RQ_SEQ_NUM_W),
// 10G/25G MAC configuration
// MAC configuration
.CFG_LOW_LATENCY(CFG_LOW_LATENCY),
.COMBINED_MAC_PCS(COMBINED_MAC_PCS),
.MAC_DATA_W(MAC_DATA_W)