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

Add 10G/25G design for Arista 7132LB-48Y4C switch

Signed-off-by: Alex Forencich <alex@alexforencich.com>
This commit is contained in:
Alex Forencich 2023-08-25 23:06:49 -07:00
parent 351ec79fef
commit 68736d02ae
17 changed files with 3284 additions and 0 deletions

View File

@ -0,0 +1,40 @@
# Verilog Ethernet Arista 7132LB Example Design
## Introduction
This example design targets the Arista 7132LB-48Y4C switch.
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.
* FPGA: xcvu9p-flgb2104-3-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
Load the design onto the FPGA in the 7132LB switch either by using the hardware manager on the switch, or by copying the bit file to the switch with scp and then loading it onto the FPGA with xc3sprog.
To load the design with xc3sprog, run the following commands on the switch:
switch>en
switch#conf t
switch(config)#bash sudo bash
bash-4.2# user@host:/path/to/fpga.bit .
bash-4.2# xc3sprog -c metamako -J 10000000 fpga.bit
Once the design is running on the FPGA, 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

View File

@ -0,0 +1,533 @@
# XDC constraints for the Arista 7132LB
# part: xcvu9p-flgb2104-3-e
# General configuration
set_property CONFIG_VOLTAGE 1.8 [current_design]
set_property BITSTREAM.GENERAL.COMPRESS true [current_design]
set_property BITSTREAM.CONFIG.EXTMASTERCCLK_EN disable [current_design]
set_property BITSTREAM.CONFIG.SPI_32BIT_ADDR YES [current_design]
set_property BITSTREAM.CONFIG.SPI_BUSWIDTH 4 [current_design]
set_property BITSTREAM.CONFIG.SPI_FALL_EDGE YES [current_design]
set_property BITSTREAM.CONFIG.CONFIGRATE 63.8 [current_design]
set_property CONFIG_MODE SPIx4 [current_design]
set_property BITSTREAM.CONFIG.OVERTEMPSHUTDOWN Enable [current_design]
# System clocks
# User refclk 0 156.26 MHz
set_property -dict {LOC AY13 IOSTANDARD LVDS DIFF_TERM_ADV TERM_NONE} [get_ports {refclk_user_p[0]}]
set_property -dict {LOC BA13 IOSTANDARD LVDS DIFF_TERM_ADV TERM_NONE} [get_ports {refclk_user_n[0]}]
create_clock -period 6.400 -name refclk_user_0 [get_ports {refclk_user_p[0]}]
# User refclk 1 156.26 MHz
set_property -dict {LOC AW28 IOSTANDARD DIFF_SSTL12} [get_ports {refclk_user_p[1]}]
set_property -dict {LOC AY28 IOSTANDARD DIFF_SSTL12} [get_ports {refclk_user_n[1]}]
create_clock -period 6.400 -name refclk_user_1 [get_ports {refclk_user_p[1]}]
# DDR4 DIMM 0 refclk
#set_property -dict {LOC N32 IOSTANDARD DIFF_SSTL12} [get_ports clk_ddr4_dimm0_refclk_p]
#set_property -dict {LOC N33 IOSTANDARD DIFF_SSTL12} [get_ports clk_ddr4_dimm0_refclk_n]
#create_clock -period 3.333 -name clk_ddr4_dimm0_refclk [get_ports clk_ddr4_dimm0_refclk_p]
# DDR4 DIMM 1 refclk
#set_property -dict {LOC BA35 IOSTANDARD DIFF_SSTL12} [get_ports clk_ddr4_dimm1_refclk_p]
#set_property -dict {LOC BB35 IOSTANDARD DIFF_SSTL12} [get_ports clk_ddr4_dimm1_refclk_n]
#create_clock -period 3.333 -name clk_ddr4_dimm1_refclk [get_ports clk_ddr4_dimm1_refclk_p]
# DDR4 DIMM 2 refclk
#set_property -dict {LOC AV19 IOSTANDARD DIFF_SSTL12} [get_ports clk_ddr4_dimm2_refclk_p]
#set_property -dict {LOC AW19 IOSTANDARD DIFF_SSTL12} [get_ports clk_ddr4_dimm2_refclk_n]
#create_clock -period 3.333 -name clk_ddr4_dimm2_refclk [get_ports clk_ddr4_dimm2_refclk_p]
# DDR4 DIMM 3 refclk
#set_property -dict {LOC J16 IOSTANDARD DIFF_SSTL12} [get_ports clk_ddr4_dimm3_refclk_p]
#set_property -dict {LOC J15 IOSTANDARD DIFF_SSTL12} [get_ports clk_ddr4_dimm3_refclk_n]
#create_clock -period 3.333 -name clk_ddr4_dimm3_refclk [get_ports clk_ddr4_dimm3_refclk_p]
# Ethernet interfaces
# GTY quad 122
# 7132LB-48Y4C: SFP 1, 2, 3, 4
set_property -dict {LOC AN45} [get_ports {eth_gt_ch_rx_p[0]}] ;# MGTYRXP0_122 GTYE4_CHANNEL_X0Y12 / GTYE4_COMMON_X0Y3
set_property -dict {LOC AN46} [get_ports {eth_gt_ch_rx_n[0]}] ;# MGTYRXN0_122 GTYE4_CHANNEL_X0Y12 / GTYE4_COMMON_X0Y3
set_property -dict {LOC AN40} [get_ports {eth_gt_ch_tx_p[0]}] ;# MGTYTXP0_122 GTYE4_CHANNEL_X0Y12 / GTYE4_COMMON_X0Y3
set_property -dict {LOC AN41} [get_ports {eth_gt_ch_tx_n[0]}] ;# MGTYTXN0_122 GTYE4_CHANNEL_X0Y12 / GTYE4_COMMON_X0Y3
set_property -dict {LOC AM43} [get_ports {eth_gt_ch_rx_p[1]}] ;# MGTYRXP1_122 GTYE4_CHANNEL_X0Y13 / GTYE4_COMMON_X0Y3
set_property -dict {LOC AM44} [get_ports {eth_gt_ch_rx_n[1]}] ;# MGTYRXN1_122 GTYE4_CHANNEL_X0Y13 / GTYE4_COMMON_X0Y3
set_property -dict {LOC AM38} [get_ports {eth_gt_ch_tx_p[1]}] ;# MGTYTXP1_122 GTYE4_CHANNEL_X0Y13 / GTYE4_COMMON_X0Y3
set_property -dict {LOC AM39} [get_ports {eth_gt_ch_tx_n[1]}] ;# MGTYTXN1_122 GTYE4_CHANNEL_X0Y13 / GTYE4_COMMON_X0Y3
set_property -dict {LOC AL45} [get_ports {eth_gt_ch_rx_p[2]}] ;# MGTYRXP2_122 GTYE4_CHANNEL_X0Y14 / GTYE4_COMMON_X0Y3
set_property -dict {LOC AL46} [get_ports {eth_gt_ch_rx_n[2]}] ;# MGTYRXN2_122 GTYE4_CHANNEL_X0Y14 / GTYE4_COMMON_X0Y3
set_property -dict {LOC AL40} [get_ports {eth_gt_ch_tx_p[2]}] ;# MGTYTXP2_122 GTYE4_CHANNEL_X0Y14 / GTYE4_COMMON_X0Y3
set_property -dict {LOC AL41} [get_ports {eth_gt_ch_tx_n[2]}] ;# MGTYTXN2_122 GTYE4_CHANNEL_X0Y14 / GTYE4_COMMON_X0Y3
set_property -dict {LOC AK43} [get_ports {eth_gt_ch_rx_p[3]}] ;# MGTYRXP3_122 GTYE4_CHANNEL_X0Y15 / GTYE4_COMMON_X0Y3
set_property -dict {LOC AK44} [get_ports {eth_gt_ch_rx_n[3]}] ;# MGTYRXN3_122 GTYE4_CHANNEL_X0Y15 / GTYE4_COMMON_X0Y3
set_property -dict {LOC AK38} [get_ports {eth_gt_ch_tx_p[3]}] ;# MGTYTXP3_122 GTYE4_CHANNEL_X0Y15 / GTYE4_COMMON_X0Y3
set_property -dict {LOC AK39} [get_ports {eth_gt_ch_tx_n[3]}] ;# MGTYTXN3_122 GTYE4_CHANNEL_X0Y15 / GTYE4_COMMON_X0Y3
set_property -dict {LOC AR36} [get_ports {eth_gt_pri_refclk_p[0]}] ;# MGTREFCLK0P_122
set_property -dict {LOC AR37} [get_ports {eth_gt_pri_refclk_n[0]}] ;# MGTREFCLK0N_122
#set_property -dict {LOC AN36} [get_ports {eth_gt_sec_refclk_p[4]}] ;# MGTREFCLK1P_122
#set_property -dict {LOC AN37} [get_ports {eth_gt_sec_refclk_n[4]}] ;# MGTREFCLK1N_122
# 156.25 MHz MGT primary reference clock
create_clock -period 6.400 -name eth_gt_pri_refclk_0 [get_ports {eth_gt_pri_refclk_p[0]}]
# 125 MHz MGT secondary reference clock
#create_clock -period 8.000 -name eth_gt_sec_refclk_4 [get_ports {eth_gt_sec_refclk_p[4]}]
# GTY quad 123
# 7132LB-48Y4C: SFP 5, 6, 7, 8
set_property -dict {LOC AJ45} [get_ports {eth_gt_ch_rx_p[4]}] ;# MGTYRXP0_123 GTYE4_CHANNEL_X0Y16 / GTYE4_COMMON_X0Y4
set_property -dict {LOC AJ46} [get_ports {eth_gt_ch_rx_n[4]}] ;# MGTYRXN0_123 GTYE4_CHANNEL_X0Y16 / GTYE4_COMMON_X0Y4
set_property -dict {LOC AJ40} [get_ports {eth_gt_ch_tx_p[4]}] ;# MGTYTXP0_123 GTYE4_CHANNEL_X0Y16 / GTYE4_COMMON_X0Y4
set_property -dict {LOC AJ41} [get_ports {eth_gt_ch_tx_n[4]}] ;# MGTYTXN0_123 GTYE4_CHANNEL_X0Y16 / GTYE4_COMMON_X0Y4
set_property -dict {LOC AH43} [get_ports {eth_gt_ch_rx_p[5]}] ;# MGTYRXP1_123 GTYE4_CHANNEL_X0Y17 / GTYE4_COMMON_X0Y4
set_property -dict {LOC AH44} [get_ports {eth_gt_ch_rx_n[5]}] ;# MGTYRXN1_123 GTYE4_CHANNEL_X0Y17 / GTYE4_COMMON_X0Y4
set_property -dict {LOC AH38} [get_ports {eth_gt_ch_tx_p[5]}] ;# MGTYTXP1_123 GTYE4_CHANNEL_X0Y17 / GTYE4_COMMON_X0Y4
set_property -dict {LOC AH39} [get_ports {eth_gt_ch_tx_n[5]}] ;# MGTYTXN1_123 GTYE4_CHANNEL_X0Y17 / GTYE4_COMMON_X0Y4
set_property -dict {LOC AG45} [get_ports {eth_gt_ch_rx_p[6]}] ;# MGTYRXP2_123 GTYE4_CHANNEL_X0Y18 / GTYE4_COMMON_X0Y4
set_property -dict {LOC AG46} [get_ports {eth_gt_ch_rx_n[6]}] ;# MGTYRXN2_123 GTYE4_CHANNEL_X0Y18 / GTYE4_COMMON_X0Y4
set_property -dict {LOC AG40} [get_ports {eth_gt_ch_tx_p[6]}] ;# MGTYTXP2_123 GTYE4_CHANNEL_X0Y18 / GTYE4_COMMON_X0Y4
set_property -dict {LOC AG41} [get_ports {eth_gt_ch_tx_n[6]}] ;# MGTYTXN2_123 GTYE4_CHANNEL_X0Y18 / GTYE4_COMMON_X0Y4
set_property -dict {LOC AF43} [get_ports {eth_gt_ch_rx_p[7]}] ;# MGTYRXP3_123 GTYE4_CHANNEL_X0Y19 / GTYE4_COMMON_X0Y4
set_property -dict {LOC AF44} [get_ports {eth_gt_ch_rx_n[7]}] ;# MGTYRXN3_123 GTYE4_CHANNEL_X0Y19 / GTYE4_COMMON_X0Y4
set_property -dict {LOC AF38} [get_ports {eth_gt_ch_tx_p[7]}] ;# MGTYTXP3_123 GTYE4_CHANNEL_X0Y19 / GTYE4_COMMON_X0Y4
set_property -dict {LOC AF39} [get_ports {eth_gt_ch_tx_n[7]}] ;# MGTYTXN3_123 GTYE4_CHANNEL_X0Y19 / GTYE4_COMMON_X0Y4
set_property -dict {LOC AL36} [get_ports {eth_gt_pri_refclk_p[1]}] ;# MGTREFCLK0P_123
set_property -dict {LOC AL37} [get_ports {eth_gt_pri_refclk_n[1]}] ;# MGTREFCLK0N_123
# 156.25 MHz MGT primary reference clock
create_clock -period 6.400 -name eth_gt_pri_refclk_1 [get_ports {eth_gt_pri_refclk_p[1]}]
# GTY quad 124
# 7132LB-48Y4C: SFP 9, 10, 11, 12
set_property -dict {LOC AE45} [get_ports {eth_gt_ch_rx_p[8]}] ;# MGTYRXP0_124 GTYE4_CHANNEL_X0Y20 / GTYE4_COMMON_X0Y5
set_property -dict {LOC AE46} [get_ports {eth_gt_ch_rx_n[8]}] ;# MGTYRXN0_124 GTYE4_CHANNEL_X0Y20 / GTYE4_COMMON_X0Y5
set_property -dict {LOC AE40} [get_ports {eth_gt_ch_tx_p[8]}] ;# MGTYTXP0_124 GTYE4_CHANNEL_X0Y20 / GTYE4_COMMON_X0Y5
set_property -dict {LOC AE41} [get_ports {eth_gt_ch_tx_n[8]}] ;# MGTYTXN0_124 GTYE4_CHANNEL_X0Y20 / GTYE4_COMMON_X0Y5
set_property -dict {LOC AD43} [get_ports {eth_gt_ch_rx_p[9]}] ;# MGTYRXP1_124 GTYE4_CHANNEL_X0Y21 / GTYE4_COMMON_X0Y5
set_property -dict {LOC AD44} [get_ports {eth_gt_ch_rx_n[9]}] ;# MGTYRXN1_124 GTYE4_CHANNEL_X0Y21 / GTYE4_COMMON_X0Y5
set_property -dict {LOC AD38} [get_ports {eth_gt_ch_tx_p[9]}] ;# MGTYTXP1_124 GTYE4_CHANNEL_X0Y21 / GTYE4_COMMON_X0Y5
set_property -dict {LOC AD39} [get_ports {eth_gt_ch_tx_n[9]}] ;# MGTYTXN1_124 GTYE4_CHANNEL_X0Y21 / GTYE4_COMMON_X0Y5
set_property -dict {LOC AC45} [get_ports {eth_gt_ch_rx_p[10]}] ;# MGTYRXP2_124 GTYE4_CHANNEL_X0Y22 / GTYE4_COMMON_X0Y5
set_property -dict {LOC AC46} [get_ports {eth_gt_ch_rx_n[10]}] ;# MGTYRXN2_124 GTYE4_CHANNEL_X0Y22 / GTYE4_COMMON_X0Y5
set_property -dict {LOC AC40} [get_ports {eth_gt_ch_tx_p[10]}] ;# MGTYTXP2_124 GTYE4_CHANNEL_X0Y22 / GTYE4_COMMON_X0Y5
set_property -dict {LOC AC41} [get_ports {eth_gt_ch_tx_n[10]}] ;# MGTYTXN2_124 GTYE4_CHANNEL_X0Y22 / GTYE4_COMMON_X0Y5
set_property -dict {LOC AB43} [get_ports {eth_gt_ch_rx_p[11]}] ;# MGTYRXP3_124 GTYE4_CHANNEL_X0Y23 / GTYE4_COMMON_X0Y5
set_property -dict {LOC AB44} [get_ports {eth_gt_ch_rx_n[11]}] ;# MGTYRXN3_124 GTYE4_CHANNEL_X0Y23 / GTYE4_COMMON_X0Y5
set_property -dict {LOC AB38} [get_ports {eth_gt_ch_tx_p[11]}] ;# MGTYTXP3_124 GTYE4_CHANNEL_X0Y23 / GTYE4_COMMON_X0Y5
set_property -dict {LOC AB39} [get_ports {eth_gt_ch_tx_n[11]}] ;# MGTYTXN3_124 GTYE4_CHANNEL_X0Y23 / GTYE4_COMMON_X0Y5
set_property -dict {LOC AG36} [get_ports {eth_gt_pri_refclk_p[2]}] ;# MGTREFCLK0P_124
set_property -dict {LOC AG37} [get_ports {eth_gt_pri_refclk_n[2]}] ;# MGTREFCLK0N_124
# 156.25 MHz MGT primary reference clock
create_clock -period 6.400 -name eth_gt_pri_refclk_2 [get_ports {eth_gt_pri_refclk_p[2]}]
# GTY quad 125
# 7132LB-48Y4C: SFP 13, 14, 15, 16
set_property -dict {LOC AA45} [get_ports {eth_gt_ch_rx_p[12]}] ;# MGTYRXP0_125 GTYE4_CHANNEL_X0Y24 / GTYE4_COMMON_X0Y6
set_property -dict {LOC AA46} [get_ports {eth_gt_ch_rx_n[12]}] ;# MGTYRXN0_125 GTYE4_CHANNEL_X0Y24 / GTYE4_COMMON_X0Y6
set_property -dict {LOC AA40} [get_ports {eth_gt_ch_tx_p[12]}] ;# MGTYTXP0_125 GTYE4_CHANNEL_X0Y24 / GTYE4_COMMON_X0Y6
set_property -dict {LOC AA41} [get_ports {eth_gt_ch_tx_n[12]}] ;# MGTYTXN0_125 GTYE4_CHANNEL_X0Y24 / GTYE4_COMMON_X0Y6
set_property -dict {LOC Y43 } [get_ports {eth_gt_ch_rx_p[13]}] ;# MGTYRXP1_125 GTYE4_CHANNEL_X0Y25 / GTYE4_COMMON_X0Y6
set_property -dict {LOC Y44 } [get_ports {eth_gt_ch_rx_n[13]}] ;# MGTYRXN1_125 GTYE4_CHANNEL_X0Y25 / GTYE4_COMMON_X0Y6
set_property -dict {LOC Y38 } [get_ports {eth_gt_ch_tx_p[13]}] ;# MGTYTXP1_125 GTYE4_CHANNEL_X0Y25 / GTYE4_COMMON_X0Y6
set_property -dict {LOC Y39 } [get_ports {eth_gt_ch_tx_n[13]}] ;# MGTYTXN1_125 GTYE4_CHANNEL_X0Y25 / GTYE4_COMMON_X0Y6
set_property -dict {LOC W45 } [get_ports {eth_gt_ch_rx_p[14]}] ;# MGTYRXP2_125 GTYE4_CHANNEL_X0Y26 / GTYE4_COMMON_X0Y6
set_property -dict {LOC W46 } [get_ports {eth_gt_ch_rx_n[14]}] ;# MGTYRXN2_125 GTYE4_CHANNEL_X0Y26 / GTYE4_COMMON_X0Y6
set_property -dict {LOC W40 } [get_ports {eth_gt_ch_tx_p[14]}] ;# MGTYTXP2_125 GTYE4_CHANNEL_X0Y26 / GTYE4_COMMON_X0Y6
set_property -dict {LOC W41 } [get_ports {eth_gt_ch_tx_n[14]}] ;# MGTYTXN2_125 GTYE4_CHANNEL_X0Y26 / GTYE4_COMMON_X0Y6
set_property -dict {LOC V43 } [get_ports {eth_gt_ch_rx_p[15]}] ;# MGTYRXP3_125 GTYE4_CHANNEL_X0Y27 / GTYE4_COMMON_X0Y6
set_property -dict {LOC V44 } [get_ports {eth_gt_ch_rx_n[15]}] ;# MGTYRXN3_125 GTYE4_CHANNEL_X0Y27 / GTYE4_COMMON_X0Y6
set_property -dict {LOC V38 } [get_ports {eth_gt_ch_tx_p[15]}] ;# MGTYTXP3_125 GTYE4_CHANNEL_X0Y27 / GTYE4_COMMON_X0Y6
set_property -dict {LOC V39 } [get_ports {eth_gt_ch_tx_n[15]}] ;# MGTYTXN3_125 GTYE4_CHANNEL_X0Y27 / GTYE4_COMMON_X0Y6
set_property -dict {LOC AC36} [get_ports {eth_gt_pri_refclk_p[3]}] ;# MGTREFCLK0P_125
set_property -dict {LOC AC37} [get_ports {eth_gt_pri_refclk_n[3]}] ;# MGTREFCLK0N_125
# 156.25 MHz MGT primary reference clock
create_clock -period 6.400 -name eth_gt_pri_refclk_3 [get_ports {eth_gt_pri_refclk_p[3]}]
# GTY quad 126
# 7132LB-48Y4C: SFP 17, 18, 19, 20
set_property -dict {LOC U45 } [get_ports {eth_gt_ch_rx_p[16]}] ;# MGTYRXP0_126 GTYE4_CHANNEL_X0Y28 / GTYE4_COMMON_X0Y7
set_property -dict {LOC U46 } [get_ports {eth_gt_ch_rx_n[16]}] ;# MGTYRXN0_126 GTYE4_CHANNEL_X0Y28 / GTYE4_COMMON_X0Y7
set_property -dict {LOC U40 } [get_ports {eth_gt_ch_tx_p[16]}] ;# MGTYTXP0_126 GTYE4_CHANNEL_X0Y28 / GTYE4_COMMON_X0Y7
set_property -dict {LOC U41 } [get_ports {eth_gt_ch_tx_n[16]}] ;# MGTYTXN0_126 GTYE4_CHANNEL_X0Y28 / GTYE4_COMMON_X0Y7
set_property -dict {LOC T43 } [get_ports {eth_gt_ch_rx_p[17]}] ;# MGTYRXP1_126 GTYE4_CHANNEL_X0Y29 / GTYE4_COMMON_X0Y7
set_property -dict {LOC T44 } [get_ports {eth_gt_ch_rx_n[17]}] ;# MGTYRXN1_126 GTYE4_CHANNEL_X0Y29 / GTYE4_COMMON_X0Y7
set_property -dict {LOC T38 } [get_ports {eth_gt_ch_tx_p[17]}] ;# MGTYTXP1_126 GTYE4_CHANNEL_X0Y29 / GTYE4_COMMON_X0Y7
set_property -dict {LOC T39 } [get_ports {eth_gt_ch_tx_n[17]}] ;# MGTYTXN1_126 GTYE4_CHANNEL_X0Y29 / GTYE4_COMMON_X0Y7
set_property -dict {LOC R45 } [get_ports {eth_gt_ch_rx_p[18]}] ;# MGTYRXP2_126 GTYE4_CHANNEL_X0Y30 / GTYE4_COMMON_X0Y7
set_property -dict {LOC R46 } [get_ports {eth_gt_ch_rx_n[18]}] ;# MGTYRXN2_126 GTYE4_CHANNEL_X0Y30 / GTYE4_COMMON_X0Y7
set_property -dict {LOC R40 } [get_ports {eth_gt_ch_tx_p[18]}] ;# MGTYTXP2_126 GTYE4_CHANNEL_X0Y30 / GTYE4_COMMON_X0Y7
set_property -dict {LOC R41 } [get_ports {eth_gt_ch_tx_n[18]}] ;# MGTYTXN2_126 GTYE4_CHANNEL_X0Y30 / GTYE4_COMMON_X0Y7
set_property -dict {LOC P43 } [get_ports {eth_gt_ch_rx_p[19]}] ;# MGTYRXP3_126 GTYE4_CHANNEL_X0Y31 / GTYE4_COMMON_X0Y7
set_property -dict {LOC P44 } [get_ports {eth_gt_ch_rx_n[19]}] ;# MGTYRXN3_126 GTYE4_CHANNEL_X0Y31 / GTYE4_COMMON_X0Y7
set_property -dict {LOC P38 } [get_ports {eth_gt_ch_tx_p[19]}] ;# MGTYTXP3_126 GTYE4_CHANNEL_X0Y31 / GTYE4_COMMON_X0Y7
set_property -dict {LOC P39 } [get_ports {eth_gt_ch_tx_n[19]}] ;# MGTYTXN3_126 GTYE4_CHANNEL_X0Y31 / GTYE4_COMMON_X0Y7
set_property -dict {LOC W36 } [get_ports {eth_gt_pri_refclk_p[4]}] ;# MGTREFCLK0P_126
set_property -dict {LOC W37 } [get_ports {eth_gt_pri_refclk_n[4]}] ;# MGTREFCLK0N_126
#set_property -dict {LOC U36 } [get_ports {eth_gt_sec_refclk_p[5]}] ;# MGTREFCLK1P_126
#set_property -dict {LOC U37 } [get_ports {eth_gt_sec_refclk_n[5]}] ;# MGTREFCLK1N_126
# 156.25 MHz MGT primary reference clock
create_clock -period 6.400 -name eth_gt_pri_refclk_4 [get_ports {eth_gt_pri_refclk_p[4]}]
# 125 MHz MGT secondary reference clock
#create_clock -period 8.000 -name eth_gt_sec_refclk_5 [get_ports {eth_gt_sec_refclk_p[5]}]
# GTY quad 127
# 7132LB-48Y4C: SFP 21, 22, 23, 24
set_property -dict {LOC N45 } [get_ports {eth_gt_ch_rx_p[20]}] ;# MGTYRXP0_127 GTYE4_CHANNEL_X0Y32 / GTYE4_COMMON_X0Y8
set_property -dict {LOC N46 } [get_ports {eth_gt_ch_rx_n[20]}] ;# MGTYRXN0_127 GTYE4_CHANNEL_X0Y32 / GTYE4_COMMON_X0Y8
set_property -dict {LOC N40 } [get_ports {eth_gt_ch_tx_p[20]}] ;# MGTYTXP0_127 GTYE4_CHANNEL_X0Y32 / GTYE4_COMMON_X0Y8
set_property -dict {LOC N41 } [get_ports {eth_gt_ch_tx_n[20]}] ;# MGTYTXN0_127 GTYE4_CHANNEL_X0Y32 / GTYE4_COMMON_X0Y8
set_property -dict {LOC M43 } [get_ports {eth_gt_ch_rx_p[21]}] ;# MGTYRXP1_127 GTYE4_CHANNEL_X0Y33 / GTYE4_COMMON_X0Y8
set_property -dict {LOC M44 } [get_ports {eth_gt_ch_rx_n[21]}] ;# MGTYRXN1_127 GTYE4_CHANNEL_X0Y33 / GTYE4_COMMON_X0Y8
set_property -dict {LOC M38 } [get_ports {eth_gt_ch_tx_p[21]}] ;# MGTYTXP1_127 GTYE4_CHANNEL_X0Y33 / GTYE4_COMMON_X0Y8
set_property -dict {LOC M39 } [get_ports {eth_gt_ch_tx_n[21]}] ;# MGTYTXN1_127 GTYE4_CHANNEL_X0Y33 / GTYE4_COMMON_X0Y8
set_property -dict {LOC L45 } [get_ports {eth_gt_ch_rx_p[22]}] ;# MGTYRXP2_127 GTYE4_CHANNEL_X0Y34 / GTYE4_COMMON_X0Y8
set_property -dict {LOC L46 } [get_ports {eth_gt_ch_rx_n[22]}] ;# MGTYRXN2_127 GTYE4_CHANNEL_X0Y34 / GTYE4_COMMON_X0Y8
set_property -dict {LOC L40 } [get_ports {eth_gt_ch_tx_p[22]}] ;# MGTYTXP2_127 GTYE4_CHANNEL_X0Y34 / GTYE4_COMMON_X0Y8
set_property -dict {LOC L41 } [get_ports {eth_gt_ch_tx_n[22]}] ;# MGTYTXN2_127 GTYE4_CHANNEL_X0Y34 / GTYE4_COMMON_X0Y8
set_property -dict {LOC K43 } [get_ports {eth_gt_ch_rx_p[23]}] ;# MGTYRXP3_127 GTYE4_CHANNEL_X0Y35 / GTYE4_COMMON_X0Y8
set_property -dict {LOC K44 } [get_ports {eth_gt_ch_rx_n[23]}] ;# MGTYRXN3_127 GTYE4_CHANNEL_X0Y35 / GTYE4_COMMON_X0Y8
set_property -dict {LOC J40 } [get_ports {eth_gt_ch_tx_p[23]}] ;# MGTYTXP3_127 GTYE4_CHANNEL_X0Y35 / GTYE4_COMMON_X0Y8
set_property -dict {LOC J41 } [get_ports {eth_gt_ch_tx_n[23]}] ;# MGTYTXN3_127 GTYE4_CHANNEL_X0Y35 / GTYE4_COMMON_X0Y8
set_property -dict {LOC R36 } [get_ports {eth_gt_pri_refclk_p[5]}] ;# MGTREFCLK0P_127
set_property -dict {LOC R37 } [get_ports {eth_gt_pri_refclk_n[5]}] ;# MGTREFCLK0N_127
# 156.25 MHz MGT primary reference clock
create_clock -period 6.400 -name eth_gt_pri_refclk_5 [get_ports {eth_gt_pri_refclk_p[5]}]
# GTY quad 232
# 7132LB-48Y4C: SFP 28, 27, 26, 25
set_property -dict {LOC F2 } [get_ports {eth_gt_ch_rx_p[24]}] ;# MGTYRXP3_232 GTYE4_CHANNEL_X1Y55 / GTYE4_COMMON_X1Y13
set_property -dict {LOC F1 } [get_ports {eth_gt_ch_rx_n[24]}] ;# MGTYRXN3_232 GTYE4_CHANNEL_X1Y55 / GTYE4_COMMON_X1Y13
set_property -dict {LOC F7 } [get_ports {eth_gt_ch_tx_p[24]}] ;# MGTYTXP3_232 GTYE4_CHANNEL_X1Y55 / GTYE4_COMMON_X1Y13
set_property -dict {LOC F6 } [get_ports {eth_gt_ch_tx_n[24]}] ;# MGTYTXN3_232 GTYE4_CHANNEL_X1Y55 / GTYE4_COMMON_X1Y13
set_property -dict {LOC G4 } [get_ports {eth_gt_ch_rx_p[25]}] ;# MGTYRXP2_232 GTYE4_CHANNEL_X1Y54 / GTYE4_COMMON_X1Y13
set_property -dict {LOC G3 } [get_ports {eth_gt_ch_rx_n[25]}] ;# MGTYRXN2_232 GTYE4_CHANNEL_X1Y54 / GTYE4_COMMON_X1Y13
set_property -dict {LOC G9 } [get_ports {eth_gt_ch_tx_p[25]}] ;# MGTYTXP2_232 GTYE4_CHANNEL_X1Y54 / GTYE4_COMMON_X1Y13
set_property -dict {LOC G8 } [get_ports {eth_gt_ch_tx_n[25]}] ;# MGTYTXN2_232 GTYE4_CHANNEL_X1Y54 / GTYE4_COMMON_X1Y13
set_property -dict {LOC H2 } [get_ports {eth_gt_ch_rx_p[26]}] ;# MGTYRXP1_232 GTYE4_CHANNEL_X1Y53 / GTYE4_COMMON_X1Y13
set_property -dict {LOC H1 } [get_ports {eth_gt_ch_rx_n[26]}] ;# MGTYRXN1_232 GTYE4_CHANNEL_X1Y53 / GTYE4_COMMON_X1Y13
set_property -dict {LOC H7 } [get_ports {eth_gt_ch_tx_p[26]}] ;# MGTYTXP1_232 GTYE4_CHANNEL_X1Y53 / GTYE4_COMMON_X1Y13
set_property -dict {LOC H6 } [get_ports {eth_gt_ch_tx_n[26]}] ;# MGTYTXN1_232 GTYE4_CHANNEL_X1Y53 / GTYE4_COMMON_X1Y13
set_property -dict {LOC J4 } [get_ports {eth_gt_ch_rx_p[27]}] ;# MGTYRXP0_232 GTYE4_CHANNEL_X1Y52 / GTYE4_COMMON_X1Y13
set_property -dict {LOC J3 } [get_ports {eth_gt_ch_rx_n[27]}] ;# MGTYRXN0_232 GTYE4_CHANNEL_X1Y52 / GTYE4_COMMON_X1Y13
set_property -dict {LOC J9 } [get_ports {eth_gt_ch_tx_p[27]}] ;# MGTYTXP0_232 GTYE4_CHANNEL_X1Y52 / GTYE4_COMMON_X1Y13
set_property -dict {LOC J8 } [get_ports {eth_gt_ch_tx_n[27]}] ;# MGTYTXN0_232 GTYE4_CHANNEL_X1Y52 / GTYE4_COMMON_X1Y13
set_property -dict {LOC H11 } [get_ports {eth_gt_pri_refclk_p[6]}] ;# MGTREFCLK0P_232
set_property -dict {LOC H10 } [get_ports {eth_gt_pri_refclk_n[6]}] ;# MGTREFCLK0N_232
# 156.25 MHz MGT primary reference clock
create_clock -period 6.400 -name eth_gt_pri_refclk_6 [get_ports {eth_gt_pri_refclk_p[6]}]
# GTY quad 231
# 7132LB-48Y4C: SFP 32, 31, 30, 29
set_property -dict {LOC K2 } [get_ports {eth_gt_ch_rx_p[28]}] ;# MGTYRXP3_231 GTYE4_CHANNEL_X1Y51 / GTYE4_COMMON_X1Y12
set_property -dict {LOC K1 } [get_ports {eth_gt_ch_rx_n[28]}] ;# MGTYRXN3_231 GTYE4_CHANNEL_X1Y51 / GTYE4_COMMON_X1Y12
set_property -dict {LOC K7 } [get_ports {eth_gt_ch_tx_p[28]}] ;# MGTYTXP3_231 GTYE4_CHANNEL_X1Y51 / GTYE4_COMMON_X1Y12
set_property -dict {LOC K6 } [get_ports {eth_gt_ch_tx_n[28]}] ;# MGTYTXN3_231 GTYE4_CHANNEL_X1Y51 / GTYE4_COMMON_X1Y12
set_property -dict {LOC L4 } [get_ports {eth_gt_ch_rx_p[29]}] ;# MGTYRXP2_231 GTYE4_CHANNEL_X1Y50 / GTYE4_COMMON_X1Y12
set_property -dict {LOC L3 } [get_ports {eth_gt_ch_rx_n[29]}] ;# MGTYRXN2_231 GTYE4_CHANNEL_X1Y50 / GTYE4_COMMON_X1Y12
set_property -dict {LOC L9 } [get_ports {eth_gt_ch_tx_p[29]}] ;# MGTYTXP2_231 GTYE4_CHANNEL_X1Y50 / GTYE4_COMMON_X1Y12
set_property -dict {LOC L8 } [get_ports {eth_gt_ch_tx_n[29]}] ;# MGTYTXN2_231 GTYE4_CHANNEL_X1Y50 / GTYE4_COMMON_X1Y12
set_property -dict {LOC M2 } [get_ports {eth_gt_ch_rx_p[30]}] ;# MGTYRXP1_231 GTYE4_CHANNEL_X1Y49 / GTYE4_COMMON_X1Y12
set_property -dict {LOC M1 } [get_ports {eth_gt_ch_rx_n[30]}] ;# MGTYRXN1_231 GTYE4_CHANNEL_X1Y49 / GTYE4_COMMON_X1Y12
set_property -dict {LOC M7 } [get_ports {eth_gt_ch_tx_p[30]}] ;# MGTYTXP1_231 GTYE4_CHANNEL_X1Y49 / GTYE4_COMMON_X1Y12
set_property -dict {LOC M6 } [get_ports {eth_gt_ch_tx_n[30]}] ;# MGTYTXN1_231 GTYE4_CHANNEL_X1Y49 / GTYE4_COMMON_X1Y12
set_property -dict {LOC N4 } [get_ports {eth_gt_ch_rx_p[31]}] ;# MGTYRXP0_231 GTYE4_CHANNEL_X1Y48 / GTYE4_COMMON_X1Y12
set_property -dict {LOC N3 } [get_ports {eth_gt_ch_rx_n[31]}] ;# MGTYRXN0_231 GTYE4_CHANNEL_X1Y48 / GTYE4_COMMON_X1Y12
set_property -dict {LOC N9 } [get_ports {eth_gt_ch_tx_p[31]}] ;# MGTYTXP0_231 GTYE4_CHANNEL_X1Y48 / GTYE4_COMMON_X1Y12
set_property -dict {LOC N8 } [get_ports {eth_gt_ch_tx_n[31]}] ;# MGTYTXN0_231 GTYE4_CHANNEL_X1Y48 / GTYE4_COMMON_X1Y12
set_property -dict {LOC M11 } [get_ports {eth_gt_pri_refclk_p[7]}] ;# MGTREFCLK0P_231
set_property -dict {LOC M10 } [get_ports {eth_gt_pri_refclk_n[7]}] ;# MGTREFCLK0N_231
#set_property -dict {LOC K11 } [get_ports {eth_gt_sec_refclk_p[2]}] ;# MGTREFCLK1P_231
#set_property -dict {LOC K10 } [get_ports {eth_gt_sec_refclk_n[2]}] ;# MGTREFCLK1N_231
# 156.25 MHz MGT primary reference clock
create_clock -period 6.400 -name eth_gt_pri_refclk_7 [get_ports {eth_gt_pri_refclk_p[7]}]
# 125 MHz MGT secondary reference clock
#create_clock -period 8.000 -name eth_gt_sec_refclk_2 [get_ports {eth_gt_sec_refclk_p[2]}]
# GTY quad 230
# 7132LB-48Y4C: SFP 36, 35, 34, 33
set_property -dict {LOC P2 } [get_ports {eth_gt_ch_rx_p[32]}] ;# MGTYRXP3_230 GTYE4_CHANNEL_X1Y47 / GTYE4_COMMON_X1Y11
set_property -dict {LOC P1 } [get_ports {eth_gt_ch_rx_n[32]}] ;# MGTYRXN3_230 GTYE4_CHANNEL_X1Y47 / GTYE4_COMMON_X1Y11
set_property -dict {LOC P7 } [get_ports {eth_gt_ch_tx_p[32]}] ;# MGTYTXP3_230 GTYE4_CHANNEL_X1Y47 / GTYE4_COMMON_X1Y11
set_property -dict {LOC P6 } [get_ports {eth_gt_ch_tx_n[32]}] ;# MGTYTXN3_230 GTYE4_CHANNEL_X1Y47 / GTYE4_COMMON_X1Y11
set_property -dict {LOC R4 } [get_ports {eth_gt_ch_rx_p[33]}] ;# MGTYRXP2_230 GTYE4_CHANNEL_X1Y46 / GTYE4_COMMON_X1Y11
set_property -dict {LOC R3 } [get_ports {eth_gt_ch_rx_n[33]}] ;# MGTYRXN2_230 GTYE4_CHANNEL_X1Y46 / GTYE4_COMMON_X1Y11
set_property -dict {LOC R9 } [get_ports {eth_gt_ch_tx_p[33]}] ;# MGTYTXP2_230 GTYE4_CHANNEL_X1Y46 / GTYE4_COMMON_X1Y11
set_property -dict {LOC R8 } [get_ports {eth_gt_ch_tx_n[33]}] ;# MGTYTXN2_230 GTYE4_CHANNEL_X1Y46 / GTYE4_COMMON_X1Y11
set_property -dict {LOC T2 } [get_ports {eth_gt_ch_rx_p[34]}] ;# MGTYRXP1_230 GTYE4_CHANNEL_X1Y45 / GTYE4_COMMON_X1Y11
set_property -dict {LOC T1 } [get_ports {eth_gt_ch_rx_n[34]}] ;# MGTYRXN1_230 GTYE4_CHANNEL_X1Y45 / GTYE4_COMMON_X1Y11
set_property -dict {LOC T7 } [get_ports {eth_gt_ch_tx_p[34]}] ;# MGTYTXP1_230 GTYE4_CHANNEL_X1Y45 / GTYE4_COMMON_X1Y11
set_property -dict {LOC T6 } [get_ports {eth_gt_ch_tx_n[34]}] ;# MGTYTXN1_230 GTYE4_CHANNEL_X1Y45 / GTYE4_COMMON_X1Y11
set_property -dict {LOC U4 } [get_ports {eth_gt_ch_rx_p[35]}] ;# MGTYRXP0_230 GTYE4_CHANNEL_X1Y44 / GTYE4_COMMON_X1Y11
set_property -dict {LOC U3 } [get_ports {eth_gt_ch_rx_n[35]}] ;# MGTYRXN0_230 GTYE4_CHANNEL_X1Y44 / GTYE4_COMMON_X1Y11
set_property -dict {LOC U9 } [get_ports {eth_gt_ch_tx_p[35]}] ;# MGTYTXP0_230 GTYE4_CHANNEL_X1Y44 / GTYE4_COMMON_X1Y11
set_property -dict {LOC U8 } [get_ports {eth_gt_ch_tx_n[35]}] ;# MGTYTXN0_230 GTYE4_CHANNEL_X1Y44 / GTYE4_COMMON_X1Y11
set_property -dict {LOC T11 } [get_ports {eth_gt_pri_refclk_p[8]}] ;# MGTREFCLK0P_230
set_property -dict {LOC T10 } [get_ports {eth_gt_pri_refclk_n[8]}] ;# MGTREFCLK0N_230
# 156.25 MHz MGT primary reference clock
create_clock -period 6.400 -name eth_gt_pri_refclk_8 [get_ports {eth_gt_pri_refclk_p[8]}]
# GTY quad 229
# 7132LB-48Y4C: SFP 40, 39, 38, 37
set_property -dict {LOC V2 } [get_ports {eth_gt_ch_rx_p[36]}] ;# MGTYRXP3_229 GTYE4_CHANNEL_X1Y43 / GTYE4_COMMON_X1Y10
set_property -dict {LOC V1 } [get_ports {eth_gt_ch_rx_n[36]}] ;# MGTYRXN3_229 GTYE4_CHANNEL_X1Y43 / GTYE4_COMMON_X1Y10
set_property -dict {LOC V7 } [get_ports {eth_gt_ch_tx_p[36]}] ;# MGTYTXP3_229 GTYE4_CHANNEL_X1Y43 / GTYE4_COMMON_X1Y10
set_property -dict {LOC V6 } [get_ports {eth_gt_ch_tx_n[36]}] ;# MGTYTXN3_229 GTYE4_CHANNEL_X1Y43 / GTYE4_COMMON_X1Y10
set_property -dict {LOC W4 } [get_ports {eth_gt_ch_rx_p[37]}] ;# MGTYRXP2_229 GTYE4_CHANNEL_X1Y42 / GTYE4_COMMON_X1Y10
set_property -dict {LOC W3 } [get_ports {eth_gt_ch_rx_n[37]}] ;# MGTYRXN2_229 GTYE4_CHANNEL_X1Y42 / GTYE4_COMMON_X1Y10
set_property -dict {LOC W9 } [get_ports {eth_gt_ch_tx_p[37]}] ;# MGTYTXP2_229 GTYE4_CHANNEL_X1Y42 / GTYE4_COMMON_X1Y10
set_property -dict {LOC W8 } [get_ports {eth_gt_ch_tx_n[37]}] ;# MGTYTXN2_229 GTYE4_CHANNEL_X1Y42 / GTYE4_COMMON_X1Y10
set_property -dict {LOC Y2 } [get_ports {eth_gt_ch_rx_p[38]}] ;# MGTYRXP1_229 GTYE4_CHANNEL_X1Y41 / GTYE4_COMMON_X1Y10
set_property -dict {LOC Y1 } [get_ports {eth_gt_ch_rx_n[38]}] ;# MGTYRXN1_229 GTYE4_CHANNEL_X1Y41 / GTYE4_COMMON_X1Y10
set_property -dict {LOC Y7 } [get_ports {eth_gt_ch_tx_p[38]}] ;# MGTYTXP1_229 GTYE4_CHANNEL_X1Y41 / GTYE4_COMMON_X1Y10
set_property -dict {LOC Y6 } [get_ports {eth_gt_ch_tx_n[38]}] ;# MGTYTXN1_229 GTYE4_CHANNEL_X1Y41 / GTYE4_COMMON_X1Y10
set_property -dict {LOC AA4 } [get_ports {eth_gt_ch_rx_p[39]}] ;# MGTYRXP0_229 GTYE4_CHANNEL_X1Y40 / GTYE4_COMMON_X1Y10
set_property -dict {LOC AA3 } [get_ports {eth_gt_ch_rx_n[39]}] ;# MGTYRXNN_229 GTYE4_CHANNEL_X1Y40 / GTYE4_COMMON_X1Y10
set_property -dict {LOC AA9 } [get_ports {eth_gt_ch_tx_p[39]}] ;# MGTYTXP0_229 GTYE4_CHANNEL_X1Y40 / GTYE4_COMMON_X1Y10
set_property -dict {LOC AA8 } [get_ports {eth_gt_ch_tx_n[39]}] ;# MGTYTXNN_229 GTYE4_CHANNEL_X1Y40 / GTYE4_COMMON_X1Y10
set_property -dict {LOC Y11 } [get_ports {eth_gt_pri_refclk_p[9]}] ;# MGTREFCLK0P_229
set_property -dict {LOC Y10 } [get_ports {eth_gt_pri_refclk_n[9]}] ;# MGTREFCLK0N_229
#set_property -dict {LOC V11 } [get_ports {eth_gt_sec_refclk_p[1]}] ;# MGTREFCLK1P_229
#set_property -dict {LOC V10 } [get_ports {eth_gt_sec_refclk_n[1]}] ;# MGTREFCLK1N_229
# 156.25 MHz MGT primary reference clock
create_clock -period 6.400 -name eth_gt_pri_refclk_9 [get_ports {eth_gt_pri_refclk_p[9]}]
# 125 MHz MGT secondary reference clock
#create_clock -period 8.000 -name eth_gt_sec_refclk_1 [get_ports {eth_gt_sec_refclk_p[1]}]
# GTY quad 228
# 7132LB-48Y4C: SFP 44, 43, 42, 41
set_property -dict {LOC AB2 } [get_ports {eth_gt_ch_rx_p[40]}] ;# MGTYRXP3_228 GTYE4_CHANNEL_X1Y39 / GTYE4_COMMON_X1Y9
set_property -dict {LOC AB1 } [get_ports {eth_gt_ch_rx_n[40]}] ;# MGTYRXN3_228 GTYE4_CHANNEL_X1Y39 / GTYE4_COMMON_X1Y9
set_property -dict {LOC AB7 } [get_ports {eth_gt_ch_tx_p[40]}] ;# MGTYTXP3_228 GTYE4_CHANNEL_X1Y39 / GTYE4_COMMON_X1Y9
set_property -dict {LOC AB6 } [get_ports {eth_gt_ch_tx_n[40]}] ;# MGTYTXN3_228 GTYE4_CHANNEL_X1Y39 / GTYE4_COMMON_X1Y9
set_property -dict {LOC AC4 } [get_ports {eth_gt_ch_rx_p[41]}] ;# MGTYRXP2_228 GTYE4_CHANNEL_X1Y38 / GTYE4_COMMON_X1Y9
set_property -dict {LOC AC3 } [get_ports {eth_gt_ch_rx_n[41]}] ;# MGTYRXN2_228 GTYE4_CHANNEL_X1Y38 / GTYE4_COMMON_X1Y9
set_property -dict {LOC AC9 } [get_ports {eth_gt_ch_tx_p[41]}] ;# MGTYTXP2_228 GTYE4_CHANNEL_X1Y38 / GTYE4_COMMON_X1Y9
set_property -dict {LOC AC8 } [get_ports {eth_gt_ch_tx_n[41]}] ;# MGTYTXN2_228 GTYE4_CHANNEL_X1Y38 / GTYE4_COMMON_X1Y9
set_property -dict {LOC AD2 } [get_ports {eth_gt_ch_rx_p[42]}] ;# MGTYRXP1_228 GTYE4_CHANNEL_X1Y37 / GTYE4_COMMON_X1Y9
set_property -dict {LOC AD1 } [get_ports {eth_gt_ch_rx_n[42]}] ;# MGTYRXN1_228 GTYE4_CHANNEL_X1Y37 / GTYE4_COMMON_X1Y9
set_property -dict {LOC AD7 } [get_ports {eth_gt_ch_tx_p[42]}] ;# MGTYTXP1_228 GTYE4_CHANNEL_X1Y37 / GTYE4_COMMON_X1Y9
set_property -dict {LOC AD6 } [get_ports {eth_gt_ch_tx_n[42]}] ;# MGTYTXN1_228 GTYE4_CHANNEL_X1Y37 / GTYE4_COMMON_X1Y9
set_property -dict {LOC AE4 } [get_ports {eth_gt_ch_rx_p[43]}] ;# MGTYRXP0_228 GTYE4_CHANNEL_X1Y36 / GTYE4_COMMON_X1Y9
set_property -dict {LOC AE3 } [get_ports {eth_gt_ch_rx_n[43]}] ;# MGTYRXN0_228 GTYE4_CHANNEL_X1Y36 / GTYE4_COMMON_X1Y9
set_property -dict {LOC AE9 } [get_ports {eth_gt_ch_tx_p[43]}] ;# MGTYTXP0_228 GTYE4_CHANNEL_X1Y36 / GTYE4_COMMON_X1Y9
set_property -dict {LOC AE8 } [get_ports {eth_gt_ch_tx_n[43]}] ;# MGTYTXN0_228 GTYE4_CHANNEL_X1Y36 / GTYE4_COMMON_X1Y9
set_property -dict {LOC AD11} [get_ports {eth_gt_pri_refclk_p[10]}] ;# MGTREFCLK0P_228
set_property -dict {LOC AD10} [get_ports {eth_gt_pri_refclk_n[10]}] ;# MGTREFCLK0N_228
# 156.25 MHz MGT primary reference clock
create_clock -period 6.400 -name eth_gt_pri_refclk_10 [get_ports {eth_gt_pri_refclk_p[10]}]
# GTY quad 227
# 7132LB-48Y4C: SFP 48, 47, 46, 45
set_property -dict {LOC AF2 } [get_ports {eth_gt_ch_rx_p[44]}] ;# MGTYRXP3_227 GTYE4_CHANNEL_X1Y35 / GTYE4_COMMON_X1Y8
set_property -dict {LOC AF1 } [get_ports {eth_gt_ch_rx_n[44]}] ;# MGTYRXN3_227 GTYE4_CHANNEL_X1Y35 / GTYE4_COMMON_X1Y8
set_property -dict {LOC AF7 } [get_ports {eth_gt_ch_tx_p[44]}] ;# MGTYTXP3_227 GTYE4_CHANNEL_X1Y35 / GTYE4_COMMON_X1Y8
set_property -dict {LOC AF6 } [get_ports {eth_gt_ch_tx_n[44]}] ;# MGTYTXN3_227 GTYE4_CHANNEL_X1Y35 / GTYE4_COMMON_X1Y8
set_property -dict {LOC AG4 } [get_ports {eth_gt_ch_rx_p[45]}] ;# MGTYRXP2_227 GTYE4_CHANNEL_X1Y34 / GTYE4_COMMON_X1Y8
set_property -dict {LOC AG3 } [get_ports {eth_gt_ch_rx_n[45]}] ;# MGTYRXN2_227 GTYE4_CHANNEL_X1Y34 / GTYE4_COMMON_X1Y8
set_property -dict {LOC AG9 } [get_ports {eth_gt_ch_tx_p[45]}] ;# MGTYTXP2_227 GTYE4_CHANNEL_X1Y34 / GTYE4_COMMON_X1Y8
set_property -dict {LOC AG8 } [get_ports {eth_gt_ch_tx_n[45]}] ;# MGTYTXN2_227 GTYE4_CHANNEL_X1Y34 / GTYE4_COMMON_X1Y8
set_property -dict {LOC AH2 } [get_ports {eth_gt_ch_rx_p[46]}] ;# MGTYRXP1_227 GTYE4_CHANNEL_X1Y33 / GTYE4_COMMON_X1Y8
set_property -dict {LOC AH1 } [get_ports {eth_gt_ch_rx_n[46]}] ;# MGTYRXN1_227 GTYE4_CHANNEL_X1Y33 / GTYE4_COMMON_X1Y8
set_property -dict {LOC AH7 } [get_ports {eth_gt_ch_tx_p[46]}] ;# MGTYTXP1_227 GTYE4_CHANNEL_X1Y33 / GTYE4_COMMON_X1Y8
set_property -dict {LOC AH6 } [get_ports {eth_gt_ch_tx_n[46]}] ;# MGTYTXN1_227 GTYE4_CHANNEL_X1Y33 / GTYE4_COMMON_X1Y8
set_property -dict {LOC AJ4 } [get_ports {eth_gt_ch_rx_p[47]}] ;# MGTYRXP0_227 GTYE4_CHANNEL_X1Y32 / GTYE4_COMMON_X1Y8
set_property -dict {LOC AJ3 } [get_ports {eth_gt_ch_rx_n[47]}] ;# MGTYRXN0_227 GTYE4_CHANNEL_X1Y32 / GTYE4_COMMON_X1Y8
set_property -dict {LOC AJ9 } [get_ports {eth_gt_ch_tx_p[47]}] ;# MGTYTXP0_227 GTYE4_CHANNEL_X1Y32 / GTYE4_COMMON_X1Y8
set_property -dict {LOC AJ8 } [get_ports {eth_gt_ch_tx_n[47]}] ;# MGTYTXN0_227 GTYE4_CHANNEL_X1Y32 / GTYE4_COMMON_X1Y8
set_property -dict {LOC AH11} [get_ports {eth_gt_pri_refclk_p[11]}] ;# MGTREFCLK0P_227
set_property -dict {LOC AH10} [get_ports {eth_gt_pri_refclk_n[11]}] ;# MGTREFCLK0N_227
#set_property -dict {LOC AF11} [get_ports {eth_gt_sec_refclk_p[0]}] ;# MGTREFCLK1P_227
#set_property -dict {LOC AF10} [get_ports {eth_gt_sec_refclk_n[0]}] ;# MGTREFCLK1N_227
# 156.25 MHz MGT primary reference clock
create_clock -period 6.400 -name eth_gt_pri_refclk_11 [get_ports {eth_gt_pri_refclk_p[11]}]
# 125 MHz MGT secondary reference clock
#create_clock -period 8.000 -name eth_gt_sec_refclk_0 [get_ports {eth_gt_sec_refclk_p[0]}]
# GTY quad 120
# 7132LB-48Y4C: QSFP 49 lanes 1, 2, 3, 4
set_property -dict {LOC BC45} [get_ports {eth_gt_ch_rx_p[48]}] ;# MGTYRXP0_120 GTYE4_CHANNEL_X0Y4 / GTYE4_COMMON_X0Y1
set_property -dict {LOC BC46} [get_ports {eth_gt_ch_rx_n[48]}] ;# MGTYRXN0_120 GTYE4_CHANNEL_X0Y4 / GTYE4_COMMON_X0Y1
set_property -dict {LOC BF42} [get_ports {eth_gt_ch_tx_p[48]}] ;# MGTYTXP0_120 GTYE4_CHANNEL_X0Y4 / GTYE4_COMMON_X0Y1
set_property -dict {LOC BF43} [get_ports {eth_gt_ch_tx_n[48]}] ;# MGTYTXN0_120 GTYE4_CHANNEL_X0Y4 / GTYE4_COMMON_X0Y1
set_property -dict {LOC BA45} [get_ports {eth_gt_ch_rx_p[49]}] ;# MGTYRXP1_120 GTYE4_CHANNEL_X0Y5 / GTYE4_COMMON_X0Y1
set_property -dict {LOC BA46} [get_ports {eth_gt_ch_rx_n[49]}] ;# MGTYRXN1_120 GTYE4_CHANNEL_X0Y5 / GTYE4_COMMON_X0Y1
set_property -dict {LOC BD42} [get_ports {eth_gt_ch_tx_p[49]}] ;# MGTYTXP1_120 GTYE4_CHANNEL_X0Y5 / GTYE4_COMMON_X0Y1
set_property -dict {LOC BD43} [get_ports {eth_gt_ch_tx_n[49]}] ;# MGTYTXN1_120 GTYE4_CHANNEL_X0Y5 / GTYE4_COMMON_X0Y1
set_property -dict {LOC AW45} [get_ports {eth_gt_ch_rx_p[50]}] ;# MGTYRXP2_120 GTYE4_CHANNEL_X0Y6 / GTYE4_COMMON_X0Y1
set_property -dict {LOC AW46} [get_ports {eth_gt_ch_rx_n[50]}] ;# MGTYRXN2_120 GTYE4_CHANNEL_X0Y6 / GTYE4_COMMON_X0Y1
set_property -dict {LOC BB42} [get_ports {eth_gt_ch_tx_p[50]}] ;# MGTYTXP2_120 GTYE4_CHANNEL_X0Y6 / GTYE4_COMMON_X0Y1
set_property -dict {LOC BB43} [get_ports {eth_gt_ch_tx_n[50]}] ;# MGTYTXN2_120 GTYE4_CHANNEL_X0Y6 / GTYE4_COMMON_X0Y1
set_property -dict {LOC AV43} [get_ports {eth_gt_ch_rx_p[51]}] ;# MGTYRXP3_120 GTYE4_CHANNEL_X0Y7 / GTYE4_COMMON_X0Y1
set_property -dict {LOC AV44} [get_ports {eth_gt_ch_rx_n[51]}] ;# MGTYRXN3_120 GTYE4_CHANNEL_X0Y7 / GTYE4_COMMON_X0Y1
set_property -dict {LOC AW40} [get_ports {eth_gt_ch_tx_p[51]}] ;# MGTYTXP3_120 GTYE4_CHANNEL_X0Y7 / GTYE4_COMMON_X0Y1
set_property -dict {LOC AW41} [get_ports {eth_gt_ch_tx_n[51]}] ;# MGTYTXN3_120 GTYE4_CHANNEL_X0Y7 / GTYE4_COMMON_X0Y1
set_property -dict {LOC BA40} [get_ports {eth_gt_pri_refclk_p[12]}] ;# MGTREFCLK0P_120
set_property -dict {LOC BA41} [get_ports {eth_gt_pri_refclk_n[12]}] ;# MGTREFCLK0N_120
# 156.25 MHz MGT primary reference clock
create_clock -period 6.400 -name eth_gt_pri_refclk_12 [get_ports {eth_gt_pri_refclk_p[12]}]
# GTY quad 128
# 7132LB-48Y4C: QSFP 50 lanes 1, 2, 3, 4
set_property -dict {LOC J45 } [get_ports {eth_gt_ch_rx_p[52]}] ;# MGTYRXP0_128 GTYE4_CHANNEL_X0Y36 / GTYE4_COMMON_X0Y9
set_property -dict {LOC J46 } [get_ports {eth_gt_ch_rx_n[52]}] ;# MGTYRXN0_128 GTYE4_CHANNEL_X0Y36 / GTYE4_COMMON_X0Y9
set_property -dict {LOC G40 } [get_ports {eth_gt_ch_tx_p[52]}] ;# MGTYTXP0_128 GTYE4_CHANNEL_X0Y36 / GTYE4_COMMON_X0Y9
set_property -dict {LOC G41 } [get_ports {eth_gt_ch_tx_n[52]}] ;# MGTYTXN0_128 GTYE4_CHANNEL_X0Y36 / GTYE4_COMMON_X0Y9
set_property -dict {LOC H43 } [get_ports {eth_gt_ch_rx_p[53]}] ;# MGTYRXP1_128 GTYE4_CHANNEL_X0Y37 / GTYE4_COMMON_X0Y9
set_property -dict {LOC H44 } [get_ports {eth_gt_ch_rx_n[53]}] ;# MGTYRXN1_128 GTYE4_CHANNEL_X0Y37 / GTYE4_COMMON_X0Y9
set_property -dict {LOC E42 } [get_ports {eth_gt_ch_tx_p[53]}] ;# MGTYTXP1_128 GTYE4_CHANNEL_X0Y37 / GTYE4_COMMON_X0Y9
set_property -dict {LOC E43 } [get_ports {eth_gt_ch_tx_n[53]}] ;# MGTYTXN1_128 GTYE4_CHANNEL_X0Y37 / GTYE4_COMMON_X0Y9
set_property -dict {LOC F45 } [get_ports {eth_gt_ch_rx_p[54]}] ;# MGTYRXP2_128 GTYE4_CHANNEL_X0Y38 / GTYE4_COMMON_X0Y9
set_property -dict {LOC F46 } [get_ports {eth_gt_ch_rx_n[54]}] ;# MGTYRXN2_128 GTYE4_CHANNEL_X0Y38 / GTYE4_COMMON_X0Y9
set_property -dict {LOC C42 } [get_ports {eth_gt_ch_tx_p[54]}] ;# MGTYTXP2_128 GTYE4_CHANNEL_X0Y38 / GTYE4_COMMON_X0Y9
set_property -dict {LOC C43 } [get_ports {eth_gt_ch_tx_n[54]}] ;# MGTYTXN2_128 GTYE4_CHANNEL_X0Y38 / GTYE4_COMMON_X0Y9
set_property -dict {LOC D45 } [get_ports {eth_gt_ch_rx_p[55]}] ;# MGTYRXP3_128 GTYE4_CHANNEL_X0Y39 / GTYE4_COMMON_X0Y9
set_property -dict {LOC D46 } [get_ports {eth_gt_ch_rx_n[55]}] ;# MGTYRXN3_128 GTYE4_CHANNEL_X0Y39 / GTYE4_COMMON_X0Y9
set_property -dict {LOC A42 } [get_ports {eth_gt_ch_tx_p[55]}] ;# MGTYTXP3_128 GTYE4_CHANNEL_X0Y39 / GTYE4_COMMON_X0Y9
set_property -dict {LOC A43 } [get_ports {eth_gt_ch_tx_n[55]}] ;# MGTYTXN3_128 GTYE4_CHANNEL_X0Y39 / GTYE4_COMMON_X0Y9
set_property -dict {LOC L36 } [get_ports {eth_gt_pri_refclk_p[13]}] ;# MGTREFCLK0P_128
set_property -dict {LOC L37 } [get_ports {eth_gt_pri_refclk_n[13]}] ;# MGTREFCLK0N_128
#set_property -dict {LOC K38 } [get_ports {eth_gt_sec_refclk_p[6]}] ;# MGTREFCLK1P_128
#set_property -dict {LOC K39 } [get_ports {eth_gt_sec_refclk_n[6]}] ;# MGTREFCLK1N_128
# 156.25 MHz MGT primary reference clock
create_clock -period 6.400 -name eth_gt_pri_refclk_13 [get_ports {eth_gt_pri_refclk_p[13]}]
# 125 MHz MGT secondary reference clock
#create_clock -period 8.000 -name eth_gt_sec_refclk_6 [get_ports {eth_gt_sec_refclk_p[6]}]
# GTY quad 233
# 7132LB-48Y4C: QSFP 51 lanes 1, 2, 3, 4
set_property -dict {LOC E4 } [get_ports {eth_gt_ch_rx_p[56]}] ;# MGTYRXP0_233 GTYE4_CHANNEL_X1Y56 / GTYE4_COMMON_X1Y14
set_property -dict {LOC E3 } [get_ports {eth_gt_ch_rx_n[56]}] ;# MGTYRXN0_233 GTYE4_CHANNEL_X1Y56 / GTYE4_COMMON_X1Y14
set_property -dict {LOC E9 } [get_ports {eth_gt_ch_tx_p[56]}] ;# MGTYTXP0_233 GTYE4_CHANNEL_X1Y56 / GTYE4_COMMON_X1Y14
set_property -dict {LOC E8 } [get_ports {eth_gt_ch_tx_n[56]}] ;# MGTYTXN0_233 GTYE4_CHANNEL_X1Y56 / GTYE4_COMMON_X1Y14
set_property -dict {LOC D2 } [get_ports {eth_gt_ch_rx_p[57]}] ;# MGTYRXP1_233 GTYE4_CHANNEL_X1Y57 / GTYE4_COMMON_X1Y14
set_property -dict {LOC D1 } [get_ports {eth_gt_ch_rx_n[57]}] ;# MGTYRXN1_233 GTYE4_CHANNEL_X1Y57 / GTYE4_COMMON_X1Y14
set_property -dict {LOC D7 } [get_ports {eth_gt_ch_tx_p[57]}] ;# MGTYTXP1_233 GTYE4_CHANNEL_X1Y57 / GTYE4_COMMON_X1Y14
set_property -dict {LOC D6 } [get_ports {eth_gt_ch_tx_n[57]}] ;# MGTYTXN1_233 GTYE4_CHANNEL_X1Y57 / GTYE4_COMMON_X1Y14
set_property -dict {LOC C4 } [get_ports {eth_gt_ch_rx_p[58]}] ;# MGTYRXP2_233 GTYE4_CHANNEL_X1Y58 / GTYE4_COMMON_X1Y14
set_property -dict {LOC C3 } [get_ports {eth_gt_ch_rx_n[58]}] ;# MGTYRXN2_233 GTYE4_CHANNEL_X1Y58 / GTYE4_COMMON_X1Y14
set_property -dict {LOC C9 } [get_ports {eth_gt_ch_tx_p[58]}] ;# MGTYTXP2_233 GTYE4_CHANNEL_X1Y58 / GTYE4_COMMON_X1Y14
set_property -dict {LOC C8 } [get_ports {eth_gt_ch_tx_n[58]}] ;# MGTYTXN2_233 GTYE4_CHANNEL_X1Y58 / GTYE4_COMMON_X1Y14
set_property -dict {LOC A5 } [get_ports {eth_gt_ch_rx_p[59]}] ;# MGTYRXP3_233 GTYE4_CHANNEL_X1Y59 / GTYE4_COMMON_X1Y14
set_property -dict {LOC A4 } [get_ports {eth_gt_ch_rx_n[59]}] ;# MGTYRXN3_233 GTYE4_CHANNEL_X1Y59 / GTYE4_COMMON_X1Y14
set_property -dict {LOC A9 } [get_ports {eth_gt_ch_tx_p[59]}] ;# MGTYTXP3_233 GTYE4_CHANNEL_X1Y59 / GTYE4_COMMON_X1Y14
set_property -dict {LOC A8 } [get_ports {eth_gt_ch_tx_n[59]}] ;# MGTYTXN3_233 GTYE4_CHANNEL_X1Y59 / GTYE4_COMMON_X1Y14
set_property -dict {LOC D11 } [get_ports {eth_gt_pri_refclk_p[14]}] ;# MGTREFCLK0P_233
set_property -dict {LOC D10 } [get_ports {eth_gt_pri_refclk_n[14]}] ;# MGTREFCLK0N_233
#set_property -dict {LOC B11 } [get_ports {eth_gt_sec_refclk_p[3]}] ;# MGTREFCLK1P_233
#set_property -dict {LOC B10 } [get_ports {eth_gt_sec_refclk_n[3]}] ;# MGTREFCLK1N_233
# 156.25 MHz MGT primary reference clock
create_clock -period 6.400 -name eth_gt_pri_refclk_14 [get_ports {eth_gt_pri_refclk_p[14]}]
# 125 MHz MGT secondary reference clock
#create_clock -period 8.000 -name eth_gt_sec_refclk_3 [get_ports {eth_gt_sec_refclk_p[3]}]
# GTY quad 226
# 7132LB-48Y4C: QSFP 52 lanes 1, 2, 3, 4
set_property -dict {LOC AN4 } [get_ports {eth_gt_ch_rx_p[60]}] ;# MGTYRXP0_226 GTYE4_CHANNEL_X1Y28 / GTYE4_COMMON_X1Y7
set_property -dict {LOC AN3 } [get_ports {eth_gt_ch_rx_n[60]}] ;# MGTYRXN0_226 GTYE4_CHANNEL_X1Y28 / GTYE4_COMMON_X1Y7
set_property -dict {LOC AN9 } [get_ports {eth_gt_ch_tx_p[60]}] ;# MGTYTXP0_226 GTYE4_CHANNEL_X1Y28 / GTYE4_COMMON_X1Y7
set_property -dict {LOC AN8 } [get_ports {eth_gt_ch_tx_n[60]}] ;# MGTYTXN0_226 GTYE4_CHANNEL_X1Y28 / GTYE4_COMMON_X1Y7
set_property -dict {LOC AM2 } [get_ports {eth_gt_ch_rx_p[61]}] ;# MGTYRXP1_226 GTYE4_CHANNEL_X1Y29 / GTYE4_COMMON_X1Y7
set_property -dict {LOC AM1 } [get_ports {eth_gt_ch_rx_n[61]}] ;# MGTYRXN1_226 GTYE4_CHANNEL_X1Y29 / GTYE4_COMMON_X1Y7
set_property -dict {LOC AM7 } [get_ports {eth_gt_ch_tx_p[61]}] ;# MGTYTXP1_226 GTYE4_CHANNEL_X1Y29 / GTYE4_COMMON_X1Y7
set_property -dict {LOC AM6 } [get_ports {eth_gt_ch_tx_n[61]}] ;# MGTYTXN1_226 GTYE4_CHANNEL_X1Y29 / GTYE4_COMMON_X1Y7
set_property -dict {LOC AL4 } [get_ports {eth_gt_ch_rx_p[62]}] ;# MGTYRXP2_226 GTYE4_CHANNEL_X1Y30 / GTYE4_COMMON_X1Y7
set_property -dict {LOC AL3 } [get_ports {eth_gt_ch_rx_n[62]}] ;# MGTYRXN2_226 GTYE4_CHANNEL_X1Y30 / GTYE4_COMMON_X1Y7
set_property -dict {LOC AL9 } [get_ports {eth_gt_ch_tx_p[62]}] ;# MGTYTXP2_226 GTYE4_CHANNEL_X1Y30 / GTYE4_COMMON_X1Y7
set_property -dict {LOC AL8 } [get_ports {eth_gt_ch_tx_n[62]}] ;# MGTYTXN2_226 GTYE4_CHANNEL_X1Y30 / GTYE4_COMMON_X1Y7
set_property -dict {LOC AK2 } [get_ports {eth_gt_ch_rx_p[63]}] ;# MGTYRXP3_226 GTYE4_CHANNEL_X1Y31 / GTYE4_COMMON_X1Y7
set_property -dict {LOC AK1 } [get_ports {eth_gt_ch_rx_n[63]}] ;# MGTYRXN3_226 GTYE4_CHANNEL_X1Y31 / GTYE4_COMMON_X1Y7
set_property -dict {LOC AK7 } [get_ports {eth_gt_ch_tx_p[63]}] ;# MGTYTXP3_226 GTYE4_CHANNEL_X1Y31 / GTYE4_COMMON_X1Y7
set_property -dict {LOC AK6 } [get_ports {eth_gt_ch_tx_n[63]}] ;# MGTYTXN3_226 GTYE4_CHANNEL_X1Y31 / GTYE4_COMMON_X1Y7
set_property -dict {LOC AM11} [get_ports {eth_gt_pri_refclk_p[15]}] ;# MGTREFCLK0P_226
set_property -dict {LOC AM10} [get_ports {eth_gt_pri_refclk_n[15]}] ;# MGTREFCLK0N_226
# 156.25 MHz MGT primary reference clock
create_clock -period 6.400 -name eth_gt_pri_refclk_15 [get_ports {eth_gt_pri_refclk_p[15]}]
# GTY quad 121
# 7132LB-48Y4C: CPU ports
set_property -dict {LOC AU45} [get_ports {eth_gt_ch_rx_p[64]}] ;# MGTYRXP0_121 GTYE4_CHANNEL_X0Y8 / GTYE4_COMMON_X0Y2
set_property -dict {LOC AU46} [get_ports {eth_gt_ch_rx_n[64]}] ;# MGTYRXN0_121 GTYE4_CHANNEL_X0Y8 / GTYE4_COMMON_X0Y2
set_property -dict {LOC AU40} [get_ports {eth_gt_ch_tx_p[64]}] ;# MGTYTXP0_121 GTYE4_CHANNEL_X0Y8 / GTYE4_COMMON_X0Y2
set_property -dict {LOC AU41} [get_ports {eth_gt_ch_tx_n[64]}] ;# MGTYTXN0_121 GTYE4_CHANNEL_X0Y8 / GTYE4_COMMON_X0Y2
set_property -dict {LOC AT43} [get_ports {eth_gt_ch_rx_p[65]}] ;# MGTYRXP1_121 GTYE4_CHANNEL_X0Y9 / GTYE4_COMMON_X0Y2
set_property -dict {LOC AT44} [get_ports {eth_gt_ch_rx_n[65]}] ;# MGTYRXN1_121 GTYE4_CHANNEL_X0Y9 / GTYE4_COMMON_X0Y2
set_property -dict {LOC AT38} [get_ports {eth_gt_ch_tx_p[65]}] ;# MGTYTXP1_121 GTYE4_CHANNEL_X0Y9 / GTYE4_COMMON_X0Y2
set_property -dict {LOC AT39} [get_ports {eth_gt_ch_tx_n[65]}] ;# MGTYTXN1_121 GTYE4_CHANNEL_X0Y9 / GTYE4_COMMON_X0Y2
set_property -dict {LOC AR45} [get_ports {eth_gt_ch_rx_p[66]}] ;# MGTYRXP2_121 GTYE4_CHANNEL_X0Y10 / GTYE4_COMMON_X0Y2
set_property -dict {LOC AR46} [get_ports {eth_gt_ch_rx_n[66]}] ;# MGTYRXN2_121 GTYE4_CHANNEL_X0Y10 / GTYE4_COMMON_X0Y2
set_property -dict {LOC AR40} [get_ports {eth_gt_ch_tx_p[66]}] ;# MGTYTXP2_121 GTYE4_CHANNEL_X0Y10 / GTYE4_COMMON_X0Y2
set_property -dict {LOC AR41} [get_ports {eth_gt_ch_tx_n[66]}] ;# MGTYTXN2_121 GTYE4_CHANNEL_X0Y10 / GTYE4_COMMON_X0Y2
set_property -dict {LOC AP43} [get_ports {eth_gt_ch_rx_p[67]}] ;# MGTYRXP3_121 GTYE4_CHANNEL_X0Y11 / GTYE4_COMMON_X0Y2
set_property -dict {LOC AP44} [get_ports {eth_gt_ch_rx_n[67]}] ;# MGTYRXN3_121 GTYE4_CHANNEL_X0Y11 / GTYE4_COMMON_X0Y2
set_property -dict {LOC AP38} [get_ports {eth_gt_ch_tx_p[67]}] ;# MGTYTXP3_121 GTYE4_CHANNEL_X0Y11 / GTYE4_COMMON_X0Y2
set_property -dict {LOC AP39} [get_ports {eth_gt_ch_tx_n[67]}] ;# MGTYTXN3_121 GTYE4_CHANNEL_X0Y11 / GTYE4_COMMON_X0Y2
set_property -dict {LOC AV38} [get_ports {eth_gt_pri_refclk_p[16]}] ;# MGTREFCLK0P_121
set_property -dict {LOC AV39} [get_ports {eth_gt_pri_refclk_n[16]}] ;# MGTREFCLK0N_121
# 156.25 MHz MGT primary reference clock
create_clock -period 6.400 -name eth_gt_pri_refclk_16 [get_ports {eth_gt_pri_refclk_p[16]}]
# PCIe Interface
#set_property -dict {LOC AP2 } [get_ports {pcie_rx_p[0]}] ;# MGTYRXP3_225 GTYE4_CHANNEL_X1Y27 / GTYE4_COMMON_X1Y6
#set_property -dict {LOC AP1 } [get_ports {pcie_rx_n[0]}] ;# MGTYRXN3_225 GTYE4_CHANNEL_X1Y27 / GTYE4_COMMON_X1Y6
#set_property -dict {LOC AP7 } [get_ports {pcie_tx_p[0]}] ;# MGTYTXP3_225 GTYE4_CHANNEL_X1Y27 / GTYE4_COMMON_X1Y6
#set_property -dict {LOC AP6 } [get_ports {pcie_tx_n[0]}] ;# MGTYTXN3_225 GTYE4_CHANNEL_X1Y27 / GTYE4_COMMON_X1Y6
#set_property -dict {LOC AR4 } [get_ports {pcie_rx_p[1]}] ;# MGTYRXP2_225 GTYE4_CHANNEL_X1Y26 / GTYE4_COMMON_X1Y6
#set_property -dict {LOC AR3 } [get_ports {pcie_rx_n[1]}] ;# MGTYRXN2_225 GTYE4_CHANNEL_X1Y26 / GTYE4_COMMON_X1Y6
#set_property -dict {LOC AR9 } [get_ports {pcie_tx_p[1]}] ;# MGTYTXP2_225 GTYE4_CHANNEL_X1Y26 / GTYE4_COMMON_X1Y6
#set_property -dict {LOC AR8 } [get_ports {pcie_tx_n[1]}] ;# MGTYTXN2_225 GTYE4_CHANNEL_X1Y26 / GTYE4_COMMON_X1Y6
#set_property -dict {LOC AT2 } [get_ports {pcie_rx_p[2]}] ;# MGTYRXP1_225 GTYE4_CHANNEL_X1Y25 / GTYE4_COMMON_X1Y6
#set_property -dict {LOC AT1 } [get_ports {pcie_rx_n[2]}] ;# MGTYRXN1_225 GTYE4_CHANNEL_X1Y25 / GTYE4_COMMON_X1Y6
#set_property -dict {LOC AT7 } [get_ports {pcie_tx_p[2]}] ;# MGTYTXP1_225 GTYE4_CHANNEL_X1Y25 / GTYE4_COMMON_X1Y6
#set_property -dict {LOC AT6 } [get_ports {pcie_tx_n[2]}] ;# MGTYTXN1_225 GTYE4_CHANNEL_X1Y25 / GTYE4_COMMON_X1Y6
#set_property -dict {LOC AU4 } [get_ports {pcie_rx_p[3]}] ;# MGTYRXP0_225 GTYE4_CHANNEL_X1Y24 / GTYE4_COMMON_X1Y6
#set_property -dict {LOC AU3 } [get_ports {pcie_rx_n[3]}] ;# MGTYRXN0_225 GTYE4_CHANNEL_X1Y24 / GTYE4_COMMON_X1Y6
#set_property -dict {LOC AU9 } [get_ports {pcie_tx_p[3]}] ;# MGTYTXP0_225 GTYE4_CHANNEL_X1Y24 / GTYE4_COMMON_X1Y6
#set_property -dict {LOC AU8 } [get_ports {pcie_tx_n[3]}] ;# MGTYTXN0_225 GTYE4_CHANNEL_X1Y24 / GTYE4_COMMON_X1Y6
#set_property -dict {LOC AV2 } [get_ports {pcie_rx_p[4]}] ;# MGTYRXP3_224 GTYE4_CHANNEL_X1Y23 / GTYE4_COMMON_X1Y5
#set_property -dict {LOC AV1 } [get_ports {pcie_rx_n[4]}] ;# MGTYRXN3_224 GTYE4_CHANNEL_X1Y23 / GTYE4_COMMON_X1Y5
#set_property -dict {LOC AV7 } [get_ports {pcie_tx_p[4]}] ;# MGTYTXP3_224 GTYE4_CHANNEL_X1Y23 / GTYE4_COMMON_X1Y5
#set_property -dict {LOC AV6 } [get_ports {pcie_tx_n[4]}] ;# MGTYTXN3_224 GTYE4_CHANNEL_X1Y23 / GTYE4_COMMON_X1Y5
#set_property -dict {LOC AW4 } [get_ports {pcie_rx_p[5]}] ;# MGTYRXP2_224 GTYE4_CHANNEL_X1Y22 / GTYE4_COMMON_X1Y5
#set_property -dict {LOC AW3 } [get_ports {pcie_rx_n[5]}] ;# MGTYRXN2_224 GTYE4_CHANNEL_X1Y22 / GTYE4_COMMON_X1Y5
#set_property -dict {LOC BB5 } [get_ports {pcie_tx_p[5]}] ;# MGTYTXP2_224 GTYE4_CHANNEL_X1Y22 / GTYE4_COMMON_X1Y5
#set_property -dict {LOC BB4 } [get_ports {pcie_tx_n[5]}] ;# MGTYTXN2_224 GTYE4_CHANNEL_X1Y22 / GTYE4_COMMON_X1Y5
#set_property -dict {LOC BA2 } [get_ports {pcie_rx_p[6]}] ;# MGTYRXP1_224 GTYE4_CHANNEL_X1Y21 / GTYE4_COMMON_X1Y5
#set_property -dict {LOC BA1 } [get_ports {pcie_rx_n[6]}] ;# MGTYRXN1_224 GTYE4_CHANNEL_X1Y21 / GTYE4_COMMON_X1Y5
#set_property -dict {LOC BD5 } [get_ports {pcie_tx_p[6]}] ;# MGTYTXP1_224 GTYE4_CHANNEL_X1Y21 / GTYE4_COMMON_X1Y5
#set_property -dict {LOC BD4 } [get_ports {pcie_tx_n[6]}] ;# MGTYTXN1_224 GTYE4_CHANNEL_X1Y21 / GTYE4_COMMON_X1Y5
#set_property -dict {LOC BC2 } [get_ports {pcie_rx_p[7]}] ;# MGTYRXP0_224 GTYE4_CHANNEL_X1Y20 / GTYE4_COMMON_X1Y5
#set_property -dict {LOC BC1 } [get_ports {pcie_rx_n[7]}] ;# MGTYRXN0_224 GTYE4_CHANNEL_X1Y20 / GTYE4_COMMON_X1Y5
#set_property -dict {LOC BF5 } [get_ports {pcie_tx_p[7]}] ;# MGTYTXP0_224 GTYE4_CHANNEL_X1Y20 / GTYE4_COMMON_X1Y5
#set_property -dict {LOC BF4 } [get_ports {pcie_tx_n[7]}] ;# MGTYTXN0_224 GTYE4_CHANNEL_X1Y20 / GTYE4_COMMON_X1Y5
#set_property -dict {LOC AT11} [get_ports pcie_refclk_p] ;# MGTREFCLK0P_225
#set_property -dict {LOC AT10} [get_ports pcie_refclk_n] ;# MGTREFCLK0P_225
#set_property -dict {LOC AR26 IOSTANDARD LVCMOS12} [get_ports pcie_rst_n]
#set_property -dict {LOC BF8 IOSTANDARD LVCMOS18} [get_ports pcie_wake_n]
# 100 MHz MGT reference clock
#create_clock -period 10.000 -name pcie_mgt_refclk [get_ports pcie_refclk_p]
#set_false_path -from [get_ports {pcie_rst_n pcie_wake_n}]
#set_input_delay 0 [get_ports {pcie_rst_n pcie_wake_n}]

