Reorganize repository

Signed-off-by: Alex Forencich <alex@alexforencich.com>
This commit is contained in:
Alex Forencich
2025-05-18 12:25:59 -07:00
parent 8cdae180a1
commit 66b53d98a2
690 changed files with 2314 additions and 1581 deletions

View File

@@ -0,0 +1,35 @@
# Taxi Example Design for ZCU106
## Introduction
This example design targets the Xilinx ZCU106 FPGA board.
The design places looped-back MACs on the SFP+ ports, as well as XFCP on the USB UART for monitoring and control.
* USB UART
* XFCP (2 Mbaud)
* QSFP28
* Looped-back 10GBASE-R MACs via GTH transceivers
## Board details
* FPGA: xczu7ev-ffvc1156-2-e
* USB UART: Silicon Labs CP2108
* 10GBASE-R PHY: Soft PCS with GTH transceivers
## Licensing
* Toolchain
* Vivado Standard (enterprise license not required)
* IP
* No licensed vendor IP or 3rd party IP
## How to build
Run `make` in the appropriate `fpga*` subdirectory to build the bitstream. Ensure that the Xilinx Vivado toolchain components are in PATH.
## How to test
Run `make program` to program the board with Vivado.
To test the looped-back MAC, it is recommended to use a network tester like the Viavi T-BERD 5800 that supports basic layer 2 tests with a loopback. Do not connect the looped-back MAC to a network as the reflected packets may cause problems.

View File

