1
0
mirror of https://github.com/corundum/corundum.git synced 2025-01-16 08:12:53 +08:00

Add HTG-9200 + HTG 6x QSFP28 example design

Signed-off-by: Alex Forencich <alex@alexforencich.com>
This commit is contained in:
Alex Forencich 2023-07-21 18:16:59 -07:00
parent 6bf727d3ef
commit f4a8561652
23 changed files with 12893 additions and 0 deletions

View File

@ -0,0 +1,28 @@
# Verilog Ethernet HTG-9200 + HTG 6x QSFP28 FMC+ Example Design
## Introduction
This example design targets the HiTech Global HTG-9200 FPGA board with the HiTech Global HTG-FMC-X6QSFP28 FMC+ board installed on J9.
The design by default listens to UDP port 1234 at IP address 192.168.1.128 and will echo back any packets received. The design will also respond correctly to ARP requests.
The design is configured to run all 15 QSFP28 modules synchronous to the GTY reference oscillator (U47) on the HTG-9200. This is done by forwarding the MGT reference clock for QSFP1 through the FPGA to the SYNC_C2M pins on the FMC+, which is connected as a reference input to the Si5341 PLL (U7) on the FMC+.
* FPGA: xcvu9p-flgb2104-2-e
* PHY: 10G BASE-R PHY IP core and internal GTY transceiver
## How to build
Run make to build. Ensure that the Xilinx Vivado toolchain components are in PATH.
## How to test
Run make program to program the HTG-9200 board with Vivado. Then run
netcat -u 192.168.1.128 1234
to open a UDP connection to port 1234. Any text entered into netcat will be echoed back after pressing enter.
It is also possible to use hping to test the design by running
hping 192.168.1.128 -2 -p 1234 -d 1024

View File

@ -0,0 +1,137 @@
###################################################################
#
# Xilinx Vivado FPGA Makefile
#
# Copyright (c) 2016 Alex Forencich
#
###################################################################
#
# Parameters:
# FPGA_TOP - Top module name
# FPGA_FAMILY - FPGA family (e.g. VirtexUltrascale)
# FPGA_DEVICE - FPGA device (e.g. xcvu095-ffva2104-2-e)
# SYN_FILES - space-separated list of source files
# INC_FILES - space-separated list of include files
# XDC_FILES - space-separated list of timing constraint files
# XCI_FILES - space-separated list of IP XCI files
#
# Example:
#
# FPGA_TOP = fpga
# FPGA_FAMILY = VirtexUltrascale
# FPGA_DEVICE = xcvu095-ffva2104-2-e
# SYN_FILES = rtl/fpga.v
# XDC_FILES = fpga.xdc
# XCI_FILES = ip/pcspma.xci
# include ../common/vivado.mk
#
###################################################################
# phony targets
.PHONY: fpga vivado tmpclean clean distclean
# prevent make from deleting intermediate files and reports
.PRECIOUS: %.xpr %.bit %.mcs %.prm
.SECONDARY:
CONFIG ?= config.mk
-include ../$(CONFIG)
FPGA_TOP ?= fpga
PROJECT ?= $(FPGA_TOP)
SYN_FILES_REL = $(foreach p,$(SYN_FILES),$(if $(filter /% ./%,$p),$p,../$p))
INC_FILES_REL = $(foreach p,$(INC_FILES),$(if $(filter /% ./%,$p),$p,../$p))
XCI_FILES_REL = $(foreach p,$(XCI_FILES),$(if $(filter /% ./%,$p),$p,../$p))
IP_TCL_FILES_REL = $(foreach p,$(IP_TCL_FILES),$(if $(filter /% ./%,$p),$p,../$p))
CONFIG_TCL_FILES_REL = $(foreach p,$(CONFIG_TCL_FILES),$(if $(filter /% ./%,$p),$p,../$p))
ifdef XDC_FILES
XDC_FILES_REL = $(foreach p,$(XDC_FILES),$(if $(filter /% ./%,$p),$p,../$p))
else
XDC_FILES_REL = $(PROJECT).xdc
endif
###################################################################
# Main Targets
#
# all: build everything
# clean: remove output files and project files
###################################################################
all: fpga
fpga: $(PROJECT).bit
vivado: $(PROJECT).xpr
vivado $(PROJECT).xpr
tmpclean::
-rm -rf *.log *.jou *.cache *.gen *.hbs *.hw *.ip_user_files *.runs *.xpr *.html *.xml *.sim *.srcs *.str .Xil defines.v
-rm -rf create_project.tcl update_config.tcl run_synth.tcl run_impl.tcl generate_bit.tcl
clean:: tmpclean
-rm -rf *.bit *.ltx program.tcl generate_mcs.tcl *.mcs *.prm flash.tcl
-rm -rf *_utilization.rpt *_utilization_hierarchical.rpt
distclean:: clean
-rm -rf rev
###################################################################
# Target implementations
###################################################################
# Vivado project file
create_project.tcl: Makefile $(XCI_FILES_REL) $(IP_TCL_FILES_REL)
rm -rf defines.v
touch defines.v
for x in $(DEFS); do echo '`define' $$x >> defines.v; done
echo "create_project -force -part $(FPGA_PART) $(PROJECT)" > $@
echo "add_files -fileset sources_1 defines.v $(SYN_FILES_REL)" >> $@
echo "set_property top $(FPGA_TOP) [current_fileset]" >> $@
echo "add_files -fileset constrs_1 $(XDC_FILES_REL)" >> $@
for x in $(XCI_FILES_REL); do echo "import_ip $$x" >> $@; done
for x in $(IP_TCL_FILES_REL); do echo "source $$x" >> $@; done
for x in $(CONFIG_TCL_FILES_REL); do echo "source $$x" >> $@; done
update_config.tcl: $(CONFIG_TCL_FILES_REL) $(SYN_FILES_REL) $(INC_FILES_REL) $(XDC_FILES_REL)
echo "open_project -quiet $(PROJECT).xpr" > $@
for x in $(CONFIG_TCL_FILES_REL); do echo "source $$x" >> $@; done
$(PROJECT).xpr: create_project.tcl update_config.tcl
vivado -nojournal -nolog -mode batch $(foreach x,$?,-source $x)
# synthesis run
$(PROJECT).runs/synth_1/$(PROJECT).dcp: create_project.tcl update_config.tcl $(SYN_FILES_REL) $(INC_FILES_REL) $(XDC_FILES_REL) | $(PROJECT).xpr
echo "open_project $(PROJECT).xpr" > run_synth.tcl
echo "reset_run synth_1" >> run_synth.tcl
echo "launch_runs -jobs 4 synth_1" >> run_synth.tcl
echo "wait_on_run synth_1" >> run_synth.tcl
vivado -nojournal -nolog -mode batch -source run_synth.tcl
# implementation run
$(PROJECT).runs/impl_1/$(PROJECT)_routed.dcp: $(PROJECT).runs/synth_1/$(PROJECT).dcp
echo "open_project $(PROJECT).xpr" > run_impl.tcl
echo "reset_run impl_1" >> run_impl.tcl
echo "launch_runs -jobs 4 impl_1" >> run_impl.tcl
echo "wait_on_run impl_1" >> run_impl.tcl
echo "open_run impl_1" >> run_impl.tcl
echo "report_utilization -file $(PROJECT)_utilization.rpt" >> run_impl.tcl
echo "report_utilization -hierarchical -file $(PROJECT)_utilization_hierarchical.rpt" >> run_impl.tcl
vivado -nojournal -nolog -mode batch -source run_impl.tcl
# bit file
$(PROJECT).bit $(PROJECT).ltx: $(PROJECT).runs/impl_1/$(PROJECT)_routed.dcp
echo "open_project $(PROJECT).xpr" > generate_bit.tcl
echo "open_run impl_1" >> generate_bit.tcl
echo "write_bitstream -force $(PROJECT).runs/impl_1/$(PROJECT).bit" >> generate_bit.tcl
echo "write_debug_probes -force $(PROJECT).runs/impl_1/$(PROJECT).ltx" >> generate_bit.tcl
vivado -nojournal -nolog -mode batch -source generate_bit.tcl
ln -f -s $(PROJECT).runs/impl_1/$(PROJECT).bit .
if [ -e $(PROJECT).runs/impl_1/$(PROJECT).ltx ]; then ln -f -s $(PROJECT).runs/impl_1/$(PROJECT).ltx .; fi
mkdir -p rev
COUNT=100; \
while [ -e rev/$(PROJECT)_rev$$COUNT.bit ]; \
do COUNT=$$((COUNT+1)); done; \
cp -pv $(PROJECT).runs/impl_1/$(PROJECT).bit rev/$(PROJECT)_rev$$COUNT.bit; \
if [ -e $(PROJECT).runs/impl_1/$(PROJECT).ltx ]; then cp -pv $(PROJECT).runs/impl_1/$(PROJECT).ltx rev/$(PROJECT)_rev$$COUNT.ltx; fi

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,115 @@
# FPGA settings
FPGA_PART = xcvu9p-flgb2104-2-e
FPGA_TOP = fpga
FPGA_ARCH = virtexuplus
# Files for synthesis
SYN_FILES = rtl/fpga.v
SYN_FILES += rtl/fpga_core.v
SYN_FILES += rtl/eth_xcvr_phy_wrapper.v
SYN_FILES += rtl/debounce_switch.v
SYN_FILES += rtl/sync_signal.v
SYN_FILES += rtl/i2c_master.v
SYN_FILES += pll/si5341_i2c_init.v
SYN_FILES += lib/eth/rtl/eth_mac_10g_fifo.v
SYN_FILES += lib/eth/rtl/eth_mac_10g.v
SYN_FILES += lib/eth/rtl/axis_xgmii_rx_64.v
SYN_FILES += lib/eth/rtl/axis_xgmii_tx_64.v
SYN_FILES += lib/eth/rtl/eth_phy_10g.v
SYN_FILES += lib/eth/rtl/eth_phy_10g_rx.v
SYN_FILES += lib/eth/rtl/eth_phy_10g_rx_if.v
SYN_FILES += lib/eth/rtl/eth_phy_10g_rx_frame_sync.v
SYN_FILES += lib/eth/rtl/eth_phy_10g_rx_ber_mon.v
SYN_FILES += lib/eth/rtl/eth_phy_10g_rx_watchdog.v
SYN_FILES += lib/eth/rtl/eth_phy_10g_tx.v
SYN_FILES += lib/eth/rtl/eth_phy_10g_tx_if.v
SYN_FILES += lib/eth/rtl/xgmii_baser_dec_64.v
SYN_FILES += lib/eth/rtl/xgmii_baser_enc_64.v
SYN_FILES += lib/eth/rtl/lfsr.v
SYN_FILES += lib/eth/rtl/eth_axis_rx.v
SYN_FILES += lib/eth/rtl/eth_axis_tx.v
SYN_FILES += lib/eth/rtl/udp_complete_64.v
SYN_FILES += lib/eth/rtl/udp_checksum_gen_64.v
SYN_FILES += lib/eth/rtl/udp_64.v
SYN_FILES += lib/eth/rtl/udp_ip_rx_64.v
SYN_FILES += lib/eth/rtl/udp_ip_tx_64.v
SYN_FILES += lib/eth/rtl/ip_complete_64.v
SYN_FILES += lib/eth/rtl/ip_64.v
SYN_FILES += lib/eth/rtl/ip_eth_rx_64.v
SYN_FILES += lib/eth/rtl/ip_eth_tx_64.v
SYN_FILES += lib/eth/rtl/ip_arb_mux.v
SYN_FILES += lib/eth/rtl/arp.v
SYN_FILES += lib/eth/rtl/arp_cache.v
SYN_FILES += lib/eth/rtl/arp_eth_rx.v
SYN_FILES += lib/eth/rtl/arp_eth_tx.v
SYN_FILES += lib/eth/rtl/eth_arb_mux.v
SYN_FILES += lib/eth/lib/axis/rtl/arbiter.v
SYN_FILES += lib/eth/lib/axis/rtl/priority_encoder.v
SYN_FILES += lib/eth/lib/axis/rtl/axis_fifo.v
SYN_FILES += lib/eth/lib/axis/rtl/axis_async_fifo.v
SYN_FILES += lib/eth/lib/axis/rtl/axis_async_fifo_adapter.v
SYN_FILES += lib/eth/lib/axis/rtl/sync_reset.v
# XDC files
XDC_FILES = fpga.xdc
XDC_FILES += lib/eth/syn/vivado/eth_mac_fifo.tcl
XDC_FILES += lib/eth/lib/axis/syn/vivado/axis_async_fifo.tcl
XDC_FILES += lib/eth/lib/axis/syn/vivado/sync_reset.tcl
# IP
IP_TCL_FILES += ip/eth_xcvr_gt.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
%_primary.mcs %_secondary.mcs %_primary.prm %_secondary.prm: %.bit
echo "write_cfgmem -force -format mcs -size 128 -interface SPIx8 -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 _primary.mcs _secondary.mcs _primary.prm _secondary.prm; \
do cp $*$$x rev/$*_rev$$COUNT$$x; \
echo "Output: rev/$*_rev$$COUNT$$x"; done;
flash: $(FPGA_TOP)_primary.mcs $(FPGA_TOP)_secondary.mcs $(FPGA_TOP)_primary.prm $(FPGA_TOP)_secondary.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 {s25fl512s-spi-x1_x2_x4_x8}] 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)_primary.mcs\" \"$(FPGA_TOP)_secondary.mcs\"] [current_hw_cfgmem]" >> flash.tcl
echo "set_property PROGRAM.PRM_FILES [list \"$(FPGA_TOP)_primary.prm\" \"$(FPGA_TOP)_secondary.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,50 @@
# Copyright (c) 2023 Alex Forencich
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
# Transceiver configuration
set eth_xcvr_freerun_freq {125}
set eth_xcvr_line_rate {25.78125}
set eth_xcvr_sec_line_rate {0}
set eth_xcvr_refclk_freq {161.1328125}
set eth_xcvr_qpll_fracn [expr {int(fmod($eth_xcvr_line_rate*1000/2 / $eth_xcvr_refclk_freq, 1)*pow(2, 24))}]
set eth_xcvr_sec_qpll_fracn [expr {int(fmod($eth_xcvr_sec_line_rate*1000/2 / $eth_xcvr_refclk_freq, 1)*pow(2, 24))}]
set eth_xcvr_rx_eq_mode {DFE}
set xcvr_config [dict create]
dict set xcvr_config CONFIG.TX_LINE_RATE $eth_xcvr_line_rate
dict set xcvr_config CONFIG.TX_QPLL_FRACN_NUMERATOR $eth_xcvr_qpll_fracn
dict set xcvr_config CONFIG.TX_REFCLK_FREQUENCY $eth_xcvr_refclk_freq
dict set xcvr_config CONFIG.RX_LINE_RATE $eth_xcvr_line_rate
dict set xcvr_config CONFIG.RX_QPLL_FRACN_NUMERATOR $eth_xcvr_qpll_fracn
dict set xcvr_config CONFIG.RX_REFCLK_FREQUENCY $eth_xcvr_refclk_freq
dict set xcvr_config CONFIG.RX_EQ_MODE $eth_xcvr_rx_eq_mode
if {$eth_xcvr_sec_line_rate != 0} {
dict set xcvr_config CONFIG.SECONDARY_QPLL_ENABLE true
dict set xcvr_config CONFIG.SECONDARY_QPLL_FRACN_NUMERATOR $eth_xcvr_sec_qpll_fracn
dict set xcvr_config CONFIG.SECONDARY_QPLL_LINE_RATE $eth_xcvr_sec_line_rate
dict set xcvr_config CONFIG.SECONDARY_QPLL_REFCLK_FREQUENCY $eth_xcvr_refclk_freq
} else {
dict set xcvr_config CONFIG.SECONDARY_QPLL_ENABLE false
}
dict set xcvr_config CONFIG.FREERUN_FREQUENCY $eth_xcvr_freerun_freq
set_property -dict $xcvr_config [get_ips eth_xcvr_gt_full]
set_property -dict $xcvr_config [get_ips eth_xcvr_gt_channel]

View File

@ -0,0 +1,115 @@
# FPGA settings
FPGA_PART = xcvu9p-flgb2104-2-e
FPGA_TOP = fpga
FPGA_ARCH = virtexuplus
# Files for synthesis
SYN_FILES = rtl/fpga.v
SYN_FILES += rtl/fpga_core.v
SYN_FILES += rtl/eth_xcvr_phy_wrapper.v
SYN_FILES += rtl/debounce_switch.v
SYN_FILES += rtl/sync_signal.v
SYN_FILES += rtl/i2c_master.v
SYN_FILES += pll/si5341_i2c_init.v
SYN_FILES += lib/eth/rtl/eth_mac_10g_fifo.v
SYN_FILES += lib/eth/rtl/eth_mac_10g.v
SYN_FILES += lib/eth/rtl/axis_xgmii_rx_64.v
SYN_FILES += lib/eth/rtl/axis_xgmii_tx_64.v
SYN_FILES += lib/eth/rtl/eth_phy_10g.v
SYN_FILES += lib/eth/rtl/eth_phy_10g_rx.v
SYN_FILES += lib/eth/rtl/eth_phy_10g_rx_if.v
SYN_FILES += lib/eth/rtl/eth_phy_10g_rx_frame_sync.v
SYN_FILES += lib/eth/rtl/eth_phy_10g_rx_ber_mon.v
SYN_FILES += lib/eth/rtl/eth_phy_10g_rx_watchdog.v
SYN_FILES += lib/eth/rtl/eth_phy_10g_tx.v
SYN_FILES += lib/eth/rtl/eth_phy_10g_tx_if.v
SYN_FILES += lib/eth/rtl/xgmii_baser_dec_64.v
SYN_FILES += lib/eth/rtl/xgmii_baser_enc_64.v
SYN_FILES += lib/eth/rtl/lfsr.v
SYN_FILES += lib/eth/rtl/eth_axis_rx.v
SYN_FILES += lib/eth/rtl/eth_axis_tx.v
SYN_FILES += lib/eth/rtl/udp_complete_64.v
SYN_FILES += lib/eth/rtl/udp_checksum_gen_64.v
SYN_FILES += lib/eth/rtl/udp_64.v
SYN_FILES += lib/eth/rtl/udp_ip_rx_64.v
SYN_FILES += lib/eth/rtl/udp_ip_tx_64.v
SYN_FILES += lib/eth/rtl/ip_complete_64.v
SYN_FILES += lib/eth/rtl/ip_64.v
SYN_FILES += lib/eth/rtl/ip_eth_rx_64.v
SYN_FILES += lib/eth/rtl/ip_eth_tx_64.v
SYN_FILES += lib/eth/rtl/ip_arb_mux.v
SYN_FILES += lib/eth/rtl/arp.v
SYN_FILES += lib/eth/rtl/arp_cache.v
SYN_FILES += lib/eth/rtl/arp_eth_rx.v
SYN_FILES += lib/eth/rtl/arp_eth_tx.v
SYN_FILES += lib/eth/rtl/eth_arb_mux.v
SYN_FILES += lib/eth/lib/axis/rtl/arbiter.v
SYN_FILES += lib/eth/lib/axis/rtl/priority_encoder.v
SYN_FILES += lib/eth/lib/axis/rtl/axis_fifo.v
SYN_FILES += lib/eth/lib/axis/rtl/axis_async_fifo.v
SYN_FILES += lib/eth/lib/axis/rtl/axis_async_fifo_adapter.v
SYN_FILES += lib/eth/lib/axis/rtl/sync_reset.v
# XDC files
XDC_FILES = fpga.xdc
XDC_FILES += lib/eth/syn/vivado/eth_mac_fifo.tcl
XDC_FILES += lib/eth/lib/axis/syn/vivado/axis_async_fifo.tcl
XDC_FILES += lib/eth/lib/axis/syn/vivado/sync_reset.tcl
# IP
IP_TCL_FILES += ip/eth_xcvr_gt.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
%_primary.mcs %_secondary.mcs %_primary.prm %_secondary.prm: %.bit
echo "write_cfgmem -force -format mcs -size 128 -interface SPIx8 -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 _primary.mcs _secondary.mcs _primary.prm _secondary.prm; \
do cp $*$$x rev/$*_rev$$COUNT$$x; \
echo "Output: rev/$*_rev$$COUNT$$x"; done;
flash: $(FPGA_TOP)_primary.mcs $(FPGA_TOP)_secondary.mcs $(FPGA_TOP)_primary.prm $(FPGA_TOP)_secondary.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 {s25fl512s-spi-x1_x2_x4_x8}] 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)_primary.mcs\" \"$(FPGA_TOP)_secondary.mcs\"] [current_hw_cfgmem]" >> flash.tcl
echo "set_property PROGRAM.PRM_FILES [list \"$(FPGA_TOP)_primary.prm\" \"$(FPGA_TOP)_secondary.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,50 @@
# Copyright (c) 2023 Alex Forencich
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
# Transceiver configuration
set eth_xcvr_freerun_freq {125}
set eth_xcvr_line_rate {10.3125}
set eth_xcvr_sec_line_rate {0}
set eth_xcvr_refclk_freq {161.1328125}
set eth_xcvr_qpll_fracn [expr {int(fmod($eth_xcvr_line_rate*1000/2 / $eth_xcvr_refclk_freq, 1)*pow(2, 24))}]
set eth_xcvr_sec_qpll_fracn [expr {int(fmod($eth_xcvr_sec_line_rate*1000/2 / $eth_xcvr_refclk_freq, 1)*pow(2, 24))}]
set eth_xcvr_rx_eq_mode {DFE}
set xcvr_config [dict create]
dict set xcvr_config CONFIG.TX_LINE_RATE $eth_xcvr_line_rate
dict set xcvr_config CONFIG.TX_QPLL_FRACN_NUMERATOR $eth_xcvr_qpll_fracn
dict set xcvr_config CONFIG.TX_REFCLK_FREQUENCY $eth_xcvr_refclk_freq
dict set xcvr_config CONFIG.RX_LINE_RATE $eth_xcvr_line_rate
dict set xcvr_config CONFIG.RX_QPLL_FRACN_NUMERATOR $eth_xcvr_qpll_fracn
dict set xcvr_config CONFIG.RX_REFCLK_FREQUENCY $eth_xcvr_refclk_freq
dict set xcvr_config CONFIG.RX_EQ_MODE $eth_xcvr_rx_eq_mode
if {$eth_xcvr_sec_line_rate != 0} {
dict set xcvr_config CONFIG.SECONDARY_QPLL_ENABLE true
dict set xcvr_config CONFIG.SECONDARY_QPLL_FRACN_NUMERATOR $eth_xcvr_sec_qpll_fracn
dict set xcvr_config CONFIG.SECONDARY_QPLL_LINE_RATE $eth_xcvr_sec_line_rate
dict set xcvr_config CONFIG.SECONDARY_QPLL_REFCLK_FREQUENCY $eth_xcvr_refclk_freq
} else {
dict set xcvr_config CONFIG.SECONDARY_QPLL_ENABLE false
}
dict set xcvr_config CONFIG.FREERUN_FREQUENCY $eth_xcvr_freerun_freq
set_property -dict $xcvr_config [get_ips eth_xcvr_gt_full]
set_property -dict $xcvr_config [get_ips eth_xcvr_gt_channel]