View File

@ -0,0 +1,75 @@
# FPGA settings
FPGA_PART = xcvu9p-flgb2104-3-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/eth_xcvr_phy_quad_wrapper.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

View File

@ -0,0 +1,51 @@
# 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_refclk_freq {156.25}
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,75 @@
# FPGA settings
FPGA_PART = xcvu9p-flgb2104-3-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/eth_xcvr_phy_quad_wrapper.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

View File

@ -0,0 +1,51 @@
# 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_refclk_freq {156.25}
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,395 @@
/*
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.
*/
// Language: Verilog 2001
`resetall
`timescale 1ns / 1ps
`default_nettype none
/*
* Transceiver and PHY quad wrapper
*/
module eth_xcvr_phy_quad_wrapper #
(
parameter COUNT = 4,
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
*/
input wire xcvr_gtrefclk00_in,
/*
* Serial data
*/
output wire [COUNT-1:0] xcvr_txp,
output wire [COUNT-1:0] xcvr_txn,
input wire [COUNT-1:0] xcvr_rxp,
input wire [COUNT-1:0] xcvr_rxn,
/*
* PHY connections
*/
output wire phy_1_tx_clk,
output wire phy_1_tx_rst,
input wire [DATA_WIDTH-1:0] phy_1_xgmii_txd,
input wire [CTRL_WIDTH-1:0] phy_1_xgmii_txc,
output wire phy_1_rx_clk,
output wire phy_1_rx_rst,
output wire [DATA_WIDTH-1:0] phy_1_xgmii_rxd,
output wire [CTRL_WIDTH-1:0] phy_1_xgmii_rxc,
output wire phy_1_tx_bad_block,
output wire [6:0] phy_1_rx_error_count,
output wire phy_1_rx_bad_block,
output wire phy_1_rx_sequence_error,
output wire phy_1_rx_block_lock,
output wire phy_1_rx_high_ber,
output wire phy_1_rx_status,
input wire phy_1_cfg_tx_prbs31_enable,
input wire phy_1_cfg_rx_prbs31_enable,
output wire phy_2_tx_clk,
output wire phy_2_tx_rst,
input wire [DATA_WIDTH-1:0] phy_2_xgmii_txd,
input wire [CTRL_WIDTH-1:0] phy_2_xgmii_txc,
output wire phy_2_rx_clk,
output wire phy_2_rx_rst,
output wire [DATA_WIDTH-1:0] phy_2_xgmii_rxd,
output wire [CTRL_WIDTH-1:0] phy_2_xgmii_rxc,
output wire phy_2_tx_bad_block,
output wire [6:0] phy_2_rx_error_count,
output wire phy_2_rx_bad_block,
output wire phy_2_rx_sequence_error,
output wire phy_2_rx_block_lock,
output wire phy_2_rx_high_ber,
output wire phy_2_rx_status,
input wire phy_2_cfg_tx_prbs31_enable,
input wire phy_2_cfg_rx_prbs31_enable,
output wire phy_3_tx_clk,
output wire phy_3_tx_rst,
input wire [DATA_WIDTH-1:0] phy_3_xgmii_txd,
input wire [CTRL_WIDTH-1:0] phy_3_xgmii_txc,
output wire phy_3_rx_clk,
output wire phy_3_rx_rst,
output wire [DATA_WIDTH-1:0] phy_3_xgmii_rxd,
output wire [CTRL_WIDTH-1:0] phy_3_xgmii_rxc,
output wire phy_3_tx_bad_block,
output wire [6:0] phy_3_rx_error_count,
output wire phy_3_rx_bad_block,
output wire phy_3_rx_sequence_error,
output wire phy_3_rx_block_lock,
output wire phy_3_rx_high_ber,
output wire phy_3_rx_status,
input wire phy_3_cfg_tx_prbs31_enable,
input wire phy_3_cfg_rx_prbs31_enable,
output wire phy_4_tx_clk,
output wire phy_4_tx_rst,
input wire [DATA_WIDTH-1:0] phy_4_xgmii_txd,
input wire [CTRL_WIDTH-1:0] phy_4_xgmii_txc,
output wire phy_4_rx_clk,
output wire phy_4_rx_rst,
output wire [DATA_WIDTH-1:0] phy_4_xgmii_rxd,
output wire [CTRL_WIDTH-1:0] phy_4_xgmii_rxc,
output wire phy_4_tx_bad_block,
output wire [6:0] phy_4_rx_error_count,
output wire phy_4_rx_bad_block,
output wire phy_4_rx_sequence_error,
output wire phy_4_rx_block_lock,
output wire phy_4_rx_high_ber,
output wire phy_4_rx_status,
input wire phy_4_cfg_tx_prbs31_enable,
input wire phy_4_cfg_rx_prbs31_enable
);
generate
wire xcvr_qpll0lock;
wire xcvr_qpll0clk;
wire xcvr_qpll0refclk;
if (COUNT > 0) begin : phy1
eth_xcvr_phy_wrapper #(
.HAS_COMMON(1),
.DATA_WIDTH(DATA_WIDTH),
.CTRL_WIDTH(CTRL_WIDTH),
.HDR_WIDTH(HDR_WIDTH),
.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)
)
eth_xcvr_phy_1 (
.xcvr_ctrl_clk(xcvr_ctrl_clk),
.xcvr_ctrl_rst(xcvr_ctrl_rst),
// Common
.xcvr_gtpowergood_out(xcvr_gtpowergood_out),
// PLL out
.xcvr_gtrefclk00_in(xcvr_gtrefclk00_in),
.xcvr_qpll0lock_out(xcvr_qpll0lock),
.xcvr_qpll0clk_out(xcvr_qpll0clk),
.xcvr_qpll0refclk_out(xcvr_qpll0refclk),
// PLL in
.xcvr_qpll0lock_in(1'b0),
.xcvr_qpll0clk_in(1'b0),
.xcvr_qpll0refclk_in(1'b0),
// Serial data
.xcvr_txp(xcvr_txp[0]),
.xcvr_txn(xcvr_txn[0]),
.xcvr_rxp(xcvr_rxp[0]),
.xcvr_rxn(xcvr_rxn[0]),
// PHY connections
.phy_tx_clk(phy_1_tx_clk),
.phy_tx_rst(phy_1_tx_rst),
.phy_xgmii_txd(phy_1_xgmii_txd),
.phy_xgmii_txc(phy_1_xgmii_txc),
.phy_rx_clk(phy_1_rx_clk),
.phy_rx_rst(phy_1_rx_rst),
.phy_xgmii_rxd(phy_1_xgmii_rxd),
.phy_xgmii_rxc(phy_1_xgmii_rxc),
.phy_tx_bad_block(phy_1_tx_bad_block),
.phy_rx_error_count(phy_1_rx_error_count),
.phy_rx_bad_block(phy_1_rx_bad_block),
.phy_rx_sequence_error(phy_1_rx_sequence_error),
.phy_rx_block_lock(phy_1_rx_block_lock),
.phy_rx_high_ber(phy_1_rx_high_ber),
.phy_rx_status(phy_1_rx_status),
.phy_cfg_tx_prbs31_enable(phy_1_cfg_tx_prbs31_enable),
.phy_cfg_rx_prbs31_enable(phy_1_cfg_rx_prbs31_enable)
);
end
if (COUNT > 1) begin : phy2
eth_xcvr_phy_wrapper #(
.HAS_COMMON(0),
.DATA_WIDTH(DATA_WIDTH),
.CTRL_WIDTH(CTRL_WIDTH),
.HDR_WIDTH(HDR_WIDTH),
.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)
)
eth_xcvr_phy_2 (
.xcvr_ctrl_clk(xcvr_ctrl_clk),
.xcvr_ctrl_rst(xcvr_ctrl_rst),
// Common
.xcvr_gtpowergood_out(),
// PLL out
.xcvr_gtrefclk00_in(1'b0),
.xcvr_qpll0lock_out(),
.xcvr_qpll0clk_out(),
.xcvr_qpll0refclk_out(),
// PLL in
.xcvr_qpll0lock_in(xcvr_qpll0lock),
.xcvr_qpll0clk_in(xcvr_qpll0clk),
.xcvr_qpll0refclk_in(xcvr_qpll0refclk),
// Serial data
.xcvr_txp(xcvr_txp[1]),
.xcvr_txn(xcvr_txn[1]),
.xcvr_rxp(xcvr_rxp[1]),
.xcvr_rxn(xcvr_rxn[1]),
// PHY connections
.phy_tx_clk(phy_2_tx_clk),
.phy_tx_rst(phy_2_tx_rst),
.phy_xgmii_txd(phy_2_xgmii_txd),
.phy_xgmii_txc(phy_2_xgmii_txc),
.phy_rx_clk(phy_2_rx_clk),
.phy_rx_rst(phy_2_rx_rst),
.phy_xgmii_rxd(phy_2_xgmii_rxd),
.phy_xgmii_rxc(phy_2_xgmii_rxc),
.phy_tx_bad_block(phy_2_tx_bad_block),
.phy_rx_error_count(phy_2_rx_error_count),
.phy_rx_bad_block(phy_2_rx_bad_block),
.phy_rx_sequence_error(phy_2_rx_sequence_error),
.phy_rx_block_lock(phy_2_rx_block_lock),
.phy_rx_high_ber(phy_2_rx_high_ber),
.phy_rx_status(phy_2_rx_status),
.phy_cfg_tx_prbs31_enable(phy_2_cfg_tx_prbs31_enable),
.phy_cfg_rx_prbs31_enable(phy_2_cfg_rx_prbs31_enable)
);
end
if (COUNT > 2) begin : phy3
eth_xcvr_phy_wrapper #(
.HAS_COMMON(0),
.DATA_WIDTH(DATA_WIDTH),
.CTRL_WIDTH(CTRL_WIDTH),
.HDR_WIDTH(HDR_WIDTH),
.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)
)
eth_xcvr_phy_3 (
.xcvr_ctrl_clk(xcvr_ctrl_clk),
.xcvr_ctrl_rst(xcvr_ctrl_rst),
// Common
.xcvr_gtpowergood_out(),
// PLL out
.xcvr_gtrefclk00_in(1'b0),
.xcvr_qpll0lock_out(),
.xcvr_qpll0clk_out(),
.xcvr_qpll0refclk_out(),
// PLL in
.xcvr_qpll0lock_in(xcvr_qpll0lock),
.xcvr_qpll0clk_in(xcvr_qpll0clk),
.xcvr_qpll0refclk_in(xcvr_qpll0refclk),
// Serial data
.xcvr_txp(xcvr_txp[2]),
.xcvr_txn(xcvr_txn[2]),
.xcvr_rxp(xcvr_rxp[2]),
.xcvr_rxn(xcvr_rxn[2]),
// PHY connections
.phy_tx_clk(phy_3_tx_clk),
.phy_tx_rst(phy_3_tx_rst),
.phy_xgmii_txd(phy_3_xgmii_txd),
.phy_xgmii_txc(phy_3_xgmii_txc),
.phy_rx_clk(phy_3_rx_clk),
.phy_rx_rst(phy_3_rx_rst),
.phy_xgmii_rxd(phy_3_xgmii_rxd),
.phy_xgmii_rxc(phy_3_xgmii_rxc),
.phy_tx_bad_block(phy_3_tx_bad_block),
.phy_rx_error_count(phy_3_rx_error_count),
.phy_rx_bad_block(phy_3_rx_bad_block),
.phy_rx_sequence_error(phy_3_rx_sequence_error),
.phy_rx_block_lock(phy_3_rx_block_lock),
.phy_rx_high_ber(phy_3_rx_high_ber),
.phy_rx_status(phy_3_rx_status),
.phy_cfg_tx_prbs31_enable(phy_3_cfg_tx_prbs31_enable),
.phy_cfg_rx_prbs31_enable(phy_3_cfg_rx_prbs31_enable)
);
end
if (COUNT > 3) begin : phy4
eth_xcvr_phy_wrapper #(
.HAS_COMMON(0),
.DATA_WIDTH(DATA_WIDTH),
.CTRL_WIDTH(CTRL_WIDTH),
.HDR_WIDTH(HDR_WIDTH),
.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)
)
eth_xcvr_phy_4 (
.xcvr_ctrl_clk(xcvr_ctrl_clk),
.xcvr_ctrl_rst(xcvr_ctrl_rst),
// Common
.xcvr_gtpowergood_out(),
// PLL out
.xcvr_gtrefclk00_in(1'b0),
.xcvr_qpll0lock_out(),
.xcvr_qpll0clk_out(),
.xcvr_qpll0refclk_out(),
// PLL in
.xcvr_qpll0lock_in(xcvr_qpll0lock),
.xcvr_qpll0clk_in(xcvr_qpll0clk),
.xcvr_qpll0refclk_in(xcvr_qpll0refclk),
// Serial data
.xcvr_txp(xcvr_txp[3]),
.xcvr_txn(xcvr_txn[3]),
.xcvr_rxp(xcvr_rxp[3]),
.xcvr_rxn(xcvr_rxn[3]),
// PHY connections
.phy_tx_clk(phy_4_tx_clk),
.phy_tx_rst(phy_4_tx_rst),
.phy_xgmii_txd(phy_4_xgmii_txd),
.phy_xgmii_txc(phy_4_xgmii_txc),
.phy_rx_clk(phy_4_rx_clk),
.phy_rx_rst(phy_4_rx_rst),
.phy_xgmii_rxd(phy_4_xgmii_rxd),
.phy_xgmii_rxc(phy_4_xgmii_rxc),
.phy_tx_bad_block(phy_4_tx_bad_block),
.phy_rx_error_count(phy_4_rx_error_count),
.phy_rx_bad_block(phy_4_rx_bad_block),
.phy_rx_sequence_error(phy_4_rx_sequence_error),
.phy_rx_block_lock(phy_4_rx_block_lock),
.phy_rx_high_ber(phy_4_rx_high_ber),
.phy_rx_status(phy_4_rx_status),
.phy_cfg_tx_prbs31_enable(phy_4_cfg_tx_prbs31_enable),
.phy_cfg_rx_prbs31_enable(phy_4_cfg_rx_prbs31_enable)
);
end
endgenerate
endmodule
`resetall

