diff --git a/src/eth/example/NT200A02/fpga/fpga_NT200A01/Makefile b/src/eth/example/NT200A02/fpga/fpga_NT200A01/Makefile index e1302a5..f0c362b 100644 --- a/src/eth/example/NT200A02/fpga/fpga_NT200A01/Makefile +++ b/src/eth/example/NT200A02/fpga/fpga_NT200A01/Makefile @@ -19,7 +19,7 @@ TAXI_SRC_DIR = $(LIB_DIR)/taxi/src SYN_FILES = $(RTL_DIR)/fpga_nt200a01.sv SYN_FILES += $(RTL_DIR)/fpga_core.sv SYN_FILES += $(RTL_DIR)/../pll/si5340_i2c_init.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)/lss/rtl/taxi_i2c_master.sv SYN_FILES += $(TAXI_SRC_DIR)/axis/rtl/taxi_axis_async_fifo.f SYN_FILES += $(TAXI_SRC_DIR)/sync/rtl/taxi_sync_reset.sv @@ -29,13 +29,15 @@ SYN_FILES += $(TAXI_SRC_DIR)/sync/rtl/taxi_sync_signal.sv XDC_FILES += ../syn/NT200A01/fpga.xdc XDC_FILES += ../syn/NT200A01/gpio.xdc XDC_FILES += ../syn/NT200A01/qsfp.xdc +XDC_FILES += ../syn/NT200A01/eth_cmac.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_322.tcl +IP_TCL_FILES += $(TAXI_SRC_DIR)/eth/rtl/us/taxi_eth_mac_100g_us_cmace3.tcl +IP_TCL_FILES += $(TAXI_SRC_DIR)/eth/rtl/us/taxi_eth_mac_100g_us_gty_322.tcl # Configuration CONFIG_TCL_FILES = config.tcl diff --git a/src/eth/example/NT200A02/fpga/fpga_NT200A01/config.tcl b/src/eth/example/NT200A02/fpga/fpga_NT200A01/config.tcl index d3508a4..4bd9a8c 100644 --- a/src/eth/example/NT200A02/fpga/fpga_NT200A01/config.tcl +++ b/src/eth/example/NT200A02/fpga/fpga_NT200A01/config.tcl @@ -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 {} diff --git a/src/eth/example/NT200A02/fpga/fpga_NT200A01_10g/config.tcl b/src/eth/example/NT200A02/fpga/fpga_NT200A01_10g/config.tcl index cd72d45..4359e24 100644 --- a/src/eth/example/NT200A02/fpga/fpga_NT200A01_10g/config.tcl +++ b/src/eth/example/NT200A02/fpga/fpga_NT200A01_10g/config.tcl @@ -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" diff --git a/src/eth/example/NT200A02/fpga/fpga_NT200A01_25g/Makefile b/src/eth/example/NT200A02/fpga/fpga_NT200A01_25g/Makefile new file mode 100644 index 0000000..e1302a5 --- /dev/null +++ b/src/eth/example/NT200A02/fpga/fpga_NT200A01_25g/Makefile @@ -0,0 +1,159 @@ +# SPDX-License-Identifier: MIT +# +# Copyright (c) 2025 FPGA Ninja, LLC +# +# Authors: +# - Alex Forencich +# + +# FPGA settings +FPGA_PART = xcvu095-ffva2104-2-e +FPGA_TOP = fpga +FPGA_ARCH = virtexu + +RTL_DIR = ../rtl +LIB_DIR = ../lib +TAXI_SRC_DIR = $(LIB_DIR)/taxi/src + +# Files for synthesis +SYN_FILES = $(RTL_DIR)/fpga_nt200a01.sv +SYN_FILES += $(RTL_DIR)/fpga_core.sv +SYN_FILES += $(RTL_DIR)/../pll/si5340_i2c_init.sv +SYN_FILES += $(TAXI_SRC_DIR)/eth/rtl/us/taxi_eth_mac_25g_us.f +SYN_FILES += $(TAXI_SRC_DIR)/lss/rtl/taxi_i2c_master.sv +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/NT200A01/fpga.xdc +XDC_FILES += ../syn/NT200A01/gpio.xdc +XDC_FILES += ../syn/NT200A01/qsfp.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_322.tcl + +# Configuration +CONFIG_TCL_FILES = config.tcl + +include ../common/vivado.mk + +%_fallback.bit: %.bit + echo "open_project $*.xpr" > generate_fallback_bit.tcl + echo "open_run impl_1" >> generate_fallback_bit.tcl + echo "startgroup" >> generate_fallback_bit.tcl + echo "set_property BITSTREAM.CONFIG.SPI_32BIT_ADDR NO [current_design]" >> generate_fallback_bit.tcl + echo "endgroup" >> generate_fallback_bit.tcl + echo "write_bitstream -verbose -force $*_fallback.bit" >> generate_fallback_bit.tcl + echo "undo" >> generate_fallback_bit.tcl + echo "exit" >> generate_fallback_bit.tcl + vivado -nojournal -nolog -mode batch -source generate_fallback_bit.tcl + mkdir -p rev + EXT=bit; COUNT=100; \ + while [ -e rev/$*_rev$$COUNT.$$EXT ]; \ + do COUNT=$$((COUNT+1)); done; \ + COUNT=$$((COUNT-1)); \ + cp $@ rev/$*_fallback_rev$$COUNT.$$EXT; \ + echo "Output: rev/$*_fallback_rev$$COUNT.$$EXT"; + +program: $(FPGA_TOP).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 {$(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 + +%.mcs %.prm: %.bit + echo "write_cfgmem -force -format mcs -size 64 -interface SPIx4 -loadbit {up 0x00000000 $*.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; + +%_fallback.mcs %_fallback.prm: %_fallback.bit + echo "write_cfgmem -force -format mcs -size 64 -interface SPIx4 -loadbit {up 0x03000000 $*_fallback.bit} -checksum -file $*_fallback.mcs" > generate_fallback_mcs.tcl + echo "exit" >> generate_fallback_mcs.tcl + vivado -nojournal -nolog -mode batch -source generate_fallback_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 $*_fallback$$x rev/$*_fallback_rev$$COUNT$$x; \ + echo "Output: rev/$*_fallback_rev$$COUNT$$x"; done; + +%_full.mcs %_full.prm: %_fallback.bit %.bit + echo "write_cfgmem -force -format mcs -size 64 -interface SPIx4 -loadbit {up 0x00000000 $*.bit up 0x03000000 $*_fallback.bit} -checksum -file $*_full.mcs" > generate_full_mcs.tcl + echo "exit" >> generate_full_mcs.tcl + vivado -nojournal -nolog -mode batch -source generate_full_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 $*_full$$x rev/$*_full_rev$$COUNT$$x; \ + echo "Output: rev/$*_full_rev$$COUNT$$x"; done; + +flash: $(FPGA_TOP).mcs $(FPGA_TOP).prm + echo "open_hw_manager" > 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 {mt25ql512-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 \"$(FPGA_TOP).mcs\"] [current_hw_cfgmem]" >> flash.tcl + echo "set_property PROGRAM.PRM_FILES [list \"$(FPGA_TOP).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 + +flash%: $(FPGA_TOP)%.mcs $(FPGA_TOP)%.prm + echo "open_hw_manager" > 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 {mt25ql512-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 \"$(FPGA_TOP)$*.mcs\"] [current_hw_cfgmem]" >> flash$*.tcl + echo "set_property PROGRAM.PRM_FILES [list \"$(FPGA_TOP)$*.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 diff --git a/src/eth/example/NT200A02/fpga/fpga_NT200A01_25g/config.tcl b/src/eth/example/NT200A02/fpga/fpga_NT200A01_25g/config.tcl new file mode 100644 index 0000000..cc1eeae --- /dev/null +++ b/src/eth/example/NT200A02/fpga/fpga_NT200A01_25g/config.tcl @@ -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] diff --git a/src/eth/example/NT200A02/fpga/fpga_NT200A02/Makefile b/src/eth/example/NT200A02/fpga/fpga_NT200A02/Makefile index 51e903e..ad03782 100644 --- a/src/eth/example/NT200A02/fpga/fpga_NT200A02/Makefile +++ b/src/eth/example/NT200A02/fpga/fpga_NT200A02/Makefile @@ -19,7 +19,7 @@ TAXI_SRC_DIR = $(LIB_DIR)/taxi/src SYN_FILES = $(RTL_DIR)/fpga_nt200a02.sv SYN_FILES += $(RTL_DIR)/fpga_core.sv SYN_FILES += $(RTL_DIR)/../pll/si5340_i2c_init.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)/lss/rtl/taxi_i2c_master.sv SYN_FILES += $(TAXI_SRC_DIR)/axis/rtl/taxi_axis_async_fifo.f SYN_FILES += $(TAXI_SRC_DIR)/sync/rtl/taxi_sync_reset.sv @@ -29,13 +29,15 @@ SYN_FILES += $(TAXI_SRC_DIR)/sync/rtl/taxi_sync_signal.sv XDC_FILES += ../syn/NT200A02/fpga.xdc XDC_FILES += ../syn/NT200A02/gpio.xdc XDC_FILES += ../syn/NT200A02/qsfp.xdc +XDC_FILES += ../syn/NT200A02/eth_cmac.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_322.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_322.tcl # Configuration CONFIG_TCL_FILES = config.tcl diff --git a/src/eth/example/NT200A02/fpga/fpga_NT200A02/config.tcl b/src/eth/example/NT200A02/fpga/fpga_NT200A02/config.tcl index d3508a4..4bd9a8c 100644 --- a/src/eth/example/NT200A02/fpga/fpga_NT200A02/config.tcl +++ b/src/eth/example/NT200A02/fpga/fpga_NT200A02/config.tcl @@ -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 {} diff --git a/src/eth/example/NT200A02/fpga/fpga_NT200A02_10g/config.tcl b/src/eth/example/NT200A02/fpga/fpga_NT200A02_10g/config.tcl index cd72d45..4359e24 100644 --- a/src/eth/example/NT200A02/fpga/fpga_NT200A02_10g/config.tcl +++ b/src/eth/example/NT200A02/fpga/fpga_NT200A02_10g/config.tcl @@ -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" diff --git a/src/eth/example/NT200A02/fpga/fpga_NT200A02_25g/Makefile b/src/eth/example/NT200A02/fpga/fpga_NT200A02_25g/Makefile new file mode 100644 index 0000000..51e903e --- /dev/null +++ b/src/eth/example/NT200A02/fpga/fpga_NT200A02_25g/Makefile @@ -0,0 +1,159 @@ +# SPDX-License-Identifier: MIT +# +# Copyright (c) 2025 FPGA Ninja, LLC +# +# Authors: +# - Alex Forencich +# + +# FPGA settings +FPGA_PART = xcvu5p-flva2104-2-e +FPGA_TOP = fpga +FPGA_ARCH = virtexuplus + +RTL_DIR = ../rtl +LIB_DIR = ../lib +TAXI_SRC_DIR = $(LIB_DIR)/taxi/src + +# Files for synthesis +SYN_FILES = $(RTL_DIR)/fpga_nt200a02.sv +SYN_FILES += $(RTL_DIR)/fpga_core.sv +SYN_FILES += $(RTL_DIR)/../pll/si5340_i2c_init.sv +SYN_FILES += $(TAXI_SRC_DIR)/eth/rtl/us/taxi_eth_mac_25g_us.f +SYN_FILES += $(TAXI_SRC_DIR)/lss/rtl/taxi_i2c_master.sv +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/NT200A02/fpga.xdc +XDC_FILES += ../syn/NT200A02/gpio.xdc +XDC_FILES += ../syn/NT200A02/qsfp.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_322.tcl + +# Configuration +CONFIG_TCL_FILES = config.tcl + +include ../common/vivado.mk + +%_fallback.bit: %.bit + echo "open_project $*.xpr" > generate_fallback_bit.tcl + echo "open_run impl_1" >> generate_fallback_bit.tcl + echo "startgroup" >> generate_fallback_bit.tcl + echo "set_property BITSTREAM.CONFIG.SPI_32BIT_ADDR NO [current_design]" >> generate_fallback_bit.tcl + echo "endgroup" >> generate_fallback_bit.tcl + echo "write_bitstream -verbose -force $*_fallback.bit" >> generate_fallback_bit.tcl + echo "undo" >> generate_fallback_bit.tcl + echo "exit" >> generate_fallback_bit.tcl + vivado -nojournal -nolog -mode batch -source generate_fallback_bit.tcl + mkdir -p rev + EXT=bit; COUNT=100; \ + while [ -e rev/$*_rev$$COUNT.$$EXT ]; \ + do COUNT=$$((COUNT+1)); done; \ + COUNT=$$((COUNT-1)); \ + cp $@ rev/$*_fallback_rev$$COUNT.$$EXT; \ + echo "Output: rev/$*_fallback_rev$$COUNT.$$EXT"; + +program: $(FPGA_TOP).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 {$(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 + +%.mcs %.prm: %.bit + echo "write_cfgmem -force -format mcs -size 256 -interface SPIx4 -loadbit {up 0x00000000 $*.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; + +%_fallback.mcs %_fallback.prm: %_fallback.bit + echo "write_cfgmem -force -format mcs -size 256 -interface SPIx4 -loadbit {up 0x0C000000 $*_fallback.bit} -checksum -file $*_fallback.mcs" > generate_fallback_mcs.tcl + echo "exit" >> generate_fallback_mcs.tcl + vivado -nojournal -nolog -mode batch -source generate_fallback_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 $*_fallback$$x rev/$*_fallback_rev$$COUNT$$x; \ + echo "Output: rev/$*_fallback_rev$$COUNT$$x"; done; + +%_full.mcs %_full.prm: %_fallback.bit %.bit + echo "write_cfgmem -force -format mcs -size 256 -interface SPIx4 -loadbit {up 0x00000000 $*.bit up 0x0C000000 $*_fallback.bit} -checksum -file $*_full.mcs" > generate_full_mcs.tcl + echo "exit" >> generate_full_mcs.tcl + vivado -nojournal -nolog -mode batch -source generate_full_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 $*_full$$x rev/$*_full_rev$$COUNT$$x; \ + echo "Output: rev/$*_full_rev$$COUNT$$x"; done; + +flash: $(FPGA_TOP).mcs $(FPGA_TOP).prm + echo "open_hw_manager" > 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 {mt25qu02g-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 \"$(FPGA_TOP).mcs\"] [current_hw_cfgmem]" >> flash.tcl + echo "set_property PROGRAM.PRM_FILES [list \"$(FPGA_TOP).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 + +flash%: $(FPGA_TOP)%.mcs $(FPGA_TOP)%.prm + echo "open_hw_manager" > 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 {mt25qu02g-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 \"$(FPGA_TOP)$*.mcs\"] [current_hw_cfgmem]" >> flash$*.tcl + echo "set_property PROGRAM.PRM_FILES [list \"$(FPGA_TOP)$*.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 diff --git a/src/eth/example/NT200A02/fpga/fpga_NT200A02_25g/config.tcl b/src/eth/example/NT200A02/fpga/fpga_NT200A02_25g/config.tcl new file mode 100644 index 0000000..cc1eeae --- /dev/null +++ b/src/eth/example/NT200A02/fpga/fpga_NT200A02_25g/config.tcl @@ -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] diff --git a/src/eth/example/NT200A02/fpga/rtl/fpga_core.sv b/src/eth/example/NT200A02/fpga/rtl/fpga_core.sv index 4bdaaa5..0a86bad 100644 --- a/src/eth/example/NT200A02/fpga/rtl/fpga_core.sv +++ b/src/eth/example/NT200A02/fpga/rtl/fpga_core.sv @@ -28,11 +28,10 @@ module fpga_core # parameter GTY_QUAD_CNT = PORT_CNT, parameter GTY_CNT = GTY_QUAD_CNT*4, parameter GTY_CLK_CNT = GTY_QUAD_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 ) ( /* @@ -79,30 +78,43 @@ assign eth_port_i2c_scl_o = '1; assign eth_port_i2c_sda_o = '1; // QSFP28 +localparam MAC_CNT = MAC_DATA_W > 64 ? GTY_QUAD_CNT : GTY_CNT; + assign eth_port_resetl = '1; assign eth_port_lpmode = '0; -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](); taxi_axis_if #(.DATA_W(16), .KEEP_W(1), .KEEP_EN(0), .LAST_EN(0), .USER_EN(1), .USER_W(1), .ID_EN(1), .ID_W(10)) axis_eth_stat[GTY_QUAD_CNT](); -wire eth_gty_rx_status[GTY_CNT]; +wire eth_gty_rx_status[MAC_CNT]; -assign qsfp_led[0][0] = eth_gty_rx_status[0]; -assign qsfp_led[0][1] = eth_gty_rx_status[1]; -assign qsfp_led[0][2] = eth_gty_rx_status[2]; -assign qsfp_led[0][3] = eth_gty_rx_status[3]; -assign qsfp_led[1][0] = eth_gty_rx_status[4]; -assign qsfp_led[1][1] = eth_gty_rx_status[5]; -assign qsfp_led[1][2] = eth_gty_rx_status[6]; -assign qsfp_led[1][3] = eth_gty_rx_status[7]; +if (MAC_CNT == 2) begin + assign qsfp_led[0][0] = eth_gty_rx_status[0]; + assign qsfp_led[0][1] = 1'b0; + assign qsfp_led[0][2] = 1'b0; + assign qsfp_led[0][3] = 1'b0; + assign qsfp_led[1][0] = eth_gty_rx_status[1]; + assign qsfp_led[1][1] = 1'b0; + assign qsfp_led[1][2] = 1'b0; + assign qsfp_led[1][3] = 1'b0; +end else begin + assign qsfp_led[0][0] = eth_gty_rx_status[0]; + assign qsfp_led[0][1] = eth_gty_rx_status[1]; + assign qsfp_led[0][2] = eth_gty_rx_status[2]; + assign qsfp_led[0][3] = eth_gty_rx_status[3]; + assign qsfp_led[1][0] = eth_gty_rx_status[4]; + assign qsfp_led[1][1] = eth_gty_rx_status[5]; + assign qsfp_led[1][2] = eth_gty_rx_status[6]; + assign qsfp_led[1][3] = eth_gty_rx_status[7]; +end wire [GTY_QUAD_CNT-1:0] eth_gty_gtpowergood; @@ -173,6 +185,7 @@ localparam logic [8*8-1:0] STAT_PREFIX_STR_QSFP1[4] = '{"QSFP1.1", "QSFP1.2", "Q for (genvar n = 0; n < GTY_QUAD_CNT; n = n + 1) begin : gt_quad + localparam CLK = n; localparam CNT = 4; taxi_apb_if #( @@ -181,274 +194,515 @@ for (genvar n = 0; n < GTY_QUAD_CNT; n = n + 1) begin : gt_quad ) gt_apb_ctrl(); - taxi_eth_mac_25g_us #( - .SIM(SIM), - .VENDOR(VENDOR), - .FAMILY(FAMILY), + if (MAC_DATA_W == 512) begin: mac - .CNT(4), + 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), - // GT parameters - .GT_TX_POLARITY(n == 0 ? 4'b0101 : 4'b0001), - .GT_RX_POLARITY(n == 0 ? 4'b1011 : 4'b0011), + // 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(0), - .STAT_TX_LEVEL(1), - .STAT_RX_LEVEL(1), - .STAT_ID_BASE(n*CNT*(16+16)), - .STAT_UPDATE_PERIOD(1024), - .STAT_STR_EN(0), - .STAT_PREFIX_STR(n == 0 ? STAT_PREFIX_STR_QSFP0 : STAT_PREFIX_STR_QSFP1) - ) - mac_inst ( - .xcvr_ctrl_clk(clk_125mhz), - .xcvr_ctrl_rst(eth_gty_rst[n]), + // GT parameters + .GT_TX_POLARITY(n == 0 ? 4'b0101 : 4'b0001), + .GT_RX_POLARITY(n == 0 ? 4'b1011 : 4'b0011), - /* - * Transceiver control - */ - .s_apb_ctrl(gt_apb_ctrl), + // 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(0), + .STAT_TX_LEVEL(1), + .STAT_RX_LEVEL(1), + .STAT_ID_BASE(n*CNT*(16+16)), + .STAT_UPDATE_PERIOD(1024), + .STAT_STR_EN(0), + .STAT_PREFIX_STR(n == 0 ? "QSFP0" : "QSFP1") + ) + mac_inst ( + .xcvr_ctrl_clk(clk_125mhz), + .xcvr_ctrl_rst(eth_gty_rst[CLK]), - /* - * Common - */ - .xcvr_gtpowergood_out(eth_gty_gtpowergood[n]), - .xcvr_gtrefclk00_in(eth_gty_mgt_refclk[n]), - .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[n]), - .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(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]), + /* + * 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(), - /* - * 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]), + /* + * 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]), - /* - * 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]), + /* + * 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]), - /* - * Receive interface (AXI stream) - */ - .m_axis_rx(eth_gty_axis_rx[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]), - /* - * 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(), + /* + * Receive interface (AXI stream) + */ + .m_axis_rx(eth_gty_axis_rx[n]), - /* - * 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(), + /* + * 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(), - /* - * 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}}), + /* + * 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), - /* - * 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}}), + /* + * 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), - /* - * Pause interface - */ - .tx_lfc_pause_en('{CNT{1'b0}}), - .tx_pause_req('{CNT{1'b0}}), - .tx_pause_ack(), + /* + * Pause interface + */ + .tx_lfc_pause_en(1'b0), + .tx_pause_req(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*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(), + /* + * 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(), - /* - * 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}}) - ); + /* + * 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) + ); + + 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"), + + // GT parameters + .GT_TX_POLARITY(n == 0 ? 4'b0101 : 4'b0001), + .GT_RX_POLARITY(n == 0 ? 4'b1011 : 4'b0011), + + // 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(0), + .STAT_TX_LEVEL(1), + .STAT_RX_LEVEL(1), + .STAT_ID_BASE(n*CNT*(16+16)), + .STAT_UPDATE_PERIOD(1024), + .STAT_STR_EN(0), + .STAT_PREFIX_STR(n == 0 ? STAT_PREFIX_STR_QSFP0 : STAT_PREFIX_STR_QSFP1) + ) + 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 : qsfp_ch +for (genvar n = 0; n < $size(eth_gty_axis_tx); n = n + 1) begin : gty_ch taxi_axis_async_fifo #( .DEPTH(16384), diff --git a/src/eth/example/NT200A02/fpga/rtl/fpga_nt200a01.sv b/src/eth/example/NT200A02/fpga/rtl/fpga_nt200a01.sv index d27e0c5..d351c83 100644 --- a/src/eth/example/NT200A02/fpga/rtl/fpga_nt200a01.sv +++ b/src/eth/example/NT200A02/fpga/rtl/fpga_nt200a01.sv @@ -23,10 +23,10 @@ module fpga # parameter string VENDOR = "XILINX", // device family parameter string FAMILY = "virtexu", - // 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 ) ( /* diff --git a/src/eth/example/NT200A02/fpga/rtl/fpga_nt200a02.sv b/src/eth/example/NT200A02/fpga/rtl/fpga_nt200a02.sv index 62b488c..dd0836a 100644 --- a/src/eth/example/NT200A02/fpga/rtl/fpga_nt200a02.sv +++ b/src/eth/example/NT200A02/fpga/rtl/fpga_nt200a02.sv @@ -23,10 +23,10 @@ module fpga # parameter string VENDOR = "XILINX", // device family parameter string FAMILY = "virtexuplus", - // 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 ) ( /* diff --git a/src/eth/example/NT200A02/fpga/syn/NT200A01/eth_cmac.xdc b/src/eth/example/NT200A02/fpga/syn/NT200A01/eth_cmac.xdc new file mode 100644 index 0000000..99cfdc5 --- /dev/null +++ b/src/eth/example/NT200A02/fpga/syn/NT200A01/eth_cmac.xdc @@ -0,0 +1,4 @@ + +# CMACs +set_property LOC CMAC_SITE_X0Y2 [get_cells -hierarchical -filter {NAME =~ core_inst/gt_quad[0].mac.* && REF_NAME==CMAC}] +set_property LOC CMAC_SITE_X0Y3 [get_cells -hierarchical -filter {NAME =~ core_inst/gt_quad[1].mac.* && REF_NAME==CMAC}] diff --git a/src/eth/example/NT200A02/fpga/syn/NT200A02/eth_cmac.xdc b/src/eth/example/NT200A02/fpga/syn/NT200A02/eth_cmac.xdc new file mode 100644 index 0000000..d90e929 --- /dev/null +++ b/src/eth/example/NT200A02/fpga/syn/NT200A02/eth_cmac.xdc @@ -0,0 +1,4 @@ + +# CMACs +set_property LOC CMACE4_X0Y4 [get_cells -hierarchical -filter {NAME =~ core_inst/gt_quad[0].mac.* && REF_NAME==CMACE4}] +set_property LOC CMACE4_X0Y5 [get_cells -hierarchical -filter {NAME =~ core_inst/gt_quad[1].mac.* && REF_NAME==CMACE4}] diff --git a/src/eth/example/NT200A02/fpga/tb/fpga_core/Makefile b/src/eth/example/NT200A02/fpga/tb/fpga_core/Makefile index b24a919..af92818 100644 --- a/src/eth/example/NT200A02/fpga/tb/fpga_core/Makefile +++ b/src/eth/example/NT200A02/fpga/tb/fpga_core/Makefile @@ -1,6 +1,6 @@ # SPDX-License-Identifier: MIT # -# Copyright (c) 2020-2026 FPGA Ninja, LLC +# Copyright (c) 2020-2025 FPGA Ninja, LLC # # Authors: # - Alex Forencich @@ -24,6 +24,7 @@ MODULE = $(COCOTB_TEST_MODULES) TOPLEVEL = $(COCOTB_TOPLEVEL) 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)/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 @@ -44,7 +45,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 diff --git a/src/eth/example/NT200A02/fpga/tb/fpga_core/test_fpga_core.py b/src/eth/example/NT200A02/fpga/tb/fpga_core/test_fpga_core.py index 3f71d39..3ac5985 100644 --- a/src/eth/example/NT200A02/fpga/tb/fpga_core/test_fpga_core.py +++ b/src/eth/example/NT200A02/fpga/tb/fpga_core/test_fpga_core.py @@ -9,7 +9,6 @@ Authors: """ -import itertools import logging import os import sys @@ -21,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 try: from baser import BaseRSerdesSource, BaseRSerdesSink @@ -49,47 +51,78 @@ class TB: for clk in dut.eth_gty_mgt_refclk_p: cocotb.start_soon(Clock(clk, 3.102, units="ns").start()) - for ch in itertools.chain.from_iterable([inst.mac_inst.ch for inst in dut.gt_quad]): - gt_inst = ch.ch_inst.gt.gt_inst + has_cmac = False - 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: - if ch.ch_inst.CFG_LOW_LATENCY.value: + for quad in dut.gt_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 has_cmac: clk = 3.102 - gbx_cfg = (66, [64, 65]) + 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]) + 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.qsfp_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.qsfp_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.qsfp_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.qsfp_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 + )) async def init(self): @@ -109,13 +142,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") @@ -125,7 +154,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() @@ -142,7 +171,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() @@ -164,12 +193,18 @@ async def run_test(dut): tests = [] - tb.log.info("Start BASE-T MAC loopback test") + 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) @@ -198,7 +233,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] @@ -207,6 +242,7 @@ def test_fpga_core(request, mac_data_w): verilog_sources = [ 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, "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"),