View File

@ -0,0 +1,76 @@
# Copyright (c) 2021 Alex Forencich
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
set base_name {eth_xcvr_gt}
set preset {GTY-10GBASE-R}
set freerun_freq {125}
set line_rate {10.3125}
set refclk_freq {161.1328125}
set qpll_fracn [expr {int(fmod($line_rate*1000/2 / $refclk_freq, 1)*pow(2, 24))}]
set user_data_width {64}
set int_data_width $user_data_width
set extra_ports [list]
set extra_pll_ports [list {qpll0lock_out}]
set config [dict create]
dict set config TX_LINE_RATE $line_rate
dict set config TX_REFCLK_FREQUENCY $refclk_freq
dict set config TX_QPLL_FRACN_NUMERATOR $qpll_fracn
dict set config TX_USER_DATA_WIDTH $user_data_width
dict set config TX_INT_DATA_WIDTH $int_data_width
dict set config RX_LINE_RATE $line_rate
dict set config RX_REFCLK_FREQUENCY $refclk_freq
dict set config RX_QPLL_FRACN_NUMERATOR $qpll_fracn
dict set config RX_USER_DATA_WIDTH $user_data_width
dict set config RX_INT_DATA_WIDTH $int_data_width
dict set config ENABLE_OPTIONAL_PORTS $extra_ports
dict set config LOCATE_COMMON {CORE}
dict set config LOCATE_RESET_CONTROLLER {CORE}
dict set config LOCATE_TX_USER_CLOCKING {CORE}
dict set config LOCATE_RX_USER_CLOCKING {CORE}
dict set config LOCATE_USER_DATA_WIDTH_SIZING {CORE}
dict set config FREERUN_FREQUENCY $freerun_freq
dict set config DISABLE_LOC_XDC {1}
proc create_gtwizard_ip {name preset config} {
create_ip -name gtwizard_ultrascale -vendor xilinx.com -library ip -module_name $name
set ip [get_ips $name]
set_property CONFIG.preset $preset $ip
set config_list {}
dict for {name value} $config {
lappend config_list "CONFIG.${name}" $value
}
set_property -dict $config_list $ip
}
# variant with channel and common
dict set config ENABLE_OPTIONAL_PORTS [concat $extra_pll_ports $extra_ports]
dict set config LOCATE_COMMON {CORE}
create_gtwizard_ip "${base_name}_full" $preset $config
# variant with channel only
dict set config ENABLE_OPTIONAL_PORTS $extra_ports
dict set config LOCATE_COMMON {EXAMPLE_DESIGN}
create_gtwizard_ip "${base_name}_channel" $preset $config

View File

@ -0,0 +1 @@
../../../../

View File

@ -0,0 +1,412 @@
# Si534x/7x/8x/9x Registers Script
#
# Part: Si5341
# Project File: X:\Projects\verilog-ethernet\example\HTG9200\fpga_25g\pll\HTG9200_161-9k2_161.slabtimeproj
# Design ID: 9k2_161
# Includes Pre/Post Download Control Register Writes: Yes
# Die Revision: B1
# Creator: ClockBuilder Pro v4.1 [2021-09-22]
# Created On: 2023-07-19 01:38:53 GMT-07:00
Address,Data
#
# Start configuration preamble
0x0B24,0xC0
0x0B25,0x00
# Rev D stuck divider fix
0x0502,0x01
0x0505,0x03
0x0957,0x17
0x0B4E,0x1A
# End configuration preamble
#
# Delay 300 msec
# Delay is worst case time for device to complete any calibration
# that is running due to device state change previous to this script
# being processed.
#
# Start configuration registers
0x0006,0x00
0x0007,0x00
0x0008,0x00
0x000B,0x74
0x0017,0xD0
0x0018,0xFF
0x0021,0x0B
0x0022,0x00
0x002B,0x02
0x002C,0x33
0x002D,0x05
0x002E,0xAE
0x002F,0x00
0x0030,0xAE
0x0031,0x00
0x0032,0x00
0x0033,0x00
0x0034,0x00
0x0035,0x00
0x0036,0xAE
0x0037,0x00
0x0038,0xAE
0x0039,0x00
0x003A,0x00
0x003B,0x00
0x003C,0x00
0x003D,0x00
0x0041,0x07
0x0042,0x07
0x0043,0x00
0x0044,0x00
0x009E,0x00
0x0102,0x01
0x0108,0x06
0x0109,0x09
0x010A,0x3B
0x010B,0x28
0x010D,0x06
0x010E,0x09
0x010F,0x3B
0x0110,0x28
0x0112,0x02
0x0113,0x09
0x0114,0x3B
0x0115,0x29
0x0117,0x06
0x0118,0x09
0x0119,0x3B
0x011A,0x28
0x011C,0x06
0x011D,0x09
0x011E,0x3B
0x011F,0x28
0x0121,0x06
0x0122,0x09
0x0123,0x3B
0x0124,0x28
0x0126,0x06
0x0127,0x09
0x0128,0x3B
0x0129,0x28
0x012B,0x06
0x012C,0x09
0x012D,0x3B
0x012E,0x28
0x0130,0x06
0x0131,0x09
0x0132,0x3B
0x0133,0x28
0x013A,0x06
0x013B,0x09
0x013C,0x3B
0x013D,0x28
0x013F,0x00
0x0140,0x00
0x0141,0x40
0x0206,0x00
0x0208,0x02
0x0209,0x00
0x020A,0x00
0x020B,0x00
0x020C,0x00
0x020D,0x00
0x020E,0x01
0x020F,0x00
0x0210,0x00
0x0211,0x00
0x0212,0x02
0x0213,0x00
0x0214,0x00
0x0215,0x00
0x0216,0x00
0x0217,0x00
0x0218,0x01
0x0219,0x00
0x021A,0x00
0x021B,0x00
0x021C,0x00
0x021D,0x00
0x021E,0x00
0x021F,0x00
0x0220,0x00
0x0221,0x00
0x0222,0x00
0x0223,0x00
0x0224,0x00
0x0225,0x00
0x0226,0x00
0x0227,0x00
0x0228,0x00
0x0229,0x00
0x022A,0x00
0x022B,0x00
0x022C,0x00
0x022D,0x00
0x022E,0x00
0x022F,0x00
0x0235,0x00
0x0236,0x00
0x0237,0x00
0x0238,0x90
0x0239,0x54
0x023A,0x00
0x023B,0x00
0x023C,0x00
0x023D,0x00
0x023E,0x80
0x024A,0x00
0x024B,0x00
0x024C,0x00
0x024D,0x00
0x024E,0x00
0x024F,0x00
0x0250,0x03
0x0251,0x00
0x0252,0x00
0x0253,0x00
0x0254,0x00
0x0255,0x00
0x0256,0x00
0x0257,0x00
0x0258,0x00
0x0259,0x00
0x025A,0x00
0x025B,0x00
0x025C,0x00
0x025D,0x00
0x025E,0x00
0x025F,0x00
0x0260,0x00
0x0261,0x00
0x0262,0x00
0x0263,0x00
0x0264,0x00
0x0268,0x00
0x0269,0x00
0x026A,0x00
0x026B,0x39
0x026C,0x6B
0x026D,0x32
0x026E,0x5F
0x026F,0x31
0x0270,0x36
0x0271,0x31
0x0272,0x00
0x0302,0x00
0x0303,0x00
0x0304,0x00
0x0305,0x80
0x0306,0x14
0x0307,0x00
0x0308,0x00
0x0309,0x00
0x030A,0x00
0x030B,0x80
0x030C,0x00
0x030D,0x00
0x030E,0x00
0x030F,0x10
0x0310,0x42
0x0311,0x08
0x0312,0x00
0x0313,0x00
0x0314,0x00
0x0315,0x00
0x0316,0x80
0x0317,0x00
0x0318,0x00
0x0319,0x00
0x031A,0x00
0x031B,0x00
0x031C,0x00
0x031D,0x00
0x031E,0x00
0x031F,0x00
0x0320,0x00
0x0321,0x00
0x0322,0x00
0x0323,0x00
0x0324,0x00
0x0325,0x00
0x0326,0x00
0x0327,0x00
0x0328,0x00
0x0329,0x00
0x032A,0x00
0x032B,0x00
0x032C,0x00
0x032D,0x00
0x032E,0x00
0x032F,0x00
0x0330,0x00
0x0331,0x00
0x0332,0x00
0x0333,0x00
0x0334,0x00
0x0335,0x00
0x0336,0x00
0x0337,0x00
0x0338,0x00
0x0339,0x1F
0x033B,0x00
0x033C,0x00
0x033D,0x00
0x033E,0x00
0x033F,0x00
0x0340,0x00
0x0341,0x00
0x0342,0x00
0x0343,0x00
0x0344,0x00
0x0345,0x00
0x0346,0x00
0x0347,0x00
0x0348,0x00
0x0349,0x00
0x034A,0x00
0x034B,0x00
0x034C,0x00
0x034D,0x00
0x034E,0x00
0x034F,0x00
0x0350,0x00
0x0351,0x00
0x0352,0x00
0x0353,0x00
0x0354,0x00
0x0355,0x00
0x0356,0x00
0x0357,0x00
0x0358,0x00
0x0359,0x00
0x035A,0x00
0x035B,0x00
0x035C,0x00
0x035D,0x00
0x035E,0x00
0x035F,0x00
0x0360,0x00
0x0361,0x00
0x0362,0x00
0x0802,0x00
0x0803,0x00
0x0804,0x00
0x0805,0x00
0x0806,0x00
0x0807,0x00
0x0808,0x00
0x0809,0x00
0x080A,0x00
0x080B,0x00
0x080C,0x00
0x080D,0x00
0x080E,0x00
0x080F,0x00
0x0810,0x00
0x0811,0x00
0x0812,0x00
0x0813,0x00
0x0814,0x00
0x0815,0x00
0x0816,0x00
0x0817,0x00
0x0818,0x00
0x0819,0x00
0x081A,0x00
0x081B,0x00
0x081C,0x00
0x081D,0x00
0x081E,0x00
0x081F,0x00
0x0820,0x00
0x0821,0x00
0x0822,0x00
0x0823,0x00
0x0824,0x00
0x0825,0x00
0x0826,0x00
0x0827,0x00
0x0828,0x00
0x0829,0x00
0x082A,0x00
0x082B,0x00
0x082C,0x00
0x082D,0x00
0x082E,0x00
0x082F,0x00
0x0830,0x00
0x0831,0x00
0x0832,0x00
0x0833,0x00
0x0834,0x00
0x0835,0x00
0x0836,0x00
0x0837,0x00
0x0838,0x00
0x0839,0x00
0x083A,0x00
0x083B,0x00
0x083C,0x00
0x083D,0x00
0x083E,0x00
0x083F,0x00
0x0840,0x00
0x0841,0x00
0x0842,0x00
0x0843,0x00
0x0844,0x00
0x0845,0x00
0x0846,0x00
0x0847,0x00
0x0848,0x00
0x0849,0x00
0x084A,0x00
0x084B,0x00
0x084C,0x00
0x084D,0x00
0x084E,0x00
0x084F,0x00
0x0850,0x00
0x0851,0x00
0x0852,0x00
0x0853,0x00
0x0854,0x00
0x0855,0x00
0x0856,0x00
0x0857,0x00
0x0858,0x00
0x0859,0x00
0x085A,0x00
0x085B,0x00
0x085C,0x00
0x085D,0x00
0x085E,0x00
0x085F,0x00
0x0860,0x00
0x0861,0x00
0x090E,0x00
0x091C,0x04
0x0943,0x00
0x0949,0x03
0x094A,0x30
0x094E,0x49
0x094F,0x02
0x095E,0x00
0x0A02,0x00
0x0A03,0x03
0x0A04,0x01
0x0A05,0x03
0x0A14,0x00
0x0A1A,0x00
0x0A20,0x00
0x0A26,0x00
0x0A2C,0x00
0x0B44,0x0F
0x0B4A,0x1C
0x0B57,0xA5
0x0B58,0x00
# End configuration registers
#
# Start configuration postamble
0x001C,0x01
0x0B24,0xC3
0x0B25,0x02
# End configuration postamble

View File

@ -0,0 +1,412 @@
# Si534x/7x/8x/9x Registers Script
#
# Part: Si5341
# Project File: X:\Projects\verilog-ethernet\example\HTG9200\fpga_fmc_htg_6qsfp_25g\pll\HTG9200_HTG_FMC_6QSFP_161-HTG6Q161.slabtimeproj
# Design ID: HTG6Q161
# Includes Pre/Post Download Control Register Writes: Yes
# Die Revision: B1
# Creator: ClockBuilder Pro v4.1 [2021-09-22]
# Created On: 2023-07-19 01:56:52 GMT-07:00
Address,Data
#
# Start configuration preamble
0x0B24,0xC0
0x0B25,0x00
# Rev D stuck divider fix
0x0502,0x01
0x0505,0x03
0x0957,0x17
0x0B4E,0x1A
# End configuration preamble
#
# Delay 300 msec
# Delay is worst case time for device to complete any calibration
# that is running due to device state change previous to this script
# being processed.
#
# Start configuration registers
0x0006,0x00
0x0007,0x00
0x0008,0x00
0x000B,0x74
0x0017,0xD0
0x0018,0xFF
0x0021,0x0D
0x0022,0x00
0x002B,0x02
0x002C,0x34
0x002D,0x10
0x002E,0x00
0x002F,0x00
0x0030,0x00
0x0031,0x00
0x0032,0xA8
0x0033,0x00
0x0034,0x00
0x0035,0x00
0x0036,0x00
0x0037,0x00
0x0038,0x00
0x0039,0x00
0x003A,0xA8
0x003B,0x00
0x003C,0x00
0x003D,0x00
0x0041,0x00
0x0042,0x00
0x0043,0x07
0x0044,0x00
0x009E,0x00
0x0102,0x01
0x0108,0x06
0x0109,0x09
0x010A,0x33
0x010B,0x08
0x010D,0x06
0x010E,0x09
0x010F,0x33
0x0110,0x08
0x0112,0x06
0x0113,0x09
0x0114,0x33
0x0115,0x08
0x0117,0x06
0x0118,0x09
0x0119,0x33
0x011A,0x08
0x011C,0x06
0x011D,0x09
0x011E,0x33
0x011F,0x08
0x0121,0x06
0x0122,0x09
0x0123,0x33
0x0124,0x08
0x0126,0x06
0x0127,0x09
0x0128,0x33
0x0129,0x08
0x012B,0x06
0x012C,0x09
0x012D,0x33
0x012E,0x08
0x0130,0x06
0x0131,0x09
0x0132,0x33
0x0133,0x08
0x013A,0x01
0x013B,0x09
0x013C,0x3B
0x013D,0x28
0x013F,0x00
0x0140,0x00
0x0141,0x40
0x0206,0x00
0x0208,0x00
0x0209,0x00
0x020A,0x00
0x020B,0x00
0x020C,0x00
0x020D,0x00
0x020E,0x00
0x020F,0x00
0x0210,0x00
0x0211,0x00
0x0212,0x00
0x0213,0x00
0x0214,0x00
0x0215,0x00
0x0216,0x00
0x0217,0x00
0x0218,0x00
0x0219,0x00
0x021A,0x00
0x021B,0x00
0x021C,0x02
0x021D,0x00
0x021E,0x00
0x021F,0x00
0x0220,0x00
0x0221,0x00
0x0222,0x01
0x0223,0x00
0x0224,0x00
0x0225,0x00
0x0226,0x00
0x0227,0x00
0x0228,0x00
0x0229,0x00
0x022A,0x00
0x022B,0x00
0x022C,0x00
0x022D,0x00
0x022E,0x00
0x022F,0x00
0x0235,0x00
0x0236,0x00
0x0237,0x00
0x0238,0x00
0x0239,0x52
0x023A,0x00
0x023B,0x00
0x023C,0x00
0x023D,0x00
0x023E,0x80
0x024A,0x00
0x024B,0x00
0x024C,0x00
0x024D,0x00
0x024E,0x00
0x024F,0x00
0x0250,0x00
0x0251,0x00
0x0252,0x00
0x0253,0x00
0x0254,0x00
0x0255,0x00
0x0256,0x00
0x0257,0x00
0x0258,0x00
0x0259,0x00
0x025A,0x00
0x025B,0x00
0x025C,0x00
0x025D,0x00
0x025E,0x00
0x025F,0x00
0x0260,0x00
0x0261,0x00
0x0262,0x00
0x0263,0x00
0x0264,0x00
0x0268,0x00
0x0269,0x00
0x026A,0x00
0x026B,0x48
0x026C,0x54
0x026D,0x47
0x026E,0x36
0x026F,0x51
0x0270,0x31
0x0271,0x36
0x0272,0x31
0x0302,0x00
0x0303,0x00
0x0304,0x00
0x0305,0x80
0x0306,0x14
0x0307,0x00
0x0308,0x00
0x0309,0x00
0x030A,0x00
0x030B,0x80
0x030C,0x00
0x030D,0x00
0x030E,0x00
0x030F,0x00
0x0310,0x00
0x0311,0x00
0x0312,0x00
0x0313,0x00
0x0314,0x00
0x0315,0x00
0x0316,0x00
0x0317,0x00
0x0318,0x00
0x0319,0x00
0x031A,0x00
0x031B,0x00
0x031C,0x00
0x031D,0x00
0x031E,0x00
0x031F,0x00
0x0320,0x00
0x0321,0x00
0x0322,0x00
0x0323,0x00
0x0324,0x00
0x0325,0x00
0x0326,0x00
0x0327,0x00
0x0328,0x00
0x0329,0x00
0x032A,0x00
0x032B,0x00
0x032C,0x00
0x032D,0x00
0x032E,0x00
0x032F,0x00
0x0330,0x00
0x0331,0x00
0x0332,0x00
0x0333,0x00
0x0334,0x00
0x0335,0x00
0x0336,0x00
0x0337,0x00
0x0338,0x00
0x0339,0x1F
0x033B,0x00
0x033C,0x00
0x033D,0x00
0x033E,0x00
0x033F,0x00
0x0340,0x00
0x0341,0x00
0x0342,0x00
0x0343,0x00
0x0344,0x00
0x0345,0x00
0x0346,0x00
0x0347,0x00
0x0348,0x00
0x0349,0x00
0x034A,0x00
0x034B,0x00
0x034C,0x00
0x034D,0x00
0x034E,0x00
0x034F,0x00
0x0350,0x00
0x0351,0x00
0x0352,0x00
0x0353,0x00
0x0354,0x00
0x0355,0x00
0x0356,0x00
0x0357,0x00
0x0358,0x00
0x0359,0x00
0x035A,0x00
0x035B,0x00
0x035C,0x00
0x035D,0x00
0x035E,0x00
0x035F,0x00
0x0360,0x00
0x0361,0x00
0x0362,0x00
0x0802,0x00
0x0803,0x00
0x0804,0x00
0x0805,0x00
0x0806,0x00
0x0807,0x00
0x0808,0x00
0x0809,0x00
0x080A,0x00
0x080B,0x00
0x080C,0x00
0x080D,0x00
0x080E,0x00
0x080F,0x00
0x0810,0x00
0x0811,0x00
0x0812,0x00
0x0813,0x00
0x0814,0x00
0x0815,0x00
0x0816,0x00
0x0817,0x00
0x0818,0x00
0x0819,0x00
0x081A,0x00
0x081B,0x00
0x081C,0x00
0x081D,0x00
0x081E,0x00
0x081F,0x00
0x0820,0x00
0x0821,0x00
0x0822,0x00
0x0823,0x00
0x0824,0x00
0x0825,0x00
0x0826,0x00
0x0827,0x00
0x0828,0x00
0x0829,0x00
0x082A,0x00
0x082B,0x00
0x082C,0x00
0x082D,0x00
0x082E,0x00
0x082F,0x00
0x0830,0x00
0x0831,0x00
0x0832,0x00
0x0833,0x00
0x0834,0x00
0x0835,0x00
0x0836,0x00
0x0837,0x00
0x0838,0x00
0x0839,0x00
0x083A,0x00
0x083B,0x00
0x083C,0x00
0x083D,0x00
0x083E,0x00
0x083F,0x00
0x0840,0x00
0x0841,0x00
0x0842,0x00
0x0843,0x00
0x0844,0x00
0x0845,0x00
0x0846,0x00
0x0847,0x00
0x0848,0x00
0x0849,0x00
0x084A,0x00
0x084B,0x00
0x084C,0x00
0x084D,0x00
0x084E,0x00
0x084F,0x00
0x0850,0x00
0x0851,0x00
0x0852,0x00
0x0853,0x00
0x0854,0x00
0x0855,0x00
0x0856,0x00
0x0857,0x00
0x0858,0x00
0x0859,0x00
0x085A,0x00
0x085B,0x00
0x085C,0x00
0x085D,0x00
0x085E,0x00
0x085F,0x00
0x0860,0x00
0x0861,0x00
0x090E,0x00
0x091C,0x04
0x0943,0x00
0x0949,0x04
0x094A,0x40
0x094E,0x49
0x094F,0x02
0x095E,0x00
0x0A02,0x00
0x0A03,0x01
0x0A04,0x01
0x0A05,0x01
0x0A14,0x00
0x0A1A,0x00
0x0A20,0x00
0x0A26,0x00
0x0A2C,0x00
0x0B44,0x0F
0x0B4A,0x1E
0x0B57,0xA0
0x0B58,0x00
# End configuration registers
#
# Start configuration postamble
0x001C,0x01
0x0B24,0xC3
0x0B25,0x02
# End configuration postamble

View File