View File

@ -0,0 +1,307 @@
/*
Copyright (c) 2021-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.
*/
// 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_qpll0clk_out,
output wire xcvr_qpll0refclk_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,
output wire phy_rx_status,
input wire phy_cfg_tx_prbs31_enable,
input wire phy_cfg_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_qpll0clk_out),
.qpll0outrefclk_out(xcvr_qpll0refclk_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()
);
assign xcvr_qpll0reset_out = 1'b0;
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()
);
assign xcvr_qpll0lock_out = 1'b0;
assign xcvr_qpll0clk_out = 1'b0;
assign xcvr_qpll0refclk_out = 1'b0;
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),
.rx_status(phy_rx_status),
.cfg_tx_prbs31_enable(phy_cfg_tx_prbs31_enable),
.cfg_rx_prbs31_enable(phy_cfg_rx_prbs31_enable)
);
endmodule
`resetall

View File

@ -0,0 +1,323 @@
/*
Copyright (c) 2014-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
/*
* FPGA top-level module
*/
module fpga (
/*
* Clock: 156.25MHz
*/
input wire [1:0] refclk_user_p,
input wire [1:0] refclk_user_n,
/*
* Ethernet: QSFP28
*/
input wire [67:0] eth_gt_ch_rx_p,
input wire [67:0] eth_gt_ch_rx_n,
output wire [67:0] eth_gt_ch_tx_p,
output wire [67:0] eth_gt_ch_tx_n,
input wire [16:0] eth_gt_pri_refclk_p,
input wire [16:0] eth_gt_pri_refclk_n
);
genvar n;
// Clock and reset
// Buffers
wire [1:0] refclk_user;
generate
for (n = 0; n < 2; n = n + 1) begin : refclk_buf
IBUFGDS #(
.DIFF_TERM("FALSE"),
.IBUF_LOW_PWR("FALSE")
)
refclk_ibufg_inst (
.O (refclk_user[n]),
.I (refclk_user_p[n]),
.IB (refclk_user_n[n])
);
end
endgenerate
// Internal 125 MHz clock
wire clk_125mhz_mmcm_out;
wire clk_125mhz_int;
wire rst_125mhz_int;
// Internal 156.25 MHz clock
wire clk_156mhz_int;
wire rst_156mhz_int;
wire mmcm_rst = 1'b0;
wire mmcm_locked;
wire mmcm_clkfb;
// MMCM instance
// 156.25 MHz in, 125 MHz out
// PFD range: 10 MHz to 500 MHz
// VCO range: 800 MHz to 1600 MHz
// M = 8, D = 1 sets Fvco = 1250 MHz
// Divide by 10 to get output frequency of 125 MHz
MMCME3_BASE #(
.BANDWIDTH("OPTIMIZED"),
.CLKOUT0_DIVIDE_F(10),
.CLKOUT0_DUTY_CYCLE(0.5),
.CLKOUT0_PHASE(0),
.CLKOUT1_DIVIDE(1),
.CLKOUT1_DUTY_CYCLE(0.5),
.CLKOUT1_PHASE(0),
.CLKOUT2_DIVIDE(1),
.CLKOUT2_DUTY_CYCLE(0.5),
.CLKOUT2_PHASE(0),
.CLKOUT3_DIVIDE(1),
.CLKOUT3_DUTY_CYCLE(0.5),
.CLKOUT3_PHASE(0),
.CLKOUT4_DIVIDE(1),
.CLKOUT4_DUTY_CYCLE(0.5),
.CLKOUT4_PHASE(0),
.CLKOUT5_DIVIDE(1),
.CLKOUT5_DUTY_CYCLE(0.5),
.CLKOUT5_PHASE(0),
.CLKOUT6_DIVIDE(1),
.CLKOUT6_DUTY_CYCLE(0.5),
.CLKOUT6_PHASE(0),
.CLKFBOUT_MULT_F(8),
.CLKFBOUT_PHASE(0),
.DIVCLK_DIVIDE(1),
.REF_JITTER1(0.010),
.CLKIN1_PERIOD(6.400),
.STARTUP_WAIT("FALSE"),
.CLKOUT4_CASCADE("FALSE")
)
clk_mmcm_inst (
.CLKIN1(refclk_user[0]),
.CLKFBIN(mmcm_clkfb),
.RST(mmcm_rst),
.PWRDWN(1'b0),
.CLKOUT0(clk_125mhz_mmcm_out),
.CLKOUT0B(),
.CLKOUT1(),
.CLKOUT1B(),
.CLKOUT2(),
.CLKOUT2B(),
.CLKOUT3(),
.CLKOUT3B(),
.CLKOUT4(),
.CLKOUT5(),
.CLKOUT6(),
.CLKFBOUT(mmcm_clkfb),
.CLKFBOUTB(),
.LOCKED(mmcm_locked)
);
BUFG
clk_125mhz_bufg_inst (
.I(clk_125mhz_mmcm_out),
.O(clk_125mhz_int)
);
sync_reset #(
.N(4)
)
sync_reset_125mhz_inst (
.clk(clk_125mhz_int),
.rst(~mmcm_locked),
.out(rst_125mhz_int)
);
// XGMII 10G PHY
parameter QUAD_CNT = 17;
parameter CH_CNT = QUAD_CNT*4;
wire [CH_CNT-1:0] eth_tx_clk;
wire [CH_CNT-1:0] eth_tx_rst;
wire [CH_CNT*64-1:0] eth_txd;
wire [CH_CNT*8-1:0] eth_txc;
wire [CH_CNT-1:0] eth_rx_clk;
wire [CH_CNT-1:0] eth_rx_rst;
wire [CH_CNT*64-1:0] eth_rxd;
wire [CH_CNT*8-1:0] eth_rxc;
assign clk_156mhz_int = eth_tx_clk[0];
assign rst_156mhz_int = eth_tx_rst[0];
generate
for (n = 0; n < QUAD_CNT; n = n + 1) begin : eth_quad
wire quad_mgt_refclk;
IBUFDS_GTE4 ibufds_gte4_qsfp_1_mgt_refclk_inst (
.I (eth_gt_pri_refclk_p[n]),
.IB (eth_gt_pri_refclk_n[n]),
.CEB (1'b0),
.O (quad_mgt_refclk),
.ODIV2 ()
);
eth_xcvr_phy_quad_wrapper
quad_phy_inst (
.xcvr_ctrl_clk(clk_125mhz_int),
.xcvr_ctrl_rst(rst_125mhz_int),
/*
* Common
*/
.xcvr_gtpowergood_out(),
/*
* PLL
*/
.xcvr_gtrefclk00_in(quad_mgt_refclk),
/*
* Serial data
*/
.xcvr_txp(eth_gt_ch_tx_p[n*4 +: 4]),
.xcvr_txn(eth_gt_ch_tx_n[n*4 +: 4]),
.xcvr_rxp(eth_gt_ch_rx_p[n*4 +: 4]),
.xcvr_rxn(eth_gt_ch_rx_n[n*4 +: 4]),
/*
* PHY connections
*/
.phy_1_tx_clk(eth_tx_clk[n*4+0 +: 1]),
.phy_1_tx_rst(eth_tx_rst[n*4+0 +: 1]),
.phy_1_xgmii_txd(eth_txd[(n*4+0)*64 +: 64]),
.phy_1_xgmii_txc(eth_txc[(n*4+0)*8 +: 8]),
.phy_1_rx_clk(eth_rx_clk[n*4+0 +: 1]),
.phy_1_rx_rst(eth_rx_rst[n*4+0 +: 1]),
.phy_1_xgmii_rxd(eth_rxd[(n*4+0)*64 +: 64]),
.phy_1_xgmii_rxc(eth_rxc[(n*4+0)*8 +: 8]),
.phy_1_tx_bad_block(),
.phy_1_rx_error_count(),
.phy_1_rx_bad_block(),
.phy_1_rx_sequence_error(),
.phy_1_rx_block_lock(),
.phy_1_rx_high_ber(),
.phy_1_rx_status(),
.phy_1_cfg_tx_prbs31_enable(1'b0),
.phy_1_cfg_rx_prbs31_enable(1'b0),
.phy_2_tx_clk(eth_tx_clk[n*4+1 +: 1]),
.phy_2_tx_rst(eth_tx_rst[n*4+1 +: 1]),
.phy_2_xgmii_txd(eth_txd[(n*4+1)*64 +: 64]),
.phy_2_xgmii_txc(eth_txc[(n*4+1)*8 +: 8]),
.phy_2_rx_clk(eth_rx_clk[n*4+1 +: 1]),
.phy_2_rx_rst(eth_rx_rst[n*4+1 +: 1]),
.phy_2_xgmii_rxd(eth_rxd[(n*4+1)*64 +: 64]),
.phy_2_xgmii_rxc(eth_rxc[(n*4+1)*8 +: 8]),
.phy_2_tx_bad_block(),
.phy_2_rx_error_count(),
.phy_2_rx_bad_block(),
.phy_2_rx_sequence_error(),
.phy_2_rx_block_lock(),
.phy_2_rx_high_ber(),
.phy_2_rx_status(),
.phy_2_cfg_tx_prbs31_enable(1'b0),
.phy_2_cfg_rx_prbs31_enable(1'b0),
.phy_3_tx_clk(eth_tx_clk[n*4+2 +: 1]),
.phy_3_tx_rst(eth_tx_rst[n*4+2 +: 1]),
.phy_3_xgmii_txd(eth_txd[(n*4+2)*64 +: 64]),
.phy_3_xgmii_txc(eth_txc[(n*4+2)*8 +: 8]),
.phy_3_rx_clk(eth_rx_clk[n*4+2 +: 1]),
.phy_3_rx_rst(eth_rx_rst[n*4+2 +: 1]),
.phy_3_xgmii_rxd(eth_rxd[(n*4+2)*64 +: 64]),
.phy_3_xgmii_rxc(eth_rxc[(n*4+2)*8 +: 8]),
.phy_3_tx_bad_block(),
.phy_3_rx_error_count(),
.phy_3_rx_bad_block(),
.phy_3_rx_sequence_error(),
.phy_3_rx_block_lock(),
.phy_3_rx_high_ber(),
.phy_3_rx_status(),
.phy_3_cfg_tx_prbs31_enable(1'b0),
.phy_3_cfg_rx_prbs31_enable(1'b0),
.phy_4_tx_clk(eth_tx_clk[n*4+3 +: 1]),
.phy_4_tx_rst(eth_tx_rst[n*4+3 +: 1]),
.phy_4_xgmii_txd(eth_txd[(n*4+3)*64 +: 64]),
.phy_4_xgmii_txc(eth_txc[(n*4+3)*8 +: 8]),
.phy_4_rx_clk(eth_rx_clk[n*4+3 +: 1]),
.phy_4_rx_rst(eth_rx_rst[n*4+3 +: 1]),
.phy_4_xgmii_rxd(eth_rxd[(n*4+3)*64 +: 64]),
.phy_4_xgmii_rxc(eth_rxc[(n*4+3)*8 +: 8]),
.phy_4_tx_bad_block(),
.phy_4_rx_error_count(),
.phy_4_rx_bad_block(),
.phy_4_rx_sequence_error(),
.phy_4_rx_block_lock(),
.phy_4_rx_high_ber(),
.phy_4_rx_status(),
.phy_4_cfg_tx_prbs31_enable(1'b0),
.phy_4_cfg_rx_prbs31_enable(1'b0)
);
end
endgenerate
fpga_core #(
.CH_CNT(CH_CNT)
)
core_inst (
/*
* Clock: 156.25 MHz
* Synchronous reset
*/
.clk(clk_156mhz_int),
.rst(rst_156mhz_int),
/*
* Ethernet: QSFP28
*/
.eth_tx_clk(eth_tx_clk),
.eth_tx_rst(eth_tx_rst),
.eth_txd(eth_txd),
.eth_txc(eth_txc),
.eth_rx_clk(eth_rx_clk),
.eth_rx_rst(eth_rx_rst),
.eth_rxd(eth_rxd),
.eth_rxc(eth_rxc)
);
endmodule
`resetall