@@ -0,0 +1,153 @@
# SPDX-License-Identifier: MIT
###################################################################
#
# Xilinx Vivado FPGA Makefile
#
# Copyright (c) 2016-2025 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 - list of source files
# INC_FILES - list of include files
# XDC_FILES - list of timing constraint files
# XCI_FILES - list of IP XCI files
# IP_TCL_FILES - list of IP TCL files (sourced during project creation)
# CONFIG_TCL_FILES - list of config TCL files (sourced before each build)
#
# Note: both SYN_FILES and INC_FILES support file list files. File list
# files are files with a .f extension that contain a list of additional
# files to include, one path relative to the .f file location per line.
# The .f files are processed recursively, and then the complete file list
# is de-duplicated, with later files in the list taking precedence.
#
# 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 %.bin %.ltx %.xsa %.mcs %.prm
.SECONDARY:
CONFIG ?= config.mk
-include $(CONFIG)
FPGA_TOP ?= fpga
PROJECT ?= $(FPGA_TOP)
XDC_FILES ?= $(PROJECT).xdc
# handle file list files
process_f_file = $(call process_f_files,$(addprefix $(dir $1),$(shell cat $1)))
process_f_files = $(foreach f,$1,$(if $(filter %.f,$f),$(call process_f_file,$f),$f))
uniq_base = $(if $1,$(call uniq_base,$(foreach f,$1,$(if $(filter-out $(notdir $(lastword $1)),$(notdir $f)),$f,))) $(lastword $1))
SYN_FILES := $(call uniq_base,$(call process_f_files,$(SYN_FILES)))
INC_FILES := $(call uniq_base,$(call process_f_files,$(INC_FILES)))
###################################################################
# Main Targets
#
# all: build everything (fpga)
# fpga: build FPGA config
# vivado: open project in Vivado
# tmpclean: remove intermediate files
# clean: remove output files and project files
# distclean: remove archived output 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 *.bin *.ltx *.xsa 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 fresh project if Makefile or IP files have changed
create_project.tcl: Makefile $(XCI_FILES) $(IP_TCL_FILES)
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)" >> $@
echo "set_property top $(FPGA_TOP) [current_fileset]" >> $@
echo "add_files -fileset constrs_1 $(XDC_FILES)" >> $@
for x in $(XCI_FILES); do echo "import_ip $$x" >> $@; done
for x in $(IP_TCL_FILES); do echo "source $$x" >> $@; done
for x in $(CONFIG_TCL_FILES); do echo "source $$x" >> $@; done
# source config TCL scripts if any source file has changed
update_config.tcl: $(CONFIG_TCL_FILES) $(SYN_FILES) $(INC_FILES) $(XDC_FILES)
echo "open_project -quiet $(PROJECT).xpr" > $@
for x in $(CONFIG_TCL_FILES); 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) $(INC_FILES) $(XDC_FILES) | $(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
# output files (including potentially bit, bin, ltx, and xsa)
$(PROJECT).bit $(PROJECT).bin $(PROJECT).ltx $(PROJECT).xsa: $(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 -bin_file $(PROJECT).runs/impl_1/$(PROJECT).bit" >> generate_bit.tcl
echo "write_debug_probes -force $(PROJECT).runs/impl_1/$(PROJECT).ltx" >> generate_bit.tcl
echo "write_hw_platform -fixed -force -include_bit $(PROJECT).xsa" >> generate_bit.tcl
vivado -nojournal -nolog -mode batch -source generate_bit.tcl
ln -f -s $(PROJECT).runs/impl_1/$(PROJECT).bit .
ln -f -s $(PROJECT).runs/impl_1/$(PROJECT).bin .
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; \
cp -pv $(PROJECT).runs/impl_1/$(PROJECT).bin rev/$(PROJECT)_rev$$COUNT.bin; \
if [ -e $(PROJECT).runs/impl_1/$(PROJECT).ltx ]; then cp -pv $(PROJECT).runs/impl_1/$(PROJECT).ltx rev/$(PROJECT)_rev$$COUNT.ltx; fi; \
if [ -e $(PROJECT).xsa ]; then cp -pv $(PROJECT).xsa rev/$(PROJECT)_rev$$COUNT.xsa; fi

View File

@@ -0,0 +1,465 @@
# SPDX-License-Identifier: MIT
#
# Copyright (c) 2025 FPGA Ninja, LLC
#
# Authors:
# - Alex Forencich
#
# XDC constraints for the Xilinx ZCU106 board
# part: xczu7ev-ffvc1156-2-e
# General configuration
set_property BITSTREAM.GENERAL.COMPRESS true [current_design]
# System clocks
# 125 MHz
set_property -dict {LOC H9 IOSTANDARD LVDS} [get_ports clk_125mhz_p]
set_property -dict {LOC G9 IOSTANDARD LVDS} [get_ports clk_125mhz_n]
create_clock -period 8.000 -name clk_125mhz [get_ports clk_125mhz_p]
# LEDs
set_property -dict {LOC AL11 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {led[0]}]
set_property -dict {LOC AL13 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {led[1]}]
set_property -dict {LOC AK13 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {led[2]}]
set_property -dict {LOC AE15 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {led[3]}]
set_property -dict {LOC AM8 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {led[4]}]
set_property -dict {LOC AM9 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {led[5]}]
set_property -dict {LOC AM10 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {led[6]}]
set_property -dict {LOC AM11 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {led[7]}]
set_false_path -to [get_ports {led[*]}]
set_output_delay 0 [get_ports {led[*]}]
# Reset button
set_property -dict {LOC G13 IOSTANDARD LVCMOS12} [get_ports reset]
set_false_path -from [get_ports {reset}]
set_input_delay 0 [get_ports {reset}]
# Push buttons
set_property -dict {LOC AG13 IOSTANDARD LVCMOS12} [get_ports btnu]
set_property -dict {LOC AK12 IOSTANDARD LVCMOS12} [get_ports btnl]
set_property -dict {LOC AP20 IOSTANDARD LVCMOS12} [get_ports btnd]
set_property -dict {LOC AC14 IOSTANDARD LVCMOS12} [get_ports btnr]
set_property -dict {LOC AL10 IOSTANDARD LVCMOS12} [get_ports btnc]
set_false_path -from [get_ports {btnu btnl btnd btnr btnc}]
set_input_delay 0 [get_ports {btnu btnl btnd btnr btnc}]
# DIP switches
set_property -dict {LOC A17 IOSTANDARD LVCMOS18} [get_ports {sw[0]}]
set_property -dict {LOC A16 IOSTANDARD LVCMOS18} [get_ports {sw[1]}]
set_property -dict {LOC B16 IOSTANDARD LVCMOS18} [get_ports {sw[2]}]
set_property -dict {LOC B15 IOSTANDARD LVCMOS18} [get_ports {sw[3]}]
set_property -dict {LOC A15 IOSTANDARD LVCMOS18} [get_ports {sw[4]}]
set_property -dict {LOC A14 IOSTANDARD LVCMOS18} [get_ports {sw[5]}]
set_property -dict {LOC B14 IOSTANDARD LVCMOS18} [get_ports {sw[6]}]
set_property -dict {LOC B13 IOSTANDARD LVCMOS18} [get_ports {sw[7]}]
set_false_path -from [get_ports {sw[*]}]
set_input_delay 0 [get_ports {sw[*]}]
# PMOD0
#set_property -dict {LOC B23 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports {pmod0[0]}] ;# J55.1
#set_property -dict {LOC A23 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports {pmod0[1]}] ;# J55.3
#set_property -dict {LOC F25 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports {pmod0[2]}] ;# J55.5
#set_property -dict {LOC E20 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports {pmod0[3]}] ;# J55.7
#set_property -dict {LOC K24 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports {pmod0[4]}] ;# J55.2
#set_property -dict {LOC L23 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports {pmod0[5]}] ;# J55.4
#set_property -dict {LOC L22 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports {pmod0[6]}] ;# J55.6
#set_property -dict {LOC D7 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports {pmod0[7]}] ;# J55.8
#set_false_path -to [get_ports {pmod0[*]}]
#set_output_delay 0 [get_ports {pmod0[*]}]
# PMOD1
#set_property -dict {LOC AN8 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports {pmod1[0]}] ;# J87.1
#set_property -dict {LOC AN9 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports {pmod1[1]}] ;# J87.3
#set_property -dict {LOC AP11 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports {pmod1[2]}] ;# J87.5
#set_property -dict {LOC AN11 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports {pmod1[3]}] ;# J87.7
#set_property -dict {LOC AP9 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports {pmod1[4]}] ;# J87.2
#set_property -dict {LOC AP10 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports {pmod1[5]}] ;# J87.4
#set_property -dict {LOC AP12 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports {pmod1[6]}] ;# J87.6
#set_property -dict {LOC AN12 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports {pmod1[7]}] ;# J87.8
#set_false_path -to [get_ports {pmod1[*]}]
#set_output_delay 0 [get_ports {pmod1[*]}]
# "Prototype header" GPIO
#set_property -dict {LOC K13 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports {proto_gpio[0]}] ;# J3.6
#set_property -dict {LOC L14 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports {proto_gpio[1]}] ;# J3.8
#set_property -dict {LOC J14 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports {proto_gpio[2]}] ;# J3.10
#set_property -dict {LOC K14 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports {proto_gpio[3]}] ;# J3.12
#set_property -dict {LOC J11 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports {proto_gpio[4]}] ;# J3.14
#set_property -dict {LOC K12 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports {proto_gpio[5]}] ;# J3.16
#set_property -dict {LOC L11 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports {proto_gpio[6]}] ;# J3.18
#set_property -dict {LOC L12 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports {proto_gpio[7]}] ;# J3.20
#set_property -dict {LOC G24 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports {proto_gpio[8]}] ;# J3.22
#set_property -dict {LOC G23 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports {proto_gpio[9]}] ;# J3.24
#set_false_path -to [get_ports {proto_gpio[*]}]
#set_output_delay 0 [get_ports {proto_gpio[*]}]
# UART (U40 CP2108 ch 2)
set_property -dict {LOC AL17 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports uart_txd] ;# U40.15 RX_2
set_property -dict {LOC AH17 IOSTANDARD LVCMOS12} [get_ports uart_rxd] ;# U40.16 TX_2
set_property -dict {LOC AM15 IOSTANDARD LVCMOS12} [get_ports uart_rts] ;# U40.14 RTS_2
set_property -dict {LOC AP17 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports uart_cts] ;# U40.13 CTS_2
set_false_path -to [get_ports {uart_txd uart_cts}]
set_output_delay 0 [get_ports {uart_txd uart_cts}]
set_false_path -from [get_ports {uart_rxd uart_rts}]
set_input_delay 0 [get_ports {uart_rxd uart_rts}]
# I2C interfaces
#set_property -dict {LOC AE19 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports i2c0_scl]
#set_property -dict {LOC AH23 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports i2c0_sda]
#set_property -dict {LOC AH19 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports i2c1_scl]
#set_property -dict {LOC AL21 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports i2c1_sda]
#set_false_path -to [get_ports {i2c1_sda i2c1_scl}]
#set_output_delay 0 [get_ports {i2c1_sda i2c1_scl}]
#set_false_path -from [get_ports {i2c1_sda i2c1_scl}]
#set_input_delay 0 [get_ports {i2c1_sda i2c1_scl}]
# SFP+ Interface
set_property -dict {LOC AA2 } [get_ports {sfp_rx_p[0]}] ;# MGTHRXP2_225 GTHE4_CHANNEL_X0Y10 / GTHE4_COMMON_X0Y2
set_property -dict {LOC AA1 } [get_ports {sfp_rx_n[0]}] ;# MGTHRXN2_225 GTHE4_CHANNEL_X0Y10 / GTHE4_COMMON_X0Y2
set_property -dict {LOC Y4 } [get_ports {sfp_tx_p[0]}] ;# MGTHTXP2_225 GTHE4_CHANNEL_X0Y10 / GTHE4_COMMON_X0Y2
set_property -dict {LOC Y3 } [get_ports {sfp_tx_n[0]}] ;# MGTHTXN2_225 GTHE4_CHANNEL_X0Y10 / GTHE4_COMMON_X0Y2
set_property -dict {LOC W2 } [get_ports {sfp_rx_p[1]}] ;# MGTHRXP3_225 GTHE4_CHANNEL_X0Y11 / GTHE4_COMMON_X0Y2
set_property -dict {LOC W1 } [get_ports {sfp_rx_n[1]}] ;# MGTHRXN3_225 GTHE4_CHANNEL_X0Y11 / GTHE4_COMMON_X0Y2
set_property -dict {LOC W6 } [get_ports {sfp_tx_p[1]}] ;# MGTHTXP3_225 GTHE4_CHANNEL_X0Y11 / GTHE4_COMMON_X0Y2
set_property -dict {LOC W5 } [get_ports {sfp_tx_n[1]}] ;# MGTHTXN3_225 GTHE4_CHANNEL_X0Y11 / GTHE4_COMMON_X0Y2
set_property -dict {LOC U10 } [get_ports {sfp_mgt_refclk_0_p}] ;# MGTREFCLK1P_226 from U56 SI570 via U51 SI53340
set_property -dict {LOC U9 } [get_ports {sfp_mgt_refclk_0_n}] ;# MGTREFCLK1N_226 from U56 SI570 via U51 SI53340
#set_property -dict {LOC W10 } [get_ports {sfp_mgt_refclk_1_p}] ;# MGTREFCLK1P_225 from U20 CKOUT2 SI5328
#set_property -dict {LOC W9 } [get_ports {sfp_mgt_refclk_1_n}] ;# MGTREFCLK1N_225 from U20 CKOUT2 SI5328
#set_property -dict {LOC H11 IOSTANDARD LVDS} [get_ports {sfp_recclk_p}] ;# to U20 CKIN1 SI5328
#set_property -dict {LOC G11 IOSTANDARD LVDS} [get_ports {sfp_recclk_n}] ;# to U20 CKIN1 SI5328
set_property -dict {LOC AE22 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {sfp_tx_disable_b[0]}]
set_property -dict {LOC AF20 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {sfp_tx_disable_b[1]}]
# 156.25 MHz MGT reference clock
create_clock -period 6.400 -name sfp_mgt_refclk_0 [get_ports {sfp_mgt_refclk_0_p}]
set_false_path -to [get_ports {sfp_tx_disable_b[*]}]
set_output_delay 0 [get_ports {sfp_tx_disable_b[*]}]
# PCIe Interface
#set_property -dict {LOC AE2 } [get_ports {pcie_rx_p[0]}] ;# MGTHRXP3_224 GTHE4_CHANNEL_X0Y7 / GTHE4_COMMON_X0Y1
#set_property -dict {LOC AE1 } [get_ports {pcie_rx_n[0]}] ;# MGTHRXN3_224 GTHE4_CHANNEL_X0Y7 / GTHE4_COMMON_X0Y1
#set_property -dict {LOC AD4 } [get_ports {pcie_tx_p[0]}] ;# MGTHTXP3_224 GTHE4_CHANNEL_X0Y7 / GTHE4_COMMON_X0Y1
#set_property -dict {LOC AD3 } [get_ports {pcie_tx_n[0]}] ;# MGTHTXN3_224 GTHE4_CHANNEL_X0Y7 / GTHE4_COMMON_X0Y1
#set_property -dict {LOC AF4 } [get_ports {pcie_rx_p[1]}] ;# MGTHRXP2_224 GTHE4_CHANNEL_X0Y6 / GTHE4_COMMON_X0Y1
#set_property -dict {LOC AF3 } [get_ports {pcie_rx_n[1]}] ;# MGTHRXN2_224 GTHE4_CHANNEL_X0Y6 / GTHE4_COMMON_X0Y1
#set_property -dict {LOC AE6 } [get_ports {pcie_tx_p[1]}] ;# MGTHTXP2_224 GTHE4_CHANNEL_X0Y6 / GTHE4_COMMON_X0Y1
#set_property -dict {LOC AE5 } [get_ports {pcie_tx_n[1]}] ;# MGTHTXN2_224 GTHE4_CHANNEL_X0Y6 / GTHE4_COMMON_X0Y1
#set_property -dict {LOC AG2 } [get_ports {pcie_rx_p[2]}] ;# MGTHRXP1_224 GTHE4_CHANNEL_X0Y5 / GTHE4_COMMON_X0Y1
#set_property -dict {LOC AG1 } [get_ports {pcie_rx_n[2]}] ;# MGTHRXN1_224 GTHE4_CHANNEL_X0Y5 / GTHE4_COMMON_X0Y1
#set_property -dict {LOC AG6 } [get_ports {pcie_tx_p[2]}] ;# MGTHTXP1_224 GTHE4_CHANNEL_X0Y5 / GTHE4_COMMON_X0Y1
#set_property -dict {LOC AG5 } [get_ports {pcie_tx_n[2]}] ;# MGTHTXN1_224 GTHE4_CHANNEL_X0Y5 / GTHE4_COMMON_X0Y1
#set_property -dict {LOC AJ2 } [get_ports {pcie_rx_p[3]}] ;# MGTHRXP0_224 GTHE4_CHANNEL_X0Y4 / GTHE4_COMMON_X0Y1
#set_property -dict {LOC AJ1 } [get_ports {pcie_rx_n[3]}] ;# MGTHRXN0_224 GTHE4_CHANNEL_X0Y4 / GTHE4_COMMON_X0Y1
#set_property -dict {LOC AH4 } [get_ports {pcie_tx_p[3]}] ;# MGTHTXP0_224 GTHE4_CHANNEL_X0Y4 / GTHE4_COMMON_X0Y1
#set_property -dict {LOC AH3 } [get_ports {pcie_tx_n[3]}] ;# MGTHTXN0_224 GTHE4_CHANNEL_X0Y4 / GTHE4_COMMON_X0Y1
#set_property -dict {LOC AB8 } [get_ports pcie_mgt_refclk_p] ;# MGTREFCLK0P_224
#set_property -dict {LOC AB7 } [get_ports pcie_mgt_refclk_n] ;# MGTREFCLK0N_224
#set_property -dict {LOC L8 IOSTANDARD LVCMOS33 PULLUP true} [get_ports pcie_reset_n]
# 100 MHz MGT reference clock
#create_clock -period 10 -name pcie_mgt_refclk [get_ports pcie_mgt_refclk_p]
#set_false_path -from [get_ports {pcie_reset_n}]
#set_input_delay 0 [get_ports {pcie_reset_n}]
# FMC interface
# FMC HPC0 J5
#set_property -dict {LOC F17 IOSTANDARD LVDS DIFF_TERM_ADV TERM_100} [get_ports {fmc_hpc0_la_p[0]}] ;# J5.G9 LA00_P_CC
#set_property -dict {LOC F16 IOSTANDARD LVDS DIFF_TERM_ADV TERM_100} [get_ports {fmc_hpc0_la_n[0]}] ;# J5.G10 LA00_N_CC
#set_property -dict {LOC H18 IOSTANDARD LVDS DIFF_TERM_ADV TERM_100} [get_ports {fmc_hpc0_la_p[1]}] ;# J5.D8 LA01_P_CC
#set_property -dict {LOC H17 IOSTANDARD LVDS DIFF_TERM_ADV TERM_100} [get_ports {fmc_hpc0_la_n[1]}] ;# J5.D9 LA01_N_CC
#set_property -dict {LOC L20 IOSTANDARD LVDS DIFF_TERM_ADV TERM_100} [get_ports {fmc_hpc0_la_p[2]}] ;# J5.H7 LA02_P
#set_property -dict {LOC K20 IOSTANDARD LVDS DIFF_TERM_ADV TERM_100} [get_ports {fmc_hpc0_la_n[2]}] ;# J5.H8 LA02_N
#set_property -dict {LOC K19 IOSTANDARD LVDS DIFF_TERM_ADV TERM_100} [get_ports {fmc_hpc0_la_p[3]}] ;# J5.G12 LA03_P
#set_property -dict {LOC K18 IOSTANDARD LVDS DIFF_TERM_ADV TERM_100} [get_ports {fmc_hpc0_la_n[3]}] ;# J5.G13 LA03_N
#set_property -dict {LOC L17 IOSTANDARD LVDS DIFF_TERM_ADV TERM_100} [get_ports {fmc_hpc0_la_p[4]}] ;# J5.H10 LA04_P
#set_property -dict {LOC L16 IOSTANDARD LVDS DIFF_TERM_ADV TERM_100} [get_ports {fmc_hpc0_la_n[4]}] ;# J5.H11 LA04_N
#set_property -dict {LOC K17 IOSTANDARD LVDS DIFF_TERM_ADV TERM_100} [get_ports {fmc_hpc0_la_p[5]}] ;# J5.D11 LA05_P
#set_property -dict {LOC J17 IOSTANDARD LVDS DIFF_TERM_ADV TERM_100} [get_ports {fmc_hpc0_la_n[5]}] ;# J5.D12 LA05_N
#set_property -dict {LOC H19 IOSTANDARD LVDS DIFF_TERM_ADV TERM_100} [get_ports {fmc_hpc0_la_p[6]}] ;# J5.C10 LA06_P
#set_property -dict {LOC G19 IOSTANDARD LVDS DIFF_TERM_ADV TERM_100} [get_ports {fmc_hpc0_la_n[6]}] ;# J5.C11 LA06_N
#set_property -dict {LOC J16 IOSTANDARD LVDS DIFF_TERM_ADV TERM_100} [get_ports {fmc_hpc0_la_p[7]}] ;# J5.H13 LA07_P
#set_property -dict {LOC J15 IOSTANDARD LVDS DIFF_TERM_ADV TERM_100} [get_ports {fmc_hpc0_la_n[7]}] ;# J5.H14 LA07_N
#set_property -dict {LOC E18 IOSTANDARD LVDS DIFF_TERM_ADV TERM_100} [get_ports {fmc_hpc0_la_p[8]}] ;# J5.G12 LA08_P
#set_property -dict {LOC E17 IOSTANDARD LVDS DIFF_TERM_ADV TERM_100} [get_ports {fmc_hpc0_la_n[8]}] ;# J5.G13 LA08_N
#set_property -dict {LOC H16 IOSTANDARD LVDS DIFF_TERM_ADV TERM_100} [get_ports {fmc_hpc0_la_p[9]}] ;# J5.D14 LA09_P
#set_property -dict {LOC G16 IOSTANDARD LVDS DIFF_TERM_ADV TERM_100} [get_ports {fmc_hpc0_la_n[9]}] ;# J5.D15 LA09_N
#set_property -dict {LOC L15 IOSTANDARD LVDS DIFF_TERM_ADV TERM_100} [get_ports {fmc_hpc0_la_p[10]}] ;# J5.C14 LA10_P
#set_property -dict {LOC K15 IOSTANDARD LVDS DIFF_TERM_ADV TERM_100} [get_ports {fmc_hpc0_la_n[10]}] ;# J5.C15 LA10_N
#set_property -dict {LOC A13 IOSTANDARD LVDS DIFF_TERM_ADV TERM_100} [get_ports {fmc_hpc0_la_p[11]}] ;# J5.H16 LA11_P
#set_property -dict {LOC A12 IOSTANDARD LVDS DIFF_TERM_ADV TERM_100} [get_ports {fmc_hpc0_la_n[11]}] ;# J5.H17 LA11_N
#set_property -dict {LOC G18 IOSTANDARD LVDS DIFF_TERM_ADV TERM_100} [get_ports {fmc_hpc0_la_p[12]}] ;# J5.G15 LA12_P
#set_property -dict {LOC F18 IOSTANDARD LVDS DIFF_TERM_ADV TERM_100} [get_ports {fmc_hpc0_la_n[12]}] ;# J5.G16 LA12_N
#set_property -dict {LOC G15 IOSTANDARD LVDS DIFF_TERM_ADV TERM_100} [get_ports {fmc_hpc0_la_p[13]}] ;# J5.D17 LA13_P
#set_property -dict {LOC F15 IOSTANDARD LVDS DIFF_TERM_ADV TERM_100} [get_ports {fmc_hpc0_la_n[13]}] ;# J5.D18 LA13_N
#set_property -dict {LOC C13 IOSTANDARD LVDS DIFF_TERM_ADV TERM_100} [get_ports {fmc_hpc0_la_p[14]}] ;# J5.C18 LA14_P
#set_property -dict {LOC C12 IOSTANDARD LVDS DIFF_TERM_ADV TERM_100} [get_ports {fmc_hpc0_la_n[14]}] ;# J5.C19 LA14_N
#set_property -dict {LOC D16 IOSTANDARD LVDS DIFF_TERM_ADV TERM_100} [get_ports {fmc_hpc0_la_p[15]}] ;# J5.H19 LA15_P
#set_property -dict {LOC C16 IOSTANDARD LVDS DIFF_TERM_ADV TERM_100} [get_ports {fmc_hpc0_la_n[15]}] ;# J5.H20 LA15_N
#set_property -dict {LOC D17 IOSTANDARD LVDS DIFF_TERM_ADV TERM_100} [get_ports {fmc_hpc0_la_p[16]}] ;# J5.G18 LA16_P
#set_property -dict {LOC C17 IOSTANDARD LVDS DIFF_TERM_ADV TERM_100} [get_ports {fmc_hpc0_la_n[16]}] ;# J5.G19 LA16_N
#set_property -dict {LOC F11 IOSTANDARD LVDS DIFF_TERM_ADV TERM_100} [get_ports {fmc_hpc0_la_p[17]}] ;# J5.D20 LA17_P_CC
#set_property -dict {LOC E10 IOSTANDARD LVDS DIFF_TERM_ADV TERM_100} [get_ports {fmc_hpc0_la_n[17]}] ;# J5.D21 LA17_N_CC
#set_property -dict {LOC D11 IOSTANDARD LVDS DIFF_TERM_ADV TERM_100} [get_ports {fmc_hpc0_la_p[18]}] ;# J5.C22 LA18_P_CC
#set_property -dict {LOC D10 IOSTANDARD LVDS DIFF_TERM_ADV TERM_100} [get_ports {fmc_hpc0_la_n[18]}] ;# J5.C23 LA18_N_CC
#set_property -dict {LOC D12 IOSTANDARD LVDS DIFF_TERM_ADV TERM_100} [get_ports {fmc_hpc0_la_p[19]}] ;# J5.H22 LA19_P
#set_property -dict {LOC C11 IOSTANDARD LVDS DIFF_TERM_ADV TERM_100} [get_ports {fmc_hpc0_la_n[19]}] ;# J5.H23 LA19_N
#set_property -dict {LOC F12 IOSTANDARD LVDS DIFF_TERM_ADV TERM_100} [get_ports {fmc_hpc0_la_p[20]}] ;# J5.G21 LA20_P
#set_property -dict {LOC E12 IOSTANDARD LVDS DIFF_TERM_ADV TERM_100} [get_ports {fmc_hpc0_la_n[20]}] ;# J5.G22 LA20_N
#set_property -dict {LOC B10 IOSTANDARD LVDS DIFF_TERM_ADV TERM_100} [get_ports {fmc_hpc0_la_p[21]}] ;# J5.H25 LA21_P
#set_property -dict {LOC A10 IOSTANDARD LVDS DIFF_TERM_ADV TERM_100} [get_ports {fmc_hpc0_la_n[21]}] ;# J5.H26 LA21_N
#set_property -dict {LOC H13 IOSTANDARD LVDS DIFF_TERM_ADV TERM_100} [get_ports {fmc_hpc0_la_p[22]}] ;# J5.G24 LA22_P
#set_property -dict {LOC H12 IOSTANDARD LVDS DIFF_TERM_ADV TERM_100} [get_ports {fmc_hpc0_la_n[22]}] ;# J5.G25 LA22_N
#set_property -dict {LOC B11 IOSTANDARD LVDS DIFF_TERM_ADV TERM_100} [get_ports {fmc_hpc0_la_p[23]}] ;# J5.D23 LA23_P
#set_property -dict {LOC A11 IOSTANDARD LVDS DIFF_TERM_ADV TERM_100} [get_ports {fmc_hpc0_la_n[23]}] ;# J5.D24 LA23_N
#set_property -dict {LOC B6 IOSTANDARD LVDS DIFF_TERM_ADV TERM_100} [get_ports {fmc_hpc0_la_p[24]}] ;# J5.H28 LA24_P
#set_property -dict {LOC A6 IOSTANDARD LVDS DIFF_TERM_ADV TERM_100} [get_ports {fmc_hpc0_la_n[24]}] ;# J5.H29 LA24_N
#set_property -dict {LOC C7 IOSTANDARD LVDS DIFF_TERM_ADV TERM_100} [get_ports {fmc_hpc0_la_p[25]}] ;# J5.G27 LA25_P
#set_property -dict {LOC C6 IOSTANDARD LVDS DIFF_TERM_ADV TERM_100} [get_ports {fmc_hpc0_la_n[25]}] ;# J5.G28 LA25_N
#set_property -dict {LOC B9 IOSTANDARD LVDS DIFF_TERM_ADV TERM_100} [get_ports {fmc_hpc0_la_p[26]}] ;# J5.D26 LA26_P
#set_property -dict {LOC B8 IOSTANDARD LVDS DIFF_TERM_ADV TERM_100} [get_ports {fmc_hpc0_la_n[26]}] ;# J5.D27 LA26_N
#set_property -dict {LOC A8 IOSTANDARD LVDS DIFF_TERM_ADV TERM_100} [get_ports {fmc_hpc0_la_p[27]}] ;# J5.C26 LA27_P
#set_property -dict {LOC A7 IOSTANDARD LVDS DIFF_TERM_ADV TERM_100} [get_ports {fmc_hpc0_la_n[27]}] ;# J5.C27 LA27_N
#set_property -dict {LOC M13 IOSTANDARD LVDS DIFF_TERM_ADV TERM_100} [get_ports {fmc_hpc0_la_p[28]}] ;# J5.H31 LA28_P
#set_property -dict {LOC L13 IOSTANDARD LVDS DIFF_TERM_ADV TERM_100} [get_ports {fmc_hpc0_la_n[28]}] ;# J5.H32 LA28_N
#set_property -dict {LOC K10 IOSTANDARD LVDS DIFF_TERM_ADV TERM_100} [get_ports {fmc_hpc0_la_p[29]}] ;# J5.G30 LA29_P
#set_property -dict {LOC J10 IOSTANDARD LVDS DIFF_TERM_ADV TERM_100} [get_ports {fmc_hpc0_la_n[29]}] ;# J5.G31 LA29_N
#set_property -dict {LOC E9 IOSTANDARD LVDS DIFF_TERM_ADV TERM_100} [get_ports {fmc_hpc0_la_p[30]}] ;# J5.H34 LA30_P
#set_property -dict {LOC D9 IOSTANDARD LVDS DIFF_TERM_ADV TERM_100} [get_ports {fmc_hpc0_la_n[30]}] ;# J5.H35 LA30_N
#set_property -dict {LOC F7 IOSTANDARD LVDS DIFF_TERM_ADV TERM_100} [get_ports {fmc_hpc0_la_p[31]}] ;# J5.G33 LA31_P
#set_property -dict {LOC E7 IOSTANDARD LVDS DIFF_TERM_ADV TERM_100} [get_ports {fmc_hpc0_la_n[31]}] ;# J5.G34 LA31_N
#set_property -dict {LOC F8 IOSTANDARD LVDS DIFF_TERM_ADV TERM_100} [get_ports {fmc_hpc0_la_p[32]}] ;# J5.H37 LA32_P
#set_property -dict {LOC E8 IOSTANDARD LVDS DIFF_TERM_ADV TERM_100} [get_ports {fmc_hpc0_la_n[32]}] ;# J5.H38 LA32_N
#set_property -dict {LOC C9 IOSTANDARD LVDS DIFF_TERM_ADV TERM_100} [get_ports {fmc_hpc0_la_p[33]}] ;# J5.G36 LA33_P
#set_property -dict {LOC C8 IOSTANDARD LVDS DIFF_TERM_ADV TERM_100} [get_ports {fmc_hpc0_la_n[33]}] ;# J5.G37 LA33_N
#set_property -dict {LOC E15 IOSTANDARD LVDS DIFF_TERM_ADV TERM_100} [get_ports {fmc_hpc0_clk0_m2c_p}] ;# J5.H4 CLK0_M2C_P
#set_property -dict {LOC E14 IOSTANDARD LVDS DIFF_TERM_ADV TERM_100} [get_ports {fmc_hpc0_clk0_m2c_n}] ;# J5.H5 CLK0_M2C_N
#set_property -dict {LOC G10 IOSTANDARD LVDS DIFF_TERM_ADV TERM_100} [get_ports {fmc_hpc0_clk1_m2c_p}] ;# J5.G2 CLK1_M2C_P
#set_property -dict {LOC F10 IOSTANDARD LVDS DIFF_TERM_ADV TERM_100} [get_ports {fmc_hpc0_clk1_m2c_n}] ;# J5.G3 CLK1_M2C_N
#set_property -dict {LOC R6 } [get_ports {fmc_hpc0_dp_c2m_p[0]}] ;# MGTHTXP2_226 GTHE4_CHANNEL_X0Y14 / GTHE4_COMMON_X0Y3 from J5.C2 DP0_C2M_P
#set_property -dict {LOC R5 } [get_ports {fmc_hpc0_dp_c2m_n[0]}] ;# MGTHTXN2_226 GTHE4_CHANNEL_X0Y14 / GTHE4_COMMON_X0Y3 from J5.C3 DP0_C2M_N
#set_property -dict {LOC R2 } [get_ports {fmc_hpc0_dp_m2c_p[0]}] ;# MGTHRXP2_226 GTHE4_CHANNEL_X0Y14 / GTHE4_COMMON_X0Y3 from J5.C6 DP0_M2C_P
#set_property -dict {LOC R1 } [get_ports {fmc_hpc0_dp_m2c_n[0]}] ;# MGTHRXN2_226 GTHE4_CHANNEL_X0Y14 / GTHE4_COMMON_X0Y3 from J5.C7 DP0_M2C_N
#set_property -dict {LOC T4 } [get_ports {fmc_hpc0_dp_c2m_p[1]}] ;# MGTHTXP1_226 GTHE4_CHANNEL_X0Y13 / GTHE4_COMMON_X0Y3 from J5.A22 DP1_C2M_P
#set_property -dict {LOC T3 } [get_ports {fmc_hpc0_dp_c2m_n[1]}] ;# MGTHTXN1_226 GTHE4_CHANNEL_X0Y13 / GTHE4_COMMON_X0Y3 from J5.A23 DP1_C2M_N
#set_property -dict {LOC U2 } [get_ports {fmc_hpc0_dp_m2c_p[1]}] ;# MGTHRXP1_226 GTHE4_CHANNEL_X0Y13 / GTHE4_COMMON_X0Y3 from J5.A2 DP1_M2C_P
#set_property -dict {LOC U1 } [get_ports {fmc_hpc0_dp_m2c_n[1]}] ;# MGTHRXN1_226 GTHE4_CHANNEL_X0Y13 / GTHE4_COMMON_X0Y3 from J5.A3 DP1_M2C_N
#set_property -dict {LOC N6 } [get_ports {fmc_hpc0_dp_c2m_p[2]}] ;# MGTHTXP3_226 GTHE4_CHANNEL_X0Y15 / GTHE4_COMMON_X0Y3 from J5.A26 DP2_C2M_P
#set_property -dict {LOC N5 } [get_ports {fmc_hpc0_dp_c2m_n[2]}] ;# MGTHTXN3_226 GTHE4_CHANNEL_X0Y15 / GTHE4_COMMON_X0Y3 from J5.A27 DP2_C2M_N
#set_property -dict {LOC P4 } [get_ports {fmc_hpc0_dp_m2c_p[2]}] ;# MGTHRXP3_226 GTHE4_CHANNEL_X0Y15 / GTHE4_COMMON_X0Y3 from J5.A6 DP2_M2C_P
#set_property -dict {LOC P3 } [get_ports {fmc_hpc0_dp_m2c_n[2]}] ;# MGTHRXN3_226 GTHE4_CHANNEL_X0Y15 / GTHE4_COMMON_X0Y3 from J5.A7 DP2_M2C_N
#set_property -dict {LOC U6 } [get_ports {fmc_hpc0_dp_c2m_p[3]}] ;# MGTHTXP0_226 GTHE4_CHANNEL_X0Y12 / GTHE4_COMMON_X0Y3 from J5.A30 DP3_C2M_P
#set_property -dict {LOC U5 } [get_ports {fmc_hpc0_dp_c2m_n[3]}] ;# MGTHTXN0_226 GTHE4_CHANNEL_X0Y12 / GTHE4_COMMON_X0Y3 from J5.A31 DP3_C2M_N
#set_property -dict {LOC V4 } [get_ports {fmc_hpc0_dp_m2c_p[3]}] ;# MGTHRXP0_226 GTHE4_CHANNEL_X0Y12 / GTHE4_COMMON_X0Y3 from J5.A10 DP3_M2C_P
#set_property -dict {LOC V3 } [get_ports {fmc_hpc0_dp_m2c_n[3]}] ;# MGTHRXN0_226 GTHE4_CHANNEL_X0Y12 / GTHE4_COMMON_X0Y3 from J5.A11 DP3_M2C_N
#set_property -dict {LOC H4 } [get_ports {fmc_hpc0_dp_c2m_p[4]}] ;# MGTHTXP3_227 GTHE4_CHANNEL_X0Y19 / GTHE4_COMMON_X0Y4 from J5.A34 DP4_C2M_P
#set_property -dict {LOC H3 } [get_ports {fmc_hpc0_dp_c2m_n[4]}] ;# MGTHTXN3_227 GTHE4_CHANNEL_X0Y19 / GTHE4_COMMON_X0Y4 from J5.A35 DP4_C2M_N
#set_property -dict {LOC G2 } [get_ports {fmc_hpc0_dp_m2c_p[4]}] ;# MGTHRXP3_227 GTHE4_CHANNEL_X0Y19 / GTHE4_COMMON_X0Y4 from J5.A14 DP4_M2C_P
#set_property -dict {LOC G1 } [get_ports {fmc_hpc0_dp_m2c_n[4]}] ;# MGTHRXN3_227 GTHE4_CHANNEL_X0Y19 / GTHE4_COMMON_X0Y4 from J5.A15 DP4_M2C_N
#set_property -dict {LOC L6 } [get_ports {fmc_hpc0_dp_c2m_p[5]}] ;# MGTHTXP1_227 GTHE4_CHANNEL_X0Y17 / GTHE4_COMMON_X0Y4 from J5.A38 DP5_C2M_P
#set_property -dict {LOC L5 } [get_ports {fmc_hpc0_dp_c2m_n[5]}] ;# MGTHTXN1_227 GTHE4_CHANNEL_X0Y17 / GTHE4_COMMON_X0Y4 from J5.A39 DP5_C2M_N
#set_property -dict {LOC L2 } [get_ports {fmc_hpc0_dp_m2c_p[5]}] ;# MGTHRXP1_227 GTHE4_CHANNEL_X0Y17 / GTHE4_COMMON_X0Y4 from J5.A18 DP5_M2C_P
#set_property -dict {LOC L1 } [get_ports {fmc_hpc0_dp_m2c_n[5]}] ;# MGTHRXN1_227 GTHE4_CHANNEL_X0Y17 / GTHE4_COMMON_X0Y4 from J5.A19 DP5_M2C_N
#set_property -dict {LOC M4 } [get_ports {fmc_hpc0_dp_c2m_p[6]}] ;# MGTHTXP0_227 GTHE4_CHANNEL_X0Y16 / GTHE4_COMMON_X0Y4 from J5.B36 DP6_C2M_P
#set_property -dict {LOC M3 } [get_ports {fmc_hpc0_dp_c2m_n[6]}] ;# MGTHTXN0_227 GTHE4_CHANNEL_X0Y16 / GTHE4_COMMON_X0Y4 from J5.B37 DP6_C2M_N
#set_property -dict {LOC N2 } [get_ports {fmc_hpc0_dp_m2c_p[6]}] ;# MGTHRXP0_227 GTHE4_CHANNEL_X0Y16 / GTHE4_COMMON_X0Y4 from J5.B16 DP6_M2C_P
#set_property -dict {LOC N1 } [get_ports {fmc_hpc0_dp_m2c_n[6]}] ;# MGTHRXN0_227 GTHE4_CHANNEL_X0Y16 / GTHE4_COMMON_X0Y4 from J5.B17 DP6_M2C_N
#set_property -dict {LOC K4 } [get_ports {fmc_hpc0_dp_c2m_p[7]}] ;# MGTHTXP2_227 GTHE4_CHANNEL_X0Y18 / GTHE4_COMMON_X0Y4 from J5.B32 DP7_C2M_P
#set_property -dict {LOC K3 } [get_ports {fmc_hpc0_dp_c2m_n[7]}] ;# MGTHTXN2_227 GTHE4_CHANNEL_X0Y18 / GTHE4_COMMON_X0Y4 from J5.B33 DP7_C2M_N
#set_property -dict {LOC J2 } [get_ports {fmc_hpc0_dp_m2c_p[7]}] ;# MGTHRXP2_227 GTHE4_CHANNEL_X0Y18 / GTHE4_COMMON_X0Y4 from J5.B12 DP7_M2C_P
#set_property -dict {LOC J1 } [get_ports {fmc_hpc0_dp_m2c_n[7]}] ;# MGTHRXN2_227 GTHE4_CHANNEL_X0Y18 / GTHE4_COMMON_X0Y4 from J5.B13 DP7_M2C_N
#set_property -dict {LOC V8 } [get_ports {fmc_hpc0_mgt_refclk_0_p}] ;# MGTREFCLK0P_226 from J5.D4 GBTCLK0_M2C_P
#set_property -dict {LOC V7 } [get_ports {fmc_hpc0_mgt_refclk_0_n}] ;# MGTREFCLK0N_226 from J5.D5 GBTCLK0_M2C_N
#set_property -dict {LOC T8 } [get_ports {fmc_hpc0_mgt_refclk_1_p}] ;# MGTREFCLK0P_227 from J5.B20 GBTCLK1_M2C_P
#set_property -dict {LOC T7 } [get_ports {fmc_hpc0_mgt_refclk_1_n}] ;# MGTREFCLK0N_227 from J5.B21 GBTCLK1_M2C_N
# reference clock
#create_clock -period 6.400 -name fmc_hpc0_mgt_refclk_0 [get_ports {fmc_hpc0_mgt_refclk_0_p}]
#create_clock -period 6.400 -name fmc_hpc0_mgt_refclk_1 [get_ports {fmc_hpc0_mgt_refclk_1_p}]
# FMC HPC1 J4
#set_property -dict {LOC B18 IOSTANDARD LVDS DIFF_TERM_ADV TERM_100} [get_ports {fmc_hpc1_la_p[0]}] ;# J4.G9 LA00_P_CC
#set_property -dict {LOC B19 IOSTANDARD LVDS DIFF_TERM_ADV TERM_100} [get_ports {fmc_hpc1_la_n[0]}] ;# J4.G10 LA00_N_CC
#set_property -dict {LOC E24 IOSTANDARD LVDS DIFF_TERM_ADV TERM_100} [get_ports {fmc_hpc1_la_p[1]}] ;# J4.D8 LA01_P_CC
#set_property -dict {LOC D24 IOSTANDARD LVDS DIFF_TERM_ADV TERM_100} [get_ports {fmc_hpc1_la_n[1]}] ;# J4.D9 LA01_N_CC
#set_property -dict {LOC K22 IOSTANDARD LVDS DIFF_TERM_ADV TERM_100} [get_ports {fmc_hpc1_la_p[2]}] ;# J4.H7 LA02_P
#set_property -dict {LOC K23 IOSTANDARD LVDS DIFF_TERM_ADV TERM_100} [get_ports {fmc_hpc1_la_n[2]}] ;# J4.H8 LA02_N
#set_property -dict {LOC J21 IOSTANDARD LVDS DIFF_TERM_ADV TERM_100} [get_ports {fmc_hpc1_la_p[3]}] ;# J4.G12 LA03_P
#set_property -dict {LOC J22 IOSTANDARD LVDS DIFF_TERM_ADV TERM_100} [get_ports {fmc_hpc1_la_n[3]}] ;# J4.G13 LA03_N
#set_property -dict {LOC J24 IOSTANDARD LVDS DIFF_TERM_ADV TERM_100} [get_ports {fmc_hpc1_la_p[4]}] ;# J4.H10 LA04_P
#set_property -dict {LOC H24 IOSTANDARD LVDS DIFF_TERM_ADV TERM_100} [get_ports {fmc_hpc1_la_n[4]}] ;# J4.H11 LA04_N
#set_property -dict {LOC G25 IOSTANDARD LVDS DIFF_TERM_ADV TERM_100} [get_ports {fmc_hpc1_la_p[5]}] ;# J4.D11 LA05_P
#set_property -dict {LOC G26 IOSTANDARD LVDS DIFF_TERM_ADV TERM_100} [get_ports {fmc_hpc1_la_n[5]}] ;# J4.D12 LA05_N
#set_property -dict {LOC H21 IOSTANDARD LVDS DIFF_TERM_ADV TERM_100} [get_ports {fmc_hpc1_la_p[6]}] ;# J4.C10 LA06_P
#set_property -dict {LOC H22 IOSTANDARD LVDS DIFF_TERM_ADV TERM_100} [get_ports {fmc_hpc1_la_n[6]}] ;# J4.C11 LA06_N
#set_property -dict {LOC D22 IOSTANDARD LVDS DIFF_TERM_ADV TERM_100} [get_ports {fmc_hpc1_la_p[7]}] ;# J4.H13 LA07_P
#set_property -dict {LOC C23 IOSTANDARD LVDS DIFF_TERM_ADV TERM_100} [get_ports {fmc_hpc1_la_n[7]}] ;# J4.H14 LA07_N
#set_property -dict {LOC J25 IOSTANDARD LVDS DIFF_TERM_ADV TERM_100} [get_ports {fmc_hpc1_la_p[8]}] ;# J4.G12 LA08_P
#set_property -dict {LOC H26 IOSTANDARD LVDS DIFF_TERM_ADV TERM_100} [get_ports {fmc_hpc1_la_n[8]}] ;# J4.G13 LA08_N
#set_property -dict {LOC G20 IOSTANDARD LVDS DIFF_TERM_ADV TERM_100} [get_ports {fmc_hpc1_la_p[9]}] ;# J4.D14 LA09_P
#set_property -dict {LOC F20 IOSTANDARD LVDS DIFF_TERM_ADV TERM_100} [get_ports {fmc_hpc1_la_n[9]}] ;# J4.D15 LA09_N
#set_property -dict {LOC F22 IOSTANDARD LVDS DIFF_TERM_ADV TERM_100} [get_ports {fmc_hpc1_la_p[10]}] ;# J4.C14 LA10_P
#set_property -dict {LOC E22 IOSTANDARD LVDS DIFF_TERM_ADV TERM_100} [get_ports {fmc_hpc1_la_n[10]}] ;# J4.C15 LA10_N
#set_property -dict {LOC A20 IOSTANDARD LVDS DIFF_TERM_ADV TERM_100} [get_ports {fmc_hpc1_la_p[11]}] ;# J4.H16 LA11_P
#set_property -dict {LOC A21 IOSTANDARD LVDS DIFF_TERM_ADV TERM_100} [get_ports {fmc_hpc1_la_n[11]}] ;# J4.H17 LA11_N
#set_property -dict {LOC E19 IOSTANDARD LVDS DIFF_TERM_ADV TERM_100} [get_ports {fmc_hpc1_la_p[12]}] ;# J4.G15 LA12_P
#set_property -dict {LOC D19 IOSTANDARD LVDS DIFF_TERM_ADV TERM_100} [get_ports {fmc_hpc1_la_n[12]}] ;# J4.G16 LA12_N
#set_property -dict {LOC C21 IOSTANDARD LVDS DIFF_TERM_ADV TERM_100} [get_ports {fmc_hpc1_la_p[13]}] ;# J4.D17 LA13_P
#set_property -dict {LOC C22 IOSTANDARD LVDS DIFF_TERM_ADV TERM_100} [get_ports {fmc_hpc1_la_n[13]}] ;# J4.D18 LA13_N
#set_property -dict {LOC D20 IOSTANDARD LVDS DIFF_TERM_ADV TERM_100} [get_ports {fmc_hpc1_la_p[14]}] ;# J4.C18 LA14_P
#set_property -dict {LOC D21 IOSTANDARD LVDS DIFF_TERM_ADV TERM_100} [get_ports {fmc_hpc1_la_n[14]}] ;# J4.C19 LA14_N
#set_property -dict {LOC A18 IOSTANDARD LVDS DIFF_TERM_ADV TERM_100} [get_ports {fmc_hpc1_la_p[15]}] ;# J4.H19 LA15_P
#set_property -dict {LOC A19 IOSTANDARD LVDS DIFF_TERM_ADV TERM_100} [get_ports {fmc_hpc1_la_n[15]}] ;# J4.H20 LA15_N
#set_property -dict {LOC C18 IOSTANDARD LVDS DIFF_TERM_ADV TERM_100} [get_ports {fmc_hpc1_la_p[16]}] ;# J4.G18 LA16_P
#set_property -dict {LOC C19 IOSTANDARD LVDS DIFF_TERM_ADV TERM_100} [get_ports {fmc_hpc1_la_n[16]}] ;# J4.G19 LA16_N
#set_property -dict {LOC F23 IOSTANDARD LVDS DIFF_TERM_ADV TERM_100} [get_ports {fmc_hpc1_clk0_m2c_p}] ;# J4.H4 CLK0_M2C_P
#set_property -dict {LOC E23 IOSTANDARD LVDS DIFF_TERM_ADV TERM_100} [get_ports {fmc_hpc1_clk0_m2c_n}] ;# J4.H5 CLK0_M2C_N
#set_property -dict {LOC AJ6 } [get_ports {fmc_hpc1_dp_c2m_p[0]}] ;# MGTHTXP3_223 GTHE4_CHANNEL_X0Y3 / GTHE4_COMMON_X0Y0 from J4.C2 DP0_C2M_P
#set_property -dict {LOC AJ5 } [get_ports {fmc_hpc1_dp_c2m_n[0]}] ;# MGTHTXN3_223 GTHE4_CHANNEL_X0Y3 / GTHE4_COMMON_X0Y0 from J4.C3 DP0_C2M_N
#set_property -dict {LOC AK4 } [get_ports {fmc_hpc1_dp_m2c_p[0]}] ;# MGTHRXP3_223 GTHE4_CHANNEL_X0Y3 / GTHE4_COMMON_X0Y0 from J4.C6 DP0_M2C_P
#set_property -dict {LOC AK3 } [get_ports {fmc_hpc1_dp_m2c_n[0]}] ;# MGTHRXN3_223 GTHE4_CHANNEL_X0Y3 / GTHE4_COMMON_X0Y0 from J4.C7 DP0_M2C_N
#set_property -dict {LOC Y8 } [get_ports {fmc_hpc1_mgt_refclk_p}] ;# MGTREFCLK0P_225 from J4.D4 GBTCLK0_M2C_P
#set_property -dict {LOC Y7 } [get_ports {fmc_hpc1_mgt_refclk_n}] ;# MGTREFCLK0N_225 from J4.D5 GBTCLK0_M2C_N
# reference clock
#create_clock -period 6.400 -name fmc_hpc1_mgt_refclk [get_ports {fmc_hpc1_mgt_refclk_p}]
# DDR4
# 4x MT40A256M16GE-075E
#set_property -dict {LOC AK9 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_adr[0]}]
#set_property -dict {LOC AG11 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_adr[1]}]
#set_property -dict {LOC AJ10 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_adr[2]}]
#set_property -dict {LOC AL8 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_adr[3]}]
#set_property -dict {LOC AK10 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_adr[4]}]
#set_property -dict {LOC AH8 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_adr[5]}]
#set_property -dict {LOC AJ9 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_adr[6]}]
#set_property -dict {LOC AG8 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_adr[7]}]
#set_property -dict {LOC AH9 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_adr[8]}]
#set_property -dict {LOC AG10 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_adr[9]}]
#set_property -dict {LOC AH13 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_adr[10]}]
#set_property -dict {LOC AG9 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_adr[11]}]
#set_property -dict {LOC AM13 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_adr[12]}]
#set_property -dict {LOC AF8 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_adr[13]}]
#set_property -dict {LOC AC12 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_adr[14]}]
#set_property -dict {LOC AE12 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_adr[15]}]
#set_property -dict {LOC AF11 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_adr[16]}]
#set_property -dict {LOC AK8 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_ba[0]}]
#set_property -dict {LOC AL12 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_ba[1]}]
#set_property -dict {LOC AE14 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_bg[0]}]
#set_property -dict {LOC AH11 IOSTANDARD DIFF_SSTL12_DCI} [get_ports {ddr4_ck_t}]
#set_property -dict {LOC AJ11 IOSTANDARD DIFF_SSTL12_DCI} [get_ports {ddr4_ck_c}]
#set_property -dict {LOC AB13 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_cke}]
#set_property -dict {LOC AD12 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_cs_n}]
#set_property -dict {LOC AD14 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_act_n}]
#set_property -dict {LOC AF10 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_odt}]
#set_property -dict {LOC AC13 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_par}]
#set_property -dict {LOC AF12 IOSTANDARD LVCMOS12 } [get_ports {ddr4_reset_n}]
#set_property -dict {LOC AF16 IOSTANDARD POD12_DCI } [get_ports {ddr4_dq[0]}] ;# U101.G2 DQL0
#set_property -dict {LOC AF18 IOSTANDARD POD12_DCI } [get_ports {ddr4_dq[1]}] ;# U101.F7 DQL1
#set_property -dict {LOC AG15 IOSTANDARD POD12_DCI } [get_ports {ddr4_dq[2]}] ;# U101.H3 DQL2
#set_property -dict {LOC AF17 IOSTANDARD POD12_DCI } [get_ports {ddr4_dq[3]}] ;# U101.H7 DQL3
#set_property -dict {LOC AF15 IOSTANDARD POD12_DCI } [get_ports {ddr4_dq[4]}] ;# U101.H2 DQL4
#set_property -dict {LOC AG18 IOSTANDARD POD12_DCI } [get_ports {ddr4_dq[5]}] ;# U101.H8 DQL5
#set_property -dict {LOC AG14 IOSTANDARD POD12_DCI } [get_ports {ddr4_dq[6]}] ;# U101.J3 DQL6
#set_property -dict {LOC AE17 IOSTANDARD POD12_DCI } [get_ports {ddr4_dq[7]}] ;# U101.J7 DQL7
#set_property -dict {LOC AA14 IOSTANDARD POD12_DCI } [get_ports {ddr4_dq[8]}] ;# U101.A3 DQU0
#set_property -dict {LOC AC16 IOSTANDARD POD12_DCI } [get_ports {ddr4_dq[9]}] ;# U101.B8 DQU1
#set_property -dict {LOC AB15 IOSTANDARD POD12_DCI } [get_ports {ddr4_dq[10]}] ;# U101.C3 DQU2
#set_property -dict {LOC AD16 IOSTANDARD POD12_DCI } [get_ports {ddr4_dq[11]}] ;# U101.C7 DQU3
#set_property -dict {LOC AB16 IOSTANDARD POD12_DCI } [get_ports {ddr4_dq[12]}] ;# U101.C2 DQU4
#set_property -dict {LOC AC17 IOSTANDARD POD12_DCI } [get_ports {ddr4_dq[13]}] ;# U101.C8 DQU5
#set_property -dict {LOC AB14 IOSTANDARD POD12_DCI } [get_ports {ddr4_dq[14]}] ;# U101.D3 DQU6
#set_property -dict {LOC AD17 IOSTANDARD POD12_DCI } [get_ports {ddr4_dq[15]}] ;# U101.D7 DQU7
#set_property -dict {LOC AH14 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_dqs_t[0]}] ;# U101.G3 DQSL_T
#set_property -dict {LOC AJ14 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_dqs_c[0]}] ;# U101.F3 DQSL_C
#set_property -dict {LOC AA16 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_dqs_t[1]}] ;# U101.B7 DQSU_T
#set_property -dict {LOC AA15 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_dqs_c[1]}] ;# U101.A7 DQSU_C
#set_property -dict {LOC AH18 IOSTANDARD POD12_DCI } [get_ports {ddr4_dm_dbi_n[0]}] ;# U101.E7 DML_B/DBIL_B
#set_property -dict {LOC AD15 IOSTANDARD POD12_DCI } [get_ports {ddr4_dm_dbi_n[1]}] ;# U101.E2 DMU_B/DBIU_B
#set_property -dict {LOC AJ16 IOSTANDARD POD12_DCI } [get_ports {ddr4_dq[16]}] ;# U99.G2 DQL0
#set_property -dict {LOC AJ17 IOSTANDARD POD12_DCI } [get_ports {ddr4_dq[17]}] ;# U99.F7 DQL1
#set_property -dict {LOC AL15 IOSTANDARD POD12_DCI } [get_ports {ddr4_dq[18]}] ;# U99.H3 DQL2
#set_property -dict {LOC AK17 IOSTANDARD POD12_DCI } [get_ports {ddr4_dq[19]}] ;# U99.H7 DQL3
#set_property -dict {LOC AJ15 IOSTANDARD POD12_DCI } [get_ports {ddr4_dq[20]}] ;# U99.H2 DQL4
#set_property -dict {LOC AK18 IOSTANDARD POD12_DCI } [get_ports {ddr4_dq[21]}] ;# U99.H8 DQL5
#set_property -dict {LOC AL16 IOSTANDARD POD12_DCI } [get_ports {ddr4_dq[22]}] ;# U99.J3 DQL6
#set_property -dict {LOC AL18 IOSTANDARD POD12_DCI } [get_ports {ddr4_dq[23]}] ;# U99.J7 DQL7
#set_property -dict {LOC AP13 IOSTANDARD POD12_DCI } [get_ports {ddr4_dq[24]}] ;# U99.A3 DQU0
#set_property -dict {LOC AP16 IOSTANDARD POD12_DCI } [get_ports {ddr4_dq[25]}] ;# U99.B8 DQU1
#set_property -dict {LOC AP15 IOSTANDARD POD12_DCI } [get_ports {ddr4_dq[26]}] ;# U99.C3 DQU2
#set_property -dict {LOC AN16 IOSTANDARD POD12_DCI } [get_ports {ddr4_dq[27]}] ;# U99.C7 DQU3
#set_property -dict {LOC AN13 IOSTANDARD POD12_DCI } [get_ports {ddr4_dq[28]}] ;# U99.C2 DQU4
#set_property -dict {LOC AM18 IOSTANDARD POD12_DCI } [get_ports {ddr4_dq[29]}] ;# U99.C8 DQU5
#set_property -dict {LOC AN17 IOSTANDARD POD12_DCI } [get_ports {ddr4_dq[30]}] ;# U99.D3 DQU6
#set_property -dict {LOC AN18 IOSTANDARD POD12_DCI } [get_ports {ddr4_dq[31]}] ;# U99.D7 DQU7
#set_property -dict {LOC AK15 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_dqs_t[2]}] ;# U99.G3 DQSL_T
#set_property -dict {LOC AK14 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_dqs_c[2]}] ;# U99.F3 DQSL_C
#set_property -dict {LOC AM14 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_dqs_t[3]}] ;# U99.B7 DQSU_T
#set_property -dict {LOC AN14 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_dqs_c[3]}] ;# U99.A7 DQSU_C
#set_property -dict {LOC AM16 IOSTANDARD POD12_DCI } [get_ports {ddr4_dm_dbi_n[2]}] ;# U99.E7 DML_B/DBIL_B
#set_property -dict {LOC AP18 IOSTANDARD POD12_DCI } [get_ports {ddr4_dm_dbi_n[3]}] ;# U99.E2 DMU_B/DBIU_B
#set_property -dict {LOC AB19 IOSTANDARD POD12_DCI } [get_ports {ddr4_dq[32]}] ;# U100.G2 DQL0
#set_property -dict {LOC AD19 IOSTANDARD POD12_DCI } [get_ports {ddr4_dq[33]}] ;# U100.F7 DQL1
#set_property -dict {LOC AC18 IOSTANDARD POD12_DCI } [get_ports {ddr4_dq[34]}] ;# U100.H3 DQL2
#set_property -dict {LOC AC19 IOSTANDARD POD12_DCI } [get_ports {ddr4_dq[35]}] ;# U100.H7 DQL3
#set_property -dict {LOC AA20 IOSTANDARD POD12_DCI } [get_ports {ddr4_dq[36]}] ;# U100.H2 DQL4
#set_property -dict {LOC AE20 IOSTANDARD POD12_DCI } [get_ports {ddr4_dq[37]}] ;# U100.H8 DQL5
#set_property -dict {LOC AA19 IOSTANDARD POD12_DCI } [get_ports {ddr4_dq[38]}] ;# U100.J3 DQL6
#set_property -dict {LOC AD20 IOSTANDARD POD12_DCI } [get_ports {ddr4_dq[39]}] ;# U100.J7 DQL7
#set_property -dict {LOC AF22 IOSTANDARD POD12_DCI } [get_ports {ddr4_dq[40]}] ;# U100.A3 DQU0
#set_property -dict {LOC AH21 IOSTANDARD POD12_DCI } [get_ports {ddr4_dq[41]}] ;# U100.B8 DQU1
#set_property -dict {LOC AG19 IOSTANDARD POD12_DCI } [get_ports {ddr4_dq[42]}] ;# U100.C3 DQU2
#set_property -dict {LOC AG21 IOSTANDARD POD12_DCI } [get_ports {ddr4_dq[43]}] ;# U100.C7 DQU3
#set_property -dict {LOC AE24 IOSTANDARD POD12_DCI } [get_ports {ddr4_dq[44]}] ;# U100.C2 DQU4
#set_property -dict {LOC AG20 IOSTANDARD POD12_DCI } [get_ports {ddr4_dq[45]}] ;# U100.C8 DQU5
#set_property -dict {LOC AE23 IOSTANDARD POD12_DCI } [get_ports {ddr4_dq[46]}] ;# U100.D3 DQU6
#set_property -dict {LOC AF21 IOSTANDARD POD12_DCI } [get_ports {ddr4_dq[47]}] ;# U100.D7 DQU7
#set_property -dict {LOC AA18 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_dqs_t[4]}] ;# U100.G3 DQSL_T
#set_property -dict {LOC AB18 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_dqs_c[4]}] ;# U100.F3 DQSL_C
#set_property -dict {LOC AF23 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_dqs_t[5]}] ;# U100.B7 DQSU_T
#set_property -dict {LOC AG23 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_dqs_c[5]}] ;# U100.A7 DQSU_C
#set_property -dict {LOC AE18 IOSTANDARD POD12_DCI } [get_ports {ddr4_dm_dbi_n[4]}] ;# U100.E7 DML_B/DBIL_B
#set_property -dict {LOC AH22 IOSTANDARD POD12_DCI } [get_ports {ddr4_dm_dbi_n[5]}] ;# U100.E2 DMU_B/DBIU_B
#set_property -dict {LOC AL22 IOSTANDARD POD12_DCI } [get_ports {ddr4_dq[48]}] ;# U2.G2 DQL0
#set_property -dict {LOC AJ22 IOSTANDARD POD12_DCI } [get_ports {ddr4_dq[49]}] ;# U2.F7 DQL1
#set_property -dict {LOC AL23 IOSTANDARD POD12_DCI } [get_ports {ddr4_dq[50]}] ;# U2.H3 DQL2
#set_property -dict {LOC AJ21 IOSTANDARD POD12_DCI } [get_ports {ddr4_dq[51]}] ;# U2.H7 DQL3
#set_property -dict {LOC AK20 IOSTANDARD POD12_DCI } [get_ports {ddr4_dq[52]}] ;# U2.H2 DQL4
#set_property -dict {LOC AJ19 IOSTANDARD POD12_DCI } [get_ports {ddr4_dq[53]}] ;# U2.H8 DQL5
#set_property -dict {LOC AK19 IOSTANDARD POD12_DCI } [get_ports {ddr4_dq[54]}] ;# U2.J3 DQL6
#set_property -dict {LOC AJ20 IOSTANDARD POD12_DCI } [get_ports {ddr4_dq[55]}] ;# U2.J7 DQL7
#set_property -dict {LOC AP22 IOSTANDARD POD12_DCI } [get_ports {ddr4_dq[56]}] ;# U2.A3 DQU0
#set_property -dict {LOC AN22 IOSTANDARD POD12_DCI } [get_ports {ddr4_dq[57]}] ;# U2.B8 DQU1
#set_property -dict {LOC AP21 IOSTANDARD POD12_DCI } [get_ports {ddr4_dq[58]}] ;# U2.C3 DQU2
#set_property -dict {LOC AP23 IOSTANDARD POD12_DCI } [get_ports {ddr4_dq[59]}] ;# U2.C7 DQU3
#set_property -dict {LOC AM19 IOSTANDARD POD12_DCI } [get_ports {ddr4_dq[60]}] ;# U2.C2 DQU4
#set_property -dict {LOC AM23 IOSTANDARD POD12_DCI } [get_ports {ddr4_dq[61]}] ;# U2.C8 DQU5
#set_property -dict {LOC AN19 IOSTANDARD POD12_DCI } [get_ports {ddr4_dq[62]}] ;# U2.D3 DQU6
#set_property -dict {LOC AN23 IOSTANDARD POD12_DCI } [get_ports {ddr4_dq[63]}] ;# U2.D7 DQU7
#set_property -dict {LOC AK22 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_dqs_t[6]}] ;# U2.G3 DQSL_T
#set_property -dict {LOC AK23 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_dqs_c[6]}] ;# U2.F3 DQSL_C
#set_property -dict {LOC AM21 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_dqs_t[7]}] ;# U2.B7 DQSU_T
#set_property -dict {LOC AN21 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_dqs_c[7]}] ;# U2.A7 DQSU_C
#set_property -dict {LOC AL20 IOSTANDARD POD12_DCI } [get_ports {ddr4_dm_dbi_n[6]}] ;# U2.E7 DML_B/DBIL_B
#set_property -dict {LOC AP19 IOSTANDARD POD12_DCI } [get_ports {ddr4_dm_dbi_n[7]}] ;# U2.E2 DMU_B/DBIU_B

View File

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

View File

@@ -0,0 +1,21 @@
# SPDX-License-Identifier: MIT
#
# Copyright (c) 2025 FPGA Ninja, LLC
#
# Authors:
# - Alex Forencich
#
set params [dict create]
# SFP+ rate
# 0 for 1G, 1 for 10G
dict set params SFP_RATE "1"
# apply parameters to top-level
set param_list {}
dict for {name value} $params {
lappend param_list $name=$value
}
set_property generic $param_list [get_filesets sources_1]

View File

@@ -0,0 +1,55 @@
# SPDX-License-Identifier: MIT
#
# Copyright (c) 2025 FPGA Ninja, LLC
#
# Authors:
# - Alex Forencich
#
# FPGA settings
FPGA_PART = xczu7ev-ffvc1156-2-e
FPGA_TOP = fpga
FPGA_ARCH = zynquplus
RTL_DIR = ../rtl
LIB_DIR = ../lib
TAXI_SRC_DIR = $(LIB_DIR)/taxi/src
# Files for synthesis
SYN_FILES = $(RTL_DIR)/fpga.sv
SYN_FILES += $(RTL_DIR)/fpga_core.sv
SYN_FILES += $(TAXI_SRC_DIR)/eth/rtl/taxi_eth_mac_1g_fifo.f
SYN_FILES += $(TAXI_SRC_DIR)/xfcp/rtl/taxi_xfcp_if_uart.f
SYN_FILES += $(TAXI_SRC_DIR)/xfcp/rtl/taxi_xfcp_switch.sv
SYN_FILES += $(TAXI_SRC_DIR)/xfcp/rtl/taxi_xfcp_mod_stats.f
SYN_FILES += $(TAXI_SRC_DIR)/sync/rtl/taxi_sync_reset.sv
SYN_FILES += $(TAXI_SRC_DIR)/sync/rtl/taxi_sync_signal.sv
SYN_FILES += $(TAXI_SRC_DIR)/io/rtl/taxi_debounce_switch.sv
# XDC files
XDC_FILES = ../fpga.xdc
XDC_FILES += $(TAXI_SRC_DIR)/eth/syn/vivado/taxi_eth_mac_fifo.tcl
XDC_FILES += $(TAXI_SRC_DIR)/axis/syn/vivado/taxi_axis_async_fifo.tcl
XDC_FILES += $(TAXI_SRC_DIR)/sync/syn/vivado/taxi_sync_reset.tcl
XDC_FILES += $(TAXI_SRC_DIR)/sync/syn/vivado/taxi_sync_signal.tcl
# IP
IP_TCL_FILES = ../ip/basex_pcs_pma_0.tcl
IP_TCL_FILES += ../ip/basex_pcs_pma_1.tcl
# Configuration
CONFIG_TCL_FILES = ./config.tcl
include ../common/vivado.mk
program: $(FPGA_TOP).bit
echo "open_hw_manager" > program.tcl
echo "connect_hw_server" >> program.tcl
echo "open_hw_target" >> program.tcl
echo "current_hw_device [lindex [get_hw_devices] 0]" >> program.tcl
echo "refresh_hw_device -update_hw_probes false [current_hw_device]" >> program.tcl
echo "set_property PROGRAM.FILE {$(FPGA_TOP).bit} [current_hw_device]" >> program.tcl
echo "program_hw_devices [current_hw_device]" >> program.tcl
echo "exit" >> program.tcl
vivado -nojournal -nolog -mode batch -source program.tcl

View File

@@ -0,0 +1,21 @@
# SPDX-License-Identifier: MIT
#
# Copyright (c) 2025 FPGA Ninja, LLC
#
# Authors:
# - Alex Forencich
#
set params [dict create]
# SFP+ rate
# 0 for 1G, 1 for 10G
dict set params SFP_RATE "0"
# apply parameters to top-level
set param_list {}
dict for {name value} $params {
lappend param_list $name=$value
}
set_property generic $param_list [get_filesets sources_1]

View File

@@ -0,0 +1,21 @@
# SPDX-License-Identifier: MIT
#
# Copyright (c) 2025 FPGA Ninja, LLC
#
# Authors:
# - Alex Forencich
#
create_ip -name gig_ethernet_pcs_pma -vendor xilinx.com -library ip -module_name basex_pcs_pma_0
set_property -dict [list \
CONFIG.Standard {1000BASEX} \
CONFIG.Physical_Interface {Transceiver} \
CONFIG.Management_Interface {false} \
CONFIG.Auto_Negotiation {false} \
CONFIG.TransceiverControl {false} \
CONFIG.RefClkRate {156.25} \
CONFIG.DrpClkRate {62.5} \
CONFIG.SupportLevel {Include_Shared_Logic_in_Core} \
CONFIG.GT_Location {X0Y10} \
] [get_ips basex_pcs_pma_0]

View File

@@ -0,0 +1,21 @@
# SPDX-License-Identifier: MIT
#
# Copyright (c) 2025 FPGA Ninja, LLC
#
# Authors:
# - Alex Forencich
#
create_ip -name gig_ethernet_pcs_pma -vendor xilinx.com -library ip -module_name basex_pcs_pma_1
set_property -dict [list \
CONFIG.Standard {1000BASEX} \
CONFIG.Physical_Interface {Transceiver} \
CONFIG.Management_Interface {false} \
CONFIG.Auto_Negotiation {false} \
CONFIG.TransceiverControl {false} \
CONFIG.RefClkRate {156.25} \
CONFIG.DrpClkRate {62.5} \
CONFIG.SupportLevel {Include_Shared_Logic_in_Example_Design} \
CONFIG.GT_Location {X0Y9} \
] [get_ips basex_pcs_pma_1]

View File

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

View File

@@ -0,0 +1,492 @@
// SPDX-License-Identifier: MIT
/*
Copyright (c) 2020-2025 FPGA Ninja, LLC
Authors:
- Alex Forencich
*/
`resetall
`timescale 1ns / 1ps
`default_nettype none
/*
* FPGA top-level module
*/
module fpga #
(
// simulation (set to avoid vendor primitives)
parameter logic SIM = 1'b0,
// vendor ("GENERIC", "XILINX", "ALTERA")
parameter string VENDOR = "XILINX",
// device family
parameter string FAMILY = "zynquplus",
// SFP rate selection (0 for 1G, 1 for 10G)
parameter logic SFP_RATE = 1'b1
)
(
/*
* Clock: 125MHz LVDS
* Reset: Push button, active low
*/
input wire logic clk_125mhz_p,
input wire logic clk_125mhz_n,
input wire logic reset,
/*
* GPIO
*/
input wire logic btnu,
input wire logic btnl,
input wire logic btnd,
input wire logic btnr,
input wire logic btnc,
input wire logic [7:0] sw,
output wire logic [7:0] led,
/*
* UART: 115200 bps, 8N1
*/
input wire logic uart_rxd,
output wire logic uart_txd,
input wire logic uart_rts,
output wire logic uart_cts,
/*
* Ethernet: SFP+
*/
input wire logic [1:0] sfp_rx_p,
input wire logic [1:0] sfp_rx_n,
output wire logic [1:0] sfp_tx_p,
output wire logic [1:0] sfp_tx_n,
input wire logic sfp_mgt_refclk_0_p,
input wire logic sfp_mgt_refclk_0_n,
output wire logic [1:0] sfp_tx_disable_b
);
wire clk_125mhz_ibufg;
// Internal 125 MHz clock
wire clk_125mhz_mmcm_out;
wire clk_125mhz_int;
wire rst_125mhz_int;
// Internal 62.5 MHz clock
wire clk_62mhz_mmcm_out;
wire clk_62mhz_int;
wire mmcm_rst = reset;
wire mmcm_locked;
wire mmcm_clkfb;
IBUFGDS #(
.DIFF_TERM("FALSE"),
.IBUF_LOW_PWR("FALSE")
)
clk_125mhz_ibufg_inst (
.O (clk_125mhz_ibufg),
.I (clk_125mhz_p),
.IB (clk_125mhz_n)
);
// MMCM instance
MMCME4_BASE #(
// 125 MHz input
.CLKIN1_PERIOD(8.0),
.REF_JITTER1(0.010),
// 125 MHz input / 1 = 125 MHz PFD (range 10 MHz to 500 MHz)
.DIVCLK_DIVIDE(1),
// 125 MHz PFD * 10 = 1250 MHz VCO (range 800 MHz to 1600 MHz)
.CLKFBOUT_MULT_F(10),
.CLKFBOUT_PHASE(0),
// 1250 MHz / 10 = 125 MHz, 0 degrees
.CLKOUT0_DIVIDE_F(10),
.CLKOUT0_DUTY_CYCLE(0.5),
.CLKOUT0_PHASE(0),
// 1250 MHz / 20 = 62.5 MHz, 0 degrees
.CLKOUT1_DIVIDE(20),
.CLKOUT1_DUTY_CYCLE(0.5),
.CLKOUT1_PHASE(0),
// Not used
.CLKOUT2_DIVIDE(1),
.CLKOUT2_DUTY_CYCLE(0.5),
.CLKOUT2_PHASE(0),
// Not used
.CLKOUT3_DIVIDE(1),
.CLKOUT3_DUTY_CYCLE(0.5),
.CLKOUT3_PHASE(0),
// Not used
.CLKOUT4_DIVIDE(1),
.CLKOUT4_DUTY_CYCLE(0.5),
.CLKOUT4_PHASE(0),
.CLKOUT4_CASCADE("FALSE"),
// Not used
.CLKOUT5_DIVIDE(1),
.CLKOUT5_DUTY_CYCLE(0.5),
.CLKOUT5_PHASE(0),
// Not used
.CLKOUT6_DIVIDE(1),
.CLKOUT6_DUTY_CYCLE(0.5),
.CLKOUT6_PHASE(0),
// optimized bandwidth
.BANDWIDTH("OPTIMIZED"),
// don't wait for lock during startup
.STARTUP_WAIT("FALSE")
)
clk_mmcm_inst (
// 125 MHz input
.CLKIN1(clk_125mhz_ibufg),
// direct clkfb feeback
.CLKFBIN(mmcm_clkfb),
.CLKFBOUT(mmcm_clkfb),
.CLKFBOUTB(),
// 125 MHz, 0 degrees
.CLKOUT0(clk_125mhz_mmcm_out),
.CLKOUT0B(),
// 62.5 MHz, 0 degrees
.CLKOUT1(clk_62mhz_mmcm_out),
.CLKOUT1B(),
// Not used
.CLKOUT2(),
.CLKOUT2B(),
// Not used
.CLKOUT3(),
.CLKOUT3B(),
// Not used
.CLKOUT4(),
// Not used
.CLKOUT5(),
// Not used
.CLKOUT6(),
// reset input
.RST(mmcm_rst),
// don't power down
.PWRDWN(1'b0),
// locked output
.LOCKED(mmcm_locked)
);
BUFG
clk_125mhz_bufg_inst (
.I(clk_125mhz_mmcm_out),
.O(clk_125mhz_int)
);
BUFG
clk_62mhz_bufg_inst (
.I(clk_62mhz_mmcm_out),
.O(clk_62mhz_int)
);
taxi_sync_reset #(
.N(4)
)
sync_reset_125mhz_inst (
.clk(clk_125mhz_int),
.rst(~mmcm_locked),
.out(rst_125mhz_int)
);
// GPIO
wire btnu_int;
wire btnl_int;
wire btnd_int;
wire btnr_int;
wire btnc_int;
wire [7:0] sw_int;
taxi_debounce_switch #(
.WIDTH(5+8),
.N(4),
.RATE(125000)
)
debounce_switch_inst (
.clk(clk_125mhz_int),
.rst(rst_125mhz_int),
.in({btnu,
btnl,
btnd,
btnr,
btnc,
sw}),
.out({btnu_int,
btnl_int,
btnd_int,
btnr_int,
btnc_int,
sw_int})
);
wire uart_rxd_int;
wire uart_rts_int;
taxi_sync_signal #(
.WIDTH(2),
.N(2)
)
sync_signal_inst (
.clk(clk_125mhz_int),
.in({uart_rxd, uart_rts}),
.out({uart_rxd_int, uart_rts_int})
);
wire [7:0] led_int;
// SFP+
wire [1:0] sfp_tx_p_int;
wire [1:0] sfp_tx_n_int;
wire sfp0_gmii_clk_int;
wire sfp0_gmii_rst_int;
wire sfp0_gmii_clk_en_int = 1'b1;
wire [7:0] sfp0_gmii_txd_int;
wire sfp0_gmii_tx_en_int;
wire sfp0_gmii_tx_er_int;
wire [7:0] sfp0_gmii_rxd_int;
wire sfp0_gmii_rx_dv_int;
wire sfp0_gmii_rx_er_int;
wire [15:0] sfp0_status_vect;
wire sfp1_gmii_clk_int;
wire sfp1_gmii_rst_int;
wire sfp1_gmii_clk_en_int = 1'b1;
wire [7:0] sfp1_gmii_txd_int;
wire sfp1_gmii_tx_en_int;
wire sfp1_gmii_tx_er_int;
wire [7:0] sfp1_gmii_rxd_int;
wire sfp1_gmii_rx_dv_int;
wire sfp1_gmii_rx_er_int;
wire [15:0] sfp1_status_vect;
if (SFP_RATE == 0) begin : sfp_phy
// 1000BASE-X
wire sfp0_gmii_gtrefclk;
wire sfp0_gmii_txuserclk;
wire sfp0_gmii_txuserclk2;
wire sfp0_gmii_resetdone;
wire sfp0_gmii_pmareset;
wire sfp0_gmii_mmcm_locked;
assign sfp0_gmii_clk_int = sfp0_gmii_txuserclk2;
taxi_sync_reset #(
.N(4)
)
sync_reset_sfp0_inst (
.clk(sfp0_gmii_clk_int),
.rst(rst_125mhz_int || !sfp0_gmii_resetdone),
.out(sfp0_gmii_rst_int)
);
wire sfp0_status_link_status = sfp0_status_vect[0];
wire sfp0_status_link_synchronization = sfp0_status_vect[1];
wire sfp0_status_rudi_c = sfp0_status_vect[2];
wire sfp0_status_rudi_i = sfp0_status_vect[3];
wire sfp0_status_rudi_invalid = sfp0_status_vect[4];
wire sfp0_status_rxdisperr = sfp0_status_vect[5];
wire sfp0_status_rxnotintable = sfp0_status_vect[6];
wire sfp0_status_phy_link_status = sfp0_status_vect[7];
wire [1:0] sfp0_status_remote_fault_encdg = sfp0_status_vect[9:8];
wire [1:0] sfp0_status_speed = sfp0_status_vect[11:10];
wire sfp0_status_duplex = sfp0_status_vect[12];
wire sfp0_status_remote_fault = sfp0_status_vect[13];
wire [1:0] sfp0_status_pause = sfp0_status_vect[15:14];
wire [4:0] sfp0_config_vect;
assign sfp0_config_vect[4] = 1'b0; // autonegotiation enable
assign sfp0_config_vect[3] = 1'b0; // isolate
assign sfp0_config_vect[2] = 1'b0; // power down
assign sfp0_config_vect[1] = 1'b0; // loopback enable
assign sfp0_config_vect[0] = 1'b0; // unidirectional enable
basex_pcs_pma_0
sfp0_pcspma (
.gtrefclk_p(sfp_mgt_refclk_0_p),
.gtrefclk_n(sfp_mgt_refclk_0_n),
.gtrefclk_out(sfp0_gmii_gtrefclk),
.txn(sfp_tx_n[0]),
.txp(sfp_tx_p[0]),
.rxn(sfp_rx_n[0]),
.rxp(sfp_rx_p[0]),
.independent_clock_bufg(clk_62mhz_int),
.userclk_out(sfp0_gmii_txuserclk),
.userclk2_out(sfp0_gmii_txuserclk2),
.rxuserclk_out(),
.rxuserclk2_out(),
.gtpowergood(),
.resetdone(sfp0_gmii_resetdone),
.pma_reset_out(sfp0_gmii_pmareset),
.mmcm_locked_out(sfp0_gmii_mmcm_locked),
.gmii_txd(sfp0_gmii_txd_int),
.gmii_tx_en(sfp0_gmii_tx_en_int),
.gmii_tx_er(sfp0_gmii_tx_er_int),
.gmii_rxd(sfp0_gmii_rxd_int),
.gmii_rx_dv(sfp0_gmii_rx_dv_int),
.gmii_rx_er(sfp0_gmii_rx_er_int),
.gmii_isolate(),
.configuration_vector(sfp0_config_vect),
.status_vector(sfp0_status_vect),
.reset(rst_125mhz_int),
.signal_detect(1'b1)
);
wire sfp1_gmii_txuserclk2 = sfp0_gmii_txuserclk2;
wire sfp1_gmii_resetdone;
assign sfp1_gmii_clk_int = sfp1_gmii_txuserclk2;
taxi_sync_reset #(
.N(4)
)
sync_reset_sfp1_inst (
.clk(sfp1_gmii_clk_int),
.rst(rst_125mhz_int || !sfp1_gmii_resetdone),
.out(sfp1_gmii_rst_int)
);
wire sfp1_status_link_status = sfp1_status_vect[0];
wire sfp1_status_link_synchronization = sfp1_status_vect[1];
wire sfp1_status_rudi_c = sfp1_status_vect[2];
wire sfp1_status_rudi_i = sfp1_status_vect[3];
wire sfp1_status_rudi_invalid = sfp1_status_vect[4];
wire sfp1_status_rxdisperr = sfp1_status_vect[5];
wire sfp1_status_rxnotintable = sfp1_status_vect[6];
wire sfp1_status_phy_link_status = sfp1_status_vect[7];
wire [1:0] sfp1_status_remote_fault_encdg = sfp1_status_vect[9:8];
wire [1:0] sfp1_status_speed = sfp1_status_vect[11:10];
wire sfp1_status_duplex = sfp1_status_vect[12];
wire sfp1_status_remote_fault = sfp1_status_vect[13];
wire [1:0] sfp1_status_pause = sfp1_status_vect[15:14];
wire [4:0] sfp1_config_vect;
assign sfp1_config_vect[4] = 1'b0; // autonegotiation enable
assign sfp1_config_vect[3] = 1'b0; // isolate
assign sfp1_config_vect[2] = 1'b0; // power down
assign sfp1_config_vect[1] = 1'b0; // loopback enable
assign sfp1_config_vect[0] = 1'b0; // unidirectional enable
basex_pcs_pma_1
sfp1_pcspma (
.gtrefclk(sfp0_gmii_gtrefclk),
.txn(sfp_tx_n[1]),
.txp(sfp_tx_p[1]),
.rxn(sfp_rx_n[1]),
.rxp(sfp_rx_p[1]),
.independent_clock_bufg(clk_62mhz_int),
.txoutclk(),
.gtpowergood(),
.rxoutclk(),
.resetdone(sfp1_gmii_resetdone),
.cplllock(),
.mmcm_reset(),
.userclk(sfp0_gmii_txuserclk),
.userclk2(sfp0_gmii_txuserclk2),
.pma_reset(sfp0_gmii_pmareset),
.mmcm_locked(sfp0_gmii_mmcm_locked),
.rxuserclk(1'b0),
.rxuserclk2(1'b0),
.gmii_txd(sfp1_gmii_txd_int),
.gmii_tx_en(sfp1_gmii_tx_en_int),
.gmii_tx_er(sfp1_gmii_tx_er_int),
.gmii_rxd(sfp1_gmii_rxd_int),
.gmii_rx_dv(sfp1_gmii_rx_dv_int),
.gmii_rx_er(sfp1_gmii_rx_er_int),
.gmii_isolate(),
.configuration_vector(sfp1_config_vect),
.status_vector(sfp1_status_vect),
.reset(rst_125mhz_int),
.signal_detect(1'b1)
);
end else begin
// 10GBASE-R
assign sfp_tx_p = sfp_tx_p_int;
assign sfp_tx_n = sfp_tx_n_int;
end
// SGMII interface debug:
// SW12:1 (sw[3]) off for payload byte, on for status vector
// SW12:2 (sw[2]) off for SFP0, on for SFP1
// SW12:4 (sw[0]) off for LSB of status vector, on for MSB
wire [15:0] sel_sv = sw[2] ? sfp1_status_vect : sfp0_status_vect;
assign led = sw[3] ? (sw[0] ? sel_sv[15:8] : sel_sv[7:0]) : led_int;
fpga_core #(
.SIM(SIM),
.VENDOR(VENDOR),
.FAMILY(FAMILY),
.SFP_RATE(SFP_RATE)
)
core_inst (
/*
* Clock: 125MHz
* Synchronous reset
*/
.clk_125mhz(clk_125mhz_int),
.rst_125mhz(rst_125mhz_int),
/*
* GPIO
*/
.btnu(btnu_int),
.btnl(btnl_int),
.btnd(btnd_int),
.btnr(btnr_int),
.btnc(btnc_int),
.sw(sw_int),
.led(led_int),
/*
* UART: 115200 bps, 8N1
*/
.uart_rxd(uart_rxd_int),
.uart_txd(uart_txd),
.uart_rts(uart_rts_int),
.uart_cts(uart_cts),
/*
* Ethernet: SFP+
*/
.sfp_rx_p(sfp_rx_p),
.sfp_rx_n(sfp_rx_n),
.sfp_tx_p(sfp_tx_p_int),
.sfp_tx_n(sfp_tx_n_int),
.sfp_mgt_refclk_0_p(sfp_mgt_refclk_0_p),
.sfp_mgt_refclk_0_n(sfp_mgt_refclk_0_n),
.sfp0_gmii_clk(sfp0_gmii_clk_int),
.sfp0_gmii_rst(sfp0_gmii_rst_int),
.sfp0_gmii_clk_en(sfp0_gmii_clk_en_int),
.sfp0_gmii_rxd(sfp0_gmii_rxd_int),
.sfp0_gmii_rx_dv(sfp0_gmii_rx_dv_int),
.sfp0_gmii_rx_er(sfp0_gmii_rx_er_int),
.sfp0_gmii_txd(sfp0_gmii_txd_int),
.sfp0_gmii_tx_en(sfp0_gmii_tx_en_int),
.sfp0_gmii_tx_er(sfp0_gmii_tx_er_int),
.sfp1_gmii_clk(sfp1_gmii_clk_int),
.sfp1_gmii_rst(sfp1_gmii_rst_int),
.sfp1_gmii_clk_en(sfp1_gmii_clk_en_int),
.sfp1_gmii_rxd(sfp1_gmii_rxd_int),
.sfp1_gmii_rx_dv(sfp1_gmii_rx_dv_int),
.sfp1_gmii_rx_er(sfp1_gmii_rx_er_int),
.sfp1_gmii_txd(sfp1_gmii_txd_int),
.sfp1_gmii_tx_en(sfp1_gmii_tx_en_int),
.sfp1_gmii_tx_er(sfp1_gmii_tx_er_int),
.sfp_tx_disable_b(sfp_tx_disable_b)
);
endmodule
`resetall

View File

@@ -0,0 +1,695 @@
// SPDX-License-Identifier: MIT
/*
Copyright (c) 2020-2025 FPGA Ninja, LLC
Authors:
- Alex Forencich
*/
`resetall
`timescale 1ns / 1ps
`default_nettype none
/*
* FPGA core logic
*/
module fpga_core #
(
// simulation (set to avoid vendor primitives)
parameter logic SIM = 1'b0,
// vendor ("GENERIC", "XILINX", "ALTERA")
parameter string VENDOR = "XILINX",
// device family
parameter string FAMILY = "zynquplus",
// SFP rate selection (0 for 1G, 1 for 10G)
parameter logic SFP_RATE = 1'b1
)
(
/*
* Clock: 125MHz
* Synchronous reset
*/
input wire logic clk_125mhz,
input wire logic rst_125mhz,
/*
* GPIO
*/
input wire logic btnu,
input wire logic btnl,
input wire logic btnd,
input wire logic btnr,
input wire logic btnc,
input wire logic [7:0] sw,
output wire logic [7:0] led,
/*
* UART: 115200 bps, 8N1
*/
input wire logic uart_rxd,
output wire logic uart_txd,
input wire logic uart_rts,
output wire logic uart_cts,
/*
* Ethernet: SFP+
*/
input wire logic [1:0] sfp_rx_p,
input wire logic [1:0] sfp_rx_n,
output wire logic [1:0] sfp_tx_p,
output wire logic [1:0] sfp_tx_n,
input wire logic sfp_mgt_refclk_0_p,
input wire logic sfp_mgt_refclk_0_n,
input wire logic sfp0_gmii_clk,
input wire logic sfp0_gmii_rst,
input wire logic sfp0_gmii_clk_en,
input wire logic [7:0] sfp0_gmii_rxd,
input wire logic sfp0_gmii_rx_dv,
input wire logic sfp0_gmii_rx_er,
output wire logic [7:0] sfp0_gmii_txd,
output wire logic sfp0_gmii_tx_en,
output wire logic sfp0_gmii_tx_er,
input wire logic sfp1_gmii_clk,
input wire logic sfp1_gmii_rst,
input wire logic sfp1_gmii_clk_en,
input wire logic [7:0] sfp1_gmii_rxd,
input wire logic sfp1_gmii_rx_dv,
input wire logic sfp1_gmii_rx_er,
output wire logic [7:0] sfp1_gmii_txd,
output wire logic sfp1_gmii_tx_en,
output wire logic sfp1_gmii_tx_er,
output wire logic [1:0] sfp_tx_disable_b
);
assign led = sw;
// XFCP
assign uart_cts = 1'b0;
taxi_axis_if #(.DATA_W(8), .USER_EN(1), .USER_W(1)) xfcp_ds(), xfcp_us();
taxi_xfcp_if_uart #(
.TX_FIFO_DEPTH(512),
.RX_FIFO_DEPTH(512)
)
xfcp_if_uart_inst (
.clk(clk_125mhz),
.rst(rst_125mhz),
/*
* UART interface
*/
.uart_rxd(uart_rxd),
.uart_txd(uart_txd),
/*
* XFCP downstream interface
*/
.xfcp_dsp_ds(xfcp_ds),
.xfcp_dsp_us(xfcp_us),
/*
* Configuration
*/
.prescale(16'(125000000/2000000))
);
taxi_axis_if #(.DATA_W(8), .USER_EN(1), .USER_W(1)) xfcp_sw_ds[1](), xfcp_sw_us[1]();
taxi_xfcp_switch #(
.XFCP_ID_STR("ZCU106"),
.XFCP_EXT_ID(0),
.XFCP_EXT_ID_STR("Taxi example"),
.PORTS($size(xfcp_sw_us))
)
xfcp_sw_inst (
.clk(clk_125mhz),
.rst(rst_125mhz),
/*
* XFCP upstream port
*/
.xfcp_usp_ds(xfcp_ds),
.xfcp_usp_us(xfcp_us),
/*
* XFCP downstream ports
*/
.xfcp_dsp_ds(xfcp_sw_ds),
.xfcp_dsp_us(xfcp_sw_us)
);
taxi_axis_if #(.DATA_W(16), .KEEP_W(1), .KEEP_EN(0), .LAST_EN(0), .USER_EN(1), .USER_W(1), .ID_EN(1), .ID_W(10)) axis_stat();
taxi_xfcp_mod_stats #(
.XFCP_ID_STR("Statistics"),
.XFCP_EXT_ID(0),
.XFCP_EXT_ID_STR(""),
.STAT_COUNT_W(64),
.STAT_PIPELINE(2)
)
xfcp_stats_inst (
.clk(clk_125mhz),
.rst(rst_125mhz),
/*
* XFCP upstream port
*/
.xfcp_usp_ds(xfcp_sw_ds[0]),
.xfcp_usp_us(xfcp_sw_us[0]),
/*
* Statistics increment input
*/
.s_axis_stat(axis_stat)
);
taxi_axis_if #(.DATA_W(16), .KEEP_W(1), .KEEP_EN(0), .LAST_EN(0), .USER_EN(1), .USER_W(1), .ID_EN(1), .ID_W(10)) axis_eth_stat[SFP_RATE ? 1 : 2]();
taxi_axis_arb_mux #(
.S_COUNT($size(axis_eth_stat)),
.UPDATE_TID(1'b0),
.ARB_ROUND_ROBIN(1'b1),
.ARB_LSB_HIGH_PRIO(1'b0)
)
stat_mux_inst (
.clk(clk_125mhz),
.rst(rst_125mhz),
/*
* AXI4-Stream inputs (sink)
*/
.s_axis(axis_eth_stat),
/*
* AXI4-Stream output (source)
*/
.m_axis(axis_stat)
);
// SFP+
assign sfp_tx_disable_b = '1;
if (SFP_RATE == 0) begin : sfp_mac
taxi_axis_if #(.DATA_W(8), .ID_W(8)) axis_sfp0_eth();
taxi_axis_if #(.DATA_W(96), .KEEP_W(1), .ID_W(8)) axis_sfp0_tx_cpl();
taxi_axis_if #(.DATA_W(8), .ID_W(8)) axis_sfp1_eth();
taxi_axis_if #(.DATA_W(96), .KEEP_W(1), .ID_W(8)) axis_sfp1_tx_cpl();
taxi_eth_mac_1g_fifo #(
.PADDING_EN(1),
.MIN_FRAME_LEN(64),
.STAT_EN(1),
.STAT_TX_LEVEL(1),
.STAT_RX_LEVEL(1),
.STAT_ID_BASE((16+16)*0),
.STAT_UPDATE_PERIOD(1024),
.STAT_STR_EN(1),
.STAT_PREFIX_STR("SFP0"),
.TX_FIFO_DEPTH(16384),
.TX_FRAME_FIFO(1),
.RX_FIFO_DEPTH(16384),
.RX_FRAME_FIFO(1)
)
sfp0_eth_mac_inst (
.rx_clk(sfp0_gmii_clk),
.rx_rst(sfp0_gmii_rst),
.tx_clk(sfp0_gmii_clk),
.tx_rst(sfp0_gmii_rst),
.logic_clk(clk_125mhz),
.logic_rst(rst_125mhz),
/*
* Transmit interface (AXI stream)
*/
.s_axis_tx(axis_sfp0_eth),
.m_axis_tx_cpl(axis_sfp0_tx_cpl),
/*
* Receive interface (AXI stream)
*/
.m_axis_rx(axis_sfp0_eth),
/*
* GMII interface
*/
.gmii_rxd(sfp0_gmii_rxd),
.gmii_rx_dv(sfp0_gmii_rx_dv),
.gmii_rx_er(sfp0_gmii_rx_er),
.gmii_txd(sfp0_gmii_txd),
.gmii_tx_en(sfp0_gmii_tx_en),
.gmii_tx_er(sfp0_gmii_tx_er),
/*
* Control
*/
.rx_clk_enable(sfp0_gmii_clk_en),
.tx_clk_enable(sfp0_gmii_clk_en),
.rx_mii_select(1'b0),
.tx_mii_select(1'b0),
/*
* Statistics
*/
.stat_clk(clk_125mhz),
.stat_rst(rst_125mhz),
.m_axis_stat(axis_eth_stat[0]),
/*
* Status
*/
.tx_error_underflow(),
.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(),
/*
* Configuration
*/
.cfg_tx_max_pkt_len(16'd9218),
.cfg_tx_ifg(8'd12),
.cfg_tx_enable(1'b1),
.cfg_rx_max_pkt_len(16'd9218),
.cfg_rx_enable(1'b1)
);
taxi_eth_mac_1g_fifo #(
.PADDING_EN(1),
.MIN_FRAME_LEN(64),
.STAT_EN(1),
.STAT_TX_LEVEL(1),
.STAT_RX_LEVEL(1),
.STAT_ID_BASE((16+16)*1),
.STAT_UPDATE_PERIOD(1024),
.STAT_STR_EN(1),
.STAT_PREFIX_STR("SFP1"),
.TX_FIFO_DEPTH(16384),
.TX_FRAME_FIFO(1),
.RX_FIFO_DEPTH(16384),
.RX_FRAME_FIFO(1)
)
sfp1_eth_mac_inst (
.rx_clk(sfp1_gmii_clk),
.rx_rst(sfp1_gmii_rst),
.tx_clk(sfp1_gmii_clk),
.tx_rst(sfp1_gmii_rst),
.logic_clk(clk_125mhz),
.logic_rst(rst_125mhz),
/*
* Transmit interface (AXI stream)
*/
.s_axis_tx(axis_sfp1_eth),
.m_axis_tx_cpl(axis_sfp1_tx_cpl),
/*
* Receive interface (AXI stream)
*/
.m_axis_rx(axis_sfp1_eth),
/*
* GMII interface
*/
.gmii_rxd(sfp1_gmii_rxd),
.gmii_rx_dv(sfp1_gmii_rx_dv),
.gmii_rx_er(sfp1_gmii_rx_er),
.gmii_txd(sfp1_gmii_txd),
.gmii_tx_en(sfp1_gmii_tx_en),
.gmii_tx_er(sfp1_gmii_tx_er),
/*
* Control
*/
.rx_clk_enable(sfp1_gmii_clk_en),
.tx_clk_enable(sfp1_gmii_clk_en),
.rx_mii_select(1'b0),
.tx_mii_select(1'b0),
/*
* Statistics
*/
.stat_clk(clk_125mhz),
.stat_rst(rst_125mhz),
.m_axis_stat(axis_eth_stat[1]),
/*
* Status
*/
.tx_error_underflow(),
.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(),
/*
* Configuration
*/
.cfg_tx_max_pkt_len(16'd9218),
.cfg_tx_ifg(8'd12),
.cfg_tx_enable(1'b1),
.cfg_rx_max_pkt_len(16'd9218),
.cfg_rx_enable(1'b1)
);
end else begin : sfp_mac
wire [1:0] sfp_tx_clk;
wire [1:0] sfp_tx_rst;
wire [1:0] sfp_rx_clk;
wire [1:0] sfp_rx_rst;
wire [1:0] sfp_rx_status;
wire sfp_gtpowergood;
wire sfp_mgt_refclk_0;
wire sfp_mgt_refclk_0_int;
wire sfp_mgt_refclk_0_bufg;
wire sfp_rst;
taxi_axis_if #(.DATA_W(64), .ID_W(8)) axis_sfp_tx[2]();
taxi_axis_if #(.DATA_W(96), .KEEP_W(1), .ID_W(8)) axis_sfp_tx_cpl[2]();
taxi_axis_if #(.DATA_W(64), .ID_W(8)) axis_sfp_rx[2]();
if (SIM) begin
assign sfp_mgt_refclk_0 = sfp_mgt_refclk_0_p;
assign sfp_mgt_refclk_0_int = sfp_mgt_refclk_0_p;
assign sfp_mgt_refclk_0_bufg = sfp_mgt_refclk_0_int;
end else begin
IBUFDS_GTE4 ibufds_gte4_sfp_mgt_refclk_0_inst (
.I (sfp_mgt_refclk_0_p),
.IB (sfp_mgt_refclk_0_n),
.CEB (1'b0),
.O (sfp_mgt_refclk_0),
.ODIV2 (sfp_mgt_refclk_0_int)
);
BUFG_GT bufg_gt_sfp_mgt_refclk_0_inst (
.CE (sfp_gtpowergood),
.CEMASK (1'b1),
.CLR (1'b0),
.CLRMASK (1'b1),
.DIV (3'd0),
.I (sfp_mgt_refclk_0_int),
.O (sfp_mgt_refclk_0_bufg)
);
end
taxi_sync_reset #(
.N(4)
)
sfp_sync_reset_inst (
.clk(sfp_mgt_refclk_0_bufg),
.rst(rst_125mhz),
.out(sfp_rst)
);
taxi_eth_mac_25g_us #(
.SIM(SIM),
.VENDOR(VENDOR),
.FAMILY(FAMILY),
.CNT(2),
// GT type
.GT_TYPE("GTH"),
// PHY parameters
.PADDING_EN(1'b1),
.DIC_EN(1'b1),
.MIN_FRAME_LEN(64),
.PTP_TS_EN(1'b0),
.PTP_TS_FMT_TOD(1'b1),
.PTP_TS_W(96),
.PRBS31_EN(1'b0),
.TX_SERDES_PIPELINE(1),
.RX_SERDES_PIPELINE(1),
.COUNT_125US(125000/6.4),
.STAT_EN(1),
.STAT_TX_LEVEL(1),
.STAT_RX_LEVEL(1),
.STAT_ID_BASE(0),
.STAT_UPDATE_PERIOD(1024)//,
// disabled due to verilator bug
// .STAT_STR_EN(1),
// .STAT_PREFIX_STR('{"SFP0", "SFP1"})
)
sfp_mac_inst (
.xcvr_ctrl_clk(clk_125mhz),
.xcvr_ctrl_rst(sfp_rst),
/*
* Common
*/
.xcvr_gtpowergood_out(sfp_gtpowergood),
.xcvr_gtrefclk00_in(sfp_mgt_refclk_0),
.xcvr_qpll0lock_out(),
.xcvr_qpll0clk_out(),
.xcvr_qpll0refclk_out(),
/*
* Serial data
*/
.xcvr_txp(sfp_tx_p),
.xcvr_txn(sfp_tx_n),
.xcvr_rxp(sfp_rx_p),
.xcvr_rxn(sfp_rx_n),
/*
* MAC clocks
*/
.rx_clk(sfp_rx_clk),
.rx_rst_in('0),
.rx_rst_out(sfp_rx_rst),
.tx_clk(sfp_tx_clk),
.tx_rst_in('0),
.tx_rst_out(sfp_tx_rst),
.ptp_sample_clk('0),
/*
* Transmit interface (AXI stream)
*/
.s_axis_tx(axis_sfp_tx),
.m_axis_tx_cpl(axis_sfp_tx_cpl),
/*
* Receive interface (AXI stream)
*/
.m_axis_rx(axis_sfp_rx),
/*
* PTP clock
*/
.tx_ptp_ts('{2{'0}}),
.tx_ptp_ts_step('0),
.rx_ptp_ts('{2{'0}}),
.rx_ptp_ts_step('0),
/*
* Link-level Flow Control (LFC) (IEEE 802.3 annex 31B PAUSE)
*/
.tx_lfc_req('0),
.tx_lfc_resend('0),
.rx_lfc_en('0),
.rx_lfc_req(),
.rx_lfc_ack('0),
/*
* Priority Flow Control (PFC) (IEEE 802.3 annex 31D PFC)
*/
.tx_pfc_req('{2{'0}}),
.tx_pfc_resend('0),
.rx_pfc_en('{2{'0}}),
.rx_pfc_req(),
.rx_pfc_ack('{2{'0}}),
/*
* Pause interface
*/
.tx_lfc_pause_en('0),
.tx_pause_req('0),
.tx_pause_ack(),
/*
* Statistics
*/
.stat_clk(clk_125mhz),
.stat_rst(rst_125mhz),
.m_axis_stat(axis_eth_stat[0]),
/*
* Status
*/
.tx_start_packet(),
.stat_tx_byte(),
.stat_tx_pkt_len(),
.stat_tx_pkt_ucast(),
.stat_tx_pkt_mcast(),
.stat_tx_pkt_bcast(),
.stat_tx_pkt_vlan(),
.stat_tx_pkt_good(),
.stat_tx_pkt_bad(),
.stat_tx_err_oversize(),
.stat_tx_err_user(),
.stat_tx_err_underflow(),
.rx_start_packet(),
.rx_error_count(),
.rx_block_lock(),
.rx_high_ber(),
.rx_status(sfp_rx_status),
.stat_rx_byte(),
.stat_rx_pkt_len(),
.stat_rx_pkt_fragment(),
.stat_rx_pkt_jabber(),
.stat_rx_pkt_ucast(),
.stat_rx_pkt_mcast(),
.stat_rx_pkt_bcast(),
.stat_rx_pkt_vlan(),
.stat_rx_pkt_good(),
.stat_rx_pkt_bad(),
.stat_rx_err_oversize(),
.stat_rx_err_bad_fcs(),
.stat_rx_err_bad_block(),
.stat_rx_err_framing(),
.stat_rx_err_preamble(),
.stat_rx_fifo_drop('0),
.stat_tx_mcf(),
.stat_rx_mcf(),
.stat_tx_lfc_pkt(),
.stat_tx_lfc_xon(),
.stat_tx_lfc_xoff(),
.stat_tx_lfc_paused(),
.stat_tx_pfc_pkt(),
.stat_tx_pfc_xon(),
.stat_tx_pfc_xoff(),
.stat_tx_pfc_paused(),
.stat_rx_lfc_pkt(),
.stat_rx_lfc_xon(),
.stat_rx_lfc_xoff(),
.stat_rx_lfc_paused(),
.stat_rx_pfc_pkt(),
.stat_rx_pfc_xon(),
.stat_rx_pfc_xoff(),
.stat_rx_pfc_paused(),
/*
* Configuration
*/
.cfg_tx_max_pkt_len('{2{16'd9218}}),
.cfg_tx_ifg('{2{8'd12}}),
.cfg_tx_enable('1),
.cfg_rx_max_pkt_len('{2{16'd9218}}),
.cfg_rx_enable('1),
.cfg_tx_prbs31_enable('0),
.cfg_rx_prbs31_enable('0),
.cfg_mcf_rx_eth_dst_mcast('{2{48'h01_80_C2_00_00_01}}),
.cfg_mcf_rx_check_eth_dst_mcast('1),
.cfg_mcf_rx_eth_dst_ucast('{2{48'd0}}),
.cfg_mcf_rx_check_eth_dst_ucast('0),
.cfg_mcf_rx_eth_src('{2{48'd0}}),
.cfg_mcf_rx_check_eth_src('0),
.cfg_mcf_rx_eth_type('{2{16'h8808}}),
.cfg_mcf_rx_opcode_lfc('{2{16'h0001}}),
.cfg_mcf_rx_check_opcode_lfc('1),
.cfg_mcf_rx_opcode_pfc('{2{16'h0101}}),
.cfg_mcf_rx_check_opcode_pfc('1),
.cfg_mcf_rx_forward('0),
.cfg_mcf_rx_enable('0),
.cfg_tx_lfc_eth_dst('{2{48'h01_80_C2_00_00_01}}),
.cfg_tx_lfc_eth_src('{2{48'h80_23_31_43_54_4C}}),
.cfg_tx_lfc_eth_type('{2{16'h8808}}),
.cfg_tx_lfc_opcode('{2{16'h0001}}),
.cfg_tx_lfc_en('0),
.cfg_tx_lfc_quanta('{2{16'hffff}}),
.cfg_tx_lfc_refresh('{2{16'h7fff}}),
.cfg_tx_pfc_eth_dst('{2{48'h01_80_C2_00_00_01}}),
.cfg_tx_pfc_eth_src('{2{48'h80_23_31_43_54_4C}}),
.cfg_tx_pfc_eth_type('{2{16'h8808}}),
.cfg_tx_pfc_opcode('{2{16'h0101}}),
.cfg_tx_pfc_en('0),
.cfg_tx_pfc_quanta('{2{'{8{16'hffff}}}}),
.cfg_tx_pfc_refresh('{2{'{8{16'h7fff}}}}),
.cfg_rx_lfc_opcode('{2{16'h0001}}),
.cfg_rx_lfc_en('0),
.cfg_rx_pfc_opcode('{2{16'h0101}}),
.cfg_rx_pfc_en('0)
);
for (genvar n = 0; n < 2; n = n + 1) begin : sfp_ch
taxi_axis_async_fifo #(
.DEPTH(16384),
.RAM_PIPELINE(2),
.FRAME_FIFO(1),
.USER_BAD_FRAME_VALUE(1'b1),
.USER_BAD_FRAME_MASK(1'b1),
.DROP_OVERSIZE_FRAME(1),
.DROP_BAD_FRAME(1),
.DROP_WHEN_FULL(1)
)
ch_fifo (
/*
* AXI4-Stream input (sink)
*/
.s_clk(sfp_rx_clk[n]),
.s_rst(sfp_rx_rst[n]),
.s_axis(axis_sfp_rx[n]),
/*
* AXI4-Stream output (source)
*/
.m_clk(sfp_tx_clk[n]),
.m_rst(sfp_tx_rst[n]),
.m_axis(axis_sfp_tx[n]),
/*
* Pause
*/
.s_pause_req(1'b0),
.s_pause_ack(),
.m_pause_req(1'b0),
.m_pause_ack(),
/*
* Status
*/
.s_status_depth(),
.s_status_depth_commit(),
.s_status_overflow(),
.s_status_bad_frame(),
.s_status_good_frame(),
.m_status_depth(),
.m_status_depth_commit(),
.m_status_overflow(),
.m_status_bad_frame(),
.m_status_good_frame()
);
end
end
endmodule
`resetall

View File

@@ -0,0 +1,60 @@
# SPDX-License-Identifier: MIT
#
# Copyright (c) 2020-2025 FPGA Ninja, LLC
#
# Authors:
# - Alex Forencich
TOPLEVEL_LANG = verilog
SIM ?= verilator
WAVES ?= 0
COCOTB_HDL_TIMEUNIT = 1ns
COCOTB_HDL_TIMEPRECISION = 1ps
RTL_DIR = ../../rtl
LIB_DIR = ../../lib
TAXI_SRC_DIR = $(LIB_DIR)/taxi/src
DUT = fpga_core
COCOTB_TEST_MODULES = test_$(DUT)
COCOTB_TOPLEVEL = $(DUT)
MODULE = $(COCOTB_TEST_MODULES)
TOPLEVEL = $(COCOTB_TOPLEVEL)
VERILOG_SOURCES += $(RTL_DIR)/$(DUT).sv
VERILOG_SOURCES += $(TAXI_SRC_DIR)/eth/rtl/taxi_eth_mac_1g_fifo.f
VERILOG_SOURCES += $(TAXI_SRC_DIR)/eth/rtl/us/taxi_eth_mac_25g_us.f
VERILOG_SOURCES += $(TAXI_SRC_DIR)/xfcp/rtl/taxi_xfcp_if_uart.f
VERILOG_SOURCES += $(TAXI_SRC_DIR)/xfcp/rtl/taxi_xfcp_switch.sv
VERILOG_SOURCES += $(TAXI_SRC_DIR)/xfcp/rtl/taxi_xfcp_mod_stats.f
VERILOG_SOURCES += $(TAXI_SRC_DIR)/sync/rtl/taxi_sync_reset.sv
VERILOG_SOURCES += $(TAXI_SRC_DIR)/sync/rtl/taxi_sync_signal.sv
VERILOG_SOURCES += $(TAXI_SRC_DIR)/io/rtl/taxi_debounce_switch.sv
# handle file list files
process_f_file = $(call process_f_files,$(addprefix $(dir $1),$(shell cat $1)))
process_f_files = $(foreach f,$1,$(if $(filter %.f,$f),$(call process_f_file,$f),$f))
uniq_base = $(if $1,$(call uniq_base,$(foreach f,$1,$(if $(filter-out $(notdir $(lastword $1)),$(notdir $f)),$f,))) $(lastword $1))
VERILOG_SOURCES := $(call uniq_base,$(call process_f_files,$(VERILOG_SOURCES)))
# module parameters
export PARAM_SIM := "1'b1"
export PARAM_VENDOR := "\"XILINX\""
export PARAM_FAMILY := "\"zynquplus\""
export PARAM_SFP_RATE := "1'b1"
ifeq ($(SIM), icarus)
PLUSARGS += -fst
COMPILE_ARGS += $(foreach v,$(filter PARAM_%,$(.VARIABLES)),-P $(COCOTB_TOPLEVEL).$(subst PARAM_,,$(v))=$($(v)))
else ifeq ($(SIM), verilator)
COMPILE_ARGS += $(foreach v,$(filter PARAM_%,$(.VARIABLES)),-G$(subst PARAM_,,$(v))=$($(v)))
ifeq ($(WAVES), 1)
COMPILE_ARGS += --trace-fst
VERILATOR_TRACE = 1
endif
endif
include $(shell cocotb-config --makefiles)/Makefile.sim

View File

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

View File

@@ -0,0 +1,276 @@
#!/usr/bin/env python
# SPDX-License-Identifier: MIT
"""
Copyright (c) 2020-2025 FPGA Ninja, LLC
Authors:
- Alex Forencich
"""
import logging
import os
import sys
import pytest
import cocotb_test.simulator
import cocotb
from cocotb.log import SimLog
from cocotb.clock import Clock
from cocotb.triggers import RisingEdge, Combine
from cocotbext.eth import GmiiFrame, GmiiSource, GmiiSink
from cocotbext.eth import XgmiiFrame
from cocotbext.uart import UartSource, UartSink
try:
from baser import BaseRSerdesSource, BaseRSerdesSink
except ImportError:
# attempt import from current directory
sys.path.insert(0, os.path.join(os.path.dirname(__file__)))
try:
from baser import BaseRSerdesSource, BaseRSerdesSink
finally:
del sys.path[0]
class TB:
def __init__(self, dut, speed=1000e6):
self.dut = dut
self.log = SimLog("cocotb.tb")
self.log.setLevel(logging.DEBUG)
cocotb.start_soon(Clock(dut.clk_125mhz, 8, units="ns").start())
self.sfp_sources = []
self.sfp_sinks = []
if dut.SFP_RATE.value == 0:
cocotb.start_soon(Clock(dut.sfp0_gmii_clk, 8, units="ns").start())
cocotb.start_soon(Clock(dut.sfp1_gmii_clk, 8, units="ns").start())
self.sfp_sources.append(GmiiSource(dut.sfp0_gmii_rxd, dut.sfp0_gmii_rx_er, dut.sfp0_gmii_rx_dv,
dut.sfp0_gmii_clk, dut.sfp0_gmii_rst, dut.sfp0_gmii_clk_en))
self.sfp_sinks.append(GmiiSink(dut.sfp0_gmii_txd, dut.sfp0_gmii_tx_er, dut.sfp0_gmii_tx_en,
dut.sfp0_gmii_clk, dut.sfp0_gmii_rst, dut.sfp0_gmii_clk_en))
self.sfp_sources.append(GmiiSource(dut.sfp1_gmii_rxd, dut.sfp1_gmii_rx_er, dut.sfp1_gmii_rx_dv,
dut.sfp1_gmii_clk, dut.sfp1_gmii_rst, dut.sfp1_gmii_clk_en))
self.sfp_sinks.append(GmiiSink(dut.sfp1_gmii_txd, dut.sfp1_gmii_tx_er, dut.sfp1_gmii_tx_en,
dut.sfp1_gmii_clk, dut.sfp1_gmii_rst, dut.sfp1_gmii_clk_en))
else:
cocotb.start_soon(Clock(dut.sfp_mgt_refclk_0_p, 6.4, units="ns").start())
for ch in dut.sfp_mac.sfp_mac_inst.ch:
cocotb.start_soon(Clock(ch.ch_inst.gt_inst.tx_clk, 6.4, units="ns").start())
cocotb.start_soon(Clock(ch.ch_inst.gt_inst.rx_clk, 6.4, units="ns").start())
self.sfp_sources.append(BaseRSerdesSource(ch.ch_inst.serdes_rx_data, ch.ch_inst.serdes_rx_hdr, ch.ch_inst.gt_inst.rx_clk, slip=ch.ch_inst.serdes_rx_bitslip, reverse=True))
self.sfp_sinks.append(BaseRSerdesSink(ch.ch_inst.serdes_tx_data, ch.ch_inst.serdes_tx_hdr, ch.ch_inst.gt_inst.tx_clk, reverse=True))
self.uart_source = UartSource(dut.uart_rxd, baud=2000000, bits=8, stop_bits=1)
self.uart_sink = UartSink(dut.uart_txd, baud=2000000, bits=8, stop_bits=1)
dut.btnu.setimmediatevalue(0)
dut.btnl.setimmediatevalue(0)
dut.btnd.setimmediatevalue(0)
dut.btnr.setimmediatevalue(0)
dut.btnc.setimmediatevalue(0)
dut.sw.setimmediatevalue(0)
dut.uart_rts.setimmediatevalue(0)
async def init(self):
self.dut.rst_125mhz.setimmediatevalue(0)
self.dut.sfp0_gmii_rst.setimmediatevalue(0)
self.dut.sfp1_gmii_rst.setimmediatevalue(0)
for k in range(10):
await RisingEdge(self.dut.clk_125mhz)
self.dut.rst_125mhz.value = 1
self.dut.sfp0_gmii_rst.value = 1
self.dut.sfp1_gmii_rst.value = 1
for k in range(10):
await RisingEdge(self.dut.clk_125mhz)
self.dut.rst_125mhz.value = 0
self.dut.sfp0_gmii_rst.value = 0
self.dut.sfp1_gmii_rst.value = 0
for k in range(10):
await RisingEdge(self.dut.clk_125mhz)
async def mac_test(tb, source, sink):
tb.log.info("Test MAC")
tb.log.info("Multiple small packets")
count = 64
pkts = [bytearray([(x+k) % 256 for x in range(60)]) for k in range(count)]
for p in pkts:
await source.send(GmiiFrame.from_payload(p))
for k in range(count):
rx_frame = await sink.recv()
tb.log.info("RX frame: %s", rx_frame)
assert rx_frame.get_payload() == pkts[k]
assert rx_frame.check_fcs()
assert rx_frame.error is None
tb.log.info("Multiple large packets")
count = 32
pkts = [bytearray([(x+k) % 256 for x in range(1514)]) for k in range(count)]
for p in pkts:
await source.send(GmiiFrame.from_payload(p))
for k in range(count):
rx_frame = await sink.recv()
tb.log.info("RX frame: %s", rx_frame)
assert rx_frame.get_payload() == pkts[k]
assert rx_frame.check_fcs()
assert rx_frame.error is None
tb.log.info("MAC test done")
async def mac_test_25g(tb, source, sink):
tb.log.info("Test MAC")
tb.log.info("Multiple small packets")
count = 64
pkts = [bytearray([(x+k) % 256 for x in range(60)]) for k in range(count)]
for p in pkts:
await source.send(XgmiiFrame.from_payload(p))
for k in range(count):
rx_frame = await sink.recv()
tb.log.info("RX frame: %s", rx_frame)
assert rx_frame.get_payload() == pkts[k]
assert rx_frame.check_fcs()
tb.log.info("Multiple large packets")
count = 32
pkts = [bytearray([(x+k) % 256 for x in range(1514)]) for k in range(count)]
for p in pkts:
await source.send(XgmiiFrame.from_payload(p))
for k in range(count):
rx_frame = await sink.recv()
tb.log.info("RX frame: %s", rx_frame)
assert rx_frame.get_payload() == pkts[k]
assert rx_frame.check_fcs()
tb.log.info("MAC test done")
@cocotb.test()
async def run_test(dut):
tb = TB(dut)
await tb.init()
tests = []
for k in range(len(tb.sfp_sources)):
if dut.SFP_RATE.value == 0:
tb.log.info("Start SFP %d 1G MAC loopback test", k)
tests.append(cocotb.start_soon(mac_test(tb, tb.sfp_sources[k], tb.sfp_sinks[k])))
else:
tb.log.info("Start SFP %d 10G MAC loopback test", k)
tests.append(cocotb.start_soon(mac_test_25g(tb, tb.sfp_sources[k], tb.sfp_sinks[k])))
await Combine(*tests)
await RisingEdge(dut.clk_125mhz)
await RisingEdge(dut.clk_125mhz)
# 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(tests_dir, '..', '..', 'lib'))
taxi_src_dir = os.path.abspath(os.path.join(lib_dir, 'taxi', 'src'))
def process_f_files(files):
lst = {}
for f in files:
if f[-2:].lower() == '.f':
with open(f, 'r') as fp:
l = fp.read().split()
for f in process_f_files([os.path.join(os.path.dirname(f), x) for x in l]):
lst[os.path.basename(f)] = f
else:
lst[os.path.basename(f)] = f
return list(lst.values())
@pytest.mark.parametrize("sfp_rate", [0, 1])
def test_fpga_core(request, sfp_rate):
dut = "fpga_core"
module = os.path.splitext(os.path.basename(__file__))[0]
toplevel = dut
verilog_sources = [
os.path.join(rtl_dir, f"{dut}.sv"),
os.path.join(taxi_src_dir, "eth", "rtl", "taxi_eth_mac_1g_fifo.f"),
os.path.join(taxi_src_dir, "eth", "rtl", "us", "taxi_eth_mac_25g_us.f"),
os.path.join(taxi_src_dir, "xfcp", "rtl", "taxi_xfcp_if_uart.f"),
os.path.join(taxi_src_dir, "xfcp", "rtl", "taxi_xfcp_switch.sv"),
os.path.join(taxi_src_dir, "xfcp", "rtl", "taxi_xfcp_mod_stats.f"),
os.path.join(taxi_src_dir, "sync", "rtl", "taxi_sync_reset.sv"),
os.path.join(taxi_src_dir, "sync", "rtl", "taxi_sync_signal.sv"),
os.path.join(taxi_src_dir, "io", "rtl", "taxi_debounce_switch.sv"),
]
verilog_sources = process_f_files(verilog_sources)
parameters = {}
parameters['SIM'] = "1'b1"
parameters['VENDOR'] = "\"XILINX\""
parameters['FAMILY'] = "\"zynquplus\""
parameters['SFP_RATE'] = f"1'b{sfp_rate}"
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(
simulator="verilator",
python_search=[tests_dir],
verilog_sources=verilog_sources,
toplevel=toplevel,
module=module,
parameters=parameters,
sim_build=sim_build,
extra_env=extra_env,
)