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

merged changes in eth

This commit is contained in:
Alex Forencich 2023-11-07 13:50:38 -08:00
commit 56887b8aed
89 changed files with 4329 additions and 7259 deletions

View File

@ -307,6 +307,14 @@ PTP clock CDC module with PPS output. Use this module to transfer and deskew a
free-running PTP clock across clock domains. Supports both 64 and 96 bit
timestamp formats.
### `ptp_td_leaf` module
PTP time distribution leaf clock module. Accepts PTP time distribution messages from the `ptp_td_phc` module, and outputs both the 96-bit time-of-day timestamp and 64-bit relative timestamp in the destination clock domain, as well as both single-cycle and stretched PPS outputs. Also supports pipelining the serial data input, automatically compensating for the pipeline delay.
### `ptp_td_phc` module
PTP time distribution master clock module. Generates PTP time distribution messages over a serial interface that can provide PTP time to one or more leaf clocks (`ptp_td_leaf`), as well as both single-cycle and stretched PPS outputs. The fractional nanoseconds portion is shared between the time-of-day and relative timestamps to support reconstruction of the 96-bit time-of-day timestamp from a truncated relative timestamp. The module supports coarse setting of both the ToD and relative timestamps as well as atomically applying offsets to the ToD and relative timestamps and the shared fractional nanoseconds.
### `ptp_ts_extract` module
PTP timestamp extract module. Use this module to extract a PTP timestamp
@ -466,6 +474,8 @@ and data lines.
rtl/oddr.v : Generic DDR output register
rtl/ptp_clock.v : PTP clock
rtl/ptp_clock_cdc.v : PTP clock CDC
rtl/ptp_td_leaf.v : PTP time distribution leaf clock
rtl/ptp_td_phc.v : PTP time distribution master clock
rtl/ptp_ts_extract.v : PTP timestamp extract
rtl/ptp_perout.v : PTP period out
rtl/rgmii_phy_if.v : RGMII PHY interface

View File

@ -1,29 +1,28 @@
# Verilog Ethernet Alveo U200 Example Design
# Verilog Ethernet Alveo U200/Alveo U250/VCU1525 Example Design
## Introduction
This example design targets the Xilinx Alveo U200 FPGA board.
This example design targets the Xilinx Alveo U200/Alveo U250/VCU1525 FPGA board.
The design by default listens to UDP port 1234 at IP address 192.168.1.128 and
will echo back any packets received. The design will also respond correctly
to ARP requests.
The design 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: xcu200-fsgd2104-2-e
* PHY: 10G BASE-R PHY IP core and internal GTY transceiver
* FPGA
* AU200: xcu200-fsgd2104-2-e
* AU250: xcu250-fsgd2104-2-e
* VCU1525: xcvu9p-fsgd2104-2L-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.
Run make to build. Ensure that the Xilinx Vivado toolchain components are in PATH.
## How to test
Run make program to program the Alveo U200 board with Vivado. Then run
Run make program to program the FPGA board with Vivado. Then run
netcat -u 192.168.1.128 1234
to open a UDP connection to port 1234. Any text entered into netcat will be
echoed back after pressing enter.
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

View File

@ -1,5 +1,7 @@
# XDC constraints for the Xilinx Alveo U200 board
# part: xcu200-fsgd2104-2-e
# XDC constraints for Xilinx AU200/AU250/VCU1525
# AU200 part: xcu200-fsgd2104-2-e
# AU250 part: xcu250-figd2104-2-e
# VCU1525 part: xcvu9p-fsgd2104-2L-e
# General configuration
set_property CFGBVS GND [current_design]

View File

@ -112,4 +112,3 @@ flash: $(FPGA_TOP).mcs $(FPGA_TOP).prm
echo "boot_hw_device [current_hw_device]" >> flash.tcl
echo "exit" >> flash.tcl
vivado -nojournal -nolog -mode batch -source flash.tcl

View File

@ -112,4 +112,3 @@ flash: $(FPGA_TOP).mcs $(FPGA_TOP).prm
echo "boot_hw_device [current_hw_device]" >> flash.tcl
echo "exit" >> flash.tcl
vivado -nojournal -nolog -mode batch -source flash.tcl

View File

@ -112,4 +112,3 @@ flash: $(FPGA_TOP).mcs $(FPGA_TOP).prm
echo "boot_hw_device [current_hw_device]" >> flash.tcl
echo "exit" >> flash.tcl
vivado -nojournal -nolog -mode batch -source flash.tcl

View File

@ -112,4 +112,3 @@ flash: $(FPGA_TOP).mcs $(FPGA_TOP).prm
echo "boot_hw_device [current_hw_device]" >> flash.tcl
echo "exit" >> flash.tcl
vivado -nojournal -nolog -mode batch -source flash.tcl

View File

@ -65,6 +65,27 @@ CONFIG_TCL_FILES = ./config.tcl
include ../common/vivado.mk
%_fallback.bit: %.bit
echo "open_project $*.xpr" > generate_fallback_bit.tcl
echo "open_run impl_1" >> generate_fallback_bit.tcl
echo "startgroup" >> generate_fallback_bit.tcl
echo "set_property BITSTREAM.CONFIG.CONFIGFALLBACK ENABLE [current_design]" >> generate_fallback_bit.tcl
echo "set_property BITSTREAM.CONFIG.TIMER_CFG 0x03000000 [current_design]" >> generate_fallback_bit.tcl
echo "set_property BITSTREAM.CONFIG.NEXT_CONFIG_REBOOT ENABLE [current_design]" >> generate_fallback_bit.tcl
echo "set_property BITSTREAM.CONFIG.NEXT_CONFIG_ADDR 0x04000000 [current_design]" >> generate_fallback_bit.tcl
echo "endgroup" >> generate_fallback_bit.tcl
echo "write_bitstream -verbose -force $*_fallback.bit" >> generate_fallback_bit.tcl
echo "undo" >> generate_fallback_bit.tcl
echo "exit" >> generate_fallback_bit.tcl
vivado -nojournal -nolog -mode batch -source generate_fallback_bit.tcl
mkdir -p rev
EXT=bit; COUNT=100; \
while [ -e rev/$*_rev$$COUNT.$$EXT ]; \
do COUNT=$$((COUNT+1)); done; \
COUNT=$$((COUNT-1)); \
cp $@ rev/$*_fallback_rev$$COUNT.$$EXT; \
echo "Output: rev/$*_fallback_rev$$COUNT.$$EXT";
program: $(FPGA_TOP).bit
echo "open_hw" > program.tcl
echo "connect_hw_server" >> program.tcl
@ -89,6 +110,32 @@ program: $(FPGA_TOP).bit
do cp $*$$x rev/$*_rev$$COUNT$$x; \
echo "Output: rev/$*_rev$$COUNT$$x"; done;
%_fallback.mcs %_fallback.prm: %_fallback.bit
echo "write_cfgmem -force -format mcs -size 128 -interface SPIx4 -loadbit {up 0x00000000 $*_fallback.bit} -checksum -file $*_fallback.mcs" > generate_fallback_mcs.tcl
echo "exit" >> generate_fallback_mcs.tcl
vivado -nojournal -nolog -mode batch -source generate_fallback_mcs.tcl
mkdir -p rev
COUNT=100; \
while [ -e rev/$*_rev$$COUNT.bit ]; \
do COUNT=$$((COUNT+1)); done; \
COUNT=$$((COUNT-1)); \
for x in .mcs .prm; \
do cp $*_fallback$$x rev/$*_fallback_rev$$COUNT$$x; \
echo "Output: rev/$*_fallback_rev$$COUNT$$x"; done;
%_full.mcs %_full.prm: %_fallback.bit %.bit
echo "write_cfgmem -force -format mcs -size 128 -interface SPIx4 -loadbit {up 0x00000000 $*_fallback.bit up 0x04000000 $*.bit} -checksum -file $*_full.mcs" > generate_full_mcs.tcl
echo "exit" >> generate_full_mcs.tcl
vivado -nojournal -nolog -mode batch -source generate_full_mcs.tcl
mkdir -p rev
COUNT=100; \
while [ -e rev/$*_rev$$COUNT.bit ]; \
do COUNT=$$((COUNT+1)); done; \
COUNT=$$((COUNT-1)); \
for x in .mcs .prm; \
do cp $*_full$$x rev/$*_full_rev$$COUNT$$x; \
echo "Output: rev/$*_full_rev$$COUNT$$x"; done;
flash: $(FPGA_TOP).mcs $(FPGA_TOP).prm
echo "open_hw" > flash.tcl
echo "connect_hw_server" >> flash.tcl
@ -113,3 +160,26 @@ flash: $(FPGA_TOP).mcs $(FPGA_TOP).prm
echo "exit" >> flash.tcl
vivado -nojournal -nolog -mode batch -source flash.tcl
flash%: $(FPGA_TOP)%.mcs $(FPGA_TOP)%.prm
echo "open_hw" > flash$*.tcl
echo "connect_hw_server" >> flash$*.tcl
echo "open_hw_target" >> flash$*.tcl
echo "current_hw_device [lindex [get_hw_devices] 0]" >> flash$*.tcl
echo "refresh_hw_device -update_hw_probes false [current_hw_device]" >> flash$*.tcl
echo "create_hw_cfgmem -hw_device [current_hw_device] [lindex [get_cfgmem_parts {mt25qu01g-spi-x1_x2_x4}] 0]" >> flash$*.tcl
echo "current_hw_cfgmem -hw_device [current_hw_device] [get_property PROGRAM.HW_CFGMEM [current_hw_device]]" >> flash$*.tcl
echo "set_property PROGRAM.FILES [list \"$(FPGA_TOP)$*.mcs\"] [current_hw_cfgmem]" >> flash$*.tcl
echo "set_property PROGRAM.PRM_FILES [list \"$(FPGA_TOP)$*.prm\"] [current_hw_cfgmem]" >> flash$*.tcl
echo "set_property PROGRAM.ERASE 1 [current_hw_cfgmem]" >> flash$*.tcl
echo "set_property PROGRAM.CFG_PROGRAM 1 [current_hw_cfgmem]" >> flash$*.tcl
echo "set_property PROGRAM.VERIFY 1 [current_hw_cfgmem]" >> flash$*.tcl
echo "set_property PROGRAM.CHECKSUM 0 [current_hw_cfgmem]" >> flash$*.tcl
echo "set_property PROGRAM.ADDRESS_RANGE {use_file} [current_hw_cfgmem]" >> flash$*.tcl
echo "set_property PROGRAM.UNUSED_PIN_TERMINATION {pull-none} [current_hw_cfgmem]" >> flash$*.tcl
echo "create_hw_bitstream -hw_device [current_hw_device] [get_property PROGRAM.HW_CFGMEM_BITFILE [current_hw_device]]" >> flash$*.tcl
echo "program_hw_devices [current_hw_device]" >> flash$*.tcl
echo "refresh_hw_device [current_hw_device]" >> flash$*.tcl
echo "program_hw_cfgmem -hw_cfgmem [current_hw_cfgmem]" >> flash$*.tcl
echo "boot_hw_device [current_hw_device]" >> flash$*.tcl
echo "exit" >> flash$*.tcl
vivado -nojournal -nolog -mode batch -source flash$*.tcl

View File

@ -65,6 +65,27 @@ CONFIG_TCL_FILES = ./config.tcl
include ../common/vivado.mk
%_fallback.bit: %.bit
echo "open_project $*.xpr" > generate_fallback_bit.tcl
echo "open_run impl_1" >> generate_fallback_bit.tcl
echo "startgroup" >> generate_fallback_bit.tcl
echo "set_property BITSTREAM.CONFIG.CONFIGFALLBACK ENABLE [current_design]" >> generate_fallback_bit.tcl
echo "set_property BITSTREAM.CONFIG.TIMER_CFG 0x03000000 [current_design]" >> generate_fallback_bit.tcl
echo "set_property BITSTREAM.CONFIG.NEXT_CONFIG_REBOOT ENABLE [current_design]" >> generate_fallback_bit.tcl
echo "set_property BITSTREAM.CONFIG.NEXT_CONFIG_ADDR 0x04000000 [current_design]" >> generate_fallback_bit.tcl
echo "endgroup" >> generate_fallback_bit.tcl
echo "write_bitstream -verbose -force $*_fallback.bit" >> generate_fallback_bit.tcl
echo "undo" >> generate_fallback_bit.tcl
echo "exit" >> generate_fallback_bit.tcl
vivado -nojournal -nolog -mode batch -source generate_fallback_bit.tcl
mkdir -p rev
EXT=bit; COUNT=100; \
while [ -e rev/$*_rev$$COUNT.$$EXT ]; \
do COUNT=$$((COUNT+1)); done; \
COUNT=$$((COUNT-1)); \
cp $@ rev/$*_fallback_rev$$COUNT.$$EXT; \
echo "Output: rev/$*_fallback_rev$$COUNT.$$EXT";
program: $(FPGA_TOP).bit
echo "open_hw" > program.tcl
echo "connect_hw_server" >> program.tcl
@ -89,6 +110,32 @@ program: $(FPGA_TOP).bit
do cp $*$$x rev/$*_rev$$COUNT$$x; \
echo "Output: rev/$*_rev$$COUNT$$x"; done;
%_fallback.mcs %_fallback.prm: %_fallback.bit
echo "write_cfgmem -force -format mcs -size 128 -interface SPIx4 -loadbit {up 0x00000000 $*_fallback.bit} -checksum -file $*_fallback.mcs" > generate_fallback_mcs.tcl
echo "exit" >> generate_fallback_mcs.tcl
vivado -nojournal -nolog -mode batch -source generate_fallback_mcs.tcl
mkdir -p rev
COUNT=100; \
while [ -e rev/$*_rev$$COUNT.bit ]; \
do COUNT=$$((COUNT+1)); done; \
COUNT=$$((COUNT-1)); \
for x in .mcs .prm; \
do cp $*_fallback$$x rev/$*_fallback_rev$$COUNT$$x; \
echo "Output: rev/$*_fallback_rev$$COUNT$$x"; done;
%_full.mcs %_full.prm: %_fallback.bit %.bit
echo "write_cfgmem -force -format mcs -size 128 -interface SPIx4 -loadbit {up 0x00000000 $*_fallback.bit up 0x04000000 $*.bit} -checksum -file $*_full.mcs" > generate_full_mcs.tcl
echo "exit" >> generate_full_mcs.tcl
vivado -nojournal -nolog -mode batch -source generate_full_mcs.tcl
mkdir -p rev
COUNT=100; \
while [ -e rev/$*_rev$$COUNT.bit ]; \
do COUNT=$$((COUNT+1)); done; \
COUNT=$$((COUNT-1)); \
for x in .mcs .prm; \
do cp $*_full$$x rev/$*_full_rev$$COUNT$$x; \
echo "Output: rev/$*_full_rev$$COUNT$$x"; done;
flash: $(FPGA_TOP).mcs $(FPGA_TOP).prm
echo "open_hw" > flash.tcl
echo "connect_hw_server" >> flash.tcl
@ -113,3 +160,26 @@ flash: $(FPGA_TOP).mcs $(FPGA_TOP).prm
echo "exit" >> flash.tcl
vivado -nojournal -nolog -mode batch -source flash.tcl
flash%: $(FPGA_TOP)%.mcs $(FPGA_TOP)%.prm
echo "open_hw" > flash$*.tcl
echo "connect_hw_server" >> flash$*.tcl
echo "open_hw_target" >> flash$*.tcl
echo "current_hw_device [lindex [get_hw_devices] 0]" >> flash$*.tcl
echo "refresh_hw_device -update_hw_probes false [current_hw_device]" >> flash$*.tcl
echo "create_hw_cfgmem -hw_device [current_hw_device] [lindex [get_cfgmem_parts {mt25qu01g-spi-x1_x2_x4}] 0]" >> flash$*.tcl
echo "current_hw_cfgmem -hw_device [current_hw_device] [get_property PROGRAM.HW_CFGMEM [current_hw_device]]" >> flash$*.tcl
echo "set_property PROGRAM.FILES [list \"$(FPGA_TOP)$*.mcs\"] [current_hw_cfgmem]" >> flash$*.tcl
echo "set_property PROGRAM.PRM_FILES [list \"$(FPGA_TOP)$*.prm\"] [current_hw_cfgmem]" >> flash$*.tcl
echo "set_property PROGRAM.ERASE 1 [current_hw_cfgmem]" >> flash$*.tcl
echo "set_property PROGRAM.CFG_PROGRAM 1 [current_hw_cfgmem]" >> flash$*.tcl
echo "set_property PROGRAM.VERIFY 1 [current_hw_cfgmem]" >> flash$*.tcl
echo "set_property PROGRAM.CHECKSUM 0 [current_hw_cfgmem]" >> flash$*.tcl
echo "set_property PROGRAM.ADDRESS_RANGE {use_file} [current_hw_cfgmem]" >> flash$*.tcl
echo "set_property PROGRAM.UNUSED_PIN_TERMINATION {pull-none} [current_hw_cfgmem]" >> flash$*.tcl
echo "create_hw_bitstream -hw_device [current_hw_device] [get_property PROGRAM.HW_CFGMEM_BITFILE [current_hw_device]]" >> flash$*.tcl
echo "program_hw_devices [current_hw_device]" >> flash$*.tcl
echo "refresh_hw_device [current_hw_device]" >> flash$*.tcl
echo "program_hw_cfgmem -hw_cfgmem [current_hw_cfgmem]" >> flash$*.tcl
echo "boot_hw_device [current_hw_device]" >> flash$*.tcl
echo "exit" >> flash$*.tcl
vivado -nojournal -nolog -mode batch -source flash$*.tcl

View File

@ -1,25 +0,0 @@
# Targets
TARGETS:=
# Subdirectories
SUBDIRS = fpga
SUBDIRS_CLEAN = $(patsubst %,%.clean,$(SUBDIRS))
# Rules
.PHONY: all
all: $(SUBDIRS) $(TARGETS)
.PHONY: $(SUBDIRS)
$(SUBDIRS):
cd $@ && $(MAKE)
.PHONY: $(SUBDIRS_CLEAN)
$(SUBDIRS_CLEAN):
cd $(@:.clean=) && $(MAKE) clean
.PHONY: clean
clean: $(SUBDIRS_CLEAN)
-rm -rf $(TARGETS)
program:
#djtgcfg prog -d Atlys --index 0 --file fpga/fpga.bit

View File

@ -1,30 +0,0 @@
# Verilog Ethernet Alveo U250 Example Design
## Introduction
This example design targets the Xilinx Alveo U250 FPGA board.
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: xcu250-figd2104-2-e
* PHY: 10G BASE-R PHY IP core and internal GTY transceiver
## How to build
Run make to build. Ensure that the Xilinx Vivado toolchain components are
in PATH.
## How to test
Run make program to program the Alveo U250 board with Vivado. Then run
netcat -u 192.168.1.128 1234
to open a UDP connection to port 1234. Any text entered into netcat will be
echoed back after pressing enter.
It is also possible to use hping to test the design by running
hping 192.168.1.128 -2 -p 1234 -d 1024

View File

@ -1,137 +0,0 @@
###################################################################
#
# 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

@ -1,848 +0,0 @@
# XDC constraints for the Xilinx Alveo U250 board
# part: xcu250-figd2104-2-e
# General configuration
set_property CFGBVS GND [current_design]
set_property CONFIG_VOLTAGE 1.8 [current_design]
set_property BITSTREAM.GENERAL.COMPRESS true [current_design]
set_property BITSTREAM.CONFIG.CONFIGFALLBACK ENABLE [current_design]
set_property BITSTREAM.CONFIG.EXTMASTERCCLK_EN DISABLE [current_design]
set_property BITSTREAM.CONFIG.CONFIGRATE 63.8 [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.UNUSEDPIN PULLUP [current_design]
set_property BITSTREAM.CONFIG.OVERTEMPSHUTDOWN Enable [current_design]
set_operating_conditions -design_power_budget 160
# System clocks
# 300 MHz (DDR 0)
#set_property -dict {LOC AY37 IOSTANDARD LVDS} [get_ports clk_300mhz_0_p]
#set_property -dict {LOC AY38 IOSTANDARD LVDS} [get_ports clk_300mhz_0_n]
#create_clock -period 3.333 -name clk_300mhz_0 [get_ports clk_300mhz_0_p]
# 300 MHz (DDR 1)
#set_property -dict {LOC AW20 IOSTANDARD LVDS} [get_ports clk_300mhz_1_p]
#set_property -dict {LOC AW19 IOSTANDARD LVDS} [get_ports clk_300mhz_1_n]
#create_clock -period 3.333 -name clk_300mhz_1 [get_ports clk_300mhz_1_p]
# 300 MHz (DDR 2)
#set_property -dict {LOC F32 IOSTANDARD LVDS} [get_ports clk_300mhz_2_p]
#set_property -dict {LOC E32 IOSTANDARD LVDS} [get_ports clk_300mhz_2_n]
#create_clock -period 3.333 -name clk_300mhz_2 [get_ports clk_300mhz_2_p]
# 300 MHz (DDR 3)
#set_property -dict {LOC J16 IOSTANDARD LVDS} [get_ports clk_300mhz_3_p]
#set_property -dict {LOC H16 IOSTANDARD LVDS} [get_ports clk_300mhz_3_n]
#create_clock -period 3.333 -name clk_300mhz_3 [get_ports clk_300mhz_3_p]
# SI570 user clock
#set_property -dict {LOC AU19 IOSTANDARD LVDS} [get_ports clk_user_p]
#set_property -dict {LOC AV19 IOSTANDARD LVDS} [get_ports clk_user_n]
#create_clock -period 6.400 -name clk_user [get_ports clk_user_p]
# LEDs
set_property -dict {LOC BC21 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {led[0]}]
set_property -dict {LOC BB21 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {led[1]}]
set_property -dict {LOC BA20 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {led[2]}]
set_false_path -to [get_ports {led[*]}]
set_output_delay 0 [get_ports {led[*]}]
# Reset button
set_property -dict {LOC AL20 IOSTANDARD LVCMOS12} [get_ports reset]
set_false_path -from [get_ports {reset}]
set_input_delay 0 [get_ports {reset}]
# DIP switches
set_property -dict {LOC AN22 IOSTANDARD LVCMOS12} [get_ports {sw[0]}]
set_property -dict {LOC AM19 IOSTANDARD LVCMOS12} [get_ports {sw[1]}]
set_property -dict {LOC AL19 IOSTANDARD LVCMOS12} [get_ports {sw[2]}]
set_property -dict {LOC AP20 IOSTANDARD LVCMOS12} [get_ports {sw[3]}]
set_false_path -from [get_ports {sw[*]}]
set_input_delay 0 [get_ports {sw[*]}]
# UART
set_property -dict {LOC BF18 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports uart_txd]
set_property -dict {LOC BB20 IOSTANDARD LVCMOS12} [get_ports uart_rxd]
#set_false_path -to [get_ports {uart_txd}]
#set_output_delay 0 [get_ports {uart_txd}]
#set_false_path -from [get_ports {uart_rxd}]
#set_input_delay 0 [get_ports {uart_rxd}]
# BMC
#set_property -dict {LOC AR20 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 4} [get_ports {msp_gpio[0]}]
#set_property -dict {LOC AM20 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 4} [get_ports {msp_gpio[1]}]
#set_property -dict {LOC AM21 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 4} [get_ports {msp_gpio[2]}]
#set_property -dict {LOC AN21 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 4} [get_ports {msp_gpio[3]}]
#set_property -dict {LOC BB19 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 4} [get_ports {msp_uart_txd}]
#set_property -dict {LOC BA19 IOSTANDARD LVCMOS12} [get_ports {msp_uart_rxd}]
#set_false_path -to [get_ports {msp_uart_txd}]
#set_output_delay 0 [get_ports {msp_uart_txd}]
#set_false_path -from [get_ports {msp_gpio[*] msp_uart_rxd}]
#set_input_delay 0 [get_ports {msp_gpio[*] msp_uart_rxd}]
# QSFP28 Interfaces
set_property -dict {LOC N4 } [get_ports {qsfp0_rx_p[0]}] ;# MGTYRXP0_231 GTYE4_CHANNEL_X1Y44 / GTYE4_COMMON_X1Y11
set_property -dict {LOC N3 } [get_ports {qsfp0_rx_n[0]}] ;# MGTYRXN0_231 GTYE4_CHANNEL_X1Y44 / GTYE4_COMMON_X1Y11
set_property -dict {LOC N9 } [get_ports {qsfp0_tx_p[0]}] ;# MGTYTXP0_231 GTYE4_CHANNEL_X1Y44 / GTYE4_COMMON_X1Y11
set_property -dict {LOC N8 } [get_ports {qsfp0_tx_n[0]}] ;# MGTYTXN0_231 GTYE4_CHANNEL_X1Y44 / GTYE4_COMMON_X1Y11
set_property -dict {LOC M2 } [get_ports {qsfp0_rx_p[1]}] ;# MGTYRXP1_231 GTYE4_CHANNEL_X1Y45 / GTYE4_COMMON_X1Y11
set_property -dict {LOC M1 } [get_ports {qsfp0_rx_n[1]}] ;# MGTYRXN1_231 GTYE4_CHANNEL_X1Y45 / GTYE4_COMMON_X1Y11
set_property -dict {LOC M7 } [get_ports {qsfp0_tx_p[1]}] ;# MGTYTXP1_231 GTYE4_CHANNEL_X1Y45 / GTYE4_COMMON_X1Y11
set_property -dict {LOC M6 } [get_ports {qsfp0_tx_n[1]}] ;# MGTYTXN1_231 GTYE4_CHANNEL_X1Y45 / GTYE4_COMMON_X1Y11
set_property -dict {LOC L4 } [get_ports {qsfp0_rx_p[2]}] ;# MGTYRXP2_231 GTYE4_CHANNEL_X1Y46 / GTYE4_COMMON_X1Y11
set_property -dict {LOC L3 } [get_ports {qsfp0_rx_n[2]}] ;# MGTYRXN2_231 GTYE4_CHANNEL_X1Y46 / GTYE4_COMMON_X1Y11
set_property -dict {LOC L9 } [get_ports {qsfp0_tx_p[2]}] ;# MGTYTXP2_231 GTYE4_CHANNEL_X1Y46 / GTYE4_COMMON_X1Y11
set_property -dict {LOC L8 } [get_ports {qsfp0_tx_n[2]}] ;# MGTYTXN2_231 GTYE4_CHANNEL_X1Y46 / GTYE4_COMMON_X1Y11
set_property -dict {LOC K2 } [get_ports {qsfp0_rx_p[3]}] ;# MGTYRXP3_231 GTYE4_CHANNEL_X1Y47 / GTYE4_COMMON_X1Y11
set_property -dict {LOC K1 } [get_ports {qsfp0_rx_n[3]}] ;# MGTYRXN3_231 GTYE4_CHANNEL_X1Y47 / GTYE4_COMMON_X1Y11
set_property -dict {LOC K7 } [get_ports {qsfp0_tx_p[3]}] ;# MGTYTXP3_231 GTYE4_CHANNEL_X1Y47 / GTYE4_COMMON_X1Y11
set_property -dict {LOC K6 } [get_ports {qsfp0_tx_n[3]}] ;# MGTYTXN3_231 GTYE4_CHANNEL_X1Y47 / GTYE4_COMMON_X1Y11
#set_property -dict {LOC M11 } [get_ports qsfp0_mgt_refclk_0_p] ;# MGTREFCLK0P_231 from U14.4 via U43.13
#set_property -dict {LOC M10 } [get_ports qsfp0_mgt_refclk_0_n] ;# MGTREFCLK0N_231 from U14.5 via U43.14
set_property -dict {LOC K11 } [get_ports qsfp0_mgt_refclk_1_p] ;# MGTREFCLK1P_231 from U9.18
set_property -dict {LOC K10 } [get_ports qsfp0_mgt_refclk_1_n] ;# MGTREFCLK1N_231 from U9.17
set_property -dict {LOC BE16 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports qsfp0_modsell]
set_property -dict {LOC BE17 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports qsfp0_resetl]
set_property -dict {LOC BE20 IOSTANDARD LVCMOS12 PULLUP true} [get_ports qsfp0_modprsl]
set_property -dict {LOC BE21 IOSTANDARD LVCMOS12 PULLUP true} [get_ports qsfp0_intl]
set_property -dict {LOC BD18 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports qsfp0_lpmode]
set_property -dict {LOC AT22 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports qsfp0_refclk_reset]
set_property -dict {LOC AT20 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {qsfp0_fs[0]}]
set_property -dict {LOC AU22 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {qsfp0_fs[1]}]
# 156.25 MHz MGT reference clock (from SI570)
#create_clock -period 6.400 -name qsfp0_mgt_refclk_0 [get_ports qsfp0_mgt_refclk_0_p]
# 156.25 MHz MGT reference clock (from SI5335, FS = 0b01)
#create_clock -period 6.400 -name qsfp0_mgt_refclk_1 [get_ports qsfp0_mgt_refclk_1_p]
# 161.1328125 MHz MGT reference clock (from SI5335, FS = 0b10)
create_clock -period 6.206 -name qsfp0_mgt_refclk_1 [get_ports qsfp0_mgt_refclk_1_p]
set_false_path -to [get_ports {qsfp0_modsell qsfp0_resetl qsfp0_lpmode qsfp0_refclk_reset qsfp0_fs[*]}]
set_output_delay 0 [get_ports {qsfp0_modsell qsfp0_resetl qsfp0_lpmode qsfp0_refclk_reset qsfp0_fs[*]}]
set_false_path -from [get_ports {qsfp0_modprsl qsfp0_intl}]
set_input_delay 0 [get_ports {qsfp0_modprsl qsfp0_intl}]
set_property -dict {LOC U4 } [get_ports {qsfp1_rx_p[0]}] ;# MGTYRXP0_230 GTYE4_CHANNEL_X1Y40 / GTYE4_COMMON_X1Y10
set_property -dict {LOC U3 } [get_ports {qsfp1_rx_n[0]}] ;# MGTYRXN0_230 GTYE4_CHANNEL_X1Y40 / GTYE4_COMMON_X1Y10
set_property -dict {LOC U9 } [get_ports {qsfp1_tx_p[0]}] ;# MGTYTXP0_230 GTYE4_CHANNEL_X1Y40 / GTYE4_COMMON_X1Y10
set_property -dict {LOC U8 } [get_ports {qsfp1_tx_n[0]}] ;# MGTYTXN0_230 GTYE4_CHANNEL_X1Y40 / GTYE4_COMMON_X1Y10
set_property -dict {LOC T2 } [get_ports {qsfp1_rx_p[1]}] ;# MGTYRXP1_230 GTYE4_CHANNEL_X1Y41 / GTYE4_COMMON_X1Y10
set_property -dict {LOC T1 } [get_ports {qsfp1_rx_n[1]}] ;# MGTYRXN1_230 GTYE4_CHANNEL_X1Y41 / GTYE4_COMMON_X1Y10
set_property -dict {LOC T7 } [get_ports {qsfp1_tx_p[1]}] ;# MGTYTXP1_230 GTYE4_CHANNEL_X1Y41 / GTYE4_COMMON_X1Y10
set_property -dict {LOC T6 } [get_ports {qsfp1_tx_n[1]}] ;# MGTYTXN1_230 GTYE4_CHANNEL_X1Y41 / GTYE4_COMMON_X1Y10
set_property -dict {LOC R4 } [get_ports {qsfp1_rx_p[2]}] ;# MGTYRXP2_230 GTYE4_CHANNEL_X1Y42 / GTYE4_COMMON_X1Y10
set_property -dict {LOC R3 } [get_ports {qsfp1_rx_n[2]}] ;# MGTYRXN2_230 GTYE4_CHANNEL_X1Y42 / GTYE4_COMMON_X1Y10
set_property -dict {LOC R9 } [get_ports {qsfp1_tx_p[2]}] ;# MGTYTXP2_230 GTYE4_CHANNEL_X1Y42 / GTYE4_COMMON_X1Y10
set_property -dict {LOC R8 } [get_ports {qsfp1_tx_n[2]}] ;# MGTYTXN2_230 GTYE4_CHANNEL_X1Y42 / GTYE4_COMMON_X1Y10
set_property -dict {LOC P2 } [get_ports {qsfp1_rx_p[3]}] ;# MGTYRXP3_230 GTYE4_CHANNEL_X1Y43 / GTYE4_COMMON_X1Y10
set_property -dict {LOC P1 } [get_ports {qsfp1_rx_n[3]}] ;# MGTYRXN3_230 GTYE4_CHANNEL_X1Y43 / GTYE4_COMMON_X1Y10
set_property -dict {LOC P7 } [get_ports {qsfp1_tx_p[3]}] ;# MGTYTXP3_230 GTYE4_CHANNEL_X1Y43 / GTYE4_COMMON_X1Y10
set_property -dict {LOC P6 } [get_ports {qsfp1_tx_n[3]}] ;# MGTYTXN3_230 GTYE4_CHANNEL_X1Y43 / GTYE4_COMMON_X1Y10
#set_property -dict {LOC T11 } [get_ports qsfp1_mgt_refclk_0_p] ;# MGTREFCLK0P_230 from U14.4 via U43.15
#set_property -dict {LOC T10 } [get_ports qsfp1_mgt_refclk_0_n] ;# MGTREFCLK0N_230 from U14.5 via U43.16
set_property -dict {LOC P11 } [get_ports qsfp1_mgt_refclk_1_p] ;# MGTREFCLK1P_230 from U12.18
set_property -dict {LOC P10 } [get_ports qsfp1_mgt_refclk_1_n] ;# MGTREFCLK1N_230 from U12.17
set_property -dict {LOC AY20 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports qsfp1_modsell]
set_property -dict {LOC BC18 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports qsfp1_resetl]
set_property -dict {LOC BC19 IOSTANDARD LVCMOS12 PULLUP true} [get_ports qsfp1_modprsl]
set_property -dict {LOC AV21 IOSTANDARD LVCMOS12 PULLUP true} [get_ports qsfp1_intl]
set_property -dict {LOC AV22 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports qsfp1_lpmode]
set_property -dict {LOC AR21 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports qsfp1_refclk_reset]
set_property -dict {LOC AR22 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {qsfp1_fs[0]}]
set_property -dict {LOC AU20 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {qsfp1_fs[1]}]
# 156.25 MHz MGT reference clock (from SI570)
#create_clock -period 6.400 -name qsfp1_mgt_refclk_0 [get_ports qsfp1_mgt_refclk_0_p]
# 156.25 MHz MGT reference clock (from SI5335, FS = 0b01)
#create_clock -period 6.400 -name qsfp1_mgt_refclk_1 [get_ports qsfp1_mgt_refclk_1_p]
# 161.1328125 MHz MGT reference clock (from SI5335, FS = 0b10)
create_clock -period 6.206 -name qsfp1_mgt_refclk_1 [get_ports qsfp1_mgt_refclk_1_p]
set_false_path -to [get_ports {qsfp1_modsell qsfp1_resetl qsfp1_lpmode qsfp1_refclk_reset qsfp1_fs[*]}]
set_output_delay 0 [get_ports {qsfp1_modsell qsfp1_resetl qsfp1_lpmode qsfp1_refclk_reset qsfp1_fs[*]}]
set_false_path -from [get_ports {qsfp1_modprsl qsfp1_intl}]
set_input_delay 0 [get_ports {qsfp1_modprsl qsfp1_intl}]
# I2C interface
#set_property -dict {LOC BF19 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports i2c_mux_reset]
set_property -dict {LOC BF20 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports i2c_scl]
set_property -dict {LOC BF17 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports i2c_sda]
set_false_path -to [get_ports {i2c_sda i2c_scl}]
set_output_delay 0 [get_ports {i2c_sda i2c_scl}]
set_false_path -from [get_ports {i2c_sda i2c_scl}]
set_input_delay 0 [get_ports {i2c_sda i2c_scl}]
# PCIe Interface
#set_property -dict {LOC AF2 } [get_ports {pcie_rx_p[0]}] ;# MGTYRXP3_227 GTYE4_CHANNEL_X1Y31 / GTYE4_COMMON_X1Y7
#set_property -dict {LOC AF1 } [get_ports {pcie_rx_n[0]}] ;# MGTYRXN3_227 GTYE4_CHANNEL_X1Y31 / GTYE4_COMMON_X1Y7
#set_property -dict {LOC AF7 } [get_ports {pcie_tx_p[0]}] ;# MGTYTXP3_227 GTYE4_CHANNEL_X1Y31 / GTYE4_COMMON_X1Y7
#set_property -dict {LOC AF6 } [get_ports {pcie_tx_n[0]}] ;# MGTYTXN3_227 GTYE4_CHANNEL_X1Y31 / GTYE4_COMMON_X1Y7
#set_property -dict {LOC AG4 } [get_ports {pcie_rx_p[1]}] ;# MGTYRXP2_227 GTYE4_CHANNEL_X1Y30 / GTYE4_COMMON_X1Y7
#set_property -dict {LOC AG3 } [get_ports {pcie_rx_n[1]}] ;# MGTYRXN2_227 GTYE4_CHANNEL_X1Y30 / GTYE4_COMMON_X1Y7
#set_property -dict {LOC AG9 } [get_ports {pcie_tx_p[1]}] ;# MGTYTXP2_227 GTYE4_CHANNEL_X1Y30 / GTYE4_COMMON_X1Y7
#set_property -dict {LOC AG8 } [get_ports {pcie_tx_n[1]}] ;# MGTYTXN2_227 GTYE4_CHANNEL_X1Y30 / GTYE4_COMMON_X1Y7
#set_property -dict {LOC AH2 } [get_ports {pcie_rx_p[2]}] ;# MGTYRXP1_227 GTYE4_CHANNEL_X1Y29 / GTYE4_COMMON_X1Y7
#set_property -dict {LOC AH1 } [get_ports {pcie_rx_n[2]}] ;# MGTYRXN1_227 GTYE4_CHANNEL_X1Y29 / GTYE4_COMMON_X1Y7
#set_property -dict {LOC AH7 } [get_ports {pcie_tx_p[2]}] ;# MGTYTXP1_227 GTYE4_CHANNEL_X1Y29 / GTYE4_COMMON_X1Y7
#set_property -dict {LOC AH6 } [get_ports {pcie_tx_n[2]}] ;# MGTYTXN1_227 GTYE4_CHANNEL_X1Y29 / GTYE4_COMMON_X1Y7
#set_property -dict {LOC AJ4 } [get_ports {pcie_rx_p[3]}] ;# MGTYRXP0_227 GTYE4_CHANNEL_X1Y28 / GTYE4_COMMON_X1Y7
#set_property -dict {LOC AJ3 } [get_ports {pcie_rx_n[3]}] ;# MGTYRXN0_227 GTYE4_CHANNEL_X1Y28 / GTYE4_COMMON_X1Y7
#set_property -dict {LOC AJ9 } [get_ports {pcie_tx_p[3]}] ;# MGTYTXP0_227 GTYE4_CHANNEL_X1Y28 / GTYE4_COMMON_X1Y7
#set_property -dict {LOC AJ8 } [get_ports {pcie_tx_n[3]}] ;# MGTYTXN0_227 GTYE4_CHANNEL_X1Y28 / GTYE4_COMMON_X1Y7
#set_property -dict {LOC AK2 } [get_ports {pcie_rx_p[4]}] ;# MGTYRXP3_226 GTYE4_CHANNEL_X1Y27 / GTYE4_COMMON_X1Y6
#set_property -dict {LOC AK1 } [get_ports {pcie_rx_n[4]}] ;# MGTYRXN3_226 GTYE4_CHANNEL_X1Y27 / GTYE4_COMMON_X1Y6
#set_property -dict {LOC AK7 } [get_ports {pcie_tx_p[4]}] ;# MGTYTXP3_226 GTYE4_CHANNEL_X1Y27 / GTYE4_COMMON_X1Y6
#set_property -dict {LOC AK6 } [get_ports {pcie_tx_n[4]}] ;# MGTYTXN3_226 GTYE4_CHANNEL_X1Y27 / GTYE4_COMMON_X1Y6
#set_property -dict {LOC AL4 } [get_ports {pcie_rx_p[5]}] ;# MGTYRXP2_226 GTYE4_CHANNEL_X1Y26 / GTYE4_COMMON_X1Y6
#set_property -dict {LOC AL3 } [get_ports {pcie_rx_n[5]}] ;# MGTYRXN2_226 GTYE4_CHANNEL_X1Y26 / GTYE4_COMMON_X1Y6
#set_property -dict {LOC AL9 } [get_ports {pcie_tx_p[5]}] ;# MGTYTXP2_226 GTYE4_CHANNEL_X1Y26 / GTYE4_COMMON_X1Y6
#set_property -dict {LOC AL8 } [get_ports {pcie_tx_n[5]}] ;# MGTYTXN2_226 GTYE4_CHANNEL_X1Y26 / GTYE4_COMMON_X1Y6
#set_property -dict {LOC AM2 } [get_ports {pcie_rx_p[6]}] ;# MGTYRXP1_226 GTYE4_CHANNEL_X1Y25 / GTYE4_COMMON_X1Y6
#set_property -dict {LOC AM1 } [get_ports {pcie_rx_n[6]}] ;# MGTYRXN1_226 GTYE4_CHANNEL_X1Y25 / GTYE4_COMMON_X1Y6
#set_property -dict {LOC AM7 } [get_ports {pcie_tx_p[6]}] ;# MGTYTXP1_226 GTYE4_CHANNEL_X1Y25 / GTYE4_COMMON_X1Y6
#set_property -dict {LOC AM6 } [get_ports {pcie_tx_n[6]}] ;# MGTYTXN1_226 GTYE4_CHANNEL_X1Y25 / GTYE4_COMMON_X1Y6
#set_property -dict {LOC AN4 } [get_ports {pcie_rx_p[7]}] ;# MGTYRXP0_226 GTYE4_CHANNEL_X1Y24 / GTYE4_COMMON_X1Y6
#set_property -dict {LOC AN3 } [get_ports {pcie_rx_n[7]}] ;# MGTYRXN0_226 GTYE4_CHANNEL_X1Y24 / GTYE4_COMMON_X1Y6
#set_property -dict {LOC AN9 } [get_ports {pcie_tx_p[7]}] ;# MGTYTXP0_226 GTYE4_CHANNEL_X1Y24 / GTYE4_COMMON_X1Y6
#set_property -dict {LOC AN8 } [get_ports {pcie_tx_n[7]}] ;# MGTYTXN0_226 GTYE4_CHANNEL_X1Y24 / GTYE4_COMMON_X1Y6
#set_property -dict {LOC AP2 } [get_ports {pcie_rx_p[8]}] ;# MGTYRXP3_225 GTYE4_CHANNEL_X1Y23 / GTYE4_COMMON_X1Y5
#set_property -dict {LOC AP1 } [get_ports {pcie_rx_n[8]}] ;# MGTYRXN3_225 GTYE4_CHANNEL_X1Y23 / GTYE4_COMMON_X1Y5
#set_property -dict {LOC AP7 } [get_ports {pcie_tx_p[8]}] ;# MGTYTXP3_225 GTYE4_CHANNEL_X1Y23 / GTYE4_COMMON_X1Y5
#set_property -dict {LOC AP6 } [get_ports {pcie_tx_n[8]}] ;# MGTYTXN3_225 GTYE4_CHANNEL_X1Y23 / GTYE4_COMMON_X1Y5
#set_property -dict {LOC AR4 } [get_ports {pcie_rx_p[9]}] ;# MGTYRXP2_225 GTYE4_CHANNEL_X1Y22 / GTYE4_COMMON_X1Y5
#set_property -dict {LOC AR3 } [get_ports {pcie_rx_n[9]}] ;# MGTYRXN2_225 GTYE4_CHANNEL_X1Y22 / GTYE4_COMMON_X1Y5
#set_property -dict {LOC AR9 } [get_ports {pcie_tx_p[9]}] ;# MGTYTXP2_225 GTYE4_CHANNEL_X1Y22 / GTYE4_COMMON_X1Y5
#set_property -dict {LOC AR8 } [get_ports {pcie_tx_n[9]}] ;# MGTYTXN2_225 GTYE4_CHANNEL_X1Y22 / GTYE4_COMMON_X1Y5
#set_property -dict {LOC AT2 } [get_ports {pcie_rx_p[10]}] ;# MGTYRXP1_225 GTYE4_CHANNEL_X1Y21 / GTYE4_COMMON_X1Y5
#set_property -dict {LOC AT1 } [get_ports {pcie_rx_n[10]}] ;# MGTYRXN1_225 GTYE4_CHANNEL_X1Y21 / GTYE4_COMMON_X1Y5
#set_property -dict {LOC AT7 } [get_ports {pcie_tx_p[10]}] ;# MGTYTXP1_225 GTYE4_CHANNEL_X1Y21 / GTYE4_COMMON_X1Y5
#set_property -dict {LOC AT6 } [get_ports {pcie_tx_n[10]}] ;# MGTYTXN1_225 GTYE4_CHANNEL_X1Y21 / GTYE4_COMMON_X1Y5
#set_property -dict {LOC AU4 } [get_ports {pcie_rx_p[11]}] ;# MGTYRXP0_225 GTYE4_CHANNEL_X1Y20 / GTYE4_COMMON_X1Y5
#set_property -dict {LOC AU3 } [get_ports {pcie_rx_n[11]}] ;# MGTYRXN0_225 GTYE4_CHANNEL_X1Y20 / GTYE4_COMMON_X1Y5
#set_property -dict {LOC AU9 } [get_ports {pcie_tx_p[11]}] ;# MGTYTXP0_225 GTYE4_CHANNEL_X1Y20 / GTYE4_COMMON_X1Y5
#set_property -dict {LOC AU8 } [get_ports {pcie_tx_n[11]}] ;# MGTYTXN0_225 GTYE4_CHANNEL_X1Y20 / GTYE4_COMMON_X1Y5
#set_property -dict {LOC AV2 } [get_ports {pcie_rx_p[12]}] ;# MGTYRXP3_224 GTYE4_CHANNEL_X1Y19 / GTYE4_COMMON_X1Y4
#set_property -dict {LOC AV1 } [get_ports {pcie_rx_n[12]}] ;# MGTYRXN3_224 GTYE4_CHANNEL_X1Y19 / GTYE4_COMMON_X1Y4
#set_property -dict {LOC AV7 } [get_ports {pcie_tx_p[12]}] ;# MGTYTXP3_224 GTYE4_CHANNEL_X1Y19 / GTYE4_COMMON_X1Y4
#set_property -dict {LOC AV6 } [get_ports {pcie_tx_n[12]}] ;# MGTYTXN3_224 GTYE4_CHANNEL_X1Y19 / GTYE4_COMMON_X1Y4
#set_property -dict {LOC AW4 } [get_ports {pcie_rx_p[13]}] ;# MGTYRXP2_224 GTYE4_CHANNEL_X1Y18 / GTYE4_COMMON_X1Y4
#set_property -dict {LOC AW3 } [get_ports {pcie_rx_n[13]}] ;# MGTYRXN2_224 GTYE4_CHANNEL_X1Y18 / GTYE4_COMMON_X1Y4
#set_property -dict {LOC BB5 } [get_ports {pcie_tx_p[13]}] ;# MGTYTXP2_224 GTYE4_CHANNEL_X1Y18 / GTYE4_COMMON_X1Y4
#set_property -dict {LOC BB4 } [get_ports {pcie_tx_n[13]}] ;# MGTYTXN2_224 GTYE4_CHANNEL_X1Y18 / GTYE4_COMMON_X1Y4
#set_property -dict {LOC BA2 } [get_ports {pcie_rx_p[14]}] ;# MGTYRXP1_224 GTYE4_CHANNEL_X1Y17 / GTYE4_COMMON_X1Y4
#set_property -dict {LOC BA1 } [get_ports {pcie_rx_n[14]}] ;# MGTYRXN1_224 GTYE4_CHANNEL_X1Y17 / GTYE4_COMMON_X1Y4
#set_property -dict {LOC BD5 } [get_ports {pcie_tx_p[14]}] ;# MGTYTXP1_224 GTYE4_CHANNEL_X1Y17 / GTYE4_COMMON_X1Y4
#set_property -dict {LOC BD4 } [get_ports {pcie_tx_n[14]}] ;# MGTYTXN1_224 GTYE4_CHANNEL_X1Y17 / GTYE4_COMMON_X1Y4
#set_property -dict {LOC BC2 } [get_ports {pcie_rx_p[15]}] ;# MGTYRXP0_224 GTYE4_CHANNEL_X1Y16 / GTYE4_COMMON_X1Y4
#set_property -dict {LOC BC1 } [get_ports {pcie_rx_n[15]}] ;# MGTYRXN0_224 GTYE4_CHANNEL_X1Y16 / GTYE4_COMMON_X1Y4
#set_property -dict {LOC BF5 } [get_ports {pcie_tx_p[15]}] ;# MGTYTXP0_224 GTYE4_CHANNEL_X1Y16 / GTYE4_COMMON_X1Y4
#set_property -dict {LOC BF4 } [get_ports {pcie_tx_n[15]}] ;# MGTYTXN0_224 GTYE4_CHANNEL_X1Y16 / GTYE4_COMMON_X1Y4
#set_property -dict {LOC AM11 } [get_ports pcie_refclk_p] ;# MGTREFCLK0P_226
#set_property -dict {LOC AM10 } [get_ports pcie_refclk_n] ;# MGTREFCLK0N_226
#set_property -dict {LOC BD21 IOSTANDARD LVCMOS12 PULLUP true} [get_ports pcie_reset_n]
# 100 MHz MGT reference clock
#create_clock -period 10 -name pcie_mgt_refclk_1 [get_ports pcie_refclk_p]
#set_false_path -from [get_ports {pcie_reset_n}]
#set_input_delay 0 [get_ports {pcie_reset_n}]
# DDR4 C0
#set_property -dict {LOC AT36 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c0_adr[0]}]
#set_property -dict {LOC AV36 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c0_adr[1]}]
#set_property -dict {LOC AV37 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c0_adr[2]}]
#set_property -dict {LOC AW35 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c0_adr[3]}]
#set_property -dict {LOC AW36 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c0_adr[4]}]
#set_property -dict {LOC AY36 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c0_adr[5]}]
#set_property -dict {LOC AY35 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c0_adr[6]}]
#set_property -dict {LOC BA40 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c0_adr[7]}]
#set_property -dict {LOC BA37 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c0_adr[8]}]
#set_property -dict {LOC BB37 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c0_adr[9]}]
#set_property -dict {LOC AR35 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c0_adr[10]}]
#set_property -dict {LOC BA39 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c0_adr[11]}]
#set_property -dict {LOC BB40 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c0_adr[12]}]
#set_property -dict {LOC AN36 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c0_adr[13]}]
#set_property -dict {LOC AP35 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c0_adr[14]}]
#set_property -dict {LOC AP36 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c0_adr[15]}]
#set_property -dict {LOC AR36 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c0_adr[16]}]
#set_property -dict {LOC AT35 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c0_ba[0]}]
#set_property -dict {LOC AT34 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c0_ba[1]}]
#set_property -dict {LOC BC37 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c0_bg[0]}]
#set_property -dict {LOC BC39 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c0_bg[1]}]
#set_property -dict {LOC AV38 IOSTANDARD DIFF_SSTL12_DCI} [get_ports {ddr4_c0_ck_t[0]}]
#set_property -dict {LOC AW38 IOSTANDARD DIFF_SSTL12_DCI} [get_ports {ddr4_c0_ck_c[0]}]
#set_property -dict {LOC AU34 IOSTANDARD DIFF_SSTL12_DCI} [get_ports {ddr4_c0_ck_t[1]}]
#set_property -dict {LOC AU35 IOSTANDARD DIFF_SSTL12_DCI} [get_ports {ddr4_c0_ck_c[1]}]
#set_property -dict {LOC BC38 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c0_cke[0]}]
#set_property -dict {LOC BC40 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c0_cke[1]}]
#set_property -dict {LOC AR33 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c0_cs_n[0]}]
#set_property -dict {LOC AP33 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c0_cs_n[1]}]
#set_property -dict {LOC AN33 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c0_cs_n[2]}]
#set_property -dict {LOC AM34 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c0_cs_n[3]}]
#set_property -dict {LOC BB39 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c0_act_n}]
#set_property -dict {LOC AP34 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c0_odt[0]}]
#set_property -dict {LOC AN34 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c0_odt[1]}]
#set_property -dict {LOC AU36 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c0_par}]
#set_property -dict {LOC AU31 IOSTANDARD LVCMOS12 } [get_ports {ddr4_c0_reset_n}]
#set_property -dict {LOC AW28 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[0]}]
#set_property -dict {LOC AW29 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[1]}]
#set_property -dict {LOC BA28 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[2]}]
#set_property -dict {LOC BA27 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[3]}]
#set_property -dict {LOC BB29 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[4]}]
#set_property -dict {LOC BA29 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[5]}]
#set_property -dict {LOC BC27 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[6]}]
#set_property -dict {LOC BB27 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[7]}]
#set_property -dict {LOC BE28 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[8]}]
#set_property -dict {LOC BF28 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[9]}]
#set_property -dict {LOC BE30 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[10]}]
#set_property -dict {LOC BD30 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[11]}]
#set_property -dict {LOC BF27 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[12]}]
#set_property -dict {LOC BE27 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[13]}]
#set_property -dict {LOC BF30 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[14]}]
#set_property -dict {LOC BF29 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[15]}]
#set_property -dict {LOC BB31 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[16]}]
#set_property -dict {LOC BB32 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[17]}]
#set_property -dict {LOC AY32 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[18]}]
#set_property -dict {LOC AY33 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[19]}]
#set_property -dict {LOC BC32 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[20]}]
#set_property -dict {LOC BC33 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[21]}]
#set_property -dict {LOC BB34 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[22]}]
#set_property -dict {LOC BC34 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[23]}]
#set_property -dict {LOC AV31 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[24]}]
#set_property -dict {LOC AV32 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[25]}]
#set_property -dict {LOC AV34 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[26]}]
#set_property -dict {LOC AW34 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[27]}]
#set_property -dict {LOC AW31 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[28]}]
#set_property -dict {LOC AY31 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[29]}]
#set_property -dict {LOC BA35 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[30]}]
#set_property -dict {LOC BA34 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[31]}]
#set_property -dict {LOC AL30 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[32]}]
#set_property -dict {LOC AM30 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[33]}]
#set_property -dict {LOC AU32 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[34]}]
#set_property -dict {LOC AT32 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[35]}]
#set_property -dict {LOC AN31 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[36]}]
#set_property -dict {LOC AN32 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[37]}]
#set_property -dict {LOC AR32 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[38]}]
#set_property -dict {LOC AR31 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[39]}]
#set_property -dict {LOC AP29 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[40]}]
#set_property -dict {LOC AP28 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[41]}]
#set_property -dict {LOC AN27 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[42]}]
#set_property -dict {LOC AM27 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[43]}]
#set_property -dict {LOC AN29 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[44]}]
#set_property -dict {LOC AM29 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[45]}]
#set_property -dict {LOC AR27 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[46]}]
#set_property -dict {LOC AR28 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[47]}]
#set_property -dict {LOC AT28 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[48]}]
#set_property -dict {LOC AV27 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[49]}]
#set_property -dict {LOC AU27 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[50]}]
#set_property -dict {LOC AT27 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[51]}]
#set_property -dict {LOC AV29 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[52]}]
#set_property -dict {LOC AY30 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[53]}]
#set_property -dict {LOC AW30 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[54]}]
#set_property -dict {LOC AV28 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[55]}]
#set_property -dict {LOC BD34 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[56]}]
#set_property -dict {LOC BD33 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[57]}]
#set_property -dict {LOC BE33 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[58]}]
#set_property -dict {LOC BD35 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[59]}]
#set_property -dict {LOC BF32 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[60]}]
#set_property -dict {LOC BF33 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[61]}]
#set_property -dict {LOC BF34 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[62]}]
#set_property -dict {LOC BF35 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[63]}]
#set_property -dict {LOC BD40 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[64]}]
#set_property -dict {LOC BD39 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[65]}]
#set_property -dict {LOC BF43 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[66]}]
#set_property -dict {LOC BF42 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[67]}]
#set_property -dict {LOC BF37 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[68]}]
#set_property -dict {LOC BE37 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[69]}]
#set_property -dict {LOC BE40 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[70]}]
#set_property -dict {LOC BF41 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[71]}]
#set_property -dict {LOC BA30 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c0_dqs_t[0]}]
#set_property -dict {LOC BB30 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c0_dqs_c[0]}]
#set_property -dict {LOC BB26 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c0_dqs_t[1]}]
#set_property -dict {LOC BC26 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c0_dqs_c[1]}]
#set_property -dict {LOC BD28 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c0_dqs_t[2]}]
#set_property -dict {LOC BD29 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c0_dqs_c[2]}]
#set_property -dict {LOC BD26 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c0_dqs_t[3]}]
#set_property -dict {LOC BE26 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c0_dqs_c[3]}]
#set_property -dict {LOC BB35 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c0_dqs_t[4]}]
#set_property -dict {LOC BB36 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c0_dqs_c[4]}]
#set_property -dict {LOC BC31 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c0_dqs_t[5]}]
#set_property -dict {LOC BD31 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c0_dqs_c[5]}]
#set_property -dict {LOC AV33 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c0_dqs_t[6]}]
#set_property -dict {LOC AW33 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c0_dqs_c[6]}]
#set_property -dict {LOC BA32 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c0_dqs_t[7]}]
#set_property -dict {LOC BA33 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c0_dqs_c[7]}]
#set_property -dict {LOC AM31 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c0_dqs_t[8]}]
#set_property -dict {LOC AM32 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c0_dqs_c[8]}]
#set_property -dict {LOC AP30 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c0_dqs_t[9]}]
#set_property -dict {LOC AP31 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c0_dqs_c[9]}]
#set_property -dict {LOC AL28 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c0_dqs_t[10]}]
#set_property -dict {LOC AL29 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c0_dqs_c[10]}]
#set_property -dict {LOC AR30 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c0_dqs_t[11]}]
#set_property -dict {LOC AT30 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c0_dqs_c[11]}]
#set_property -dict {LOC AU29 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c0_dqs_t[12]}]
#set_property -dict {LOC AU30 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c0_dqs_c[12]}]
#set_property -dict {LOC AY27 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c0_dqs_t[13]}]
#set_property -dict {LOC AY28 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c0_dqs_c[13]}]
#set_property -dict {LOC BE35 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c0_dqs_t[14]}]
#set_property -dict {LOC BE36 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c0_dqs_c[14]}]
#set_property -dict {LOC BE31 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c0_dqs_t[15]}]
#set_property -dict {LOC BE32 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c0_dqs_c[15]}]
#set_property -dict {LOC BE38 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c0_dqs_t[16]}]
#set_property -dict {LOC BF38 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c0_dqs_c[16]}]
#set_property -dict {LOC BF39 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c0_dqs_t[17]}]
#set_property -dict {LOC BF40 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c0_dqs_c[17]}]
# DDR4 C1
#set_property -dict {LOC AN24 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c1_adr[0]}]
#set_property -dict {LOC AT24 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c1_adr[1]}]
#set_property -dict {LOC AW24 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c1_adr[2]}]
#set_property -dict {LOC AN26 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c1_adr[3]}]
#set_property -dict {LOC AY22 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c1_adr[4]}]
#set_property -dict {LOC AY23 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c1_adr[5]}]
#set_property -dict {LOC AV24 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c1_adr[6]}]
#set_property -dict {LOC BA22 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c1_adr[7]}]
#set_property -dict {LOC AY25 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c1_adr[8]}]
#set_property -dict {LOC BA23 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c1_adr[9]}]
#set_property -dict {LOC AM26 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c1_adr[10]}]
#set_property -dict {LOC BA25 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c1_adr[11]}]
#set_property -dict {LOC BB22 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c1_adr[12]}]
#set_property -dict {LOC AL24 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c1_adr[13]}]
#set_property -dict {LOC AL25 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c1_adr[14]}]
#set_property -dict {LOC AM25 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c1_adr[15]}]
#set_property -dict {LOC AN23 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c1_adr[16]}]
#set_property -dict {LOC AU24 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c1_ba[0]}]
#set_property -dict {LOC AP26 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c1_ba[1]}]
#set_property -dict {LOC BC22 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c1_bg[0]}]
#set_property -dict {LOC AW26 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c1_bg[1]}]
#set_property -dict {LOC AT25 IOSTANDARD DIFF_SSTL12_DCI} [get_ports {ddr4_c1_ck_t[0]}]
#set_property -dict {LOC AU25 IOSTANDARD DIFF_SSTL12_DCI} [get_ports {ddr4_c1_ck_c[0]}]
#set_property -dict {LOC AU26 IOSTANDARD DIFF_SSTL12_DCI} [get_ports {ddr4_c1_ck_t[1]}]
#set_property -dict {LOC AV26 IOSTANDARD DIFF_SSTL12_DCI} [get_ports {ddr4_c1_ck_c[1]}]
#set_property -dict {LOC BB25 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c1_cke[0]}]
#set_property -dict {LOC BB24 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c1_cke[1]}]
#set_property -dict {LOC AV23 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c1_cs_n[0]}]
#set_property -dict {LOC AP25 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c1_cs_n[1]}]
#set_property -dict {LOC AR23 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c1_cs_n[2]}]
#set_property -dict {LOC AP23 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c1_cs_n[3]}]
#set_property -dict {LOC AW25 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c1_act_n}]
#set_property -dict {LOC AW23 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c1_odt[0]}]
#set_property -dict {LOC AP24 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c1_odt[1]}]
#set_property -dict {LOC AT23 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c1_par}]
#set_property -dict {LOC AR17 IOSTANDARD LVCMOS12 } [get_ports {ddr4_c1_reset_n}]
#set_property -dict {LOC BD9 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[0]}]
#set_property -dict {LOC BD7 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[1]}]
#set_property -dict {LOC BC7 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[2]}]
#set_property -dict {LOC BD8 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[3]}]
#set_property -dict {LOC BD10 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[4]}]
#set_property -dict {LOC BE10 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[5]}]
#set_property -dict {LOC BE7 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[6]}]
#set_property -dict {LOC BF7 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[7]}]
#set_property -dict {LOC AU13 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[8]}]
#set_property -dict {LOC AV13 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[9]}]
#set_property -dict {LOC AW13 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[10]}]
#set_property -dict {LOC AW14 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[11]}]
#set_property -dict {LOC AU14 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[12]}]
#set_property -dict {LOC AY11 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[13]}]
#set_property -dict {LOC AV14 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[14]}]
#set_property -dict {LOC BA11 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[15]}]
#set_property -dict {LOC BA12 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[16]}]
#set_property -dict {LOC BB12 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[17]}]
#set_property -dict {LOC BA13 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[18]}]
#set_property -dict {LOC BA14 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[19]}]
#set_property -dict {LOC BC9 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[20]}]
#set_property -dict {LOC BB9 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[21]}]
#set_property -dict {LOC BA7 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[22]}]
#set_property -dict {LOC BA8 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[23]}]
#set_property -dict {LOC AN13 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[24]}]
#set_property -dict {LOC AR13 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[25]}]
#set_property -dict {LOC AM13 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[26]}]
#set_property -dict {LOC AP13 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[27]}]
#set_property -dict {LOC AM14 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[28]}]
#set_property -dict {LOC AR15 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[29]}]
#set_property -dict {LOC AL14 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[30]}]
#set_property -dict {LOC AT15 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[31]}]
#set_property -dict {LOC BE13 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[32]}]
#set_property -dict {LOC BD14 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[33]}]
#set_property -dict {LOC BF12 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[34]}]
#set_property -dict {LOC BD13 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[35]}]
#set_property -dict {LOC BD15 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[36]}]
#set_property -dict {LOC BD16 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[37]}]
#set_property -dict {LOC BF14 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[38]}]
#set_property -dict {LOC BF13 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[39]}]
#set_property -dict {LOC AY17 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[40]}]
#set_property -dict {LOC BA17 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[41]}]
#set_property -dict {LOC AY18 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[42]}]
#set_property -dict {LOC BA18 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[43]}]
#set_property -dict {LOC BA15 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[44]}]
#set_property -dict {LOC BB15 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[45]}]
#set_property -dict {LOC BC11 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[46]}]
#set_property -dict {LOC BD11 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[47]}]
#set_property -dict {LOC AV16 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[48]}]
#set_property -dict {LOC AV17 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[49]}]
#set_property -dict {LOC AU16 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[50]}]
#set_property -dict {LOC AU17 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[51]}]
#set_property -dict {LOC BB17 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[52]}]
#set_property -dict {LOC BB16 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[53]}]
#set_property -dict {LOC AT18 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[54]}]
#set_property -dict {LOC AT17 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[55]}]
#set_property -dict {LOC AM15 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[56]}]
#set_property -dict {LOC AL15 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[57]}]
#set_property -dict {LOC AN17 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[58]}]
#set_property -dict {LOC AN16 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[59]}]
#set_property -dict {LOC AR18 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[60]}]
#set_property -dict {LOC AP18 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[61]}]
#set_property -dict {LOC AL17 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[62]}]
#set_property -dict {LOC AL16 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[63]}]
#set_property -dict {LOC BF25 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[64]}]
#set_property -dict {LOC BF24 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[65]}]
#set_property -dict {LOC BD25 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[66]}]
#set_property -dict {LOC BE25 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[67]}]
#set_property -dict {LOC BD23 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[68]}]
#set_property -dict {LOC BC23 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[69]}]
#set_property -dict {LOC BF23 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[70]}]
#set_property -dict {LOC BE23 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[71]}]
#set_property -dict {LOC BF10 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c1_dqs_t[0]}]
#set_property -dict {LOC BF9 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c1_dqs_c[0]}]
#set_property -dict {LOC BE8 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c1_dqs_t[1]}]
#set_property -dict {LOC BF8 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c1_dqs_c[1]}]
#set_property -dict {LOC AW15 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c1_dqs_t[2]}]
#set_property -dict {LOC AY15 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c1_dqs_c[2]}]
#set_property -dict {LOC AY13 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c1_dqs_t[3]}]
#set_property -dict {LOC AY12 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c1_dqs_c[3]}]
#set_property -dict {LOC BB11 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c1_dqs_t[4]}]
#set_property -dict {LOC BB10 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c1_dqs_c[4]}]
#set_property -dict {LOC BA10 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c1_dqs_t[5]}]
#set_property -dict {LOC BA9 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c1_dqs_c[5]}]
#set_property -dict {LOC AT14 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c1_dqs_t[6]}]
#set_property -dict {LOC AT13 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c1_dqs_c[6]}]
#set_property -dict {LOC AN14 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c1_dqs_t[7]}]
#set_property -dict {LOC AP14 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c1_dqs_c[7]}]
#set_property -dict {LOC BE12 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c1_dqs_t[8]}]
#set_property -dict {LOC BE11 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c1_dqs_c[8]}]
#set_property -dict {LOC BE15 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c1_dqs_t[9]}]
#set_property -dict {LOC BF15 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c1_dqs_c[9]}]
#set_property -dict {LOC BC13 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c1_dqs_t[10]}]
#set_property -dict {LOC BC12 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c1_dqs_c[10]}]
#set_property -dict {LOC BB14 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c1_dqs_t[11]}]
#set_property -dict {LOC BC14 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c1_dqs_c[11]}]
#set_property -dict {LOC AV18 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c1_dqs_t[12]}]
#set_property -dict {LOC AW18 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c1_dqs_c[12]}]
#set_property -dict {LOC AW16 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c1_dqs_t[13]}]
#set_property -dict {LOC AY16 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c1_dqs_c[13]}]
#set_property -dict {LOC AP16 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c1_dqs_t[14]}]
#set_property -dict {LOC AR16 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c1_dqs_c[14]}]
#set_property -dict {LOC AM17 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c1_dqs_t[15]}]
#set_property -dict {LOC AM16 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c1_dqs_c[15]}]
#set_property -dict {LOC BC24 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c1_dqs_t[16]}]
#set_property -dict {LOC BD24 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c1_dqs_c[16]}]
#set_property -dict {LOC BE22 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c1_dqs_t[17]}]
#set_property -dict {LOC BF22 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c1_dqs_c[17]}]
# DDR4 C2
#set_property -dict {LOC L29 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c2_adr[0]}]
#set_property -dict {LOC A33 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c2_adr[1]}]
#set_property -dict {LOC C33 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c2_adr[2]}]
#set_property -dict {LOC J29 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c2_adr[3]}]
#set_property -dict {LOC H31 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c2_adr[4]}]
#set_property -dict {LOC G31 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c2_adr[5]}]
#set_property -dict {LOC C32 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c2_adr[6]}]
#set_property -dict {LOC B32 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c2_adr[7]}]
#set_property -dict {LOC A32 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c2_adr[8]}]
#set_property -dict {LOC D31 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c2_adr[9]}]
#set_property -dict {LOC A34 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c2_adr[10]}]
#set_property -dict {LOC E31 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c2_adr[11]}]
#set_property -dict {LOC M30 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c2_adr[12]}]
#set_property -dict {LOC F33 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c2_adr[13]}]
#set_property -dict {LOC A35 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c2_adr[14]}]
#set_property -dict {LOC G32 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c2_adr[15]}]
#set_property -dict {LOC K30 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c2_adr[16]}]
#set_property -dict {LOC D33 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c2_ba[0]}]
#set_property -dict {LOC B36 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c2_ba[1]}]
#set_property -dict {LOC C31 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c2_bg[0]}]
#set_property -dict {LOC J30 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c2_bg[1]}]
#set_property -dict {LOC C34 IOSTANDARD DIFF_SSTL12_DCI} [get_ports {ddr4_c2_ck_t[0]}]
#set_property -dict {LOC B34 IOSTANDARD DIFF_SSTL12_DCI} [get_ports {ddr4_c2_ck_c[0]}]
#set_property -dict {LOC D34 IOSTANDARD DIFF_SSTL12_DCI} [get_ports {ddr4_c2_ck_t[1]}]
#set_property -dict {LOC D35 IOSTANDARD DIFF_SSTL12_DCI} [get_ports {ddr4_c2_ck_c[1]}]
#set_property -dict {LOC G30 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c2_cke[0]}]
#set_property -dict {LOC E30 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c2_cke[1]}]
#set_property -dict {LOC B35 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c2_cs_n[0]}]
#set_property -dict {LOC J31 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c2_cs_n[1]}]
#set_property -dict {LOC L30 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c2_cs_n[2]}]
#set_property -dict {LOC K31 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c2_cs_n[3]}]
#set_property -dict {LOC B31 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c2_act_n}]
#set_property -dict {LOC E33 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c2_odt[0]}]
#set_property -dict {LOC F34 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c2_odt[1]}]
#set_property -dict {LOC M29 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c2_par}]
#set_property -dict {LOC D36 IOSTANDARD LVCMOS12 } [get_ports {ddr4_c2_reset_n}]
#set_property -dict {LOC R25 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[0]}]
#set_property -dict {LOC P25 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[1]}]
#set_property -dict {LOC M25 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[2]}]
#set_property -dict {LOC L25 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[3]}]
#set_property -dict {LOC P26 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[4]}]
#set_property -dict {LOC R26 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[5]}]
#set_property -dict {LOC N27 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[6]}]
#set_property -dict {LOC N28 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[7]}]
#set_property -dict {LOC J28 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[8]}]
#set_property -dict {LOC H29 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[9]}]
#set_property -dict {LOC H28 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[10]}]
#set_property -dict {LOC G29 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[11]}]
#set_property -dict {LOC K25 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[12]}]
#set_property -dict {LOC L27 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[13]}]
#set_property -dict {LOC K26 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[14]}]
#set_property -dict {LOC K27 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[15]}]
#set_property -dict {LOC F27 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[16]}]
#set_property -dict {LOC E27 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[17]}]
#set_property -dict {LOC E28 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[18]}]
#set_property -dict {LOC D28 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[19]}]
#set_property -dict {LOC G27 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[20]}]
#set_property -dict {LOC G26 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[21]}]
#set_property -dict {LOC F28 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[22]}]
#set_property -dict {LOC F29 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[23]}]
#set_property -dict {LOC D26 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[24]}]
#set_property -dict {LOC C26 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[25]}]
#set_property -dict {LOC B27 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[26]}]
#set_property -dict {LOC B26 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[27]}]
#set_property -dict {LOC A29 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[28]}]
#set_property -dict {LOC A30 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[29]}]
#set_property -dict {LOC C27 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[30]}]
#set_property -dict {LOC C28 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[31]}]
#set_property -dict {LOC F35 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[32]}]
#set_property -dict {LOC E38 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[33]}]
#set_property -dict {LOC D38 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[34]}]
#set_property -dict {LOC E35 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[35]}]
#set_property -dict {LOC E36 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[36]}]
#set_property -dict {LOC E37 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[37]}]
#set_property -dict {LOC F38 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[38]}]
#set_property -dict {LOC G38 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[39]}]
#set_property -dict {LOC P30 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[40]}]
#set_property -dict {LOC R30 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[41]}]
#set_property -dict {LOC P29 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[42]}]
#set_property -dict {LOC N29 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[43]}]
#set_property -dict {LOC L32 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[44]}]
#set_property -dict {LOC M32 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[45]}]
#set_property -dict {LOC P31 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[46]}]
#set_property -dict {LOC N32 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[47]}]
#set_property -dict {LOC J35 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[48]}]
#set_property -dict {LOC K35 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[49]}]
#set_property -dict {LOC L33 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[50]}]
#set_property -dict {LOC K33 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[51]}]
#set_property -dict {LOC J34 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[52]}]
#set_property -dict {LOC J33 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[53]}]
#set_property -dict {LOC N34 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[54]}]
#set_property -dict {LOC P34 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[55]}]
#set_property -dict {LOC H36 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[56]}]
#set_property -dict {LOC G36 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[57]}]
#set_property -dict {LOC H37 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[58]}]
#set_property -dict {LOC J36 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[59]}]
#set_property -dict {LOC K37 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[60]}]
#set_property -dict {LOC K38 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[61]}]
#set_property -dict {LOC G35 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[62]}]
#set_property -dict {LOC G34 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[63]}]
#set_property -dict {LOC C36 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[64]}]
#set_property -dict {LOC B37 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[65]}]
#set_property -dict {LOC A37 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[66]}]
#set_property -dict {LOC A38 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[67]}]
#set_property -dict {LOC C39 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[68]}]
#set_property -dict {LOC D39 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[69]}]
#set_property -dict {LOC A40 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[70]}]
#set_property -dict {LOC B40 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[71]}]
#set_property -dict {LOC N26 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c2_dqs_t[0]}]
#set_property -dict {LOC M26 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c2_dqs_c[0]}]
#set_property -dict {LOC R28 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c2_dqs_t[1]}]
#set_property -dict {LOC P28 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c2_dqs_c[1]}]
#set_property -dict {LOC J25 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c2_dqs_t[2]}]
#set_property -dict {LOC J26 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c2_dqs_c[2]}]
#set_property -dict {LOC M27 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c2_dqs_t[3]}]
#set_property -dict {LOC L28 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c2_dqs_c[3]}]
#set_property -dict {LOC D29 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c2_dqs_t[4]}]
#set_property -dict {LOC D30 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c2_dqs_c[4]}]
#set_property -dict {LOC H26 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c2_dqs_t[5]}]
#set_property -dict {LOC H27 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c2_dqs_c[5]}]
#set_property -dict {LOC A27 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c2_dqs_t[6]}]
#set_property -dict {LOC A28 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c2_dqs_c[6]}]
#set_property -dict {LOC C29 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c2_dqs_t[7]}]
#set_property -dict {LOC B29 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c2_dqs_c[7]}]
#set_property -dict {LOC E39 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c2_dqs_t[8]}]
#set_property -dict {LOC E40 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c2_dqs_c[8]}]
#set_property -dict {LOC G37 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c2_dqs_t[9]}]
#set_property -dict {LOC F37 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c2_dqs_c[9]}]
#set_property -dict {LOC N31 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c2_dqs_t[10]}]
#set_property -dict {LOC M31 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c2_dqs_c[10]}]
#set_property -dict {LOC T30 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c2_dqs_t[11]}]
#set_property -dict {LOC R31 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c2_dqs_c[11]}]
#set_property -dict {LOC L35 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c2_dqs_t[12]}]
#set_property -dict {LOC L36 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c2_dqs_c[12]}]
#set_property -dict {LOC M34 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c2_dqs_t[13]}]
#set_property -dict {LOC L34 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c2_dqs_c[13]}]
#set_property -dict {LOC J38 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c2_dqs_t[14]}]
#set_property -dict {LOC H38 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c2_dqs_c[14]}]
#set_property -dict {LOC H33 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c2_dqs_t[15]}]
#set_property -dict {LOC H34 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c2_dqs_c[15]}]
#set_property -dict {LOC B39 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c2_dqs_t[16]}]
#set_property -dict {LOC A39 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c2_dqs_c[16]}]
#set_property -dict {LOC C37 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c2_dqs_t[17]}]
#set_property -dict {LOC C38 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c2_dqs_c[17]}]
# DDR4 C3
#set_property -dict {LOC K15 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c3_adr[0]}]
#set_property -dict {LOC B15 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c3_adr[1]}]
#set_property -dict {LOC F14 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c3_adr[2]}]
#set_property -dict {LOC A15 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c3_adr[3]}]
#set_property -dict {LOC C14 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c3_adr[4]}]
#set_property -dict {LOC A14 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c3_adr[5]}]
#set_property -dict {LOC B14 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c3_adr[6]}]
#set_property -dict {LOC E13 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c3_adr[7]}]
#set_property -dict {LOC F13 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c3_adr[8]}]
#set_property -dict {LOC A13 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c3_adr[9]}]
#set_property -dict {LOC D14 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c3_adr[10]}]
#set_property -dict {LOC C13 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c3_adr[11]}]
#set_property -dict {LOC B13 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c3_adr[12]}]
#set_property -dict {LOC K16 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c3_adr[13]}]
#set_property -dict {LOC D15 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c3_adr[14]}]
#set_property -dict {LOC E15 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c3_adr[15]}]
#set_property -dict {LOC F15 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c3_adr[16]}]
#set_property -dict {LOC J15 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c3_ba[0]}]
#set_property -dict {LOC H14 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c3_ba[1]}]
#set_property -dict {LOC D13 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c3_bg[0]}]
#set_property -dict {LOC J13 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c3_bg[1]}]
#set_property -dict {LOC L14 IOSTANDARD DIFF_SSTL12_DCI} [get_ports {ddr4_c3_ck_t[0]}]
#set_property -dict {LOC L13 IOSTANDARD DIFF_SSTL12_DCI} [get_ports {ddr4_c3_ck_c[0]}]
#set_property -dict {LOC G14 IOSTANDARD DIFF_SSTL12_DCI} [get_ports {ddr4_c3_ck_t[1]}]
#set_property -dict {LOC G13 IOSTANDARD DIFF_SSTL12_DCI} [get_ports {ddr4_c3_ck_c[1]}]
#set_property -dict {LOC K13 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c3_cke[0]}]
#set_property -dict {LOC L15 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c3_cke[1]}]
#set_property -dict {LOC B16 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c3_cs_n[0]}]
#set_property -dict {LOC D16 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c3_cs_n[1]}]
#set_property -dict {LOC M14 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c3_cs_n[2]}]
#set_property -dict {LOC M13 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c3_cs_n[3]}]
#set_property -dict {LOC H13 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c3_act_n}]
#set_property -dict {LOC C16 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c3_odt[0]}]
#set_property -dict {LOC E16 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c3_odt[1]}]
#set_property -dict {LOC J14 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c3_par}]
#set_property -dict {LOC D21 IOSTANDARD LVCMOS12 } [get_ports {ddr4_c3_reset_n}]
#set_property -dict {LOC P24 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[0]}]
#set_property -dict {LOC N24 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[1]}]
#set_property -dict {LOC T24 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[2]}]
#set_property -dict {LOC R23 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[3]}]
#set_property -dict {LOC N23 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[4]}]
#set_property -dict {LOC P21 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[5]}]
#set_property -dict {LOC P23 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[6]}]
#set_property -dict {LOC R21 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[7]}]
#set_property -dict {LOC J24 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[8]}]
#set_property -dict {LOC J23 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[9]}]
#set_property -dict {LOC H24 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[10]}]
#set_property -dict {LOC G24 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[11]}]
#set_property -dict {LOC L24 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[12]}]
#set_property -dict {LOC L23 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[13]}]
#set_property -dict {LOC K22 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[14]}]
#set_property -dict {LOC K21 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[15]}]
#set_property -dict {LOC G20 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[16]}]
#set_property -dict {LOC H17 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[17]}]
#set_property -dict {LOC F19 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[18]}]
#set_property -dict {LOC G17 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[19]}]
#set_property -dict {LOC J20 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[20]}]
#set_property -dict {LOC L19 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[21]}]
#set_property -dict {LOC L18 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[22]}]
#set_property -dict {LOC J19 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[23]}]
#set_property -dict {LOC M19 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[24]}]
#set_property -dict {LOC M20 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[25]}]
#set_property -dict {LOC R18 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[26]}]
#set_property -dict {LOC R17 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[27]}]
#set_property -dict {LOC R20 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[28]}]
#set_property -dict {LOC T20 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[29]}]
#set_property -dict {LOC N18 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[30]}]
#set_property -dict {LOC N19 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[31]}]
#set_property -dict {LOC A23 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[32]}]
#set_property -dict {LOC A22 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[33]}]
#set_property -dict {LOC B24 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[34]}]
#set_property -dict {LOC B25 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[35]}]
#set_property -dict {LOC B22 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[36]}]
#set_property -dict {LOC C22 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[37]}]
#set_property -dict {LOC C24 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[38]}]
#set_property -dict {LOC C23 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[39]}]
#set_property -dict {LOC C19 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[40]}]
#set_property -dict {LOC C18 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[41]}]
#set_property -dict {LOC C21 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[42]}]
#set_property -dict {LOC B21 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[43]}]
#set_property -dict {LOC A18 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[44]}]
#set_property -dict {LOC A17 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[45]}]
#set_property -dict {LOC A20 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[46]}]
#set_property -dict {LOC B20 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[47]}]
#set_property -dict {LOC E17 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[48]}]
#set_property -dict {LOC F20 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[49]}]
#set_property -dict {LOC E18 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[50]}]
#set_property -dict {LOC E20 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[51]}]
#set_property -dict {LOC D19 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[52]}]
#set_property -dict {LOC D20 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[53]}]
#set_property -dict {LOC H18 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[54]}]
#set_property -dict {LOC J18 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[55]}]
#set_property -dict {LOC F22 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[56]}]
#set_property -dict {LOC E22 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[57]}]
#set_property -dict {LOC G22 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[58]}]
#set_property -dict {LOC G21 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[59]}]
#set_property -dict {LOC F24 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[60]}]
#set_property -dict {LOC E25 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[61]}]
#set_property -dict {LOC F25 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[62]}]
#set_property -dict {LOC G25 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[63]}]
#set_property -dict {LOC M16 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[64]}]
#set_property -dict {LOC N16 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[65]}]
#set_property -dict {LOC N13 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[66]}]
#set_property -dict {LOC N14 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[67]}]
#set_property -dict {LOC T15 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[68]}]
#set_property -dict {LOC R15 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[69]}]
#set_property -dict {LOC P13 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[70]}]
#set_property -dict {LOC P14 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[71]}]
#set_property -dict {LOC T22 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c3_dqs_t[0]}]
#set_property -dict {LOC R22 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c3_dqs_c[0]}]
#set_property -dict {LOC N22 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c3_dqs_t[1]}]
#set_property -dict {LOC N21 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c3_dqs_c[1]}]
#set_property -dict {LOC J21 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c3_dqs_t[2]}]
#set_property -dict {LOC H21 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c3_dqs_c[2]}]
#set_property -dict {LOC M22 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c3_dqs_t[3]}]
#set_property -dict {LOC L22 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c3_dqs_c[3]}]
#set_property -dict {LOC L20 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c3_dqs_t[4]}]
#set_property -dict {LOC K20 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c3_dqs_c[4]}]
#set_property -dict {LOC K18 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c3_dqs_t[5]}]
#set_property -dict {LOC K17 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c3_dqs_c[5]}]
#set_property -dict {LOC P19 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c3_dqs_t[6]}]
#set_property -dict {LOC P18 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c3_dqs_c[6]}]
#set_property -dict {LOC N17 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c3_dqs_t[7]}]
#set_property -dict {LOC M17 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c3_dqs_c[7]}]
#set_property -dict {LOC A25 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c3_dqs_t[8]}]
#set_property -dict {LOC A24 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c3_dqs_c[8]}]
#set_property -dict {LOC D24 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c3_dqs_t[9]}]
#set_property -dict {LOC D23 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c3_dqs_c[9]}]
#set_property -dict {LOC C17 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c3_dqs_t[10]}]
#set_property -dict {LOC B17 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c3_dqs_c[10]}]
#set_property -dict {LOC B19 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c3_dqs_t[11]}]
#set_property -dict {LOC A19 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c3_dqs_c[11]}]
#set_property -dict {LOC F18 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c3_dqs_t[12]}]
#set_property -dict {LOC F17 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c3_dqs_c[12]}]
#set_property -dict {LOC H19 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c3_dqs_t[13]}]
#set_property -dict {LOC G19 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c3_dqs_c[13]}]
#set_property -dict {LOC F23 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c3_dqs_t[14]}]
#set_property -dict {LOC E23 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c3_dqs_c[14]}]
#set_property -dict {LOC H23 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c3_dqs_t[15]}]
#set_property -dict {LOC H22 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c3_dqs_c[15]}]
#set_property -dict {LOC R16 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c3_dqs_t[16]}]
#set_property -dict {LOC P15 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c3_dqs_c[16]}]
#set_property -dict {LOC T13 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c3_dqs_t[17]}]
#set_property -dict {LOC R13 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c3_dqs_c[17]}]

View File

@ -1,76 +0,0 @@
# 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

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

View File

@ -1,93 +0,0 @@
/*
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 switch and button inputs with a slow sampled shift register
*/
module debounce_switch #(
parameter WIDTH=1, // width of the input and output signals
parameter N=3, // length of shift register
parameter RATE=125000 // clock division factor
)(
input wire clk,
input wire rst,
input wire [WIDTH-1:0] in,
output wire [WIDTH-1:0] out
);
reg [23:0] cnt_reg = 24'd0;
reg [N-1:0] debounce_reg[WIDTH-1:0];
reg [WIDTH-1:0] state;
/*
* The synchronized output is the state register
*/
assign out = state;
integer k;
always @(posedge clk or posedge rst) begin
if (rst) begin
cnt_reg <= 0;
state <= 0;
for (k = 0; k < WIDTH; k = k + 1) begin
debounce_reg[k] <= 0;
end
end else begin
if (cnt_reg < RATE) begin
cnt_reg <= cnt_reg + 24'd1;
end else begin
cnt_reg <= 24'd0;
end
if (cnt_reg == 24'd0) begin
for (k = 0; k < WIDTH; k = k + 1) begin
debounce_reg[k] <= {debounce_reg[k][N-2:0], in[k]};
end
end
for (k = 0; k < WIDTH; k = k + 1) begin
if (|debounce_reg[k] == 0) begin
state[k] <= 0;
end else if (&debounce_reg[k] == 1) begin
state[k] <= 1;
end else begin
state[k] <= state[k];
end
end
end
end
endmodule
`resetall

View File

@ -1,395 +0,0 @@
/*
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

@ -1,307 +0,0 @@
/*
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

@ -1,702 +0,0 @@
/*
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 (
/*
* Reset: Push button, active low
*/
input wire reset,
/*
* GPIO
*/
input wire [3:0] sw,
output wire [2:0] led,
/*
* I2C for board management
*/
inout wire i2c_scl,
inout wire i2c_sda,
/*
* Ethernet: QSFP28
*/
output wire [3:0] qsfp0_tx_p,
output wire [3:0] qsfp0_tx_n,
input wire [3:0] qsfp0_rx_p,
input wire [3:0] qsfp0_rx_n,
// input wire qsfp0_mgt_refclk_0_p,
// input wire qsfp0_mgt_refclk_0_n,
input wire qsfp0_mgt_refclk_1_p,
input wire qsfp0_mgt_refclk_1_n,
output wire qsfp0_modsell,
output wire qsfp0_resetl,
input wire qsfp0_modprsl,
input wire qsfp0_intl,
output wire qsfp0_lpmode,
output wire qsfp0_refclk_reset,
output wire [1:0] qsfp0_fs,
output wire [3:0] qsfp1_tx_p,
output wire [3:0] qsfp1_tx_n,
input wire [3:0] qsfp1_rx_p,
input wire [3:0] qsfp1_rx_n,
// input wire qsfp1_mgt_refclk_0_p,
// input wire qsfp1_mgt_refclk_0_n,
input wire qsfp1_mgt_refclk_1_p,
input wire qsfp1_mgt_refclk_1_n,
output wire qsfp1_modsell,
output wire qsfp1_resetl,
input wire qsfp1_modprsl,
input wire qsfp1_intl,
output wire qsfp1_lpmode,
output wire qsfp1_refclk_reset,
output wire [1:0] qsfp1_fs,
/*
* UART: 500000 bps, 8N1
*/
output wire uart_rxd,
input wire uart_txd
);
// Clock and reset
wire cfgmclk_int;
wire clk_161mhz_ref_int;
// 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;
wire mmcm_locked;
wire mmcm_clkfb;
// MMCM instance
// 161.13 MHz in, 125 MHz out
// PFD range: 10 MHz to 500 MHz
// VCO range: 800 MHz to 1600 MHz
// M = 64, D = 11 sets Fvco = 937.5 MHz (in range)
// Divide by 7.5 to get output frequency of 125 MHz
MMCME4_BASE #(
.BANDWIDTH("OPTIMIZED"),
.CLKOUT0_DIVIDE_F(7.5),
.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(64),
.CLKFBOUT_PHASE(0),
.DIVCLK_DIVIDE(11),
.REF_JITTER1(0.010),
.CLKIN1_PERIOD(6.206),
.STARTUP_WAIT("FALSE"),
.CLKOUT4_CASCADE("FALSE")
)
clk_mmcm_inst (
.CLKIN1(clk_161mhz_ref_int),
.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)
);
// GPIO
wire [3:0] sw_int;
debounce_switch #(
.WIDTH(4),
.N(4),
.RATE(156000)
)
debounce_switch_inst (
.clk(clk_156mhz_int),
.rst(rst_156mhz_int),
.in({sw}),
.out({sw_int})
);
wire uart_txd_int;
sync_signal #(
.WIDTH(1),
.N(2)
)
sync_signal_inst (
.clk(clk_156mhz_int),
.in({uart_txd}),
.out({uart_txd_int})
);
// SI570 I2C
wire i2c_scl_i;
wire i2c_scl_o = 1'b1;
wire i2c_scl_t = 1'b1;
wire i2c_sda_i;
wire i2c_sda_o = 1'b1;
wire i2c_sda_t = 1'b1;
assign i2c_scl_i = i2c_scl;
assign i2c_scl = i2c_scl_t ? 1'bz : i2c_scl_o;
assign i2c_sda_i = i2c_sda;
assign i2c_sda = i2c_sda_t ? 1'bz : i2c_sda_o;
// startupe3 instance
wire cfgmclk;
STARTUPE3
startupe3_inst (
.CFGCLK(),
.CFGMCLK(cfgmclk),
.DI(4'd0),
.DO(),
.DTS(1'b1),
.EOS(),
.FCSBO(1'b0),
.FCSBTS(1'b1),
.GSR(1'b0),
.GTS(1'b0),
.KEYCLEARB(1'b1),
.PACK(1'b0),
.PREQ(),
.USRCCLKO(1'b0),
.USRCCLKTS(1'b1),
.USRDONEO(1'b0),
.USRDONETS(1'b1)
);
BUFG
cfgmclk_bufg_inst (
.I(cfgmclk),
.O(cfgmclk_int)
);
// configure SI5335 clock generators
reg qsfp_refclk_reset_reg = 1'b1;
reg sys_reset_reg = 1'b1;
reg [9:0] reset_timer_reg = 0;
assign mmcm_rst = sys_reset_reg;
always @(posedge cfgmclk_int) begin
if (&reset_timer_reg) begin
if (qsfp_refclk_reset_reg) begin
qsfp_refclk_reset_reg <= 1'b0;
reset_timer_reg <= 0;
end else begin
qsfp_refclk_reset_reg <= 1'b0;
sys_reset_reg <= 1'b0;
end
end else begin
reset_timer_reg <= reset_timer_reg + 1;
end
if (!reset) begin
qsfp_refclk_reset_reg <= 1'b1;
sys_reset_reg <= 1'b1;
reset_timer_reg <= 0;
end
end
// XGMII 10G PHY
// QSFP0
assign qsfp0_modsell = 1'b0;
assign qsfp0_resetl = 1'b1;
assign qsfp0_lpmode = 1'b0;
assign qsfp0_refclk_reset = qsfp_refclk_reset_reg;
assign qsfp0_fs = 2'b10;
wire qsfp0_tx_clk_1_int;
wire qsfp0_tx_rst_1_int;
wire [63:0] qsfp0_txd_1_int;
wire [7:0] qsfp0_txc_1_int;
wire qsfp0_rx_clk_1_int;
wire qsfp0_rx_rst_1_int;
wire [63:0] qsfp0_rxd_1_int;
wire [7:0] qsfp0_rxc_1_int;
wire qsfp0_tx_clk_2_int;
wire qsfp0_tx_rst_2_int;
wire [63:0] qsfp0_txd_2_int;
wire [7:0] qsfp0_txc_2_int;
wire qsfp0_rx_clk_2_int;
wire qsfp0_rx_rst_2_int;
wire [63:0] qsfp0_rxd_2_int;
wire [7:0] qsfp0_rxc_2_int;
wire qsfp0_tx_clk_3_int;
wire qsfp0_tx_rst_3_int;
wire [63:0] qsfp0_txd_3_int;
wire [7:0] qsfp0_txc_3_int;
wire qsfp0_rx_clk_3_int;
wire qsfp0_rx_rst_3_int;
wire [63:0] qsfp0_rxd_3_int;
wire [7:0] qsfp0_rxc_3_int;
wire qsfp0_tx_clk_4_int;
wire qsfp0_tx_rst_4_int;
wire [63:0] qsfp0_txd_4_int;
wire [7:0] qsfp0_txc_4_int;
wire qsfp0_rx_clk_4_int;
wire qsfp0_rx_rst_4_int;
wire [63:0] qsfp0_rxd_4_int;
wire [7:0] qsfp0_rxc_4_int;
assign clk_156mhz_int = qsfp0_tx_clk_1_int;
assign rst_156mhz_int = qsfp0_tx_rst_1_int;
wire qsfp0_rx_block_lock_1;
wire qsfp0_rx_block_lock_2;
wire qsfp0_rx_block_lock_3;
wire qsfp0_rx_block_lock_4;
wire qsfp0_gtpowergood;
wire qsfp0_mgt_refclk_1;
wire qsfp0_mgt_refclk_1_int;
wire qsfp0_mgt_refclk_1_bufg;
assign clk_161mhz_ref_int = qsfp0_mgt_refclk_1_bufg;
IBUFDS_GTE4 ibufds_gte4_qsfp0_mgt_refclk_1_inst (
.I (qsfp0_mgt_refclk_1_p),
.IB (qsfp0_mgt_refclk_1_n),
.CEB (1'b0),
.O (qsfp0_mgt_refclk_1),
.ODIV2 (qsfp0_mgt_refclk_1_int)
);
BUFG_GT bufg_gt_refclk_inst (
.CE (qsfp0_gtpowergood),
.CEMASK (1'b1),
.CLR (1'b0),
.CLRMASK (1'b1),
.DIV (3'd0),
.I (qsfp0_mgt_refclk_1_int),
.O (qsfp0_mgt_refclk_1_bufg)
);
eth_xcvr_phy_quad_wrapper #(
.TX_SERDES_PIPELINE(2),
.RX_SERDES_PIPELINE(2),
.COUNT_125US(125000/2.56)
)
qsfp0_phy_inst (
.xcvr_ctrl_clk(clk_125mhz_int),
.xcvr_ctrl_rst(rst_125mhz_int),
/*
* Common
*/
.xcvr_gtpowergood_out(qsfp0_gtpowergood),
/*
* PLL
*/
.xcvr_gtrefclk00_in(qsfp0_mgt_refclk_1),
/*
* Serial data
*/
.xcvr_txp(qsfp0_tx_p),
.xcvr_txn(qsfp0_tx_n),
.xcvr_rxp(qsfp0_rx_p),
.xcvr_rxn(qsfp0_rx_n),
/*
* PHY connections
*/
.phy_1_tx_clk(qsfp0_tx_clk_1_int),
.phy_1_tx_rst(qsfp0_tx_rst_1_int),
.phy_1_xgmii_txd(qsfp0_txd_1_int),
.phy_1_xgmii_txc(qsfp0_txc_1_int),
.phy_1_rx_clk(qsfp0_rx_clk_1_int),
.phy_1_rx_rst(qsfp0_rx_rst_1_int),
.phy_1_xgmii_rxd(qsfp0_rxd_1_int),
.phy_1_xgmii_rxc(qsfp0_rxc_1_int),
.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(qsfp0_rx_block_lock_1),
.phy_1_rx_status(),
.phy_1_cfg_tx_prbs31_enable(1'b0),
.phy_1_cfg_rx_prbs31_enable(1'b0),
.phy_2_tx_clk(qsfp0_tx_clk_2_int),
.phy_2_tx_rst(qsfp0_tx_rst_2_int),
.phy_2_xgmii_txd(qsfp0_txd_2_int),
.phy_2_xgmii_txc(qsfp0_txc_2_int),
.phy_2_rx_clk(qsfp0_rx_clk_2_int),
.phy_2_rx_rst(qsfp0_rx_rst_2_int),
.phy_2_xgmii_rxd(qsfp0_rxd_2_int),
.phy_2_xgmii_rxc(qsfp0_rxc_2_int),
.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(qsfp0_rx_block_lock_2),
.phy_2_rx_status(),
.phy_2_cfg_tx_prbs31_enable(1'b0),
.phy_2_cfg_rx_prbs31_enable(1'b0),
.phy_3_tx_clk(qsfp0_tx_clk_3_int),
.phy_3_tx_rst(qsfp0_tx_rst_3_int),
.phy_3_xgmii_txd(qsfp0_txd_3_int),
.phy_3_xgmii_txc(qsfp0_txc_3_int),
.phy_3_rx_clk(qsfp0_rx_clk_3_int),
.phy_3_rx_rst(qsfp0_rx_rst_3_int),
.phy_3_xgmii_rxd(qsfp0_rxd_3_int),
.phy_3_xgmii_rxc(qsfp0_rxc_3_int),
.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(qsfp0_rx_block_lock_3),
.phy_3_rx_status(),
.phy_3_cfg_tx_prbs31_enable(1'b0),
.phy_3_cfg_rx_prbs31_enable(1'b0),
.phy_4_tx_clk(qsfp0_tx_clk_4_int),
.phy_4_tx_rst(qsfp0_tx_rst_4_int),
.phy_4_xgmii_txd(qsfp0_txd_4_int),
.phy_4_xgmii_txc(qsfp0_txc_4_int),
.phy_4_rx_clk(qsfp0_rx_clk_4_int),
.phy_4_rx_rst(qsfp0_rx_rst_4_int),
.phy_4_xgmii_rxd(qsfp0_rxd_4_int),
.phy_4_xgmii_rxc(qsfp0_rxc_4_int),
.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(qsfp0_rx_block_lock_4),
.phy_4_rx_status(),
.phy_4_cfg_tx_prbs31_enable(1'b0),
.phy_4_cfg_rx_prbs31_enable(1'b0)
);
// QSFP1
assign qsfp1_modsell = 1'b0;
assign qsfp1_resetl = 1'b1;
assign qsfp1_lpmode = 1'b0;
assign qsfp1_refclk_reset = qsfp_refclk_reset_reg;
assign qsfp1_fs = 2'b10;
wire qsfp1_tx_clk_1_int;
wire qsfp1_tx_rst_1_int;
wire [63:0] qsfp1_txd_1_int;
wire [7:0] qsfp1_txc_1_int;
wire qsfp1_rx_clk_1_int;
wire qsfp1_rx_rst_1_int;
wire [63:0] qsfp1_rxd_1_int;
wire [7:0] qsfp1_rxc_1_int;
wire qsfp1_tx_clk_2_int;
wire qsfp1_tx_rst_2_int;
wire [63:0] qsfp1_txd_2_int;
wire [7:0] qsfp1_txc_2_int;
wire qsfp1_rx_clk_2_int;
wire qsfp1_rx_rst_2_int;
wire [63:0] qsfp1_rxd_2_int;
wire [7:0] qsfp1_rxc_2_int;
wire qsfp1_tx_clk_3_int;
wire qsfp1_tx_rst_3_int;
wire [63:0] qsfp1_txd_3_int;
wire [7:0] qsfp1_txc_3_int;
wire qsfp1_rx_clk_3_int;
wire qsfp1_rx_rst_3_int;
wire [63:0] qsfp1_rxd_3_int;
wire [7:0] qsfp1_rxc_3_int;
wire qsfp1_tx_clk_4_int;
wire qsfp1_tx_rst_4_int;
wire [63:0] qsfp1_txd_4_int;
wire [7:0] qsfp1_txc_4_int;
wire qsfp1_rx_clk_4_int;
wire qsfp1_rx_rst_4_int;
wire [63:0] qsfp1_rxd_4_int;
wire [7:0] qsfp1_rxc_4_int;
wire qsfp1_rx_block_lock_1;
wire qsfp1_rx_block_lock_2;
wire qsfp1_rx_block_lock_3;
wire qsfp1_rx_block_lock_4;
wire qsfp1_mgt_refclk_1;
IBUFDS_GTE4 ibufds_gte4_qsfp1_mgt_refclk_1_inst (
.I (qsfp1_mgt_refclk_1_p),
.IB (qsfp1_mgt_refclk_1_n),
.CEB (1'b0),
.O (qsfp1_mgt_refclk_1),
.ODIV2 ()
);
eth_xcvr_phy_quad_wrapper #(
.TX_SERDES_PIPELINE(2),
.RX_SERDES_PIPELINE(2),
.COUNT_125US(125000/2.56)
)
qsfp1_phy_inst (
.xcvr_ctrl_clk(clk_125mhz_int),
.xcvr_ctrl_rst(rst_125mhz_int),
/*
* Common
*/
.xcvr_gtpowergood_out(),
/*
* PLL
*/
.xcvr_gtrefclk00_in(qsfp1_mgt_refclk_1),
/*
* Serial data
*/
.xcvr_txp(qsfp1_tx_p),
.xcvr_txn(qsfp1_tx_n),
.xcvr_rxp(qsfp1_rx_p),
.xcvr_rxn(qsfp1_rx_n),
/*
* PHY connections
*/
.phy_1_tx_clk(qsfp1_tx_clk_1_int),
.phy_1_tx_rst(qsfp1_tx_rst_1_int),
.phy_1_xgmii_txd(qsfp1_txd_1_int),
.phy_1_xgmii_txc(qsfp1_txc_1_int),
.phy_1_rx_clk(qsfp1_rx_clk_1_int),
.phy_1_rx_rst(qsfp1_rx_rst_1_int),
.phy_1_xgmii_rxd(qsfp1_rxd_1_int),
.phy_1_xgmii_rxc(qsfp1_rxc_1_int),
.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(qsfp1_rx_block_lock_1),
.phy_1_rx_status(),
.phy_1_cfg_tx_prbs31_enable(1'b0),
.phy_1_cfg_rx_prbs31_enable(1'b0),
.phy_2_tx_clk(qsfp1_tx_clk_2_int),
.phy_2_tx_rst(qsfp1_tx_rst_2_int),
.phy_2_xgmii_txd(qsfp1_txd_2_int),
.phy_2_xgmii_txc(qsfp1_txc_2_int),
.phy_2_rx_clk(qsfp1_rx_clk_2_int),
.phy_2_rx_rst(qsfp1_rx_rst_2_int),
.phy_2_xgmii_rxd(qsfp1_rxd_2_int),
.phy_2_xgmii_rxc(qsfp1_rxc_2_int),
.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(qsfp1_rx_block_lock_2),
.phy_2_rx_status(),
.phy_2_cfg_tx_prbs31_enable(1'b0),
.phy_2_cfg_rx_prbs31_enable(1'b0),
.phy_3_tx_clk(qsfp1_tx_clk_3_int),
.phy_3_tx_rst(qsfp1_tx_rst_3_int),
.phy_3_xgmii_txd(qsfp1_txd_3_int),
.phy_3_xgmii_txc(qsfp1_txc_3_int),
.phy_3_rx_clk(qsfp1_rx_clk_3_int),
.phy_3_rx_rst(qsfp1_rx_rst_3_int),
.phy_3_xgmii_rxd(qsfp1_rxd_3_int),
.phy_3_xgmii_rxc(qsfp1_rxc_3_int),
.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(qsfp1_rx_block_lock_3),
.phy_3_rx_status(),
.phy_3_cfg_tx_prbs31_enable(1'b0),
.phy_3_cfg_rx_prbs31_enable(1'b0),
.phy_4_tx_clk(qsfp1_tx_clk_4_int),
.phy_4_tx_rst(qsfp1_tx_rst_4_int),
.phy_4_xgmii_txd(qsfp1_txd_4_int),
.phy_4_xgmii_txc(qsfp1_txc_4_int),
.phy_4_rx_clk(qsfp1_rx_clk_4_int),
.phy_4_rx_rst(qsfp1_rx_rst_4_int),
.phy_4_xgmii_rxd(qsfp1_rxd_4_int),
.phy_4_xgmii_rxc(qsfp1_rxc_4_int),
.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(qsfp1_rx_block_lock_4),
.phy_4_rx_status(),
.phy_4_cfg_tx_prbs31_enable(1'b0),
.phy_4_cfg_rx_prbs31_enable(1'b0)
);
fpga_core
core_inst (
/*
* Clock: 156.25 MHz
* Synchronous reset
*/
.clk(clk_156mhz_int),
.rst(rst_156mhz_int),
/*
* GPIO
*/
.sw(sw_int),
.led(led),
/*
* Ethernet: QSFP28
*/
.qsfp0_tx_clk_1(qsfp0_tx_clk_1_int),
.qsfp0_tx_rst_1(qsfp0_tx_rst_1_int),
.qsfp0_txd_1(qsfp0_txd_1_int),
.qsfp0_txc_1(qsfp0_txc_1_int),
.qsfp0_rx_clk_1(qsfp0_rx_clk_1_int),
.qsfp0_rx_rst_1(qsfp0_rx_rst_1_int),
.qsfp0_rxd_1(qsfp0_rxd_1_int),
.qsfp0_rxc_1(qsfp0_rxc_1_int),
.qsfp0_tx_clk_2(qsfp0_tx_clk_2_int),
.qsfp0_tx_rst_2(qsfp0_tx_rst_2_int),
.qsfp0_txd_2(qsfp0_txd_2_int),
.qsfp0_txc_2(qsfp0_txc_2_int),
.qsfp0_rx_clk_2(qsfp0_rx_clk_2_int),
.qsfp0_rx_rst_2(qsfp0_rx_rst_2_int),
.qsfp0_rxd_2(qsfp0_rxd_2_int),
.qsfp0_rxc_2(qsfp0_rxc_2_int),
.qsfp0_tx_clk_3(qsfp0_tx_clk_3_int),
.qsfp0_tx_rst_3(qsfp0_tx_rst_3_int),
.qsfp0_txd_3(qsfp0_txd_3_int),
.qsfp0_txc_3(qsfp0_txc_3_int),
.qsfp0_rx_clk_3(qsfp0_rx_clk_3_int),
.qsfp0_rx_rst_3(qsfp0_rx_rst_3_int),
.qsfp0_rxd_3(qsfp0_rxd_3_int),
.qsfp0_rxc_3(qsfp0_rxc_3_int),
.qsfp0_tx_clk_4(qsfp0_tx_clk_4_int),
.qsfp0_tx_rst_4(qsfp0_tx_rst_4_int),
.qsfp0_txd_4(qsfp0_txd_4_int),
.qsfp0_txc_4(qsfp0_txc_4_int),
.qsfp0_rx_clk_4(qsfp0_rx_clk_4_int),
.qsfp0_rx_rst_4(qsfp0_rx_rst_4_int),
.qsfp0_rxd_4(qsfp0_rxd_4_int),
.qsfp0_rxc_4(qsfp0_rxc_4_int),
.qsfp1_tx_clk_1(qsfp1_tx_clk_1_int),
.qsfp1_tx_rst_1(qsfp1_tx_rst_1_int),
.qsfp1_txd_1(qsfp1_txd_1_int),
.qsfp1_txc_1(qsfp1_txc_1_int),
.qsfp1_rx_clk_1(qsfp1_rx_clk_1_int),
.qsfp1_rx_rst_1(qsfp1_rx_rst_1_int),
.qsfp1_rxd_1(qsfp1_rxd_1_int),
.qsfp1_rxc_1(qsfp1_rxc_1_int),
.qsfp1_tx_clk_2(qsfp1_tx_clk_2_int),
.qsfp1_tx_rst_2(qsfp1_tx_rst_2_int),
.qsfp1_txd_2(qsfp1_txd_2_int),
.qsfp1_txc_2(qsfp1_txc_2_int),
.qsfp1_rx_clk_2(qsfp1_rx_clk_2_int),
.qsfp1_rx_rst_2(qsfp1_rx_rst_2_int),
.qsfp1_rxd_2(qsfp1_rxd_2_int),
.qsfp1_rxc_2(qsfp1_rxc_2_int),
.qsfp1_tx_clk_3(qsfp1_tx_clk_3_int),
.qsfp1_tx_rst_3(qsfp1_tx_rst_3_int),
.qsfp1_txd_3(qsfp1_txd_3_int),
.qsfp1_txc_3(qsfp1_txc_3_int),
.qsfp1_rx_clk_3(qsfp1_rx_clk_3_int),
.qsfp1_rx_rst_3(qsfp1_rx_rst_3_int),
.qsfp1_rxd_3(qsfp1_rxd_3_int),
.qsfp1_rxc_3(qsfp1_rxc_3_int),
.qsfp1_tx_clk_4(qsfp1_tx_clk_4_int),
.qsfp1_tx_rst_4(qsfp1_tx_rst_4_int),
.qsfp1_txd_4(qsfp1_txd_4_int),
.qsfp1_txc_4(qsfp1_txc_4_int),
.qsfp1_rx_clk_4(qsfp1_rx_clk_4_int),
.qsfp1_rx_rst_4(qsfp1_rx_rst_4_int),
.qsfp1_rxd_4(qsfp1_rxd_4_int),
.qsfp1_rxc_4(qsfp1_rxc_4_int),
/*
* UART: 115200 bps, 8N1
*/
.uart_rxd(uart_rxd),
.uart_txd(uart_txd_int)
);
endmodule
`resetall

View File

@ -1,670 +0,0 @@
/*
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 TARGET = "XILINX"
)
(
/*
* Clock: 156.25MHz
* Synchronous reset
*/
input wire clk,
input wire rst,
/*
* GPIO
*/
input wire [3:0] sw,
output wire [2:0] led,
/*
* Ethernet: QSFP28
*/
input wire qsfp0_tx_clk_1,
input wire qsfp0_tx_rst_1,
output wire [63:0] qsfp0_txd_1,
output wire [7:0] qsfp0_txc_1,
input wire qsfp0_rx_clk_1,
input wire qsfp0_rx_rst_1,
input wire [63:0] qsfp0_rxd_1,
input wire [7:0] qsfp0_rxc_1,
input wire qsfp0_tx_clk_2,
input wire qsfp0_tx_rst_2,
output wire [63:0] qsfp0_txd_2,
output wire [7:0] qsfp0_txc_2,
input wire qsfp0_rx_clk_2,
input wire qsfp0_rx_rst_2,
input wire [63:0] qsfp0_rxd_2,
input wire [7:0] qsfp0_rxc_2,
input wire qsfp0_tx_clk_3,
input wire qsfp0_tx_rst_3,
output wire [63:0] qsfp0_txd_3,
output wire [7:0] qsfp0_txc_3,
input wire qsfp0_rx_clk_3,
input wire qsfp0_rx_rst_3,
input wire [63:0] qsfp0_rxd_3,
input wire [7:0] qsfp0_rxc_3,
input wire qsfp0_tx_clk_4,
input wire qsfp0_tx_rst_4,
output wire [63:0] qsfp0_txd_4,
output wire [7:0] qsfp0_txc_4,
input wire qsfp0_rx_clk_4,
input wire qsfp0_rx_rst_4,
input wire [63:0] qsfp0_rxd_4,
input wire [7:0] qsfp0_rxc_4,
input wire qsfp1_tx_clk_1,
input wire qsfp1_tx_rst_1,
output wire [63:0] qsfp1_txd_1,
output wire [7:0] qsfp1_txc_1,
input wire qsfp1_rx_clk_1,
input wire qsfp1_rx_rst_1,
input wire [63:0] qsfp1_rxd_1,
input wire [7:0] qsfp1_rxc_1,
input wire qsfp1_tx_clk_2,
input wire qsfp1_tx_rst_2,
output wire [63:0] qsfp1_txd_2,
output wire [7:0] qsfp1_txc_2,
input wire qsfp1_rx_clk_2,
input wire qsfp1_rx_rst_2,
input wire [63:0] qsfp1_rxd_2,
input wire [7:0] qsfp1_rxc_2,
input wire qsfp1_tx_clk_3,
input wire qsfp1_tx_rst_3,
output wire [63:0] qsfp1_txd_3,
output wire [7:0] qsfp1_txc_3,
input wire qsfp1_rx_clk_3,
input wire qsfp1_rx_rst_3,
input wire [63:0] qsfp1_rxd_3,
input wire [7:0] qsfp1_rxc_3,
input wire qsfp1_tx_clk_4,
input wire qsfp1_tx_rst_4,
output wire [63:0] qsfp1_txd_4,
output wire [7:0] qsfp1_txc_4,
input wire qsfp1_rx_clk_4,
input wire qsfp1_rx_rst_4,
input wire [63:0] qsfp1_rxd_4,
input wire [7:0] qsfp1_rxc_4,
/*
* UART: 115200 bps, 8N1
*/
output wire uart_rxd,
input wire uart_txd
);
// 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 led = sw;
assign led = led_reg;
assign qsfp0_txd_2 = 64'h0707070707070707;
assign qsfp0_txc_2 = 8'hff;
assign qsfp0_txd_3 = 64'h0707070707070707;
assign qsfp0_txc_3 = 8'hff;
assign qsfp0_txd_4 = 64'h0707070707070707;
assign qsfp0_txc_4 = 8'hff;
assign qsfp1_txd_1 = 64'h0707070707070707;
assign qsfp1_txc_1 = 8'hff;
assign qsfp1_txd_2 = 64'h0707070707070707;
assign qsfp1_txc_2 = 8'hff;
assign qsfp1_txd_3 = 64'h0707070707070707;
assign qsfp1_txc_3 = 8'hff;
assign qsfp1_txd_4 = 64'h0707070707070707;
assign qsfp1_txc_4 = 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(qsfp0_rx_clk_1),
.rx_rst(qsfp0_rx_rst_1),
.tx_clk(qsfp0_tx_clk_1),
.tx_rst(qsfp0_tx_rst_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(qsfp0_rxd_1),
.xgmii_rxc(qsfp0_rxc_1),
.xgmii_txd(qsfp0_txd_1),
.xgmii_txc(qsfp0_txc_1),
.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

@ -1,62 +0,0 @@
/*
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

@ -1,229 +0,0 @@
"""
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.qsfp_source = []
self.qsfp_sink = []
for x in range(2):
sources = []
sinks = []
for y in range(1, 5):
cocotb.start_soon(Clock(getattr(dut, f"qsfp{x}_rx_clk_{y}"), 2.56, units="ns").start())
source = XgmiiSource(getattr(dut, f"qsfp{x}_rxd_{y}"), getattr(dut, f"qsfp{x}_rxc_{y}"), getattr(dut, f"qsfp{x}_rx_clk_{y}"), getattr(dut, f"qsfp{x}_rx_rst_{y}"))
sources.append(source)
cocotb.start_soon(Clock(getattr(dut, f"qsfp{x}_tx_clk_{y}"), 2.56, units="ns").start())
sink = XgmiiSink(getattr(dut, f"qsfp{x}_txd_{y}"), getattr(dut, f"qsfp{x}_txc_{y}"), getattr(dut, f"qsfp{x}_tx_clk_{y}"), getattr(dut, f"qsfp{x}_tx_rst_{y}"))
sinks.append(sink)
self.qsfp_source.append(sources)
self.qsfp_sink.append(sinks)
dut.sw.setimmediatevalue(0)
async def init(self):
self.dut.rst.setimmediatevalue(0)
for x in range(2):
for y in range(1, 5):
getattr(self.dut, f"qsfp{x}_rx_rst_{y}").setimmediatevalue(0)
getattr(self.dut, f"qsfp{x}_tx_rst_{y}").setimmediatevalue(0)
for k in range(10):
await RisingEdge(self.dut.clk)
self.dut.rst.value = 1
for x in range(2):
for y in range(1, 5):
getattr(self.dut, f"qsfp{x}_rx_rst_{y}").value = 1
getattr(self.dut, f"qsfp{x}_tx_rst_{y}").value = 1
for k in range(10):
await RisingEdge(self.dut.clk)
self.dut.rst.value = 0
for x in range(2):
for y in range(1, 5):
getattr(self.dut, f"qsfp{x}_rx_rst_{y}").value = 0
getattr(self.dut, f"qsfp{x}_tx_rst_{y}").value = 0
@cocotb.test()
async def run_test(dut):
tb = TB(dut)
await tb.init()
tb.log.info("test UDP RX packet")
payload = bytes([x % 256 for x in range(256)])
eth = Ether(src='5a:51:52:53:54:55', dst='02:00:00:00:00:00')
ip = IP(src='192.168.1.100', dst='192.168.1.128')
udp = UDP(sport=5678, dport=1234)
test_pkt = eth / ip / udp / payload
test_frame = XgmiiFrame.from_payload(test_pkt.build())
await tb.qsfp_source[0][0].send(test_frame)
tb.log.info("receive ARP request")
rx_frame = await tb.qsfp_sink[0][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.qsfp_source[0][0].send(resp_frame)
tb.log.info("receive UDP packet")
rx_frame = await tb.qsfp_sink[0][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 = dut
verilog_sources = [
os.path.join(rtl_dir, f"{dut}.v"),
os.path.join(eth_rtl_dir, "eth_mac_10g_fifo.v"),
os.path.join(eth_rtl_dir, "eth_mac_10g.v"),
os.path.join(eth_rtl_dir, "axis_xgmii_rx_64.v"),
os.path.join(eth_rtl_dir, "axis_xgmii_tx_64.v"),
os.path.join(eth_rtl_dir, "lfsr.v"),
os.path.join(eth_rtl_dir, "eth_axis_rx.v"),
os.path.join(eth_rtl_dir, "eth_axis_tx.v"),
os.path.join(eth_rtl_dir, "udp_complete_64.v"),
os.path.join(eth_rtl_dir, "udp_checksum_gen_64.v"),
os.path.join(eth_rtl_dir, "udp_64.v"),
os.path.join(eth_rtl_dir, "udp_ip_rx_64.v"),
os.path.join(eth_rtl_dir, "udp_ip_tx_64.v"),
os.path.join(eth_rtl_dir, "ip_complete_64.v"),
os.path.join(eth_rtl_dir, "ip_64.v"),
os.path.join(eth_rtl_dir, "ip_eth_rx_64.v"),
os.path.join(eth_rtl_dir, "ip_eth_tx_64.v"),
os.path.join(eth_rtl_dir, "ip_arb_mux.v"),
os.path.join(eth_rtl_dir, "arp.v"),
os.path.join(eth_rtl_dir, "arp_cache.v"),
os.path.join(eth_rtl_dir, "arp_eth_rx.v"),
os.path.join(eth_rtl_dir, "arp_eth_tx.v"),
os.path.join(eth_rtl_dir, "eth_arb_mux.v"),
os.path.join(axis_rtl_dir, "arbiter.v"),
os.path.join(axis_rtl_dir, "priority_encoder.v"),
os.path.join(axis_rtl_dir, "axis_fifo.v"),
os.path.join(axis_rtl_dir, "axis_async_fifo.v"),
os.path.join(axis_rtl_dir, "axis_async_fifo_adapter.v"),
]
parameters = {}
# parameters['A'] = val
extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()}
sim_build = os.path.join(tests_dir, "sim_build",
request.node.name.replace('[', '-').replace(']', ''))
cocotb_test.simulator.run(
python_search=[tests_dir],
verilog_sources=verilog_sources,
toplevel=toplevel,
module=module,
parameters=parameters,
sim_build=sim_build,
extra_env=extra_env,
)

View File

@ -4,17 +4,46 @@
This example design targets the HiTech Global HTG-9200 FPGA board.
The design by default listens to UDP port 1234 at IP address 192.168.1.128 and
will echo back any packets received. The design will also respond correctly
to ARP requests.
The design 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-2-e
* FPGA: xcvu9p-flgb2104-2-e or xcvu13p-fhgb2104-2-e
* PHY: 10G BASE-R PHY IP core and internal GTY transceiver
## How to build
Run make to build. Ensure that the Xilinx Vivado toolchain components are
in PATH.
Run make to build. Ensure that the Xilinx Vivado toolchain components are in PATH.
## Board configuration
For correct operation, several DIP switches need to be set correctly. Additionally, some other component-level modifications may be required.
DIP switch settings:
* S2.1: off (enable EMCCLK, if needed to boot from flash)
* S3.2: off (enable U24 ref_clk)
* S4.5: off (enable U47 osc_gty2)
* S4.8: on (enable U48 outputs)
Note that S4.8 has no effect if R441 is not installed (which appears to be the default configuration) as U48 has an internal pull-down on OEb. The PLL configuration in this design also ignores the IN_SEL pins, so S4.6 and S4.7 have no effect. The other DIP switches do not affect the operation of this design.
When using optical modules or active optical cables, it is necessary to pull the lpmode pins low to enable the lasers. On the HTG-9200, the lpmode pins are not connected to the FPGA, so it is necessary to pull the pins low on the board. The board has footprints for pull-down resistors on the lpmode pins, which are not populated by default. These are R414, R392, R336, R316, R276, R475, R471, R473, and R477 (respectively for QSFP0-9). Shorting across these footprints or installing pull-down resistors of around 150 ohms will bring installed modules out of low power mode.
The HTG-9200 was originally designed for Virtex UltraScale, so by default some of the power supply voltages are too high for an UltraScale+ device. In particular, the Avcc supplies for the GTY transceivers are set to 1.0 V, which is not only outside of the recommended range of 0.873-0.927 V but it also matches the absolute max of 1.0 V. Additionally, Vccint and Vccbram are set to 0.95V, which is outside of the recommended range of 0.825-0.876 V for standard speed grades but below the absolute max of 1.0 V. Checking the supply voltages and swapping out the feedback resistors on the Vccint, Vccbram and MGT Avcc power supplies is therefore highly recommended. Note that the supplies labeled GTH feed the MGT banks on the right side of the device, which are GTH transceivers on UltraScale and GTY transceivers on UltraScale+.
The table below contains the power rail test points and feedback resistor values for the power supply rails in question for several different speed grades of Virtex UltraScale and UltraScale+ devices.
| Rail | VCCINT | VCCBRAM | GTY_AVCC | GTH_AVCC |
| ----------- | ------------ | ------------ | ------------ | ------------ |
| Test point | P6 | P8 | P9 | P1 |
| Regulator | U4, U56 | U11 | U13 | U20 |
| Part | 4/2 LTM4650 | LTM4625 | 4/4 LTM4644 | 4/4 LTM4644 |
| Current | 100A | 5A | 16A | 16A |
| FB resistor | R354 | R494 | R38 | R61 |
| US -3, -1H | 90.9K (1.0V) | 90.9K (1.0V) | 22.6K (1.0V) | 22.6K (1.0V) |
| US -2, -1 | 105K (0.95V) | 105K (0.95V) | 22.6K (1.0V) | 22.6K (1.0V) |
| US+ -3 | 121K (0.90V) | 121K (0.90V) | 30.1K (0.9V) | 30.1K (0.9V) |
| US+ -2, -1 | 147K (0.85V) | 147K (0.85V) | 30.1K (0.9V) | 30.1K (0.9V) |
| US+ -2L | 301K (0.72V) | 147K (0.85V) | 30.1K (0.9V) | 30.1K (0.9V) |
## How to test
@ -22,8 +51,7 @@ Run make program to program the HTG-9200 board with Vivado. Then run
netcat -u 192.168.1.128 1234
to open a UDP connection to port 1234. Any text entered into netcat will be
echoed back after pressing enter.
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

View File

@ -1,5 +1,6 @@
# XDC constraints for the HiTech Global HTG-9200 board
# part: xcvu9p-flgb2104-2-e
# part: xcvu13p-fhgb2104-2-e
# General configuration
set_property CFGBVS GND [current_design]

View File

@ -0,0 +1,116 @@
# FPGA settings
FPGA_PART = xcvu13p-fhgb2104-2-e
FPGA_TOP = fpga
FPGA_ARCH = virtexuplus
# Files for synthesis
SYN_FILES = rtl/fpga.v
SYN_FILES += rtl/fpga_core.v
SYN_FILES += rtl/eth_xcvr_phy_wrapper.v
SYN_FILES += rtl/eth_xcvr_phy_quad_wrapper.v
SYN_FILES += rtl/debounce_switch.v
SYN_FILES += rtl/sync_signal.v
SYN_FILES += rtl/i2c_master.v
SYN_FILES += pll/si5341_i2c_init.v
SYN_FILES += lib/eth/rtl/eth_mac_10g_fifo.v
SYN_FILES += lib/eth/rtl/eth_mac_10g.v
SYN_FILES += lib/eth/rtl/axis_xgmii_rx_64.v
SYN_FILES += lib/eth/rtl/axis_xgmii_tx_64.v
SYN_FILES += lib/eth/rtl/eth_phy_10g.v
SYN_FILES += lib/eth/rtl/eth_phy_10g_rx.v
SYN_FILES += lib/eth/rtl/eth_phy_10g_rx_if.v
SYN_FILES += lib/eth/rtl/eth_phy_10g_rx_frame_sync.v
SYN_FILES += lib/eth/rtl/eth_phy_10g_rx_ber_mon.v
SYN_FILES += lib/eth/rtl/eth_phy_10g_rx_watchdog.v
SYN_FILES += lib/eth/rtl/eth_phy_10g_tx.v
SYN_FILES += lib/eth/rtl/eth_phy_10g_tx_if.v
SYN_FILES += lib/eth/rtl/xgmii_baser_dec_64.v
SYN_FILES += lib/eth/rtl/xgmii_baser_enc_64.v
SYN_FILES += lib/eth/rtl/lfsr.v
SYN_FILES += lib/eth/rtl/eth_axis_rx.v
SYN_FILES += lib/eth/rtl/eth_axis_tx.v
SYN_FILES += lib/eth/rtl/udp_complete_64.v
SYN_FILES += lib/eth/rtl/udp_checksum_gen_64.v
SYN_FILES += lib/eth/rtl/udp_64.v
SYN_FILES += lib/eth/rtl/udp_ip_rx_64.v
SYN_FILES += lib/eth/rtl/udp_ip_tx_64.v
SYN_FILES += lib/eth/rtl/ip_complete_64.v
SYN_FILES += lib/eth/rtl/ip_64.v
SYN_FILES += lib/eth/rtl/ip_eth_rx_64.v
SYN_FILES += lib/eth/rtl/ip_eth_tx_64.v
SYN_FILES += lib/eth/rtl/ip_arb_mux.v
SYN_FILES += lib/eth/rtl/arp.v
SYN_FILES += lib/eth/rtl/arp_cache.v
SYN_FILES += lib/eth/rtl/arp_eth_rx.v
SYN_FILES += lib/eth/rtl/arp_eth_tx.v
SYN_FILES += lib/eth/rtl/eth_arb_mux.v
SYN_FILES += lib/eth/lib/axis/rtl/arbiter.v
SYN_FILES += lib/eth/lib/axis/rtl/priority_encoder.v
SYN_FILES += lib/eth/lib/axis/rtl/axis_fifo.v
SYN_FILES += lib/eth/lib/axis/rtl/axis_async_fifo.v
SYN_FILES += lib/eth/lib/axis/rtl/axis_async_fifo_adapter.v
SYN_FILES += lib/eth/lib/axis/rtl/sync_reset.v
# XDC files
XDC_FILES = fpga.xdc
XDC_FILES += lib/eth/syn/vivado/eth_mac_fifo.tcl
XDC_FILES += lib/eth/lib/axis/syn/vivado/axis_async_fifo.tcl
XDC_FILES += lib/eth/lib/axis/syn/vivado/sync_reset.tcl
# IP
IP_TCL_FILES += ip/eth_xcvr_gt.tcl
# Configuration
CONFIG_TCL_FILES = ./config.tcl
include ../common/vivado.mk
program: $(FPGA_TOP).bit
echo "open_hw" > program.tcl
echo "connect_hw_server" >> program.tcl
echo "open_hw_target" >> program.tcl
echo "current_hw_device [lindex [get_hw_devices] 0]" >> program.tcl
echo "refresh_hw_device -update_hw_probes false [current_hw_device]" >> program.tcl
echo "set_property PROGRAM.FILE {$(FPGA_TOP).bit} [current_hw_device]" >> program.tcl
echo "program_hw_devices [current_hw_device]" >> program.tcl
echo "exit" >> program.tcl
vivado -nojournal -nolog -mode batch -source program.tcl
%_primary.mcs %_secondary.mcs %_primary.prm %_secondary.prm: %.bit
echo "write_cfgmem -force -format mcs -size 128 -interface SPIx8 -loadbit {up 0x0000000 $*.bit} -checksum -file $*.mcs" > generate_mcs.tcl
echo "exit" >> generate_mcs.tcl
vivado -nojournal -nolog -mode batch -source generate_mcs.tcl
mkdir -p rev
COUNT=100; \
while [ -e rev/$*_rev$$COUNT.bit ]; \
do COUNT=$$((COUNT+1)); done; \
COUNT=$$((COUNT-1)); \
for x in _primary.mcs _secondary.mcs _primary.prm _secondary.prm; \
do cp $*$$x rev/$*_rev$$COUNT$$x; \
echo "Output: rev/$*_rev$$COUNT$$x"; done;
flash: $(FPGA_TOP)_primary.mcs $(FPGA_TOP)_secondary.mcs $(FPGA_TOP)_primary.prm $(FPGA_TOP)_secondary.prm
echo "open_hw" > flash.tcl
echo "connect_hw_server" >> flash.tcl
echo "open_hw_target" >> flash.tcl
echo "current_hw_device [lindex [get_hw_devices] 0]" >> flash.tcl
echo "refresh_hw_device -update_hw_probes false [current_hw_device]" >> flash.tcl
echo "create_hw_cfgmem -hw_device [current_hw_device] [lindex [get_cfgmem_parts {s25fl512s-spi-x1_x2_x4_x8}] 0]" >> flash.tcl
echo "current_hw_cfgmem -hw_device [current_hw_device] [get_property PROGRAM.HW_CFGMEM [current_hw_device]]" >> flash.tcl
echo "set_property PROGRAM.FILES [list \"$(FPGA_TOP)_primary.mcs\" \"$(FPGA_TOP)_secondary.mcs\"] [current_hw_cfgmem]" >> flash.tcl
echo "set_property PROGRAM.PRM_FILES [list \"$(FPGA_TOP)_primary.prm\" \"$(FPGA_TOP)_secondary.prm\"] [current_hw_cfgmem]" >> flash.tcl
echo "set_property PROGRAM.ERASE 1 [current_hw_cfgmem]" >> flash.tcl
echo "set_property PROGRAM.CFG_PROGRAM 1 [current_hw_cfgmem]" >> flash.tcl
echo "set_property PROGRAM.VERIFY 1 [current_hw_cfgmem]" >> flash.tcl
echo "set_property PROGRAM.CHECKSUM 0 [current_hw_cfgmem]" >> flash.tcl
echo "set_property PROGRAM.ADDRESS_RANGE {use_file} [current_hw_cfgmem]" >> flash.tcl
echo "set_property PROGRAM.UNUSED_PIN_TERMINATION {pull-none} [current_hw_cfgmem]" >> flash.tcl
echo "create_hw_bitstream -hw_device [current_hw_device] [get_property PROGRAM.HW_CFGMEM_BITFILE [current_hw_device]]" >> flash.tcl
echo "program_hw_devices [current_hw_device]" >> flash.tcl
echo "refresh_hw_device [current_hw_device]" >> flash.tcl
echo "program_hw_cfgmem -hw_cfgmem [current_hw_cfgmem]" >> flash.tcl
echo "boot_hw_device [current_hw_device]" >> flash.tcl
echo "exit" >> flash.tcl
vivado -nojournal -nolog -mode batch -source flash.tcl

View File

@ -0,0 +1,116 @@
# FPGA settings
FPGA_PART = xcvu13p-fhgb2104-2-e
FPGA_TOP = fpga
FPGA_ARCH = virtexuplus
# Files for synthesis
SYN_FILES = rtl/fpga.v
SYN_FILES += rtl/fpga_core.v
SYN_FILES += rtl/eth_xcvr_phy_wrapper.v
SYN_FILES += rtl/eth_xcvr_phy_quad_wrapper.v
SYN_FILES += rtl/debounce_switch.v
SYN_FILES += rtl/sync_signal.v
SYN_FILES += rtl/i2c_master.v
SYN_FILES += pll/si5341_i2c_init.v
SYN_FILES += lib/eth/rtl/eth_mac_10g_fifo.v
SYN_FILES += lib/eth/rtl/eth_mac_10g.v
SYN_FILES += lib/eth/rtl/axis_xgmii_rx_64.v
SYN_FILES += lib/eth/rtl/axis_xgmii_tx_64.v
SYN_FILES += lib/eth/rtl/eth_phy_10g.v
SYN_FILES += lib/eth/rtl/eth_phy_10g_rx.v
SYN_FILES += lib/eth/rtl/eth_phy_10g_rx_if.v
SYN_FILES += lib/eth/rtl/eth_phy_10g_rx_frame_sync.v
SYN_FILES += lib/eth/rtl/eth_phy_10g_rx_ber_mon.v
SYN_FILES += lib/eth/rtl/eth_phy_10g_rx_watchdog.v
SYN_FILES += lib/eth/rtl/eth_phy_10g_tx.v
SYN_FILES += lib/eth/rtl/eth_phy_10g_tx_if.v
SYN_FILES += lib/eth/rtl/xgmii_baser_dec_64.v
SYN_FILES += lib/eth/rtl/xgmii_baser_enc_64.v
SYN_FILES += lib/eth/rtl/lfsr.v
SYN_FILES += lib/eth/rtl/eth_axis_rx.v
SYN_FILES += lib/eth/rtl/eth_axis_tx.v
SYN_FILES += lib/eth/rtl/udp_complete_64.v
SYN_FILES += lib/eth/rtl/udp_checksum_gen_64.v
SYN_FILES += lib/eth/rtl/udp_64.v
SYN_FILES += lib/eth/rtl/udp_ip_rx_64.v
SYN_FILES += lib/eth/rtl/udp_ip_tx_64.v
SYN_FILES += lib/eth/rtl/ip_complete_64.v
SYN_FILES += lib/eth/rtl/ip_64.v
SYN_FILES += lib/eth/rtl/ip_eth_rx_64.v
SYN_FILES += lib/eth/rtl/ip_eth_tx_64.v
SYN_FILES += lib/eth/rtl/ip_arb_mux.v
SYN_FILES += lib/eth/rtl/arp.v
SYN_FILES += lib/eth/rtl/arp_cache.v
SYN_FILES += lib/eth/rtl/arp_eth_rx.v
SYN_FILES += lib/eth/rtl/arp_eth_tx.v
SYN_FILES += lib/eth/rtl/eth_arb_mux.v
SYN_FILES += lib/eth/lib/axis/rtl/arbiter.v
SYN_FILES += lib/eth/lib/axis/rtl/priority_encoder.v
SYN_FILES += lib/eth/lib/axis/rtl/axis_fifo.v
SYN_FILES += lib/eth/lib/axis/rtl/axis_async_fifo.v
SYN_FILES += lib/eth/lib/axis/rtl/axis_async_fifo_adapter.v
SYN_FILES += lib/eth/lib/axis/rtl/sync_reset.v
# XDC files
XDC_FILES = fpga.xdc
XDC_FILES += lib/eth/syn/vivado/eth_mac_fifo.tcl
XDC_FILES += lib/eth/lib/axis/syn/vivado/axis_async_fifo.tcl
XDC_FILES += lib/eth/lib/axis/syn/vivado/sync_reset.tcl
# IP
IP_TCL_FILES += ip/eth_xcvr_gt.tcl
# Configuration
CONFIG_TCL_FILES = ./config.tcl
include ../common/vivado.mk
program: $(FPGA_TOP).bit
echo "open_hw" > program.tcl
echo "connect_hw_server" >> program.tcl
echo "open_hw_target" >> program.tcl
echo "current_hw_device [lindex [get_hw_devices] 0]" >> program.tcl
echo "refresh_hw_device -update_hw_probes false [current_hw_device]" >> program.tcl
echo "set_property PROGRAM.FILE {$(FPGA_TOP).bit} [current_hw_device]" >> program.tcl
echo "program_hw_devices [current_hw_device]" >> program.tcl
echo "exit" >> program.tcl
vivado -nojournal -nolog -mode batch -source program.tcl
%_primary.mcs %_secondary.mcs %_primary.prm %_secondary.prm: %.bit
echo "write_cfgmem -force -format mcs -size 128 -interface SPIx8 -loadbit {up 0x0000000 $*.bit} -checksum -file $*.mcs" > generate_mcs.tcl
echo "exit" >> generate_mcs.tcl
vivado -nojournal -nolog -mode batch -source generate_mcs.tcl
mkdir -p rev
COUNT=100; \
while [ -e rev/$*_rev$$COUNT.bit ]; \
do COUNT=$$((COUNT+1)); done; \
COUNT=$$((COUNT-1)); \
for x in _primary.mcs _secondary.mcs _primary.prm _secondary.prm; \
do cp $*$$x rev/$*_rev$$COUNT$$x; \
echo "Output: rev/$*_rev$$COUNT$$x"; done;
flash: $(FPGA_TOP)_primary.mcs $(FPGA_TOP)_secondary.mcs $(FPGA_TOP)_primary.prm $(FPGA_TOP)_secondary.prm
echo "open_hw" > flash.tcl
echo "connect_hw_server" >> flash.tcl
echo "open_hw_target" >> flash.tcl
echo "current_hw_device [lindex [get_hw_devices] 0]" >> flash.tcl
echo "refresh_hw_device -update_hw_probes false [current_hw_device]" >> flash.tcl
echo "create_hw_cfgmem -hw_device [current_hw_device] [lindex [get_cfgmem_parts {s25fl512s-spi-x1_x2_x4_x8}] 0]" >> flash.tcl
echo "current_hw_cfgmem -hw_device [current_hw_device] [get_property PROGRAM.HW_CFGMEM [current_hw_device]]" >> flash.tcl
echo "set_property PROGRAM.FILES [list \"$(FPGA_TOP)_primary.mcs\" \"$(FPGA_TOP)_secondary.mcs\"] [current_hw_cfgmem]" >> flash.tcl
echo "set_property PROGRAM.PRM_FILES [list \"$(FPGA_TOP)_primary.prm\" \"$(FPGA_TOP)_secondary.prm\"] [current_hw_cfgmem]" >> flash.tcl
echo "set_property PROGRAM.ERASE 1 [current_hw_cfgmem]" >> flash.tcl
echo "set_property PROGRAM.CFG_PROGRAM 1 [current_hw_cfgmem]" >> flash.tcl
echo "set_property PROGRAM.VERIFY 1 [current_hw_cfgmem]" >> flash.tcl
echo "set_property PROGRAM.CHECKSUM 0 [current_hw_cfgmem]" >> flash.tcl
echo "set_property PROGRAM.ADDRESS_RANGE {use_file} [current_hw_cfgmem]" >> flash.tcl
echo "set_property PROGRAM.UNUSED_PIN_TERMINATION {pull-none} [current_hw_cfgmem]" >> flash.tcl
echo "create_hw_bitstream -hw_device [current_hw_device] [get_property PROGRAM.HW_CFGMEM_BITFILE [current_hw_device]]" >> flash.tcl
echo "program_hw_devices [current_hw_device]" >> flash.tcl
echo "refresh_hw_device [current_hw_device]" >> flash.tcl
echo "program_hw_cfgmem -hw_cfgmem [current_hw_cfgmem]" >> flash.tcl
echo "boot_hw_device [current_hw_device]" >> flash.tcl
echo "exit" >> flash.tcl
vivado -nojournal -nolog -mode batch -source flash.tcl

View File

@ -8,13 +8,46 @@ The design by default listens to UDP port 1234 at IP address 192.168.1.128 and w
The design is configured to run all 15 QSFP28 modules synchronous to the GTY reference oscillator (U47) on the HTG-9200. This is done by forwarding the MGT reference clock for QSFP1 through the FPGA to the SYNC_C2M pins on the FMC+, which is connected as a reference input to the Si5341 PLL (U7) on the FMC+.
* FPGA: xcvu9p-flgb2104-2-e
* FPGA: xcvu9p-flgb2104-2-e or xcvu13p-fhgb2104-2-e
* PHY: 10G BASE-R PHY IP core and internal GTY transceiver
* FMC+: HTG-FMC-X6QSFP28
## How to build
Run make to build. Ensure that the Xilinx Vivado toolchain components are in PATH.
## Board configuration
For correct operation, several DIP switches need to be set correctly. Additionally, some other component-level modifications may be required.
DIP switch settings:
* S2.1: off (enable EMCCLK, if needed to boot from flash)
* S3.2: off (enable U24 ref_clk)
* S4.5: off (enable U47 osc_gty2)
* S4.8: on (enable U48 outputs)
Note that S4.8 has no effect if R441 is not installed (which appears to be the default configuration) as U48 has an internal pull-down on OEb. The PLL configuration in this design also ignores the IN_SEL pins, so S4.6 and S4.7 have no effect. The other DIP switches do not affect the operation of this design.
When using optical modules or active optical cables, it is necessary to pull the lpmode pins low to enable the lasers. On the HTG-9200, the lpmode pins are not connected to the FPGA, so it is necessary to pull the pins low on the board. The board has footprints for pull-down resistors on the lpmode pins, which are not populated by default. These are R414, R392, R336, R316, R276, R475, R471, R473, and R477 (respectively for QSFP0-9). Shorting across these footprints or installing pull-down resistors of around 150 ohms will bring installed modules out of low power mode.
The HTG-9200 was originally designed for Virtex UltraScale, so by default some of the power supply voltages are too high for an UltraScale+ device. In particular, the Avcc supplies for the GTY transceivers are set to 1.0 V, which is not only outside of the recommended range of 0.873-0.927 V but it also matches the absolute max of 1.0 V. Additionally, Vccint and Vccbram are set to 0.95V, which is outside of the recommended range of 0.825-0.876 V for standard speed grades but below the absolute max of 1.0 V. Checking the supply voltages and swapping out the feedback resistors on the Vccint, Vccbram and MGT Avcc power supplies is therefore highly recommended. Note that the supplies labeled GTH feed the MGT banks on the right side of the device, which are GTH transceivers on UltraScale and GTY transceivers on UltraScale+.
The table below contains the power rail test points and feedback resistor values for the power supply rails in question for several different speed grades of Virtex UltraScale and UltraScale+ devices.
| Rail | VCCINT | VCCBRAM | GTY_AVCC | GTH_AVCC |
| ----------- | ------------ | ------------ | ------------ | ------------ |
| Test point | P6 | P8 | P9 | P1 |
| Regulator | U4, U56 | U11 | U13 | U20 |
| Part | 4/2 LTM4650 | LTM4625 | 4/4 LTM4644 | 4/4 LTM4644 |
| Current | 100A | 5A | 16A | 16A |
| FB resistor | R354 | R494 | R38 | R61 |
| US -3, -1H | 90.9K (1.0V) | 90.9K (1.0V) | 22.6K (1.0V) | 22.6K (1.0V) |
| US -2, -1 | 105K (0.95V) | 105K (0.95V) | 22.6K (1.0V) | 22.6K (1.0V) |
| US+ -3 | 121K (0.90V) | 121K (0.90V) | 30.1K (0.9V) | 30.1K (0.9V) |
| US+ -2, -1 | 147K (0.85V) | 147K (0.85V) | 30.1K (0.9V) | 30.1K (0.9V) |
| US+ -2L | 301K (0.72V) | 147K (0.85V) | 30.1K (0.9V) | 30.1K (0.9V) |
## How to test
Run make program to program the HTG-9200 board with Vivado. Then run

View File

@ -1,5 +1,6 @@
# XDC constraints for the HiTech Global HTG-9200 board
# part: xcvu9p-flgb2104-2-e
# part: xcvu13p-fhgb2104-2-e
# General configuration
set_property CFGBVS GND [current_design]

View File

@ -0,0 +1,116 @@
# FPGA settings
FPGA_PART = xcvu13p-fhgb2104-2-e
FPGA_TOP = fpga
FPGA_ARCH = virtexuplus
# Files for synthesis
SYN_FILES = rtl/fpga.v
SYN_FILES += rtl/fpga_core.v
SYN_FILES += rtl/eth_xcvr_phy_wrapper.v
SYN_FILES += rtl/eth_xcvr_phy_quad_wrapper.v
SYN_FILES += rtl/debounce_switch.v
SYN_FILES += rtl/sync_signal.v
SYN_FILES += rtl/i2c_master.v
SYN_FILES += pll/si5341_i2c_init.v
SYN_FILES += lib/eth/rtl/eth_mac_10g_fifo.v
SYN_FILES += lib/eth/rtl/eth_mac_10g.v
SYN_FILES += lib/eth/rtl/axis_xgmii_rx_64.v
SYN_FILES += lib/eth/rtl/axis_xgmii_tx_64.v
SYN_FILES += lib/eth/rtl/eth_phy_10g.v
SYN_FILES += lib/eth/rtl/eth_phy_10g_rx.v
SYN_FILES += lib/eth/rtl/eth_phy_10g_rx_if.v
SYN_FILES += lib/eth/rtl/eth_phy_10g_rx_frame_sync.v
SYN_FILES += lib/eth/rtl/eth_phy_10g_rx_ber_mon.v
SYN_FILES += lib/eth/rtl/eth_phy_10g_rx_watchdog.v
SYN_FILES += lib/eth/rtl/eth_phy_10g_tx.v
SYN_FILES += lib/eth/rtl/eth_phy_10g_tx_if.v
SYN_FILES += lib/eth/rtl/xgmii_baser_dec_64.v
SYN_FILES += lib/eth/rtl/xgmii_baser_enc_64.v
SYN_FILES += lib/eth/rtl/lfsr.v
SYN_FILES += lib/eth/rtl/eth_axis_rx.v
SYN_FILES += lib/eth/rtl/eth_axis_tx.v
SYN_FILES += lib/eth/rtl/udp_complete_64.v
SYN_FILES += lib/eth/rtl/udp_checksum_gen_64.v
SYN_FILES += lib/eth/rtl/udp_64.v
SYN_FILES += lib/eth/rtl/udp_ip_rx_64.v
SYN_FILES += lib/eth/rtl/udp_ip_tx_64.v
SYN_FILES += lib/eth/rtl/ip_complete_64.v
SYN_FILES += lib/eth/rtl/ip_64.v
SYN_FILES += lib/eth/rtl/ip_eth_rx_64.v
SYN_FILES += lib/eth/rtl/ip_eth_tx_64.v
SYN_FILES += lib/eth/rtl/ip_arb_mux.v
SYN_FILES += lib/eth/rtl/arp.v
SYN_FILES += lib/eth/rtl/arp_cache.v
SYN_FILES += lib/eth/rtl/arp_eth_rx.v
SYN_FILES += lib/eth/rtl/arp_eth_tx.v
SYN_FILES += lib/eth/rtl/eth_arb_mux.v
SYN_FILES += lib/eth/lib/axis/rtl/arbiter.v
SYN_FILES += lib/eth/lib/axis/rtl/priority_encoder.v
SYN_FILES += lib/eth/lib/axis/rtl/axis_fifo.v
SYN_FILES += lib/eth/lib/axis/rtl/axis_async_fifo.v
SYN_FILES += lib/eth/lib/axis/rtl/axis_async_fifo_adapter.v
SYN_FILES += lib/eth/lib/axis/rtl/sync_reset.v
# XDC files
XDC_FILES = fpga.xdc
XDC_FILES += lib/eth/syn/vivado/eth_mac_fifo.tcl
XDC_FILES += lib/eth/lib/axis/syn/vivado/axis_async_fifo.tcl
XDC_FILES += lib/eth/lib/axis/syn/vivado/sync_reset.tcl
# IP
IP_TCL_FILES += ip/eth_xcvr_gt.tcl
# Configuration
CONFIG_TCL_FILES = ./config.tcl
include ../common/vivado.mk
program: $(FPGA_TOP).bit
echo "open_hw" > program.tcl
echo "connect_hw_server" >> program.tcl
echo "open_hw_target" >> program.tcl
echo "current_hw_device [lindex [get_hw_devices] 0]" >> program.tcl
echo "refresh_hw_device -update_hw_probes false [current_hw_device]" >> program.tcl
echo "set_property PROGRAM.FILE {$(FPGA_TOP).bit} [current_hw_device]" >> program.tcl
echo "program_hw_devices [current_hw_device]" >> program.tcl
echo "exit" >> program.tcl
vivado -nojournal -nolog -mode batch -source program.tcl
%_primary.mcs %_secondary.mcs %_primary.prm %_secondary.prm: %.bit
echo "write_cfgmem -force -format mcs -size 128 -interface SPIx8 -loadbit {up 0x0000000 $*.bit} -checksum -file $*.mcs" > generate_mcs.tcl
echo "exit" >> generate_mcs.tcl
vivado -nojournal -nolog -mode batch -source generate_mcs.tcl
mkdir -p rev
COUNT=100; \
while [ -e rev/$*_rev$$COUNT.bit ]; \
do COUNT=$$((COUNT+1)); done; \
COUNT=$$((COUNT-1)); \
for x in _primary.mcs _secondary.mcs _primary.prm _secondary.prm; \
do cp $*$$x rev/$*_rev$$COUNT$$x; \
echo "Output: rev/$*_rev$$COUNT$$x"; done;
flash: $(FPGA_TOP)_primary.mcs $(FPGA_TOP)_secondary.mcs $(FPGA_TOP)_primary.prm $(FPGA_TOP)_secondary.prm
echo "open_hw" > flash.tcl
echo "connect_hw_server" >> flash.tcl
echo "open_hw_target" >> flash.tcl
echo "current_hw_device [lindex [get_hw_devices] 0]" >> flash.tcl
echo "refresh_hw_device -update_hw_probes false [current_hw_device]" >> flash.tcl
echo "create_hw_cfgmem -hw_device [current_hw_device] [lindex [get_cfgmem_parts {s25fl512s-spi-x1_x2_x4_x8}] 0]" >> flash.tcl
echo "current_hw_cfgmem -hw_device [current_hw_device] [get_property PROGRAM.HW_CFGMEM [current_hw_device]]" >> flash.tcl
echo "set_property PROGRAM.FILES [list \"$(FPGA_TOP)_primary.mcs\" \"$(FPGA_TOP)_secondary.mcs\"] [current_hw_cfgmem]" >> flash.tcl
echo "set_property PROGRAM.PRM_FILES [list \"$(FPGA_TOP)_primary.prm\" \"$(FPGA_TOP)_secondary.prm\"] [current_hw_cfgmem]" >> flash.tcl
echo "set_property PROGRAM.ERASE 1 [current_hw_cfgmem]" >> flash.tcl
echo "set_property PROGRAM.CFG_PROGRAM 1 [current_hw_cfgmem]" >> flash.tcl
echo "set_property PROGRAM.VERIFY 1 [current_hw_cfgmem]" >> flash.tcl
echo "set_property PROGRAM.CHECKSUM 0 [current_hw_cfgmem]" >> flash.tcl
echo "set_property PROGRAM.ADDRESS_RANGE {use_file} [current_hw_cfgmem]" >> flash.tcl
echo "set_property PROGRAM.UNUSED_PIN_TERMINATION {pull-none} [current_hw_cfgmem]" >> flash.tcl
echo "create_hw_bitstream -hw_device [current_hw_device] [get_property PROGRAM.HW_CFGMEM_BITFILE [current_hw_device]]" >> flash.tcl
echo "program_hw_devices [current_hw_device]" >> flash.tcl
echo "refresh_hw_device [current_hw_device]" >> flash.tcl
echo "program_hw_cfgmem -hw_cfgmem [current_hw_cfgmem]" >> flash.tcl
echo "boot_hw_device [current_hw_device]" >> flash.tcl
echo "exit" >> flash.tcl
vivado -nojournal -nolog -mode batch -source flash.tcl

View File

@ -0,0 +1,50 @@
# Copyright (c) 2023 Alex Forencich
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
# Transceiver configuration
set eth_xcvr_freerun_freq {125}
set eth_xcvr_line_rate {10.3125}
set eth_xcvr_sec_line_rate {0}
set eth_xcvr_refclk_freq {161.1328125}
set eth_xcvr_qpll_fracn [expr {int(fmod($eth_xcvr_line_rate*1000/2 / $eth_xcvr_refclk_freq, 1)*pow(2, 24))}]
set eth_xcvr_sec_qpll_fracn [expr {int(fmod($eth_xcvr_sec_line_rate*1000/2 / $eth_xcvr_refclk_freq, 1)*pow(2, 24))}]
set eth_xcvr_rx_eq_mode {DFE}
set xcvr_config [dict create]
dict set xcvr_config CONFIG.TX_LINE_RATE $eth_xcvr_line_rate
dict set xcvr_config CONFIG.TX_QPLL_FRACN_NUMERATOR $eth_xcvr_qpll_fracn
dict set xcvr_config CONFIG.TX_REFCLK_FREQUENCY $eth_xcvr_refclk_freq
dict set xcvr_config CONFIG.RX_LINE_RATE $eth_xcvr_line_rate
dict set xcvr_config CONFIG.RX_QPLL_FRACN_NUMERATOR $eth_xcvr_qpll_fracn
dict set xcvr_config CONFIG.RX_REFCLK_FREQUENCY $eth_xcvr_refclk_freq
dict set xcvr_config CONFIG.RX_EQ_MODE $eth_xcvr_rx_eq_mode
if {$eth_xcvr_sec_line_rate != 0} {
dict set xcvr_config CONFIG.SECONDARY_QPLL_ENABLE true
dict set xcvr_config CONFIG.SECONDARY_QPLL_FRACN_NUMERATOR $eth_xcvr_sec_qpll_fracn
dict set xcvr_config CONFIG.SECONDARY_QPLL_LINE_RATE $eth_xcvr_sec_line_rate
dict set xcvr_config CONFIG.SECONDARY_QPLL_REFCLK_FREQUENCY $eth_xcvr_refclk_freq
} else {
dict set xcvr_config CONFIG.SECONDARY_QPLL_ENABLE false
}
dict set xcvr_config CONFIG.FREERUN_FREQUENCY $eth_xcvr_freerun_freq
set_property -dict $xcvr_config [get_ips eth_xcvr_gt_full]
set_property -dict $xcvr_config [get_ips eth_xcvr_gt_channel]

View File

@ -0,0 +1,50 @@
# Copyright (c) 2023 Alex Forencich
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
# Transceiver configuration
set eth_xcvr_freerun_freq {125}
set eth_xcvr_line_rate {10.3125}
set eth_xcvr_sec_line_rate {0}
set eth_xcvr_refclk_freq {161.1328125}
set eth_xcvr_qpll_fracn [expr {int(fmod($eth_xcvr_line_rate*1000/2 / $eth_xcvr_refclk_freq, 1)*pow(2, 24))}]
set eth_xcvr_sec_qpll_fracn [expr {int(fmod($eth_xcvr_sec_line_rate*1000/2 / $eth_xcvr_refclk_freq, 1)*pow(2, 24))}]
set eth_xcvr_rx_eq_mode {DFE}
set xcvr_config [dict create]
dict set xcvr_config CONFIG.TX_LINE_RATE $eth_xcvr_line_rate
dict set xcvr_config CONFIG.TX_QPLL_FRACN_NUMERATOR $eth_xcvr_qpll_fracn
dict set xcvr_config CONFIG.TX_REFCLK_FREQUENCY $eth_xcvr_refclk_freq
dict set xcvr_config CONFIG.RX_LINE_RATE $eth_xcvr_line_rate
dict set xcvr_config CONFIG.RX_QPLL_FRACN_NUMERATOR $eth_xcvr_qpll_fracn
dict set xcvr_config CONFIG.RX_REFCLK_FREQUENCY $eth_xcvr_refclk_freq
dict set xcvr_config CONFIG.RX_EQ_MODE $eth_xcvr_rx_eq_mode
if {$eth_xcvr_sec_line_rate != 0} {
dict set xcvr_config CONFIG.SECONDARY_QPLL_ENABLE true
dict set xcvr_config CONFIG.SECONDARY_QPLL_FRACN_NUMERATOR $eth_xcvr_sec_qpll_fracn
dict set xcvr_config CONFIG.SECONDARY_QPLL_LINE_RATE $eth_xcvr_sec_line_rate
dict set xcvr_config CONFIG.SECONDARY_QPLL_REFCLK_FREQUENCY $eth_xcvr_refclk_freq
} else {
dict set xcvr_config CONFIG.SECONDARY_QPLL_ENABLE false
}
dict set xcvr_config CONFIG.FREERUN_FREQUENCY $eth_xcvr_freerun_freq
set_property -dict $xcvr_config [get_ips eth_xcvr_gt_full]
set_property -dict $xcvr_config [get_ips eth_xcvr_gt_channel]

View File

@ -0,0 +1,116 @@
# FPGA settings
FPGA_PART = xcvu13p-fhgb2104-2-e
FPGA_TOP = fpga
FPGA_ARCH = virtexuplus
# Files for synthesis
SYN_FILES = rtl/fpga.v
SYN_FILES += rtl/fpga_core.v
SYN_FILES += rtl/eth_xcvr_phy_wrapper.v
SYN_FILES += rtl/eth_xcvr_phy_quad_wrapper.v
SYN_FILES += rtl/debounce_switch.v
SYN_FILES += rtl/sync_signal.v
SYN_FILES += rtl/i2c_master.v
SYN_FILES += pll/si5341_i2c_init.v
SYN_FILES += lib/eth/rtl/eth_mac_10g_fifo.v
SYN_FILES += lib/eth/rtl/eth_mac_10g.v
SYN_FILES += lib/eth/rtl/axis_xgmii_rx_64.v
SYN_FILES += lib/eth/rtl/axis_xgmii_tx_64.v
SYN_FILES += lib/eth/rtl/eth_phy_10g.v
SYN_FILES += lib/eth/rtl/eth_phy_10g_rx.v
SYN_FILES += lib/eth/rtl/eth_phy_10g_rx_if.v
SYN_FILES += lib/eth/rtl/eth_phy_10g_rx_frame_sync.v
SYN_FILES += lib/eth/rtl/eth_phy_10g_rx_ber_mon.v
SYN_FILES += lib/eth/rtl/eth_phy_10g_rx_watchdog.v
SYN_FILES += lib/eth/rtl/eth_phy_10g_tx.v
SYN_FILES += lib/eth/rtl/eth_phy_10g_tx_if.v
SYN_FILES += lib/eth/rtl/xgmii_baser_dec_64.v
SYN_FILES += lib/eth/rtl/xgmii_baser_enc_64.v
SYN_FILES += lib/eth/rtl/lfsr.v
SYN_FILES += lib/eth/rtl/eth_axis_rx.v
SYN_FILES += lib/eth/rtl/eth_axis_tx.v
SYN_FILES += lib/eth/rtl/udp_complete_64.v
SYN_FILES += lib/eth/rtl/udp_checksum_gen_64.v
SYN_FILES += lib/eth/rtl/udp_64.v
SYN_FILES += lib/eth/rtl/udp_ip_rx_64.v
SYN_FILES += lib/eth/rtl/udp_ip_tx_64.v
SYN_FILES += lib/eth/rtl/ip_complete_64.v
SYN_FILES += lib/eth/rtl/ip_64.v
SYN_FILES += lib/eth/rtl/ip_eth_rx_64.v
SYN_FILES += lib/eth/rtl/ip_eth_tx_64.v
SYN_FILES += lib/eth/rtl/ip_arb_mux.v
SYN_FILES += lib/eth/rtl/arp.v
SYN_FILES += lib/eth/rtl/arp_cache.v
SYN_FILES += lib/eth/rtl/arp_eth_rx.v
SYN_FILES += lib/eth/rtl/arp_eth_tx.v
SYN_FILES += lib/eth/rtl/eth_arb_mux.v
SYN_FILES += lib/eth/lib/axis/rtl/arbiter.v
SYN_FILES += lib/eth/lib/axis/rtl/priority_encoder.v
SYN_FILES += lib/eth/lib/axis/rtl/axis_fifo.v
SYN_FILES += lib/eth/lib/axis/rtl/axis_async_fifo.v
SYN_FILES += lib/eth/lib/axis/rtl/axis_async_fifo_adapter.v
SYN_FILES += lib/eth/lib/axis/rtl/sync_reset.v
# XDC files
XDC_FILES = fpga.xdc
XDC_FILES += lib/eth/syn/vivado/eth_mac_fifo.tcl
XDC_FILES += lib/eth/lib/axis/syn/vivado/axis_async_fifo.tcl
XDC_FILES += lib/eth/lib/axis/syn/vivado/sync_reset.tcl
# IP
IP_TCL_FILES += ip/eth_xcvr_gt.tcl
# Configuration
CONFIG_TCL_FILES = ./config.tcl
include ../common/vivado.mk
program: $(FPGA_TOP).bit
echo "open_hw" > program.tcl
echo "connect_hw_server" >> program.tcl
echo "open_hw_target" >> program.tcl
echo "current_hw_device [lindex [get_hw_devices] 0]" >> program.tcl
echo "refresh_hw_device -update_hw_probes false [current_hw_device]" >> program.tcl
echo "set_property PROGRAM.FILE {$(FPGA_TOP).bit} [current_hw_device]" >> program.tcl
echo "program_hw_devices [current_hw_device]" >> program.tcl
echo "exit" >> program.tcl
vivado -nojournal -nolog -mode batch -source program.tcl
%_primary.mcs %_secondary.mcs %_primary.prm %_secondary.prm: %.bit
echo "write_cfgmem -force -format mcs -size 128 -interface SPIx8 -loadbit {up 0x0000000 $*.bit} -checksum -file $*.mcs" > generate_mcs.tcl
echo "exit" >> generate_mcs.tcl
vivado -nojournal -nolog -mode batch -source generate_mcs.tcl
mkdir -p rev
COUNT=100; \
while [ -e rev/$*_rev$$COUNT.bit ]; \
do COUNT=$$((COUNT+1)); done; \
COUNT=$$((COUNT-1)); \
for x in _primary.mcs _secondary.mcs _primary.prm _secondary.prm; \
do cp $*$$x rev/$*_rev$$COUNT$$x; \
echo "Output: rev/$*_rev$$COUNT$$x"; done;
flash: $(FPGA_TOP)_primary.mcs $(FPGA_TOP)_secondary.mcs $(FPGA_TOP)_primary.prm $(FPGA_TOP)_secondary.prm
echo "open_hw" > flash.tcl
echo "connect_hw_server" >> flash.tcl
echo "open_hw_target" >> flash.tcl
echo "current_hw_device [lindex [get_hw_devices] 0]" >> flash.tcl
echo "refresh_hw_device -update_hw_probes false [current_hw_device]" >> flash.tcl
echo "create_hw_cfgmem -hw_device [current_hw_device] [lindex [get_cfgmem_parts {s25fl512s-spi-x1_x2_x4_x8}] 0]" >> flash.tcl
echo "current_hw_cfgmem -hw_device [current_hw_device] [get_property PROGRAM.HW_CFGMEM [current_hw_device]]" >> flash.tcl
echo "set_property PROGRAM.FILES [list \"$(FPGA_TOP)_primary.mcs\" \"$(FPGA_TOP)_secondary.mcs\"] [current_hw_cfgmem]" >> flash.tcl
echo "set_property PROGRAM.PRM_FILES [list \"$(FPGA_TOP)_primary.prm\" \"$(FPGA_TOP)_secondary.prm\"] [current_hw_cfgmem]" >> flash.tcl
echo "set_property PROGRAM.ERASE 1 [current_hw_cfgmem]" >> flash.tcl
echo "set_property PROGRAM.CFG_PROGRAM 1 [current_hw_cfgmem]" >> flash.tcl
echo "set_property PROGRAM.VERIFY 1 [current_hw_cfgmem]" >> flash.tcl
echo "set_property PROGRAM.CHECKSUM 0 [current_hw_cfgmem]" >> flash.tcl
echo "set_property PROGRAM.ADDRESS_RANGE {use_file} [current_hw_cfgmem]" >> flash.tcl
echo "set_property PROGRAM.UNUSED_PIN_TERMINATION {pull-none} [current_hw_cfgmem]" >> flash.tcl
echo "create_hw_bitstream -hw_device [current_hw_device] [get_property PROGRAM.HW_CFGMEM_BITFILE [current_hw_device]]" >> flash.tcl
echo "program_hw_devices [current_hw_device]" >> flash.tcl
echo "refresh_hw_device [current_hw_device]" >> flash.tcl
echo "program_hw_cfgmem -hw_cfgmem [current_hw_cfgmem]" >> flash.tcl
echo "boot_hw_device [current_hw_device]" >> flash.tcl
echo "exit" >> flash.tcl
vivado -nojournal -nolog -mode batch -source flash.tcl

View File

@ -0,0 +1,50 @@
# Copyright (c) 2023 Alex Forencich
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
# Transceiver configuration
set eth_xcvr_freerun_freq {125}
set eth_xcvr_line_rate {25.78125}
set eth_xcvr_sec_line_rate {0}
set eth_xcvr_refclk_freq {161.1328125}
set eth_xcvr_qpll_fracn [expr {int(fmod($eth_xcvr_line_rate*1000/2 / $eth_xcvr_refclk_freq, 1)*pow(2, 24))}]
set eth_xcvr_sec_qpll_fracn [expr {int(fmod($eth_xcvr_sec_line_rate*1000/2 / $eth_xcvr_refclk_freq, 1)*pow(2, 24))}]
set eth_xcvr_rx_eq_mode {DFE}
set xcvr_config [dict create]
dict set xcvr_config CONFIG.TX_LINE_RATE $eth_xcvr_line_rate
dict set xcvr_config CONFIG.TX_QPLL_FRACN_NUMERATOR $eth_xcvr_qpll_fracn
dict set xcvr_config CONFIG.TX_REFCLK_FREQUENCY $eth_xcvr_refclk_freq
dict set xcvr_config CONFIG.RX_LINE_RATE $eth_xcvr_line_rate
dict set xcvr_config CONFIG.RX_QPLL_FRACN_NUMERATOR $eth_xcvr_qpll_fracn
dict set xcvr_config CONFIG.RX_REFCLK_FREQUENCY $eth_xcvr_refclk_freq
dict set xcvr_config CONFIG.RX_EQ_MODE $eth_xcvr_rx_eq_mode
if {$eth_xcvr_sec_line_rate != 0} {
dict set xcvr_config CONFIG.SECONDARY_QPLL_ENABLE true
dict set xcvr_config CONFIG.SECONDARY_QPLL_FRACN_NUMERATOR $eth_xcvr_sec_qpll_fracn
dict set xcvr_config CONFIG.SECONDARY_QPLL_LINE_RATE $eth_xcvr_sec_line_rate
dict set xcvr_config CONFIG.SECONDARY_QPLL_REFCLK_FREQUENCY $eth_xcvr_refclk_freq
} else {
dict set xcvr_config CONFIG.SECONDARY_QPLL_ENABLE false
}
dict set xcvr_config CONFIG.FREERUN_FREQUENCY $eth_xcvr_freerun_freq
set_property -dict $xcvr_config [get_ips eth_xcvr_gt_full]
set_property -dict $xcvr_config [get_ips eth_xcvr_gt_channel]

View File

@ -0,0 +1,50 @@
# Copyright (c) 2023 Alex Forencich
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
# Transceiver configuration
set eth_xcvr_freerun_freq {125}
set eth_xcvr_line_rate {25.78125}
set eth_xcvr_sec_line_rate {0}
set eth_xcvr_refclk_freq {161.1328125}
set eth_xcvr_qpll_fracn [expr {int(fmod($eth_xcvr_line_rate*1000/2 / $eth_xcvr_refclk_freq, 1)*pow(2, 24))}]
set eth_xcvr_sec_qpll_fracn [expr {int(fmod($eth_xcvr_sec_line_rate*1000/2 / $eth_xcvr_refclk_freq, 1)*pow(2, 24))}]
set eth_xcvr_rx_eq_mode {DFE}
set xcvr_config [dict create]
dict set xcvr_config CONFIG.TX_LINE_RATE $eth_xcvr_line_rate
dict set xcvr_config CONFIG.TX_QPLL_FRACN_NUMERATOR $eth_xcvr_qpll_fracn
dict set xcvr_config CONFIG.TX_REFCLK_FREQUENCY $eth_xcvr_refclk_freq
dict set xcvr_config CONFIG.RX_LINE_RATE $eth_xcvr_line_rate
dict set xcvr_config CONFIG.RX_QPLL_FRACN_NUMERATOR $eth_xcvr_qpll_fracn
dict set xcvr_config CONFIG.RX_REFCLK_FREQUENCY $eth_xcvr_refclk_freq
dict set xcvr_config CONFIG.RX_EQ_MODE $eth_xcvr_rx_eq_mode
if {$eth_xcvr_sec_line_rate != 0} {
dict set xcvr_config CONFIG.SECONDARY_QPLL_ENABLE true
dict set xcvr_config CONFIG.SECONDARY_QPLL_FRACN_NUMERATOR $eth_xcvr_sec_qpll_fracn
dict set xcvr_config CONFIG.SECONDARY_QPLL_LINE_RATE $eth_xcvr_sec_line_rate
dict set xcvr_config CONFIG.SECONDARY_QPLL_REFCLK_FREQUENCY $eth_xcvr_refclk_freq
} else {
dict set xcvr_config CONFIG.SECONDARY_QPLL_ENABLE false
}
dict set xcvr_config CONFIG.FREERUN_FREQUENCY $eth_xcvr_freerun_freq
set_property -dict $xcvr_config [get_ips eth_xcvr_gt_full]
set_property -dict $xcvr_config [get_ips eth_xcvr_gt_channel]

View File

@ -1,25 +0,0 @@
# Targets
TARGETS:=
# Subdirectories
SUBDIRS = fpga
SUBDIRS_CLEAN = $(patsubst %,%.clean,$(SUBDIRS))
# Rules
.PHONY: all
all: $(SUBDIRS) $(TARGETS)
.PHONY: $(SUBDIRS)
$(SUBDIRS):
cd $@ && $(MAKE)
.PHONY: $(SUBDIRS_CLEAN)
$(SUBDIRS_CLEAN):
cd $(@:.clean=) && $(MAKE) clean
.PHONY: clean
clean: $(SUBDIRS_CLEAN)
-rm -rf $(TARGETS)
program:
#djtgcfg prog -d Atlys --index 0 --file fpga/fpga.bit

View File

@ -1,30 +0,0 @@
# Verilog Ethernet VCU1525 Example Design
## Introduction
This example design targets the Xilinx VCU1525 FPGA board.
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-fsgd2104-2L-e
* PHY: 10G BASE-R PHY IP core and internal GTY transceiver
## How to build
Run make to build. Ensure that the Xilinx Vivado toolchain components are
in PATH.
## How to test
Run make program to program the VCU1525 board with Vivado. Then run
netcat -u 192.168.1.128 1234
to open a UDP connection to port 1234. Any text entered into netcat will be
echoed back after pressing enter.
It is also possible to use hping to test the design by running
hping 192.168.1.128 -2 -p 1234 -d 1024

View File

@ -1,137 +0,0 @@
###################################################################
#
# 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

@ -1,833 +0,0 @@
# XDC constraints for the Xilinx VCU1525 board
# part: xcvu9p-fsgd2104-2L-e
# General configuration
set_property CFGBVS GND [current_design]
set_property CONFIG_VOLTAGE 1.8 [current_design]
set_property BITSTREAM.GENERAL.COMPRESS true [current_design]
set_property BITSTREAM.CONFIG.CONFIGFALLBACK ENABLE [current_design]
set_property BITSTREAM.CONFIG.EXTMASTERCCLK_EN DISABLE [current_design]
set_property BITSTREAM.CONFIG.CONFIGRATE 85.0 [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.UNUSEDPIN PULLUP [current_design]
set_property BITSTREAM.CONFIG.OVERTEMPSHUTDOWN Enable [current_design]
# System clocks
# 300 MHz (DDR 0)
#set_property -dict {LOC AY37 IOSTANDARD LVDS} [get_ports clk_300mhz_0_p]
#set_property -dict {LOC AY38 IOSTANDARD LVDS} [get_ports clk_300mhz_0_n]
#create_clock -period 3.333 -name clk_300mhz_0 [get_ports clk_300mhz_0_p]
# 300 MHz (DDR 1)
#set_property -dict {LOC AW20 IOSTANDARD LVDS} [get_ports clk_300mhz_1_p]
#set_property -dict {LOC AW19 IOSTANDARD LVDS} [get_ports clk_300mhz_1_n]
#create_clock -period 3.333 -name clk_300mhz_1 [get_ports clk_300mhz_1_p]
# 300 MHz (DDR 2)
#set_property -dict {LOC F32 IOSTANDARD LVDS} [get_ports clk_300mhz_2_p]
#set_property -dict {LOC E32 IOSTANDARD LVDS} [get_ports clk_300mhz_2_n]
#create_clock -period 3.333 -name clk_300mhz_2 [get_ports clk_300mhz_2_p]
# 300 MHz (DDR 3)
#set_property -dict {LOC J16 IOSTANDARD LVDS} [get_ports clk_300mhz_3_p]
#set_property -dict {LOC H16 IOSTANDARD LVDS} [get_ports clk_300mhz_3_n]
#create_clock -period 3.333 -name clk_300mhz_3 [get_ports clk_300mhz_3_p]
# SI570 user clock
#set_property -dict {LOC AU19 IOSTANDARD LVDS} [get_ports clk_user_p]
#set_property -dict {LOC AV19 IOSTANDARD LVDS} [get_ports clk_user_n]
#create_clock -period 6.400 -name clk_user [get_ports clk_user_p]
# LEDs
set_property -dict {LOC BC21 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {led[0]}]
set_property -dict {LOC BB21 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {led[1]}]
set_property -dict {LOC BA20 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {led[2]}]
set_false_path -to [get_ports {led[*]}]
set_output_delay 0 [get_ports {led[*]}]
# Reset button
set_property -dict {LOC AL20 IOSTANDARD LVCMOS12} [get_ports reset]
set_false_path -from [get_ports {reset}]
set_input_delay 0 [get_ports {reset}]
# DIP switches
set_property -dict {LOC AN22 IOSTANDARD LVCMOS12} [get_ports {sw[0]}]
set_property -dict {LOC AM19 IOSTANDARD LVCMOS12} [get_ports {sw[1]}]
set_property -dict {LOC AL19 IOSTANDARD LVCMOS12} [get_ports {sw[2]}]
set_property -dict {LOC AP20 IOSTANDARD LVCMOS12} [get_ports {sw[3]}]
set_false_path -from [get_ports {sw[*]}]
set_input_delay 0 [get_ports {sw[*]}]
# UART
set_property -dict {LOC BF18 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports uart_txd]
set_property -dict {LOC BB20 IOSTANDARD LVCMOS12} [get_ports uart_rxd]
#set_false_path -to [get_ports {uart_txd}]
#set_output_delay 0 [get_ports {uart_txd}]
#set_false_path -from [get_ports {uart_rxd}]
#set_input_delay 0 [get_ports {uart_rxd}]
# QSFP28 Interfaces
set_property -dict {LOC N4 } [get_ports {qsfp0_rx_p[0]}] ;# MGTYRXP0_231 GTYE4_CHANNEL_X1Y48 / GTYE4_COMMON_X1Y12
set_property -dict {LOC N3 } [get_ports {qsfp0_rx_n[0]}] ;# MGTYRXN0_231 GTYE4_CHANNEL_X1Y48 / GTYE4_COMMON_X1Y12
set_property -dict {LOC N9 } [get_ports {qsfp0_tx_p[0]}] ;# MGTYTXP0_231 GTYE4_CHANNEL_X1Y48 / GTYE4_COMMON_X1Y12
set_property -dict {LOC N8 } [get_ports {qsfp0_tx_n[0]}] ;# MGTYTXN0_231 GTYE4_CHANNEL_X1Y48 / GTYE4_COMMON_X1Y12
set_property -dict {LOC M2 } [get_ports {qsfp0_rx_p[1]}] ;# MGTYRXP1_231 GTYE4_CHANNEL_X1Y49 / GTYE4_COMMON_X1Y12
set_property -dict {LOC M1 } [get_ports {qsfp0_rx_n[1]}] ;# MGTYRXN1_231 GTYE4_CHANNEL_X1Y49 / GTYE4_COMMON_X1Y12
set_property -dict {LOC M7 } [get_ports {qsfp0_tx_p[1]}] ;# MGTYTXP1_231 GTYE4_CHANNEL_X1Y49 / GTYE4_COMMON_X1Y12
set_property -dict {LOC M6 } [get_ports {qsfp0_tx_n[1]}] ;# MGTYTXN1_231 GTYE4_CHANNEL_X1Y49 / GTYE4_COMMON_X1Y12
set_property -dict {LOC L4 } [get_ports {qsfp0_rx_p[2]}] ;# MGTYRXP2_231 GTYE4_CHANNEL_X1Y50 / GTYE4_COMMON_X1Y12
set_property -dict {LOC L3 } [get_ports {qsfp0_rx_n[2]}] ;# MGTYRXN2_231 GTYE4_CHANNEL_X1Y50 / GTYE4_COMMON_X1Y12
set_property -dict {LOC L9 } [get_ports {qsfp0_tx_p[2]}] ;# MGTYTXP2_231 GTYE4_CHANNEL_X1Y50 / GTYE4_COMMON_X1Y12
set_property -dict {LOC L8 } [get_ports {qsfp0_tx_n[2]}] ;# MGTYTXN2_231 GTYE4_CHANNEL_X1Y50 / GTYE4_COMMON_X1Y12
set_property -dict {LOC K2 } [get_ports {qsfp0_rx_p[3]}] ;# MGTYRXP3_231 GTYE4_CHANNEL_X1Y51 / GTYE4_COMMON_X1Y12
set_property -dict {LOC K1 } [get_ports {qsfp0_rx_n[3]}] ;# MGTYRXN3_231 GTYE4_CHANNEL_X1Y51 / GTYE4_COMMON_X1Y12
set_property -dict {LOC K7 } [get_ports {qsfp0_tx_p[3]}] ;# MGTYTXP3_231 GTYE4_CHANNEL_X1Y51 / GTYE4_COMMON_X1Y12
set_property -dict {LOC K6 } [get_ports {qsfp0_tx_n[3]}] ;# MGTYTXN3_231 GTYE4_CHANNEL_X1Y51 / GTYE4_COMMON_X1Y12
#set_property -dict {LOC M11 } [get_ports qsfp0_mgt_refclk_0_p] ;# MGTREFCLK0P_231 from U14.4 via U43.13
#set_property -dict {LOC M10 } [get_ports qsfp0_mgt_refclk_0_n] ;# MGTREFCLK0N_231 from U14.5 via U43.14
set_property -dict {LOC K11 } [get_ports qsfp0_mgt_refclk_1_p] ;# MGTREFCLK1P_231 from U9.18
set_property -dict {LOC K10 } [get_ports qsfp0_mgt_refclk_1_n] ;# MGTREFCLK1N_231 from U9.17
set_property -dict {LOC BE16 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports qsfp0_modsell]
set_property -dict {LOC BE17 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports qsfp0_resetl]
set_property -dict {LOC BE20 IOSTANDARD LVCMOS12 PULLUP true} [get_ports qsfp0_modprsl]
set_property -dict {LOC BE21 IOSTANDARD LVCMOS12 PULLUP true} [get_ports qsfp0_intl]
set_property -dict {LOC BD18 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports qsfp0_lpmode]
set_property -dict {LOC AT22 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports qsfp0_refclk_reset]
set_property -dict {LOC AT20 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {qsfp0_fs[0]}]
set_property -dict {LOC AU22 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {qsfp0_fs[1]}]
# 156.25 MHz MGT reference clock (from SI570)
#create_clock -period 6.400 -name qsfp0_mgt_refclk_0 [get_ports qsfp0_mgt_refclk_0_p]
# 156.25 MHz MGT reference clock (from SI5335, FS = 0b01)
#create_clock -period 6.400 -name qsfp0_mgt_refclk_1 [get_ports qsfp0_mgt_refclk_1_p]
# 161.1328125 MHz MGT reference clock (from SI5335, FS = 0b10)
create_clock -period 6.206 -name qsfp0_mgt_refclk_1 [get_ports qsfp0_mgt_refclk_1_p]
set_false_path -to [get_ports {qsfp0_modsell qsfp0_resetl qsfp0_lpmode qsfp0_refclk_reset qsfp0_fs[*]}]
set_output_delay 0 [get_ports {qsfp0_modsell qsfp0_resetl qsfp0_lpmode qsfp0_refclk_reset qsfp0_fs[*]}]
set_false_path -from [get_ports {qsfp0_modprsl qsfp0_intl}]
set_input_delay 0 [get_ports {qsfp0_modprsl qsfp0_intl}]
set_property -dict {LOC U4 } [get_ports {qsfp1_rx_p[0]}] ;# MGTYRXP0_230 GTYE4_CHANNEL_X1Y44 / GTYE4_COMMON_X1Y11
set_property -dict {LOC U3 } [get_ports {qsfp1_rx_n[0]}] ;# MGTYRXN0_230 GTYE4_CHANNEL_X1Y44 / GTYE4_COMMON_X1Y11
set_property -dict {LOC U9 } [get_ports {qsfp1_tx_p[0]}] ;# MGTYTXP0_230 GTYE4_CHANNEL_X1Y44 / GTYE4_COMMON_X1Y11
set_property -dict {LOC U8 } [get_ports {qsfp1_tx_n[0]}] ;# MGTYTXN0_230 GTYE4_CHANNEL_X1Y44 / GTYE4_COMMON_X1Y11
set_property -dict {LOC T2 } [get_ports {qsfp1_rx_p[1]}] ;# MGTYRXP1_230 GTYE4_CHANNEL_X1Y45 / GTYE4_COMMON_X1Y11
set_property -dict {LOC T1 } [get_ports {qsfp1_rx_n[1]}] ;# MGTYRXN1_230 GTYE4_CHANNEL_X1Y45 / GTYE4_COMMON_X1Y11
set_property -dict {LOC T7 } [get_ports {qsfp1_tx_p[1]}] ;# MGTYTXP1_230 GTYE4_CHANNEL_X1Y45 / GTYE4_COMMON_X1Y11
set_property -dict {LOC T6 } [get_ports {qsfp1_tx_n[1]}] ;# MGTYTXN1_230 GTYE4_CHANNEL_X1Y45 / GTYE4_COMMON_X1Y11
set_property -dict {LOC R4 } [get_ports {qsfp1_rx_p[2]}] ;# MGTYRXP2_230 GTYE4_CHANNEL_X1Y46 / GTYE4_COMMON_X1Y11
set_property -dict {LOC R3 } [get_ports {qsfp1_rx_n[2]}] ;# MGTYRXN2_230 GTYE4_CHANNEL_X1Y46 / GTYE4_COMMON_X1Y11
set_property -dict {LOC R9 } [get_ports {qsfp1_tx_p[2]}] ;# MGTYTXP2_230 GTYE4_CHANNEL_X1Y46 / GTYE4_COMMON_X1Y11
set_property -dict {LOC R8 } [get_ports {qsfp1_tx_n[2]}] ;# MGTYTXN2_230 GTYE4_CHANNEL_X1Y46 / GTYE4_COMMON_X1Y11
set_property -dict {LOC P2 } [get_ports {qsfp1_rx_p[3]}] ;# MGTYRXP3_230 GTYE4_CHANNEL_X1Y47 / GTYE4_COMMON_X1Y11
set_property -dict {LOC P1 } [get_ports {qsfp1_rx_n[3]}] ;# MGTYRXN3_230 GTYE4_CHANNEL_X1Y47 / GTYE4_COMMON_X1Y11
set_property -dict {LOC P7 } [get_ports {qsfp1_tx_p[3]}] ;# MGTYTXP3_230 GTYE4_CHANNEL_X1Y47 / GTYE4_COMMON_X1Y11
set_property -dict {LOC P6 } [get_ports {qsfp1_tx_n[3]}] ;# MGTYTXN3_230 GTYE4_CHANNEL_X1Y47 / GTYE4_COMMON_X1Y11
#set_property -dict {LOC T11 } [get_ports qsfp1_mgt_refclk_0_p] ;# MGTREFCLK0P_230 from U14.4 via U43.15
#set_property -dict {LOC T10 } [get_ports qsfp1_mgt_refclk_0_n] ;# MGTREFCLK0N_230 from U14.5 via U43.16
set_property -dict {LOC P11 } [get_ports qsfp1_mgt_refclk_1_p] ;# MGTREFCLK1P_230 from U12.18
set_property -dict {LOC P10 } [get_ports qsfp1_mgt_refclk_1_n] ;# MGTREFCLK1N_230 from U12.17
set_property -dict {LOC AY20 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports qsfp1_modsell]
set_property -dict {LOC BC18 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports qsfp1_resetl]
set_property -dict {LOC BC19 IOSTANDARD LVCMOS12 PULLUP true} [get_ports qsfp1_modprsl]
set_property -dict {LOC AV21 IOSTANDARD LVCMOS12 PULLUP true} [get_ports qsfp1_intl]
set_property -dict {LOC AV22 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports qsfp1_lpmode]
set_property -dict {LOC AR21 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports qsfp1_refclk_reset]
set_property -dict {LOC AR22 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {qsfp1_fs[0]}]
set_property -dict {LOC AU20 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {qsfp1_fs[1]}]
# 156.25 MHz MGT reference clock (from SI570)
#create_clock -period 6.400 -name qsfp1_mgt_refclk_0 [get_ports qsfp1_mgt_refclk_0_p]
# 156.25 MHz MGT reference clock (from SI5335, FS = 0b01)
#create_clock -period 6.400 -name qsfp1_mgt_refclk_1 [get_ports qsfp1_mgt_refclk_1_p]
# 161.1328125 MHz MGT reference clock (from SI5335, FS = 0b10)
create_clock -period 6.206 -name qsfp1_mgt_refclk_1 [get_ports qsfp1_mgt_refclk_1_p]
set_false_path -to [get_ports {qsfp1_modsell qsfp1_resetl qsfp1_lpmode qsfp1_refclk_reset qsfp1_fs[*]}]
set_output_delay 0 [get_ports {qsfp1_modsell qsfp1_resetl qsfp1_lpmode qsfp1_refclk_reset qsfp1_fs[*]}]
set_false_path -from [get_ports {qsfp1_modprsl qsfp1_intl}]
set_input_delay 0 [get_ports {qsfp1_modprsl qsfp1_intl}]
# I2C interface
#set_property -dict {LOC BF19 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports i2c_mux_reset]
set_property -dict {LOC BF20 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports i2c_scl]
set_property -dict {LOC BF17 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports i2c_sda]
set_false_path -to [get_ports {i2c_sda i2c_scl}]
set_output_delay 0 [get_ports {i2c_sda i2c_scl}]
set_false_path -from [get_ports {i2c_sda i2c_scl}]
set_input_delay 0 [get_ports {i2c_sda i2c_scl}]
# PCIe Interface
#set_property -dict {LOC AF2 } [get_ports {pcie_rx_p[0]}] ;# MGTYRXP3_227 GTYE4_CHANNEL_X1Y35 / GTYE4_COMMON_X1Y8
#set_property -dict {LOC AF1 } [get_ports {pcie_rx_n[0]}] ;# MGTYRXN3_227 GTYE4_CHANNEL_X1Y35 / GTYE4_COMMON_X1Y8
#set_property -dict {LOC AF7 } [get_ports {pcie_tx_p[0]}] ;# MGTYTXP3_227 GTYE4_CHANNEL_X1Y35 / GTYE4_COMMON_X1Y8
#set_property -dict {LOC AF6 } [get_ports {pcie_tx_n[0]}] ;# MGTYTXN3_227 GTYE4_CHANNEL_X1Y35 / GTYE4_COMMON_X1Y8
#set_property -dict {LOC AG4 } [get_ports {pcie_rx_p[1]}] ;# MGTYRXP2_227 GTYE4_CHANNEL_X1Y34 / GTYE4_COMMON_X1Y8
#set_property -dict {LOC AG3 } [get_ports {pcie_rx_n[1]}] ;# MGTYRXN2_227 GTYE4_CHANNEL_X1Y34 / GTYE4_COMMON_X1Y8
#set_property -dict {LOC AG9 } [get_ports {pcie_tx_p[1]}] ;# MGTYTXP2_227 GTYE4_CHANNEL_X1Y34 / GTYE4_COMMON_X1Y8
#set_property -dict {LOC AG8 } [get_ports {pcie_tx_n[1]}] ;# MGTYTXN2_227 GTYE4_CHANNEL_X1Y34 / GTYE4_COMMON_X1Y8
#set_property -dict {LOC AH2 } [get_ports {pcie_rx_p[2]}] ;# MGTYRXP1_227 GTYE4_CHANNEL_X1Y33 / GTYE4_COMMON_X1Y8
#set_property -dict {LOC AH1 } [get_ports {pcie_rx_n[2]}] ;# MGTYRXN1_227 GTYE4_CHANNEL_X1Y33 / GTYE4_COMMON_X1Y8
#set_property -dict {LOC AH7 } [get_ports {pcie_tx_p[2]}] ;# MGTYTXP1_227 GTYE4_CHANNEL_X1Y33 / GTYE4_COMMON_X1Y8
#set_property -dict {LOC AH6 } [get_ports {pcie_tx_n[2]}] ;# MGTYTXN1_227 GTYE4_CHANNEL_X1Y33 / GTYE4_COMMON_X1Y8
#set_property -dict {LOC AJ4 } [get_ports {pcie_rx_p[3]}] ;# MGTYRXP0_227 GTYE4_CHANNEL_X1Y32 / GTYE4_COMMON_X1Y8
#set_property -dict {LOC AJ3 } [get_ports {pcie_rx_n[3]}] ;# MGTYRXN0_227 GTYE4_CHANNEL_X1Y32 / GTYE4_COMMON_X1Y8
#set_property -dict {LOC AJ9 } [get_ports {pcie_tx_p[3]}] ;# MGTYTXP0_227 GTYE4_CHANNEL_X1Y32 / GTYE4_COMMON_X1Y8
#set_property -dict {LOC AJ8 } [get_ports {pcie_tx_n[3]}] ;# MGTYTXN0_227 GTYE4_CHANNEL_X1Y32 / GTYE4_COMMON_X1Y8
#set_property -dict {LOC AK2 } [get_ports {pcie_rx_p[4]}] ;# MGTYRXP3_226 GTYE4_CHANNEL_X1Y31 / GTYE4_COMMON_X1Y7
#set_property -dict {LOC AK1 } [get_ports {pcie_rx_n[4]}] ;# MGTYRXN3_226 GTYE4_CHANNEL_X1Y31 / GTYE4_COMMON_X1Y7
#set_property -dict {LOC AK7 } [get_ports {pcie_tx_p[4]}] ;# MGTYTXP3_226 GTYE4_CHANNEL_X1Y31 / GTYE4_COMMON_X1Y7
#set_property -dict {LOC AK6 } [get_ports {pcie_tx_n[4]}] ;# MGTYTXN3_226 GTYE4_CHANNEL_X1Y31 / GTYE4_COMMON_X1Y7
#set_property -dict {LOC AL4 } [get_ports {pcie_rx_p[5]}] ;# MGTYRXP2_226 GTYE4_CHANNEL_X1Y30 / GTYE4_COMMON_X1Y7
#set_property -dict {LOC AL3 } [get_ports {pcie_rx_n[5]}] ;# MGTYRXN2_226 GTYE4_CHANNEL_X1Y30 / GTYE4_COMMON_X1Y7
#set_property -dict {LOC AL9 } [get_ports {pcie_tx_p[5]}] ;# MGTYTXP2_226 GTYE4_CHANNEL_X1Y30 / GTYE4_COMMON_X1Y7
#set_property -dict {LOC AL8 } [get_ports {pcie_tx_n[5]}] ;# MGTYTXN2_226 GTYE4_CHANNEL_X1Y30 / GTYE4_COMMON_X1Y7
#set_property -dict {LOC AM2 } [get_ports {pcie_rx_p[6]}] ;# MGTYRXP1_226 GTYE4_CHANNEL_X1Y29 / GTYE4_COMMON_X1Y7
#set_property -dict {LOC AM1 } [get_ports {pcie_rx_n[6]}] ;# MGTYRXN1_226 GTYE4_CHANNEL_X1Y29 / GTYE4_COMMON_X1Y7
#set_property -dict {LOC AM7 } [get_ports {pcie_tx_p[6]}] ;# MGTYTXP1_226 GTYE4_CHANNEL_X1Y29 / GTYE4_COMMON_X1Y7
#set_property -dict {LOC AM6 } [get_ports {pcie_tx_n[6]}] ;# MGTYTXN1_226 GTYE4_CHANNEL_X1Y29 / GTYE4_COMMON_X1Y7
#set_property -dict {LOC AN4 } [get_ports {pcie_rx_p[7]}] ;# MGTYRXP0_226 GTYE4_CHANNEL_X1Y28 / GTYE4_COMMON_X1Y7
#set_property -dict {LOC AN3 } [get_ports {pcie_rx_n[7]}] ;# MGTYRXN0_226 GTYE4_CHANNEL_X1Y28 / GTYE4_COMMON_X1Y7
#set_property -dict {LOC AN9 } [get_ports {pcie_tx_p[7]}] ;# MGTYTXP0_226 GTYE4_CHANNEL_X1Y28 / GTYE4_COMMON_X1Y7
#set_property -dict {LOC AN8 } [get_ports {pcie_tx_n[7]}] ;# MGTYTXN0_226 GTYE4_CHANNEL_X1Y28 / GTYE4_COMMON_X1Y7
#set_property -dict {LOC AP2 } [get_ports {pcie_rx_p[8]}] ;# MGTYRXP3_225 GTYE4_CHANNEL_X1Y27 / GTYE4_COMMON_X1Y6
#set_property -dict {LOC AP1 } [get_ports {pcie_rx_n[8]}] ;# MGTYRXN3_225 GTYE4_CHANNEL_X1Y27 / GTYE4_COMMON_X1Y6
#set_property -dict {LOC AP7 } [get_ports {pcie_tx_p[8]}] ;# MGTYTXP3_225 GTYE4_CHANNEL_X1Y27 / GTYE4_COMMON_X1Y6
#set_property -dict {LOC AP6 } [get_ports {pcie_tx_n[8]}] ;# MGTYTXN3_225 GTYE4_CHANNEL_X1Y27 / GTYE4_COMMON_X1Y6
#set_property -dict {LOC AR4 } [get_ports {pcie_rx_p[9]}] ;# MGTYRXP2_225 GTYE4_CHANNEL_X1Y26 / GTYE4_COMMON_X1Y6
#set_property -dict {LOC AR3 } [get_ports {pcie_rx_n[9]}] ;# MGTYRXN2_225 GTYE4_CHANNEL_X1Y26 / GTYE4_COMMON_X1Y6
#set_property -dict {LOC AR9 } [get_ports {pcie_tx_p[9]}] ;# MGTYTXP2_225 GTYE4_CHANNEL_X1Y26 / GTYE4_COMMON_X1Y6
#set_property -dict {LOC AR8 } [get_ports {pcie_tx_n[9]}] ;# MGTYTXN2_225 GTYE4_CHANNEL_X1Y26 / GTYE4_COMMON_X1Y6
#set_property -dict {LOC AT2 } [get_ports {pcie_rx_p[10]}] ;# MGTYRXP1_225 GTYE4_CHANNEL_X1Y25 / GTYE4_COMMON_X1Y6
#set_property -dict {LOC AT1 } [get_ports {pcie_rx_n[10]}] ;# MGTYRXN1_225 GTYE4_CHANNEL_X1Y25 / GTYE4_COMMON_X1Y6
#set_property -dict {LOC AT7 } [get_ports {pcie_tx_p[10]}] ;# MGTYTXP1_225 GTYE4_CHANNEL_X1Y25 / GTYE4_COMMON_X1Y6
#set_property -dict {LOC AT6 } [get_ports {pcie_tx_n[10]}] ;# MGTYTXN1_225 GTYE4_CHANNEL_X1Y25 / GTYE4_COMMON_X1Y6
#set_property -dict {LOC AU4 } [get_ports {pcie_rx_p[11]}] ;# MGTYRXP0_225 GTYE4_CHANNEL_X1Y24 / GTYE4_COMMON_X1Y6
#set_property -dict {LOC AU3 } [get_ports {pcie_rx_n[11]}] ;# MGTYRXN0_225 GTYE4_CHANNEL_X1Y24 / GTYE4_COMMON_X1Y6
#set_property -dict {LOC AU9 } [get_ports {pcie_tx_p[11]}] ;# MGTYTXP0_225 GTYE4_CHANNEL_X1Y24 / GTYE4_COMMON_X1Y6
#set_property -dict {LOC AU8 } [get_ports {pcie_tx_n[11]}] ;# MGTYTXN0_225 GTYE4_CHANNEL_X1Y24 / GTYE4_COMMON_X1Y6
#set_property -dict {LOC AV2 } [get_ports {pcie_rx_p[12]}] ;# MGTYRXP3_224 GTYE4_CHANNEL_X1Y23 / GTYE4_COMMON_X1Y5
#set_property -dict {LOC AV1 } [get_ports {pcie_rx_n[12]}] ;# MGTYRXN3_224 GTYE4_CHANNEL_X1Y23 / GTYE4_COMMON_X1Y5
#set_property -dict {LOC AV7 } [get_ports {pcie_tx_p[12]}] ;# MGTYTXP3_224 GTYE4_CHANNEL_X1Y23 / GTYE4_COMMON_X1Y5
#set_property -dict {LOC AV6 } [get_ports {pcie_tx_n[12]}] ;# MGTYTXN3_224 GTYE4_CHANNEL_X1Y23 / GTYE4_COMMON_X1Y5
#set_property -dict {LOC AW4 } [get_ports {pcie_rx_p[13]}] ;# MGTYRXP2_224 GTYE4_CHANNEL_X1Y22 / GTYE4_COMMON_X1Y5
#set_property -dict {LOC AW3 } [get_ports {pcie_rx_n[13]}] ;# MGTYRXN2_224 GTYE4_CHANNEL_X1Y22 / GTYE4_COMMON_X1Y5
#set_property -dict {LOC BB5 } [get_ports {pcie_tx_p[13]}] ;# MGTYTXP2_224 GTYE4_CHANNEL_X1Y22 / GTYE4_COMMON_X1Y5
#set_property -dict {LOC BB4 } [get_ports {pcie_tx_n[13]}] ;# MGTYTXN2_224 GTYE4_CHANNEL_X1Y22 / GTYE4_COMMON_X1Y5
#set_property -dict {LOC BA2 } [get_ports {pcie_rx_p[14]}] ;# MGTYRXP1_224 GTYE4_CHANNEL_X1Y21 / GTYE4_COMMON_X1Y5
#set_property -dict {LOC BA1 } [get_ports {pcie_rx_n[14]}] ;# MGTYRXN1_224 GTYE4_CHANNEL_X1Y21 / GTYE4_COMMON_X1Y5
#set_property -dict {LOC BD5 } [get_ports {pcie_tx_p[14]}] ;# MGTYTXP1_224 GTYE4_CHANNEL_X1Y21 / GTYE4_COMMON_X1Y5
#set_property -dict {LOC BD4 } [get_ports {pcie_tx_n[14]}] ;# MGTYTXN1_224 GTYE4_CHANNEL_X1Y21 / GTYE4_COMMON_X1Y5
#set_property -dict {LOC BC2 } [get_ports {pcie_rx_p[15]}] ;# MGTYRXP0_224 GTYE4_CHANNEL_X1Y20 / GTYE4_COMMON_X1Y5
#set_property -dict {LOC BC1 } [get_ports {pcie_rx_n[15]}] ;# MGTYRXN0_224 GTYE4_CHANNEL_X1Y20 / GTYE4_COMMON_X1Y5
#set_property -dict {LOC BF5 } [get_ports {pcie_tx_p[15]}] ;# MGTYTXP0_224 GTYE4_CHANNEL_X1Y20 / GTYE4_COMMON_X1Y5
#set_property -dict {LOC BF4 } [get_ports {pcie_tx_n[15]}] ;# MGTYTXN0_224 GTYE4_CHANNEL_X1Y20 / GTYE4_COMMON_X1Y5
#set_property -dict {LOC AM11 } [get_ports pcie_refclk_p] ;# MGTREFCLK0P_226
#set_property -dict {LOC AM10 } [get_ports pcie_refclk_n] ;# MGTREFCLK0N_226
#set_property -dict {LOC BD21 IOSTANDARD LVCMOS12 PULLUP true} [get_ports pcie_reset_n]
# 100 MHz MGT reference clock
#create_clock -period 10 -name pcie_mgt_refclk_1 [get_ports pcie_refclk_p]
#set_false_path -from [get_ports {pcie_reset_n}]
#set_input_delay 0 [get_ports {pcie_reset_n}]
# DDR4 C0
#set_property -dict {LOC AT36 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c0_adr[0]}]
#set_property -dict {LOC AV36 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c0_adr[1]}]
#set_property -dict {LOC AV37 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c0_adr[2]}]
#set_property -dict {LOC AW35 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c0_adr[3]}]
#set_property -dict {LOC AW36 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c0_adr[4]}]
#set_property -dict {LOC AY36 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c0_adr[5]}]
#set_property -dict {LOC AY35 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c0_adr[6]}]
#set_property -dict {LOC BA40 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c0_adr[7]}]
#set_property -dict {LOC BA37 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c0_adr[8]}]
#set_property -dict {LOC BB37 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c0_adr[9]}]
#set_property -dict {LOC AR35 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c0_adr[10]}]
#set_property -dict {LOC BA39 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c0_adr[11]}]
#set_property -dict {LOC BB40 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c0_adr[12]}]
#set_property -dict {LOC AN36 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c0_adr[13]}]
#set_property -dict {LOC AP35 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c0_adr[14]}]
#set_property -dict {LOC AP36 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c0_adr[15]}]
#set_property -dict {LOC AR36 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c0_adr[16]}]
#set_property -dict {LOC AT35 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c0_ba[0]}]
#set_property -dict {LOC AT34 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c0_ba[1]}]
#set_property -dict {LOC BC37 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c0_bg[0]}]
#set_property -dict {LOC BC39 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c0_bg[1]}]
#set_property -dict {LOC AV38 IOSTANDARD DIFF_SSTL12_DCI} [get_ports {ddr4_c0_ck_t[0]}]
#set_property -dict {LOC AW38 IOSTANDARD DIFF_SSTL12_DCI} [get_ports {ddr4_c0_ck_c[0]}]
#set_property -dict {LOC AU34 IOSTANDARD DIFF_SSTL12_DCI} [get_ports {ddr4_c0_ck_t[1]}]
#set_property -dict {LOC AU35 IOSTANDARD DIFF_SSTL12_DCI} [get_ports {ddr4_c0_ck_c[1]}]
#set_property -dict {LOC BC38 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c0_cke[0]}]
#set_property -dict {LOC BC40 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c0_cke[1]}]
#set_property -dict {LOC AR33 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c0_cs_n[0]}]
#set_property -dict {LOC AP33 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c0_cs_n[1]}]
#set_property -dict {LOC AN33 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c0_cs_n[2]}]
#set_property -dict {LOC AM34 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c0_cs_n[3]}]
#set_property -dict {LOC BB39 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c0_act_n}]
#set_property -dict {LOC AP34 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c0_odt[0]}]
#set_property -dict {LOC AN34 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c0_odt[1]}]
#set_property -dict {LOC AU36 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c0_par}]
#set_property -dict {LOC AU31 IOSTANDARD LVCMOS12 } [get_ports {ddr4_c0_reset_n}]
#set_property -dict {LOC AW28 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[0]}]
#set_property -dict {LOC AW29 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[1]}]
#set_property -dict {LOC BA28 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[2]}]
#set_property -dict {LOC BA27 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[3]}]
#set_property -dict {LOC BB29 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[4]}]
#set_property -dict {LOC BA29 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[5]}]
#set_property -dict {LOC BC27 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[6]}]
#set_property -dict {LOC BB27 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[7]}]
#set_property -dict {LOC BE28 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[8]}]
#set_property -dict {LOC BF28 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[9]}]
#set_property -dict {LOC BE30 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[10]}]
#set_property -dict {LOC BD30 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[11]}]
#set_property -dict {LOC BF27 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[12]}]
#set_property -dict {LOC BE27 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[13]}]
#set_property -dict {LOC BF30 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[14]}]
#set_property -dict {LOC BF29 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[15]}]
#set_property -dict {LOC BB31 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[16]}]
#set_property -dict {LOC BB32 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[17]}]
#set_property -dict {LOC AY32 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[18]}]
#set_property -dict {LOC AY33 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[19]}]
#set_property -dict {LOC BC32 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[20]}]
#set_property -dict {LOC BC33 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[21]}]
#set_property -dict {LOC BB34 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[22]}]
#set_property -dict {LOC BC34 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[23]}]
#set_property -dict {LOC AV31 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[24]}]
#set_property -dict {LOC AV32 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[25]}]
#set_property -dict {LOC AV34 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[26]}]
#set_property -dict {LOC AW34 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[27]}]
#set_property -dict {LOC AW31 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[28]}]
#set_property -dict {LOC AY31 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[29]}]
#set_property -dict {LOC BA35 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[30]}]
#set_property -dict {LOC BA34 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[31]}]
#set_property -dict {LOC AL30 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[32]}]
#set_property -dict {LOC AM30 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[33]}]
#set_property -dict {LOC AU32 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[34]}]
#set_property -dict {LOC AT32 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[35]}]
#set_property -dict {LOC AN31 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[36]}]
#set_property -dict {LOC AN32 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[37]}]
#set_property -dict {LOC AR32 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[38]}]
#set_property -dict {LOC AR31 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[39]}]
#set_property -dict {LOC AP29 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[40]}]
#set_property -dict {LOC AP28 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[41]}]
#set_property -dict {LOC AN27 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[42]}]
#set_property -dict {LOC AM27 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[43]}]
#set_property -dict {LOC AN29 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[44]}]
#set_property -dict {LOC AM29 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[45]}]
#set_property -dict {LOC AR27 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[46]}]
#set_property -dict {LOC AR28 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[47]}]
#set_property -dict {LOC AT28 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[48]}]
#set_property -dict {LOC AV27 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[49]}]
#set_property -dict {LOC AU27 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[50]}]
#set_property -dict {LOC AT27 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[51]}]
#set_property -dict {LOC AV29 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[52]}]
#set_property -dict {LOC AY30 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[53]}]
#set_property -dict {LOC AW30 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[54]}]
#set_property -dict {LOC AV28 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[55]}]
#set_property -dict {LOC BD34 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[56]}]
#set_property -dict {LOC BD33 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[57]}]
#set_property -dict {LOC BE33 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[58]}]
#set_property -dict {LOC BD35 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[59]}]
#set_property -dict {LOC BF32 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[60]}]
#set_property -dict {LOC BF33 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[61]}]
#set_property -dict {LOC BF34 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[62]}]
#set_property -dict {LOC BF35 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[63]}]
#set_property -dict {LOC BD40 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[64]}]
#set_property -dict {LOC BD39 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[65]}]
#set_property -dict {LOC BF43 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[66]}]
#set_property -dict {LOC BF42 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[67]}]
#set_property -dict {LOC BF37 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[68]}]
#set_property -dict {LOC BE37 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[69]}]
#set_property -dict {LOC BE40 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[70]}]
#set_property -dict {LOC BF41 IOSTANDARD POD12_DCI } [get_ports {ddr4_c0_dq[71]}]
#set_property -dict {LOC BA30 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c0_dqs_t[0]}]
#set_property -dict {LOC BB30 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c0_dqs_c[0]}]
#set_property -dict {LOC BB26 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c0_dqs_t[1]}]
#set_property -dict {LOC BC26 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c0_dqs_c[1]}]
#set_property -dict {LOC BD28 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c0_dqs_t[2]}]
#set_property -dict {LOC BD29 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c0_dqs_c[2]}]
#set_property -dict {LOC BD26 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c0_dqs_t[3]}]
#set_property -dict {LOC BE26 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c0_dqs_c[3]}]
#set_property -dict {LOC BB35 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c0_dqs_t[4]}]
#set_property -dict {LOC BB36 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c0_dqs_c[4]}]
#set_property -dict {LOC BC31 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c0_dqs_t[5]}]
#set_property -dict {LOC BD31 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c0_dqs_c[5]}]
#set_property -dict {LOC AV33 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c0_dqs_t[6]}]
#set_property -dict {LOC AW33 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c0_dqs_c[6]}]
#set_property -dict {LOC BA32 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c0_dqs_t[7]}]
#set_property -dict {LOC BA33 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c0_dqs_c[7]}]
#set_property -dict {LOC AM31 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c0_dqs_t[8]}]
#set_property -dict {LOC AM32 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c0_dqs_c[8]}]
#set_property -dict {LOC AP30 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c0_dqs_t[9]}]
#set_property -dict {LOC AP31 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c0_dqs_c[9]}]
#set_property -dict {LOC AL28 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c0_dqs_t[10]}]
#set_property -dict {LOC AL29 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c0_dqs_c[10]}]
#set_property -dict {LOC AR30 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c0_dqs_t[11]}]
#set_property -dict {LOC AT30 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c0_dqs_c[11]}]
#set_property -dict {LOC AU29 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c0_dqs_t[12]}]
#set_property -dict {LOC AU30 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c0_dqs_c[12]}]
#set_property -dict {LOC AY27 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c0_dqs_t[13]}]
#set_property -dict {LOC AY28 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c0_dqs_c[13]}]
#set_property -dict {LOC BE35 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c0_dqs_t[14]}]
#set_property -dict {LOC BE36 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c0_dqs_c[14]}]
#set_property -dict {LOC BE31 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c0_dqs_t[15]}]
#set_property -dict {LOC BE32 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c0_dqs_c[15]}]
#set_property -dict {LOC BE38 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c0_dqs_t[16]}]
#set_property -dict {LOC BF38 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c0_dqs_c[16]}]
#set_property -dict {LOC BF39 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c0_dqs_t[17]}]
#set_property -dict {LOC BF40 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c0_dqs_c[17]}]
# DDR4 C1
#set_property -dict {LOC AN24 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c1_adr[0]}]
#set_property -dict {LOC AT24 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c1_adr[1]}]
#set_property -dict {LOC AW24 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c1_adr[2]}]
#set_property -dict {LOC AN26 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c1_adr[3]}]
#set_property -dict {LOC AY22 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c1_adr[4]}]
#set_property -dict {LOC AY23 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c1_adr[5]}]
#set_property -dict {LOC AV24 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c1_adr[6]}]
#set_property -dict {LOC BA22 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c1_adr[7]}]
#set_property -dict {LOC AY25 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c1_adr[8]}]
#set_property -dict {LOC BA23 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c1_adr[9]}]
#set_property -dict {LOC AM26 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c1_adr[10]}]
#set_property -dict {LOC BA25 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c1_adr[11]}]
#set_property -dict {LOC BB22 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c1_adr[12]}]
#set_property -dict {LOC AL24 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c1_adr[13]}]
#set_property -dict {LOC AL25 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c1_adr[14]}]
#set_property -dict {LOC AM25 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c1_adr[15]}]
#set_property -dict {LOC AN23 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c1_adr[16]}]
#set_property -dict {LOC AU24 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c1_ba[0]}]
#set_property -dict {LOC AP26 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c1_ba[1]}]
#set_property -dict {LOC BC22 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c1_bg[0]}]
#set_property -dict {LOC AW26 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c1_bg[1]}]
#set_property -dict {LOC AT25 IOSTANDARD DIFF_SSTL12_DCI} [get_ports {ddr4_c1_ck_t[0]}]
#set_property -dict {LOC AU25 IOSTANDARD DIFF_SSTL12_DCI} [get_ports {ddr4_c1_ck_c[0]}]
#set_property -dict {LOC AU26 IOSTANDARD DIFF_SSTL12_DCI} [get_ports {ddr4_c1_ck_t[1]}]
#set_property -dict {LOC AV26 IOSTANDARD DIFF_SSTL12_DCI} [get_ports {ddr4_c1_ck_c[1]}]
#set_property -dict {LOC BB25 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c1_cke[0]}]
#set_property -dict {LOC BB24 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c1_cke[1]}]
#set_property -dict {LOC AV23 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c1_cs_n[0]}]
#set_property -dict {LOC AP25 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c1_cs_n[1]}]
#set_property -dict {LOC AR23 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c1_cs_n[2]}]
#set_property -dict {LOC AP23 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c1_cs_n[3]}]
#set_property -dict {LOC AW25 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c1_act_n}]
#set_property -dict {LOC AW23 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c1_odt[0]}]
#set_property -dict {LOC AP24 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c1_odt[1]}]
#set_property -dict {LOC AT23 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c1_par}]
#set_property -dict {LOC AR17 IOSTANDARD LVCMOS12 } [get_ports {ddr4_c1_reset_n}]
#set_property -dict {LOC BD9 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[0]}]
#set_property -dict {LOC BD7 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[1]}]
#set_property -dict {LOC BC7 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[2]}]
#set_property -dict {LOC BD8 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[3]}]
#set_property -dict {LOC BD10 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[4]}]
#set_property -dict {LOC BE10 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[5]}]
#set_property -dict {LOC BE7 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[6]}]
#set_property -dict {LOC BF7 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[7]}]
#set_property -dict {LOC AU13 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[8]}]
#set_property -dict {LOC AV13 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[9]}]
#set_property -dict {LOC AW13 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[10]}]
#set_property -dict {LOC AW14 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[11]}]
#set_property -dict {LOC AU14 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[12]}]
#set_property -dict {LOC AY11 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[13]}]
#set_property -dict {LOC AV14 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[14]}]
#set_property -dict {LOC BA11 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[15]}]
#set_property -dict {LOC BA12 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[16]}]
#set_property -dict {LOC BB12 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[17]}]
#set_property -dict {LOC BA13 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[18]}]
#set_property -dict {LOC BA14 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[19]}]
#set_property -dict {LOC BC9 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[20]}]
#set_property -dict {LOC BB9 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[21]}]
#set_property -dict {LOC BA7 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[22]}]
#set_property -dict {LOC BA8 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[23]}]
#set_property -dict {LOC AN13 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[24]}]
#set_property -dict {LOC AR13 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[25]}]
#set_property -dict {LOC AM13 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[26]}]
#set_property -dict {LOC AP13 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[27]}]
#set_property -dict {LOC AM14 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[28]}]
#set_property -dict {LOC AR15 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[29]}]
#set_property -dict {LOC AL14 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[30]}]
#set_property -dict {LOC AT15 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[31]}]
#set_property -dict {LOC BE13 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[32]}]
#set_property -dict {LOC BD14 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[33]}]
#set_property -dict {LOC BF12 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[34]}]
#set_property -dict {LOC BD13 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[35]}]
#set_property -dict {LOC BD15 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[36]}]
#set_property -dict {LOC BD16 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[37]}]
#set_property -dict {LOC BF14 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[38]}]
#set_property -dict {LOC BF13 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[39]}]
#set_property -dict {LOC AY17 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[40]}]
#set_property -dict {LOC BA17 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[41]}]
#set_property -dict {LOC AY18 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[42]}]
#set_property -dict {LOC BA18 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[43]}]
#set_property -dict {LOC BA15 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[44]}]
#set_property -dict {LOC BB15 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[45]}]
#set_property -dict {LOC BC11 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[46]}]
#set_property -dict {LOC BD11 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[47]}]
#set_property -dict {LOC AV16 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[48]}]
#set_property -dict {LOC AV17 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[49]}]
#set_property -dict {LOC AU16 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[50]}]
#set_property -dict {LOC AU17 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[51]}]
#set_property -dict {LOC BB17 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[52]}]
#set_property -dict {LOC BB16 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[53]}]
#set_property -dict {LOC AT18 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[54]}]
#set_property -dict {LOC AT17 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[55]}]
#set_property -dict {LOC AM15 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[56]}]
#set_property -dict {LOC AL15 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[57]}]
#set_property -dict {LOC AN17 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[58]}]
#set_property -dict {LOC AN16 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[59]}]
#set_property -dict {LOC AR18 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[60]}]
#set_property -dict {LOC AP18 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[61]}]
#set_property -dict {LOC AL17 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[62]}]
#set_property -dict {LOC AL16 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[63]}]
#set_property -dict {LOC BF25 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[64]}]
#set_property -dict {LOC BF24 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[65]}]
#set_property -dict {LOC BD25 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[66]}]
#set_property -dict {LOC BE25 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[67]}]
#set_property -dict {LOC BD23 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[68]}]
#set_property -dict {LOC BC23 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[69]}]
#set_property -dict {LOC BF23 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[70]}]
#set_property -dict {LOC BE23 IOSTANDARD POD12_DCI } [get_ports {ddr4_c1_dq[71]}]
#set_property -dict {LOC BF10 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c1_dqs_t[0]}]
#set_property -dict {LOC BF9 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c1_dqs_c[0]}]
#set_property -dict {LOC BE8 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c1_dqs_t[1]}]
#set_property -dict {LOC BF8 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c1_dqs_c[1]}]
#set_property -dict {LOC AW15 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c1_dqs_t[2]}]
#set_property -dict {LOC AY15 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c1_dqs_c[2]}]
#set_property -dict {LOC AY13 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c1_dqs_t[3]}]
#set_property -dict {LOC AY12 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c1_dqs_c[3]}]
#set_property -dict {LOC BB11 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c1_dqs_t[4]}]
#set_property -dict {LOC BB10 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c1_dqs_c[4]}]
#set_property -dict {LOC BA10 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c1_dqs_t[5]}]
#set_property -dict {LOC BA9 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c1_dqs_c[5]}]
#set_property -dict {LOC AT14 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c1_dqs_t[6]}]
#set_property -dict {LOC AT13 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c1_dqs_c[6]}]
#set_property -dict {LOC AN14 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c1_dqs_t[7]}]
#set_property -dict {LOC AP14 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c1_dqs_c[7]}]
#set_property -dict {LOC BE12 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c1_dqs_t[8]}]
#set_property -dict {LOC BE11 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c1_dqs_c[8]}]
#set_property -dict {LOC BE15 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c1_dqs_t[9]}]
#set_property -dict {LOC BF15 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c1_dqs_c[9]}]
#set_property -dict {LOC BC13 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c1_dqs_t[10]}]
#set_property -dict {LOC BC12 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c1_dqs_c[10]}]
#set_property -dict {LOC BB14 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c1_dqs_t[11]}]
#set_property -dict {LOC BC14 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c1_dqs_c[11]}]
#set_property -dict {LOC AV18 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c1_dqs_t[12]}]
#set_property -dict {LOC AW18 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c1_dqs_c[12]}]
#set_property -dict {LOC AW16 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c1_dqs_t[13]}]
#set_property -dict {LOC AY16 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c1_dqs_c[13]}]
#set_property -dict {LOC AP16 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c1_dqs_t[14]}]
#set_property -dict {LOC AR16 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c1_dqs_c[14]}]
#set_property -dict {LOC AM17 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c1_dqs_t[15]}]
#set_property -dict {LOC AM16 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c1_dqs_c[15]}]
#set_property -dict {LOC BC24 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c1_dqs_t[16]}]
#set_property -dict {LOC BD24 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c1_dqs_c[16]}]
#set_property -dict {LOC BE22 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c1_dqs_t[17]}]
#set_property -dict {LOC BF22 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c1_dqs_c[17]}]
# DDR4 C2
#set_property -dict {LOC L29 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c2_adr[0]}]
#set_property -dict {LOC A33 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c2_adr[1]}]
#set_property -dict {LOC C33 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c2_adr[2]}]
#set_property -dict {LOC J29 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c2_adr[3]}]
#set_property -dict {LOC H31 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c2_adr[4]}]
#set_property -dict {LOC G31 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c2_adr[5]}]
#set_property -dict {LOC C32 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c2_adr[6]}]
#set_property -dict {LOC B32 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c2_adr[7]}]
#set_property -dict {LOC A32 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c2_adr[8]}]
#set_property -dict {LOC D31 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c2_adr[9]}]
#set_property -dict {LOC A34 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c2_adr[10]}]
#set_property -dict {LOC E31 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c2_adr[11]}]
#set_property -dict {LOC M30 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c2_adr[12]}]
#set_property -dict {LOC F33 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c2_adr[13]}]
#set_property -dict {LOC A35 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c2_adr[14]}]
#set_property -dict {LOC G32 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c2_adr[15]}]
#set_property -dict {LOC K30 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c2_adr[16]}]
#set_property -dict {LOC D33 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c2_ba[0]}]
#set_property -dict {LOC B36 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c2_ba[1]}]
#set_property -dict {LOC C31 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c2_bg[0]}]
#set_property -dict {LOC J30 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c2_bg[1]}]
#set_property -dict {LOC C34 IOSTANDARD DIFF_SSTL12_DCI} [get_ports {ddr4_c2_ck_t[0]}]
#set_property -dict {LOC B34 IOSTANDARD DIFF_SSTL12_DCI} [get_ports {ddr4_c2_ck_c[0]}]
#set_property -dict {LOC D34 IOSTANDARD DIFF_SSTL12_DCI} [get_ports {ddr4_c2_ck_t[1]}]
#set_property -dict {LOC D35 IOSTANDARD DIFF_SSTL12_DCI} [get_ports {ddr4_c2_ck_c[1]}]
#set_property -dict {LOC G30 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c2_cke[0]}]
#set_property -dict {LOC E30 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c2_cke[1]}]
#set_property -dict {LOC B35 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c2_cs_n[0]}]
#set_property -dict {LOC J31 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c2_cs_n[1]}]
#set_property -dict {LOC L30 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c2_cs_n[2]}]
#set_property -dict {LOC K31 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c2_cs_n[3]}]
#set_property -dict {LOC B31 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c2_act_n}]
#set_property -dict {LOC E33 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c2_odt[0]}]
#set_property -dict {LOC F34 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c2_odt[1]}]
#set_property -dict {LOC M29 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c2_par}]
#set_property -dict {LOC D36 IOSTANDARD LVCMOS12 } [get_ports {ddr4_c2_reset_n}]
#set_property -dict {LOC R25 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[0]}]
#set_property -dict {LOC P25 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[1]}]
#set_property -dict {LOC M25 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[2]}]
#set_property -dict {LOC L25 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[3]}]
#set_property -dict {LOC P26 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[4]}]
#set_property -dict {LOC R26 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[5]}]
#set_property -dict {LOC N27 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[6]}]
#set_property -dict {LOC N28 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[7]}]
#set_property -dict {LOC J28 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[8]}]
#set_property -dict {LOC H29 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[9]}]
#set_property -dict {LOC H28 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[10]}]
#set_property -dict {LOC G29 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[11]}]
#set_property -dict {LOC K25 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[12]}]
#set_property -dict {LOC L27 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[13]}]
#set_property -dict {LOC K26 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[14]}]
#set_property -dict {LOC K27 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[15]}]
#set_property -dict {LOC F27 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[16]}]
#set_property -dict {LOC E27 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[17]}]
#set_property -dict {LOC E28 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[18]}]
#set_property -dict {LOC D28 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[19]}]
#set_property -dict {LOC G27 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[20]}]
#set_property -dict {LOC G26 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[21]}]
#set_property -dict {LOC F28 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[22]}]
#set_property -dict {LOC F29 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[23]}]
#set_property -dict {LOC D26 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[24]}]
#set_property -dict {LOC C26 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[25]}]
#set_property -dict {LOC B27 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[26]}]
#set_property -dict {LOC B26 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[27]}]
#set_property -dict {LOC A29 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[28]}]
#set_property -dict {LOC A30 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[29]}]
#set_property -dict {LOC C27 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[30]}]
#set_property -dict {LOC C28 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[31]}]
#set_property -dict {LOC F35 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[32]}]
#set_property -dict {LOC E38 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[33]}]
#set_property -dict {LOC D38 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[34]}]
#set_property -dict {LOC E35 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[35]}]
#set_property -dict {LOC E36 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[36]}]
#set_property -dict {LOC E37 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[37]}]
#set_property -dict {LOC F38 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[38]}]
#set_property -dict {LOC G38 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[39]}]
#set_property -dict {LOC P30 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[40]}]
#set_property -dict {LOC R30 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[41]}]
#set_property -dict {LOC P29 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[42]}]
#set_property -dict {LOC N29 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[43]}]
#set_property -dict {LOC L32 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[44]}]
#set_property -dict {LOC M32 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[45]}]
#set_property -dict {LOC P31 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[46]}]
#set_property -dict {LOC N32 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[47]}]
#set_property -dict {LOC J35 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[48]}]
#set_property -dict {LOC K35 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[49]}]
#set_property -dict {LOC L33 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[50]}]
#set_property -dict {LOC K33 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[51]}]
#set_property -dict {LOC J34 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[52]}]
#set_property -dict {LOC J33 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[53]}]
#set_property -dict {LOC N34 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[54]}]
#set_property -dict {LOC P34 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[55]}]
#set_property -dict {LOC H36 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[56]}]
#set_property -dict {LOC G36 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[57]}]
#set_property -dict {LOC H37 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[58]}]
#set_property -dict {LOC J36 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[59]}]
#set_property -dict {LOC K37 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[60]}]
#set_property -dict {LOC K38 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[61]}]
#set_property -dict {LOC G35 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[62]}]
#set_property -dict {LOC G34 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[63]}]
#set_property -dict {LOC C36 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[64]}]
#set_property -dict {LOC B37 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[65]}]
#set_property -dict {LOC A37 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[66]}]
#set_property -dict {LOC A38 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[67]}]
#set_property -dict {LOC C39 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[68]}]
#set_property -dict {LOC D39 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[69]}]
#set_property -dict {LOC A40 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[70]}]
#set_property -dict {LOC B40 IOSTANDARD POD12_DCI } [get_ports {ddr4_c2_dq[71]}]
#set_property -dict {LOC N26 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c2_dqs_t[0]}]
#set_property -dict {LOC M26 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c2_dqs_c[0]}]
#set_property -dict {LOC R28 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c2_dqs_t[1]}]
#set_property -dict {LOC P28 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c2_dqs_c[1]}]
#set_property -dict {LOC J25 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c2_dqs_t[2]}]
#set_property -dict {LOC J26 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c2_dqs_c[2]}]
#set_property -dict {LOC M27 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c2_dqs_t[3]}]
#set_property -dict {LOC L28 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c2_dqs_c[3]}]
#set_property -dict {LOC D29 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c2_dqs_t[4]}]
#set_property -dict {LOC D30 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c2_dqs_c[4]}]
#set_property -dict {LOC H26 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c2_dqs_t[5]}]
#set_property -dict {LOC H27 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c2_dqs_c[5]}]
#set_property -dict {LOC A27 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c2_dqs_t[6]}]
#set_property -dict {LOC A28 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c2_dqs_c[6]}]
#set_property -dict {LOC C29 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c2_dqs_t[7]}]
#set_property -dict {LOC B29 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c2_dqs_c[7]}]
#set_property -dict {LOC E39 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c2_dqs_t[8]}]
#set_property -dict {LOC E40 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c2_dqs_c[8]}]
#set_property -dict {LOC G37 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c2_dqs_t[9]}]
#set_property -dict {LOC F37 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c2_dqs_c[9]}]
#set_property -dict {LOC N31 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c2_dqs_t[10]}]
#set_property -dict {LOC M31 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c2_dqs_c[10]}]
#set_property -dict {LOC T30 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c2_dqs_t[11]}]
#set_property -dict {LOC R31 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c2_dqs_c[11]}]
#set_property -dict {LOC L35 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c2_dqs_t[12]}]
#set_property -dict {LOC L36 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c2_dqs_c[12]}]
#set_property -dict {LOC M34 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c2_dqs_t[13]}]
#set_property -dict {LOC L34 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c2_dqs_c[13]}]
#set_property -dict {LOC J38 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c2_dqs_t[14]}]
#set_property -dict {LOC H38 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c2_dqs_c[14]}]
#set_property -dict {LOC H33 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c2_dqs_t[15]}]
#set_property -dict {LOC H34 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c2_dqs_c[15]}]
#set_property -dict {LOC B39 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c2_dqs_t[16]}]
#set_property -dict {LOC A39 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c2_dqs_c[16]}]
#set_property -dict {LOC C37 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c2_dqs_t[17]}]
#set_property -dict {LOC C38 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c2_dqs_c[17]}]
# DDR4 C3
#set_property -dict {LOC K15 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c3_adr[0]}]
#set_property -dict {LOC B15 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c3_adr[1]}]
#set_property -dict {LOC F14 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c3_adr[2]}]
#set_property -dict {LOC A15 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c3_adr[3]}]
#set_property -dict {LOC C14 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c3_adr[4]}]
#set_property -dict {LOC A14 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c3_adr[5]}]
#set_property -dict {LOC B14 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c3_adr[6]}]
#set_property -dict {LOC E13 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c3_adr[7]}]
#set_property -dict {LOC F13 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c3_adr[8]}]
#set_property -dict {LOC A13 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c3_adr[9]}]
#set_property -dict {LOC D14 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c3_adr[10]}]
#set_property -dict {LOC C13 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c3_adr[11]}]
#set_property -dict {LOC B13 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c3_adr[12]}]
#set_property -dict {LOC K16 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c3_adr[13]}]
#set_property -dict {LOC D15 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c3_adr[14]}]
#set_property -dict {LOC E15 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c3_adr[15]}]
#set_property -dict {LOC F15 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c3_adr[16]}]
#set_property -dict {LOC J15 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c3_ba[0]}]
#set_property -dict {LOC H14 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c3_ba[1]}]
#set_property -dict {LOC D13 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c3_bg[0]}]
#set_property -dict {LOC J13 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c3_bg[1]}]
#set_property -dict {LOC L14 IOSTANDARD DIFF_SSTL12_DCI} [get_ports {ddr4_c3_ck_t[0]}]
#set_property -dict {LOC L13 IOSTANDARD DIFF_SSTL12_DCI} [get_ports {ddr4_c3_ck_c[0]}]
#set_property -dict {LOC G14 IOSTANDARD DIFF_SSTL12_DCI} [get_ports {ddr4_c3_ck_t[1]}]
#set_property -dict {LOC G13 IOSTANDARD DIFF_SSTL12_DCI} [get_ports {ddr4_c3_ck_c[1]}]
#set_property -dict {LOC K13 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c3_cke[0]}]
#set_property -dict {LOC L15 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c3_cke[1]}]
#set_property -dict {LOC B16 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c3_cs_n[0]}]
#set_property -dict {LOC D16 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c3_cs_n[1]}]
#set_property -dict {LOC M14 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c3_cs_n[2]}]
#set_property -dict {LOC M13 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c3_cs_n[3]}]
#set_property -dict {LOC H13 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c3_act_n}]
#set_property -dict {LOC C16 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c3_odt[0]}]
#set_property -dict {LOC E16 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c3_odt[1]}]
#set_property -dict {LOC J14 IOSTANDARD SSTL12_DCI } [get_ports {ddr4_c3_par}]
#set_property -dict {LOC D21 IOSTANDARD LVCMOS12 } [get_ports {ddr4_c3_reset_n}]
#set_property -dict {LOC P24 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[0]}]
#set_property -dict {LOC N24 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[1]}]
#set_property -dict {LOC T24 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[2]}]
#set_property -dict {LOC R23 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[3]}]
#set_property -dict {LOC N23 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[4]}]
#set_property -dict {LOC P21 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[5]}]
#set_property -dict {LOC P23 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[6]}]
#set_property -dict {LOC R21 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[7]}]
#set_property -dict {LOC J24 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[8]}]
#set_property -dict {LOC J23 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[9]}]
#set_property -dict {LOC H24 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[10]}]
#set_property -dict {LOC G24 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[11]}]
#set_property -dict {LOC L24 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[12]}]
#set_property -dict {LOC L23 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[13]}]
#set_property -dict {LOC K22 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[14]}]
#set_property -dict {LOC K21 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[15]}]
#set_property -dict {LOC G20 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[16]}]
#set_property -dict {LOC H17 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[17]}]
#set_property -dict {LOC F19 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[18]}]
#set_property -dict {LOC G17 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[19]}]
#set_property -dict {LOC J20 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[20]}]
#set_property -dict {LOC L19 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[21]}]
#set_property -dict {LOC L18 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[22]}]
#set_property -dict {LOC J19 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[23]}]
#set_property -dict {LOC M19 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[24]}]
#set_property -dict {LOC M20 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[25]}]
#set_property -dict {LOC R18 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[26]}]
#set_property -dict {LOC R17 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[27]}]
#set_property -dict {LOC R20 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[28]}]
#set_property -dict {LOC T20 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[29]}]
#set_property -dict {LOC N18 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[30]}]
#set_property -dict {LOC N19 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[31]}]
#set_property -dict {LOC A23 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[32]}]
#set_property -dict {LOC A22 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[33]}]
#set_property -dict {LOC B24 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[34]}]
#set_property -dict {LOC B25 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[35]}]
#set_property -dict {LOC B22 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[36]}]
#set_property -dict {LOC C22 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[37]}]
#set_property -dict {LOC C24 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[38]}]
#set_property -dict {LOC C23 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[39]}]
#set_property -dict {LOC C19 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[40]}]
#set_property -dict {LOC C18 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[41]}]
#set_property -dict {LOC C21 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[42]}]
#set_property -dict {LOC B21 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[43]}]
#set_property -dict {LOC A18 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[44]}]
#set_property -dict {LOC A17 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[45]}]
#set_property -dict {LOC A20 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[46]}]
#set_property -dict {LOC B20 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[47]}]
#set_property -dict {LOC E17 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[48]}]
#set_property -dict {LOC F20 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[49]}]
#set_property -dict {LOC E18 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[50]}]
#set_property -dict {LOC E20 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[51]}]
#set_property -dict {LOC D19 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[52]}]
#set_property -dict {LOC D20 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[53]}]
#set_property -dict {LOC H18 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[54]}]
#set_property -dict {LOC J18 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[55]}]
#set_property -dict {LOC F22 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[56]}]
#set_property -dict {LOC E22 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[57]}]
#set_property -dict {LOC G22 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[58]}]
#set_property -dict {LOC G21 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[59]}]
#set_property -dict {LOC F24 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[60]}]
#set_property -dict {LOC E25 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[61]}]
#set_property -dict {LOC F25 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[62]}]
#set_property -dict {LOC G25 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[63]}]
#set_property -dict {LOC M16 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[64]}]
#set_property -dict {LOC N16 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[65]}]
#set_property -dict {LOC N13 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[66]}]
#set_property -dict {LOC N14 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[67]}]
#set_property -dict {LOC T15 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[68]}]
#set_property -dict {LOC R15 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[69]}]
#set_property -dict {LOC P13 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[70]}]
#set_property -dict {LOC P14 IOSTANDARD POD12_DCI } [get_ports {ddr4_c3_dq[71]}]
#set_property -dict {LOC T22 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c3_dqs_t[0]}]
#set_property -dict {LOC R22 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c3_dqs_c[0]}]
#set_property -dict {LOC N22 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c3_dqs_t[1]}]
#set_property -dict {LOC N21 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c3_dqs_c[1]}]
#set_property -dict {LOC J21 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c3_dqs_t[2]}]
#set_property -dict {LOC H21 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c3_dqs_c[2]}]
#set_property -dict {LOC M22 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c3_dqs_t[3]}]
#set_property -dict {LOC L22 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c3_dqs_c[3]}]
#set_property -dict {LOC L20 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c3_dqs_t[4]}]
#set_property -dict {LOC K20 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c3_dqs_c[4]}]
#set_property -dict {LOC K18 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c3_dqs_t[5]}]
#set_property -dict {LOC K17 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c3_dqs_c[5]}]
#set_property -dict {LOC P19 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c3_dqs_t[6]}]
#set_property -dict {LOC P18 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c3_dqs_c[6]}]
#set_property -dict {LOC N17 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c3_dqs_t[7]}]
#set_property -dict {LOC M17 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c3_dqs_c[7]}]
#set_property -dict {LOC A25 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c3_dqs_t[8]}]
#set_property -dict {LOC A24 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c3_dqs_c[8]}]
#set_property -dict {LOC D24 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c3_dqs_t[9]}]
#set_property -dict {LOC D23 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c3_dqs_c[9]}]
#set_property -dict {LOC C17 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c3_dqs_t[10]}]
#set_property -dict {LOC B17 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c3_dqs_c[10]}]
#set_property -dict {LOC B19 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c3_dqs_t[11]}]
#set_property -dict {LOC A19 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c3_dqs_c[11]}]
#set_property -dict {LOC F18 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c3_dqs_t[12]}]
#set_property -dict {LOC F17 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c3_dqs_c[12]}]
#set_property -dict {LOC H19 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c3_dqs_t[13]}]
#set_property -dict {LOC G19 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c3_dqs_c[13]}]
#set_property -dict {LOC F23 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c3_dqs_t[14]}]
#set_property -dict {LOC E23 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c3_dqs_c[14]}]
#set_property -dict {LOC H23 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c3_dqs_t[15]}]
#set_property -dict {LOC H22 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c3_dqs_c[15]}]
#set_property -dict {LOC R16 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c3_dqs_t[16]}]
#set_property -dict {LOC P15 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c3_dqs_c[16]}]
#set_property -dict {LOC T13 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c3_dqs_t[17]}]
#set_property -dict {LOC R13 IOSTANDARD DIFF_POD12_DCI } [get_ports {ddr4_c3_dqs_c[17]}]

View File

@ -1,76 +0,0 @@
# 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

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

View File

@ -1,93 +0,0 @@
/*
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 switch and button inputs with a slow sampled shift register
*/
module debounce_switch #(
parameter WIDTH=1, // width of the input and output signals
parameter N=3, // length of shift register
parameter RATE=125000 // clock division factor
)(
input wire clk,
input wire rst,
input wire [WIDTH-1:0] in,
output wire [WIDTH-1:0] out
);
reg [23:0] cnt_reg = 24'd0;
reg [N-1:0] debounce_reg[WIDTH-1:0];
reg [WIDTH-1:0] state;
/*
* The synchronized output is the state register
*/
assign out = state;
integer k;
always @(posedge clk or posedge rst) begin
if (rst) begin
cnt_reg <= 0;
state <= 0;
for (k = 0; k < WIDTH; k = k + 1) begin
debounce_reg[k] <= 0;
end
end else begin
if (cnt_reg < RATE) begin
cnt_reg <= cnt_reg + 24'd1;
end else begin
cnt_reg <= 24'd0;
end
if (cnt_reg == 24'd0) begin
for (k = 0; k < WIDTH; k = k + 1) begin
debounce_reg[k] <= {debounce_reg[k][N-2:0], in[k]};
end
end
for (k = 0; k < WIDTH; k = k + 1) begin
if (|debounce_reg[k] == 0) begin
state[k] <= 0;
end else if (&debounce_reg[k] == 1) begin
state[k] <= 1;
end else begin
state[k] <= state[k];
end
end
end
end
endmodule
`resetall

View File

@ -1,395 +0,0 @@
/*
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

@ -1,307 +0,0 @@
/*
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

@ -1,702 +0,0 @@
/*
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 (
/*
* Reset: Push button, active low
*/
input wire reset,
/*
* GPIO
*/
input wire [3:0] sw,
output wire [2:0] led,
/*
* I2C for board management
*/
inout wire i2c_scl,
inout wire i2c_sda,
/*
* Ethernet: QSFP28
*/
output wire [3:0] qsfp0_tx_p,
output wire [3:0] qsfp0_tx_n,
input wire [3:0] qsfp0_rx_p,
input wire [3:0] qsfp0_rx_n,
// input wire qsfp0_mgt_refclk_0_p,
// input wire qsfp0_mgt_refclk_0_n,
input wire qsfp0_mgt_refclk_1_p,
input wire qsfp0_mgt_refclk_1_n,
output wire qsfp0_modsell,
output wire qsfp0_resetl,
input wire qsfp0_modprsl,
input wire qsfp0_intl,
output wire qsfp0_lpmode,
output wire qsfp0_refclk_reset,
output wire [1:0] qsfp0_fs,
output wire [3:0] qsfp1_tx_p,
output wire [3:0] qsfp1_tx_n,
input wire [3:0] qsfp1_rx_p,
input wire [3:0] qsfp1_rx_n,
// input wire qsfp1_mgt_refclk_0_p,
// input wire qsfp1_mgt_refclk_0_n,
input wire qsfp1_mgt_refclk_1_p,
input wire qsfp1_mgt_refclk_1_n,
output wire qsfp1_modsell,
output wire qsfp1_resetl,
input wire qsfp1_modprsl,
input wire qsfp1_intl,
output wire qsfp1_lpmode,
output wire qsfp1_refclk_reset,
output wire [1:0] qsfp1_fs,
/*
* UART: 500000 bps, 8N1
*/
output wire uart_rxd,
input wire uart_txd
);
// Clock and reset
wire cfgmclk_int;
wire clk_161mhz_ref_int;
// 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;
wire mmcm_locked;
wire mmcm_clkfb;
// MMCM instance
// 161.13 MHz in, 125 MHz out
// PFD range: 10 MHz to 500 MHz
// VCO range: 800 MHz to 1600 MHz
// M = 64, D = 11 sets Fvco = 937.5 MHz (in range)
// Divide by 7.5 to get output frequency of 125 MHz
MMCME4_BASE #(
.BANDWIDTH("OPTIMIZED"),
.CLKOUT0_DIVIDE_F(7.5),
.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(64),
.CLKFBOUT_PHASE(0),
.DIVCLK_DIVIDE(11),
.REF_JITTER1(0.010),
.CLKIN1_PERIOD(6.206),
.STARTUP_WAIT("FALSE"),
.CLKOUT4_CASCADE("FALSE")
)
clk_mmcm_inst (
.CLKIN1(clk_161mhz_ref_int),
.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)
);
// GPIO
wire [3:0] sw_int;
debounce_switch #(
.WIDTH(4),
.N(4),
.RATE(156000)
)
debounce_switch_inst (
.clk(clk_156mhz_int),
.rst(rst_156mhz_int),
.in({sw}),
.out({sw_int})
);
wire uart_txd_int;
sync_signal #(
.WIDTH(1),
.N(2)
)
sync_signal_inst (
.clk(clk_156mhz_int),
.in({uart_txd}),
.out({uart_txd_int})
);
// SI570 I2C
wire i2c_scl_i;
wire i2c_scl_o = 1'b1;
wire i2c_scl_t = 1'b1;
wire i2c_sda_i;
wire i2c_sda_o = 1'b1;
wire i2c_sda_t = 1'b1;
assign i2c_scl_i = i2c_scl;
assign i2c_scl = i2c_scl_t ? 1'bz : i2c_scl_o;
assign i2c_sda_i = i2c_sda;
assign i2c_sda = i2c_sda_t ? 1'bz : i2c_sda_o;
// startupe3 instance
wire cfgmclk;
STARTUPE3
startupe3_inst (
.CFGCLK(),
.CFGMCLK(cfgmclk),
.DI(4'd0),
.DO(),
.DTS(1'b1),
.EOS(),
.FCSBO(1'b0),
.FCSBTS(1'b1),
.GSR(1'b0),
.GTS(1'b0),
.KEYCLEARB(1'b1),
.PACK(1'b0),
.PREQ(),
.USRCCLKO(1'b0),
.USRCCLKTS(1'b1),
.USRDONEO(1'b0),
.USRDONETS(1'b1)
);
BUFG
cfgmclk_bufg_inst (
.I(cfgmclk),
.O(cfgmclk_int)
);
// configure SI5335 clock generators
reg qsfp_refclk_reset_reg = 1'b1;
reg sys_reset_reg = 1'b1;
reg [9:0] reset_timer_reg = 0;
assign mmcm_rst = sys_reset_reg;
always @(posedge cfgmclk_int) begin
if (&reset_timer_reg) begin
if (qsfp_refclk_reset_reg) begin
qsfp_refclk_reset_reg <= 1'b0;
reset_timer_reg <= 0;
end else begin
qsfp_refclk_reset_reg <= 1'b0;
sys_reset_reg <= 1'b0;
end
end else begin
reset_timer_reg <= reset_timer_reg + 1;
end
if (!reset) begin
qsfp_refclk_reset_reg <= 1'b1;
sys_reset_reg <= 1'b1;
reset_timer_reg <= 0;
end
end
// XGMII 10G PHY
// QSFP0
assign qsfp0_modsell = 1'b0;
assign qsfp0_resetl = 1'b1;
assign qsfp0_lpmode = 1'b0;
assign qsfp0_refclk_reset = qsfp_refclk_reset_reg;
assign qsfp0_fs = 2'b10;
wire qsfp0_tx_clk_1_int;
wire qsfp0_tx_rst_1_int;
wire [63:0] qsfp0_txd_1_int;
wire [7:0] qsfp0_txc_1_int;
wire qsfp0_rx_clk_1_int;
wire qsfp0_rx_rst_1_int;
wire [63:0] qsfp0_rxd_1_int;
wire [7:0] qsfp0_rxc_1_int;
wire qsfp0_tx_clk_2_int;
wire qsfp0_tx_rst_2_int;
wire [63:0] qsfp0_txd_2_int;
wire [7:0] qsfp0_txc_2_int;
wire qsfp0_rx_clk_2_int;
wire qsfp0_rx_rst_2_int;
wire [63:0] qsfp0_rxd_2_int;
wire [7:0] qsfp0_rxc_2_int;
wire qsfp0_tx_clk_3_int;
wire qsfp0_tx_rst_3_int;
wire [63:0] qsfp0_txd_3_int;
wire [7:0] qsfp0_txc_3_int;
wire qsfp0_rx_clk_3_int;
wire qsfp0_rx_rst_3_int;
wire [63:0] qsfp0_rxd_3_int;
wire [7:0] qsfp0_rxc_3_int;
wire qsfp0_tx_clk_4_int;
wire qsfp0_tx_rst_4_int;
wire [63:0] qsfp0_txd_4_int;
wire [7:0] qsfp0_txc_4_int;
wire qsfp0_rx_clk_4_int;
wire qsfp0_rx_rst_4_int;
wire [63:0] qsfp0_rxd_4_int;
wire [7:0] qsfp0_rxc_4_int;
assign clk_156mhz_int = qsfp0_tx_clk_1_int;
assign rst_156mhz_int = qsfp0_tx_rst_1_int;
wire qsfp0_rx_block_lock_1;
wire qsfp0_rx_block_lock_2;
wire qsfp0_rx_block_lock_3;
wire qsfp0_rx_block_lock_4;
wire qsfp0_gtpowergood;
wire qsfp0_mgt_refclk_1;
wire qsfp0_mgt_refclk_1_int;
wire qsfp0_mgt_refclk_1_bufg;
assign clk_161mhz_ref_int = qsfp0_mgt_refclk_1_bufg;
IBUFDS_GTE4 ibufds_gte4_qsfp0_mgt_refclk_1_inst (
.I (qsfp0_mgt_refclk_1_p),
.IB (qsfp0_mgt_refclk_1_n),
.CEB (1'b0),
.O (qsfp0_mgt_refclk_1),
.ODIV2 (qsfp0_mgt_refclk_1_int)
);
BUFG_GT bufg_gt_refclk_inst (
.CE (qsfp0_gtpowergood),
.CEMASK (1'b1),
.CLR (1'b0),
.CLRMASK (1'b1),
.DIV (3'd0),
.I (qsfp0_mgt_refclk_1_int),
.O (qsfp0_mgt_refclk_1_bufg)
);
eth_xcvr_phy_quad_wrapper #(
.TX_SERDES_PIPELINE(2),
.RX_SERDES_PIPELINE(2),
.COUNT_125US(125000/2.56)
)
qsfp0_phy_inst (
.xcvr_ctrl_clk(clk_125mhz_int),
.xcvr_ctrl_rst(rst_125mhz_int),
/*
* Common
*/
.xcvr_gtpowergood_out(qsfp0_gtpowergood),
/*
* PLL
*/
.xcvr_gtrefclk00_in(qsfp0_mgt_refclk_1),
/*
* Serial data
*/
.xcvr_txp(qsfp0_tx_p),
.xcvr_txn(qsfp0_tx_n),
.xcvr_rxp(qsfp0_rx_p),
.xcvr_rxn(qsfp0_rx_n),
/*
* PHY connections
*/
.phy_1_tx_clk(qsfp0_tx_clk_1_int),
.phy_1_tx_rst(qsfp0_tx_rst_1_int),
.phy_1_xgmii_txd(qsfp0_txd_1_int),
.phy_1_xgmii_txc(qsfp0_txc_1_int),
.phy_1_rx_clk(qsfp0_rx_clk_1_int),
.phy_1_rx_rst(qsfp0_rx_rst_1_int),
.phy_1_xgmii_rxd(qsfp0_rxd_1_int),
.phy_1_xgmii_rxc(qsfp0_rxc_1_int),
.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(qsfp0_rx_block_lock_1),
.phy_1_rx_status(),
.phy_1_cfg_tx_prbs31_enable(1'b0),
.phy_1_cfg_rx_prbs31_enable(1'b0),
.phy_2_tx_clk(qsfp0_tx_clk_2_int),
.phy_2_tx_rst(qsfp0_tx_rst_2_int),
.phy_2_xgmii_txd(qsfp0_txd_2_int),
.phy_2_xgmii_txc(qsfp0_txc_2_int),
.phy_2_rx_clk(qsfp0_rx_clk_2_int),
.phy_2_rx_rst(qsfp0_rx_rst_2_int),
.phy_2_xgmii_rxd(qsfp0_rxd_2_int),
.phy_2_xgmii_rxc(qsfp0_rxc_2_int),
.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(qsfp0_rx_block_lock_2),
.phy_2_rx_status(),
.phy_2_cfg_tx_prbs31_enable(1'b0),
.phy_2_cfg_rx_prbs31_enable(1'b0),
.phy_3_tx_clk(qsfp0_tx_clk_3_int),
.phy_3_tx_rst(qsfp0_tx_rst_3_int),
.phy_3_xgmii_txd(qsfp0_txd_3_int),
.phy_3_xgmii_txc(qsfp0_txc_3_int),
.phy_3_rx_clk(qsfp0_rx_clk_3_int),
.phy_3_rx_rst(qsfp0_rx_rst_3_int),
.phy_3_xgmii_rxd(qsfp0_rxd_3_int),
.phy_3_xgmii_rxc(qsfp0_rxc_3_int),
.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(qsfp0_rx_block_lock_3),
.phy_3_rx_status(),
.phy_3_cfg_tx_prbs31_enable(1'b0),
.phy_3_cfg_rx_prbs31_enable(1'b0),
.phy_4_tx_clk(qsfp0_tx_clk_4_int),
.phy_4_tx_rst(qsfp0_tx_rst_4_int),
.phy_4_xgmii_txd(qsfp0_txd_4_int),
.phy_4_xgmii_txc(qsfp0_txc_4_int),
.phy_4_rx_clk(qsfp0_rx_clk_4_int),
.phy_4_rx_rst(qsfp0_rx_rst_4_int),
.phy_4_xgmii_rxd(qsfp0_rxd_4_int),
.phy_4_xgmii_rxc(qsfp0_rxc_4_int),
.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(qsfp0_rx_block_lock_4),
.phy_4_rx_status(),
.phy_4_cfg_tx_prbs31_enable(1'b0),
.phy_4_cfg_rx_prbs31_enable(1'b0)
);
// QSFP1
assign qsfp1_modsell = 1'b0;
assign qsfp1_resetl = 1'b1;
assign qsfp1_lpmode = 1'b0;
assign qsfp1_refclk_reset = qsfp_refclk_reset_reg;
assign qsfp1_fs = 2'b10;
wire qsfp1_tx_clk_1_int;
wire qsfp1_tx_rst_1_int;
wire [63:0] qsfp1_txd_1_int;
wire [7:0] qsfp1_txc_1_int;
wire qsfp1_rx_clk_1_int;
wire qsfp1_rx_rst_1_int;
wire [63:0] qsfp1_rxd_1_int;
wire [7:0] qsfp1_rxc_1_int;
wire qsfp1_tx_clk_2_int;
wire qsfp1_tx_rst_2_int;
wire [63:0] qsfp1_txd_2_int;
wire [7:0] qsfp1_txc_2_int;
wire qsfp1_rx_clk_2_int;
wire qsfp1_rx_rst_2_int;
wire [63:0] qsfp1_rxd_2_int;
wire [7:0] qsfp1_rxc_2_int;
wire qsfp1_tx_clk_3_int;
wire qsfp1_tx_rst_3_int;
wire [63:0] qsfp1_txd_3_int;
wire [7:0] qsfp1_txc_3_int;
wire qsfp1_rx_clk_3_int;
wire qsfp1_rx_rst_3_int;
wire [63:0] qsfp1_rxd_3_int;
wire [7:0] qsfp1_rxc_3_int;
wire qsfp1_tx_clk_4_int;
wire qsfp1_tx_rst_4_int;
wire [63:0] qsfp1_txd_4_int;
wire [7:0] qsfp1_txc_4_int;
wire qsfp1_rx_clk_4_int;
wire qsfp1_rx_rst_4_int;
wire [63:0] qsfp1_rxd_4_int;
wire [7:0] qsfp1_rxc_4_int;
wire qsfp1_rx_block_lock_1;
wire qsfp1_rx_block_lock_2;
wire qsfp1_rx_block_lock_3;
wire qsfp1_rx_block_lock_4;
wire qsfp1_mgt_refclk_1;
IBUFDS_GTE4 ibufds_gte4_qsfp1_mgt_refclk_1_inst (
.I (qsfp1_mgt_refclk_1_p),
.IB (qsfp1_mgt_refclk_1_n),
.CEB (1'b0),
.O (qsfp1_mgt_refclk_1),
.ODIV2 ()
);
eth_xcvr_phy_quad_wrapper #(
.TX_SERDES_PIPELINE(2),
.RX_SERDES_PIPELINE(2),
.COUNT_125US(125000/2.56)
)
qsfp1_phy_inst (
.xcvr_ctrl_clk(clk_125mhz_int),
.xcvr_ctrl_rst(rst_125mhz_int),
/*
* Common
*/
.xcvr_gtpowergood_out(),
/*
* PLL
*/
.xcvr_gtrefclk00_in(qsfp1_mgt_refclk_1),
/*
* Serial data
*/
.xcvr_txp(qsfp1_tx_p),
.xcvr_txn(qsfp1_tx_n),
.xcvr_rxp(qsfp1_rx_p),
.xcvr_rxn(qsfp1_rx_n),
/*
* PHY connections
*/
.phy_1_tx_clk(qsfp1_tx_clk_1_int),
.phy_1_tx_rst(qsfp1_tx_rst_1_int),
.phy_1_xgmii_txd(qsfp1_txd_1_int),
.phy_1_xgmii_txc(qsfp1_txc_1_int),
.phy_1_rx_clk(qsfp1_rx_clk_1_int),
.phy_1_rx_rst(qsfp1_rx_rst_1_int),
.phy_1_xgmii_rxd(qsfp1_rxd_1_int),
.phy_1_xgmii_rxc(qsfp1_rxc_1_int),
.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(qsfp1_rx_block_lock_1),
.phy_1_rx_status(),
.phy_1_cfg_tx_prbs31_enable(1'b0),
.phy_1_cfg_rx_prbs31_enable(1'b0),
.phy_2_tx_clk(qsfp1_tx_clk_2_int),
.phy_2_tx_rst(qsfp1_tx_rst_2_int),
.phy_2_xgmii_txd(qsfp1_txd_2_int),
.phy_2_xgmii_txc(qsfp1_txc_2_int),
.phy_2_rx_clk(qsfp1_rx_clk_2_int),
.phy_2_rx_rst(qsfp1_rx_rst_2_int),
.phy_2_xgmii_rxd(qsfp1_rxd_2_int),
.phy_2_xgmii_rxc(qsfp1_rxc_2_int),
.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(qsfp1_rx_block_lock_2),
.phy_2_rx_status(),
.phy_2_cfg_tx_prbs31_enable(1'b0),
.phy_2_cfg_rx_prbs31_enable(1'b0),
.phy_3_tx_clk(qsfp1_tx_clk_3_int),
.phy_3_tx_rst(qsfp1_tx_rst_3_int),
.phy_3_xgmii_txd(qsfp1_txd_3_int),
.phy_3_xgmii_txc(qsfp1_txc_3_int),
.phy_3_rx_clk(qsfp1_rx_clk_3_int),
.phy_3_rx_rst(qsfp1_rx_rst_3_int),
.phy_3_xgmii_rxd(qsfp1_rxd_3_int),
.phy_3_xgmii_rxc(qsfp1_rxc_3_int),
.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(qsfp1_rx_block_lock_3),
.phy_3_rx_status(),
.phy_3_cfg_tx_prbs31_enable(1'b0),
.phy_3_cfg_rx_prbs31_enable(1'b0),
.phy_4_tx_clk(qsfp1_tx_clk_4_int),
.phy_4_tx_rst(qsfp1_tx_rst_4_int),
.phy_4_xgmii_txd(qsfp1_txd_4_int),
.phy_4_xgmii_txc(qsfp1_txc_4_int),
.phy_4_rx_clk(qsfp1_rx_clk_4_int),
.phy_4_rx_rst(qsfp1_rx_rst_4_int),
.phy_4_xgmii_rxd(qsfp1_rxd_4_int),
.phy_4_xgmii_rxc(qsfp1_rxc_4_int),
.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(qsfp1_rx_block_lock_4),
.phy_4_rx_status(),
.phy_4_cfg_tx_prbs31_enable(1'b0),
.phy_4_cfg_rx_prbs31_enable(1'b0)
);
fpga_core
core_inst (
/*
* Clock: 156.25 MHz
* Synchronous reset
*/
.clk(clk_156mhz_int),
.rst(rst_156mhz_int),
/*
* GPIO
*/
.sw(sw_int),
.led(led),
/*
* Ethernet: QSFP28
*/
.qsfp0_tx_clk_1(qsfp0_tx_clk_1_int),
.qsfp0_tx_rst_1(qsfp0_tx_rst_1_int),
.qsfp0_txd_1(qsfp0_txd_1_int),
.qsfp0_txc_1(qsfp0_txc_1_int),
.qsfp0_rx_clk_1(qsfp0_rx_clk_1_int),
.qsfp0_rx_rst_1(qsfp0_rx_rst_1_int),
.qsfp0_rxd_1(qsfp0_rxd_1_int),
.qsfp0_rxc_1(qsfp0_rxc_1_int),
.qsfp0_tx_clk_2(qsfp0_tx_clk_2_int),
.qsfp0_tx_rst_2(qsfp0_tx_rst_2_int),
.qsfp0_txd_2(qsfp0_txd_2_int),
.qsfp0_txc_2(qsfp0_txc_2_int),
.qsfp0_rx_clk_2(qsfp0_rx_clk_2_int),
.qsfp0_rx_rst_2(qsfp0_rx_rst_2_int),
.qsfp0_rxd_2(qsfp0_rxd_2_int),
.qsfp0_rxc_2(qsfp0_rxc_2_int),
.qsfp0_tx_clk_3(qsfp0_tx_clk_3_int),
.qsfp0_tx_rst_3(qsfp0_tx_rst_3_int),
.qsfp0_txd_3(qsfp0_txd_3_int),
.qsfp0_txc_3(qsfp0_txc_3_int),
.qsfp0_rx_clk_3(qsfp0_rx_clk_3_int),
.qsfp0_rx_rst_3(qsfp0_rx_rst_3_int),
.qsfp0_rxd_3(qsfp0_rxd_3_int),
.qsfp0_rxc_3(qsfp0_rxc_3_int),
.qsfp0_tx_clk_4(qsfp0_tx_clk_4_int),
.qsfp0_tx_rst_4(qsfp0_tx_rst_4_int),
.qsfp0_txd_4(qsfp0_txd_4_int),
.qsfp0_txc_4(qsfp0_txc_4_int),
.qsfp0_rx_clk_4(qsfp0_rx_clk_4_int),
.qsfp0_rx_rst_4(qsfp0_rx_rst_4_int),
.qsfp0_rxd_4(qsfp0_rxd_4_int),
.qsfp0_rxc_4(qsfp0_rxc_4_int),
.qsfp1_tx_clk_1(qsfp1_tx_clk_1_int),
.qsfp1_tx_rst_1(qsfp1_tx_rst_1_int),
.qsfp1_txd_1(qsfp1_txd_1_int),
.qsfp1_txc_1(qsfp1_txc_1_int),
.qsfp1_rx_clk_1(qsfp1_rx_clk_1_int),
.qsfp1_rx_rst_1(qsfp1_rx_rst_1_int),
.qsfp1_rxd_1(qsfp1_rxd_1_int),
.qsfp1_rxc_1(qsfp1_rxc_1_int),
.qsfp1_tx_clk_2(qsfp1_tx_clk_2_int),
.qsfp1_tx_rst_2(qsfp1_tx_rst_2_int),
.qsfp1_txd_2(qsfp1_txd_2_int),
.qsfp1_txc_2(qsfp1_txc_2_int),
.qsfp1_rx_clk_2(qsfp1_rx_clk_2_int),
.qsfp1_rx_rst_2(qsfp1_rx_rst_2_int),
.qsfp1_rxd_2(qsfp1_rxd_2_int),
.qsfp1_rxc_2(qsfp1_rxc_2_int),
.qsfp1_tx_clk_3(qsfp1_tx_clk_3_int),
.qsfp1_tx_rst_3(qsfp1_tx_rst_3_int),
.qsfp1_txd_3(qsfp1_txd_3_int),
.qsfp1_txc_3(qsfp1_txc_3_int),
.qsfp1_rx_clk_3(qsfp1_rx_clk_3_int),
.qsfp1_rx_rst_3(qsfp1_rx_rst_3_int),
.qsfp1_rxd_3(qsfp1_rxd_3_int),
.qsfp1_rxc_3(qsfp1_rxc_3_int),
.qsfp1_tx_clk_4(qsfp1_tx_clk_4_int),
.qsfp1_tx_rst_4(qsfp1_tx_rst_4_int),
.qsfp1_txd_4(qsfp1_txd_4_int),
.qsfp1_txc_4(qsfp1_txc_4_int),
.qsfp1_rx_clk_4(qsfp1_rx_clk_4_int),
.qsfp1_rx_rst_4(qsfp1_rx_rst_4_int),
.qsfp1_rxd_4(qsfp1_rxd_4_int),
.qsfp1_rxc_4(qsfp1_rxc_4_int),
/*
* UART: 115200 bps, 8N1
*/
.uart_rxd(uart_rxd),
.uart_txd(uart_txd_int)
);
endmodule
`resetall

View File

@ -1,670 +0,0 @@
/*
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 TARGET = "XILINX"
)
(
/*
* Clock: 156.25MHz
* Synchronous reset
*/
input wire clk,
input wire rst,
/*
* GPIO
*/
input wire [3:0] sw,
output wire [2:0] led,
/*
* Ethernet: QSFP28
*/
input wire qsfp0_tx_clk_1,
input wire qsfp0_tx_rst_1,
output wire [63:0] qsfp0_txd_1,
output wire [7:0] qsfp0_txc_1,
input wire qsfp0_rx_clk_1,
input wire qsfp0_rx_rst_1,
input wire [63:0] qsfp0_rxd_1,
input wire [7:0] qsfp0_rxc_1,
input wire qsfp0_tx_clk_2,
input wire qsfp0_tx_rst_2,
output wire [63:0] qsfp0_txd_2,
output wire [7:0] qsfp0_txc_2,
input wire qsfp0_rx_clk_2,
input wire qsfp0_rx_rst_2,
input wire [63:0] qsfp0_rxd_2,
input wire [7:0] qsfp0_rxc_2,
input wire qsfp0_tx_clk_3,
input wire qsfp0_tx_rst_3,
output wire [63:0] qsfp0_txd_3,
output wire [7:0] qsfp0_txc_3,
input wire qsfp0_rx_clk_3,
input wire qsfp0_rx_rst_3,
input wire [63:0] qsfp0_rxd_3,
input wire [7:0] qsfp0_rxc_3,
input wire qsfp0_tx_clk_4,
input wire qsfp0_tx_rst_4,
output wire [63:0] qsfp0_txd_4,
output wire [7:0] qsfp0_txc_4,
input wire qsfp0_rx_clk_4,
input wire qsfp0_rx_rst_4,
input wire [63:0] qsfp0_rxd_4,
input wire [7:0] qsfp0_rxc_4,
input wire qsfp1_tx_clk_1,
input wire qsfp1_tx_rst_1,
output wire [63:0] qsfp1_txd_1,
output wire [7:0] qsfp1_txc_1,
input wire qsfp1_rx_clk_1,
input wire qsfp1_rx_rst_1,
input wire [63:0] qsfp1_rxd_1,
input wire [7:0] qsfp1_rxc_1,
input wire qsfp1_tx_clk_2,
input wire qsfp1_tx_rst_2,
output wire [63:0] qsfp1_txd_2,
output wire [7:0] qsfp1_txc_2,
input wire qsfp1_rx_clk_2,
input wire qsfp1_rx_rst_2,
input wire [63:0] qsfp1_rxd_2,
input wire [7:0] qsfp1_rxc_2,
input wire qsfp1_tx_clk_3,
input wire qsfp1_tx_rst_3,
output wire [63:0] qsfp1_txd_3,
output wire [7:0] qsfp1_txc_3,
input wire qsfp1_rx_clk_3,
input wire qsfp1_rx_rst_3,
input wire [63:0] qsfp1_rxd_3,
input wire [7:0] qsfp1_rxc_3,
input wire qsfp1_tx_clk_4,
input wire qsfp1_tx_rst_4,
output wire [63:0] qsfp1_txd_4,
output wire [7:0] qsfp1_txc_4,
input wire qsfp1_rx_clk_4,
input wire qsfp1_rx_rst_4,
input wire [63:0] qsfp1_rxd_4,
input wire [7:0] qsfp1_rxc_4,
/*
* UART: 115200 bps, 8N1
*/
output wire uart_rxd,
input wire uart_txd
);
// 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 led = sw;
assign led = led_reg;
assign qsfp0_txd_2 = 64'h0707070707070707;
assign qsfp0_txc_2 = 8'hff;
assign qsfp0_txd_3 = 64'h0707070707070707;
assign qsfp0_txc_3 = 8'hff;
assign qsfp0_txd_4 = 64'h0707070707070707;
assign qsfp0_txc_4 = 8'hff;
assign qsfp1_txd_1 = 64'h0707070707070707;
assign qsfp1_txc_1 = 8'hff;
assign qsfp1_txd_2 = 64'h0707070707070707;
assign qsfp1_txc_2 = 8'hff;
assign qsfp1_txd_3 = 64'h0707070707070707;
assign qsfp1_txc_3 = 8'hff;
assign qsfp1_txd_4 = 64'h0707070707070707;
assign qsfp1_txc_4 = 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(qsfp0_rx_clk_1),
.rx_rst(qsfp0_rx_rst_1),
.tx_clk(qsfp0_tx_clk_1),
.tx_rst(qsfp0_tx_rst_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(qsfp0_rxd_1),
.xgmii_rxc(qsfp0_rxc_1),
.xgmii_txd(qsfp0_txd_1),
.xgmii_txc(qsfp0_txc_1),
.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

@ -1,62 +0,0 @@
/*
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

@ -1,229 +0,0 @@
"""
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.qsfp_source = []
self.qsfp_sink = []
for x in range(2):
sources = []
sinks = []
for y in range(1, 5):
cocotb.start_soon(Clock(getattr(dut, f"qsfp{x}_rx_clk_{y}"), 2.56, units="ns").start())
source = XgmiiSource(getattr(dut, f"qsfp{x}_rxd_{y}"), getattr(dut, f"qsfp{x}_rxc_{y}"), getattr(dut, f"qsfp{x}_rx_clk_{y}"), getattr(dut, f"qsfp{x}_rx_rst_{y}"))
sources.append(source)
cocotb.start_soon(Clock(getattr(dut, f"qsfp{x}_tx_clk_{y}"), 2.56, units="ns").start())
sink = XgmiiSink(getattr(dut, f"qsfp{x}_txd_{y}"), getattr(dut, f"qsfp{x}_txc_{y}"), getattr(dut, f"qsfp{x}_tx_clk_{y}"), getattr(dut, f"qsfp{x}_tx_rst_{y}"))
sinks.append(sink)
self.qsfp_source.append(sources)
self.qsfp_sink.append(sinks)
dut.sw.setimmediatevalue(0)
async def init(self):
self.dut.rst.setimmediatevalue(0)
for x in range(2):
for y in range(1, 5):
getattr(self.dut, f"qsfp{x}_rx_rst_{y}").setimmediatevalue(0)
getattr(self.dut, f"qsfp{x}_tx_rst_{y}").setimmediatevalue(0)
for k in range(10):
await RisingEdge(self.dut.clk)
self.dut.rst.value = 1
for x in range(2):
for y in range(1, 5):
getattr(self.dut, f"qsfp{x}_rx_rst_{y}").value = 1
getattr(self.dut, f"qsfp{x}_tx_rst_{y}").value = 1
for k in range(10):
await RisingEdge(self.dut.clk)
self.dut.rst.value = 0
for x in range(2):
for y in range(1, 5):
getattr(self.dut, f"qsfp{x}_rx_rst_{y}").value = 0
getattr(self.dut, f"qsfp{x}_tx_rst_{y}").value = 0
@cocotb.test()
async def run_test(dut):
tb = TB(dut)
await tb.init()
tb.log.info("test UDP RX packet")
payload = bytes([x % 256 for x in range(256)])
eth = Ether(src='5a:51:52:53:54:55', dst='02:00:00:00:00:00')
ip = IP(src='192.168.1.100', dst='192.168.1.128')
udp = UDP(sport=5678, dport=1234)
test_pkt = eth / ip / udp / payload
test_frame = XgmiiFrame.from_payload(test_pkt.build())
await tb.qsfp_source[0][0].send(test_frame)
tb.log.info("receive ARP request")
rx_frame = await tb.qsfp_sink[0][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.qsfp_source[0][0].send(resp_frame)
tb.log.info("receive UDP packet")
rx_frame = await tb.qsfp_sink[0][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 = dut
verilog_sources = [
os.path.join(rtl_dir, f"{dut}.v"),
os.path.join(eth_rtl_dir, "eth_mac_10g_fifo.v"),
os.path.join(eth_rtl_dir, "eth_mac_10g.v"),
os.path.join(eth_rtl_dir, "axis_xgmii_rx_64.v"),
os.path.join(eth_rtl_dir, "axis_xgmii_tx_64.v"),
os.path.join(eth_rtl_dir, "lfsr.v"),
os.path.join(eth_rtl_dir, "eth_axis_rx.v"),
os.path.join(eth_rtl_dir, "eth_axis_tx.v"),
os.path.join(eth_rtl_dir, "udp_complete_64.v"),
os.path.join(eth_rtl_dir, "udp_checksum_gen_64.v"),
os.path.join(eth_rtl_dir, "udp_64.v"),
os.path.join(eth_rtl_dir, "udp_ip_rx_64.v"),
os.path.join(eth_rtl_dir, "udp_ip_tx_64.v"),
os.path.join(eth_rtl_dir, "ip_complete_64.v"),
os.path.join(eth_rtl_dir, "ip_64.v"),
os.path.join(eth_rtl_dir, "ip_eth_rx_64.v"),
os.path.join(eth_rtl_dir, "ip_eth_tx_64.v"),
os.path.join(eth_rtl_dir, "ip_arb_mux.v"),
os.path.join(eth_rtl_dir, "arp.v"),
os.path.join(eth_rtl_dir, "arp_cache.v"),
os.path.join(eth_rtl_dir, "arp_eth_rx.v"),
os.path.join(eth_rtl_dir, "arp_eth_tx.v"),
os.path.join(eth_rtl_dir, "eth_arb_mux.v"),
os.path.join(axis_rtl_dir, "arbiter.v"),
os.path.join(axis_rtl_dir, "priority_encoder.v"),
os.path.join(axis_rtl_dir, "axis_fifo.v"),
os.path.join(axis_rtl_dir, "axis_async_fifo.v"),
os.path.join(axis_rtl_dir, "axis_async_fifo_adapter.v"),
]
parameters = {}
# parameters['A'] = val
extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()}
sim_build = os.path.join(tests_dir, "sim_build",
request.node.name.replace('[', '-').replace(']', ''))
cocotb_test.simulator.run(
python_search=[tests_dir],
verilog_sources=verilog_sources,
toplevel=toplevel,
module=module,
parameters=parameters,
sim_build=sim_build,
extra_env=extra_env,
)

View File

@ -302,12 +302,6 @@ always @(posedge clk) begin
drift_ns_reg <= DRIFT_NS;
drift_fns_reg <= DRIFT_FNS;
drift_rate_reg <= DRIFT_RATE;
ts_inc_ns_reg <= 0;
ts_inc_fns_reg <= 0;
ts_inc_ns_delay_reg <= 0;
ts_inc_fns_delay_reg <= 0;
ts_inc_ns_ovf_reg <= 0;
ts_inc_fns_ovf_reg <= 0;
ts_96_s_reg <= 0;
ts_96_ns_reg <= 0;
ts_96_fns_reg <= 0;

View File

@ -100,9 +100,9 @@ localparam TIME_ERR_INT_WIDTH = NS_WIDTH+FNS_WIDTH;
localparam [30:0] NS_PER_S = 31'd1_000_000_000;
reg [NS_WIDTH+FNS_WIDTH-1:0] period_ns_reg = 0, period_ns_next;
reg [NS_WIDTH+FNS_WIDTH-1:0] period_ns_delay_reg = 0, period_ns_delay_next;
reg [31+FNS_WIDTH-1:0] period_ns_ovf_reg = 0, period_ns_ovf_next;
reg [NS_WIDTH+FNS_WIDTH-1:0] period_ns_reg = 0, period_ns_next = 0;
reg [NS_WIDTH+FNS_WIDTH-1:0] period_ns_delay_reg = 0, period_ns_delay_next = 0;
reg [31+FNS_WIDTH-1:0] period_ns_ovf_reg = 0, period_ns_ovf_next = 0;
reg [47:0] src_ts_s_capt_reg = 0;
reg [TS_NS_WIDTH+CMP_FNS_WIDTH-1:0] src_ts_ns_capt_reg = 0;
@ -115,10 +115,10 @@ reg [47:0] src_ts_s_sync_reg = 0;
reg [TS_NS_WIDTH+CMP_FNS_WIDTH-1:0] src_ts_ns_sync_reg = 0;
reg src_ts_step_sync_reg = 0;
reg [47:0] ts_s_reg = 0, ts_s_next;
reg [TS_NS_WIDTH+FNS_WIDTH-1:0] ts_ns_reg = 0, ts_ns_next;
reg [TS_NS_WIDTH+FNS_WIDTH-1:0] ts_ns_inc_reg = 0, ts_ns_inc_next;
reg [TS_NS_WIDTH+FNS_WIDTH+1-1:0] ts_ns_ovf_reg = {TS_NS_WIDTH+FNS_WIDTH+1{1'b1}}, ts_ns_ovf_next;
reg [47:0] ts_s_reg = 0, ts_s_next = 0;
reg [TS_NS_WIDTH+FNS_WIDTH-1:0] ts_ns_reg = 0, ts_ns_next = 0;
reg [TS_NS_WIDTH+FNS_WIDTH-1:0] ts_ns_inc_reg = 0, ts_ns_inc_next = 0;
reg [TS_NS_WIDTH+FNS_WIDTH+1-1:0] ts_ns_ovf_reg = {TS_NS_WIDTH+FNS_WIDTH+1{1'b1}}, ts_ns_ovf_next = 0;
reg ts_step_reg = 1'b0, ts_step_next;
@ -795,8 +795,6 @@ always @(posedge output_clk) begin
if (output_rst) begin
period_ns_reg <= 0;
period_ns_delay_reg <= 0;
period_ns_ovf_reg <= 0;
ts_s_reg <= 0;
ts_ns_reg <= 0;
ts_ns_inc_reg <= 0;

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,603 @@
/*
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
/*
* PTP time distribution PHC
*/
module ptp_td_phc #
(
parameter PERIOD_NS_NUM = 32,
parameter PERIOD_NS_DENOM = 5
)
(
input wire clk,
input wire rst,
/*
* ToD timestamp control
*/
input wire [47:0] input_ts_tod_s,
input wire [29:0] input_ts_tod_ns,
input wire input_ts_tod_valid,
output wire input_ts_tod_ready,
input wire [29:0] input_ts_tod_offset_ns,
input wire input_ts_tod_offset_valid,
output wire input_ts_tod_offset_ready,
/*
* Relative timestamp control
*/
input wire [47:0] input_ts_rel_ns,
input wire input_ts_rel_valid,
output wire input_ts_rel_ready,
input wire [31:0] input_ts_rel_offset_ns,
input wire input_ts_rel_offset_valid,
output wire input_ts_rel_offset_ready,
/*
* Fractional ns control
*/
input wire [31:0] input_ts_offset_fns,
input wire input_ts_offset_valid,
output wire input_ts_offset_ready,
/*
* Period control
*/
input wire [7:0] input_period_ns,
input wire [31:0] input_period_fns,
input wire input_period_valid,
output wire input_period_ready,
input wire [15:0] input_drift_num,
input wire [15:0] input_drift_denom,
input wire input_drift_valid,
output wire input_drift_ready,
/*
* Time distribution serial data output
*/
output wire ptp_td_sdo,
/*
* PPS output
*/
output wire output_pps,
output wire output_pps_str
);
localparam INC_NS_W = 9+8;
localparam FNS_W = 32;
localparam PERIOD_NS = PERIOD_NS_NUM / PERIOD_NS_DENOM;
localparam PERIOD_NS_REM = PERIOD_NS_NUM - PERIOD_NS*PERIOD_NS_DENOM;
localparam PERIOD_FNS = (PERIOD_NS_REM * {32'd1, {FNS_W{1'b0}}}) / PERIOD_NS_DENOM;
localparam PERIOD_FNS_REM = (PERIOD_NS_REM * {32'd1, {FNS_W{1'b0}}}) - PERIOD_FNS*PERIOD_NS_DENOM;
localparam [30:0] NS_PER_S = 31'd1_000_000_000;
reg [7:0] period_ns_reg = PERIOD_NS;
reg [FNS_W-1:0] period_fns_reg = PERIOD_FNS;
reg [15:0] drift_num_reg = PERIOD_FNS_REM;
reg [15:0] drift_denom_reg = PERIOD_NS_DENOM;
reg [15:0] drift_cnt_reg = 0;
reg [15:0] drift_cnt_d1_reg = 0;
reg drift_apply_reg = 1'b0;
reg [23:0] drift_acc_reg = 0;
reg [INC_NS_W-1:0] ts_inc_ns_reg = 0;
reg [FNS_W-1:0] ts_fns_reg = 0;
reg [32:0] ts_rel_ns_inc_reg = 0;
reg [47:0] ts_rel_ns_reg = 0;
reg ts_rel_updated_reg = 1'b0;
reg [47:0] ts_tod_s_reg = 0;
reg [29:0] ts_tod_ns_reg = 0;
reg ts_tod_updated_reg = 1'b0;
reg [31:0] ts_tod_offset_ns_reg = 0;
reg [47:0] ts_tod_alt_s_reg = 0;
reg [31:0] ts_tod_alt_offset_ns_reg = 0;
reg [7:0] td_update_cnt_reg = 0;
reg td_update_reg = 1'b0;
reg [1:0] td_msg_i_reg = 0;
reg input_ts_tod_ready_reg = 1'b0;
reg input_ts_tod_offset_ready_reg = 1'b0;
reg input_ts_rel_ready_reg = 1'b0;
reg input_ts_rel_offset_ready_reg = 1'b0;
reg input_ts_offset_ready_reg = 1'b0;
reg [17*14-1:0] td_shift_reg = {17*14{1'b1}};
reg [15:0] pps_gen_fns_reg = 0;
reg [9:0] pps_gen_ns_inc_reg = 0;
reg [30:0] pps_gen_ns_reg = 31'h40000000;
reg [9:0] pps_delay_reg = 0;
reg pps_reg = 0;
reg pps_str_reg = 0;
reg [3:0] update_state_reg = 0;
reg [47:0] adder_a_reg = 0;
reg [47:0] adder_b_reg = 0;
reg adder_cin_reg = 0;
wire [47:0] adder_sum;
wire adder_cout;
assign {adder_cout, adder_sum} = adder_a_reg + adder_b_reg + adder_cin_reg;
assign input_ts_tod_ready = input_ts_tod_ready_reg;
assign input_ts_tod_offset_ready = input_ts_tod_offset_ready_reg;
assign input_ts_rel_ready = input_ts_rel_ready_reg;
assign input_ts_rel_offset_ready = input_ts_rel_offset_ready_reg;
assign input_ts_offset_ready = input_ts_offset_ready_reg;
assign input_period_ready = 1'b1;
assign input_drift_ready = 1'b1;
assign output_pps = pps_reg;
assign output_pps_str = pps_str_reg;
assign ptp_td_sdo = td_shift_reg[0];
always @(posedge clk) begin
drift_apply_reg <= 1'b0;
input_ts_tod_ready_reg <= 1'b0;
input_ts_tod_offset_ready_reg <= 1'b0;
input_ts_rel_ready_reg <= 1'b0;
input_ts_rel_offset_ready_reg <= 1'b0;
input_ts_offset_ready_reg <= 1'b0;
// update and message generation cadence
{td_update_reg, td_update_cnt_reg} <= td_update_cnt_reg + 1;
// latch drift setting
if (input_drift_valid) begin
drift_num_reg <= input_drift_num;
drift_denom_reg <= input_drift_denom;
end
// drift
if (drift_denom_reg) begin
if (drift_cnt_reg == 0) begin
drift_cnt_reg <= drift_denom_reg - 1;
drift_apply_reg <= 1'b1;
end else begin
drift_cnt_reg <= drift_cnt_reg - 1;
end
end else begin
drift_cnt_reg <= 0;
end
drift_cnt_d1_reg <= drift_cnt_reg;
// drift accumulation
if (drift_apply_reg) begin
drift_acc_reg <= drift_acc_reg + drift_num_reg;
end
// latch period setting
if (input_period_valid) begin
period_ns_reg <= input_period_ns;
period_fns_reg <= input_period_fns;
end
// PPS generation
if (td_update_reg) begin
{pps_gen_ns_inc_reg, pps_gen_fns_reg} <= {period_ns_reg, period_fns_reg[31:16]} + ts_fns_reg[31:16];
end else begin
{pps_gen_ns_inc_reg, pps_gen_fns_reg} <= {period_ns_reg, period_fns_reg[31:16]} + pps_gen_fns_reg;
end
pps_gen_ns_reg <= pps_gen_ns_reg + pps_gen_ns_inc_reg;
if (!pps_gen_ns_reg[30]) begin
// pps_delay_reg <= 14*17 + 32 + 1;
pps_delay_reg <= 14*17 + 32 + 248;
pps_gen_ns_reg[30] <= 1'b1;
end
pps_reg <= 1'b0;
if (ts_tod_ns_reg[29]) begin
pps_str_reg <= 1'b0;
end
if (pps_delay_reg) begin
pps_delay_reg <= pps_delay_reg - 1;
if (pps_delay_reg == 1) begin
pps_reg <= 1'b1;
pps_str_reg <= 1'b1;
end
end
// update state machine
case (update_state_reg)
0: begin
// idle
// set relative timestamp
if (input_ts_rel_valid) begin
ts_rel_ns_reg <= input_ts_rel_ns;
input_ts_rel_ready_reg <= 1'b1;
ts_rel_updated_reg <= 1'b1;
end
// set ToD timestamp
if (input_ts_tod_valid) begin
ts_tod_s_reg <= input_ts_tod_s;
ts_tod_ns_reg <= input_ts_tod_ns;
input_ts_tod_ready_reg <= 1'b1;
ts_tod_updated_reg <= 1'b1;
end
// compute period 1 - add drift and requested offset
if (drift_apply_reg) begin
adder_a_reg <= drift_acc_reg + drift_num_reg;
end else begin
adder_a_reg <= drift_acc_reg;
end
adder_b_reg <= input_ts_offset_valid ? $signed(input_ts_offset_fns) : 0;
adder_cin_reg <= 0;
if (td_update_reg) begin
drift_acc_reg <= 0;
input_ts_offset_ready_reg <= input_ts_offset_valid;
update_state_reg <= 1;
end else begin
update_state_reg <= 0;
end
end
1: begin
// compute period 2 - add drift and offset to period
adder_a_reg <= adder_sum;
adder_b_reg <= {period_ns_reg, period_fns_reg, 8'd0};
adder_cin_reg <= 0;
update_state_reg <= 2;
end
2: begin
// compute next fns
adder_a_reg <= adder_sum;
adder_b_reg <= ts_fns_reg;
adder_cin_reg <= 0;
update_state_reg <= 3;
end
3: begin
// store fns; compute relative timestamp 1 - add previous value and offset
{ts_inc_ns_reg, ts_fns_reg} <= {adder_cout, adder_sum};
adder_a_reg <= ts_rel_ns_reg;
adder_b_reg <= 0;
adder_cin_reg <= 0;
// offset relative timestamp if requested
if (input_ts_rel_offset_valid) begin
adder_b_reg <= $signed(input_ts_rel_offset_ns);
input_ts_rel_offset_ready_reg <= 1'b1;
ts_rel_updated_reg <= 1'b1;
end
update_state_reg <= 4;
end
4: begin
// compute relative timestamp 2 - add increment
adder_a_reg <= adder_sum;
adder_b_reg <= ts_inc_ns_reg;
adder_cin_reg <= 0;
update_state_reg <= 5;
end
5: begin
// store relative timestamp; compute ToD timestamp 1 - add previous value and increment
ts_rel_ns_reg <= adder_sum;
adder_a_reg <= ts_tod_ns_reg;
adder_b_reg <= ts_inc_ns_reg;
adder_cin_reg <= 0;
update_state_reg <= 6;
end
6: begin
// compute ToD timestamp 2 - add offset
adder_a_reg <= adder_sum;
adder_b_reg <= 0;
adder_cin_reg <= 0;
// offset ToD timestamp if requested
if (input_ts_tod_offset_valid) begin
adder_b_reg <= $signed(input_ts_tod_offset_ns);
input_ts_tod_offset_ready_reg <= 1'b1;
ts_tod_updated_reg <= 1'b1;
end
update_state_reg <= 7;
end
7: begin
// compute ToD timestamp 2 - check for underflow/overflow
ts_tod_ns_reg <= adder_sum;
if (adder_b_reg[47] && !adder_cout) begin
// borrowed; add 1 billion
adder_a_reg <= adder_sum;
adder_b_reg <= NS_PER_S;
adder_cin_reg <= 0;
update_state_reg <= 8;
end else begin
// did not borrow; subtract 1 billion to check for overflow
adder_a_reg <= adder_sum;
adder_b_reg <= -NS_PER_S;
adder_cin_reg <= 0;
update_state_reg <= 9;
end
end
8: begin
// seconds decrement
ts_tod_ns_reg <= adder_sum;
pps_gen_ns_reg[30] <= 1'b1;
adder_a_reg <= ts_tod_s_reg;
adder_b_reg <= -1;
adder_cin_reg <= 0;
update_state_reg <= 10;
end
9: begin
// seconds increment
pps_gen_ns_reg <= adder_sum;
if (!adder_cout) begin
// borrowed; leave seconds alone
adder_a_reg <= ts_tod_s_reg;
adder_b_reg <= 0;
adder_cin_reg <= 0;
end else begin
// did not borrow; decrement seconds
ts_tod_ns_reg <= adder_sum;
adder_a_reg <= ts_tod_s_reg;
adder_b_reg <= 1;
adder_cin_reg <= 0;
end
update_state_reg <= 10;
end
10: begin
// store seconds; compute offset
ts_tod_s_reg <= adder_sum;
if (adder_sum == ts_tod_alt_s_reg) begin
// store previous offset as alternate
ts_tod_alt_s_reg <= ts_tod_s_reg;
ts_tod_alt_offset_ns_reg <= ts_tod_offset_ns_reg;
end
adder_a_reg <= ts_tod_ns_reg;
adder_b_reg <= ~ts_rel_ns_reg;
adder_cin_reg <= 1;
update_state_reg <= 11;
end
11: begin
// store offset
ts_tod_offset_ns_reg <= adder_sum;
adder_a_reg <= adder_sum;
adder_b_reg <= -NS_PER_S;
adder_cin_reg <= 0;
if (ts_tod_ns_reg[29]) begin
// latter half of second; compute offset for next second
adder_b_reg <= -NS_PER_S;
update_state_reg <= 12;
end else begin
// former half of second; compute offset for previous second
adder_b_reg <= NS_PER_S;
update_state_reg <= 14;
end
end
12: begin
// store alternate offset for next second
ts_tod_alt_offset_ns_reg <= adder_sum;
adder_a_reg <= ts_tod_s_reg;
adder_b_reg <= 1;
adder_cin_reg <= 0;
update_state_reg <= 13;
end
13: begin
// store alternate second for next second
ts_tod_alt_s_reg <= adder_sum;
update_state_reg <= 0;
end
14: begin
// store alternate offset for previous second
ts_tod_alt_offset_ns_reg <= adder_sum;
adder_a_reg <= ts_tod_s_reg;
adder_b_reg <= -1;
adder_cin_reg <= 0;
update_state_reg <= 15;
end
15: begin
// store alternate second for previous second
ts_tod_alt_s_reg <= adder_sum;
update_state_reg <= 0;
end
default: begin
// invalid state; return to idle
update_state_reg <= 0;
end
endcase
// time distribution message generation
td_shift_reg <= {1'b1, td_shift_reg} >> 1;
if (td_update_reg) begin
// word 0: control
td_shift_reg[17*0+0 +: 1] <= 1'b0;
td_shift_reg[17*0+1 +: 16] <= 0;
td_shift_reg[17*0+1+0 +: 4] <= td_msg_i_reg;
td_shift_reg[17*0+1+8 +: 1] <= ts_rel_updated_reg;
td_shift_reg[17*0+1+9 +: 1] <= ts_tod_s_reg[0];
ts_rel_updated_reg <= 1'b0;
case (td_msg_i_reg)
2'd0: begin
// msg 0 word 1: current ToD ns 15:0
td_shift_reg[17*1+0 +: 1] <= 1'b0;
td_shift_reg[17*1+1 +: 16] <= ts_tod_ns_reg[15:0];
// msg 0 word 2: current ToD ns 29:16
td_shift_reg[17*2+0 +: 1] <= 1'b0;
td_shift_reg[17*2+1+0 +: 15] <= ts_tod_ns_reg[29:16];
td_shift_reg[17*2+1+15 +: 1] <= ts_tod_updated_reg;
ts_tod_updated_reg <= 1'b0;
// msg 0 word 3: current ToD seconds 15:0
td_shift_reg[17*3+0 +: 1] <= 1'b0;
td_shift_reg[17*3+1 +: 16] <= ts_tod_s_reg[15:0];
// msg 0 word 4: current ToD seconds 31:16
td_shift_reg[17*4+0 +: 1] <= 1'b0;
td_shift_reg[17*4+1 +: 16] <= ts_tod_s_reg[31:16];
// msg 0 word 5: current ToD seconds 47:32
td_shift_reg[17*5+0 +: 1] <= 1'b0;
td_shift_reg[17*5+1 +: 16] <= ts_tod_s_reg[47:32];
td_msg_i_reg <= 2'd1;
end
2'd1: begin
// msg 1 word 1: current ToD ns offset 15:0
td_shift_reg[17*1+0 +: 1] <= 1'b0;
td_shift_reg[17*1+1 +: 16] <= ts_tod_offset_ns_reg[15:0];
// msg 1 word 2: current ToD ns offset 31:16
td_shift_reg[17*2+0 +: 1] <= 1'b0;
td_shift_reg[17*2+1 +: 16] <= ts_tod_offset_ns_reg[31:16];
// msg 1 word 3: drift num
td_shift_reg[17*3+0 +: 1] <= 1'b0;
td_shift_reg[17*3+1 +: 16] <= drift_num_reg;
// msg 1 word 4: drift denom
td_shift_reg[17*4+0 +: 1] <= 1'b0;
td_shift_reg[17*4+1 +: 16] <= drift_denom_reg;
// msg 1 word 5: drift state
td_shift_reg[17*5+0 +: 1] <= 1'b0;
td_shift_reg[17*5+1 +: 16] <= drift_cnt_d1_reg;
td_msg_i_reg <= 2'd2;
end
2'd2: begin
// msg 2 word 1: alternate ToD ns offset 15:0
td_shift_reg[17*1+0 +: 1] <= 1'b0;
td_shift_reg[17*1+1 +: 16] <= ts_tod_alt_offset_ns_reg[15:0];
// msg 2 word 2: alternate ToD ns offset 31:16
td_shift_reg[17*2+0 +: 1] <= 1'b0;
td_shift_reg[17*2+1 +: 16] <= ts_tod_alt_offset_ns_reg[31:16];
// msg 2 word 3: alternate ToD seconds 15:0
td_shift_reg[17*3+0 +: 1] <= 1'b0;
td_shift_reg[17*3+1 +: 16] <= ts_tod_alt_s_reg[15:0];
// msg 2 word 4: alternate ToD seconds 31:16
td_shift_reg[17*4+0 +: 1] <= 1'b0;
td_shift_reg[17*4+1 +: 16] <= ts_tod_alt_s_reg[31:16];
// msg 2 word 5: alternate ToD seconds 47:32
td_shift_reg[17*5+0 +: 1] <= 1'b0;
td_shift_reg[17*5+1 +: 16] <= ts_tod_alt_s_reg[47:32];
td_msg_i_reg <= 2'd0;
end
endcase
// word 6: current fns 15:0
td_shift_reg[17*6+0 +: 1] <= 1'b0;
td_shift_reg[17*6+1 +: 16] <= ts_fns_reg[15:0];
// word 7: current fns 31:16
td_shift_reg[17*7+0 +: 1] <= 1'b0;
td_shift_reg[17*7+1 +: 16] <= ts_fns_reg[31:16];
// word 8: current ns 15:0
td_shift_reg[17*8+0 +: 1] <= 1'b0;
td_shift_reg[17*8+1 +: 16] <= ts_rel_ns_reg[15:0];
// word 9: current ns 31:16
td_shift_reg[17*9+0 +: 1] <= 1'b0;
td_shift_reg[17*9+1 +: 16] <= ts_rel_ns_reg[31:16];
// word 10: current ns 47:32
td_shift_reg[17*10+0 +: 1] <= 1'b0;
td_shift_reg[17*10+1 +: 16] <= ts_rel_ns_reg[47:32];
// word 11: current phase increment fns 15:0
td_shift_reg[17*11+0 +: 1] <= 1'b0;
td_shift_reg[17*11+1 +: 16] <= period_fns_reg[15:0];
// word 12: current phase increment fns 31:16
td_shift_reg[17*12+0 +: 1] <= 1'b0;
td_shift_reg[17*12+1 +: 16] <= period_fns_reg[31:16];
// word 13: current phase increment ns 7:0 + crc
td_shift_reg[17*13+0 +: 1] <= 1'b0;
td_shift_reg[17*13+1 +: 16] <= period_ns_reg[7:0];
end
if (rst) begin
period_ns_reg <= PERIOD_NS;
period_fns_reg <= PERIOD_FNS;
drift_num_reg <= PERIOD_FNS_REM;
drift_denom_reg <= PERIOD_NS_DENOM;
drift_cnt_reg <= 0;
drift_acc_reg <= 0;
ts_fns_reg <= 0;
ts_rel_ns_reg <= 0;
ts_rel_updated_reg <= 0;
ts_tod_s_reg <= 0;
ts_tod_ns_reg <= 0;
ts_tod_updated_reg <= 0;
pps_gen_ns_reg[30] <= 1'b1;
pps_delay_reg <= 0;
pps_reg <= 0;
pps_str_reg <= 0;
td_update_cnt_reg <= 0;
td_update_reg <= 1'b0;
td_msg_i_reg <= 0;
td_shift_reg <= {17*14{1'b1}};
end
end
endmodule
`resetall

View File

@ -0,0 +1,104 @@
# Copyright (c) 2019-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.
# PTP time distribution leaf module
foreach inst [get_cells -hier -filter {(ORIG_REF_NAME == ptp_td_leaf || REF_NAME == ptp_td_leaf)}] {
puts "Inserting timing constraints for ptp_td_leaf instance $inst"
# get clock periods
set input_clk [get_clocks -of_objects [get_pins "$inst/src_sync_reg_reg/C"]]
set output_clk [get_clocks -of_objects [get_pins "$inst/dst_sync_reg_reg/C"]]
set input_clk_period [if {[llength $input_clk]} {get_property -min PERIOD $input_clk} {expr 1.0}]
set output_clk_period [if {[llength $output_clk]} {get_property -min PERIOD $output_clk} {expr 1.0}]
# TD data sync
set_property ASYNC_REG TRUE [get_cells -hier -regexp ".*/dst_td_(tdata|tid)_reg_reg(\\\[\\d+\\\])?" -filter "PARENT == $inst"]
set_max_delay -from [get_cells "$inst/td_tdata_reg_reg[*]"] -to [get_cells "$inst/dst_td_tdata_reg_reg[*]"] -datapath_only $output_clk_period
set_bus_skew -from [get_cells "$inst/td_tdata_reg_reg[*]"] -to [get_cells "$inst/dst_td_tdata_reg_reg[*]"] $input_clk_period
set_max_delay -from [get_cells "$inst/td_tid_reg_reg[*]"] -to [get_cells "$inst/dst_td_tid_reg_reg[*]"] -datapath_only $output_clk_period
set_bus_skew -from [get_cells "$inst/td_tid_reg_reg[*]"] -to [get_cells "$inst/dst_td_tid_reg_reg[*]"] $input_clk_period
set sync_ffs [get_cells -quiet -hier -regexp ".*/td_sync_sync\[12\]_reg_reg" -filter "PARENT == $inst"]
if {[llength $sync_ffs]} {
set_property ASYNC_REG TRUE $sync_ffs
set_max_delay -from [get_cells "$inst/td_sync_reg_reg"] -to [get_cells "$inst/td_sync_sync1_reg_reg"] -datapath_only $input_clk_period
}
# timestamp sync
set_property ASYNC_REG TRUE [get_cells -hier -regexp ".*/src_ns_sync_reg_reg(\\\[\\d+\\\])?" -filter "PARENT == $inst"]
set_max_delay -from [get_cells "$inst/src_ns_reg_reg[*]"] -to [get_cells "$inst/src_ns_sync_reg_reg[*]"] -datapath_only $output_clk_period
set_bus_skew -from [get_cells "$inst/src_ns_reg_reg[*]"] -to [get_cells "$inst/src_ns_sync_reg_reg[*]"] $input_clk_period
# sample clock
set sync_ffs [get_cells -quiet -hier -regexp ".*/src_sync_sample_sync\[12\]_reg_reg" -filter "PARENT == $inst"]
if {[llength $sync_ffs]} {
set_property ASYNC_REG TRUE $sync_ffs
set_max_delay -from [get_cells "$inst/src_sync_reg_reg"] -to [get_cells "$inst/src_sync_sample_sync1_reg_reg"] -datapath_only $input_clk_period
}
set sync_ffs [get_cells -quiet -hier -regexp ".*/dst_sync_sample_sync\[12\]_reg_reg" -filter "PARENT == $inst"]
if {[llength $sync_ffs]} {
set_property ASYNC_REG TRUE $sync_ffs
set_max_delay -from [get_cells "$inst/dst_sync_reg_reg"] -to [get_cells "$inst/dst_sync_sample_sync1_reg_reg"] -datapath_only $output_clk_period
}
# sample update sync
set sync_ffs [get_cells -quiet -hier -regexp ".*/sample_update_sync\[123\]_reg_reg" -filter "PARENT == $inst"]
if {[llength $sync_ffs]} {
set_property ASYNC_REG TRUE $sync_ffs
set src_clk [get_clocks -of_objects [get_pins "$inst/sample_update_reg_reg/C"]]
set src_clk_period [if {[llength $src_clk]} {get_property -min PERIOD $src_clk} {expr 1.0}]
set_max_delay -from [get_cells "$inst/sample_update_reg_reg"] -to [get_cells "$inst/sample_update_sync1_reg_reg"] -datapath_only $src_clk_period
set_max_delay -from [get_cells "$inst/sample_acc_out_reg_reg[*]"] -to [get_cells $inst/sample_acc_sync_reg_reg[*]] -datapath_only $src_clk_period
set_bus_skew -from [get_cells "$inst/sample_acc_out_reg_reg[*]"] -to [get_cells $inst/sample_acc_sync_reg_reg[*]] $output_clk_period
}
# timestamp transfer sync
set sync_ffs [get_cells -quiet -hier -regexp ".*/src_sync_sync\[12\]_reg_reg" -filter "PARENT == $inst"]
if {[llength $sync_ffs]} {
set_property ASYNC_REG TRUE $sync_ffs
set_max_delay -from [get_cells "$inst/src_sync_reg_reg"] -to [get_cells "$inst/src_sync_sync1_reg_reg"] -datapath_only $input_clk_period
}
set sync_ffs [get_cells -quiet -hier -regexp ".*/src_marker_sync\[12\]_reg_reg" -filter "PARENT == $inst"]
if {[llength $sync_ffs]} {
set_property ASYNC_REG TRUE $sync_ffs
set_max_delay -from [get_cells "$inst/src_marker_reg_reg"] -to [get_cells "$inst/src_marker_sync1_reg_reg"] -datapath_only $input_clk_period
}
}

View File

@ -62,7 +62,7 @@ class TB:
self.source = BaseRSerdesSource(dut.encoded_rx_data, dut.encoded_rx_hdr, dut.clk, scramble=False)
self.sink = AxiStreamSink(AxiStreamBus.from_prefix(dut, "m_axis"), dut.clk, dut.rst)
self.ptp_clock = PtpClockSimTime(ts_64=dut.ptp_ts, clock=dut.clk)
self.ptp_clock = PtpClockSimTime(ts_tod=dut.ptp_ts, clock=dut.clk)
dut.cfg_rx_enable.setimmediatevalue(0)

View File

@ -70,7 +70,7 @@ class TB:
self.source = AxiStreamSource(AxiStreamBus.from_prefix(dut, "s_axis"), dut.clk, dut.rst)
self.sink = BaseRSerdesSink(dut.encoded_tx_data, dut.encoded_tx_hdr, dut.clk, scramble=False)
self.ptp_clock = PtpClockSimTime(ts_64=dut.ptp_ts, clock=dut.clk)
self.ptp_clock = PtpClockSimTime(ts_tod=dut.ptp_ts, clock=dut.clk)
self.ptp_ts_sink = PtpTsSink(PtpTsBus.from_prefix(dut, "m_axis_ptp"), dut.clk, dut.rst)
dut.cfg_ifg.setimmediatevalue(0)

View File

@ -55,7 +55,7 @@ class TB:
dut.clk, dut.rst, dut.clk_enable, dut.mii_select)
self.sink = AxiStreamSink(AxiStreamBus.from_prefix(dut, "m_axis"), dut.clk, dut.rst)
self.ptp_clock = PtpClockSimTime(ts_64=dut.ptp_ts, clock=dut.clk)
self.ptp_clock = PtpClockSimTime(ts_tod=dut.ptp_ts, clock=dut.clk)
dut.clk_enable.setimmediatevalue(1)
dut.mii_select.setimmediatevalue(0)

View File

@ -62,7 +62,7 @@ class TB:
self.sink = GmiiSink(dut.gmii_txd, dut.gmii_tx_er, dut.gmii_tx_en,
dut.clk, dut.rst, dut.clk_enable, dut.mii_select)
self.ptp_clock = PtpClockSimTime(ts_64=dut.ptp_ts, clock=dut.clk)
self.ptp_clock = PtpClockSimTime(ts_tod=dut.ptp_ts, clock=dut.clk)
self.ptp_ts_sink = PtpTsSink(PtpTsBus.from_prefix(dut, "m_axis_ptp"), dut.clk, dut.rst)
dut.clk_enable.setimmediatevalue(1)

View File

@ -51,7 +51,7 @@ class TB:
self.source = XgmiiSource(dut.xgmii_rxd, dut.xgmii_rxc, dut.clk, dut.rst)
self.sink = AxiStreamSink(AxiStreamBus.from_prefix(dut, "m_axis"), dut.clk, dut.rst)
self.ptp_clock = PtpClockSimTime(ts_64=dut.ptp_ts, clock=dut.clk)
self.ptp_clock = PtpClockSimTime(ts_tod=dut.ptp_ts, clock=dut.clk)
dut.cfg_rx_enable.setimmediatevalue(0)

View File

@ -51,7 +51,7 @@ class TB:
self.source = XgmiiSource(dut.xgmii_rxd, dut.xgmii_rxc, dut.clk, dut.rst)
self.sink = AxiStreamSink(AxiStreamBus.from_prefix(dut, "m_axis"), dut.clk, dut.rst)
self.ptp_clock = PtpClockSimTime(ts_64=dut.ptp_ts, clock=dut.clk)
self.ptp_clock = PtpClockSimTime(ts_tod=dut.ptp_ts, clock=dut.clk)
dut.cfg_rx_enable.setimmediatevalue(0)

View File

@ -59,7 +59,7 @@ class TB:
self.source = AxiStreamSource(AxiStreamBus.from_prefix(dut, "s_axis"), dut.clk, dut.rst)
self.sink = XgmiiSink(dut.xgmii_txd, dut.xgmii_txc, dut.clk, dut.rst)
self.ptp_clock = PtpClockSimTime(ts_64=dut.ptp_ts, clock=dut.clk)
self.ptp_clock = PtpClockSimTime(ts_tod=dut.ptp_ts, clock=dut.clk)
self.ptp_ts_sink = PtpTsSink(PtpTsBus.from_prefix(dut, "m_axis_ptp"), dut.clk, dut.rst)
dut.cfg_ifg.setimmediatevalue(0)

View File

@ -59,7 +59,7 @@ class TB:
self.source = AxiStreamSource(AxiStreamBus.from_prefix(dut, "s_axis"), dut.clk, dut.rst)
self.sink = XgmiiSink(dut.xgmii_txd, dut.xgmii_txc, dut.clk, dut.rst)
self.ptp_clock = PtpClockSimTime(ts_64=dut.ptp_ts, clock=dut.clk)
self.ptp_clock = PtpClockSimTime(ts_tod=dut.ptp_ts, clock=dut.clk)
self.ptp_ts_sink = PtpTsSink(PtpTsBus.from_prefix(dut, "m_axis_ptp"), dut.clk, dut.rst)
dut.cfg_ifg.setimmediatevalue(0)

View File

@ -71,8 +71,8 @@ class TB:
self.axis_source = AxiStreamSource(AxiStreamBus.from_prefix(dut, "tx_axis"), dut.tx_clk, dut.tx_rst)
self.axis_sink = AxiStreamSink(AxiStreamBus.from_prefix(dut, "rx_axis"), dut.rx_clk, dut.rx_rst)
self.rx_ptp_clock = PtpClockSimTime(ts_64=dut.rx_ptp_ts, clock=dut.rx_clk)
self.tx_ptp_clock = PtpClockSimTime(ts_64=dut.tx_ptp_ts, clock=dut.tx_clk)
self.rx_ptp_clock = PtpClockSimTime(ts_tod=dut.rx_ptp_ts, clock=dut.rx_clk)
self.tx_ptp_clock = PtpClockSimTime(ts_tod=dut.tx_ptp_ts, clock=dut.tx_clk)
self.tx_ptp_ts_sink = PtpTsSink(PtpTsBus.from_prefix(dut, "tx_axis_ptp"), dut.tx_clk, dut.tx_rst)
dut.tx_lfc_req.setimmediatevalue(0)

View File

@ -70,7 +70,7 @@ class TB:
self.axis_source = AxiStreamSource(AxiStreamBus.from_prefix(dut, "tx_axis"), dut.logic_clk, dut.logic_rst)
self.axis_sink = AxiStreamSink(AxiStreamBus.from_prefix(dut, "rx_axis"), dut.logic_clk, dut.logic_rst)
self.ptp_clock = PtpClockSimTime(ts_64=dut.ptp_ts_96, clock=dut.logic_clk)
self.ptp_clock = PtpClockSimTime(ts_tod=dut.ptp_ts_96, clock=dut.logic_clk)
self.tx_ptp_ts_sink = PtpTsSink(PtpTsBus.from_prefix(dut, "tx_axis_ptp"), dut.tx_clk, dut.tx_rst)
dut.ptp_ts_step.setimmediatevalue(0)

View File

@ -73,8 +73,8 @@ class TB:
self.axis_source = AxiStreamSource(AxiStreamBus.from_prefix(dut, "tx_axis"), dut.tx_clk, dut.tx_rst)
self.axis_sink = AxiStreamSink(AxiStreamBus.from_prefix(dut, "rx_axis"), dut.rx_clk, dut.rx_rst)
self.rx_ptp_clock = PtpClockSimTime(ts_64=dut.rx_ptp_ts, clock=dut.rx_clk)
self.tx_ptp_clock = PtpClockSimTime(ts_64=dut.tx_ptp_ts, clock=dut.tx_clk)
self.rx_ptp_clock = PtpClockSimTime(ts_tod=dut.rx_ptp_ts, clock=dut.rx_clk)
self.tx_ptp_clock = PtpClockSimTime(ts_tod=dut.tx_ptp_ts, clock=dut.tx_clk)
self.tx_ptp_ts_sink = PtpTsSink(PtpTsBus.from_prefix(dut, "tx_axis_ptp"), dut.tx_clk, dut.tx_rst)
dut.tx_lfc_req.setimmediatevalue(0)

View File

@ -79,8 +79,8 @@ class TB:
self.axis_source = AxiStreamSource(AxiStreamBus.from_prefix(dut, "tx_axis"), dut.tx_clk, dut.tx_rst)
self.axis_sink = AxiStreamSink(AxiStreamBus.from_prefix(dut, "rx_axis"), dut.rx_clk, dut.rx_rst)
self.rx_ptp_clock = PtpClockSimTime(ts_64=dut.rx_ptp_ts, clock=dut.rx_clk)
self.tx_ptp_clock = PtpClockSimTime(ts_64=dut.tx_ptp_ts, clock=dut.tx_clk)
self.rx_ptp_clock = PtpClockSimTime(ts_tod=dut.rx_ptp_ts, clock=dut.rx_clk)
self.tx_ptp_clock = PtpClockSimTime(ts_tod=dut.tx_ptp_ts, clock=dut.tx_clk)
self.tx_ptp_ts_sink = PtpTsSink(PtpTsBus.from_prefix(dut, "tx_axis_ptp"), dut.tx_clk, dut.tx_rst)
dut.cfg_ifg.setimmediatevalue(0)

View File

@ -81,7 +81,7 @@ class TB:
self.axis_source = AxiStreamSource(AxiStreamBus.from_prefix(dut, "tx_axis"), dut.logic_clk, dut.logic_rst)
self.axis_sink = AxiStreamSink(AxiStreamBus.from_prefix(dut, "rx_axis"), dut.logic_clk, dut.logic_rst)
self.ptp_clock = PtpClockSimTime(ts_64=dut.ptp_ts_96, clock=dut.logic_clk)
self.ptp_clock = PtpClockSimTime(ts_tod=dut.ptp_ts_96, clock=dut.logic_clk)
self.tx_ptp_ts_sink = PtpTsSink(PtpTsBus.from_prefix(dut, "tx_axis_ptp"), dut.tx_clk, dut.tx_rst)
dut.ptp_ts_step.setimmediatevalue(0)

View File

@ -49,7 +49,7 @@ class TB:
if len(dut.input_ts) == 64:
self.ptp_clock = PtpClock(
ts_64=dut.input_ts,
ts_rel=dut.input_ts,
ts_step=dut.input_ts_step,
clock=dut.input_clk,
reset=dut.input_rst,
@ -57,7 +57,7 @@ class TB:
)
else:
self.ptp_clock = PtpClock(
ts_96=dut.input_ts,
ts_tod=dut.input_ts,
ts_step=dut.input_ts_step,
clock=dut.input_clk,
reset=dut.input_rst,

View File

@ -45,7 +45,7 @@ class TB:
cocotb.start_soon(Clock(dut.clk, 6.4, units="ns").start())
self.ptp_clock = PtpClock(
ts_96=dut.input_ts_96,
ts_tod=dut.input_ts_96,
ts_step=dut.input_ts_step,
clock=dut.clk,
reset=dut.rst,

604
fpga/lib/eth/tb/ptp_td.py Normal file
View File

@ -0,0 +1,604 @@
"""
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.
"""
import logging
from decimal import Decimal, Context
from fractions import Fraction
import cocotb
from cocotb.triggers import RisingEdge, Event
from cocotb.utils import get_sim_time
from cocotbext.eth.reset import Reset
class PtpTdSource(Reset):
def __init__(self,
data=None,
clock=None,
reset=None,
reset_active_level=True,
period_ns=6.4,
td_delay=32,
*args, **kwargs):
self.log = logging.getLogger(f"cocotb.{data._path}")
self.data = data
self.clock = clock
self.reset = reset
self.log.info("PTP time distribution source")
self.log.info("Copyright (c) 2023 Alex Forencich")
self.log.info("https://github.com/alexforencich/verilog-ethernet")
super().__init__(*args, **kwargs)
self.ctx = Context(prec=60)
self.period_ns = 0
self.period_fns = 0
self.drift_num = 0
self.drift_denom = 0
self.drift_cnt = 0
self.set_period_ns(period_ns)
self.ts_fns = 0
self.ts_rel_ns = 0
self.ts_rel_updated = False
self.ts_tod_s = 0
self.ts_tod_ns = 0
self.ts_tod_updated = False
self.ts_tod_offset_ns = 0
self.ts_tod_alt_s = 0
self.ts_tod_alt_offset_ns = 0
self.td_delay = td_delay
self.timestamp_delay = [(0, 0, 0, 0)]
self.data.setimmediatevalue(1)
self.pps = Event()
self._run_cr = None
self._init_reset(reset, reset_active_level)
def set_period(self, ns, fns):
self.period_ns = int(ns)
self.period_fns = int(fns) & 0xffffffff
def set_drift(self, num, denom):
self.drift_num = int(num)
self.drift_denom = int(denom)
def set_period_ns(self, t):
t = Decimal(t)
period, drift = self.ctx.divmod(Decimal(t) * Decimal(2**32), Decimal(1))
period = int(period)
frac = Fraction(drift).limit_denominator(2**16-1)
self.set_period(period >> 32, period & 0xffffffff)
self.set_drift(frac.numerator, frac.denominator)
self.log.info("Set period: %s ns", t)
self.log.info("Period: 0x%x ns 0x%08x fns", self.period_ns, self.period_fns)
self.log.info("Drift: 0x%04x / 0x%04x fns", self.drift_num, self.drift_denom)
def get_period_ns(self):
p = Decimal((self.period_ns << 32) | self.period_fns)
if self.drift_denom:
p += Decimal(self.drift_num) / Decimal(self.drift_denom)
return p / Decimal(2**32)
def set_ts_tod(self, ts_s, ts_ns, ts_fns):
self.ts_tod_s = int(ts_s)
self.ts_tod_ns = int(ts_ns)
self.ts_fns = int(ts_fns)
self.ts_tod_updated = True
def set_ts_tod_64(self, ts):
ts = int(ts)
self.set_ts_tod(ts >> 48, (ts >> 32) & 0x3fffffff, (ts & 0xffff) << 16)
def set_ts_tod_ns(self, t):
ts_s, ts_ns = self.ctx.divmod(Decimal(t), Decimal(1000000000))
ts_s = ts_s.scaleb(-9).to_integral_value()
ts_ns, ts_fns = self.ctx.divmod(ts_ns, Decimal(1))
ts_ns = ts_ns.to_integral_value()
ts_fns = (ts_fns * Decimal(2**32)).to_integral_value()
self.set_ts_tod(ts_s, ts_ns, ts_fns)
def set_ts_tod_s(self, t):
self.set_ts_tod_ns(Decimal(t).scaleb(9, self.ctx))
def set_ts_tod_sim_time(self):
self.set_ts_tod_ns(Decimal(get_sim_time('fs')).scaleb(-6))
def get_ts_tod(self):
ts_tod_s, ts_tod_ns, ts_rel_ns, ts_fns = self.timestamp_delay[0]
return (ts_tod_s, ts_tod_ns, ts_fns)
def get_ts_tod_96(self):
ts_tod_s, ts_tod_ns, ts_fns = self.get_ts_tod()
return (ts_tod_s << 48) | (ts_tod_ns << 16) | (ts_fns >> 16)
def get_ts_tod_ns(self):
ts_tod_s, ts_tod_ns, ts_fns = self.get_ts_tod()
ns = Decimal(ts_fns) / Decimal(2**32)
ns = self.ctx.add(ns, Decimal(ts_tod_ns))
return self.ctx.add(ns, Decimal(ts_tod_s).scaleb(9))
def get_ts_tod_s(self):
return self.get_ts_tod_ns().scaleb(-9, self.ctx)
def set_ts_rel(self, ts_ns, ts_fns):
self.ts_rel_ns = int(ts_ns)
self.ts_fns = int(ts_fns)
self.ts_rel_updated = True
def set_ts_rel_64(self, ts):
ts = int(ts)
self.set_ts_rel(ts >> 16, (ts & 0xffff) << 16)
def set_ts_rel_ns(self, t):
ts_ns, ts_fns = self.ctx.divmod(Decimal(t), Decimal(1))
ts_ns = ts_ns.to_integral_value()
ts_fns = (ts_fns * Decimal(2**32)).to_integral_value()
self.set_ts_rel(ts_ns, ts_fns)
def set_ts_rel_s(self, t):
self.set_ts_rel_ns(Decimal(t).scaleb(9, self.ctx))
def set_ts_rel_sim_time(self):
self.set_ts_rel_ns(Decimal(get_sim_time('fs')).scaleb(-6))
def get_ts_rel(self):
ts_tod_s, ts_tod_ns, ts_rel_ns, ts_fns = self.timestamp_delay[0]
return (ts_rel_ns, ts_fns)
def get_ts_rel_64(self):
ts_rel_ns, ts_fns = self.get_ts_rel()
return (ts_rel_ns << 16) | (ts_fns >> 16)
def get_ts_rel_ns(self):
ts_rel_ns, ts_fns = self.get_ts_rel()
return self.ctx.add(Decimal(ts_fns) / Decimal(2**32), Decimal(ts_rel_ns))
def get_ts_rel_s(self):
return self.get_ts_rel_ns().scaleb(-9, self.ctx)
def _handle_reset(self, state):
if state:
self.log.info("Reset asserted")
if self._run_cr is not None:
self._run_cr.kill()
self._run_cr = None
self.ts_tod_s = 0
self.ts_tod_ns = 0
self.ts_rel_ns = 0
self.ts_fns = 0
self.drift_cnt = 0
self.data.value = 1
else:
self.log.info("Reset de-asserted")
if self._run_cr is None:
self._run_cr = cocotb.start_soon(self._run())
async def _run(self):
clock_edge_event = RisingEdge(self.clock)
msg_index = 0
msg = None
msg_delay = 0
word = None
bit_index = 0
while True:
await clock_edge_event
# delay timestamp
self.timestamp_delay.append((self.ts_tod_s, self.ts_tod_ns, self.ts_rel_ns, self.ts_fns))
while len(self.timestamp_delay) > 14*17+self.td_delay:
self.timestamp_delay.pop(0)
# increment fns portion
self.ts_fns += ((self.period_ns << 32) + self.period_fns)
if self.drift_denom:
if self.drift_cnt > 0:
self.drift_cnt -= 1
else:
self.drift_cnt = self.drift_denom-1
self.ts_fns += self.drift_num
ns_inc = self.ts_fns >> 32
self.ts_fns &= 0xffffffff
# increment relative timestamp
self.ts_rel_ns = (self.ts_rel_ns + ns_inc) & 0xffffffffffff
# increment ToD timestamp
self.ts_tod_ns = self.ts_tod_ns + ns_inc
if self.ts_tod_ns >= 1000000000:
self.log.info("Seconds rollover")
self.pps.set()
self.ts_tod_s += 1
self.ts_tod_ns -= 1000000000
# compute offset for current second
self.ts_tod_offset_ns = (self.ts_tod_ns - self.ts_rel_ns) & 0xffffffff
# compute alternate offset
if self.ts_tod_ns & (1 << 29):
# latter half of second; compute offset for next second
self.ts_tod_alt_s = self.ts_tod_s+1
self.ts_tod_alt_offset_ns = (self.ts_tod_offset_ns - 1000000000) & 0xffffffff
else:
# former half of second; compute offset for previous second
self.ts_tod_alt_s = self.ts_tod_s-1
self.ts_tod_alt_offset_ns = (self.ts_tod_offset_ns + 1000000000) & 0xffffffff
if msg_delay <= 0:
# build message
msg = []
# word 0: control
ctrl = 0
ctrl |= msg_index & 0xf
ctrl |= bool(self.ts_rel_updated) << 8
ctrl |= bool(self.ts_tod_s & 1) << 9
self.ts_rel_updated = False
msg.append(ctrl)
if msg_index == 0:
# msg 0 word 1: current ToD TS ns 15:0
msg.append(self.ts_tod_ns & 0xffff)
# msg 0 word 2: current ToD TS ns 29:16 and flag bit
msg.append(((self.ts_tod_ns >> 16) & 0x3fff) | (0x8000 if self.ts_tod_updated else 0))
self.ts_tod_updated = False
# msg 0 word 3: current ToD TS seconds 15:0
msg.append(self.ts_tod_s & 0xffff)
# msg 0 word 4: current ToD TS seconds 31:16
msg.append((self.ts_tod_s >> 16) & 0xffff)
# msg 0 word 5: current ToD TS seconds 47:32
msg.append((self.ts_tod_s >> 32) & 0xffff)
msg_index = 1
elif msg_index == 1:
# msg 1 word 1: current ToD TS ns offset 15:0
msg.append(self.ts_tod_offset_ns & 0xffff)
# msg 1 word 2: current ToD TS ns offset 31:16
msg.append((self.ts_tod_offset_ns >> 16) & 0xffff)
# msg 1 word 3: drift num
msg.append(self.drift_num)
# msg 1 word 4: drift denom
msg.append(self.drift_denom)
# msg 1 word 5: drift state
msg.append(self.drift_cnt)
msg_index = 2
elif msg_index == 2:
# msg 2 word 1: alternate ToD TS ns offset 15:0
msg.append(self.ts_tod_alt_offset_ns & 0xffff)
# msg 2 word 2: alternate ToD TS ns offset 31:16
msg.append((self.ts_tod_alt_offset_ns >> 16) & 0xffff)
# msg 2 word 3: alternate ToD TS seconds 15:0
msg.append(self.ts_tod_alt_s & 0xffff)
# msg 2 word 4: alternate ToD TS seconds 31:16
msg.append((self.ts_tod_alt_s >> 16) & 0xffff)
# msg 2 word 5: alternate ToD TS seconds 47:32
msg.append((self.ts_tod_alt_s >> 32) & 0xffff)
msg_index = 0
# word 6: current fns 15:0
msg.append(self.ts_fns & 0xffff)
# word 7: current fns 31:16
msg.append((self.ts_fns >> 16) & 0xffff)
# word 8: current relative TS ns 15:0
msg.append(self.ts_rel_ns & 0xffff)
# word 9: current relative TS ns 31:16
msg.append((self.ts_rel_ns >> 16) & 0xffff)
# word 10: current relative TS ns 47:32
msg.append((self.ts_rel_ns >> 32) & 0xffff)
# word 11: current phase increment fns 15:0
msg.append(self.period_fns & 0xffff)
# word 12: current phase increment fns 31:16
msg.append((self.period_fns >> 16) & 0xffff)
# word 13: current phase increment ns 7:0 + crc
msg.append(self.period_ns & 0xff)
msg_delay = 255
else:
msg_delay -= 1
# serialize message
if word is None:
if msg:
word = msg.pop(0)
bit_index = 0
self.data.value = 0
else:
self.data.value = 1
else:
self.data.value = bool((word >> bit_index) & 1)
bit_index += 1
if bit_index == 16:
word = None
class PtpTdSink(Reset):
def __init__(self,
data=None,
clock=None,
reset=None,
reset_active_level=True,
period_ns=6.4,
td_delay=32,
*args, **kwargs):
self.log = logging.getLogger(f"cocotb.{data._path}")
self.data = data
self.clock = clock
self.reset = reset
self.log.info("PTP time distribution sink")
self.log.info("Copyright (c) 2023 Alex Forencich")
self.log.info("https://github.com/alexforencich/verilog-ethernet")
super().__init__(*args, **kwargs)
self.ctx = Context(prec=60)
self.period_ns = 0
self.period_fns = 0
self.drift_num = 0
self.drift_denom = 0
self.ts_fns = 0
self.ts_rel_ns = 0
self.ts_tod_s = 0
self.ts_tod_ns = 0
self.ts_tod_offset_ns = 0
self.ts_tod_alt_s = 0
self.ts_tod_alt_offset_ns = 0
self.td_delay = td_delay
self.drift_cnt = 0
self.pps = Event()
self._run_cr = None
self._init_reset(reset, reset_active_level)
def get_period_ns(self):
p = Decimal((self.period_ns << 32) | self.period_fns)
if self.drift_denom:
return p + Decimal(self.drift_num) / Decimal(self.drift_denom)
return p / Decimal(2**32)
def get_ts_tod(self):
return (self.ts_tod_s, self.ts_tod_ns, self.ts_fns)
def get_ts_tod_96(self):
ts_tod_s, ts_tod_ns, ts_fns = self.get_ts_tod()
return (ts_tod_s << 48) | (ts_tod_ns << 16) | (ts_fns >> 16)
def get_ts_tod_ns(self):
ts_tod_s, ts_tod_ns, ts_fns = self.get_ts_tod()
ns = Decimal(ts_fns) / Decimal(2**32)
ns = self.ctx.add(ns, Decimal(ts_tod_ns))
return self.ctx.add(ns, Decimal(ts_tod_s).scaleb(9))
def get_ts_tod_s(self):
return self.get_ts_tod_ns().scaleb(-9, self.ctx)
def get_ts_rel(self):
return (self.ts_rel_ns, self.ts_fns)
def get_ts_rel_64(self):
ts_rel_ns, ts_fns = self.get_ts_rel()
return (ts_rel_ns << 16) | (ts_fns >> 16)
def get_ts_rel_ns(self):
ts_rel_ns, ts_fns = self.get_ts_rel()
return self.ctx.add(Decimal(ts_fns) / Decimal(2**32), Decimal(ts_rel_ns))
def get_ts_rel_s(self):
return self.get_ts_rel_ns().scaleb(-9, self.ctx)
def _handle_reset(self, state):
if state:
self.log.info("Reset asserted")
if self._run_cr is not None:
self._run_cr.kill()
self._run_cr = None
self.ts_tod_s = 0
self.ts_tod_ns = 0
self.ts_rel_ns = 0
self.ts_fns = 0
self.drift_cnt = 0
self.data.value = 1
else:
self.log.info("Reset de-asserted")
if self._run_cr is None:
self._run_cr = cocotb.start_soon(self._run())
async def _run(self):
clock_edge_event = RisingEdge(self.clock)
msg_index = 0
msg = None
msg_delay = 0
cur_msg = []
word = None
bit_index = 0
while True:
await clock_edge_event
sdi_sample = self.data.value.integer
# increment fns portion
self.ts_fns += ((self.period_ns << 32) + self.period_fns)
if self.drift_denom:
if self.drift_cnt > 0:
self.drift_cnt -= 1
else:
self.drift_cnt = self.drift_denom-1
self.ts_fns += self.drift_num
ns_inc = self.ts_fns >> 32
self.ts_fns &= 0xffffffff
# increment relative timestamp
self.ts_rel_ns = (self.ts_rel_ns + ns_inc) & 0xffffffffffff
# increment ToD timestamp
self.ts_tod_ns = self.ts_tod_ns + ns_inc
if self.ts_tod_ns >= 1000000000:
self.log.info("Seconds rollover")
self.pps.set()
self.ts_tod_s += 1
self.ts_tod_ns -= 1000000000
# process messages
if msg_delay > 0:
msg_delay -= 1
if msg_delay == 0 and msg:
self.log.info("process message %r", msg)
# word 0: control
msg_index = msg[0] & 0xf
if msg_index == 0:
# msg 0 word 1: current ToD TS ns 15:0
# msg 0 word 2: current ToD TS ns 29:16
val = ((msg[2] & 0x3fff) << 16) | msg[1]
if self.ts_tod_ns != val:
self.log.info("update ts_tod_ns: old 0x%x, new 0x%x", self.ts_tod_ns, val)
self.ts_tod_ns = val
# msg 0 word 3: current ToD TS seconds 15:0
# msg 0 word 4: current ToD TS seconds 31:16
# msg 0 word 5: current ToD TS seconds 47:32
val = (msg[5] << 32) | (msg[4] << 16) | msg[3]
if self.ts_tod_s != val:
self.log.info("update ts_tod_s: old 0x%x, new 0x%x", self.ts_tod_s, val)
self.ts_tod_s = val
elif msg_index == 1:
# msg 1 word 1: current ToD TS ns offset 15:0
# msg 1 word 2: current ToD TS ns offset 31:16
val = (msg[2] << 16) | msg[1]
if self.ts_tod_offset_ns != val:
self.log.info("update ts_tod_offset_ns: old 0x%x, new 0x%x", self.ts_tod_offset_ns, val)
self.ts_tod_offset_ns = val
# msg 1 word 3: drift num
val = msg[3]
if self.drift_num != val:
self.log.info("update drift_num: old 0x%x, new 0x%x", self.drift_num, val)
self.drift_num = val
# msg 1 word 4: drift denom
val = msg[4]
if self.drift_denom != val:
self.log.info("update drift_denom: old 0x%x, new 0x%x", self.drift_denom, val)
self.drift_denom = val
# msg 1 word 5: drift state
val = msg[5]
if self.drift_cnt != val:
self.log.info("update drift_cnt: old 0x%x, new 0x%x", self.drift_cnt, val)
self.drift_cnt = val
elif msg_index == 2:
# msg 2 word 1: alternate ToD TS ns offset 15:0
# msg 2 word 2: alternate ToD TS ns offset 31:16
val = (msg[2] << 16) | msg[1]
if self.ts_tod_alt_offset_ns != val:
self.log.info("update ts_tod_alt_offset_ns: old 0x%x, new 0x%x", self.ts_tod_alt_offset_ns, val)
self.ts_tod_alt_offset_ns = val
# msg 2 word 3: alternate ToD TS seconds 15:0
# msg 2 word 4: alternate ToD TS seconds 31:16
# msg 2 word 5: alternate ToD TS seconds 47:32
val = (msg[5] << 32) | (msg[4] << 16) | msg[3]
if self.ts_tod_alt_s != val:
self.log.info("update ts_tod_alt_s: old 0x%x, new 0x%x", self.ts_tod_alt_s, val)
self.ts_tod_alt_s = val
# word 6: current fns 15:0
# word 7: current fns 31:16
val = (msg[7] << 16) | msg[6]
if self.ts_fns != val:
self.log.info("update ts_fns: old 0x%x, new 0x%x", self.ts_fns, val)
self.ts_fns = val
# word 8: current relative TS ns 15:0
# word 9: current relative TS ns 31:16
# word 10: current relative TS ns 47:32
val = (msg[10] << 32) | (msg[9] << 16) | msg[8]
if self.ts_rel_ns != val:
self.log.info("update ts_rel_ns: old 0x%x, new 0x%x", self.ts_rel_ns, val)
self.ts_rel_ns = val
# word 11: current phase increment fns 15:0
# word 12: current phase increment fns 31:16
val = (msg[12] << 16) | msg[11]
if self.period_fns != val:
self.log.info("update period_fns: old 0x%x, new 0x%x", self.period_fns, val)
self.period_fns = val
# word 13: current phase increment ns 7:0 + crc
val = msg[13] & 0xff
if self.period_ns != val:
self.log.info("update period_ns: old 0x%x, new 0x%x", self.period_ns, val)
self.period_ns = val
msg = None
# deserialize message
if word is not None:
word = word | (sdi_sample << bit_index)
bit_index += 1
if bit_index == 16:
cur_msg.append(word)
word = None
else:
if not sdi_sample:
# start bit
word = 0
bit_index = 0
elif cur_msg:
# idle
msg = cur_msg
msg_delay = self.td_delay
cur_msg = []

View File

@ -26,45 +26,25 @@ WAVES ?= 0
COCOTB_HDL_TIMEUNIT = 1ns
COCOTB_HDL_TIMEPRECISION = 1ps
DUT = fpga_core
DUT = ptp_td_leaf
TOPLEVEL = $(DUT)
MODULE = test_$(DUT)
VERILOG_SOURCES += ../../rtl/$(DUT).v
VERILOG_SOURCES += ../../lib/eth/rtl/eth_mac_10g_fifo.v
VERILOG_SOURCES += ../../lib/eth/rtl/eth_mac_10g.v
VERILOG_SOURCES += ../../lib/eth/rtl/axis_xgmii_rx_64.v
VERILOG_SOURCES += ../../lib/eth/rtl/axis_xgmii_tx_64.v
VERILOG_SOURCES += ../../lib/eth/rtl/lfsr.v
VERILOG_SOURCES += ../../lib/eth/rtl/eth_axis_rx.v
VERILOG_SOURCES += ../../lib/eth/rtl/eth_axis_tx.v
VERILOG_SOURCES += ../../lib/eth/rtl/udp_complete_64.v
VERILOG_SOURCES += ../../lib/eth/rtl/udp_checksum_gen_64.v
VERILOG_SOURCES += ../../lib/eth/rtl/udp_64.v
VERILOG_SOURCES += ../../lib/eth/rtl/udp_ip_rx_64.v
VERILOG_SOURCES += ../../lib/eth/rtl/udp_ip_tx_64.v
VERILOG_SOURCES += ../../lib/eth/rtl/ip_complete_64.v
VERILOG_SOURCES += ../../lib/eth/rtl/ip_64.v
VERILOG_SOURCES += ../../lib/eth/rtl/ip_eth_rx_64.v
VERILOG_SOURCES += ../../lib/eth/rtl/ip_eth_tx_64.v
VERILOG_SOURCES += ../../lib/eth/rtl/ip_arb_mux.v
VERILOG_SOURCES += ../../lib/eth/rtl/arp.v
VERILOG_SOURCES += ../../lib/eth/rtl/arp_cache.v
VERILOG_SOURCES += ../../lib/eth/rtl/arp_eth_rx.v
VERILOG_SOURCES += ../../lib/eth/rtl/arp_eth_tx.v
VERILOG_SOURCES += ../../lib/eth/rtl/eth_arb_mux.v
VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/arbiter.v
VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/priority_encoder.v
VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_fifo.v
VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_async_fifo.v
VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_async_fifo_adapter.v
# module parameters
#export PARAM_A := value
export PARAM_TS_REL_EN := 1
export PARAM_TS_TOD_EN := 1
export PARAM_TS_FNS_W := 16
export PARAM_TS_REL_NS_W := 48
export PARAM_TS_TOD_S_W := 48
export PARAM_TS_REL_W := $(shell expr $(PARAM_TS_REL_NS_W) + $(PARAM_TS_FNS_W))
export PARAM_TS_TOD_W := $(shell expr $(PARAM_TS_TOD_S_W) + 32 + $(PARAM_TS_FNS_W))
export PARAM_TD_SDI_PIPELINE := 2
ifeq ($(SIM), icarus)
PLUSARGS += -fst
# COMPILE_ARGS += -P $(TOPLEVEL).A=$(PARAM_A)
COMPILE_ARGS += $(foreach v,$(filter PARAM_%,$(.VARIABLES)),-P $(TOPLEVEL).$(subst PARAM_,,$(v))=$($(v)))
ifeq ($(WAVES), 1)
VERILOG_SOURCES += iverilog_dump.v
@ -73,7 +53,7 @@ ifeq ($(SIM), icarus)
else ifeq ($(SIM), verilator)
COMPILE_ARGS += -Wno-SELRANGE -Wno-WIDTH
# COMPILE_ARGS += -GA=$(PARAM_A)
COMPILE_ARGS += $(foreach v,$(filter PARAM_%,$(.VARIABLES)),-G$(subst PARAM_,,$(v))=$($(v)))
ifeq ($(WAVES), 1)
COMPILE_ARGS += --trace-fst

View File

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

View File

@ -0,0 +1,507 @@
#!/usr/bin/env python
"""
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.
"""
import logging
import os
import sys
from decimal import Decimal
from statistics import mean, stdev
import cocotb_test.simulator
import cocotb
from cocotb.clock import Clock
from cocotb.triggers import RisingEdge, Timer
from cocotb.utils import get_sim_steps, get_sim_time
try:
from ptp_td import PtpTdSource
except ImportError:
# attempt import from current directory
sys.path.insert(0, os.path.join(os.path.dirname(__file__)))
try:
from ptp_td import PtpTdSource
finally:
del sys.path[0]
class TB:
def __init__(self, dut):
self.dut = dut
self.log = logging.getLogger("cocotb.tb")
self.log.setLevel(logging.DEBUG)
cocotb.start_soon(Clock(dut.sample_clk, 9.9, units="ns").start())
self.ptp_td_source = PtpTdSource(
data=dut.ptp_td_sdi,
clock=dut.ptp_clk,
reset=dut.ptp_rst,
period_ns=6.4
)
self.ptp_clock_period = 6.4
dut.ptp_clk.setimmediatevalue(0)
cocotb.start_soon(self._run_ptp_clock())
self.clock_period = 6.4
dut.clk.setimmediatevalue(0)
cocotb.start_soon(self._run_clock())
self.ref_ts_rel = []
self.ref_ts_tod = []
self.output_ts_rel = []
self.output_ts_tod = []
cocotb.start_soon(self._run_collect_ref_ts())
cocotb.start_soon(self._run_collect_output_ts())
async def reset(self):
self.dut.ptp_rst.setimmediatevalue(0)
self.dut.rst.setimmediatevalue(0)
await RisingEdge(self.dut.ptp_clk)
await RisingEdge(self.dut.ptp_clk)
self.dut.ptp_rst.value = 1
self.dut.rst.value = 1
for k in range(10):
await RisingEdge(self.dut.ptp_clk)
self.dut.ptp_rst.value = 0
self.dut.rst.value = 0
for k in range(10):
await RisingEdge(self.dut.ptp_clk)
def set_ptp_clock_period(self, period):
self.ptp_clock_period = period
async def _run_ptp_clock(self):
period = None
steps_per_ns = get_sim_steps(1.0, 'ns')
while True:
if period != self.ptp_clock_period:
period = self.ptp_clock_period
t = Timer(int(steps_per_ns * period / 2.0))
await t
self.dut.ptp_clk.value = 1
await t
self.dut.ptp_clk.value = 0
def set_clock_period(self, period):
self.clock_period = period
def get_output_ts_tod_ns(self):
ts = self.dut.output_ts_tod.value.integer
return Decimal(ts >> 48).scaleb(9) + (Decimal(ts & 0xffffffffffff) / Decimal(2**16))
def get_output_ts_rel_ns(self):
ts = self.dut.output_ts_rel.value.integer
return Decimal(ts) / Decimal(2**16)
async def _run_clock(self):
period = None
steps_per_ns = get_sim_steps(1.0, 'ns')
while True:
if period != self.clock_period:
period = self.clock_period
t = Timer(int(steps_per_ns * period / 2.0))
await t
self.dut.clk.value = 1
await t
self.dut.clk.value = 0
async def _run_collect_ref_ts(self):
clk_event = RisingEdge(self.dut.ptp_clk)
while True:
await clk_event
st = Decimal(get_sim_time('fs')).scaleb(-6)
self.ref_ts_rel.append((st, self.ptp_td_source.get_ts_rel_ns()))
self.ref_ts_tod.append((st, self.ptp_td_source.get_ts_tod_ns()))
async def _run_collect_output_ts(self):
clk_event = RisingEdge(self.dut.clk)
while True:
await clk_event
st = Decimal(get_sim_time('fs')).scaleb(-6)
self.output_ts_rel.append((st, self.get_output_ts_rel_ns()))
self.output_ts_tod.append((st, self.get_output_ts_tod_ns()))
def compute_ts_diff(self, ts_lst_1, ts_lst_2):
ts_lst_1 = [x for x in ts_lst_1]
diffs = []
its1 = ts_lst_1.pop(0)
its2 = ts_lst_1.pop(0)
for ots in ts_lst_2:
while its2[0] < ots[0] and ts_lst_1:
its1 = its2
its2 = ts_lst_1.pop(0)
if its2[0] < ots[0]:
break
dt = its2[0] - its1[0]
dts = its2[1] - its1[1]
its = its1[1]+dts/dt*(ots[0]-its1[0])
# diffs.append(ots[1] - its)
diffs.append(float(ots[1] - its))
return diffs
async def measure_ts_diff(self, N=100):
self.ref_ts_rel = []
self.ref_ts_tod = []
self.output_ts_rel = []
self.output_ts_tod = []
for k in range(N):
await RisingEdge(self.dut.clk)
rel_diffs = self.compute_ts_diff(self.ref_ts_rel, self.output_ts_rel)
tod_diffs = self.compute_ts_diff(self.ref_ts_tod, self.output_ts_tod)
return rel_diffs, tod_diffs
@cocotb.test()
async def run_test(dut):
tb = TB(dut)
await tb.reset()
# set small offset between timestamps
tb.ptp_td_source.set_ts_rel_ns(0)
tb.ptp_td_source.set_ts_tod_ns(10000)
await RisingEdge(dut.clk)
tb.log.info("Same clock speed")
tb.set_ptp_clock_period(6.4)
tb.set_clock_period(6.4)
await RisingEdge(dut.clk)
for i in range(100000):
await RisingEdge(dut.clk)
assert tb.dut.locked.value.integer
rel_diffs, tod_diffs = await tb.measure_ts_diff()
tb.log.info(f"Difference (rel): {mean(rel_diffs)} ns (stdev: {stdev(rel_diffs)})")
tb.log.info(f"Difference (ToD): {mean(tod_diffs)} ns (stdev: {stdev(tod_diffs)})")
assert abs(mean(rel_diffs)) < 5
assert abs(mean(tod_diffs)) < 5
await RisingEdge(dut.clk)
tb.log.info("10 ppm slower")
tb.set_ptp_clock_period(6.4)
tb.set_clock_period(6.4*(1+.00001))
await RisingEdge(dut.clk)
for i in range(100000):
await RisingEdge(dut.clk)
assert tb.dut.locked.value.integer
rel_diffs, tod_diffs = await tb.measure_ts_diff()
tb.log.info(f"Difference (rel): {mean(rel_diffs)} ns (stdev: {stdev(rel_diffs)})")
tb.log.info(f"Difference (ToD): {mean(tod_diffs)} ns (stdev: {stdev(tod_diffs)})")
assert abs(mean(rel_diffs)) < 5
assert abs(mean(tod_diffs)) < 5
await RisingEdge(dut.clk)
tb.log.info("10 ppm faster")
tb.set_ptp_clock_period(6.4)
tb.set_clock_period(6.4*(1-.00001))
await RisingEdge(dut.clk)
for i in range(100000):
await RisingEdge(dut.clk)
assert tb.dut.locked.value.integer
rel_diffs, tod_diffs = await tb.measure_ts_diff()
tb.log.info(f"Difference (rel): {mean(rel_diffs)} ns (stdev: {stdev(rel_diffs)})")
tb.log.info(f"Difference (ToD): {mean(tod_diffs)} ns (stdev: {stdev(tod_diffs)})")
assert abs(mean(rel_diffs)) < 5
assert abs(mean(tod_diffs)) < 5
await RisingEdge(dut.clk)
tb.log.info("200 ppm slower")
tb.set_ptp_clock_period(6.4)
tb.set_clock_period(6.4*(1+.0002))
await RisingEdge(dut.clk)
for i in range(100000):
await RisingEdge(dut.clk)
assert tb.dut.locked.value.integer
rel_diffs, tod_diffs = await tb.measure_ts_diff()
tb.log.info(f"Difference (rel): {mean(rel_diffs)} ns (stdev: {stdev(rel_diffs)})")
tb.log.info(f"Difference (ToD): {mean(tod_diffs)} ns (stdev: {stdev(tod_diffs)})")
assert abs(mean(rel_diffs)) < 5
assert abs(mean(tod_diffs)) < 5
await RisingEdge(dut.clk)
tb.log.info("200 ppm faster")
tb.set_ptp_clock_period(6.4)
tb.set_clock_period(6.4*(1-.0002))
await RisingEdge(dut.clk)
for i in range(100000):
await RisingEdge(dut.clk)
assert tb.dut.locked.value.integer
rel_diffs, tod_diffs = await tb.measure_ts_diff()
tb.log.info(f"Difference (rel): {mean(rel_diffs)} ns (stdev: {stdev(rel_diffs)})")
tb.log.info(f"Difference (ToD): {mean(tod_diffs)} ns (stdev: {stdev(tod_diffs)})")
assert abs(mean(rel_diffs)) < 5
assert abs(mean(tod_diffs)) < 5
await RisingEdge(dut.clk)
tb.log.info("Coherent tracking (+/- 10 ppm)")
tb.set_ptp_clock_period(6.4)
tb.set_clock_period(6.4)
await RisingEdge(dut.clk)
period = 6.400
step = 0.000002
period_min = 6.4*(1-.00001)
period_max = 6.4*(1+.00001)
for i in range(500):
period += step
if period <= period_min:
step = abs(step)
if period >= period_max:
step = -abs(step)
tb.set_clock_period(period)
for i in range(200):
await RisingEdge(dut.clk)
assert tb.dut.locked.value.integer
rel_diffs, tod_diffs = await tb.measure_ts_diff()
tb.log.info(f"Difference (rel): {mean(rel_diffs)} ns (stdev: {stdev(rel_diffs)})")
tb.log.info(f"Difference (ToD): {mean(tod_diffs)} ns (stdev: {stdev(tod_diffs)})")
assert abs(mean(rel_diffs)) < 5
assert abs(mean(tod_diffs)) < 5
await RisingEdge(dut.clk)
tb.log.info("Coherent tracking (+/- 200 ppm)")
tb.set_ptp_clock_period(6.4)
tb.set_clock_period(6.4)
await RisingEdge(dut.clk)
period = 6.400
step = 0.000002
period_min = 6.4*(1-.0002)
period_max = 6.4*(1+.0002)
for i in range(5000):
period += step
if period <= period_min:
step = abs(step)
if period >= period_max:
step = -abs(step)
tb.set_clock_period(period)
for i in range(20):
await RisingEdge(dut.clk)
assert tb.dut.locked.value.integer
rel_diffs, tod_diffs = await tb.measure_ts_diff()
tb.log.info(f"Difference (rel): {mean(rel_diffs)} ns (stdev: {stdev(rel_diffs)})")
tb.log.info(f"Difference (ToD): {mean(tod_diffs)} ns (stdev: {stdev(tod_diffs)})")
assert abs(mean(rel_diffs)) < 5
assert abs(mean(tod_diffs)) < 5
await RisingEdge(dut.clk)
tb.log.info("Slightly faster (6.3 ns)")
tb.set_ptp_clock_period(6.4)
tb.set_clock_period(6.3)
await RisingEdge(dut.clk)
for i in range(100000):
await RisingEdge(dut.clk)
assert tb.dut.locked.value.integer
rel_diffs, tod_diffs = await tb.measure_ts_diff()
tb.log.info(f"Difference (rel): {mean(rel_diffs)} ns (stdev: {stdev(rel_diffs)})")
tb.log.info(f"Difference (ToD): {mean(tod_diffs)} ns (stdev: {stdev(tod_diffs)})")
assert abs(mean(rel_diffs)) < 5
assert abs(mean(tod_diffs)) < 5
await RisingEdge(dut.clk)
tb.log.info("Slightly slower (6.5 ns)")
tb.set_ptp_clock_period(6.4)
tb.set_clock_period(6.5)
await RisingEdge(dut.clk)
for i in range(100000):
await RisingEdge(dut.clk)
assert tb.dut.locked.value.integer
rel_diffs, tod_diffs = await tb.measure_ts_diff()
tb.log.info(f"Difference (rel): {mean(rel_diffs)} ns (stdev: {stdev(rel_diffs)})")
tb.log.info(f"Difference (ToD): {mean(tod_diffs)} ns (stdev: {stdev(tod_diffs)})")
assert abs(mean(rel_diffs)) < 5
assert abs(mean(tod_diffs)) < 5
await RisingEdge(dut.clk)
tb.log.info("Significantly faster (250 MHz)")
tb.set_ptp_clock_period(6.4)
tb.set_clock_period(4.0)
await RisingEdge(dut.clk)
for i in range(100000):
await RisingEdge(dut.clk)
assert tb.dut.locked.value.integer
rel_diffs, tod_diffs = await tb.measure_ts_diff()
tb.log.info(f"Difference (rel): {mean(rel_diffs)} ns (stdev: {stdev(rel_diffs)})")
tb.log.info(f"Difference (ToD): {mean(tod_diffs)} ns (stdev: {stdev(tod_diffs)})")
assert abs(mean(rel_diffs)) < 5
assert abs(mean(tod_diffs)) < 5
await RisingEdge(dut.clk)
tb.log.info("Significantly slower (100 MHz)")
tb.set_ptp_clock_period(6.4)
tb.set_clock_period(10.0)
await RisingEdge(dut.clk)
for i in range(100000):
await RisingEdge(dut.clk)
assert tb.dut.locked.value.integer
rel_diffs, tod_diffs = await tb.measure_ts_diff()
tb.log.info(f"Difference (rel): {mean(rel_diffs)} ns (stdev: {stdev(rel_diffs)})")
tb.log.info(f"Difference (ToD): {mean(tod_diffs)} ns (stdev: {stdev(tod_diffs)})")
assert abs(mean(rel_diffs)) < 5
assert abs(mean(tod_diffs)) < 5
await RisingEdge(dut.clk)
tb.log.info("Significantly faster (390.625 MHz)")
tb.set_ptp_clock_period(6.4)
tb.set_clock_period(2.56)
await RisingEdge(dut.clk)
for i in range(100000):
await RisingEdge(dut.clk)
assert tb.dut.locked.value.integer
rel_diffs, tod_diffs = await tb.measure_ts_diff()
tb.log.info(f"Difference (rel): {mean(rel_diffs)} ns (stdev: {stdev(rel_diffs)})")
tb.log.info(f"Difference (ToD): {mean(tod_diffs)} ns (stdev: {stdev(tod_diffs)})")
assert abs(mean(rel_diffs)) < 5
assert abs(mean(tod_diffs)) < 5
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, 'axis', 'rtl'))
def test_ptp_td_leaf(request):
dut = "ptp_td_leaf"
module = os.path.splitext(os.path.basename(__file__))[0]
toplevel = dut
verilog_sources = [
os.path.join(rtl_dir, f"{dut}.v"),
]
parameters = {}
parameters['TS_REL_EN'] = 1
parameters['TS_TOD_EN'] = 1
parameters['TS_FNS_W'] = 16
parameters['TS_REL_NS_W'] = 48
parameters['TS_TOD_S_W'] = 48
parameters['TS_REL_W'] = parameters['TS_REL_NS_W'] + parameters['TS_FNS_W']
parameters['TS_TOD_W'] = parameters['TS_TOD_S_W'] + 32 + parameters['TS_FNS_W']
parameters['TD_SDI_PIPELINE'] = 2
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

@ -26,45 +26,19 @@ WAVES ?= 0
COCOTB_HDL_TIMEUNIT = 1ns
COCOTB_HDL_TIMEPRECISION = 1ps
DUT = fpga_core
DUT = ptp_td_phc
TOPLEVEL = $(DUT)
MODULE = test_$(DUT)
VERILOG_SOURCES += ../../rtl/$(DUT).v
VERILOG_SOURCES += ../../lib/eth/rtl/eth_mac_10g_fifo.v
VERILOG_SOURCES += ../../lib/eth/rtl/eth_mac_10g.v
VERILOG_SOURCES += ../../lib/eth/rtl/axis_xgmii_rx_64.v
VERILOG_SOURCES += ../../lib/eth/rtl/axis_xgmii_tx_64.v
VERILOG_SOURCES += ../../lib/eth/rtl/lfsr.v
VERILOG_SOURCES += ../../lib/eth/rtl/eth_axis_rx.v
VERILOG_SOURCES += ../../lib/eth/rtl/eth_axis_tx.v
VERILOG_SOURCES += ../../lib/eth/rtl/udp_complete_64.v
VERILOG_SOURCES += ../../lib/eth/rtl/udp_checksum_gen_64.v
VERILOG_SOURCES += ../../lib/eth/rtl/udp_64.v
VERILOG_SOURCES += ../../lib/eth/rtl/udp_ip_rx_64.v
VERILOG_SOURCES += ../../lib/eth/rtl/udp_ip_tx_64.v
VERILOG_SOURCES += ../../lib/eth/rtl/ip_complete_64.v
VERILOG_SOURCES += ../../lib/eth/rtl/ip_64.v
VERILOG_SOURCES += ../../lib/eth/rtl/ip_eth_rx_64.v
VERILOG_SOURCES += ../../lib/eth/rtl/ip_eth_tx_64.v
VERILOG_SOURCES += ../../lib/eth/rtl/ip_arb_mux.v
VERILOG_SOURCES += ../../lib/eth/rtl/arp.v
VERILOG_SOURCES += ../../lib/eth/rtl/arp_cache.v
VERILOG_SOURCES += ../../lib/eth/rtl/arp_eth_rx.v
VERILOG_SOURCES += ../../lib/eth/rtl/arp_eth_tx.v
VERILOG_SOURCES += ../../lib/eth/rtl/eth_arb_mux.v
VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/arbiter.v
VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/priority_encoder.v
VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_fifo.v
VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_async_fifo.v
VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_async_fifo_adapter.v
# module parameters
#export PARAM_A := value
export PARAM_PERIOD_NS_NUM := 32
export PARAM_PERIOD_NS_DENOM := 5
ifeq ($(SIM), icarus)
PLUSARGS += -fst
# COMPILE_ARGS += -P $(TOPLEVEL).A=$(PARAM_A)
COMPILE_ARGS += $(foreach v,$(filter PARAM_%,$(.VARIABLES)),-P $(TOPLEVEL).$(subst PARAM_,,$(v))=$($(v)))
ifeq ($(WAVES), 1)
VERILOG_SOURCES += iverilog_dump.v
@ -73,7 +47,7 @@ ifeq ($(SIM), icarus)
else ifeq ($(SIM), verilator)
COMPILE_ARGS += -Wno-SELRANGE -Wno-WIDTH
# COMPILE_ARGS += -GA=$(PARAM_A)
COMPILE_ARGS += $(foreach v,$(filter PARAM_%,$(.VARIABLES)),-G$(subst PARAM_,,$(v))=$($(v)))
ifeq ($(WAVES), 1)
COMPILE_ARGS += --trace-fst

View File

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

View File

@ -0,0 +1,550 @@
#!/usr/bin/env python
"""
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.
"""
import logging
import os
import sys
from decimal import Decimal
import cocotb_test.simulator
import cocotb
from cocotb.clock import Clock
from cocotb.triggers import RisingEdge
from cocotb.utils import get_sim_time
try:
from ptp_td import PtpTdSink
except ImportError:
# attempt import from current directory
sys.path.insert(0, os.path.join(os.path.dirname(__file__)))
try:
from ptp_td import PtpTdSink
finally:
del sys.path[0]
class TB:
def __init__(self, dut):
self.dut = dut
self.log = logging.getLogger("cocotb.tb")
self.log.setLevel(logging.DEBUG)
cocotb.start_soon(Clock(dut.clk, 6.4, units="ns").start())
self.ptp_td_sink = PtpTdSink(
data=dut.ptp_td_sdo,
clock=dut.clk,
reset=dut.rst,
period_ns=6.4
)
dut.input_ts_rel_ns.setimmediatevalue(0)
dut.input_ts_rel_valid.setimmediatevalue(0)
dut.input_ts_rel_offset_ns.setimmediatevalue(0)
dut.input_ts_rel_offset_valid.setimmediatevalue(0)
dut.input_ts_tod_s.setimmediatevalue(0)
dut.input_ts_tod_ns.setimmediatevalue(0)
dut.input_ts_tod_valid.setimmediatevalue(0)
dut.input_ts_tod_offset_ns.setimmediatevalue(0)
dut.input_ts_tod_offset_valid.setimmediatevalue(0)
dut.input_ts_offset_fns.setimmediatevalue(0)
dut.input_ts_offset_valid.setimmediatevalue(0)
dut.input_period_ns.setimmediatevalue(0)
dut.input_period_fns.setimmediatevalue(0)
dut.input_period_valid.setimmediatevalue(0)
dut.input_drift_num.setimmediatevalue(0)
dut.input_drift_denom.setimmediatevalue(0)
dut.input_drift_valid.setimmediatevalue(0)
async def reset(self):
self.dut.rst.setimmediatevalue(0)
await RisingEdge(self.dut.clk)
await RisingEdge(self.dut.clk)
self.dut.rst.value = 1
await RisingEdge(self.dut.clk)
await RisingEdge(self.dut.clk)
self.dut.rst.value = 0
await RisingEdge(self.dut.clk)
await RisingEdge(self.dut.clk)
@cocotb.test()
async def run_default_rate(dut):
tb = TB(dut)
await tb.reset()
for k in range(256*6):
await RisingEdge(dut.clk)
await RisingEdge(dut.clk)
start_time = Decimal(get_sim_time('fs')).scaleb(-6)
start_ts_tod = tb.ptp_td_sink.get_ts_tod_ns()
start_ts_rel = tb.ptp_td_sink.get_ts_rel_ns()
for k in range(10000):
await RisingEdge(dut.clk)
stop_time = Decimal(get_sim_time('fs')).scaleb(-6)
stop_ts_tod = tb.ptp_td_sink.get_ts_tod_ns()
stop_ts_rel = tb.ptp_td_sink.get_ts_rel_ns()
time_delta = stop_time-start_time
ts_tod_delta = stop_ts_tod-start_ts_tod
ts_rel_delta = stop_ts_rel-start_ts_rel
tb.log.info("sim time delta : %s ns", time_delta)
tb.log.info("ToD ts delta : %s ns", ts_tod_delta)
tb.log.info("Rel ts delta : %s ns", ts_rel_delta)
ts_tod_diff = time_delta - ts_tod_delta
ts_rel_diff = time_delta - ts_rel_delta
tb.log.info("ToD ts diff : %s ns", ts_tod_diff)
tb.log.info("Rel ts diff : %s ns", ts_rel_diff)
assert abs(ts_tod_diff) < 1e-3
assert abs(ts_rel_diff) < 1e-3
await RisingEdge(dut.clk)
await RisingEdge(dut.clk)
@cocotb.test()
async def run_load_timestamps(dut):
tb = TB(dut)
await tb.reset()
await RisingEdge(dut.clk)
dut.input_ts_tod_s.value = 12
dut.input_ts_tod_ns.value = 123456789
dut.input_ts_tod_valid.value = 1
await RisingEdge(dut.clk)
while not dut.input_ts_tod_ready.value:
await RisingEdge(dut.clk)
dut.input_ts_tod_valid.value = 0
dut.input_ts_rel_ns.value = 123456789
dut.input_ts_rel_valid.value = 1
await RisingEdge(dut.clk)
while not dut.input_ts_rel_ready.value:
await RisingEdge(dut.clk)
dut.input_ts_rel_valid.value = 0
for k in range(256*6):
await RisingEdge(dut.clk)
# assert tb.ptp_td_sink.get_ts_tod_s() - (12.123456789 + (256*6-(14*17+32)-2)*6.4e-9) < 6.4e-9
# assert tb.ptp_td_sink.get_ts_rel_ns() - (123456789 + (256*6-(14*17+32)-1)*6.4) < 6.4
await RisingEdge(dut.clk)
start_time = Decimal(get_sim_time('fs')).scaleb(-6)
start_ts_tod = tb.ptp_td_sink.get_ts_tod_ns()
start_ts_rel = tb.ptp_td_sink.get_ts_rel_ns()
for k in range(10000):
await RisingEdge(dut.clk)
stop_time = Decimal(get_sim_time('fs')).scaleb(-6)
stop_ts_tod = tb.ptp_td_sink.get_ts_tod_ns()
stop_ts_rel = tb.ptp_td_sink.get_ts_rel_ns()
time_delta = stop_time-start_time
ts_tod_delta = stop_ts_tod-start_ts_tod
ts_rel_delta = stop_ts_rel-start_ts_rel
tb.log.info("sim time delta : %s ns", time_delta)
tb.log.info("ToD ts delta : %s ns", ts_tod_delta)
tb.log.info("Rel ts delta : %s ns", ts_rel_delta)
ts_tod_diff = time_delta - ts_tod_delta
ts_rel_diff = time_delta - ts_rel_delta
tb.log.info("ToD ts diff : %s ns", ts_tod_diff)
tb.log.info("Rel ts diff : %s ns", ts_rel_diff)
assert abs(ts_tod_diff) < 1e-3
assert abs(ts_rel_diff) < 1e-3
await RisingEdge(dut.clk)
await RisingEdge(dut.clk)
@cocotb.test()
async def run_offsets(dut):
tb = TB(dut)
await tb.reset()
for k in range(256*6):
await RisingEdge(dut.clk)
await RisingEdge(dut.clk)
start_time = Decimal(get_sim_time('fs')).scaleb(-6)
start_ts_tod = tb.ptp_td_sink.get_ts_tod_ns()
start_ts_rel = tb.ptp_td_sink.get_ts_rel_ns()
for k in range(2000):
await RisingEdge(dut.clk)
tb.log.info("Offset FNS (positive)")
await RisingEdge(dut.clk)
dut.input_ts_offset_fns.value = 0x78000000 & 0xffffffff
dut.input_ts_offset_valid.value = 1
await RisingEdge(dut.clk)
while not dut.input_ts_offset_ready.value:
await RisingEdge(dut.clk)
dut.input_ts_offset_valid.value = 0
for k in range(2000):
await RisingEdge(dut.clk)
tb.log.info("Offset FNS (negative)")
await RisingEdge(dut.clk)
dut.input_ts_offset_fns.value = -0x70000000 & 0xffffffff
dut.input_ts_offset_valid.value = 1
await RisingEdge(dut.clk)
while not dut.input_ts_offset_ready.value:
await RisingEdge(dut.clk)
dut.input_ts_offset_valid.value = 0
for k in range(2000):
await RisingEdge(dut.clk)
tb.log.info("Offset relative TS (positive)")
dut.input_ts_rel_offset_ns.value = 30000 & 0xffffffff
dut.input_ts_rel_offset_valid.value = 1
await RisingEdge(dut.clk)
while not dut.input_ts_rel_offset_ready.value:
await RisingEdge(dut.clk)
dut.input_ts_rel_offset_valid.value = 0
for k in range(2000):
await RisingEdge(dut.clk)
tb.log.info("Offset relative TS (negative)")
dut.input_ts_rel_offset_ns.value = -10000 & 0xffffffff
dut.input_ts_rel_offset_valid.value = 1
await RisingEdge(dut.clk)
while not dut.input_ts_rel_offset_ready.value:
await RisingEdge(dut.clk)
dut.input_ts_rel_offset_valid.value = 0
for k in range(2000):
await RisingEdge(dut.clk)
tb.log.info("Offset ToD TS (positive)")
dut.input_ts_tod_offset_ns.value = 510000000 & 0x3fffffff
dut.input_ts_tod_offset_valid.value = 1
await RisingEdge(dut.clk)
while not dut.input_ts_tod_offset_ready.value:
await RisingEdge(dut.clk)
await RisingEdge(dut.clk)
while not dut.input_ts_tod_offset_ready.value:
await RisingEdge(dut.clk)
dut.input_ts_tod_offset_valid.value = 0
for k in range(2000):
await RisingEdge(dut.clk)
tb.log.info("Offset ToD TS (negative)")
dut.input_ts_tod_offset_ns.value = -500000000 & 0x3fffffff
dut.input_ts_tod_offset_valid.value = 1
await RisingEdge(dut.clk)
while not dut.input_ts_tod_offset_ready.value:
await RisingEdge(dut.clk)
await RisingEdge(dut.clk)
while not dut.input_ts_tod_offset_ready.value:
await RisingEdge(dut.clk)
dut.input_ts_tod_offset_valid.value = 0
for k in range(10000):
await RisingEdge(dut.clk)
stop_time = Decimal(get_sim_time('fs')).scaleb(-6)
stop_ts_tod = tb.ptp_td_sink.get_ts_tod_ns()
stop_ts_rel = tb.ptp_td_sink.get_ts_rel_ns()
time_delta = stop_time-start_time
ts_tod_delta = stop_ts_tod-start_ts_tod
ts_rel_delta = stop_ts_rel-start_ts_rel
tb.log.info("sim time delta : %s ns", time_delta)
tb.log.info("ToD ts delta : %s ns", ts_tod_delta)
tb.log.info("Rel ts delta : %s ns", ts_rel_delta)
ts_tod_diff = time_delta - ts_tod_delta + Decimal(0.03125) + Decimal(20000000)
ts_rel_diff = time_delta - ts_rel_delta + Decimal(0.03125) + Decimal(20000)
tb.log.info("ToD ts diff : %s ns", ts_tod_diff)
tb.log.info("Rel ts diff : %s ns", ts_rel_diff)
assert abs(ts_tod_diff) < 1e-3
assert abs(ts_rel_diff) < 1e-3
await RisingEdge(dut.clk)
await RisingEdge(dut.clk)
@cocotb.test()
async def run_seconds_increment(dut):
tb = TB(dut)
await tb.reset()
await RisingEdge(dut.clk)
dut.input_ts_tod_s.value = 0
dut.input_ts_tod_ns.value = 999990000
dut.input_ts_tod_valid.value = 1
await RisingEdge(dut.clk)
while not dut.input_ts_tod_ready.value:
await RisingEdge(dut.clk)
dut.input_ts_tod_valid.value = 0
for k in range(256*6):
await RisingEdge(dut.clk)
await RisingEdge(dut.clk)
start_time = Decimal(get_sim_time('fs')).scaleb(-6)
start_ts_tod = tb.ptp_td_sink.get_ts_tod_ns()
start_ts_rel = tb.ptp_td_sink.get_ts_rel_ns()
saw_pps = False
for k in range(3000):
await RisingEdge(dut.clk)
if dut.output_pps.value.integer:
saw_pps = True
tb.log.info("Got PPS with sink ToD TS %s", tb.ptp_td_sink.get_ts_tod_ns())
assert (tb.ptp_td_sink.get_ts_tod_s() - 1) < 6.4e-9
assert saw_pps
stop_time = Decimal(get_sim_time('fs')).scaleb(-6)
stop_ts_tod = tb.ptp_td_sink.get_ts_tod_ns()
stop_ts_rel = tb.ptp_td_sink.get_ts_rel_ns()
time_delta = stop_time-start_time
ts_tod_delta = stop_ts_tod-start_ts_tod
ts_rel_delta = stop_ts_rel-start_ts_rel
tb.log.info("sim time delta : %s ns", time_delta)
tb.log.info("ToD ts delta : %s ns", ts_tod_delta)
tb.log.info("Rel ts delta : %s ns", ts_rel_delta)
ts_tod_diff = time_delta - ts_tod_delta
ts_rel_diff = time_delta - ts_rel_delta
tb.log.info("ToD ts diff : %s ns", ts_tod_diff)
tb.log.info("Rel ts diff : %s ns", ts_rel_diff)
assert abs(ts_tod_diff) < 1e-3
assert abs(ts_rel_diff) < 1e-3
await RisingEdge(dut.clk)
await RisingEdge(dut.clk)
@cocotb.test()
async def run_frequency_adjustment(dut):
tb = TB(dut)
await tb.reset()
await RisingEdge(dut.clk)
dut.input_period_ns.value = 0x6
dut.input_period_fns.value = 0x66240000
dut.input_period_valid.value = 1
await RisingEdge(dut.clk)
dut.input_period_valid.value = 0
for k in range(256*6):
await RisingEdge(dut.clk)
await RisingEdge(dut.clk)
start_time = Decimal(get_sim_time('fs')).scaleb(-6)
start_ts_tod = tb.ptp_td_sink.get_ts_tod_ns()
start_ts_rel = tb.ptp_td_sink.get_ts_rel_ns()
for k in range(10000):
await RisingEdge(dut.clk)
stop_time = Decimal(get_sim_time('fs')).scaleb(-6)
stop_ts_tod = tb.ptp_td_sink.get_ts_tod_ns()
stop_ts_rel = tb.ptp_td_sink.get_ts_rel_ns()
time_delta = stop_time-start_time
ts_tod_delta = stop_ts_tod-start_ts_tod
ts_rel_delta = stop_ts_rel-start_ts_rel
tb.log.info("sim time delta : %s ns", time_delta)
tb.log.info("ToD ts delta : %s ns", ts_tod_delta)
tb.log.info("Rel ts delta : %s ns", ts_rel_delta)
ts_tod_diff = time_delta - ts_tod_delta * Decimal(6.4/(6+(0x66240000+2/5)/2**32))
ts_rel_diff = time_delta - ts_rel_delta * Decimal(6.4/(6+(0x66240000+2/5)/2**32))
tb.log.info("ToD ts diff : %s ns", ts_tod_diff)
tb.log.info("Rel ts diff : %s ns", ts_rel_diff)
assert abs(ts_tod_diff) < 1e-3
assert abs(ts_rel_diff) < 1e-3
await RisingEdge(dut.clk)
await RisingEdge(dut.clk)
@cocotb.test()
async def run_drift_adjustment(dut):
tb = TB(dut)
await tb.reset()
dut.input_drift_num.value = 20000
dut.input_drift_denom.value = 5
dut.input_drift_valid.value = 1
await RisingEdge(dut.clk)
dut.input_drift_valid.value = 0
for k in range(256*6):
await RisingEdge(dut.clk)
await RisingEdge(dut.clk)
start_time = Decimal(get_sim_time('fs')).scaleb(-6)
start_ts_tod = tb.ptp_td_sink.get_ts_tod_ns()
start_ts_rel = tb.ptp_td_sink.get_ts_rel_ns()
for k in range(10000):
await RisingEdge(dut.clk)
stop_time = Decimal(get_sim_time('fs')).scaleb(-6)
stop_ts_tod = tb.ptp_td_sink.get_ts_tod_ns()
stop_ts_rel = tb.ptp_td_sink.get_ts_rel_ns()
time_delta = stop_time-start_time
ts_tod_delta = stop_ts_tod-start_ts_tod
ts_rel_delta = stop_ts_rel-start_ts_rel
tb.log.info("sim time delta : %s ns", time_delta)
tb.log.info("ToD ts delta : %s ns", ts_tod_delta)
tb.log.info("Rel ts delta : %s ns", ts_rel_delta)
ts_tod_diff = time_delta - ts_tod_delta * Decimal(6.4/(6+(0x66666666+20000/5)/2**32))
ts_rel_diff = time_delta - ts_rel_delta * Decimal(6.4/(6+(0x66666666+20000/5)/2**32))
tb.log.info("ToD ts diff : %s ns", ts_tod_diff)
tb.log.info("Rel ts diff : %s ns", ts_rel_diff)
assert abs(ts_tod_diff) < 1e-3
assert abs(ts_rel_diff) < 1e-3
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, 'axis', 'rtl'))
def test_ptp_td_phc(request):
dut = "ptp_td_phc"
module = os.path.splitext(os.path.basename(__file__))[0]
toplevel = dut
verilog_sources = [
os.path.join(rtl_dir, f"{dut}.v"),
]
parameters = {}
parameters['PERIOD_NS_NUM'] = 32
parameters['PERIOD_NS_DENOM'] = 5
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

@ -18,7 +18,7 @@ deps =
cocotb-bus == 0.2.1
cocotb-test == 0.2.4
cocotbext-axi == 0.1.20
cocotbext-eth == 0.1.20
cocotbext-eth == 0.1.22
scapy == 2.5.0
jinja2 == 3.1.2