@ -0,0 +1,606 @@
#!/usr/bin/env python
"""
Generates an I2C init module for multiple chips
"""
from jinja2 import Template
def si5341_cmds(regs, dev_addr=0x77):
cur_page = None
cur_addr = None
cmds = []
print(f"Reading register list file '{regs}'...")
with open(regs, "r") as f:
for line in f:
line = line.strip()
if not line or line == "Address,Data":
continue
if line[0] == '#':
cmds.append(f"// {line[1:].strip()}")
if line.startswith("# Delay"):
cmds.append("9'b000011010; // delay 300 ms")
cur_addr = None
continue
d = line.split(",")
addr = int(d[0], 0)
page = (addr >> 8) & 0xff
data = int(d[1], 0)
if page != cur_page:
cmds.append(f"{{2'b01, 7'h{dev_addr:02x}}};")
cmds.append("{1'b1, 8'h01};")
cmds.append(f"{{1'b1, 8'h{page:02x}}}; // set page {page:#04x}")
cur_page = page
cur_addr = None
if addr != cur_addr:
cmds.append(f"{{2'b01, 7'h{dev_addr:02x}}};")
cmds.append(f"{{1'b1, 8'h{addr & 0xff:02x}}};")
cur_addr = addr
cmds.append(f"{{1'b1, 8'h{data:02x}}}; // write {data:#04x} to {addr:#06x}")
cur_addr += 1
return cmds
def mux_cmds(val, dev_addr):
cmds = []
cmds.append(f"{{2'b01, 7'h{dev_addr:02x}}};")
cmds.append(f"{{1'b1, 8'h{val:02x}}};")
cmds.append("9'b001000001; // I2C stop")
return cmds
def main():
cmds = []
cmds.append("// Initial delay")
cmds.append("9'b000010110; // delay 30 ms")
# Si5341 on HTG 9200
cmds.append("// Set muxes to select U48 Si5341 on HTG-9200")
cmds.extend(mux_cmds(0x00, 0x70))
cmds.extend(mux_cmds(0x04, 0x71))
cmds.extend(si5341_cmds("HTG9200_161-9k2_161-Registers.txt", 0x77))
# Si5341 on FMC+
cmds.append("// Set muxes to select U7 Si5341 on HTG-FMC-x6-QSFP28")
cmds.extend(mux_cmds(0x00, 0x70))
cmds.extend(mux_cmds(0x02, 0x71))
cmds.extend(si5341_cmds("HTG9200_HTG_FMC_6QSFP_161-HTG6Q161-Registers.txt", 0x77))
generate(cmds)
def generate(cmds=None, name=None, output=None):
if cmds is None:
raise Exception("Command list is required")
if name is None:
name = "si5341_i2c_init"
if output is None:
output = name + ".v"
print(f"Generating Si5341 I2C init module {name}...")
cmds.append("9'd0; // end")
cmd_str = ""
cmd_count = 0
for cmd in cmds:
if cmd.startswith('//'):
cmd_str += f" {cmd}\n"
else:
cmd_str += f" init_data[{cmd_count}] = {cmd}\n"
cmd_count += 1
t = Template(u"""/*
Copyright (c) 2015-2021 Alex Forencich
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
// Language: Verilog 2001
`resetall
`timescale 1ns / 1ps
`default_nettype none
/*
* {{name}}
*/
module {{name}} (
input wire clk,
input wire rst,
/*
* I2C master interface
*/
output wire [6:0] m_axis_cmd_address,
output wire m_axis_cmd_start,
output wire m_axis_cmd_read,
output wire m_axis_cmd_write,
output wire m_axis_cmd_write_multiple,
output wire m_axis_cmd_stop,
output wire m_axis_cmd_valid,
input wire m_axis_cmd_ready,
output wire [7:0] m_axis_data_tdata,
output wire m_axis_data_tvalid,
input wire m_axis_data_tready,
output wire m_axis_data_tlast,
/*
* Status
*/
output wire busy,
/*
* Configuration
*/
input wire start
);
/*
Generic module for I2C bus initialization. Good for use when multiple devices
on an I2C bus must be initialized on system start without intervention of a
general-purpose processor.
Copy this file and change init_data and INIT_DATA_LEN as needed.
This module can be used in two modes: simple device initialization, or multiple
device initialization. In multiple device mode, the same initialization sequence
can be performed on multiple different device addresses.
To use single device mode, only use the start write to address and write data commands.
The module will generate the I2C commands in sequential order. Terminate the list
with a 0 entry.
To use the multiple device mode, use the start data and start address block commands
to set up lists of initialization data and device addresses. The module enters
multiple device mode upon seeing a start data block command. The module stores the
offset of the start of the data block and then skips ahead until it reaches a start
address block command. The module will store the offset to the address block and
read the first address in the block. Then it will jump back to the data block
and execute it, substituting the stored address for each current address write
command. Upon reaching the start address block command, the module will read out the
next address and start again at the top of the data block. If the module encounters
a start data block command while looking for an address, then it will store a new data
offset and then look for a start address block command. Terminate the list with a 0
entry. Normal address commands will operate normally inside a data block.
Commands:
00 0000000 : stop
00 0000001 : exit multiple device mode
00 0000011 : start write to current address
00 0001000 : start address block
00 0001001 : start data block
00 001dddd : delay 2**(16+d) cycles
00 1000001 : send I2C stop
01 aaaaaaa : start write to address
1 dddddddd : write 8-bit data
Examples
write 0x11223344 to register 0x0004 on device at 0x50
01 1010000 start write to 0x50
1 00000000 write address 0x0004
1 00000100
1 00010001 write data 0x11223344
1 00100010
1 00110011
1 01000100
0 00000000 stop
write 0x11223344 to register 0x0004 on devices at 0x50, 0x51, 0x52, and 0x53
00 0001001 start data block
00 0000011 start write to current address
1 00000000 write address 0x0004
1 00000100
1 00010001 write data 0x11223344
1 00100010
1 00110011
1 01000100
00 0001000 start address block
01 1010000 address 0x50
01 1010001 address 0x51
01 1010010 address 0x52
01 1010011 address 0x53
00 0000000 stop
*/
// init_data ROM
localparam INIT_DATA_LEN = {{cmd_count}};
reg [8:0] init_data [INIT_DATA_LEN-1:0];
initial begin
{{cmd_str-}}
end
localparam [3:0]
STATE_IDLE = 3'd0,
STATE_RUN = 3'd1,
STATE_TABLE_1 = 3'd2,
STATE_TABLE_2 = 3'd3,
STATE_TABLE_3 = 3'd4;
reg [4:0] state_reg = STATE_IDLE, state_next;
parameter AW = $clog2(INIT_DATA_LEN);
reg [8:0] init_data_reg = 9'd0;
reg [AW-1:0] address_reg = {AW{1'b0}}, address_next;
reg [AW-1:0] address_ptr_reg = {AW{1'b0}}, address_ptr_next;
reg [AW-1:0] data_ptr_reg = {AW{1'b0}}, data_ptr_next;
reg [6:0] cur_address_reg = 7'd0, cur_address_next;
reg [31:0] delay_counter_reg = 32'd0, delay_counter_next;
reg [6:0] m_axis_cmd_address_reg = 7'd0, m_axis_cmd_address_next;
reg m_axis_cmd_start_reg = 1'b0, m_axis_cmd_start_next;
reg m_axis_cmd_write_reg = 1'b0, m_axis_cmd_write_next;
reg m_axis_cmd_stop_reg = 1'b0, m_axis_cmd_stop_next;
reg m_axis_cmd_valid_reg = 1'b0, m_axis_cmd_valid_next;
reg [7:0] m_axis_data_tdata_reg = 8'd0, m_axis_data_tdata_next;
reg m_axis_data_tvalid_reg = 1'b0, m_axis_data_tvalid_next;
reg start_flag_reg = 1'b0, start_flag_next;
reg busy_reg = 1'b0;
assign m_axis_cmd_address = m_axis_cmd_address_reg;
assign m_axis_cmd_start = m_axis_cmd_start_reg;
assign m_axis_cmd_read = 1'b0;
assign m_axis_cmd_write = m_axis_cmd_write_reg;
assign m_axis_cmd_write_multiple = 1'b0;
assign m_axis_cmd_stop = m_axis_cmd_stop_reg;
assign m_axis_cmd_valid = m_axis_cmd_valid_reg;
assign m_axis_data_tdata = m_axis_data_tdata_reg;
assign m_axis_data_tvalid = m_axis_data_tvalid_reg;
assign m_axis_data_tlast = 1'b1;
assign busy = busy_reg;
always @* begin
state_next = STATE_IDLE;
address_next = address_reg;
address_ptr_next = address_ptr_reg;
data_ptr_next = data_ptr_reg;
cur_address_next = cur_address_reg;
delay_counter_next = delay_counter_reg;
m_axis_cmd_address_next = m_axis_cmd_address_reg;
m_axis_cmd_start_next = m_axis_cmd_start_reg & ~(m_axis_cmd_valid & m_axis_cmd_ready);
m_axis_cmd_write_next = m_axis_cmd_write_reg & ~(m_axis_cmd_valid & m_axis_cmd_ready);
m_axis_cmd_stop_next = m_axis_cmd_stop_reg & ~(m_axis_cmd_valid & m_axis_cmd_ready);
m_axis_cmd_valid_next = m_axis_cmd_valid_reg & ~m_axis_cmd_ready;
m_axis_data_tdata_next = m_axis_data_tdata_reg;
m_axis_data_tvalid_next = m_axis_data_tvalid_reg & ~m_axis_data_tready;
start_flag_next = start_flag_reg;
if (m_axis_cmd_valid | m_axis_data_tvalid) begin
// wait for output registers to clear
state_next = state_reg;
end else if (delay_counter_reg != 0) begin
// delay
delay_counter_next = delay_counter_reg - 1;
state_next = state_reg;
end else begin
case (state_reg)
STATE_IDLE: begin
// wait for start signal
if (~start_flag_reg & start) begin
address_next = {AW{1'b0}};
start_flag_next = 1'b1;
state_next = STATE_RUN;
end else begin
state_next = STATE_IDLE;
end
end
STATE_RUN: begin
// process commands
if (init_data_reg[8] == 1'b1) begin
// write data
m_axis_cmd_write_next = 1'b1;
m_axis_cmd_stop_next = 1'b0;
m_axis_cmd_valid_next = 1'b1;
m_axis_data_tdata_next = init_data_reg[7:0];
m_axis_data_tvalid_next = 1'b1;
address_next = address_reg + 1;
state_next = STATE_RUN;
end else if (init_data_reg[8:7] == 2'b01) begin
// write address
m_axis_cmd_address_next = init_data_reg[6:0];
m_axis_cmd_start_next = 1'b1;
address_next = address_reg + 1;
state_next = STATE_RUN;
end else if (init_data_reg[8:4] == 5'b00001) begin
// delay
delay_counter_next = 32'd1 << (init_data_reg[3:0]+16);
address_next = address_reg + 1;
state_next = STATE_RUN;
end else if (init_data_reg == 9'b001000001) begin
// send stop
m_axis_cmd_write_next = 1'b0;
m_axis_cmd_start_next = 1'b0;
m_axis_cmd_stop_next = 1'b1;
m_axis_cmd_valid_next = 1'b1;
address_next = address_reg + 1;
state_next = STATE_RUN;
end else if (init_data_reg == 9'b000001001) begin
// data table start
data_ptr_next = address_reg + 1;
address_next = address_reg + 1;
state_next = STATE_TABLE_1;
end else if (init_data_reg == 9'd0) begin
// stop
m_axis_cmd_start_next = 1'b0;
m_axis_cmd_write_next = 1'b0;
m_axis_cmd_stop_next = 1'b1;
m_axis_cmd_valid_next = 1'b1;
state_next = STATE_IDLE;
end else begin
// invalid command, skip
address_next = address_reg + 1;
state_next = STATE_RUN;
end
end
STATE_TABLE_1: begin
// find address table start
if (init_data_reg == 9'b000001000) begin
// address table start
address_ptr_next = address_reg + 1;
address_next = address_reg + 1;
state_next = STATE_TABLE_2;
end else if (init_data_reg == 9'b000001001) begin
// data table start
data_ptr_next = address_reg + 1;
address_next = address_reg + 1;
state_next = STATE_TABLE_1;
end else if (init_data_reg == 1) begin
// exit mode
address_next = address_reg + 1;
state_next = STATE_RUN;
end else if (init_data_reg == 9'd0) begin
// stop
m_axis_cmd_start_next = 1'b0;
m_axis_cmd_write_next = 1'b0;
m_axis_cmd_stop_next = 1'b1;
m_axis_cmd_valid_next = 1'b1;
state_next = STATE_IDLE;
end else begin
// invalid command, skip
address_next = address_reg + 1;
state_next = STATE_TABLE_1;
end
end
STATE_TABLE_2: begin
// find next address
if (init_data_reg[8:7] == 2'b01) begin
// write address command
// store address and move to data table
cur_address_next = init_data_reg[6:0];
address_ptr_next = address_reg + 1;
address_next = data_ptr_reg;
state_next = STATE_TABLE_3;
end else if (init_data_reg == 9'b000001001) begin
// data table start
data_ptr_next = address_reg + 1;
address_next = address_reg + 1;
state_next = STATE_TABLE_1;
end else if (init_data_reg == 9'd1) begin
// exit mode
address_next = address_reg + 1;
state_next = STATE_RUN;
end else if (init_data_reg == 9'd0) begin
// stop
m_axis_cmd_start_next = 1'b0;
m_axis_cmd_write_next = 1'b0;
m_axis_cmd_stop_next = 1'b1;
m_axis_cmd_valid_next = 1'b1;
state_next = STATE_IDLE;
end else begin
// invalid command, skip
address_next = address_reg + 1;
state_next = STATE_TABLE_2;
end
end
STATE_TABLE_3: begin
// process data table with selected address
if (init_data_reg[8] == 1'b1) begin
// write data
m_axis_cmd_write_next = 1'b1;
m_axis_cmd_stop_next = 1'b0;
m_axis_cmd_valid_next = 1'b1;
m_axis_data_tdata_next = init_data_reg[7:0];
m_axis_data_tvalid_next = 1'b1;
address_next = address_reg + 1;
state_next = STATE_TABLE_3;
end else if (init_data_reg[8:7] == 2'b01) begin
// write address
m_axis_cmd_address_next = init_data_reg[6:0];
m_axis_cmd_start_next = 1'b1;
address_next = address_reg + 1;
state_next = STATE_TABLE_3;
end else if (init_data_reg == 9'b000000011) begin
// write current address
m_axis_cmd_address_next = cur_address_reg;
m_axis_cmd_start_next = 1'b1;
address_next = address_reg + 1;
state_next = STATE_TABLE_3;
end else if (init_data_reg == 9'b001000001) begin
// send stop
m_axis_cmd_write_next = 1'b0;
m_axis_cmd_start_next = 1'b0;
m_axis_cmd_stop_next = 1'b1;
m_axis_cmd_valid_next = 1'b1;
address_next = address_reg + 1;
state_next = STATE_TABLE_3;
end else if (init_data_reg == 9'b000001001) begin
// data table start
data_ptr_next = address_reg + 1;
address_next = address_reg + 1;
state_next = STATE_TABLE_1;
end else if (init_data_reg == 9'b000001000) begin
// address table start
address_next = address_ptr_reg;
state_next = STATE_TABLE_2;
end else if (init_data_reg == 9'd1) begin
// exit mode
address_next = address_reg + 1;
state_next = STATE_RUN;
end else if (init_data_reg == 9'd0) begin
// stop
m_axis_cmd_start_next = 1'b0;
m_axis_cmd_write_next = 1'b0;
m_axis_cmd_stop_next = 1'b1;
m_axis_cmd_valid_next = 1'b1;
state_next = STATE_IDLE;
end else begin
// invalid command, skip
address_next = address_reg + 1;
state_next = STATE_TABLE_3;
end
end
endcase
end
end
always @(posedge clk) begin
state_reg <= state_next;
// read init_data ROM
init_data_reg <= init_data[address_next];
address_reg <= address_next;
address_ptr_reg <= address_ptr_next;
data_ptr_reg <= data_ptr_next;
cur_address_reg <= cur_address_next;
delay_counter_reg <= delay_counter_next;
m_axis_cmd_address_reg <= m_axis_cmd_address_next;
m_axis_cmd_start_reg <= m_axis_cmd_start_next;
m_axis_cmd_write_reg <= m_axis_cmd_write_next;
m_axis_cmd_stop_reg <= m_axis_cmd_stop_next;
m_axis_cmd_valid_reg <= m_axis_cmd_valid_next;
m_axis_data_tdata_reg <= m_axis_data_tdata_next;
m_axis_data_tvalid_reg <= m_axis_data_tvalid_next;
start_flag_reg <= start & start_flag_next;
busy_reg <= (state_reg != STATE_IDLE);
if (rst) begin
state_reg <= STATE_IDLE;
init_data_reg <= 9'd0;
address_reg <= {AW{1'b0}};
address_ptr_reg <= {AW{1'b0}};
data_ptr_reg <= {AW{1'b0}};
cur_address_reg <= 7'd0;
delay_counter_reg <= 32'd0;
m_axis_cmd_valid_reg <= 1'b0;
m_axis_data_tvalid_reg <= 1'b0;
start_flag_reg <= 1'b0;
busy_reg <= 1'b0;
end
end
endmodule
`resetall
""")
print(f"Writing file '{output}'...")
with open(output, 'w') as f:
f.write(t.render(
cmd_str=cmd_str,
cmd_count=cmd_count,
name=name
))
f.flush()
print("Done")
if __name__ == "__main__":
main()

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,93 @@
/*
Copyright (c) 2014-2017 Alex Forencich
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
// Language: Verilog-2001
`resetall
`timescale 1 ns / 1 ps
`default_nettype none
/*
* Synchronizes switch and button inputs with a slow sampled shift register
*/
module debounce_switch #(
parameter WIDTH=1, // width of the input and output signals
parameter N=3, // length of shift register
parameter RATE=125000 // clock division factor
)(
input wire clk,
input wire rst,
input wire [WIDTH-1:0] in,
output wire [WIDTH-1:0] out
);
reg [23:0] cnt_reg = 24'd0;
reg [N-1:0] debounce_reg[WIDTH-1:0];
reg [WIDTH-1:0] state;
/*
* The synchronized output is the state register
*/
assign out = state;
integer k;
always @(posedge clk or posedge rst) begin
if (rst) begin
cnt_reg <= 0;
state <= 0;
for (k = 0; k < WIDTH; k = k + 1) begin
debounce_reg[k] <= 0;
end
end else begin
if (cnt_reg < RATE) begin
cnt_reg <= cnt_reg + 24'd1;
end else begin
cnt_reg <= 24'd0;
end
if (cnt_reg == 24'd0) begin
for (k = 0; k < WIDTH; k = k + 1) begin
debounce_reg[k] <= {debounce_reg[k][N-2:0], in[k]};
end
end
for (k = 0; k < WIDTH; k = k + 1) begin
if (|debounce_reg[k] == 0) begin
state[k] <= 0;
end else if (&debounce_reg[k] == 1) begin
state[k] <= 1;
end else begin
state[k] <= state[k];
end
end
end
end
endmodule
`resetall

View File

@ -0,0 +1,299 @@
/*
Copyright (c) 2021 Alex Forencich
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
// Language: Verilog 2001
`resetall
`timescale 1ns / 1ps
`default_nettype none
/*
* Transceiver and PHY wrapper
*/
module eth_xcvr_phy_wrapper #
(
parameter HAS_COMMON = 1,
parameter DATA_WIDTH = 64,
parameter CTRL_WIDTH = (DATA_WIDTH/8),
parameter HDR_WIDTH = 2,
parameter PRBS31_ENABLE = 0,
parameter TX_SERDES_PIPELINE = 0,
parameter RX_SERDES_PIPELINE = 0,
parameter BITSLIP_HIGH_CYCLES = 1,
parameter BITSLIP_LOW_CYCLES = 8,
parameter COUNT_125US = 125000/6.4
)
(
input wire xcvr_ctrl_clk,
input wire xcvr_ctrl_rst,
/*
* Common
*/
output wire xcvr_gtpowergood_out,
/*
* PLL out
*/
input wire xcvr_gtrefclk00_in,
output wire xcvr_qpll0lock_out,
output wire xcvr_qpll0outclk_out,
output wire xcvr_qpll0outrefclk_out,
/*
* PLL in
*/
input wire xcvr_qpll0lock_in,
output wire xcvr_qpll0reset_out,
input wire xcvr_qpll0clk_in,
input wire xcvr_qpll0refclk_in,
/*
* Serial data
*/
output wire xcvr_txp,
output wire xcvr_txn,
input wire xcvr_rxp,
input wire xcvr_rxn,
/*
* PHY connections
*/
output wire phy_tx_clk,
output wire phy_tx_rst,
input wire [DATA_WIDTH-1:0] phy_xgmii_txd,
input wire [CTRL_WIDTH-1:0] phy_xgmii_txc,
output wire phy_rx_clk,
output wire phy_rx_rst,
output wire [DATA_WIDTH-1:0] phy_xgmii_rxd,
output wire [CTRL_WIDTH-1:0] phy_xgmii_rxc,
output wire phy_tx_bad_block,
output wire [6:0] phy_rx_error_count,
output wire phy_rx_bad_block,
output wire phy_rx_sequence_error,
output wire phy_rx_block_lock,
output wire phy_rx_high_ber,
input wire phy_tx_prbs31_enable,
input wire phy_rx_prbs31_enable
);
wire phy_rx_reset_req;
wire gt_reset_tx_datapath = 1'b0;
wire gt_reset_rx_datapath = phy_rx_reset_req;
wire gt_reset_tx_done;
wire gt_reset_rx_done;
wire [5:0] gt_txheader;
wire [63:0] gt_txdata;
wire gt_rxgearboxslip;
wire [5:0] gt_rxheader;
wire [1:0] gt_rxheadervalid;
wire [63:0] gt_rxdata;
wire [1:0] gt_rxdatavalid;
generate
if (HAS_COMMON) begin : xcvr
eth_xcvr_gt_full
eth_xcvr_gt_full_inst (
// Common
.gtwiz_reset_clk_freerun_in(xcvr_ctrl_clk),
.gtwiz_reset_all_in(xcvr_ctrl_rst),
.gtpowergood_out(xcvr_gtpowergood_out),
// PLL
.gtrefclk00_in(xcvr_gtrefclk00_in),
.qpll0lock_out(xcvr_qpll0lock_out),
.qpll0outclk_out(xcvr_qpll0outclk_out),
.qpll0outrefclk_out(xcvr_qpll0outrefclk_out),
// Serial data
.gtytxp_out(xcvr_txp),
.gtytxn_out(xcvr_txn),
.gtyrxp_in(xcvr_rxp),
.gtyrxn_in(xcvr_rxn),
// Transmit
.gtwiz_userclk_tx_reset_in(1'b0),
.gtwiz_userclk_tx_srcclk_out(),
.gtwiz_userclk_tx_usrclk_out(),
.gtwiz_userclk_tx_usrclk2_out(phy_tx_clk),
.gtwiz_userclk_tx_active_out(),
.gtwiz_reset_tx_pll_and_datapath_in(1'b0),
.gtwiz_reset_tx_datapath_in(gt_reset_tx_datapath),
.gtwiz_reset_tx_done_out(gt_reset_tx_done),
.txpmaresetdone_out(),
.txprgdivresetdone_out(),
.gtwiz_userdata_tx_in(gt_txdata),
.txheader_in(gt_txheader),
.txsequence_in(7'b0),
// Receive
.gtwiz_userclk_rx_reset_in(1'b0),
.gtwiz_userclk_rx_srcclk_out(),
.gtwiz_userclk_rx_usrclk_out(),
.gtwiz_userclk_rx_usrclk2_out(phy_rx_clk),
.gtwiz_userclk_rx_active_out(),
.gtwiz_reset_rx_pll_and_datapath_in(1'b0),
.gtwiz_reset_rx_datapath_in(gt_reset_rx_datapath),
.gtwiz_reset_rx_cdr_stable_out(),
.gtwiz_reset_rx_done_out(gt_reset_rx_done),
.rxpmaresetdone_out(),
.rxprgdivresetdone_out(),
.rxgearboxslip_in(gt_rxgearboxslip),
.gtwiz_userdata_rx_out(gt_rxdata),
.rxdatavalid_out(gt_rxdatavalid),
.rxheader_out(gt_rxheader),
.rxheadervalid_out(gt_rxheadervalid),
.rxstartofseq_out()
);
end else begin : xcvr
eth_xcvr_gt_channel
eth_xcvr_gt_channel_inst (
// Common
.gtwiz_reset_clk_freerun_in(xcvr_ctrl_clk),
.gtwiz_reset_all_in(xcvr_ctrl_rst),
.gtpowergood_out(xcvr_gtpowergood_out),
// PLL
.gtwiz_reset_qpll0lock_in(xcvr_qpll0lock_in),
.gtwiz_reset_qpll0reset_out(xcvr_qpll0reset_out),
.qpll0clk_in(xcvr_qpll0clk_in),
.qpll0refclk_in(xcvr_qpll0refclk_in),
.qpll1clk_in(1'b0),
.qpll1refclk_in(1'b0),
// Serial data
.gtytxp_out(xcvr_txp),
.gtytxn_out(xcvr_txn),
.gtyrxp_in(xcvr_rxp),
.gtyrxn_in(xcvr_rxn),
// Transmit
.gtwiz_userclk_tx_reset_in(1'b0),
.gtwiz_userclk_tx_srcclk_out(),
.gtwiz_userclk_tx_usrclk_out(),
.gtwiz_userclk_tx_usrclk2_out(phy_tx_clk),
.gtwiz_userclk_tx_active_out(),
.gtwiz_reset_tx_pll_and_datapath_in(1'b0),
.gtwiz_reset_tx_datapath_in(gt_reset_tx_datapath),
.gtwiz_reset_tx_done_out(gt_reset_tx_done),
.txpmaresetdone_out(),
.txprgdivresetdone_out(),
.gtwiz_userdata_tx_in(gt_txdata),
.txheader_in(gt_txheader),
.txsequence_in(7'b0),
// Receive
.gtwiz_userclk_rx_reset_in(1'b0),
.gtwiz_userclk_rx_srcclk_out(),
.gtwiz_userclk_rx_usrclk_out(),
.gtwiz_userclk_rx_usrclk2_out(phy_rx_clk),
.gtwiz_userclk_rx_active_out(),
.gtwiz_reset_rx_pll_and_datapath_in(1'b0),
.gtwiz_reset_rx_datapath_in(gt_reset_rx_datapath),
.gtwiz_reset_rx_cdr_stable_out(),
.gtwiz_reset_rx_done_out(gt_reset_rx_done),
.rxpmaresetdone_out(),
.rxprgdivresetdone_out(),
.rxgearboxslip_in(gt_rxgearboxslip),
.gtwiz_userdata_rx_out(gt_rxdata),
.rxdatavalid_out(gt_rxdatavalid),
.rxheader_out(gt_rxheader),
.rxheadervalid_out(gt_rxheadervalid),
.rxstartofseq_out()
);
end
endgenerate
sync_reset #(
.N(4)
)
tx_reset_sync_inst (
.clk(phy_tx_clk),
.rst(!gt_reset_tx_done),
.out(phy_tx_rst)
);
sync_reset #(
.N(4)
)
rx_reset_sync_inst (
.clk(phy_rx_clk),
.rst(!gt_reset_rx_done),
.out(phy_rx_rst)
);
eth_phy_10g #(
.DATA_WIDTH(DATA_WIDTH),
.CTRL_WIDTH(CTRL_WIDTH),
.HDR_WIDTH(HDR_WIDTH),
.BIT_REVERSE(1),
.SCRAMBLER_DISABLE(0),
.PRBS31_ENABLE(PRBS31_ENABLE),
.TX_SERDES_PIPELINE(TX_SERDES_PIPELINE),
.RX_SERDES_PIPELINE(RX_SERDES_PIPELINE),
.BITSLIP_HIGH_CYCLES(BITSLIP_HIGH_CYCLES),
.BITSLIP_LOW_CYCLES(BITSLIP_LOW_CYCLES),
.COUNT_125US(COUNT_125US)
)
phy_inst (
.tx_clk(phy_tx_clk),
.tx_rst(phy_tx_rst),
.rx_clk(phy_rx_clk),
.rx_rst(phy_rx_rst),
.xgmii_txd(phy_xgmii_txd),
.xgmii_txc(phy_xgmii_txc),
.xgmii_rxd(phy_xgmii_rxd),
.xgmii_rxc(phy_xgmii_rxc),
.serdes_tx_data(gt_txdata),
.serdes_tx_hdr(gt_txheader),
.serdes_rx_data(gt_rxdata),
.serdes_rx_hdr(gt_rxheader),
.serdes_rx_bitslip(gt_rxgearboxslip),
.serdes_rx_reset_req(phy_rx_reset_req),
.tx_bad_block(phy_tx_bad_block),
.rx_error_count(phy_rx_error_count),
.rx_bad_block(phy_rx_bad_block),
.rx_sequence_error(phy_rx_sequence_error),
.rx_block_lock(phy_rx_block_lock),
.rx_high_ber(phy_rx_high_ber),
.tx_prbs31_enable(phy_tx_prbs31_enable),
.rx_prbs31_enable(phy_rx_prbs31_enable)
);
endmodule
`resetall

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,901 @@
/*
Copyright (c) 2015-2017 Alex Forencich
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
// Language: Verilog 2001
`resetall
`timescale 1ns / 1ps
`default_nettype none
/*
* I2C master
*/
module i2c_master (
input wire clk,
input wire rst,
/*
* Host interface
*/
input wire [6:0] s_axis_cmd_address,
input wire s_axis_cmd_start,
input wire s_axis_cmd_read,
input wire s_axis_cmd_write,
input wire s_axis_cmd_write_multiple,
input wire s_axis_cmd_stop,
input wire s_axis_cmd_valid,
output wire s_axis_cmd_ready,
input wire [7:0] s_axis_data_tdata,
input wire s_axis_data_tvalid,
output wire s_axis_data_tready,
input wire s_axis_data_tlast,
output wire [7:0] m_axis_data_tdata,
output wire m_axis_data_tvalid,
input wire m_axis_data_tready,
output wire m_axis_data_tlast,
/*
* I2C interface
*/
input wire scl_i,
output wire scl_o,
output wire scl_t,
input wire sda_i,
output wire sda_o,
output wire sda_t,
/*
* Status
*/
output wire busy,
output wire bus_control,
output wire bus_active,
output wire missed_ack,
/*
* Configuration
*/
input wire [15:0] prescale,
input wire stop_on_idle
);
/*
I2C
Read
__ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ __
sda \__/_6_X_5_X_4_X_3_X_2_X_1_X_0_\_R___A_/_7_X_6_X_5_X_4_X_3_X_2_X_1_X_0_\_A_/_7_X_6_X_5_X_4_X_3_X_2_X_1_X_0_\_A____/
____ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ____
scl ST \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ SP
Write
__ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ __
sda \__/_6_X_5_X_4_X_3_X_2_X_1_X_0_/ W \_A_/_7_X_6_X_5_X_4_X_3_X_2_X_1_X_0_\_A_/_7_X_6_X_5_X_4_X_3_X_2_X_1_X_0_/ N \__/
____ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ____
scl ST \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ SP
Commands:
read
read data byte
set start to force generation of a start condition
start is implied when bus is inactive or active with write or different address
set stop to issue a stop condition after reading current byte
if stop is set with read command, then m_axis_data_tlast will be set
write
write data byte
set start to force generation of a start condition
start is implied when bus is inactive or active with read or different address
set stop to issue a stop condition after writing current byte
write multiple
write multiple data bytes (until s_axis_data_tlast)
set start to force generation of a start condition
start is implied when bus is inactive or active with read or different address
set stop to issue a stop condition after writing block
stop
issue stop condition if bus is active
Status:
busy
module is communicating over the bus
bus_control
module has control of bus in active state
bus_active
bus is active, not necessarily controlled by this module
missed_ack
strobed when a slave ack is missed
Parameters:
prescale
set prescale to 1/4 of the minimum clock period in units
of input clk cycles (prescale = Fclk / (FI2Cclk * 4))
stop_on_idle
automatically issue stop when command input is not valid
Example of interfacing with tristate pins:
(this will work for any tristate bus)
assign scl_i = scl_pin;
assign scl_pin = scl_t ? 1'bz : scl_o;
assign sda_i = sda_pin;
assign sda_pin = sda_t ? 1'bz : sda_o;
Equivalent code that does not use *_t connections:
(we can get away with this because I2C is open-drain)
assign scl_i = scl_pin;
assign scl_pin = scl_o ? 1'bz : 1'b0;
assign sda_i = sda_pin;
assign sda_pin = sda_o ? 1'bz : 1'b0;
Example of two interconnected I2C devices:
assign scl_1_i = scl_1_o & scl_2_o;
assign scl_2_i = scl_1_o & scl_2_o;
assign sda_1_i = sda_1_o & sda_2_o;
assign sda_2_i = sda_1_o & sda_2_o;
Example of two I2C devices sharing the same pins:
assign scl_1_i = scl_pin;
assign scl_2_i = scl_pin;
assign scl_pin = (scl_1_o & scl_2_o) ? 1'bz : 1'b0;
assign sda_1_i = sda_pin;
assign sda_2_i = sda_pin;
assign sda_pin = (sda_1_o & sda_2_o) ? 1'bz : 1'b0;
Notes:
scl_o should not be connected directly to scl_i, only via AND logic or a tristate
I/O pin. This would prevent devices from stretching the clock period.
*/
localparam [4:0]
STATE_IDLE = 4'd0,
STATE_ACTIVE_WRITE = 4'd1,
STATE_ACTIVE_READ = 4'd2,
STATE_START_WAIT = 4'd3,
STATE_START = 4'd4,
STATE_ADDRESS_1 = 4'd5,
STATE_ADDRESS_2 = 4'd6,
STATE_WRITE_1 = 4'd7,
STATE_WRITE_2 = 4'd8,
STATE_WRITE_3 = 4'd9,
STATE_READ = 4'd10,
STATE_STOP = 4'd11;
reg [4:0] state_reg = STATE_IDLE, state_next;
localparam [4:0]
PHY_STATE_IDLE = 5'd0,
PHY_STATE_ACTIVE = 5'd1,
PHY_STATE_REPEATED_START_1 = 5'd2,
PHY_STATE_REPEATED_START_2 = 5'd3,
PHY_STATE_START_1 = 5'd4,
PHY_STATE_START_2 = 5'd5,
PHY_STATE_WRITE_BIT_1 = 5'd6,
PHY_STATE_WRITE_BIT_2 = 5'd7,
PHY_STATE_WRITE_BIT_3 = 5'd8,
PHY_STATE_READ_BIT_1 = 5'd9,
PHY_STATE_READ_BIT_2 = 5'd10,
PHY_STATE_READ_BIT_3 = 5'd11,
PHY_STATE_READ_BIT_4 = 5'd12,
PHY_STATE_STOP_1 = 5'd13,
PHY_STATE_STOP_2 = 5'd14,
PHY_STATE_STOP_3 = 5'd15;
reg [4:0] phy_state_reg = STATE_IDLE, phy_state_next;
reg phy_start_bit;
reg phy_stop_bit;
reg phy_write_bit;
reg phy_read_bit;
reg phy_release_bus;
reg phy_tx_data;
reg phy_rx_data_reg = 1'b0, phy_rx_data_next;
reg [6:0] addr_reg = 7'd0, addr_next;
reg [7:0] data_reg = 8'd0, data_next;
reg last_reg = 1'b0, last_next;
reg mode_read_reg = 1'b0, mode_read_next;
reg mode_write_multiple_reg = 1'b0, mode_write_multiple_next;
reg mode_stop_reg = 1'b0, mode_stop_next;
reg [16:0] delay_reg = 16'd0, delay_next;
reg delay_scl_reg = 1'b0, delay_scl_next;
reg delay_sda_reg = 1'b0, delay_sda_next;
reg [3:0] bit_count_reg = 4'd0, bit_count_next;
reg s_axis_cmd_ready_reg = 1'b0, s_axis_cmd_ready_next;
reg s_axis_data_tready_reg = 1'b0, s_axis_data_tready_next;
reg [7:0] m_axis_data_tdata_reg = 8'd0, m_axis_data_tdata_next;
reg m_axis_data_tvalid_reg = 1'b0, m_axis_data_tvalid_next;
reg m_axis_data_tlast_reg = 1'b0, m_axis_data_tlast_next;
reg scl_i_reg = 1'b1;
reg sda_i_reg = 1'b1;
reg scl_o_reg = 1'b1, scl_o_next;
reg sda_o_reg = 1'b1, sda_o_next;
reg last_scl_i_reg = 1'b1;
reg last_sda_i_reg = 1'b1;
reg busy_reg = 1'b0;
reg bus_active_reg = 1'b0;
reg bus_control_reg = 1'b0, bus_control_next;
reg missed_ack_reg = 1'b0, missed_ack_next;
assign s_axis_cmd_ready = s_axis_cmd_ready_reg;
assign s_axis_data_tready = s_axis_data_tready_reg;
assign m_axis_data_tdata = m_axis_data_tdata_reg;
assign m_axis_data_tvalid = m_axis_data_tvalid_reg;
assign m_axis_data_tlast = m_axis_data_tlast_reg;
assign scl_o = scl_o_reg;
assign scl_t = scl_o_reg;
assign sda_o = sda_o_reg;
assign sda_t = sda_o_reg;
assign busy = busy_reg;
assign bus_active = bus_active_reg;
assign bus_control = bus_control_reg;
assign missed_ack = missed_ack_reg;
wire scl_posedge = scl_i_reg & ~last_scl_i_reg;
wire scl_negedge = ~scl_i_reg & last_scl_i_reg;
wire sda_posedge = sda_i_reg & ~last_sda_i_reg;
wire sda_negedge = ~sda_i_reg & last_sda_i_reg;
wire start_bit = sda_negedge & scl_i_reg;
wire stop_bit = sda_posedge & scl_i_reg;
always @* begin
state_next = STATE_IDLE;
phy_start_bit = 1'b0;
phy_stop_bit = 1'b0;
phy_write_bit = 1'b0;
phy_read_bit = 1'b0;
phy_tx_data = 1'b0;
phy_release_bus = 1'b0;
addr_next = addr_reg;
data_next = data_reg;
last_next = last_reg;
mode_read_next = mode_read_reg;
mode_write_multiple_next = mode_write_multiple_reg;
mode_stop_next = mode_stop_reg;
bit_count_next = bit_count_reg;
s_axis_cmd_ready_next = 1'b0;
s_axis_data_tready_next = 1'b0;
m_axis_data_tdata_next = m_axis_data_tdata_reg;
m_axis_data_tvalid_next = m_axis_data_tvalid_reg & ~m_axis_data_tready;
m_axis_data_tlast_next = m_axis_data_tlast_reg;
missed_ack_next = 1'b0;
// generate delays
if (phy_state_reg != PHY_STATE_IDLE && phy_state_reg != PHY_STATE_ACTIVE) begin
// wait for phy operation
state_next = state_reg;
end else begin
// process states
case (state_reg)
STATE_IDLE: begin
// line idle
s_axis_cmd_ready_next = 1'b1;
if (s_axis_cmd_ready & s_axis_cmd_valid) begin
// command valid
if (s_axis_cmd_read ^ (s_axis_cmd_write | s_axis_cmd_write_multiple)) begin
// read or write command
addr_next = s_axis_cmd_address;
mode_read_next = s_axis_cmd_read;
mode_write_multiple_next = s_axis_cmd_write_multiple;
mode_stop_next = s_axis_cmd_stop;
s_axis_cmd_ready_next = 1'b0;
// start bit
if (bus_active) begin
state_next = STATE_START_WAIT;
end else begin
phy_start_bit = 1'b1;
bit_count_next = 4'd8;
state_next = STATE_ADDRESS_1;
end
end else begin
// invalid or unspecified - ignore
state_next = STATE_IDLE;
end
end else begin
state_next = STATE_IDLE;
end
end
STATE_ACTIVE_WRITE: begin
// line active with current address and read/write mode
s_axis_cmd_ready_next = 1'b1;
if (s_axis_cmd_ready & s_axis_cmd_valid) begin
// command valid
if (s_axis_cmd_read ^ (s_axis_cmd_write | s_axis_cmd_write_multiple)) begin
// read or write command
addr_next = s_axis_cmd_address;
mode_read_next = s_axis_cmd_read;
mode_write_multiple_next = s_axis_cmd_write_multiple;
mode_stop_next = s_axis_cmd_stop;
s_axis_cmd_ready_next = 1'b0;
if (s_axis_cmd_start || s_axis_cmd_address != addr_reg || s_axis_cmd_read) begin
// address or mode mismatch or forced start - repeated start
// repeated start bit
phy_start_bit = 1'b1;
bit_count_next = 4'd8;
state_next = STATE_ADDRESS_1;
end else begin
// address and mode match
// start write
s_axis_data_tready_next = 1'b1;
state_next = STATE_WRITE_1;
end
end else if (s_axis_cmd_stop && !(s_axis_cmd_read || s_axis_cmd_write || s_axis_cmd_write_multiple)) begin
// stop command
phy_stop_bit = 1'b1;
state_next = STATE_IDLE;
end else begin
// invalid or unspecified - ignore
state_next = STATE_ACTIVE_WRITE;
end
end else begin
if (stop_on_idle & s_axis_cmd_ready & ~s_axis_cmd_valid) begin
// no waiting command and stop_on_idle selected, issue stop condition
phy_stop_bit = 1'b1;
state_next = STATE_IDLE;
end else begin
state_next = STATE_ACTIVE_WRITE;
end
end
end
STATE_ACTIVE_READ: begin
// line active to current address
s_axis_cmd_ready_next = ~m_axis_data_tvalid;
if (s_axis_cmd_ready & s_axis_cmd_valid) begin
// command valid
if (s_axis_cmd_read ^ (s_axis_cmd_write | s_axis_cmd_write_multiple)) begin
// read or write command
addr_next = s_axis_cmd_address;
mode_read_next = s_axis_cmd_read;
mode_write_multiple_next = s_axis_cmd_write_multiple;
mode_stop_next = s_axis_cmd_stop;
s_axis_cmd_ready_next = 1'b0;
if (s_axis_cmd_start || s_axis_cmd_address != addr_reg || s_axis_cmd_write) begin
// address or mode mismatch or forced start - repeated start
// write nack for previous read
phy_write_bit = 1'b1;
phy_tx_data = 1'b1;
// repeated start bit
state_next = STATE_START;
end else begin
// address and mode match
// write ack for previous read
phy_write_bit = 1'b1;
phy_tx_data = 1'b0;
// start next read
bit_count_next = 4'd8;
data_next = 8'd0;
state_next = STATE_READ;
end
end else if (s_axis_cmd_stop && !(s_axis_cmd_read || s_axis_cmd_write || s_axis_cmd_write_multiple)) begin
// stop command
// write nack for previous read
phy_write_bit = 1'b1;
phy_tx_data = 1'b1;
// send stop bit
state_next = STATE_STOP;
end else begin
// invalid or unspecified - ignore
state_next = STATE_ACTIVE_READ;
end
end else begin
if (stop_on_idle & s_axis_cmd_ready & ~s_axis_cmd_valid) begin
// no waiting command and stop_on_idle selected, issue stop condition
// write ack for previous read
phy_write_bit = 1'b1;
phy_tx_data = 1'b1;
// send stop bit
state_next = STATE_STOP;
end else begin
state_next = STATE_ACTIVE_READ;
end
end
end
STATE_START_WAIT: begin
// wait for bus idle
if (bus_active) begin
state_next = STATE_START_WAIT;
end else begin
// bus is idle, take control
phy_start_bit = 1'b1;
bit_count_next = 4'd8;
state_next = STATE_ADDRESS_1;
end
end
STATE_START: begin
// send start bit
phy_start_bit = 1'b1;
bit_count_next = 4'd8;
state_next = STATE_ADDRESS_1;
end
STATE_ADDRESS_1: begin
// send address
bit_count_next = bit_count_reg - 1;
if (bit_count_reg > 1) begin
// send address
phy_write_bit = 1'b1;
phy_tx_data = addr_reg[bit_count_reg-2];
state_next = STATE_ADDRESS_1;
end else if (bit_count_reg > 0) begin
// send read/write bit
phy_write_bit = 1'b1;
phy_tx_data = mode_read_reg;
state_next = STATE_ADDRESS_1;
end else begin
// read ack bit
phy_read_bit = 1'b1;
state_next = STATE_ADDRESS_2;
end
end
STATE_ADDRESS_2: begin
// read ack bit
missed_ack_next = phy_rx_data_reg;
if (mode_read_reg) begin
// start read
bit_count_next = 4'd8;
data_next = 1'b0;
state_next = STATE_READ;
end else begin
// start write
s_axis_data_tready_next = 1'b1;
state_next = STATE_WRITE_1;
end
end
STATE_WRITE_1: begin
s_axis_data_tready_next = 1'b1;
if (s_axis_data_tready & s_axis_data_tvalid) begin
// got data, start write
data_next = s_axis_data_tdata;
last_next = s_axis_data_tlast;
bit_count_next = 4'd8;
s_axis_data_tready_next = 1'b0;
state_next = STATE_WRITE_2;
end else begin
// wait for data
state_next = STATE_WRITE_1;
end
end
STATE_WRITE_2: begin
// send data
bit_count_next = bit_count_reg - 1;
if (bit_count_reg > 0) begin
// write data bit
phy_write_bit = 1'b1;
phy_tx_data = data_reg[bit_count_reg-1];
state_next = STATE_WRITE_2;
end else begin
// read ack bit
phy_read_bit = 1'b1;
state_next = STATE_WRITE_3;
end
end
STATE_WRITE_3: begin
// read ack bit
missed_ack_next = phy_rx_data_reg;
if (mode_write_multiple_reg && !last_reg) begin
// more to write
state_next = STATE_WRITE_1;
end else if (mode_stop_reg) begin
// last cycle and stop selected
phy_stop_bit = 1'b1;
state_next = STATE_IDLE;
end else begin
// otherwise, return to bus active state
state_next = STATE_ACTIVE_WRITE;
end
end
STATE_READ: begin
// read data
bit_count_next = bit_count_reg - 1;
data_next = {data_reg[6:0], phy_rx_data_reg};
if (bit_count_reg > 0) begin
// read next bit
phy_read_bit = 1'b1;
state_next = STATE_READ;
end else begin
// output data word
m_axis_data_tdata_next = data_next;
m_axis_data_tvalid_next = 1'b1;
m_axis_data_tlast_next = 1'b0;
if (mode_stop_reg) begin
// send nack and stop
m_axis_data_tlast_next = 1'b1;
phy_write_bit = 1'b1;
phy_tx_data = 1'b1;
state_next = STATE_STOP;
end else begin
// return to bus active state
state_next = STATE_ACTIVE_READ;
end
end
end
STATE_STOP: begin
// send stop bit
phy_stop_bit = 1'b1;
state_next = STATE_IDLE;
end
endcase
end
end
always @* begin
phy_state_next = PHY_STATE_IDLE;
phy_rx_data_next = phy_rx_data_reg;
delay_next = delay_reg;
delay_scl_next = delay_scl_reg;
delay_sda_next = delay_sda_reg;
scl_o_next = scl_o_reg;
sda_o_next = sda_o_reg;
bus_control_next = bus_control_reg;
if (phy_release_bus) begin
// release bus and return to idle state
sda_o_next = 1'b1;
scl_o_next = 1'b1;
delay_scl_next = 1'b0;
delay_sda_next = 1'b0;
delay_next = 1'b0;
phy_state_next = PHY_STATE_IDLE;
end else if (delay_scl_reg) begin
// wait for SCL to match command
delay_scl_next = scl_o_reg & ~scl_i_reg;
phy_state_next = phy_state_reg;
end else if (delay_sda_reg) begin
// wait for SDA to match command
delay_sda_next = sda_o_reg & ~sda_i_reg;
phy_state_next = phy_state_reg;
end else if (delay_reg > 0) begin
// time delay
delay_next = delay_reg - 1;
phy_state_next = phy_state_reg;
end else begin
case (phy_state_reg)
PHY_STATE_IDLE: begin
// bus idle - wait for start command
sda_o_next = 1'b1;
scl_o_next = 1'b1;
if (phy_start_bit) begin
sda_o_next = 1'b0;
delay_next = prescale;
phy_state_next = PHY_STATE_START_1;
end else begin
phy_state_next = PHY_STATE_IDLE;
end
end
PHY_STATE_ACTIVE: begin
// bus active
if (phy_start_bit) begin
sda_o_next = 1'b1;
delay_next = prescale;
phy_state_next = PHY_STATE_REPEATED_START_1;
end else if (phy_write_bit) begin
sda_o_next = phy_tx_data;
delay_next = prescale;
phy_state_next = PHY_STATE_WRITE_BIT_1;
end else if (phy_read_bit) begin
sda_o_next = 1'b1;
delay_next = prescale;
phy_state_next = PHY_STATE_READ_BIT_1;
end else if (phy_stop_bit) begin
sda_o_next = 1'b0;
delay_next = prescale;
phy_state_next = PHY_STATE_STOP_1;
end else begin
phy_state_next = PHY_STATE_ACTIVE;
end
end
PHY_STATE_REPEATED_START_1: begin
// generate repeated start bit
// ______
// sda XXX/ \_______
// _______
// scl ______/ \___
//
scl_o_next = 1'b1;
delay_scl_next = 1'b1;
delay_next = prescale;
phy_state_next = PHY_STATE_REPEATED_START_2;
end
PHY_STATE_REPEATED_START_2: begin
// generate repeated start bit
// ______
// sda XXX/ \_______
// _______
// scl ______/ \___
//
sda_o_next = 1'b0;
delay_next = prescale;
phy_state_next = PHY_STATE_START_1;
end
PHY_STATE_START_1: begin
// generate start bit
// ___
// sda \_______
// _______
// scl \___
//
scl_o_next = 1'b0;
delay_next = prescale;
phy_state_next = PHY_STATE_START_2;
end
PHY_STATE_START_2: begin
// generate start bit
// ___
// sda \_______
// _______
// scl \___
//
bus_control_next = 1'b1;
phy_state_next = PHY_STATE_ACTIVE;
end
PHY_STATE_WRITE_BIT_1: begin
// write bit
// ________
// sda X________X
// ____
// scl __/ \__
scl_o_next = 1'b1;
delay_scl_next = 1'b1;
delay_next = prescale << 1;
phy_state_next = PHY_STATE_WRITE_BIT_2;
end
PHY_STATE_WRITE_BIT_2: begin
// write bit
// ________
// sda X________X
// ____
// scl __/ \__
scl_o_next = 1'b0;
delay_next = prescale;
phy_state_next = PHY_STATE_WRITE_BIT_3;
end
PHY_STATE_WRITE_BIT_3: begin
// write bit
// ________
// sda X________X
// ____
// scl __/ \__
phy_state_next = PHY_STATE_ACTIVE;
end
PHY_STATE_READ_BIT_1: begin
// read bit
// ________
// sda X________X
// ____
// scl __/ \__
scl_o_next = 1'b1;
delay_scl_next = 1'b1;
delay_next = prescale;
phy_state_next = PHY_STATE_READ_BIT_2;
end
PHY_STATE_READ_BIT_2: begin
// read bit
// ________
// sda X________X
// ____
// scl __/ \__
phy_rx_data_next = sda_i_reg;
delay_next = prescale;
phy_state_next = PHY_STATE_READ_BIT_3;
end
PHY_STATE_READ_BIT_3: begin
// read bit
// ________
// sda X________X
// ____
// scl __/ \__
scl_o_next = 1'b0;
delay_next = prescale;
phy_state_next = PHY_STATE_READ_BIT_4;
end
PHY_STATE_READ_BIT_4: begin
// read bit
// ________
// sda X________X
// ____
// scl __/ \__
phy_state_next = PHY_STATE_ACTIVE;
end
PHY_STATE_STOP_1: begin
// stop bit
// ___
// sda XXX\_______/
// _______
// scl _______/
scl_o_next = 1'b1;
delay_scl_next = 1'b1;
delay_next = prescale;
phy_state_next = PHY_STATE_STOP_2;
end
PHY_STATE_STOP_2: begin
// stop bit
// ___
// sda XXX\_______/
// _______
// scl _______/
sda_o_next = 1'b1;
delay_next = prescale;
phy_state_next = PHY_STATE_STOP_3;
end
PHY_STATE_STOP_3: begin
// stop bit
// ___
// sda XXX\_______/
// _______
// scl _______/
bus_control_next = 1'b0;
phy_state_next = PHY_STATE_IDLE;
end
endcase
end
end
always @(posedge clk) begin
state_reg <= state_next;
phy_state_reg <= phy_state_next;
phy_rx_data_reg <= phy_rx_data_next;
addr_reg <= addr_next;
data_reg <= data_next;
last_reg <= last_next;
mode_read_reg <= mode_read_next;
mode_write_multiple_reg <= mode_write_multiple_next;
mode_stop_reg <= mode_stop_next;
delay_reg <= delay_next;
delay_scl_reg <= delay_scl_next;
delay_sda_reg <= delay_sda_next;
bit_count_reg <= bit_count_next;
s_axis_cmd_ready_reg <= s_axis_cmd_ready_next;
s_axis_data_tready_reg <= s_axis_data_tready_next;
m_axis_data_tdata_reg <= m_axis_data_tdata_next;
m_axis_data_tlast_reg <= m_axis_data_tlast_next;
m_axis_data_tvalid_reg <= m_axis_data_tvalid_next;
scl_i_reg <= scl_i;
sda_i_reg <= sda_i;
scl_o_reg <= scl_o_next;
sda_o_reg <= sda_o_next;
last_scl_i_reg <= scl_i_reg;
last_sda_i_reg <= sda_i_reg;
busy_reg <= !(state_reg == STATE_IDLE || state_reg == STATE_ACTIVE_WRITE || state_reg == STATE_ACTIVE_READ) || !(phy_state_reg == PHY_STATE_IDLE || phy_state_reg == PHY_STATE_ACTIVE);
if (start_bit) begin
bus_active_reg <= 1'b1;
end else if (stop_bit) begin
bus_active_reg <= 1'b0;
end else begin
bus_active_reg <= bus_active_reg;
end
bus_control_reg <= bus_control_next;
missed_ack_reg <= missed_ack_next;
if (rst) begin
state_reg <= STATE_IDLE;
phy_state_reg <= PHY_STATE_IDLE;
delay_reg <= 16'd0;
delay_scl_reg <= 1'b0;
delay_sda_reg <= 1'b0;
s_axis_cmd_ready_reg <= 1'b0;
s_axis_data_tready_reg <= 1'b0;
m_axis_data_tvalid_reg <= 1'b0;
scl_o_reg <= 1'b1;
sda_o_reg <= 1'b1;
busy_reg <= 1'b0;
bus_active_reg <= 1'b0;
bus_control_reg <= 1'b0;
missed_ack_reg <= 1'b0;
end
end
endmodule
`resetall

View File

@ -0,0 +1,62 @@
/*
Copyright (c) 2014-2017 Alex Forencich
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
// Language: Verilog-2001
`resetall
`timescale 1 ns / 1 ps
`default_nettype none
/*
* Synchronizes an asyncronous signal to a given clock by using a pipeline of
* two registers.
*/
module sync_signal #(
parameter WIDTH=1, // width of the input and output signals
parameter N=2 // depth of synchronizer
)(
input wire clk,
input wire [WIDTH-1:0] in,
output wire [WIDTH-1:0] out
);
reg [WIDTH-1:0] sync_reg[N-1:0];
/*
* The synchronized output is the last register in the pipeline.
*/
assign out = sync_reg[N-1];
integer k;
always @(posedge clk) begin
sync_reg[0] <= in;
for (k = 1; k < N; k = k + 1) begin
sync_reg[k] <= sync_reg[k-1];
end
end
endmodule
`resetall

View File

@ -0,0 +1,95 @@
# Copyright (c) 2020 Alex Forencich
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
TOPLEVEL_LANG = verilog
SIM ?= icarus
WAVES ?= 0
COCOTB_HDL_TIMEUNIT = 1ns
COCOTB_HDL_TIMEPRECISION = 1ps
DUT = fpga_core
TOPLEVEL = $(DUT)
MODULE = test_$(DUT)
VERILOG_SOURCES += ../../rtl/$(DUT).v
VERILOG_SOURCES += ../../lib/eth/rtl/eth_mac_10g_fifo.v
VERILOG_SOURCES += ../../lib/eth/rtl/eth_mac_10g.v
VERILOG_SOURCES += ../../lib/eth/rtl/axis_xgmii_rx_64.v
VERILOG_SOURCES += ../../lib/eth/rtl/axis_xgmii_tx_64.v
VERILOG_SOURCES += ../../lib/eth/rtl/lfsr.v
VERILOG_SOURCES += ../../lib/eth/rtl/eth_axis_rx.v
VERILOG_SOURCES += ../../lib/eth/rtl/eth_axis_tx.v
VERILOG_SOURCES += ../../lib/eth/rtl/udp_complete_64.v
VERILOG_SOURCES += ../../lib/eth/rtl/udp_checksum_gen_64.v
VERILOG_SOURCES += ../../lib/eth/rtl/udp_64.v
VERILOG_SOURCES += ../../lib/eth/rtl/udp_ip_rx_64.v
VERILOG_SOURCES += ../../lib/eth/rtl/udp_ip_tx_64.v
VERILOG_SOURCES += ../../lib/eth/rtl/ip_complete_64.v
VERILOG_SOURCES += ../../lib/eth/rtl/ip_64.v
VERILOG_SOURCES += ../../lib/eth/rtl/ip_eth_rx_64.v
VERILOG_SOURCES += ../../lib/eth/rtl/ip_eth_tx_64.v
VERILOG_SOURCES += ../../lib/eth/rtl/ip_arb_mux.v
VERILOG_SOURCES += ../../lib/eth/rtl/arp.v
VERILOG_SOURCES += ../../lib/eth/rtl/arp_cache.v
VERILOG_SOURCES += ../../lib/eth/rtl/arp_eth_rx.v
VERILOG_SOURCES += ../../lib/eth/rtl/arp_eth_tx.v
VERILOG_SOURCES += ../../lib/eth/rtl/eth_arb_mux.v
VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/arbiter.v
VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/priority_encoder.v
VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_fifo.v
VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_async_fifo.v
VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_async_fifo_adapter.v
# module parameters
#export PARAM_A := value
ifeq ($(SIM), icarus)
PLUSARGS += -fst
# COMPILE_ARGS += -P $(TOPLEVEL).A=$(PARAM_A)
ifeq ($(WAVES), 1)
VERILOG_SOURCES += iverilog_dump.v
COMPILE_ARGS += -s iverilog_dump
endif
else ifeq ($(SIM), verilator)
COMPILE_ARGS += -Wno-SELRANGE -Wno-WIDTH
# COMPILE_ARGS += -GA=$(PARAM_A)
ifeq ($(WAVES), 1)
COMPILE_ARGS += --trace-fst
endif
endif
include $(shell cocotb-config --makefiles)/Makefile.sim
iverilog_dump.v:
echo 'module iverilog_dump();' > $@
echo 'initial begin' >> $@
echo ' $$dumpfile("$(TOPLEVEL).fst");' >> $@
echo ' $$dumpvars(0, $(TOPLEVEL));' >> $@
echo 'end' >> $@
echo 'endmodule' >> $@
clean::
@rm -rf iverilog_dump.v
@rm -rf dump.fst $(TOPLEVEL).fst

View File

@ -0,0 +1,865 @@
"""
Copyright (c) 2020 Alex Forencich
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
"""
import logging
import os
from scapy.layers.l2 import Ether, ARP
from scapy.layers.inet import IP, UDP
import cocotb_test.simulator
import cocotb
from cocotb.log import SimLog
from cocotb.clock import Clock
from cocotb.triggers import RisingEdge
from cocotbext.eth import XgmiiFrame, XgmiiSource, XgmiiSink
class TB:
def __init__(self, dut):
self.dut = dut
self.log = SimLog("cocotb.tb")
self.log.setLevel(logging.DEBUG)
cocotb.start_soon(Clock(dut.clk, 2.56, units="ns").start())
dut.btn.setimmediatevalue(0)
dut.sw.setimmediatevalue(0)
dut.uart_txd.setimmediatevalue(1)
dut.uart_rts.setimmediatevalue(1)
# Ethernet
cocotb.start_soon(Clock(dut.qsfp_1_rx_clk_1, 2.56, units="ns").start())
self.qsfp_1_1_source = XgmiiSource(dut.qsfp_1_rxd_1, dut.qsfp_1_rxc_1, dut.qsfp_1_rx_clk_1, dut.qsfp_1_rx_rst_1)
cocotb.start_soon(Clock(dut.qsfp_1_tx_clk_1, 2.56, units="ns").start())
self.qsfp_1_1_sink = XgmiiSink(dut.qsfp_1_txd_1, dut.qsfp_1_txc_1, dut.qsfp_1_tx_clk_1, dut.qsfp_1_tx_rst_1)
cocotb.start_soon(Clock(dut.qsfp_1_rx_clk_2, 2.56, units="ns").start())
self.qsfp_1_2_source = XgmiiSource(dut.qsfp_1_rxd_2, dut.qsfp_1_rxc_2, dut.qsfp_1_rx_clk_2, dut.qsfp_1_rx_rst_2)
cocotb.start_soon(Clock(dut.qsfp_1_tx_clk_2, 2.56, units="ns").start())
self.qsfp_1_2_sink = XgmiiSink(dut.qsfp_1_txd_2, dut.qsfp_1_txc_2, dut.qsfp_1_tx_clk_2, dut.qsfp_1_tx_rst_2)
cocotb.start_soon(Clock(dut.qsfp_1_rx_clk_3, 2.56, units="ns").start())
self.qsfp_1_3_source = XgmiiSource(dut.qsfp_1_rxd_3, dut.qsfp_1_rxc_3, dut.qsfp_1_rx_clk_3, dut.qsfp_1_rx_rst_3)
cocotb.start_soon(Clock(dut.qsfp_1_tx_clk_3, 2.56, units="ns").start())
self.qsfp_1_3_sink = XgmiiSink(dut.qsfp_1_txd_3, dut.qsfp_1_txc_3, dut.qsfp_1_tx_clk_3, dut.qsfp_1_tx_rst_3)
cocotb.start_soon(Clock(dut.qsfp_1_rx_clk_4, 2.56, units="ns").start())
self.qsfp_1_4_source = XgmiiSource(dut.qsfp_1_rxd_4, dut.qsfp_1_rxc_4, dut.qsfp_1_rx_clk_4, dut.qsfp_1_rx_rst_4)
cocotb.start_soon(Clock(dut.qsfp_1_tx_clk_4, 2.56, units="ns").start())
self.qsfp_1_4_sink = XgmiiSink(dut.qsfp_1_txd_4, dut.qsfp_1_txc_4, dut.qsfp_1_tx_clk_4, dut.qsfp_1_tx_rst_4)
cocotb.start_soon(Clock(dut.qsfp_2_rx_clk_1, 2.56, units="ns").start())
self.qsfp_2_1_source = XgmiiSource(dut.qsfp_2_rxd_1, dut.qsfp_2_rxc_1, dut.qsfp_2_rx_clk_1, dut.qsfp_2_rx_rst_1)
cocotb.start_soon(Clock(dut.qsfp_2_tx_clk_1, 2.56, units="ns").start())
self.qsfp_2_1_sink = XgmiiSink(dut.qsfp_2_txd_1, dut.qsfp_2_txc_1, dut.qsfp_2_tx_clk_1, dut.qsfp_2_tx_rst_1)
cocotb.start_soon(Clock(dut.qsfp_2_rx_clk_2, 2.56, units="ns").start())
self.qsfp_2_2_source = XgmiiSource(dut.qsfp_2_rxd_2, dut.qsfp_2_rxc_2, dut.qsfp_2_rx_clk_2, dut.qsfp_2_rx_rst_2)
cocotb.start_soon(Clock(dut.qsfp_2_tx_clk_2, 2.56, units="ns").start())
self.qsfp_2_2_sink = XgmiiSink(dut.qsfp_2_txd_2, dut.qsfp_2_txc_2, dut.qsfp_2_tx_clk_2, dut.qsfp_2_tx_rst_2)
cocotb.start_soon(Clock(dut.qsfp_2_rx_clk_3, 2.56, units="ns").start())
self.qsfp_2_3_source = XgmiiSource(dut.qsfp_2_rxd_3, dut.qsfp_2_rxc_3, dut.qsfp_2_rx_clk_3, dut.qsfp_2_rx_rst_3)
cocotb.start_soon(Clock(dut.qsfp_2_tx_clk_3, 2.56, units="ns").start())
self.qsfp_2_3_sink = XgmiiSink(dut.qsfp_2_txd_3, dut.qsfp_2_txc_3, dut.qsfp_2_tx_clk_3, dut.qsfp_2_tx_rst_3)
cocotb.start_soon(Clock(dut.qsfp_2_rx_clk_4, 2.56, units="ns").start())
self.qsfp_2_4_source = XgmiiSource(dut.qsfp_2_rxd_4, dut.qsfp_2_rxc_4, dut.qsfp_2_rx_clk_4, dut.qsfp_2_rx_rst_4)
cocotb.start_soon(Clock(dut.qsfp_2_tx_clk_4, 2.56, units="ns").start())
self.qsfp_2_4_sink = XgmiiSink(dut.qsfp_2_txd_4, dut.qsfp_2_txc_4, dut.qsfp_2_tx_clk_4, dut.qsfp_2_tx_rst_4)
cocotb.start_soon(Clock(dut.qsfp_3_rx_clk_1, 2.56, units="ns").start())
self.qsfp_3_1_source = XgmiiSource(dut.qsfp_3_rxd_1, dut.qsfp_3_rxc_1, dut.qsfp_3_rx_clk_1, dut.qsfp_3_rx_rst_1)
cocotb.start_soon(Clock(dut.qsfp_3_tx_clk_1, 2.56, units="ns").start())
self.qsfp_3_1_sink = XgmiiSink(dut.qsfp_3_txd_1, dut.qsfp_3_txc_1, dut.qsfp_3_tx_clk_1, dut.qsfp_3_tx_rst_1)
cocotb.start_soon(Clock(dut.qsfp_3_rx_clk_2, 2.56, units="ns").start())
self.qsfp_3_2_source = XgmiiSource(dut.qsfp_3_rxd_2, dut.qsfp_3_rxc_2, dut.qsfp_3_rx_clk_2, dut.qsfp_3_rx_rst_2)
cocotb.start_soon(Clock(dut.qsfp_3_tx_clk_2, 2.56, units="ns").start())
self.qsfp_3_2_sink = XgmiiSink(dut.qsfp_3_txd_2, dut.qsfp_3_txc_2, dut.qsfp_3_tx_clk_2, dut.qsfp_3_tx_rst_2)
cocotb.start_soon(Clock(dut.qsfp_3_rx_clk_3, 2.56, units="ns").start())
self.qsfp_3_3_source = XgmiiSource(dut.qsfp_3_rxd_3, dut.qsfp_3_rxc_3, dut.qsfp_3_rx_clk_3, dut.qsfp_3_rx_rst_3)
cocotb.start_soon(Clock(dut.qsfp_3_tx_clk_3, 2.56, units="ns").start())
self.qsfp_3_3_sink = XgmiiSink(dut.qsfp_3_txd_3, dut.qsfp_3_txc_3, dut.qsfp_3_tx_clk_3, dut.qsfp_3_tx_rst_3)
cocotb.start_soon(Clock(dut.qsfp_3_rx_clk_4, 2.56, units="ns").start())
self.qsfp_3_4_source = XgmiiSource(dut.qsfp_3_rxd_4, dut.qsfp_3_rxc_4, dut.qsfp_3_rx_clk_4, dut.qsfp_3_rx_rst_4)
cocotb.start_soon(Clock(dut.qsfp_3_tx_clk_4, 2.56, units="ns").start())
self.qsfp_3_4_sink = XgmiiSink(dut.qsfp_3_txd_4, dut.qsfp_3_txc_4, dut.qsfp_3_tx_clk_4, dut.qsfp_3_tx_rst_4)
cocotb.start_soon(Clock(dut.qsfp_4_rx_clk_1, 2.56, units="ns").start())
self.qsfp_4_1_source = XgmiiSource(dut.qsfp_4_rxd_1, dut.qsfp_4_rxc_1, dut.qsfp_4_rx_clk_1, dut.qsfp_4_rx_rst_1)
cocotb.start_soon(Clock(dut.qsfp_4_tx_clk_1, 2.56, units="ns").start())
self.qsfp_4_1_sink = XgmiiSink(dut.qsfp_4_txd_1, dut.qsfp_4_txc_1, dut.qsfp_4_tx_clk_1, dut.qsfp_4_tx_rst_1)
cocotb.start_soon(Clock(dut.qsfp_4_rx_clk_2, 2.56, units="ns").start())
self.qsfp_4_2_source = XgmiiSource(dut.qsfp_4_rxd_2, dut.qsfp_4_rxc_2, dut.qsfp_4_rx_clk_2, dut.qsfp_4_rx_rst_2)
cocotb.start_soon(Clock(dut.qsfp_4_tx_clk_2, 2.56, units="ns").start())
self.qsfp_4_2_sink = XgmiiSink(dut.qsfp_4_txd_2, dut.qsfp_4_txc_2, dut.qsfp_4_tx_clk_2, dut.qsfp_4_tx_rst_2)
cocotb.start_soon(Clock(dut.qsfp_4_rx_clk_3, 2.56, units="ns").start())
self.qsfp_4_3_source = XgmiiSource(dut.qsfp_4_rxd_3, dut.qsfp_4_rxc_3, dut.qsfp_4_rx_clk_3, dut.qsfp_4_rx_rst_3)
cocotb.start_soon(Clock(dut.qsfp_4_tx_clk_3, 2.56, units="ns").start())
self.qsfp_4_3_sink = XgmiiSink(dut.qsfp_4_txd_3, dut.qsfp_4_txc_3, dut.qsfp_4_tx_clk_3, dut.qsfp_4_tx_rst_3)
cocotb.start_soon(Clock(dut.qsfp_4_rx_clk_4, 2.56, units="ns").start())
self.qsfp_4_4_source = XgmiiSource(dut.qsfp_4_rxd_4, dut.qsfp_4_rxc_4, dut.qsfp_4_rx_clk_4, dut.qsfp_4_rx_rst_4)
cocotb.start_soon(Clock(dut.qsfp_4_tx_clk_4, 2.56, units="ns").start())
self.qsfp_4_4_sink = XgmiiSink(dut.qsfp_4_txd_4, dut.qsfp_4_txc_4, dut.qsfp_4_tx_clk_4, dut.qsfp_4_tx_rst_4)
cocotb.start_soon(Clock(dut.qsfp_5_rx_clk_1, 2.56, units="ns").start())
self.qsfp_5_1_source = XgmiiSource(dut.qsfp_5_rxd_1, dut.qsfp_5_rxc_1, dut.qsfp_5_rx_clk_1, dut.qsfp_5_rx_rst_1)
cocotb.start_soon(Clock(dut.qsfp_5_tx_clk_1, 2.56, units="ns").start())
self.qsfp_5_1_sink = XgmiiSink(dut.qsfp_5_txd_1, dut.qsfp_5_txc_1, dut.qsfp_5_tx_clk_1, dut.qsfp_5_tx_rst_1)
cocotb.start_soon(Clock(dut.qsfp_5_rx_clk_2, 2.56, units="ns").start())
self.qsfp_5_2_source = XgmiiSource(dut.qsfp_5_rxd_2, dut.qsfp_5_rxc_2, dut.qsfp_5_rx_clk_2, dut.qsfp_5_rx_rst_2)
cocotb.start_soon(Clock(dut.qsfp_5_tx_clk_2, 2.56, units="ns").start())
self.qsfp_5_2_sink = XgmiiSink(dut.qsfp_5_txd_2, dut.qsfp_5_txc_2, dut.qsfp_5_tx_clk_2, dut.qsfp_5_tx_rst_2)
cocotb.start_soon(Clock(dut.qsfp_5_rx_clk_3, 2.56, units="ns").start())
self.qsfp_5_3_source = XgmiiSource(dut.qsfp_5_rxd_3, dut.qsfp_5_rxc_3, dut.qsfp_5_rx_clk_3, dut.qsfp_5_rx_rst_3)
cocotb.start_soon(Clock(dut.qsfp_5_tx_clk_3, 2.56, units="ns").start())
self.qsfp_5_3_sink = XgmiiSink(dut.qsfp_5_txd_3, dut.qsfp_5_txc_3, dut.qsfp_5_tx_clk_3, dut.qsfp_5_tx_rst_3)
cocotb.start_soon(Clock(dut.qsfp_5_rx_clk_4, 2.56, units="ns").start())
self.qsfp_5_4_source = XgmiiSource(dut.qsfp_5_rxd_4, dut.qsfp_5_rxc_4, dut.qsfp_5_rx_clk_4, dut.qsfp_5_rx_rst_4)
cocotb.start_soon(Clock(dut.qsfp_5_tx_clk_4, 2.56, units="ns").start())
self.qsfp_5_4_sink = XgmiiSink(dut.qsfp_5_txd_4, dut.qsfp_5_txc_4, dut.qsfp_5_tx_clk_4, dut.qsfp_5_tx_rst_4)
cocotb.start_soon(Clock(dut.qsfp_6_rx_clk_1, 2.56, units="ns").start())
self.qsfp_6_1_source = XgmiiSource(dut.qsfp_6_rxd_1, dut.qsfp_6_rxc_1, dut.qsfp_6_rx_clk_1, dut.qsfp_6_rx_rst_1)
cocotb.start_soon(Clock(dut.qsfp_6_tx_clk_1, 2.56, units="ns").start())
self.qsfp_6_1_sink = XgmiiSink(dut.qsfp_6_txd_1, dut.qsfp_6_txc_1, dut.qsfp_6_tx_clk_1, dut.qsfp_6_tx_rst_1)
cocotb.start_soon(Clock(dut.qsfp_6_rx_clk_2, 2.56, units="ns").start())
self.qsfp_6_2_source = XgmiiSource(dut.qsfp_6_rxd_2, dut.qsfp_6_rxc_2, dut.qsfp_6_rx_clk_2, dut.qsfp_6_rx_rst_2)
cocotb.start_soon(Clock(dut.qsfp_6_tx_clk_2, 2.56, units="ns").start())
self.qsfp_6_2_sink = XgmiiSink(dut.qsfp_6_txd_2, dut.qsfp_6_txc_2, dut.qsfp_6_tx_clk_2, dut.qsfp_6_tx_rst_2)
cocotb.start_soon(Clock(dut.qsfp_6_rx_clk_3, 2.56, units="ns").start())
self.qsfp_6_3_source = XgmiiSource(dut.qsfp_6_rxd_3, dut.qsfp_6_rxc_3, dut.qsfp_6_rx_clk_3, dut.qsfp_6_rx_rst_3)
cocotb.start_soon(Clock(dut.qsfp_6_tx_clk_3, 2.56, units="ns").start())
self.qsfp_6_3_sink = XgmiiSink(dut.qsfp_6_txd_3, dut.qsfp_6_txc_3, dut.qsfp_6_tx_clk_3, dut.qsfp_6_tx_rst_3)
cocotb.start_soon(Clock(dut.qsfp_6_rx_clk_4, 2.56, units="ns").start())
self.qsfp_6_4_source = XgmiiSource(dut.qsfp_6_rxd_4, dut.qsfp_6_rxc_4, dut.qsfp_6_rx_clk_4, dut.qsfp_6_rx_rst_4)
cocotb.start_soon(Clock(dut.qsfp_6_tx_clk_4, 2.56, units="ns").start())
self.qsfp_6_4_sink = XgmiiSink(dut.qsfp_6_txd_4, dut.qsfp_6_txc_4, dut.qsfp_6_tx_clk_4, dut.qsfp_6_tx_rst_4)
cocotb.start_soon(Clock(dut.qsfp_7_rx_clk_1, 2.56, units="ns").start())
self.qsfp_7_1_source = XgmiiSource(dut.qsfp_7_rxd_1, dut.qsfp_7_rxc_1, dut.qsfp_7_rx_clk_1, dut.qsfp_7_rx_rst_1)
cocotb.start_soon(Clock(dut.qsfp_7_tx_clk_1, 2.56, units="ns").start())
self.qsfp_7_1_sink = XgmiiSink(dut.qsfp_7_txd_1, dut.qsfp_7_txc_1, dut.qsfp_7_tx_clk_1, dut.qsfp_7_tx_rst_1)
cocotb.start_soon(Clock(dut.qsfp_7_rx_clk_2, 2.56, units="ns").start())
self.qsfp_7_2_source = XgmiiSource(dut.qsfp_7_rxd_2, dut.qsfp_7_rxc_2, dut.qsfp_7_rx_clk_2, dut.qsfp_7_rx_rst_2)
cocotb.start_soon(Clock(dut.qsfp_7_tx_clk_2, 2.56, units="ns").start())
self.qsfp_7_2_sink = XgmiiSink(dut.qsfp_7_txd_2, dut.qsfp_7_txc_2, dut.qsfp_7_tx_clk_2, dut.qsfp_7_tx_rst_2)
cocotb.start_soon(Clock(dut.qsfp_7_rx_clk_3, 2.56, units="ns").start())
self.qsfp_7_3_source = XgmiiSource(dut.qsfp_7_rxd_3, dut.qsfp_7_rxc_3, dut.qsfp_7_rx_clk_3, dut.qsfp_7_rx_rst_3)
cocotb.start_soon(Clock(dut.qsfp_7_tx_clk_3, 2.56, units="ns").start())
self.qsfp_7_3_sink = XgmiiSink(dut.qsfp_7_txd_3, dut.qsfp_7_txc_3, dut.qsfp_7_tx_clk_3, dut.qsfp_7_tx_rst_3)
cocotb.start_soon(Clock(dut.qsfp_7_rx_clk_4, 2.56, units="ns").start())
self.qsfp_7_4_source = XgmiiSource(dut.qsfp_7_rxd_4, dut.qsfp_7_rxc_4, dut.qsfp_7_rx_clk_4, dut.qsfp_7_rx_rst_4)
cocotb.start_soon(Clock(dut.qsfp_7_tx_clk_4, 2.56, units="ns").start())
self.qsfp_7_4_sink = XgmiiSink(dut.qsfp_7_txd_4, dut.qsfp_7_txc_4, dut.qsfp_7_tx_clk_4, dut.qsfp_7_tx_rst_4)
cocotb.start_soon(Clock(dut.qsfp_8_rx_clk_1, 2.56, units="ns").start())
self.qsfp_8_1_source = XgmiiSource(dut.qsfp_8_rxd_1, dut.qsfp_8_rxc_1, dut.qsfp_8_rx_clk_1, dut.qsfp_8_rx_rst_1)
cocotb.start_soon(Clock(dut.qsfp_8_tx_clk_1, 2.56, units="ns").start())
self.qsfp_8_1_sink = XgmiiSink(dut.qsfp_8_txd_1, dut.qsfp_8_txc_1, dut.qsfp_8_tx_clk_1, dut.qsfp_8_tx_rst_1)
cocotb.start_soon(Clock(dut.qsfp_8_rx_clk_2, 2.56, units="ns").start())
self.qsfp_8_2_source = XgmiiSource(dut.qsfp_8_rxd_2, dut.qsfp_8_rxc_2, dut.qsfp_8_rx_clk_2, dut.qsfp_8_rx_rst_2)
cocotb.start_soon(Clock(dut.qsfp_8_tx_clk_2, 2.56, units="ns").start())
self.qsfp_8_2_sink = XgmiiSink(dut.qsfp_8_txd_2, dut.qsfp_8_txc_2, dut.qsfp_8_tx_clk_2, dut.qsfp_8_tx_rst_2)
cocotb.start_soon(Clock(dut.qsfp_8_rx_clk_3, 2.56, units="ns").start())
self.qsfp_8_3_source = XgmiiSource(dut.qsfp_8_rxd_3, dut.qsfp_8_rxc_3, dut.qsfp_8_rx_clk_3, dut.qsfp_8_rx_rst_3)
cocotb.start_soon(Clock(dut.qsfp_8_tx_clk_3, 2.56, units="ns").start())
self.qsfp_8_3_sink = XgmiiSink(dut.qsfp_8_txd_3, dut.qsfp_8_txc_3, dut.qsfp_8_tx_clk_3, dut.qsfp_8_tx_rst_3)
cocotb.start_soon(Clock(dut.qsfp_8_rx_clk_4, 2.56, units="ns").start())
self.qsfp_8_4_source = XgmiiSource(dut.qsfp_8_rxd_4, dut.qsfp_8_rxc_4, dut.qsfp_8_rx_clk_4, dut.qsfp_8_rx_rst_4)
cocotb.start_soon(Clock(dut.qsfp_8_tx_clk_4, 2.56, units="ns").start())
self.qsfp_8_4_sink = XgmiiSink(dut.qsfp_8_txd_4, dut.qsfp_8_txc_4, dut.qsfp_8_tx_clk_4, dut.qsfp_8_tx_rst_4)
cocotb.start_soon(Clock(dut.qsfp_9_rx_clk_1, 2.56, units="ns").start())
self.qsfp_9_1_source = XgmiiSource(dut.qsfp_9_rxd_1, dut.qsfp_9_rxc_1, dut.qsfp_9_rx_clk_1, dut.qsfp_9_rx_rst_1)
cocotb.start_soon(Clock(dut.qsfp_9_tx_clk_1, 2.56, units="ns").start())
self.qsfp_9_1_sink = XgmiiSink(dut.qsfp_9_txd_1, dut.qsfp_9_txc_1, dut.qsfp_9_tx_clk_1, dut.qsfp_9_tx_rst_1)
cocotb.start_soon(Clock(dut.qsfp_9_rx_clk_2, 2.56, units="ns").start())
self.qsfp_9_2_source = XgmiiSource(dut.qsfp_9_rxd_2, dut.qsfp_9_rxc_2, dut.qsfp_9_rx_clk_2, dut.qsfp_9_rx_rst_2)
cocotb.start_soon(Clock(dut.qsfp_9_tx_clk_2, 2.56, units="ns").start())
self.qsfp_9_2_sink = XgmiiSink(dut.qsfp_9_txd_2, dut.qsfp_9_txc_2, dut.qsfp_9_tx_clk_2, dut.qsfp_9_tx_rst_2)
cocotb.start_soon(Clock(dut.qsfp_9_rx_clk_3, 2.56, units="ns").start())
self.qsfp_9_3_source = XgmiiSource(dut.qsfp_9_rxd_3, dut.qsfp_9_rxc_3, dut.qsfp_9_rx_clk_3, dut.qsfp_9_rx_rst_3)
cocotb.start_soon(Clock(dut.qsfp_9_tx_clk_3, 2.56, units="ns").start())
self.qsfp_9_3_sink = XgmiiSink(dut.qsfp_9_txd_3, dut.qsfp_9_txc_3, dut.qsfp_9_tx_clk_3, dut.qsfp_9_tx_rst_3)
cocotb.start_soon(Clock(dut.qsfp_9_rx_clk_4, 2.56, units="ns").start())
self.qsfp_9_4_source = XgmiiSource(dut.qsfp_9_rxd_4, dut.qsfp_9_rxc_4, dut.qsfp_9_rx_clk_4, dut.qsfp_9_rx_rst_4)
cocotb.start_soon(Clock(dut.qsfp_9_tx_clk_4, 2.56, units="ns").start())
self.qsfp_9_4_sink = XgmiiSink(dut.qsfp_9_txd_4, dut.qsfp_9_txc_4, dut.qsfp_9_tx_clk_4, dut.qsfp_9_tx_rst_4)
cocotb.start_soon(Clock(dut.fmc_qsfp_1_rx_clk_1, 2.56, units="ns").start())
self.fmc_qsfp_1_1_source = XgmiiSource(dut.fmc_qsfp_1_rxd_1, dut.fmc_qsfp_1_rxc_1, dut.fmc_qsfp_1_rx_clk_1, dut.fmc_qsfp_1_rx_rst_1)
cocotb.start_soon(Clock(dut.fmc_qsfp_1_tx_clk_1, 2.56, units="ns").start())
self.fmc_qsfp_1_1_sink = XgmiiSink(dut.fmc_qsfp_1_txd_1, dut.fmc_qsfp_1_txc_1, dut.fmc_qsfp_1_tx_clk_1, dut.fmc_qsfp_1_tx_rst_1)
cocotb.start_soon(Clock(dut.fmc_qsfp_1_rx_clk_2, 2.56, units="ns").start())
self.fmc_qsfp_1_2_source = XgmiiSource(dut.fmc_qsfp_1_rxd_2, dut.fmc_qsfp_1_rxc_2, dut.fmc_qsfp_1_rx_clk_2, dut.fmc_qsfp_1_rx_rst_2)
cocotb.start_soon(Clock(dut.fmc_qsfp_1_tx_clk_2, 2.56, units="ns").start())
self.fmc_qsfp_1_2_sink = XgmiiSink(dut.fmc_qsfp_1_txd_2, dut.fmc_qsfp_1_txc_2, dut.fmc_qsfp_1_tx_clk_2, dut.fmc_qsfp_1_tx_rst_2)
cocotb.start_soon(Clock(dut.fmc_qsfp_1_rx_clk_3, 2.56, units="ns").start())
self.fmc_qsfp_1_3_source = XgmiiSource(dut.fmc_qsfp_1_rxd_3, dut.fmc_qsfp_1_rxc_3, dut.fmc_qsfp_1_rx_clk_3, dut.fmc_qsfp_1_rx_rst_3)
cocotb.start_soon(Clock(dut.fmc_qsfp_1_tx_clk_3, 2.56, units="ns").start())
self.fmc_qsfp_1_3_sink = XgmiiSink(dut.fmc_qsfp_1_txd_3, dut.fmc_qsfp_1_txc_3, dut.fmc_qsfp_1_tx_clk_3, dut.fmc_qsfp_1_tx_rst_3)
cocotb.start_soon(Clock(dut.fmc_qsfp_1_rx_clk_4, 2.56, units="ns").start())
self.fmc_qsfp_1_4_source = XgmiiSource(dut.fmc_qsfp_1_rxd_4, dut.fmc_qsfp_1_rxc_4, dut.fmc_qsfp_1_rx_clk_4, dut.fmc_qsfp_1_rx_rst_4)
cocotb.start_soon(Clock(dut.fmc_qsfp_1_tx_clk_4, 2.56, units="ns").start())
self.fmc_qsfp_1_4_sink = XgmiiSink(dut.fmc_qsfp_1_txd_4, dut.fmc_qsfp_1_txc_4, dut.fmc_qsfp_1_tx_clk_4, dut.fmc_qsfp_1_tx_rst_4)
cocotb.start_soon(Clock(dut.fmc_qsfp_2_rx_clk_1, 2.56, units="ns").start())
self.fmc_qsfp_2_1_source = XgmiiSource(dut.fmc_qsfp_2_rxd_1, dut.fmc_qsfp_2_rxc_1, dut.fmc_qsfp_2_rx_clk_1, dut.fmc_qsfp_2_rx_rst_1)
cocotb.start_soon(Clock(dut.fmc_qsfp_2_tx_clk_1, 2.56, units="ns").start())
self.fmc_qsfp_2_1_sink = XgmiiSink(dut.fmc_qsfp_2_txd_1, dut.fmc_qsfp_2_txc_1, dut.fmc_qsfp_2_tx_clk_1, dut.fmc_qsfp_2_tx_rst_1)
cocotb.start_soon(Clock(dut.fmc_qsfp_2_rx_clk_2, 2.56, units="ns").start())
self.fmc_qsfp_2_2_source = XgmiiSource(dut.fmc_qsfp_2_rxd_2, dut.fmc_qsfp_2_rxc_2, dut.fmc_qsfp_2_rx_clk_2, dut.fmc_qsfp_2_rx_rst_2)
cocotb.start_soon(Clock(dut.fmc_qsfp_2_tx_clk_2, 2.56, units="ns").start())
self.fmc_qsfp_2_2_sink = XgmiiSink(dut.fmc_qsfp_2_txd_2, dut.fmc_qsfp_2_txc_2, dut.fmc_qsfp_2_tx_clk_2, dut.fmc_qsfp_2_tx_rst_2)
cocotb.start_soon(Clock(dut.fmc_qsfp_2_rx_clk_3, 2.56, units="ns").start())
self.fmc_qsfp_2_3_source = XgmiiSource(dut.fmc_qsfp_2_rxd_3, dut.fmc_qsfp_2_rxc_3, dut.fmc_qsfp_2_rx_clk_3, dut.fmc_qsfp_2_rx_rst_3)
cocotb.start_soon(Clock(dut.fmc_qsfp_2_tx_clk_3, 2.56, units="ns").start())
self.fmc_qsfp_2_3_sink = XgmiiSink(dut.fmc_qsfp_2_txd_3, dut.fmc_qsfp_2_txc_3, dut.fmc_qsfp_2_tx_clk_3, dut.fmc_qsfp_2_tx_rst_3)
cocotb.start_soon(Clock(dut.fmc_qsfp_2_rx_clk_4, 2.56, units="ns").start())
self.fmc_qsfp_2_4_source = XgmiiSource(dut.fmc_qsfp_2_rxd_4, dut.fmc_qsfp_2_rxc_4, dut.fmc_qsfp_2_rx_clk_4, dut.fmc_qsfp_2_rx_rst_4)
cocotb.start_soon(Clock(dut.fmc_qsfp_2_tx_clk_4, 2.56, units="ns").start())
self.fmc_qsfp_2_4_sink = XgmiiSink(dut.fmc_qsfp_2_txd_4, dut.fmc_qsfp_2_txc_4, dut.fmc_qsfp_2_tx_clk_4, dut.fmc_qsfp_2_tx_rst_4)
cocotb.start_soon(Clock(dut.fmc_qsfp_3_rx_clk_1, 2.56, units="ns").start())
self.fmc_qsfp_3_1_source = XgmiiSource(dut.fmc_qsfp_3_rxd_1, dut.fmc_qsfp_3_rxc_1, dut.fmc_qsfp_3_rx_clk_1, dut.fmc_qsfp_3_rx_rst_1)
cocotb.start_soon(Clock(dut.fmc_qsfp_3_tx_clk_1, 2.56, units="ns").start())
self.fmc_qsfp_3_1_sink = XgmiiSink(dut.fmc_qsfp_3_txd_1, dut.fmc_qsfp_3_txc_1, dut.fmc_qsfp_3_tx_clk_1, dut.fmc_qsfp_3_tx_rst_1)
cocotb.start_soon(Clock(dut.fmc_qsfp_3_rx_clk_2, 2.56, units="ns").start())
self.fmc_qsfp_3_2_source = XgmiiSource(dut.fmc_qsfp_3_rxd_2, dut.fmc_qsfp_3_rxc_2, dut.fmc_qsfp_3_rx_clk_2, dut.fmc_qsfp_3_rx_rst_2)
cocotb.start_soon(Clock(dut.fmc_qsfp_3_tx_clk_2, 2.56, units="ns").start())
self.fmc_qsfp_3_2_sink = XgmiiSink(dut.fmc_qsfp_3_txd_2, dut.fmc_qsfp_3_txc_2, dut.fmc_qsfp_3_tx_clk_2, dut.fmc_qsfp_3_tx_rst_2)
cocotb.start_soon(Clock(dut.fmc_qsfp_3_rx_clk_3, 2.56, units="ns").start())
self.fmc_qsfp_3_3_source = XgmiiSource(dut.fmc_qsfp_3_rxd_3, dut.fmc_qsfp_3_rxc_3, dut.fmc_qsfp_3_rx_clk_3, dut.fmc_qsfp_3_rx_rst_3)
cocotb.start_soon(Clock(dut.fmc_qsfp_3_tx_clk_3, 2.56, units="ns").start())
self.fmc_qsfp_3_3_sink = XgmiiSink(dut.fmc_qsfp_3_txd_3, dut.fmc_qsfp_3_txc_3, dut.fmc_qsfp_3_tx_clk_3, dut.fmc_qsfp_3_tx_rst_3)
cocotb.start_soon(Clock(dut.fmc_qsfp_3_rx_clk_4, 2.56, units="ns").start())
self.fmc_qsfp_3_4_source = XgmiiSource(dut.fmc_qsfp_3_rxd_4, dut.fmc_qsfp_3_rxc_4, dut.fmc_qsfp_3_rx_clk_4, dut.fmc_qsfp_3_rx_rst_4)
cocotb.start_soon(Clock(dut.fmc_qsfp_3_tx_clk_4, 2.56, units="ns").start())
self.fmc_qsfp_3_4_sink = XgmiiSink(dut.fmc_qsfp_3_txd_4, dut.fmc_qsfp_3_txc_4, dut.fmc_qsfp_3_tx_clk_4, dut.fmc_qsfp_3_tx_rst_4)
cocotb.start_soon(Clock(dut.fmc_qsfp_4_rx_clk_1, 2.56, units="ns").start())
self.fmc_qsfp_4_1_source = XgmiiSource(dut.fmc_qsfp_4_rxd_1, dut.fmc_qsfp_4_rxc_1, dut.fmc_qsfp_4_rx_clk_1, dut.fmc_qsfp_4_rx_rst_1)
cocotb.start_soon(Clock(dut.fmc_qsfp_4_tx_clk_1, 2.56, units="ns").start())
self.fmc_qsfp_4_1_sink = XgmiiSink(dut.fmc_qsfp_4_txd_1, dut.fmc_qsfp_4_txc_1, dut.fmc_qsfp_4_tx_clk_1, dut.fmc_qsfp_4_tx_rst_1)
cocotb.start_soon(Clock(dut.fmc_qsfp_4_rx_clk_2, 2.56, units="ns").start())
self.fmc_qsfp_4_2_source = XgmiiSource(dut.fmc_qsfp_4_rxd_2, dut.fmc_qsfp_4_rxc_2, dut.fmc_qsfp_4_rx_clk_2, dut.fmc_qsfp_4_rx_rst_2)
cocotb.start_soon(Clock(dut.fmc_qsfp_4_tx_clk_2, 2.56, units="ns").start())
self.fmc_qsfp_4_2_sink = XgmiiSink(dut.fmc_qsfp_4_txd_2, dut.fmc_qsfp_4_txc_2, dut.fmc_qsfp_4_tx_clk_2, dut.fmc_qsfp_4_tx_rst_2)
cocotb.start_soon(Clock(dut.fmc_qsfp_4_rx_clk_3, 2.56, units="ns").start())
self.fmc_qsfp_4_3_source = XgmiiSource(dut.fmc_qsfp_4_rxd_3, dut.fmc_qsfp_4_rxc_3, dut.fmc_qsfp_4_rx_clk_3, dut.fmc_qsfp_4_rx_rst_3)
cocotb.start_soon(Clock(dut.fmc_qsfp_4_tx_clk_3, 2.56, units="ns").start())
self.fmc_qsfp_4_3_sink = XgmiiSink(dut.fmc_qsfp_4_txd_3, dut.fmc_qsfp_4_txc_3, dut.fmc_qsfp_4_tx_clk_3, dut.fmc_qsfp_4_tx_rst_3)
cocotb.start_soon(Clock(dut.fmc_qsfp_4_rx_clk_4, 2.56, units="ns").start())
self.fmc_qsfp_4_4_source = XgmiiSource(dut.fmc_qsfp_4_rxd_4, dut.fmc_qsfp_4_rxc_4, dut.fmc_qsfp_4_rx_clk_4, dut.fmc_qsfp_4_rx_rst_4)
cocotb.start_soon(Clock(dut.fmc_qsfp_4_tx_clk_4, 2.56, units="ns").start())
self.fmc_qsfp_4_4_sink = XgmiiSink(dut.fmc_qsfp_4_txd_4, dut.fmc_qsfp_4_txc_4, dut.fmc_qsfp_4_tx_clk_4, dut.fmc_qsfp_4_tx_rst_4)
cocotb.start_soon(Clock(dut.fmc_qsfp_5_rx_clk_1, 2.56, units="ns").start())
self.fmc_qsfp_5_1_source = XgmiiSource(dut.fmc_qsfp_5_rxd_1, dut.fmc_qsfp_5_rxc_1, dut.fmc_qsfp_5_rx_clk_1, dut.fmc_qsfp_5_rx_rst_1)
cocotb.start_soon(Clock(dut.fmc_qsfp_5_tx_clk_1, 2.56, units="ns").start())
self.fmc_qsfp_5_1_sink = XgmiiSink(dut.fmc_qsfp_5_txd_1, dut.fmc_qsfp_5_txc_1, dut.fmc_qsfp_5_tx_clk_1, dut.fmc_qsfp_5_tx_rst_1)
cocotb.start_soon(Clock(dut.fmc_qsfp_5_rx_clk_2, 2.56, units="ns").start())
self.fmc_qsfp_5_2_source = XgmiiSource(dut.fmc_qsfp_5_rxd_2, dut.fmc_qsfp_5_rxc_2, dut.fmc_qsfp_5_rx_clk_2, dut.fmc_qsfp_5_rx_rst_2)
cocotb.start_soon(Clock(dut.fmc_qsfp_5_tx_clk_2, 2.56, units="ns").start())
self.fmc_qsfp_5_2_sink = XgmiiSink(dut.fmc_qsfp_5_txd_2, dut.fmc_qsfp_5_txc_2, dut.fmc_qsfp_5_tx_clk_2, dut.fmc_qsfp_5_tx_rst_2)
cocotb.start_soon(Clock(dut.fmc_qsfp_5_rx_clk_3, 2.56, units="ns").start())
self.fmc_qsfp_5_3_source = XgmiiSource(dut.fmc_qsfp_5_rxd_3, dut.fmc_qsfp_5_rxc_3, dut.fmc_qsfp_5_rx_clk_3, dut.fmc_qsfp_5_rx_rst_3)
cocotb.start_soon(Clock(dut.fmc_qsfp_5_tx_clk_3, 2.56, units="ns").start())
self.fmc_qsfp_5_3_sink = XgmiiSink(dut.fmc_qsfp_5_txd_3, dut.fmc_qsfp_5_txc_3, dut.fmc_qsfp_5_tx_clk_3, dut.fmc_qsfp_5_tx_rst_3)
cocotb.start_soon(Clock(dut.fmc_qsfp_5_rx_clk_4, 2.56, units="ns").start())
self.fmc_qsfp_5_4_source = XgmiiSource(dut.fmc_qsfp_5_rxd_4, dut.fmc_qsfp_5_rxc_4, dut.fmc_qsfp_5_rx_clk_4, dut.fmc_qsfp_5_rx_rst_4)
cocotb.start_soon(Clock(dut.fmc_qsfp_5_tx_clk_4, 2.56, units="ns").start())
self.fmc_qsfp_5_4_sink = XgmiiSink(dut.fmc_qsfp_5_txd_4, dut.fmc_qsfp_5_txc_4, dut.fmc_qsfp_5_tx_clk_4, dut.fmc_qsfp_5_tx_rst_4)
cocotb.start_soon(Clock(dut.fmc_qsfp_6_rx_clk_1, 2.56, units="ns").start())
self.fmc_qsfp_6_1_source = XgmiiSource(dut.fmc_qsfp_6_rxd_1, dut.fmc_qsfp_6_rxc_1, dut.fmc_qsfp_6_rx_clk_1, dut.fmc_qsfp_6_rx_rst_1)
cocotb.start_soon(Clock(dut.fmc_qsfp_6_tx_clk_1, 2.56, units="ns").start())
self.fmc_qsfp_6_1_sink = XgmiiSink(dut.fmc_qsfp_6_txd_1, dut.fmc_qsfp_6_txc_1, dut.fmc_qsfp_6_tx_clk_1, dut.fmc_qsfp_6_tx_rst_1)
cocotb.start_soon(Clock(dut.fmc_qsfp_6_rx_clk_2, 2.56, units="ns").start())
self.fmc_qsfp_6_2_source = XgmiiSource(dut.fmc_qsfp_6_rxd_2, dut.fmc_qsfp_6_rxc_2, dut.fmc_qsfp_6_rx_clk_2, dut.fmc_qsfp_6_rx_rst_2)
cocotb.start_soon(Clock(dut.fmc_qsfp_6_tx_clk_2, 2.56, units="ns").start())
self.fmc_qsfp_6_2_sink = XgmiiSink(dut.fmc_qsfp_6_txd_2, dut.fmc_qsfp_6_txc_2, dut.fmc_qsfp_6_tx_clk_2, dut.fmc_qsfp_6_tx_rst_2)
cocotb.start_soon(Clock(dut.fmc_qsfp_6_rx_clk_3, 2.56, units="ns").start())
self.fmc_qsfp_6_3_source = XgmiiSource(dut.fmc_qsfp_6_rxd_3, dut.fmc_qsfp_6_rxc_3, dut.fmc_qsfp_6_rx_clk_3, dut.fmc_qsfp_6_rx_rst_3)
cocotb.start_soon(Clock(dut.fmc_qsfp_6_tx_clk_3, 2.56, units="ns").start())
self.fmc_qsfp_6_3_sink = XgmiiSink(dut.fmc_qsfp_6_txd_3, dut.fmc_qsfp_6_txc_3, dut.fmc_qsfp_6_tx_clk_3, dut.fmc_qsfp_6_tx_rst_3)
cocotb.start_soon(Clock(dut.fmc_qsfp_6_rx_clk_4, 2.56, units="ns").start())
self.fmc_qsfp_6_4_source = XgmiiSource(dut.fmc_qsfp_6_rxd_4, dut.fmc_qsfp_6_rxc_4, dut.fmc_qsfp_6_rx_clk_4, dut.fmc_qsfp_6_rx_rst_4)
cocotb.start_soon(Clock(dut.fmc_qsfp_6_tx_clk_4, 2.56, units="ns").start())
self.fmc_qsfp_6_4_sink = XgmiiSink(dut.fmc_qsfp_6_txd_4, dut.fmc_qsfp_6_txc_4, dut.fmc_qsfp_6_tx_clk_4, dut.fmc_qsfp_6_tx_rst_4)
async def init(self):
self.dut.rst.setimmediatevalue(0)
self.dut.qsfp_1_rx_rst_1.setimmediatevalue(0)
self.dut.qsfp_1_tx_rst_1.setimmediatevalue(0)
self.dut.qsfp_1_rx_rst_2.setimmediatevalue(0)
self.dut.qsfp_1_tx_rst_2.setimmediatevalue(0)
self.dut.qsfp_1_rx_rst_3.setimmediatevalue(0)
self.dut.qsfp_1_tx_rst_3.setimmediatevalue(0)
self.dut.qsfp_1_rx_rst_4.setimmediatevalue(0)
self.dut.qsfp_1_tx_rst_4.setimmediatevalue(0)
self.dut.qsfp_2_rx_rst_1.setimmediatevalue(0)
self.dut.qsfp_2_tx_rst_1.setimmediatevalue(0)
self.dut.qsfp_2_rx_rst_2.setimmediatevalue(0)
self.dut.qsfp_2_tx_rst_2.setimmediatevalue(0)
self.dut.qsfp_2_rx_rst_3.setimmediatevalue(0)
self.dut.qsfp_2_tx_rst_3.setimmediatevalue(0)
self.dut.qsfp_2_rx_rst_4.setimmediatevalue(0)
self.dut.qsfp_2_tx_rst_4.setimmediatevalue(0)
self.dut.qsfp_3_rx_rst_1.setimmediatevalue(0)
self.dut.qsfp_3_tx_rst_1.setimmediatevalue(0)
self.dut.qsfp_3_rx_rst_2.setimmediatevalue(0)
self.dut.qsfp_3_tx_rst_2.setimmediatevalue(0)
self.dut.qsfp_3_rx_rst_3.setimmediatevalue(0)
self.dut.qsfp_3_tx_rst_3.setimmediatevalue(0)
self.dut.qsfp_3_rx_rst_4.setimmediatevalue(0)
self.dut.qsfp_3_tx_rst_4.setimmediatevalue(0)
self.dut.qsfp_4_rx_rst_1.setimmediatevalue(0)
self.dut.qsfp_4_tx_rst_1.setimmediatevalue(0)
self.dut.qsfp_4_rx_rst_2.setimmediatevalue(0)
self.dut.qsfp_4_tx_rst_2.setimmediatevalue(0)
self.dut.qsfp_4_rx_rst_3.setimmediatevalue(0)
self.dut.qsfp_4_tx_rst_3.setimmediatevalue(0)
self.dut.qsfp_4_rx_rst_4.setimmediatevalue(0)
self.dut.qsfp_4_tx_rst_4.setimmediatevalue(0)
self.dut.qsfp_5_rx_rst_1.setimmediatevalue(0)
self.dut.qsfp_5_tx_rst_1.setimmediatevalue(0)
self.dut.qsfp_5_rx_rst_2.setimmediatevalue(0)
self.dut.qsfp_5_tx_rst_2.setimmediatevalue(0)
self.dut.qsfp_5_rx_rst_3.setimmediatevalue(0)
self.dut.qsfp_5_tx_rst_3.setimmediatevalue(0)
self.dut.qsfp_5_rx_rst_4.setimmediatevalue(0)
self.dut.qsfp_5_tx_rst_4.setimmediatevalue(0)
self.dut.qsfp_6_rx_rst_1.setimmediatevalue(0)
self.dut.qsfp_6_tx_rst_1.setimmediatevalue(0)
self.dut.qsfp_6_rx_rst_2.setimmediatevalue(0)
self.dut.qsfp_6_tx_rst_2.setimmediatevalue(0)
self.dut.qsfp_6_rx_rst_3.setimmediatevalue(0)
self.dut.qsfp_6_tx_rst_3.setimmediatevalue(0)
self.dut.qsfp_6_rx_rst_4.setimmediatevalue(0)
self.dut.qsfp_6_tx_rst_4.setimmediatevalue(0)
self.dut.qsfp_7_rx_rst_1.setimmediatevalue(0)
self.dut.qsfp_7_tx_rst_1.setimmediatevalue(0)
self.dut.qsfp_7_rx_rst_2.setimmediatevalue(0)
self.dut.qsfp_7_tx_rst_2.setimmediatevalue(0)
self.dut.qsfp_7_rx_rst_3.setimmediatevalue(0)
self.dut.qsfp_7_tx_rst_3.setimmediatevalue(0)
self.dut.qsfp_7_rx_rst_4.setimmediatevalue(0)
self.dut.qsfp_7_tx_rst_4.setimmediatevalue(0)
self.dut.qsfp_8_rx_rst_1.setimmediatevalue(0)
self.dut.qsfp_8_tx_rst_1.setimmediatevalue(0)
self.dut.qsfp_8_rx_rst_2.setimmediatevalue(0)
self.dut.qsfp_8_tx_rst_2.setimmediatevalue(0)
self.dut.qsfp_8_rx_rst_3.setimmediatevalue(0)
self.dut.qsfp_8_tx_rst_3.setimmediatevalue(0)
self.dut.qsfp_8_rx_rst_4.setimmediatevalue(0)
self.dut.qsfp_8_tx_rst_4.setimmediatevalue(0)
self.dut.qsfp_9_rx_rst_1.setimmediatevalue(0)
self.dut.qsfp_9_tx_rst_1.setimmediatevalue(0)
self.dut.qsfp_9_rx_rst_2.setimmediatevalue(0)
self.dut.qsfp_9_tx_rst_2.setimmediatevalue(0)
self.dut.qsfp_9_rx_rst_3.setimmediatevalue(0)
self.dut.qsfp_9_tx_rst_3.setimmediatevalue(0)
self.dut.qsfp_9_rx_rst_4.setimmediatevalue(0)
self.dut.qsfp_9_tx_rst_4.setimmediatevalue(0)
self.dut.fmc_qsfp_1_rx_rst_1.setimmediatevalue(0)
self.dut.fmc_qsfp_1_tx_rst_1.setimmediatevalue(0)
self.dut.fmc_qsfp_1_rx_rst_2.setimmediatevalue(0)
self.dut.fmc_qsfp_1_tx_rst_2.setimmediatevalue(0)
self.dut.fmc_qsfp_1_rx_rst_3.setimmediatevalue(0)
self.dut.fmc_qsfp_1_tx_rst_3.setimmediatevalue(0)
self.dut.fmc_qsfp_1_rx_rst_4.setimmediatevalue(0)
self.dut.fmc_qsfp_1_tx_rst_4.setimmediatevalue(0)
self.dut.fmc_qsfp_2_rx_rst_1.setimmediatevalue(0)
self.dut.fmc_qsfp_2_tx_rst_1.setimmediatevalue(0)
self.dut.fmc_qsfp_2_rx_rst_2.setimmediatevalue(0)
self.dut.fmc_qsfp_2_tx_rst_2.setimmediatevalue(0)
self.dut.fmc_qsfp_2_rx_rst_3.setimmediatevalue(0)
self.dut.fmc_qsfp_2_tx_rst_3.setimmediatevalue(0)
self.dut.fmc_qsfp_2_rx_rst_4.setimmediatevalue(0)
self.dut.fmc_qsfp_2_tx_rst_4.setimmediatevalue(0)
self.dut.fmc_qsfp_3_rx_rst_1.setimmediatevalue(0)
self.dut.fmc_qsfp_3_tx_rst_1.setimmediatevalue(0)
self.dut.fmc_qsfp_3_rx_rst_2.setimmediatevalue(0)
self.dut.fmc_qsfp_3_tx_rst_2.setimmediatevalue(0)
self.dut.fmc_qsfp_3_rx_rst_3.setimmediatevalue(0)
self.dut.fmc_qsfp_3_tx_rst_3.setimmediatevalue(0)
self.dut.fmc_qsfp_3_rx_rst_4.setimmediatevalue(0)
self.dut.fmc_qsfp_3_tx_rst_4.setimmediatevalue(0)
self.dut.fmc_qsfp_4_rx_rst_1.setimmediatevalue(0)
self.dut.fmc_qsfp_4_tx_rst_1.setimmediatevalue(0)
self.dut.fmc_qsfp_4_rx_rst_2.setimmediatevalue(0)
self.dut.fmc_qsfp_4_tx_rst_2.setimmediatevalue(0)
self.dut.fmc_qsfp_4_rx_rst_3.setimmediatevalue(0)
self.dut.fmc_qsfp_4_tx_rst_3.setimmediatevalue(0)
self.dut.fmc_qsfp_4_rx_rst_4.setimmediatevalue(0)
self.dut.fmc_qsfp_4_tx_rst_4.setimmediatevalue(0)
self.dut.fmc_qsfp_5_rx_rst_1.setimmediatevalue(0)
self.dut.fmc_qsfp_5_tx_rst_1.setimmediatevalue(0)
self.dut.fmc_qsfp_5_rx_rst_2.setimmediatevalue(0)
self.dut.fmc_qsfp_5_tx_rst_2.setimmediatevalue(0)
self.dut.fmc_qsfp_5_rx_rst_3.setimmediatevalue(0)
self.dut.fmc_qsfp_5_tx_rst_3.setimmediatevalue(0)
self.dut.fmc_qsfp_5_rx_rst_4.setimmediatevalue(0)
self.dut.fmc_qsfp_5_tx_rst_4.setimmediatevalue(0)
self.dut.fmc_qsfp_6_rx_rst_1.setimmediatevalue(0)
self.dut.fmc_qsfp_6_tx_rst_1.setimmediatevalue(0)
self.dut.fmc_qsfp_6_rx_rst_2.setimmediatevalue(0)
self.dut.fmc_qsfp_6_tx_rst_2.setimmediatevalue(0)
self.dut.fmc_qsfp_6_rx_rst_3.setimmediatevalue(0)
self.dut.fmc_qsfp_6_tx_rst_3.setimmediatevalue(0)
self.dut.fmc_qsfp_6_rx_rst_4.setimmediatevalue(0)
self.dut.fmc_qsfp_6_tx_rst_4.setimmediatevalue(0)
for k in range(10):
await RisingEdge(self.dut.clk)
self.dut.rst.value = 1
self.dut.qsfp_1_rx_rst_1.value = 1
self.dut.qsfp_1_tx_rst_1.value = 1
self.dut.qsfp_1_rx_rst_2.value = 1
self.dut.qsfp_1_tx_rst_2.value = 1
self.dut.qsfp_1_rx_rst_3.value = 1
self.dut.qsfp_1_tx_rst_3.value = 1
self.dut.qsfp_1_rx_rst_4.value = 1
self.dut.qsfp_1_tx_rst_4.value = 1
self.dut.qsfp_2_rx_rst_1.value = 1
self.dut.qsfp_2_tx_rst_1.value = 1
self.dut.qsfp_2_rx_rst_2.value = 1
self.dut.qsfp_2_tx_rst_2.value = 1
self.dut.qsfp_2_rx_rst_3.value = 1
self.dut.qsfp_2_tx_rst_3.value = 1
self.dut.qsfp_2_rx_rst_4.value = 1
self.dut.qsfp_2_tx_rst_4.value = 1
self.dut.qsfp_3_rx_rst_1.value = 1
self.dut.qsfp_3_tx_rst_1.value = 1
self.dut.qsfp_3_rx_rst_2.value = 1
self.dut.qsfp_3_tx_rst_2.value = 1
self.dut.qsfp_3_rx_rst_3.value = 1
self.dut.qsfp_3_tx_rst_3.value = 1
self.dut.qsfp_3_rx_rst_4.value = 1
self.dut.qsfp_3_tx_rst_4.value = 1
self.dut.qsfp_4_rx_rst_1.value = 1
self.dut.qsfp_4_tx_rst_1.value = 1
self.dut.qsfp_4_rx_rst_2.value = 1
self.dut.qsfp_4_tx_rst_2.value = 1
self.dut.qsfp_4_rx_rst_3.value = 1
self.dut.qsfp_4_tx_rst_3.value = 1
self.dut.qsfp_4_rx_rst_4.value = 1
self.dut.qsfp_4_tx_rst_4.value = 1
self.dut.qsfp_5_rx_rst_1.value = 1
self.dut.qsfp_5_tx_rst_1.value = 1
self.dut.qsfp_5_rx_rst_2.value = 1
self.dut.qsfp_5_tx_rst_2.value = 1
self.dut.qsfp_5_rx_rst_3.value = 1
self.dut.qsfp_5_tx_rst_3.value = 1
self.dut.qsfp_5_rx_rst_4.value = 1
self.dut.qsfp_5_tx_rst_4.value = 1
self.dut.qsfp_6_rx_rst_1.value = 1
self.dut.qsfp_6_tx_rst_1.value = 1
self.dut.qsfp_6_rx_rst_2.value = 1
self.dut.qsfp_6_tx_rst_2.value = 1
self.dut.qsfp_6_rx_rst_3.value = 1
self.dut.qsfp_6_tx_rst_3.value = 1
self.dut.qsfp_6_rx_rst_4.value = 1
self.dut.qsfp_6_tx_rst_4.value = 1
self.dut.qsfp_7_rx_rst_1.value = 1
self.dut.qsfp_7_tx_rst_1.value = 1
self.dut.qsfp_7_rx_rst_2.value = 1
self.dut.qsfp_7_tx_rst_2.value = 1
self.dut.qsfp_7_rx_rst_3.value = 1
self.dut.qsfp_7_tx_rst_3.value = 1
self.dut.qsfp_7_rx_rst_4.value = 1
self.dut.qsfp_7_tx_rst_4.value = 1
self.dut.qsfp_8_rx_rst_1.value = 1
self.dut.qsfp_8_tx_rst_1.value = 1
self.dut.qsfp_8_rx_rst_2.value = 1
self.dut.qsfp_8_tx_rst_2.value = 1
self.dut.qsfp_8_rx_rst_3.value = 1
self.dut.qsfp_8_tx_rst_3.value = 1
self.dut.qsfp_8_rx_rst_4.value = 1
self.dut.qsfp_8_tx_rst_4.value = 1
self.dut.qsfp_9_rx_rst_1.value = 1
self.dut.qsfp_9_tx_rst_1.value = 1
self.dut.qsfp_9_rx_rst_2.value = 1
self.dut.qsfp_9_tx_rst_2.value = 1
self.dut.qsfp_9_rx_rst_3.value = 1
self.dut.qsfp_9_tx_rst_3.value = 1
self.dut.qsfp_9_rx_rst_4.value = 1
self.dut.qsfp_9_tx_rst_4.value = 1
self.dut.fmc_qsfp_1_rx_rst_1.value = 1
self.dut.fmc_qsfp_1_tx_rst_1.value = 1
self.dut.fmc_qsfp_1_rx_rst_2.value = 1
self.dut.fmc_qsfp_1_tx_rst_2.value = 1
self.dut.fmc_qsfp_1_rx_rst_3.value = 1
self.dut.fmc_qsfp_1_tx_rst_3.value = 1
self.dut.fmc_qsfp_1_rx_rst_4.value = 1
self.dut.fmc_qsfp_1_tx_rst_4.value = 1
self.dut.fmc_qsfp_2_rx_rst_1.value = 1
self.dut.fmc_qsfp_2_tx_rst_1.value = 1
self.dut.fmc_qsfp_2_rx_rst_2.value = 1
self.dut.fmc_qsfp_2_tx_rst_2.value = 1
self.dut.fmc_qsfp_2_rx_rst_3.value = 1
self.dut.fmc_qsfp_2_tx_rst_3.value = 1
self.dut.fmc_qsfp_2_rx_rst_4.value = 1
self.dut.fmc_qsfp_2_tx_rst_4.value = 1
self.dut.fmc_qsfp_3_rx_rst_1.value = 1
self.dut.fmc_qsfp_3_tx_rst_1.value = 1
self.dut.fmc_qsfp_3_rx_rst_2.value = 1
self.dut.fmc_qsfp_3_tx_rst_2.value = 1
self.dut.fmc_qsfp_3_rx_rst_3.value = 1
self.dut.fmc_qsfp_3_tx_rst_3.value = 1
self.dut.fmc_qsfp_3_rx_rst_4.value = 1
self.dut.fmc_qsfp_3_tx_rst_4.value = 1
self.dut.fmc_qsfp_4_rx_rst_1.value = 1
self.dut.fmc_qsfp_4_tx_rst_1.value = 1
self.dut.fmc_qsfp_4_rx_rst_2.value = 1
self.dut.fmc_qsfp_4_tx_rst_2.value = 1
self.dut.fmc_qsfp_4_rx_rst_3.value = 1
self.dut.fmc_qsfp_4_tx_rst_3.value = 1
self.dut.fmc_qsfp_4_rx_rst_4.value = 1
self.dut.fmc_qsfp_4_tx_rst_4.value = 1
self.dut.fmc_qsfp_5_rx_rst_1.value = 1
self.dut.fmc_qsfp_5_tx_rst_1.value = 1
self.dut.fmc_qsfp_5_rx_rst_2.value = 1
self.dut.fmc_qsfp_5_tx_rst_2.value = 1
self.dut.fmc_qsfp_5_rx_rst_3.value = 1
self.dut.fmc_qsfp_5_tx_rst_3.value = 1
self.dut.fmc_qsfp_5_rx_rst_4.value = 1
self.dut.fmc_qsfp_5_tx_rst_4.value = 1
self.dut.fmc_qsfp_6_rx_rst_1.value = 1
self.dut.fmc_qsfp_6_tx_rst_1.value = 1
self.dut.fmc_qsfp_6_rx_rst_2.value = 1
self.dut.fmc_qsfp_6_tx_rst_2.value = 1
self.dut.fmc_qsfp_6_rx_rst_3.value = 1
self.dut.fmc_qsfp_6_tx_rst_3.value = 1
self.dut.fmc_qsfp_6_rx_rst_4.value = 1
self.dut.fmc_qsfp_6_tx_rst_4.value = 1
for k in range(10):
await RisingEdge(self.dut.clk)
self.dut.rst.value = 0
self.dut.qsfp_1_rx_rst_1.value = 0
self.dut.qsfp_1_tx_rst_1.value = 0
self.dut.qsfp_1_rx_rst_2.value = 0
self.dut.qsfp_1_tx_rst_2.value = 0
self.dut.qsfp_1_rx_rst_3.value = 0
self.dut.qsfp_1_tx_rst_3.value = 0
self.dut.qsfp_1_rx_rst_4.value = 0
self.dut.qsfp_1_tx_rst_4.value = 0
self.dut.qsfp_2_rx_rst_1.value = 0
self.dut.qsfp_2_tx_rst_1.value = 0
self.dut.qsfp_2_rx_rst_2.value = 0
self.dut.qsfp_2_tx_rst_2.value = 0
self.dut.qsfp_2_rx_rst_3.value = 0
self.dut.qsfp_2_tx_rst_3.value = 0
self.dut.qsfp_2_rx_rst_4.value = 0
self.dut.qsfp_2_tx_rst_4.value = 0
self.dut.qsfp_3_rx_rst_1.value = 0
self.dut.qsfp_3_tx_rst_1.value = 0
self.dut.qsfp_3_rx_rst_2.value = 0
self.dut.qsfp_3_tx_rst_2.value = 0
self.dut.qsfp_3_rx_rst_3.value = 0
self.dut.qsfp_3_tx_rst_3.value = 0
self.dut.qsfp_3_rx_rst_4.value = 0
self.dut.qsfp_3_tx_rst_4.value = 0
self.dut.qsfp_4_rx_rst_1.value = 0
self.dut.qsfp_4_tx_rst_1.value = 0
self.dut.qsfp_4_rx_rst_2.value = 0
self.dut.qsfp_4_tx_rst_2.value = 0
self.dut.qsfp_4_rx_rst_3.value = 0
self.dut.qsfp_4_tx_rst_3.value = 0
self.dut.qsfp_4_rx_rst_4.value = 0
self.dut.qsfp_4_tx_rst_4.value = 0
self.dut.qsfp_5_rx_rst_1.value = 0
self.dut.qsfp_5_tx_rst_1.value = 0
self.dut.qsfp_5_rx_rst_2.value = 0
self.dut.qsfp_5_tx_rst_2.value = 0
self.dut.qsfp_5_rx_rst_3.value = 0
self.dut.qsfp_5_tx_rst_3.value = 0
self.dut.qsfp_5_rx_rst_4.value = 0
self.dut.qsfp_5_tx_rst_4.value = 0
self.dut.qsfp_6_rx_rst_1.value = 0
self.dut.qsfp_6_tx_rst_1.value = 0
self.dut.qsfp_6_rx_rst_2.value = 0
self.dut.qsfp_6_tx_rst_2.value = 0
self.dut.qsfp_6_rx_rst_3.value = 0
self.dut.qsfp_6_tx_rst_3.value = 0
self.dut.qsfp_6_rx_rst_4.value = 0
self.dut.qsfp_6_tx_rst_4.value = 0
self.dut.qsfp_7_rx_rst_1.value = 0
self.dut.qsfp_7_tx_rst_1.value = 0
self.dut.qsfp_7_rx_rst_2.value = 0
self.dut.qsfp_7_tx_rst_2.value = 0
self.dut.qsfp_7_rx_rst_3.value = 0
self.dut.qsfp_7_tx_rst_3.value = 0
self.dut.qsfp_7_rx_rst_4.value = 0
self.dut.qsfp_7_tx_rst_4.value = 0
self.dut.qsfp_8_rx_rst_1.value = 0
self.dut.qsfp_8_tx_rst_1.value = 0
self.dut.qsfp_8_rx_rst_2.value = 0
self.dut.qsfp_8_tx_rst_2.value = 0
self.dut.qsfp_8_rx_rst_3.value = 0
self.dut.qsfp_8_tx_rst_3.value = 0
self.dut.qsfp_8_rx_rst_4.value = 0
self.dut.qsfp_8_tx_rst_4.value = 0
self.dut.qsfp_9_rx_rst_1.value = 0
self.dut.qsfp_9_tx_rst_1.value = 0
self.dut.qsfp_9_rx_rst_2.value = 0
self.dut.qsfp_9_tx_rst_2.value = 0
self.dut.qsfp_9_rx_rst_3.value = 0
self.dut.qsfp_9_tx_rst_3.value = 0
self.dut.qsfp_9_rx_rst_4.value = 0
self.dut.qsfp_9_tx_rst_4.value = 0
self.dut.fmc_qsfp_1_rx_rst_1.value = 0
self.dut.fmc_qsfp_1_tx_rst_1.value = 0
self.dut.fmc_qsfp_1_rx_rst_2.value = 0
self.dut.fmc_qsfp_1_tx_rst_2.value = 0
self.dut.fmc_qsfp_1_rx_rst_3.value = 0
self.dut.fmc_qsfp_1_tx_rst_3.value = 0
self.dut.fmc_qsfp_1_rx_rst_4.value = 0
self.dut.fmc_qsfp_1_tx_rst_4.value = 0
self.dut.fmc_qsfp_2_rx_rst_1.value = 0
self.dut.fmc_qsfp_2_tx_rst_1.value = 0
self.dut.fmc_qsfp_2_rx_rst_2.value = 0
self.dut.fmc_qsfp_2_tx_rst_2.value = 0
self.dut.fmc_qsfp_2_rx_rst_3.value = 0
self.dut.fmc_qsfp_2_tx_rst_3.value = 0
self.dut.fmc_qsfp_2_rx_rst_4.value = 0
self.dut.fmc_qsfp_2_tx_rst_4.value = 0
self.dut.fmc_qsfp_3_rx_rst_1.value = 0
self.dut.fmc_qsfp_3_tx_rst_1.value = 0
self.dut.fmc_qsfp_3_rx_rst_2.value = 0
self.dut.fmc_qsfp_3_tx_rst_2.value = 0
self.dut.fmc_qsfp_3_rx_rst_3.value = 0
self.dut.fmc_qsfp_3_tx_rst_3.value = 0
self.dut.fmc_qsfp_3_rx_rst_4.value = 0
self.dut.fmc_qsfp_3_tx_rst_4.value = 0
self.dut.fmc_qsfp_4_rx_rst_1.value = 0
self.dut.fmc_qsfp_4_tx_rst_1.value = 0
self.dut.fmc_qsfp_4_rx_rst_2.value = 0
self.dut.fmc_qsfp_4_tx_rst_2.value = 0
self.dut.fmc_qsfp_4_rx_rst_3.value = 0
self.dut.fmc_qsfp_4_tx_rst_3.value = 0
self.dut.fmc_qsfp_4_rx_rst_4.value = 0
self.dut.fmc_qsfp_4_tx_rst_4.value = 0
self.dut.fmc_qsfp_5_rx_rst_1.value = 0
self.dut.fmc_qsfp_5_tx_rst_1.value = 0
self.dut.fmc_qsfp_5_rx_rst_2.value = 0
self.dut.fmc_qsfp_5_tx_rst_2.value = 0
self.dut.fmc_qsfp_5_rx_rst_3.value = 0
self.dut.fmc_qsfp_5_tx_rst_3.value = 0
self.dut.fmc_qsfp_5_rx_rst_4.value = 0
self.dut.fmc_qsfp_5_tx_rst_4.value = 0
self.dut.fmc_qsfp_6_rx_rst_1.value = 0
self.dut.fmc_qsfp_6_tx_rst_1.value = 0
self.dut.fmc_qsfp_6_rx_rst_2.value = 0
self.dut.fmc_qsfp_6_tx_rst_2.value = 0
self.dut.fmc_qsfp_6_rx_rst_3.value = 0
self.dut.fmc_qsfp_6_tx_rst_3.value = 0
self.dut.fmc_qsfp_6_rx_rst_4.value = 0
self.dut.fmc_qsfp_6_tx_rst_4.value = 0
@cocotb.test()
async def run_test(dut):
tb = TB(dut)
await tb.init()
tb.log.info("test UDP RX packet")
payload = bytes([x % 256 for x in range(256)])
eth = Ether(src='5a:51:52:53:54:55', dst='02:00:00:00:00:00')
ip = IP(src='192.168.1.100', dst='192.168.1.128')
udp = UDP(sport=5678, dport=1234)
test_pkt = eth / ip / udp / payload
test_frame = XgmiiFrame.from_payload(test_pkt.build())
await tb.qsfp_1_1_source.send(test_frame)
tb.log.info("receive ARP request")
rx_frame = await tb.qsfp_1_1_sink.recv()
rx_pkt = Ether(bytes(rx_frame.get_payload()))
tb.log.info("RX packet: %s", repr(rx_pkt))
assert rx_pkt.dst == 'ff:ff:ff:ff:ff:ff'
assert rx_pkt.src == test_pkt.dst
assert rx_pkt[ARP].hwtype == 1
assert rx_pkt[ARP].ptype == 0x0800
assert rx_pkt[ARP].hwlen == 6
assert rx_pkt[ARP].plen == 4
assert rx_pkt[ARP].op == 1
assert rx_pkt[ARP].hwsrc == test_pkt.dst
assert rx_pkt[ARP].psrc == test_pkt[IP].dst
assert rx_pkt[ARP].hwdst == '00:00:00:00:00:00'
assert rx_pkt[ARP].pdst == test_pkt[IP].src
tb.log.info("send ARP response")
eth = Ether(src=test_pkt.src, dst=test_pkt.dst)
arp = ARP(hwtype=1, ptype=0x0800, hwlen=6, plen=4, op=2,
hwsrc=test_pkt.src, psrc=test_pkt[IP].src,
hwdst=test_pkt.dst, pdst=test_pkt[IP].dst)
resp_pkt = eth / arp
resp_frame = XgmiiFrame.from_payload(resp_pkt.build())
await tb.qsfp_1_1_source.send(resp_frame)
tb.log.info("receive UDP packet")
rx_frame = await tb.qsfp_1_1_sink.recv()
rx_pkt = Ether(bytes(rx_frame.get_payload()))
tb.log.info("RX packet: %s", repr(rx_pkt))
assert rx_pkt.dst == test_pkt.src
assert rx_pkt.src == test_pkt.dst
assert rx_pkt[IP].dst == test_pkt[IP].src
assert rx_pkt[IP].src == test_pkt[IP].dst
assert rx_pkt[UDP].dport == test_pkt[UDP].sport
assert rx_pkt[UDP].sport == test_pkt[UDP].dport
assert rx_pkt[UDP].payload == test_pkt[UDP].payload
await RisingEdge(dut.clk)
await RisingEdge(dut.clk)
# cocotb-test
tests_dir = os.path.abspath(os.path.dirname(__file__))
rtl_dir = os.path.abspath(os.path.join(tests_dir, '..', '..', 'rtl'))
lib_dir = os.path.abspath(os.path.join(rtl_dir, '..', 'lib'))
axis_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'eth', 'lib', 'axis', 'rtl'))
eth_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'eth', 'rtl'))
def test_fpga_core(request):
dut = "fpga_core"
module = os.path.splitext(os.path.basename(__file__))[0]
toplevel = dut
verilog_sources = [
os.path.join(rtl_dir, f"{dut}.v"),
os.path.join(eth_rtl_dir, "eth_mac_10g_fifo.v"),
os.path.join(eth_rtl_dir, "eth_mac_10g.v"),
os.path.join(eth_rtl_dir, "axis_xgmii_rx_64.v"),
os.path.join(eth_rtl_dir, "axis_xgmii_tx_64.v"),
os.path.join(eth_rtl_dir, "lfsr.v"),
os.path.join(eth_rtl_dir, "eth_axis_rx.v"),
os.path.join(eth_rtl_dir, "eth_axis_tx.v"),
os.path.join(eth_rtl_dir, "udp_complete_64.v"),
os.path.join(eth_rtl_dir, "udp_checksum_gen_64.v"),
os.path.join(eth_rtl_dir, "udp_64.v"),
os.path.join(eth_rtl_dir, "udp_ip_rx_64.v"),
os.path.join(eth_rtl_dir, "udp_ip_tx_64.v"),
os.path.join(eth_rtl_dir, "ip_complete_64.v"),
os.path.join(eth_rtl_dir, "ip_64.v"),
os.path.join(eth_rtl_dir, "ip_eth_rx_64.v"),
os.path.join(eth_rtl_dir, "ip_eth_tx_64.v"),
os.path.join(eth_rtl_dir, "ip_arb_mux.v"),
os.path.join(eth_rtl_dir, "arp.v"),
os.path.join(eth_rtl_dir, "arp_cache.v"),
os.path.join(eth_rtl_dir, "arp_eth_rx.v"),
os.path.join(eth_rtl_dir, "arp_eth_tx.v"),
os.path.join(eth_rtl_dir, "eth_arb_mux.v"),
os.path.join(axis_rtl_dir, "arbiter.v"),
os.path.join(axis_rtl_dir, "priority_encoder.v"),
os.path.join(axis_rtl_dir, "axis_fifo.v"),
os.path.join(axis_rtl_dir, "axis_async_fifo.v"),
os.path.join(axis_rtl_dir, "axis_async_fifo_adapter.v"),
]
parameters = {}
# parameters['A'] = val
extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()}
sim_build = os.path.join(tests_dir, "sim_build",
request.node.name.replace('[', '-').replace(']', ''))
cocotb_test.simulator.run(
python_search=[tests_dir],
verilog_sources=verilog_sources,
toplevel=toplevel,
module=module,
parameters=parameters,
sim_build=sim_build,
extra_env=extra_env,
)