View File

@ -0,0 +1,738 @@
/*
Copyright (c) 2014-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
/*
* FPGA core logic
*/
module fpga_core #
(
parameter CH_CNT = 68
)
(
/*
* Clock: 156.25MHz
* Synchronous reset
*/
input wire clk,
input wire rst,
/*
* Ethernet
*/
input wire [CH_CNT-1:0] eth_tx_clk,
input wire [CH_CNT-1:0] eth_tx_rst,
output wire [CH_CNT*64-1:0] eth_txd,
output wire [CH_CNT*8-1:0] eth_txc,
input wire [CH_CNT-1:0] eth_rx_clk,
input wire [CH_CNT-1:0] eth_rx_rst,
input wire [CH_CNT*64-1:0] eth_rxd,
input wire [CH_CNT*8-1:0] eth_rxc
);
// AXI between MAC and Ethernet modules
wire [63:0] rx_axis_tdata;
wire [7:0] rx_axis_tkeep;
wire rx_axis_tvalid;
wire rx_axis_tready;
wire rx_axis_tlast;
wire rx_axis_tuser;
wire [63:0] tx_axis_tdata;
wire [7:0] tx_axis_tkeep;
wire tx_axis_tvalid;
wire tx_axis_tready;
wire tx_axis_tlast;
wire tx_axis_tuser;
// Ethernet frame between Ethernet modules and UDP stack
wire rx_eth_hdr_ready;
wire rx_eth_hdr_valid;
wire [47:0] rx_eth_dest_mac;
wire [47:0] rx_eth_src_mac;
wire [15:0] rx_eth_type;
wire [63:0] rx_eth_payload_axis_tdata;
wire [7:0] rx_eth_payload_axis_tkeep;
wire rx_eth_payload_axis_tvalid;
wire rx_eth_payload_axis_tready;
wire rx_eth_payload_axis_tlast;
wire rx_eth_payload_axis_tuser;
wire tx_eth_hdr_ready;
wire tx_eth_hdr_valid;
wire [47:0] tx_eth_dest_mac;
wire [47:0] tx_eth_src_mac;
wire [15:0] tx_eth_type;
wire [63:0] tx_eth_payload_axis_tdata;
wire [7:0] tx_eth_payload_axis_tkeep;
wire tx_eth_payload_axis_tvalid;
wire tx_eth_payload_axis_tready;
wire tx_eth_payload_axis_tlast;
wire tx_eth_payload_axis_tuser;
// IP frame connections
wire rx_ip_hdr_valid;
wire rx_ip_hdr_ready;
wire [47:0] rx_ip_eth_dest_mac;
wire [47:0] rx_ip_eth_src_mac;
wire [15:0] rx_ip_eth_type;
wire [3:0] rx_ip_version;
wire [3:0] rx_ip_ihl;
wire [5:0] rx_ip_dscp;
wire [1:0] rx_ip_ecn;
wire [15:0] rx_ip_length;
wire [15:0] rx_ip_identification;
wire [2:0] rx_ip_flags;
wire [12:0] rx_ip_fragment_offset;
wire [7:0] rx_ip_ttl;
wire [7:0] rx_ip_protocol;
wire [15:0] rx_ip_header_checksum;
wire [31:0] rx_ip_source_ip;
wire [31:0] rx_ip_dest_ip;
wire [63:0] rx_ip_payload_axis_tdata;
wire [7:0] rx_ip_payload_axis_tkeep;
wire rx_ip_payload_axis_tvalid;
wire rx_ip_payload_axis_tready;
wire rx_ip_payload_axis_tlast;
wire rx_ip_payload_axis_tuser;
wire tx_ip_hdr_valid;
wire tx_ip_hdr_ready;
wire [5:0] tx_ip_dscp;
wire [1:0] tx_ip_ecn;
wire [15:0] tx_ip_length;
wire [7:0] tx_ip_ttl;
wire [7:0] tx_ip_protocol;
wire [31:0] tx_ip_source_ip;
wire [31:0] tx_ip_dest_ip;
wire [63:0] tx_ip_payload_axis_tdata;
wire [7:0] tx_ip_payload_axis_tkeep;
wire tx_ip_payload_axis_tvalid;
wire tx_ip_payload_axis_tready;
wire tx_ip_payload_axis_tlast;
wire tx_ip_payload_axis_tuser;
// UDP frame connections
wire rx_udp_hdr_valid;
wire rx_udp_hdr_ready;
wire [47:0] rx_udp_eth_dest_mac;
wire [47:0] rx_udp_eth_src_mac;
wire [15:0] rx_udp_eth_type;
wire [3:0] rx_udp_ip_version;
wire [3:0] rx_udp_ip_ihl;
wire [5:0] rx_udp_ip_dscp;
wire [1:0] rx_udp_ip_ecn;
wire [15:0] rx_udp_ip_length;
wire [15:0] rx_udp_ip_identification;
wire [2:0] rx_udp_ip_flags;
wire [12:0] rx_udp_ip_fragment_offset;
wire [7:0] rx_udp_ip_ttl;
wire [7:0] rx_udp_ip_protocol;
wire [15:0] rx_udp_ip_header_checksum;
wire [31:0] rx_udp_ip_source_ip;
wire [31:0] rx_udp_ip_dest_ip;
wire [15:0] rx_udp_source_port;
wire [15:0] rx_udp_dest_port;
wire [15:0] rx_udp_length;
wire [15:0] rx_udp_checksum;
wire [63:0] rx_udp_payload_axis_tdata;
wire [7:0] rx_udp_payload_axis_tkeep;
wire rx_udp_payload_axis_tvalid;
wire rx_udp_payload_axis_tready;
wire rx_udp_payload_axis_tlast;
wire rx_udp_payload_axis_tuser;
wire tx_udp_hdr_valid;
wire tx_udp_hdr_ready;
wire [5:0] tx_udp_ip_dscp;
wire [1:0] tx_udp_ip_ecn;
wire [7:0] tx_udp_ip_ttl;
wire [31:0] tx_udp_ip_source_ip;
wire [31:0] tx_udp_ip_dest_ip;
wire [15:0] tx_udp_source_port;
wire [15:0] tx_udp_dest_port;
wire [15:0] tx_udp_length;
wire [15:0] tx_udp_checksum;
wire [63:0] tx_udp_payload_axis_tdata;
wire [7:0] tx_udp_payload_axis_tkeep;
wire tx_udp_payload_axis_tvalid;
wire tx_udp_payload_axis_tready;
wire tx_udp_payload_axis_tlast;
wire tx_udp_payload_axis_tuser;
wire [63:0] rx_fifo_udp_payload_axis_tdata;
wire [7:0] rx_fifo_udp_payload_axis_tkeep;
wire rx_fifo_udp_payload_axis_tvalid;
wire rx_fifo_udp_payload_axis_tready;
wire rx_fifo_udp_payload_axis_tlast;
wire rx_fifo_udp_payload_axis_tuser;
wire [63:0] tx_fifo_udp_payload_axis_tdata;
wire [7:0] tx_fifo_udp_payload_axis_tkeep;
wire tx_fifo_udp_payload_axis_tvalid;
wire tx_fifo_udp_payload_axis_tready;
wire tx_fifo_udp_payload_axis_tlast;
wire tx_fifo_udp_payload_axis_tuser;
// Configuration
wire [47:0] local_mac = 48'h02_00_00_00_00_00;
wire [31:0] local_ip = {8'd192, 8'd168, 8'd1, 8'd128};
wire [31:0] gateway_ip = {8'd192, 8'd168, 8'd1, 8'd1};
wire [31:0] subnet_mask = {8'd255, 8'd255, 8'd255, 8'd0};
// IP ports not used
assign rx_ip_hdr_ready = 1;
assign rx_ip_payload_axis_tready = 1;
assign tx_ip_hdr_valid = 0;
assign tx_ip_dscp = 0;
assign tx_ip_ecn = 0;
assign tx_ip_length = 0;
assign tx_ip_ttl = 0;
assign tx_ip_protocol = 0;
assign tx_ip_source_ip = 0;
assign tx_ip_dest_ip = 0;
assign tx_ip_payload_axis_tdata = 0;
assign tx_ip_payload_axis_tkeep = 0;
assign tx_ip_payload_axis_tvalid = 0;
assign tx_ip_payload_axis_tlast = 0;
assign tx_ip_payload_axis_tuser = 0;
// Loop back UDP
wire match_cond = rx_udp_dest_port == 1234;
wire no_match = !match_cond;
reg match_cond_reg = 0;
reg no_match_reg = 0;
always @(posedge clk) begin
if (rst) begin
match_cond_reg <= 0;
no_match_reg <= 0;
end else begin
if (rx_udp_payload_axis_tvalid) begin
if ((!match_cond_reg && !no_match_reg) ||
(rx_udp_payload_axis_tvalid && rx_udp_payload_axis_tready && rx_udp_payload_axis_tlast)) begin
match_cond_reg <= match_cond;
no_match_reg <= no_match;
end
end else begin
match_cond_reg <= 0;
no_match_reg <= 0;
end
end
end
assign tx_udp_hdr_valid = rx_udp_hdr_valid && match_cond;
assign rx_udp_hdr_ready = (tx_eth_hdr_ready && match_cond) || no_match;
assign tx_udp_ip_dscp = 0;
assign tx_udp_ip_ecn = 0;
assign tx_udp_ip_ttl = 64;
assign tx_udp_ip_source_ip = local_ip;
assign tx_udp_ip_dest_ip = rx_udp_ip_source_ip;
assign tx_udp_source_port = rx_udp_dest_port;
assign tx_udp_dest_port = rx_udp_source_port;
assign tx_udp_length = rx_udp_length;
assign tx_udp_checksum = 0;
assign tx_udp_payload_axis_tdata = tx_fifo_udp_payload_axis_tdata;
assign tx_udp_payload_axis_tkeep = tx_fifo_udp_payload_axis_tkeep;
assign tx_udp_payload_axis_tvalid = tx_fifo_udp_payload_axis_tvalid;
assign tx_fifo_udp_payload_axis_tready = tx_udp_payload_axis_tready;
assign tx_udp_payload_axis_tlast = tx_fifo_udp_payload_axis_tlast;
assign tx_udp_payload_axis_tuser = tx_fifo_udp_payload_axis_tuser;
assign rx_fifo_udp_payload_axis_tdata = rx_udp_payload_axis_tdata;
assign rx_fifo_udp_payload_axis_tkeep = rx_udp_payload_axis_tkeep;
assign rx_fifo_udp_payload_axis_tvalid = rx_udp_payload_axis_tvalid && match_cond_reg;
assign rx_udp_payload_axis_tready = (rx_fifo_udp_payload_axis_tready && match_cond_reg) || no_match_reg;
assign rx_fifo_udp_payload_axis_tlast = rx_udp_payload_axis_tlast;
assign rx_fifo_udp_payload_axis_tuser = rx_udp_payload_axis_tuser;
// Place first payload byte onto LEDs
reg valid_last = 0;
reg [7:0] led_reg = 0;
always @(posedge clk) begin
if (rst) begin
led_reg <= 0;
end else begin
valid_last <= tx_udp_payload_axis_tvalid;
if (tx_udp_payload_axis_tvalid && !valid_last) begin
led_reg <= tx_udp_payload_axis_tdata;
end
end
end
assign eth_txd[1*64 +: 64] = 64'h0707070707070707;
assign eth_txc[1*8 +: 8] = 8'hff;
assign eth_txd[2*64 +: 64] = 64'h0707070707070707;
assign eth_txc[2*8 +: 8] = 8'hff;
assign eth_txd[3*64 +: 64] = 64'h0707070707070707;
assign eth_txc[3*8 +: 8] = 8'hff;
assign eth_txd[4*64 +: 64] = 64'h0707070707070707;
assign eth_txc[4*8 +: 8] = 8'hff;
assign eth_txd[5*64 +: 64] = 64'h0707070707070707;
assign eth_txc[5*8 +: 8] = 8'hff;
assign eth_txd[6*64 +: 64] = 64'h0707070707070707;
assign eth_txc[6*8 +: 8] = 8'hff;
assign eth_txd[7*64 +: 64] = 64'h0707070707070707;
assign eth_txc[7*8 +: 8] = 8'hff;
assign eth_txd[8*64 +: 64] = 64'h0707070707070707;
assign eth_txc[8*8 +: 8] = 8'hff;
assign eth_txd[9*64 +: 64] = 64'h0707070707070707;
assign eth_txc[9*8 +: 8] = 8'hff;
assign eth_txd[10*64 +: 64] = 64'h0707070707070707;
assign eth_txc[10*8 +: 8] = 8'hff;
assign eth_txd[11*64 +: 64] = 64'h0707070707070707;
assign eth_txc[11*8 +: 8] = 8'hff;
assign eth_txd[12*64 +: 64] = 64'h0707070707070707;
assign eth_txc[12*8 +: 8] = 8'hff;
assign eth_txd[13*64 +: 64] = 64'h0707070707070707;
assign eth_txc[13*8 +: 8] = 8'hff;
assign eth_txd[14*64 +: 64] = 64'h0707070707070707;
assign eth_txc[14*8 +: 8] = 8'hff;
assign eth_txd[15*64 +: 64] = 64'h0707070707070707;
assign eth_txc[15*8 +: 8] = 8'hff;
assign eth_txd[16*64 +: 64] = 64'h0707070707070707;
assign eth_txc[16*8 +: 8] = 8'hff;
assign eth_txd[17*64 +: 64] = 64'h0707070707070707;
assign eth_txc[17*8 +: 8] = 8'hff;
assign eth_txd[18*64 +: 64] = 64'h0707070707070707;
assign eth_txc[18*8 +: 8] = 8'hff;
assign eth_txd[19*64 +: 64] = 64'h0707070707070707;
assign eth_txc[19*8 +: 8] = 8'hff;
assign eth_txd[10*64 +: 64] = 64'h0707070707070707;
assign eth_txc[10*8 +: 8] = 8'hff;
assign eth_txd[11*64 +: 64] = 64'h0707070707070707;
assign eth_txc[11*8 +: 8] = 8'hff;
assign eth_txd[12*64 +: 64] = 64'h0707070707070707;
assign eth_txc[12*8 +: 8] = 8'hff;
assign eth_txd[13*64 +: 64] = 64'h0707070707070707;
assign eth_txc[13*8 +: 8] = 8'hff;
assign eth_txd[14*64 +: 64] = 64'h0707070707070707;
assign eth_txc[14*8 +: 8] = 8'hff;
assign eth_txd[15*64 +: 64] = 64'h0707070707070707;
assign eth_txc[15*8 +: 8] = 8'hff;
assign eth_txd[16*64 +: 64] = 64'h0707070707070707;
assign eth_txc[16*8 +: 8] = 8'hff;
assign eth_txd[17*64 +: 64] = 64'h0707070707070707;
assign eth_txc[17*8 +: 8] = 8'hff;
assign eth_txd[18*64 +: 64] = 64'h0707070707070707;
assign eth_txc[18*8 +: 8] = 8'hff;
assign eth_txd[19*64 +: 64] = 64'h0707070707070707;
assign eth_txc[19*8 +: 8] = 8'hff;
assign eth_txd[20*64 +: 64] = 64'h0707070707070707;
assign eth_txc[20*8 +: 8] = 8'hff;
assign eth_txd[21*64 +: 64] = 64'h0707070707070707;
assign eth_txc[21*8 +: 8] = 8'hff;
assign eth_txd[22*64 +: 64] = 64'h0707070707070707;
assign eth_txc[22*8 +: 8] = 8'hff;
assign eth_txd[23*64 +: 64] = 64'h0707070707070707;
assign eth_txc[23*8 +: 8] = 8'hff;
assign eth_txd[24*64 +: 64] = 64'h0707070707070707;
assign eth_txc[24*8 +: 8] = 8'hff;
assign eth_txd[25*64 +: 64] = 64'h0707070707070707;
assign eth_txc[25*8 +: 8] = 8'hff;
assign eth_txd[26*64 +: 64] = 64'h0707070707070707;
assign eth_txc[26*8 +: 8] = 8'hff;
assign eth_txd[27*64 +: 64] = 64'h0707070707070707;
assign eth_txc[27*8 +: 8] = 8'hff;
assign eth_txd[28*64 +: 64] = 64'h0707070707070707;
assign eth_txc[28*8 +: 8] = 8'hff;
assign eth_txd[29*64 +: 64] = 64'h0707070707070707;
assign eth_txc[29*8 +: 8] = 8'hff;
assign eth_txd[30*64 +: 64] = 64'h0707070707070707;
assign eth_txc[30*8 +: 8] = 8'hff;
assign eth_txd[31*64 +: 64] = 64'h0707070707070707;
assign eth_txc[31*8 +: 8] = 8'hff;
assign eth_txd[32*64 +: 64] = 64'h0707070707070707;
assign eth_txc[32*8 +: 8] = 8'hff;
assign eth_txd[33*64 +: 64] = 64'h0707070707070707;
assign eth_txc[33*8 +: 8] = 8'hff;
assign eth_txd[34*64 +: 64] = 64'h0707070707070707;
assign eth_txc[34*8 +: 8] = 8'hff;
assign eth_txd[35*64 +: 64] = 64'h0707070707070707;
assign eth_txc[35*8 +: 8] = 8'hff;
assign eth_txd[36*64 +: 64] = 64'h0707070707070707;
assign eth_txc[36*8 +: 8] = 8'hff;
assign eth_txd[37*64 +: 64] = 64'h0707070707070707;
assign eth_txc[37*8 +: 8] = 8'hff;
assign eth_txd[38*64 +: 64] = 64'h0707070707070707;
assign eth_txc[38*8 +: 8] = 8'hff;
assign eth_txd[39*64 +: 64] = 64'h0707070707070707;
assign eth_txc[39*8 +: 8] = 8'hff;
assign eth_txd[40*64 +: 64] = 64'h0707070707070707;
assign eth_txc[40*8 +: 8] = 8'hff;
assign eth_txd[41*64 +: 64] = 64'h0707070707070707;
assign eth_txc[41*8 +: 8] = 8'hff;
assign eth_txd[42*64 +: 64] = 64'h0707070707070707;
assign eth_txc[42*8 +: 8] = 8'hff;
assign eth_txd[43*64 +: 64] = 64'h0707070707070707;
assign eth_txc[43*8 +: 8] = 8'hff;
assign eth_txd[44*64 +: 64] = 64'h0707070707070707;
assign eth_txc[44*8 +: 8] = 8'hff;
assign eth_txd[45*64 +: 64] = 64'h0707070707070707;
assign eth_txc[45*8 +: 8] = 8'hff;
assign eth_txd[46*64 +: 64] = 64'h0707070707070707;
assign eth_txc[46*8 +: 8] = 8'hff;
assign eth_txd[47*64 +: 64] = 64'h0707070707070707;
assign eth_txc[47*8 +: 8] = 8'hff;
assign eth_txd[48*64 +: 64] = 64'h0707070707070707;
assign eth_txc[48*8 +: 8] = 8'hff;
assign eth_txd[49*64 +: 64] = 64'h0707070707070707;
assign eth_txc[49*8 +: 8] = 8'hff;
assign eth_txd[50*64 +: 64] = 64'h0707070707070707;
assign eth_txc[50*8 +: 8] = 8'hff;
assign eth_txd[51*64 +: 64] = 64'h0707070707070707;
assign eth_txc[51*8 +: 8] = 8'hff;
assign eth_txd[52*64 +: 64] = 64'h0707070707070707;
assign eth_txc[52*8 +: 8] = 8'hff;
assign eth_txd[53*64 +: 64] = 64'h0707070707070707;
assign eth_txc[53*8 +: 8] = 8'hff;
assign eth_txd[54*64 +: 64] = 64'h0707070707070707;
assign eth_txc[54*8 +: 8] = 8'hff;
assign eth_txd[55*64 +: 64] = 64'h0707070707070707;
assign eth_txc[55*8 +: 8] = 8'hff;
assign eth_txd[56*64 +: 64] = 64'h0707070707070707;
assign eth_txc[56*8 +: 8] = 8'hff;
assign eth_txd[57*64 +: 64] = 64'h0707070707070707;
assign eth_txc[57*8 +: 8] = 8'hff;
assign eth_txd[58*64 +: 64] = 64'h0707070707070707;
assign eth_txc[58*8 +: 8] = 8'hff;
assign eth_txd[59*64 +: 64] = 64'h0707070707070707;
assign eth_txc[59*8 +: 8] = 8'hff;
assign eth_txd[60*64 +: 64] = 64'h0707070707070707;
assign eth_txc[60*8 +: 8] = 8'hff;
assign eth_txd[61*64 +: 64] = 64'h0707070707070707;
assign eth_txc[61*8 +: 8] = 8'hff;
assign eth_txd[62*64 +: 64] = 64'h0707070707070707;
assign eth_txc[62*8 +: 8] = 8'hff;
assign eth_txd[63*64 +: 64] = 64'h0707070707070707;
assign eth_txc[63*8 +: 8] = 8'hff;
assign eth_txd[64*64 +: 64] = 64'h0707070707070707;
assign eth_txc[64*8 +: 8] = 8'hff;
assign eth_txd[65*64 +: 64] = 64'h0707070707070707;
assign eth_txc[65*8 +: 8] = 8'hff;
assign eth_txd[66*64 +: 64] = 64'h0707070707070707;
assign eth_txc[66*8 +: 8] = 8'hff;
assign eth_txd[67*64 +: 64] = 64'h0707070707070707;
assign eth_txc[67*8 +: 8] = 8'hff;
eth_mac_10g_fifo #(
.ENABLE_PADDING(1),
.ENABLE_DIC(1),
.MIN_FRAME_LENGTH(64),
.TX_FIFO_DEPTH(4096),
.TX_FRAME_FIFO(1),
.RX_FIFO_DEPTH(4096),
.RX_FRAME_FIFO(1)
)
eth_mac_10g_fifo_inst (
.rx_clk(eth_rx_clk[0 +: 1]),
.rx_rst(eth_rx_rst[0 +: 1]),
.tx_clk(eth_tx_clk[0 +: 1]),
.tx_rst(eth_tx_rst[0 +: 1]),
.logic_clk(clk),
.logic_rst(rst),
.tx_axis_tdata(tx_axis_tdata),
.tx_axis_tkeep(tx_axis_tkeep),
.tx_axis_tvalid(tx_axis_tvalid),
.tx_axis_tready(tx_axis_tready),
.tx_axis_tlast(tx_axis_tlast),
.tx_axis_tuser(tx_axis_tuser),
.rx_axis_tdata(rx_axis_tdata),
.rx_axis_tkeep(rx_axis_tkeep),
.rx_axis_tvalid(rx_axis_tvalid),
.rx_axis_tready(rx_axis_tready),
.rx_axis_tlast(rx_axis_tlast),
.rx_axis_tuser(rx_axis_tuser),
.xgmii_rxd(eth_rxd[0*64 +: 64]),
.xgmii_rxc(eth_rxc[0*8 +: 8]),
.xgmii_txd(eth_txd[0*64 +: 64]),
.xgmii_txc(eth_txc[0*8 +: 8]),
.tx_fifo_overflow(),
.tx_fifo_bad_frame(),
.tx_fifo_good_frame(),
.rx_error_bad_frame(),
.rx_error_bad_fcs(),
.rx_fifo_overflow(),
.rx_fifo_bad_frame(),
.rx_fifo_good_frame(),
.cfg_ifg(8'd12),
.cfg_tx_enable(1'b1),
.cfg_rx_enable(1'b1)
);
eth_axis_rx #(
.DATA_WIDTH(64)
)
eth_axis_rx_inst (
.clk(clk),
.rst(rst),
// AXI input
.s_axis_tdata(rx_axis_tdata),
.s_axis_tkeep(rx_axis_tkeep),
.s_axis_tvalid(rx_axis_tvalid),
.s_axis_tready(rx_axis_tready),
.s_axis_tlast(rx_axis_tlast),
.s_axis_tuser(rx_axis_tuser),
// Ethernet frame output
.m_eth_hdr_valid(rx_eth_hdr_valid),
.m_eth_hdr_ready(rx_eth_hdr_ready),
.m_eth_dest_mac(rx_eth_dest_mac),
.m_eth_src_mac(rx_eth_src_mac),
.m_eth_type(rx_eth_type),
.m_eth_payload_axis_tdata(rx_eth_payload_axis_tdata),
.m_eth_payload_axis_tkeep(rx_eth_payload_axis_tkeep),
.m_eth_payload_axis_tvalid(rx_eth_payload_axis_tvalid),
.m_eth_payload_axis_tready(rx_eth_payload_axis_tready),
.m_eth_payload_axis_tlast(rx_eth_payload_axis_tlast),
.m_eth_payload_axis_tuser(rx_eth_payload_axis_tuser),
// Status signals
.busy(),
.error_header_early_termination()
);
eth_axis_tx #(
.DATA_WIDTH(64)
)
eth_axis_tx_inst (
.clk(clk),
.rst(rst),
// Ethernet frame input
.s_eth_hdr_valid(tx_eth_hdr_valid),
.s_eth_hdr_ready(tx_eth_hdr_ready),
.s_eth_dest_mac(tx_eth_dest_mac),
.s_eth_src_mac(tx_eth_src_mac),
.s_eth_type(tx_eth_type),
.s_eth_payload_axis_tdata(tx_eth_payload_axis_tdata),
.s_eth_payload_axis_tkeep(tx_eth_payload_axis_tkeep),
.s_eth_payload_axis_tvalid(tx_eth_payload_axis_tvalid),
.s_eth_payload_axis_tready(tx_eth_payload_axis_tready),
.s_eth_payload_axis_tlast(tx_eth_payload_axis_tlast),
.s_eth_payload_axis_tuser(tx_eth_payload_axis_tuser),
// AXI output
.m_axis_tdata(tx_axis_tdata),
.m_axis_tkeep(tx_axis_tkeep),
.m_axis_tvalid(tx_axis_tvalid),
.m_axis_tready(tx_axis_tready),
.m_axis_tlast(tx_axis_tlast),
.m_axis_tuser(tx_axis_tuser),
// Status signals
.busy()
);
udp_complete_64
udp_complete_inst (
.clk(clk),
.rst(rst),
// Ethernet frame input
.s_eth_hdr_valid(rx_eth_hdr_valid),
.s_eth_hdr_ready(rx_eth_hdr_ready),
.s_eth_dest_mac(rx_eth_dest_mac),
.s_eth_src_mac(rx_eth_src_mac),
.s_eth_type(rx_eth_type),
.s_eth_payload_axis_tdata(rx_eth_payload_axis_tdata),
.s_eth_payload_axis_tkeep(rx_eth_payload_axis_tkeep),
.s_eth_payload_axis_tvalid(rx_eth_payload_axis_tvalid),
.s_eth_payload_axis_tready(rx_eth_payload_axis_tready),
.s_eth_payload_axis_tlast(rx_eth_payload_axis_tlast),
.s_eth_payload_axis_tuser(rx_eth_payload_axis_tuser),
// Ethernet frame output
.m_eth_hdr_valid(tx_eth_hdr_valid),
.m_eth_hdr_ready(tx_eth_hdr_ready),
.m_eth_dest_mac(tx_eth_dest_mac),
.m_eth_src_mac(tx_eth_src_mac),
.m_eth_type(tx_eth_type),
.m_eth_payload_axis_tdata(tx_eth_payload_axis_tdata),
.m_eth_payload_axis_tkeep(tx_eth_payload_axis_tkeep),
.m_eth_payload_axis_tvalid(tx_eth_payload_axis_tvalid),
.m_eth_payload_axis_tready(tx_eth_payload_axis_tready),
.m_eth_payload_axis_tlast(tx_eth_payload_axis_tlast),
.m_eth_payload_axis_tuser(tx_eth_payload_axis_tuser),
// IP frame input
.s_ip_hdr_valid(tx_ip_hdr_valid),
.s_ip_hdr_ready(tx_ip_hdr_ready),
.s_ip_dscp(tx_ip_dscp),
.s_ip_ecn(tx_ip_ecn),
.s_ip_length(tx_ip_length),
.s_ip_ttl(tx_ip_ttl),
.s_ip_protocol(tx_ip_protocol),
.s_ip_source_ip(tx_ip_source_ip),
.s_ip_dest_ip(tx_ip_dest_ip),
.s_ip_payload_axis_tdata(tx_ip_payload_axis_tdata),
.s_ip_payload_axis_tkeep(tx_ip_payload_axis_tkeep),
.s_ip_payload_axis_tvalid(tx_ip_payload_axis_tvalid),
.s_ip_payload_axis_tready(tx_ip_payload_axis_tready),
.s_ip_payload_axis_tlast(tx_ip_payload_axis_tlast),
.s_ip_payload_axis_tuser(tx_ip_payload_axis_tuser),
// IP frame output
.m_ip_hdr_valid(rx_ip_hdr_valid),
.m_ip_hdr_ready(rx_ip_hdr_ready),
.m_ip_eth_dest_mac(rx_ip_eth_dest_mac),
.m_ip_eth_src_mac(rx_ip_eth_src_mac),
.m_ip_eth_type(rx_ip_eth_type),
.m_ip_version(rx_ip_version),
.m_ip_ihl(rx_ip_ihl),
.m_ip_dscp(rx_ip_dscp),
.m_ip_ecn(rx_ip_ecn),
.m_ip_length(rx_ip_length),
.m_ip_identification(rx_ip_identification),
.m_ip_flags(rx_ip_flags),
.m_ip_fragment_offset(rx_ip_fragment_offset),
.m_ip_ttl(rx_ip_ttl),
.m_ip_protocol(rx_ip_protocol),
.m_ip_header_checksum(rx_ip_header_checksum),
.m_ip_source_ip(rx_ip_source_ip),
.m_ip_dest_ip(rx_ip_dest_ip),
.m_ip_payload_axis_tdata(rx_ip_payload_axis_tdata),
.m_ip_payload_axis_tkeep(rx_ip_payload_axis_tkeep),
.m_ip_payload_axis_tvalid(rx_ip_payload_axis_tvalid),
.m_ip_payload_axis_tready(rx_ip_payload_axis_tready),
.m_ip_payload_axis_tlast(rx_ip_payload_axis_tlast),
.m_ip_payload_axis_tuser(rx_ip_payload_axis_tuser),
// UDP frame input
.s_udp_hdr_valid(tx_udp_hdr_valid),
.s_udp_hdr_ready(tx_udp_hdr_ready),
.s_udp_ip_dscp(tx_udp_ip_dscp),
.s_udp_ip_ecn(tx_udp_ip_ecn),
.s_udp_ip_ttl(tx_udp_ip_ttl),
.s_udp_ip_source_ip(tx_udp_ip_source_ip),
.s_udp_ip_dest_ip(tx_udp_ip_dest_ip),
.s_udp_source_port(tx_udp_source_port),
.s_udp_dest_port(tx_udp_dest_port),
.s_udp_length(tx_udp_length),
.s_udp_checksum(tx_udp_checksum),
.s_udp_payload_axis_tdata(tx_udp_payload_axis_tdata),
.s_udp_payload_axis_tkeep(tx_udp_payload_axis_tkeep),
.s_udp_payload_axis_tvalid(tx_udp_payload_axis_tvalid),
.s_udp_payload_axis_tready(tx_udp_payload_axis_tready),
.s_udp_payload_axis_tlast(tx_udp_payload_axis_tlast),
.s_udp_payload_axis_tuser(tx_udp_payload_axis_tuser),
// UDP frame output
.m_udp_hdr_valid(rx_udp_hdr_valid),
.m_udp_hdr_ready(rx_udp_hdr_ready),
.m_udp_eth_dest_mac(rx_udp_eth_dest_mac),
.m_udp_eth_src_mac(rx_udp_eth_src_mac),
.m_udp_eth_type(rx_udp_eth_type),
.m_udp_ip_version(rx_udp_ip_version),
.m_udp_ip_ihl(rx_udp_ip_ihl),
.m_udp_ip_dscp(rx_udp_ip_dscp),
.m_udp_ip_ecn(rx_udp_ip_ecn),
.m_udp_ip_length(rx_udp_ip_length),
.m_udp_ip_identification(rx_udp_ip_identification),
.m_udp_ip_flags(rx_udp_ip_flags),
.m_udp_ip_fragment_offset(rx_udp_ip_fragment_offset),
.m_udp_ip_ttl(rx_udp_ip_ttl),
.m_udp_ip_protocol(rx_udp_ip_protocol),
.m_udp_ip_header_checksum(rx_udp_ip_header_checksum),
.m_udp_ip_source_ip(rx_udp_ip_source_ip),
.m_udp_ip_dest_ip(rx_udp_ip_dest_ip),
.m_udp_source_port(rx_udp_source_port),
.m_udp_dest_port(rx_udp_dest_port),
.m_udp_length(rx_udp_length),
.m_udp_checksum(rx_udp_checksum),
.m_udp_payload_axis_tdata(rx_udp_payload_axis_tdata),
.m_udp_payload_axis_tkeep(rx_udp_payload_axis_tkeep),
.m_udp_payload_axis_tvalid(rx_udp_payload_axis_tvalid),
.m_udp_payload_axis_tready(rx_udp_payload_axis_tready),
.m_udp_payload_axis_tlast(rx_udp_payload_axis_tlast),
.m_udp_payload_axis_tuser(rx_udp_payload_axis_tuser),
// Status signals
.ip_rx_busy(),
.ip_tx_busy(),
.udp_rx_busy(),
.udp_tx_busy(),
.ip_rx_error_header_early_termination(),
.ip_rx_error_payload_early_termination(),
.ip_rx_error_invalid_header(),
.ip_rx_error_invalid_checksum(),
.ip_tx_error_payload_early_termination(),
.ip_tx_error_arp_failed(),
.udp_rx_error_header_early_termination(),
.udp_rx_error_payload_early_termination(),
.udp_tx_error_payload_early_termination(),
// Configuration
.local_mac(local_mac),
.local_ip(local_ip),
.gateway_ip(gateway_ip),
.subnet_mask(subnet_mask),
.clear_arp_cache(1'b0)
);
axis_fifo #(
.DEPTH(8192),
.DATA_WIDTH(64),
.KEEP_ENABLE(1),
.KEEP_WIDTH(8),
.ID_ENABLE(0),
.DEST_ENABLE(0),
.USER_ENABLE(1),
.USER_WIDTH(1),
.FRAME_FIFO(0)
)
udp_payload_fifo (
.clk(clk),
.rst(rst),
// AXI input
.s_axis_tdata(rx_fifo_udp_payload_axis_tdata),
.s_axis_tkeep(rx_fifo_udp_payload_axis_tkeep),
.s_axis_tvalid(rx_fifo_udp_payload_axis_tvalid),
.s_axis_tready(rx_fifo_udp_payload_axis_tready),
.s_axis_tlast(rx_fifo_udp_payload_axis_tlast),
.s_axis_tid(0),
.s_axis_tdest(0),
.s_axis_tuser(rx_fifo_udp_payload_axis_tuser),
// AXI output
.m_axis_tdata(tx_fifo_udp_payload_axis_tdata),
.m_axis_tkeep(tx_fifo_udp_payload_axis_tkeep),
.m_axis_tvalid(tx_fifo_udp_payload_axis_tvalid),
.m_axis_tready(tx_fifo_udp_payload_axis_tready),
.m_axis_tlast(tx_fifo_udp_payload_axis_tlast),
.m_axis_tid(),
.m_axis_tdest(),
.m_axis_tuser(tx_fifo_udp_payload_axis_tuser),
// Status
.status_overflow(),
.status_bad_frame(),
.status_good_frame()
);
endmodule
`resetall

View File

@ -0,0 +1,62 @@
/*
Copyright (c) 2014-2018 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,96 @@
# 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 = test_$(DUT)
MODULE = test_$(DUT)
VERILOG_SOURCES += $(TOPLEVEL).v
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,220 @@
"""
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())
# Ethernet
self.ch_source = []
self.ch_sink = []
for ch in self.dut.ch:
cocotb.start_soon(Clock(ch.ch_rx_clk, 2.56, units="ns").start())
source = XgmiiSource(ch.ch_rxd, ch.ch_rxc, ch.ch_rx_clk, ch.ch_rx_rst)
self.ch_source.append(source)
cocotb.start_soon(Clock(ch.ch_tx_clk, 2.56, units="ns").start())
sink = XgmiiSink(ch.ch_txd, ch.ch_txc, ch.ch_tx_clk, ch.ch_tx_rst)
self.ch_sink.append(sink)
async def init(self):
self.dut.rst.setimmediatevalue(0)
for ch in self.dut.ch:
ch.ch_rx_rst.setimmediatevalue(0)
ch.ch_tx_rst.setimmediatevalue(0)
for k in range(10):
await RisingEdge(self.dut.clk)
self.dut.rst.value = 1
for ch in self.dut.ch:
ch.ch_rx_rst.value = 1
ch.ch_tx_rst.value = 1
for k in range(10):
await RisingEdge(self.dut.clk)
self.dut.rst.value = 0
for ch in self.dut.ch:
ch.ch_rx_rst.value = 0
ch.ch_tx_rst.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.ch_source[0].send(test_frame)
tb.log.info("receive ARP request")
rx_frame = await tb.ch_sink[0].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.ch_source[0].send(resp_frame)
tb.log.info("receive UDP packet")
rx_frame = await tb.ch_sink[0].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 = "test_fpga_core"
verilog_sources = [
os.path.join(tests_dir, f"{toplevel}.v"),
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,
)

View File

@ -0,0 +1,104 @@
/*
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.
*/
// Language: Verilog 2001
`resetall
`timescale 1ns / 1ps
`default_nettype none
/*
* Testbench top-level module
*/
module test_fpga_core ();
genvar n;
wire clk;
wire rst;
// XGMII 10G PHY
parameter QUAD_CNT = 17;
parameter CH_CNT = QUAD_CNT*4;
wire [CH_CNT-1:0] eth_tx_clk;
wire [CH_CNT-1:0] eth_tx_rst;
wire [CH_CNT*64-1:0] eth_txd;
wire [CH_CNT*8-1:0] eth_txc;
wire [CH_CNT-1:0] eth_rx_clk;
wire [CH_CNT-1:0] eth_rx_rst;
wire [CH_CNT*64-1:0] eth_rxd;
wire [CH_CNT*8-1:0] eth_rxc;
generate
for (n = 0; n < CH_CNT; n = n + 1) begin : ch
wire ch_tx_clk;
wire ch_tx_rst;
wire [63:0] ch_txd;
wire [7:0] ch_txc;
wire ch_rx_clk;
wire ch_rx_rst;
wire [63:0] ch_rxd;
wire [7:0] ch_rxc;
assign eth_tx_clk[n +: 1] = ch_tx_clk;
assign eth_tx_rst[n +: 1] = ch_tx_rst;
assign ch_txd = eth_txd[n*64 +: 64];
assign ch_txc = eth_txc[n*8 +: 8];
assign eth_rx_clk[n +: 1] = ch_rx_clk;
assign eth_rx_rst[n +: 1] = ch_rx_rst;
assign eth_rxd[n*64 +: 64] = ch_rxd;
assign eth_rxc[n*8 +: 8] = ch_rxc;
end
endgenerate
fpga_core
core_inst (
/*
* Clock: 156.25 MHz
* Synchronous reset
*/
.clk(clk),
.rst(rst),
/*
* Ethernet: QSFP28
*/
.eth_tx_clk(eth_tx_clk),
.eth_tx_rst(eth_tx_rst),
.eth_txd(eth_txd),
.eth_txc(eth_txc),
.eth_rx_clk(eth_rx_clk),
.eth_rx_rst(eth_rx_rst),
.eth_rxd(eth_rxd),
.eth_rxc(eth_rxc)
);
endmodule
`resetall