diff --git a/fpga/lib/pcie/README.md b/fpga/lib/pcie/README.md index 817098acb..467bcb783 100644 --- a/fpga/lib/pcie/README.md +++ b/fpga/lib/pcie/README.md @@ -12,10 +12,20 @@ Collection of PCI express related components. Includes PCIe to AXI and AXI lite Example designs are included for the following FPGA boards: +* Alpha Data ADM-PCIE-9V3 (Xilinx Virtex UltraScale+ XCVU3P) * BittWare 520N-MX (Intel Stratix 10 MX 1SM21CHU2F53E2VG) * Exablaze ExaNIC X10 (Xilinx Kintex UltraScale XCKU035) +* Exablaze ExaNIC X25 (Xilinx Kintex UltraScale+ XCKU3P) * Silicom fb2CG@KU15P (Xilinx Kintex UltraScale+ XCKU15P) * Intel Stratix 10 MX dev kit (Intel Stratix 10 MX 1SM21CHU1F53E1VG) +* Xilinx Alveo U50 (Xilinx Virtex UltraScale+ XCU50) +* Xilinx Alveo U200 (Xilinx Virtex UltraScale+ XCU200) +* Xilinx Alveo U250 (Xilinx Virtex UltraScale+ XCU250) +* Xilinx Alveo U280 (Xilinx Virtex UltraScale+ XCU280) +* Xilinx VCU108 (Xilinx Virtex UltraScale XCVU095) +* Xilinx VCU118 (Xilinx Virtex UltraScale+ XCVU9P) +* Xilinx VCU1525 (Xilinx Virtex UltraScale+ XCVU9P) +* Xilinx ZCU106 (Xilinx Zynq UltraScale+ XCZU7EV) ## Documentation diff --git a/fpga/lib/pcie/example/520N_MX/fpga/tb/fpga_core/test_fpga_core.py b/fpga/lib/pcie/example/520N_MX/fpga/tb/fpga_core/test_fpga_core.py index b9198d503..87888d60c 100644 --- a/fpga/lib/pcie/example/520N_MX/fpga/tb/fpga_core/test_fpga_core.py +++ b/fpga/lib/pcie/example/520N_MX/fpga/tb/fpga_core/test_fpga_core.py @@ -33,7 +33,6 @@ from cocotb.triggers import RisingEdge, FallingEdge, Timer from cocotbext.pcie.core import RootComplex from cocotbext.pcie.intel.s10 import S10PcieDevice, S10RxBus, S10TxBus -from cocotbext.axi.utils import hexdump_str class TB(object): @@ -156,8 +155,8 @@ class TB(object): self.dev.functions[0].msi_multiple_message_capable = 5 - self.dev.functions[0].configure_bar(0, 2**22) - self.dev.functions[0].configure_bar(2, 2**22) + self.dev.functions[0].configure_bar(0, 2**len(dut.example_core_pcie_s10_inst.core_pcie_inst.axil_ctrl_awaddr)) + self.dev.functions[0].configure_bar(2, 2**len(dut.example_core_pcie_s10_inst.core_pcie_inst.axi_ram_awaddr)) async def init(self): diff --git a/fpga/lib/pcie/example/ADM_PCIE_9V3/fpga/README.md b/fpga/lib/pcie/example/ADM_PCIE_9V3/fpga/README.md new file mode 100644 index 000000000..de7f83b51 --- /dev/null +++ b/fpga/lib/pcie/example/ADM_PCIE_9V3/fpga/README.md @@ -0,0 +1,19 @@ +# Verilog PCIe ADM-PCIE-9V3 Example Design + +## Introduction + +This example design targets the Alpha Data ADM-PCIE-9V3 FPGA board. + +The design implements the PCIe AXI lite master module, the PCIe AXI master module, and the PCIe DMA module. A very simple Linux driver is included to test the FPGA design. + +* FPGA: xcvu3p-ffvc1517-2-i + +## How to build + +Run `make` to build. Ensure that the Xilinx Vivado components are in PATH. + +Run `make` to build the driver. Ensure the headers for the running kernel are installed, otherwise the driver cannot be compiled. + +## How to test + +Run `make program` to program the ADM-PCIE-9V3 board with Vivado. Then load the driver with `insmod example.ko`. Check dmesg for the output. diff --git a/fpga/lib/pcie/example/ADM_PCIE_9V3/fpga/common/vivado.mk b/fpga/lib/pcie/example/ADM_PCIE_9V3/fpga/common/vivado.mk new file mode 100644 index 000000000..d47a43947 --- /dev/null +++ b/fpga/lib/pcie/example/ADM_PCIE_9V3/fpga/common/vivado.mk @@ -0,0 +1,126 @@ +################################################################### +# +# 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) + +SYN_FILES_REL = $(patsubst %, ../%, $(filter-out /% ./%,$(SYN_FILES))) $(filter /% ./%,$(SYN_FILES)) +INC_FILES_REL = $(patsubst %, ../%, $(filter-out /% ./%,$(INC_FILES))) $(filter /% ./%,$(INC_FILES)) +XCI_FILES_REL = $(patsubst %, ../%, $(filter-out /% ./%,$(XCI_FILES))) $(filter /% ./%,$(XCI_FILES)) +IP_TCL_FILES_REL = $(patsubst %, ../%, $(filter-out /% ./%,$(IP_TCL_FILES))) $(filter /% ./%,$(IP_TCL_FILES)) +CONFIG_TCL_FILES_REL = $(patsubst %, ../%, $(filter-out /% ./%,$(CONFIG_TCL_FILES))) $(filter /% ./%,$(CONFIG_TCL_FILES)) + +ifdef XDC_FILES + XDC_FILES_REL = $(patsubst %, ../%, $(filter-out /% ./%,$(XDC_FILES))) $(filter /% ./%,$(XDC_FILES)) +else + XDC_FILES_REL = $(FPGA_TOP).xdc +endif + +################################################################### +# Main Targets +# +# all: build everything +# clean: remove output files and project files +################################################################### + +all: fpga + +fpga: $(FPGA_TOP).bit + +vivado: $(FPGA_TOP).xpr + vivado $(FPGA_TOP).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 program.tcl generate_mcs.tcl *.mcs *.prm flash.tcl + +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) $(FPGA_TOP)" > $@ + echo "add_files -fileset sources_1 defines.v $(SYN_FILES_REL)" >> $@ + 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) + echo "open_project -quiet $(FPGA_TOP).xpr" > $@ + for x in $(CONFIG_TCL_FILES_REL); do echo "source $$x" >> $@; done + +$(FPGA_TOP).xpr: create_project.tcl update_config.tcl + vivado -nojournal -nolog -mode batch $(foreach x,$?,-source $x) + +# synthesis run +%.runs/synth_1/%.dcp: %.xpr $(SYN_FILES_REL) $(INC_FILES_REL) $(XDC_FILES_REL) $(CONFIG_TCL_FILES_REL) + echo "open_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 +%.runs/impl_1/%_routed.dcp: %.runs/synth_1/%.dcp + echo "open_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 + vivado -nojournal -nolog -mode batch -source run_impl.tcl + +# bit file +%.bit: %.runs/impl_1/%_routed.dcp + echo "open_project $*.xpr" > generate_bit.tcl + echo "open_run impl_1" >> generate_bit.tcl + echo "write_bitstream -force $*.bit" >> generate_bit.tcl + vivado -nojournal -nolog -mode batch -source generate_bit.tcl + mkdir -p rev + EXT=bit; COUNT=100; \ + while [ -e rev/$*_rev$$COUNT.$$EXT ]; \ + do COUNT=$$((COUNT+1)); done; \ + cp $@ rev/$*_rev$$COUNT.$$EXT; \ + echo "Output: rev/$*_rev$$COUNT.$$EXT"; diff --git a/fpga/lib/pcie/example/ADM_PCIE_9V3/fpga/driver b/fpga/lib/pcie/example/ADM_PCIE_9V3/fpga/driver new file mode 120000 index 000000000..4a54c76b5 --- /dev/null +++ b/fpga/lib/pcie/example/ADM_PCIE_9V3/fpga/driver @@ -0,0 +1 @@ +../../common/driver/example/ \ No newline at end of file diff --git a/fpga/lib/pcie/example/ADM_PCIE_9V3/fpga/fpga.xdc b/fpga/lib/pcie/example/ADM_PCIE_9V3/fpga/fpga.xdc new file mode 100644 index 000000000..9810b2d08 --- /dev/null +++ b/fpga/lib/pcie/example/ADM_PCIE_9V3/fpga/fpga.xdc @@ -0,0 +1,206 @@ +# XDC constraints for the ADM-PCIE-9V3 +# part: xcvu3p-ffvc1517-2-i + +# 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.EXTMASTERCCLK_EN {DIV-1} [current_design] +set_property BITSTREAM.CONFIG.SPI_32BIT_ADDR YES [current_design] +set_property BITSTREAM.CONFIG.SPI_BUSWIDTH 8 [current_design] +set_property BITSTREAM.CONFIG.SPI_FALL_EDGE YES [current_design] +set_property BITSTREAM.CONFIG.UNUSEDPIN {Pullnone} [current_design] +set_property BITSTREAM.CONFIG.OVERTEMPSHUTDOWN Enable [current_design] + +# 300 MHz system clock +#set_property -dict {LOC AP26 IOSTANDARD LVDS DIFF_TERM_ADV TERM_100} [get_ports clk_300mhz_p] +#set_property -dict {LOC AP27 IOSTANDARD LVDS DIFF_TERM_ADV TERM_100} [get_ports clk_300mhz_n] +#create_clock -period 3.333 -name clk_300mhz [get_ports clk_300mhz_p] + +# LEDs +set_property -dict {LOC AT27 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 12} [get_ports {user_led_g[0]}] +set_property -dict {LOC AU27 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 12} [get_ports {user_led_g[1]}] +set_property -dict {LOC AU23 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 12} [get_ports {user_led_r}] +set_property -dict {LOC AH24 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 12} [get_ports {front_led[0]}] +set_property -dict {LOC AJ23 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 12} [get_ports {front_led[1]}] + +set_false_path -to [get_ports {user_led_g[*] user_led_r front_led[*]}] +set_output_delay 0 [get_ports {user_led_g[*] user_led_r front_led[*]}] + +# Switches +#set_property -dict {LOC AV27 IOSTANDARD LVCMOS18} [get_ports {user_sw[0]}] +#set_property -dict {LOC AW27 IOSTANDARD LVCMOS18} [get_ports {user_sw[1]}] + +#set_false_path -from [get_ports {user_sw[*]}] +#set_input_delay 0 [get_ports {user_sw[*]}] + +# GPIO +#set_property -dict {LOC G30 IOSTANDARD LVCMOS18} [get_ports gpio_p[0]] +#set_property -dict {LOC F30 IOSTANDARD LVCMOS18} [get_ports gpio_n[0]] +#set_property -dict {LOC J31 IOSTANDARD LVCMOS18} [get_ports gpio_p[1]] +#set_property -dict {LOC H31 IOSTANDARD LVCMOS18} [get_ports gpio_n[1]] + +# QSFP28 Interfaces +#set_property -dict {LOC G38 } [get_ports qsfp_0_rx_0_p] ;# MGTYRXP0_128 GTYE4_CHANNEL_X0Y16 / GTYE4_COMMON_X0Y4 +#set_property -dict {LOC G39 } [get_ports qsfp_0_rx_0_n] ;# MGTYRXN0_128 GTYE4_CHANNEL_X0Y16 / GTYE4_COMMON_X0Y4 +#set_property -dict {LOC F35 } [get_ports qsfp_0_tx_0_p] ;# MGTYTXP0_128 GTYE4_CHANNEL_X0Y16 / GTYE4_COMMON_X0Y4 +#set_property -dict {LOC F36 } [get_ports qsfp_0_tx_0_n] ;# MGTYTXN0_128 GTYE4_CHANNEL_X0Y16 / GTYE4_COMMON_X0Y4 +#set_property -dict {LOC E38 } [get_ports qsfp_0_rx_1_p] ;# MGTYRXP1_128 GTYE4_CHANNEL_X0Y17 / GTYE4_COMMON_X0Y4 +#set_property -dict {LOC E39 } [get_ports qsfp_0_rx_1_n] ;# MGTYRXN1_128 GTYE4_CHANNEL_X0Y17 / GTYE4_COMMON_X0Y4 +#set_property -dict {LOC D35 } [get_ports qsfp_0_tx_1_p] ;# MGTYTXP1_128 GTYE4_CHANNEL_X0Y17 / GTYE4_COMMON_X0Y4 +#set_property -dict {LOC D36 } [get_ports qsfp_0_tx_1_n] ;# MGTYTXN1_128 GTYE4_CHANNEL_X0Y17 / GTYE4_COMMON_X0Y4 +#set_property -dict {LOC C38 } [get_ports qsfp_0_rx_2_p] ;# MGTYRXP2_128 GTYE4_CHANNEL_X0Y18 / GTYE4_COMMON_X0Y4 +#set_property -dict {LOC C39 } [get_ports qsfp_0_rx_2_n] ;# MGTYRXN2_128 GTYE4_CHANNEL_X0Y18 / GTYE4_COMMON_X0Y4 +#set_property -dict {LOC C33 } [get_ports qsfp_0_tx_2_p] ;# MGTYTXP2_128 GTYE4_CHANNEL_X0Y18 / GTYE4_COMMON_X0Y4 +#set_property -dict {LOC C34 } [get_ports qsfp_0_tx_2_n] ;# MGTYTXN2_128 GTYE4_CHANNEL_X0Y18 / GTYE4_COMMON_X0Y4 +#set_property -dict {LOC B36 } [get_ports qsfp_0_rx_3_p] ;# MGTYRXP3_128 GTYE4_CHANNEL_X0Y19 / GTYE4_COMMON_X0Y4 +#set_property -dict {LOC B37 } [get_ports qsfp_0_rx_3_n] ;# MGTYRXN3_128 GTYE4_CHANNEL_X0Y19 / GTYE4_COMMON_X0Y4 +#set_property -dict {LOC A33 } [get_ports qsfp_0_tx_3_p] ;# MGTYTXP3_128 GTYE4_CHANNEL_X0Y19 / GTYE4_COMMON_X0Y4 +#set_property -dict {LOC A34 } [get_ports qsfp_0_tx_3_n] ;# MGTYTXN3_128 GTYE4_CHANNEL_X0Y19 / GTYE4_COMMON_X0Y4 +#set_property -dict {LOC N33 } [get_ports qsfp_0_mgt_refclk_p] ;# MGTREFCLK0P_128 from ? +#set_property -dict {LOC N34 } [get_ports qsfp_0_mgt_refclk_n] ;# MGTREFCLK0N_128 from ? +#set_property -dict {LOC F29 IOSTANDARD LVCMOS18 PULLUP true} [get_ports qsfp_0_modprs_l] +#set_property -dict {LOC D31 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 12} [get_ports qsfp_0_sel_l] + +# 161.1328125 MHz MGT reference clock +#create_clock -period 6.206 -name qsfp_0_mgt_refclk [get_ports qsfp_0_mgt_refclk_p] + +#set_property -dict {LOC R38 } [get_ports qsfp_1_rx_0_p] ;# MGTYRXP0_127 GTYE4_CHANNEL_X0Y12 / GTYE4_COMMON_X0Y3 +#set_property -dict {LOC R39 } [get_ports qsfp_1_rx_0_n] ;# MGTYRXN0_127 GTYE4_CHANNEL_X0Y12 / GTYE4_COMMON_X0Y3 +#set_property -dict {LOC P35 } [get_ports qsfp_1_tx_0_p] ;# MGTYTXP0_127 GTYE4_CHANNEL_X0Y12 / GTYE4_COMMON_X0Y3 +#set_property -dict {LOC P36 } [get_ports qsfp_1_tx_0_n] ;# MGTYTXN0_127 GTYE4_CHANNEL_X0Y12 / GTYE4_COMMON_X0Y3 +#set_property -dict {LOC N38 } [get_ports qsfp_1_rx_1_p] ;# MGTYRXP1_127 GTYE4_CHANNEL_X0Y13 / GTYE4_COMMON_X0Y3 +#set_property -dict {LOC N39 } [get_ports qsfp_1_rx_1_n] ;# MGTYRXN1_127 GTYE4_CHANNEL_X0Y13 / GTYE4_COMMON_X0Y3 +#set_property -dict {LOC M35 } [get_ports qsfp_1_tx_1_p] ;# MGTYTXP1_127 GTYE4_CHANNEL_X0Y13 / GTYE4_COMMON_X0Y3 +#set_property -dict {LOC M36 } [get_ports qsfp_1_tx_1_n] ;# MGTYTXN1_127 GTYE4_CHANNEL_X0Y13 / GTYE4_COMMON_X0Y3 +#set_property -dict {LOC L38 } [get_ports qsfp_1_rx_2_p] ;# MGTYRXP2_127 GTYE4_CHANNEL_X0Y14 / GTYE4_COMMON_X0Y3 +#set_property -dict {LOC L39 } [get_ports qsfp_1_rx_2_n] ;# MGTYRXN2_127 GTYE4_CHANNEL_X0Y14 / GTYE4_COMMON_X0Y3 +#set_property -dict {LOC K35 } [get_ports qsfp_1_tx_2_p] ;# MGTYTXP2_127 GTYE4_CHANNEL_X0Y14 / GTYE4_COMMON_X0Y3 +#set_property -dict {LOC K36 } [get_ports qsfp_1_tx_2_n] ;# MGTYTXN2_127 GTYE4_CHANNEL_X0Y14 / GTYE4_COMMON_X0Y3 +#set_property -dict {LOC J38 } [get_ports qsfp_1_rx_3_p] ;# MGTYRXP3_127 GTYE4_CHANNEL_X0Y15 / GTYE4_COMMON_X0Y3 +#set_property -dict {LOC J39 } [get_ports qsfp_1_rx_3_n] ;# MGTYRXN3_127 GTYE4_CHANNEL_X0Y15 / GTYE4_COMMON_X0Y3 +#set_property -dict {LOC H35 } [get_ports qsfp_1_tx_3_p] ;# MGTYTXP3_127 GTYE4_CHANNEL_X0Y15 / GTYE4_COMMON_X0Y3 +#set_property -dict {LOC H36 } [get_ports qsfp_1_tx_3_n] ;# MGTYTXN3_127 GTYE4_CHANNEL_X0Y15 / GTYE4_COMMON_X0Y3 +#set_property -dict {LOC U33 } [get_ports qsfp_1_mgt_refclk_p] ;# MGTREFCLK0P_127 from ? +#set_property -dict {LOC U34 } [get_ports qsfp_1_mgt_refclk_n] ;# MGTREFCLK0N_127 from ? +#set_property -dict {LOC F33 IOSTANDARD LVCMOS18 PULLUP true} [get_ports qsfp_1_modprs_l] +#set_property -dict {LOC D30 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 12} [get_ports qsfp_1_sel_l] + +# 161.1328125 MHz MGT reference clock +#create_clock -period 6.206 -name qsfp_1_mgt_refclk [get_ports qsfp_1_mgt_refclk_p] + +#set_property -dict {LOC B29 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 12} [get_ports qsfp_reset_l] +#set_property -dict {LOC C29 IOSTANDARD LVCMOS18 PULLUP true} [get_ports qsfp_int_l] +#set_property -dict {LOC A28 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 12 PULLUP true} [get_ports qsfp_i2c_scl] +#set_property -dict {LOC A29 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 12 PULLUP true} [get_ports qsfp_i2c_sda] + +#set_false_path -to [get_ports {qsfp_0_sel_l qsfp_1_sel_l qsfp_reset_l}] +#set_output_delay 0 [get_ports {qsfp_0_sel_l qsfp_1_sel_l qsfp_reset_l}] +#set_false_path -from [get_ports {qsfp_0_modprs_l qsfp_1_modprs_l qsfp_int_l}] +#set_input_delay 0 [get_ports {qsfp_0_modprs_l qsfp_1_modprs_l qsfp_int_l}] + +#set_false_path -to [get_ports {qsfp_i2c_sda qsfp_i2c_scl}] +#set_output_delay 0 [get_ports {qsfp_i2c_sda qsfp_i2c_scl}] +#set_false_path -from [get_ports {qsfp_i2c_sda qsfp_i2c_scl}] +#set_input_delay 0 [get_ports {qsfp_i2c_sda qsfp_i2c_scl}] + +# I2C interface +#set_property -dict {LOC AT25 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 12 PULLUP true} [get_ports eeprom_i2c_scl] +#set_property -dict {LOC AT26 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 12 PULLUP true} [get_ports eeprom_i2c_sda] +#set_property -dict {LOC AP23 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 12 PULLUP true} [get_ports eeprom_wp] + +#set_false_path -to [get_ports {eeprom_i2c_sda eeprom_i2c_scl eeprom_wp}] +#set_output_delay 0 [get_ports {eeprom_i2c_sda eeprom_i2c_scl eeprom_wp}] +#set_false_path -from [get_ports {eeprom_i2c_sda eeprom_i2c_scl}] +#set_input_delay 0 [get_ports {eeprom_i2c_sda eeprom_i2c_scl}] + +# PCIe Interface +set_property -dict {LOC J2 } [get_ports {pcie_rx_p[0]}] ;# MGTYRXP3_227 GTYE4_CHANNEL_X1Y15 / GTYE4_COMMON_X1Y3 +set_property -dict {LOC J1 } [get_ports {pcie_rx_n[0]}] ;# MGTYRXN3_227 GTYE4_CHANNEL_X1Y15 / GTYE4_COMMON_X1Y3 +set_property -dict {LOC H5 } [get_ports {pcie_tx_p[0]}] ;# MGTYTXP3_227 GTYE4_CHANNEL_X1Y15 / GTYE4_COMMON_X1Y3 +set_property -dict {LOC H4 } [get_ports {pcie_tx_n[0]}] ;# MGTYTXN3_227 GTYE4_CHANNEL_X1Y15 / GTYE4_COMMON_X1Y3 +set_property -dict {LOC L2 } [get_ports {pcie_rx_p[1]}] ;# MGTYRXP2_227 GTYE4_CHANNEL_X1Y14 / GTYE4_COMMON_X1Y3 +set_property -dict {LOC L1 } [get_ports {pcie_rx_n[1]}] ;# MGTYRXN2_227 GTYE4_CHANNEL_X1Y14 / GTYE4_COMMON_X1Y3 +set_property -dict {LOC K5 } [get_ports {pcie_tx_p[1]}] ;# MGTYTXP2_227 GTYE4_CHANNEL_X1Y14 / GTYE4_COMMON_X1Y3 +set_property -dict {LOC K4 } [get_ports {pcie_tx_n[1]}] ;# MGTYTXN2_227 GTYE4_CHANNEL_X1Y14 / GTYE4_COMMON_X1Y3 +set_property -dict {LOC N2 } [get_ports {pcie_rx_p[2]}] ;# MGTYRXP1_227 GTYE4_CHANNEL_X1Y13 / GTYE4_COMMON_X1Y3 +set_property -dict {LOC N1 } [get_ports {pcie_rx_n[2]}] ;# MGTYRXN1_227 GTYE4_CHANNEL_X1Y13 / GTYE4_COMMON_X1Y3 +set_property -dict {LOC M5 } [get_ports {pcie_tx_p[2]}] ;# MGTYTXP1_227 GTYE4_CHANNEL_X1Y13 / GTYE4_COMMON_X1Y3 +set_property -dict {LOC M4 } [get_ports {pcie_tx_n[2]}] ;# MGTYTXN1_227 GTYE4_CHANNEL_X1Y13 / GTYE4_COMMON_X1Y3 +set_property -dict {LOC R2 } [get_ports {pcie_rx_p[3]}] ;# MGTYRXP0_227 GTYE4_CHANNEL_X1Y12 / GTYE4_COMMON_X1Y3 +set_property -dict {LOC R1 } [get_ports {pcie_rx_n[3]}] ;# MGTYRXN0_227 GTYE4_CHANNEL_X1Y12 / GTYE4_COMMON_X1Y3 +set_property -dict {LOC P5 } [get_ports {pcie_tx_p[3]}] ;# MGTYTXP0_227 GTYE4_CHANNEL_X1Y12 / GTYE4_COMMON_X1Y3 +set_property -dict {LOC P4 } [get_ports {pcie_tx_n[3]}] ;# MGTYTXN0_227 GTYE4_CHANNEL_X1Y12 / GTYE4_COMMON_X1Y3 +set_property -dict {LOC U2 } [get_ports {pcie_rx_p[4]}] ;# MGTYRXP3_226 GTYE4_CHANNEL_X1Y11 / GTYE4_COMMON_X1Y2 +set_property -dict {LOC U1 } [get_ports {pcie_rx_n[4]}] ;# MGTYRXN3_226 GTYE4_CHANNEL_X1Y11 / GTYE4_COMMON_X1Y2 +set_property -dict {LOC T5 } [get_ports {pcie_tx_p[4]}] ;# MGTYTXP3_226 GTYE4_CHANNEL_X1Y11 / GTYE4_COMMON_X1Y2 +set_property -dict {LOC T4 } [get_ports {pcie_tx_n[4]}] ;# MGTYTXN3_226 GTYE4_CHANNEL_X1Y11 / GTYE4_COMMON_X1Y2 +set_property -dict {LOC W2 } [get_ports {pcie_rx_p[5]}] ;# MGTYRXP2_226 GTYE4_CHANNEL_X1Y10 / GTYE4_COMMON_X1Y2 +set_property -dict {LOC W1 } [get_ports {pcie_rx_n[5]}] ;# MGTYRXN2_226 GTYE4_CHANNEL_X1Y10 / GTYE4_COMMON_X1Y2 +set_property -dict {LOC V5 } [get_ports {pcie_tx_p[5]}] ;# MGTYTXP2_226 GTYE4_CHANNEL_X1Y10 / GTYE4_COMMON_X1Y2 +set_property -dict {LOC V4 } [get_ports {pcie_tx_n[5]}] ;# MGTYTXN2_226 GTYE4_CHANNEL_X1Y10 / GTYE4_COMMON_X1Y2 +set_property -dict {LOC AA2 } [get_ports {pcie_rx_p[6]}] ;# MGTYRXP1_226 GTYE4_CHANNEL_X1Y9 / GTYE4_COMMON_X1Y2 +set_property -dict {LOC AA1 } [get_ports {pcie_rx_n[6]}] ;# MGTYRXN1_226 GTYE4_CHANNEL_X1Y9 / GTYE4_COMMON_X1Y2 +set_property -dict {LOC AB5 } [get_ports {pcie_tx_p[6]}] ;# MGTYTXP1_226 GTYE4_CHANNEL_X1Y9 / GTYE4_COMMON_X1Y2 +set_property -dict {LOC AB4 } [get_ports {pcie_tx_n[6]}] ;# MGTYTXN1_226 GTYE4_CHANNEL_X1Y9 / GTYE4_COMMON_X1Y2 +set_property -dict {LOC AC2 } [get_ports {pcie_rx_p[7]}] ;# MGTYRXP0_226 GTYE4_CHANNEL_X1Y8 / GTYE4_COMMON_X1Y2 +set_property -dict {LOC AC1 } [get_ports {pcie_rx_n[7]}] ;# MGTYRXN0_226 GTYE4_CHANNEL_X1Y8 / GTYE4_COMMON_X1Y2 +set_property -dict {LOC AD5 } [get_ports {pcie_tx_p[7]}] ;# MGTYTXP0_226 GTYE4_CHANNEL_X1Y8 / GTYE4_COMMON_X1Y2 +set_property -dict {LOC AD4 } [get_ports {pcie_tx_n[7]}] ;# MGTYTXN0_226 GTYE4_CHANNEL_X1Y8 / GTYE4_COMMON_X1Y2 +set_property -dict {LOC AE2 } [get_ports {pcie_rx_p[8]}] ;# MGTYRXP3_225 GTYE4_CHANNEL_X1Y7 / GTYE4_COMMON_X1Y1 +set_property -dict {LOC AE1 } [get_ports {pcie_rx_n[8]}] ;# MGTYRXN3_225 GTYE4_CHANNEL_X1Y7 / GTYE4_COMMON_X1Y1 +set_property -dict {LOC AF5 } [get_ports {pcie_tx_p[8]}] ;# MGTYTXP3_225 GTYE4_CHANNEL_X1Y7 / GTYE4_COMMON_X1Y1 +set_property -dict {LOC AF4 } [get_ports {pcie_tx_n[8]}] ;# MGTYTXN3_225 GTYE4_CHANNEL_X1Y7 / GTYE4_COMMON_X1Y1 +set_property -dict {LOC AG2 } [get_ports {pcie_rx_p[9]}] ;# MGTYRXP2_225 GTYE4_CHANNEL_X1Y6 / GTYE4_COMMON_X1Y1 +set_property -dict {LOC AG1 } [get_ports {pcie_rx_n[9]}] ;# MGTYRXN2_225 GTYE4_CHANNEL_X1Y6 / GTYE4_COMMON_X1Y1 +set_property -dict {LOC AH5 } [get_ports {pcie_tx_p[9]}] ;# MGTYTXP2_225 GTYE4_CHANNEL_X1Y6 / GTYE4_COMMON_X1Y1 +set_property -dict {LOC AH4 } [get_ports {pcie_tx_n[9]}] ;# MGTYTXN2_225 GTYE4_CHANNEL_X1Y6 / GTYE4_COMMON_X1Y1 +set_property -dict {LOC AJ2 } [get_ports {pcie_rx_p[10]}] ;# MGTYRXP1_225 GTYE4_CHANNEL_X1Y5 / GTYE4_COMMON_X1Y1 +set_property -dict {LOC AJ1 } [get_ports {pcie_rx_n[10]}] ;# MGTYRXN1_225 GTYE4_CHANNEL_X1Y5 / GTYE4_COMMON_X1Y1 +set_property -dict {LOC AK5 } [get_ports {pcie_tx_p[10]}] ;# MGTYTXP1_225 GTYE4_CHANNEL_X1Y5 / GTYE4_COMMON_X1Y1 +set_property -dict {LOC AK4 } [get_ports {pcie_tx_n[10]}] ;# MGTYTXN1_225 GTYE4_CHANNEL_X1Y5 / GTYE4_COMMON_X1Y1 +set_property -dict {LOC AL2 } [get_ports {pcie_rx_p[11]}] ;# MGTYRXP0_225 GTYE4_CHANNEL_X1Y4 / GTYE4_COMMON_X1Y1 +set_property -dict {LOC AL1 } [get_ports {pcie_rx_n[11]}] ;# MGTYRXN0_225 GTYE4_CHANNEL_X1Y4 / GTYE4_COMMON_X1Y1 +set_property -dict {LOC AM5 } [get_ports {pcie_tx_p[11]}] ;# MGTYTXP0_225 GTYE4_CHANNEL_X1Y4 / GTYE4_COMMON_X1Y1 +set_property -dict {LOC AM4 } [get_ports {pcie_tx_n[11]}] ;# MGTYTXN0_225 GTYE4_CHANNEL_X1Y4 / GTYE4_COMMON_X1Y1 +set_property -dict {LOC AN2 } [get_ports {pcie_rx_p[12]}] ;# MGTYRXP3_224 GTYE4_CHANNEL_X1Y3 / GTYE4_COMMON_X1Y0 +set_property -dict {LOC AN1 } [get_ports {pcie_rx_n[12]}] ;# MGTYRXN3_224 GTYE4_CHANNEL_X1Y3 / GTYE4_COMMON_X1Y0 +set_property -dict {LOC AP5 } [get_ports {pcie_tx_p[12]}] ;# MGTYTXP3_224 GTYE4_CHANNEL_X1Y3 / GTYE4_COMMON_X1Y0 +set_property -dict {LOC AP4 } [get_ports {pcie_tx_n[12]}] ;# MGTYTXN3_224 GTYE4_CHANNEL_X1Y3 / GTYE4_COMMON_X1Y0 +set_property -dict {LOC AR2 } [get_ports {pcie_rx_p[13]}] ;# MGTYRXP2_224 GTYE4_CHANNEL_X1Y2 / GTYE4_COMMON_X1Y0 +set_property -dict {LOC AR1 } [get_ports {pcie_rx_n[13]}] ;# MGTYRXN2_224 GTYE4_CHANNEL_X1Y2 / GTYE4_COMMON_X1Y0 +set_property -dict {LOC AT5 } [get_ports {pcie_tx_p[13]}] ;# MGTYTXP2_224 GTYE4_CHANNEL_X1Y2 / GTYE4_COMMON_X1Y0 +set_property -dict {LOC AT4 } [get_ports {pcie_tx_n[13]}] ;# MGTYTXN2_224 GTYE4_CHANNEL_X1Y2 / GTYE4_COMMON_X1Y0 +set_property -dict {LOC AU2 } [get_ports {pcie_rx_p[14]}] ;# MGTYRXP1_224 GTYE4_CHANNEL_X1Y1 / GTYE4_COMMON_X1Y0 +set_property -dict {LOC AU1 } [get_ports {pcie_rx_n[14]}] ;# MGTYRXN1_224 GTYE4_CHANNEL_X1Y1 / GTYE4_COMMON_X1Y0 +set_property -dict {LOC AU7 } [get_ports {pcie_tx_p[14]}] ;# MGTYTXP1_224 GTYE4_CHANNEL_X1Y1 / GTYE4_COMMON_X1Y0 +set_property -dict {LOC AU6 } [get_ports {pcie_tx_n[14]}] ;# MGTYTXN1_224 GTYE4_CHANNEL_X1Y1 / GTYE4_COMMON_X1Y0 +set_property -dict {LOC AV4 } [get_ports {pcie_rx_p[15]}] ;# MGTYRXP0_224 GTYE4_CHANNEL_X1Y0 / GTYE4_COMMON_X1Y0 +set_property -dict {LOC AV3 } [get_ports {pcie_rx_n[15]}] ;# MGTYRXN0_224 GTYE4_CHANNEL_X1Y0 / GTYE4_COMMON_X1Y0 +set_property -dict {LOC AW7 } [get_ports {pcie_tx_p[15]}] ;# MGTYTXP0_224 GTYE4_CHANNEL_X1Y0 / GTYE4_COMMON_X1Y0 +set_property -dict {LOC AW6 } [get_ports {pcie_tx_n[15]}] ;# MGTYTXN0_224 GTYE4_CHANNEL_X1Y0 / GTYE4_COMMON_X1Y0 +set_property -dict {LOC AA7 } [get_ports pcie_refclk_1_p] ;# MGTREFCLK0P_226 +set_property -dict {LOC AA6 } [get_ports pcie_refclk_1_n] ;# MGTREFCLK0N_226 +#set_property -dict {LOC AJ7 } [get_ports pcie_refclk_2_p] ;# MGTREFCLK0P_224 +#set_property -dict {LOC AJ6 } [get_ports pcie_refclk_2_n] ;# MGTREFCLK0N_224 +set_property -dict {LOC AJ31 IOSTANDARD LVCMOS18 PULLUP true} [get_ports perst_0] +#set_property -dict {LOC AH29 IOSTANDARD LVCMOS18 PULLUP true} [get_ports perst_1] + +# 100 MHz MGT reference clock +create_clock -period 10 -name pcie_mgt_refclk_1 [get_ports pcie_refclk_1_p] +#create_clock -period 10 -name pcie_mgt_refclk_2 [get_ports pcie_refclk_2_p] + +set_false_path -from [get_ports {perst_0}] +set_input_delay 0 [get_ports {perst_0}] + +# QSPI flash +#set_property -dict {LOC AF30 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {qspi_1_dq[0]}] +#set_property -dict {LOC AG30 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {qspi_1_dq[1]}] +#set_property -dict {LOC AF28 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {qspi_1_dq[2]}] +#set_property -dict {LOC AG28 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {qspi_1_dq[3]}] +#set_property -dict {LOC AV30 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {qspi_1_cs}] + +#set_false_path -to [get_ports {qspi_1_dq[*] qspi_1_cs}] +#set_output_delay 0 [get_ports {qspi_1_dq[*] qspi_1_cs}] +#set_false_path -from [get_ports {qspi_1_dq}] +#set_input_delay 0 [get_ports {qspi_1_dq}] diff --git a/fpga/lib/pcie/example/ADM_PCIE_9V3/fpga/fpga/Makefile b/fpga/lib/pcie/example/ADM_PCIE_9V3/fpga/fpga/Makefile new file mode 100644 index 000000000..a056e3ea0 --- /dev/null +++ b/fpga/lib/pcie/example/ADM_PCIE_9V3/fpga/fpga/Makefile @@ -0,0 +1,94 @@ + +# FPGA settings +FPGA_PART = xcvu3p-ffvc1517-2-i +FPGA_TOP = fpga +FPGA_ARCH = virtexuplus + +# Files for synthesis +SYN_FILES = rtl/fpga.v +SYN_FILES += rtl/fpga_core.v +SYN_FILES += rtl/debounce_switch.v +SYN_FILES += rtl/sync_reset.v +SYN_FILES += rtl/sync_signal.v +SYN_FILES += rtl/common/example_core_pcie_us.v +SYN_FILES += rtl/common/example_core_pcie.v +SYN_FILES += rtl/common/example_core.v +SYN_FILES += rtl/common/axi_ram.v +SYN_FILES += lib/pcie/rtl/pcie_us_if.v +SYN_FILES += lib/pcie/rtl/pcie_us_if_rc.v +SYN_FILES += lib/pcie/rtl/pcie_us_if_rq.v +SYN_FILES += lib/pcie/rtl/pcie_us_if_cq.v +SYN_FILES += lib/pcie/rtl/pcie_us_if_cc.v +SYN_FILES += lib/pcie/rtl/pcie_us_cfg.v +SYN_FILES += lib/pcie/rtl/pcie_us_msi.v +SYN_FILES += lib/pcie/rtl/pcie_axil_master.v +SYN_FILES += lib/pcie/rtl/pcie_axi_master.v +SYN_FILES += lib/pcie/rtl/pcie_axi_master_rd.v +SYN_FILES += lib/pcie/rtl/pcie_axi_master_wr.v +SYN_FILES += lib/pcie/rtl/pcie_tlp_demux_bar.v +SYN_FILES += lib/pcie/rtl/pcie_tlp_demux.v +SYN_FILES += lib/pcie/rtl/pcie_tlp_mux.v +SYN_FILES += lib/pcie/rtl/dma_if_pcie.v +SYN_FILES += lib/pcie/rtl/dma_if_pcie_rd.v +SYN_FILES += lib/pcie/rtl/dma_if_pcie_wr.v +SYN_FILES += lib/pcie/rtl/dma_psdpram.v +SYN_FILES += lib/pcie/rtl/arbiter.v +SYN_FILES += lib/pcie/rtl/priority_encoder.v +SYN_FILES += lib/pcie/rtl/pulse_merge.v + +# XDC files +XDC_FILES = fpga.xdc + +# IP +IP_TCL_FILES = ip/pcie4_uscale_plus_0.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 64 -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 {mt25qu256-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 + diff --git a/fpga/lib/pcie/example/ADM_PCIE_9V3/fpga/ip/pcie4_uscale_plus_0.tcl b/fpga/lib/pcie/example/ADM_PCIE_9V3/fpga/ip/pcie4_uscale_plus_0.tcl new file mode 100644 index 000000000..01d44aa32 --- /dev/null +++ b/fpga/lib/pcie/example/ADM_PCIE_9V3/fpga/ip/pcie4_uscale_plus_0.tcl @@ -0,0 +1,28 @@ + +create_ip -name pcie4_uscale_plus -vendor xilinx.com -library ip -module_name pcie4_uscale_plus_0 + +set_property -dict [list \ + CONFIG.PL_LINK_CAP_MAX_LINK_SPEED {8.0_GT/s} \ + CONFIG.PL_LINK_CAP_MAX_LINK_WIDTH {X16} \ + CONFIG.AXISTEN_IF_EXT_512_RQ_STRADDLE {false} \ + CONFIG.axisten_if_enable_client_tag {true} \ + CONFIG.axisten_if_width {512_bit} \ + CONFIG.axisten_freq {250} \ + CONFIG.PF0_CLASS_CODE {058000} \ + CONFIG.PF0_DEVICE_ID {0001} \ + CONFIG.PF0_MSI_CAP_MULTIMSGCAP {32_vectors} \ + CONFIG.PF0_SUBSYSTEM_ID {9003} \ + CONFIG.PF0_SUBSYSTEM_VENDOR_ID {4144} \ + CONFIG.pf0_bar0_64bit {true} \ + CONFIG.pf0_bar0_prefetchable {true} \ + CONFIG.pf0_bar0_scale {Megabytes} \ + CONFIG.pf0_bar0_size {16} \ + CONFIG.pf0_bar2_64bit {true} \ + CONFIG.pf0_bar2_prefetchable {true} \ + CONFIG.pf0_bar2_enabled {true} \ + CONFIG.pf0_bar2_type {Memory} \ + CONFIG.pf0_bar2_scale {Megabytes} \ + CONFIG.pf0_bar2_size {16} \ + CONFIG.vendor_id {1234} \ + CONFIG.en_msi_per_vec_masking {true} \ +] [get_ips pcie4_uscale_plus_0] diff --git a/fpga/lib/pcie/example/ADM_PCIE_9V3/fpga/lib/pcie b/fpga/lib/pcie/example/ADM_PCIE_9V3/fpga/lib/pcie new file mode 120000 index 000000000..11a54ed36 --- /dev/null +++ b/fpga/lib/pcie/example/ADM_PCIE_9V3/fpga/lib/pcie @@ -0,0 +1 @@ +../../../../ \ No newline at end of file diff --git a/fpga/lib/pcie/example/ADM_PCIE_9V3/fpga/rtl/common b/fpga/lib/pcie/example/ADM_PCIE_9V3/fpga/rtl/common new file mode 120000 index 000000000..e60fada70 --- /dev/null +++ b/fpga/lib/pcie/example/ADM_PCIE_9V3/fpga/rtl/common @@ -0,0 +1 @@ +../../../common/rtl/ \ No newline at end of file diff --git a/fpga/lib/pcie/example/ADM_PCIE_9V3/fpga/rtl/debounce_switch.v b/fpga/lib/pcie/example/ADM_PCIE_9V3/fpga/rtl/debounce_switch.v new file mode 100644 index 000000000..8e93a50c4 --- /dev/null +++ b/fpga/lib/pcie/example/ADM_PCIE_9V3/fpga/rtl/debounce_switch.v @@ -0,0 +1,93 @@ +/* + +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 diff --git a/fpga/lib/pcie/example/ADM_PCIE_9V3/fpga/rtl/fpga.v b/fpga/lib/pcie/example/ADM_PCIE_9V3/fpga/rtl/fpga.v new file mode 100644 index 000000000..af5e55463 --- /dev/null +++ b/fpga/lib/pcie/example/ADM_PCIE_9V3/fpga/rtl/fpga.v @@ -0,0 +1,449 @@ +/* + +Copyright (c) 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 1ns / 1ps +`default_nettype none + +/* + * FPGA top-level module + */ +module fpga ( + /* + * GPIO + */ + output wire [1:0] user_led_g, + output wire user_led_r, + output wire [1:0] front_led, + + /* + * PCI express + */ + input wire [15:0] pcie_rx_p, + input wire [15:0] pcie_rx_n, + output wire [15:0] pcie_tx_p, + output wire [15:0] pcie_tx_n, + input wire pcie_refclk_1_p, + input wire pcie_refclk_1_n, + input wire perst_0 +); + +parameter AXIS_PCIE_DATA_WIDTH = 512; +parameter AXIS_PCIE_KEEP_WIDTH = (AXIS_PCIE_DATA_WIDTH/32); +parameter AXIS_PCIE_RC_USER_WIDTH = AXIS_PCIE_DATA_WIDTH < 512 ? 75 : 161; +parameter AXIS_PCIE_RQ_USER_WIDTH = AXIS_PCIE_DATA_WIDTH < 512 ? 60 : 137; +parameter AXIS_PCIE_CQ_USER_WIDTH = AXIS_PCIE_DATA_WIDTH < 512 ? 85 : 183; +parameter AXIS_PCIE_CC_USER_WIDTH = AXIS_PCIE_DATA_WIDTH < 512 ? 33 : 81; + +parameter RQ_SEQ_NUM_WIDTH = AXIS_PCIE_RQ_USER_WIDTH == 60 ? 4 : 6; +parameter RQ_SEQ_NUM_ENABLE = 1; + +parameter PCIE_TAG_COUNT = 64; +parameter BAR0_APERTURE = 24; +parameter BAR2_APERTURE = 24; + +// PCIe +wire pcie_user_clk; +wire pcie_user_reset; + +wire pcie_sys_clk; +wire pcie_sys_clk_gt; + +IBUFDS_GTE4 #( + .REFCLK_HROW_CK_SEL(2'b00) +) +ibufds_gte4_pcie_mgt_refclk_inst ( + .I (pcie_refclk_1_p), + .IB (pcie_refclk_1_n), + .CEB (1'b0), + .O (pcie_sys_clk_gt), + .ODIV2 (pcie_sys_clk) +); + +wire [AXIS_PCIE_DATA_WIDTH-1:0] axis_rq_tdata; +wire [AXIS_PCIE_KEEP_WIDTH-1:0] axis_rq_tkeep; +wire axis_rq_tlast; +wire axis_rq_tready; +wire [AXIS_PCIE_RQ_USER_WIDTH-1:0] axis_rq_tuser; +wire axis_rq_tvalid; + +wire [AXIS_PCIE_DATA_WIDTH-1:0] axis_rc_tdata; +wire [AXIS_PCIE_KEEP_WIDTH-1:0] axis_rc_tkeep; +wire axis_rc_tlast; +wire axis_rc_tready; +wire [AXIS_PCIE_RC_USER_WIDTH-1:0] axis_rc_tuser; +wire axis_rc_tvalid; + +wire [AXIS_PCIE_DATA_WIDTH-1:0] axis_cq_tdata; +wire [AXIS_PCIE_KEEP_WIDTH-1:0] axis_cq_tkeep; +wire axis_cq_tlast; +wire axis_cq_tready; +wire [AXIS_PCIE_CQ_USER_WIDTH-1:0] axis_cq_tuser; +wire axis_cq_tvalid; + +wire [AXIS_PCIE_DATA_WIDTH-1:0] axis_cc_tdata; +wire [AXIS_PCIE_KEEP_WIDTH-1:0] axis_cc_tkeep; +wire axis_cc_tlast; +wire axis_cc_tready; +wire [AXIS_PCIE_CC_USER_WIDTH-1:0] axis_cc_tuser; +wire axis_cc_tvalid; + +wire [RQ_SEQ_NUM_WIDTH-1:0] pcie_rq_seq_num0; +wire pcie_rq_seq_num_vld0; +wire [RQ_SEQ_NUM_WIDTH-1:0] pcie_rq_seq_num1; +wire pcie_rq_seq_num_vld1; + +// ila_0 rq_ila ( +// .clk(pcie_user_clk), +// .probe0(axis_rq_tdata), +// .probe1(axis_rq_tkeep), +// .probe2(axis_rq_tlast), +// .probe3(axis_rq_tready), +// .probe4(axis_rq_tuser), +// .probe5(axis_rq_tvalid) +// ); + +// ila_0 rc_ila ( +// .clk(pcie_user_clk), +// .probe0(axis_rc_tdata), +// .probe1(axis_rc_tkeep), +// .probe2(axis_rc_tlast), +// .probe3(axis_rc_tready), +// .probe4(axis_rc_tuser), +// .probe5(axis_rc_tvalid) +// ); + +wire [2:0] cfg_max_payload; +wire [2:0] cfg_max_read_req; + +wire [9:0] cfg_mgmt_addr; +wire [7:0] cfg_mgmt_function_number; +wire cfg_mgmt_write; +wire [31:0] cfg_mgmt_write_data; +wire [3:0] cfg_mgmt_byte_enable; +wire cfg_mgmt_read; +wire [31:0] cfg_mgmt_read_data; +wire cfg_mgmt_read_write_done; + +wire [7:0] cfg_fc_ph; +wire [11:0] cfg_fc_pd; +wire [7:0] cfg_fc_nph; +wire [11:0] cfg_fc_npd; +wire [7:0] cfg_fc_cplh; +wire [11:0] cfg_fc_cpld; +wire [2:0] cfg_fc_sel; + +wire [3:0] cfg_interrupt_msi_enable; +wire [11:0] cfg_interrupt_msi_mmenable; +wire cfg_interrupt_msi_mask_update; +wire [31:0] cfg_interrupt_msi_data; +wire [3:0] cfg_interrupt_msi_select; +wire [31:0] cfg_interrupt_msi_int; +wire [31:0] cfg_interrupt_msi_pending_status; +wire cfg_interrupt_msi_pending_status_data_enable; +wire [3:0] cfg_interrupt_msi_pending_status_function_num; +wire cfg_interrupt_msi_sent; +wire cfg_interrupt_msi_fail; +wire [2:0] cfg_interrupt_msi_attr; +wire cfg_interrupt_msi_tph_present; +wire [1:0] cfg_interrupt_msi_tph_type; +wire [8:0] cfg_interrupt_msi_tph_st_tag; +wire [3:0] cfg_interrupt_msi_function_number; + +wire status_error_cor; +wire status_error_uncor; + +pcie4_uscale_plus_0 +pcie4_uscale_plus_inst ( + .pci_exp_txn(pcie_tx_n), + .pci_exp_txp(pcie_tx_p), + .pci_exp_rxn(pcie_rx_n), + .pci_exp_rxp(pcie_rx_p), + .user_clk(pcie_user_clk), + .user_reset(pcie_user_reset), + .user_lnk_up(), + + .s_axis_rq_tdata(axis_rq_tdata), + .s_axis_rq_tkeep(axis_rq_tkeep), + .s_axis_rq_tlast(axis_rq_tlast), + .s_axis_rq_tready(axis_rq_tready), + .s_axis_rq_tuser(axis_rq_tuser), + .s_axis_rq_tvalid(axis_rq_tvalid), + + .m_axis_rc_tdata(axis_rc_tdata), + .m_axis_rc_tkeep(axis_rc_tkeep), + .m_axis_rc_tlast(axis_rc_tlast), + .m_axis_rc_tready(axis_rc_tready), + .m_axis_rc_tuser(axis_rc_tuser), + .m_axis_rc_tvalid(axis_rc_tvalid), + + .m_axis_cq_tdata(axis_cq_tdata), + .m_axis_cq_tkeep(axis_cq_tkeep), + .m_axis_cq_tlast(axis_cq_tlast), + .m_axis_cq_tready(axis_cq_tready), + .m_axis_cq_tuser(axis_cq_tuser), + .m_axis_cq_tvalid(axis_cq_tvalid), + + .s_axis_cc_tdata(axis_cc_tdata), + .s_axis_cc_tkeep(axis_cc_tkeep), + .s_axis_cc_tlast(axis_cc_tlast), + .s_axis_cc_tready(axis_cc_tready), + .s_axis_cc_tuser(axis_cc_tuser), + .s_axis_cc_tvalid(axis_cc_tvalid), + + .pcie_rq_seq_num0(pcie_rq_seq_num0), + .pcie_rq_seq_num_vld0(pcie_rq_seq_num_vld0), + .pcie_rq_seq_num1(pcie_rq_seq_num1), + .pcie_rq_seq_num_vld1(pcie_rq_seq_num_vld1), + .pcie_rq_tag0(), + .pcie_rq_tag1(), + .pcie_rq_tag_av(), + .pcie_rq_tag_vld0(), + .pcie_rq_tag_vld1(), + + .pcie_tfc_nph_av(), + .pcie_tfc_npd_av(), + + .pcie_cq_np_req(1'b1), + .pcie_cq_np_req_count(), + + .cfg_phy_link_down(), + .cfg_phy_link_status(), + .cfg_negotiated_width(), + .cfg_current_speed(), + .cfg_max_payload(cfg_max_payload), + .cfg_max_read_req(cfg_max_read_req), + .cfg_function_status(), + .cfg_function_power_state(), + .cfg_vf_status(), + .cfg_vf_power_state(), + .cfg_link_power_state(), + + .cfg_mgmt_addr(cfg_mgmt_addr), + .cfg_mgmt_function_number(cfg_mgmt_function_number), + .cfg_mgmt_write(cfg_mgmt_write), + .cfg_mgmt_write_data(cfg_mgmt_write_data), + .cfg_mgmt_byte_enable(cfg_mgmt_byte_enable), + .cfg_mgmt_read(cfg_mgmt_read), + .cfg_mgmt_read_data(cfg_mgmt_read_data), + .cfg_mgmt_read_write_done(cfg_mgmt_read_write_done), + .cfg_mgmt_debug_access(1'b0), + + .cfg_err_cor_out(), + .cfg_err_nonfatal_out(), + .cfg_err_fatal_out(), + .cfg_local_error_valid(), + .cfg_local_error_out(), + .cfg_ltssm_state(), + .cfg_rx_pm_state(), + .cfg_tx_pm_state(), + .cfg_rcb_status(), + .cfg_obff_enable(), + .cfg_pl_status_change(), + .cfg_tph_requester_enable(), + .cfg_tph_st_mode(), + .cfg_vf_tph_requester_enable(), + .cfg_vf_tph_st_mode(), + + .cfg_msg_received(), + .cfg_msg_received_data(), + .cfg_msg_received_type(), + .cfg_msg_transmit(1'b0), + .cfg_msg_transmit_type(3'd0), + .cfg_msg_transmit_data(32'd0), + .cfg_msg_transmit_done(), + + .cfg_fc_ph(cfg_fc_ph), + .cfg_fc_pd(cfg_fc_pd), + .cfg_fc_nph(cfg_fc_nph), + .cfg_fc_npd(cfg_fc_npd), + .cfg_fc_cplh(cfg_fc_cplh), + .cfg_fc_cpld(cfg_fc_cpld), + .cfg_fc_sel(cfg_fc_sel), + + .cfg_dsn(64'd0), + + .cfg_bus_number(), + + .cfg_power_state_change_ack(1'b1), + .cfg_power_state_change_interrupt(), + + .cfg_err_cor_in(status_error_cor), + .cfg_err_uncor_in(status_error_uncor), + .cfg_flr_in_process(), + .cfg_flr_done(4'd0), + .cfg_vf_flr_in_process(), + .cfg_vf_flr_func_num(8'd0), + .cfg_vf_flr_done(8'd0), + + .cfg_link_training_enable(1'b1), + + .cfg_interrupt_int(4'd0), + .cfg_interrupt_pending(4'd0), + .cfg_interrupt_sent(), + .cfg_interrupt_msi_enable(cfg_interrupt_msi_enable), + .cfg_interrupt_msi_mmenable(cfg_interrupt_msi_mmenable), + .cfg_interrupt_msi_mask_update(cfg_interrupt_msi_mask_update), + .cfg_interrupt_msi_data(cfg_interrupt_msi_data), + .cfg_interrupt_msi_select(cfg_interrupt_msi_select), + .cfg_interrupt_msi_int(cfg_interrupt_msi_int), + .cfg_interrupt_msi_pending_status(cfg_interrupt_msi_pending_status), + .cfg_interrupt_msi_pending_status_data_enable(cfg_interrupt_msi_pending_status_data_enable), + .cfg_interrupt_msi_pending_status_function_num(cfg_interrupt_msi_pending_status_function_num), + .cfg_interrupt_msi_sent(cfg_interrupt_msi_sent), + .cfg_interrupt_msi_fail(cfg_interrupt_msi_fail), + .cfg_interrupt_msi_attr(cfg_interrupt_msi_attr), + .cfg_interrupt_msi_tph_present(cfg_interrupt_msi_tph_present), + .cfg_interrupt_msi_tph_type(cfg_interrupt_msi_tph_type), + .cfg_interrupt_msi_tph_st_tag(cfg_interrupt_msi_tph_st_tag), + .cfg_interrupt_msi_function_number(cfg_interrupt_msi_function_number), + + .cfg_pm_aspm_l1_entry_reject(1'b0), + .cfg_pm_aspm_tx_l0s_entry_disable(1'b0), + + .cfg_hot_reset_out(), + + .cfg_config_space_enable(1'b1), + .cfg_req_pm_transition_l23_ready(1'b0), + .cfg_hot_reset_in(1'b0), + + .cfg_ds_port_number(8'd0), + .cfg_ds_bus_number(8'd0), + .cfg_ds_device_number(5'd0), + + .sys_clk(pcie_sys_clk), + .sys_clk_gt(pcie_sys_clk_gt), + .sys_reset(perst_0), + + .phy_rdy_out() +); + +fpga_core #( + .AXIS_PCIE_DATA_WIDTH(AXIS_PCIE_DATA_WIDTH), + .AXIS_PCIE_KEEP_WIDTH(AXIS_PCIE_KEEP_WIDTH), + .AXIS_PCIE_RC_USER_WIDTH(AXIS_PCIE_RC_USER_WIDTH), + .AXIS_PCIE_RQ_USER_WIDTH(AXIS_PCIE_RQ_USER_WIDTH), + .AXIS_PCIE_CQ_USER_WIDTH(AXIS_PCIE_CQ_USER_WIDTH), + .AXIS_PCIE_CC_USER_WIDTH(AXIS_PCIE_CC_USER_WIDTH), + .RQ_SEQ_NUM_WIDTH(RQ_SEQ_NUM_WIDTH), + .RQ_SEQ_NUM_ENABLE(RQ_SEQ_NUM_ENABLE), + .PCIE_TAG_COUNT(PCIE_TAG_COUNT), + .BAR0_APERTURE(BAR0_APERTURE), + .BAR2_APERTURE(BAR2_APERTURE) +) +core_inst ( + /* + * Clock: 250 MHz + * Synchronous reset + */ + .clk(pcie_user_clk), + .rst(pcie_user_reset), + /* + * GPIO + */ + .user_led_g(user_led_g), + .user_led_r(user_led_r), + .front_led(front_led), + /* + * PCIe + */ + .m_axis_rq_tdata(axis_rq_tdata), + .m_axis_rq_tkeep(axis_rq_tkeep), + .m_axis_rq_tlast(axis_rq_tlast), + .m_axis_rq_tready(axis_rq_tready), + .m_axis_rq_tuser(axis_rq_tuser), + .m_axis_rq_tvalid(axis_rq_tvalid), + + .s_axis_rc_tdata(axis_rc_tdata), + .s_axis_rc_tkeep(axis_rc_tkeep), + .s_axis_rc_tlast(axis_rc_tlast), + .s_axis_rc_tready(axis_rc_tready), + .s_axis_rc_tuser(axis_rc_tuser), + .s_axis_rc_tvalid(axis_rc_tvalid), + + .s_axis_cq_tdata(axis_cq_tdata), + .s_axis_cq_tkeep(axis_cq_tkeep), + .s_axis_cq_tlast(axis_cq_tlast), + .s_axis_cq_tready(axis_cq_tready), + .s_axis_cq_tuser(axis_cq_tuser), + .s_axis_cq_tvalid(axis_cq_tvalid), + + .m_axis_cc_tdata(axis_cc_tdata), + .m_axis_cc_tkeep(axis_cc_tkeep), + .m_axis_cc_tlast(axis_cc_tlast), + .m_axis_cc_tready(axis_cc_tready), + .m_axis_cc_tuser(axis_cc_tuser), + .m_axis_cc_tvalid(axis_cc_tvalid), + + .s_axis_rq_seq_num_0(pcie_rq_seq_num0), + .s_axis_rq_seq_num_valid_0(pcie_rq_seq_num_vld0), + .s_axis_rq_seq_num_1(pcie_rq_seq_num1), + .s_axis_rq_seq_num_valid_1(pcie_rq_seq_num_vld1), + + .cfg_max_payload(cfg_max_payload), + .cfg_max_read_req(cfg_max_read_req), + + .cfg_mgmt_addr(cfg_mgmt_addr), + .cfg_mgmt_function_number(cfg_mgmt_function_number), + .cfg_mgmt_write(cfg_mgmt_write), + .cfg_mgmt_write_data(cfg_mgmt_write_data), + .cfg_mgmt_byte_enable(cfg_mgmt_byte_enable), + .cfg_mgmt_read(cfg_mgmt_read), + .cfg_mgmt_read_data(cfg_mgmt_read_data), + .cfg_mgmt_read_write_done(cfg_mgmt_read_write_done), + + .cfg_fc_ph(cfg_fc_ph), + .cfg_fc_pd(cfg_fc_pd), + .cfg_fc_nph(cfg_fc_nph), + .cfg_fc_npd(cfg_fc_npd), + .cfg_fc_cplh(cfg_fc_cplh), + .cfg_fc_cpld(cfg_fc_cpld), + .cfg_fc_sel(cfg_fc_sel), + + .cfg_interrupt_msi_enable(cfg_interrupt_msi_enable), + .cfg_interrupt_msi_mmenable(cfg_interrupt_msi_mmenable), + .cfg_interrupt_msi_mask_update(cfg_interrupt_msi_mask_update), + .cfg_interrupt_msi_data(cfg_interrupt_msi_data), + .cfg_interrupt_msi_select(cfg_interrupt_msi_select), + .cfg_interrupt_msi_int(cfg_interrupt_msi_int), + .cfg_interrupt_msi_pending_status(cfg_interrupt_msi_pending_status), + .cfg_interrupt_msi_pending_status_data_enable(cfg_interrupt_msi_pending_status_data_enable), + .cfg_interrupt_msi_pending_status_function_num(cfg_interrupt_msi_pending_status_function_num), + .cfg_interrupt_msi_sent(cfg_interrupt_msi_sent), + .cfg_interrupt_msi_fail(cfg_interrupt_msi_fail), + .cfg_interrupt_msi_attr(cfg_interrupt_msi_attr), + .cfg_interrupt_msi_tph_present(cfg_interrupt_msi_tph_present), + .cfg_interrupt_msi_tph_type(cfg_interrupt_msi_tph_type), + .cfg_interrupt_msi_tph_st_tag(cfg_interrupt_msi_tph_st_tag), + .cfg_interrupt_msi_function_number(cfg_interrupt_msi_function_number), + + .status_error_cor(status_error_cor), + .status_error_uncor(status_error_uncor) +); + +endmodule + +`resetall diff --git a/fpga/lib/pcie/example/ADM_PCIE_9V3/fpga/rtl/fpga_core.v b/fpga/lib/pcie/example/ADM_PCIE_9V3/fpga/rtl/fpga_core.v new file mode 100644 index 000000000..0ff9616b8 --- /dev/null +++ b/fpga/lib/pcie/example/ADM_PCIE_9V3/fpga/rtl/fpga_core.v @@ -0,0 +1,274 @@ +/* + +Copyright (c) 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 1ns / 1ps +`default_nettype none + +/* + * FPGA core logic + */ +module fpga_core # +( + parameter AXIS_PCIE_DATA_WIDTH = 512, + parameter AXIS_PCIE_KEEP_WIDTH = (AXIS_PCIE_DATA_WIDTH/32), + parameter AXIS_PCIE_RC_USER_WIDTH = AXIS_PCIE_DATA_WIDTH < 512 ? 75 : 161, + parameter AXIS_PCIE_RQ_USER_WIDTH = AXIS_PCIE_DATA_WIDTH < 512 ? 60 : 137, + parameter AXIS_PCIE_CQ_USER_WIDTH = AXIS_PCIE_DATA_WIDTH < 512 ? 85 : 183, + parameter AXIS_PCIE_CC_USER_WIDTH = AXIS_PCIE_DATA_WIDTH < 512 ? 33 : 81, + parameter RQ_SEQ_NUM_WIDTH = AXIS_PCIE_RQ_USER_WIDTH == 60 ? 4 : 6, + parameter RQ_SEQ_NUM_ENABLE = 1, + parameter PCIE_TAG_COUNT = 64, + parameter BAR0_APERTURE = 24, + parameter BAR2_APERTURE = 24 +) +( + /* + * Clock: 250 MHz + * Synchronous reset + */ + input wire clk, + input wire rst, + + /* + * GPIO + */ + output wire [1:0] user_led_g, + output wire user_led_r, + output wire [1:0] front_led, + + /* + * PCIe + */ + output wire [AXIS_PCIE_DATA_WIDTH-1:0] m_axis_rq_tdata, + output wire [AXIS_PCIE_KEEP_WIDTH-1:0] m_axis_rq_tkeep, + output wire m_axis_rq_tlast, + input wire m_axis_rq_tready, + output wire [AXIS_PCIE_RQ_USER_WIDTH-1:0] m_axis_rq_tuser, + output wire m_axis_rq_tvalid, + + input wire [AXIS_PCIE_DATA_WIDTH-1:0] s_axis_rc_tdata, + input wire [AXIS_PCIE_KEEP_WIDTH-1:0] s_axis_rc_tkeep, + input wire s_axis_rc_tlast, + output wire s_axis_rc_tready, + input wire [AXIS_PCIE_RC_USER_WIDTH-1:0] s_axis_rc_tuser, + input wire s_axis_rc_tvalid, + + input wire [AXIS_PCIE_DATA_WIDTH-1:0] s_axis_cq_tdata, + input wire [AXIS_PCIE_KEEP_WIDTH-1:0] s_axis_cq_tkeep, + input wire s_axis_cq_tlast, + output wire s_axis_cq_tready, + input wire [AXIS_PCIE_CQ_USER_WIDTH-1:0] s_axis_cq_tuser, + input wire s_axis_cq_tvalid, + + output wire [AXIS_PCIE_DATA_WIDTH-1:0] m_axis_cc_tdata, + output wire [AXIS_PCIE_KEEP_WIDTH-1:0] m_axis_cc_tkeep, + output wire m_axis_cc_tlast, + input wire m_axis_cc_tready, + output wire [AXIS_PCIE_CC_USER_WIDTH-1:0] m_axis_cc_tuser, + output wire m_axis_cc_tvalid, + + input wire [RQ_SEQ_NUM_WIDTH-1:0] s_axis_rq_seq_num_0, + input wire s_axis_rq_seq_num_valid_0, + input wire [RQ_SEQ_NUM_WIDTH-1:0] s_axis_rq_seq_num_1, + input wire s_axis_rq_seq_num_valid_1, + + input wire [2:0] cfg_max_payload, + input wire [2:0] cfg_max_read_req, + + output wire [9:0] cfg_mgmt_addr, + output wire [7:0] cfg_mgmt_function_number, + output wire cfg_mgmt_write, + output wire [31:0] cfg_mgmt_write_data, + output wire [3:0] cfg_mgmt_byte_enable, + output wire cfg_mgmt_read, + input wire [31:0] cfg_mgmt_read_data, + input wire cfg_mgmt_read_write_done, + + input wire [7:0] cfg_fc_ph, + input wire [11:0] cfg_fc_pd, + input wire [7:0] cfg_fc_nph, + input wire [11:0] cfg_fc_npd, + input wire [7:0] cfg_fc_cplh, + input wire [11:0] cfg_fc_cpld, + output wire [2:0] cfg_fc_sel, + + input wire [3:0] cfg_interrupt_msi_enable, + input wire [11:0] cfg_interrupt_msi_mmenable, + input wire cfg_interrupt_msi_mask_update, + input wire [31:0] cfg_interrupt_msi_data, + output wire [3:0] cfg_interrupt_msi_select, + output wire [31:0] cfg_interrupt_msi_int, + output wire [31:0] cfg_interrupt_msi_pending_status, + output wire cfg_interrupt_msi_pending_status_data_enable, + output wire [3:0] cfg_interrupt_msi_pending_status_function_num, + input wire cfg_interrupt_msi_sent, + input wire cfg_interrupt_msi_fail, + output wire [2:0] cfg_interrupt_msi_attr, + output wire cfg_interrupt_msi_tph_present, + output wire [1:0] cfg_interrupt_msi_tph_type, + output wire [8:0] cfg_interrupt_msi_tph_st_tag, + output wire [3:0] cfg_interrupt_msi_function_number, + + output wire status_error_cor, + output wire status_error_uncor +); + +assign user_led_g = 2'b11; +assign user_led_r = 1'b1; +assign front_led = 2'b00; + +example_core_pcie_us #( + .AXIS_PCIE_DATA_WIDTH(AXIS_PCIE_DATA_WIDTH), + .AXIS_PCIE_KEEP_WIDTH(AXIS_PCIE_KEEP_WIDTH), + .AXIS_PCIE_RC_USER_WIDTH(AXIS_PCIE_RC_USER_WIDTH), + .AXIS_PCIE_RQ_USER_WIDTH(AXIS_PCIE_RQ_USER_WIDTH), + .AXIS_PCIE_CQ_USER_WIDTH(AXIS_PCIE_CQ_USER_WIDTH), + .AXIS_PCIE_CC_USER_WIDTH(AXIS_PCIE_CC_USER_WIDTH), + .RQ_SEQ_NUM_WIDTH(RQ_SEQ_NUM_WIDTH), + .RQ_SEQ_NUM_ENABLE(RQ_SEQ_NUM_ENABLE), + .PCIE_TAG_COUNT(PCIE_TAG_COUNT), + .READ_OP_TABLE_SIZE(PCIE_TAG_COUNT), + .READ_TX_LIMIT(2**(RQ_SEQ_NUM_WIDTH-1)), + .READ_TX_FC_ENABLE(1), + .WRITE_OP_TABLE_SIZE(2**(RQ_SEQ_NUM_WIDTH-1)), + .WRITE_TX_LIMIT(2**(RQ_SEQ_NUM_WIDTH-1)), + .WRITE_TX_FC_ENABLE(1), + .BAR0_APERTURE(BAR0_APERTURE), + .BAR2_APERTURE(BAR2_APERTURE) +) +example_core_pcie_us_inst ( + .clk(clk), + .rst(rst), + + /* + * AXI input (RC) + */ + .s_axis_rc_tdata(s_axis_rc_tdata), + .s_axis_rc_tkeep(s_axis_rc_tkeep), + .s_axis_rc_tvalid(s_axis_rc_tvalid), + .s_axis_rc_tready(s_axis_rc_tready), + .s_axis_rc_tlast(s_axis_rc_tlast), + .s_axis_rc_tuser(s_axis_rc_tuser), + + /* + * AXI output (RQ) + */ + .m_axis_rq_tdata(m_axis_rq_tdata), + .m_axis_rq_tkeep(m_axis_rq_tkeep), + .m_axis_rq_tvalid(m_axis_rq_tvalid), + .m_axis_rq_tready(m_axis_rq_tready), + .m_axis_rq_tlast(m_axis_rq_tlast), + .m_axis_rq_tuser(m_axis_rq_tuser), + + /* + * AXI input (CQ) + */ + .s_axis_cq_tdata(s_axis_cq_tdata), + .s_axis_cq_tkeep(s_axis_cq_tkeep), + .s_axis_cq_tvalid(s_axis_cq_tvalid), + .s_axis_cq_tready(s_axis_cq_tready), + .s_axis_cq_tlast(s_axis_cq_tlast), + .s_axis_cq_tuser(s_axis_cq_tuser), + + /* + * AXI output (CC) + */ + .m_axis_cc_tdata(m_axis_cc_tdata), + .m_axis_cc_tkeep(m_axis_cc_tkeep), + .m_axis_cc_tvalid(m_axis_cc_tvalid), + .m_axis_cc_tready(m_axis_cc_tready), + .m_axis_cc_tlast(m_axis_cc_tlast), + .m_axis_cc_tuser(m_axis_cc_tuser), + + /* + * Transmit sequence number input + */ + .s_axis_rq_seq_num_0(s_axis_rq_seq_num_0), + .s_axis_rq_seq_num_valid_0(s_axis_rq_seq_num_valid_0), + .s_axis_rq_seq_num_1(s_axis_rq_seq_num_1), + .s_axis_rq_seq_num_valid_1(s_axis_rq_seq_num_valid_1), + + /* + * Flow control + */ + .cfg_fc_ph(cfg_fc_ph), + .cfg_fc_pd(cfg_fc_pd), + .cfg_fc_nph(cfg_fc_nph), + .cfg_fc_npd(cfg_fc_npd), + .cfg_fc_cplh(cfg_fc_cplh), + .cfg_fc_cpld(cfg_fc_cpld), + .cfg_fc_sel(cfg_fc_sel), + + /* + * Configuration interface + */ + .cfg_mgmt_addr(cfg_mgmt_addr), + .cfg_mgmt_function_number(cfg_mgmt_function_number), + .cfg_mgmt_write(cfg_mgmt_write), + .cfg_mgmt_write_data(cfg_mgmt_write_data), + .cfg_mgmt_byte_enable(cfg_mgmt_byte_enable), + .cfg_mgmt_read(cfg_mgmt_read), + .cfg_mgmt_read_data(cfg_mgmt_read_data), + .cfg_mgmt_read_write_done(cfg_mgmt_read_write_done), + + /* + * Interrupt interface + */ + .cfg_interrupt_msi_enable(cfg_interrupt_msi_enable), + .cfg_interrupt_msi_vf_enable(8'd0), + .cfg_interrupt_msi_mmenable(cfg_interrupt_msi_mmenable), + .cfg_interrupt_msi_mask_update(cfg_interrupt_msi_mask_update), + .cfg_interrupt_msi_data(cfg_interrupt_msi_data), + .cfg_interrupt_msi_select(cfg_interrupt_msi_select), + .cfg_interrupt_msi_int(cfg_interrupt_msi_int), + .cfg_interrupt_msi_pending_status(cfg_interrupt_msi_pending_status), + .cfg_interrupt_msi_pending_status_data_enable(cfg_interrupt_msi_pending_status_data_enable), + .cfg_interrupt_msi_pending_status_function_num(cfg_interrupt_msi_pending_status_function_num), + .cfg_interrupt_msi_sent(cfg_interrupt_msi_sent), + .cfg_interrupt_msi_fail(cfg_interrupt_msi_fail), + .cfg_interrupt_msi_attr(cfg_interrupt_msi_attr), + .cfg_interrupt_msi_tph_present(cfg_interrupt_msi_tph_present), + .cfg_interrupt_msi_tph_type(cfg_interrupt_msi_tph_type), + .cfg_interrupt_msi_tph_st_tag(cfg_interrupt_msi_tph_st_tag), + .cfg_interrupt_msi_function_number(cfg_interrupt_msi_function_number), + + /* + * Configuration + */ + .cfg_max_read_req(cfg_max_read_req), + .cfg_max_payload(cfg_max_payload), + + /* + * Status + */ + .status_error_cor(status_error_cor), + .status_error_uncor(status_error_uncor) +); + +endmodule + +`resetall diff --git a/fpga/lib/pcie/example/ADM_PCIE_9V3/fpga/rtl/sync_reset.v b/fpga/lib/pcie/example/ADM_PCIE_9V3/fpga/rtl/sync_reset.v new file mode 100644 index 000000000..1fd24d361 --- /dev/null +++ b/fpga/lib/pcie/example/ADM_PCIE_9V3/fpga/rtl/sync_reset.v @@ -0,0 +1,56 @@ +/* + +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 active-high asynchronous reset signal to a given clock by + * using a pipeline of N registers. + */ +module sync_reset #( + parameter N=2 // depth of synchronizer +)( + input wire clk, + input wire rst, + output wire sync_reset_out +); + +reg [N-1:0] sync_reg = {N{1'b1}}; + +assign sync_reset_out = sync_reg[N-1]; + +always @(posedge clk or posedge rst) begin + if (rst) + sync_reg <= {N{1'b1}}; + else + sync_reg <= {sync_reg[N-2:0], 1'b0}; +end + +endmodule + +`resetall diff --git a/fpga/lib/pcie/example/ADM_PCIE_9V3/fpga/rtl/sync_signal.v b/fpga/lib/pcie/example/ADM_PCIE_9V3/fpga/rtl/sync_signal.v new file mode 100644 index 000000000..74b855fa1 --- /dev/null +++ b/fpga/lib/pcie/example/ADM_PCIE_9V3/fpga/rtl/sync_signal.v @@ -0,0 +1,62 @@ +/* + +Copyright (c) 2014-2018 Alex Forencich + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +*/ + +// Language: Verilog-2001 + +`resetall +`timescale 1 ns / 1 ps +`default_nettype none + +/* + * Synchronizes an asyncronous signal to a given clock by using a pipeline of + * two registers. + */ +module sync_signal #( + parameter WIDTH=1, // width of the input and output signals + parameter N=2 // depth of synchronizer +)( + input wire clk, + input wire [WIDTH-1:0] in, + output wire [WIDTH-1:0] out +); + +reg [WIDTH-1:0] sync_reg[N-1:0]; + +/* + * The synchronized output is the last register in the pipeline. + */ +assign out = sync_reg[N-1]; + +integer k; + +always @(posedge clk) begin + sync_reg[0] <= in; + for (k = 1; k < N; k = k + 1) begin + sync_reg[k] <= sync_reg[k-1]; + end +end + +endmodule + +`resetall diff --git a/fpga/lib/pcie/example/ADM_PCIE_9V3/fpga/tb/fpga_core/Makefile b/fpga/lib/pcie/example/ADM_PCIE_9V3/fpga/tb/fpga_core/Makefile new file mode 100644 index 000000000..7c85b6e54 --- /dev/null +++ b/fpga/lib/pcie/example/ADM_PCIE_9V3/fpga/tb/fpga_core/Makefile @@ -0,0 +1,123 @@ +# Copyright (c) 2020 Alex Forencich +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +TOPLEVEL_LANG = verilog + +SIM ?= icarus +WAVES ?= 0 + +COCOTB_HDL_TIMEUNIT = 1ns +COCOTB_HDL_TIMEPRECISION = 1ps + +DUT = fpga_core +TOPLEVEL = $(DUT) +MODULE = test_$(DUT) +VERILOG_SOURCES += ../../rtl/$(DUT).v +VERILOG_SOURCES += ../../rtl/common/example_core_pcie_us.v +VERILOG_SOURCES += ../../rtl/common/example_core_pcie.v +VERILOG_SOURCES += ../../rtl/common/example_core.v +VERILOG_SOURCES += ../../rtl/common/axi_ram.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_if.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_if_rc.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_if_rq.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_if_cq.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_if_cc.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_cfg.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_msi.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_axil_master.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_axi_master.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_axi_master_rd.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_axi_master_wr.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_tlp_demux_bar.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_tlp_demux.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_tlp_mux.v +VERILOG_SOURCES += ../../lib/pcie/rtl/dma_if_pcie.v +VERILOG_SOURCES += ../../lib/pcie/rtl/dma_if_pcie_rd.v +VERILOG_SOURCES += ../../lib/pcie/rtl/dma_if_pcie_wr.v +VERILOG_SOURCES += ../../lib/pcie/rtl/dma_psdpram.v +VERILOG_SOURCES += ../../lib/pcie/rtl/arbiter.v +VERILOG_SOURCES += ../../lib/pcie/rtl/priority_encoder.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pulse_merge.v + +# module parameters +export PARAM_AXIS_PCIE_DATA_WIDTH ?= 512 +export PARAM_AXIS_PCIE_KEEP_WIDTH ?= $(shell expr $(PARAM_AXIS_PCIE_DATA_WIDTH) / 32 ) +export PARAM_AXIS_PCIE_RQ_USER_WIDTH ?= $(if $(filter-out 512,$(PARAM_AXIS_PCIE_DATA_WIDTH)),62,137) +export PARAM_AXIS_PCIE_RC_USER_WIDTH ?= $(if $(filter-out 512,$(PARAM_AXIS_PCIE_DATA_WIDTH)),75,161) +export PARAM_AXIS_PCIE_CQ_USER_WIDTH ?= $(if $(filter-out 512,$(PARAM_AXIS_PCIE_DATA_WIDTH)),88,183) +export PARAM_AXIS_PCIE_CC_USER_WIDTH ?= $(if $(filter-out 512,$(PARAM_AXIS_PCIE_DATA_WIDTH)),33,81) +export PARAM_RQ_SEQ_NUM_WIDTH ?= 6 +export PARAM_RQ_SEQ_NUM_ENABLE ?= 1 +export PARAM_PCIE_TAG_COUNT ?= 64 +export PARAM_BAR0_APERTURE ?= 24 +export PARAM_BAR2_APERTURE ?= 24 + +ifeq ($(SIM), icarus) + PLUSARGS += -fst + + COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_DATA_WIDTH=$(PARAM_AXIS_PCIE_DATA_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_KEEP_WIDTH=$(PARAM_AXIS_PCIE_KEEP_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_RQ_USER_WIDTH=$(PARAM_AXIS_PCIE_RQ_USER_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_RC_USER_WIDTH=$(PARAM_AXIS_PCIE_RC_USER_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_CQ_USER_WIDTH=$(PARAM_AXIS_PCIE_CQ_USER_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_CC_USER_WIDTH=$(PARAM_AXIS_PCIE_CC_USER_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).RQ_SEQ_NUM_WIDTH=$(PARAM_RQ_SEQ_NUM_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).RQ_SEQ_NUM_ENABLE=$(PARAM_RQ_SEQ_NUM_ENABLE) + COMPILE_ARGS += -P $(TOPLEVEL).PCIE_TAG_COUNT=$(PARAM_PCIE_TAG_COUNT) + COMPILE_ARGS += -P $(TOPLEVEL).BAR0_APERTURE=$(PARAM_BAR0_APERTURE) + COMPILE_ARGS += -P $(TOPLEVEL).BAR2_APERTURE=$(PARAM_BAR2_APERTURE) + + ifeq ($(WAVES), 1) + VERILOG_SOURCES += iverilog_dump.v + COMPILE_ARGS += -s iverilog_dump + endif +else ifeq ($(SIM), verilator) + COMPILE_ARGS += -Wno-SELRANGE -Wno-WIDTH + + COMPILE_ARGS += -GAXIS_PCIE_DATA_WIDTH=$(PARAM_AXIS_PCIE_DATA_WIDTH) + COMPILE_ARGS += -GAXIS_PCIE_KEEP_WIDTH=$(PARAM_AXIS_PCIE_KEEP_WIDTH) + COMPILE_ARGS += -GAXIS_PCIE_RQ_USER_WIDTH=$(PARAM_AXIS_PCIE_RQ_USER_WIDTH) + COMPILE_ARGS += -GAXIS_PCIE_RC_USER_WIDTH=$(PARAM_AXIS_PCIE_RC_USER_WIDTH) + COMPILE_ARGS += -GAXIS_PCIE_CQ_USER_WIDTH=$(PARAM_AXIS_PCIE_CQ_USER_WIDTH) + COMPILE_ARGS += -GAXIS_PCIE_CC_USER_WIDTH=$(PARAM_AXIS_PCIE_CC_USER_WIDTH) + COMPILE_ARGS += -GRQ_SEQ_NUM_WIDTH=$(PARAM_RQ_SEQ_NUM_WIDTH) + COMPILE_ARGS += -GRQ_SEQ_NUM_ENABLE=$(PARAM_RQ_SEQ_NUM_ENABLE) + COMPILE_ARGS += -GPCIE_TAG_COUNT=$(PARAM_PCIE_TAG_COUNT) + COMPILE_ARGS += -GBAR0_APERTURE=$(PARAM_BAR0_APERTURE) + COMPILE_ARGS += -GBAR2_APERTURE=$(PARAM_BAR2_APERTURE) + + ifeq ($(WAVES), 1) + COMPILE_ARGS += --trace-fst + endif +endif + +include $(shell cocotb-config --makefiles)/Makefile.sim + +iverilog_dump.v: + echo 'module iverilog_dump();' > $@ + echo 'initial begin' >> $@ + echo ' $$dumpfile("$(TOPLEVEL).fst");' >> $@ + echo ' $$dumpvars(0, $(TOPLEVEL));' >> $@ + echo 'end' >> $@ + echo 'endmodule' >> $@ + +clean:: + @rm -rf iverilog_dump.v + @rm -rf dump.fst $(TOPLEVEL).fst diff --git a/fpga/lib/pcie/example/ADM_PCIE_9V3/fpga/tb/fpga_core/test_fpga_core.py b/fpga/lib/pcie/example/ADM_PCIE_9V3/fpga/tb/fpga_core/test_fpga_core.py new file mode 100644 index 000000000..f2c657c91 --- /dev/null +++ b/fpga/lib/pcie/example/ADM_PCIE_9V3/fpga/tb/fpga_core/test_fpga_core.py @@ -0,0 +1,472 @@ +""" + +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 + +import cocotb_test.simulator + +import cocotb +from cocotb.log import SimLog +from cocotb.triggers import RisingEdge, FallingEdge, Timer + +from cocotbext.axi import AxiStreamBus +from cocotbext.pcie.core import RootComplex +from cocotbext.pcie.xilinx.us import UltraScalePlusPcieDevice + + +class TB(object): + def __init__(self, dut): + self.dut = dut + + self.log = SimLog("cocotb.tb") + self.log.setLevel(logging.DEBUG) + + # PCIe + self.rc = RootComplex() + + self.dev = UltraScalePlusPcieDevice( + # configuration options + pcie_generation=3, + pcie_link_width=16, + user_clk_frequency=250e6, + alignment="dword", + cq_cc_straddle=False, + rq_rc_straddle=False, + rc_4tlp_straddle=False, + enable_pf1=False, + enable_client_tag=True, + enable_extended_tag=True, + enable_parity=False, + enable_rx_msg_interface=False, + enable_sriov=False, + enable_extended_configuration=False, + + enable_pf0_msi=True, + enable_pf1_msi=False, + + # signals + # Clock and Reset Interface + user_clk=dut.clk, + user_reset=dut.rst, + # user_lnk_up + # sys_clk + # sys_clk_gt + # sys_reset + # phy_rdy_out + + # Requester reQuest Interface + rq_bus=AxiStreamBus.from_prefix(dut, "m_axis_rq"), + pcie_rq_seq_num0=dut.s_axis_rq_seq_num_0, + pcie_rq_seq_num_vld0=dut.s_axis_rq_seq_num_valid_0, + pcie_rq_seq_num1=dut.s_axis_rq_seq_num_1, + pcie_rq_seq_num_vld1=dut.s_axis_rq_seq_num_valid_1, + # pcie_rq_tag0 + # pcie_rq_tag1 + # pcie_rq_tag_av + # pcie_rq_tag_vld0 + # pcie_rq_tag_vld1 + + # Requester Completion Interface + rc_bus=AxiStreamBus.from_prefix(dut, "s_axis_rc"), + + # Completer reQuest Interface + cq_bus=AxiStreamBus.from_prefix(dut, "s_axis_cq"), + # pcie_cq_np_req + # pcie_cq_np_req_count + + # Completer Completion Interface + cc_bus=AxiStreamBus.from_prefix(dut, "m_axis_cc"), + + # Transmit Flow Control Interface + # pcie_tfc_nph_av=dut.pcie_tfc_nph_av, + # pcie_tfc_npd_av=dut.pcie_tfc_npd_av, + + # Configuration Management Interface + cfg_mgmt_addr=dut.cfg_mgmt_addr, + cfg_mgmt_function_number=dut.cfg_mgmt_function_number, + cfg_mgmt_write=dut.cfg_mgmt_write, + cfg_mgmt_write_data=dut.cfg_mgmt_write_data, + cfg_mgmt_byte_enable=dut.cfg_mgmt_byte_enable, + cfg_mgmt_read=dut.cfg_mgmt_read, + cfg_mgmt_read_data=dut.cfg_mgmt_read_data, + cfg_mgmt_read_write_done=dut.cfg_mgmt_read_write_done, + # cfg_mgmt_debug_access + + # Configuration Status Interface + # cfg_phy_link_down + # cfg_phy_link_status + # cfg_negotiated_width + # cfg_current_speed + cfg_max_payload=dut.cfg_max_payload, + cfg_max_read_req=dut.cfg_max_read_req, + # cfg_function_status + # cfg_vf_status + # cfg_function_power_state + # cfg_vf_power_state + # cfg_link_power_state + # cfg_err_cor_out + # cfg_err_nonfatal_out + # cfg_err_fatal_out + # cfg_local_error_out + # cfg_local_error_valid + # cfg_rx_pm_state + # cfg_tx_pm_state + # cfg_ltssm_state + # cfg_rcb_status + # cfg_obff_enable + # cfg_pl_status_change + # cfg_tph_requester_enable + # cfg_tph_st_mode + # cfg_vf_tph_requester_enable + # cfg_vf_tph_st_mode + + # Configuration Received Message Interface + # cfg_msg_received + # cfg_msg_received_data + # cfg_msg_received_type + + # Configuration Transmit Message Interface + # cfg_msg_transmit + # cfg_msg_transmit_type + # cfg_msg_transmit_data + # cfg_msg_transmit_done + + # Configuration Flow Control Interface + cfg_fc_ph=dut.cfg_fc_ph, + cfg_fc_pd=dut.cfg_fc_pd, + cfg_fc_nph=dut.cfg_fc_nph, + cfg_fc_npd=dut.cfg_fc_npd, + cfg_fc_cplh=dut.cfg_fc_cplh, + cfg_fc_cpld=dut.cfg_fc_cpld, + cfg_fc_sel=dut.cfg_fc_sel, + + # Configuration Control Interface + # cfg_hot_reset_in + # cfg_hot_reset_out + # cfg_config_space_enable + # cfg_dsn + # cfg_bus_number + # cfg_ds_port_number + # cfg_ds_bus_number + # cfg_ds_device_number + # cfg_ds_function_number + # cfg_power_state_change_ack + # cfg_power_state_change_interrupt + cfg_err_cor_in=dut.status_error_cor, + cfg_err_uncor_in=dut.status_error_uncor, + # cfg_flr_in_process + # cfg_flr_done + # cfg_vf_flr_in_process + # cfg_vf_flr_func_num + # cfg_vf_flr_done + # cfg_pm_aspm_l1_entry_reject + # cfg_pm_aspm_tx_l0s_entry_disable + # cfg_req_pm_transition_l23_ready + # cfg_link_training_enable + + # Configuration Interrupt Controller Interface + # cfg_interrupt_int + # cfg_interrupt_sent + # cfg_interrupt_pending + cfg_interrupt_msi_enable=dut.cfg_interrupt_msi_enable, + cfg_interrupt_msi_mmenable=dut.cfg_interrupt_msi_mmenable, + cfg_interrupt_msi_mask_update=dut.cfg_interrupt_msi_mask_update, + cfg_interrupt_msi_data=dut.cfg_interrupt_msi_data, + # cfg_interrupt_msi_select=dut.cfg_interrupt_msi_select, + cfg_interrupt_msi_int=dut.cfg_interrupt_msi_int, + cfg_interrupt_msi_pending_status=dut.cfg_interrupt_msi_pending_status, + cfg_interrupt_msi_pending_status_data_enable=dut.cfg_interrupt_msi_pending_status_data_enable, + # cfg_interrupt_msi_pending_status_function_num=dut.cfg_interrupt_msi_pending_status_function_num, + cfg_interrupt_msi_sent=dut.cfg_interrupt_msi_sent, + cfg_interrupt_msi_fail=dut.cfg_interrupt_msi_fail, + # cfg_interrupt_msix_enable + # cfg_interrupt_msix_mask + # cfg_interrupt_msix_vf_enable + # cfg_interrupt_msix_vf_mask + # cfg_interrupt_msix_address + # cfg_interrupt_msix_data + # cfg_interrupt_msix_int + # cfg_interrupt_msix_vec_pending + # cfg_interrupt_msix_vec_pending_status + cfg_interrupt_msi_attr=dut.cfg_interrupt_msi_attr, + cfg_interrupt_msi_tph_present=dut.cfg_interrupt_msi_tph_present, + cfg_interrupt_msi_tph_type=dut.cfg_interrupt_msi_tph_type, + # cfg_interrupt_msi_tph_st_tag=dut.cfg_interrupt_msi_tph_st_tag, + # cfg_interrupt_msi_function_number=dut.cfg_interrupt_msi_function_number, + + # Configuration Extend Interface + # cfg_ext_read_received + # cfg_ext_write_received + # cfg_ext_register_number + # cfg_ext_function_number + # cfg_ext_write_data + # cfg_ext_write_byte_enable + # cfg_ext_read_data + # cfg_ext_read_data_valid + ) + + # self.dev.log.setLevel(logging.DEBUG) + + self.rc.make_port().connect(self.dev) + + self.dev.functions[0].msi_multiple_message_capable = 5 + + self.dev.functions[0].configure_bar(0, 2**len(dut.example_core_pcie_us_inst.core_pcie_inst.axil_ctrl_awaddr)) + self.dev.functions[0].configure_bar(2, 2**len(dut.example_core_pcie_us_inst.core_pcie_inst.axi_ram_awaddr)) + + async def init(self): + + await FallingEdge(self.dut.rst) + await Timer(100, 'ns') + + await self.rc.enumerate(enable_bus_mastering=True, configure_msi=True) + + +@cocotb.test() +async def run_test(dut): + + tb = TB(dut) + + await tb.init() + + mem = tb.rc.mem_pool.alloc_region(16*1024*1024) + mem_base = mem.get_absolute_address(0) + + dev_pf0_bar0 = tb.rc.tree[0][0].bar_window[0] + dev_pf0_bar2 = tb.rc.tree[0][0].bar_window[2] + + tb.log.info("Test memory write to BAR 2") + + test_data = b'\x11\x22\x33\x44' + await dev_pf0_bar2.write(0, test_data) + + await Timer(100, 'ns') + + tb.log.info("Test memory read from BAR 2") + + val = await dev_pf0_bar2.read(0, len(test_data), timeout=1000) + tb.log.info("Read data: %s", val) + assert val == test_data + + tb.log.info("Test DMA") + + # write packet data + mem[0:1024] = bytearray([x % 256 for x in range(1024)]) + + # enable DMA + await dev_pf0_bar0.write_dword(0x000000, 1) + + # write pcie read descriptor + await dev_pf0_bar0.write_dword(0x000100, (mem_base+0x0000) & 0xffffffff) + await dev_pf0_bar0.write_dword(0x000104, (mem_base+0x0000 >> 32) & 0xffffffff) + await dev_pf0_bar0.write_dword(0x000108, 0x100) + await dev_pf0_bar0.write_dword(0x000110, 0x400) + await dev_pf0_bar0.write_dword(0x000114, 0xAA) + + await Timer(2000, 'ns') + + # read status + val = await dev_pf0_bar0.read_dword(0x000118) + tb.log.info("Status: 0x%x", val) + assert val == 0x800000AA + + # write pcie write descriptor + await dev_pf0_bar0.write_dword(0x000200, (mem_base+0x1000) & 0xffffffff) + await dev_pf0_bar0.write_dword(0x000204, (mem_base+0x1000 >> 32) & 0xffffffff) + await dev_pf0_bar0.write_dword(0x000208, 0x100) + await dev_pf0_bar0.write_dword(0x000210, 0x400) + await dev_pf0_bar0.write_dword(0x000214, 0x55) + + await Timer(2000, 'ns') + + # read status + val = await dev_pf0_bar0.read_dword(0x000218) + tb.log.info("Status: 0x%x", val) + assert val == 0x80000055 + + tb.log.info("%s", mem.hexdump_str(0x1000, 64)) + + assert mem[0:1024] == mem[0x1000:0x1000+1024] + + tb.log.info("Test DMA block operations") + + # write packet data + mem[0:1024] = bytearray([x % 256 for x in range(1024)]) + + # enable DMA + await dev_pf0_bar0.write_dword(0x000000, 1) + # disable interrupts + await dev_pf0_bar0.write_dword(0x000008, 0) + + # configure operation (read) + # DMA base address + await dev_pf0_bar0.write_dword(0x001080, (mem_base+0x0000) & 0xffffffff) + await dev_pf0_bar0.write_dword(0x001084, (mem_base+0x0000 >> 32) & 0xffffffff) + # DMA offset address + await dev_pf0_bar0.write_dword(0x001088, 0) + await dev_pf0_bar0.write_dword(0x00108c, 0) + # DMA offset mask + await dev_pf0_bar0.write_dword(0x001090, 0x000003ff) + await dev_pf0_bar0.write_dword(0x001094, 0) + # DMA stride + await dev_pf0_bar0.write_dword(0x001098, 256) + await dev_pf0_bar0.write_dword(0x00109c, 0) + # RAM base address + await dev_pf0_bar0.write_dword(0x0010c0, 0) + await dev_pf0_bar0.write_dword(0x0010c4, 0) + # RAM offset address + await dev_pf0_bar0.write_dword(0x0010c8, 0) + await dev_pf0_bar0.write_dword(0x0010cc, 0) + # RAM offset mask + await dev_pf0_bar0.write_dword(0x0010d0, 0x000003ff) + await dev_pf0_bar0.write_dword(0x0010d4, 0) + # RAM stride + await dev_pf0_bar0.write_dword(0x0010d8, 256) + await dev_pf0_bar0.write_dword(0x0010dc, 0) + # clear cycle count + await dev_pf0_bar0.write_dword(0x001008, 0) + await dev_pf0_bar0.write_dword(0x00100c, 0) + # block length + await dev_pf0_bar0.write_dword(0x001010, 256) + # block count + await dev_pf0_bar0.write_dword(0x001018, 32) + await dev_pf0_bar0.write_dword(0x00101c, 0) + # start + await dev_pf0_bar0.write_dword(0x001000, 1) + + await Timer(2000, 'ns') + + # configure operation (write) + # DMA base address + await dev_pf0_bar0.write_dword(0x001180, (mem_base+0x0000) & 0xffffffff) + await dev_pf0_bar0.write_dword(0x001184, (mem_base+0x0000 >> 32) & 0xffffffff) + # DMA offset address + await dev_pf0_bar0.write_dword(0x001188, 0) + await dev_pf0_bar0.write_dword(0x00118c, 0) + # DMA offset mask + await dev_pf0_bar0.write_dword(0x001190, 0x000003ff) + await dev_pf0_bar0.write_dword(0x001194, 0) + # DMA stride + await dev_pf0_bar0.write_dword(0x001198, 256) + await dev_pf0_bar0.write_dword(0x00119c, 0) + # RAM base address + await dev_pf0_bar0.write_dword(0x0011c0, 0) + await dev_pf0_bar0.write_dword(0x0011c4, 0) + # RAM offset address + await dev_pf0_bar0.write_dword(0x0011c8, 0) + await dev_pf0_bar0.write_dword(0x0011cc, 0) + # RAM offset mask + await dev_pf0_bar0.write_dword(0x0011d0, 0x000003ff) + await dev_pf0_bar0.write_dword(0x0011d4, 0) + # RAM stride + await dev_pf0_bar0.write_dword(0x0011d8, 256) + await dev_pf0_bar0.write_dword(0x0011dc, 0) + # clear cycle count + await dev_pf0_bar0.write_dword(0x001108, 0) + await dev_pf0_bar0.write_dword(0x00110c, 0) + # block length + await dev_pf0_bar0.write_dword(0x001110, 256) + # block count + await dev_pf0_bar0.write_dword(0x001118, 32) + await dev_pf0_bar0.write_dword(0x00111c, 0) + # start + await dev_pf0_bar0.write_dword(0x001100, 1) + + await Timer(2000, 'ns') + + await RisingEdge(dut.clk) + await RisingEdge(dut.clk) + + +# cocotb-test + +tests_dir = 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')) +pcie_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'pcie', '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(rtl_dir, "common", "example_core_pcie_us.v"), + os.path.join(rtl_dir, "common", "example_core_pcie.v"), + os.path.join(rtl_dir, "common", "example_core.v"), + os.path.join(rtl_dir, "common", "axi_ram.v"), + os.path.join(pcie_rtl_dir, "pcie_us_if.v"), + os.path.join(pcie_rtl_dir, "pcie_us_if_rc.v"), + os.path.join(pcie_rtl_dir, "pcie_us_if_rq.v"), + os.path.join(pcie_rtl_dir, "pcie_us_if_cq.v"), + os.path.join(pcie_rtl_dir, "pcie_us_if_cc.v"), + os.path.join(pcie_rtl_dir, "pcie_us_cfg.v"), + os.path.join(pcie_rtl_dir, "pcie_us_msi.v"), + os.path.join(pcie_rtl_dir, "pcie_axil_master.v"), + os.path.join(pcie_rtl_dir, "pcie_axi_master.v"), + os.path.join(pcie_rtl_dir, "pcie_axi_master_rd.v"), + os.path.join(pcie_rtl_dir, "pcie_axi_master_wr.v"), + os.path.join(pcie_rtl_dir, "pcie_tlp_demux_bar.v"), + os.path.join(pcie_rtl_dir, "pcie_tlp_demux.v"), + os.path.join(pcie_rtl_dir, "pcie_tlp_mux.v"), + os.path.join(pcie_rtl_dir, "dma_if_pcie.v"), + os.path.join(pcie_rtl_dir, "dma_if_pcie_rd.v"), + os.path.join(pcie_rtl_dir, "dma_if_pcie_wr.v"), + os.path.join(pcie_rtl_dir, "dma_psdpram.v"), + os.path.join(pcie_rtl_dir, "arbiter.v"), + os.path.join(pcie_rtl_dir, "priority_encoder.v"), + os.path.join(pcie_rtl_dir, "pulse_merge.v"), + ] + + parameters = {} + + parameters['AXIS_PCIE_DATA_WIDTH'] = 512 + parameters['AXIS_PCIE_KEEP_WIDTH'] = parameters['AXIS_PCIE_DATA_WIDTH'] // 32 + parameters['AXIS_PCIE_RQ_USER_WIDTH'] = 62 if parameters['AXIS_PCIE_DATA_WIDTH'] < 512 else 137 + parameters['AXIS_PCIE_RC_USER_WIDTH'] = 75 if parameters['AXIS_PCIE_DATA_WIDTH'] < 512 else 161 + parameters['AXIS_PCIE_CQ_USER_WIDTH'] = 88 if parameters['AXIS_PCIE_DATA_WIDTH'] < 512 else 183 + parameters['AXIS_PCIE_CC_USER_WIDTH'] = 33 if parameters['AXIS_PCIE_DATA_WIDTH'] < 512 else 81 + parameters['RQ_SEQ_NUM_WIDTH'] = 6 + parameters['RQ_SEQ_NUM_ENABLE'] = 1 + parameters['PCIE_TAG_COUNT'] = 64 + parameters['BAR0_APERTURE'] = 24 + parameters['BAR2_APERTURE'] = 24 + + 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, + ) diff --git a/fpga/lib/pcie/example/AU200/fpga/README.md b/fpga/lib/pcie/example/AU200/fpga/README.md new file mode 100644 index 000000000..71537314b --- /dev/null +++ b/fpga/lib/pcie/example/AU200/fpga/README.md @@ -0,0 +1,19 @@ +# Verilog PCIe Alveo U200 Example Design + +## Introduction + +This example design targets the Xilinx Alveo U200 FPGA board. + +The design implements the PCIe AXI lite master module, the PCIe AXI master module, and the PCIe DMA module. A very simple Linux driver is included to test the FPGA design. + +* FPGA: xcu200-fsgd2104-2-e + +## How to build + +Run `make` to build. Ensure that the Xilinx Vivado components are in PATH. + +Run `make` to build the driver. Ensure the headers for the running kernel are installed, otherwise the driver cannot be compiled. + +## How to test + +Run `make program` to program the Alveo U200 board with Vivado. Then load the driver with `insmod example.ko`. Check dmesg for the output. diff --git a/fpga/lib/pcie/example/AU200/fpga/common/vivado.mk b/fpga/lib/pcie/example/AU200/fpga/common/vivado.mk new file mode 100644 index 000000000..d47a43947 --- /dev/null +++ b/fpga/lib/pcie/example/AU200/fpga/common/vivado.mk @@ -0,0 +1,126 @@ +################################################################### +# +# 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) + +SYN_FILES_REL = $(patsubst %, ../%, $(filter-out /% ./%,$(SYN_FILES))) $(filter /% ./%,$(SYN_FILES)) +INC_FILES_REL = $(patsubst %, ../%, $(filter-out /% ./%,$(INC_FILES))) $(filter /% ./%,$(INC_FILES)) +XCI_FILES_REL = $(patsubst %, ../%, $(filter-out /% ./%,$(XCI_FILES))) $(filter /% ./%,$(XCI_FILES)) +IP_TCL_FILES_REL = $(patsubst %, ../%, $(filter-out /% ./%,$(IP_TCL_FILES))) $(filter /% ./%,$(IP_TCL_FILES)) +CONFIG_TCL_FILES_REL = $(patsubst %, ../%, $(filter-out /% ./%,$(CONFIG_TCL_FILES))) $(filter /% ./%,$(CONFIG_TCL_FILES)) + +ifdef XDC_FILES + XDC_FILES_REL = $(patsubst %, ../%, $(filter-out /% ./%,$(XDC_FILES))) $(filter /% ./%,$(XDC_FILES)) +else + XDC_FILES_REL = $(FPGA_TOP).xdc +endif + +################################################################### +# Main Targets +# +# all: build everything +# clean: remove output files and project files +################################################################### + +all: fpga + +fpga: $(FPGA_TOP).bit + +vivado: $(FPGA_TOP).xpr + vivado $(FPGA_TOP).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 program.tcl generate_mcs.tcl *.mcs *.prm flash.tcl + +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) $(FPGA_TOP)" > $@ + echo "add_files -fileset sources_1 defines.v $(SYN_FILES_REL)" >> $@ + 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) + echo "open_project -quiet $(FPGA_TOP).xpr" > $@ + for x in $(CONFIG_TCL_FILES_REL); do echo "source $$x" >> $@; done + +$(FPGA_TOP).xpr: create_project.tcl update_config.tcl + vivado -nojournal -nolog -mode batch $(foreach x,$?,-source $x) + +# synthesis run +%.runs/synth_1/%.dcp: %.xpr $(SYN_FILES_REL) $(INC_FILES_REL) $(XDC_FILES_REL) $(CONFIG_TCL_FILES_REL) + echo "open_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 +%.runs/impl_1/%_routed.dcp: %.runs/synth_1/%.dcp + echo "open_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 + vivado -nojournal -nolog -mode batch -source run_impl.tcl + +# bit file +%.bit: %.runs/impl_1/%_routed.dcp + echo "open_project $*.xpr" > generate_bit.tcl + echo "open_run impl_1" >> generate_bit.tcl + echo "write_bitstream -force $*.bit" >> generate_bit.tcl + vivado -nojournal -nolog -mode batch -source generate_bit.tcl + mkdir -p rev + EXT=bit; COUNT=100; \ + while [ -e rev/$*_rev$$COUNT.$$EXT ]; \ + do COUNT=$$((COUNT+1)); done; \ + cp $@ rev/$*_rev$$COUNT.$$EXT; \ + echo "Output: rev/$*_rev$$COUNT.$$EXT"; diff --git a/fpga/lib/pcie/example/AU200/fpga/driver b/fpga/lib/pcie/example/AU200/fpga/driver new file mode 120000 index 000000000..4a54c76b5 --- /dev/null +++ b/fpga/lib/pcie/example/AU200/fpga/driver @@ -0,0 +1 @@ +../../common/driver/example/ \ No newline at end of file diff --git a/fpga/lib/pcie/example/AU200/fpga/fpga.xdc b/fpga/lib/pcie/example/AU200/fpga/fpga.xdc new file mode 100644 index 000000000..4253448be --- /dev/null +++ b/fpga/lib/pcie/example/AU200/fpga/fpga.xdc @@ -0,0 +1,259 @@ +# XDC constraints for the Xilinx Alveo U200 board +# part: xcu200-fsgd2104-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_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_rx1_p] ;# MGTYRXP0_231 GTYE4_CHANNEL_X1Y48 / GTYE4_COMMON_X1Y12 +#set_property -dict {LOC N3 } [get_ports qsfp0_rx1_n] ;# MGTYRXN0_231 GTYE4_CHANNEL_X1Y48 / GTYE4_COMMON_X1Y12 +#set_property -dict {LOC N9 } [get_ports qsfp0_tx1_p] ;# MGTYTXP0_231 GTYE4_CHANNEL_X1Y48 / GTYE4_COMMON_X1Y12 +#set_property -dict {LOC N8 } [get_ports qsfp0_tx1_n] ;# MGTYTXN0_231 GTYE4_CHANNEL_X1Y48 / GTYE4_COMMON_X1Y12 +#set_property -dict {LOC M2 } [get_ports qsfp0_rx2_p] ;# MGTYRXP1_231 GTYE4_CHANNEL_X1Y49 / GTYE4_COMMON_X1Y12 +#set_property -dict {LOC M1 } [get_ports qsfp0_rx2_n] ;# MGTYRXN1_231 GTYE4_CHANNEL_X1Y49 / GTYE4_COMMON_X1Y12 +#set_property -dict {LOC M7 } [get_ports qsfp0_tx2_p] ;# MGTYTXP1_231 GTYE4_CHANNEL_X1Y49 / GTYE4_COMMON_X1Y12 +#set_property -dict {LOC M6 } [get_ports qsfp0_tx2_n] ;# MGTYTXN1_231 GTYE4_CHANNEL_X1Y49 / GTYE4_COMMON_X1Y12 +#set_property -dict {LOC L4 } [get_ports qsfp0_rx3_p] ;# MGTYRXP2_231 GTYE4_CHANNEL_X1Y50 / GTYE4_COMMON_X1Y12 +#set_property -dict {LOC L3 } [get_ports qsfp0_rx3_n] ;# MGTYRXN2_231 GTYE4_CHANNEL_X1Y50 / GTYE4_COMMON_X1Y12 +#set_property -dict {LOC L9 } [get_ports qsfp0_tx3_p] ;# MGTYTXP2_231 GTYE4_CHANNEL_X1Y50 / GTYE4_COMMON_X1Y12 +#set_property -dict {LOC L8 } [get_ports qsfp0_tx3_n] ;# MGTYTXN2_231 GTYE4_CHANNEL_X1Y50 / GTYE4_COMMON_X1Y12 +#set_property -dict {LOC K2 } [get_ports qsfp0_rx4_p] ;# MGTYRXP3_231 GTYE4_CHANNEL_X1Y51 / GTYE4_COMMON_X1Y12 +#set_property -dict {LOC K1 } [get_ports qsfp0_rx4_n] ;# MGTYRXN3_231 GTYE4_CHANNEL_X1Y51 / GTYE4_COMMON_X1Y12 +#set_property -dict {LOC K7 } [get_ports qsfp0_tx4_p] ;# MGTYTXP3_231 GTYE4_CHANNEL_X1Y51 / GTYE4_COMMON_X1Y12 +#set_property -dict {LOC K6 } [get_ports qsfp0_tx4_n] ;# 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_rx1_p] ;# MGTYRXP0_230 GTYE4_CHANNEL_X1Y44 / GTYE4_COMMON_X1Y11 +#set_property -dict {LOC U3 } [get_ports qsfp1_rx1_n] ;# MGTYRXN0_230 GTYE4_CHANNEL_X1Y44 / GTYE4_COMMON_X1Y11 +#set_property -dict {LOC U9 } [get_ports qsfp1_tx1_p] ;# MGTYTXP0_230 GTYE4_CHANNEL_X1Y44 / GTYE4_COMMON_X1Y11 +#set_property -dict {LOC U8 } [get_ports qsfp1_tx1_n] ;# MGTYTXN0_230 GTYE4_CHANNEL_X1Y44 / GTYE4_COMMON_X1Y11 +#set_property -dict {LOC T2 } [get_ports qsfp1_rx2_p] ;# MGTYRXP1_230 GTYE4_CHANNEL_X1Y45 / GTYE4_COMMON_X1Y11 +#set_property -dict {LOC T1 } [get_ports qsfp1_rx2_n] ;# MGTYRXN1_230 GTYE4_CHANNEL_X1Y45 / GTYE4_COMMON_X1Y11 +#set_property -dict {LOC T7 } [get_ports qsfp1_tx2_p] ;# MGTYTXP1_230 GTYE4_CHANNEL_X1Y45 / GTYE4_COMMON_X1Y11 +#set_property -dict {LOC T6 } [get_ports qsfp1_tx2_n] ;# MGTYTXN1_230 GTYE4_CHANNEL_X1Y45 / GTYE4_COMMON_X1Y11 +#set_property -dict {LOC R4 } [get_ports qsfp1_rx3_p] ;# MGTYRXP2_230 GTYE4_CHANNEL_X1Y46 / GTYE4_COMMON_X1Y11 +#set_property -dict {LOC R3 } [get_ports qsfp1_rx3_n] ;# MGTYRXN2_230 GTYE4_CHANNEL_X1Y46 / GTYE4_COMMON_X1Y11 +#set_property -dict {LOC R9 } [get_ports qsfp1_tx3_p] ;# MGTYTXP2_230 GTYE4_CHANNEL_X1Y46 / GTYE4_COMMON_X1Y11 +#set_property -dict {LOC R8 } [get_ports qsfp1_tx3_n] ;# MGTYTXN2_230 GTYE4_CHANNEL_X1Y46 / GTYE4_COMMON_X1Y11 +#set_property -dict {LOC P2 } [get_ports qsfp1_rx4_p] ;# MGTYRXP3_230 GTYE4_CHANNEL_X1Y47 / GTYE4_COMMON_X1Y11 +#set_property -dict {LOC P1 } [get_ports qsfp1_rx4_n] ;# MGTYRXN3_230 GTYE4_CHANNEL_X1Y47 / GTYE4_COMMON_X1Y11 +#set_property -dict {LOC P7 } [get_ports qsfp1_tx4_p] ;# MGTYTXP3_230 GTYE4_CHANNEL_X1Y47 / GTYE4_COMMON_X1Y11 +#set_property -dict {LOC P6 } [get_ports qsfp1_tx4_n] ;# 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}] diff --git a/fpga/lib/pcie/example/AU200/fpga/fpga/Makefile b/fpga/lib/pcie/example/AU200/fpga/fpga/Makefile new file mode 100644 index 000000000..9e4dba59c --- /dev/null +++ b/fpga/lib/pcie/example/AU200/fpga/fpga/Makefile @@ -0,0 +1,94 @@ + +# FPGA settings +FPGA_PART = xcu200-fsgd2104-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/debounce_switch.v +SYN_FILES += rtl/sync_reset.v +SYN_FILES += rtl/sync_signal.v +SYN_FILES += rtl/common/example_core_pcie_us.v +SYN_FILES += rtl/common/example_core_pcie.v +SYN_FILES += rtl/common/example_core.v +SYN_FILES += rtl/common/axi_ram.v +SYN_FILES += lib/pcie/rtl/pcie_us_if.v +SYN_FILES += lib/pcie/rtl/pcie_us_if_rc.v +SYN_FILES += lib/pcie/rtl/pcie_us_if_rq.v +SYN_FILES += lib/pcie/rtl/pcie_us_if_cq.v +SYN_FILES += lib/pcie/rtl/pcie_us_if_cc.v +SYN_FILES += lib/pcie/rtl/pcie_us_cfg.v +SYN_FILES += lib/pcie/rtl/pcie_us_msi.v +SYN_FILES += lib/pcie/rtl/pcie_axil_master.v +SYN_FILES += lib/pcie/rtl/pcie_axi_master.v +SYN_FILES += lib/pcie/rtl/pcie_axi_master_rd.v +SYN_FILES += lib/pcie/rtl/pcie_axi_master_wr.v +SYN_FILES += lib/pcie/rtl/pcie_tlp_demux_bar.v +SYN_FILES += lib/pcie/rtl/pcie_tlp_demux.v +SYN_FILES += lib/pcie/rtl/pcie_tlp_mux.v +SYN_FILES += lib/pcie/rtl/dma_if_pcie.v +SYN_FILES += lib/pcie/rtl/dma_if_pcie_rd.v +SYN_FILES += lib/pcie/rtl/dma_if_pcie_wr.v +SYN_FILES += lib/pcie/rtl/dma_psdpram.v +SYN_FILES += lib/pcie/rtl/arbiter.v +SYN_FILES += lib/pcie/rtl/priority_encoder.v +SYN_FILES += lib/pcie/rtl/pulse_merge.v + +# XDC files +XDC_FILES = fpga.xdc + +# IP +IP_TCL_FILES = ip/pcie4_uscale_plus_0.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 + +%.mcs %.prm: %.bit + echo "write_cfgmem -force -format mcs -size 128 -interface SPIx4 -loadbit {up 0x01002000 $*.bit} -checksum -file $*.mcs" > generate_mcs.tcl + echo "exit" >> generate_mcs.tcl + vivado -nojournal -nolog -mode batch -source generate_mcs.tcl + mkdir -p rev + COUNT=100; \ + while [ -e rev/$*_rev$$COUNT.bit ]; \ + do COUNT=$$((COUNT+1)); done; \ + COUNT=$$((COUNT-1)); \ + for x in .mcs .prm; \ + do cp $*$$x rev/$*_rev$$COUNT$$x; \ + echo "Output: rev/$*_rev$$COUNT$$x"; done; + +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 + diff --git a/fpga/lib/pcie/example/AU200/fpga/ip/pcie4_uscale_plus_0.tcl b/fpga/lib/pcie/example/AU200/fpga/ip/pcie4_uscale_plus_0.tcl new file mode 100644 index 000000000..3496725d4 --- /dev/null +++ b/fpga/lib/pcie/example/AU200/fpga/ip/pcie4_uscale_plus_0.tcl @@ -0,0 +1,28 @@ + +create_ip -name pcie4_uscale_plus -vendor xilinx.com -library ip -module_name pcie4_uscale_plus_0 + +set_property -dict [list \ + CONFIG.PL_LINK_CAP_MAX_LINK_SPEED {8.0_GT/s} \ + CONFIG.PL_LINK_CAP_MAX_LINK_WIDTH {X16} \ + CONFIG.AXISTEN_IF_EXT_512_RQ_STRADDLE {false} \ + CONFIG.axisten_if_enable_client_tag {true} \ + CONFIG.axisten_if_width {512_bit} \ + CONFIG.axisten_freq {250} \ + CONFIG.PF0_CLASS_CODE {058000} \ + CONFIG.PF0_DEVICE_ID {0001} \ + CONFIG.PF0_MSI_CAP_MULTIMSGCAP {32_vectors} \ + CONFIG.PF0_SUBSYSTEM_ID {90c8} \ + CONFIG.PF0_SUBSYSTEM_VENDOR_ID {10ee} \ + CONFIG.pf0_bar0_64bit {true} \ + CONFIG.pf0_bar0_prefetchable {true} \ + CONFIG.pf0_bar0_scale {Megabytes} \ + CONFIG.pf0_bar0_size {16} \ + CONFIG.pf0_bar2_64bit {true} \ + CONFIG.pf0_bar2_prefetchable {true} \ + CONFIG.pf0_bar2_enabled {true} \ + CONFIG.pf0_bar2_type {Memory} \ + CONFIG.pf0_bar2_scale {Megabytes} \ + CONFIG.pf0_bar2_size {16} \ + CONFIG.vendor_id {1234} \ + CONFIG.en_msi_per_vec_masking {true} \ +] [get_ips pcie4_uscale_plus_0] diff --git a/fpga/lib/pcie/example/AU200/fpga/lib/pcie b/fpga/lib/pcie/example/AU200/fpga/lib/pcie new file mode 120000 index 000000000..11a54ed36 --- /dev/null +++ b/fpga/lib/pcie/example/AU200/fpga/lib/pcie @@ -0,0 +1 @@ +../../../../ \ No newline at end of file diff --git a/fpga/lib/pcie/example/AU200/fpga/rtl/common b/fpga/lib/pcie/example/AU200/fpga/rtl/common new file mode 120000 index 000000000..e60fada70 --- /dev/null +++ b/fpga/lib/pcie/example/AU200/fpga/rtl/common @@ -0,0 +1 @@ +../../../common/rtl/ \ No newline at end of file diff --git a/fpga/lib/pcie/example/AU200/fpga/rtl/debounce_switch.v b/fpga/lib/pcie/example/AU200/fpga/rtl/debounce_switch.v new file mode 100644 index 000000000..8e93a50c4 --- /dev/null +++ b/fpga/lib/pcie/example/AU200/fpga/rtl/debounce_switch.v @@ -0,0 +1,93 @@ +/* + +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 diff --git a/fpga/lib/pcie/example/AU200/fpga/rtl/fpga.v b/fpga/lib/pcie/example/AU200/fpga/rtl/fpga.v new file mode 100644 index 000000000..da734e647 --- /dev/null +++ b/fpga/lib/pcie/example/AU200/fpga/rtl/fpga.v @@ -0,0 +1,463 @@ +/* + +Copyright (c) 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 1ns / 1ps +`default_nettype none + +/* + * FPGA top-level module + */ +module fpga ( + /* + * GPIO + */ + input wire [3:0] sw, + output wire [2:0] led, + + /* + * PCI express + */ + input wire [15:0] pcie_rx_p, + input wire [15:0] pcie_rx_n, + output wire [15:0] pcie_tx_p, + output wire [15:0] pcie_tx_n, + input wire pcie_refclk_p, + input wire pcie_refclk_n, + input wire pcie_reset_n +); + +parameter AXIS_PCIE_DATA_WIDTH = 512; +parameter AXIS_PCIE_KEEP_WIDTH = (AXIS_PCIE_DATA_WIDTH/32); +parameter AXIS_PCIE_RC_USER_WIDTH = AXIS_PCIE_DATA_WIDTH < 512 ? 75 : 161; +parameter AXIS_PCIE_RQ_USER_WIDTH = AXIS_PCIE_DATA_WIDTH < 512 ? 60 : 137; +parameter AXIS_PCIE_CQ_USER_WIDTH = AXIS_PCIE_DATA_WIDTH < 512 ? 85 : 183; +parameter AXIS_PCIE_CC_USER_WIDTH = AXIS_PCIE_DATA_WIDTH < 512 ? 33 : 81; + +parameter RQ_SEQ_NUM_WIDTH = AXIS_PCIE_RQ_USER_WIDTH == 60 ? 4 : 6; +parameter RQ_SEQ_NUM_ENABLE = 1; + +parameter PCIE_TAG_COUNT = 64; +parameter BAR0_APERTURE = 24; +parameter BAR2_APERTURE = 24; + +// Clock and reset +wire pcie_user_clk; +wire pcie_user_reset; + +// GPIO +wire [3:0] sw_int; + +debounce_switch #( + .WIDTH(4), + .N(4), + .RATE(250000) +) +debounce_switch_inst ( + .clk(pcie_user_clk), + .rst(pcie_user_reset), + .in({sw}), + .out({sw_int}) +); + +// PCIe +wire pcie_sys_clk; +wire pcie_sys_clk_gt; + +IBUFDS_GTE4 #( + .REFCLK_HROW_CK_SEL(2'b00) +) +ibufds_gte4_pcie_mgt_refclk_inst ( + .I (pcie_refclk_p), + .IB (pcie_refclk_n), + .CEB (1'b0), + .O (pcie_sys_clk_gt), + .ODIV2 (pcie_sys_clk) +); + +wire [AXIS_PCIE_DATA_WIDTH-1:0] axis_rq_tdata; +wire [AXIS_PCIE_KEEP_WIDTH-1:0] axis_rq_tkeep; +wire axis_rq_tlast; +wire axis_rq_tready; +wire [AXIS_PCIE_RQ_USER_WIDTH-1:0] axis_rq_tuser; +wire axis_rq_tvalid; + +wire [AXIS_PCIE_DATA_WIDTH-1:0] axis_rc_tdata; +wire [AXIS_PCIE_KEEP_WIDTH-1:0] axis_rc_tkeep; +wire axis_rc_tlast; +wire axis_rc_tready; +wire [AXIS_PCIE_RC_USER_WIDTH-1:0] axis_rc_tuser; +wire axis_rc_tvalid; + +wire [AXIS_PCIE_DATA_WIDTH-1:0] axis_cq_tdata; +wire [AXIS_PCIE_KEEP_WIDTH-1:0] axis_cq_tkeep; +wire axis_cq_tlast; +wire axis_cq_tready; +wire [AXIS_PCIE_CQ_USER_WIDTH-1:0] axis_cq_tuser; +wire axis_cq_tvalid; + +wire [AXIS_PCIE_DATA_WIDTH-1:0] axis_cc_tdata; +wire [AXIS_PCIE_KEEP_WIDTH-1:0] axis_cc_tkeep; +wire axis_cc_tlast; +wire axis_cc_tready; +wire [AXIS_PCIE_CC_USER_WIDTH-1:0] axis_cc_tuser; +wire axis_cc_tvalid; + +wire [RQ_SEQ_NUM_WIDTH-1:0] pcie_rq_seq_num0; +wire pcie_rq_seq_num_vld0; +wire [RQ_SEQ_NUM_WIDTH-1:0] pcie_rq_seq_num1; +wire pcie_rq_seq_num_vld1; + +// ila_0 rq_ila ( +// .clk(pcie_user_clk), +// .probe0(axis_rq_tdata), +// .probe1(axis_rq_tkeep), +// .probe2(axis_rq_tlast), +// .probe3(axis_rq_tready), +// .probe4(axis_rq_tuser), +// .probe5(axis_rq_tvalid) +// ); + +// ila_0 rc_ila ( +// .clk(pcie_user_clk), +// .probe0(axis_rc_tdata), +// .probe1(axis_rc_tkeep), +// .probe2(axis_rc_tlast), +// .probe3(axis_rc_tready), +// .probe4(axis_rc_tuser), +// .probe5(axis_rc_tvalid) +// ); + +wire [2:0] cfg_max_payload; +wire [2:0] cfg_max_read_req; + +wire [9:0] cfg_mgmt_addr; +wire [7:0] cfg_mgmt_function_number; +wire cfg_mgmt_write; +wire [31:0] cfg_mgmt_write_data; +wire [3:0] cfg_mgmt_byte_enable; +wire cfg_mgmt_read; +wire [31:0] cfg_mgmt_read_data; +wire cfg_mgmt_read_write_done; + +wire [7:0] cfg_fc_ph; +wire [11:0] cfg_fc_pd; +wire [7:0] cfg_fc_nph; +wire [11:0] cfg_fc_npd; +wire [7:0] cfg_fc_cplh; +wire [11:0] cfg_fc_cpld; +wire [2:0] cfg_fc_sel; + +wire [3:0] cfg_interrupt_msi_enable; +wire [11:0] cfg_interrupt_msi_mmenable; +wire cfg_interrupt_msi_mask_update; +wire [31:0] cfg_interrupt_msi_data; +wire [3:0] cfg_interrupt_msi_select; +wire [31:0] cfg_interrupt_msi_int; +wire [31:0] cfg_interrupt_msi_pending_status; +wire cfg_interrupt_msi_pending_status_data_enable; +wire [3:0] cfg_interrupt_msi_pending_status_function_num; +wire cfg_interrupt_msi_sent; +wire cfg_interrupt_msi_fail; +wire [2:0] cfg_interrupt_msi_attr; +wire cfg_interrupt_msi_tph_present; +wire [1:0] cfg_interrupt_msi_tph_type; +wire [8:0] cfg_interrupt_msi_tph_st_tag; +wire [3:0] cfg_interrupt_msi_function_number; + +wire status_error_cor; +wire status_error_uncor; + +pcie4_uscale_plus_0 +pcie4_uscale_plus_inst ( + .pci_exp_txn(pcie_tx_n), + .pci_exp_txp(pcie_tx_p), + .pci_exp_rxn(pcie_rx_n), + .pci_exp_rxp(pcie_rx_p), + .user_clk(pcie_user_clk), + .user_reset(pcie_user_reset), + .user_lnk_up(), + + .s_axis_rq_tdata(axis_rq_tdata), + .s_axis_rq_tkeep(axis_rq_tkeep), + .s_axis_rq_tlast(axis_rq_tlast), + .s_axis_rq_tready(axis_rq_tready), + .s_axis_rq_tuser(axis_rq_tuser), + .s_axis_rq_tvalid(axis_rq_tvalid), + + .m_axis_rc_tdata(axis_rc_tdata), + .m_axis_rc_tkeep(axis_rc_tkeep), + .m_axis_rc_tlast(axis_rc_tlast), + .m_axis_rc_tready(axis_rc_tready), + .m_axis_rc_tuser(axis_rc_tuser), + .m_axis_rc_tvalid(axis_rc_tvalid), + + .m_axis_cq_tdata(axis_cq_tdata), + .m_axis_cq_tkeep(axis_cq_tkeep), + .m_axis_cq_tlast(axis_cq_tlast), + .m_axis_cq_tready(axis_cq_tready), + .m_axis_cq_tuser(axis_cq_tuser), + .m_axis_cq_tvalid(axis_cq_tvalid), + + .s_axis_cc_tdata(axis_cc_tdata), + .s_axis_cc_tkeep(axis_cc_tkeep), + .s_axis_cc_tlast(axis_cc_tlast), + .s_axis_cc_tready(axis_cc_tready), + .s_axis_cc_tuser(axis_cc_tuser), + .s_axis_cc_tvalid(axis_cc_tvalid), + + .pcie_rq_seq_num0(pcie_rq_seq_num0), + .pcie_rq_seq_num_vld0(pcie_rq_seq_num_vld0), + .pcie_rq_seq_num1(pcie_rq_seq_num1), + .pcie_rq_seq_num_vld1(pcie_rq_seq_num_vld1), + .pcie_rq_tag0(), + .pcie_rq_tag1(), + .pcie_rq_tag_av(), + .pcie_rq_tag_vld0(), + .pcie_rq_tag_vld1(), + + .pcie_tfc_nph_av(), + .pcie_tfc_npd_av(), + + .pcie_cq_np_req(1'b1), + .pcie_cq_np_req_count(), + + .cfg_phy_link_down(), + .cfg_phy_link_status(), + .cfg_negotiated_width(), + .cfg_current_speed(), + .cfg_max_payload(cfg_max_payload), + .cfg_max_read_req(cfg_max_read_req), + .cfg_function_status(), + .cfg_function_power_state(), + .cfg_vf_status(), + .cfg_vf_power_state(), + .cfg_link_power_state(), + + .cfg_mgmt_addr(cfg_mgmt_addr), + .cfg_mgmt_function_number(cfg_mgmt_function_number), + .cfg_mgmt_write(cfg_mgmt_write), + .cfg_mgmt_write_data(cfg_mgmt_write_data), + .cfg_mgmt_byte_enable(cfg_mgmt_byte_enable), + .cfg_mgmt_read(cfg_mgmt_read), + .cfg_mgmt_read_data(cfg_mgmt_read_data), + .cfg_mgmt_read_write_done(cfg_mgmt_read_write_done), + .cfg_mgmt_debug_access(1'b0), + + .cfg_err_cor_out(), + .cfg_err_nonfatal_out(), + .cfg_err_fatal_out(), + .cfg_local_error_valid(), + .cfg_local_error_out(), + .cfg_ltssm_state(), + .cfg_rx_pm_state(), + .cfg_tx_pm_state(), + .cfg_rcb_status(), + .cfg_obff_enable(), + .cfg_pl_status_change(), + .cfg_tph_requester_enable(), + .cfg_tph_st_mode(), + .cfg_vf_tph_requester_enable(), + .cfg_vf_tph_st_mode(), + + .cfg_msg_received(), + .cfg_msg_received_data(), + .cfg_msg_received_type(), + .cfg_msg_transmit(1'b0), + .cfg_msg_transmit_type(3'd0), + .cfg_msg_transmit_data(32'd0), + .cfg_msg_transmit_done(), + + .cfg_fc_ph(cfg_fc_ph), + .cfg_fc_pd(cfg_fc_pd), + .cfg_fc_nph(cfg_fc_nph), + .cfg_fc_npd(cfg_fc_npd), + .cfg_fc_cplh(cfg_fc_cplh), + .cfg_fc_cpld(cfg_fc_cpld), + .cfg_fc_sel(cfg_fc_sel), + + .cfg_dsn(64'd0), + + .cfg_bus_number(), + + .cfg_power_state_change_ack(1'b1), + .cfg_power_state_change_interrupt(), + + .cfg_err_cor_in(status_error_cor), + .cfg_err_uncor_in(status_error_uncor), + .cfg_flr_in_process(), + .cfg_flr_done(4'd0), + .cfg_vf_flr_in_process(), + .cfg_vf_flr_func_num(8'd0), + .cfg_vf_flr_done(8'd0), + + .cfg_link_training_enable(1'b1), + + .cfg_interrupt_int(4'd0), + .cfg_interrupt_pending(4'd0), + .cfg_interrupt_sent(), + .cfg_interrupt_msi_enable(cfg_interrupt_msi_enable), + .cfg_interrupt_msi_mmenable(cfg_interrupt_msi_mmenable), + .cfg_interrupt_msi_mask_update(cfg_interrupt_msi_mask_update), + .cfg_interrupt_msi_data(cfg_interrupt_msi_data), + .cfg_interrupt_msi_select(cfg_interrupt_msi_select), + .cfg_interrupt_msi_int(cfg_interrupt_msi_int), + .cfg_interrupt_msi_pending_status(cfg_interrupt_msi_pending_status), + .cfg_interrupt_msi_pending_status_data_enable(cfg_interrupt_msi_pending_status_data_enable), + .cfg_interrupt_msi_pending_status_function_num(cfg_interrupt_msi_pending_status_function_num), + .cfg_interrupt_msi_sent(cfg_interrupt_msi_sent), + .cfg_interrupt_msi_fail(cfg_interrupt_msi_fail), + .cfg_interrupt_msi_attr(cfg_interrupt_msi_attr), + .cfg_interrupt_msi_tph_present(cfg_interrupt_msi_tph_present), + .cfg_interrupt_msi_tph_type(cfg_interrupt_msi_tph_type), + .cfg_interrupt_msi_tph_st_tag(cfg_interrupt_msi_tph_st_tag), + .cfg_interrupt_msi_function_number(cfg_interrupt_msi_function_number), + + .cfg_pm_aspm_l1_entry_reject(1'b0), + .cfg_pm_aspm_tx_l0s_entry_disable(1'b0), + + .cfg_hot_reset_out(), + + .cfg_config_space_enable(1'b1), + .cfg_req_pm_transition_l23_ready(1'b0), + .cfg_hot_reset_in(1'b0), + + .cfg_ds_port_number(8'd0), + .cfg_ds_bus_number(8'd0), + .cfg_ds_device_number(5'd0), + + .sys_clk(pcie_sys_clk), + .sys_clk_gt(pcie_sys_clk_gt), + .sys_reset(pcie_reset_n), + + .phy_rdy_out() +); + +fpga_core #( + .AXIS_PCIE_DATA_WIDTH(AXIS_PCIE_DATA_WIDTH), + .AXIS_PCIE_KEEP_WIDTH(AXIS_PCIE_KEEP_WIDTH), + .AXIS_PCIE_RC_USER_WIDTH(AXIS_PCIE_RC_USER_WIDTH), + .AXIS_PCIE_RQ_USER_WIDTH(AXIS_PCIE_RQ_USER_WIDTH), + .AXIS_PCIE_CQ_USER_WIDTH(AXIS_PCIE_CQ_USER_WIDTH), + .AXIS_PCIE_CC_USER_WIDTH(AXIS_PCIE_CC_USER_WIDTH), + .RQ_SEQ_NUM_WIDTH(RQ_SEQ_NUM_WIDTH), + .RQ_SEQ_NUM_ENABLE(RQ_SEQ_NUM_ENABLE), + .PCIE_TAG_COUNT(PCIE_TAG_COUNT), + .BAR0_APERTURE(BAR0_APERTURE), + .BAR2_APERTURE(BAR2_APERTURE) +) +core_inst ( + /* + * Clock: 250 MHz + * Synchronous reset + */ + .clk(pcie_user_clk), + .rst(pcie_user_reset), + /* + * GPIO + */ + .sw(sw_int), + .led(led), + /* + * PCIe + */ + .m_axis_rq_tdata(axis_rq_tdata), + .m_axis_rq_tkeep(axis_rq_tkeep), + .m_axis_rq_tlast(axis_rq_tlast), + .m_axis_rq_tready(axis_rq_tready), + .m_axis_rq_tuser(axis_rq_tuser), + .m_axis_rq_tvalid(axis_rq_tvalid), + + .s_axis_rc_tdata(axis_rc_tdata), + .s_axis_rc_tkeep(axis_rc_tkeep), + .s_axis_rc_tlast(axis_rc_tlast), + .s_axis_rc_tready(axis_rc_tready), + .s_axis_rc_tuser(axis_rc_tuser), + .s_axis_rc_tvalid(axis_rc_tvalid), + + .s_axis_cq_tdata(axis_cq_tdata), + .s_axis_cq_tkeep(axis_cq_tkeep), + .s_axis_cq_tlast(axis_cq_tlast), + .s_axis_cq_tready(axis_cq_tready), + .s_axis_cq_tuser(axis_cq_tuser), + .s_axis_cq_tvalid(axis_cq_tvalid), + + .m_axis_cc_tdata(axis_cc_tdata), + .m_axis_cc_tkeep(axis_cc_tkeep), + .m_axis_cc_tlast(axis_cc_tlast), + .m_axis_cc_tready(axis_cc_tready), + .m_axis_cc_tuser(axis_cc_tuser), + .m_axis_cc_tvalid(axis_cc_tvalid), + + .s_axis_rq_seq_num_0(pcie_rq_seq_num0), + .s_axis_rq_seq_num_valid_0(pcie_rq_seq_num_vld0), + .s_axis_rq_seq_num_1(pcie_rq_seq_num1), + .s_axis_rq_seq_num_valid_1(pcie_rq_seq_num_vld1), + + .cfg_max_payload(cfg_max_payload), + .cfg_max_read_req(cfg_max_read_req), + + .cfg_mgmt_addr(cfg_mgmt_addr), + .cfg_mgmt_function_number(cfg_mgmt_function_number), + .cfg_mgmt_write(cfg_mgmt_write), + .cfg_mgmt_write_data(cfg_mgmt_write_data), + .cfg_mgmt_byte_enable(cfg_mgmt_byte_enable), + .cfg_mgmt_read(cfg_mgmt_read), + .cfg_mgmt_read_data(cfg_mgmt_read_data), + .cfg_mgmt_read_write_done(cfg_mgmt_read_write_done), + + .cfg_fc_ph(cfg_fc_ph), + .cfg_fc_pd(cfg_fc_pd), + .cfg_fc_nph(cfg_fc_nph), + .cfg_fc_npd(cfg_fc_npd), + .cfg_fc_cplh(cfg_fc_cplh), + .cfg_fc_cpld(cfg_fc_cpld), + .cfg_fc_sel(cfg_fc_sel), + + .cfg_interrupt_msi_enable(cfg_interrupt_msi_enable), + .cfg_interrupt_msi_mmenable(cfg_interrupt_msi_mmenable), + .cfg_interrupt_msi_mask_update(cfg_interrupt_msi_mask_update), + .cfg_interrupt_msi_data(cfg_interrupt_msi_data), + .cfg_interrupt_msi_select(cfg_interrupt_msi_select), + .cfg_interrupt_msi_int(cfg_interrupt_msi_int), + .cfg_interrupt_msi_pending_status(cfg_interrupt_msi_pending_status), + .cfg_interrupt_msi_pending_status_data_enable(cfg_interrupt_msi_pending_status_data_enable), + .cfg_interrupt_msi_pending_status_function_num(cfg_interrupt_msi_pending_status_function_num), + .cfg_interrupt_msi_sent(cfg_interrupt_msi_sent), + .cfg_interrupt_msi_fail(cfg_interrupt_msi_fail), + .cfg_interrupt_msi_attr(cfg_interrupt_msi_attr), + .cfg_interrupt_msi_tph_present(cfg_interrupt_msi_tph_present), + .cfg_interrupt_msi_tph_type(cfg_interrupt_msi_tph_type), + .cfg_interrupt_msi_tph_st_tag(cfg_interrupt_msi_tph_st_tag), + .cfg_interrupt_msi_function_number(cfg_interrupt_msi_function_number), + + .status_error_cor(status_error_cor), + .status_error_uncor(status_error_uncor) +); + +endmodule + +`resetall diff --git a/fpga/lib/pcie/example/AU200/fpga/rtl/fpga_core.v b/fpga/lib/pcie/example/AU200/fpga/rtl/fpga_core.v new file mode 100644 index 000000000..a6c947b68 --- /dev/null +++ b/fpga/lib/pcie/example/AU200/fpga/rtl/fpga_core.v @@ -0,0 +1,271 @@ +/* + +Copyright (c) 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 1ns / 1ps +`default_nettype none + +/* + * FPGA core logic + */ +module fpga_core # +( + parameter AXIS_PCIE_DATA_WIDTH = 512, + parameter AXIS_PCIE_KEEP_WIDTH = (AXIS_PCIE_DATA_WIDTH/32), + parameter AXIS_PCIE_RC_USER_WIDTH = AXIS_PCIE_DATA_WIDTH < 512 ? 75 : 161, + parameter AXIS_PCIE_RQ_USER_WIDTH = AXIS_PCIE_DATA_WIDTH < 512 ? 60 : 137, + parameter AXIS_PCIE_CQ_USER_WIDTH = AXIS_PCIE_DATA_WIDTH < 512 ? 85 : 183, + parameter AXIS_PCIE_CC_USER_WIDTH = AXIS_PCIE_DATA_WIDTH < 512 ? 33 : 81, + parameter RQ_SEQ_NUM_WIDTH = AXIS_PCIE_RQ_USER_WIDTH == 60 ? 4 : 6, + parameter RQ_SEQ_NUM_ENABLE = 1, + parameter PCIE_TAG_COUNT = 64, + parameter BAR0_APERTURE = 24, + parameter BAR2_APERTURE = 24 +) +( + /* + * Clock: 250 MHz + * Synchronous reset + */ + input wire clk, + input wire rst, + + /* + * GPIO + */ + input wire [3:0] sw, + output wire [2:0] led, + + /* + * PCIe + */ + output wire [AXIS_PCIE_DATA_WIDTH-1:0] m_axis_rq_tdata, + output wire [AXIS_PCIE_KEEP_WIDTH-1:0] m_axis_rq_tkeep, + output wire m_axis_rq_tlast, + input wire m_axis_rq_tready, + output wire [AXIS_PCIE_RQ_USER_WIDTH-1:0] m_axis_rq_tuser, + output wire m_axis_rq_tvalid, + + input wire [AXIS_PCIE_DATA_WIDTH-1:0] s_axis_rc_tdata, + input wire [AXIS_PCIE_KEEP_WIDTH-1:0] s_axis_rc_tkeep, + input wire s_axis_rc_tlast, + output wire s_axis_rc_tready, + input wire [AXIS_PCIE_RC_USER_WIDTH-1:0] s_axis_rc_tuser, + input wire s_axis_rc_tvalid, + + input wire [AXIS_PCIE_DATA_WIDTH-1:0] s_axis_cq_tdata, + input wire [AXIS_PCIE_KEEP_WIDTH-1:0] s_axis_cq_tkeep, + input wire s_axis_cq_tlast, + output wire s_axis_cq_tready, + input wire [AXIS_PCIE_CQ_USER_WIDTH-1:0] s_axis_cq_tuser, + input wire s_axis_cq_tvalid, + + output wire [AXIS_PCIE_DATA_WIDTH-1:0] m_axis_cc_tdata, + output wire [AXIS_PCIE_KEEP_WIDTH-1:0] m_axis_cc_tkeep, + output wire m_axis_cc_tlast, + input wire m_axis_cc_tready, + output wire [AXIS_PCIE_CC_USER_WIDTH-1:0] m_axis_cc_tuser, + output wire m_axis_cc_tvalid, + + input wire [RQ_SEQ_NUM_WIDTH-1:0] s_axis_rq_seq_num_0, + input wire s_axis_rq_seq_num_valid_0, + input wire [RQ_SEQ_NUM_WIDTH-1:0] s_axis_rq_seq_num_1, + input wire s_axis_rq_seq_num_valid_1, + + input wire [2:0] cfg_max_payload, + input wire [2:0] cfg_max_read_req, + + output wire [9:0] cfg_mgmt_addr, + output wire [7:0] cfg_mgmt_function_number, + output wire cfg_mgmt_write, + output wire [31:0] cfg_mgmt_write_data, + output wire [3:0] cfg_mgmt_byte_enable, + output wire cfg_mgmt_read, + input wire [31:0] cfg_mgmt_read_data, + input wire cfg_mgmt_read_write_done, + + input wire [7:0] cfg_fc_ph, + input wire [11:0] cfg_fc_pd, + input wire [7:0] cfg_fc_nph, + input wire [11:0] cfg_fc_npd, + input wire [7:0] cfg_fc_cplh, + input wire [11:0] cfg_fc_cpld, + output wire [2:0] cfg_fc_sel, + + input wire [3:0] cfg_interrupt_msi_enable, + input wire [11:0] cfg_interrupt_msi_mmenable, + input wire cfg_interrupt_msi_mask_update, + input wire [31:0] cfg_interrupt_msi_data, + output wire [3:0] cfg_interrupt_msi_select, + output wire [31:0] cfg_interrupt_msi_int, + output wire [31:0] cfg_interrupt_msi_pending_status, + output wire cfg_interrupt_msi_pending_status_data_enable, + output wire [3:0] cfg_interrupt_msi_pending_status_function_num, + input wire cfg_interrupt_msi_sent, + input wire cfg_interrupt_msi_fail, + output wire [2:0] cfg_interrupt_msi_attr, + output wire cfg_interrupt_msi_tph_present, + output wire [1:0] cfg_interrupt_msi_tph_type, + output wire [8:0] cfg_interrupt_msi_tph_st_tag, + output wire [3:0] cfg_interrupt_msi_function_number, + + output wire status_error_cor, + output wire status_error_uncor +); + +assign led = 3'd0; + +example_core_pcie_us #( + .AXIS_PCIE_DATA_WIDTH(AXIS_PCIE_DATA_WIDTH), + .AXIS_PCIE_KEEP_WIDTH(AXIS_PCIE_KEEP_WIDTH), + .AXIS_PCIE_RC_USER_WIDTH(AXIS_PCIE_RC_USER_WIDTH), + .AXIS_PCIE_RQ_USER_WIDTH(AXIS_PCIE_RQ_USER_WIDTH), + .AXIS_PCIE_CQ_USER_WIDTH(AXIS_PCIE_CQ_USER_WIDTH), + .AXIS_PCIE_CC_USER_WIDTH(AXIS_PCIE_CC_USER_WIDTH), + .RQ_SEQ_NUM_WIDTH(RQ_SEQ_NUM_WIDTH), + .RQ_SEQ_NUM_ENABLE(RQ_SEQ_NUM_ENABLE), + .PCIE_TAG_COUNT(PCIE_TAG_COUNT), + .READ_OP_TABLE_SIZE(PCIE_TAG_COUNT), + .READ_TX_LIMIT(2**(RQ_SEQ_NUM_WIDTH-1)), + .READ_TX_FC_ENABLE(1), + .WRITE_OP_TABLE_SIZE(2**(RQ_SEQ_NUM_WIDTH-1)), + .WRITE_TX_LIMIT(2**(RQ_SEQ_NUM_WIDTH-1)), + .WRITE_TX_FC_ENABLE(1), + .BAR0_APERTURE(BAR0_APERTURE), + .BAR2_APERTURE(BAR2_APERTURE) +) +example_core_pcie_us_inst ( + .clk(clk), + .rst(rst), + + /* + * AXI input (RC) + */ + .s_axis_rc_tdata(s_axis_rc_tdata), + .s_axis_rc_tkeep(s_axis_rc_tkeep), + .s_axis_rc_tvalid(s_axis_rc_tvalid), + .s_axis_rc_tready(s_axis_rc_tready), + .s_axis_rc_tlast(s_axis_rc_tlast), + .s_axis_rc_tuser(s_axis_rc_tuser), + + /* + * AXI output (RQ) + */ + .m_axis_rq_tdata(m_axis_rq_tdata), + .m_axis_rq_tkeep(m_axis_rq_tkeep), + .m_axis_rq_tvalid(m_axis_rq_tvalid), + .m_axis_rq_tready(m_axis_rq_tready), + .m_axis_rq_tlast(m_axis_rq_tlast), + .m_axis_rq_tuser(m_axis_rq_tuser), + + /* + * AXI input (CQ) + */ + .s_axis_cq_tdata(s_axis_cq_tdata), + .s_axis_cq_tkeep(s_axis_cq_tkeep), + .s_axis_cq_tvalid(s_axis_cq_tvalid), + .s_axis_cq_tready(s_axis_cq_tready), + .s_axis_cq_tlast(s_axis_cq_tlast), + .s_axis_cq_tuser(s_axis_cq_tuser), + + /* + * AXI output (CC) + */ + .m_axis_cc_tdata(m_axis_cc_tdata), + .m_axis_cc_tkeep(m_axis_cc_tkeep), + .m_axis_cc_tvalid(m_axis_cc_tvalid), + .m_axis_cc_tready(m_axis_cc_tready), + .m_axis_cc_tlast(m_axis_cc_tlast), + .m_axis_cc_tuser(m_axis_cc_tuser), + + /* + * Transmit sequence number input + */ + .s_axis_rq_seq_num_0(s_axis_rq_seq_num_0), + .s_axis_rq_seq_num_valid_0(s_axis_rq_seq_num_valid_0), + .s_axis_rq_seq_num_1(s_axis_rq_seq_num_1), + .s_axis_rq_seq_num_valid_1(s_axis_rq_seq_num_valid_1), + + /* + * Flow control + */ + .cfg_fc_ph(cfg_fc_ph), + .cfg_fc_pd(cfg_fc_pd), + .cfg_fc_nph(cfg_fc_nph), + .cfg_fc_npd(cfg_fc_npd), + .cfg_fc_cplh(cfg_fc_cplh), + .cfg_fc_cpld(cfg_fc_cpld), + .cfg_fc_sel(cfg_fc_sel), + + /* + * Configuration interface + */ + .cfg_mgmt_addr(cfg_mgmt_addr), + .cfg_mgmt_function_number(cfg_mgmt_function_number), + .cfg_mgmt_write(cfg_mgmt_write), + .cfg_mgmt_write_data(cfg_mgmt_write_data), + .cfg_mgmt_byte_enable(cfg_mgmt_byte_enable), + .cfg_mgmt_read(cfg_mgmt_read), + .cfg_mgmt_read_data(cfg_mgmt_read_data), + .cfg_mgmt_read_write_done(cfg_mgmt_read_write_done), + + /* + * Interrupt interface + */ + .cfg_interrupt_msi_enable(cfg_interrupt_msi_enable), + .cfg_interrupt_msi_vf_enable(8'd0), + .cfg_interrupt_msi_mmenable(cfg_interrupt_msi_mmenable), + .cfg_interrupt_msi_mask_update(cfg_interrupt_msi_mask_update), + .cfg_interrupt_msi_data(cfg_interrupt_msi_data), + .cfg_interrupt_msi_select(cfg_interrupt_msi_select), + .cfg_interrupt_msi_int(cfg_interrupt_msi_int), + .cfg_interrupt_msi_pending_status(cfg_interrupt_msi_pending_status), + .cfg_interrupt_msi_pending_status_data_enable(cfg_interrupt_msi_pending_status_data_enable), + .cfg_interrupt_msi_pending_status_function_num(cfg_interrupt_msi_pending_status_function_num), + .cfg_interrupt_msi_sent(cfg_interrupt_msi_sent), + .cfg_interrupt_msi_fail(cfg_interrupt_msi_fail), + .cfg_interrupt_msi_attr(cfg_interrupt_msi_attr), + .cfg_interrupt_msi_tph_present(cfg_interrupt_msi_tph_present), + .cfg_interrupt_msi_tph_type(cfg_interrupt_msi_tph_type), + .cfg_interrupt_msi_tph_st_tag(cfg_interrupt_msi_tph_st_tag), + .cfg_interrupt_msi_function_number(cfg_interrupt_msi_function_number), + + /* + * Configuration + */ + .cfg_max_read_req(cfg_max_read_req), + .cfg_max_payload(cfg_max_payload), + + /* + * Status + */ + .status_error_cor(status_error_cor), + .status_error_uncor(status_error_uncor) +); + +endmodule + +`resetall diff --git a/fpga/lib/pcie/example/AU200/fpga/rtl/sync_reset.v b/fpga/lib/pcie/example/AU200/fpga/rtl/sync_reset.v new file mode 100644 index 000000000..1fd24d361 --- /dev/null +++ b/fpga/lib/pcie/example/AU200/fpga/rtl/sync_reset.v @@ -0,0 +1,56 @@ +/* + +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 active-high asynchronous reset signal to a given clock by + * using a pipeline of N registers. + */ +module sync_reset #( + parameter N=2 // depth of synchronizer +)( + input wire clk, + input wire rst, + output wire sync_reset_out +); + +reg [N-1:0] sync_reg = {N{1'b1}}; + +assign sync_reset_out = sync_reg[N-1]; + +always @(posedge clk or posedge rst) begin + if (rst) + sync_reg <= {N{1'b1}}; + else + sync_reg <= {sync_reg[N-2:0], 1'b0}; +end + +endmodule + +`resetall diff --git a/fpga/lib/pcie/example/AU200/fpga/rtl/sync_signal.v b/fpga/lib/pcie/example/AU200/fpga/rtl/sync_signal.v new file mode 100644 index 000000000..74b855fa1 --- /dev/null +++ b/fpga/lib/pcie/example/AU200/fpga/rtl/sync_signal.v @@ -0,0 +1,62 @@ +/* + +Copyright (c) 2014-2018 Alex Forencich + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +*/ + +// Language: Verilog-2001 + +`resetall +`timescale 1 ns / 1 ps +`default_nettype none + +/* + * Synchronizes an asyncronous signal to a given clock by using a pipeline of + * two registers. + */ +module sync_signal #( + parameter WIDTH=1, // width of the input and output signals + parameter N=2 // depth of synchronizer +)( + input wire clk, + input wire [WIDTH-1:0] in, + output wire [WIDTH-1:0] out +); + +reg [WIDTH-1:0] sync_reg[N-1:0]; + +/* + * The synchronized output is the last register in the pipeline. + */ +assign out = sync_reg[N-1]; + +integer k; + +always @(posedge clk) begin + sync_reg[0] <= in; + for (k = 1; k < N; k = k + 1) begin + sync_reg[k] <= sync_reg[k-1]; + end +end + +endmodule + +`resetall diff --git a/fpga/lib/pcie/example/AU200/fpga/tb/fpga_core/Makefile b/fpga/lib/pcie/example/AU200/fpga/tb/fpga_core/Makefile new file mode 100644 index 000000000..7c85b6e54 --- /dev/null +++ b/fpga/lib/pcie/example/AU200/fpga/tb/fpga_core/Makefile @@ -0,0 +1,123 @@ +# Copyright (c) 2020 Alex Forencich +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +TOPLEVEL_LANG = verilog + +SIM ?= icarus +WAVES ?= 0 + +COCOTB_HDL_TIMEUNIT = 1ns +COCOTB_HDL_TIMEPRECISION = 1ps + +DUT = fpga_core +TOPLEVEL = $(DUT) +MODULE = test_$(DUT) +VERILOG_SOURCES += ../../rtl/$(DUT).v +VERILOG_SOURCES += ../../rtl/common/example_core_pcie_us.v +VERILOG_SOURCES += ../../rtl/common/example_core_pcie.v +VERILOG_SOURCES += ../../rtl/common/example_core.v +VERILOG_SOURCES += ../../rtl/common/axi_ram.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_if.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_if_rc.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_if_rq.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_if_cq.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_if_cc.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_cfg.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_msi.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_axil_master.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_axi_master.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_axi_master_rd.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_axi_master_wr.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_tlp_demux_bar.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_tlp_demux.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_tlp_mux.v +VERILOG_SOURCES += ../../lib/pcie/rtl/dma_if_pcie.v +VERILOG_SOURCES += ../../lib/pcie/rtl/dma_if_pcie_rd.v +VERILOG_SOURCES += ../../lib/pcie/rtl/dma_if_pcie_wr.v +VERILOG_SOURCES += ../../lib/pcie/rtl/dma_psdpram.v +VERILOG_SOURCES += ../../lib/pcie/rtl/arbiter.v +VERILOG_SOURCES += ../../lib/pcie/rtl/priority_encoder.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pulse_merge.v + +# module parameters +export PARAM_AXIS_PCIE_DATA_WIDTH ?= 512 +export PARAM_AXIS_PCIE_KEEP_WIDTH ?= $(shell expr $(PARAM_AXIS_PCIE_DATA_WIDTH) / 32 ) +export PARAM_AXIS_PCIE_RQ_USER_WIDTH ?= $(if $(filter-out 512,$(PARAM_AXIS_PCIE_DATA_WIDTH)),62,137) +export PARAM_AXIS_PCIE_RC_USER_WIDTH ?= $(if $(filter-out 512,$(PARAM_AXIS_PCIE_DATA_WIDTH)),75,161) +export PARAM_AXIS_PCIE_CQ_USER_WIDTH ?= $(if $(filter-out 512,$(PARAM_AXIS_PCIE_DATA_WIDTH)),88,183) +export PARAM_AXIS_PCIE_CC_USER_WIDTH ?= $(if $(filter-out 512,$(PARAM_AXIS_PCIE_DATA_WIDTH)),33,81) +export PARAM_RQ_SEQ_NUM_WIDTH ?= 6 +export PARAM_RQ_SEQ_NUM_ENABLE ?= 1 +export PARAM_PCIE_TAG_COUNT ?= 64 +export PARAM_BAR0_APERTURE ?= 24 +export PARAM_BAR2_APERTURE ?= 24 + +ifeq ($(SIM), icarus) + PLUSARGS += -fst + + COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_DATA_WIDTH=$(PARAM_AXIS_PCIE_DATA_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_KEEP_WIDTH=$(PARAM_AXIS_PCIE_KEEP_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_RQ_USER_WIDTH=$(PARAM_AXIS_PCIE_RQ_USER_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_RC_USER_WIDTH=$(PARAM_AXIS_PCIE_RC_USER_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_CQ_USER_WIDTH=$(PARAM_AXIS_PCIE_CQ_USER_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_CC_USER_WIDTH=$(PARAM_AXIS_PCIE_CC_USER_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).RQ_SEQ_NUM_WIDTH=$(PARAM_RQ_SEQ_NUM_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).RQ_SEQ_NUM_ENABLE=$(PARAM_RQ_SEQ_NUM_ENABLE) + COMPILE_ARGS += -P $(TOPLEVEL).PCIE_TAG_COUNT=$(PARAM_PCIE_TAG_COUNT) + COMPILE_ARGS += -P $(TOPLEVEL).BAR0_APERTURE=$(PARAM_BAR0_APERTURE) + COMPILE_ARGS += -P $(TOPLEVEL).BAR2_APERTURE=$(PARAM_BAR2_APERTURE) + + ifeq ($(WAVES), 1) + VERILOG_SOURCES += iverilog_dump.v + COMPILE_ARGS += -s iverilog_dump + endif +else ifeq ($(SIM), verilator) + COMPILE_ARGS += -Wno-SELRANGE -Wno-WIDTH + + COMPILE_ARGS += -GAXIS_PCIE_DATA_WIDTH=$(PARAM_AXIS_PCIE_DATA_WIDTH) + COMPILE_ARGS += -GAXIS_PCIE_KEEP_WIDTH=$(PARAM_AXIS_PCIE_KEEP_WIDTH) + COMPILE_ARGS += -GAXIS_PCIE_RQ_USER_WIDTH=$(PARAM_AXIS_PCIE_RQ_USER_WIDTH) + COMPILE_ARGS += -GAXIS_PCIE_RC_USER_WIDTH=$(PARAM_AXIS_PCIE_RC_USER_WIDTH) + COMPILE_ARGS += -GAXIS_PCIE_CQ_USER_WIDTH=$(PARAM_AXIS_PCIE_CQ_USER_WIDTH) + COMPILE_ARGS += -GAXIS_PCIE_CC_USER_WIDTH=$(PARAM_AXIS_PCIE_CC_USER_WIDTH) + COMPILE_ARGS += -GRQ_SEQ_NUM_WIDTH=$(PARAM_RQ_SEQ_NUM_WIDTH) + COMPILE_ARGS += -GRQ_SEQ_NUM_ENABLE=$(PARAM_RQ_SEQ_NUM_ENABLE) + COMPILE_ARGS += -GPCIE_TAG_COUNT=$(PARAM_PCIE_TAG_COUNT) + COMPILE_ARGS += -GBAR0_APERTURE=$(PARAM_BAR0_APERTURE) + COMPILE_ARGS += -GBAR2_APERTURE=$(PARAM_BAR2_APERTURE) + + ifeq ($(WAVES), 1) + COMPILE_ARGS += --trace-fst + endif +endif + +include $(shell cocotb-config --makefiles)/Makefile.sim + +iverilog_dump.v: + echo 'module iverilog_dump();' > $@ + echo 'initial begin' >> $@ + echo ' $$dumpfile("$(TOPLEVEL).fst");' >> $@ + echo ' $$dumpvars(0, $(TOPLEVEL));' >> $@ + echo 'end' >> $@ + echo 'endmodule' >> $@ + +clean:: + @rm -rf iverilog_dump.v + @rm -rf dump.fst $(TOPLEVEL).fst diff --git a/fpga/lib/pcie/example/AU200/fpga/tb/fpga_core/test_fpga_core.py b/fpga/lib/pcie/example/AU200/fpga/tb/fpga_core/test_fpga_core.py new file mode 100644 index 000000000..429f0383f --- /dev/null +++ b/fpga/lib/pcie/example/AU200/fpga/tb/fpga_core/test_fpga_core.py @@ -0,0 +1,474 @@ +""" + +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 + +import cocotb_test.simulator + +import cocotb +from cocotb.log import SimLog +from cocotb.triggers import RisingEdge, FallingEdge, Timer + +from cocotbext.axi import AxiStreamBus +from cocotbext.pcie.core import RootComplex +from cocotbext.pcie.xilinx.us import UltraScalePlusPcieDevice + + +class TB(object): + def __init__(self, dut): + self.dut = dut + + self.log = SimLog("cocotb.tb") + self.log.setLevel(logging.DEBUG) + + # PCIe + self.rc = RootComplex() + + self.dev = UltraScalePlusPcieDevice( + # configuration options + pcie_generation=3, + pcie_link_width=16, + user_clk_frequency=250e6, + alignment="dword", + cq_cc_straddle=False, + rq_rc_straddle=False, + rc_4tlp_straddle=False, + enable_pf1=False, + enable_client_tag=True, + enable_extended_tag=True, + enable_parity=False, + enable_rx_msg_interface=False, + enable_sriov=False, + enable_extended_configuration=False, + + enable_pf0_msi=True, + enable_pf1_msi=False, + + # signals + # Clock and Reset Interface + user_clk=dut.clk, + user_reset=dut.rst, + # user_lnk_up + # sys_clk + # sys_clk_gt + # sys_reset + # phy_rdy_out + + # Requester reQuest Interface + rq_bus=AxiStreamBus.from_prefix(dut, "m_axis_rq"), + pcie_rq_seq_num0=dut.s_axis_rq_seq_num_0, + pcie_rq_seq_num_vld0=dut.s_axis_rq_seq_num_valid_0, + pcie_rq_seq_num1=dut.s_axis_rq_seq_num_1, + pcie_rq_seq_num_vld1=dut.s_axis_rq_seq_num_valid_1, + # pcie_rq_tag0 + # pcie_rq_tag1 + # pcie_rq_tag_av + # pcie_rq_tag_vld0 + # pcie_rq_tag_vld1 + + # Requester Completion Interface + rc_bus=AxiStreamBus.from_prefix(dut, "s_axis_rc"), + + # Completer reQuest Interface + cq_bus=AxiStreamBus.from_prefix(dut, "s_axis_cq"), + # pcie_cq_np_req + # pcie_cq_np_req_count + + # Completer Completion Interface + cc_bus=AxiStreamBus.from_prefix(dut, "m_axis_cc"), + + # Transmit Flow Control Interface + # pcie_tfc_nph_av=dut.pcie_tfc_nph_av, + # pcie_tfc_npd_av=dut.pcie_tfc_npd_av, + + # Configuration Management Interface + cfg_mgmt_addr=dut.cfg_mgmt_addr, + cfg_mgmt_function_number=dut.cfg_mgmt_function_number, + cfg_mgmt_write=dut.cfg_mgmt_write, + cfg_mgmt_write_data=dut.cfg_mgmt_write_data, + cfg_mgmt_byte_enable=dut.cfg_mgmt_byte_enable, + cfg_mgmt_read=dut.cfg_mgmt_read, + cfg_mgmt_read_data=dut.cfg_mgmt_read_data, + cfg_mgmt_read_write_done=dut.cfg_mgmt_read_write_done, + # cfg_mgmt_debug_access + + # Configuration Status Interface + # cfg_phy_link_down + # cfg_phy_link_status + # cfg_negotiated_width + # cfg_current_speed + cfg_max_payload=dut.cfg_max_payload, + cfg_max_read_req=dut.cfg_max_read_req, + # cfg_function_status + # cfg_vf_status + # cfg_function_power_state + # cfg_vf_power_state + # cfg_link_power_state + # cfg_err_cor_out + # cfg_err_nonfatal_out + # cfg_err_fatal_out + # cfg_local_error_out + # cfg_local_error_valid + # cfg_rx_pm_state + # cfg_tx_pm_state + # cfg_ltssm_state + # cfg_rcb_status + # cfg_obff_enable + # cfg_pl_status_change + # cfg_tph_requester_enable + # cfg_tph_st_mode + # cfg_vf_tph_requester_enable + # cfg_vf_tph_st_mode + + # Configuration Received Message Interface + # cfg_msg_received + # cfg_msg_received_data + # cfg_msg_received_type + + # Configuration Transmit Message Interface + # cfg_msg_transmit + # cfg_msg_transmit_type + # cfg_msg_transmit_data + # cfg_msg_transmit_done + + # Configuration Flow Control Interface + cfg_fc_ph=dut.cfg_fc_ph, + cfg_fc_pd=dut.cfg_fc_pd, + cfg_fc_nph=dut.cfg_fc_nph, + cfg_fc_npd=dut.cfg_fc_npd, + cfg_fc_cplh=dut.cfg_fc_cplh, + cfg_fc_cpld=dut.cfg_fc_cpld, + cfg_fc_sel=dut.cfg_fc_sel, + + # Configuration Control Interface + # cfg_hot_reset_in + # cfg_hot_reset_out + # cfg_config_space_enable + # cfg_dsn + # cfg_bus_number + # cfg_ds_port_number + # cfg_ds_bus_number + # cfg_ds_device_number + # cfg_ds_function_number + # cfg_power_state_change_ack + # cfg_power_state_change_interrupt + cfg_err_cor_in=dut.status_error_cor, + cfg_err_uncor_in=dut.status_error_uncor, + # cfg_flr_in_process + # cfg_flr_done + # cfg_vf_flr_in_process + # cfg_vf_flr_func_num + # cfg_vf_flr_done + # cfg_pm_aspm_l1_entry_reject + # cfg_pm_aspm_tx_l0s_entry_disable + # cfg_req_pm_transition_l23_ready + # cfg_link_training_enable + + # Configuration Interrupt Controller Interface + # cfg_interrupt_int + # cfg_interrupt_sent + # cfg_interrupt_pending + cfg_interrupt_msi_enable=dut.cfg_interrupt_msi_enable, + cfg_interrupt_msi_mmenable=dut.cfg_interrupt_msi_mmenable, + cfg_interrupt_msi_mask_update=dut.cfg_interrupt_msi_mask_update, + cfg_interrupt_msi_data=dut.cfg_interrupt_msi_data, + # cfg_interrupt_msi_select=dut.cfg_interrupt_msi_select, + cfg_interrupt_msi_int=dut.cfg_interrupt_msi_int, + cfg_interrupt_msi_pending_status=dut.cfg_interrupt_msi_pending_status, + cfg_interrupt_msi_pending_status_data_enable=dut.cfg_interrupt_msi_pending_status_data_enable, + # cfg_interrupt_msi_pending_status_function_num=dut.cfg_interrupt_msi_pending_status_function_num, + cfg_interrupt_msi_sent=dut.cfg_interrupt_msi_sent, + cfg_interrupt_msi_fail=dut.cfg_interrupt_msi_fail, + # cfg_interrupt_msix_enable + # cfg_interrupt_msix_mask + # cfg_interrupt_msix_vf_enable + # cfg_interrupt_msix_vf_mask + # cfg_interrupt_msix_address + # cfg_interrupt_msix_data + # cfg_interrupt_msix_int + # cfg_interrupt_msix_vec_pending + # cfg_interrupt_msix_vec_pending_status + cfg_interrupt_msi_attr=dut.cfg_interrupt_msi_attr, + cfg_interrupt_msi_tph_present=dut.cfg_interrupt_msi_tph_present, + cfg_interrupt_msi_tph_type=dut.cfg_interrupt_msi_tph_type, + # cfg_interrupt_msi_tph_st_tag=dut.cfg_interrupt_msi_tph_st_tag, + # cfg_interrupt_msi_function_number=dut.cfg_interrupt_msi_function_number, + + # Configuration Extend Interface + # cfg_ext_read_received + # cfg_ext_write_received + # cfg_ext_register_number + # cfg_ext_function_number + # cfg_ext_write_data + # cfg_ext_write_byte_enable + # cfg_ext_read_data + # cfg_ext_read_data_valid + ) + + # self.dev.log.setLevel(logging.DEBUG) + + self.rc.make_port().connect(self.dev) + + self.dev.functions[0].msi_multiple_message_capable = 5 + + self.dev.functions[0].configure_bar(0, 2**len(dut.example_core_pcie_us_inst.core_pcie_inst.axil_ctrl_awaddr)) + self.dev.functions[0].configure_bar(2, 2**len(dut.example_core_pcie_us_inst.core_pcie_inst.axi_ram_awaddr)) + + dut.sw.setimmediatevalue(0) + + async def init(self): + + await FallingEdge(self.dut.rst) + await Timer(100, 'ns') + + await self.rc.enumerate(enable_bus_mastering=True, configure_msi=True) + + +@cocotb.test() +async def run_test(dut): + + tb = TB(dut) + + await tb.init() + + mem = tb.rc.mem_pool.alloc_region(16*1024*1024) + mem_base = mem.get_absolute_address(0) + + dev_pf0_bar0 = tb.rc.tree[0][0].bar_window[0] + dev_pf0_bar2 = tb.rc.tree[0][0].bar_window[2] + + tb.log.info("Test memory write to BAR 2") + + test_data = b'\x11\x22\x33\x44' + await dev_pf0_bar2.write(0, test_data) + + await Timer(100, 'ns') + + tb.log.info("Test memory read from BAR 2") + + val = await dev_pf0_bar2.read(0, len(test_data), timeout=1000) + tb.log.info("Read data: %s", val) + assert val == test_data + + tb.log.info("Test DMA") + + # write packet data + mem[0:1024] = bytearray([x % 256 for x in range(1024)]) + + # enable DMA + await dev_pf0_bar0.write_dword(0x000000, 1) + + # write pcie read descriptor + await dev_pf0_bar0.write_dword(0x000100, (mem_base+0x0000) & 0xffffffff) + await dev_pf0_bar0.write_dword(0x000104, (mem_base+0x0000 >> 32) & 0xffffffff) + await dev_pf0_bar0.write_dword(0x000108, 0x100) + await dev_pf0_bar0.write_dword(0x000110, 0x400) + await dev_pf0_bar0.write_dword(0x000114, 0xAA) + + await Timer(2000, 'ns') + + # read status + val = await dev_pf0_bar0.read_dword(0x000118) + tb.log.info("Status: 0x%x", val) + assert val == 0x800000AA + + # write pcie write descriptor + await dev_pf0_bar0.write_dword(0x000200, (mem_base+0x1000) & 0xffffffff) + await dev_pf0_bar0.write_dword(0x000204, (mem_base+0x1000 >> 32) & 0xffffffff) + await dev_pf0_bar0.write_dword(0x000208, 0x100) + await dev_pf0_bar0.write_dword(0x000210, 0x400) + await dev_pf0_bar0.write_dword(0x000214, 0x55) + + await Timer(2000, 'ns') + + # read status + val = await dev_pf0_bar0.read_dword(0x000218) + tb.log.info("Status: 0x%x", val) + assert val == 0x80000055 + + tb.log.info("%s", mem.hexdump_str(0x1000, 64)) + + assert mem[0:1024] == mem[0x1000:0x1000+1024] + + tb.log.info("Test DMA block operations") + + # write packet data + mem[0:1024] = bytearray([x % 256 for x in range(1024)]) + + # enable DMA + await dev_pf0_bar0.write_dword(0x000000, 1) + # disable interrupts + await dev_pf0_bar0.write_dword(0x000008, 0) + + # configure operation (read) + # DMA base address + await dev_pf0_bar0.write_dword(0x001080, (mem_base+0x0000) & 0xffffffff) + await dev_pf0_bar0.write_dword(0x001084, (mem_base+0x0000 >> 32) & 0xffffffff) + # DMA offset address + await dev_pf0_bar0.write_dword(0x001088, 0) + await dev_pf0_bar0.write_dword(0x00108c, 0) + # DMA offset mask + await dev_pf0_bar0.write_dword(0x001090, 0x000003ff) + await dev_pf0_bar0.write_dword(0x001094, 0) + # DMA stride + await dev_pf0_bar0.write_dword(0x001098, 256) + await dev_pf0_bar0.write_dword(0x00109c, 0) + # RAM base address + await dev_pf0_bar0.write_dword(0x0010c0, 0) + await dev_pf0_bar0.write_dword(0x0010c4, 0) + # RAM offset address + await dev_pf0_bar0.write_dword(0x0010c8, 0) + await dev_pf0_bar0.write_dword(0x0010cc, 0) + # RAM offset mask + await dev_pf0_bar0.write_dword(0x0010d0, 0x000003ff) + await dev_pf0_bar0.write_dword(0x0010d4, 0) + # RAM stride + await dev_pf0_bar0.write_dword(0x0010d8, 256) + await dev_pf0_bar0.write_dword(0x0010dc, 0) + # clear cycle count + await dev_pf0_bar0.write_dword(0x001008, 0) + await dev_pf0_bar0.write_dword(0x00100c, 0) + # block length + await dev_pf0_bar0.write_dword(0x001010, 256) + # block count + await dev_pf0_bar0.write_dword(0x001018, 32) + await dev_pf0_bar0.write_dword(0x00101c, 0) + # start + await dev_pf0_bar0.write_dword(0x001000, 1) + + await Timer(2000, 'ns') + + # configure operation (write) + # DMA base address + await dev_pf0_bar0.write_dword(0x001180, (mem_base+0x0000) & 0xffffffff) + await dev_pf0_bar0.write_dword(0x001184, (mem_base+0x0000 >> 32) & 0xffffffff) + # DMA offset address + await dev_pf0_bar0.write_dword(0x001188, 0) + await dev_pf0_bar0.write_dword(0x00118c, 0) + # DMA offset mask + await dev_pf0_bar0.write_dword(0x001190, 0x000003ff) + await dev_pf0_bar0.write_dword(0x001194, 0) + # DMA stride + await dev_pf0_bar0.write_dword(0x001198, 256) + await dev_pf0_bar0.write_dword(0x00119c, 0) + # RAM base address + await dev_pf0_bar0.write_dword(0x0011c0, 0) + await dev_pf0_bar0.write_dword(0x0011c4, 0) + # RAM offset address + await dev_pf0_bar0.write_dword(0x0011c8, 0) + await dev_pf0_bar0.write_dword(0x0011cc, 0) + # RAM offset mask + await dev_pf0_bar0.write_dword(0x0011d0, 0x000003ff) + await dev_pf0_bar0.write_dword(0x0011d4, 0) + # RAM stride + await dev_pf0_bar0.write_dword(0x0011d8, 256) + await dev_pf0_bar0.write_dword(0x0011dc, 0) + # clear cycle count + await dev_pf0_bar0.write_dword(0x001108, 0) + await dev_pf0_bar0.write_dword(0x00110c, 0) + # block length + await dev_pf0_bar0.write_dword(0x001110, 256) + # block count + await dev_pf0_bar0.write_dword(0x001118, 32) + await dev_pf0_bar0.write_dword(0x00111c, 0) + # start + await dev_pf0_bar0.write_dword(0x001100, 1) + + await Timer(2000, 'ns') + + await RisingEdge(dut.clk) + await RisingEdge(dut.clk) + + +# cocotb-test + +tests_dir = 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')) +pcie_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'pcie', '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(rtl_dir, "common", "example_core_pcie_us.v"), + os.path.join(rtl_dir, "common", "example_core_pcie.v"), + os.path.join(rtl_dir, "common", "example_core.v"), + os.path.join(rtl_dir, "common", "axi_ram.v"), + os.path.join(pcie_rtl_dir, "pcie_us_if.v"), + os.path.join(pcie_rtl_dir, "pcie_us_if_rc.v"), + os.path.join(pcie_rtl_dir, "pcie_us_if_rq.v"), + os.path.join(pcie_rtl_dir, "pcie_us_if_cq.v"), + os.path.join(pcie_rtl_dir, "pcie_us_if_cc.v"), + os.path.join(pcie_rtl_dir, "pcie_us_cfg.v"), + os.path.join(pcie_rtl_dir, "pcie_us_msi.v"), + os.path.join(pcie_rtl_dir, "pcie_axil_master.v"), + os.path.join(pcie_rtl_dir, "pcie_axi_master.v"), + os.path.join(pcie_rtl_dir, "pcie_axi_master_rd.v"), + os.path.join(pcie_rtl_dir, "pcie_axi_master_wr.v"), + os.path.join(pcie_rtl_dir, "pcie_tlp_demux_bar.v"), + os.path.join(pcie_rtl_dir, "pcie_tlp_demux.v"), + os.path.join(pcie_rtl_dir, "pcie_tlp_mux.v"), + os.path.join(pcie_rtl_dir, "dma_if_pcie.v"), + os.path.join(pcie_rtl_dir, "dma_if_pcie_rd.v"), + os.path.join(pcie_rtl_dir, "dma_if_pcie_wr.v"), + os.path.join(pcie_rtl_dir, "dma_psdpram.v"), + os.path.join(pcie_rtl_dir, "arbiter.v"), + os.path.join(pcie_rtl_dir, "priority_encoder.v"), + os.path.join(pcie_rtl_dir, "pulse_merge.v"), + ] + + parameters = {} + + parameters['AXIS_PCIE_DATA_WIDTH'] = 512 + parameters['AXIS_PCIE_KEEP_WIDTH'] = parameters['AXIS_PCIE_DATA_WIDTH'] // 32 + parameters['AXIS_PCIE_RQ_USER_WIDTH'] = 62 if parameters['AXIS_PCIE_DATA_WIDTH'] < 512 else 137 + parameters['AXIS_PCIE_RC_USER_WIDTH'] = 75 if parameters['AXIS_PCIE_DATA_WIDTH'] < 512 else 161 + parameters['AXIS_PCIE_CQ_USER_WIDTH'] = 88 if parameters['AXIS_PCIE_DATA_WIDTH'] < 512 else 183 + parameters['AXIS_PCIE_CC_USER_WIDTH'] = 33 if parameters['AXIS_PCIE_DATA_WIDTH'] < 512 else 81 + parameters['RQ_SEQ_NUM_WIDTH'] = 6 + parameters['RQ_SEQ_NUM_ENABLE'] = 1 + parameters['PCIE_TAG_COUNT'] = 64 + parameters['BAR0_APERTURE'] = 24 + parameters['BAR2_APERTURE'] = 24 + + 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, + ) diff --git a/fpga/lib/pcie/example/AU250/fpga/README.md b/fpga/lib/pcie/example/AU250/fpga/README.md new file mode 100644 index 000000000..b1cb98571 --- /dev/null +++ b/fpga/lib/pcie/example/AU250/fpga/README.md @@ -0,0 +1,19 @@ +# Verilog PCIe Alveo U250 Example Design + +## Introduction + +This example design targets the Xilinx Alveo U250 FPGA board. + +The design implements the PCIe AXI lite master module, the PCIe AXI master module, and the PCIe DMA module. A very simple Linux driver is included to test the FPGA design. + +* FPGA: xcu250-figd2104-2-e + +## How to build + +Run `make` to build. Ensure that the Xilinx Vivado components are in PATH. + +Run `make` to build the driver. Ensure the headers for the running kernel are installed, otherwise the driver cannot be compiled. + +## How to test + +Run `make program` to program the Alveo U250 board with Vivado. Then load the driver with `insmod example.ko`. Check dmesg for the output. diff --git a/fpga/lib/pcie/example/AU250/fpga/common/vivado.mk b/fpga/lib/pcie/example/AU250/fpga/common/vivado.mk new file mode 100644 index 000000000..d47a43947 --- /dev/null +++ b/fpga/lib/pcie/example/AU250/fpga/common/vivado.mk @@ -0,0 +1,126 @@ +################################################################### +# +# 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) + +SYN_FILES_REL = $(patsubst %, ../%, $(filter-out /% ./%,$(SYN_FILES))) $(filter /% ./%,$(SYN_FILES)) +INC_FILES_REL = $(patsubst %, ../%, $(filter-out /% ./%,$(INC_FILES))) $(filter /% ./%,$(INC_FILES)) +XCI_FILES_REL = $(patsubst %, ../%, $(filter-out /% ./%,$(XCI_FILES))) $(filter /% ./%,$(XCI_FILES)) +IP_TCL_FILES_REL = $(patsubst %, ../%, $(filter-out /% ./%,$(IP_TCL_FILES))) $(filter /% ./%,$(IP_TCL_FILES)) +CONFIG_TCL_FILES_REL = $(patsubst %, ../%, $(filter-out /% ./%,$(CONFIG_TCL_FILES))) $(filter /% ./%,$(CONFIG_TCL_FILES)) + +ifdef XDC_FILES + XDC_FILES_REL = $(patsubst %, ../%, $(filter-out /% ./%,$(XDC_FILES))) $(filter /% ./%,$(XDC_FILES)) +else + XDC_FILES_REL = $(FPGA_TOP).xdc +endif + +################################################################### +# Main Targets +# +# all: build everything +# clean: remove output files and project files +################################################################### + +all: fpga + +fpga: $(FPGA_TOP).bit + +vivado: $(FPGA_TOP).xpr + vivado $(FPGA_TOP).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 program.tcl generate_mcs.tcl *.mcs *.prm flash.tcl + +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) $(FPGA_TOP)" > $@ + echo "add_files -fileset sources_1 defines.v $(SYN_FILES_REL)" >> $@ + 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) + echo "open_project -quiet $(FPGA_TOP).xpr" > $@ + for x in $(CONFIG_TCL_FILES_REL); do echo "source $$x" >> $@; done + +$(FPGA_TOP).xpr: create_project.tcl update_config.tcl + vivado -nojournal -nolog -mode batch $(foreach x,$?,-source $x) + +# synthesis run +%.runs/synth_1/%.dcp: %.xpr $(SYN_FILES_REL) $(INC_FILES_REL) $(XDC_FILES_REL) $(CONFIG_TCL_FILES_REL) + echo "open_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 +%.runs/impl_1/%_routed.dcp: %.runs/synth_1/%.dcp + echo "open_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 + vivado -nojournal -nolog -mode batch -source run_impl.tcl + +# bit file +%.bit: %.runs/impl_1/%_routed.dcp + echo "open_project $*.xpr" > generate_bit.tcl + echo "open_run impl_1" >> generate_bit.tcl + echo "write_bitstream -force $*.bit" >> generate_bit.tcl + vivado -nojournal -nolog -mode batch -source generate_bit.tcl + mkdir -p rev + EXT=bit; COUNT=100; \ + while [ -e rev/$*_rev$$COUNT.$$EXT ]; \ + do COUNT=$$((COUNT+1)); done; \ + cp $@ rev/$*_rev$$COUNT.$$EXT; \ + echo "Output: rev/$*_rev$$COUNT.$$EXT"; diff --git a/fpga/lib/pcie/example/AU250/fpga/driver b/fpga/lib/pcie/example/AU250/fpga/driver new file mode 120000 index 000000000..4a54c76b5 --- /dev/null +++ b/fpga/lib/pcie/example/AU250/fpga/driver @@ -0,0 +1 @@ +../../common/driver/example/ \ No newline at end of file diff --git a/fpga/lib/pcie/example/AU250/fpga/fpga.xdc b/fpga/lib/pcie/example/AU250/fpga/fpga.xdc new file mode 100644 index 000000000..2fd2bc456 --- /dev/null +++ b/fpga/lib/pcie/example/AU250/fpga/fpga.xdc @@ -0,0 +1,259 @@ +# 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_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_rx1_p] ;# MGTYRXP0_231 GTYE4_CHANNEL_X1Y44 / GTYE4_COMMON_X1Y11 +#set_property -dict {LOC N3 } [get_ports qsfp0_rx1_n] ;# MGTYRXN0_231 GTYE4_CHANNEL_X1Y44 / GTYE4_COMMON_X1Y11 +#set_property -dict {LOC N9 } [get_ports qsfp0_tx1_p] ;# MGTYTXP0_231 GTYE4_CHANNEL_X1Y44 / GTYE4_COMMON_X1Y11 +#set_property -dict {LOC N8 } [get_ports qsfp0_tx1_n] ;# MGTYTXN0_231 GTYE4_CHANNEL_X1Y44 / GTYE4_COMMON_X1Y11 +#set_property -dict {LOC M2 } [get_ports qsfp0_rx2_p] ;# MGTYRXP1_231 GTYE4_CHANNEL_X1Y45 / GTYE4_COMMON_X1Y11 +#set_property -dict {LOC M1 } [get_ports qsfp0_rx2_n] ;# MGTYRXN1_231 GTYE4_CHANNEL_X1Y45 / GTYE4_COMMON_X1Y11 +#set_property -dict {LOC M7 } [get_ports qsfp0_tx2_p] ;# MGTYTXP1_231 GTYE4_CHANNEL_X1Y45 / GTYE4_COMMON_X1Y11 +#set_property -dict {LOC M6 } [get_ports qsfp0_tx2_n] ;# MGTYTXN1_231 GTYE4_CHANNEL_X1Y45 / GTYE4_COMMON_X1Y11 +#set_property -dict {LOC L4 } [get_ports qsfp0_rx3_p] ;# MGTYRXP2_231 GTYE4_CHANNEL_X1Y46 / GTYE4_COMMON_X1Y11 +#set_property -dict {LOC L3 } [get_ports qsfp0_rx3_n] ;# MGTYRXN2_231 GTYE4_CHANNEL_X1Y46 / GTYE4_COMMON_X1Y11 +#set_property -dict {LOC L9 } [get_ports qsfp0_tx3_p] ;# MGTYTXP2_231 GTYE4_CHANNEL_X1Y46 / GTYE4_COMMON_X1Y11 +#set_property -dict {LOC L8 } [get_ports qsfp0_tx3_n] ;# MGTYTXN2_231 GTYE4_CHANNEL_X1Y46 / GTYE4_COMMON_X1Y11 +#set_property -dict {LOC K2 } [get_ports qsfp0_rx4_p] ;# MGTYRXP3_231 GTYE4_CHANNEL_X1Y47 / GTYE4_COMMON_X1Y11 +#set_property -dict {LOC K1 } [get_ports qsfp0_rx4_n] ;# MGTYRXN3_231 GTYE4_CHANNEL_X1Y47 / GTYE4_COMMON_X1Y11 +#set_property -dict {LOC K7 } [get_ports qsfp0_tx4_p] ;# MGTYTXP3_231 GTYE4_CHANNEL_X1Y47 / GTYE4_COMMON_X1Y11 +#set_property -dict {LOC K6 } [get_ports qsfp0_tx4_n] ;# 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_rx1_p] ;# MGTYRXP0_230 GTYE4_CHANNEL_X1Y40 / GTYE4_COMMON_X1Y10 +#set_property -dict {LOC U3 } [get_ports qsfp1_rx1_n] ;# MGTYRXN0_230 GTYE4_CHANNEL_X1Y40 / GTYE4_COMMON_X1Y10 +#set_property -dict {LOC U9 } [get_ports qsfp1_tx1_p] ;# MGTYTXP0_230 GTYE4_CHANNEL_X1Y40 / GTYE4_COMMON_X1Y10 +#set_property -dict {LOC U8 } [get_ports qsfp1_tx1_n] ;# MGTYTXN0_230 GTYE4_CHANNEL_X1Y40 / GTYE4_COMMON_X1Y10 +#set_property -dict {LOC T2 } [get_ports qsfp1_rx2_p] ;# MGTYRXP1_230 GTYE4_CHANNEL_X1Y41 / GTYE4_COMMON_X1Y10 +#set_property -dict {LOC T1 } [get_ports qsfp1_rx2_n] ;# MGTYRXN1_230 GTYE4_CHANNEL_X1Y41 / GTYE4_COMMON_X1Y10 +#set_property -dict {LOC T7 } [get_ports qsfp1_tx2_p] ;# MGTYTXP1_230 GTYE4_CHANNEL_X1Y41 / GTYE4_COMMON_X1Y10 +#set_property -dict {LOC T6 } [get_ports qsfp1_tx2_n] ;# MGTYTXN1_230 GTYE4_CHANNEL_X1Y41 / GTYE4_COMMON_X1Y10 +#set_property -dict {LOC R4 } [get_ports qsfp1_rx3_p] ;# MGTYRXP2_230 GTYE4_CHANNEL_X1Y42 / GTYE4_COMMON_X1Y10 +#set_property -dict {LOC R3 } [get_ports qsfp1_rx3_n] ;# MGTYRXN2_230 GTYE4_CHANNEL_X1Y42 / GTYE4_COMMON_X1Y10 +#set_property -dict {LOC R9 } [get_ports qsfp1_tx3_p] ;# MGTYTXP2_230 GTYE4_CHANNEL_X1Y42 / GTYE4_COMMON_X1Y10 +#set_property -dict {LOC R8 } [get_ports qsfp1_tx3_n] ;# MGTYTXN2_230 GTYE4_CHANNEL_X1Y42 / GTYE4_COMMON_X1Y10 +#set_property -dict {LOC P2 } [get_ports qsfp1_rx4_p] ;# MGTYRXP3_230 GTYE4_CHANNEL_X1Y43 / GTYE4_COMMON_X1Y10 +#set_property -dict {LOC P1 } [get_ports qsfp1_rx4_n] ;# MGTYRXN3_230 GTYE4_CHANNEL_X1Y43 / GTYE4_COMMON_X1Y10 +#set_property -dict {LOC P7 } [get_ports qsfp1_tx4_p] ;# MGTYTXP3_230 GTYE4_CHANNEL_X1Y43 / GTYE4_COMMON_X1Y10 +#set_property -dict {LOC P6 } [get_ports qsfp1_tx4_n] ;# 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}] diff --git a/fpga/lib/pcie/example/AU250/fpga/fpga/Makefile b/fpga/lib/pcie/example/AU250/fpga/fpga/Makefile new file mode 100644 index 000000000..2dced7d09 --- /dev/null +++ b/fpga/lib/pcie/example/AU250/fpga/fpga/Makefile @@ -0,0 +1,94 @@ + +# FPGA settings +FPGA_PART = xcu250-figd2104-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/debounce_switch.v +SYN_FILES += rtl/sync_reset.v +SYN_FILES += rtl/sync_signal.v +SYN_FILES += rtl/common/example_core_pcie_us.v +SYN_FILES += rtl/common/example_core_pcie.v +SYN_FILES += rtl/common/example_core.v +SYN_FILES += rtl/common/axi_ram.v +SYN_FILES += lib/pcie/rtl/pcie_us_if.v +SYN_FILES += lib/pcie/rtl/pcie_us_if_rc.v +SYN_FILES += lib/pcie/rtl/pcie_us_if_rq.v +SYN_FILES += lib/pcie/rtl/pcie_us_if_cq.v +SYN_FILES += lib/pcie/rtl/pcie_us_if_cc.v +SYN_FILES += lib/pcie/rtl/pcie_us_cfg.v +SYN_FILES += lib/pcie/rtl/pcie_us_msi.v +SYN_FILES += lib/pcie/rtl/pcie_axil_master.v +SYN_FILES += lib/pcie/rtl/pcie_axi_master.v +SYN_FILES += lib/pcie/rtl/pcie_axi_master_rd.v +SYN_FILES += lib/pcie/rtl/pcie_axi_master_wr.v +SYN_FILES += lib/pcie/rtl/pcie_tlp_demux_bar.v +SYN_FILES += lib/pcie/rtl/pcie_tlp_demux.v +SYN_FILES += lib/pcie/rtl/pcie_tlp_mux.v +SYN_FILES += lib/pcie/rtl/dma_if_pcie.v +SYN_FILES += lib/pcie/rtl/dma_if_pcie_rd.v +SYN_FILES += lib/pcie/rtl/dma_if_pcie_wr.v +SYN_FILES += lib/pcie/rtl/dma_psdpram.v +SYN_FILES += lib/pcie/rtl/arbiter.v +SYN_FILES += lib/pcie/rtl/priority_encoder.v +SYN_FILES += lib/pcie/rtl/pulse_merge.v + +# XDC files +XDC_FILES = fpga.xdc + +# IP +IP_TCL_FILES = ip/pcie4_uscale_plus_0.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 + +%.mcs %.prm: %.bit + echo "write_cfgmem -force -format mcs -size 128 -interface SPIx4 -loadbit {up 0x01002000 $*.bit} -checksum -file $*.mcs" > generate_mcs.tcl + echo "exit" >> generate_mcs.tcl + vivado -nojournal -nolog -mode batch -source generate_mcs.tcl + mkdir -p rev + COUNT=100; \ + while [ -e rev/$*_rev$$COUNT.bit ]; \ + do COUNT=$$((COUNT+1)); done; \ + COUNT=$$((COUNT-1)); \ + for x in .mcs .prm; \ + do cp $*$$x rev/$*_rev$$COUNT$$x; \ + echo "Output: rev/$*_rev$$COUNT$$x"; done; + +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 + diff --git a/fpga/lib/pcie/example/AU250/fpga/ip/pcie4_uscale_plus_0.tcl b/fpga/lib/pcie/example/AU250/fpga/ip/pcie4_uscale_plus_0.tcl new file mode 100644 index 000000000..d5a908b6e --- /dev/null +++ b/fpga/lib/pcie/example/AU250/fpga/ip/pcie4_uscale_plus_0.tcl @@ -0,0 +1,28 @@ + +create_ip -name pcie4_uscale_plus -vendor xilinx.com -library ip -module_name pcie4_uscale_plus_0 + +set_property -dict [list \ + CONFIG.PL_LINK_CAP_MAX_LINK_SPEED {8.0_GT/s} \ + CONFIG.PL_LINK_CAP_MAX_LINK_WIDTH {X16} \ + CONFIG.AXISTEN_IF_EXT_512_RQ_STRADDLE {false} \ + CONFIG.axisten_if_enable_client_tag {true} \ + CONFIG.axisten_if_width {512_bit} \ + CONFIG.axisten_freq {250} \ + CONFIG.PF0_CLASS_CODE {058000} \ + CONFIG.PF0_DEVICE_ID {0001} \ + CONFIG.PF0_MSI_CAP_MULTIMSGCAP {32_vectors} \ + CONFIG.PF0_SUBSYSTEM_ID {90fa} \ + CONFIG.PF0_SUBSYSTEM_VENDOR_ID {10ee} \ + CONFIG.pf0_bar0_64bit {true} \ + CONFIG.pf0_bar0_prefetchable {true} \ + CONFIG.pf0_bar0_scale {Megabytes} \ + CONFIG.pf0_bar0_size {16} \ + CONFIG.pf0_bar2_64bit {true} \ + CONFIG.pf0_bar2_prefetchable {true} \ + CONFIG.pf0_bar2_enabled {true} \ + CONFIG.pf0_bar2_type {Memory} \ + CONFIG.pf0_bar2_scale {Megabytes} \ + CONFIG.pf0_bar2_size {16} \ + CONFIG.vendor_id {1234} \ + CONFIG.en_msi_per_vec_masking {true} \ +] [get_ips pcie4_uscale_plus_0] diff --git a/fpga/lib/pcie/example/AU250/fpga/lib/pcie b/fpga/lib/pcie/example/AU250/fpga/lib/pcie new file mode 120000 index 000000000..11a54ed36 --- /dev/null +++ b/fpga/lib/pcie/example/AU250/fpga/lib/pcie @@ -0,0 +1 @@ +../../../../ \ No newline at end of file diff --git a/fpga/lib/pcie/example/AU250/fpga/rtl/common b/fpga/lib/pcie/example/AU250/fpga/rtl/common new file mode 120000 index 000000000..e60fada70 --- /dev/null +++ b/fpga/lib/pcie/example/AU250/fpga/rtl/common @@ -0,0 +1 @@ +../../../common/rtl/ \ No newline at end of file diff --git a/fpga/lib/pcie/example/AU250/fpga/rtl/debounce_switch.v b/fpga/lib/pcie/example/AU250/fpga/rtl/debounce_switch.v new file mode 100644 index 000000000..8e93a50c4 --- /dev/null +++ b/fpga/lib/pcie/example/AU250/fpga/rtl/debounce_switch.v @@ -0,0 +1,93 @@ +/* + +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 diff --git a/fpga/lib/pcie/example/AU250/fpga/rtl/fpga.v b/fpga/lib/pcie/example/AU250/fpga/rtl/fpga.v new file mode 100644 index 000000000..da734e647 --- /dev/null +++ b/fpga/lib/pcie/example/AU250/fpga/rtl/fpga.v @@ -0,0 +1,463 @@ +/* + +Copyright (c) 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 1ns / 1ps +`default_nettype none + +/* + * FPGA top-level module + */ +module fpga ( + /* + * GPIO + */ + input wire [3:0] sw, + output wire [2:0] led, + + /* + * PCI express + */ + input wire [15:0] pcie_rx_p, + input wire [15:0] pcie_rx_n, + output wire [15:0] pcie_tx_p, + output wire [15:0] pcie_tx_n, + input wire pcie_refclk_p, + input wire pcie_refclk_n, + input wire pcie_reset_n +); + +parameter AXIS_PCIE_DATA_WIDTH = 512; +parameter AXIS_PCIE_KEEP_WIDTH = (AXIS_PCIE_DATA_WIDTH/32); +parameter AXIS_PCIE_RC_USER_WIDTH = AXIS_PCIE_DATA_WIDTH < 512 ? 75 : 161; +parameter AXIS_PCIE_RQ_USER_WIDTH = AXIS_PCIE_DATA_WIDTH < 512 ? 60 : 137; +parameter AXIS_PCIE_CQ_USER_WIDTH = AXIS_PCIE_DATA_WIDTH < 512 ? 85 : 183; +parameter AXIS_PCIE_CC_USER_WIDTH = AXIS_PCIE_DATA_WIDTH < 512 ? 33 : 81; + +parameter RQ_SEQ_NUM_WIDTH = AXIS_PCIE_RQ_USER_WIDTH == 60 ? 4 : 6; +parameter RQ_SEQ_NUM_ENABLE = 1; + +parameter PCIE_TAG_COUNT = 64; +parameter BAR0_APERTURE = 24; +parameter BAR2_APERTURE = 24; + +// Clock and reset +wire pcie_user_clk; +wire pcie_user_reset; + +// GPIO +wire [3:0] sw_int; + +debounce_switch #( + .WIDTH(4), + .N(4), + .RATE(250000) +) +debounce_switch_inst ( + .clk(pcie_user_clk), + .rst(pcie_user_reset), + .in({sw}), + .out({sw_int}) +); + +// PCIe +wire pcie_sys_clk; +wire pcie_sys_clk_gt; + +IBUFDS_GTE4 #( + .REFCLK_HROW_CK_SEL(2'b00) +) +ibufds_gte4_pcie_mgt_refclk_inst ( + .I (pcie_refclk_p), + .IB (pcie_refclk_n), + .CEB (1'b0), + .O (pcie_sys_clk_gt), + .ODIV2 (pcie_sys_clk) +); + +wire [AXIS_PCIE_DATA_WIDTH-1:0] axis_rq_tdata; +wire [AXIS_PCIE_KEEP_WIDTH-1:0] axis_rq_tkeep; +wire axis_rq_tlast; +wire axis_rq_tready; +wire [AXIS_PCIE_RQ_USER_WIDTH-1:0] axis_rq_tuser; +wire axis_rq_tvalid; + +wire [AXIS_PCIE_DATA_WIDTH-1:0] axis_rc_tdata; +wire [AXIS_PCIE_KEEP_WIDTH-1:0] axis_rc_tkeep; +wire axis_rc_tlast; +wire axis_rc_tready; +wire [AXIS_PCIE_RC_USER_WIDTH-1:0] axis_rc_tuser; +wire axis_rc_tvalid; + +wire [AXIS_PCIE_DATA_WIDTH-1:0] axis_cq_tdata; +wire [AXIS_PCIE_KEEP_WIDTH-1:0] axis_cq_tkeep; +wire axis_cq_tlast; +wire axis_cq_tready; +wire [AXIS_PCIE_CQ_USER_WIDTH-1:0] axis_cq_tuser; +wire axis_cq_tvalid; + +wire [AXIS_PCIE_DATA_WIDTH-1:0] axis_cc_tdata; +wire [AXIS_PCIE_KEEP_WIDTH-1:0] axis_cc_tkeep; +wire axis_cc_tlast; +wire axis_cc_tready; +wire [AXIS_PCIE_CC_USER_WIDTH-1:0] axis_cc_tuser; +wire axis_cc_tvalid; + +wire [RQ_SEQ_NUM_WIDTH-1:0] pcie_rq_seq_num0; +wire pcie_rq_seq_num_vld0; +wire [RQ_SEQ_NUM_WIDTH-1:0] pcie_rq_seq_num1; +wire pcie_rq_seq_num_vld1; + +// ila_0 rq_ila ( +// .clk(pcie_user_clk), +// .probe0(axis_rq_tdata), +// .probe1(axis_rq_tkeep), +// .probe2(axis_rq_tlast), +// .probe3(axis_rq_tready), +// .probe4(axis_rq_tuser), +// .probe5(axis_rq_tvalid) +// ); + +// ila_0 rc_ila ( +// .clk(pcie_user_clk), +// .probe0(axis_rc_tdata), +// .probe1(axis_rc_tkeep), +// .probe2(axis_rc_tlast), +// .probe3(axis_rc_tready), +// .probe4(axis_rc_tuser), +// .probe5(axis_rc_tvalid) +// ); + +wire [2:0] cfg_max_payload; +wire [2:0] cfg_max_read_req; + +wire [9:0] cfg_mgmt_addr; +wire [7:0] cfg_mgmt_function_number; +wire cfg_mgmt_write; +wire [31:0] cfg_mgmt_write_data; +wire [3:0] cfg_mgmt_byte_enable; +wire cfg_mgmt_read; +wire [31:0] cfg_mgmt_read_data; +wire cfg_mgmt_read_write_done; + +wire [7:0] cfg_fc_ph; +wire [11:0] cfg_fc_pd; +wire [7:0] cfg_fc_nph; +wire [11:0] cfg_fc_npd; +wire [7:0] cfg_fc_cplh; +wire [11:0] cfg_fc_cpld; +wire [2:0] cfg_fc_sel; + +wire [3:0] cfg_interrupt_msi_enable; +wire [11:0] cfg_interrupt_msi_mmenable; +wire cfg_interrupt_msi_mask_update; +wire [31:0] cfg_interrupt_msi_data; +wire [3:0] cfg_interrupt_msi_select; +wire [31:0] cfg_interrupt_msi_int; +wire [31:0] cfg_interrupt_msi_pending_status; +wire cfg_interrupt_msi_pending_status_data_enable; +wire [3:0] cfg_interrupt_msi_pending_status_function_num; +wire cfg_interrupt_msi_sent; +wire cfg_interrupt_msi_fail; +wire [2:0] cfg_interrupt_msi_attr; +wire cfg_interrupt_msi_tph_present; +wire [1:0] cfg_interrupt_msi_tph_type; +wire [8:0] cfg_interrupt_msi_tph_st_tag; +wire [3:0] cfg_interrupt_msi_function_number; + +wire status_error_cor; +wire status_error_uncor; + +pcie4_uscale_plus_0 +pcie4_uscale_plus_inst ( + .pci_exp_txn(pcie_tx_n), + .pci_exp_txp(pcie_tx_p), + .pci_exp_rxn(pcie_rx_n), + .pci_exp_rxp(pcie_rx_p), + .user_clk(pcie_user_clk), + .user_reset(pcie_user_reset), + .user_lnk_up(), + + .s_axis_rq_tdata(axis_rq_tdata), + .s_axis_rq_tkeep(axis_rq_tkeep), + .s_axis_rq_tlast(axis_rq_tlast), + .s_axis_rq_tready(axis_rq_tready), + .s_axis_rq_tuser(axis_rq_tuser), + .s_axis_rq_tvalid(axis_rq_tvalid), + + .m_axis_rc_tdata(axis_rc_tdata), + .m_axis_rc_tkeep(axis_rc_tkeep), + .m_axis_rc_tlast(axis_rc_tlast), + .m_axis_rc_tready(axis_rc_tready), + .m_axis_rc_tuser(axis_rc_tuser), + .m_axis_rc_tvalid(axis_rc_tvalid), + + .m_axis_cq_tdata(axis_cq_tdata), + .m_axis_cq_tkeep(axis_cq_tkeep), + .m_axis_cq_tlast(axis_cq_tlast), + .m_axis_cq_tready(axis_cq_tready), + .m_axis_cq_tuser(axis_cq_tuser), + .m_axis_cq_tvalid(axis_cq_tvalid), + + .s_axis_cc_tdata(axis_cc_tdata), + .s_axis_cc_tkeep(axis_cc_tkeep), + .s_axis_cc_tlast(axis_cc_tlast), + .s_axis_cc_tready(axis_cc_tready), + .s_axis_cc_tuser(axis_cc_tuser), + .s_axis_cc_tvalid(axis_cc_tvalid), + + .pcie_rq_seq_num0(pcie_rq_seq_num0), + .pcie_rq_seq_num_vld0(pcie_rq_seq_num_vld0), + .pcie_rq_seq_num1(pcie_rq_seq_num1), + .pcie_rq_seq_num_vld1(pcie_rq_seq_num_vld1), + .pcie_rq_tag0(), + .pcie_rq_tag1(), + .pcie_rq_tag_av(), + .pcie_rq_tag_vld0(), + .pcie_rq_tag_vld1(), + + .pcie_tfc_nph_av(), + .pcie_tfc_npd_av(), + + .pcie_cq_np_req(1'b1), + .pcie_cq_np_req_count(), + + .cfg_phy_link_down(), + .cfg_phy_link_status(), + .cfg_negotiated_width(), + .cfg_current_speed(), + .cfg_max_payload(cfg_max_payload), + .cfg_max_read_req(cfg_max_read_req), + .cfg_function_status(), + .cfg_function_power_state(), + .cfg_vf_status(), + .cfg_vf_power_state(), + .cfg_link_power_state(), + + .cfg_mgmt_addr(cfg_mgmt_addr), + .cfg_mgmt_function_number(cfg_mgmt_function_number), + .cfg_mgmt_write(cfg_mgmt_write), + .cfg_mgmt_write_data(cfg_mgmt_write_data), + .cfg_mgmt_byte_enable(cfg_mgmt_byte_enable), + .cfg_mgmt_read(cfg_mgmt_read), + .cfg_mgmt_read_data(cfg_mgmt_read_data), + .cfg_mgmt_read_write_done(cfg_mgmt_read_write_done), + .cfg_mgmt_debug_access(1'b0), + + .cfg_err_cor_out(), + .cfg_err_nonfatal_out(), + .cfg_err_fatal_out(), + .cfg_local_error_valid(), + .cfg_local_error_out(), + .cfg_ltssm_state(), + .cfg_rx_pm_state(), + .cfg_tx_pm_state(), + .cfg_rcb_status(), + .cfg_obff_enable(), + .cfg_pl_status_change(), + .cfg_tph_requester_enable(), + .cfg_tph_st_mode(), + .cfg_vf_tph_requester_enable(), + .cfg_vf_tph_st_mode(), + + .cfg_msg_received(), + .cfg_msg_received_data(), + .cfg_msg_received_type(), + .cfg_msg_transmit(1'b0), + .cfg_msg_transmit_type(3'd0), + .cfg_msg_transmit_data(32'd0), + .cfg_msg_transmit_done(), + + .cfg_fc_ph(cfg_fc_ph), + .cfg_fc_pd(cfg_fc_pd), + .cfg_fc_nph(cfg_fc_nph), + .cfg_fc_npd(cfg_fc_npd), + .cfg_fc_cplh(cfg_fc_cplh), + .cfg_fc_cpld(cfg_fc_cpld), + .cfg_fc_sel(cfg_fc_sel), + + .cfg_dsn(64'd0), + + .cfg_bus_number(), + + .cfg_power_state_change_ack(1'b1), + .cfg_power_state_change_interrupt(), + + .cfg_err_cor_in(status_error_cor), + .cfg_err_uncor_in(status_error_uncor), + .cfg_flr_in_process(), + .cfg_flr_done(4'd0), + .cfg_vf_flr_in_process(), + .cfg_vf_flr_func_num(8'd0), + .cfg_vf_flr_done(8'd0), + + .cfg_link_training_enable(1'b1), + + .cfg_interrupt_int(4'd0), + .cfg_interrupt_pending(4'd0), + .cfg_interrupt_sent(), + .cfg_interrupt_msi_enable(cfg_interrupt_msi_enable), + .cfg_interrupt_msi_mmenable(cfg_interrupt_msi_mmenable), + .cfg_interrupt_msi_mask_update(cfg_interrupt_msi_mask_update), + .cfg_interrupt_msi_data(cfg_interrupt_msi_data), + .cfg_interrupt_msi_select(cfg_interrupt_msi_select), + .cfg_interrupt_msi_int(cfg_interrupt_msi_int), + .cfg_interrupt_msi_pending_status(cfg_interrupt_msi_pending_status), + .cfg_interrupt_msi_pending_status_data_enable(cfg_interrupt_msi_pending_status_data_enable), + .cfg_interrupt_msi_pending_status_function_num(cfg_interrupt_msi_pending_status_function_num), + .cfg_interrupt_msi_sent(cfg_interrupt_msi_sent), + .cfg_interrupt_msi_fail(cfg_interrupt_msi_fail), + .cfg_interrupt_msi_attr(cfg_interrupt_msi_attr), + .cfg_interrupt_msi_tph_present(cfg_interrupt_msi_tph_present), + .cfg_interrupt_msi_tph_type(cfg_interrupt_msi_tph_type), + .cfg_interrupt_msi_tph_st_tag(cfg_interrupt_msi_tph_st_tag), + .cfg_interrupt_msi_function_number(cfg_interrupt_msi_function_number), + + .cfg_pm_aspm_l1_entry_reject(1'b0), + .cfg_pm_aspm_tx_l0s_entry_disable(1'b0), + + .cfg_hot_reset_out(), + + .cfg_config_space_enable(1'b1), + .cfg_req_pm_transition_l23_ready(1'b0), + .cfg_hot_reset_in(1'b0), + + .cfg_ds_port_number(8'd0), + .cfg_ds_bus_number(8'd0), + .cfg_ds_device_number(5'd0), + + .sys_clk(pcie_sys_clk), + .sys_clk_gt(pcie_sys_clk_gt), + .sys_reset(pcie_reset_n), + + .phy_rdy_out() +); + +fpga_core #( + .AXIS_PCIE_DATA_WIDTH(AXIS_PCIE_DATA_WIDTH), + .AXIS_PCIE_KEEP_WIDTH(AXIS_PCIE_KEEP_WIDTH), + .AXIS_PCIE_RC_USER_WIDTH(AXIS_PCIE_RC_USER_WIDTH), + .AXIS_PCIE_RQ_USER_WIDTH(AXIS_PCIE_RQ_USER_WIDTH), + .AXIS_PCIE_CQ_USER_WIDTH(AXIS_PCIE_CQ_USER_WIDTH), + .AXIS_PCIE_CC_USER_WIDTH(AXIS_PCIE_CC_USER_WIDTH), + .RQ_SEQ_NUM_WIDTH(RQ_SEQ_NUM_WIDTH), + .RQ_SEQ_NUM_ENABLE(RQ_SEQ_NUM_ENABLE), + .PCIE_TAG_COUNT(PCIE_TAG_COUNT), + .BAR0_APERTURE(BAR0_APERTURE), + .BAR2_APERTURE(BAR2_APERTURE) +) +core_inst ( + /* + * Clock: 250 MHz + * Synchronous reset + */ + .clk(pcie_user_clk), + .rst(pcie_user_reset), + /* + * GPIO + */ + .sw(sw_int), + .led(led), + /* + * PCIe + */ + .m_axis_rq_tdata(axis_rq_tdata), + .m_axis_rq_tkeep(axis_rq_tkeep), + .m_axis_rq_tlast(axis_rq_tlast), + .m_axis_rq_tready(axis_rq_tready), + .m_axis_rq_tuser(axis_rq_tuser), + .m_axis_rq_tvalid(axis_rq_tvalid), + + .s_axis_rc_tdata(axis_rc_tdata), + .s_axis_rc_tkeep(axis_rc_tkeep), + .s_axis_rc_tlast(axis_rc_tlast), + .s_axis_rc_tready(axis_rc_tready), + .s_axis_rc_tuser(axis_rc_tuser), + .s_axis_rc_tvalid(axis_rc_tvalid), + + .s_axis_cq_tdata(axis_cq_tdata), + .s_axis_cq_tkeep(axis_cq_tkeep), + .s_axis_cq_tlast(axis_cq_tlast), + .s_axis_cq_tready(axis_cq_tready), + .s_axis_cq_tuser(axis_cq_tuser), + .s_axis_cq_tvalid(axis_cq_tvalid), + + .m_axis_cc_tdata(axis_cc_tdata), + .m_axis_cc_tkeep(axis_cc_tkeep), + .m_axis_cc_tlast(axis_cc_tlast), + .m_axis_cc_tready(axis_cc_tready), + .m_axis_cc_tuser(axis_cc_tuser), + .m_axis_cc_tvalid(axis_cc_tvalid), + + .s_axis_rq_seq_num_0(pcie_rq_seq_num0), + .s_axis_rq_seq_num_valid_0(pcie_rq_seq_num_vld0), + .s_axis_rq_seq_num_1(pcie_rq_seq_num1), + .s_axis_rq_seq_num_valid_1(pcie_rq_seq_num_vld1), + + .cfg_max_payload(cfg_max_payload), + .cfg_max_read_req(cfg_max_read_req), + + .cfg_mgmt_addr(cfg_mgmt_addr), + .cfg_mgmt_function_number(cfg_mgmt_function_number), + .cfg_mgmt_write(cfg_mgmt_write), + .cfg_mgmt_write_data(cfg_mgmt_write_data), + .cfg_mgmt_byte_enable(cfg_mgmt_byte_enable), + .cfg_mgmt_read(cfg_mgmt_read), + .cfg_mgmt_read_data(cfg_mgmt_read_data), + .cfg_mgmt_read_write_done(cfg_mgmt_read_write_done), + + .cfg_fc_ph(cfg_fc_ph), + .cfg_fc_pd(cfg_fc_pd), + .cfg_fc_nph(cfg_fc_nph), + .cfg_fc_npd(cfg_fc_npd), + .cfg_fc_cplh(cfg_fc_cplh), + .cfg_fc_cpld(cfg_fc_cpld), + .cfg_fc_sel(cfg_fc_sel), + + .cfg_interrupt_msi_enable(cfg_interrupt_msi_enable), + .cfg_interrupt_msi_mmenable(cfg_interrupt_msi_mmenable), + .cfg_interrupt_msi_mask_update(cfg_interrupt_msi_mask_update), + .cfg_interrupt_msi_data(cfg_interrupt_msi_data), + .cfg_interrupt_msi_select(cfg_interrupt_msi_select), + .cfg_interrupt_msi_int(cfg_interrupt_msi_int), + .cfg_interrupt_msi_pending_status(cfg_interrupt_msi_pending_status), + .cfg_interrupt_msi_pending_status_data_enable(cfg_interrupt_msi_pending_status_data_enable), + .cfg_interrupt_msi_pending_status_function_num(cfg_interrupt_msi_pending_status_function_num), + .cfg_interrupt_msi_sent(cfg_interrupt_msi_sent), + .cfg_interrupt_msi_fail(cfg_interrupt_msi_fail), + .cfg_interrupt_msi_attr(cfg_interrupt_msi_attr), + .cfg_interrupt_msi_tph_present(cfg_interrupt_msi_tph_present), + .cfg_interrupt_msi_tph_type(cfg_interrupt_msi_tph_type), + .cfg_interrupt_msi_tph_st_tag(cfg_interrupt_msi_tph_st_tag), + .cfg_interrupt_msi_function_number(cfg_interrupt_msi_function_number), + + .status_error_cor(status_error_cor), + .status_error_uncor(status_error_uncor) +); + +endmodule + +`resetall diff --git a/fpga/lib/pcie/example/AU250/fpga/rtl/fpga_core.v b/fpga/lib/pcie/example/AU250/fpga/rtl/fpga_core.v new file mode 100644 index 000000000..a6c947b68 --- /dev/null +++ b/fpga/lib/pcie/example/AU250/fpga/rtl/fpga_core.v @@ -0,0 +1,271 @@ +/* + +Copyright (c) 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 1ns / 1ps +`default_nettype none + +/* + * FPGA core logic + */ +module fpga_core # +( + parameter AXIS_PCIE_DATA_WIDTH = 512, + parameter AXIS_PCIE_KEEP_WIDTH = (AXIS_PCIE_DATA_WIDTH/32), + parameter AXIS_PCIE_RC_USER_WIDTH = AXIS_PCIE_DATA_WIDTH < 512 ? 75 : 161, + parameter AXIS_PCIE_RQ_USER_WIDTH = AXIS_PCIE_DATA_WIDTH < 512 ? 60 : 137, + parameter AXIS_PCIE_CQ_USER_WIDTH = AXIS_PCIE_DATA_WIDTH < 512 ? 85 : 183, + parameter AXIS_PCIE_CC_USER_WIDTH = AXIS_PCIE_DATA_WIDTH < 512 ? 33 : 81, + parameter RQ_SEQ_NUM_WIDTH = AXIS_PCIE_RQ_USER_WIDTH == 60 ? 4 : 6, + parameter RQ_SEQ_NUM_ENABLE = 1, + parameter PCIE_TAG_COUNT = 64, + parameter BAR0_APERTURE = 24, + parameter BAR2_APERTURE = 24 +) +( + /* + * Clock: 250 MHz + * Synchronous reset + */ + input wire clk, + input wire rst, + + /* + * GPIO + */ + input wire [3:0] sw, + output wire [2:0] led, + + /* + * PCIe + */ + output wire [AXIS_PCIE_DATA_WIDTH-1:0] m_axis_rq_tdata, + output wire [AXIS_PCIE_KEEP_WIDTH-1:0] m_axis_rq_tkeep, + output wire m_axis_rq_tlast, + input wire m_axis_rq_tready, + output wire [AXIS_PCIE_RQ_USER_WIDTH-1:0] m_axis_rq_tuser, + output wire m_axis_rq_tvalid, + + input wire [AXIS_PCIE_DATA_WIDTH-1:0] s_axis_rc_tdata, + input wire [AXIS_PCIE_KEEP_WIDTH-1:0] s_axis_rc_tkeep, + input wire s_axis_rc_tlast, + output wire s_axis_rc_tready, + input wire [AXIS_PCIE_RC_USER_WIDTH-1:0] s_axis_rc_tuser, + input wire s_axis_rc_tvalid, + + input wire [AXIS_PCIE_DATA_WIDTH-1:0] s_axis_cq_tdata, + input wire [AXIS_PCIE_KEEP_WIDTH-1:0] s_axis_cq_tkeep, + input wire s_axis_cq_tlast, + output wire s_axis_cq_tready, + input wire [AXIS_PCIE_CQ_USER_WIDTH-1:0] s_axis_cq_tuser, + input wire s_axis_cq_tvalid, + + output wire [AXIS_PCIE_DATA_WIDTH-1:0] m_axis_cc_tdata, + output wire [AXIS_PCIE_KEEP_WIDTH-1:0] m_axis_cc_tkeep, + output wire m_axis_cc_tlast, + input wire m_axis_cc_tready, + output wire [AXIS_PCIE_CC_USER_WIDTH-1:0] m_axis_cc_tuser, + output wire m_axis_cc_tvalid, + + input wire [RQ_SEQ_NUM_WIDTH-1:0] s_axis_rq_seq_num_0, + input wire s_axis_rq_seq_num_valid_0, + input wire [RQ_SEQ_NUM_WIDTH-1:0] s_axis_rq_seq_num_1, + input wire s_axis_rq_seq_num_valid_1, + + input wire [2:0] cfg_max_payload, + input wire [2:0] cfg_max_read_req, + + output wire [9:0] cfg_mgmt_addr, + output wire [7:0] cfg_mgmt_function_number, + output wire cfg_mgmt_write, + output wire [31:0] cfg_mgmt_write_data, + output wire [3:0] cfg_mgmt_byte_enable, + output wire cfg_mgmt_read, + input wire [31:0] cfg_mgmt_read_data, + input wire cfg_mgmt_read_write_done, + + input wire [7:0] cfg_fc_ph, + input wire [11:0] cfg_fc_pd, + input wire [7:0] cfg_fc_nph, + input wire [11:0] cfg_fc_npd, + input wire [7:0] cfg_fc_cplh, + input wire [11:0] cfg_fc_cpld, + output wire [2:0] cfg_fc_sel, + + input wire [3:0] cfg_interrupt_msi_enable, + input wire [11:0] cfg_interrupt_msi_mmenable, + input wire cfg_interrupt_msi_mask_update, + input wire [31:0] cfg_interrupt_msi_data, + output wire [3:0] cfg_interrupt_msi_select, + output wire [31:0] cfg_interrupt_msi_int, + output wire [31:0] cfg_interrupt_msi_pending_status, + output wire cfg_interrupt_msi_pending_status_data_enable, + output wire [3:0] cfg_interrupt_msi_pending_status_function_num, + input wire cfg_interrupt_msi_sent, + input wire cfg_interrupt_msi_fail, + output wire [2:0] cfg_interrupt_msi_attr, + output wire cfg_interrupt_msi_tph_present, + output wire [1:0] cfg_interrupt_msi_tph_type, + output wire [8:0] cfg_interrupt_msi_tph_st_tag, + output wire [3:0] cfg_interrupt_msi_function_number, + + output wire status_error_cor, + output wire status_error_uncor +); + +assign led = 3'd0; + +example_core_pcie_us #( + .AXIS_PCIE_DATA_WIDTH(AXIS_PCIE_DATA_WIDTH), + .AXIS_PCIE_KEEP_WIDTH(AXIS_PCIE_KEEP_WIDTH), + .AXIS_PCIE_RC_USER_WIDTH(AXIS_PCIE_RC_USER_WIDTH), + .AXIS_PCIE_RQ_USER_WIDTH(AXIS_PCIE_RQ_USER_WIDTH), + .AXIS_PCIE_CQ_USER_WIDTH(AXIS_PCIE_CQ_USER_WIDTH), + .AXIS_PCIE_CC_USER_WIDTH(AXIS_PCIE_CC_USER_WIDTH), + .RQ_SEQ_NUM_WIDTH(RQ_SEQ_NUM_WIDTH), + .RQ_SEQ_NUM_ENABLE(RQ_SEQ_NUM_ENABLE), + .PCIE_TAG_COUNT(PCIE_TAG_COUNT), + .READ_OP_TABLE_SIZE(PCIE_TAG_COUNT), + .READ_TX_LIMIT(2**(RQ_SEQ_NUM_WIDTH-1)), + .READ_TX_FC_ENABLE(1), + .WRITE_OP_TABLE_SIZE(2**(RQ_SEQ_NUM_WIDTH-1)), + .WRITE_TX_LIMIT(2**(RQ_SEQ_NUM_WIDTH-1)), + .WRITE_TX_FC_ENABLE(1), + .BAR0_APERTURE(BAR0_APERTURE), + .BAR2_APERTURE(BAR2_APERTURE) +) +example_core_pcie_us_inst ( + .clk(clk), + .rst(rst), + + /* + * AXI input (RC) + */ + .s_axis_rc_tdata(s_axis_rc_tdata), + .s_axis_rc_tkeep(s_axis_rc_tkeep), + .s_axis_rc_tvalid(s_axis_rc_tvalid), + .s_axis_rc_tready(s_axis_rc_tready), + .s_axis_rc_tlast(s_axis_rc_tlast), + .s_axis_rc_tuser(s_axis_rc_tuser), + + /* + * AXI output (RQ) + */ + .m_axis_rq_tdata(m_axis_rq_tdata), + .m_axis_rq_tkeep(m_axis_rq_tkeep), + .m_axis_rq_tvalid(m_axis_rq_tvalid), + .m_axis_rq_tready(m_axis_rq_tready), + .m_axis_rq_tlast(m_axis_rq_tlast), + .m_axis_rq_tuser(m_axis_rq_tuser), + + /* + * AXI input (CQ) + */ + .s_axis_cq_tdata(s_axis_cq_tdata), + .s_axis_cq_tkeep(s_axis_cq_tkeep), + .s_axis_cq_tvalid(s_axis_cq_tvalid), + .s_axis_cq_tready(s_axis_cq_tready), + .s_axis_cq_tlast(s_axis_cq_tlast), + .s_axis_cq_tuser(s_axis_cq_tuser), + + /* + * AXI output (CC) + */ + .m_axis_cc_tdata(m_axis_cc_tdata), + .m_axis_cc_tkeep(m_axis_cc_tkeep), + .m_axis_cc_tvalid(m_axis_cc_tvalid), + .m_axis_cc_tready(m_axis_cc_tready), + .m_axis_cc_tlast(m_axis_cc_tlast), + .m_axis_cc_tuser(m_axis_cc_tuser), + + /* + * Transmit sequence number input + */ + .s_axis_rq_seq_num_0(s_axis_rq_seq_num_0), + .s_axis_rq_seq_num_valid_0(s_axis_rq_seq_num_valid_0), + .s_axis_rq_seq_num_1(s_axis_rq_seq_num_1), + .s_axis_rq_seq_num_valid_1(s_axis_rq_seq_num_valid_1), + + /* + * Flow control + */ + .cfg_fc_ph(cfg_fc_ph), + .cfg_fc_pd(cfg_fc_pd), + .cfg_fc_nph(cfg_fc_nph), + .cfg_fc_npd(cfg_fc_npd), + .cfg_fc_cplh(cfg_fc_cplh), + .cfg_fc_cpld(cfg_fc_cpld), + .cfg_fc_sel(cfg_fc_sel), + + /* + * Configuration interface + */ + .cfg_mgmt_addr(cfg_mgmt_addr), + .cfg_mgmt_function_number(cfg_mgmt_function_number), + .cfg_mgmt_write(cfg_mgmt_write), + .cfg_mgmt_write_data(cfg_mgmt_write_data), + .cfg_mgmt_byte_enable(cfg_mgmt_byte_enable), + .cfg_mgmt_read(cfg_mgmt_read), + .cfg_mgmt_read_data(cfg_mgmt_read_data), + .cfg_mgmt_read_write_done(cfg_mgmt_read_write_done), + + /* + * Interrupt interface + */ + .cfg_interrupt_msi_enable(cfg_interrupt_msi_enable), + .cfg_interrupt_msi_vf_enable(8'd0), + .cfg_interrupt_msi_mmenable(cfg_interrupt_msi_mmenable), + .cfg_interrupt_msi_mask_update(cfg_interrupt_msi_mask_update), + .cfg_interrupt_msi_data(cfg_interrupt_msi_data), + .cfg_interrupt_msi_select(cfg_interrupt_msi_select), + .cfg_interrupt_msi_int(cfg_interrupt_msi_int), + .cfg_interrupt_msi_pending_status(cfg_interrupt_msi_pending_status), + .cfg_interrupt_msi_pending_status_data_enable(cfg_interrupt_msi_pending_status_data_enable), + .cfg_interrupt_msi_pending_status_function_num(cfg_interrupt_msi_pending_status_function_num), + .cfg_interrupt_msi_sent(cfg_interrupt_msi_sent), + .cfg_interrupt_msi_fail(cfg_interrupt_msi_fail), + .cfg_interrupt_msi_attr(cfg_interrupt_msi_attr), + .cfg_interrupt_msi_tph_present(cfg_interrupt_msi_tph_present), + .cfg_interrupt_msi_tph_type(cfg_interrupt_msi_tph_type), + .cfg_interrupt_msi_tph_st_tag(cfg_interrupt_msi_tph_st_tag), + .cfg_interrupt_msi_function_number(cfg_interrupt_msi_function_number), + + /* + * Configuration + */ + .cfg_max_read_req(cfg_max_read_req), + .cfg_max_payload(cfg_max_payload), + + /* + * Status + */ + .status_error_cor(status_error_cor), + .status_error_uncor(status_error_uncor) +); + +endmodule + +`resetall diff --git a/fpga/lib/pcie/example/AU250/fpga/rtl/sync_reset.v b/fpga/lib/pcie/example/AU250/fpga/rtl/sync_reset.v new file mode 100644 index 000000000..1fd24d361 --- /dev/null +++ b/fpga/lib/pcie/example/AU250/fpga/rtl/sync_reset.v @@ -0,0 +1,56 @@ +/* + +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 active-high asynchronous reset signal to a given clock by + * using a pipeline of N registers. + */ +module sync_reset #( + parameter N=2 // depth of synchronizer +)( + input wire clk, + input wire rst, + output wire sync_reset_out +); + +reg [N-1:0] sync_reg = {N{1'b1}}; + +assign sync_reset_out = sync_reg[N-1]; + +always @(posedge clk or posedge rst) begin + if (rst) + sync_reg <= {N{1'b1}}; + else + sync_reg <= {sync_reg[N-2:0], 1'b0}; +end + +endmodule + +`resetall diff --git a/fpga/lib/pcie/example/AU250/fpga/rtl/sync_signal.v b/fpga/lib/pcie/example/AU250/fpga/rtl/sync_signal.v new file mode 100644 index 000000000..74b855fa1 --- /dev/null +++ b/fpga/lib/pcie/example/AU250/fpga/rtl/sync_signal.v @@ -0,0 +1,62 @@ +/* + +Copyright (c) 2014-2018 Alex Forencich + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +*/ + +// Language: Verilog-2001 + +`resetall +`timescale 1 ns / 1 ps +`default_nettype none + +/* + * Synchronizes an asyncronous signal to a given clock by using a pipeline of + * two registers. + */ +module sync_signal #( + parameter WIDTH=1, // width of the input and output signals + parameter N=2 // depth of synchronizer +)( + input wire clk, + input wire [WIDTH-1:0] in, + output wire [WIDTH-1:0] out +); + +reg [WIDTH-1:0] sync_reg[N-1:0]; + +/* + * The synchronized output is the last register in the pipeline. + */ +assign out = sync_reg[N-1]; + +integer k; + +always @(posedge clk) begin + sync_reg[0] <= in; + for (k = 1; k < N; k = k + 1) begin + sync_reg[k] <= sync_reg[k-1]; + end +end + +endmodule + +`resetall diff --git a/fpga/lib/pcie/example/AU250/fpga/tb/fpga_core/Makefile b/fpga/lib/pcie/example/AU250/fpga/tb/fpga_core/Makefile new file mode 100644 index 000000000..7c85b6e54 --- /dev/null +++ b/fpga/lib/pcie/example/AU250/fpga/tb/fpga_core/Makefile @@ -0,0 +1,123 @@ +# Copyright (c) 2020 Alex Forencich +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +TOPLEVEL_LANG = verilog + +SIM ?= icarus +WAVES ?= 0 + +COCOTB_HDL_TIMEUNIT = 1ns +COCOTB_HDL_TIMEPRECISION = 1ps + +DUT = fpga_core +TOPLEVEL = $(DUT) +MODULE = test_$(DUT) +VERILOG_SOURCES += ../../rtl/$(DUT).v +VERILOG_SOURCES += ../../rtl/common/example_core_pcie_us.v +VERILOG_SOURCES += ../../rtl/common/example_core_pcie.v +VERILOG_SOURCES += ../../rtl/common/example_core.v +VERILOG_SOURCES += ../../rtl/common/axi_ram.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_if.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_if_rc.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_if_rq.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_if_cq.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_if_cc.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_cfg.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_msi.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_axil_master.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_axi_master.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_axi_master_rd.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_axi_master_wr.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_tlp_demux_bar.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_tlp_demux.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_tlp_mux.v +VERILOG_SOURCES += ../../lib/pcie/rtl/dma_if_pcie.v +VERILOG_SOURCES += ../../lib/pcie/rtl/dma_if_pcie_rd.v +VERILOG_SOURCES += ../../lib/pcie/rtl/dma_if_pcie_wr.v +VERILOG_SOURCES += ../../lib/pcie/rtl/dma_psdpram.v +VERILOG_SOURCES += ../../lib/pcie/rtl/arbiter.v +VERILOG_SOURCES += ../../lib/pcie/rtl/priority_encoder.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pulse_merge.v + +# module parameters +export PARAM_AXIS_PCIE_DATA_WIDTH ?= 512 +export PARAM_AXIS_PCIE_KEEP_WIDTH ?= $(shell expr $(PARAM_AXIS_PCIE_DATA_WIDTH) / 32 ) +export PARAM_AXIS_PCIE_RQ_USER_WIDTH ?= $(if $(filter-out 512,$(PARAM_AXIS_PCIE_DATA_WIDTH)),62,137) +export PARAM_AXIS_PCIE_RC_USER_WIDTH ?= $(if $(filter-out 512,$(PARAM_AXIS_PCIE_DATA_WIDTH)),75,161) +export PARAM_AXIS_PCIE_CQ_USER_WIDTH ?= $(if $(filter-out 512,$(PARAM_AXIS_PCIE_DATA_WIDTH)),88,183) +export PARAM_AXIS_PCIE_CC_USER_WIDTH ?= $(if $(filter-out 512,$(PARAM_AXIS_PCIE_DATA_WIDTH)),33,81) +export PARAM_RQ_SEQ_NUM_WIDTH ?= 6 +export PARAM_RQ_SEQ_NUM_ENABLE ?= 1 +export PARAM_PCIE_TAG_COUNT ?= 64 +export PARAM_BAR0_APERTURE ?= 24 +export PARAM_BAR2_APERTURE ?= 24 + +ifeq ($(SIM), icarus) + PLUSARGS += -fst + + COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_DATA_WIDTH=$(PARAM_AXIS_PCIE_DATA_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_KEEP_WIDTH=$(PARAM_AXIS_PCIE_KEEP_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_RQ_USER_WIDTH=$(PARAM_AXIS_PCIE_RQ_USER_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_RC_USER_WIDTH=$(PARAM_AXIS_PCIE_RC_USER_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_CQ_USER_WIDTH=$(PARAM_AXIS_PCIE_CQ_USER_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_CC_USER_WIDTH=$(PARAM_AXIS_PCIE_CC_USER_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).RQ_SEQ_NUM_WIDTH=$(PARAM_RQ_SEQ_NUM_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).RQ_SEQ_NUM_ENABLE=$(PARAM_RQ_SEQ_NUM_ENABLE) + COMPILE_ARGS += -P $(TOPLEVEL).PCIE_TAG_COUNT=$(PARAM_PCIE_TAG_COUNT) + COMPILE_ARGS += -P $(TOPLEVEL).BAR0_APERTURE=$(PARAM_BAR0_APERTURE) + COMPILE_ARGS += -P $(TOPLEVEL).BAR2_APERTURE=$(PARAM_BAR2_APERTURE) + + ifeq ($(WAVES), 1) + VERILOG_SOURCES += iverilog_dump.v + COMPILE_ARGS += -s iverilog_dump + endif +else ifeq ($(SIM), verilator) + COMPILE_ARGS += -Wno-SELRANGE -Wno-WIDTH + + COMPILE_ARGS += -GAXIS_PCIE_DATA_WIDTH=$(PARAM_AXIS_PCIE_DATA_WIDTH) + COMPILE_ARGS += -GAXIS_PCIE_KEEP_WIDTH=$(PARAM_AXIS_PCIE_KEEP_WIDTH) + COMPILE_ARGS += -GAXIS_PCIE_RQ_USER_WIDTH=$(PARAM_AXIS_PCIE_RQ_USER_WIDTH) + COMPILE_ARGS += -GAXIS_PCIE_RC_USER_WIDTH=$(PARAM_AXIS_PCIE_RC_USER_WIDTH) + COMPILE_ARGS += -GAXIS_PCIE_CQ_USER_WIDTH=$(PARAM_AXIS_PCIE_CQ_USER_WIDTH) + COMPILE_ARGS += -GAXIS_PCIE_CC_USER_WIDTH=$(PARAM_AXIS_PCIE_CC_USER_WIDTH) + COMPILE_ARGS += -GRQ_SEQ_NUM_WIDTH=$(PARAM_RQ_SEQ_NUM_WIDTH) + COMPILE_ARGS += -GRQ_SEQ_NUM_ENABLE=$(PARAM_RQ_SEQ_NUM_ENABLE) + COMPILE_ARGS += -GPCIE_TAG_COUNT=$(PARAM_PCIE_TAG_COUNT) + COMPILE_ARGS += -GBAR0_APERTURE=$(PARAM_BAR0_APERTURE) + COMPILE_ARGS += -GBAR2_APERTURE=$(PARAM_BAR2_APERTURE) + + ifeq ($(WAVES), 1) + COMPILE_ARGS += --trace-fst + endif +endif + +include $(shell cocotb-config --makefiles)/Makefile.sim + +iverilog_dump.v: + echo 'module iverilog_dump();' > $@ + echo 'initial begin' >> $@ + echo ' $$dumpfile("$(TOPLEVEL).fst");' >> $@ + echo ' $$dumpvars(0, $(TOPLEVEL));' >> $@ + echo 'end' >> $@ + echo 'endmodule' >> $@ + +clean:: + @rm -rf iverilog_dump.v + @rm -rf dump.fst $(TOPLEVEL).fst diff --git a/fpga/lib/pcie/example/AU250/fpga/tb/fpga_core/test_fpga_core.py b/fpga/lib/pcie/example/AU250/fpga/tb/fpga_core/test_fpga_core.py new file mode 100644 index 000000000..429f0383f --- /dev/null +++ b/fpga/lib/pcie/example/AU250/fpga/tb/fpga_core/test_fpga_core.py @@ -0,0 +1,474 @@ +""" + +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 + +import cocotb_test.simulator + +import cocotb +from cocotb.log import SimLog +from cocotb.triggers import RisingEdge, FallingEdge, Timer + +from cocotbext.axi import AxiStreamBus +from cocotbext.pcie.core import RootComplex +from cocotbext.pcie.xilinx.us import UltraScalePlusPcieDevice + + +class TB(object): + def __init__(self, dut): + self.dut = dut + + self.log = SimLog("cocotb.tb") + self.log.setLevel(logging.DEBUG) + + # PCIe + self.rc = RootComplex() + + self.dev = UltraScalePlusPcieDevice( + # configuration options + pcie_generation=3, + pcie_link_width=16, + user_clk_frequency=250e6, + alignment="dword", + cq_cc_straddle=False, + rq_rc_straddle=False, + rc_4tlp_straddle=False, + enable_pf1=False, + enable_client_tag=True, + enable_extended_tag=True, + enable_parity=False, + enable_rx_msg_interface=False, + enable_sriov=False, + enable_extended_configuration=False, + + enable_pf0_msi=True, + enable_pf1_msi=False, + + # signals + # Clock and Reset Interface + user_clk=dut.clk, + user_reset=dut.rst, + # user_lnk_up + # sys_clk + # sys_clk_gt + # sys_reset + # phy_rdy_out + + # Requester reQuest Interface + rq_bus=AxiStreamBus.from_prefix(dut, "m_axis_rq"), + pcie_rq_seq_num0=dut.s_axis_rq_seq_num_0, + pcie_rq_seq_num_vld0=dut.s_axis_rq_seq_num_valid_0, + pcie_rq_seq_num1=dut.s_axis_rq_seq_num_1, + pcie_rq_seq_num_vld1=dut.s_axis_rq_seq_num_valid_1, + # pcie_rq_tag0 + # pcie_rq_tag1 + # pcie_rq_tag_av + # pcie_rq_tag_vld0 + # pcie_rq_tag_vld1 + + # Requester Completion Interface + rc_bus=AxiStreamBus.from_prefix(dut, "s_axis_rc"), + + # Completer reQuest Interface + cq_bus=AxiStreamBus.from_prefix(dut, "s_axis_cq"), + # pcie_cq_np_req + # pcie_cq_np_req_count + + # Completer Completion Interface + cc_bus=AxiStreamBus.from_prefix(dut, "m_axis_cc"), + + # Transmit Flow Control Interface + # pcie_tfc_nph_av=dut.pcie_tfc_nph_av, + # pcie_tfc_npd_av=dut.pcie_tfc_npd_av, + + # Configuration Management Interface + cfg_mgmt_addr=dut.cfg_mgmt_addr, + cfg_mgmt_function_number=dut.cfg_mgmt_function_number, + cfg_mgmt_write=dut.cfg_mgmt_write, + cfg_mgmt_write_data=dut.cfg_mgmt_write_data, + cfg_mgmt_byte_enable=dut.cfg_mgmt_byte_enable, + cfg_mgmt_read=dut.cfg_mgmt_read, + cfg_mgmt_read_data=dut.cfg_mgmt_read_data, + cfg_mgmt_read_write_done=dut.cfg_mgmt_read_write_done, + # cfg_mgmt_debug_access + + # Configuration Status Interface + # cfg_phy_link_down + # cfg_phy_link_status + # cfg_negotiated_width + # cfg_current_speed + cfg_max_payload=dut.cfg_max_payload, + cfg_max_read_req=dut.cfg_max_read_req, + # cfg_function_status + # cfg_vf_status + # cfg_function_power_state + # cfg_vf_power_state + # cfg_link_power_state + # cfg_err_cor_out + # cfg_err_nonfatal_out + # cfg_err_fatal_out + # cfg_local_error_out + # cfg_local_error_valid + # cfg_rx_pm_state + # cfg_tx_pm_state + # cfg_ltssm_state + # cfg_rcb_status + # cfg_obff_enable + # cfg_pl_status_change + # cfg_tph_requester_enable + # cfg_tph_st_mode + # cfg_vf_tph_requester_enable + # cfg_vf_tph_st_mode + + # Configuration Received Message Interface + # cfg_msg_received + # cfg_msg_received_data + # cfg_msg_received_type + + # Configuration Transmit Message Interface + # cfg_msg_transmit + # cfg_msg_transmit_type + # cfg_msg_transmit_data + # cfg_msg_transmit_done + + # Configuration Flow Control Interface + cfg_fc_ph=dut.cfg_fc_ph, + cfg_fc_pd=dut.cfg_fc_pd, + cfg_fc_nph=dut.cfg_fc_nph, + cfg_fc_npd=dut.cfg_fc_npd, + cfg_fc_cplh=dut.cfg_fc_cplh, + cfg_fc_cpld=dut.cfg_fc_cpld, + cfg_fc_sel=dut.cfg_fc_sel, + + # Configuration Control Interface + # cfg_hot_reset_in + # cfg_hot_reset_out + # cfg_config_space_enable + # cfg_dsn + # cfg_bus_number + # cfg_ds_port_number + # cfg_ds_bus_number + # cfg_ds_device_number + # cfg_ds_function_number + # cfg_power_state_change_ack + # cfg_power_state_change_interrupt + cfg_err_cor_in=dut.status_error_cor, + cfg_err_uncor_in=dut.status_error_uncor, + # cfg_flr_in_process + # cfg_flr_done + # cfg_vf_flr_in_process + # cfg_vf_flr_func_num + # cfg_vf_flr_done + # cfg_pm_aspm_l1_entry_reject + # cfg_pm_aspm_tx_l0s_entry_disable + # cfg_req_pm_transition_l23_ready + # cfg_link_training_enable + + # Configuration Interrupt Controller Interface + # cfg_interrupt_int + # cfg_interrupt_sent + # cfg_interrupt_pending + cfg_interrupt_msi_enable=dut.cfg_interrupt_msi_enable, + cfg_interrupt_msi_mmenable=dut.cfg_interrupt_msi_mmenable, + cfg_interrupt_msi_mask_update=dut.cfg_interrupt_msi_mask_update, + cfg_interrupt_msi_data=dut.cfg_interrupt_msi_data, + # cfg_interrupt_msi_select=dut.cfg_interrupt_msi_select, + cfg_interrupt_msi_int=dut.cfg_interrupt_msi_int, + cfg_interrupt_msi_pending_status=dut.cfg_interrupt_msi_pending_status, + cfg_interrupt_msi_pending_status_data_enable=dut.cfg_interrupt_msi_pending_status_data_enable, + # cfg_interrupt_msi_pending_status_function_num=dut.cfg_interrupt_msi_pending_status_function_num, + cfg_interrupt_msi_sent=dut.cfg_interrupt_msi_sent, + cfg_interrupt_msi_fail=dut.cfg_interrupt_msi_fail, + # cfg_interrupt_msix_enable + # cfg_interrupt_msix_mask + # cfg_interrupt_msix_vf_enable + # cfg_interrupt_msix_vf_mask + # cfg_interrupt_msix_address + # cfg_interrupt_msix_data + # cfg_interrupt_msix_int + # cfg_interrupt_msix_vec_pending + # cfg_interrupt_msix_vec_pending_status + cfg_interrupt_msi_attr=dut.cfg_interrupt_msi_attr, + cfg_interrupt_msi_tph_present=dut.cfg_interrupt_msi_tph_present, + cfg_interrupt_msi_tph_type=dut.cfg_interrupt_msi_tph_type, + # cfg_interrupt_msi_tph_st_tag=dut.cfg_interrupt_msi_tph_st_tag, + # cfg_interrupt_msi_function_number=dut.cfg_interrupt_msi_function_number, + + # Configuration Extend Interface + # cfg_ext_read_received + # cfg_ext_write_received + # cfg_ext_register_number + # cfg_ext_function_number + # cfg_ext_write_data + # cfg_ext_write_byte_enable + # cfg_ext_read_data + # cfg_ext_read_data_valid + ) + + # self.dev.log.setLevel(logging.DEBUG) + + self.rc.make_port().connect(self.dev) + + self.dev.functions[0].msi_multiple_message_capable = 5 + + self.dev.functions[0].configure_bar(0, 2**len(dut.example_core_pcie_us_inst.core_pcie_inst.axil_ctrl_awaddr)) + self.dev.functions[0].configure_bar(2, 2**len(dut.example_core_pcie_us_inst.core_pcie_inst.axi_ram_awaddr)) + + dut.sw.setimmediatevalue(0) + + async def init(self): + + await FallingEdge(self.dut.rst) + await Timer(100, 'ns') + + await self.rc.enumerate(enable_bus_mastering=True, configure_msi=True) + + +@cocotb.test() +async def run_test(dut): + + tb = TB(dut) + + await tb.init() + + mem = tb.rc.mem_pool.alloc_region(16*1024*1024) + mem_base = mem.get_absolute_address(0) + + dev_pf0_bar0 = tb.rc.tree[0][0].bar_window[0] + dev_pf0_bar2 = tb.rc.tree[0][0].bar_window[2] + + tb.log.info("Test memory write to BAR 2") + + test_data = b'\x11\x22\x33\x44' + await dev_pf0_bar2.write(0, test_data) + + await Timer(100, 'ns') + + tb.log.info("Test memory read from BAR 2") + + val = await dev_pf0_bar2.read(0, len(test_data), timeout=1000) + tb.log.info("Read data: %s", val) + assert val == test_data + + tb.log.info("Test DMA") + + # write packet data + mem[0:1024] = bytearray([x % 256 for x in range(1024)]) + + # enable DMA + await dev_pf0_bar0.write_dword(0x000000, 1) + + # write pcie read descriptor + await dev_pf0_bar0.write_dword(0x000100, (mem_base+0x0000) & 0xffffffff) + await dev_pf0_bar0.write_dword(0x000104, (mem_base+0x0000 >> 32) & 0xffffffff) + await dev_pf0_bar0.write_dword(0x000108, 0x100) + await dev_pf0_bar0.write_dword(0x000110, 0x400) + await dev_pf0_bar0.write_dword(0x000114, 0xAA) + + await Timer(2000, 'ns') + + # read status + val = await dev_pf0_bar0.read_dword(0x000118) + tb.log.info("Status: 0x%x", val) + assert val == 0x800000AA + + # write pcie write descriptor + await dev_pf0_bar0.write_dword(0x000200, (mem_base+0x1000) & 0xffffffff) + await dev_pf0_bar0.write_dword(0x000204, (mem_base+0x1000 >> 32) & 0xffffffff) + await dev_pf0_bar0.write_dword(0x000208, 0x100) + await dev_pf0_bar0.write_dword(0x000210, 0x400) + await dev_pf0_bar0.write_dword(0x000214, 0x55) + + await Timer(2000, 'ns') + + # read status + val = await dev_pf0_bar0.read_dword(0x000218) + tb.log.info("Status: 0x%x", val) + assert val == 0x80000055 + + tb.log.info("%s", mem.hexdump_str(0x1000, 64)) + + assert mem[0:1024] == mem[0x1000:0x1000+1024] + + tb.log.info("Test DMA block operations") + + # write packet data + mem[0:1024] = bytearray([x % 256 for x in range(1024)]) + + # enable DMA + await dev_pf0_bar0.write_dword(0x000000, 1) + # disable interrupts + await dev_pf0_bar0.write_dword(0x000008, 0) + + # configure operation (read) + # DMA base address + await dev_pf0_bar0.write_dword(0x001080, (mem_base+0x0000) & 0xffffffff) + await dev_pf0_bar0.write_dword(0x001084, (mem_base+0x0000 >> 32) & 0xffffffff) + # DMA offset address + await dev_pf0_bar0.write_dword(0x001088, 0) + await dev_pf0_bar0.write_dword(0x00108c, 0) + # DMA offset mask + await dev_pf0_bar0.write_dword(0x001090, 0x000003ff) + await dev_pf0_bar0.write_dword(0x001094, 0) + # DMA stride + await dev_pf0_bar0.write_dword(0x001098, 256) + await dev_pf0_bar0.write_dword(0x00109c, 0) + # RAM base address + await dev_pf0_bar0.write_dword(0x0010c0, 0) + await dev_pf0_bar0.write_dword(0x0010c4, 0) + # RAM offset address + await dev_pf0_bar0.write_dword(0x0010c8, 0) + await dev_pf0_bar0.write_dword(0x0010cc, 0) + # RAM offset mask + await dev_pf0_bar0.write_dword(0x0010d0, 0x000003ff) + await dev_pf0_bar0.write_dword(0x0010d4, 0) + # RAM stride + await dev_pf0_bar0.write_dword(0x0010d8, 256) + await dev_pf0_bar0.write_dword(0x0010dc, 0) + # clear cycle count + await dev_pf0_bar0.write_dword(0x001008, 0) + await dev_pf0_bar0.write_dword(0x00100c, 0) + # block length + await dev_pf0_bar0.write_dword(0x001010, 256) + # block count + await dev_pf0_bar0.write_dword(0x001018, 32) + await dev_pf0_bar0.write_dword(0x00101c, 0) + # start + await dev_pf0_bar0.write_dword(0x001000, 1) + + await Timer(2000, 'ns') + + # configure operation (write) + # DMA base address + await dev_pf0_bar0.write_dword(0x001180, (mem_base+0x0000) & 0xffffffff) + await dev_pf0_bar0.write_dword(0x001184, (mem_base+0x0000 >> 32) & 0xffffffff) + # DMA offset address + await dev_pf0_bar0.write_dword(0x001188, 0) + await dev_pf0_bar0.write_dword(0x00118c, 0) + # DMA offset mask + await dev_pf0_bar0.write_dword(0x001190, 0x000003ff) + await dev_pf0_bar0.write_dword(0x001194, 0) + # DMA stride + await dev_pf0_bar0.write_dword(0x001198, 256) + await dev_pf0_bar0.write_dword(0x00119c, 0) + # RAM base address + await dev_pf0_bar0.write_dword(0x0011c0, 0) + await dev_pf0_bar0.write_dword(0x0011c4, 0) + # RAM offset address + await dev_pf0_bar0.write_dword(0x0011c8, 0) + await dev_pf0_bar0.write_dword(0x0011cc, 0) + # RAM offset mask + await dev_pf0_bar0.write_dword(0x0011d0, 0x000003ff) + await dev_pf0_bar0.write_dword(0x0011d4, 0) + # RAM stride + await dev_pf0_bar0.write_dword(0x0011d8, 256) + await dev_pf0_bar0.write_dword(0x0011dc, 0) + # clear cycle count + await dev_pf0_bar0.write_dword(0x001108, 0) + await dev_pf0_bar0.write_dword(0x00110c, 0) + # block length + await dev_pf0_bar0.write_dword(0x001110, 256) + # block count + await dev_pf0_bar0.write_dword(0x001118, 32) + await dev_pf0_bar0.write_dword(0x00111c, 0) + # start + await dev_pf0_bar0.write_dword(0x001100, 1) + + await Timer(2000, 'ns') + + await RisingEdge(dut.clk) + await RisingEdge(dut.clk) + + +# cocotb-test + +tests_dir = 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')) +pcie_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'pcie', '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(rtl_dir, "common", "example_core_pcie_us.v"), + os.path.join(rtl_dir, "common", "example_core_pcie.v"), + os.path.join(rtl_dir, "common", "example_core.v"), + os.path.join(rtl_dir, "common", "axi_ram.v"), + os.path.join(pcie_rtl_dir, "pcie_us_if.v"), + os.path.join(pcie_rtl_dir, "pcie_us_if_rc.v"), + os.path.join(pcie_rtl_dir, "pcie_us_if_rq.v"), + os.path.join(pcie_rtl_dir, "pcie_us_if_cq.v"), + os.path.join(pcie_rtl_dir, "pcie_us_if_cc.v"), + os.path.join(pcie_rtl_dir, "pcie_us_cfg.v"), + os.path.join(pcie_rtl_dir, "pcie_us_msi.v"), + os.path.join(pcie_rtl_dir, "pcie_axil_master.v"), + os.path.join(pcie_rtl_dir, "pcie_axi_master.v"), + os.path.join(pcie_rtl_dir, "pcie_axi_master_rd.v"), + os.path.join(pcie_rtl_dir, "pcie_axi_master_wr.v"), + os.path.join(pcie_rtl_dir, "pcie_tlp_demux_bar.v"), + os.path.join(pcie_rtl_dir, "pcie_tlp_demux.v"), + os.path.join(pcie_rtl_dir, "pcie_tlp_mux.v"), + os.path.join(pcie_rtl_dir, "dma_if_pcie.v"), + os.path.join(pcie_rtl_dir, "dma_if_pcie_rd.v"), + os.path.join(pcie_rtl_dir, "dma_if_pcie_wr.v"), + os.path.join(pcie_rtl_dir, "dma_psdpram.v"), + os.path.join(pcie_rtl_dir, "arbiter.v"), + os.path.join(pcie_rtl_dir, "priority_encoder.v"), + os.path.join(pcie_rtl_dir, "pulse_merge.v"), + ] + + parameters = {} + + parameters['AXIS_PCIE_DATA_WIDTH'] = 512 + parameters['AXIS_PCIE_KEEP_WIDTH'] = parameters['AXIS_PCIE_DATA_WIDTH'] // 32 + parameters['AXIS_PCIE_RQ_USER_WIDTH'] = 62 if parameters['AXIS_PCIE_DATA_WIDTH'] < 512 else 137 + parameters['AXIS_PCIE_RC_USER_WIDTH'] = 75 if parameters['AXIS_PCIE_DATA_WIDTH'] < 512 else 161 + parameters['AXIS_PCIE_CQ_USER_WIDTH'] = 88 if parameters['AXIS_PCIE_DATA_WIDTH'] < 512 else 183 + parameters['AXIS_PCIE_CC_USER_WIDTH'] = 33 if parameters['AXIS_PCIE_DATA_WIDTH'] < 512 else 81 + parameters['RQ_SEQ_NUM_WIDTH'] = 6 + parameters['RQ_SEQ_NUM_ENABLE'] = 1 + parameters['PCIE_TAG_COUNT'] = 64 + parameters['BAR0_APERTURE'] = 24 + parameters['BAR2_APERTURE'] = 24 + + 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, + ) diff --git a/fpga/lib/pcie/example/AU280/fpga/README.md b/fpga/lib/pcie/example/AU280/fpga/README.md new file mode 100644 index 000000000..903a890ed --- /dev/null +++ b/fpga/lib/pcie/example/AU280/fpga/README.md @@ -0,0 +1,19 @@ +# Verilog PCIe Alveo U280 Example Design + +## Introduction + +This example design targets the Xilinx Alveo U280 FPGA board. + +The design implements the PCIe AXI lite master module, the PCIe AXI master module, and the PCIe DMA module. A very simple Linux driver is included to test the FPGA design. + +* FPGA: xcu280-fsvh2892-2L-e + +## How to build + +Run `make` to build. Ensure that the Xilinx Vivado components are in PATH. + +Run `make` to build the driver. Ensure the headers for the running kernel are installed, otherwise the driver cannot be compiled. + +## How to test + +Run `make program` to program the Alveo U280 board with Vivado. Then load the driver with `insmod example.ko`. Check dmesg for the output. diff --git a/fpga/lib/pcie/example/AU280/fpga/common/vivado.mk b/fpga/lib/pcie/example/AU280/fpga/common/vivado.mk new file mode 100644 index 000000000..d47a43947 --- /dev/null +++ b/fpga/lib/pcie/example/AU280/fpga/common/vivado.mk @@ -0,0 +1,126 @@ +################################################################### +# +# 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) + +SYN_FILES_REL = $(patsubst %, ../%, $(filter-out /% ./%,$(SYN_FILES))) $(filter /% ./%,$(SYN_FILES)) +INC_FILES_REL = $(patsubst %, ../%, $(filter-out /% ./%,$(INC_FILES))) $(filter /% ./%,$(INC_FILES)) +XCI_FILES_REL = $(patsubst %, ../%, $(filter-out /% ./%,$(XCI_FILES))) $(filter /% ./%,$(XCI_FILES)) +IP_TCL_FILES_REL = $(patsubst %, ../%, $(filter-out /% ./%,$(IP_TCL_FILES))) $(filter /% ./%,$(IP_TCL_FILES)) +CONFIG_TCL_FILES_REL = $(patsubst %, ../%, $(filter-out /% ./%,$(CONFIG_TCL_FILES))) $(filter /% ./%,$(CONFIG_TCL_FILES)) + +ifdef XDC_FILES + XDC_FILES_REL = $(patsubst %, ../%, $(filter-out /% ./%,$(XDC_FILES))) $(filter /% ./%,$(XDC_FILES)) +else + XDC_FILES_REL = $(FPGA_TOP).xdc +endif + +################################################################### +# Main Targets +# +# all: build everything +# clean: remove output files and project files +################################################################### + +all: fpga + +fpga: $(FPGA_TOP).bit + +vivado: $(FPGA_TOP).xpr + vivado $(FPGA_TOP).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 program.tcl generate_mcs.tcl *.mcs *.prm flash.tcl + +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) $(FPGA_TOP)" > $@ + echo "add_files -fileset sources_1 defines.v $(SYN_FILES_REL)" >> $@ + 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) + echo "open_project -quiet $(FPGA_TOP).xpr" > $@ + for x in $(CONFIG_TCL_FILES_REL); do echo "source $$x" >> $@; done + +$(FPGA_TOP).xpr: create_project.tcl update_config.tcl + vivado -nojournal -nolog -mode batch $(foreach x,$?,-source $x) + +# synthesis run +%.runs/synth_1/%.dcp: %.xpr $(SYN_FILES_REL) $(INC_FILES_REL) $(XDC_FILES_REL) $(CONFIG_TCL_FILES_REL) + echo "open_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 +%.runs/impl_1/%_routed.dcp: %.runs/synth_1/%.dcp + echo "open_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 + vivado -nojournal -nolog -mode batch -source run_impl.tcl + +# bit file +%.bit: %.runs/impl_1/%_routed.dcp + echo "open_project $*.xpr" > generate_bit.tcl + echo "open_run impl_1" >> generate_bit.tcl + echo "write_bitstream -force $*.bit" >> generate_bit.tcl + vivado -nojournal -nolog -mode batch -source generate_bit.tcl + mkdir -p rev + EXT=bit; COUNT=100; \ + while [ -e rev/$*_rev$$COUNT.$$EXT ]; \ + do COUNT=$$((COUNT+1)); done; \ + cp $@ rev/$*_rev$$COUNT.$$EXT; \ + echo "Output: rev/$*_rev$$COUNT.$$EXT"; diff --git a/fpga/lib/pcie/example/AU280/fpga/driver b/fpga/lib/pcie/example/AU280/fpga/driver new file mode 120000 index 000000000..4a54c76b5 --- /dev/null +++ b/fpga/lib/pcie/example/AU280/fpga/driver @@ -0,0 +1 @@ +../../common/driver/example/ \ No newline at end of file diff --git a/fpga/lib/pcie/example/AU280/fpga/fpga.xdc b/fpga/lib/pcie/example/AU280/fpga/fpga.xdc new file mode 100644 index 000000000..ec2d7674e --- /dev/null +++ b/fpga/lib/pcie/example/AU280/fpga/fpga.xdc @@ -0,0 +1,227 @@ +# XDC constraints for the Xilinx Alveo U280 board +# part: xcu280-fsvh2892-2L-e + +# General configuration +set_property CFGBVS GND [current_design] +set_property CONFIG_VOLTAGE 1.8 [current_design] +set_property BITSTREAM.CONFIG.CONFIGFALLBACK ENABLE [current_design] +set_property BITSTREAM.GENERAL.COMPRESS TRUE [current_design] +set_property CONFIG_MODE SPIx4 [current_design] +set_property BITSTREAM.CONFIG.SPI_BUSWIDTH 4 [current_design] +set_property BITSTREAM.CONFIG.CONFIGRATE 85.0 [current_design] +set_property BITSTREAM.CONFIG.EXTMASTERCCLK_EN DISABLE [current_design] +set_property BITSTREAM.CONFIG.SPI_FALL_EDGE YES [current_design] +set_property BITSTREAM.CONFIG.UNUSEDPIN PULLUP [current_design] +set_property BITSTREAM.CONFIG.SPI_32BIT_ADDR YES [current_design] + +set_operating_conditions -design_power_budget 160 + +# System clocks +# 100 MHz (DDR4) +#set_property -dict {LOC BJ43 IOSTANDARD LVDS} [get_ports clk_100mhz_0_p] +#set_property -dict {LOC BJ44 IOSTANDARD LVDS} [get_ports clk_100mhz_0_n] +#create_clock -period 10 -name clk_100mhz_0 [get_ports clk_100mhz_0_p] + +# 100 MHz (DDR4) +#set_property -dict {LOC BH6 IOSTANDARD LVDS} [get_ports clk_100mhz_1_p] +#set_property -dict {LOC BJ6 IOSTANDARD LVDS} [get_ports clk_100mhz_1_n] +#create_clock -period 10 -name clk_100mhz_1 [get_ports clk_100mhz_1_p] + +# 100 MHz +#set_property -dict {LOC G31 IOSTANDARD LVDS} [get_ports clk_100mhz_2_p] +#set_property -dict {LOC F31 IOSTANDARD LVDS} [get_ports clk_100mhz_2_n] +#create_clock -period 10 -name clk_100mhz_2 [get_ports clk_100mhz_2_p] + +# SI570 user clock +#set_property -dict {LOC G30 IOSTANDARD LVDS} [get_ports clk_si570_p] +#set_property -dict {LOC F30 IOSTANDARD LVDS} [get_ports clk_si570_n] +#create_clock -period 6.4 -name clk_si570 [get_ports clk_si570_p] + +# Reset button +#set_property -dict {LOC L30 IOSTANDARD LVCMOS18} [get_ports reset] + +#set_false_path -from [get_ports {reset}] +#set_input_delay 0 [get_ports {reset}] + +# UART +#set_property -dict {LOC A28 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports usb_uart_txd] +#set_property -dict {LOC B33 IOSTANDARD LVCMOS18} [get_ports usb_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 K28 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 4} [get_ports {msp_gpio[0]}] +#set_property -dict {LOC J29 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 4} [get_ports {msp_gpio[1]}] +#set_property -dict {LOC K29 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 4} [get_ports {msp_gpio[2]}] +#set_property -dict {LOC J31 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 4} [get_ports {msp_gpio[3]}] +#set_property -dict {LOC D29 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 4} [get_ports {msp_uart_txd}] +#set_property -dict {LOC E28 IOSTANDARD LVCMOS18} [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}] + +# HBM overtemp +set_property -dict {LOC D32 IOSTANDARD LVCMOS18} [get_ports hbm_cattrip] + +set_false_path -to [get_ports {hbm_cattrip}] +set_output_delay 0 [get_ports {hbm_cattrip}] + +# QSFP28 Interfaces +#set_property -dict {LOC L53 } [get_ports qsfp0_rx1_p] ;# MGTYRXP0_134 GTYE4_CHANNEL_X0Y40 / GTYE4_COMMON_X0Y10 +#set_property -dict {LOC L54 } [get_ports qsfp0_rx1_n] ;# MGTYRXN0_134 GTYE4_CHANNEL_X0Y40 / GTYE4_COMMON_X0Y10 +#set_property -dict {LOC L48 } [get_ports qsfp0_tx1_p] ;# MGTYTXP0_134 GTYE4_CHANNEL_X0Y40 / GTYE4_COMMON_X0Y10 +#set_property -dict {LOC L49 } [get_ports qsfp0_tx1_n] ;# MGTYTXN0_134 GTYE4_CHANNEL_X0Y40 / GTYE4_COMMON_X0Y10 +#set_property -dict {LOC K51 } [get_ports qsfp0_rx2_p] ;# MGTYRXP1_134 GTYE4_CHANNEL_X0Y41 / GTYE4_COMMON_X0Y10 +#set_property -dict {LOC K52 } [get_ports qsfp0_rx2_n] ;# MGTYRXN1_134 GTYE4_CHANNEL_X0Y41 / GTYE4_COMMON_X0Y10 +#set_property -dict {LOC L44 } [get_ports qsfp0_tx2_p] ;# MGTYTXP1_134 GTYE4_CHANNEL_X0Y41 / GTYE4_COMMON_X0Y10 +#set_property -dict {LOC L45 } [get_ports qsfp0_tx2_n] ;# MGTYTXN1_134 GTYE4_CHANNEL_X0Y41 / GTYE4_COMMON_X0Y10 +#set_property -dict {LOC J53 } [get_ports qsfp0_rx3_p] ;# MGTYRXP2_134 GTYE4_CHANNEL_X0Y42 / GTYE4_COMMON_X0Y10 +#set_property -dict {LOC J54 } [get_ports qsfp0_rx3_n] ;# MGTYRXN2_134 GTYE4_CHANNEL_X0Y42 / GTYE4_COMMON_X0Y10 +#set_property -dict {LOC K46 } [get_ports qsfp0_tx3_p] ;# MGTYTXP2_134 GTYE4_CHANNEL_X0Y42 / GTYE4_COMMON_X0Y10 +#set_property -dict {LOC K47 } [get_ports qsfp0_tx3_n] ;# MGTYTXN2_134 GTYE4_CHANNEL_X0Y42 / GTYE4_COMMON_X0Y10 +#set_property -dict {LOC H51 } [get_ports qsfp0_rx4_p] ;# MGTYRXP3_134 GTYE4_CHANNEL_X0Y43 / GTYE4_COMMON_X0Y10 +#set_property -dict {LOC H52 } [get_ports qsfp0_rx4_n] ;# MGTYRXN3_134 GTYE4_CHANNEL_X0Y43 / GTYE4_COMMON_X0Y10 +#set_property -dict {LOC J48 } [get_ports qsfp0_tx4_p] ;# MGTYTXP3_134 GTYE4_CHANNEL_X0Y43 / GTYE4_COMMON_X0Y10 +#set_property -dict {LOC J49 } [get_ports qsfp0_tx4_n] ;# MGTYTXN3_134 GTYE4_CHANNEL_X0Y43 / GTYE4_COMMON_X0Y10 +#set_property -dict {LOC T42 } [get_ports qsfp0_mgt_refclk_0_p] ;# MGTREFCLK0P_134 from SI570 +#set_property -dict {LOC T43 } [get_ports qsfp0_mgt_refclk_0_n] ;# MGTREFCLK0N_134 from SI570 +#set_property -dict {LOC R40 } [get_ports qsfp0_mgt_refclk_1_p] ;# MGTREFCLK1P_134 from SI546 +#set_property -dict {LOC R41 } [get_ports qsfp0_mgt_refclk_1_n] ;# MGTREFCLK1N_134 from SI546 +#set_property -dict {LOC H32 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports qsfp0_refclk_oe_b] +#set_property -dict {LOC G32 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports qsfp0_refclk_fs] + +# 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 SI546, fs = 0) +#create_clock -period 6.400 -name qsfp0_mgt_refclk_1 [get_ports qsfp0_mgt_refclk_1_p] + +# 161.1328125 MHz MGT reference clock (from SI546, fs = 1) +#create_clock -period 6.206 -name qsfp0_mgt_refclk_1 [get_ports qsfp0_mgt_refclk_1_p] + +#set_false_path -to [get_ports {qsfp0_refclk_oe_b qsfp0_refclk_fs}] +#set_output_delay 0 [get_ports {qsfp0_refclk_oe_b qsfp0_refclk_fs}] + +#set_property -dict {LOC G53 } [get_ports qsfp1_rx1_p] ;# MGTYRXP0_135 GTYE4_CHANNEL_X0Y44 / GTYE4_COMMON_X0Y11 +#set_property -dict {LOC G54 } [get_ports qsfp1_rx1_n] ;# MGTYRXN0_135 GTYE4_CHANNEL_X0Y44 / GTYE4_COMMON_X0Y11 +#set_property -dict {LOC G48 } [get_ports qsfp1_tx1_p] ;# MGTYTXP0_135 GTYE4_CHANNEL_X0Y44 / GTYE4_COMMON_X0Y11 +#set_property -dict {LOC G49 } [get_ports qsfp1_tx1_n] ;# MGTYTXN0_135 GTYE4_CHANNEL_X0Y44 / GTYE4_COMMON_X0Y11 +#set_property -dict {LOC F51 } [get_ports qsfp1_rx2_p] ;# MGTYRXP1_135 GTYE4_CHANNEL_X0Y45 / GTYE4_COMMON_X0Y11 +#set_property -dict {LOC F52 } [get_ports qsfp1_rx2_n] ;# MGTYRXN1_135 GTYE4_CHANNEL_X0Y45 / GTYE4_COMMON_X0Y11 +#set_property -dict {LOC E48 } [get_ports qsfp1_tx2_p] ;# MGTYTXP1_135 GTYE4_CHANNEL_X0Y45 / GTYE4_COMMON_X0Y11 +#set_property -dict {LOC E49 } [get_ports qsfp1_tx2_n] ;# MGTYTXN1_135 GTYE4_CHANNEL_X0Y45 / GTYE4_COMMON_X0Y11 +#set_property -dict {LOC E53 } [get_ports qsfp1_rx3_p] ;# MGTYRXP2_135 GTYE4_CHANNEL_X0Y46 / GTYE4_COMMON_X0Y11 +#set_property -dict {LOC E54 } [get_ports qsfp1_rx3_n] ;# MGTYRXN2_135 GTYE4_CHANNEL_X0Y46 / GTYE4_COMMON_X0Y11 +#set_property -dict {LOC C48 } [get_ports qsfp1_tx3_p] ;# MGTYTXP2_135 GTYE4_CHANNEL_X0Y46 / GTYE4_COMMON_X0Y11 +#set_property -dict {LOC C49 } [get_ports qsfp1_tx3_n] ;# MGTYTXN2_135 GTYE4_CHANNEL_X0Y46 / GTYE4_COMMON_X0Y11 +#set_property -dict {LOC D51 } [get_ports qsfp1_rx4_p] ;# MGTYRXP3_135 GTYE4_CHANNEL_X0Y47 / GTYE4_COMMON_X0Y11 +#set_property -dict {LOC D52 } [get_ports qsfp1_rx4_n] ;# MGTYRXN3_135 GTYE4_CHANNEL_X0Y47 / GTYE4_COMMON_X0Y11 +#set_property -dict {LOC A49 } [get_ports qsfp1_tx4_p] ;# MGTYTXP3_135 GTYE4_CHANNEL_X0Y47 / GTYE4_COMMON_X0Y11 +#set_property -dict {LOC A50 } [get_ports qsfp1_tx4_n] ;# MGTYTXN3_135 GTYE4_CHANNEL_X0Y47 / GTYE4_COMMON_X0Y11 +#set_property -dict {LOC P42 } [get_ports qsfp1_mgt_refclk_0_p] ;# MGTREFCLK0P_135 from SI570 +#set_property -dict {LOC P43 } [get_ports qsfp1_mgt_refclk_0_n] ;# MGTREFCLK0N_135 from SI570 +#set_property -dict {LOC M42 } [get_ports qsfp1_mgt_refclk_1_p] ;# MGTREFCLK1P_135 from SI546 +#set_property -dict {LOC M43 } [get_ports qsfp1_mgt_refclk_1_n] ;# MGTREFCLK1N_135 from SI546 +#set_property -dict {LOC H30 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports qsfp1_refclk_oe_b] +#set_property -dict {LOC G33 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports qsfp1_refclk_fs] + +# 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 SI546, fs = 0) +#create_clock -period 6.400 -name qsfp1_mgt_refclk_1 [get_ports qsfp1_mgt_refclk_1_p] + +# 161.1328125 MHz MGT reference clock (from SI546, fs = 1) +#create_clock -period 6.206 -name qsfp1_mgt_refclk_1 [get_ports qsfp1_mgt_refclk_1_p] + +#set_false_path -to [get_ports {qsfp1_refclk_oe_b qsfp1_refclk_fs}] +#set_output_delay 0 [get_ports {qsfp1_refclk_oe_b qsfp1_refclk_fs}] + +# PCIe Interface +set_property -dict {LOC AL2 } [get_ports {pcie_rx_p[0]}] ;# MGTYRXP3_227 GTYE4_CHANNEL_X1Y15 / GTYE4_COMMON_X1Y3 +set_property -dict {LOC AL1 } [get_ports {pcie_rx_n[0]}] ;# MGTYRXN3_227 GTYE4_CHANNEL_X1Y15 / GTYE4_COMMON_X1Y3 +set_property -dict {LOC AL11} [get_ports {pcie_tx_p[0]}] ;# MGTYTXP3_227 GTYE4_CHANNEL_X1Y15 / GTYE4_COMMON_X1Y3 +set_property -dict {LOC AL10} [get_ports {pcie_tx_n[0]}] ;# MGTYTXN3_227 GTYE4_CHANNEL_X1Y15 / GTYE4_COMMON_X1Y3 +set_property -dict {LOC AM4 } [get_ports {pcie_rx_p[1]}] ;# MGTYRXP2_227 GTYE4_CHANNEL_X1Y14 / GTYE4_COMMON_X1Y3 +set_property -dict {LOC AM3 } [get_ports {pcie_rx_n[1]}] ;# MGTYRXN2_227 GTYE4_CHANNEL_X1Y14 / GTYE4_COMMON_X1Y3 +set_property -dict {LOC AM9 } [get_ports {pcie_tx_p[1]}] ;# MGTYTXP2_227 GTYE4_CHANNEL_X1Y14 / GTYE4_COMMON_X1Y3 +set_property -dict {LOC AM8 } [get_ports {pcie_tx_n[1]}] ;# MGTYTXN2_227 GTYE4_CHANNEL_X1Y14 / GTYE4_COMMON_X1Y3 +set_property -dict {LOC AN6 } [get_ports {pcie_rx_p[2]}] ;# MGTYRXP1_227 GTYE4_CHANNEL_X1Y13 / GTYE4_COMMON_X1Y3 +set_property -dict {LOC AN5 } [get_ports {pcie_rx_n[2]}] ;# MGTYRXN1_227 GTYE4_CHANNEL_X1Y13 / GTYE4_COMMON_X1Y3 +set_property -dict {LOC AN11} [get_ports {pcie_tx_p[2]}] ;# MGTYTXP1_227 GTYE4_CHANNEL_X1Y13 / GTYE4_COMMON_X1Y3 +set_property -dict {LOC AN10} [get_ports {pcie_tx_n[2]}] ;# MGTYTXN1_227 GTYE4_CHANNEL_X1Y13 / GTYE4_COMMON_X1Y3 +set_property -dict {LOC AN2 } [get_ports {pcie_rx_p[3]}] ;# MGTYRXP0_227 GTYE4_CHANNEL_X1Y12 / GTYE4_COMMON_X1Y3 +set_property -dict {LOC AN1 } [get_ports {pcie_rx_n[3]}] ;# MGTYRXN0_227 GTYE4_CHANNEL_X1Y12 / GTYE4_COMMON_X1Y3 +set_property -dict {LOC AP9 } [get_ports {pcie_tx_p[3]}] ;# MGTYTXP0_227 GTYE4_CHANNEL_X1Y12 / GTYE4_COMMON_X1Y3 +set_property -dict {LOC AP8 } [get_ports {pcie_tx_n[3]}] ;# MGTYTXN0_227 GTYE4_CHANNEL_X1Y12 / GTYE4_COMMON_X1Y3 +set_property -dict {LOC AP4 } [get_ports {pcie_rx_p[4]}] ;# MGTYRXP3_226 GTYE4_CHANNEL_X1Y11 / GTYE4_COMMON_X1Y2 +set_property -dict {LOC AP3 } [get_ports {pcie_rx_n[4]}] ;# MGTYRXN3_226 GTYE4_CHANNEL_X1Y11 / GTYE4_COMMON_X1Y2 +set_property -dict {LOC AR11} [get_ports {pcie_tx_p[4]}] ;# MGTYTXP3_226 GTYE4_CHANNEL_X1Y11 / GTYE4_COMMON_X1Y2 +set_property -dict {LOC AR10} [get_ports {pcie_tx_n[4]}] ;# MGTYTXN3_226 GTYE4_CHANNEL_X1Y11 / GTYE4_COMMON_X1Y2 +set_property -dict {LOC AR2 } [get_ports {pcie_rx_p[5]}] ;# MGTYRXP2_226 GTYE4_CHANNEL_X1Y10 / GTYE4_COMMON_X1Y2 +set_property -dict {LOC AR1 } [get_ports {pcie_rx_n[5]}] ;# MGTYRXN2_226 GTYE4_CHANNEL_X1Y10 / GTYE4_COMMON_X1Y2 +set_property -dict {LOC AR7 } [get_ports {pcie_tx_p[5]}] ;# MGTYTXP2_226 GTYE4_CHANNEL_X1Y10 / GTYE4_COMMON_X1Y2 +set_property -dict {LOC AR6 } [get_ports {pcie_tx_n[5]}] ;# MGTYTXN2_226 GTYE4_CHANNEL_X1Y10 / GTYE4_COMMON_X1Y2 +set_property -dict {LOC AT4 } [get_ports {pcie_rx_p[6]}] ;# MGTYRXP1_226 GTYE4_CHANNEL_X1Y9 / GTYE4_COMMON_X1Y2 +set_property -dict {LOC AT3 } [get_ports {pcie_rx_n[6]}] ;# MGTYRXN1_226 GTYE4_CHANNEL_X1Y9 / GTYE4_COMMON_X1Y2 +set_property -dict {LOC AT9 } [get_ports {pcie_tx_p[6]}] ;# MGTYTXP1_226 GTYE4_CHANNEL_X1Y9 / GTYE4_COMMON_X1Y2 +set_property -dict {LOC AT8 } [get_ports {pcie_tx_n[6]}] ;# MGTYTXN1_226 GTYE4_CHANNEL_X1Y9 / GTYE4_COMMON_X1Y2 +set_property -dict {LOC AU2 } [get_ports {pcie_rx_p[7]}] ;# MGTYRXP0_226 GTYE4_CHANNEL_X1Y8 / GTYE4_COMMON_X1Y2 +set_property -dict {LOC AU1 } [get_ports {pcie_rx_n[7]}] ;# MGTYRXN0_226 GTYE4_CHANNEL_X1Y8 / GTYE4_COMMON_X1Y2 +set_property -dict {LOC AU11} [get_ports {pcie_tx_p[7]}] ;# MGTYTXP0_226 GTYE4_CHANNEL_X1Y8 / GTYE4_COMMON_X1Y2 +set_property -dict {LOC AU10} [get_ports {pcie_tx_n[7]}] ;# MGTYTXN0_226 GTYE4_CHANNEL_X1Y8 / GTYE4_COMMON_X1Y2 +set_property -dict {LOC AV4 } [get_ports {pcie_rx_p[8]}] ;# MGTYRXP3_225 GTYE4_CHANNEL_X1Y7 / GTYE4_COMMON_X1Y1 +set_property -dict {LOC AV3 } [get_ports {pcie_rx_n[8]}] ;# MGTYRXN3_225 GTYE4_CHANNEL_X1Y7 / GTYE4_COMMON_X1Y1 +set_property -dict {LOC AU7 } [get_ports {pcie_tx_p[8]}] ;# MGTYTXP3_225 GTYE4_CHANNEL_X1Y7 / GTYE4_COMMON_X1Y1 +set_property -dict {LOC AU6 } [get_ports {pcie_tx_n[8]}] ;# MGTYTXN3_225 GTYE4_CHANNEL_X1Y7 / GTYE4_COMMON_X1Y1 +set_property -dict {LOC AW6 } [get_ports {pcie_rx_p[9]}] ;# MGTYRXP2_225 GTYE4_CHANNEL_X1Y6 / GTYE4_COMMON_X1Y1 +set_property -dict {LOC AW5 } [get_ports {pcie_rx_n[9]}] ;# MGTYRXN2_225 GTYE4_CHANNEL_X1Y6 / GTYE4_COMMON_X1Y1 +set_property -dict {LOC AV9 } [get_ports {pcie_tx_p[9]}] ;# MGTYTXP2_225 GTYE4_CHANNEL_X1Y6 / GTYE4_COMMON_X1Y1 +set_property -dict {LOC AV8 } [get_ports {pcie_tx_n[9]}] ;# MGTYTXN2_225 GTYE4_CHANNEL_X1Y6 / GTYE4_COMMON_X1Y1 +set_property -dict {LOC AW2 } [get_ports {pcie_rx_p[10]}] ;# MGTYRXP1_225 GTYE4_CHANNEL_X1Y5 / GTYE4_COMMON_X1Y1 +set_property -dict {LOC AW1 } [get_ports {pcie_rx_n[10]}] ;# MGTYRXN1_225 GTYE4_CHANNEL_X1Y5 / GTYE4_COMMON_X1Y1 +set_property -dict {LOC AW11} [get_ports {pcie_tx_p[10]}] ;# MGTYTXP1_225 GTYE4_CHANNEL_X1Y5 / GTYE4_COMMON_X1Y1 +set_property -dict {LOC AW10} [get_ports {pcie_tx_n[10]}] ;# MGTYTXN1_225 GTYE4_CHANNEL_X1Y5 / GTYE4_COMMON_X1Y1 +set_property -dict {LOC AY4 } [get_ports {pcie_rx_p[11]}] ;# MGTYRXP0_225 GTYE4_CHANNEL_X1Y4 / GTYE4_COMMON_X1Y1 +set_property -dict {LOC AY3 } [get_ports {pcie_rx_n[11]}] ;# MGTYRXN0_225 GTYE4_CHANNEL_X1Y4 / GTYE4_COMMON_X1Y1 +set_property -dict {LOC AY9 } [get_ports {pcie_tx_p[11]}] ;# MGTYTXP0_225 GTYE4_CHANNEL_X1Y4 / GTYE4_COMMON_X1Y1 +set_property -dict {LOC AY8 } [get_ports {pcie_tx_n[11]}] ;# MGTYTXN0_225 GTYE4_CHANNEL_X1Y4 / GTYE4_COMMON_X1Y1 +set_property -dict {LOC BA6 } [get_ports {pcie_rx_p[12]}] ;# MGTYRXP3_224 GTYE4_CHANNEL_X1Y3 / GTYE4_COMMON_X1Y0 +set_property -dict {LOC BA5 } [get_ports {pcie_rx_n[12]}] ;# MGTYRXN3_224 GTYE4_CHANNEL_X1Y3 / GTYE4_COMMON_X1Y0 +set_property -dict {LOC BA11} [get_ports {pcie_tx_p[12]}] ;# MGTYTXP3_224 GTYE4_CHANNEL_X1Y3 / GTYE4_COMMON_X1Y0 +set_property -dict {LOC BA10} [get_ports {pcie_tx_n[12]}] ;# MGTYTXN3_224 GTYE4_CHANNEL_X1Y3 / GTYE4_COMMON_X1Y0 +set_property -dict {LOC BA2 } [get_ports {pcie_rx_p[13]}] ;# MGTYRXP2_224 GTYE4_CHANNEL_X1Y2 / GTYE4_COMMON_X1Y0 +set_property -dict {LOC BA1 } [get_ports {pcie_rx_n[13]}] ;# MGTYRXN2_224 GTYE4_CHANNEL_X1Y2 / GTYE4_COMMON_X1Y0 +set_property -dict {LOC BB9 } [get_ports {pcie_tx_p[13]}] ;# MGTYTXP2_224 GTYE4_CHANNEL_X1Y2 / GTYE4_COMMON_X1Y0 +set_property -dict {LOC BB8 } [get_ports {pcie_tx_n[13]}] ;# MGTYTXN2_224 GTYE4_CHANNEL_X1Y2 / GTYE4_COMMON_X1Y0 +set_property -dict {LOC BB4 } [get_ports {pcie_rx_p[14]}] ;# MGTYRXP1_224 GTYE4_CHANNEL_X1Y1 / GTYE4_COMMON_X1Y0 +set_property -dict {LOC BB3 } [get_ports {pcie_rx_n[14]}] ;# MGTYRXN1_224 GTYE4_CHANNEL_X1Y1 / GTYE4_COMMON_X1Y0 +set_property -dict {LOC BC11} [get_ports {pcie_tx_p[14]}] ;# MGTYTXP1_224 GTYE4_CHANNEL_X1Y1 / GTYE4_COMMON_X1Y0 +set_property -dict {LOC BC10} [get_ports {pcie_tx_n[14]}] ;# MGTYTXN1_224 GTYE4_CHANNEL_X1Y1 / GTYE4_COMMON_X1Y0 +set_property -dict {LOC BC2 } [get_ports {pcie_rx_p[15]}] ;# MGTYRXP0_224 GTYE4_CHANNEL_X1Y0 / GTYE4_COMMON_X1Y0 +set_property -dict {LOC BC1 } [get_ports {pcie_rx_n[15]}] ;# MGTYRXN0_224 GTYE4_CHANNEL_X1Y0 / GTYE4_COMMON_X1Y0 +set_property -dict {LOC BC7 } [get_ports {pcie_tx_p[15]}] ;# MGTYTXP0_224 GTYE4_CHANNEL_X1Y0 / GTYE4_COMMON_X1Y0 +set_property -dict {LOC BC6 } [get_ports {pcie_tx_n[15]}] ;# MGTYTXN0_224 GTYE4_CHANNEL_X1Y0 / GTYE4_COMMON_X1Y0 +#set_property -dict {LOC AL15} [get_ports pcie_refclk_0_p] ;# MGTREFCLK0P_227 (for x8 bifurcated lanes 0-7) +#set_property -dict {LOC AL14} [get_ports pcie_refclk_0_n] ;# MGTREFCLK0N_227 (for x8 bifurcated lanes 0-7) +#set_property -dict {LOC AK13} [get_ports pcie_refclk_2_p] ;# MGTREFCLK1P_227 (for async x8 bifurcated lanes 0-7) +#set_property -dict {LOC AK12} [get_ports pcie_refclk_2_n] ;# MGTREFCLK1N_227 (for async x8 bifurcated lanes 0-7) +set_property -dict {LOC AR15} [get_ports pcie_refclk_1_p] ;# MGTREFCLK0P_225 (for x16 or x8 bifurcated lanes 8-16) +set_property -dict {LOC AR14} [get_ports pcie_refclk_1_n] ;# MGTREFCLK0N_225 (for x16 or x8 bifurcated lanes 8-16) +#set_property -dict {LOC AP13} [get_ports pcie_refclk_3_p] ;# MGTREFCLK1P_225 (for async x16 or x8 bifurcated lanes 8-16) +#set_property -dict {LOC AP12} [get_ports pcie_refclk_3_n] ;# MGTREFCLK1N_225 (for async x16 or x8 bifurcated lanes 8-16) +set_property -dict {LOC BH26 IOSTANDARD LVCMOS18 PULLUP true} [get_ports pcie_reset_n] + +# 100 MHz MGT reference clock +#create_clock -period 10 -name pcie_mgt_refclk_0 [get_ports pcie_refclk_0_p] +create_clock -period 10 -name pcie_mgt_refclk_1 [get_ports pcie_refclk_1_p] +#create_clock -period 10 -name pcie_mgt_refclk_2 [get_ports pcie_refclk_2_p] +#create_clock -period 10 -name pcie_mgt_refclk_3 [get_ports pcie_refclk_3_p] + +set_false_path -from [get_ports {pcie_reset_n}] +set_input_delay 0 [get_ports {pcie_reset_n}] diff --git a/fpga/lib/pcie/example/AU280/fpga/fpga/Makefile b/fpga/lib/pcie/example/AU280/fpga/fpga/Makefile new file mode 100644 index 000000000..e3ff6807c --- /dev/null +++ b/fpga/lib/pcie/example/AU280/fpga/fpga/Makefile @@ -0,0 +1,94 @@ + +# FPGA settings +FPGA_PART = xcu280-fsvh2892-2L-e +FPGA_TOP = fpga +FPGA_ARCH = virtexuplus + +# Files for synthesis +SYN_FILES = rtl/fpga.v +SYN_FILES += rtl/fpga_core.v +SYN_FILES += rtl/sync_reset.v +SYN_FILES += rtl/sync_signal.v +SYN_FILES += rtl/common/example_core_pcie_us.v +SYN_FILES += rtl/common/example_core_pcie.v +SYN_FILES += rtl/common/example_core.v +SYN_FILES += rtl/common/axi_ram.v +SYN_FILES += lib/pcie/rtl/pcie_us_if.v +SYN_FILES += lib/pcie/rtl/pcie_us_if_rc.v +SYN_FILES += lib/pcie/rtl/pcie_us_if_rq.v +SYN_FILES += lib/pcie/rtl/pcie_us_if_cq.v +SYN_FILES += lib/pcie/rtl/pcie_us_if_cc.v +SYN_FILES += lib/pcie/rtl/pcie_us_cfg.v +SYN_FILES += lib/pcie/rtl/pcie_us_msi.v +SYN_FILES += lib/pcie/rtl/pcie_axil_master.v +SYN_FILES += lib/pcie/rtl/pcie_axi_master.v +SYN_FILES += lib/pcie/rtl/pcie_axi_master_rd.v +SYN_FILES += lib/pcie/rtl/pcie_axi_master_wr.v +SYN_FILES += lib/pcie/rtl/pcie_tlp_demux_bar.v +SYN_FILES += lib/pcie/rtl/pcie_tlp_demux.v +SYN_FILES += lib/pcie/rtl/pcie_tlp_mux.v +SYN_FILES += lib/pcie/rtl/dma_if_pcie.v +SYN_FILES += lib/pcie/rtl/dma_if_pcie_rd.v +SYN_FILES += lib/pcie/rtl/dma_if_pcie_wr.v +SYN_FILES += lib/pcie/rtl/dma_psdpram.v +SYN_FILES += lib/pcie/rtl/arbiter.v +SYN_FILES += lib/pcie/rtl/priority_encoder.v +SYN_FILES += lib/pcie/rtl/pulse_merge.v + +# XDC files +XDC_FILES = fpga.xdc + +# IP +#XCI_FILES = +IP_TCL_FILES = ip/pcie4c_uscale_plus_0.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 + +%.mcs %.prm: %.bit + echo "write_cfgmem -force -format mcs -size 128 -interface SPIx4 -loadbit {up 0x01002000 $*.bit} -checksum -file $*.mcs" > generate_mcs.tcl + echo "exit" >> generate_mcs.tcl + vivado -nojournal -nolog -mode batch -source generate_mcs.tcl + mkdir -p rev + COUNT=100; \ + while [ -e rev/$*_rev$$COUNT.bit ]; \ + do COUNT=$$((COUNT+1)); done; \ + COUNT=$$((COUNT-1)); \ + for x in .mcs .prm; \ + do cp $*$$x rev/$*_rev$$COUNT$$x; \ + echo "Output: rev/$*_rev$$COUNT$$x"; done; + +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 + diff --git a/fpga/lib/pcie/example/AU280/fpga/ip/pcie4c_uscale_plus_0.tcl b/fpga/lib/pcie/example/AU280/fpga/ip/pcie4c_uscale_plus_0.tcl new file mode 100644 index 000000000..36fbed63b --- /dev/null +++ b/fpga/lib/pcie/example/AU280/fpga/ip/pcie4c_uscale_plus_0.tcl @@ -0,0 +1,28 @@ + +create_ip -name pcie4c_uscale_plus -vendor xilinx.com -library ip -module_name pcie4c_uscale_plus_0 + +set_property -dict [list \ + CONFIG.PL_LINK_CAP_MAX_LINK_SPEED {8.0_GT/s} \ + CONFIG.PL_LINK_CAP_MAX_LINK_WIDTH {X16} \ + CONFIG.AXISTEN_IF_EXT_512_RQ_STRADDLE {false} \ + CONFIG.axisten_if_enable_client_tag {true} \ + CONFIG.axisten_if_width {512_bit} \ + CONFIG.axisten_freq {250} \ + CONFIG.PF0_CLASS_CODE {058000} \ + CONFIG.PF0_DEVICE_ID {0001} \ + CONFIG.PF0_MSI_CAP_MULTIMSGCAP {32_vectors} \ + CONFIG.PF0_SUBSYSTEM_ID {9118} \ + CONFIG.PF0_SUBSYSTEM_VENDOR_ID {10ee} \ + CONFIG.pf0_bar0_64bit {true} \ + CONFIG.pf0_bar0_prefetchable {true} \ + CONFIG.pf0_bar0_scale {Megabytes} \ + CONFIG.pf0_bar0_size {16} \ + CONFIG.pf0_bar2_64bit {true} \ + CONFIG.pf0_bar2_prefetchable {true} \ + CONFIG.pf0_bar2_enabled {true} \ + CONFIG.pf0_bar2_type {Memory} \ + CONFIG.pf0_bar2_scale {Megabytes} \ + CONFIG.pf0_bar2_size {16} \ + CONFIG.vendor_id {1234} \ + CONFIG.en_msi_per_vec_masking {true} \ +] [get_ips pcie4c_uscale_plus_0] diff --git a/fpga/lib/pcie/example/AU280/fpga/lib/pcie b/fpga/lib/pcie/example/AU280/fpga/lib/pcie new file mode 120000 index 000000000..11a54ed36 --- /dev/null +++ b/fpga/lib/pcie/example/AU280/fpga/lib/pcie @@ -0,0 +1 @@ +../../../../ \ No newline at end of file diff --git a/fpga/lib/pcie/example/AU280/fpga/rtl/common b/fpga/lib/pcie/example/AU280/fpga/rtl/common new file mode 120000 index 000000000..e60fada70 --- /dev/null +++ b/fpga/lib/pcie/example/AU280/fpga/rtl/common @@ -0,0 +1 @@ +../../../common/rtl/ \ No newline at end of file diff --git a/fpga/lib/pcie/example/AU280/fpga/rtl/fpga.v b/fpga/lib/pcie/example/AU280/fpga/rtl/fpga.v new file mode 100644 index 000000000..ab3b526db --- /dev/null +++ b/fpga/lib/pcie/example/AU280/fpga/rtl/fpga.v @@ -0,0 +1,445 @@ +/* + +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. + +*/ + +// Language: Verilog 2001 + +`resetall +`timescale 1ns / 1ps +`default_nettype none + +/* + * FPGA top-level module + */ +module fpga ( + /* + * GPIO + */ + output wire hbm_cattrip, + + /* + * PCI express + */ + input wire [15:0] pcie_rx_p, + input wire [15:0] pcie_rx_n, + output wire [15:0] pcie_tx_p, + output wire [15:0] pcie_tx_n, + input wire pcie_refclk_1_p, + input wire pcie_refclk_1_n, + input wire pcie_reset_n +); + +parameter AXIS_PCIE_DATA_WIDTH = 512; +parameter AXIS_PCIE_KEEP_WIDTH = (AXIS_PCIE_DATA_WIDTH/32); +parameter AXIS_PCIE_RC_USER_WIDTH = AXIS_PCIE_DATA_WIDTH < 512 ? 75 : 161; +parameter AXIS_PCIE_RQ_USER_WIDTH = AXIS_PCIE_DATA_WIDTH < 512 ? 60 : 137; +parameter AXIS_PCIE_CQ_USER_WIDTH = AXIS_PCIE_DATA_WIDTH < 512 ? 85 : 183; +parameter AXIS_PCIE_CC_USER_WIDTH = AXIS_PCIE_DATA_WIDTH < 512 ? 33 : 81; + +parameter RQ_SEQ_NUM_WIDTH = AXIS_PCIE_RQ_USER_WIDTH == 60 ? 4 : 6; +parameter RQ_SEQ_NUM_ENABLE = 1; + +parameter PCIE_TAG_COUNT = 64; +parameter BAR0_APERTURE = 24; +parameter BAR2_APERTURE = 24; + +// Clock and reset +wire pcie_user_clk; +wire pcie_user_reset; + +// GPIO +assign hbm_cattrip = 1'b0; + +// PCIe +wire pcie_sys_clk; +wire pcie_sys_clk_gt; + +IBUFDS_GTE4 #( + .REFCLK_HROW_CK_SEL(2'b00) +) +ibufds_gte4_pcie_mgt_refclk_inst ( + .I (pcie_refclk_1_p), + .IB (pcie_refclk_1_n), + .CEB (1'b0), + .O (pcie_sys_clk_gt), + .ODIV2 (pcie_sys_clk) +); + +wire [AXIS_PCIE_DATA_WIDTH-1:0] axis_rq_tdata; +wire [AXIS_PCIE_KEEP_WIDTH-1:0] axis_rq_tkeep; +wire axis_rq_tlast; +wire axis_rq_tready; +wire [AXIS_PCIE_RQ_USER_WIDTH-1:0] axis_rq_tuser; +wire axis_rq_tvalid; + +wire [AXIS_PCIE_DATA_WIDTH-1:0] axis_rc_tdata; +wire [AXIS_PCIE_KEEP_WIDTH-1:0] axis_rc_tkeep; +wire axis_rc_tlast; +wire axis_rc_tready; +wire [AXIS_PCIE_RC_USER_WIDTH-1:0] axis_rc_tuser; +wire axis_rc_tvalid; + +wire [AXIS_PCIE_DATA_WIDTH-1:0] axis_cq_tdata; +wire [AXIS_PCIE_KEEP_WIDTH-1:0] axis_cq_tkeep; +wire axis_cq_tlast; +wire axis_cq_tready; +wire [AXIS_PCIE_CQ_USER_WIDTH-1:0] axis_cq_tuser; +wire axis_cq_tvalid; + +wire [AXIS_PCIE_DATA_WIDTH-1:0] axis_cc_tdata; +wire [AXIS_PCIE_KEEP_WIDTH-1:0] axis_cc_tkeep; +wire axis_cc_tlast; +wire axis_cc_tready; +wire [AXIS_PCIE_CC_USER_WIDTH-1:0] axis_cc_tuser; +wire axis_cc_tvalid; + +wire [RQ_SEQ_NUM_WIDTH-1:0] pcie_rq_seq_num0; +wire pcie_rq_seq_num_vld0; +wire [RQ_SEQ_NUM_WIDTH-1:0] pcie_rq_seq_num1; +wire pcie_rq_seq_num_vld1; + +// ila_0 rq_ila ( +// .clk(pcie_user_clk), +// .probe0(axis_rq_tdata), +// .probe1(axis_rq_tkeep), +// .probe2(axis_rq_tlast), +// .probe3(axis_rq_tready), +// .probe4(axis_rq_tuser), +// .probe5(axis_rq_tvalid) +// ); + +// ila_0 rc_ila ( +// .clk(pcie_user_clk), +// .probe0(axis_rc_tdata), +// .probe1(axis_rc_tkeep), +// .probe2(axis_rc_tlast), +// .probe3(axis_rc_tready), +// .probe4(axis_rc_tuser), +// .probe5(axis_rc_tvalid) +// ); + +wire [2:0] cfg_max_payload; +wire [2:0] cfg_max_read_req; + +wire [9:0] cfg_mgmt_addr; +wire [7:0] cfg_mgmt_function_number; +wire cfg_mgmt_write; +wire [31:0] cfg_mgmt_write_data; +wire [3:0] cfg_mgmt_byte_enable; +wire cfg_mgmt_read; +wire [31:0] cfg_mgmt_read_data; +wire cfg_mgmt_read_write_done; + +wire [7:0] cfg_fc_ph; +wire [11:0] cfg_fc_pd; +wire [7:0] cfg_fc_nph; +wire [11:0] cfg_fc_npd; +wire [7:0] cfg_fc_cplh; +wire [11:0] cfg_fc_cpld; +wire [2:0] cfg_fc_sel; + +wire [3:0] cfg_interrupt_msi_enable; +wire [11:0] cfg_interrupt_msi_mmenable; +wire cfg_interrupt_msi_mask_update; +wire [31:0] cfg_interrupt_msi_data; +wire [3:0] cfg_interrupt_msi_select; +wire [31:0] cfg_interrupt_msi_int; +wire [31:0] cfg_interrupt_msi_pending_status; +wire cfg_interrupt_msi_pending_status_data_enable; +wire [3:0] cfg_interrupt_msi_pending_status_function_num; +wire cfg_interrupt_msi_sent; +wire cfg_interrupt_msi_fail; +wire [2:0] cfg_interrupt_msi_attr; +wire cfg_interrupt_msi_tph_present; +wire [1:0] cfg_interrupt_msi_tph_type; +wire [8:0] cfg_interrupt_msi_tph_st_tag; +wire [3:0] cfg_interrupt_msi_function_number; + +wire status_error_cor; +wire status_error_uncor; + +pcie4c_uscale_plus_0 +pcie4c_uscale_plus_inst ( + .pci_exp_txn(pcie_tx_n), + .pci_exp_txp(pcie_tx_p), + .pci_exp_rxn(pcie_rx_n), + .pci_exp_rxp(pcie_rx_p), + .user_clk(pcie_user_clk), + .user_reset(pcie_user_reset), + .user_lnk_up(), + + .s_axis_rq_tdata(axis_rq_tdata), + .s_axis_rq_tkeep(axis_rq_tkeep), + .s_axis_rq_tlast(axis_rq_tlast), + .s_axis_rq_tready(axis_rq_tready), + .s_axis_rq_tuser(axis_rq_tuser), + .s_axis_rq_tvalid(axis_rq_tvalid), + + .m_axis_rc_tdata(axis_rc_tdata), + .m_axis_rc_tkeep(axis_rc_tkeep), + .m_axis_rc_tlast(axis_rc_tlast), + .m_axis_rc_tready(axis_rc_tready), + .m_axis_rc_tuser(axis_rc_tuser), + .m_axis_rc_tvalid(axis_rc_tvalid), + + .m_axis_cq_tdata(axis_cq_tdata), + .m_axis_cq_tkeep(axis_cq_tkeep), + .m_axis_cq_tlast(axis_cq_tlast), + .m_axis_cq_tready(axis_cq_tready), + .m_axis_cq_tuser(axis_cq_tuser), + .m_axis_cq_tvalid(axis_cq_tvalid), + + .s_axis_cc_tdata(axis_cc_tdata), + .s_axis_cc_tkeep(axis_cc_tkeep), + .s_axis_cc_tlast(axis_cc_tlast), + .s_axis_cc_tready(axis_cc_tready), + .s_axis_cc_tuser(axis_cc_tuser), + .s_axis_cc_tvalid(axis_cc_tvalid), + + .pcie_rq_seq_num0(pcie_rq_seq_num0), + .pcie_rq_seq_num_vld0(pcie_rq_seq_num_vld0), + .pcie_rq_seq_num1(pcie_rq_seq_num1), + .pcie_rq_seq_num_vld1(pcie_rq_seq_num_vld1), + .pcie_rq_tag0(), + .pcie_rq_tag1(), + .pcie_rq_tag_av(), + .pcie_rq_tag_vld0(), + .pcie_rq_tag_vld1(), + + .pcie_tfc_nph_av(), + .pcie_tfc_npd_av(), + + .pcie_cq_np_req(1'b1), + .pcie_cq_np_req_count(), + + .cfg_phy_link_down(), + .cfg_phy_link_status(), + .cfg_negotiated_width(), + .cfg_current_speed(), + .cfg_max_payload(cfg_max_payload), + .cfg_max_read_req(cfg_max_read_req), + .cfg_function_status(), + .cfg_function_power_state(), + .cfg_vf_status(), + .cfg_vf_power_state(), + .cfg_link_power_state(), + + .cfg_mgmt_addr(cfg_mgmt_addr), + .cfg_mgmt_function_number(cfg_mgmt_function_number), + .cfg_mgmt_write(cfg_mgmt_write), + .cfg_mgmt_write_data(cfg_mgmt_write_data), + .cfg_mgmt_byte_enable(cfg_mgmt_byte_enable), + .cfg_mgmt_read(cfg_mgmt_read), + .cfg_mgmt_read_data(cfg_mgmt_read_data), + .cfg_mgmt_read_write_done(cfg_mgmt_read_write_done), + .cfg_mgmt_debug_access(1'b0), + + .cfg_err_cor_out(), + .cfg_err_nonfatal_out(), + .cfg_err_fatal_out(), + .cfg_local_error_valid(), + .cfg_local_error_out(), + .cfg_ltssm_state(), + .cfg_rx_pm_state(), + .cfg_tx_pm_state(), + .cfg_rcb_status(), + .cfg_obff_enable(), + .cfg_pl_status_change(), + .cfg_tph_requester_enable(), + .cfg_tph_st_mode(), + .cfg_vf_tph_requester_enable(), + .cfg_vf_tph_st_mode(), + + .cfg_msg_received(), + .cfg_msg_received_data(), + .cfg_msg_received_type(), + .cfg_msg_transmit(1'b0), + .cfg_msg_transmit_type(3'd0), + .cfg_msg_transmit_data(32'd0), + .cfg_msg_transmit_done(), + + .cfg_fc_ph(cfg_fc_ph), + .cfg_fc_pd(cfg_fc_pd), + .cfg_fc_nph(cfg_fc_nph), + .cfg_fc_npd(cfg_fc_npd), + .cfg_fc_cplh(cfg_fc_cplh), + .cfg_fc_cpld(cfg_fc_cpld), + .cfg_fc_sel(cfg_fc_sel), + + .cfg_dsn(64'd0), + + .cfg_bus_number(), + + .cfg_power_state_change_ack(1'b1), + .cfg_power_state_change_interrupt(), + + .cfg_err_cor_in(status_error_cor), + .cfg_err_uncor_in(status_error_uncor), + .cfg_flr_in_process(), + .cfg_flr_done(4'd0), + .cfg_vf_flr_in_process(), + .cfg_vf_flr_func_num(8'd0), + .cfg_vf_flr_done(8'd0), + + .cfg_link_training_enable(1'b1), + + .cfg_interrupt_int(4'd0), + .cfg_interrupt_pending(4'd0), + .cfg_interrupt_sent(), + .cfg_interrupt_msi_enable(cfg_interrupt_msi_enable), + .cfg_interrupt_msi_mmenable(cfg_interrupt_msi_mmenable), + .cfg_interrupt_msi_mask_update(cfg_interrupt_msi_mask_update), + .cfg_interrupt_msi_data(cfg_interrupt_msi_data), + .cfg_interrupt_msi_select(cfg_interrupt_msi_select), + .cfg_interrupt_msi_int(cfg_interrupt_msi_int), + .cfg_interrupt_msi_pending_status(cfg_interrupt_msi_pending_status), + .cfg_interrupt_msi_pending_status_data_enable(cfg_interrupt_msi_pending_status_data_enable), + .cfg_interrupt_msi_pending_status_function_num(cfg_interrupt_msi_pending_status_function_num), + .cfg_interrupt_msi_sent(cfg_interrupt_msi_sent), + .cfg_interrupt_msi_fail(cfg_interrupt_msi_fail), + .cfg_interrupt_msi_attr(cfg_interrupt_msi_attr), + .cfg_interrupt_msi_tph_present(cfg_interrupt_msi_tph_present), + .cfg_interrupt_msi_tph_type(cfg_interrupt_msi_tph_type), + .cfg_interrupt_msi_tph_st_tag(cfg_interrupt_msi_tph_st_tag), + .cfg_interrupt_msi_function_number(cfg_interrupt_msi_function_number), + + .cfg_pm_aspm_l1_entry_reject(1'b0), + .cfg_pm_aspm_tx_l0s_entry_disable(1'b0), + + .cfg_hot_reset_out(), + + .cfg_config_space_enable(1'b1), + .cfg_req_pm_transition_l23_ready(1'b0), + .cfg_hot_reset_in(1'b0), + + .cfg_ds_port_number(8'd0), + .cfg_ds_bus_number(8'd0), + .cfg_ds_device_number(5'd0), + + .sys_clk(pcie_sys_clk), + .sys_clk_gt(pcie_sys_clk_gt), + .sys_reset(pcie_reset_n), + + .phy_rdy_out() +); + +fpga_core #( + .AXIS_PCIE_DATA_WIDTH(AXIS_PCIE_DATA_WIDTH), + .AXIS_PCIE_KEEP_WIDTH(AXIS_PCIE_KEEP_WIDTH), + .AXIS_PCIE_RC_USER_WIDTH(AXIS_PCIE_RC_USER_WIDTH), + .AXIS_PCIE_RQ_USER_WIDTH(AXIS_PCIE_RQ_USER_WIDTH), + .AXIS_PCIE_CQ_USER_WIDTH(AXIS_PCIE_CQ_USER_WIDTH), + .AXIS_PCIE_CC_USER_WIDTH(AXIS_PCIE_CC_USER_WIDTH), + .RQ_SEQ_NUM_WIDTH(RQ_SEQ_NUM_WIDTH), + .RQ_SEQ_NUM_ENABLE(RQ_SEQ_NUM_ENABLE), + .PCIE_TAG_COUNT(PCIE_TAG_COUNT), + .BAR0_APERTURE(BAR0_APERTURE), + .BAR2_APERTURE(BAR2_APERTURE) +) +core_inst ( + /* + * Clock: 250 MHz + * Synchronous reset + */ + .clk(pcie_user_clk), + .rst(pcie_user_reset), + /* + * PCIe + */ + .m_axis_rq_tdata(axis_rq_tdata), + .m_axis_rq_tkeep(axis_rq_tkeep), + .m_axis_rq_tlast(axis_rq_tlast), + .m_axis_rq_tready(axis_rq_tready), + .m_axis_rq_tuser(axis_rq_tuser), + .m_axis_rq_tvalid(axis_rq_tvalid), + + .s_axis_rc_tdata(axis_rc_tdata), + .s_axis_rc_tkeep(axis_rc_tkeep), + .s_axis_rc_tlast(axis_rc_tlast), + .s_axis_rc_tready(axis_rc_tready), + .s_axis_rc_tuser(axis_rc_tuser), + .s_axis_rc_tvalid(axis_rc_tvalid), + + .s_axis_cq_tdata(axis_cq_tdata), + .s_axis_cq_tkeep(axis_cq_tkeep), + .s_axis_cq_tlast(axis_cq_tlast), + .s_axis_cq_tready(axis_cq_tready), + .s_axis_cq_tuser(axis_cq_tuser), + .s_axis_cq_tvalid(axis_cq_tvalid), + + .m_axis_cc_tdata(axis_cc_tdata), + .m_axis_cc_tkeep(axis_cc_tkeep), + .m_axis_cc_tlast(axis_cc_tlast), + .m_axis_cc_tready(axis_cc_tready), + .m_axis_cc_tuser(axis_cc_tuser), + .m_axis_cc_tvalid(axis_cc_tvalid), + + .s_axis_rq_seq_num_0(pcie_rq_seq_num0), + .s_axis_rq_seq_num_valid_0(pcie_rq_seq_num_vld0), + .s_axis_rq_seq_num_1(pcie_rq_seq_num1), + .s_axis_rq_seq_num_valid_1(pcie_rq_seq_num_vld1), + + .cfg_max_payload(cfg_max_payload), + .cfg_max_read_req(cfg_max_read_req), + + .cfg_mgmt_addr(cfg_mgmt_addr), + .cfg_mgmt_function_number(cfg_mgmt_function_number), + .cfg_mgmt_write(cfg_mgmt_write), + .cfg_mgmt_write_data(cfg_mgmt_write_data), + .cfg_mgmt_byte_enable(cfg_mgmt_byte_enable), + .cfg_mgmt_read(cfg_mgmt_read), + .cfg_mgmt_read_data(cfg_mgmt_read_data), + .cfg_mgmt_read_write_done(cfg_mgmt_read_write_done), + + .cfg_fc_ph(cfg_fc_ph), + .cfg_fc_pd(cfg_fc_pd), + .cfg_fc_nph(cfg_fc_nph), + .cfg_fc_npd(cfg_fc_npd), + .cfg_fc_cplh(cfg_fc_cplh), + .cfg_fc_cpld(cfg_fc_cpld), + .cfg_fc_sel(cfg_fc_sel), + + .cfg_interrupt_msi_enable(cfg_interrupt_msi_enable), + .cfg_interrupt_msi_mmenable(cfg_interrupt_msi_mmenable), + .cfg_interrupt_msi_mask_update(cfg_interrupt_msi_mask_update), + .cfg_interrupt_msi_data(cfg_interrupt_msi_data), + .cfg_interrupt_msi_select(cfg_interrupt_msi_select), + .cfg_interrupt_msi_int(cfg_interrupt_msi_int), + .cfg_interrupt_msi_pending_status(cfg_interrupt_msi_pending_status), + .cfg_interrupt_msi_pending_status_data_enable(cfg_interrupt_msi_pending_status_data_enable), + .cfg_interrupt_msi_pending_status_function_num(cfg_interrupt_msi_pending_status_function_num), + .cfg_interrupt_msi_sent(cfg_interrupt_msi_sent), + .cfg_interrupt_msi_fail(cfg_interrupt_msi_fail), + .cfg_interrupt_msi_attr(cfg_interrupt_msi_attr), + .cfg_interrupt_msi_tph_present(cfg_interrupt_msi_tph_present), + .cfg_interrupt_msi_tph_type(cfg_interrupt_msi_tph_type), + .cfg_interrupt_msi_tph_st_tag(cfg_interrupt_msi_tph_st_tag), + .cfg_interrupt_msi_function_number(cfg_interrupt_msi_function_number), + + .status_error_cor(status_error_cor), + .status_error_uncor(status_error_uncor) +); + +endmodule + +`resetall diff --git a/fpga/lib/pcie/example/AU280/fpga/rtl/fpga_core.v b/fpga/lib/pcie/example/AU280/fpga/rtl/fpga_core.v new file mode 100644 index 000000000..23a51e09a --- /dev/null +++ b/fpga/lib/pcie/example/AU280/fpga/rtl/fpga_core.v @@ -0,0 +1,263 @@ +/* + +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. + +*/ + +// Language: Verilog 2001 + +`resetall +`timescale 1ns / 1ps +`default_nettype none + +/* + * FPGA core logic + */ +module fpga_core # +( + parameter AXIS_PCIE_DATA_WIDTH = 512, + parameter AXIS_PCIE_KEEP_WIDTH = (AXIS_PCIE_DATA_WIDTH/32), + parameter AXIS_PCIE_RC_USER_WIDTH = AXIS_PCIE_DATA_WIDTH < 512 ? 75 : 161, + parameter AXIS_PCIE_RQ_USER_WIDTH = AXIS_PCIE_DATA_WIDTH < 512 ? 60 : 137, + parameter AXIS_PCIE_CQ_USER_WIDTH = AXIS_PCIE_DATA_WIDTH < 512 ? 85 : 183, + parameter AXIS_PCIE_CC_USER_WIDTH = AXIS_PCIE_DATA_WIDTH < 512 ? 33 : 81, + parameter RQ_SEQ_NUM_WIDTH = AXIS_PCIE_RQ_USER_WIDTH == 60 ? 4 : 6, + parameter RQ_SEQ_NUM_ENABLE = 1, + parameter PCIE_TAG_COUNT = 64, + parameter BAR0_APERTURE = 24, + parameter BAR2_APERTURE = 24 +) +( + /* + * Clock: 250 MHz + * Synchronous reset + */ + input wire clk, + input wire rst, + + /* + * PCIe + */ + output wire [AXIS_PCIE_DATA_WIDTH-1:0] m_axis_rq_tdata, + output wire [AXIS_PCIE_KEEP_WIDTH-1:0] m_axis_rq_tkeep, + output wire m_axis_rq_tlast, + input wire m_axis_rq_tready, + output wire [AXIS_PCIE_RQ_USER_WIDTH-1:0] m_axis_rq_tuser, + output wire m_axis_rq_tvalid, + + input wire [AXIS_PCIE_DATA_WIDTH-1:0] s_axis_rc_tdata, + input wire [AXIS_PCIE_KEEP_WIDTH-1:0] s_axis_rc_tkeep, + input wire s_axis_rc_tlast, + output wire s_axis_rc_tready, + input wire [AXIS_PCIE_RC_USER_WIDTH-1:0] s_axis_rc_tuser, + input wire s_axis_rc_tvalid, + + input wire [AXIS_PCIE_DATA_WIDTH-1:0] s_axis_cq_tdata, + input wire [AXIS_PCIE_KEEP_WIDTH-1:0] s_axis_cq_tkeep, + input wire s_axis_cq_tlast, + output wire s_axis_cq_tready, + input wire [AXIS_PCIE_CQ_USER_WIDTH-1:0] s_axis_cq_tuser, + input wire s_axis_cq_tvalid, + + output wire [AXIS_PCIE_DATA_WIDTH-1:0] m_axis_cc_tdata, + output wire [AXIS_PCIE_KEEP_WIDTH-1:0] m_axis_cc_tkeep, + output wire m_axis_cc_tlast, + input wire m_axis_cc_tready, + output wire [AXIS_PCIE_CC_USER_WIDTH-1:0] m_axis_cc_tuser, + output wire m_axis_cc_tvalid, + + input wire [RQ_SEQ_NUM_WIDTH-1:0] s_axis_rq_seq_num_0, + input wire s_axis_rq_seq_num_valid_0, + input wire [RQ_SEQ_NUM_WIDTH-1:0] s_axis_rq_seq_num_1, + input wire s_axis_rq_seq_num_valid_1, + + input wire [2:0] cfg_max_payload, + input wire [2:0] cfg_max_read_req, + + output wire [9:0] cfg_mgmt_addr, + output wire [7:0] cfg_mgmt_function_number, + output wire cfg_mgmt_write, + output wire [31:0] cfg_mgmt_write_data, + output wire [3:0] cfg_mgmt_byte_enable, + output wire cfg_mgmt_read, + input wire [31:0] cfg_mgmt_read_data, + input wire cfg_mgmt_read_write_done, + + input wire [7:0] cfg_fc_ph, + input wire [11:0] cfg_fc_pd, + input wire [7:0] cfg_fc_nph, + input wire [11:0] cfg_fc_npd, + input wire [7:0] cfg_fc_cplh, + input wire [11:0] cfg_fc_cpld, + output wire [2:0] cfg_fc_sel, + + input wire [3:0] cfg_interrupt_msi_enable, + input wire [11:0] cfg_interrupt_msi_mmenable, + input wire cfg_interrupt_msi_mask_update, + input wire [31:0] cfg_interrupt_msi_data, + output wire [3:0] cfg_interrupt_msi_select, + output wire [31:0] cfg_interrupt_msi_int, + output wire [31:0] cfg_interrupt_msi_pending_status, + output wire cfg_interrupt_msi_pending_status_data_enable, + output wire [3:0] cfg_interrupt_msi_pending_status_function_num, + input wire cfg_interrupt_msi_sent, + input wire cfg_interrupt_msi_fail, + output wire [2:0] cfg_interrupt_msi_attr, + output wire cfg_interrupt_msi_tph_present, + output wire [1:0] cfg_interrupt_msi_tph_type, + output wire [8:0] cfg_interrupt_msi_tph_st_tag, + output wire [3:0] cfg_interrupt_msi_function_number, + + output wire status_error_cor, + output wire status_error_uncor +); + +example_core_pcie_us #( + .AXIS_PCIE_DATA_WIDTH(AXIS_PCIE_DATA_WIDTH), + .AXIS_PCIE_KEEP_WIDTH(AXIS_PCIE_KEEP_WIDTH), + .AXIS_PCIE_RC_USER_WIDTH(AXIS_PCIE_RC_USER_WIDTH), + .AXIS_PCIE_RQ_USER_WIDTH(AXIS_PCIE_RQ_USER_WIDTH), + .AXIS_PCIE_CQ_USER_WIDTH(AXIS_PCIE_CQ_USER_WIDTH), + .AXIS_PCIE_CC_USER_WIDTH(AXIS_PCIE_CC_USER_WIDTH), + .RQ_SEQ_NUM_WIDTH(RQ_SEQ_NUM_WIDTH), + .RQ_SEQ_NUM_ENABLE(RQ_SEQ_NUM_ENABLE), + .PCIE_TAG_COUNT(PCIE_TAG_COUNT), + .READ_OP_TABLE_SIZE(PCIE_TAG_COUNT), + .READ_TX_LIMIT(2**(RQ_SEQ_NUM_WIDTH-1)), + .READ_TX_FC_ENABLE(1), + .WRITE_OP_TABLE_SIZE(2**(RQ_SEQ_NUM_WIDTH-1)), + .WRITE_TX_LIMIT(2**(RQ_SEQ_NUM_WIDTH-1)), + .WRITE_TX_FC_ENABLE(1), + .BAR0_APERTURE(BAR0_APERTURE), + .BAR2_APERTURE(BAR2_APERTURE) +) +example_core_pcie_us_inst ( + .clk(clk), + .rst(rst), + + /* + * AXI input (RC) + */ + .s_axis_rc_tdata(s_axis_rc_tdata), + .s_axis_rc_tkeep(s_axis_rc_tkeep), + .s_axis_rc_tvalid(s_axis_rc_tvalid), + .s_axis_rc_tready(s_axis_rc_tready), + .s_axis_rc_tlast(s_axis_rc_tlast), + .s_axis_rc_tuser(s_axis_rc_tuser), + + /* + * AXI output (RQ) + */ + .m_axis_rq_tdata(m_axis_rq_tdata), + .m_axis_rq_tkeep(m_axis_rq_tkeep), + .m_axis_rq_tvalid(m_axis_rq_tvalid), + .m_axis_rq_tready(m_axis_rq_tready), + .m_axis_rq_tlast(m_axis_rq_tlast), + .m_axis_rq_tuser(m_axis_rq_tuser), + + /* + * AXI input (CQ) + */ + .s_axis_cq_tdata(s_axis_cq_tdata), + .s_axis_cq_tkeep(s_axis_cq_tkeep), + .s_axis_cq_tvalid(s_axis_cq_tvalid), + .s_axis_cq_tready(s_axis_cq_tready), + .s_axis_cq_tlast(s_axis_cq_tlast), + .s_axis_cq_tuser(s_axis_cq_tuser), + + /* + * AXI output (CC) + */ + .m_axis_cc_tdata(m_axis_cc_tdata), + .m_axis_cc_tkeep(m_axis_cc_tkeep), + .m_axis_cc_tvalid(m_axis_cc_tvalid), + .m_axis_cc_tready(m_axis_cc_tready), + .m_axis_cc_tlast(m_axis_cc_tlast), + .m_axis_cc_tuser(m_axis_cc_tuser), + + /* + * Transmit sequence number input + */ + .s_axis_rq_seq_num_0(s_axis_rq_seq_num_0), + .s_axis_rq_seq_num_valid_0(s_axis_rq_seq_num_valid_0), + .s_axis_rq_seq_num_1(s_axis_rq_seq_num_1), + .s_axis_rq_seq_num_valid_1(s_axis_rq_seq_num_valid_1), + + /* + * Flow control + */ + .cfg_fc_ph(cfg_fc_ph), + .cfg_fc_pd(cfg_fc_pd), + .cfg_fc_nph(cfg_fc_nph), + .cfg_fc_npd(cfg_fc_npd), + .cfg_fc_cplh(cfg_fc_cplh), + .cfg_fc_cpld(cfg_fc_cpld), + .cfg_fc_sel(cfg_fc_sel), + + /* + * Configuration interface + */ + .cfg_mgmt_addr(cfg_mgmt_addr), + .cfg_mgmt_function_number(cfg_mgmt_function_number), + .cfg_mgmt_write(cfg_mgmt_write), + .cfg_mgmt_write_data(cfg_mgmt_write_data), + .cfg_mgmt_byte_enable(cfg_mgmt_byte_enable), + .cfg_mgmt_read(cfg_mgmt_read), + .cfg_mgmt_read_data(cfg_mgmt_read_data), + .cfg_mgmt_read_write_done(cfg_mgmt_read_write_done), + + /* + * Interrupt interface + */ + .cfg_interrupt_msi_enable(cfg_interrupt_msi_enable), + .cfg_interrupt_msi_vf_enable(8'd0), + .cfg_interrupt_msi_mmenable(cfg_interrupt_msi_mmenable), + .cfg_interrupt_msi_mask_update(cfg_interrupt_msi_mask_update), + .cfg_interrupt_msi_data(cfg_interrupt_msi_data), + .cfg_interrupt_msi_select(cfg_interrupt_msi_select), + .cfg_interrupt_msi_int(cfg_interrupt_msi_int), + .cfg_interrupt_msi_pending_status(cfg_interrupt_msi_pending_status), + .cfg_interrupt_msi_pending_status_data_enable(cfg_interrupt_msi_pending_status_data_enable), + .cfg_interrupt_msi_pending_status_function_num(cfg_interrupt_msi_pending_status_function_num), + .cfg_interrupt_msi_sent(cfg_interrupt_msi_sent), + .cfg_interrupt_msi_fail(cfg_interrupt_msi_fail), + .cfg_interrupt_msi_attr(cfg_interrupt_msi_attr), + .cfg_interrupt_msi_tph_present(cfg_interrupt_msi_tph_present), + .cfg_interrupt_msi_tph_type(cfg_interrupt_msi_tph_type), + .cfg_interrupt_msi_tph_st_tag(cfg_interrupt_msi_tph_st_tag), + .cfg_interrupt_msi_function_number(cfg_interrupt_msi_function_number), + + /* + * Configuration + */ + .cfg_max_read_req(cfg_max_read_req), + .cfg_max_payload(cfg_max_payload), + + /* + * Status + */ + .status_error_cor(status_error_cor), + .status_error_uncor(status_error_uncor) +); + +endmodule + +`resetall diff --git a/fpga/lib/pcie/example/AU280/fpga/rtl/sync_reset.v b/fpga/lib/pcie/example/AU280/fpga/rtl/sync_reset.v new file mode 100644 index 000000000..1fd24d361 --- /dev/null +++ b/fpga/lib/pcie/example/AU280/fpga/rtl/sync_reset.v @@ -0,0 +1,56 @@ +/* + +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 active-high asynchronous reset signal to a given clock by + * using a pipeline of N registers. + */ +module sync_reset #( + parameter N=2 // depth of synchronizer +)( + input wire clk, + input wire rst, + output wire sync_reset_out +); + +reg [N-1:0] sync_reg = {N{1'b1}}; + +assign sync_reset_out = sync_reg[N-1]; + +always @(posedge clk or posedge rst) begin + if (rst) + sync_reg <= {N{1'b1}}; + else + sync_reg <= {sync_reg[N-2:0], 1'b0}; +end + +endmodule + +`resetall diff --git a/fpga/lib/pcie/example/AU280/fpga/rtl/sync_signal.v b/fpga/lib/pcie/example/AU280/fpga/rtl/sync_signal.v new file mode 100644 index 000000000..74b855fa1 --- /dev/null +++ b/fpga/lib/pcie/example/AU280/fpga/rtl/sync_signal.v @@ -0,0 +1,62 @@ +/* + +Copyright (c) 2014-2018 Alex Forencich + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +*/ + +// Language: Verilog-2001 + +`resetall +`timescale 1 ns / 1 ps +`default_nettype none + +/* + * Synchronizes an asyncronous signal to a given clock by using a pipeline of + * two registers. + */ +module sync_signal #( + parameter WIDTH=1, // width of the input and output signals + parameter N=2 // depth of synchronizer +)( + input wire clk, + input wire [WIDTH-1:0] in, + output wire [WIDTH-1:0] out +); + +reg [WIDTH-1:0] sync_reg[N-1:0]; + +/* + * The synchronized output is the last register in the pipeline. + */ +assign out = sync_reg[N-1]; + +integer k; + +always @(posedge clk) begin + sync_reg[0] <= in; + for (k = 1; k < N; k = k + 1) begin + sync_reg[k] <= sync_reg[k-1]; + end +end + +endmodule + +`resetall diff --git a/fpga/lib/pcie/example/AU280/fpga/tb/fpga_core/Makefile b/fpga/lib/pcie/example/AU280/fpga/tb/fpga_core/Makefile new file mode 100644 index 000000000..7c85b6e54 --- /dev/null +++ b/fpga/lib/pcie/example/AU280/fpga/tb/fpga_core/Makefile @@ -0,0 +1,123 @@ +# Copyright (c) 2020 Alex Forencich +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +TOPLEVEL_LANG = verilog + +SIM ?= icarus +WAVES ?= 0 + +COCOTB_HDL_TIMEUNIT = 1ns +COCOTB_HDL_TIMEPRECISION = 1ps + +DUT = fpga_core +TOPLEVEL = $(DUT) +MODULE = test_$(DUT) +VERILOG_SOURCES += ../../rtl/$(DUT).v +VERILOG_SOURCES += ../../rtl/common/example_core_pcie_us.v +VERILOG_SOURCES += ../../rtl/common/example_core_pcie.v +VERILOG_SOURCES += ../../rtl/common/example_core.v +VERILOG_SOURCES += ../../rtl/common/axi_ram.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_if.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_if_rc.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_if_rq.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_if_cq.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_if_cc.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_cfg.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_msi.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_axil_master.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_axi_master.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_axi_master_rd.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_axi_master_wr.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_tlp_demux_bar.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_tlp_demux.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_tlp_mux.v +VERILOG_SOURCES += ../../lib/pcie/rtl/dma_if_pcie.v +VERILOG_SOURCES += ../../lib/pcie/rtl/dma_if_pcie_rd.v +VERILOG_SOURCES += ../../lib/pcie/rtl/dma_if_pcie_wr.v +VERILOG_SOURCES += ../../lib/pcie/rtl/dma_psdpram.v +VERILOG_SOURCES += ../../lib/pcie/rtl/arbiter.v +VERILOG_SOURCES += ../../lib/pcie/rtl/priority_encoder.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pulse_merge.v + +# module parameters +export PARAM_AXIS_PCIE_DATA_WIDTH ?= 512 +export PARAM_AXIS_PCIE_KEEP_WIDTH ?= $(shell expr $(PARAM_AXIS_PCIE_DATA_WIDTH) / 32 ) +export PARAM_AXIS_PCIE_RQ_USER_WIDTH ?= $(if $(filter-out 512,$(PARAM_AXIS_PCIE_DATA_WIDTH)),62,137) +export PARAM_AXIS_PCIE_RC_USER_WIDTH ?= $(if $(filter-out 512,$(PARAM_AXIS_PCIE_DATA_WIDTH)),75,161) +export PARAM_AXIS_PCIE_CQ_USER_WIDTH ?= $(if $(filter-out 512,$(PARAM_AXIS_PCIE_DATA_WIDTH)),88,183) +export PARAM_AXIS_PCIE_CC_USER_WIDTH ?= $(if $(filter-out 512,$(PARAM_AXIS_PCIE_DATA_WIDTH)),33,81) +export PARAM_RQ_SEQ_NUM_WIDTH ?= 6 +export PARAM_RQ_SEQ_NUM_ENABLE ?= 1 +export PARAM_PCIE_TAG_COUNT ?= 64 +export PARAM_BAR0_APERTURE ?= 24 +export PARAM_BAR2_APERTURE ?= 24 + +ifeq ($(SIM), icarus) + PLUSARGS += -fst + + COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_DATA_WIDTH=$(PARAM_AXIS_PCIE_DATA_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_KEEP_WIDTH=$(PARAM_AXIS_PCIE_KEEP_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_RQ_USER_WIDTH=$(PARAM_AXIS_PCIE_RQ_USER_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_RC_USER_WIDTH=$(PARAM_AXIS_PCIE_RC_USER_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_CQ_USER_WIDTH=$(PARAM_AXIS_PCIE_CQ_USER_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_CC_USER_WIDTH=$(PARAM_AXIS_PCIE_CC_USER_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).RQ_SEQ_NUM_WIDTH=$(PARAM_RQ_SEQ_NUM_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).RQ_SEQ_NUM_ENABLE=$(PARAM_RQ_SEQ_NUM_ENABLE) + COMPILE_ARGS += -P $(TOPLEVEL).PCIE_TAG_COUNT=$(PARAM_PCIE_TAG_COUNT) + COMPILE_ARGS += -P $(TOPLEVEL).BAR0_APERTURE=$(PARAM_BAR0_APERTURE) + COMPILE_ARGS += -P $(TOPLEVEL).BAR2_APERTURE=$(PARAM_BAR2_APERTURE) + + ifeq ($(WAVES), 1) + VERILOG_SOURCES += iverilog_dump.v + COMPILE_ARGS += -s iverilog_dump + endif +else ifeq ($(SIM), verilator) + COMPILE_ARGS += -Wno-SELRANGE -Wno-WIDTH + + COMPILE_ARGS += -GAXIS_PCIE_DATA_WIDTH=$(PARAM_AXIS_PCIE_DATA_WIDTH) + COMPILE_ARGS += -GAXIS_PCIE_KEEP_WIDTH=$(PARAM_AXIS_PCIE_KEEP_WIDTH) + COMPILE_ARGS += -GAXIS_PCIE_RQ_USER_WIDTH=$(PARAM_AXIS_PCIE_RQ_USER_WIDTH) + COMPILE_ARGS += -GAXIS_PCIE_RC_USER_WIDTH=$(PARAM_AXIS_PCIE_RC_USER_WIDTH) + COMPILE_ARGS += -GAXIS_PCIE_CQ_USER_WIDTH=$(PARAM_AXIS_PCIE_CQ_USER_WIDTH) + COMPILE_ARGS += -GAXIS_PCIE_CC_USER_WIDTH=$(PARAM_AXIS_PCIE_CC_USER_WIDTH) + COMPILE_ARGS += -GRQ_SEQ_NUM_WIDTH=$(PARAM_RQ_SEQ_NUM_WIDTH) + COMPILE_ARGS += -GRQ_SEQ_NUM_ENABLE=$(PARAM_RQ_SEQ_NUM_ENABLE) + COMPILE_ARGS += -GPCIE_TAG_COUNT=$(PARAM_PCIE_TAG_COUNT) + COMPILE_ARGS += -GBAR0_APERTURE=$(PARAM_BAR0_APERTURE) + COMPILE_ARGS += -GBAR2_APERTURE=$(PARAM_BAR2_APERTURE) + + ifeq ($(WAVES), 1) + COMPILE_ARGS += --trace-fst + endif +endif + +include $(shell cocotb-config --makefiles)/Makefile.sim + +iverilog_dump.v: + echo 'module iverilog_dump();' > $@ + echo 'initial begin' >> $@ + echo ' $$dumpfile("$(TOPLEVEL).fst");' >> $@ + echo ' $$dumpvars(0, $(TOPLEVEL));' >> $@ + echo 'end' >> $@ + echo 'endmodule' >> $@ + +clean:: + @rm -rf iverilog_dump.v + @rm -rf dump.fst $(TOPLEVEL).fst diff --git a/fpga/lib/pcie/example/AU280/fpga/tb/fpga_core/test_fpga_core.py b/fpga/lib/pcie/example/AU280/fpga/tb/fpga_core/test_fpga_core.py new file mode 100644 index 000000000..f2c657c91 --- /dev/null +++ b/fpga/lib/pcie/example/AU280/fpga/tb/fpga_core/test_fpga_core.py @@ -0,0 +1,472 @@ +""" + +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 + +import cocotb_test.simulator + +import cocotb +from cocotb.log import SimLog +from cocotb.triggers import RisingEdge, FallingEdge, Timer + +from cocotbext.axi import AxiStreamBus +from cocotbext.pcie.core import RootComplex +from cocotbext.pcie.xilinx.us import UltraScalePlusPcieDevice + + +class TB(object): + def __init__(self, dut): + self.dut = dut + + self.log = SimLog("cocotb.tb") + self.log.setLevel(logging.DEBUG) + + # PCIe + self.rc = RootComplex() + + self.dev = UltraScalePlusPcieDevice( + # configuration options + pcie_generation=3, + pcie_link_width=16, + user_clk_frequency=250e6, + alignment="dword", + cq_cc_straddle=False, + rq_rc_straddle=False, + rc_4tlp_straddle=False, + enable_pf1=False, + enable_client_tag=True, + enable_extended_tag=True, + enable_parity=False, + enable_rx_msg_interface=False, + enable_sriov=False, + enable_extended_configuration=False, + + enable_pf0_msi=True, + enable_pf1_msi=False, + + # signals + # Clock and Reset Interface + user_clk=dut.clk, + user_reset=dut.rst, + # user_lnk_up + # sys_clk + # sys_clk_gt + # sys_reset + # phy_rdy_out + + # Requester reQuest Interface + rq_bus=AxiStreamBus.from_prefix(dut, "m_axis_rq"), + pcie_rq_seq_num0=dut.s_axis_rq_seq_num_0, + pcie_rq_seq_num_vld0=dut.s_axis_rq_seq_num_valid_0, + pcie_rq_seq_num1=dut.s_axis_rq_seq_num_1, + pcie_rq_seq_num_vld1=dut.s_axis_rq_seq_num_valid_1, + # pcie_rq_tag0 + # pcie_rq_tag1 + # pcie_rq_tag_av + # pcie_rq_tag_vld0 + # pcie_rq_tag_vld1 + + # Requester Completion Interface + rc_bus=AxiStreamBus.from_prefix(dut, "s_axis_rc"), + + # Completer reQuest Interface + cq_bus=AxiStreamBus.from_prefix(dut, "s_axis_cq"), + # pcie_cq_np_req + # pcie_cq_np_req_count + + # Completer Completion Interface + cc_bus=AxiStreamBus.from_prefix(dut, "m_axis_cc"), + + # Transmit Flow Control Interface + # pcie_tfc_nph_av=dut.pcie_tfc_nph_av, + # pcie_tfc_npd_av=dut.pcie_tfc_npd_av, + + # Configuration Management Interface + cfg_mgmt_addr=dut.cfg_mgmt_addr, + cfg_mgmt_function_number=dut.cfg_mgmt_function_number, + cfg_mgmt_write=dut.cfg_mgmt_write, + cfg_mgmt_write_data=dut.cfg_mgmt_write_data, + cfg_mgmt_byte_enable=dut.cfg_mgmt_byte_enable, + cfg_mgmt_read=dut.cfg_mgmt_read, + cfg_mgmt_read_data=dut.cfg_mgmt_read_data, + cfg_mgmt_read_write_done=dut.cfg_mgmt_read_write_done, + # cfg_mgmt_debug_access + + # Configuration Status Interface + # cfg_phy_link_down + # cfg_phy_link_status + # cfg_negotiated_width + # cfg_current_speed + cfg_max_payload=dut.cfg_max_payload, + cfg_max_read_req=dut.cfg_max_read_req, + # cfg_function_status + # cfg_vf_status + # cfg_function_power_state + # cfg_vf_power_state + # cfg_link_power_state + # cfg_err_cor_out + # cfg_err_nonfatal_out + # cfg_err_fatal_out + # cfg_local_error_out + # cfg_local_error_valid + # cfg_rx_pm_state + # cfg_tx_pm_state + # cfg_ltssm_state + # cfg_rcb_status + # cfg_obff_enable + # cfg_pl_status_change + # cfg_tph_requester_enable + # cfg_tph_st_mode + # cfg_vf_tph_requester_enable + # cfg_vf_tph_st_mode + + # Configuration Received Message Interface + # cfg_msg_received + # cfg_msg_received_data + # cfg_msg_received_type + + # Configuration Transmit Message Interface + # cfg_msg_transmit + # cfg_msg_transmit_type + # cfg_msg_transmit_data + # cfg_msg_transmit_done + + # Configuration Flow Control Interface + cfg_fc_ph=dut.cfg_fc_ph, + cfg_fc_pd=dut.cfg_fc_pd, + cfg_fc_nph=dut.cfg_fc_nph, + cfg_fc_npd=dut.cfg_fc_npd, + cfg_fc_cplh=dut.cfg_fc_cplh, + cfg_fc_cpld=dut.cfg_fc_cpld, + cfg_fc_sel=dut.cfg_fc_sel, + + # Configuration Control Interface + # cfg_hot_reset_in + # cfg_hot_reset_out + # cfg_config_space_enable + # cfg_dsn + # cfg_bus_number + # cfg_ds_port_number + # cfg_ds_bus_number + # cfg_ds_device_number + # cfg_ds_function_number + # cfg_power_state_change_ack + # cfg_power_state_change_interrupt + cfg_err_cor_in=dut.status_error_cor, + cfg_err_uncor_in=dut.status_error_uncor, + # cfg_flr_in_process + # cfg_flr_done + # cfg_vf_flr_in_process + # cfg_vf_flr_func_num + # cfg_vf_flr_done + # cfg_pm_aspm_l1_entry_reject + # cfg_pm_aspm_tx_l0s_entry_disable + # cfg_req_pm_transition_l23_ready + # cfg_link_training_enable + + # Configuration Interrupt Controller Interface + # cfg_interrupt_int + # cfg_interrupt_sent + # cfg_interrupt_pending + cfg_interrupt_msi_enable=dut.cfg_interrupt_msi_enable, + cfg_interrupt_msi_mmenable=dut.cfg_interrupt_msi_mmenable, + cfg_interrupt_msi_mask_update=dut.cfg_interrupt_msi_mask_update, + cfg_interrupt_msi_data=dut.cfg_interrupt_msi_data, + # cfg_interrupt_msi_select=dut.cfg_interrupt_msi_select, + cfg_interrupt_msi_int=dut.cfg_interrupt_msi_int, + cfg_interrupt_msi_pending_status=dut.cfg_interrupt_msi_pending_status, + cfg_interrupt_msi_pending_status_data_enable=dut.cfg_interrupt_msi_pending_status_data_enable, + # cfg_interrupt_msi_pending_status_function_num=dut.cfg_interrupt_msi_pending_status_function_num, + cfg_interrupt_msi_sent=dut.cfg_interrupt_msi_sent, + cfg_interrupt_msi_fail=dut.cfg_interrupt_msi_fail, + # cfg_interrupt_msix_enable + # cfg_interrupt_msix_mask + # cfg_interrupt_msix_vf_enable + # cfg_interrupt_msix_vf_mask + # cfg_interrupt_msix_address + # cfg_interrupt_msix_data + # cfg_interrupt_msix_int + # cfg_interrupt_msix_vec_pending + # cfg_interrupt_msix_vec_pending_status + cfg_interrupt_msi_attr=dut.cfg_interrupt_msi_attr, + cfg_interrupt_msi_tph_present=dut.cfg_interrupt_msi_tph_present, + cfg_interrupt_msi_tph_type=dut.cfg_interrupt_msi_tph_type, + # cfg_interrupt_msi_tph_st_tag=dut.cfg_interrupt_msi_tph_st_tag, + # cfg_interrupt_msi_function_number=dut.cfg_interrupt_msi_function_number, + + # Configuration Extend Interface + # cfg_ext_read_received + # cfg_ext_write_received + # cfg_ext_register_number + # cfg_ext_function_number + # cfg_ext_write_data + # cfg_ext_write_byte_enable + # cfg_ext_read_data + # cfg_ext_read_data_valid + ) + + # self.dev.log.setLevel(logging.DEBUG) + + self.rc.make_port().connect(self.dev) + + self.dev.functions[0].msi_multiple_message_capable = 5 + + self.dev.functions[0].configure_bar(0, 2**len(dut.example_core_pcie_us_inst.core_pcie_inst.axil_ctrl_awaddr)) + self.dev.functions[0].configure_bar(2, 2**len(dut.example_core_pcie_us_inst.core_pcie_inst.axi_ram_awaddr)) + + async def init(self): + + await FallingEdge(self.dut.rst) + await Timer(100, 'ns') + + await self.rc.enumerate(enable_bus_mastering=True, configure_msi=True) + + +@cocotb.test() +async def run_test(dut): + + tb = TB(dut) + + await tb.init() + + mem = tb.rc.mem_pool.alloc_region(16*1024*1024) + mem_base = mem.get_absolute_address(0) + + dev_pf0_bar0 = tb.rc.tree[0][0].bar_window[0] + dev_pf0_bar2 = tb.rc.tree[0][0].bar_window[2] + + tb.log.info("Test memory write to BAR 2") + + test_data = b'\x11\x22\x33\x44' + await dev_pf0_bar2.write(0, test_data) + + await Timer(100, 'ns') + + tb.log.info("Test memory read from BAR 2") + + val = await dev_pf0_bar2.read(0, len(test_data), timeout=1000) + tb.log.info("Read data: %s", val) + assert val == test_data + + tb.log.info("Test DMA") + + # write packet data + mem[0:1024] = bytearray([x % 256 for x in range(1024)]) + + # enable DMA + await dev_pf0_bar0.write_dword(0x000000, 1) + + # write pcie read descriptor + await dev_pf0_bar0.write_dword(0x000100, (mem_base+0x0000) & 0xffffffff) + await dev_pf0_bar0.write_dword(0x000104, (mem_base+0x0000 >> 32) & 0xffffffff) + await dev_pf0_bar0.write_dword(0x000108, 0x100) + await dev_pf0_bar0.write_dword(0x000110, 0x400) + await dev_pf0_bar0.write_dword(0x000114, 0xAA) + + await Timer(2000, 'ns') + + # read status + val = await dev_pf0_bar0.read_dword(0x000118) + tb.log.info("Status: 0x%x", val) + assert val == 0x800000AA + + # write pcie write descriptor + await dev_pf0_bar0.write_dword(0x000200, (mem_base+0x1000) & 0xffffffff) + await dev_pf0_bar0.write_dword(0x000204, (mem_base+0x1000 >> 32) & 0xffffffff) + await dev_pf0_bar0.write_dword(0x000208, 0x100) + await dev_pf0_bar0.write_dword(0x000210, 0x400) + await dev_pf0_bar0.write_dword(0x000214, 0x55) + + await Timer(2000, 'ns') + + # read status + val = await dev_pf0_bar0.read_dword(0x000218) + tb.log.info("Status: 0x%x", val) + assert val == 0x80000055 + + tb.log.info("%s", mem.hexdump_str(0x1000, 64)) + + assert mem[0:1024] == mem[0x1000:0x1000+1024] + + tb.log.info("Test DMA block operations") + + # write packet data + mem[0:1024] = bytearray([x % 256 for x in range(1024)]) + + # enable DMA + await dev_pf0_bar0.write_dword(0x000000, 1) + # disable interrupts + await dev_pf0_bar0.write_dword(0x000008, 0) + + # configure operation (read) + # DMA base address + await dev_pf0_bar0.write_dword(0x001080, (mem_base+0x0000) & 0xffffffff) + await dev_pf0_bar0.write_dword(0x001084, (mem_base+0x0000 >> 32) & 0xffffffff) + # DMA offset address + await dev_pf0_bar0.write_dword(0x001088, 0) + await dev_pf0_bar0.write_dword(0x00108c, 0) + # DMA offset mask + await dev_pf0_bar0.write_dword(0x001090, 0x000003ff) + await dev_pf0_bar0.write_dword(0x001094, 0) + # DMA stride + await dev_pf0_bar0.write_dword(0x001098, 256) + await dev_pf0_bar0.write_dword(0x00109c, 0) + # RAM base address + await dev_pf0_bar0.write_dword(0x0010c0, 0) + await dev_pf0_bar0.write_dword(0x0010c4, 0) + # RAM offset address + await dev_pf0_bar0.write_dword(0x0010c8, 0) + await dev_pf0_bar0.write_dword(0x0010cc, 0) + # RAM offset mask + await dev_pf0_bar0.write_dword(0x0010d0, 0x000003ff) + await dev_pf0_bar0.write_dword(0x0010d4, 0) + # RAM stride + await dev_pf0_bar0.write_dword(0x0010d8, 256) + await dev_pf0_bar0.write_dword(0x0010dc, 0) + # clear cycle count + await dev_pf0_bar0.write_dword(0x001008, 0) + await dev_pf0_bar0.write_dword(0x00100c, 0) + # block length + await dev_pf0_bar0.write_dword(0x001010, 256) + # block count + await dev_pf0_bar0.write_dword(0x001018, 32) + await dev_pf0_bar0.write_dword(0x00101c, 0) + # start + await dev_pf0_bar0.write_dword(0x001000, 1) + + await Timer(2000, 'ns') + + # configure operation (write) + # DMA base address + await dev_pf0_bar0.write_dword(0x001180, (mem_base+0x0000) & 0xffffffff) + await dev_pf0_bar0.write_dword(0x001184, (mem_base+0x0000 >> 32) & 0xffffffff) + # DMA offset address + await dev_pf0_bar0.write_dword(0x001188, 0) + await dev_pf0_bar0.write_dword(0x00118c, 0) + # DMA offset mask + await dev_pf0_bar0.write_dword(0x001190, 0x000003ff) + await dev_pf0_bar0.write_dword(0x001194, 0) + # DMA stride + await dev_pf0_bar0.write_dword(0x001198, 256) + await dev_pf0_bar0.write_dword(0x00119c, 0) + # RAM base address + await dev_pf0_bar0.write_dword(0x0011c0, 0) + await dev_pf0_bar0.write_dword(0x0011c4, 0) + # RAM offset address + await dev_pf0_bar0.write_dword(0x0011c8, 0) + await dev_pf0_bar0.write_dword(0x0011cc, 0) + # RAM offset mask + await dev_pf0_bar0.write_dword(0x0011d0, 0x000003ff) + await dev_pf0_bar0.write_dword(0x0011d4, 0) + # RAM stride + await dev_pf0_bar0.write_dword(0x0011d8, 256) + await dev_pf0_bar0.write_dword(0x0011dc, 0) + # clear cycle count + await dev_pf0_bar0.write_dword(0x001108, 0) + await dev_pf0_bar0.write_dword(0x00110c, 0) + # block length + await dev_pf0_bar0.write_dword(0x001110, 256) + # block count + await dev_pf0_bar0.write_dword(0x001118, 32) + await dev_pf0_bar0.write_dword(0x00111c, 0) + # start + await dev_pf0_bar0.write_dword(0x001100, 1) + + await Timer(2000, 'ns') + + await RisingEdge(dut.clk) + await RisingEdge(dut.clk) + + +# cocotb-test + +tests_dir = 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')) +pcie_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'pcie', '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(rtl_dir, "common", "example_core_pcie_us.v"), + os.path.join(rtl_dir, "common", "example_core_pcie.v"), + os.path.join(rtl_dir, "common", "example_core.v"), + os.path.join(rtl_dir, "common", "axi_ram.v"), + os.path.join(pcie_rtl_dir, "pcie_us_if.v"), + os.path.join(pcie_rtl_dir, "pcie_us_if_rc.v"), + os.path.join(pcie_rtl_dir, "pcie_us_if_rq.v"), + os.path.join(pcie_rtl_dir, "pcie_us_if_cq.v"), + os.path.join(pcie_rtl_dir, "pcie_us_if_cc.v"), + os.path.join(pcie_rtl_dir, "pcie_us_cfg.v"), + os.path.join(pcie_rtl_dir, "pcie_us_msi.v"), + os.path.join(pcie_rtl_dir, "pcie_axil_master.v"), + os.path.join(pcie_rtl_dir, "pcie_axi_master.v"), + os.path.join(pcie_rtl_dir, "pcie_axi_master_rd.v"), + os.path.join(pcie_rtl_dir, "pcie_axi_master_wr.v"), + os.path.join(pcie_rtl_dir, "pcie_tlp_demux_bar.v"), + os.path.join(pcie_rtl_dir, "pcie_tlp_demux.v"), + os.path.join(pcie_rtl_dir, "pcie_tlp_mux.v"), + os.path.join(pcie_rtl_dir, "dma_if_pcie.v"), + os.path.join(pcie_rtl_dir, "dma_if_pcie_rd.v"), + os.path.join(pcie_rtl_dir, "dma_if_pcie_wr.v"), + os.path.join(pcie_rtl_dir, "dma_psdpram.v"), + os.path.join(pcie_rtl_dir, "arbiter.v"), + os.path.join(pcie_rtl_dir, "priority_encoder.v"), + os.path.join(pcie_rtl_dir, "pulse_merge.v"), + ] + + parameters = {} + + parameters['AXIS_PCIE_DATA_WIDTH'] = 512 + parameters['AXIS_PCIE_KEEP_WIDTH'] = parameters['AXIS_PCIE_DATA_WIDTH'] // 32 + parameters['AXIS_PCIE_RQ_USER_WIDTH'] = 62 if parameters['AXIS_PCIE_DATA_WIDTH'] < 512 else 137 + parameters['AXIS_PCIE_RC_USER_WIDTH'] = 75 if parameters['AXIS_PCIE_DATA_WIDTH'] < 512 else 161 + parameters['AXIS_PCIE_CQ_USER_WIDTH'] = 88 if parameters['AXIS_PCIE_DATA_WIDTH'] < 512 else 183 + parameters['AXIS_PCIE_CC_USER_WIDTH'] = 33 if parameters['AXIS_PCIE_DATA_WIDTH'] < 512 else 81 + parameters['RQ_SEQ_NUM_WIDTH'] = 6 + parameters['RQ_SEQ_NUM_ENABLE'] = 1 + parameters['PCIE_TAG_COUNT'] = 64 + parameters['BAR0_APERTURE'] = 24 + parameters['BAR2_APERTURE'] = 24 + + 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, + ) diff --git a/fpga/lib/pcie/example/AU50/fpga/README.md b/fpga/lib/pcie/example/AU50/fpga/README.md new file mode 100644 index 000000000..62607c16a --- /dev/null +++ b/fpga/lib/pcie/example/AU50/fpga/README.md @@ -0,0 +1,19 @@ +# Verilog PCIe Alveo U50 Example Design + +## Introduction + +This example design targets the Xilinx Alveo U50 FPGA board. + +The design implements the PCIe AXI lite master module, the PCIe AXI master module, and the PCIe DMA module. A very simple Linux driver is included to test the FPGA design. + +* FPGA: xcu50-fsvh2104-2-e + +## How to build + +Run `make` to build. Ensure that the Xilinx Vivado components are in PATH. + +Run `make` to build the driver. Ensure the headers for the running kernel are installed, otherwise the driver cannot be compiled. + +## How to test + +Run `make program` to program the Alveo U50 board with Vivado. Then load the driver with `insmod example.ko`. Check dmesg for the output. diff --git a/fpga/lib/pcie/example/AU50/fpga/common/vivado.mk b/fpga/lib/pcie/example/AU50/fpga/common/vivado.mk new file mode 100644 index 000000000..d47a43947 --- /dev/null +++ b/fpga/lib/pcie/example/AU50/fpga/common/vivado.mk @@ -0,0 +1,126 @@ +################################################################### +# +# 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) + +SYN_FILES_REL = $(patsubst %, ../%, $(filter-out /% ./%,$(SYN_FILES))) $(filter /% ./%,$(SYN_FILES)) +INC_FILES_REL = $(patsubst %, ../%, $(filter-out /% ./%,$(INC_FILES))) $(filter /% ./%,$(INC_FILES)) +XCI_FILES_REL = $(patsubst %, ../%, $(filter-out /% ./%,$(XCI_FILES))) $(filter /% ./%,$(XCI_FILES)) +IP_TCL_FILES_REL = $(patsubst %, ../%, $(filter-out /% ./%,$(IP_TCL_FILES))) $(filter /% ./%,$(IP_TCL_FILES)) +CONFIG_TCL_FILES_REL = $(patsubst %, ../%, $(filter-out /% ./%,$(CONFIG_TCL_FILES))) $(filter /% ./%,$(CONFIG_TCL_FILES)) + +ifdef XDC_FILES + XDC_FILES_REL = $(patsubst %, ../%, $(filter-out /% ./%,$(XDC_FILES))) $(filter /% ./%,$(XDC_FILES)) +else + XDC_FILES_REL = $(FPGA_TOP).xdc +endif + +################################################################### +# Main Targets +# +# all: build everything +# clean: remove output files and project files +################################################################### + +all: fpga + +fpga: $(FPGA_TOP).bit + +vivado: $(FPGA_TOP).xpr + vivado $(FPGA_TOP).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 program.tcl generate_mcs.tcl *.mcs *.prm flash.tcl + +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) $(FPGA_TOP)" > $@ + echo "add_files -fileset sources_1 defines.v $(SYN_FILES_REL)" >> $@ + 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) + echo "open_project -quiet $(FPGA_TOP).xpr" > $@ + for x in $(CONFIG_TCL_FILES_REL); do echo "source $$x" >> $@; done + +$(FPGA_TOP).xpr: create_project.tcl update_config.tcl + vivado -nojournal -nolog -mode batch $(foreach x,$?,-source $x) + +# synthesis run +%.runs/synth_1/%.dcp: %.xpr $(SYN_FILES_REL) $(INC_FILES_REL) $(XDC_FILES_REL) $(CONFIG_TCL_FILES_REL) + echo "open_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 +%.runs/impl_1/%_routed.dcp: %.runs/synth_1/%.dcp + echo "open_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 + vivado -nojournal -nolog -mode batch -source run_impl.tcl + +# bit file +%.bit: %.runs/impl_1/%_routed.dcp + echo "open_project $*.xpr" > generate_bit.tcl + echo "open_run impl_1" >> generate_bit.tcl + echo "write_bitstream -force $*.bit" >> generate_bit.tcl + vivado -nojournal -nolog -mode batch -source generate_bit.tcl + mkdir -p rev + EXT=bit; COUNT=100; \ + while [ -e rev/$*_rev$$COUNT.$$EXT ]; \ + do COUNT=$$((COUNT+1)); done; \ + cp $@ rev/$*_rev$$COUNT.$$EXT; \ + echo "Output: rev/$*_rev$$COUNT.$$EXT"; diff --git a/fpga/lib/pcie/example/AU50/fpga/driver b/fpga/lib/pcie/example/AU50/fpga/driver new file mode 120000 index 000000000..4a54c76b5 --- /dev/null +++ b/fpga/lib/pcie/example/AU50/fpga/driver @@ -0,0 +1 @@ +../../common/driver/example/ \ No newline at end of file diff --git a/fpga/lib/pcie/example/AU50/fpga/fpga.xdc b/fpga/lib/pcie/example/AU50/fpga/fpga.xdc new file mode 100644 index 000000000..c17079056 --- /dev/null +++ b/fpga/lib/pcie/example/AU50/fpga/fpga.xdc @@ -0,0 +1,203 @@ +# XDC constraints for the Xilinx Alveo U50 board +# part: xcu50-fsvh2104-2-e + +# General configuration +set_property CFGBVS GND [current_design] +set_property CONFIG_VOLTAGE 1.8 [current_design] +set_property BITSTREAM.CONFIG.CONFIGFALLBACK ENABLE [current_design] +set_property BITSTREAM.GENERAL.COMPRESS TRUE [current_design] +set_property CONFIG_MODE SPIx4 [current_design] +set_property BITSTREAM.CONFIG.SPI_BUSWIDTH 4 [current_design] +set_property BITSTREAM.CONFIG.CONFIGRATE 85.0 [current_design] +set_property BITSTREAM.CONFIG.EXTMASTERCCLK_EN DISABLE [current_design] +set_property BITSTREAM.CONFIG.SPI_FALL_EDGE YES [current_design] +set_property BITSTREAM.CONFIG.UNUSEDPIN PULLUP [current_design] +set_property BITSTREAM.CONFIG.SPI_32BIT_ADDR YES [current_design] + +set_operating_conditions -design_power_budget 63 + +# System clocks +# 100 MHz +#set_property -dict {LOC G17 IOSTANDARD LVDS} [get_ports clk_100mhz_0_p] +#set_property -dict {LOC G16 IOSTANDARD LVDS} [get_ports clk_100mhz_0_n] +#create_clock -period 10 -name clk_100mhz_0 [get_ports clk_100mhz_0_p] + +# 100 MHz +#set_property -dict {LOC BB18 IOSTANDARD LVDS} [get_ports clk_100mhz_1_p] +#set_property -dict {LOC BC18 IOSTANDARD LVDS} [get_ports clk_100mhz_1_n] +#create_clock -period 10 -name clk_100mhz_1 [get_ports clk_100mhz_1_p] + +# LEDs +set_property -dict {LOC E18 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports qsfp_led_act] +set_property -dict {LOC E16 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports qsfp_led_stat_g] +set_property -dict {LOC F17 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports qsfp_led_stat_y] + +set_false_path -to [get_ports {qsfp_led_act qsfp_led_stat_g qsfp_led_stat_y}] +set_output_delay 0 [get_ports {qsfp_led_act qsfp_led_stat_g qsfp_led_stat_y}] + +# UART +#set_property -dict {LOC BE26 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports usb_uart0_txd] +#set_property -dict {LOC BF26 IOSTANDARD LVCMOS18} [get_ports usb_uart0_rxd] +#set_property -dict {LOC A17 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports usb_uart1_txd] +#set_property -dict {LOC B15 IOSTANDARD LVCMOS18} [get_ports usb_uart1_rxd] +#set_property -dict {LOC A19 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports usb_uart2_txd] +#set_property -dict {LOC A18 IOSTANDARD LVCMOS18} [get_ports usb_uart2_rxd] + +#set_false_path -to [get_ports {usb_uart0_txd usb_uart1_txd usb_uart2_txd}] +#set_output_delay 0 [get_ports {usb_uart0_txd usb_uart1_txd usb_uart2_txd}] +#set_false_path -from [get_ports {usb_uart0_rxd usb_uart1_rxd usb_uart2_rxd}] +#set_input_delay 0 [get_ports {usb_uart0_rxd usb_uart1_rxd usb_uart2_rxd}] + +# BMC +#set_property -dict {LOC C16 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 4} [get_ports {msp_gpio[0]}] +#set_property -dict {LOC C17 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 4} [get_ports {msp_gpio[1]}] +#set_property -dict {LOC BB25 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 4} [get_ports {msp_uart_txd}] +#set_property -dict {LOC BB26 IOSTANDARD LVCMOS18} [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}] + +# HBM overtemp +set_property -dict {LOC J18 IOSTANDARD LVCMOS18} [get_ports hbm_cattrip] + +set_false_path -to [get_ports {hbm_cattrip}] +set_output_delay 0 [get_ports {hbm_cattrip}] + +# SI5394 (SI5394B-A10605-GM) +# I2C address 0x68 +# IN0: 161.1328125 MHz from qsfp_recclk +# OUT0: 161.1328125 MHz to qsfp_mgt_refclk_0 +# OUT2: 322.265625 MHz to qsfp_mgt_refclk_1 +# OUT3: 100 MHz to clk_100mhz_0, clk_100mhz_1, pcie_refclk_2, pcie_refclk_3 +#set_property -dict {LOC F20 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports si5394_rst_b] +#set_property -dict {LOC H18 IOSTANDARD LVCMOS18 PULLUP true} [get_ports si5394_int_b] +#set_property -dict {LOC G19 IOSTANDARD LVCMOS18 PULLUP true} [get_ports si5394_lol_b] +#set_property -dict {LOC H19 IOSTANDARD LVCMOS18 PULLUP true} [get_ports si5394_los_b] +#set_property -dict {LOC J16 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8 PULLUP true} [get_ports si5394_i2c_sda] +#set_property -dict {LOC L19 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8 PULLUP true} [get_ports si5394_i2c_scl] + +#set_false_path -to [get_ports {si5394_rst_b}] +#set_output_delay 0 [get_ports {si5394_rst_b}] +#set_false_path -from [get_ports {si5394_int_b si5394_lol_b si5394_los_b}] +#set_input_delay 0 [get_ports {si5394_int_b si5394_lol_b si5394_los_b}] + +#set_false_path -to [get_ports {si5394_i2c_sda si5394_i2c_scl}] +#set_output_delay 0 [get_ports {si5394_i2c_sda si5394_i2c_scl}] +#set_false_path -from [get_ports {si5394_i2c_sda si5394_i2c_scl}] +#set_input_delay 0 [get_ports {si5394_i2c_sda si5394_i2c_scl}] + +# QSFP28 Interfaces +#set_property -dict {LOC J45 } [get_ports qsfp_rx1_p] ;# MGTYRXP0_131 GTYE4_CHANNEL_X0Y28 / GTYE4_COMMON_X0Y7 +#set_property -dict {LOC J46 } [get_ports qsfp_rx1_n] ;# MGTYRXN0_131 GTYE4_CHANNEL_X0Y28 / GTYE4_COMMON_X0Y7 +#set_property -dict {LOC D42 } [get_ports qsfp_tx1_p] ;# MGTYTXP0_131 GTYE4_CHANNEL_X0Y28 / GTYE4_COMMON_X0Y7 +#set_property -dict {LOC D43 } [get_ports qsfp_tx1_n] ;# MGTYTXN0_131 GTYE4_CHANNEL_X0Y28 / GTYE4_COMMON_X0Y7 +#set_property -dict {LOC G45 } [get_ports qsfp_rx2_p] ;# MGTYRXP1_131 GTYE4_CHANNEL_X0Y29 / GTYE4_COMMON_X0Y7 +#set_property -dict {LOC G46 } [get_ports qsfp_rx2_n] ;# MGTYRXN1_131 GTYE4_CHANNEL_X0Y29 / GTYE4_COMMON_X0Y7 +#set_property -dict {LOC C40 } [get_ports qsfp_tx2_p] ;# MGTYTXP1_131 GTYE4_CHANNEL_X0Y29 / GTYE4_COMMON_X0Y7 +#set_property -dict {LOC C41 } [get_ports qsfp_tx2_n] ;# MGTYTXN1_131 GTYE4_CHANNEL_X0Y29 / GTYE4_COMMON_X0Y7 +#set_property -dict {LOC F43 } [get_ports qsfp_rx3_p] ;# MGTYRXP2_131 GTYE4_CHANNEL_X0Y30 / GTYE4_COMMON_X0Y7 +#set_property -dict {LOC F44 } [get_ports qsfp_rx3_n] ;# MGTYRXN2_131 GTYE4_CHANNEL_X0Y30 / GTYE4_COMMON_X0Y7 +#set_property -dict {LOC B42 } [get_ports qsfp_tx3_p] ;# MGTYTXP2_131 GTYE4_CHANNEL_X0Y30 / GTYE4_COMMON_X0Y7 +#set_property -dict {LOC B43 } [get_ports qsfp_tx3_n] ;# MGTYTXN2_131 GTYE4_CHANNEL_X0Y30 / GTYE4_COMMON_X0Y7 +#set_property -dict {LOC E45 } [get_ports qsfp_rx4_p] ;# MGTYRXP3_131 GTYE4_CHANNEL_X0Y31 / GTYE4_COMMON_X0Y7 +#set_property -dict {LOC E46 } [get_ports qsfp_rx4_n] ;# MGTYRXN3_131 GTYE4_CHANNEL_X0Y31 / GTYE4_COMMON_X0Y7 +#set_property -dict {LOC A40 } [get_ports qsfp_tx4_p] ;# MGTYTXP3_131 GTYE4_CHANNEL_X0Y31 / GTYE4_COMMON_X0Y7 +#set_property -dict {LOC A41 } [get_ports qsfp_tx4_n] ;# MGTYTXN3_131 GTYE4_CHANNEL_X0Y31 / GTYE4_COMMON_X0Y7 +#set_property -dict {LOC N36 } [get_ports qsfp_mgt_refclk_0_p] ;# MGTREFCLK0P_131 from SI5394 OUT0 +#set_property -dict {LOC N37 } [get_ports qsfp_mgt_refclk_0_n] ;# MGTREFCLK0N_131 from SI5394 OUT0 +#set_property -dict {LOC M38 } [get_ports qsfp_mgt_refclk_1_p] ;# MGTREFCLK1P_131 from SI5394 OUT2 +#set_property -dict {LOC M39 } [get_ports qsfp_mgt_refclk_1_n] ;# MGTREFCLK1N_131 from SI5394 OUT2 +#set_property -dict {LOC F19 IOSTANDARD LVDS} [get_ports qsfp_recclk_p] ;# to SI5394 IN0 +#set_property -dict {LOC F18 IOSTANDARD LVDS} [get_ports qsfp_recclk_n] ;# to SI5394 IN0 + +# 161.1328125 MHz MGT reference clock (SI5394 OUT0) +#create_clock -period 6.206 -name qsfp_mgt_refclk_0 [get_ports qsfp_mgt_refclk_0_p] + +# 322.265625 MHz MGT reference clock (SI5394 OUT2) +#create_clock -period 3.103 -name qsfp_mgt_refclk_1 [get_ports qsfp_mgt_refclk_1_p] + +# PCIe Interface +set_property -dict {LOC AL2 } [get_ports {pcie_rx_p[0]}] ;# MGTYRXP3_227 GTYE4_CHANNEL_X1Y15 / GTYE4_COMMON_X1Y3 +set_property -dict {LOC AL1 } [get_ports {pcie_rx_n[0]}] ;# MGTYRXN3_227 GTYE4_CHANNEL_X1Y15 / GTYE4_COMMON_X1Y3 +set_property -dict {LOC Y5 } [get_ports {pcie_tx_p[0]}] ;# MGTYTXP3_227 GTYE4_CHANNEL_X1Y15 / GTYE4_COMMON_X1Y3 +set_property -dict {LOC Y4 } [get_ports {pcie_tx_n[0]}] ;# MGTYTXN3_227 GTYE4_CHANNEL_X1Y15 / GTYE4_COMMON_X1Y3 +set_property -dict {LOC AM4 } [get_ports {pcie_rx_p[1]}] ;# MGTYRXP2_227 GTYE4_CHANNEL_X1Y14 / GTYE4_COMMON_X1Y3 +set_property -dict {LOC AM3 } [get_ports {pcie_rx_n[1]}] ;# MGTYRXN2_227 GTYE4_CHANNEL_X1Y14 / GTYE4_COMMON_X1Y3 +set_property -dict {LOC AA7 } [get_ports {pcie_tx_p[1]}] ;# MGTYTXP2_227 GTYE4_CHANNEL_X1Y14 / GTYE4_COMMON_X1Y3 +set_property -dict {LOC AA6 } [get_ports {pcie_tx_n[1]}] ;# MGTYTXN2_227 GTYE4_CHANNEL_X1Y14 / GTYE4_COMMON_X1Y3 +set_property -dict {LOC AK4 } [get_ports {pcie_rx_p[2]}] ;# MGTYRXP1_227 GTYE4_CHANNEL_X1Y13 / GTYE4_COMMON_X1Y3 +set_property -dict {LOC AK3 } [get_ports {pcie_rx_n[2]}] ;# MGTYRXN1_227 GTYE4_CHANNEL_X1Y13 / GTYE4_COMMON_X1Y3 +set_property -dict {LOC AB5 } [get_ports {pcie_tx_p[2]}] ;# MGTYTXP1_227 GTYE4_CHANNEL_X1Y13 / GTYE4_COMMON_X1Y3 +set_property -dict {LOC AB4 } [get_ports {pcie_tx_n[2]}] ;# MGTYTXN1_227 GTYE4_CHANNEL_X1Y13 / GTYE4_COMMON_X1Y3 +set_property -dict {LOC AN2 } [get_ports {pcie_rx_p[3]}] ;# MGTYRXP0_227 GTYE4_CHANNEL_X1Y12 / GTYE4_COMMON_X1Y3 +set_property -dict {LOC AN1 } [get_ports {pcie_rx_n[3]}] ;# MGTYRXN0_227 GTYE4_CHANNEL_X1Y12 / GTYE4_COMMON_X1Y3 +set_property -dict {LOC AC7 } [get_ports {pcie_tx_p[3]}] ;# MGTYTXP0_227 GTYE4_CHANNEL_X1Y12 / GTYE4_COMMON_X1Y3 +set_property -dict {LOC AC6 } [get_ports {pcie_tx_n[3]}] ;# MGTYTXN0_227 GTYE4_CHANNEL_X1Y12 / GTYE4_COMMON_X1Y3 +set_property -dict {LOC AP4 } [get_ports {pcie_rx_p[4]}] ;# MGTYRXP3_226 GTYE4_CHANNEL_X1Y11 / GTYE4_COMMON_X1Y2 +set_property -dict {LOC AP3 } [get_ports {pcie_rx_n[4]}] ;# MGTYRXN3_226 GTYE4_CHANNEL_X1Y11 / GTYE4_COMMON_X1Y2 +set_property -dict {LOC AD5 } [get_ports {pcie_tx_p[4]}] ;# MGTYTXP3_226 GTYE4_CHANNEL_X1Y11 / GTYE4_COMMON_X1Y2 +set_property -dict {LOC AD4 } [get_ports {pcie_tx_n[4]}] ;# MGTYTXN3_226 GTYE4_CHANNEL_X1Y11 / GTYE4_COMMON_X1Y2 +set_property -dict {LOC AR2 } [get_ports {pcie_rx_p[5]}] ;# MGTYRXP2_226 GTYE4_CHANNEL_X1Y10 / GTYE4_COMMON_X1Y2 +set_property -dict {LOC AR1 } [get_ports {pcie_rx_n[5]}] ;# MGTYRXN2_226 GTYE4_CHANNEL_X1Y10 / GTYE4_COMMON_X1Y2 +set_property -dict {LOC AF5 } [get_ports {pcie_tx_p[5]}] ;# MGTYTXP2_226 GTYE4_CHANNEL_X1Y10 / GTYE4_COMMON_X1Y2 +set_property -dict {LOC AF4 } [get_ports {pcie_tx_n[5]}] ;# MGTYTXN2_226 GTYE4_CHANNEL_X1Y10 / GTYE4_COMMON_X1Y2 +set_property -dict {LOC AT4 } [get_ports {pcie_rx_p[6]}] ;# MGTYRXP1_226 GTYE4_CHANNEL_X1Y9 / GTYE4_COMMON_X1Y2 +set_property -dict {LOC AT3 } [get_ports {pcie_rx_n[6]}] ;# MGTYRXN1_226 GTYE4_CHANNEL_X1Y9 / GTYE4_COMMON_X1Y2 +set_property -dict {LOC AE7 } [get_ports {pcie_tx_p[6]}] ;# MGTYTXP1_226 GTYE4_CHANNEL_X1Y9 / GTYE4_COMMON_X1Y2 +set_property -dict {LOC AE6 } [get_ports {pcie_tx_n[6]}] ;# MGTYTXN1_226 GTYE4_CHANNEL_X1Y9 / GTYE4_COMMON_X1Y2 +set_property -dict {LOC AU2 } [get_ports {pcie_rx_p[7]}] ;# MGTYRXP0_226 GTYE4_CHANNEL_X1Y8 / GTYE4_COMMON_X1Y2 +set_property -dict {LOC AU1 } [get_ports {pcie_rx_n[7]}] ;# MGTYRXN0_226 GTYE4_CHANNEL_X1Y8 / GTYE4_COMMON_X1Y2 +set_property -dict {LOC AH5 } [get_ports {pcie_tx_p[7]}] ;# MGTYTXP0_226 GTYE4_CHANNEL_X1Y8 / GTYE4_COMMON_X1Y2 +set_property -dict {LOC AH4 } [get_ports {pcie_tx_n[7]}] ;# MGTYTXN0_226 GTYE4_CHANNEL_X1Y8 / GTYE4_COMMON_X1Y2 +set_property -dict {LOC AV4 } [get_ports {pcie_rx_p[8]}] ;# MGTYRXP3_225 GTYE4_CHANNEL_X1Y7 / GTYE4_COMMON_X1Y1 +set_property -dict {LOC AV3 } [get_ports {pcie_rx_n[8]}] ;# MGTYRXN3_225 GTYE4_CHANNEL_X1Y7 / GTYE4_COMMON_X1Y1 +set_property -dict {LOC AG7 } [get_ports {pcie_tx_p[8]}] ;# MGTYTXP3_225 GTYE4_CHANNEL_X1Y7 / GTYE4_COMMON_X1Y1 +set_property -dict {LOC AG6 } [get_ports {pcie_tx_n[8]}] ;# MGTYTXN3_225 GTYE4_CHANNEL_X1Y7 / GTYE4_COMMON_X1Y1 +set_property -dict {LOC AW2 } [get_ports {pcie_rx_p[9]}] ;# MGTYRXP2_225 GTYE4_CHANNEL_X1Y6 / GTYE4_COMMON_X1Y1 +set_property -dict {LOC AW1 } [get_ports {pcie_rx_n[9]}] ;# MGTYRXN2_225 GTYE4_CHANNEL_X1Y6 / GTYE4_COMMON_X1Y1 +set_property -dict {LOC AJ7 } [get_ports {pcie_tx_p[9]}] ;# MGTYTXP2_225 GTYE4_CHANNEL_X1Y6 / GTYE4_COMMON_X1Y1 +set_property -dict {LOC AJ6 } [get_ports {pcie_tx_n[9]}] ;# MGTYTXN2_225 GTYE4_CHANNEL_X1Y6 / GTYE4_COMMON_X1Y1 +set_property -dict {LOC BA2 } [get_ports {pcie_rx_p[10]}] ;# MGTYRXP1_225 GTYE4_CHANNEL_X1Y5 / GTYE4_COMMON_X1Y1 +set_property -dict {LOC BA1 } [get_ports {pcie_rx_n[10]}] ;# MGTYRXN1_225 GTYE4_CHANNEL_X1Y5 / GTYE4_COMMON_X1Y1 +set_property -dict {LOC AL7 } [get_ports {pcie_tx_p[10]}] ;# MGTYTXP1_225 GTYE4_CHANNEL_X1Y5 / GTYE4_COMMON_X1Y1 +set_property -dict {LOC AL6 } [get_ports {pcie_tx_n[10]}] ;# MGTYTXN1_225 GTYE4_CHANNEL_X1Y5 / GTYE4_COMMON_X1Y1 +set_property -dict {LOC BC2 } [get_ports {pcie_rx_p[11]}] ;# MGTYRXP0_225 GTYE4_CHANNEL_X1Y4 / GTYE4_COMMON_X1Y1 +set_property -dict {LOC BC1 } [get_ports {pcie_rx_n[11]}] ;# MGTYRXN0_225 GTYE4_CHANNEL_X1Y4 / GTYE4_COMMON_X1Y1 +set_property -dict {LOC AM9 } [get_ports {pcie_tx_p[11]}] ;# MGTYTXP0_225 GTYE4_CHANNEL_X1Y4 / GTYE4_COMMON_X1Y1 +set_property -dict {LOC AM8 } [get_ports {pcie_tx_n[11]}] ;# MGTYTXN0_225 GTYE4_CHANNEL_X1Y4 / GTYE4_COMMON_X1Y1 +set_property -dict {LOC AY4 } [get_ports {pcie_rx_p[12]}] ;# MGTYRXP3_224 GTYE4_CHANNEL_X1Y3 / GTYE4_COMMON_X1Y0 +set_property -dict {LOC AY3 } [get_ports {pcie_rx_n[12]}] ;# MGTYRXN3_224 GTYE4_CHANNEL_X1Y3 / GTYE4_COMMON_X1Y0 +set_property -dict {LOC AN7 } [get_ports {pcie_tx_p[12]}] ;# MGTYTXP3_224 GTYE4_CHANNEL_X1Y3 / GTYE4_COMMON_X1Y0 +set_property -dict {LOC AN6 } [get_ports {pcie_tx_n[12]}] ;# MGTYTXN3_224 GTYE4_CHANNEL_X1Y3 / GTYE4_COMMON_X1Y0 +set_property -dict {LOC BB4 } [get_ports {pcie_rx_p[13]}] ;# MGTYRXP2_224 GTYE4_CHANNEL_X1Y2 / GTYE4_COMMON_X1Y0 +set_property -dict {LOC BB3 } [get_ports {pcie_rx_n[13]}] ;# MGTYRXN2_224 GTYE4_CHANNEL_X1Y2 / GTYE4_COMMON_X1Y0 +set_property -dict {LOC AP9 } [get_ports {pcie_tx_p[13]}] ;# MGTYTXP2_224 GTYE4_CHANNEL_X1Y2 / GTYE4_COMMON_X1Y0 +set_property -dict {LOC AP8 } [get_ports {pcie_tx_n[13]}] ;# MGTYTXN2_224 GTYE4_CHANNEL_X1Y2 / GTYE4_COMMON_X1Y0 +set_property -dict {LOC BD4 } [get_ports {pcie_rx_p[14]}] ;# MGTYRXP1_224 GTYE4_CHANNEL_X1Y1 / GTYE4_COMMON_X1Y0 +set_property -dict {LOC BD3 } [get_ports {pcie_rx_n[14]}] ;# MGTYRXN1_224 GTYE4_CHANNEL_X1Y1 / GTYE4_COMMON_X1Y0 +set_property -dict {LOC AR7 } [get_ports {pcie_tx_p[14]}] ;# MGTYTXP1_224 GTYE4_CHANNEL_X1Y1 / GTYE4_COMMON_X1Y0 +set_property -dict {LOC AR6 } [get_ports {pcie_tx_n[14]}] ;# MGTYTXN1_224 GTYE4_CHANNEL_X1Y1 / GTYE4_COMMON_X1Y0 +set_property -dict {LOC BE6 } [get_ports {pcie_rx_p[15]}] ;# MGTYRXP0_224 GTYE4_CHANNEL_X1Y0 / GTYE4_COMMON_X1Y0 +set_property -dict {LOC BE5 } [get_ports {pcie_rx_n[15]}] ;# MGTYRXN0_224 GTYE4_CHANNEL_X1Y0 / GTYE4_COMMON_X1Y0 +set_property -dict {LOC AT9 } [get_ports {pcie_tx_p[15]}] ;# MGTYTXP0_224 GTYE4_CHANNEL_X1Y0 / GTYE4_COMMON_X1Y0 +set_property -dict {LOC AT8 } [get_ports {pcie_tx_n[15]}] ;# MGTYTXN0_224 GTYE4_CHANNEL_X1Y0 / GTYE4_COMMON_X1Y0 +#set_property -dict {LOC AB9 } [get_ports pcie_refclk_0_p] ;# MGTREFCLK0P_227 (for x8 bifurcated lanes 0-7) +#set_property -dict {LOC AB8 } [get_ports pcie_refclk_0_n] ;# MGTREFCLK0N_227 (for x8 bifurcated lanes 0-7) +#set_property -dict {LOC AA11} [get_ports pcie_refclk_2_p] ;# MGTREFCLK1P_227 (for async x8 bifurcated lanes 0-7) +#set_property -dict {LOC AA10} [get_ports pcie_refclk_2_n] ;# MGTREFCLK1N_227 (for async x8 bifurcated lanes 0-7) +set_property -dict {LOC AF9 } [get_ports pcie_refclk_1_p] ;# MGTREFCLK0P_225 (for x16 or x8 bifurcated lanes 8-16) +set_property -dict {LOC AF8 } [get_ports pcie_refclk_1_n] ;# MGTREFCLK0N_225 (for x16 or x8 bifurcated lanes 8-16) +#set_property -dict {LOC AE11} [get_ports pcie_refclk_3_p] ;# MGTREFCLK1P_225 (for async x16 or x8 bifurcated lanes 8-16) +#set_property -dict {LOC AE10} [get_ports pcie_refclk_3_n] ;# MGTREFCLK1N_225 (for async x16 or x8 bifurcated lanes 8-16) +set_property -dict {LOC AW27 IOSTANDARD LVCMOS18 PULLUP true} [get_ports pcie_reset_n] + +# 100 MHz MGT reference clock +#create_clock -period 10 -name pcie_mgt_refclk_0 [get_ports pcie_refclk_0_p] +create_clock -period 10 -name pcie_mgt_refclk_1 [get_ports pcie_refclk_1_p] +#create_clock -period 10 -name pcie_mgt_refclk_2 [get_ports pcie_refclk_2_p] +#create_clock -period 10 -name pcie_mgt_refclk_3 [get_ports pcie_refclk_3_p] + +set_false_path -from [get_ports {pcie_reset_n}] +set_input_delay 0 [get_ports {pcie_reset_n}] diff --git a/fpga/lib/pcie/example/AU50/fpga/fpga/Makefile b/fpga/lib/pcie/example/AU50/fpga/fpga/Makefile new file mode 100644 index 000000000..4534c3289 --- /dev/null +++ b/fpga/lib/pcie/example/AU50/fpga/fpga/Makefile @@ -0,0 +1,93 @@ + +# FPGA settings +FPGA_PART = xcu50-fsvh2104-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/sync_reset.v +SYN_FILES += rtl/sync_signal.v +SYN_FILES += rtl/common/example_core_pcie_us.v +SYN_FILES += rtl/common/example_core_pcie.v +SYN_FILES += rtl/common/example_core.v +SYN_FILES += rtl/common/axi_ram.v +SYN_FILES += lib/pcie/rtl/pcie_us_if.v +SYN_FILES += lib/pcie/rtl/pcie_us_if_rc.v +SYN_FILES += lib/pcie/rtl/pcie_us_if_rq.v +SYN_FILES += lib/pcie/rtl/pcie_us_if_cq.v +SYN_FILES += lib/pcie/rtl/pcie_us_if_cc.v +SYN_FILES += lib/pcie/rtl/pcie_us_cfg.v +SYN_FILES += lib/pcie/rtl/pcie_us_msi.v +SYN_FILES += lib/pcie/rtl/pcie_axil_master.v +SYN_FILES += lib/pcie/rtl/pcie_axi_master.v +SYN_FILES += lib/pcie/rtl/pcie_axi_master_rd.v +SYN_FILES += lib/pcie/rtl/pcie_axi_master_wr.v +SYN_FILES += lib/pcie/rtl/pcie_tlp_demux_bar.v +SYN_FILES += lib/pcie/rtl/pcie_tlp_demux.v +SYN_FILES += lib/pcie/rtl/pcie_tlp_mux.v +SYN_FILES += lib/pcie/rtl/dma_if_pcie.v +SYN_FILES += lib/pcie/rtl/dma_if_pcie_rd.v +SYN_FILES += lib/pcie/rtl/dma_if_pcie_wr.v +SYN_FILES += lib/pcie/rtl/dma_psdpram.v +SYN_FILES += lib/pcie/rtl/arbiter.v +SYN_FILES += lib/pcie/rtl/priority_encoder.v +SYN_FILES += lib/pcie/rtl/pulse_merge.v + +# XDC files +XDC_FILES = fpga.xdc + +# IP +IP_TCL_FILES = ip/pcie4c_uscale_plus_0.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 + +%.mcs %.prm: %.bit + echo "write_cfgmem -force -format mcs -size 128 -interface SPIx4 -loadbit {up 0x01002000 $*.bit} -checksum -file $*.mcs" > generate_mcs.tcl + echo "exit" >> generate_mcs.tcl + vivado -nojournal -nolog -mode batch -source generate_mcs.tcl + mkdir -p rev + COUNT=100; \ + while [ -e rev/$*_rev$$COUNT.bit ]; \ + do COUNT=$$((COUNT+1)); done; \ + COUNT=$$((COUNT-1)); \ + for x in .mcs .prm; \ + do cp $*$$x rev/$*_rev$$COUNT$$x; \ + echo "Output: rev/$*_rev$$COUNT$$x"; done; + +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 + diff --git a/fpga/lib/pcie/example/AU50/fpga/ip/pcie4c_uscale_plus_0.tcl b/fpga/lib/pcie/example/AU50/fpga/ip/pcie4c_uscale_plus_0.tcl new file mode 100644 index 000000000..fba62239f --- /dev/null +++ b/fpga/lib/pcie/example/AU50/fpga/ip/pcie4c_uscale_plus_0.tcl @@ -0,0 +1,28 @@ + +create_ip -name pcie4c_uscale_plus -vendor xilinx.com -library ip -module_name pcie4c_uscale_plus_0 + +set_property -dict [list \ + CONFIG.PL_LINK_CAP_MAX_LINK_SPEED {8.0_GT/s} \ + CONFIG.PL_LINK_CAP_MAX_LINK_WIDTH {X16} \ + CONFIG.AXISTEN_IF_EXT_512_RQ_STRADDLE {false} \ + CONFIG.axisten_if_enable_client_tag {true} \ + CONFIG.axisten_if_width {512_bit} \ + CONFIG.axisten_freq {250} \ + CONFIG.PF0_CLASS_CODE {058000} \ + CONFIG.PF0_DEVICE_ID {0001} \ + CONFIG.PF0_MSI_CAP_MULTIMSGCAP {32_vectors} \ + CONFIG.PF0_SUBSYSTEM_ID {9032} \ + CONFIG.PF0_SUBSYSTEM_VENDOR_ID {10ee} \ + CONFIG.pf0_bar0_64bit {true} \ + CONFIG.pf0_bar0_prefetchable {true} \ + CONFIG.pf0_bar0_scale {Megabytes} \ + CONFIG.pf0_bar0_size {16} \ + CONFIG.pf0_bar2_64bit {true} \ + CONFIG.pf0_bar2_prefetchable {true} \ + CONFIG.pf0_bar2_enabled {true} \ + CONFIG.pf0_bar2_type {Memory} \ + CONFIG.pf0_bar2_scale {Megabytes} \ + CONFIG.pf0_bar2_size {16} \ + CONFIG.vendor_id {1234} \ + CONFIG.en_msi_per_vec_masking {true} \ +] [get_ips pcie4c_uscale_plus_0] diff --git a/fpga/lib/pcie/example/AU50/fpga/lib/pcie b/fpga/lib/pcie/example/AU50/fpga/lib/pcie new file mode 120000 index 000000000..11a54ed36 --- /dev/null +++ b/fpga/lib/pcie/example/AU50/fpga/lib/pcie @@ -0,0 +1 @@ +../../../../ \ No newline at end of file diff --git a/fpga/lib/pcie/example/AU50/fpga/rtl/common b/fpga/lib/pcie/example/AU50/fpga/rtl/common new file mode 120000 index 000000000..e60fada70 --- /dev/null +++ b/fpga/lib/pcie/example/AU50/fpga/rtl/common @@ -0,0 +1 @@ +../../../common/rtl/ \ No newline at end of file diff --git a/fpga/lib/pcie/example/AU50/fpga/rtl/fpga.v b/fpga/lib/pcie/example/AU50/fpga/rtl/fpga.v new file mode 100644 index 000000000..48caa3395 --- /dev/null +++ b/fpga/lib/pcie/example/AU50/fpga/rtl/fpga.v @@ -0,0 +1,454 @@ +/* + +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. + +*/ + +// Language: Verilog 2001 + +`resetall +`timescale 1ns / 1ps +`default_nettype none + +/* + * FPGA top-level module + */ +module fpga ( + /* + * GPIO + */ + output wire qsfp_led_act, + output wire qsfp_led_stat_g, + output wire qsfp_led_stat_y, + output wire hbm_cattrip, + + /* + * PCI express + */ + input wire [15:0] pcie_rx_p, + input wire [15:0] pcie_rx_n, + output wire [15:0] pcie_tx_p, + output wire [15:0] pcie_tx_n, + input wire pcie_refclk_1_p, + input wire pcie_refclk_1_n, + input wire pcie_reset_n +); + +parameter AXIS_PCIE_DATA_WIDTH = 512; +parameter AXIS_PCIE_KEEP_WIDTH = (AXIS_PCIE_DATA_WIDTH/32); +parameter AXIS_PCIE_RC_USER_WIDTH = AXIS_PCIE_DATA_WIDTH < 512 ? 75 : 161; +parameter AXIS_PCIE_RQ_USER_WIDTH = AXIS_PCIE_DATA_WIDTH < 512 ? 60 : 137; +parameter AXIS_PCIE_CQ_USER_WIDTH = AXIS_PCIE_DATA_WIDTH < 512 ? 85 : 183; +parameter AXIS_PCIE_CC_USER_WIDTH = AXIS_PCIE_DATA_WIDTH < 512 ? 33 : 81; + +parameter RQ_SEQ_NUM_WIDTH = AXIS_PCIE_RQ_USER_WIDTH == 60 ? 4 : 6; +parameter RQ_SEQ_NUM_ENABLE = 1; + +parameter PCIE_TAG_COUNT = 64; +parameter BAR0_APERTURE = 24; +parameter BAR2_APERTURE = 24; + +// Clock and reset +wire pcie_user_clk; +wire pcie_user_reset; + +// GPIO +assign hbm_cattrip = 1'b0; + +// PCIe +wire pcie_sys_clk; +wire pcie_sys_clk_gt; + +IBUFDS_GTE4 #( + .REFCLK_HROW_CK_SEL(2'b00) +) +ibufds_gte4_pcie_mgt_refclk_inst ( + .I (pcie_refclk_1_p), + .IB (pcie_refclk_1_n), + .CEB (1'b0), + .O (pcie_sys_clk_gt), + .ODIV2 (pcie_sys_clk) +); + +wire [AXIS_PCIE_DATA_WIDTH-1:0] axis_rq_tdata; +wire [AXIS_PCIE_KEEP_WIDTH-1:0] axis_rq_tkeep; +wire axis_rq_tlast; +wire axis_rq_tready; +wire [AXIS_PCIE_RQ_USER_WIDTH-1:0] axis_rq_tuser; +wire axis_rq_tvalid; + +wire [AXIS_PCIE_DATA_WIDTH-1:0] axis_rc_tdata; +wire [AXIS_PCIE_KEEP_WIDTH-1:0] axis_rc_tkeep; +wire axis_rc_tlast; +wire axis_rc_tready; +wire [AXIS_PCIE_RC_USER_WIDTH-1:0] axis_rc_tuser; +wire axis_rc_tvalid; + +wire [AXIS_PCIE_DATA_WIDTH-1:0] axis_cq_tdata; +wire [AXIS_PCIE_KEEP_WIDTH-1:0] axis_cq_tkeep; +wire axis_cq_tlast; +wire axis_cq_tready; +wire [AXIS_PCIE_CQ_USER_WIDTH-1:0] axis_cq_tuser; +wire axis_cq_tvalid; + +wire [AXIS_PCIE_DATA_WIDTH-1:0] axis_cc_tdata; +wire [AXIS_PCIE_KEEP_WIDTH-1:0] axis_cc_tkeep; +wire axis_cc_tlast; +wire axis_cc_tready; +wire [AXIS_PCIE_CC_USER_WIDTH-1:0] axis_cc_tuser; +wire axis_cc_tvalid; + +wire [RQ_SEQ_NUM_WIDTH-1:0] pcie_rq_seq_num0; +wire pcie_rq_seq_num_vld0; +wire [RQ_SEQ_NUM_WIDTH-1:0] pcie_rq_seq_num1; +wire pcie_rq_seq_num_vld1; + +// ila_0 rq_ila ( +// .clk(pcie_user_clk), +// .probe0(axis_rq_tdata), +// .probe1(axis_rq_tkeep), +// .probe2(axis_rq_tlast), +// .probe3(axis_rq_tready), +// .probe4(axis_rq_tuser), +// .probe5(axis_rq_tvalid) +// ); + +// ila_0 rc_ila ( +// .clk(pcie_user_clk), +// .probe0(axis_rc_tdata), +// .probe1(axis_rc_tkeep), +// .probe2(axis_rc_tlast), +// .probe3(axis_rc_tready), +// .probe4(axis_rc_tuser), +// .probe5(axis_rc_tvalid) +// ); + +wire [2:0] cfg_max_payload; +wire [2:0] cfg_max_read_req; + +wire [9:0] cfg_mgmt_addr; +wire [7:0] cfg_mgmt_function_number; +wire cfg_mgmt_write; +wire [31:0] cfg_mgmt_write_data; +wire [3:0] cfg_mgmt_byte_enable; +wire cfg_mgmt_read; +wire [31:0] cfg_mgmt_read_data; +wire cfg_mgmt_read_write_done; + +wire [7:0] cfg_fc_ph; +wire [11:0] cfg_fc_pd; +wire [7:0] cfg_fc_nph; +wire [11:0] cfg_fc_npd; +wire [7:0] cfg_fc_cplh; +wire [11:0] cfg_fc_cpld; +wire [2:0] cfg_fc_sel; + +wire [3:0] cfg_interrupt_msi_enable; +wire [11:0] cfg_interrupt_msi_mmenable; +wire cfg_interrupt_msi_mask_update; +wire [31:0] cfg_interrupt_msi_data; +wire [3:0] cfg_interrupt_msi_select; +wire [31:0] cfg_interrupt_msi_int; +wire [31:0] cfg_interrupt_msi_pending_status; +wire cfg_interrupt_msi_pending_status_data_enable; +wire [3:0] cfg_interrupt_msi_pending_status_function_num; +wire cfg_interrupt_msi_sent; +wire cfg_interrupt_msi_fail; +wire [2:0] cfg_interrupt_msi_attr; +wire cfg_interrupt_msi_tph_present; +wire [1:0] cfg_interrupt_msi_tph_type; +wire [8:0] cfg_interrupt_msi_tph_st_tag; +wire [3:0] cfg_interrupt_msi_function_number; + +wire status_error_cor; +wire status_error_uncor; + +pcie4c_uscale_plus_0 +pcie4c_uscale_plus_inst ( + .pci_exp_txn(pcie_tx_n), + .pci_exp_txp(pcie_tx_p), + .pci_exp_rxn(pcie_rx_n), + .pci_exp_rxp(pcie_rx_p), + .user_clk(pcie_user_clk), + .user_reset(pcie_user_reset), + .user_lnk_up(), + + .s_axis_rq_tdata(axis_rq_tdata), + .s_axis_rq_tkeep(axis_rq_tkeep), + .s_axis_rq_tlast(axis_rq_tlast), + .s_axis_rq_tready(axis_rq_tready), + .s_axis_rq_tuser(axis_rq_tuser), + .s_axis_rq_tvalid(axis_rq_tvalid), + + .m_axis_rc_tdata(axis_rc_tdata), + .m_axis_rc_tkeep(axis_rc_tkeep), + .m_axis_rc_tlast(axis_rc_tlast), + .m_axis_rc_tready(axis_rc_tready), + .m_axis_rc_tuser(axis_rc_tuser), + .m_axis_rc_tvalid(axis_rc_tvalid), + + .m_axis_cq_tdata(axis_cq_tdata), + .m_axis_cq_tkeep(axis_cq_tkeep), + .m_axis_cq_tlast(axis_cq_tlast), + .m_axis_cq_tready(axis_cq_tready), + .m_axis_cq_tuser(axis_cq_tuser), + .m_axis_cq_tvalid(axis_cq_tvalid), + + .s_axis_cc_tdata(axis_cc_tdata), + .s_axis_cc_tkeep(axis_cc_tkeep), + .s_axis_cc_tlast(axis_cc_tlast), + .s_axis_cc_tready(axis_cc_tready), + .s_axis_cc_tuser(axis_cc_tuser), + .s_axis_cc_tvalid(axis_cc_tvalid), + + .pcie_rq_seq_num0(pcie_rq_seq_num0), + .pcie_rq_seq_num_vld0(pcie_rq_seq_num_vld0), + .pcie_rq_seq_num1(pcie_rq_seq_num1), + .pcie_rq_seq_num_vld1(pcie_rq_seq_num_vld1), + .pcie_rq_tag0(), + .pcie_rq_tag1(), + .pcie_rq_tag_av(), + .pcie_rq_tag_vld0(), + .pcie_rq_tag_vld1(), + + .pcie_tfc_nph_av(), + .pcie_tfc_npd_av(), + + .pcie_cq_np_req(1'b1), + .pcie_cq_np_req_count(), + + .cfg_phy_link_down(), + .cfg_phy_link_status(), + .cfg_negotiated_width(), + .cfg_current_speed(), + .cfg_max_payload(cfg_max_payload), + .cfg_max_read_req(cfg_max_read_req), + .cfg_function_status(), + .cfg_function_power_state(), + .cfg_vf_status(), + .cfg_vf_power_state(), + .cfg_link_power_state(), + + .cfg_mgmt_addr(cfg_mgmt_addr), + .cfg_mgmt_function_number(cfg_mgmt_function_number), + .cfg_mgmt_write(cfg_mgmt_write), + .cfg_mgmt_write_data(cfg_mgmt_write_data), + .cfg_mgmt_byte_enable(cfg_mgmt_byte_enable), + .cfg_mgmt_read(cfg_mgmt_read), + .cfg_mgmt_read_data(cfg_mgmt_read_data), + .cfg_mgmt_read_write_done(cfg_mgmt_read_write_done), + .cfg_mgmt_debug_access(1'b0), + + .cfg_err_cor_out(), + .cfg_err_nonfatal_out(), + .cfg_err_fatal_out(), + .cfg_local_error_valid(), + .cfg_local_error_out(), + .cfg_ltssm_state(), + .cfg_rx_pm_state(), + .cfg_tx_pm_state(), + .cfg_rcb_status(), + .cfg_obff_enable(), + .cfg_pl_status_change(), + .cfg_tph_requester_enable(), + .cfg_tph_st_mode(), + .cfg_vf_tph_requester_enable(), + .cfg_vf_tph_st_mode(), + + .cfg_msg_received(), + .cfg_msg_received_data(), + .cfg_msg_received_type(), + .cfg_msg_transmit(1'b0), + .cfg_msg_transmit_type(3'd0), + .cfg_msg_transmit_data(32'd0), + .cfg_msg_transmit_done(), + + .cfg_fc_ph(cfg_fc_ph), + .cfg_fc_pd(cfg_fc_pd), + .cfg_fc_nph(cfg_fc_nph), + .cfg_fc_npd(cfg_fc_npd), + .cfg_fc_cplh(cfg_fc_cplh), + .cfg_fc_cpld(cfg_fc_cpld), + .cfg_fc_sel(cfg_fc_sel), + + .cfg_dsn(64'd0), + + .cfg_bus_number(), + + .cfg_power_state_change_ack(1'b1), + .cfg_power_state_change_interrupt(), + + .cfg_err_cor_in(status_error_cor), + .cfg_err_uncor_in(status_error_uncor), + .cfg_flr_in_process(), + .cfg_flr_done(4'd0), + .cfg_vf_flr_in_process(), + .cfg_vf_flr_func_num(8'd0), + .cfg_vf_flr_done(8'd0), + + .cfg_link_training_enable(1'b1), + + .cfg_interrupt_int(4'd0), + .cfg_interrupt_pending(4'd0), + .cfg_interrupt_sent(), + .cfg_interrupt_msi_enable(cfg_interrupt_msi_enable), + .cfg_interrupt_msi_mmenable(cfg_interrupt_msi_mmenable), + .cfg_interrupt_msi_mask_update(cfg_interrupt_msi_mask_update), + .cfg_interrupt_msi_data(cfg_interrupt_msi_data), + .cfg_interrupt_msi_select(cfg_interrupt_msi_select), + .cfg_interrupt_msi_int(cfg_interrupt_msi_int), + .cfg_interrupt_msi_pending_status(cfg_interrupt_msi_pending_status), + .cfg_interrupt_msi_pending_status_data_enable(cfg_interrupt_msi_pending_status_data_enable), + .cfg_interrupt_msi_pending_status_function_num(cfg_interrupt_msi_pending_status_function_num), + .cfg_interrupt_msi_sent(cfg_interrupt_msi_sent), + .cfg_interrupt_msi_fail(cfg_interrupt_msi_fail), + .cfg_interrupt_msi_attr(cfg_interrupt_msi_attr), + .cfg_interrupt_msi_tph_present(cfg_interrupt_msi_tph_present), + .cfg_interrupt_msi_tph_type(cfg_interrupt_msi_tph_type), + .cfg_interrupt_msi_tph_st_tag(cfg_interrupt_msi_tph_st_tag), + .cfg_interrupt_msi_function_number(cfg_interrupt_msi_function_number), + + .cfg_pm_aspm_l1_entry_reject(1'b0), + .cfg_pm_aspm_tx_l0s_entry_disable(1'b0), + + .cfg_hot_reset_out(), + + .cfg_config_space_enable(1'b1), + .cfg_req_pm_transition_l23_ready(1'b0), + .cfg_hot_reset_in(1'b0), + + .cfg_ds_port_number(8'd0), + .cfg_ds_bus_number(8'd0), + .cfg_ds_device_number(5'd0), + + .sys_clk(pcie_sys_clk), + .sys_clk_gt(pcie_sys_clk_gt), + .sys_reset(pcie_reset_n), + + .phy_rdy_out() +); + +fpga_core #( + .AXIS_PCIE_DATA_WIDTH(AXIS_PCIE_DATA_WIDTH), + .AXIS_PCIE_KEEP_WIDTH(AXIS_PCIE_KEEP_WIDTH), + .AXIS_PCIE_RC_USER_WIDTH(AXIS_PCIE_RC_USER_WIDTH), + .AXIS_PCIE_RQ_USER_WIDTH(AXIS_PCIE_RQ_USER_WIDTH), + .AXIS_PCIE_CQ_USER_WIDTH(AXIS_PCIE_CQ_USER_WIDTH), + .AXIS_PCIE_CC_USER_WIDTH(AXIS_PCIE_CC_USER_WIDTH), + .RQ_SEQ_NUM_WIDTH(RQ_SEQ_NUM_WIDTH), + .RQ_SEQ_NUM_ENABLE(RQ_SEQ_NUM_ENABLE), + .PCIE_TAG_COUNT(PCIE_TAG_COUNT), + .BAR0_APERTURE(BAR0_APERTURE), + .BAR2_APERTURE(BAR2_APERTURE) +) +core_inst ( + /* + * Clock: 250 MHz + * Synchronous reset + */ + .clk(pcie_user_clk), + .rst(pcie_user_reset), + /* + * GPIO + */ + .qsfp_led_act(qsfp_led_act), + .qsfp_led_stat_g(qsfp_led_stat_g), + .qsfp_led_stat_y(qsfp_led_stat_y), + /* + * PCIe + */ + .m_axis_rq_tdata(axis_rq_tdata), + .m_axis_rq_tkeep(axis_rq_tkeep), + .m_axis_rq_tlast(axis_rq_tlast), + .m_axis_rq_tready(axis_rq_tready), + .m_axis_rq_tuser(axis_rq_tuser), + .m_axis_rq_tvalid(axis_rq_tvalid), + + .s_axis_rc_tdata(axis_rc_tdata), + .s_axis_rc_tkeep(axis_rc_tkeep), + .s_axis_rc_tlast(axis_rc_tlast), + .s_axis_rc_tready(axis_rc_tready), + .s_axis_rc_tuser(axis_rc_tuser), + .s_axis_rc_tvalid(axis_rc_tvalid), + + .s_axis_cq_tdata(axis_cq_tdata), + .s_axis_cq_tkeep(axis_cq_tkeep), + .s_axis_cq_tlast(axis_cq_tlast), + .s_axis_cq_tready(axis_cq_tready), + .s_axis_cq_tuser(axis_cq_tuser), + .s_axis_cq_tvalid(axis_cq_tvalid), + + .m_axis_cc_tdata(axis_cc_tdata), + .m_axis_cc_tkeep(axis_cc_tkeep), + .m_axis_cc_tlast(axis_cc_tlast), + .m_axis_cc_tready(axis_cc_tready), + .m_axis_cc_tuser(axis_cc_tuser), + .m_axis_cc_tvalid(axis_cc_tvalid), + + .s_axis_rq_seq_num_0(pcie_rq_seq_num0), + .s_axis_rq_seq_num_valid_0(pcie_rq_seq_num_vld0), + .s_axis_rq_seq_num_1(pcie_rq_seq_num1), + .s_axis_rq_seq_num_valid_1(pcie_rq_seq_num_vld1), + + .cfg_max_payload(cfg_max_payload), + .cfg_max_read_req(cfg_max_read_req), + + .cfg_mgmt_addr(cfg_mgmt_addr), + .cfg_mgmt_function_number(cfg_mgmt_function_number), + .cfg_mgmt_write(cfg_mgmt_write), + .cfg_mgmt_write_data(cfg_mgmt_write_data), + .cfg_mgmt_byte_enable(cfg_mgmt_byte_enable), + .cfg_mgmt_read(cfg_mgmt_read), + .cfg_mgmt_read_data(cfg_mgmt_read_data), + .cfg_mgmt_read_write_done(cfg_mgmt_read_write_done), + + .cfg_fc_ph(cfg_fc_ph), + .cfg_fc_pd(cfg_fc_pd), + .cfg_fc_nph(cfg_fc_nph), + .cfg_fc_npd(cfg_fc_npd), + .cfg_fc_cplh(cfg_fc_cplh), + .cfg_fc_cpld(cfg_fc_cpld), + .cfg_fc_sel(cfg_fc_sel), + + .cfg_interrupt_msi_enable(cfg_interrupt_msi_enable), + .cfg_interrupt_msi_mmenable(cfg_interrupt_msi_mmenable), + .cfg_interrupt_msi_mask_update(cfg_interrupt_msi_mask_update), + .cfg_interrupt_msi_data(cfg_interrupt_msi_data), + .cfg_interrupt_msi_select(cfg_interrupt_msi_select), + .cfg_interrupt_msi_int(cfg_interrupt_msi_int), + .cfg_interrupt_msi_pending_status(cfg_interrupt_msi_pending_status), + .cfg_interrupt_msi_pending_status_data_enable(cfg_interrupt_msi_pending_status_data_enable), + .cfg_interrupt_msi_pending_status_function_num(cfg_interrupt_msi_pending_status_function_num), + .cfg_interrupt_msi_sent(cfg_interrupt_msi_sent), + .cfg_interrupt_msi_fail(cfg_interrupt_msi_fail), + .cfg_interrupt_msi_attr(cfg_interrupt_msi_attr), + .cfg_interrupt_msi_tph_present(cfg_interrupt_msi_tph_present), + .cfg_interrupt_msi_tph_type(cfg_interrupt_msi_tph_type), + .cfg_interrupt_msi_tph_st_tag(cfg_interrupt_msi_tph_st_tag), + .cfg_interrupt_msi_function_number(cfg_interrupt_msi_function_number), + + .status_error_cor(status_error_cor), + .status_error_uncor(status_error_uncor) +); + +endmodule + +`resetall diff --git a/fpga/lib/pcie/example/AU50/fpga/rtl/fpga_core.v b/fpga/lib/pcie/example/AU50/fpga/rtl/fpga_core.v new file mode 100644 index 000000000..7619b4438 --- /dev/null +++ b/fpga/lib/pcie/example/AU50/fpga/rtl/fpga_core.v @@ -0,0 +1,274 @@ +/* + +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. + +*/ + +// Language: Verilog 2001 + +`resetall +`timescale 1ns / 1ps +`default_nettype none + +/* + * FPGA core logic + */ +module fpga_core # +( + parameter AXIS_PCIE_DATA_WIDTH = 512, + parameter AXIS_PCIE_KEEP_WIDTH = (AXIS_PCIE_DATA_WIDTH/32), + parameter AXIS_PCIE_RC_USER_WIDTH = AXIS_PCIE_DATA_WIDTH < 512 ? 75 : 161, + parameter AXIS_PCIE_RQ_USER_WIDTH = AXIS_PCIE_DATA_WIDTH < 512 ? 60 : 137, + parameter AXIS_PCIE_CQ_USER_WIDTH = AXIS_PCIE_DATA_WIDTH < 512 ? 85 : 183, + parameter AXIS_PCIE_CC_USER_WIDTH = AXIS_PCIE_DATA_WIDTH < 512 ? 33 : 81, + parameter RQ_SEQ_NUM_WIDTH = AXIS_PCIE_RQ_USER_WIDTH == 60 ? 4 : 6, + parameter RQ_SEQ_NUM_ENABLE = 1, + parameter PCIE_TAG_COUNT = 64, + parameter BAR0_APERTURE = 24, + parameter BAR2_APERTURE = 24 +) +( + /* + * Clock: 250 MHz + * Synchronous reset + */ + input wire clk, + input wire rst, + + /* + * GPIO + */ + output wire qsfp_led_act, + output wire qsfp_led_stat_g, + output wire qsfp_led_stat_y, + + /* + * PCIe + */ + output wire [AXIS_PCIE_DATA_WIDTH-1:0] m_axis_rq_tdata, + output wire [AXIS_PCIE_KEEP_WIDTH-1:0] m_axis_rq_tkeep, + output wire m_axis_rq_tlast, + input wire m_axis_rq_tready, + output wire [AXIS_PCIE_RQ_USER_WIDTH-1:0] m_axis_rq_tuser, + output wire m_axis_rq_tvalid, + + input wire [AXIS_PCIE_DATA_WIDTH-1:0] s_axis_rc_tdata, + input wire [AXIS_PCIE_KEEP_WIDTH-1:0] s_axis_rc_tkeep, + input wire s_axis_rc_tlast, + output wire s_axis_rc_tready, + input wire [AXIS_PCIE_RC_USER_WIDTH-1:0] s_axis_rc_tuser, + input wire s_axis_rc_tvalid, + + input wire [AXIS_PCIE_DATA_WIDTH-1:0] s_axis_cq_tdata, + input wire [AXIS_PCIE_KEEP_WIDTH-1:0] s_axis_cq_tkeep, + input wire s_axis_cq_tlast, + output wire s_axis_cq_tready, + input wire [AXIS_PCIE_CQ_USER_WIDTH-1:0] s_axis_cq_tuser, + input wire s_axis_cq_tvalid, + + output wire [AXIS_PCIE_DATA_WIDTH-1:0] m_axis_cc_tdata, + output wire [AXIS_PCIE_KEEP_WIDTH-1:0] m_axis_cc_tkeep, + output wire m_axis_cc_tlast, + input wire m_axis_cc_tready, + output wire [AXIS_PCIE_CC_USER_WIDTH-1:0] m_axis_cc_tuser, + output wire m_axis_cc_tvalid, + + input wire [RQ_SEQ_NUM_WIDTH-1:0] s_axis_rq_seq_num_0, + input wire s_axis_rq_seq_num_valid_0, + input wire [RQ_SEQ_NUM_WIDTH-1:0] s_axis_rq_seq_num_1, + input wire s_axis_rq_seq_num_valid_1, + + input wire [2:0] cfg_max_payload, + input wire [2:0] cfg_max_read_req, + + output wire [9:0] cfg_mgmt_addr, + output wire [7:0] cfg_mgmt_function_number, + output wire cfg_mgmt_write, + output wire [31:0] cfg_mgmt_write_data, + output wire [3:0] cfg_mgmt_byte_enable, + output wire cfg_mgmt_read, + input wire [31:0] cfg_mgmt_read_data, + input wire cfg_mgmt_read_write_done, + + input wire [7:0] cfg_fc_ph, + input wire [11:0] cfg_fc_pd, + input wire [7:0] cfg_fc_nph, + input wire [11:0] cfg_fc_npd, + input wire [7:0] cfg_fc_cplh, + input wire [11:0] cfg_fc_cpld, + output wire [2:0] cfg_fc_sel, + + input wire [3:0] cfg_interrupt_msi_enable, + input wire [11:0] cfg_interrupt_msi_mmenable, + input wire cfg_interrupt_msi_mask_update, + input wire [31:0] cfg_interrupt_msi_data, + output wire [3:0] cfg_interrupt_msi_select, + output wire [31:0] cfg_interrupt_msi_int, + output wire [31:0] cfg_interrupt_msi_pending_status, + output wire cfg_interrupt_msi_pending_status_data_enable, + output wire [3:0] cfg_interrupt_msi_pending_status_function_num, + input wire cfg_interrupt_msi_sent, + input wire cfg_interrupt_msi_fail, + output wire [2:0] cfg_interrupt_msi_attr, + output wire cfg_interrupt_msi_tph_present, + output wire [1:0] cfg_interrupt_msi_tph_type, + output wire [8:0] cfg_interrupt_msi_tph_st_tag, + output wire [3:0] cfg_interrupt_msi_function_number, + + output wire status_error_cor, + output wire status_error_uncor +); + +assign qsfp_led_act = 1'b0; +assign qsfp_led_stat_g = 1'b0; +assign qsfp_led_stat_y = 1'b0; + +example_core_pcie_us #( + .AXIS_PCIE_DATA_WIDTH(AXIS_PCIE_DATA_WIDTH), + .AXIS_PCIE_KEEP_WIDTH(AXIS_PCIE_KEEP_WIDTH), + .AXIS_PCIE_RC_USER_WIDTH(AXIS_PCIE_RC_USER_WIDTH), + .AXIS_PCIE_RQ_USER_WIDTH(AXIS_PCIE_RQ_USER_WIDTH), + .AXIS_PCIE_CQ_USER_WIDTH(AXIS_PCIE_CQ_USER_WIDTH), + .AXIS_PCIE_CC_USER_WIDTH(AXIS_PCIE_CC_USER_WIDTH), + .RQ_SEQ_NUM_WIDTH(RQ_SEQ_NUM_WIDTH), + .RQ_SEQ_NUM_ENABLE(RQ_SEQ_NUM_ENABLE), + .PCIE_TAG_COUNT(PCIE_TAG_COUNT), + .READ_OP_TABLE_SIZE(PCIE_TAG_COUNT), + .READ_TX_LIMIT(2**(RQ_SEQ_NUM_WIDTH-1)), + .READ_TX_FC_ENABLE(1), + .WRITE_OP_TABLE_SIZE(2**(RQ_SEQ_NUM_WIDTH-1)), + .WRITE_TX_LIMIT(2**(RQ_SEQ_NUM_WIDTH-1)), + .WRITE_TX_FC_ENABLE(1), + .BAR0_APERTURE(BAR0_APERTURE), + .BAR2_APERTURE(BAR2_APERTURE) +) +example_core_pcie_us_inst ( + .clk(clk), + .rst(rst), + + /* + * AXI input (RC) + */ + .s_axis_rc_tdata(s_axis_rc_tdata), + .s_axis_rc_tkeep(s_axis_rc_tkeep), + .s_axis_rc_tvalid(s_axis_rc_tvalid), + .s_axis_rc_tready(s_axis_rc_tready), + .s_axis_rc_tlast(s_axis_rc_tlast), + .s_axis_rc_tuser(s_axis_rc_tuser), + + /* + * AXI output (RQ) + */ + .m_axis_rq_tdata(m_axis_rq_tdata), + .m_axis_rq_tkeep(m_axis_rq_tkeep), + .m_axis_rq_tvalid(m_axis_rq_tvalid), + .m_axis_rq_tready(m_axis_rq_tready), + .m_axis_rq_tlast(m_axis_rq_tlast), + .m_axis_rq_tuser(m_axis_rq_tuser), + + /* + * AXI input (CQ) + */ + .s_axis_cq_tdata(s_axis_cq_tdata), + .s_axis_cq_tkeep(s_axis_cq_tkeep), + .s_axis_cq_tvalid(s_axis_cq_tvalid), + .s_axis_cq_tready(s_axis_cq_tready), + .s_axis_cq_tlast(s_axis_cq_tlast), + .s_axis_cq_tuser(s_axis_cq_tuser), + + /* + * AXI output (CC) + */ + .m_axis_cc_tdata(m_axis_cc_tdata), + .m_axis_cc_tkeep(m_axis_cc_tkeep), + .m_axis_cc_tvalid(m_axis_cc_tvalid), + .m_axis_cc_tready(m_axis_cc_tready), + .m_axis_cc_tlast(m_axis_cc_tlast), + .m_axis_cc_tuser(m_axis_cc_tuser), + + /* + * Transmit sequence number input + */ + .s_axis_rq_seq_num_0(s_axis_rq_seq_num_0), + .s_axis_rq_seq_num_valid_0(s_axis_rq_seq_num_valid_0), + .s_axis_rq_seq_num_1(s_axis_rq_seq_num_1), + .s_axis_rq_seq_num_valid_1(s_axis_rq_seq_num_valid_1), + + /* + * Flow control + */ + .cfg_fc_ph(cfg_fc_ph), + .cfg_fc_pd(cfg_fc_pd), + .cfg_fc_nph(cfg_fc_nph), + .cfg_fc_npd(cfg_fc_npd), + .cfg_fc_cplh(cfg_fc_cplh), + .cfg_fc_cpld(cfg_fc_cpld), + .cfg_fc_sel(cfg_fc_sel), + + /* + * Configuration interface + */ + .cfg_mgmt_addr(cfg_mgmt_addr), + .cfg_mgmt_function_number(cfg_mgmt_function_number), + .cfg_mgmt_write(cfg_mgmt_write), + .cfg_mgmt_write_data(cfg_mgmt_write_data), + .cfg_mgmt_byte_enable(cfg_mgmt_byte_enable), + .cfg_mgmt_read(cfg_mgmt_read), + .cfg_mgmt_read_data(cfg_mgmt_read_data), + .cfg_mgmt_read_write_done(cfg_mgmt_read_write_done), + + /* + * Interrupt interface + */ + .cfg_interrupt_msi_enable(cfg_interrupt_msi_enable), + .cfg_interrupt_msi_vf_enable(8'd0), + .cfg_interrupt_msi_mmenable(cfg_interrupt_msi_mmenable), + .cfg_interrupt_msi_mask_update(cfg_interrupt_msi_mask_update), + .cfg_interrupt_msi_data(cfg_interrupt_msi_data), + .cfg_interrupt_msi_select(cfg_interrupt_msi_select), + .cfg_interrupt_msi_int(cfg_interrupt_msi_int), + .cfg_interrupt_msi_pending_status(cfg_interrupt_msi_pending_status), + .cfg_interrupt_msi_pending_status_data_enable(cfg_interrupt_msi_pending_status_data_enable), + .cfg_interrupt_msi_pending_status_function_num(cfg_interrupt_msi_pending_status_function_num), + .cfg_interrupt_msi_sent(cfg_interrupt_msi_sent), + .cfg_interrupt_msi_fail(cfg_interrupt_msi_fail), + .cfg_interrupt_msi_attr(cfg_interrupt_msi_attr), + .cfg_interrupt_msi_tph_present(cfg_interrupt_msi_tph_present), + .cfg_interrupt_msi_tph_type(cfg_interrupt_msi_tph_type), + .cfg_interrupt_msi_tph_st_tag(cfg_interrupt_msi_tph_st_tag), + .cfg_interrupt_msi_function_number(cfg_interrupt_msi_function_number), + + /* + * Configuration + */ + .cfg_max_read_req(cfg_max_read_req), + .cfg_max_payload(cfg_max_payload), + + /* + * Status + */ + .status_error_cor(status_error_cor), + .status_error_uncor(status_error_uncor) +); + +endmodule + +`resetall diff --git a/fpga/lib/pcie/example/AU50/fpga/rtl/sync_reset.v b/fpga/lib/pcie/example/AU50/fpga/rtl/sync_reset.v new file mode 100644 index 000000000..1fd24d361 --- /dev/null +++ b/fpga/lib/pcie/example/AU50/fpga/rtl/sync_reset.v @@ -0,0 +1,56 @@ +/* + +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 active-high asynchronous reset signal to a given clock by + * using a pipeline of N registers. + */ +module sync_reset #( + parameter N=2 // depth of synchronizer +)( + input wire clk, + input wire rst, + output wire sync_reset_out +); + +reg [N-1:0] sync_reg = {N{1'b1}}; + +assign sync_reset_out = sync_reg[N-1]; + +always @(posedge clk or posedge rst) begin + if (rst) + sync_reg <= {N{1'b1}}; + else + sync_reg <= {sync_reg[N-2:0], 1'b0}; +end + +endmodule + +`resetall diff --git a/fpga/lib/pcie/example/AU50/fpga/rtl/sync_signal.v b/fpga/lib/pcie/example/AU50/fpga/rtl/sync_signal.v new file mode 100644 index 000000000..74b855fa1 --- /dev/null +++ b/fpga/lib/pcie/example/AU50/fpga/rtl/sync_signal.v @@ -0,0 +1,62 @@ +/* + +Copyright (c) 2014-2018 Alex Forencich + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +*/ + +// Language: Verilog-2001 + +`resetall +`timescale 1 ns / 1 ps +`default_nettype none + +/* + * Synchronizes an asyncronous signal to a given clock by using a pipeline of + * two registers. + */ +module sync_signal #( + parameter WIDTH=1, // width of the input and output signals + parameter N=2 // depth of synchronizer +)( + input wire clk, + input wire [WIDTH-1:0] in, + output wire [WIDTH-1:0] out +); + +reg [WIDTH-1:0] sync_reg[N-1:0]; + +/* + * The synchronized output is the last register in the pipeline. + */ +assign out = sync_reg[N-1]; + +integer k; + +always @(posedge clk) begin + sync_reg[0] <= in; + for (k = 1; k < N; k = k + 1) begin + sync_reg[k] <= sync_reg[k-1]; + end +end + +endmodule + +`resetall diff --git a/fpga/lib/pcie/example/AU50/fpga/tb/fpga_core/Makefile b/fpga/lib/pcie/example/AU50/fpga/tb/fpga_core/Makefile new file mode 100644 index 000000000..7c85b6e54 --- /dev/null +++ b/fpga/lib/pcie/example/AU50/fpga/tb/fpga_core/Makefile @@ -0,0 +1,123 @@ +# Copyright (c) 2020 Alex Forencich +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +TOPLEVEL_LANG = verilog + +SIM ?= icarus +WAVES ?= 0 + +COCOTB_HDL_TIMEUNIT = 1ns +COCOTB_HDL_TIMEPRECISION = 1ps + +DUT = fpga_core +TOPLEVEL = $(DUT) +MODULE = test_$(DUT) +VERILOG_SOURCES += ../../rtl/$(DUT).v +VERILOG_SOURCES += ../../rtl/common/example_core_pcie_us.v +VERILOG_SOURCES += ../../rtl/common/example_core_pcie.v +VERILOG_SOURCES += ../../rtl/common/example_core.v +VERILOG_SOURCES += ../../rtl/common/axi_ram.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_if.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_if_rc.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_if_rq.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_if_cq.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_if_cc.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_cfg.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_msi.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_axil_master.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_axi_master.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_axi_master_rd.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_axi_master_wr.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_tlp_demux_bar.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_tlp_demux.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_tlp_mux.v +VERILOG_SOURCES += ../../lib/pcie/rtl/dma_if_pcie.v +VERILOG_SOURCES += ../../lib/pcie/rtl/dma_if_pcie_rd.v +VERILOG_SOURCES += ../../lib/pcie/rtl/dma_if_pcie_wr.v +VERILOG_SOURCES += ../../lib/pcie/rtl/dma_psdpram.v +VERILOG_SOURCES += ../../lib/pcie/rtl/arbiter.v +VERILOG_SOURCES += ../../lib/pcie/rtl/priority_encoder.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pulse_merge.v + +# module parameters +export PARAM_AXIS_PCIE_DATA_WIDTH ?= 512 +export PARAM_AXIS_PCIE_KEEP_WIDTH ?= $(shell expr $(PARAM_AXIS_PCIE_DATA_WIDTH) / 32 ) +export PARAM_AXIS_PCIE_RQ_USER_WIDTH ?= $(if $(filter-out 512,$(PARAM_AXIS_PCIE_DATA_WIDTH)),62,137) +export PARAM_AXIS_PCIE_RC_USER_WIDTH ?= $(if $(filter-out 512,$(PARAM_AXIS_PCIE_DATA_WIDTH)),75,161) +export PARAM_AXIS_PCIE_CQ_USER_WIDTH ?= $(if $(filter-out 512,$(PARAM_AXIS_PCIE_DATA_WIDTH)),88,183) +export PARAM_AXIS_PCIE_CC_USER_WIDTH ?= $(if $(filter-out 512,$(PARAM_AXIS_PCIE_DATA_WIDTH)),33,81) +export PARAM_RQ_SEQ_NUM_WIDTH ?= 6 +export PARAM_RQ_SEQ_NUM_ENABLE ?= 1 +export PARAM_PCIE_TAG_COUNT ?= 64 +export PARAM_BAR0_APERTURE ?= 24 +export PARAM_BAR2_APERTURE ?= 24 + +ifeq ($(SIM), icarus) + PLUSARGS += -fst + + COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_DATA_WIDTH=$(PARAM_AXIS_PCIE_DATA_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_KEEP_WIDTH=$(PARAM_AXIS_PCIE_KEEP_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_RQ_USER_WIDTH=$(PARAM_AXIS_PCIE_RQ_USER_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_RC_USER_WIDTH=$(PARAM_AXIS_PCIE_RC_USER_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_CQ_USER_WIDTH=$(PARAM_AXIS_PCIE_CQ_USER_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_CC_USER_WIDTH=$(PARAM_AXIS_PCIE_CC_USER_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).RQ_SEQ_NUM_WIDTH=$(PARAM_RQ_SEQ_NUM_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).RQ_SEQ_NUM_ENABLE=$(PARAM_RQ_SEQ_NUM_ENABLE) + COMPILE_ARGS += -P $(TOPLEVEL).PCIE_TAG_COUNT=$(PARAM_PCIE_TAG_COUNT) + COMPILE_ARGS += -P $(TOPLEVEL).BAR0_APERTURE=$(PARAM_BAR0_APERTURE) + COMPILE_ARGS += -P $(TOPLEVEL).BAR2_APERTURE=$(PARAM_BAR2_APERTURE) + + ifeq ($(WAVES), 1) + VERILOG_SOURCES += iverilog_dump.v + COMPILE_ARGS += -s iverilog_dump + endif +else ifeq ($(SIM), verilator) + COMPILE_ARGS += -Wno-SELRANGE -Wno-WIDTH + + COMPILE_ARGS += -GAXIS_PCIE_DATA_WIDTH=$(PARAM_AXIS_PCIE_DATA_WIDTH) + COMPILE_ARGS += -GAXIS_PCIE_KEEP_WIDTH=$(PARAM_AXIS_PCIE_KEEP_WIDTH) + COMPILE_ARGS += -GAXIS_PCIE_RQ_USER_WIDTH=$(PARAM_AXIS_PCIE_RQ_USER_WIDTH) + COMPILE_ARGS += -GAXIS_PCIE_RC_USER_WIDTH=$(PARAM_AXIS_PCIE_RC_USER_WIDTH) + COMPILE_ARGS += -GAXIS_PCIE_CQ_USER_WIDTH=$(PARAM_AXIS_PCIE_CQ_USER_WIDTH) + COMPILE_ARGS += -GAXIS_PCIE_CC_USER_WIDTH=$(PARAM_AXIS_PCIE_CC_USER_WIDTH) + COMPILE_ARGS += -GRQ_SEQ_NUM_WIDTH=$(PARAM_RQ_SEQ_NUM_WIDTH) + COMPILE_ARGS += -GRQ_SEQ_NUM_ENABLE=$(PARAM_RQ_SEQ_NUM_ENABLE) + COMPILE_ARGS += -GPCIE_TAG_COUNT=$(PARAM_PCIE_TAG_COUNT) + COMPILE_ARGS += -GBAR0_APERTURE=$(PARAM_BAR0_APERTURE) + COMPILE_ARGS += -GBAR2_APERTURE=$(PARAM_BAR2_APERTURE) + + ifeq ($(WAVES), 1) + COMPILE_ARGS += --trace-fst + endif +endif + +include $(shell cocotb-config --makefiles)/Makefile.sim + +iverilog_dump.v: + echo 'module iverilog_dump();' > $@ + echo 'initial begin' >> $@ + echo ' $$dumpfile("$(TOPLEVEL).fst");' >> $@ + echo ' $$dumpvars(0, $(TOPLEVEL));' >> $@ + echo 'end' >> $@ + echo 'endmodule' >> $@ + +clean:: + @rm -rf iverilog_dump.v + @rm -rf dump.fst $(TOPLEVEL).fst diff --git a/fpga/lib/pcie/example/AU50/fpga/tb/fpga_core/test_fpga_core.py b/fpga/lib/pcie/example/AU50/fpga/tb/fpga_core/test_fpga_core.py new file mode 100644 index 000000000..f2c657c91 --- /dev/null +++ b/fpga/lib/pcie/example/AU50/fpga/tb/fpga_core/test_fpga_core.py @@ -0,0 +1,472 @@ +""" + +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 + +import cocotb_test.simulator + +import cocotb +from cocotb.log import SimLog +from cocotb.triggers import RisingEdge, FallingEdge, Timer + +from cocotbext.axi import AxiStreamBus +from cocotbext.pcie.core import RootComplex +from cocotbext.pcie.xilinx.us import UltraScalePlusPcieDevice + + +class TB(object): + def __init__(self, dut): + self.dut = dut + + self.log = SimLog("cocotb.tb") + self.log.setLevel(logging.DEBUG) + + # PCIe + self.rc = RootComplex() + + self.dev = UltraScalePlusPcieDevice( + # configuration options + pcie_generation=3, + pcie_link_width=16, + user_clk_frequency=250e6, + alignment="dword", + cq_cc_straddle=False, + rq_rc_straddle=False, + rc_4tlp_straddle=False, + enable_pf1=False, + enable_client_tag=True, + enable_extended_tag=True, + enable_parity=False, + enable_rx_msg_interface=False, + enable_sriov=False, + enable_extended_configuration=False, + + enable_pf0_msi=True, + enable_pf1_msi=False, + + # signals + # Clock and Reset Interface + user_clk=dut.clk, + user_reset=dut.rst, + # user_lnk_up + # sys_clk + # sys_clk_gt + # sys_reset + # phy_rdy_out + + # Requester reQuest Interface + rq_bus=AxiStreamBus.from_prefix(dut, "m_axis_rq"), + pcie_rq_seq_num0=dut.s_axis_rq_seq_num_0, + pcie_rq_seq_num_vld0=dut.s_axis_rq_seq_num_valid_0, + pcie_rq_seq_num1=dut.s_axis_rq_seq_num_1, + pcie_rq_seq_num_vld1=dut.s_axis_rq_seq_num_valid_1, + # pcie_rq_tag0 + # pcie_rq_tag1 + # pcie_rq_tag_av + # pcie_rq_tag_vld0 + # pcie_rq_tag_vld1 + + # Requester Completion Interface + rc_bus=AxiStreamBus.from_prefix(dut, "s_axis_rc"), + + # Completer reQuest Interface + cq_bus=AxiStreamBus.from_prefix(dut, "s_axis_cq"), + # pcie_cq_np_req + # pcie_cq_np_req_count + + # Completer Completion Interface + cc_bus=AxiStreamBus.from_prefix(dut, "m_axis_cc"), + + # Transmit Flow Control Interface + # pcie_tfc_nph_av=dut.pcie_tfc_nph_av, + # pcie_tfc_npd_av=dut.pcie_tfc_npd_av, + + # Configuration Management Interface + cfg_mgmt_addr=dut.cfg_mgmt_addr, + cfg_mgmt_function_number=dut.cfg_mgmt_function_number, + cfg_mgmt_write=dut.cfg_mgmt_write, + cfg_mgmt_write_data=dut.cfg_mgmt_write_data, + cfg_mgmt_byte_enable=dut.cfg_mgmt_byte_enable, + cfg_mgmt_read=dut.cfg_mgmt_read, + cfg_mgmt_read_data=dut.cfg_mgmt_read_data, + cfg_mgmt_read_write_done=dut.cfg_mgmt_read_write_done, + # cfg_mgmt_debug_access + + # Configuration Status Interface + # cfg_phy_link_down + # cfg_phy_link_status + # cfg_negotiated_width + # cfg_current_speed + cfg_max_payload=dut.cfg_max_payload, + cfg_max_read_req=dut.cfg_max_read_req, + # cfg_function_status + # cfg_vf_status + # cfg_function_power_state + # cfg_vf_power_state + # cfg_link_power_state + # cfg_err_cor_out + # cfg_err_nonfatal_out + # cfg_err_fatal_out + # cfg_local_error_out + # cfg_local_error_valid + # cfg_rx_pm_state + # cfg_tx_pm_state + # cfg_ltssm_state + # cfg_rcb_status + # cfg_obff_enable + # cfg_pl_status_change + # cfg_tph_requester_enable + # cfg_tph_st_mode + # cfg_vf_tph_requester_enable + # cfg_vf_tph_st_mode + + # Configuration Received Message Interface + # cfg_msg_received + # cfg_msg_received_data + # cfg_msg_received_type + + # Configuration Transmit Message Interface + # cfg_msg_transmit + # cfg_msg_transmit_type + # cfg_msg_transmit_data + # cfg_msg_transmit_done + + # Configuration Flow Control Interface + cfg_fc_ph=dut.cfg_fc_ph, + cfg_fc_pd=dut.cfg_fc_pd, + cfg_fc_nph=dut.cfg_fc_nph, + cfg_fc_npd=dut.cfg_fc_npd, + cfg_fc_cplh=dut.cfg_fc_cplh, + cfg_fc_cpld=dut.cfg_fc_cpld, + cfg_fc_sel=dut.cfg_fc_sel, + + # Configuration Control Interface + # cfg_hot_reset_in + # cfg_hot_reset_out + # cfg_config_space_enable + # cfg_dsn + # cfg_bus_number + # cfg_ds_port_number + # cfg_ds_bus_number + # cfg_ds_device_number + # cfg_ds_function_number + # cfg_power_state_change_ack + # cfg_power_state_change_interrupt + cfg_err_cor_in=dut.status_error_cor, + cfg_err_uncor_in=dut.status_error_uncor, + # cfg_flr_in_process + # cfg_flr_done + # cfg_vf_flr_in_process + # cfg_vf_flr_func_num + # cfg_vf_flr_done + # cfg_pm_aspm_l1_entry_reject + # cfg_pm_aspm_tx_l0s_entry_disable + # cfg_req_pm_transition_l23_ready + # cfg_link_training_enable + + # Configuration Interrupt Controller Interface + # cfg_interrupt_int + # cfg_interrupt_sent + # cfg_interrupt_pending + cfg_interrupt_msi_enable=dut.cfg_interrupt_msi_enable, + cfg_interrupt_msi_mmenable=dut.cfg_interrupt_msi_mmenable, + cfg_interrupt_msi_mask_update=dut.cfg_interrupt_msi_mask_update, + cfg_interrupt_msi_data=dut.cfg_interrupt_msi_data, + # cfg_interrupt_msi_select=dut.cfg_interrupt_msi_select, + cfg_interrupt_msi_int=dut.cfg_interrupt_msi_int, + cfg_interrupt_msi_pending_status=dut.cfg_interrupt_msi_pending_status, + cfg_interrupt_msi_pending_status_data_enable=dut.cfg_interrupt_msi_pending_status_data_enable, + # cfg_interrupt_msi_pending_status_function_num=dut.cfg_interrupt_msi_pending_status_function_num, + cfg_interrupt_msi_sent=dut.cfg_interrupt_msi_sent, + cfg_interrupt_msi_fail=dut.cfg_interrupt_msi_fail, + # cfg_interrupt_msix_enable + # cfg_interrupt_msix_mask + # cfg_interrupt_msix_vf_enable + # cfg_interrupt_msix_vf_mask + # cfg_interrupt_msix_address + # cfg_interrupt_msix_data + # cfg_interrupt_msix_int + # cfg_interrupt_msix_vec_pending + # cfg_interrupt_msix_vec_pending_status + cfg_interrupt_msi_attr=dut.cfg_interrupt_msi_attr, + cfg_interrupt_msi_tph_present=dut.cfg_interrupt_msi_tph_present, + cfg_interrupt_msi_tph_type=dut.cfg_interrupt_msi_tph_type, + # cfg_interrupt_msi_tph_st_tag=dut.cfg_interrupt_msi_tph_st_tag, + # cfg_interrupt_msi_function_number=dut.cfg_interrupt_msi_function_number, + + # Configuration Extend Interface + # cfg_ext_read_received + # cfg_ext_write_received + # cfg_ext_register_number + # cfg_ext_function_number + # cfg_ext_write_data + # cfg_ext_write_byte_enable + # cfg_ext_read_data + # cfg_ext_read_data_valid + ) + + # self.dev.log.setLevel(logging.DEBUG) + + self.rc.make_port().connect(self.dev) + + self.dev.functions[0].msi_multiple_message_capable = 5 + + self.dev.functions[0].configure_bar(0, 2**len(dut.example_core_pcie_us_inst.core_pcie_inst.axil_ctrl_awaddr)) + self.dev.functions[0].configure_bar(2, 2**len(dut.example_core_pcie_us_inst.core_pcie_inst.axi_ram_awaddr)) + + async def init(self): + + await FallingEdge(self.dut.rst) + await Timer(100, 'ns') + + await self.rc.enumerate(enable_bus_mastering=True, configure_msi=True) + + +@cocotb.test() +async def run_test(dut): + + tb = TB(dut) + + await tb.init() + + mem = tb.rc.mem_pool.alloc_region(16*1024*1024) + mem_base = mem.get_absolute_address(0) + + dev_pf0_bar0 = tb.rc.tree[0][0].bar_window[0] + dev_pf0_bar2 = tb.rc.tree[0][0].bar_window[2] + + tb.log.info("Test memory write to BAR 2") + + test_data = b'\x11\x22\x33\x44' + await dev_pf0_bar2.write(0, test_data) + + await Timer(100, 'ns') + + tb.log.info("Test memory read from BAR 2") + + val = await dev_pf0_bar2.read(0, len(test_data), timeout=1000) + tb.log.info("Read data: %s", val) + assert val == test_data + + tb.log.info("Test DMA") + + # write packet data + mem[0:1024] = bytearray([x % 256 for x in range(1024)]) + + # enable DMA + await dev_pf0_bar0.write_dword(0x000000, 1) + + # write pcie read descriptor + await dev_pf0_bar0.write_dword(0x000100, (mem_base+0x0000) & 0xffffffff) + await dev_pf0_bar0.write_dword(0x000104, (mem_base+0x0000 >> 32) & 0xffffffff) + await dev_pf0_bar0.write_dword(0x000108, 0x100) + await dev_pf0_bar0.write_dword(0x000110, 0x400) + await dev_pf0_bar0.write_dword(0x000114, 0xAA) + + await Timer(2000, 'ns') + + # read status + val = await dev_pf0_bar0.read_dword(0x000118) + tb.log.info("Status: 0x%x", val) + assert val == 0x800000AA + + # write pcie write descriptor + await dev_pf0_bar0.write_dword(0x000200, (mem_base+0x1000) & 0xffffffff) + await dev_pf0_bar0.write_dword(0x000204, (mem_base+0x1000 >> 32) & 0xffffffff) + await dev_pf0_bar0.write_dword(0x000208, 0x100) + await dev_pf0_bar0.write_dword(0x000210, 0x400) + await dev_pf0_bar0.write_dword(0x000214, 0x55) + + await Timer(2000, 'ns') + + # read status + val = await dev_pf0_bar0.read_dword(0x000218) + tb.log.info("Status: 0x%x", val) + assert val == 0x80000055 + + tb.log.info("%s", mem.hexdump_str(0x1000, 64)) + + assert mem[0:1024] == mem[0x1000:0x1000+1024] + + tb.log.info("Test DMA block operations") + + # write packet data + mem[0:1024] = bytearray([x % 256 for x in range(1024)]) + + # enable DMA + await dev_pf0_bar0.write_dword(0x000000, 1) + # disable interrupts + await dev_pf0_bar0.write_dword(0x000008, 0) + + # configure operation (read) + # DMA base address + await dev_pf0_bar0.write_dword(0x001080, (mem_base+0x0000) & 0xffffffff) + await dev_pf0_bar0.write_dword(0x001084, (mem_base+0x0000 >> 32) & 0xffffffff) + # DMA offset address + await dev_pf0_bar0.write_dword(0x001088, 0) + await dev_pf0_bar0.write_dword(0x00108c, 0) + # DMA offset mask + await dev_pf0_bar0.write_dword(0x001090, 0x000003ff) + await dev_pf0_bar0.write_dword(0x001094, 0) + # DMA stride + await dev_pf0_bar0.write_dword(0x001098, 256) + await dev_pf0_bar0.write_dword(0x00109c, 0) + # RAM base address + await dev_pf0_bar0.write_dword(0x0010c0, 0) + await dev_pf0_bar0.write_dword(0x0010c4, 0) + # RAM offset address + await dev_pf0_bar0.write_dword(0x0010c8, 0) + await dev_pf0_bar0.write_dword(0x0010cc, 0) + # RAM offset mask + await dev_pf0_bar0.write_dword(0x0010d0, 0x000003ff) + await dev_pf0_bar0.write_dword(0x0010d4, 0) + # RAM stride + await dev_pf0_bar0.write_dword(0x0010d8, 256) + await dev_pf0_bar0.write_dword(0x0010dc, 0) + # clear cycle count + await dev_pf0_bar0.write_dword(0x001008, 0) + await dev_pf0_bar0.write_dword(0x00100c, 0) + # block length + await dev_pf0_bar0.write_dword(0x001010, 256) + # block count + await dev_pf0_bar0.write_dword(0x001018, 32) + await dev_pf0_bar0.write_dword(0x00101c, 0) + # start + await dev_pf0_bar0.write_dword(0x001000, 1) + + await Timer(2000, 'ns') + + # configure operation (write) + # DMA base address + await dev_pf0_bar0.write_dword(0x001180, (mem_base+0x0000) & 0xffffffff) + await dev_pf0_bar0.write_dword(0x001184, (mem_base+0x0000 >> 32) & 0xffffffff) + # DMA offset address + await dev_pf0_bar0.write_dword(0x001188, 0) + await dev_pf0_bar0.write_dword(0x00118c, 0) + # DMA offset mask + await dev_pf0_bar0.write_dword(0x001190, 0x000003ff) + await dev_pf0_bar0.write_dword(0x001194, 0) + # DMA stride + await dev_pf0_bar0.write_dword(0x001198, 256) + await dev_pf0_bar0.write_dword(0x00119c, 0) + # RAM base address + await dev_pf0_bar0.write_dword(0x0011c0, 0) + await dev_pf0_bar0.write_dword(0x0011c4, 0) + # RAM offset address + await dev_pf0_bar0.write_dword(0x0011c8, 0) + await dev_pf0_bar0.write_dword(0x0011cc, 0) + # RAM offset mask + await dev_pf0_bar0.write_dword(0x0011d0, 0x000003ff) + await dev_pf0_bar0.write_dword(0x0011d4, 0) + # RAM stride + await dev_pf0_bar0.write_dword(0x0011d8, 256) + await dev_pf0_bar0.write_dword(0x0011dc, 0) + # clear cycle count + await dev_pf0_bar0.write_dword(0x001108, 0) + await dev_pf0_bar0.write_dword(0x00110c, 0) + # block length + await dev_pf0_bar0.write_dword(0x001110, 256) + # block count + await dev_pf0_bar0.write_dword(0x001118, 32) + await dev_pf0_bar0.write_dword(0x00111c, 0) + # start + await dev_pf0_bar0.write_dword(0x001100, 1) + + await Timer(2000, 'ns') + + await RisingEdge(dut.clk) + await RisingEdge(dut.clk) + + +# cocotb-test + +tests_dir = 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')) +pcie_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'pcie', '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(rtl_dir, "common", "example_core_pcie_us.v"), + os.path.join(rtl_dir, "common", "example_core_pcie.v"), + os.path.join(rtl_dir, "common", "example_core.v"), + os.path.join(rtl_dir, "common", "axi_ram.v"), + os.path.join(pcie_rtl_dir, "pcie_us_if.v"), + os.path.join(pcie_rtl_dir, "pcie_us_if_rc.v"), + os.path.join(pcie_rtl_dir, "pcie_us_if_rq.v"), + os.path.join(pcie_rtl_dir, "pcie_us_if_cq.v"), + os.path.join(pcie_rtl_dir, "pcie_us_if_cc.v"), + os.path.join(pcie_rtl_dir, "pcie_us_cfg.v"), + os.path.join(pcie_rtl_dir, "pcie_us_msi.v"), + os.path.join(pcie_rtl_dir, "pcie_axil_master.v"), + os.path.join(pcie_rtl_dir, "pcie_axi_master.v"), + os.path.join(pcie_rtl_dir, "pcie_axi_master_rd.v"), + os.path.join(pcie_rtl_dir, "pcie_axi_master_wr.v"), + os.path.join(pcie_rtl_dir, "pcie_tlp_demux_bar.v"), + os.path.join(pcie_rtl_dir, "pcie_tlp_demux.v"), + os.path.join(pcie_rtl_dir, "pcie_tlp_mux.v"), + os.path.join(pcie_rtl_dir, "dma_if_pcie.v"), + os.path.join(pcie_rtl_dir, "dma_if_pcie_rd.v"), + os.path.join(pcie_rtl_dir, "dma_if_pcie_wr.v"), + os.path.join(pcie_rtl_dir, "dma_psdpram.v"), + os.path.join(pcie_rtl_dir, "arbiter.v"), + os.path.join(pcie_rtl_dir, "priority_encoder.v"), + os.path.join(pcie_rtl_dir, "pulse_merge.v"), + ] + + parameters = {} + + parameters['AXIS_PCIE_DATA_WIDTH'] = 512 + parameters['AXIS_PCIE_KEEP_WIDTH'] = parameters['AXIS_PCIE_DATA_WIDTH'] // 32 + parameters['AXIS_PCIE_RQ_USER_WIDTH'] = 62 if parameters['AXIS_PCIE_DATA_WIDTH'] < 512 else 137 + parameters['AXIS_PCIE_RC_USER_WIDTH'] = 75 if parameters['AXIS_PCIE_DATA_WIDTH'] < 512 else 161 + parameters['AXIS_PCIE_CQ_USER_WIDTH'] = 88 if parameters['AXIS_PCIE_DATA_WIDTH'] < 512 else 183 + parameters['AXIS_PCIE_CC_USER_WIDTH'] = 33 if parameters['AXIS_PCIE_DATA_WIDTH'] < 512 else 81 + parameters['RQ_SEQ_NUM_WIDTH'] = 6 + parameters['RQ_SEQ_NUM_ENABLE'] = 1 + parameters['PCIE_TAG_COUNT'] = 64 + parameters['BAR0_APERTURE'] = 24 + parameters['BAR2_APERTURE'] = 24 + + 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, + ) diff --git a/fpga/lib/pcie/example/ExaNIC_X10/fpga/tb/fpga_core/test_fpga_core.py b/fpga/lib/pcie/example/ExaNIC_X10/fpga/tb/fpga_core/test_fpga_core.py index 3a55373c3..f1d721c63 100644 --- a/fpga/lib/pcie/example/ExaNIC_X10/fpga/tb/fpga_core/test_fpga_core.py +++ b/fpga/lib/pcie/example/ExaNIC_X10/fpga/tb/fpga_core/test_fpga_core.py @@ -34,7 +34,6 @@ from cocotb.triggers import RisingEdge, FallingEdge, Timer from cocotbext.axi import AxiStreamBus from cocotbext.pcie.core import RootComplex from cocotbext.pcie.xilinx.us import UltraScalePcieDevice -from cocotbext.axi.utils import hexdump_str class TB(object): @@ -228,8 +227,8 @@ class TB(object): self.dev.functions[0].msi_multiple_message_capable = 5 - self.dev.functions[0].configure_bar(0, 2**24) - self.dev.functions[0].configure_bar(2, 2**24) + self.dev.functions[0].configure_bar(0, 2**len(dut.example_core_pcie_us_inst.core_pcie_inst.axil_ctrl_awaddr)) + self.dev.functions[0].configure_bar(2, 2**len(dut.example_core_pcie_us_inst.core_pcie_inst.axi_ram_awaddr)) async def init(self): diff --git a/fpga/lib/pcie/example/ExaNIC_X25/fpga/README.md b/fpga/lib/pcie/example/ExaNIC_X25/fpga/README.md new file mode 100644 index 000000000..b6f4b2acb --- /dev/null +++ b/fpga/lib/pcie/example/ExaNIC_X25/fpga/README.md @@ -0,0 +1,19 @@ +# Verilog PCIe ExaNIC X25 Example Design + +## Introduction + +This example design targets the Exablaze ExaNIC X25 FPGA board. + +The design implements the PCIe AXI lite master module, the PCIe AXI master module, and the PCIe DMA module. A very simple Linux driver is included to test the FPGA design. + +* FPGA: xcku3p-ffvb676-2-e + +## How to build + +Run `make` to build. Ensure that the Xilinx Vivado components are in PATH. + +Run `make` to build the driver. Ensure the headers for the running kernel are installed, otherwise the driver cannot be compiled. + +## How to test + +Run `make program` to program the ExaNIC X25 board with Vivado. Then load the driver with `insmod example.ko`. Check dmesg for the output. diff --git a/fpga/lib/pcie/example/ExaNIC_X25/fpga/common/vivado.mk b/fpga/lib/pcie/example/ExaNIC_X25/fpga/common/vivado.mk new file mode 100644 index 000000000..d47a43947 --- /dev/null +++ b/fpga/lib/pcie/example/ExaNIC_X25/fpga/common/vivado.mk @@ -0,0 +1,126 @@ +################################################################### +# +# 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) + +SYN_FILES_REL = $(patsubst %, ../%, $(filter-out /% ./%,$(SYN_FILES))) $(filter /% ./%,$(SYN_FILES)) +INC_FILES_REL = $(patsubst %, ../%, $(filter-out /% ./%,$(INC_FILES))) $(filter /% ./%,$(INC_FILES)) +XCI_FILES_REL = $(patsubst %, ../%, $(filter-out /% ./%,$(XCI_FILES))) $(filter /% ./%,$(XCI_FILES)) +IP_TCL_FILES_REL = $(patsubst %, ../%, $(filter-out /% ./%,$(IP_TCL_FILES))) $(filter /% ./%,$(IP_TCL_FILES)) +CONFIG_TCL_FILES_REL = $(patsubst %, ../%, $(filter-out /% ./%,$(CONFIG_TCL_FILES))) $(filter /% ./%,$(CONFIG_TCL_FILES)) + +ifdef XDC_FILES + XDC_FILES_REL = $(patsubst %, ../%, $(filter-out /% ./%,$(XDC_FILES))) $(filter /% ./%,$(XDC_FILES)) +else + XDC_FILES_REL = $(FPGA_TOP).xdc +endif + +################################################################### +# Main Targets +# +# all: build everything +# clean: remove output files and project files +################################################################### + +all: fpga + +fpga: $(FPGA_TOP).bit + +vivado: $(FPGA_TOP).xpr + vivado $(FPGA_TOP).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 program.tcl generate_mcs.tcl *.mcs *.prm flash.tcl + +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) $(FPGA_TOP)" > $@ + echo "add_files -fileset sources_1 defines.v $(SYN_FILES_REL)" >> $@ + 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) + echo "open_project -quiet $(FPGA_TOP).xpr" > $@ + for x in $(CONFIG_TCL_FILES_REL); do echo "source $$x" >> $@; done + +$(FPGA_TOP).xpr: create_project.tcl update_config.tcl + vivado -nojournal -nolog -mode batch $(foreach x,$?,-source $x) + +# synthesis run +%.runs/synth_1/%.dcp: %.xpr $(SYN_FILES_REL) $(INC_FILES_REL) $(XDC_FILES_REL) $(CONFIG_TCL_FILES_REL) + echo "open_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 +%.runs/impl_1/%_routed.dcp: %.runs/synth_1/%.dcp + echo "open_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 + vivado -nojournal -nolog -mode batch -source run_impl.tcl + +# bit file +%.bit: %.runs/impl_1/%_routed.dcp + echo "open_project $*.xpr" > generate_bit.tcl + echo "open_run impl_1" >> generate_bit.tcl + echo "write_bitstream -force $*.bit" >> generate_bit.tcl + vivado -nojournal -nolog -mode batch -source generate_bit.tcl + mkdir -p rev + EXT=bit; COUNT=100; \ + while [ -e rev/$*_rev$$COUNT.$$EXT ]; \ + do COUNT=$$((COUNT+1)); done; \ + cp $@ rev/$*_rev$$COUNT.$$EXT; \ + echo "Output: rev/$*_rev$$COUNT.$$EXT"; diff --git a/fpga/lib/pcie/example/ExaNIC_X25/fpga/driver b/fpga/lib/pcie/example/ExaNIC_X25/fpga/driver new file mode 120000 index 000000000..4a54c76b5 --- /dev/null +++ b/fpga/lib/pcie/example/ExaNIC_X25/fpga/driver @@ -0,0 +1 @@ +../../common/driver/example/ \ No newline at end of file diff --git a/fpga/lib/pcie/example/ExaNIC_X25/fpga/fpga.xdc b/fpga/lib/pcie/example/ExaNIC_X25/fpga/fpga.xdc new file mode 100644 index 000000000..80936aa73 --- /dev/null +++ b/fpga/lib/pcie/example/ExaNIC_X25/fpga/fpga.xdc @@ -0,0 +1,187 @@ +# XDC constraints for the ExaNIC X25 +# part: xcku3p-ffvb676-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.UNUSEDPIN Pullup [current_design] +set_property BITSTREAM.CONFIG.CONFIGRATE 31.9 [current_design] +set_property BITSTREAM.CONFIG.BPI_PAGE_SIZE 8 [current_design] +set_property BITSTREAM.CONFIG.BPI_1ST_READ_CYCLE 4 [current_design] +set_property CONFIG_MODE BPI16 [current_design] +set_property BITSTREAM.CONFIG.OVERTEMPSHUTDOWN Enable [current_design] + +# 10 MHz TXCO +#set_property -dict {LOC D14 IOSTANDARD LVCMOS33} [get_ports clk_10mhz] +#create_clock -period 100 -name clk_100mhz [get_ports clk_10mhz] + +# LEDs +set_property -dict {LOC J12 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 12} [get_ports {sfp_1_led[0]}] +set_property -dict {LOC H12 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 12} [get_ports {sfp_1_led[1]}] +set_property -dict {LOC J13 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 12} [get_ports {sfp_2_led[0]}] +set_property -dict {LOC H13 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 12} [get_ports {sfp_2_led[1]}] +set_property -dict {LOC J14 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 12} [get_ports {sma_led[0]}] +set_property -dict {LOC G12 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 12} [get_ports {sma_led[1]}] + +set_false_path -to [get_ports {sfp_1_led[*] sfp_2_led[*] sma_led[*]}] +set_output_delay 0 [get_ports {sfp_1_led[*] sfp_2_led[*] sma_led[*]}] + +# GPIO +#set_property -dict {LOC F9 IOSTANDARD LVCMOS18} [get_ports gpio[0]] +#set_property -dict {LOC F10 IOSTANDARD LVCMOS18} [get_ports gpio[1]] +#set_property -dict {LOC G9 IOSTANDARD LVCMOS18} [get_ports gpio[2]] +#set_property -dict {LOC G10 IOSTANDARD LVCMOS18} [get_ports gpio[3]] + +# SMA +#set_property -dict {LOC A14 IOSTANDARD LVCMOS33} [get_ports sma_in] +#set_property -dict {LOC A12 IOSTANDARD LVCMOS33 SLEW FAST DRIVE 12} [get_ports sma_out] +#set_property -dict {LOC A13 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 12} [get_ports sma_out_en] +#set_property -dict {LOC B12 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 12} [get_ports sma_term_en] + +#set_false_path -to [get_ports {sma_out sma_term sma_term_en}] +#set_output_delay 0 [get_ports {sma_out sma_term sma_term_en}] +#set_false_path -from [get_ports {sma_in}] +#set_input_delay 0 [get_ports {sma_in}] + +# Config +#set_property -dict {LOC C14 IOSTANDARD LVCMOS33} [get_ports ddr_npres] + +# SFP28 Interfaces +#set_property -dict {LOC D2 } [get_ports sfp_1_rx_p] ;# MGTYRXP0_227 GTYE4_CHANNEL_X0Y12 / GTYE4_COMMON_X0Y3 +#set_property -dict {LOC D1 } [get_ports sfp_1_rx_n] ;# MGTYRXN0_227 GTYE4_CHANNEL_X0Y12 / GTYE4_COMMON_X0Y3 +#set_property -dict {LOC A4 } [get_ports sfp_2_rx_p] ;# MGTYRXP3_227 GTYE4_CHANNEL_X0Y15 / GTYE4_COMMON_X0Y3 +#set_property -dict {LOC A3 } [get_ports sfp_2_rx_n] ;# MGTYRXN3_227 GTYE4_CHANNEL_X0Y15 / GTYE4_COMMON_X0Y3 +#set_property -dict {LOC F7 } [get_ports sfp_1_tx_p] ;# MGTYTXP0_227 GTYE4_CHANNEL_X0Y12 / GTYE4_COMMON_X0Y3 +#set_property -dict {LOC F6 } [get_ports sfp_1_tx_n] ;# MGTYTXN0_227 GTYE4_CHANNEL_X0Y12 / GTYE4_COMMON_X0Y3 +#set_property -dict {LOC B7 } [get_ports sfp_2_tx_p] ;# MGTYTXP3_227 GTYE4_CHANNEL_X0Y15 / GTYE4_COMMON_X0Y3 +#set_property -dict {LOC B6 } [get_ports sfp_2_tx_n] ;# MGTYTXN3_227 GTYE4_CHANNEL_X0Y15 / GTYE4_COMMON_X0Y3 +#set_property -dict {LOC K7 } [get_ports sfp_mgt_refclk_p] ;# MGTREFCLK0P_227 from X2 +#set_property -dict {LOC K6 } [get_ports sfp_mgt_refclk_n] ;# MGTREFCLK0N_227 from X2 +#set_property -dict {LOC AC17 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 12} [get_ports sfp_1_tx_disable] +#set_property -dict {LOC AA17 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 12} [get_ports sfp_2_tx_disable] +#set_property -dict {LOC F12 IOSTANDARD LVCMOS33 PULLUP true} [get_ports sfp_1_npres] +#set_property -dict {LOC F14 IOSTANDARD LVCMOS33 PULLUP true} [get_ports sfp_2_npres] +#set_property -dict {LOC AC16 IOSTANDARD LVCMOS18 PULLUP true} [get_ports sfp_1_los] +#set_property -dict {LOC Y17 IOSTANDARD LVCMOS18 PULLUP true} [get_ports sfp_2_los] +#set_property -dict {LOC G14 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 12} [get_ports sfp_1_rs] +#set_property -dict {LOC H14 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 12} [get_ports sfp_2_rs] +#set_property -dict {LOC A10 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 12 PULLUP true} [get_ports sfp_i2c_scl] +#set_property -dict {LOC C11 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 12 PULLUP true} [get_ports sfp_1_i2c_sda] +#set_property -dict {LOC B11 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 12 PULLUP true} [get_ports sfp_2_i2c_sda] + +# 161.1328125 MHz MGT reference clock +#create_clock -period 6.206 -name sfp_mgt_refclk [get_ports sfp_mgt_refclk_p] + +#set_false_path -to [get_ports {sfp_1_tx_disable sfp_2_tx_disable sfp_1_rs sfp_2_rs}] +#set_output_delay 0 [get_ports {sfp_1_tx_disable sfp_2_tx_disable sfp_1_rs sfp_2_rs}] +#set_false_path -from [get_ports {sfp_1_npres sfp_2_npres sfp_1_los sfp_2_los}] +#set_input_delay 0 [get_ports {sfp_1_npres sfp_2_npres sfp_1_los sfp_2_los}] + +#set_false_path -to [get_ports {sfp_1_i2c_sda sfp_2_i2c_sda sfp_i2c_scl}] +#set_output_delay 0 [get_ports {sfp_1_i2c_sda sfp_2_i2c_sda sfp_i2c_scl}] +#set_false_path -from [get_ports {sfp_1_i2c_sda sfp_2_i2c_sda sfp_i2c_scl}] +#set_input_delay 0 [get_ports {sfp_1_i2c_sda sfp_2_i2c_sda sfp_i2c_scl}] + +# I2C interface +#set_property -dict {LOC B9 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 12 PULLUP true} [get_ports eeprom_i2c_scl] +#set_property -dict {LOC A9 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 12 PULLUP true} [get_ports eeprom_i2c_sda] + +#set_false_path -to [get_ports {eeprom_i2c_sda eeprom_i2c_scl}] +#set_output_delay 0 [get_ports {eeprom_i2c_sda eeprom_i2c_scl}] +#set_false_path -from [get_ports {eeprom_i2c_sda eeprom_i2c_scl}] +#set_input_delay 0 [get_ports {eeprom_i2c_sda eeprom_i2c_scl}] + +# PCIe Interface +set_property -dict {LOC P2 } [get_ports {pcie_rx_p[0]}] ;# MGTYRXP3_225 GTYE4_CHANNEL_X0Y7 / GTYE4_COMMON_X0Y1 +set_property -dict {LOC P1 } [get_ports {pcie_rx_n[0]}] ;# MGTYRXN3_225 GTYE4_CHANNEL_X0Y7 / GTYE4_COMMON_X0Y1 +set_property -dict {LOC R5 } [get_ports {pcie_tx_p[0]}] ;# MGTYTXP3_225 GTYE4_CHANNEL_X0Y7 / GTYE4_COMMON_X0Y1 +set_property -dict {LOC R4 } [get_ports {pcie_tx_n[0]}] ;# MGTYTXN3_225 GTYE4_CHANNEL_X0Y7 / GTYE4_COMMON_X0Y1 +set_property -dict {LOC T2 } [get_ports {pcie_rx_p[1]}] ;# MGTYRXP2_225 GTYE4_CHANNEL_X0Y6 / GTYE4_COMMON_X0Y1 +set_property -dict {LOC T1 } [get_ports {pcie_rx_n[1]}] ;# MGTYRXN2_225 GTYE4_CHANNEL_X0Y6 / GTYE4_COMMON_X0Y1 +set_property -dict {LOC U5 } [get_ports {pcie_tx_p[1]}] ;# MGTYTXP2_225 GTYE4_CHANNEL_X0Y6 / GTYE4_COMMON_X0Y1 +set_property -dict {LOC U4 } [get_ports {pcie_tx_n[1]}] ;# MGTYTXN2_225 GTYE4_CHANNEL_X0Y6 / GTYE4_COMMON_X0Y1 +set_property -dict {LOC V2 } [get_ports {pcie_rx_p[2]}] ;# MGTYRXP1_225 GTYE4_CHANNEL_X0Y5 / GTYE4_COMMON_X0Y1 +set_property -dict {LOC V1 } [get_ports {pcie_rx_n[2]}] ;# MGTYRXN1_225 GTYE4_CHANNEL_X0Y5 / GTYE4_COMMON_X0Y1 +set_property -dict {LOC W5 } [get_ports {pcie_tx_p[2]}] ;# MGTYTXP1_225 GTYE4_CHANNEL_X0Y5 / GTYE4_COMMON_X0Y1 +set_property -dict {LOC W4 } [get_ports {pcie_tx_n[2]}] ;# MGTYTXN1_225 GTYE4_CHANNEL_X0Y5 / GTYE4_COMMON_X0Y1 +set_property -dict {LOC Y2 } [get_ports {pcie_rx_p[3]}] ;# MGTYRXP0_225 GTYE4_CHANNEL_X0Y4 / GTYE4_COMMON_X0Y1 +set_property -dict {LOC Y1 } [get_ports {pcie_rx_n[3]}] ;# MGTYRXN0_225 GTYE4_CHANNEL_X0Y4 / GTYE4_COMMON_X0Y1 +set_property -dict {LOC AA5 } [get_ports {pcie_tx_p[3]}] ;# MGTYTXP0_225 GTYE4_CHANNEL_X0Y4 / GTYE4_COMMON_X0Y1 +set_property -dict {LOC AA4 } [get_ports {pcie_tx_n[3]}] ;# MGTYTXN0_225 GTYE4_CHANNEL_X0Y4 / GTYE4_COMMON_X0Y1 +set_property -dict {LOC AB2 } [get_ports {pcie_rx_p[4]}] ;# MGTYRXP3_224 GTYE4_CHANNEL_X0Y3 / GTYE4_COMMON_X0Y0 +set_property -dict {LOC AB1 } [get_ports {pcie_rx_n[4]}] ;# MGTYRXN3_224 GTYE4_CHANNEL_X0Y3 / GTYE4_COMMON_X0Y0 +set_property -dict {LOC AC5 } [get_ports {pcie_tx_p[4]}] ;# MGTYTXP3_224 GTYE4_CHANNEL_X0Y3 / GTYE4_COMMON_X0Y0 +set_property -dict {LOC AC4 } [get_ports {pcie_tx_n[4]}] ;# MGTYTXN3_224 GTYE4_CHANNEL_X0Y3 / GTYE4_COMMON_X0Y0 +set_property -dict {LOC AD2 } [get_ports {pcie_rx_p[5]}] ;# MGTYRXP2_224 GTYE4_CHANNEL_X0Y2 / GTYE4_COMMON_X0Y0 +set_property -dict {LOC AD1 } [get_ports {pcie_rx_n[5]}] ;# MGTYRXN2_224 GTYE4_CHANNEL_X0Y2 / GTYE4_COMMON_X0Y0 +set_property -dict {LOC AD7 } [get_ports {pcie_tx_p[5]}] ;# MGTYTXP2_224 GTYE4_CHANNEL_X0Y2 / GTYE4_COMMON_X0Y0 +set_property -dict {LOC AD6 } [get_ports {pcie_tx_n[5]}] ;# MGTYTXN2_224 GTYE4_CHANNEL_X0Y2 / GTYE4_COMMON_X0Y0 +set_property -dict {LOC AE4 } [get_ports {pcie_rx_p[6]}] ;# MGTYRXP1_224 GTYE4_CHANNEL_X0Y1 / GTYE4_COMMON_X0Y0 +set_property -dict {LOC AE3 } [get_ports {pcie_rx_n[6]}] ;# MGTYRXN1_224 GTYE4_CHANNEL_X0Y1 / GTYE4_COMMON_X0Y0 +set_property -dict {LOC AE9 } [get_ports {pcie_tx_p[6]}] ;# MGTYTXP1_224 GTYE4_CHANNEL_X0Y1 / GTYE4_COMMON_X0Y0 +set_property -dict {LOC AE8 } [get_ports {pcie_tx_n[6]}] ;# MGTYTXN1_224 GTYE4_CHANNEL_X0Y1 / GTYE4_COMMON_X0Y0 +set_property -dict {LOC AF2 } [get_ports {pcie_rx_p[7]}] ;# MGTYRXP0_224 GTYE4_CHANNEL_X0Y0 / GTYE4_COMMON_X0Y0 +set_property -dict {LOC AF1 } [get_ports {pcie_rx_n[7]}] ;# MGTYRXN0_224 GTYE4_CHANNEL_X0Y0 / GTYE4_COMMON_X0Y0 +set_property -dict {LOC AF7 } [get_ports {pcie_tx_p[7]}] ;# MGTYTXP0_224 GTYE4_CHANNEL_X0Y0 / GTYE4_COMMON_X0Y0 +set_property -dict {LOC AF6 } [get_ports {pcie_tx_n[7]}] ;# MGTYTXN0_224 GTYE4_CHANNEL_X0Y0 / GTYE4_COMMON_X0Y0 +set_property -dict {LOC V7 } [get_ports pcie_refclk_p] ;# MGTREFCLK0P_225 +set_property -dict {LOC V6 } [get_ports pcie_refclk_n] ;# MGTREFCLK0N_225 +set_property -dict {LOC T19 IOSTANDARD LVCMOS18 PULLUP true} [get_ports pcie_reset_n] + +set_false_path -from [get_ports {pcie_reset_n}] +set_input_delay 0 [get_ports {pcie_reset_n}] + +# 100 MHz MGT reference clock +create_clock -period 10 -name pcie_mgt_refclk [get_ports pcie_refclk_p] + +# BPI flash +#set_property -dict {LOC AF20 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_dq[0]}] +#set_property -dict {LOC AE18 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_dq[1]}] +#set_property -dict {LOC AF19 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_dq[2]}] +#set_property -dict {LOC AF17 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_dq[3]}] +#set_property -dict {LOC AB19 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_dq[4]}] +#set_property -dict {LOC AD19 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_dq[5]}] +#set_property -dict {LOC AB17 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_dq[6]}] +#set_property -dict {LOC AE17 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_dq[7]}] +#set_property -dict {LOC AD16 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_dq[8]}] +#set_property -dict {LOC AE16 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_dq[9]}] +#set_property -dict {LOC AD18 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_dq[10]}] +#set_property -dict {LOC AC21 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_dq[11]}] +#set_property -dict {LOC AE22 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_dq[12]}] +#set_property -dict {LOC AF22 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_dq[13]}] +#set_property -dict {LOC AF25 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_dq[14]}] +#set_property -dict {LOC AF24 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_dq[15]}] +#set_property -dict {LOC AE20 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_addr[0]}] +#set_property -dict {LOC AE26 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_addr[1]}] +#set_property -dict {LOC AD24 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_addr[2]}] +#set_property -dict {LOC AC23 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_addr[3]}] +#set_property -dict {LOC AE23 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_addr[4]}] +#set_property -dict {LOC AD20 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_addr[5]}] +#set_property -dict {LOC AC24 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_addr[6]}] +#set_property -dict {LOC AC22 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_addr[7]}] +#set_property -dict {LOC AD23 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_addr[8]}] +#set_property -dict {LOC AD21 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_addr[9]}] +#set_property -dict {LOC AB22 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_addr[10]}] +#set_property -dict {LOC AA22 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_addr[11]}] +#set_property -dict {LOC AE25 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_addr[12]}] +#set_property -dict {LOC AD26 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_addr[13]}] +#set_property -dict {LOC AB25 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_addr[14]}] +#set_property -dict {LOC AB26 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_addr[15]}] +#set_property -dict {LOC AD25 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_addr[16]}] +#set_property -dict {LOC AC26 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_addr[17]}] +#set_property -dict {LOC AB21 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_addr[18]}] +#set_property -dict {LOC AB24 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_addr[19]}] +#set_property -dict {LOC Y18 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_addr[20]}] +#set_property -dict {LOC AA20 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_addr[21]}] +#set_property -dict {LOC AC19 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_addr[22]}] +#set_property -dict {LOC Y20 IOSTANDARD LVCMOS18 PULLUP true} [get_ports {flash_region}] +#set_property -dict {LOC AF18 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_ce_n}] +#set_property -dict {LOC Y21 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_oe_n}] +#set_property -dict {LOC AB20 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_we_n}] +#set_property -dict {LOC AF23 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_adv_n}] + +#set_false_path -to [get_ports {flash_dq[*] flash_addr[*] flash_region flash_ce_n flash_oe_n flash_we_n flash_adv_n}] +#set_output_delay 0 [get_ports {flash_dq[*] flash_addr[*] flash_region flash_ce_n flash_oe_n flash_we_n flash_adv_n}] +#set_false_path -from [get_ports {flash_dq[*]}] +#set_input_delay 0 [get_ports {flash_dq[*]}] diff --git a/fpga/lib/pcie/example/ExaNIC_X25/fpga/fpga/Makefile b/fpga/lib/pcie/example/ExaNIC_X25/fpga/fpga/Makefile new file mode 100644 index 000000000..557d12385 --- /dev/null +++ b/fpga/lib/pcie/example/ExaNIC_X25/fpga/fpga/Makefile @@ -0,0 +1,95 @@ + +# FPGA settings +FPGA_PART = xcku3p-ffvb676-2-e +FPGA_TOP = fpga +FPGA_ARCH = kintexuplus + +# Files for synthesis +SYN_FILES = rtl/fpga.v +SYN_FILES += rtl/fpga_core.v +SYN_FILES += rtl/debounce_switch.v +SYN_FILES += rtl/sync_reset.v +SYN_FILES += rtl/sync_signal.v +SYN_FILES += rtl/common/example_core_pcie_us.v +SYN_FILES += rtl/common/example_core_pcie.v +SYN_FILES += rtl/common/example_core.v +SYN_FILES += rtl/common/axi_ram.v +SYN_FILES += lib/pcie/rtl/pcie_us_if.v +SYN_FILES += lib/pcie/rtl/pcie_us_if_rc.v +SYN_FILES += lib/pcie/rtl/pcie_us_if_rq.v +SYN_FILES += lib/pcie/rtl/pcie_us_if_cq.v +SYN_FILES += lib/pcie/rtl/pcie_us_if_cc.v +SYN_FILES += lib/pcie/rtl/pcie_us_cfg.v +SYN_FILES += lib/pcie/rtl/pcie_us_msi.v +SYN_FILES += lib/pcie/rtl/pcie_axil_master.v +SYN_FILES += lib/pcie/rtl/pcie_axi_master.v +SYN_FILES += lib/pcie/rtl/pcie_axi_master_rd.v +SYN_FILES += lib/pcie/rtl/pcie_axi_master_wr.v +SYN_FILES += lib/pcie/rtl/pcie_tlp_demux_bar.v +SYN_FILES += lib/pcie/rtl/pcie_tlp_demux.v +SYN_FILES += lib/pcie/rtl/pcie_tlp_mux.v +SYN_FILES += lib/pcie/rtl/dma_if_pcie.v +SYN_FILES += lib/pcie/rtl/dma_if_pcie_rd.v +SYN_FILES += lib/pcie/rtl/dma_if_pcie_wr.v +SYN_FILES += lib/pcie/rtl/dma_psdpram.v +SYN_FILES += lib/pcie/rtl/arbiter.v +SYN_FILES += lib/pcie/rtl/priority_encoder.v +SYN_FILES += lib/pcie/rtl/pulse_merge.v + +# XDC files +XDC_FILES = fpga.xdc + +# IP +IP_TCL_FILES = ip/pcie4_uscale_plus_0.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 + +%.mcs %.prm: %.bit + echo "write_cfgmem -force -format mcs -size 32 -interface BPIx16 -loadbit {up 0x00800000 $*.bit} -checksum -file $*.mcs" > generate_mcs.tcl + echo "exit" >> generate_mcs.tcl + vivado -nojournal -nolog -mode batch -source generate_mcs.tcl + mkdir -p rev + COUNT=100; \ + while [ -e rev/$*_rev$$COUNT.bit ]; \ + do COUNT=$$((COUNT+1)); done; \ + COUNT=$$((COUNT-1)); \ + for x in .mcs .prm; \ + do cp $*$$x rev/$*_rev$$COUNT$$x; \ + echo "Output: rev/$*_rev$$COUNT$$x"; done; + +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 {s29gl256p-bpi-x16}] 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.BPI_RS_PINS {24:23} [current_hw_cfgmem]" >> flash.tcl + echo "set_property PROGRAM.UNUSED_PIN_TERMINATION {pull-none} [current_hw_cfgmem]" >> flash.tcl + echo "create_hw_bitstream -hw_device [current_hw_device] [get_property PROGRAM.HW_CFGMEM_BITFILE [current_hw_device]]" >> flash.tcl + echo "program_hw_devices [current_hw_device]" >> flash.tcl + echo "refresh_hw_device [current_hw_device]" >> flash.tcl + echo "program_hw_cfgmem -hw_cfgmem [current_hw_cfgmem]" >> flash.tcl + echo "boot_hw_device [current_hw_device]" >> flash.tcl + echo "exit" >> flash.tcl + vivado -nojournal -nolog -mode batch -source flash.tcl + diff --git a/fpga/lib/pcie/example/ExaNIC_X25/fpga/ip/pcie4_uscale_plus_0.tcl b/fpga/lib/pcie/example/ExaNIC_X25/fpga/ip/pcie4_uscale_plus_0.tcl new file mode 100644 index 000000000..ba3d07176 --- /dev/null +++ b/fpga/lib/pcie/example/ExaNIC_X25/fpga/ip/pcie4_uscale_plus_0.tcl @@ -0,0 +1,32 @@ + +create_ip -name pcie4_uscale_plus -vendor xilinx.com -library ip -module_name pcie4_uscale_plus_0 + +set_property -dict [list \ + CONFIG.PL_LINK_CAP_MAX_LINK_SPEED {8.0_GT/s} \ + CONFIG.PL_LINK_CAP_MAX_LINK_WIDTH {X8} \ + CONFIG.AXISTEN_IF_RC_STRADDLE {false} \ + CONFIG.axisten_if_enable_client_tag {true} \ + CONFIG.axisten_if_width {256_bit} \ + CONFIG.extended_tag_field {true} \ + CONFIG.axisten_freq {250} \ + CONFIG.PF0_CLASS_CODE {058000} \ + CONFIG.PF0_DEVICE_ID {0001} \ + CONFIG.PF0_MSI_CAP_MULTIMSGCAP {32_vectors} \ + CONFIG.PF0_SUBSYSTEM_ID {0009} \ + CONFIG.PF0_SUBSYSTEM_VENDOR_ID {1ce4} \ + CONFIG.pf0_bar0_64bit {true} \ + CONFIG.pf0_bar0_prefetchable {true} \ + CONFIG.pf0_bar0_scale {Megabytes} \ + CONFIG.pf0_bar0_size {16} \ + CONFIG.pf0_bar2_64bit {true} \ + CONFIG.pf0_bar2_prefetchable {true} \ + CONFIG.pf0_bar2_enabled {true} \ + CONFIG.pf0_bar2_type {Memory} \ + CONFIG.pf0_bar2_scale {Megabytes} \ + CONFIG.pf0_bar2_size {16} \ + CONFIG.vendor_id {1234} \ + CONFIG.en_msi_per_vec_masking {true} \ + CONFIG.mode_selection {Advanced} \ + CONFIG.en_gt_selection {true} \ + CONFIG.MASTER_GT {GTYE4_CHANNEL_X0Y7} \ +] [get_ips pcie4_uscale_plus_0] diff --git a/fpga/lib/pcie/example/ExaNIC_X25/fpga/lib/pcie b/fpga/lib/pcie/example/ExaNIC_X25/fpga/lib/pcie new file mode 120000 index 000000000..11a54ed36 --- /dev/null +++ b/fpga/lib/pcie/example/ExaNIC_X25/fpga/lib/pcie @@ -0,0 +1 @@ +../../../../ \ No newline at end of file diff --git a/fpga/lib/pcie/example/ExaNIC_X25/fpga/rtl/common b/fpga/lib/pcie/example/ExaNIC_X25/fpga/rtl/common new file mode 120000 index 000000000..e60fada70 --- /dev/null +++ b/fpga/lib/pcie/example/ExaNIC_X25/fpga/rtl/common @@ -0,0 +1 @@ +../../../common/rtl/ \ No newline at end of file diff --git a/fpga/lib/pcie/example/ExaNIC_X25/fpga/rtl/debounce_switch.v b/fpga/lib/pcie/example/ExaNIC_X25/fpga/rtl/debounce_switch.v new file mode 100644 index 000000000..8e93a50c4 --- /dev/null +++ b/fpga/lib/pcie/example/ExaNIC_X25/fpga/rtl/debounce_switch.v @@ -0,0 +1,93 @@ +/* + +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 diff --git a/fpga/lib/pcie/example/ExaNIC_X25/fpga/rtl/fpga.v b/fpga/lib/pcie/example/ExaNIC_X25/fpga/rtl/fpga.v new file mode 100644 index 000000000..bb672e28c --- /dev/null +++ b/fpga/lib/pcie/example/ExaNIC_X25/fpga/rtl/fpga.v @@ -0,0 +1,449 @@ +/* + +Copyright (c) 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 1ns / 1ps +`default_nettype none + +/* + * FPGA top-level module + */ +module fpga ( + /* + * GPIO + */ + output wire [1:0] sfp_1_led, + output wire [1:0] sfp_2_led, + output wire [1:0] sma_led, + + /* + * PCI express + */ + input wire [7:0] pcie_rx_p, + input wire [7:0] pcie_rx_n, + output wire [7:0] pcie_tx_p, + output wire [7:0] pcie_tx_n, + input wire pcie_refclk_p, + input wire pcie_refclk_n, + input wire pcie_reset_n +); + +parameter AXIS_PCIE_DATA_WIDTH = 256; +parameter AXIS_PCIE_KEEP_WIDTH = (AXIS_PCIE_DATA_WIDTH/32); +parameter AXIS_PCIE_RC_USER_WIDTH = AXIS_PCIE_DATA_WIDTH < 512 ? 75 : 161; +parameter AXIS_PCIE_RQ_USER_WIDTH = AXIS_PCIE_DATA_WIDTH < 512 ? 60 : 137; +parameter AXIS_PCIE_CQ_USER_WIDTH = AXIS_PCIE_DATA_WIDTH < 512 ? 85 : 183; +parameter AXIS_PCIE_CC_USER_WIDTH = AXIS_PCIE_DATA_WIDTH < 512 ? 33 : 81; + +parameter RQ_SEQ_NUM_WIDTH = AXIS_PCIE_RQ_USER_WIDTH == 60 ? 4 : 6; +parameter RQ_SEQ_NUM_ENABLE = 1; + +parameter PCIE_TAG_COUNT = 64; +parameter BAR0_APERTURE = 24; +parameter BAR2_APERTURE = 24; + +// PCIe +wire pcie_user_clk; +wire pcie_user_reset; + +wire pcie_sys_clk; +wire pcie_sys_clk_gt; + +IBUFDS_GTE4 #( + .REFCLK_HROW_CK_SEL(2'b00) +) +ibufds_gte4_pcie_mgt_refclk_inst ( + .I (pcie_refclk_p), + .IB (pcie_refclk_n), + .CEB (1'b0), + .O (pcie_sys_clk_gt), + .ODIV2 (pcie_sys_clk) +); + +wire [AXIS_PCIE_DATA_WIDTH-1:0] axis_rq_tdata; +wire [AXIS_PCIE_KEEP_WIDTH-1:0] axis_rq_tkeep; +wire axis_rq_tlast; +wire axis_rq_tready; +wire [AXIS_PCIE_RQ_USER_WIDTH-1:0] axis_rq_tuser; +wire axis_rq_tvalid; + +wire [AXIS_PCIE_DATA_WIDTH-1:0] axis_rc_tdata; +wire [AXIS_PCIE_KEEP_WIDTH-1:0] axis_rc_tkeep; +wire axis_rc_tlast; +wire axis_rc_tready; +wire [AXIS_PCIE_RC_USER_WIDTH-1:0] axis_rc_tuser; +wire axis_rc_tvalid; + +wire [AXIS_PCIE_DATA_WIDTH-1:0] axis_cq_tdata; +wire [AXIS_PCIE_KEEP_WIDTH-1:0] axis_cq_tkeep; +wire axis_cq_tlast; +wire axis_cq_tready; +wire [AXIS_PCIE_CQ_USER_WIDTH-1:0] axis_cq_tuser; +wire axis_cq_tvalid; + +wire [AXIS_PCIE_DATA_WIDTH-1:0] axis_cc_tdata; +wire [AXIS_PCIE_KEEP_WIDTH-1:0] axis_cc_tkeep; +wire axis_cc_tlast; +wire axis_cc_tready; +wire [AXIS_PCIE_CC_USER_WIDTH-1:0] axis_cc_tuser; +wire axis_cc_tvalid; + +wire [RQ_SEQ_NUM_WIDTH-1:0] pcie_rq_seq_num0; +wire pcie_rq_seq_num_vld0; +wire [RQ_SEQ_NUM_WIDTH-1:0] pcie_rq_seq_num1; +wire pcie_rq_seq_num_vld1; + +// ila_0 rq_ila ( +// .clk(pcie_user_clk), +// .probe0(axis_rq_tdata), +// .probe1(axis_rq_tkeep), +// .probe2(axis_rq_tlast), +// .probe3(axis_rq_tready), +// .probe4(axis_rq_tuser), +// .probe5(axis_rq_tvalid) +// ); + +// ila_0 rc_ila ( +// .clk(pcie_user_clk), +// .probe0(axis_rc_tdata), +// .probe1(axis_rc_tkeep), +// .probe2(axis_rc_tlast), +// .probe3(axis_rc_tready), +// .probe4(axis_rc_tuser), +// .probe5(axis_rc_tvalid) +// ); + +wire [2:0] cfg_max_payload; +wire [2:0] cfg_max_read_req; + +wire [9:0] cfg_mgmt_addr; +wire [7:0] cfg_mgmt_function_number; +wire cfg_mgmt_write; +wire [31:0] cfg_mgmt_write_data; +wire [3:0] cfg_mgmt_byte_enable; +wire cfg_mgmt_read; +wire [31:0] cfg_mgmt_read_data; +wire cfg_mgmt_read_write_done; + +wire [7:0] cfg_fc_ph; +wire [11:0] cfg_fc_pd; +wire [7:0] cfg_fc_nph; +wire [11:0] cfg_fc_npd; +wire [7:0] cfg_fc_cplh; +wire [11:0] cfg_fc_cpld; +wire [2:0] cfg_fc_sel; + +wire [3:0] cfg_interrupt_msi_enable; +wire [11:0] cfg_interrupt_msi_mmenable; +wire cfg_interrupt_msi_mask_update; +wire [31:0] cfg_interrupt_msi_data; +wire [3:0] cfg_interrupt_msi_select; +wire [31:0] cfg_interrupt_msi_int; +wire [31:0] cfg_interrupt_msi_pending_status; +wire cfg_interrupt_msi_pending_status_data_enable; +wire [3:0] cfg_interrupt_msi_pending_status_function_num; +wire cfg_interrupt_msi_sent; +wire cfg_interrupt_msi_fail; +wire [2:0] cfg_interrupt_msi_attr; +wire cfg_interrupt_msi_tph_present; +wire [1:0] cfg_interrupt_msi_tph_type; +wire [8:0] cfg_interrupt_msi_tph_st_tag; +wire [3:0] cfg_interrupt_msi_function_number; + +wire status_error_cor; +wire status_error_uncor; + +pcie4_uscale_plus_0 +pcie4_uscale_plus_inst ( + .pci_exp_txn(pcie_tx_n), + .pci_exp_txp(pcie_tx_p), + .pci_exp_rxn(pcie_rx_n), + .pci_exp_rxp(pcie_rx_p), + .user_clk(pcie_user_clk), + .user_reset(pcie_user_reset), + .user_lnk_up(), + + .s_axis_rq_tdata(axis_rq_tdata), + .s_axis_rq_tkeep(axis_rq_tkeep), + .s_axis_rq_tlast(axis_rq_tlast), + .s_axis_rq_tready(axis_rq_tready), + .s_axis_rq_tuser(axis_rq_tuser), + .s_axis_rq_tvalid(axis_rq_tvalid), + + .m_axis_rc_tdata(axis_rc_tdata), + .m_axis_rc_tkeep(axis_rc_tkeep), + .m_axis_rc_tlast(axis_rc_tlast), + .m_axis_rc_tready(axis_rc_tready), + .m_axis_rc_tuser(axis_rc_tuser), + .m_axis_rc_tvalid(axis_rc_tvalid), + + .m_axis_cq_tdata(axis_cq_tdata), + .m_axis_cq_tkeep(axis_cq_tkeep), + .m_axis_cq_tlast(axis_cq_tlast), + .m_axis_cq_tready(axis_cq_tready), + .m_axis_cq_tuser(axis_cq_tuser), + .m_axis_cq_tvalid(axis_cq_tvalid), + + .s_axis_cc_tdata(axis_cc_tdata), + .s_axis_cc_tkeep(axis_cc_tkeep), + .s_axis_cc_tlast(axis_cc_tlast), + .s_axis_cc_tready(axis_cc_tready), + .s_axis_cc_tuser(axis_cc_tuser), + .s_axis_cc_tvalid(axis_cc_tvalid), + + .pcie_rq_seq_num0(pcie_rq_seq_num0), + .pcie_rq_seq_num_vld0(pcie_rq_seq_num_vld0), + .pcie_rq_seq_num1(pcie_rq_seq_num1), + .pcie_rq_seq_num_vld1(pcie_rq_seq_num_vld1), + .pcie_rq_tag0(), + .pcie_rq_tag1(), + .pcie_rq_tag_av(), + .pcie_rq_tag_vld0(), + .pcie_rq_tag_vld1(), + + .pcie_tfc_nph_av(), + .pcie_tfc_npd_av(), + + .pcie_cq_np_req(1'b1), + .pcie_cq_np_req_count(), + + .cfg_phy_link_down(), + .cfg_phy_link_status(), + .cfg_negotiated_width(), + .cfg_current_speed(), + .cfg_max_payload(cfg_max_payload), + .cfg_max_read_req(cfg_max_read_req), + .cfg_function_status(), + .cfg_function_power_state(), + .cfg_vf_status(), + .cfg_vf_power_state(), + .cfg_link_power_state(), + + .cfg_mgmt_addr(cfg_mgmt_addr), + .cfg_mgmt_function_number(cfg_mgmt_function_number), + .cfg_mgmt_write(cfg_mgmt_write), + .cfg_mgmt_write_data(cfg_mgmt_write_data), + .cfg_mgmt_byte_enable(cfg_mgmt_byte_enable), + .cfg_mgmt_read(cfg_mgmt_read), + .cfg_mgmt_read_data(cfg_mgmt_read_data), + .cfg_mgmt_read_write_done(cfg_mgmt_read_write_done), + .cfg_mgmt_debug_access(1'b0), + + .cfg_err_cor_out(), + .cfg_err_nonfatal_out(), + .cfg_err_fatal_out(), + .cfg_local_error_valid(), + .cfg_local_error_out(), + .cfg_ltssm_state(), + .cfg_rx_pm_state(), + .cfg_tx_pm_state(), + .cfg_rcb_status(), + .cfg_obff_enable(), + .cfg_pl_status_change(), + .cfg_tph_requester_enable(), + .cfg_tph_st_mode(), + .cfg_vf_tph_requester_enable(), + .cfg_vf_tph_st_mode(), + + .cfg_msg_received(), + .cfg_msg_received_data(), + .cfg_msg_received_type(), + .cfg_msg_transmit(1'b0), + .cfg_msg_transmit_type(3'd0), + .cfg_msg_transmit_data(32'd0), + .cfg_msg_transmit_done(), + + .cfg_fc_ph(cfg_fc_ph), + .cfg_fc_pd(cfg_fc_pd), + .cfg_fc_nph(cfg_fc_nph), + .cfg_fc_npd(cfg_fc_npd), + .cfg_fc_cplh(cfg_fc_cplh), + .cfg_fc_cpld(cfg_fc_cpld), + .cfg_fc_sel(cfg_fc_sel), + + .cfg_dsn(64'd0), + + .cfg_bus_number(), + + .cfg_power_state_change_ack(1'b1), + .cfg_power_state_change_interrupt(), + + .cfg_err_cor_in(status_error_cor), + .cfg_err_uncor_in(status_error_uncor), + .cfg_flr_in_process(), + .cfg_flr_done(4'd0), + .cfg_vf_flr_in_process(), + .cfg_vf_flr_func_num(8'd0), + .cfg_vf_flr_done(8'd0), + + .cfg_link_training_enable(1'b1), + + .cfg_interrupt_int(4'd0), + .cfg_interrupt_pending(4'd0), + .cfg_interrupt_sent(), + .cfg_interrupt_msi_enable(cfg_interrupt_msi_enable), + .cfg_interrupt_msi_mmenable(cfg_interrupt_msi_mmenable), + .cfg_interrupt_msi_mask_update(cfg_interrupt_msi_mask_update), + .cfg_interrupt_msi_data(cfg_interrupt_msi_data), + .cfg_interrupt_msi_select(cfg_interrupt_msi_select), + .cfg_interrupt_msi_int(cfg_interrupt_msi_int), + .cfg_interrupt_msi_pending_status(cfg_interrupt_msi_pending_status), + .cfg_interrupt_msi_pending_status_data_enable(cfg_interrupt_msi_pending_status_data_enable), + .cfg_interrupt_msi_pending_status_function_num(cfg_interrupt_msi_pending_status_function_num), + .cfg_interrupt_msi_sent(cfg_interrupt_msi_sent), + .cfg_interrupt_msi_fail(cfg_interrupt_msi_fail), + .cfg_interrupt_msi_attr(cfg_interrupt_msi_attr), + .cfg_interrupt_msi_tph_present(cfg_interrupt_msi_tph_present), + .cfg_interrupt_msi_tph_type(cfg_interrupt_msi_tph_type), + .cfg_interrupt_msi_tph_st_tag(cfg_interrupt_msi_tph_st_tag), + .cfg_interrupt_msi_function_number(cfg_interrupt_msi_function_number), + + .cfg_pm_aspm_l1_entry_reject(1'b0), + .cfg_pm_aspm_tx_l0s_entry_disable(1'b0), + + .cfg_hot_reset_out(), + + .cfg_config_space_enable(1'b1), + .cfg_req_pm_transition_l23_ready(1'b0), + .cfg_hot_reset_in(1'b0), + + .cfg_ds_port_number(8'd0), + .cfg_ds_bus_number(8'd0), + .cfg_ds_device_number(5'd0), + + .sys_clk(pcie_sys_clk), + .sys_clk_gt(pcie_sys_clk_gt), + .sys_reset(pcie_reset_n), + + .phy_rdy_out() +); + +fpga_core #( + .AXIS_PCIE_DATA_WIDTH(AXIS_PCIE_DATA_WIDTH), + .AXIS_PCIE_KEEP_WIDTH(AXIS_PCIE_KEEP_WIDTH), + .AXIS_PCIE_RC_USER_WIDTH(AXIS_PCIE_RC_USER_WIDTH), + .AXIS_PCIE_RQ_USER_WIDTH(AXIS_PCIE_RQ_USER_WIDTH), + .AXIS_PCIE_CQ_USER_WIDTH(AXIS_PCIE_CQ_USER_WIDTH), + .AXIS_PCIE_CC_USER_WIDTH(AXIS_PCIE_CC_USER_WIDTH), + .RQ_SEQ_NUM_WIDTH(RQ_SEQ_NUM_WIDTH), + .RQ_SEQ_NUM_ENABLE(RQ_SEQ_NUM_ENABLE), + .PCIE_TAG_COUNT(PCIE_TAG_COUNT), + .BAR0_APERTURE(BAR0_APERTURE), + .BAR2_APERTURE(BAR2_APERTURE) +) +core_inst ( + /* + * Clock: 250 MHz + * Synchronous reset + */ + .clk(pcie_user_clk), + .rst(pcie_user_reset), + /* + * GPIO + */ + .sfp_1_led(sfp_1_led), + .sfp_2_led(sfp_2_led), + .sma_led(sma_led), + /* + * PCIe + */ + .m_axis_rq_tdata(axis_rq_tdata), + .m_axis_rq_tkeep(axis_rq_tkeep), + .m_axis_rq_tlast(axis_rq_tlast), + .m_axis_rq_tready(axis_rq_tready), + .m_axis_rq_tuser(axis_rq_tuser), + .m_axis_rq_tvalid(axis_rq_tvalid), + + .s_axis_rc_tdata(axis_rc_tdata), + .s_axis_rc_tkeep(axis_rc_tkeep), + .s_axis_rc_tlast(axis_rc_tlast), + .s_axis_rc_tready(axis_rc_tready), + .s_axis_rc_tuser(axis_rc_tuser), + .s_axis_rc_tvalid(axis_rc_tvalid), + + .s_axis_cq_tdata(axis_cq_tdata), + .s_axis_cq_tkeep(axis_cq_tkeep), + .s_axis_cq_tlast(axis_cq_tlast), + .s_axis_cq_tready(axis_cq_tready), + .s_axis_cq_tuser(axis_cq_tuser), + .s_axis_cq_tvalid(axis_cq_tvalid), + + .m_axis_cc_tdata(axis_cc_tdata), + .m_axis_cc_tkeep(axis_cc_tkeep), + .m_axis_cc_tlast(axis_cc_tlast), + .m_axis_cc_tready(axis_cc_tready), + .m_axis_cc_tuser(axis_cc_tuser), + .m_axis_cc_tvalid(axis_cc_tvalid), + + .s_axis_rq_seq_num_0(pcie_rq_seq_num0), + .s_axis_rq_seq_num_valid_0(pcie_rq_seq_num_vld0), + .s_axis_rq_seq_num_1(pcie_rq_seq_num1), + .s_axis_rq_seq_num_valid_1(pcie_rq_seq_num_vld1), + + .cfg_max_payload(cfg_max_payload), + .cfg_max_read_req(cfg_max_read_req), + + .cfg_mgmt_addr(cfg_mgmt_addr), + .cfg_mgmt_function_number(cfg_mgmt_function_number), + .cfg_mgmt_write(cfg_mgmt_write), + .cfg_mgmt_write_data(cfg_mgmt_write_data), + .cfg_mgmt_byte_enable(cfg_mgmt_byte_enable), + .cfg_mgmt_read(cfg_mgmt_read), + .cfg_mgmt_read_data(cfg_mgmt_read_data), + .cfg_mgmt_read_write_done(cfg_mgmt_read_write_done), + + .cfg_fc_ph(cfg_fc_ph), + .cfg_fc_pd(cfg_fc_pd), + .cfg_fc_nph(cfg_fc_nph), + .cfg_fc_npd(cfg_fc_npd), + .cfg_fc_cplh(cfg_fc_cplh), + .cfg_fc_cpld(cfg_fc_cpld), + .cfg_fc_sel(cfg_fc_sel), + + .cfg_interrupt_msi_enable(cfg_interrupt_msi_enable), + .cfg_interrupt_msi_mmenable(cfg_interrupt_msi_mmenable), + .cfg_interrupt_msi_mask_update(cfg_interrupt_msi_mask_update), + .cfg_interrupt_msi_data(cfg_interrupt_msi_data), + .cfg_interrupt_msi_select(cfg_interrupt_msi_select), + .cfg_interrupt_msi_int(cfg_interrupt_msi_int), + .cfg_interrupt_msi_pending_status(cfg_interrupt_msi_pending_status), + .cfg_interrupt_msi_pending_status_data_enable(cfg_interrupt_msi_pending_status_data_enable), + .cfg_interrupt_msi_pending_status_function_num(cfg_interrupt_msi_pending_status_function_num), + .cfg_interrupt_msi_sent(cfg_interrupt_msi_sent), + .cfg_interrupt_msi_fail(cfg_interrupt_msi_fail), + .cfg_interrupt_msi_attr(cfg_interrupt_msi_attr), + .cfg_interrupt_msi_tph_present(cfg_interrupt_msi_tph_present), + .cfg_interrupt_msi_tph_type(cfg_interrupt_msi_tph_type), + .cfg_interrupt_msi_tph_st_tag(cfg_interrupt_msi_tph_st_tag), + .cfg_interrupt_msi_function_number(cfg_interrupt_msi_function_number), + + .status_error_cor(status_error_cor), + .status_error_uncor(status_error_uncor) +); + +endmodule + +`resetall diff --git a/fpga/lib/pcie/example/ExaNIC_X25/fpga/rtl/fpga_core.v b/fpga/lib/pcie/example/ExaNIC_X25/fpga/rtl/fpga_core.v new file mode 100644 index 000000000..4f621471b --- /dev/null +++ b/fpga/lib/pcie/example/ExaNIC_X25/fpga/rtl/fpga_core.v @@ -0,0 +1,274 @@ +/* + +Copyright (c) 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 1ns / 1ps +`default_nettype none + +/* + * FPGA core logic + */ +module fpga_core # +( + parameter AXIS_PCIE_DATA_WIDTH = 256, + parameter AXIS_PCIE_KEEP_WIDTH = (AXIS_PCIE_DATA_WIDTH/32), + parameter AXIS_PCIE_RC_USER_WIDTH = AXIS_PCIE_DATA_WIDTH < 512 ? 75 : 161, + parameter AXIS_PCIE_RQ_USER_WIDTH = AXIS_PCIE_DATA_WIDTH < 512 ? 60 : 137, + parameter AXIS_PCIE_CQ_USER_WIDTH = AXIS_PCIE_DATA_WIDTH < 512 ? 85 : 183, + parameter AXIS_PCIE_CC_USER_WIDTH = AXIS_PCIE_DATA_WIDTH < 512 ? 33 : 81, + parameter RQ_SEQ_NUM_WIDTH = AXIS_PCIE_RQ_USER_WIDTH == 60 ? 4 : 6, + parameter RQ_SEQ_NUM_ENABLE = 1, + parameter PCIE_TAG_COUNT = 64, + parameter BAR0_APERTURE = 24, + parameter BAR2_APERTURE = 24 +) +( + /* + * Clock: 250 MHz + * Synchronous reset + */ + input wire clk, + input wire rst, + + /* + * GPIO + */ + output wire [1:0] sfp_1_led, + output wire [1:0] sfp_2_led, + output wire [1:0] sma_led, + + /* + * PCIe + */ + output wire [AXIS_PCIE_DATA_WIDTH-1:0] m_axis_rq_tdata, + output wire [AXIS_PCIE_KEEP_WIDTH-1:0] m_axis_rq_tkeep, + output wire m_axis_rq_tlast, + input wire m_axis_rq_tready, + output wire [AXIS_PCIE_RQ_USER_WIDTH-1:0] m_axis_rq_tuser, + output wire m_axis_rq_tvalid, + + input wire [AXIS_PCIE_DATA_WIDTH-1:0] s_axis_rc_tdata, + input wire [AXIS_PCIE_KEEP_WIDTH-1:0] s_axis_rc_tkeep, + input wire s_axis_rc_tlast, + output wire s_axis_rc_tready, + input wire [AXIS_PCIE_RC_USER_WIDTH-1:0] s_axis_rc_tuser, + input wire s_axis_rc_tvalid, + + input wire [AXIS_PCIE_DATA_WIDTH-1:0] s_axis_cq_tdata, + input wire [AXIS_PCIE_KEEP_WIDTH-1:0] s_axis_cq_tkeep, + input wire s_axis_cq_tlast, + output wire s_axis_cq_tready, + input wire [AXIS_PCIE_CQ_USER_WIDTH-1:0] s_axis_cq_tuser, + input wire s_axis_cq_tvalid, + + output wire [AXIS_PCIE_DATA_WIDTH-1:0] m_axis_cc_tdata, + output wire [AXIS_PCIE_KEEP_WIDTH-1:0] m_axis_cc_tkeep, + output wire m_axis_cc_tlast, + input wire m_axis_cc_tready, + output wire [AXIS_PCIE_CC_USER_WIDTH-1:0] m_axis_cc_tuser, + output wire m_axis_cc_tvalid, + + input wire [RQ_SEQ_NUM_WIDTH-1:0] s_axis_rq_seq_num_0, + input wire s_axis_rq_seq_num_valid_0, + input wire [RQ_SEQ_NUM_WIDTH-1:0] s_axis_rq_seq_num_1, + input wire s_axis_rq_seq_num_valid_1, + + input wire [2:0] cfg_max_payload, + input wire [2:0] cfg_max_read_req, + + output wire [9:0] cfg_mgmt_addr, + output wire [7:0] cfg_mgmt_function_number, + output wire cfg_mgmt_write, + output wire [31:0] cfg_mgmt_write_data, + output wire [3:0] cfg_mgmt_byte_enable, + output wire cfg_mgmt_read, + input wire [31:0] cfg_mgmt_read_data, + input wire cfg_mgmt_read_write_done, + + input wire [7:0] cfg_fc_ph, + input wire [11:0] cfg_fc_pd, + input wire [7:0] cfg_fc_nph, + input wire [11:0] cfg_fc_npd, + input wire [7:0] cfg_fc_cplh, + input wire [11:0] cfg_fc_cpld, + output wire [2:0] cfg_fc_sel, + + input wire [3:0] cfg_interrupt_msi_enable, + input wire [11:0] cfg_interrupt_msi_mmenable, + input wire cfg_interrupt_msi_mask_update, + input wire [31:0] cfg_interrupt_msi_data, + output wire [3:0] cfg_interrupt_msi_select, + output wire [31:0] cfg_interrupt_msi_int, + output wire [31:0] cfg_interrupt_msi_pending_status, + output wire cfg_interrupt_msi_pending_status_data_enable, + output wire [3:0] cfg_interrupt_msi_pending_status_function_num, + input wire cfg_interrupt_msi_sent, + input wire cfg_interrupt_msi_fail, + output wire [2:0] cfg_interrupt_msi_attr, + output wire cfg_interrupt_msi_tph_present, + output wire [1:0] cfg_interrupt_msi_tph_type, + output wire [8:0] cfg_interrupt_msi_tph_st_tag, + output wire [3:0] cfg_interrupt_msi_function_number, + + output wire status_error_cor, + output wire status_error_uncor +); + +assign sfp_1_led = 2'b00; +assign sfp_2_led = 2'b00; +assign sma_led = 2'b00; + +example_core_pcie_us #( + .AXIS_PCIE_DATA_WIDTH(AXIS_PCIE_DATA_WIDTH), + .AXIS_PCIE_KEEP_WIDTH(AXIS_PCIE_KEEP_WIDTH), + .AXIS_PCIE_RC_USER_WIDTH(AXIS_PCIE_RC_USER_WIDTH), + .AXIS_PCIE_RQ_USER_WIDTH(AXIS_PCIE_RQ_USER_WIDTH), + .AXIS_PCIE_CQ_USER_WIDTH(AXIS_PCIE_CQ_USER_WIDTH), + .AXIS_PCIE_CC_USER_WIDTH(AXIS_PCIE_CC_USER_WIDTH), + .RQ_SEQ_NUM_WIDTH(RQ_SEQ_NUM_WIDTH), + .RQ_SEQ_NUM_ENABLE(RQ_SEQ_NUM_ENABLE), + .PCIE_TAG_COUNT(PCIE_TAG_COUNT), + .READ_OP_TABLE_SIZE(PCIE_TAG_COUNT), + .READ_TX_LIMIT(2**(RQ_SEQ_NUM_WIDTH-1)), + .READ_TX_FC_ENABLE(1), + .WRITE_OP_TABLE_SIZE(2**(RQ_SEQ_NUM_WIDTH-1)), + .WRITE_TX_LIMIT(2**(RQ_SEQ_NUM_WIDTH-1)), + .WRITE_TX_FC_ENABLE(1), + .BAR0_APERTURE(BAR0_APERTURE), + .BAR2_APERTURE(BAR2_APERTURE) +) +example_core_pcie_us_inst ( + .clk(clk), + .rst(rst), + + /* + * AXI input (RC) + */ + .s_axis_rc_tdata(s_axis_rc_tdata), + .s_axis_rc_tkeep(s_axis_rc_tkeep), + .s_axis_rc_tvalid(s_axis_rc_tvalid), + .s_axis_rc_tready(s_axis_rc_tready), + .s_axis_rc_tlast(s_axis_rc_tlast), + .s_axis_rc_tuser(s_axis_rc_tuser), + + /* + * AXI output (RQ) + */ + .m_axis_rq_tdata(m_axis_rq_tdata), + .m_axis_rq_tkeep(m_axis_rq_tkeep), + .m_axis_rq_tvalid(m_axis_rq_tvalid), + .m_axis_rq_tready(m_axis_rq_tready), + .m_axis_rq_tlast(m_axis_rq_tlast), + .m_axis_rq_tuser(m_axis_rq_tuser), + + /* + * AXI input (CQ) + */ + .s_axis_cq_tdata(s_axis_cq_tdata), + .s_axis_cq_tkeep(s_axis_cq_tkeep), + .s_axis_cq_tvalid(s_axis_cq_tvalid), + .s_axis_cq_tready(s_axis_cq_tready), + .s_axis_cq_tlast(s_axis_cq_tlast), + .s_axis_cq_tuser(s_axis_cq_tuser), + + /* + * AXI output (CC) + */ + .m_axis_cc_tdata(m_axis_cc_tdata), + .m_axis_cc_tkeep(m_axis_cc_tkeep), + .m_axis_cc_tvalid(m_axis_cc_tvalid), + .m_axis_cc_tready(m_axis_cc_tready), + .m_axis_cc_tlast(m_axis_cc_tlast), + .m_axis_cc_tuser(m_axis_cc_tuser), + + /* + * Transmit sequence number input + */ + .s_axis_rq_seq_num_0(s_axis_rq_seq_num_0), + .s_axis_rq_seq_num_valid_0(s_axis_rq_seq_num_valid_0), + .s_axis_rq_seq_num_1(s_axis_rq_seq_num_1), + .s_axis_rq_seq_num_valid_1(s_axis_rq_seq_num_valid_1), + + /* + * Flow control + */ + .cfg_fc_ph(cfg_fc_ph), + .cfg_fc_pd(cfg_fc_pd), + .cfg_fc_nph(cfg_fc_nph), + .cfg_fc_npd(cfg_fc_npd), + .cfg_fc_cplh(cfg_fc_cplh), + .cfg_fc_cpld(cfg_fc_cpld), + .cfg_fc_sel(cfg_fc_sel), + + /* + * Configuration interface + */ + .cfg_mgmt_addr(cfg_mgmt_addr), + .cfg_mgmt_function_number(cfg_mgmt_function_number), + .cfg_mgmt_write(cfg_mgmt_write), + .cfg_mgmt_write_data(cfg_mgmt_write_data), + .cfg_mgmt_byte_enable(cfg_mgmt_byte_enable), + .cfg_mgmt_read(cfg_mgmt_read), + .cfg_mgmt_read_data(cfg_mgmt_read_data), + .cfg_mgmt_read_write_done(cfg_mgmt_read_write_done), + + /* + * Interrupt interface + */ + .cfg_interrupt_msi_enable(cfg_interrupt_msi_enable), + .cfg_interrupt_msi_vf_enable(8'd0), + .cfg_interrupt_msi_mmenable(cfg_interrupt_msi_mmenable), + .cfg_interrupt_msi_mask_update(cfg_interrupt_msi_mask_update), + .cfg_interrupt_msi_data(cfg_interrupt_msi_data), + .cfg_interrupt_msi_select(cfg_interrupt_msi_select), + .cfg_interrupt_msi_int(cfg_interrupt_msi_int), + .cfg_interrupt_msi_pending_status(cfg_interrupt_msi_pending_status), + .cfg_interrupt_msi_pending_status_data_enable(cfg_interrupt_msi_pending_status_data_enable), + .cfg_interrupt_msi_pending_status_function_num(cfg_interrupt_msi_pending_status_function_num), + .cfg_interrupt_msi_sent(cfg_interrupt_msi_sent), + .cfg_interrupt_msi_fail(cfg_interrupt_msi_fail), + .cfg_interrupt_msi_attr(cfg_interrupt_msi_attr), + .cfg_interrupt_msi_tph_present(cfg_interrupt_msi_tph_present), + .cfg_interrupt_msi_tph_type(cfg_interrupt_msi_tph_type), + .cfg_interrupt_msi_tph_st_tag(cfg_interrupt_msi_tph_st_tag), + .cfg_interrupt_msi_function_number(cfg_interrupt_msi_function_number), + + /* + * Configuration + */ + .cfg_max_read_req(cfg_max_read_req), + .cfg_max_payload(cfg_max_payload), + + /* + * Status + */ + .status_error_cor(status_error_cor), + .status_error_uncor(status_error_uncor) +); + +endmodule + +`resetall diff --git a/fpga/lib/pcie/example/ExaNIC_X25/fpga/rtl/sync_reset.v b/fpga/lib/pcie/example/ExaNIC_X25/fpga/rtl/sync_reset.v new file mode 100644 index 000000000..1fd24d361 --- /dev/null +++ b/fpga/lib/pcie/example/ExaNIC_X25/fpga/rtl/sync_reset.v @@ -0,0 +1,56 @@ +/* + +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 active-high asynchronous reset signal to a given clock by + * using a pipeline of N registers. + */ +module sync_reset #( + parameter N=2 // depth of synchronizer +)( + input wire clk, + input wire rst, + output wire sync_reset_out +); + +reg [N-1:0] sync_reg = {N{1'b1}}; + +assign sync_reset_out = sync_reg[N-1]; + +always @(posedge clk or posedge rst) begin + if (rst) + sync_reg <= {N{1'b1}}; + else + sync_reg <= {sync_reg[N-2:0], 1'b0}; +end + +endmodule + +`resetall diff --git a/fpga/lib/pcie/example/ExaNIC_X25/fpga/rtl/sync_signal.v b/fpga/lib/pcie/example/ExaNIC_X25/fpga/rtl/sync_signal.v new file mode 100644 index 000000000..74b855fa1 --- /dev/null +++ b/fpga/lib/pcie/example/ExaNIC_X25/fpga/rtl/sync_signal.v @@ -0,0 +1,62 @@ +/* + +Copyright (c) 2014-2018 Alex Forencich + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +*/ + +// Language: Verilog-2001 + +`resetall +`timescale 1 ns / 1 ps +`default_nettype none + +/* + * Synchronizes an asyncronous signal to a given clock by using a pipeline of + * two registers. + */ +module sync_signal #( + parameter WIDTH=1, // width of the input and output signals + parameter N=2 // depth of synchronizer +)( + input wire clk, + input wire [WIDTH-1:0] in, + output wire [WIDTH-1:0] out +); + +reg [WIDTH-1:0] sync_reg[N-1:0]; + +/* + * The synchronized output is the last register in the pipeline. + */ +assign out = sync_reg[N-1]; + +integer k; + +always @(posedge clk) begin + sync_reg[0] <= in; + for (k = 1; k < N; k = k + 1) begin + sync_reg[k] <= sync_reg[k-1]; + end +end + +endmodule + +`resetall diff --git a/fpga/lib/pcie/example/ExaNIC_X25/fpga/tb/fpga_core/Makefile b/fpga/lib/pcie/example/ExaNIC_X25/fpga/tb/fpga_core/Makefile new file mode 100644 index 000000000..5f08ec54c --- /dev/null +++ b/fpga/lib/pcie/example/ExaNIC_X25/fpga/tb/fpga_core/Makefile @@ -0,0 +1,123 @@ +# Copyright (c) 2020 Alex Forencich +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +TOPLEVEL_LANG = verilog + +SIM ?= icarus +WAVES ?= 0 + +COCOTB_HDL_TIMEUNIT = 1ns +COCOTB_HDL_TIMEPRECISION = 1ps + +DUT = fpga_core +TOPLEVEL = $(DUT) +MODULE = test_$(DUT) +VERILOG_SOURCES += ../../rtl/$(DUT).v +VERILOG_SOURCES += ../../rtl/common/example_core_pcie_us.v +VERILOG_SOURCES += ../../rtl/common/example_core_pcie.v +VERILOG_SOURCES += ../../rtl/common/example_core.v +VERILOG_SOURCES += ../../rtl/common/axi_ram.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_if.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_if_rc.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_if_rq.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_if_cq.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_if_cc.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_cfg.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_msi.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_axil_master.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_axi_master.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_axi_master_rd.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_axi_master_wr.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_tlp_demux_bar.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_tlp_demux.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_tlp_mux.v +VERILOG_SOURCES += ../../lib/pcie/rtl/dma_if_pcie.v +VERILOG_SOURCES += ../../lib/pcie/rtl/dma_if_pcie_rd.v +VERILOG_SOURCES += ../../lib/pcie/rtl/dma_if_pcie_wr.v +VERILOG_SOURCES += ../../lib/pcie/rtl/dma_psdpram.v +VERILOG_SOURCES += ../../lib/pcie/rtl/arbiter.v +VERILOG_SOURCES += ../../lib/pcie/rtl/priority_encoder.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pulse_merge.v + +# module parameters +export PARAM_AXIS_PCIE_DATA_WIDTH ?= 256 +export PARAM_AXIS_PCIE_KEEP_WIDTH ?= $(shell expr $(PARAM_AXIS_PCIE_DATA_WIDTH) / 32 ) +export PARAM_AXIS_PCIE_RQ_USER_WIDTH ?= $(if $(filter-out 512,$(PARAM_AXIS_PCIE_DATA_WIDTH)),62,137) +export PARAM_AXIS_PCIE_RC_USER_WIDTH ?= $(if $(filter-out 512,$(PARAM_AXIS_PCIE_DATA_WIDTH)),75,161) +export PARAM_AXIS_PCIE_CQ_USER_WIDTH ?= $(if $(filter-out 512,$(PARAM_AXIS_PCIE_DATA_WIDTH)),88,183) +export PARAM_AXIS_PCIE_CC_USER_WIDTH ?= $(if $(filter-out 512,$(PARAM_AXIS_PCIE_DATA_WIDTH)),33,81) +export PARAM_RQ_SEQ_NUM_WIDTH ?= 6 +export PARAM_RQ_SEQ_NUM_ENABLE ?= 1 +export PARAM_PCIE_TAG_COUNT ?= 64 +export PARAM_BAR0_APERTURE ?= 24 +export PARAM_BAR2_APERTURE ?= 24 + +ifeq ($(SIM), icarus) + PLUSARGS += -fst + + COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_DATA_WIDTH=$(PARAM_AXIS_PCIE_DATA_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_KEEP_WIDTH=$(PARAM_AXIS_PCIE_KEEP_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_RQ_USER_WIDTH=$(PARAM_AXIS_PCIE_RQ_USER_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_RC_USER_WIDTH=$(PARAM_AXIS_PCIE_RC_USER_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_CQ_USER_WIDTH=$(PARAM_AXIS_PCIE_CQ_USER_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_CC_USER_WIDTH=$(PARAM_AXIS_PCIE_CC_USER_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).RQ_SEQ_NUM_WIDTH=$(PARAM_RQ_SEQ_NUM_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).RQ_SEQ_NUM_ENABLE=$(PARAM_RQ_SEQ_NUM_ENABLE) + COMPILE_ARGS += -P $(TOPLEVEL).PCIE_TAG_COUNT=$(PARAM_PCIE_TAG_COUNT) + COMPILE_ARGS += -P $(TOPLEVEL).BAR0_APERTURE=$(PARAM_BAR0_APERTURE) + COMPILE_ARGS += -P $(TOPLEVEL).BAR2_APERTURE=$(PARAM_BAR2_APERTURE) + + ifeq ($(WAVES), 1) + VERILOG_SOURCES += iverilog_dump.v + COMPILE_ARGS += -s iverilog_dump + endif +else ifeq ($(SIM), verilator) + COMPILE_ARGS += -Wno-SELRANGE -Wno-WIDTH + + COMPILE_ARGS += -GAXIS_PCIE_DATA_WIDTH=$(PARAM_AXIS_PCIE_DATA_WIDTH) + COMPILE_ARGS += -GAXIS_PCIE_KEEP_WIDTH=$(PARAM_AXIS_PCIE_KEEP_WIDTH) + COMPILE_ARGS += -GAXIS_PCIE_RQ_USER_WIDTH=$(PARAM_AXIS_PCIE_RQ_USER_WIDTH) + COMPILE_ARGS += -GAXIS_PCIE_RC_USER_WIDTH=$(PARAM_AXIS_PCIE_RC_USER_WIDTH) + COMPILE_ARGS += -GAXIS_PCIE_CQ_USER_WIDTH=$(PARAM_AXIS_PCIE_CQ_USER_WIDTH) + COMPILE_ARGS += -GAXIS_PCIE_CC_USER_WIDTH=$(PARAM_AXIS_PCIE_CC_USER_WIDTH) + COMPILE_ARGS += -GRQ_SEQ_NUM_WIDTH=$(PARAM_RQ_SEQ_NUM_WIDTH) + COMPILE_ARGS += -GRQ_SEQ_NUM_ENABLE=$(PARAM_RQ_SEQ_NUM_ENABLE) + COMPILE_ARGS += -GPCIE_TAG_COUNT=$(PARAM_PCIE_TAG_COUNT) + COMPILE_ARGS += -GBAR0_APERTURE=$(PARAM_BAR0_APERTURE) + COMPILE_ARGS += -GBAR2_APERTURE=$(PARAM_BAR2_APERTURE) + + ifeq ($(WAVES), 1) + COMPILE_ARGS += --trace-fst + endif +endif + +include $(shell cocotb-config --makefiles)/Makefile.sim + +iverilog_dump.v: + echo 'module iverilog_dump();' > $@ + echo 'initial begin' >> $@ + echo ' $$dumpfile("$(TOPLEVEL).fst");' >> $@ + echo ' $$dumpvars(0, $(TOPLEVEL));' >> $@ + echo 'end' >> $@ + echo 'endmodule' >> $@ + +clean:: + @rm -rf iverilog_dump.v + @rm -rf dump.fst $(TOPLEVEL).fst diff --git a/fpga/lib/pcie/example/ExaNIC_X25/fpga/tb/fpga_core/test_fpga_core.py b/fpga/lib/pcie/example/ExaNIC_X25/fpga/tb/fpga_core/test_fpga_core.py new file mode 100644 index 000000000..a4258a9a8 --- /dev/null +++ b/fpga/lib/pcie/example/ExaNIC_X25/fpga/tb/fpga_core/test_fpga_core.py @@ -0,0 +1,472 @@ +""" + +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 + +import cocotb_test.simulator + +import cocotb +from cocotb.log import SimLog +from cocotb.triggers import RisingEdge, FallingEdge, Timer + +from cocotbext.axi import AxiStreamBus +from cocotbext.pcie.core import RootComplex +from cocotbext.pcie.xilinx.us import UltraScalePlusPcieDevice + + +class TB(object): + def __init__(self, dut): + self.dut = dut + + self.log = SimLog("cocotb.tb") + self.log.setLevel(logging.DEBUG) + + # PCIe + self.rc = RootComplex() + + self.dev = UltraScalePlusPcieDevice( + # configuration options + pcie_generation=3, + pcie_link_width=8, + user_clk_frequency=250e6, + alignment="dword", + cq_cc_straddle=False, + rq_rc_straddle=False, + rc_4tlp_straddle=False, + enable_pf1=False, + enable_client_tag=True, + enable_extended_tag=True, + enable_parity=False, + enable_rx_msg_interface=False, + enable_sriov=False, + enable_extended_configuration=False, + + enable_pf0_msi=True, + enable_pf1_msi=False, + + # signals + # Clock and Reset Interface + user_clk=dut.clk, + user_reset=dut.rst, + # user_lnk_up + # sys_clk + # sys_clk_gt + # sys_reset + # phy_rdy_out + + # Requester reQuest Interface + rq_bus=AxiStreamBus.from_prefix(dut, "m_axis_rq"), + pcie_rq_seq_num0=dut.s_axis_rq_seq_num_0, + pcie_rq_seq_num_vld0=dut.s_axis_rq_seq_num_valid_0, + pcie_rq_seq_num1=dut.s_axis_rq_seq_num_1, + pcie_rq_seq_num_vld1=dut.s_axis_rq_seq_num_valid_1, + # pcie_rq_tag0 + # pcie_rq_tag1 + # pcie_rq_tag_av + # pcie_rq_tag_vld0 + # pcie_rq_tag_vld1 + + # Requester Completion Interface + rc_bus=AxiStreamBus.from_prefix(dut, "s_axis_rc"), + + # Completer reQuest Interface + cq_bus=AxiStreamBus.from_prefix(dut, "s_axis_cq"), + # pcie_cq_np_req + # pcie_cq_np_req_count + + # Completer Completion Interface + cc_bus=AxiStreamBus.from_prefix(dut, "m_axis_cc"), + + # Transmit Flow Control Interface + # pcie_tfc_nph_av=dut.pcie_tfc_nph_av, + # pcie_tfc_npd_av=dut.pcie_tfc_npd_av, + + # Configuration Management Interface + cfg_mgmt_addr=dut.cfg_mgmt_addr, + cfg_mgmt_function_number=dut.cfg_mgmt_function_number, + cfg_mgmt_write=dut.cfg_mgmt_write, + cfg_mgmt_write_data=dut.cfg_mgmt_write_data, + cfg_mgmt_byte_enable=dut.cfg_mgmt_byte_enable, + cfg_mgmt_read=dut.cfg_mgmt_read, + cfg_mgmt_read_data=dut.cfg_mgmt_read_data, + cfg_mgmt_read_write_done=dut.cfg_mgmt_read_write_done, + # cfg_mgmt_debug_access + + # Configuration Status Interface + # cfg_phy_link_down + # cfg_phy_link_status + # cfg_negotiated_width + # cfg_current_speed + cfg_max_payload=dut.cfg_max_payload, + cfg_max_read_req=dut.cfg_max_read_req, + # cfg_function_status + # cfg_vf_status + # cfg_function_power_state + # cfg_vf_power_state + # cfg_link_power_state + # cfg_err_cor_out + # cfg_err_nonfatal_out + # cfg_err_fatal_out + # cfg_local_error_out + # cfg_local_error_valid + # cfg_rx_pm_state + # cfg_tx_pm_state + # cfg_ltssm_state + # cfg_rcb_status + # cfg_obff_enable + # cfg_pl_status_change + # cfg_tph_requester_enable + # cfg_tph_st_mode + # cfg_vf_tph_requester_enable + # cfg_vf_tph_st_mode + + # Configuration Received Message Interface + # cfg_msg_received + # cfg_msg_received_data + # cfg_msg_received_type + + # Configuration Transmit Message Interface + # cfg_msg_transmit + # cfg_msg_transmit_type + # cfg_msg_transmit_data + # cfg_msg_transmit_done + + # Configuration Flow Control Interface + cfg_fc_ph=dut.cfg_fc_ph, + cfg_fc_pd=dut.cfg_fc_pd, + cfg_fc_nph=dut.cfg_fc_nph, + cfg_fc_npd=dut.cfg_fc_npd, + cfg_fc_cplh=dut.cfg_fc_cplh, + cfg_fc_cpld=dut.cfg_fc_cpld, + cfg_fc_sel=dut.cfg_fc_sel, + + # Configuration Control Interface + # cfg_hot_reset_in + # cfg_hot_reset_out + # cfg_config_space_enable + # cfg_dsn + # cfg_bus_number + # cfg_ds_port_number + # cfg_ds_bus_number + # cfg_ds_device_number + # cfg_ds_function_number + # cfg_power_state_change_ack + # cfg_power_state_change_interrupt + cfg_err_cor_in=dut.status_error_cor, + cfg_err_uncor_in=dut.status_error_uncor, + # cfg_flr_in_process + # cfg_flr_done + # cfg_vf_flr_in_process + # cfg_vf_flr_func_num + # cfg_vf_flr_done + # cfg_pm_aspm_l1_entry_reject + # cfg_pm_aspm_tx_l0s_entry_disable + # cfg_req_pm_transition_l23_ready + # cfg_link_training_enable + + # Configuration Interrupt Controller Interface + # cfg_interrupt_int + # cfg_interrupt_sent + # cfg_interrupt_pending + cfg_interrupt_msi_enable=dut.cfg_interrupt_msi_enable, + cfg_interrupt_msi_mmenable=dut.cfg_interrupt_msi_mmenable, + cfg_interrupt_msi_mask_update=dut.cfg_interrupt_msi_mask_update, + cfg_interrupt_msi_data=dut.cfg_interrupt_msi_data, + # cfg_interrupt_msi_select=dut.cfg_interrupt_msi_select, + cfg_interrupt_msi_int=dut.cfg_interrupt_msi_int, + cfg_interrupt_msi_pending_status=dut.cfg_interrupt_msi_pending_status, + cfg_interrupt_msi_pending_status_data_enable=dut.cfg_interrupt_msi_pending_status_data_enable, + # cfg_interrupt_msi_pending_status_function_num=dut.cfg_interrupt_msi_pending_status_function_num, + cfg_interrupt_msi_sent=dut.cfg_interrupt_msi_sent, + cfg_interrupt_msi_fail=dut.cfg_interrupt_msi_fail, + # cfg_interrupt_msix_enable + # cfg_interrupt_msix_mask + # cfg_interrupt_msix_vf_enable + # cfg_interrupt_msix_vf_mask + # cfg_interrupt_msix_address + # cfg_interrupt_msix_data + # cfg_interrupt_msix_int + # cfg_interrupt_msix_vec_pending + # cfg_interrupt_msix_vec_pending_status + cfg_interrupt_msi_attr=dut.cfg_interrupt_msi_attr, + cfg_interrupt_msi_tph_present=dut.cfg_interrupt_msi_tph_present, + cfg_interrupt_msi_tph_type=dut.cfg_interrupt_msi_tph_type, + # cfg_interrupt_msi_tph_st_tag=dut.cfg_interrupt_msi_tph_st_tag, + # cfg_interrupt_msi_function_number=dut.cfg_interrupt_msi_function_number, + + # Configuration Extend Interface + # cfg_ext_read_received + # cfg_ext_write_received + # cfg_ext_register_number + # cfg_ext_function_number + # cfg_ext_write_data + # cfg_ext_write_byte_enable + # cfg_ext_read_data + # cfg_ext_read_data_valid + ) + + # self.dev.log.setLevel(logging.DEBUG) + + self.rc.make_port().connect(self.dev) + + self.dev.functions[0].msi_multiple_message_capable = 5 + + self.dev.functions[0].configure_bar(0, 2**len(dut.example_core_pcie_us_inst.core_pcie_inst.axil_ctrl_awaddr)) + self.dev.functions[0].configure_bar(2, 2**len(dut.example_core_pcie_us_inst.core_pcie_inst.axi_ram_awaddr)) + + async def init(self): + + await FallingEdge(self.dut.rst) + await Timer(100, 'ns') + + await self.rc.enumerate(enable_bus_mastering=True, configure_msi=True) + + +@cocotb.test() +async def run_test(dut): + + tb = TB(dut) + + await tb.init() + + mem = tb.rc.mem_pool.alloc_region(16*1024*1024) + mem_base = mem.get_absolute_address(0) + + dev_pf0_bar0 = tb.rc.tree[0][0].bar_window[0] + dev_pf0_bar2 = tb.rc.tree[0][0].bar_window[2] + + tb.log.info("Test memory write to BAR 2") + + test_data = b'\x11\x22\x33\x44' + await dev_pf0_bar2.write(0, test_data) + + await Timer(100, 'ns') + + tb.log.info("Test memory read from BAR 2") + + val = await dev_pf0_bar2.read(0, len(test_data), timeout=1000) + tb.log.info("Read data: %s", val) + assert val == test_data + + tb.log.info("Test DMA") + + # write packet data + mem[0:1024] = bytearray([x % 256 for x in range(1024)]) + + # enable DMA + await dev_pf0_bar0.write_dword(0x000000, 1) + + # write pcie read descriptor + await dev_pf0_bar0.write_dword(0x000100, (mem_base+0x0000) & 0xffffffff) + await dev_pf0_bar0.write_dword(0x000104, (mem_base+0x0000 >> 32) & 0xffffffff) + await dev_pf0_bar0.write_dword(0x000108, 0x100) + await dev_pf0_bar0.write_dword(0x000110, 0x400) + await dev_pf0_bar0.write_dword(0x000114, 0xAA) + + await Timer(2000, 'ns') + + # read status + val = await dev_pf0_bar0.read_dword(0x000118) + tb.log.info("Status: 0x%x", val) + assert val == 0x800000AA + + # write pcie write descriptor + await dev_pf0_bar0.write_dword(0x000200, (mem_base+0x1000) & 0xffffffff) + await dev_pf0_bar0.write_dword(0x000204, (mem_base+0x1000 >> 32) & 0xffffffff) + await dev_pf0_bar0.write_dword(0x000208, 0x100) + await dev_pf0_bar0.write_dword(0x000210, 0x400) + await dev_pf0_bar0.write_dword(0x000214, 0x55) + + await Timer(2000, 'ns') + + # read status + val = await dev_pf0_bar0.read_dword(0x000218) + tb.log.info("Status: 0x%x", val) + assert val == 0x80000055 + + tb.log.info("%s", mem.hexdump_str(0x1000, 64)) + + assert mem[0:1024] == mem[0x1000:0x1000+1024] + + tb.log.info("Test DMA block operations") + + # write packet data + mem[0:1024] = bytearray([x % 256 for x in range(1024)]) + + # enable DMA + await dev_pf0_bar0.write_dword(0x000000, 1) + # disable interrupts + await dev_pf0_bar0.write_dword(0x000008, 0) + + # configure operation (read) + # DMA base address + await dev_pf0_bar0.write_dword(0x001080, (mem_base+0x0000) & 0xffffffff) + await dev_pf0_bar0.write_dword(0x001084, (mem_base+0x0000 >> 32) & 0xffffffff) + # DMA offset address + await dev_pf0_bar0.write_dword(0x001088, 0) + await dev_pf0_bar0.write_dword(0x00108c, 0) + # DMA offset mask + await dev_pf0_bar0.write_dword(0x001090, 0x000003ff) + await dev_pf0_bar0.write_dword(0x001094, 0) + # DMA stride + await dev_pf0_bar0.write_dword(0x001098, 256) + await dev_pf0_bar0.write_dword(0x00109c, 0) + # RAM base address + await dev_pf0_bar0.write_dword(0x0010c0, 0) + await dev_pf0_bar0.write_dword(0x0010c4, 0) + # RAM offset address + await dev_pf0_bar0.write_dword(0x0010c8, 0) + await dev_pf0_bar0.write_dword(0x0010cc, 0) + # RAM offset mask + await dev_pf0_bar0.write_dword(0x0010d0, 0x000003ff) + await dev_pf0_bar0.write_dword(0x0010d4, 0) + # RAM stride + await dev_pf0_bar0.write_dword(0x0010d8, 256) + await dev_pf0_bar0.write_dword(0x0010dc, 0) + # clear cycle count + await dev_pf0_bar0.write_dword(0x001008, 0) + await dev_pf0_bar0.write_dword(0x00100c, 0) + # block length + await dev_pf0_bar0.write_dword(0x001010, 256) + # block count + await dev_pf0_bar0.write_dword(0x001018, 32) + await dev_pf0_bar0.write_dword(0x00101c, 0) + # start + await dev_pf0_bar0.write_dword(0x001000, 1) + + await Timer(2000, 'ns') + + # configure operation (write) + # DMA base address + await dev_pf0_bar0.write_dword(0x001180, (mem_base+0x0000) & 0xffffffff) + await dev_pf0_bar0.write_dword(0x001184, (mem_base+0x0000 >> 32) & 0xffffffff) + # DMA offset address + await dev_pf0_bar0.write_dword(0x001188, 0) + await dev_pf0_bar0.write_dword(0x00118c, 0) + # DMA offset mask + await dev_pf0_bar0.write_dword(0x001190, 0x000003ff) + await dev_pf0_bar0.write_dword(0x001194, 0) + # DMA stride + await dev_pf0_bar0.write_dword(0x001198, 256) + await dev_pf0_bar0.write_dword(0x00119c, 0) + # RAM base address + await dev_pf0_bar0.write_dword(0x0011c0, 0) + await dev_pf0_bar0.write_dword(0x0011c4, 0) + # RAM offset address + await dev_pf0_bar0.write_dword(0x0011c8, 0) + await dev_pf0_bar0.write_dword(0x0011cc, 0) + # RAM offset mask + await dev_pf0_bar0.write_dword(0x0011d0, 0x000003ff) + await dev_pf0_bar0.write_dword(0x0011d4, 0) + # RAM stride + await dev_pf0_bar0.write_dword(0x0011d8, 256) + await dev_pf0_bar0.write_dword(0x0011dc, 0) + # clear cycle count + await dev_pf0_bar0.write_dword(0x001108, 0) + await dev_pf0_bar0.write_dword(0x00110c, 0) + # block length + await dev_pf0_bar0.write_dword(0x001110, 256) + # block count + await dev_pf0_bar0.write_dword(0x001118, 32) + await dev_pf0_bar0.write_dword(0x00111c, 0) + # start + await dev_pf0_bar0.write_dword(0x001100, 1) + + await Timer(2000, 'ns') + + await RisingEdge(dut.clk) + await RisingEdge(dut.clk) + + +# cocotb-test + +tests_dir = 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')) +pcie_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'pcie', '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(rtl_dir, "common", "example_core_pcie_us.v"), + os.path.join(rtl_dir, "common", "example_core_pcie.v"), + os.path.join(rtl_dir, "common", "example_core.v"), + os.path.join(rtl_dir, "common", "axi_ram.v"), + os.path.join(pcie_rtl_dir, "pcie_us_if.v"), + os.path.join(pcie_rtl_dir, "pcie_us_if_rc.v"), + os.path.join(pcie_rtl_dir, "pcie_us_if_rq.v"), + os.path.join(pcie_rtl_dir, "pcie_us_if_cq.v"), + os.path.join(pcie_rtl_dir, "pcie_us_if_cc.v"), + os.path.join(pcie_rtl_dir, "pcie_us_cfg.v"), + os.path.join(pcie_rtl_dir, "pcie_us_msi.v"), + os.path.join(pcie_rtl_dir, "pcie_axil_master.v"), + os.path.join(pcie_rtl_dir, "pcie_axi_master.v"), + os.path.join(pcie_rtl_dir, "pcie_axi_master_rd.v"), + os.path.join(pcie_rtl_dir, "pcie_axi_master_wr.v"), + os.path.join(pcie_rtl_dir, "pcie_tlp_demux_bar.v"), + os.path.join(pcie_rtl_dir, "pcie_tlp_demux.v"), + os.path.join(pcie_rtl_dir, "pcie_tlp_mux.v"), + os.path.join(pcie_rtl_dir, "dma_if_pcie.v"), + os.path.join(pcie_rtl_dir, "dma_if_pcie_rd.v"), + os.path.join(pcie_rtl_dir, "dma_if_pcie_wr.v"), + os.path.join(pcie_rtl_dir, "dma_psdpram.v"), + os.path.join(pcie_rtl_dir, "arbiter.v"), + os.path.join(pcie_rtl_dir, "priority_encoder.v"), + os.path.join(pcie_rtl_dir, "pulse_merge.v"), + ] + + parameters = {} + + parameters['AXIS_PCIE_DATA_WIDTH'] = 256 + parameters['AXIS_PCIE_KEEP_WIDTH'] = parameters['AXIS_PCIE_DATA_WIDTH'] // 32 + parameters['AXIS_PCIE_RQ_USER_WIDTH'] = 62 if parameters['AXIS_PCIE_DATA_WIDTH'] < 512 else 137 + parameters['AXIS_PCIE_RC_USER_WIDTH'] = 75 if parameters['AXIS_PCIE_DATA_WIDTH'] < 512 else 161 + parameters['AXIS_PCIE_CQ_USER_WIDTH'] = 88 if parameters['AXIS_PCIE_DATA_WIDTH'] < 512 else 183 + parameters['AXIS_PCIE_CC_USER_WIDTH'] = 33 if parameters['AXIS_PCIE_DATA_WIDTH'] < 512 else 81 + parameters['RQ_SEQ_NUM_WIDTH'] = 6 + parameters['RQ_SEQ_NUM_ENABLE'] = 1 + parameters['PCIE_TAG_COUNT'] = 64 + parameters['BAR0_APERTURE'] = 24 + parameters['BAR2_APERTURE'] = 24 + + 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, + ) diff --git a/fpga/lib/pcie/example/S10MX_DK/fpga/tb/fpga_core/test_fpga_core.py b/fpga/lib/pcie/example/S10MX_DK/fpga/tb/fpga_core/test_fpga_core.py index b9198d503..87888d60c 100644 --- a/fpga/lib/pcie/example/S10MX_DK/fpga/tb/fpga_core/test_fpga_core.py +++ b/fpga/lib/pcie/example/S10MX_DK/fpga/tb/fpga_core/test_fpga_core.py @@ -33,7 +33,6 @@ from cocotb.triggers import RisingEdge, FallingEdge, Timer from cocotbext.pcie.core import RootComplex from cocotbext.pcie.intel.s10 import S10PcieDevice, S10RxBus, S10TxBus -from cocotbext.axi.utils import hexdump_str class TB(object): @@ -156,8 +155,8 @@ class TB(object): self.dev.functions[0].msi_multiple_message_capable = 5 - self.dev.functions[0].configure_bar(0, 2**22) - self.dev.functions[0].configure_bar(2, 2**22) + self.dev.functions[0].configure_bar(0, 2**len(dut.example_core_pcie_s10_inst.core_pcie_inst.axil_ctrl_awaddr)) + self.dev.functions[0].configure_bar(2, 2**len(dut.example_core_pcie_s10_inst.core_pcie_inst.axi_ram_awaddr)) async def init(self): diff --git a/fpga/lib/pcie/example/VCU108/fpga/README.md b/fpga/lib/pcie/example/VCU108/fpga/README.md new file mode 100644 index 000000000..deb7ebdee --- /dev/null +++ b/fpga/lib/pcie/example/VCU108/fpga/README.md @@ -0,0 +1,19 @@ +# Verilog PCIe VCU108 Example Design + +## Introduction + +This example design targets the Xilinx VCU108 FPGA board. + +The design implements the PCIe AXI lite master module, the PCIe AXI master module, and the PCIe DMA module. A very simple Linux driver is included to test the FPGA design. + +* FPGA: xcvu095-ffva2104-2-e + +## How to build + +Run `make` to build. Ensure that the Xilinx Vivado components are in PATH. + +Run `make` to build the driver. Ensure the headers for the running kernel are installed, otherwise the driver cannot be compiled. + +## How to test + +Run `make program` to program the VCU108 board with Vivado. Then load the driver with `insmod example.ko`. Check dmesg for the output. diff --git a/fpga/lib/pcie/example/VCU108/fpga/common/vivado.mk b/fpga/lib/pcie/example/VCU108/fpga/common/vivado.mk new file mode 100644 index 000000000..d47a43947 --- /dev/null +++ b/fpga/lib/pcie/example/VCU108/fpga/common/vivado.mk @@ -0,0 +1,126 @@ +################################################################### +# +# 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) + +SYN_FILES_REL = $(patsubst %, ../%, $(filter-out /% ./%,$(SYN_FILES))) $(filter /% ./%,$(SYN_FILES)) +INC_FILES_REL = $(patsubst %, ../%, $(filter-out /% ./%,$(INC_FILES))) $(filter /% ./%,$(INC_FILES)) +XCI_FILES_REL = $(patsubst %, ../%, $(filter-out /% ./%,$(XCI_FILES))) $(filter /% ./%,$(XCI_FILES)) +IP_TCL_FILES_REL = $(patsubst %, ../%, $(filter-out /% ./%,$(IP_TCL_FILES))) $(filter /% ./%,$(IP_TCL_FILES)) +CONFIG_TCL_FILES_REL = $(patsubst %, ../%, $(filter-out /% ./%,$(CONFIG_TCL_FILES))) $(filter /% ./%,$(CONFIG_TCL_FILES)) + +ifdef XDC_FILES + XDC_FILES_REL = $(patsubst %, ../%, $(filter-out /% ./%,$(XDC_FILES))) $(filter /% ./%,$(XDC_FILES)) +else + XDC_FILES_REL = $(FPGA_TOP).xdc +endif + +################################################################### +# Main Targets +# +# all: build everything +# clean: remove output files and project files +################################################################### + +all: fpga + +fpga: $(FPGA_TOP).bit + +vivado: $(FPGA_TOP).xpr + vivado $(FPGA_TOP).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 program.tcl generate_mcs.tcl *.mcs *.prm flash.tcl + +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) $(FPGA_TOP)" > $@ + echo "add_files -fileset sources_1 defines.v $(SYN_FILES_REL)" >> $@ + 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) + echo "open_project -quiet $(FPGA_TOP).xpr" > $@ + for x in $(CONFIG_TCL_FILES_REL); do echo "source $$x" >> $@; done + +$(FPGA_TOP).xpr: create_project.tcl update_config.tcl + vivado -nojournal -nolog -mode batch $(foreach x,$?,-source $x) + +# synthesis run +%.runs/synth_1/%.dcp: %.xpr $(SYN_FILES_REL) $(INC_FILES_REL) $(XDC_FILES_REL) $(CONFIG_TCL_FILES_REL) + echo "open_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 +%.runs/impl_1/%_routed.dcp: %.runs/synth_1/%.dcp + echo "open_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 + vivado -nojournal -nolog -mode batch -source run_impl.tcl + +# bit file +%.bit: %.runs/impl_1/%_routed.dcp + echo "open_project $*.xpr" > generate_bit.tcl + echo "open_run impl_1" >> generate_bit.tcl + echo "write_bitstream -force $*.bit" >> generate_bit.tcl + vivado -nojournal -nolog -mode batch -source generate_bit.tcl + mkdir -p rev + EXT=bit; COUNT=100; \ + while [ -e rev/$*_rev$$COUNT.$$EXT ]; \ + do COUNT=$$((COUNT+1)); done; \ + cp $@ rev/$*_rev$$COUNT.$$EXT; \ + echo "Output: rev/$*_rev$$COUNT.$$EXT"; diff --git a/fpga/lib/pcie/example/VCU108/fpga/driver b/fpga/lib/pcie/example/VCU108/fpga/driver new file mode 120000 index 000000000..4a54c76b5 --- /dev/null +++ b/fpga/lib/pcie/example/VCU108/fpga/driver @@ -0,0 +1 @@ +../../common/driver/example/ \ No newline at end of file diff --git a/fpga/lib/pcie/example/VCU108/fpga/fpga.xdc b/fpga/lib/pcie/example/VCU108/fpga/fpga.xdc new file mode 100644 index 000000000..d0ac76506 --- /dev/null +++ b/fpga/lib/pcie/example/VCU108/fpga/fpga.xdc @@ -0,0 +1,262 @@ +# XDC constraints for the Xilinx VCU108 board +# part: xcvu095-ffva2104-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.EXTMASTERCCLK_EN {DIV-1} [current_design] +set_property BITSTREAM.CONFIG.BPI_SYNC_MODE Type1 [current_design] +set_property CONFIG_MODE BPI16 [current_design] + +# System clocks +# 300 MHz +#set_property -dict {LOC G31 IOSTANDARD DIFF_SSTL12} [get_ports clk_300mhz_1_p] +#set_property -dict {LOC F31 IOSTANDARD DIFF_SSTL12} [get_ports clk_300mhz_1_n] +#create_clock -period 3.333 -name clk_300mhz_1 [get_ports clk_300mhz_1_p] + +#set_property -dict {LOC G22 IOSTANDARD DIFF_SSTL12} [get_ports clk_300mhz_2_p] +#set_property -dict {LOC G21 IOSTANDARD DIFF_SSTL12} [get_ports clk_300mhz_2_n] +#create_clock -period 3.333 -name clk_300mhz_2 [get_ports clk_300mhz_2_p] + +# 125 MHz +#set_property -dict {LOC BC9 IOSTANDARD LVDS} [get_ports clk_125mhz_p] +#set_property -dict {LOC BC8 IOSTANDARD LVDS} [get_ports clk_125mhz_n] +#create_clock -period 8.000 -name clk_125mhz [get_ports clk_125mhz_p] + +# 90 MHz +#set_property -dict {LOC AL20 IOSTANDARD LVCMOS18} [get_ports clk_90mhz] +#create_clock -period 11.111 -name clk_90mhz [get_ports clk_90mhz] + +# LEDs +set_property -dict {LOC AT32 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {led[0]}] +set_property -dict {LOC AV34 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {led[1]}] +set_property -dict {LOC AY30 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {led[2]}] +set_property -dict {LOC BB32 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {led[3]}] +set_property -dict {LOC BF32 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {led[4]}] +set_property -dict {LOC AV36 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {led[5]}] +set_property -dict {LOC AY35 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {led[6]}] +set_property -dict {LOC BA37 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {led[7]}] + +set_false_path -to [get_ports {led[*]}] +set_output_delay 0 [get_ports {led[*]}] + +# Reset button +#set_property -dict {LOC E36 IOSTANDARD LVCMOS12} [get_ports reset] + +#set_false_path -from [get_ports {reset}] +#set_input_delay 0 [get_ports {reset}] + +# Push buttons +set_property -dict {LOC E34 IOSTANDARD LVCMOS12} [get_ports btnu] +set_property -dict {LOC M22 IOSTANDARD LVCMOS12} [get_ports btnl] +set_property -dict {LOC D9 IOSTANDARD LVCMOS12} [get_ports btnd] +set_property -dict {LOC A10 IOSTANDARD LVCMOS12} [get_ports btnr] +set_property -dict {LOC AW27 IOSTANDARD LVCMOS12} [get_ports btnc] + +set_false_path -from [get_ports {btnu btnl btnd btnr btnc}] +set_input_delay 0 [get_ports {btnu btnl btnd btnr btnc}] + +# DIP switches +set_property -dict {LOC BC40 IOSTANDARD LVCMOS12} [get_ports {sw[0]}] +set_property -dict {LOC L19 IOSTANDARD LVCMOS12} [get_ports {sw[1]}] +set_property -dict {LOC C37 IOSTANDARD LVCMOS12} [get_ports {sw[2]}] +set_property -dict {LOC C38 IOSTANDARD LVCMOS12} [get_ports {sw[3]}] + +set_false_path -from [get_ports {sw[*]}] +set_input_delay 0 [get_ports {sw[*]}] + +# PMOD0 +#set_property -dict {LOC BC14 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports {pmod0[0]}] +#set_property -dict {LOC BA10 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports {pmod0[1]}] +#set_property -dict {LOC AW16 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports {pmod0[2]}] +#set_property -dict {LOC BB16 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports {pmod0[3]}] +#set_property -dict {LOC BC13 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports {pmod0[4]}] +#set_property -dict {LOC BF7 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports {pmod0[5]}] +#set_property -dict {LOC AW12 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports {pmod0[6]}] +#set_property -dict {LOC BC16 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports {pmod0[7]}] + +#set_false_path -to [get_ports {pmod0[*]}] +#set_output_delay 0 [get_ports {pmod0[*]}] + +# PMOD1 +#set_property -dict {LOC P22 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {pmod1[0]}] +#set_property -dict {LOC N22 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {pmod1[1]}] +#set_property -dict {LOC J20 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {pmod1[2]}] +#set_property -dict {LOC K24 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {pmod1[3]}] +#set_property -dict {LOC J24 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {pmod1[4]}] +#set_property -dict {LOC T23 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {pmod1[5]}] +#set_property -dict {LOC R23 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {pmod1[6]}] +#set_property -dict {LOC R22 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {pmod1[7]}] + +#set_false_path -to [get_ports {pmod1[*]}] +#set_output_delay 0 [get_ports {pmod1[*]}] + +# UART +#set_property -dict {LOC BE24 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports uart_txd] +#set_property -dict {LOC BC24 IOSTANDARD LVCMOS18} [get_ports uart_rxd] +#set_property -dict {LOC BF24 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports uart_rts] +#set_property -dict {LOC BD22 IOSTANDARD LVCMOS18} [get_ports uart_cts] + +#set_false_path -to [get_ports {uart_txd uart_rts}] +#set_output_delay 0 [get_ports {uart_txd uart_rts}] +#set_false_path -from [get_ports {uart_rxd uart_cts}] +#set_input_delay 0 [get_ports {uart_rxd uart_cts}] + +# Gigabit Ethernet SGMII PHY +#set_property -dict {LOC AR24 IOSTANDARD DIFF_HSTL_I_18} [get_ports phy_sgmii_rx_p] +#set_property -dict {LOC AT24 IOSTANDARD DIFF_HSTL_I_18} [get_ports phy_sgmii_rx_n] +#set_property -dict {LOC AR23 IOSTANDARD DIFF_HSTL_I_18} [get_ports phy_sgmii_tx_p] +#set_property -dict {LOC AR22 IOSTANDARD DIFF_HSTL_I_18} [get_ports phy_sgmii_tx_n] +#set_property -dict {LOC AT22 IOSTANDARD LVDS_25} [get_ports phy_sgmii_clk_p] +#set_property -dict {LOC AU22 IOSTANDARD LVDS_25} [get_ports phy_sgmii_clk_n] +#set_property -dict {LOC AU21 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports phy_reset_n] +#set_property -dict {LOC AT21 IOSTANDARD LVCMOS18} [get_ports phy_int_n] +#set_property -dict {LOC AV24 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports phy_mdio] +#set_property -dict {LOC AV21 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports phy_mdc] + +# 625 MHz ref clock from SGMII PHY +#create_clock -period 1.600 -name phy_sgmii_clk [get_ports phy_sgmii_clk_p] + +#set_false_path -to [get_ports {phy_reset_n phy_mdio phy_mdc}] +#set_output_delay 0 [get_ports {phy_reset_n phy_mdio phy_mdc}] +#set_false_path -from [get_ports {phy_int_n phy_mdio}] +#set_input_delay 0 [get_ports {phy_int_n phy_mdio}] + +# QSFP+ Interface +#set_property -dict {LOC AG45} [get_ports qsfp_rx1_p] ;# MGTYRXP0_127 GTYE3_CHANNEL_X0Y12 / GTYE3_COMMON_X0Y3 +#set_property -dict {LOC AG46} [get_ports qsfp_rx1_n] ;# MGTYRXN0_127 GTYE3_CHANNEL_X0Y12 / GTYE3_COMMON_X0Y3 +#set_property -dict {LOC AK42} [get_ports qsfp_tx1_p] ;# MGTYTXP0_127 GTYE3_CHANNEL_X0Y12 / GTYE3_COMMON_X0Y3 +#set_property -dict {LOC AK43} [get_ports qsfp_tx1_n] ;# MGTYTXN0_127 GTYE3_CHANNEL_X0Y12 / GTYE3_COMMON_X0Y3 +#set_property -dict {LOC AF43} [get_ports qsfp_rx2_p] ;# MGTYRXP1_127 GTYE3_CHANNEL_X0Y13 / GTYE3_COMMON_X0Y3 +#set_property -dict {LOC AF44} [get_ports qsfp_rx2_n] ;# MGTYRXN1_127 GTYE3_CHANNEL_X0Y13 / GTYE3_COMMON_X0Y3 +#set_property -dict {LOC AJ40} [get_ports qsfp_tx2_p] ;# MGTYTXP1_127 GTYE3_CHANNEL_X0Y13 / GTYE3_COMMON_X0Y3 +#set_property -dict {LOC AJ41} [get_ports qsfp_tx2_n] ;# MGTYTXN1_127 GTYE3_CHANNEL_X0Y13 / GTYE3_COMMON_X0Y3 +#set_property -dict {LOC AE45} [get_ports qsfp_rx3_p] ;# MGTYRXP2_127 GTYE3_CHANNEL_X0Y14 / GTYE3_COMMON_X0Y3 +#set_property -dict {LOC AE46} [get_ports qsfp_rx3_n] ;# MGTYRXN2_127 GTYE3_CHANNEL_X0Y14 / GTYE3_COMMON_X0Y3 +#set_property -dict {LOC AG40} [get_ports qsfp_tx3_p] ;# MGTYTXP2_127 GTYE3_CHANNEL_X0Y14 / GTYE3_COMMON_X0Y3 +#set_property -dict {LOC AG41} [get_ports qsfp_tx3_n] ;# MGTYTXN2_127 GTYE3_CHANNEL_X0Y14 / GTYE3_COMMON_X0Y3 +#set_property -dict {LOC AD43} [get_ports qsfp_rx4_p] ;# MGTYRXP3_127 GTYE3_CHANNEL_X0Y15 / GTYE3_COMMON_X0Y3 +#set_property -dict {LOC AD44} [get_ports qsfp_rx4_n] ;# MGTYRXN3_127 GTYE3_CHANNEL_X0Y15 / GTYE3_COMMON_X0Y3 +#set_property -dict {LOC AE40} [get_ports qsfp_tx4_p] ;# MGTYTXP3_127 GTYE3_CHANNEL_X0Y15 / GTYE3_COMMON_X0Y3 +#set_property -dict {LOC AE41} [get_ports qsfp_tx4_n] ;# MGTYTXN3_127 GTYE3_CHANNEL_X0Y15 / GTYE3_COMMON_X0Y3 +#set_property -dict {LOC AF38} [get_ports qsfp_mgt_refclk_0_p] ;# MGTREFCLK0P_127 from U32 SI570 via U102 SI53340 +#set_property -dict {LOC AF39} [get_ports qsfp_mgt_refclk_0_n] ;# MGTREFCLK0N_127 from U32 SI570 via U102 SI53340 +#set_property -dict {LOC AD38} [get_ports qsfp_mgt_refclk_1_p] ;# MGTREFCLK1P_127 from U57 CKOUT2 SI5328 +#set_property -dict {LOC AD39} [get_ports qsfp_mgt_refclk_1_n] ;# MGTREFCLK1N_127 from U57 CKOUT2 SI5328 +#set_property -dict {LOC AG34 IOSTANDARD LVDS} [get_ports qsfp_recclk_p] ;# to U57 CKIN1 SI5328 +#set_property -dict {LOC AH35 IOSTANDARD LVDS} [get_ports qsfp_recclk_n] ;# to U57 CKIN1 SI5328 +#set_property -dict {LOC AL24 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports qsfp_modsell] +#set_property -dict {LOC AM24 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports qsfp_resetl] +#set_property -dict {LOC AL25 IOSTANDARD LVCMOS18 PULLUP true} [get_ports qsfp_modprsl] +#set_property -dict {LOC AL21 IOSTANDARD LVCMOS18 PULLUP true} [get_ports qsfp_intl] +#set_property -dict {LOC AM21 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports qsfp_lpmode] + +# 156.25 MHz MGT reference clock +#create_clock -period 6.400 -name qsfp_mgt_refclk_0 [get_ports qsfp_mgt_refclk_0_p] + +#set_false_path -to [get_ports {qsfp_modsell qsfp_resetl qsfp_lpmode}] +#set_output_delay 0 [get_ports {qsfp_modsell qsfp_resetl qsfp_lpmode}] +#set_false_path -from [get_ports {qsfp_modprsl qsfp_intl}] +#set_input_delay 0 [get_ports {qsfp_modprsl qsfp_intl}] + +# I2C interface +#set_property -dict {LOC AN21 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports i2c_scl] +#set_property -dict {LOC AP21 IOSTANDARD LVCMOS18 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 AJ4 } [get_ports {pcie_rx_p[0]}] ;# MGTHRXP3_225 GTHE3_CHANNEL_X0Y7 / GTHE3_COMMON_X0Y1 +set_property -dict {LOC AJ3 } [get_ports {pcie_rx_n[0]}] ;# MGTHRXN3_225 GTHE3_CHANNEL_X0Y7 / GTHE3_COMMON_X0Y1 +set_property -dict {LOC AP7 } [get_ports {pcie_tx_p[0]}] ;# MGTHTXP3_225 GTHE3_CHANNEL_X0Y7 / GTHE3_COMMON_X0Y1 +set_property -dict {LOC AP6 } [get_ports {pcie_tx_n[0]}] ;# MGTHTXN3_225 GTHE3_CHANNEL_X0Y7 / GTHE3_COMMON_X0Y1 +set_property -dict {LOC AK2 } [get_ports {pcie_rx_p[1]}] ;# MGTHRXP2_225 GTHE3_CHANNEL_X0Y6 / GTHE3_COMMON_X0Y1 +set_property -dict {LOC AK1 } [get_ports {pcie_rx_n[1]}] ;# MGTHRXN2_225 GTHE3_CHANNEL_X0Y6 / GTHE3_COMMON_X0Y1 +set_property -dict {LOC AR5 } [get_ports {pcie_tx_p[1]}] ;# MGTHTXP2_225 GTHE3_CHANNEL_X0Y6 / GTHE3_COMMON_X0Y1 +set_property -dict {LOC AR4 } [get_ports {pcie_tx_n[1]}] ;# MGTHTXN2_225 GTHE3_CHANNEL_X0Y6 / GTHE3_COMMON_X0Y1 +set_property -dict {LOC AM2 } [get_ports {pcie_rx_p[2]}] ;# MGTHRXP1_225 GTHE3_CHANNEL_X0Y5 / GTHE3_COMMON_X0Y1 +set_property -dict {LOC AM1 } [get_ports {pcie_rx_n[2]}] ;# MGTHRXN1_225 GTHE3_CHANNEL_X0Y5 / GTHE3_COMMON_X0Y1 +set_property -dict {LOC AT7 } [get_ports {pcie_tx_p[2]}] ;# MGTHTXP1_225 GTHE3_CHANNEL_X0Y5 / GTHE3_COMMON_X0Y1 +set_property -dict {LOC AT6 } [get_ports {pcie_tx_n[2]}] ;# MGTHTXN1_225 GTHE3_CHANNEL_X0Y5 / GTHE3_COMMON_X0Y1 +set_property -dict {LOC AP2 } [get_ports {pcie_rx_p[3]}] ;# MGTHRXP0_225 GTHE3_CHANNEL_X0Y4 / GTHE3_COMMON_X0Y1 +set_property -dict {LOC AP1 } [get_ports {pcie_rx_n[3]}] ;# MGTHRXN0_225 GTHE3_CHANNEL_X0Y4 / GTHE3_COMMON_X0Y1 +set_property -dict {LOC AU5 } [get_ports {pcie_tx_p[3]}] ;# MGTHTXP0_225 GTHE3_CHANNEL_X0Y4 / GTHE3_COMMON_X0Y1 +set_property -dict {LOC AU4 } [get_ports {pcie_tx_n[3]}] ;# MGTHTXN0_225 GTHE3_CHANNEL_X0Y4 / GTHE3_COMMON_X0Y1 +set_property -dict {LOC AT2 } [get_ports {pcie_rx_p[4]}] ;# MGTHRXP3_224 GTHE3_CHANNEL_X0Y3 / GTHE3_COMMON_X0Y0 +set_property -dict {LOC AT1 } [get_ports {pcie_rx_n[4]}] ;# MGTHRXN3_224 GTHE3_CHANNEL_X0Y3 / GTHE3_COMMON_X0Y0 +set_property -dict {LOC AW5 } [get_ports {pcie_tx_p[4]}] ;# MGTHTXP3_224 GTHE3_CHANNEL_X0Y3 / GTHE3_COMMON_X0Y0 +set_property -dict {LOC AW4 } [get_ports {pcie_tx_n[4]}] ;# MGTHTXN3_224 GTHE3_CHANNEL_X0Y3 / GTHE3_COMMON_X0Y0 +set_property -dict {LOC AV2 } [get_ports {pcie_rx_p[5]}] ;# MGTHRXP2_224 GTHE3_CHANNEL_X0Y2 / GTHE3_COMMON_X0Y0 +set_property -dict {LOC AV1 } [get_ports {pcie_rx_n[5]}] ;# MGTHRXN2_224 GTHE3_CHANNEL_X0Y2 / GTHE3_COMMON_X0Y0 +set_property -dict {LOC BA5 } [get_ports {pcie_tx_p[5]}] ;# MGTHTXP2_224 GTHE3_CHANNEL_X0Y2 / GTHE3_COMMON_X0Y0 +set_property -dict {LOC BA4 } [get_ports {pcie_tx_n[5]}] ;# MGTHTXN2_224 GTHE3_CHANNEL_X0Y2 / GTHE3_COMMON_X0Y0 +set_property -dict {LOC AY2 } [get_ports {pcie_rx_p[6]}] ;# MGTHRXP1_224 GTHE3_CHANNEL_X0Y1 / GTHE3_COMMON_X0Y0 +set_property -dict {LOC AY1 } [get_ports {pcie_rx_n[6]}] ;# MGTHRXN1_224 GTHE3_CHANNEL_X0Y1 / GTHE3_COMMON_X0Y0 +set_property -dict {LOC BC5 } [get_ports {pcie_tx_p[6]}] ;# MGTHTXP1_224 GTHE3_CHANNEL_X0Y1 / GTHE3_COMMON_X0Y0 +set_property -dict {LOC BC4 } [get_ports {pcie_tx_n[6]}] ;# MGTHTXN1_224 GTHE3_CHANNEL_X0Y1 / GTHE3_COMMON_X0Y0 +set_property -dict {LOC BB2 } [get_ports {pcie_rx_p[7]}] ;# MGTHRXP0_224 GTHE3_CHANNEL_X0Y0 / GTHE3_COMMON_X0Y0 +set_property -dict {LOC BB1 } [get_ports {pcie_rx_n[7]}] ;# MGTHRXN0_224 GTHE3_CHANNEL_X0Y0 / GTHE3_COMMON_X0Y0 +set_property -dict {LOC BE5 } [get_ports {pcie_tx_p[7]}] ;# MGTHTXP0_224 GTHE3_CHANNEL_X0Y0 / GTHE3_COMMON_X0Y0 +set_property -dict {LOC BE4 } [get_ports {pcie_tx_n[7]}] ;# MGTHTXN0_224 GTHE3_CHANNEL_X0Y0 / GTHE3_COMMON_X0Y0 +set_property -dict {LOC AL9 } [get_ports pcie_mgt_refclk_p] ;# MGTREFCLK0P_225 +set_property -dict {LOC AL8 } [get_ports pcie_mgt_refclk_n] ;# MGTREFCLK0N_225 +set_property -dict {LOC AM17 IOSTANDARD LVCMOS18 PULLUP true} [get_ports pcie_reset_n] + +# 100 MHz MGT reference clock +create_clock -period 10 -name pcie_mgt_refclk [get_ports pcie_mgt_refclk_p] + +set_false_path -from [get_ports {pcie_reset_n}] +set_input_delay 0 [get_ports {pcie_reset_n}] + +# BPI flash +#set_property -dict {LOC AM19 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_dq[4]}] +#set_property -dict {LOC AM18 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_dq[5]}] +#set_property -dict {LOC AN20 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_dq[6]}] +#set_property -dict {LOC AP20 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_dq[7]}] +#set_property -dict {LOC AN19 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_dq[8]}] +#set_property -dict {LOC AN18 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_dq[9]}] +#set_property -dict {LOC AR18 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_dq[10]}] +#set_property -dict {LOC AR17 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_dq[11]}] +#set_property -dict {LOC AT20 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_dq[12]}] +#set_property -dict {LOC AT19 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_dq[13]}] +#set_property -dict {LOC AT17 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_dq[14]}] +#set_property -dict {LOC AU17 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_dq[15]}] +#set_property -dict {LOC AR20 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_addr[0]}] +#set_property -dict {LOC AR19 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_addr[1]}] +#set_property -dict {LOC AV20 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_addr[2]}] +#set_property -dict {LOC AW20 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_addr[3]}] +#set_property -dict {LOC AU19 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_addr[4]}] +#set_property -dict {LOC AU18 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_addr[5]}] +#set_property -dict {LOC AV19 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_addr[6]}] +#set_property -dict {LOC AV18 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_addr[7]}] +#set_property -dict {LOC AW18 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_addr[8]}] +#set_property -dict {LOC AY18 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_addr[9]}] +#set_property -dict {LOC AY19 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_addr[10]}] +#set_property -dict {LOC BA19 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_addr[11]}] +#set_property -dict {LOC BA17 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_addr[12]}] +#set_property -dict {LOC BB17 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_addr[13]}] +#set_property -dict {LOC BB19 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_addr[14]}] +#set_property -dict {LOC BC19 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_addr[15]}] +#set_property -dict {LOC BB18 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_addr[16]}] +#set_property -dict {LOC BC18 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_addr[17]}] +#set_property -dict {LOC AY20 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_addr[18]}] +#set_property -dict {LOC BA20 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_addr[19]}] +#set_property -dict {LOC BD18 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_addr[20]}] +#set_property -dict {LOC BD17 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_addr[21]}] +#set_property -dict {LOC BC20 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_addr[22]}] +#set_property -dict {LOC BD20 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_addr[23]}] +#set_property -dict {LOC BE20 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_region[0]}] +#set_property -dict {LOC BF20 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_region[1]}] +#set_property -dict {LOC BF17 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_oe_n}] +#set_property -dict {LOC BF16 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_we_n}] +#set_property -dict {LOC AW17 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {flash_adv_n}] +#set_property -dict {LOC BC23 IOSTANDARD LVCMOS18} [get_ports {flash_wait}] + +#set_false_path -to [get_ports {flash_dq[*] flash_addr[*] flash_region[*] flash_oe_n flash_we_n flash_adv_n}] +#set_output_delay 0 [get_ports {flash_dq[*] flash_addr[*] flash_region[*] flash_oe_n flash_we_n flash_adv_n}] +#set_false_path -from [get_ports {flash_dq[*] flash_wait}] +#set_input_delay 0 [get_ports {flash_dq[*] flash_wait}] diff --git a/fpga/lib/pcie/example/VCU108/fpga/fpga/Makefile b/fpga/lib/pcie/example/VCU108/fpga/fpga/Makefile new file mode 100644 index 000000000..44724d530 --- /dev/null +++ b/fpga/lib/pcie/example/VCU108/fpga/fpga/Makefile @@ -0,0 +1,95 @@ + +# FPGA settings +FPGA_PART = xcvu095-ffva2104-2-e +FPGA_TOP = fpga +FPGA_ARCH = VirtexUltrascale + +# Files for synthesis +SYN_FILES = rtl/fpga.v +SYN_FILES += rtl/fpga_core.v +SYN_FILES += rtl/debounce_switch.v +SYN_FILES += rtl/sync_reset.v +SYN_FILES += rtl/sync_signal.v +SYN_FILES += rtl/common/example_core_pcie_us.v +SYN_FILES += rtl/common/example_core_pcie.v +SYN_FILES += rtl/common/example_core.v +SYN_FILES += rtl/common/axi_ram.v +SYN_FILES += lib/pcie/rtl/pcie_us_if.v +SYN_FILES += lib/pcie/rtl/pcie_us_if_rc.v +SYN_FILES += lib/pcie/rtl/pcie_us_if_rq.v +SYN_FILES += lib/pcie/rtl/pcie_us_if_cq.v +SYN_FILES += lib/pcie/rtl/pcie_us_if_cc.v +SYN_FILES += lib/pcie/rtl/pcie_us_cfg.v +SYN_FILES += lib/pcie/rtl/pcie_us_msi.v +SYN_FILES += lib/pcie/rtl/pcie_axil_master.v +SYN_FILES += lib/pcie/rtl/pcie_axi_master.v +SYN_FILES += lib/pcie/rtl/pcie_axi_master_rd.v +SYN_FILES += lib/pcie/rtl/pcie_axi_master_wr.v +SYN_FILES += lib/pcie/rtl/pcie_tlp_demux_bar.v +SYN_FILES += lib/pcie/rtl/pcie_tlp_demux.v +SYN_FILES += lib/pcie/rtl/pcie_tlp_mux.v +SYN_FILES += lib/pcie/rtl/dma_if_pcie.v +SYN_FILES += lib/pcie/rtl/dma_if_pcie_rd.v +SYN_FILES += lib/pcie/rtl/dma_if_pcie_wr.v +SYN_FILES += lib/pcie/rtl/dma_psdpram.v +SYN_FILES += lib/pcie/rtl/arbiter.v +SYN_FILES += lib/pcie/rtl/priority_encoder.v +SYN_FILES += lib/pcie/rtl/pulse_merge.v + +# XDC files +XDC_FILES = fpga.xdc + +# IP +IP_TCL_FILES = ip/pcie3_ultrascale_0.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 + +%.mcs %.prm: %.bit + echo "write_cfgmem -force -format mcs -size 128 -interface BPIx16 -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 .mcs .prm; \ + do cp $*$$x rev/$*_rev$$COUNT$$x; \ + echo "Output: rev/$*_rev$$COUNT$$x"; done; + +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 {mt28gu01gaax1e-bpi-x16}] 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.BPI_RS_PINS {25:24} [current_hw_cfgmem]" >> flash.tcl + echo "set_property PROGRAM.UNUSED_PIN_TERMINATION {pull-none} [current_hw_cfgmem]" >> flash.tcl + echo "create_hw_bitstream -hw_device [current_hw_device] [get_property PROGRAM.HW_CFGMEM_BITFILE [current_hw_device]]" >> flash.tcl + echo "program_hw_devices [current_hw_device]" >> flash.tcl + echo "refresh_hw_device [current_hw_device]" >> flash.tcl + echo "program_hw_cfgmem -hw_cfgmem [current_hw_cfgmem]" >> flash.tcl + echo "boot_hw_device [current_hw_device]" >> flash.tcl + echo "exit" >> flash.tcl + vivado -nojournal -nolog -mode batch -source flash.tcl + diff --git a/fpga/lib/pcie/example/VCU108/fpga/ip/pcie3_ultrascale_0.tcl b/fpga/lib/pcie/example/VCU108/fpga/ip/pcie3_ultrascale_0.tcl new file mode 100644 index 000000000..535e29ce4 --- /dev/null +++ b/fpga/lib/pcie/example/VCU108/fpga/ip/pcie3_ultrascale_0.tcl @@ -0,0 +1,31 @@ + +create_ip -name pcie3_ultrascale -vendor xilinx.com -library ip -module_name pcie3_ultrascale_0 + +set_property -dict [list \ + CONFIG.PL_LINK_CAP_MAX_LINK_SPEED {8.0_GT/s} \ + CONFIG.PL_LINK_CAP_MAX_LINK_WIDTH {X8} \ + CONFIG.AXISTEN_IF_RC_STRADDLE {false} \ + CONFIG.axisten_if_width {256_bit} \ + CONFIG.extended_tag_field {true} \ + CONFIG.axisten_freq {250} \ + CONFIG.PF0_CLASS_CODE {058000} \ + CONFIG.PF0_DEVICE_ID {0001} \ + CONFIG.PF0_MSI_CAP_MULTIMSGCAP {32_vectors} \ + CONFIG.PF0_SUBSYSTEM_ID {806c} \ + CONFIG.PF0_SUBSYSTEM_VENDOR_ID {10ee} \ + CONFIG.pf0_bar0_64bit {true} \ + CONFIG.pf0_bar0_prefetchable {true} \ + CONFIG.pf0_bar0_scale {Megabytes} \ + CONFIG.pf0_bar0_size {16} \ + CONFIG.pf0_bar2_64bit {true} \ + CONFIG.pf0_bar2_prefetchable {true} \ + CONFIG.pf0_bar2_enabled {true} \ + CONFIG.pf0_bar2_type {Memory} \ + CONFIG.pf0_bar2_scale {Megabytes} \ + CONFIG.pf0_bar2_size {16} \ + CONFIG.PF0_INTERRUPT_PIN {NONE} \ + CONFIG.PF0_MSIX_CAP_TABLE_BIR {BAR_0} \ + CONFIG.PF0_MSIX_CAP_PBA_BIR {BAR_0} \ + CONFIG.vendor_id {1234} \ + CONFIG.en_msi_per_vec_masking {true} \ +] [get_ips pcie3_ultrascale_0] diff --git a/fpga/lib/pcie/example/VCU108/fpga/lib/pcie b/fpga/lib/pcie/example/VCU108/fpga/lib/pcie new file mode 120000 index 000000000..11a54ed36 --- /dev/null +++ b/fpga/lib/pcie/example/VCU108/fpga/lib/pcie @@ -0,0 +1 @@ +../../../../ \ No newline at end of file diff --git a/fpga/lib/pcie/example/VCU108/fpga/rtl/common b/fpga/lib/pcie/example/VCU108/fpga/rtl/common new file mode 120000 index 000000000..e60fada70 --- /dev/null +++ b/fpga/lib/pcie/example/VCU108/fpga/rtl/common @@ -0,0 +1 @@ +../../../common/rtl/ \ No newline at end of file diff --git a/fpga/lib/pcie/example/VCU108/fpga/rtl/debounce_switch.v b/fpga/lib/pcie/example/VCU108/fpga/rtl/debounce_switch.v new file mode 100644 index 000000000..8e93a50c4 --- /dev/null +++ b/fpga/lib/pcie/example/VCU108/fpga/rtl/debounce_switch.v @@ -0,0 +1,93 @@ +/* + +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 diff --git a/fpga/lib/pcie/example/VCU108/fpga/rtl/fpga.v b/fpga/lib/pcie/example/VCU108/fpga/rtl/fpga.v new file mode 100644 index 000000000..4eb017f2a --- /dev/null +++ b/fpga/lib/pcie/example/VCU108/fpga/rtl/fpga.v @@ -0,0 +1,488 @@ +/* + +Copyright (c) 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 1ns / 1ps +`default_nettype none + +/* + * FPGA top-level module + */ +module fpga ( + /* + * GPIO + */ + input wire btnu, + input wire btnl, + input wire btnd, + input wire btnr, + input wire btnc, + input wire [3:0] sw, + output wire [7:0] led, + + /* + * PCI express + */ + input wire [7:0] pcie_rx_p, + input wire [7:0] pcie_rx_n, + output wire [7:0] pcie_tx_p, + output wire [7:0] pcie_tx_n, + input wire pcie_mgt_refclk_p, + input wire pcie_mgt_refclk_n, + input wire pcie_reset_n +); + +parameter AXIS_PCIE_DATA_WIDTH = 256; +parameter AXIS_PCIE_KEEP_WIDTH = (AXIS_PCIE_DATA_WIDTH/32); +parameter AXIS_PCIE_RC_USER_WIDTH = 75; +parameter AXIS_PCIE_RQ_USER_WIDTH = 60; +parameter AXIS_PCIE_CQ_USER_WIDTH = 85; +parameter AXIS_PCIE_CC_USER_WIDTH = 33; + +parameter RQ_SEQ_NUM_WIDTH = AXIS_PCIE_RQ_USER_WIDTH == 60 ? 4 : 6; +parameter RQ_SEQ_NUM_ENABLE = 1; + +parameter PCIE_TAG_COUNT = 64; +parameter BAR0_APERTURE = 24; +parameter BAR2_APERTURE = 24; + +// Clock and reset +wire pcie_user_clk; +wire pcie_user_reset; + +// GPIO +wire btnu_int; +wire btnl_int; +wire btnd_int; +wire btnr_int; +wire btnc_int; +wire [3:0] sw_int; + +debounce_switch #( + .WIDTH(9), + .N(4), + .RATE(250000) +) +debounce_switch_inst ( + .clk(pcie_user_clk), + .rst(pcie_user_reset), + .in({btnu, + btnl, + btnd, + btnr, + btnc, + sw}), + .out({btnu_int, + btnl_int, + btnd_int, + btnr_int, + btnc_int, + sw_int}) +); + +// PCIe +wire pcie_sys_clk; +wire pcie_sys_clk_gt; + +IBUFDS_GTE3 #( + .REFCLK_HROW_CK_SEL(2'b00) +) +ibufds_gte3_pcie_mgt_refclk_inst ( + .I (pcie_mgt_refclk_p), + .IB (pcie_mgt_refclk_n), + .CEB (1'b0), + .O (pcie_sys_clk_gt), + .ODIV2 (pcie_sys_clk) +); + +wire [AXIS_PCIE_DATA_WIDTH-1:0] axis_rq_tdata; +wire [AXIS_PCIE_KEEP_WIDTH-1:0] axis_rq_tkeep; +wire axis_rq_tlast; +wire axis_rq_tready; +wire [AXIS_PCIE_RQ_USER_WIDTH-1:0] axis_rq_tuser; +wire axis_rq_tvalid; + +wire [AXIS_PCIE_DATA_WIDTH-1:0] axis_rc_tdata; +wire [AXIS_PCIE_KEEP_WIDTH-1:0] axis_rc_tkeep; +wire axis_rc_tlast; +wire axis_rc_tready; +wire [AXIS_PCIE_RC_USER_WIDTH-1:0] axis_rc_tuser; +wire axis_rc_tvalid; + +wire [AXIS_PCIE_DATA_WIDTH-1:0] axis_cq_tdata; +wire [AXIS_PCIE_KEEP_WIDTH-1:0] axis_cq_tkeep; +wire axis_cq_tlast; +wire axis_cq_tready; +wire [AXIS_PCIE_CQ_USER_WIDTH-1:0] axis_cq_tuser; +wire axis_cq_tvalid; + +wire [AXIS_PCIE_DATA_WIDTH-1:0] axis_cc_tdata; +wire [AXIS_PCIE_KEEP_WIDTH-1:0] axis_cc_tkeep; +wire axis_cc_tlast; +wire axis_cc_tready; +wire [AXIS_PCIE_CC_USER_WIDTH-1:0] axis_cc_tuser; +wire axis_cc_tvalid; + +wire [RQ_SEQ_NUM_WIDTH-1:0] pcie_rq_seq_num; +wire pcie_rq_seq_num_vld; + +// ila_0 rq_ila ( +// .clk(pcie_user_clk), +// .probe0(axis_rq_tdata), +// .probe1(axis_rq_tkeep), +// .probe2(axis_rq_tlast), +// .probe3(axis_rq_tready), +// .probe4(axis_rq_tuser), +// .probe5(axis_rq_tvalid) +// ); + +// ila_0 rc_ila ( +// .clk(pcie_user_clk), +// .probe0(axis_rc_tdata), +// .probe1(axis_rc_tkeep), +// .probe2(axis_rc_tlast), +// .probe3(axis_rc_tready), +// .probe4(axis_rc_tuser), +// .probe5(axis_rc_tvalid) +// ); + +wire [2:0] cfg_max_payload; +wire [2:0] cfg_max_read_req; + +wire [18:0] cfg_mgmt_addr; +wire cfg_mgmt_write; +wire [31:0] cfg_mgmt_write_data; +wire [3:0] cfg_mgmt_byte_enable; +wire cfg_mgmt_read; +wire [31:0] cfg_mgmt_read_data; +wire cfg_mgmt_read_write_done; + +wire [7:0] cfg_fc_ph; +wire [11:0] cfg_fc_pd; +wire [7:0] cfg_fc_nph; +wire [11:0] cfg_fc_npd; +wire [7:0] cfg_fc_cplh; +wire [11:0] cfg_fc_cpld; +wire [2:0] cfg_fc_sel; + +wire [3:0] cfg_interrupt_msi_enable; +wire [7:0] cfg_interrupt_msi_vf_enable; +wire [11:0] cfg_interrupt_msi_mmenable; +wire cfg_interrupt_msi_mask_update; +wire [31:0] cfg_interrupt_msi_data; +wire [3:0] cfg_interrupt_msi_select; +wire [31:0] cfg_interrupt_msi_int; +wire [31:0] cfg_interrupt_msi_pending_status; +wire cfg_interrupt_msi_pending_status_data_enable; +wire [3:0] cfg_interrupt_msi_pending_status_function_num; +wire cfg_interrupt_msi_sent; +wire cfg_interrupt_msi_fail; +wire [2:0] cfg_interrupt_msi_attr; +wire cfg_interrupt_msi_tph_present; +wire [1:0] cfg_interrupt_msi_tph_type; +wire [8:0] cfg_interrupt_msi_tph_st_tag; +wire [3:0] cfg_interrupt_msi_function_number; + +wire status_error_cor; +wire status_error_uncor; + +pcie3_ultrascale_0 +pcie3_ultrascale_inst ( + .pci_exp_txn(pcie_tx_n), + .pci_exp_txp(pcie_tx_p), + .pci_exp_rxn(pcie_rx_n), + .pci_exp_rxp(pcie_rx_p), + .user_clk(pcie_user_clk), + .user_reset(pcie_user_reset), + .user_lnk_up(), + + .s_axis_rq_tdata(axis_rq_tdata), + .s_axis_rq_tkeep(axis_rq_tkeep), + .s_axis_rq_tlast(axis_rq_tlast), + .s_axis_rq_tready(axis_rq_tready), + .s_axis_rq_tuser(axis_rq_tuser), + .s_axis_rq_tvalid(axis_rq_tvalid), + + .m_axis_rc_tdata(axis_rc_tdata), + .m_axis_rc_tkeep(axis_rc_tkeep), + .m_axis_rc_tlast(axis_rc_tlast), + .m_axis_rc_tready(axis_rc_tready), + .m_axis_rc_tuser(axis_rc_tuser), + .m_axis_rc_tvalid(axis_rc_tvalid), + + .m_axis_cq_tdata(axis_cq_tdata), + .m_axis_cq_tkeep(axis_cq_tkeep), + .m_axis_cq_tlast(axis_cq_tlast), + .m_axis_cq_tready(axis_cq_tready), + .m_axis_cq_tuser(axis_cq_tuser), + .m_axis_cq_tvalid(axis_cq_tvalid), + + .s_axis_cc_tdata(axis_cc_tdata), + .s_axis_cc_tkeep(axis_cc_tkeep), + .s_axis_cc_tlast(axis_cc_tlast), + .s_axis_cc_tready(axis_cc_tready), + .s_axis_cc_tuser(axis_cc_tuser), + .s_axis_cc_tvalid(axis_cc_tvalid), + + .pcie_rq_seq_num(pcie_rq_seq_num), + .pcie_rq_seq_num_vld(pcie_rq_seq_num_vld), + .pcie_rq_tag(), + .pcie_rq_tag_av(), + .pcie_rq_tag_vld(), + + .pcie_tfc_nph_av(), + .pcie_tfc_npd_av(), + + .pcie_cq_np_req(1'b1), + .pcie_cq_np_req_count(), + + .cfg_phy_link_down(), + .cfg_phy_link_status(), + .cfg_negotiated_width(), + .cfg_current_speed(), + .cfg_max_payload(cfg_max_payload), + .cfg_max_read_req(cfg_max_read_req), + .cfg_function_status(), + .cfg_function_power_state(), + .cfg_vf_status(), + .cfg_vf_power_state(), + .cfg_link_power_state(), + + .cfg_mgmt_addr(cfg_mgmt_addr), + .cfg_mgmt_write(cfg_mgmt_write), + .cfg_mgmt_write_data(cfg_mgmt_write_data), + .cfg_mgmt_byte_enable(cfg_mgmt_byte_enable), + .cfg_mgmt_read(cfg_mgmt_read), + .cfg_mgmt_read_data(cfg_mgmt_read_data), + .cfg_mgmt_read_write_done(cfg_mgmt_read_write_done), + .cfg_mgmt_type1_cfg_reg_access(1'b0), + + .cfg_err_cor_out(), + .cfg_err_nonfatal_out(), + .cfg_err_fatal_out(), + .cfg_local_error(), + .cfg_ltr_enable(), + .cfg_ltssm_state(), + .cfg_rcb_status(), + .cfg_dpa_substate_change(), + .cfg_obff_enable(), + .cfg_pl_status_change(), + .cfg_tph_requester_enable(), + .cfg_tph_st_mode(), + .cfg_vf_tph_requester_enable(), + .cfg_vf_tph_st_mode(), + + .cfg_msg_received(), + .cfg_msg_received_data(), + .cfg_msg_received_type(), + .cfg_msg_transmit(1'b0), + .cfg_msg_transmit_type(3'd0), + .cfg_msg_transmit_data(32'd0), + .cfg_msg_transmit_done(), + + .cfg_fc_ph(cfg_fc_ph), + .cfg_fc_pd(cfg_fc_pd), + .cfg_fc_nph(cfg_fc_nph), + .cfg_fc_npd(cfg_fc_npd), + .cfg_fc_cplh(cfg_fc_cplh), + .cfg_fc_cpld(cfg_fc_cpld), + .cfg_fc_sel(cfg_fc_sel), + + .cfg_per_func_status_control(3'd0), + .cfg_per_func_status_data(), + .cfg_per_function_number(4'd0), + .cfg_per_function_output_request(1'b0), + .cfg_per_function_update_done(), + + .cfg_dsn(64'd0), + + .cfg_power_state_change_ack(1'b1), + .cfg_power_state_change_interrupt(), + + .cfg_err_cor_in(status_error_cor), + .cfg_err_uncor_in(status_error_uncor), + .cfg_flr_in_process(), + .cfg_flr_done(4'd0), + .cfg_vf_flr_in_process(), + .cfg_vf_flr_done(8'd0), + + .cfg_link_training_enable(1'b1), + + .cfg_interrupt_int(4'd0), + .cfg_interrupt_pending(4'd0), + .cfg_interrupt_sent(), + .cfg_interrupt_msi_enable(cfg_interrupt_msi_enable), + .cfg_interrupt_msi_vf_enable(cfg_interrupt_msi_vf_enable), + .cfg_interrupt_msi_mmenable(cfg_interrupt_msi_mmenable), + .cfg_interrupt_msi_mask_update(cfg_interrupt_msi_mask_update), + .cfg_interrupt_msi_data(cfg_interrupt_msi_data), + .cfg_interrupt_msi_select(cfg_interrupt_msi_select), + .cfg_interrupt_msi_int(cfg_interrupt_msi_int), + .cfg_interrupt_msi_pending_status(cfg_interrupt_msi_pending_status), + .cfg_interrupt_msi_pending_status_data_enable(cfg_interrupt_msi_pending_status_data_enable), + .cfg_interrupt_msi_pending_status_function_num(cfg_interrupt_msi_pending_status_function_num), + .cfg_interrupt_msi_sent(cfg_interrupt_msi_sent), + .cfg_interrupt_msi_fail(cfg_interrupt_msi_fail), + .cfg_interrupt_msi_attr(cfg_interrupt_msi_attr), + .cfg_interrupt_msi_tph_present(cfg_interrupt_msi_tph_present), + .cfg_interrupt_msi_tph_type(cfg_interrupt_msi_tph_type), + .cfg_interrupt_msi_tph_st_tag(cfg_interrupt_msi_tph_st_tag), + .cfg_interrupt_msi_function_number(cfg_interrupt_msi_function_number), + + .cfg_hot_reset_out(), + + .cfg_config_space_enable(1'b1), + .cfg_req_pm_transition_l23_ready(1'b0), + .cfg_hot_reset_in(1'b0), + + .cfg_ds_port_number(8'd0), + .cfg_ds_bus_number(8'd0), + .cfg_ds_device_number(5'd0), + .cfg_ds_function_number(3'd0), + + .cfg_subsys_vend_id(16'h1234), + + .sys_clk(pcie_sys_clk), + .sys_clk_gt(pcie_sys_clk_gt), + .sys_reset(pcie_reset_n), + .pcie_perstn1_in(1'b0), + .pcie_perstn0_out(), + .pcie_perstn1_out(), + + .int_qpll1lock_out(), + .int_qpll1outrefclk_out(), + .int_qpll1outclk_out(), + .phy_rdy_out() +); + +fpga_core #( + .AXIS_PCIE_DATA_WIDTH(AXIS_PCIE_DATA_WIDTH), + .AXIS_PCIE_KEEP_WIDTH(AXIS_PCIE_KEEP_WIDTH), + .AXIS_PCIE_RC_USER_WIDTH(AXIS_PCIE_RC_USER_WIDTH), + .AXIS_PCIE_RQ_USER_WIDTH(AXIS_PCIE_RQ_USER_WIDTH), + .AXIS_PCIE_CQ_USER_WIDTH(AXIS_PCIE_CQ_USER_WIDTH), + .AXIS_PCIE_CC_USER_WIDTH(AXIS_PCIE_CC_USER_WIDTH), + .RQ_SEQ_NUM_WIDTH(RQ_SEQ_NUM_WIDTH), + .RQ_SEQ_NUM_ENABLE(RQ_SEQ_NUM_ENABLE), + .PCIE_TAG_COUNT(PCIE_TAG_COUNT), + .BAR0_APERTURE(BAR0_APERTURE), + .BAR2_APERTURE(BAR2_APERTURE) +) +core_inst ( + /* + * Clock: 250 MHz + * Synchronous reset + */ + .clk(pcie_user_clk), + .rst(pcie_user_reset), + /* + * GPIO + */ + .btnu(btnu_int), + .btnl(btnl_int), + .btnd(btnd_int), + .btnr(btnr_int), + .btnc(btnc_int), + .sw(sw_int), + .led(led), + /* + * PCIe + */ + .m_axis_rq_tdata(axis_rq_tdata), + .m_axis_rq_tkeep(axis_rq_tkeep), + .m_axis_rq_tlast(axis_rq_tlast), + .m_axis_rq_tready(axis_rq_tready), + .m_axis_rq_tuser(axis_rq_tuser), + .m_axis_rq_tvalid(axis_rq_tvalid), + + .s_axis_rc_tdata(axis_rc_tdata), + .s_axis_rc_tkeep(axis_rc_tkeep), + .s_axis_rc_tlast(axis_rc_tlast), + .s_axis_rc_tready(axis_rc_tready), + .s_axis_rc_tuser(axis_rc_tuser), + .s_axis_rc_tvalid(axis_rc_tvalid), + + .s_axis_cq_tdata(axis_cq_tdata), + .s_axis_cq_tkeep(axis_cq_tkeep), + .s_axis_cq_tlast(axis_cq_tlast), + .s_axis_cq_tready(axis_cq_tready), + .s_axis_cq_tuser(axis_cq_tuser), + .s_axis_cq_tvalid(axis_cq_tvalid), + + .m_axis_cc_tdata(axis_cc_tdata), + .m_axis_cc_tkeep(axis_cc_tkeep), + .m_axis_cc_tlast(axis_cc_tlast), + .m_axis_cc_tready(axis_cc_tready), + .m_axis_cc_tuser(axis_cc_tuser), + .m_axis_cc_tvalid(axis_cc_tvalid), + + .s_axis_rq_seq_num(pcie_rq_seq_num), + .s_axis_rq_seq_num_valid(pcie_rq_seq_num_vld), + + .cfg_max_payload(cfg_max_payload), + .cfg_max_read_req(cfg_max_read_req), + + .cfg_mgmt_addr(cfg_mgmt_addr), + .cfg_mgmt_write(cfg_mgmt_write), + .cfg_mgmt_write_data(cfg_mgmt_write_data), + .cfg_mgmt_byte_enable(cfg_mgmt_byte_enable), + .cfg_mgmt_read(cfg_mgmt_read), + .cfg_mgmt_read_data(cfg_mgmt_read_data), + .cfg_mgmt_read_write_done(cfg_mgmt_read_write_done), + + .cfg_fc_ph(cfg_fc_ph), + .cfg_fc_pd(cfg_fc_pd), + .cfg_fc_nph(cfg_fc_nph), + .cfg_fc_npd(cfg_fc_npd), + .cfg_fc_cplh(cfg_fc_cplh), + .cfg_fc_cpld(cfg_fc_cpld), + .cfg_fc_sel(cfg_fc_sel), + + .cfg_interrupt_msi_enable(cfg_interrupt_msi_enable), + .cfg_interrupt_msi_vf_enable(cfg_interrupt_msi_vf_enable), + .cfg_interrupt_msi_mmenable(cfg_interrupt_msi_mmenable), + .cfg_interrupt_msi_mask_update(cfg_interrupt_msi_mask_update), + .cfg_interrupt_msi_data(cfg_interrupt_msi_data), + .cfg_interrupt_msi_select(cfg_interrupt_msi_select), + .cfg_interrupt_msi_int(cfg_interrupt_msi_int), + .cfg_interrupt_msi_pending_status(cfg_interrupt_msi_pending_status), + .cfg_interrupt_msi_pending_status_data_enable(cfg_interrupt_msi_pending_status_data_enable), + .cfg_interrupt_msi_pending_status_function_num(cfg_interrupt_msi_pending_status_function_num), + .cfg_interrupt_msi_sent(cfg_interrupt_msi_sent), + .cfg_interrupt_msi_fail(cfg_interrupt_msi_fail), + .cfg_interrupt_msi_attr(cfg_interrupt_msi_attr), + .cfg_interrupt_msi_tph_present(cfg_interrupt_msi_tph_present), + .cfg_interrupt_msi_tph_type(cfg_interrupt_msi_tph_type), + .cfg_interrupt_msi_tph_st_tag(cfg_interrupt_msi_tph_st_tag), + .cfg_interrupt_msi_function_number(cfg_interrupt_msi_function_number), + + .status_error_cor(status_error_cor), + .status_error_uncor(status_error_uncor) +); + +endmodule + +`resetall diff --git a/fpga/lib/pcie/example/VCU108/fpga/rtl/fpga_core.v b/fpga/lib/pcie/example/VCU108/fpga/rtl/fpga_core.v new file mode 100644 index 000000000..2c8e30e91 --- /dev/null +++ b/fpga/lib/pcie/example/VCU108/fpga/rtl/fpga_core.v @@ -0,0 +1,276 @@ +/* + +Copyright (c) 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 1ns / 1ps +`default_nettype none + +/* + * FPGA core logic + */ +module fpga_core # +( + parameter AXIS_PCIE_DATA_WIDTH = 256, + parameter AXIS_PCIE_KEEP_WIDTH = (AXIS_PCIE_DATA_WIDTH/32), + parameter AXIS_PCIE_RC_USER_WIDTH = 75, + parameter AXIS_PCIE_RQ_USER_WIDTH = 60, + parameter AXIS_PCIE_CQ_USER_WIDTH = 85, + parameter AXIS_PCIE_CC_USER_WIDTH = 33, + parameter RQ_SEQ_NUM_WIDTH = AXIS_PCIE_RQ_USER_WIDTH == 60 ? 4 : 6, + parameter RQ_SEQ_NUM_ENABLE = 1, + parameter PCIE_TAG_COUNT = 64, + parameter BAR0_APERTURE = 24, + parameter BAR2_APERTURE = 24 +) +( + /* + * Clock: 250 MHz + * Synchronous reset + */ + input wire clk, + input wire rst, + + /* + * GPIO + */ + input wire btnu, + input wire btnl, + input wire btnd, + input wire btnr, + input wire btnc, + input wire [3:0] sw, + output wire [7:0] led, + + /* + * PCIe + */ + output wire [AXIS_PCIE_DATA_WIDTH-1:0] m_axis_rq_tdata, + output wire [AXIS_PCIE_KEEP_WIDTH-1:0] m_axis_rq_tkeep, + output wire m_axis_rq_tlast, + input wire m_axis_rq_tready, + output wire [AXIS_PCIE_RQ_USER_WIDTH-1:0] m_axis_rq_tuser, + output wire m_axis_rq_tvalid, + + input wire [AXIS_PCIE_DATA_WIDTH-1:0] s_axis_rc_tdata, + input wire [AXIS_PCIE_KEEP_WIDTH-1:0] s_axis_rc_tkeep, + input wire s_axis_rc_tlast, + output wire s_axis_rc_tready, + input wire [AXIS_PCIE_RC_USER_WIDTH-1:0] s_axis_rc_tuser, + input wire s_axis_rc_tvalid, + + input wire [AXIS_PCIE_DATA_WIDTH-1:0] s_axis_cq_tdata, + input wire [AXIS_PCIE_KEEP_WIDTH-1:0] s_axis_cq_tkeep, + input wire s_axis_cq_tlast, + output wire s_axis_cq_tready, + input wire [AXIS_PCIE_CQ_USER_WIDTH-1:0] s_axis_cq_tuser, + input wire s_axis_cq_tvalid, + + output wire [AXIS_PCIE_DATA_WIDTH-1:0] m_axis_cc_tdata, + output wire [AXIS_PCIE_KEEP_WIDTH-1:0] m_axis_cc_tkeep, + output wire m_axis_cc_tlast, + input wire m_axis_cc_tready, + output wire [AXIS_PCIE_CC_USER_WIDTH-1:0] m_axis_cc_tuser, + output wire m_axis_cc_tvalid, + + input wire [RQ_SEQ_NUM_WIDTH-1:0] s_axis_rq_seq_num, + input wire s_axis_rq_seq_num_valid, + + input wire [2:0] cfg_max_payload, + input wire [2:0] cfg_max_read_req, + + output wire [18:0] cfg_mgmt_addr, + output wire cfg_mgmt_write, + output wire [31:0] cfg_mgmt_write_data, + output wire [3:0] cfg_mgmt_byte_enable, + output wire cfg_mgmt_read, + input wire [31:0] cfg_mgmt_read_data, + input wire cfg_mgmt_read_write_done, + + input wire [7:0] cfg_fc_ph, + input wire [11:0] cfg_fc_pd, + input wire [7:0] cfg_fc_nph, + input wire [11:0] cfg_fc_npd, + input wire [7:0] cfg_fc_cplh, + input wire [11:0] cfg_fc_cpld, + output wire [2:0] cfg_fc_sel, + + input wire [3:0] cfg_interrupt_msi_enable, + input wire [7:0] cfg_interrupt_msi_vf_enable, + input wire [11:0] cfg_interrupt_msi_mmenable, + input wire cfg_interrupt_msi_mask_update, + input wire [31:0] cfg_interrupt_msi_data, + output wire [3:0] cfg_interrupt_msi_select, + output wire [31:0] cfg_interrupt_msi_int, + output wire [31:0] cfg_interrupt_msi_pending_status, + output wire cfg_interrupt_msi_pending_status_data_enable, + output wire [3:0] cfg_interrupt_msi_pending_status_function_num, + input wire cfg_interrupt_msi_sent, + input wire cfg_interrupt_msi_fail, + output wire [2:0] cfg_interrupt_msi_attr, + output wire cfg_interrupt_msi_tph_present, + output wire [1:0] cfg_interrupt_msi_tph_type, + output wire [8:0] cfg_interrupt_msi_tph_st_tag, + output wire [3:0] cfg_interrupt_msi_function_number, + + output wire status_error_cor, + output wire status_error_uncor +); + +assign led = 8'd0; + +example_core_pcie_us #( + .AXIS_PCIE_DATA_WIDTH(AXIS_PCIE_DATA_WIDTH), + .AXIS_PCIE_KEEP_WIDTH(AXIS_PCIE_KEEP_WIDTH), + .AXIS_PCIE_RC_USER_WIDTH(AXIS_PCIE_RC_USER_WIDTH), + .AXIS_PCIE_RQ_USER_WIDTH(AXIS_PCIE_RQ_USER_WIDTH), + .AXIS_PCIE_CQ_USER_WIDTH(AXIS_PCIE_CQ_USER_WIDTH), + .AXIS_PCIE_CC_USER_WIDTH(AXIS_PCIE_CC_USER_WIDTH), + .RQ_SEQ_NUM_WIDTH(RQ_SEQ_NUM_WIDTH), + .RQ_SEQ_NUM_ENABLE(RQ_SEQ_NUM_ENABLE), + .PCIE_TAG_COUNT(PCIE_TAG_COUNT), + .READ_OP_TABLE_SIZE(PCIE_TAG_COUNT), + .READ_TX_LIMIT(2**(RQ_SEQ_NUM_WIDTH-1)), + .READ_TX_FC_ENABLE(1), + .WRITE_OP_TABLE_SIZE(2**(RQ_SEQ_NUM_WIDTH-1)), + .WRITE_TX_LIMIT(2**(RQ_SEQ_NUM_WIDTH-1)), + .WRITE_TX_FC_ENABLE(1), + .BAR0_APERTURE(BAR0_APERTURE), + .BAR2_APERTURE(BAR2_APERTURE) +) +example_core_pcie_us_inst ( + .clk(clk), + .rst(rst), + + /* + * AXI input (RC) + */ + .s_axis_rc_tdata(s_axis_rc_tdata), + .s_axis_rc_tkeep(s_axis_rc_tkeep), + .s_axis_rc_tvalid(s_axis_rc_tvalid), + .s_axis_rc_tready(s_axis_rc_tready), + .s_axis_rc_tlast(s_axis_rc_tlast), + .s_axis_rc_tuser(s_axis_rc_tuser), + + /* + * AXI output (RQ) + */ + .m_axis_rq_tdata(m_axis_rq_tdata), + .m_axis_rq_tkeep(m_axis_rq_tkeep), + .m_axis_rq_tvalid(m_axis_rq_tvalid), + .m_axis_rq_tready(m_axis_rq_tready), + .m_axis_rq_tlast(m_axis_rq_tlast), + .m_axis_rq_tuser(m_axis_rq_tuser), + + /* + * AXI input (CQ) + */ + .s_axis_cq_tdata(s_axis_cq_tdata), + .s_axis_cq_tkeep(s_axis_cq_tkeep), + .s_axis_cq_tvalid(s_axis_cq_tvalid), + .s_axis_cq_tready(s_axis_cq_tready), + .s_axis_cq_tlast(s_axis_cq_tlast), + .s_axis_cq_tuser(s_axis_cq_tuser), + + /* + * AXI output (CC) + */ + .m_axis_cc_tdata(m_axis_cc_tdata), + .m_axis_cc_tkeep(m_axis_cc_tkeep), + .m_axis_cc_tvalid(m_axis_cc_tvalid), + .m_axis_cc_tready(m_axis_cc_tready), + .m_axis_cc_tlast(m_axis_cc_tlast), + .m_axis_cc_tuser(m_axis_cc_tuser), + + /* + * Transmit sequence number input + */ + .s_axis_rq_seq_num_0(s_axis_rq_seq_num), + .s_axis_rq_seq_num_valid_0(s_axis_rq_seq_num_valid), + .s_axis_rq_seq_num_1(0), + .s_axis_rq_seq_num_valid_1(0), + + /* + * Flow control + */ + .cfg_fc_ph(cfg_fc_ph), + .cfg_fc_pd(cfg_fc_pd), + .cfg_fc_nph(cfg_fc_nph), + .cfg_fc_npd(cfg_fc_npd), + .cfg_fc_cplh(cfg_fc_cplh), + .cfg_fc_cpld(cfg_fc_cpld), + .cfg_fc_sel(cfg_fc_sel), + + /* + * Configuration interface + */ + .cfg_mgmt_addr(cfg_mgmt_addr[9:0]), + .cfg_mgmt_function_number(cfg_mgmt_addr[17:10]), + .cfg_mgmt_write(cfg_mgmt_write), + .cfg_mgmt_write_data(cfg_mgmt_write_data), + .cfg_mgmt_byte_enable(cfg_mgmt_byte_enable), + .cfg_mgmt_read(cfg_mgmt_read), + .cfg_mgmt_read_data(cfg_mgmt_read_data), + .cfg_mgmt_read_write_done(cfg_mgmt_read_write_done), + + /* + * Interrupt interface + */ + .cfg_interrupt_msi_enable(cfg_interrupt_msi_enable), + .cfg_interrupt_msi_vf_enable(cfg_interrupt_msi_vf_enable), + .cfg_interrupt_msi_mmenable(cfg_interrupt_msi_mmenable), + .cfg_interrupt_msi_mask_update(cfg_interrupt_msi_mask_update), + .cfg_interrupt_msi_data(cfg_interrupt_msi_data), + .cfg_interrupt_msi_select(cfg_interrupt_msi_select), + .cfg_interrupt_msi_int(cfg_interrupt_msi_int), + .cfg_interrupt_msi_pending_status(cfg_interrupt_msi_pending_status), + .cfg_interrupt_msi_pending_status_data_enable(cfg_interrupt_msi_pending_status_data_enable), + .cfg_interrupt_msi_pending_status_function_num(cfg_interrupt_msi_pending_status_function_num), + .cfg_interrupt_msi_sent(cfg_interrupt_msi_sent), + .cfg_interrupt_msi_fail(cfg_interrupt_msi_fail), + .cfg_interrupt_msi_attr(cfg_interrupt_msi_attr), + .cfg_interrupt_msi_tph_present(cfg_interrupt_msi_tph_present), + .cfg_interrupt_msi_tph_type(cfg_interrupt_msi_tph_type), + .cfg_interrupt_msi_tph_st_tag(cfg_interrupt_msi_tph_st_tag), + .cfg_interrupt_msi_function_number(cfg_interrupt_msi_function_number), + + /* + * Configuration + */ + .cfg_max_read_req(cfg_max_read_req), + .cfg_max_payload(cfg_max_payload), + + /* + * Status + */ + .status_error_cor(status_error_cor), + .status_error_uncor(status_error_uncor) +); + +assign cfg_mgmt_addr[18] = 1'b0; + +endmodule + +`resetall diff --git a/fpga/lib/pcie/example/VCU108/fpga/rtl/sync_reset.v b/fpga/lib/pcie/example/VCU108/fpga/rtl/sync_reset.v new file mode 100644 index 000000000..1fd24d361 --- /dev/null +++ b/fpga/lib/pcie/example/VCU108/fpga/rtl/sync_reset.v @@ -0,0 +1,56 @@ +/* + +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 active-high asynchronous reset signal to a given clock by + * using a pipeline of N registers. + */ +module sync_reset #( + parameter N=2 // depth of synchronizer +)( + input wire clk, + input wire rst, + output wire sync_reset_out +); + +reg [N-1:0] sync_reg = {N{1'b1}}; + +assign sync_reset_out = sync_reg[N-1]; + +always @(posedge clk or posedge rst) begin + if (rst) + sync_reg <= {N{1'b1}}; + else + sync_reg <= {sync_reg[N-2:0], 1'b0}; +end + +endmodule + +`resetall diff --git a/fpga/lib/pcie/example/VCU108/fpga/rtl/sync_signal.v b/fpga/lib/pcie/example/VCU108/fpga/rtl/sync_signal.v new file mode 100644 index 000000000..74b855fa1 --- /dev/null +++ b/fpga/lib/pcie/example/VCU108/fpga/rtl/sync_signal.v @@ -0,0 +1,62 @@ +/* + +Copyright (c) 2014-2018 Alex Forencich + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +*/ + +// Language: Verilog-2001 + +`resetall +`timescale 1 ns / 1 ps +`default_nettype none + +/* + * Synchronizes an asyncronous signal to a given clock by using a pipeline of + * two registers. + */ +module sync_signal #( + parameter WIDTH=1, // width of the input and output signals + parameter N=2 // depth of synchronizer +)( + input wire clk, + input wire [WIDTH-1:0] in, + output wire [WIDTH-1:0] out +); + +reg [WIDTH-1:0] sync_reg[N-1:0]; + +/* + * The synchronized output is the last register in the pipeline. + */ +assign out = sync_reg[N-1]; + +integer k; + +always @(posedge clk) begin + sync_reg[0] <= in; + for (k = 1; k < N; k = k + 1) begin + sync_reg[k] <= sync_reg[k-1]; + end +end + +endmodule + +`resetall diff --git a/fpga/lib/pcie/example/VCU108/fpga/tb/fpga_core/Makefile b/fpga/lib/pcie/example/VCU108/fpga/tb/fpga_core/Makefile new file mode 100644 index 000000000..2cd4c6b21 --- /dev/null +++ b/fpga/lib/pcie/example/VCU108/fpga/tb/fpga_core/Makefile @@ -0,0 +1,123 @@ +# Copyright (c) 2020 Alex Forencich +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +TOPLEVEL_LANG = verilog + +SIM ?= icarus +WAVES ?= 0 + +COCOTB_HDL_TIMEUNIT = 1ns +COCOTB_HDL_TIMEPRECISION = 1ps + +DUT = fpga_core +TOPLEVEL = $(DUT) +MODULE = test_$(DUT) +VERILOG_SOURCES += ../../rtl/$(DUT).v +VERILOG_SOURCES += ../../rtl/common/example_core_pcie_us.v +VERILOG_SOURCES += ../../rtl/common/example_core_pcie.v +VERILOG_SOURCES += ../../rtl/common/example_core.v +VERILOG_SOURCES += ../../rtl/common/axi_ram.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_if.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_if_rc.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_if_rq.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_if_cq.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_if_cc.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_cfg.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_msi.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_axil_master.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_axi_master.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_axi_master_rd.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_axi_master_wr.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_tlp_demux_bar.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_tlp_demux.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_tlp_mux.v +VERILOG_SOURCES += ../../lib/pcie/rtl/dma_if_pcie.v +VERILOG_SOURCES += ../../lib/pcie/rtl/dma_if_pcie_rd.v +VERILOG_SOURCES += ../../lib/pcie/rtl/dma_if_pcie_wr.v +VERILOG_SOURCES += ../../lib/pcie/rtl/dma_psdpram.v +VERILOG_SOURCES += ../../lib/pcie/rtl/arbiter.v +VERILOG_SOURCES += ../../lib/pcie/rtl/priority_encoder.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pulse_merge.v + +# module parameters +export PARAM_AXIS_PCIE_DATA_WIDTH ?= 256 +export PARAM_AXIS_PCIE_KEEP_WIDTH ?= $(shell expr $(PARAM_AXIS_PCIE_DATA_WIDTH) / 32 ) +export PARAM_AXIS_PCIE_RQ_USER_WIDTH ?= 60 +export PARAM_AXIS_PCIE_RC_USER_WIDTH ?= 75 +export PARAM_AXIS_PCIE_CQ_USER_WIDTH ?= 85 +export PARAM_AXIS_PCIE_CC_USER_WIDTH ?= 33 +export PARAM_RQ_SEQ_NUM_WIDTH ?= 4 +export PARAM_RQ_SEQ_NUM_ENABLE ?= 1 +export PARAM_PCIE_TAG_COUNT ?= 64 +export PARAM_BAR0_APERTURE ?= 24 +export PARAM_BAR2_APERTURE ?= 24 + +ifeq ($(SIM), icarus) + PLUSARGS += -fst + + COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_DATA_WIDTH=$(PARAM_AXIS_PCIE_DATA_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_KEEP_WIDTH=$(PARAM_AXIS_PCIE_KEEP_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_RQ_USER_WIDTH=$(PARAM_AXIS_PCIE_RQ_USER_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_RC_USER_WIDTH=$(PARAM_AXIS_PCIE_RC_USER_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_CQ_USER_WIDTH=$(PARAM_AXIS_PCIE_CQ_USER_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_CC_USER_WIDTH=$(PARAM_AXIS_PCIE_CC_USER_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).RQ_SEQ_NUM_WIDTH=$(PARAM_RQ_SEQ_NUM_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).RQ_SEQ_NUM_ENABLE=$(PARAM_RQ_SEQ_NUM_ENABLE) + COMPILE_ARGS += -P $(TOPLEVEL).PCIE_TAG_COUNT=$(PARAM_PCIE_TAG_COUNT) + COMPILE_ARGS += -P $(TOPLEVEL).BAR0_APERTURE=$(PARAM_BAR0_APERTURE) + COMPILE_ARGS += -P $(TOPLEVEL).BAR2_APERTURE=$(PARAM_BAR2_APERTURE) + + ifeq ($(WAVES), 1) + VERILOG_SOURCES += iverilog_dump.v + COMPILE_ARGS += -s iverilog_dump + endif +else ifeq ($(SIM), verilator) + COMPILE_ARGS += -Wno-SELRANGE -Wno-WIDTH + + COMPILE_ARGS += -GAXIS_PCIE_DATA_WIDTH=$(PARAM_AXIS_PCIE_DATA_WIDTH) + COMPILE_ARGS += -GAXIS_PCIE_KEEP_WIDTH=$(PARAM_AXIS_PCIE_KEEP_WIDTH) + COMPILE_ARGS += -GAXIS_PCIE_RQ_USER_WIDTH=$(PARAM_AXIS_PCIE_RQ_USER_WIDTH) + COMPILE_ARGS += -GAXIS_PCIE_RC_USER_WIDTH=$(PARAM_AXIS_PCIE_RC_USER_WIDTH) + COMPILE_ARGS += -GAXIS_PCIE_CQ_USER_WIDTH=$(PARAM_AXIS_PCIE_CQ_USER_WIDTH) + COMPILE_ARGS += -GAXIS_PCIE_CC_USER_WIDTH=$(PARAM_AXIS_PCIE_CC_USER_WIDTH) + COMPILE_ARGS += -GRQ_SEQ_NUM_WIDTH=$(PARAM_RQ_SEQ_NUM_WIDTH) + COMPILE_ARGS += -GRQ_SEQ_NUM_ENABLE=$(PARAM_RQ_SEQ_NUM_ENABLE) + COMPILE_ARGS += -GPCIE_TAG_COUNT=$(PARAM_PCIE_TAG_COUNT) + COMPILE_ARGS += -GBAR0_APERTURE=$(PARAM_BAR0_APERTURE) + COMPILE_ARGS += -GBAR2_APERTURE=$(PARAM_BAR2_APERTURE) + + ifeq ($(WAVES), 1) + COMPILE_ARGS += --trace-fst + endif +endif + +include $(shell cocotb-config --makefiles)/Makefile.sim + +iverilog_dump.v: + echo 'module iverilog_dump();' > $@ + echo 'initial begin' >> $@ + echo ' $$dumpfile("$(TOPLEVEL).fst");' >> $@ + echo ' $$dumpvars(0, $(TOPLEVEL));' >> $@ + echo 'end' >> $@ + echo 'endmodule' >> $@ + +clean:: + @rm -rf iverilog_dump.v + @rm -rf dump.fst $(TOPLEVEL).fst diff --git a/fpga/lib/pcie/example/VCU108/fpga/tb/fpga_core/test_fpga_core.py b/fpga/lib/pcie/example/VCU108/fpga/tb/fpga_core/test_fpga_core.py new file mode 100644 index 000000000..742d4efed --- /dev/null +++ b/fpga/lib/pcie/example/VCU108/fpga/tb/fpga_core/test_fpga_core.py @@ -0,0 +1,473 @@ +""" + +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 + +import cocotb_test.simulator + +import cocotb +from cocotb.log import SimLog +from cocotb.triggers import RisingEdge, FallingEdge, Timer + +from cocotbext.axi import AxiStreamBus +from cocotbext.pcie.core import RootComplex +from cocotbext.pcie.xilinx.us import UltraScalePcieDevice + + +class TB(object): + def __init__(self, dut): + self.dut = dut + + self.log = SimLog("cocotb.tb") + self.log.setLevel(logging.DEBUG) + + # PCIe + self.rc = RootComplex() + + self.dev = UltraScalePcieDevice( + # configuration options + pcie_generation=3, + pcie_link_width=8, + user_clk_frequency=250e6, + alignment="dword", + straddle=False, + enable_pf1=False, + enable_client_tag=True, + enable_extended_tag=True, + enable_parity=False, + enable_rx_msg_interface=False, + enable_sriov=False, + enable_extended_configuration=False, + + enable_pf0_msi=True, + enable_pf1_msi=False, + + # signals + # Clock and Reset Interface + user_clk=dut.clk, + user_reset=dut.rst, + # user_lnk_up + # sys_clk + # sys_clk_gt + # sys_reset + # phy_rdy_out + + # Requester reQuest Interface + rq_bus=AxiStreamBus.from_prefix(dut, "m_axis_rq"), + pcie_rq_seq_num=dut.s_axis_rq_seq_num, + pcie_rq_seq_num_vld=dut.s_axis_rq_seq_num_valid, + # pcie_rq_tag + # pcie_rq_tag_av + # pcie_rq_tag_vld + + # Requester Completion Interface + rc_bus=AxiStreamBus.from_prefix(dut, "s_axis_rc"), + + # Completer reQuest Interface + cq_bus=AxiStreamBus.from_prefix(dut, "s_axis_cq"), + # pcie_cq_np_req + # pcie_cq_np_req_count + + # Completer Completion Interface + cc_bus=AxiStreamBus.from_prefix(dut, "m_axis_cc"), + + # Transmit Flow Control Interface + # pcie_tfc_nph_av=dut.pcie_tfc_nph_av, + # pcie_tfc_npd_av=dut.pcie_tfc_npd_av, + + # Configuration Management Interface + cfg_mgmt_addr=dut.cfg_mgmt_addr, + cfg_mgmt_write=dut.cfg_mgmt_write, + cfg_mgmt_write_data=dut.cfg_mgmt_write_data, + cfg_mgmt_byte_enable=dut.cfg_mgmt_byte_enable, + cfg_mgmt_read=dut.cfg_mgmt_read, + cfg_mgmt_read_data=dut.cfg_mgmt_read_data, + cfg_mgmt_read_write_done=dut.cfg_mgmt_read_write_done, + # cfg_mgmt_debug_access + + # Configuration Status Interface + # cfg_phy_link_down + # cfg_phy_link_status + # cfg_negotiated_width + # cfg_current_speed + cfg_max_payload=dut.cfg_max_payload, + cfg_max_read_req=dut.cfg_max_read_req, + # cfg_function_status + # cfg_vf_status + # cfg_function_power_state + # cfg_vf_power_state + # cfg_link_power_state + # cfg_err_cor_out + # cfg_err_nonfatal_out + # cfg_err_fatal_out + # cfg_local_error_out + # cfg_local_error_valid + # cfg_rx_pm_state + # cfg_tx_pm_state + # cfg_ltssm_state + # cfg_rcb_status + # cfg_obff_enable + # cfg_pl_status_change + # cfg_tph_requester_enable + # cfg_tph_st_mode + # cfg_vf_tph_requester_enable + # cfg_vf_tph_st_mode + + # Configuration Received Message Interface + # cfg_msg_received + # cfg_msg_received_data + # cfg_msg_received_type + + # Configuration Transmit Message Interface + # cfg_msg_transmit + # cfg_msg_transmit_type + # cfg_msg_transmit_data + # cfg_msg_transmit_done + + # Configuration Flow Control Interface + cfg_fc_ph=dut.cfg_fc_ph, + cfg_fc_pd=dut.cfg_fc_pd, + cfg_fc_nph=dut.cfg_fc_nph, + cfg_fc_npd=dut.cfg_fc_npd, + cfg_fc_cplh=dut.cfg_fc_cplh, + cfg_fc_cpld=dut.cfg_fc_cpld, + cfg_fc_sel=dut.cfg_fc_sel, + + # Configuration Control Interface + # cfg_hot_reset_in + # cfg_hot_reset_out + # cfg_config_space_enable + # cfg_dsn + # cfg_bus_number + # cfg_ds_port_number + # cfg_ds_bus_number + # cfg_ds_device_number + # cfg_ds_function_number + # cfg_power_state_change_ack + # cfg_power_state_change_interrupt + cfg_err_cor_in=dut.status_error_cor, + cfg_err_uncor_in=dut.status_error_uncor, + # cfg_flr_in_process + # cfg_flr_done + # cfg_vf_flr_in_process + # cfg_vf_flr_func_num + # cfg_vf_flr_done + # cfg_pm_aspm_l1_entry_reject + # cfg_pm_aspm_tx_l0s_entry_disable + # cfg_req_pm_transition_l23_ready + # cfg_link_training_enable + + # Configuration Interrupt Controller Interface + # cfg_interrupt_int + # cfg_interrupt_sent + # cfg_interrupt_pending + cfg_interrupt_msi_enable=dut.cfg_interrupt_msi_enable, + cfg_interrupt_msi_vf_enable=dut.cfg_interrupt_msi_vf_enable, + cfg_interrupt_msi_mmenable=dut.cfg_interrupt_msi_mmenable, + cfg_interrupt_msi_mask_update=dut.cfg_interrupt_msi_mask_update, + cfg_interrupt_msi_data=dut.cfg_interrupt_msi_data, + cfg_interrupt_msi_select=dut.cfg_interrupt_msi_select, + cfg_interrupt_msi_int=dut.cfg_interrupt_msi_int, + cfg_interrupt_msi_pending_status=dut.cfg_interrupt_msi_pending_status, + cfg_interrupt_msi_pending_status_data_enable=dut.cfg_interrupt_msi_pending_status_data_enable, + cfg_interrupt_msi_pending_status_function_num=dut.cfg_interrupt_msi_pending_status_function_num, + cfg_interrupt_msi_sent=dut.cfg_interrupt_msi_sent, + cfg_interrupt_msi_fail=dut.cfg_interrupt_msi_fail, + # cfg_interrupt_msix_enable + # cfg_interrupt_msix_mask + # cfg_interrupt_msix_vf_enable + # cfg_interrupt_msix_vf_mask + # cfg_interrupt_msix_address + # cfg_interrupt_msix_data + # cfg_interrupt_msix_int + # cfg_interrupt_msix_vec_pending + # cfg_interrupt_msix_vec_pending_status + cfg_interrupt_msi_attr=dut.cfg_interrupt_msi_attr, + cfg_interrupt_msi_tph_present=dut.cfg_interrupt_msi_tph_present, + cfg_interrupt_msi_tph_type=dut.cfg_interrupt_msi_tph_type, + # cfg_interrupt_msi_tph_st_tag=dut.cfg_interrupt_msi_tph_st_tag, + # cfg_interrupt_msi_function_number=dut.cfg_interrupt_msi_function_number, + + # Configuration Extend Interface + # cfg_ext_read_received + # cfg_ext_write_received + # cfg_ext_register_number + # cfg_ext_function_number + # cfg_ext_write_data + # cfg_ext_write_byte_enable + # cfg_ext_read_data + # cfg_ext_read_data_valid + ) + + # self.dev.log.setLevel(logging.DEBUG) + + self.rc.make_port().connect(self.dev) + + self.dev.functions[0].msi_multiple_message_capable = 5 + + self.dev.functions[0].configure_bar(0, 2**len(dut.example_core_pcie_us_inst.core_pcie_inst.axil_ctrl_awaddr)) + self.dev.functions[0].configure_bar(2, 2**len(dut.example_core_pcie_us_inst.core_pcie_inst.axi_ram_awaddr)) + + dut.btnu.setimmediatevalue(0) + dut.btnl.setimmediatevalue(0) + dut.btnd.setimmediatevalue(0) + dut.btnr.setimmediatevalue(0) + dut.btnc.setimmediatevalue(0) + dut.sw.setimmediatevalue(0) + + async def init(self): + + await FallingEdge(self.dut.rst) + await Timer(100, 'ns') + + await self.rc.enumerate(enable_bus_mastering=True, configure_msi=True) + + +@cocotb.test() +async def run_test(dut): + + tb = TB(dut) + + await tb.init() + + mem = tb.rc.mem_pool.alloc_region(16*1024*1024) + mem_base = mem.get_absolute_address(0) + + dev_pf0_bar0 = tb.rc.tree[0][0].bar_window[0] + dev_pf0_bar2 = tb.rc.tree[0][0].bar_window[2] + + tb.log.info("Test memory write to BAR 2") + + test_data = b'\x11\x22\x33\x44' + await dev_pf0_bar2.write(0, test_data) + + await Timer(100, 'ns') + + tb.log.info("Test memory read from BAR 2") + + val = await dev_pf0_bar2.read(0, len(test_data), timeout=1000) + tb.log.info("Read data: %s", val) + assert val == test_data + + tb.log.info("Test DMA") + + # write packet data + mem[0:1024] = bytearray([x % 256 for x in range(1024)]) + + # enable DMA + await dev_pf0_bar0.write_dword(0x000000, 1) + + # write pcie read descriptor + await dev_pf0_bar0.write_dword(0x000100, (mem_base+0x0000) & 0xffffffff) + await dev_pf0_bar0.write_dword(0x000104, (mem_base+0x0000 >> 32) & 0xffffffff) + await dev_pf0_bar0.write_dword(0x000108, 0x100) + await dev_pf0_bar0.write_dword(0x000110, 0x400) + await dev_pf0_bar0.write_dword(0x000114, 0xAA) + + await Timer(2000, 'ns') + + # read status + val = await dev_pf0_bar0.read_dword(0x000118) + tb.log.info("Status: 0x%x", val) + assert val == 0x800000AA + + # write pcie write descriptor + await dev_pf0_bar0.write_dword(0x000200, (mem_base+0x1000) & 0xffffffff) + await dev_pf0_bar0.write_dword(0x000204, (mem_base+0x1000 >> 32) & 0xffffffff) + await dev_pf0_bar0.write_dword(0x000208, 0x100) + await dev_pf0_bar0.write_dword(0x000210, 0x400) + await dev_pf0_bar0.write_dword(0x000214, 0x55) + + await Timer(2000, 'ns') + + # read status + val = await dev_pf0_bar0.read_dword(0x000218) + tb.log.info("Status: 0x%x", val) + assert val == 0x80000055 + + tb.log.info("%s", mem.hexdump_str(0x1000, 64)) + + assert mem[0:1024] == mem[0x1000:0x1000+1024] + + tb.log.info("Test DMA block operations") + + # write packet data + mem[0:1024] = bytearray([x % 256 for x in range(1024)]) + + # enable DMA + await dev_pf0_bar0.write_dword(0x000000, 1) + # disable interrupts + await dev_pf0_bar0.write_dword(0x000008, 0) + + # configure operation (read) + # DMA base address + await dev_pf0_bar0.write_dword(0x001080, (mem_base+0x0000) & 0xffffffff) + await dev_pf0_bar0.write_dword(0x001084, (mem_base+0x0000 >> 32) & 0xffffffff) + # DMA offset address + await dev_pf0_bar0.write_dword(0x001088, 0) + await dev_pf0_bar0.write_dword(0x00108c, 0) + # DMA offset mask + await dev_pf0_bar0.write_dword(0x001090, 0x000003ff) + await dev_pf0_bar0.write_dword(0x001094, 0) + # DMA stride + await dev_pf0_bar0.write_dword(0x001098, 256) + await dev_pf0_bar0.write_dword(0x00109c, 0) + # RAM base address + await dev_pf0_bar0.write_dword(0x0010c0, 0) + await dev_pf0_bar0.write_dword(0x0010c4, 0) + # RAM offset address + await dev_pf0_bar0.write_dword(0x0010c8, 0) + await dev_pf0_bar0.write_dword(0x0010cc, 0) + # RAM offset mask + await dev_pf0_bar0.write_dword(0x0010d0, 0x000003ff) + await dev_pf0_bar0.write_dword(0x0010d4, 0) + # RAM stride + await dev_pf0_bar0.write_dword(0x0010d8, 256) + await dev_pf0_bar0.write_dword(0x0010dc, 0) + # clear cycle count + await dev_pf0_bar0.write_dword(0x001008, 0) + await dev_pf0_bar0.write_dword(0x00100c, 0) + # block length + await dev_pf0_bar0.write_dword(0x001010, 256) + # block count + await dev_pf0_bar0.write_dword(0x001018, 32) + await dev_pf0_bar0.write_dword(0x00101c, 0) + # start + await dev_pf0_bar0.write_dword(0x001000, 1) + + await Timer(2000, 'ns') + + # configure operation (write) + # DMA base address + await dev_pf0_bar0.write_dword(0x001180, (mem_base+0x0000) & 0xffffffff) + await dev_pf0_bar0.write_dword(0x001184, (mem_base+0x0000 >> 32) & 0xffffffff) + # DMA offset address + await dev_pf0_bar0.write_dword(0x001188, 0) + await dev_pf0_bar0.write_dword(0x00118c, 0) + # DMA offset mask + await dev_pf0_bar0.write_dword(0x001190, 0x000003ff) + await dev_pf0_bar0.write_dword(0x001194, 0) + # DMA stride + await dev_pf0_bar0.write_dword(0x001198, 256) + await dev_pf0_bar0.write_dword(0x00119c, 0) + # RAM base address + await dev_pf0_bar0.write_dword(0x0011c0, 0) + await dev_pf0_bar0.write_dword(0x0011c4, 0) + # RAM offset address + await dev_pf0_bar0.write_dword(0x0011c8, 0) + await dev_pf0_bar0.write_dword(0x0011cc, 0) + # RAM offset mask + await dev_pf0_bar0.write_dword(0x0011d0, 0x000003ff) + await dev_pf0_bar0.write_dword(0x0011d4, 0) + # RAM stride + await dev_pf0_bar0.write_dword(0x0011d8, 256) + await dev_pf0_bar0.write_dword(0x0011dc, 0) + # clear cycle count + await dev_pf0_bar0.write_dword(0x001108, 0) + await dev_pf0_bar0.write_dword(0x00110c, 0) + # block length + await dev_pf0_bar0.write_dword(0x001110, 256) + # block count + await dev_pf0_bar0.write_dword(0x001118, 32) + await dev_pf0_bar0.write_dword(0x00111c, 0) + # start + await dev_pf0_bar0.write_dword(0x001100, 1) + + await Timer(2000, 'ns') + + await RisingEdge(dut.clk) + await RisingEdge(dut.clk) + + +# cocotb-test + +tests_dir = 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')) +pcie_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'pcie', '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(rtl_dir, "common", "example_core_pcie_us.v"), + os.path.join(rtl_dir, "common", "example_core_pcie.v"), + os.path.join(rtl_dir, "common", "example_core.v"), + os.path.join(rtl_dir, "common", "axi_ram.v"), + os.path.join(pcie_rtl_dir, "pcie_us_if.v"), + os.path.join(pcie_rtl_dir, "pcie_us_if_rc.v"), + os.path.join(pcie_rtl_dir, "pcie_us_if_rq.v"), + os.path.join(pcie_rtl_dir, "pcie_us_if_cq.v"), + os.path.join(pcie_rtl_dir, "pcie_us_if_cc.v"), + os.path.join(pcie_rtl_dir, "pcie_us_cfg.v"), + os.path.join(pcie_rtl_dir, "pcie_us_msi.v"), + os.path.join(pcie_rtl_dir, "pcie_axil_master.v"), + os.path.join(pcie_rtl_dir, "pcie_axi_master.v"), + os.path.join(pcie_rtl_dir, "pcie_axi_master_rd.v"), + os.path.join(pcie_rtl_dir, "pcie_axi_master_wr.v"), + os.path.join(pcie_rtl_dir, "pcie_tlp_demux_bar.v"), + os.path.join(pcie_rtl_dir, "pcie_tlp_demux.v"), + os.path.join(pcie_rtl_dir, "pcie_tlp_mux.v"), + os.path.join(pcie_rtl_dir, "dma_if_pcie.v"), + os.path.join(pcie_rtl_dir, "dma_if_pcie_rd.v"), + os.path.join(pcie_rtl_dir, "dma_if_pcie_wr.v"), + os.path.join(pcie_rtl_dir, "dma_psdpram.v"), + os.path.join(pcie_rtl_dir, "arbiter.v"), + os.path.join(pcie_rtl_dir, "priority_encoder.v"), + os.path.join(pcie_rtl_dir, "pulse_merge.v"), + ] + + parameters = {} + + parameters['AXIS_PCIE_DATA_WIDTH'] = 256 + parameters['AXIS_PCIE_KEEP_WIDTH'] = parameters['AXIS_PCIE_DATA_WIDTH'] // 32 + parameters['AXIS_PCIE_RQ_USER_WIDTH'] = 60 + parameters['AXIS_PCIE_RC_USER_WIDTH'] = 75 + parameters['AXIS_PCIE_CQ_USER_WIDTH'] = 85 + parameters['AXIS_PCIE_CC_USER_WIDTH'] = 33 + parameters['RQ_SEQ_NUM_WIDTH'] = 4 + parameters['RQ_SEQ_NUM_ENABLE'] = 1 + parameters['PCIE_TAG_COUNT'] = 64 + parameters['BAR0_APERTURE'] = 24 + parameters['BAR2_APERTURE'] = 24 + + 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, + ) diff --git a/fpga/lib/pcie/example/VCU118/fpga/README.md b/fpga/lib/pcie/example/VCU118/fpga/README.md new file mode 100644 index 000000000..9db0d6bec --- /dev/null +++ b/fpga/lib/pcie/example/VCU118/fpga/README.md @@ -0,0 +1,19 @@ +# Verilog PCIe VCU118 Example Design + +## Introduction + +This example design targets the Xilinx VCU118 FPGA board. + +The design implements the PCIe AXI lite master module, the PCIe AXI master module, and the PCIe DMA module. A very simple Linux driver is included to test the FPGA design. + +* FPGA: xcvu9p-flga2104-2L-e + +## How to build + +Run `make` to build. Ensure that the Xilinx Vivado components are in PATH. + +Run `make` to build the driver. Ensure the headers for the running kernel are installed, otherwise the driver cannot be compiled. + +## How to test + +Run `make program` to program the VCU118 board with Vivado. Then load the driver with `insmod example.ko`. Check dmesg for the output. diff --git a/fpga/lib/pcie/example/VCU118/fpga/common/vivado.mk b/fpga/lib/pcie/example/VCU118/fpga/common/vivado.mk new file mode 100644 index 000000000..d47a43947 --- /dev/null +++ b/fpga/lib/pcie/example/VCU118/fpga/common/vivado.mk @@ -0,0 +1,126 @@ +################################################################### +# +# 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) + +SYN_FILES_REL = $(patsubst %, ../%, $(filter-out /% ./%,$(SYN_FILES))) $(filter /% ./%,$(SYN_FILES)) +INC_FILES_REL = $(patsubst %, ../%, $(filter-out /% ./%,$(INC_FILES))) $(filter /% ./%,$(INC_FILES)) +XCI_FILES_REL = $(patsubst %, ../%, $(filter-out /% ./%,$(XCI_FILES))) $(filter /% ./%,$(XCI_FILES)) +IP_TCL_FILES_REL = $(patsubst %, ../%, $(filter-out /% ./%,$(IP_TCL_FILES))) $(filter /% ./%,$(IP_TCL_FILES)) +CONFIG_TCL_FILES_REL = $(patsubst %, ../%, $(filter-out /% ./%,$(CONFIG_TCL_FILES))) $(filter /% ./%,$(CONFIG_TCL_FILES)) + +ifdef XDC_FILES + XDC_FILES_REL = $(patsubst %, ../%, $(filter-out /% ./%,$(XDC_FILES))) $(filter /% ./%,$(XDC_FILES)) +else + XDC_FILES_REL = $(FPGA_TOP).xdc +endif + +################################################################### +# Main Targets +# +# all: build everything +# clean: remove output files and project files +################################################################### + +all: fpga + +fpga: $(FPGA_TOP).bit + +vivado: $(FPGA_TOP).xpr + vivado $(FPGA_TOP).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 program.tcl generate_mcs.tcl *.mcs *.prm flash.tcl + +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) $(FPGA_TOP)" > $@ + echo "add_files -fileset sources_1 defines.v $(SYN_FILES_REL)" >> $@ + 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) + echo "open_project -quiet $(FPGA_TOP).xpr" > $@ + for x in $(CONFIG_TCL_FILES_REL); do echo "source $$x" >> $@; done + +$(FPGA_TOP).xpr: create_project.tcl update_config.tcl + vivado -nojournal -nolog -mode batch $(foreach x,$?,-source $x) + +# synthesis run +%.runs/synth_1/%.dcp: %.xpr $(SYN_FILES_REL) $(INC_FILES_REL) $(XDC_FILES_REL) $(CONFIG_TCL_FILES_REL) + echo "open_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 +%.runs/impl_1/%_routed.dcp: %.runs/synth_1/%.dcp + echo "open_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 + vivado -nojournal -nolog -mode batch -source run_impl.tcl + +# bit file +%.bit: %.runs/impl_1/%_routed.dcp + echo "open_project $*.xpr" > generate_bit.tcl + echo "open_run impl_1" >> generate_bit.tcl + echo "write_bitstream -force $*.bit" >> generate_bit.tcl + vivado -nojournal -nolog -mode batch -source generate_bit.tcl + mkdir -p rev + EXT=bit; COUNT=100; \ + while [ -e rev/$*_rev$$COUNT.$$EXT ]; \ + do COUNT=$$((COUNT+1)); done; \ + cp $@ rev/$*_rev$$COUNT.$$EXT; \ + echo "Output: rev/$*_rev$$COUNT.$$EXT"; diff --git a/fpga/lib/pcie/example/VCU118/fpga/driver b/fpga/lib/pcie/example/VCU118/fpga/driver new file mode 120000 index 000000000..4a54c76b5 --- /dev/null +++ b/fpga/lib/pcie/example/VCU118/fpga/driver @@ -0,0 +1 @@ +../../common/driver/example/ \ No newline at end of file diff --git a/fpga/lib/pcie/example/VCU118/fpga/fpga.xdc b/fpga/lib/pcie/example/VCU118/fpga/fpga.xdc new file mode 100644 index 000000000..c596d6931 --- /dev/null +++ b/fpga/lib/pcie/example/VCU118/fpga/fpga.xdc @@ -0,0 +1,302 @@ +# XDC constraints for the Xilinx VCU118 board +# part: xcvu9p-flga2104-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.EXTMASTERCCLK_EN {DIV-1} [current_design] +set_property BITSTREAM.CONFIG.SPI_32BIT_ADDR YES [current_design] +set_property BITSTREAM.CONFIG.SPI_BUSWIDTH 8 [current_design] +set_property BITSTREAM.CONFIG.SPI_FALL_EDGE YES [current_design] + +# System clocks +# 300 MHz +#set_property -dict {LOC G31 IOSTANDARD DIFF_SSTL12} [get_ports clk_300mhz_p] +#set_property -dict {LOC F31 IOSTANDARD DIFF_SSTL12} [get_ports clk_300mhz_n] +#create_clock -period 3.333 -name clk_300mhz [get_ports clk_300mhz_p] + +# 250 MHz +#set_property -dict {LOC E12 IOSTANDARD DIFF_SSTL12} [get_ports clk_250mhz_1_p] +#set_property -dict {LOC D12 IOSTANDARD DIFF_SSTL12} [get_ports clk_250mhz_1_n] +#create_clock -period 4 -name clk_250mhz_1 [get_ports clk_250mhz_1_p] + +#set_property -dict {LOC AW26 IOSTANDARD DIFF_SSTL12} [get_ports clk_250mhz_2_p] +#set_property -dict {LOC AW27 IOSTANDARD DIFF_SSTL12} [get_ports clk_250mhz_2_n] +#create_clock -period 4 -name clk_250mhz_2 [get_ports clk_250mhz_2_p] + +# 125 MHz +#set_property -dict {LOC AY24 IOSTANDARD LVDS} [get_ports clk_125mhz_p] +#set_property -dict {LOC AY23 IOSTANDARD LVDS} [get_ports clk_125mhz_n] +#create_clock -period 8.000 -name clk_125mhz [get_ports clk_125mhz_p] + +# 90 MHz +#set_property -dict {LOC AL20 IOSTANDARD LVCMOS18} [get_ports clk_90mhz] +#create_clock -period 11.111 -name clk_90mhz [get_ports clk_90mhz] + +# LEDs +set_property -dict {LOC AT32 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {led[0]}] +set_property -dict {LOC AV34 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {led[1]}] +set_property -dict {LOC AY30 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {led[2]}] +set_property -dict {LOC BB32 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {led[3]}] +set_property -dict {LOC BF32 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {led[4]}] +set_property -dict {LOC AU37 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {led[5]}] +set_property -dict {LOC AV36 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {led[6]}] +set_property -dict {LOC BA37 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {led[7]}] + +set_false_path -to [get_ports {led[*]}] +set_output_delay 0 [get_ports {led[*]}] + +# Reset button +#set_property -dict {LOC L19 IOSTANDARD LVCMOS12} [get_ports reset] + +#set_false_path -from [get_ports {reset}] +#set_input_delay 0 [get_ports {reset}] + +# Push buttons +set_property -dict {LOC BB24 IOSTANDARD LVCMOS18} [get_ports btnu] +set_property -dict {LOC BF22 IOSTANDARD LVCMOS18} [get_ports btnl] +set_property -dict {LOC BE22 IOSTANDARD LVCMOS18} [get_ports btnd] +set_property -dict {LOC BE23 IOSTANDARD LVCMOS18} [get_ports btnr] +set_property -dict {LOC BD23 IOSTANDARD LVCMOS18} [get_ports btnc] + +set_false_path -from [get_ports {btnu btnl btnd btnr btnc}] +set_input_delay 0 [get_ports {btnu btnl btnd btnr btnc}] + +# DIP switches +set_property -dict {LOC B17 IOSTANDARD LVCMOS12} [get_ports {sw[0]}] +set_property -dict {LOC G16 IOSTANDARD LVCMOS12} [get_ports {sw[1]}] +set_property -dict {LOC J16 IOSTANDARD LVCMOS12} [get_ports {sw[2]}] +set_property -dict {LOC D21 IOSTANDARD LVCMOS12} [get_ports {sw[3]}] + +set_false_path -from [get_ports {sw[*]}] +set_input_delay 0 [get_ports {sw[*]}] + +# PMOD0 +#set_property -dict {LOC AY14 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports {pmod0[0]}] +#set_property -dict {LOC AY15 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports {pmod0[1]}] +#set_property -dict {LOC AW15 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports {pmod0[2]}] +#set_property -dict {LOC AV15 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports {pmod0[3]}] +#set_property -dict {LOC AV16 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports {pmod0[4]}] +#set_property -dict {LOC AU16 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports {pmod0[5]}] +#set_property -dict {LOC AT15 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports {pmod0[6]}] +#set_property -dict {LOC AT16 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports {pmod0[7]}] + +#set_false_path -to [get_ports {pmod0[*]}] +#set_output_delay 0 [get_ports {pmod0[*]}] + +# PMOD1 +#set_property -dict {LOC N28 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {pmod1[0]}] +#set_property -dict {LOC M30 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {pmod1[1]}] +#set_property -dict {LOC N30 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {pmod1[2]}] +#set_property -dict {LOC P30 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {pmod1[3]}] +#set_property -dict {LOC P29 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {pmod1[4]}] +#set_property -dict {LOC L31 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {pmod1[5]}] +#set_property -dict {LOC M31 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {pmod1[6]}] +#set_property -dict {LOC R29 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {pmod1[7]}] + +#set_false_path -to [get_ports {pmod1[*]}] +#set_output_delay 0 [get_ports {pmod1[*]}] + +# UART +#set_property -dict {LOC BB21 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports uart_txd] +#set_property -dict {LOC AW25 IOSTANDARD LVCMOS18} [get_ports uart_rxd] +#set_property -dict {LOC BB22 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports uart_rts] +#set_property -dict {LOC AY25 IOSTANDARD LVCMOS18} [get_ports uart_cts] + +#set_false_path -to [get_ports {uart_txd uart_rts}] +#set_output_delay 0 [get_ports {uart_txd uart_rts}] +#set_false_path -from [get_ports {uart_rxd uart_cts}] +#set_input_delay 0 [get_ports {uart_rxd uart_cts}] + +# Gigabit Ethernet SGMII PHY +#set_property -dict {LOC AU24 IOSTANDARD LVDS} [get_ports phy_sgmii_rx_p] +#set_property -dict {LOC AV24 IOSTANDARD LVDS} [get_ports phy_sgmii_rx_n] +#set_property -dict {LOC AU21 IOSTANDARD LVDS} [get_ports phy_sgmii_tx_p] +#set_property -dict {LOC AV21 IOSTANDARD LVDS} [get_ports phy_sgmii_tx_n] +#set_property -dict {LOC AT22 IOSTANDARD LVDS} [get_ports phy_sgmii_clk_p] +#set_property -dict {LOC AU22 IOSTANDARD LVDS} [get_ports phy_sgmii_clk_n] +#set_property -dict {LOC BA21 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports phy_reset_n] +#set_property -dict {LOC AR24 IOSTANDARD LVCMOS18} [get_ports phy_int_n] +#set_property -dict {LOC AR23 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports phy_mdio] +#set_property -dict {LOC AV23 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports phy_mdc] + +# 625 MHz ref clock from SGMII PHY +#create_clock -period 1.600 -name phy_sgmii_clk [get_ports phy_sgmii_clk_p] + +#set_false_path -to [get_ports {phy_reset_n phy_mdio phy_mdc}] +#set_output_delay 0 [get_ports {phy_reset_n phy_mdio phy_mdc}] +#set_false_path -from [get_ports {phy_int_n phy_mdio}] +#set_input_delay 0 [get_ports {phy_int_n phy_mdio}] + +# QSFP28 Interfaces +#set_property -dict {LOC Y2 } [get_ports qsfp1_rx1_p] ;# MGTYRXP0_231 GTYE4_CHANNEL_X1Y48 / GTYE4_COMMON_X1Y12 +#set_property -dict {LOC Y1 } [get_ports qsfp1_rx1_n] ;# MGTYRXN0_231 GTYE4_CHANNEL_X1Y48 / GTYE4_COMMON_X1Y12 +#set_property -dict {LOC V7 } [get_ports qsfp1_tx1_p] ;# MGTYTXP0_231 GTYE4_CHANNEL_X1Y48 / GTYE4_COMMON_X1Y12 +#set_property -dict {LOC V6 } [get_ports qsfp1_tx1_n] ;# MGTYTXN0_231 GTYE4_CHANNEL_X1Y48 / GTYE4_COMMON_X1Y12 +#set_property -dict {LOC W4 } [get_ports qsfp1_rx2_p] ;# MGTYRXP1_231 GTYE4_CHANNEL_X1Y49 / GTYE4_COMMON_X1Y12 +#set_property -dict {LOC W3 } [get_ports qsfp1_rx2_n] ;# MGTYRXN1_231 GTYE4_CHANNEL_X1Y49 / GTYE4_COMMON_X1Y12 +#set_property -dict {LOC T7 } [get_ports qsfp1_tx2_p] ;# MGTYTXP1_231 GTYE4_CHANNEL_X1Y49 / GTYE4_COMMON_X1Y12 +#set_property -dict {LOC T6 } [get_ports qsfp1_tx2_n] ;# MGTYTXN1_231 GTYE4_CHANNEL_X1Y49 / GTYE4_COMMON_X1Y12 +#set_property -dict {LOC V2 } [get_ports qsfp1_rx3_p] ;# MGTYRXP2_231 GTYE4_CHANNEL_X1Y50 / GTYE4_COMMON_X1Y12 +#set_property -dict {LOC V1 } [get_ports qsfp1_rx3_n] ;# MGTYRXN2_231 GTYE4_CHANNEL_X1Y50 / GTYE4_COMMON_X1Y12 +#set_property -dict {LOC P7 } [get_ports qsfp1_tx3_p] ;# MGTYTXP2_231 GTYE4_CHANNEL_X1Y50 / GTYE4_COMMON_X1Y12 +#set_property -dict {LOC P6 } [get_ports qsfp1_tx3_n] ;# MGTYTXN2_231 GTYE4_CHANNEL_X1Y50 / GTYE4_COMMON_X1Y12 +#set_property -dict {LOC U4 } [get_ports qsfp1_rx4_p] ;# MGTYRXP3_231 GTYE4_CHANNEL_X1Y51 / GTYE4_COMMON_X1Y12 +#set_property -dict {LOC U3 } [get_ports qsfp1_rx4_n] ;# MGTYRXN3_231 GTYE4_CHANNEL_X1Y51 / GTYE4_COMMON_X1Y12 +#set_property -dict {LOC M7 } [get_ports qsfp1_tx4_p] ;# MGTYTXP3_231 GTYE4_CHANNEL_X1Y51 / GTYE4_COMMON_X1Y12 +#set_property -dict {LOC M6 } [get_ports qsfp1_tx4_n] ;# MGTYTXN3_231 GTYE4_CHANNEL_X1Y51 / GTYE4_COMMON_X1Y12 +#set_property -dict {LOC W9 } [get_ports qsfp1_mgt_refclk_0_p] ;# MGTREFCLK0P_231 from U38.4 +#set_property -dict {LOC W8 } [get_ports qsfp1_mgt_refclk_0_n] ;# MGTREFCLK0N_231 from U38.5 +#set_property -dict {LOC U9 } [get_ports qsfp1_mgt_refclk_1_p] ;# MGTREFCLK1P_231 from U57.28 +#set_property -dict {LOC U8 } [get_ports qsfp1_mgt_refclk_1_n] ;# MGTREFCLK1N_231 from U57.29 +#set_property -dict {LOC AM23 IOSTANDARD LVDS} [get_ports qsfp1_recclk_p] ;# to U57.16 +#set_property -dict {LOC AM22 IOSTANDARD LVDS} [get_ports qsfp1_recclk_n] ;# to U57.17 +#set_property -dict {LOC AM21 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports qsfp1_modsell] +#set_property -dict {LOC BA22 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports qsfp1_resetl] +#set_property -dict {LOC AL21 IOSTANDARD LVCMOS18 PULLUP true} [get_ports qsfp1_modprsl] +#set_property -dict {LOC AP21 IOSTANDARD LVCMOS18 PULLUP true} [get_ports qsfp1_intl] +#set_property -dict {LOC AN21 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports qsfp1_lpmode] + +# 156.25 MHz MGT reference clock +#create_clock -period 6.400 -name qsfp1_mgt_refclk_0 [get_ports qsfp1_mgt_refclk_0_p] + +#set_false_path -to [get_ports {qsfp1_modsell qsfp1_resetl qsfp1_lpmode}] +#set_output_delay 0 [get_ports {qsfp1_modsell qsfp1_resetl qsfp1_lpmode}] +#set_false_path -from [get_ports {qsfp1_modprsl qsfp1_intl}] +#set_input_delay 0 [get_ports {qsfp1_modprsl qsfp1_intl}] + +#set_property -dict {LOC T2 } [get_ports qsfp2_rx1_p] ;# MGTYRXP0_232 GTYE4_CHANNEL_X1Y52 / GTYE4_COMMON_X1Y13 +#set_property -dict {LOC T1 } [get_ports qsfp2_rx1_n] ;# MGTYRXN0_232 GTYE4_CHANNEL_X1Y52 / GTYE4_COMMON_X1Y13 +#set_property -dict {LOC L5 } [get_ports qsfp2_tx1_p] ;# MGTYTXP0_232 GTYE4_CHANNEL_X1Y52 / GTYE4_COMMON_X1Y13 +#set_property -dict {LOC L4 } [get_ports qsfp2_tx1_n] ;# MGTYTXN0_232 GTYE4_CHANNEL_X1Y52 / GTYE4_COMMON_X1Y13 +#set_property -dict {LOC R4 } [get_ports qsfp2_rx2_p] ;# MGTYRXP1_232 GTYE4_CHANNEL_X1Y53 / GTYE4_COMMON_X1Y13 +#set_property -dict {LOC R3 } [get_ports qsfp2_rx2_n] ;# MGTYRXN1_232 GTYE4_CHANNEL_X1Y53 / GTYE4_COMMON_X1Y13 +#set_property -dict {LOC K7 } [get_ports qsfp2_tx2_p] ;# MGTYTXP1_232 GTYE4_CHANNEL_X1Y53 / GTYE4_COMMON_X1Y13 +#set_property -dict {LOC K6 } [get_ports qsfp2_tx2_n] ;# MGTYTXN1_232 GTYE4_CHANNEL_X1Y53 / GTYE4_COMMON_X1Y13 +#set_property -dict {LOC P2 } [get_ports qsfp2_rx3_p] ;# MGTYRXP2_232 GTYE4_CHANNEL_X1Y54 / GTYE4_COMMON_X1Y13 +#set_property -dict {LOC P1 } [get_ports qsfp2_rx3_n] ;# MGTYRXN2_232 GTYE4_CHANNEL_X1Y54 / GTYE4_COMMON_X1Y13 +#set_property -dict {LOC J5 } [get_ports qsfp2_tx3_p] ;# MGTYTXP2_232 GTYE4_CHANNEL_X1Y54 / GTYE4_COMMON_X1Y13 +#set_property -dict {LOC J4 } [get_ports qsfp2_tx3_n] ;# MGTYTXN2_232 GTYE4_CHANNEL_X1Y54 / GTYE4_COMMON_X1Y13 +#set_property -dict {LOC M2 } [get_ports qsfp2_rx4_p] ;# MGTYRXP3_232 GTYE4_CHANNEL_X1Y55 / GTYE4_COMMON_X1Y13 +#set_property -dict {LOC M1 } [get_ports qsfp2_rx4_n] ;# MGTYRXN3_232 GTYE4_CHANNEL_X1Y55 / GTYE4_COMMON_X1Y13 +#set_property -dict {LOC H7 } [get_ports qsfp2_tx4_p] ;# MGTYTXP3_232 GTYE4_CHANNEL_X1Y55 / GTYE4_COMMON_X1Y13 +#set_property -dict {LOC H6 } [get_ports qsfp2_tx4_n] ;# MGTYTXN3_232 GTYE4_CHANNEL_X1Y55 / GTYE4_COMMON_X1Y13 +#set_property -dict {LOC R9 } [get_ports qsfp2_mgt_refclk_0_p] ;# MGTREFCLK0P_232 from U104.13 +#set_property -dict {LOC R8 } [get_ports qsfp2_mgt_refclk_0_n] ;# MGTREFCLK0N_232 from U104.14 +#set_property -dict {LOC N9 } [get_ports qsfp2_mgt_refclk_1_p] ;# MGTREFCLK1P_232 from U57.35 +#set_property -dict {LOC N8 } [get_ports qsfp2_mgt_refclk_1_n] ;# MGTREFCLK1N_232 from U57.34 +#set_property -dict {LOC AP23 IOSTANDARD LVDS} [get_ports qsfp2_recclk_p] ;# to U57.12 +#set_property -dict {LOC AP22 IOSTANDARD LVDS} [get_ports qsfp2_recclk_n] ;# to U57.13 +#set_property -dict {LOC AN23 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports qsfp2_modsell] +#set_property -dict {LOC AY22 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports qsfp2_resetl] +#set_property -dict {LOC AN24 IOSTANDARD LVCMOS18 PULLUP true} [get_ports qsfp2_modprsl] +#set_property -dict {LOC AT21 IOSTANDARD LVCMOS18 PULLUP true} [get_ports qsfp2_intl] +#set_property -dict {LOC AT24 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports qsfp2_lpmode] + +# 156.25 MHz MGT reference clock +#create_clock -period 6.400 -name qsfp2_mgt_refclk_0 [get_ports qsfp2_mgt_refclk_0_p] + +#set_false_path -to [get_ports {qsfp2_modsell qsfp2_resetl qsfp2_lpmode}] +#set_output_delay 0 [get_ports {qsfp2_modsell qsfp2_resetl qsfp2_lpmode}] +#set_false_path -from [get_ports {qsfp2_modprsl qsfp2_intl}] +#set_input_delay 0 [get_ports {qsfp2_modprsl qsfp2_intl}] + +# I2C interface +#set_property -dict {LOC AM24 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports i2c_scl] +#set_property -dict {LOC AL24 IOSTANDARD LVCMOS18 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 AA4 } [get_ports {pcie_rx_p[0]}] ;# MGTYRXP3_227 GTYE4_CHANNEL_X1Y35 / GTYE4_COMMON_X1Y8 +set_property -dict {LOC AA3 } [get_ports {pcie_rx_n[0]}] ;# MGTYRXN3_227 GTYE4_CHANNEL_X1Y35 / GTYE4_COMMON_X1Y8 +set_property -dict {LOC Y7 } [get_ports {pcie_tx_p[0]}] ;# MGTYTXP3_227 GTYE4_CHANNEL_X1Y35 / GTYE4_COMMON_X1Y8 +set_property -dict {LOC Y6 } [get_ports {pcie_tx_n[0]}] ;# MGTYTXN3_227 GTYE4_CHANNEL_X1Y35 / GTYE4_COMMON_X1Y8 +set_property -dict {LOC AB2 } [get_ports {pcie_rx_p[1]}] ;# MGTYRXP2_227 GTYE4_CHANNEL_X1Y34 / GTYE4_COMMON_X1Y8 +set_property -dict {LOC AB1 } [get_ports {pcie_rx_n[1]}] ;# MGTYRXN2_227 GTYE4_CHANNEL_X1Y34 / GTYE4_COMMON_X1Y8 +set_property -dict {LOC AB7 } [get_ports {pcie_tx_p[1]}] ;# MGTYTXP2_227 GTYE4_CHANNEL_X1Y34 / GTYE4_COMMON_X1Y8 +set_property -dict {LOC AB6 } [get_ports {pcie_tx_n[1]}] ;# MGTYTXN2_227 GTYE4_CHANNEL_X1Y34 / GTYE4_COMMON_X1Y8 +set_property -dict {LOC AC4 } [get_ports {pcie_rx_p[2]}] ;# MGTYRXP1_227 GTYE4_CHANNEL_X1Y33 / GTYE4_COMMON_X1Y8 +set_property -dict {LOC AC3 } [get_ports {pcie_rx_n[2]}] ;# MGTYRXN1_227 GTYE4_CHANNEL_X1Y33 / GTYE4_COMMON_X1Y8 +set_property -dict {LOC AD7 } [get_ports {pcie_tx_p[2]}] ;# MGTYTXP1_227 GTYE4_CHANNEL_X1Y33 / GTYE4_COMMON_X1Y8 +set_property -dict {LOC AD6 } [get_ports {pcie_tx_n[2]}] ;# MGTYTXN1_227 GTYE4_CHANNEL_X1Y33 / GTYE4_COMMON_X1Y8 +set_property -dict {LOC AD2 } [get_ports {pcie_rx_p[3]}] ;# MGTYRXP0_227 GTYE4_CHANNEL_X1Y32 / GTYE4_COMMON_X1Y8 +set_property -dict {LOC AD1 } [get_ports {pcie_rx_n[3]}] ;# MGTYRXN0_227 GTYE4_CHANNEL_X1Y32 / GTYE4_COMMON_X1Y8 +set_property -dict {LOC AF7 } [get_ports {pcie_tx_p[3]}] ;# MGTYTXP0_227 GTYE4_CHANNEL_X1Y32 / GTYE4_COMMON_X1Y8 +set_property -dict {LOC AF6 } [get_ports {pcie_tx_n[3]}] ;# MGTYTXN0_227 GTYE4_CHANNEL_X1Y32 / GTYE4_COMMON_X1Y8 +set_property -dict {LOC AE4 } [get_ports {pcie_rx_p[4]}] ;# MGTYRXP3_226 GTYE4_CHANNEL_X1Y31 / GTYE4_COMMON_X1Y7 +set_property -dict {LOC AE3 } [get_ports {pcie_rx_n[4]}] ;# MGTYRXN3_226 GTYE4_CHANNEL_X1Y31 / GTYE4_COMMON_X1Y7 +set_property -dict {LOC AH7 } [get_ports {pcie_tx_p[4]}] ;# MGTYTXP3_226 GTYE4_CHANNEL_X1Y31 / GTYE4_COMMON_X1Y7 +set_property -dict {LOC AH6 } [get_ports {pcie_tx_n[4]}] ;# MGTYTXN3_226 GTYE4_CHANNEL_X1Y31 / GTYE4_COMMON_X1Y7 +set_property -dict {LOC AF2 } [get_ports {pcie_rx_p[5]}] ;# MGTYRXP2_226 GTYE4_CHANNEL_X1Y30 / GTYE4_COMMON_X1Y7 +set_property -dict {LOC AF1 } [get_ports {pcie_rx_n[5]}] ;# MGTYRXN2_226 GTYE4_CHANNEL_X1Y30 / GTYE4_COMMON_X1Y7 +set_property -dict {LOC AK7 } [get_ports {pcie_tx_p[5]}] ;# MGTYTXP2_226 GTYE4_CHANNEL_X1Y30 / GTYE4_COMMON_X1Y7 +set_property -dict {LOC AK6 } [get_ports {pcie_tx_n[5]}] ;# MGTYTXN2_226 GTYE4_CHANNEL_X1Y30 / GTYE4_COMMON_X1Y7 +set_property -dict {LOC AG4 } [get_ports {pcie_rx_p[6]}] ;# MGTYRXP1_226 GTYE4_CHANNEL_X1Y29 / GTYE4_COMMON_X1Y7 +set_property -dict {LOC AG3 } [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 AH2 } [get_ports {pcie_rx_p[7]}] ;# MGTYRXP0_226 GTYE4_CHANNEL_X1Y28 / GTYE4_COMMON_X1Y7 +set_property -dict {LOC AH1 } [get_ports {pcie_rx_n[7]}] ;# MGTYRXN0_226 GTYE4_CHANNEL_X1Y28 / GTYE4_COMMON_X1Y7 +set_property -dict {LOC AN5 } [get_ports {pcie_tx_p[7]}] ;# MGTYTXP0_226 GTYE4_CHANNEL_X1Y28 / GTYE4_COMMON_X1Y7 +set_property -dict {LOC AN4 } [get_ports {pcie_tx_n[7]}] ;# MGTYTXN0_226 GTYE4_CHANNEL_X1Y28 / GTYE4_COMMON_X1Y7 +set_property -dict {LOC AJ4 } [get_ports {pcie_rx_p[8]}] ;# MGTYRXP3_225 GTYE4_CHANNEL_X1Y27 / GTYE4_COMMON_X1Y6 +set_property -dict {LOC AJ3 } [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 AK2 } [get_ports {pcie_rx_p[9]}] ;# MGTYRXP2_225 GTYE4_CHANNEL_X1Y26 / GTYE4_COMMON_X1Y6 +set_property -dict {LOC AK1 } [get_ports {pcie_rx_n[9]}] ;# MGTYRXN2_225 GTYE4_CHANNEL_X1Y26 / GTYE4_COMMON_X1Y6 +set_property -dict {LOC AR5 } [get_ports {pcie_tx_p[9]}] ;# MGTYTXP2_225 GTYE4_CHANNEL_X1Y26 / GTYE4_COMMON_X1Y6 +set_property -dict {LOC AR4 } [get_ports {pcie_tx_n[9]}] ;# MGTYTXN2_225 GTYE4_CHANNEL_X1Y26 / GTYE4_COMMON_X1Y6 +set_property -dict {LOC AM2 } [get_ports {pcie_rx_p[10]}] ;# MGTYRXP1_225 GTYE4_CHANNEL_X1Y25 / GTYE4_COMMON_X1Y6 +set_property -dict {LOC AM1 } [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 AP2 } [get_ports {pcie_rx_p[11]}] ;# MGTYRXP0_225 GTYE4_CHANNEL_X1Y24 / GTYE4_COMMON_X1Y6 +set_property -dict {LOC AP1 } [get_ports {pcie_rx_n[11]}] ;# MGTYRXN0_225 GTYE4_CHANNEL_X1Y24 / GTYE4_COMMON_X1Y6 +set_property -dict {LOC AU5 } [get_ports {pcie_tx_p[11]}] ;# MGTYTXP0_225 GTYE4_CHANNEL_X1Y24 / GTYE4_COMMON_X1Y6 +set_property -dict {LOC AU4 } [get_ports {pcie_tx_n[11]}] ;# MGTYTXN0_225 GTYE4_CHANNEL_X1Y24 / GTYE4_COMMON_X1Y6 +set_property -dict {LOC AT2 } [get_ports {pcie_rx_p[12]}] ;# MGTYRXP3_224 GTYE4_CHANNEL_X1Y23 / GTYE4_COMMON_X1Y5 +set_property -dict {LOC AT1 } [get_ports {pcie_rx_n[12]}] ;# MGTYRXN3_224 GTYE4_CHANNEL_X1Y23 / GTYE4_COMMON_X1Y5 +set_property -dict {LOC AW5 } [get_ports {pcie_tx_p[12]}] ;# MGTYTXP3_224 GTYE4_CHANNEL_X1Y23 / GTYE4_COMMON_X1Y5 +set_property -dict {LOC AW4 } [get_ports {pcie_tx_n[12]}] ;# MGTYTXN3_224 GTYE4_CHANNEL_X1Y23 / GTYE4_COMMON_X1Y5 +set_property -dict {LOC AV2 } [get_ports {pcie_rx_p[13]}] ;# MGTYRXP2_224 GTYE4_CHANNEL_X1Y22 / GTYE4_COMMON_X1Y5 +set_property -dict {LOC AV1 } [get_ports {pcie_rx_n[13]}] ;# MGTYRXN2_224 GTYE4_CHANNEL_X1Y22 / GTYE4_COMMON_X1Y5 +set_property -dict {LOC BA5 } [get_ports {pcie_tx_p[13]}] ;# MGTYTXP2_224 GTYE4_CHANNEL_X1Y22 / GTYE4_COMMON_X1Y5 +set_property -dict {LOC BA4 } [get_ports {pcie_tx_n[13]}] ;# MGTYTXN2_224 GTYE4_CHANNEL_X1Y22 / GTYE4_COMMON_X1Y5 +set_property -dict {LOC AY2 } [get_ports {pcie_rx_p[14]}] ;# MGTYRXP1_224 GTYE4_CHANNEL_X1Y21 / GTYE4_COMMON_X1Y5 +set_property -dict {LOC AY1 } [get_ports {pcie_rx_n[14]}] ;# MGTYRXN1_224 GTYE4_CHANNEL_X1Y21 / GTYE4_COMMON_X1Y5 +set_property -dict {LOC BC5 } [get_ports {pcie_tx_p[14]}] ;# MGTYTXP1_224 GTYE4_CHANNEL_X1Y21 / GTYE4_COMMON_X1Y5 +set_property -dict {LOC BC4 } [get_ports {pcie_tx_n[14]}] ;# MGTYTXN1_224 GTYE4_CHANNEL_X1Y21 / GTYE4_COMMON_X1Y5 +set_property -dict {LOC BB2 } [get_ports {pcie_rx_p[15]}] ;# MGTYRXP0_224 GTYE4_CHANNEL_X1Y20 / GTYE4_COMMON_X1Y5 +set_property -dict {LOC BB1 } [get_ports {pcie_rx_n[15]}] ;# MGTYRXN0_224 GTYE4_CHANNEL_X1Y20 / GTYE4_COMMON_X1Y5 +set_property -dict {LOC BE5 } [get_ports {pcie_tx_p[15]}] ;# MGTYTXP0_224 GTYE4_CHANNEL_X1Y20 / GTYE4_COMMON_X1Y5 +set_property -dict {LOC BE4 } [get_ports {pcie_tx_n[15]}] ;# MGTYTXN0_224 GTYE4_CHANNEL_X1Y20 / GTYE4_COMMON_X1Y5 +#set_property -dict {LOC AC9 } [get_ports pcie_refclk_1_p] ;# MGTREFCLK0P_227 +#set_property -dict {LOC AC8 } [get_ports pcie_refclk_1_n] ;# MGTREFCLK0N_227 +set_property -dict {LOC AL9 } [get_ports pcie_refclk_2_p] ;# MGTREFCLK0P_225 +set_property -dict {LOC AL8 } [get_ports pcie_refclk_2_n] ;# MGTREFCLK0N_225 +set_property -dict {LOC AM17 IOSTANDARD LVCMOS18 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_1_p] +#create_clock -period 10 -name pcie_mgt_refclk_2 [get_ports pcie_refclk_2_p] + +set_false_path -from [get_ports {pcie_reset_n}] +set_input_delay 0 [get_ports {pcie_reset_n}] + +# QSPI flash +#set_property -dict {LOC AM19 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {qspi_1_dq[0]}] +#set_property -dict {LOC AM18 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {qspi_1_dq[1]}] +#set_property -dict {LOC AN20 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {qspi_1_dq[2]}] +#set_property -dict {LOC AP20 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {qspi_1_dq[3]}] +#set_property -dict {LOC BF16 IOSTANDARD LVCMOS18 DRIVE 12} [get_ports {qspi_1_cs}] + +#set_false_path -to [get_ports {qspi_1_dq[*] qspi_1_cs}] +#set_output_delay 0 [get_ports {qspi_1_dq[*] qspi_1_cs}] +#set_false_path -from [get_ports {qspi_1_dq}] +#set_input_delay 0 [get_ports {qspi_1_dq}] diff --git a/fpga/lib/pcie/example/VCU118/fpga/fpga/Makefile b/fpga/lib/pcie/example/VCU118/fpga/fpga/Makefile new file mode 100644 index 000000000..66c56cfe8 --- /dev/null +++ b/fpga/lib/pcie/example/VCU118/fpga/fpga/Makefile @@ -0,0 +1,94 @@ + +# FPGA settings +FPGA_PART = xcvu9p-flga2104-2L-e +FPGA_TOP = fpga +FPGA_ARCH = virtexuplus + +# Files for synthesis +SYN_FILES = rtl/fpga.v +SYN_FILES += rtl/fpga_core.v +SYN_FILES += rtl/debounce_switch.v +SYN_FILES += rtl/sync_reset.v +SYN_FILES += rtl/sync_signal.v +SYN_FILES += rtl/common/example_core_pcie_us.v +SYN_FILES += rtl/common/example_core_pcie.v +SYN_FILES += rtl/common/example_core.v +SYN_FILES += rtl/common/axi_ram.v +SYN_FILES += lib/pcie/rtl/pcie_us_if.v +SYN_FILES += lib/pcie/rtl/pcie_us_if_rc.v +SYN_FILES += lib/pcie/rtl/pcie_us_if_rq.v +SYN_FILES += lib/pcie/rtl/pcie_us_if_cq.v +SYN_FILES += lib/pcie/rtl/pcie_us_if_cc.v +SYN_FILES += lib/pcie/rtl/pcie_us_cfg.v +SYN_FILES += lib/pcie/rtl/pcie_us_msi.v +SYN_FILES += lib/pcie/rtl/pcie_axil_master.v +SYN_FILES += lib/pcie/rtl/pcie_axi_master.v +SYN_FILES += lib/pcie/rtl/pcie_axi_master_rd.v +SYN_FILES += lib/pcie/rtl/pcie_axi_master_wr.v +SYN_FILES += lib/pcie/rtl/pcie_tlp_demux_bar.v +SYN_FILES += lib/pcie/rtl/pcie_tlp_demux.v +SYN_FILES += lib/pcie/rtl/pcie_tlp_mux.v +SYN_FILES += lib/pcie/rtl/dma_if_pcie.v +SYN_FILES += lib/pcie/rtl/dma_if_pcie_rd.v +SYN_FILES += lib/pcie/rtl/dma_if_pcie_wr.v +SYN_FILES += lib/pcie/rtl/dma_psdpram.v +SYN_FILES += lib/pcie/rtl/arbiter.v +SYN_FILES += lib/pcie/rtl/priority_encoder.v +SYN_FILES += lib/pcie/rtl/pulse_merge.v + +# XDC files +XDC_FILES = fpga.xdc + +# IP +IP_TCL_FILES = ip/pcie4_uscale_plus_0.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 256 -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 {mt25qu01g-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 + diff --git a/fpga/lib/pcie/example/VCU118/fpga/ip/pcie4_uscale_plus_0.tcl b/fpga/lib/pcie/example/VCU118/fpga/ip/pcie4_uscale_plus_0.tcl new file mode 100644 index 000000000..86e78fdf1 --- /dev/null +++ b/fpga/lib/pcie/example/VCU118/fpga/ip/pcie4_uscale_plus_0.tcl @@ -0,0 +1,28 @@ + +create_ip -name pcie4_uscale_plus -vendor xilinx.com -library ip -module_name pcie4_uscale_plus_0 + +set_property -dict [list \ + CONFIG.PL_LINK_CAP_MAX_LINK_SPEED {8.0_GT/s} \ + CONFIG.PL_LINK_CAP_MAX_LINK_WIDTH {X16} \ + CONFIG.AXISTEN_IF_EXT_512_RQ_STRADDLE {false} \ + CONFIG.axisten_if_enable_client_tag {true} \ + CONFIG.axisten_if_width {512_bit} \ + CONFIG.axisten_freq {250} \ + CONFIG.PF0_CLASS_CODE {058000} \ + CONFIG.PF0_DEVICE_ID {0001} \ + CONFIG.PF0_MSI_CAP_MULTIMSGCAP {32_vectors} \ + CONFIG.PF0_SUBSYSTEM_ID {9076} \ + CONFIG.PF0_SUBSYSTEM_VENDOR_ID {10ee} \ + CONFIG.pf0_bar0_64bit {true} \ + CONFIG.pf0_bar0_prefetchable {true} \ + CONFIG.pf0_bar0_scale {Megabytes} \ + CONFIG.pf0_bar0_size {16} \ + CONFIG.pf0_bar2_64bit {true} \ + CONFIG.pf0_bar2_prefetchable {true} \ + CONFIG.pf0_bar2_enabled {true} \ + CONFIG.pf0_bar2_type {Memory} \ + CONFIG.pf0_bar2_scale {Megabytes} \ + CONFIG.pf0_bar2_size {16} \ + CONFIG.vendor_id {1234} \ + CONFIG.en_msi_per_vec_masking {true} \ +] [get_ips pcie4_uscale_plus_0] diff --git a/fpga/lib/pcie/example/VCU118/fpga/lib/pcie b/fpga/lib/pcie/example/VCU118/fpga/lib/pcie new file mode 120000 index 000000000..11a54ed36 --- /dev/null +++ b/fpga/lib/pcie/example/VCU118/fpga/lib/pcie @@ -0,0 +1 @@ +../../../../ \ No newline at end of file diff --git a/fpga/lib/pcie/example/VCU118/fpga/rtl/common b/fpga/lib/pcie/example/VCU118/fpga/rtl/common new file mode 120000 index 000000000..e60fada70 --- /dev/null +++ b/fpga/lib/pcie/example/VCU118/fpga/rtl/common @@ -0,0 +1 @@ +../../../common/rtl/ \ No newline at end of file diff --git a/fpga/lib/pcie/example/VCU118/fpga/rtl/debounce_switch.v b/fpga/lib/pcie/example/VCU118/fpga/rtl/debounce_switch.v new file mode 100644 index 000000000..8e93a50c4 --- /dev/null +++ b/fpga/lib/pcie/example/VCU118/fpga/rtl/debounce_switch.v @@ -0,0 +1,93 @@ +/* + +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 diff --git a/fpga/lib/pcie/example/VCU118/fpga/rtl/fpga.v b/fpga/lib/pcie/example/VCU118/fpga/rtl/fpga.v new file mode 100644 index 000000000..fe94c565d --- /dev/null +++ b/fpga/lib/pcie/example/VCU118/fpga/rtl/fpga.v @@ -0,0 +1,488 @@ +/* + +Copyright (c) 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 1ns / 1ps +`default_nettype none + +/* + * FPGA top-level module + */ +module fpga ( + /* + * GPIO + */ + input wire btnu, + input wire btnl, + input wire btnd, + input wire btnr, + input wire btnc, + input wire [3:0] sw, + output wire [7:0] led, + + /* + * PCI express + */ + input wire [15:0] pcie_rx_p, + input wire [15:0] pcie_rx_n, + output wire [15:0] pcie_tx_p, + output wire [15:0] pcie_tx_n, + input wire pcie_refclk_2_p, + input wire pcie_refclk_2_n, + input wire pcie_reset_n +); + +parameter AXIS_PCIE_DATA_WIDTH = 512; +parameter AXIS_PCIE_KEEP_WIDTH = (AXIS_PCIE_DATA_WIDTH/32); +parameter AXIS_PCIE_RC_USER_WIDTH = AXIS_PCIE_DATA_WIDTH < 512 ? 75 : 161; +parameter AXIS_PCIE_RQ_USER_WIDTH = AXIS_PCIE_DATA_WIDTH < 512 ? 60 : 137; +parameter AXIS_PCIE_CQ_USER_WIDTH = AXIS_PCIE_DATA_WIDTH < 512 ? 85 : 183; +parameter AXIS_PCIE_CC_USER_WIDTH = AXIS_PCIE_DATA_WIDTH < 512 ? 33 : 81; + +parameter RQ_SEQ_NUM_WIDTH = AXIS_PCIE_RQ_USER_WIDTH == 60 ? 4 : 6; +parameter RQ_SEQ_NUM_ENABLE = 1; + +parameter PCIE_TAG_COUNT = 64; +parameter BAR0_APERTURE = 24; +parameter BAR2_APERTURE = 24; + +// Clock and reset +wire pcie_user_clk; +wire pcie_user_reset; + +// GPIO +wire btnu_int; +wire btnl_int; +wire btnd_int; +wire btnr_int; +wire btnc_int; +wire [3:0] sw_int; + +debounce_switch #( + .WIDTH(9), + .N(4), + .RATE(250000) +) +debounce_switch_inst ( + .clk(pcie_user_clk), + .rst(pcie_user_reset), + .in({btnu, + btnl, + btnd, + btnr, + btnc, + sw}), + .out({btnu_int, + btnl_int, + btnd_int, + btnr_int, + btnc_int, + sw_int}) +); + +// PCIe +wire pcie_sys_clk; +wire pcie_sys_clk_gt; + +IBUFDS_GTE4 #( + .REFCLK_HROW_CK_SEL(2'b00) +) +ibufds_gte4_pcie_mgt_refclk_inst ( + .I (pcie_refclk_2_p), + .IB (pcie_refclk_2_n), + .CEB (1'b0), + .O (pcie_sys_clk_gt), + .ODIV2 (pcie_sys_clk) +); + +wire [AXIS_PCIE_DATA_WIDTH-1:0] axis_rq_tdata; +wire [AXIS_PCIE_KEEP_WIDTH-1:0] axis_rq_tkeep; +wire axis_rq_tlast; +wire axis_rq_tready; +wire [AXIS_PCIE_RQ_USER_WIDTH-1:0] axis_rq_tuser; +wire axis_rq_tvalid; + +wire [AXIS_PCIE_DATA_WIDTH-1:0] axis_rc_tdata; +wire [AXIS_PCIE_KEEP_WIDTH-1:0] axis_rc_tkeep; +wire axis_rc_tlast; +wire axis_rc_tready; +wire [AXIS_PCIE_RC_USER_WIDTH-1:0] axis_rc_tuser; +wire axis_rc_tvalid; + +wire [AXIS_PCIE_DATA_WIDTH-1:0] axis_cq_tdata; +wire [AXIS_PCIE_KEEP_WIDTH-1:0] axis_cq_tkeep; +wire axis_cq_tlast; +wire axis_cq_tready; +wire [AXIS_PCIE_CQ_USER_WIDTH-1:0] axis_cq_tuser; +wire axis_cq_tvalid; + +wire [AXIS_PCIE_DATA_WIDTH-1:0] axis_cc_tdata; +wire [AXIS_PCIE_KEEP_WIDTH-1:0] axis_cc_tkeep; +wire axis_cc_tlast; +wire axis_cc_tready; +wire [AXIS_PCIE_CC_USER_WIDTH-1:0] axis_cc_tuser; +wire axis_cc_tvalid; + +wire [RQ_SEQ_NUM_WIDTH-1:0] pcie_rq_seq_num0; +wire pcie_rq_seq_num_vld0; +wire [RQ_SEQ_NUM_WIDTH-1:0] pcie_rq_seq_num1; +wire pcie_rq_seq_num_vld1; + +// ila_0 rq_ila ( +// .clk(pcie_user_clk), +// .probe0(axis_rq_tdata), +// .probe1(axis_rq_tkeep), +// .probe2(axis_rq_tlast), +// .probe3(axis_rq_tready), +// .probe4(axis_rq_tuser), +// .probe5(axis_rq_tvalid) +// ); + +// ila_0 rc_ila ( +// .clk(pcie_user_clk), +// .probe0(axis_rc_tdata), +// .probe1(axis_rc_tkeep), +// .probe2(axis_rc_tlast), +// .probe3(axis_rc_tready), +// .probe4(axis_rc_tuser), +// .probe5(axis_rc_tvalid) +// ); + +wire [2:0] cfg_max_payload; +wire [2:0] cfg_max_read_req; + +wire [9:0] cfg_mgmt_addr; +wire [7:0] cfg_mgmt_function_number; +wire cfg_mgmt_write; +wire [31:0] cfg_mgmt_write_data; +wire [3:0] cfg_mgmt_byte_enable; +wire cfg_mgmt_read; +wire [31:0] cfg_mgmt_read_data; +wire cfg_mgmt_read_write_done; + +wire [7:0] cfg_fc_ph; +wire [11:0] cfg_fc_pd; +wire [7:0] cfg_fc_nph; +wire [11:0] cfg_fc_npd; +wire [7:0] cfg_fc_cplh; +wire [11:0] cfg_fc_cpld; +wire [2:0] cfg_fc_sel; + +wire [3:0] cfg_interrupt_msi_enable; +wire [11:0] cfg_interrupt_msi_mmenable; +wire cfg_interrupt_msi_mask_update; +wire [31:0] cfg_interrupt_msi_data; +wire [3:0] cfg_interrupt_msi_select; +wire [31:0] cfg_interrupt_msi_int; +wire [31:0] cfg_interrupt_msi_pending_status; +wire cfg_interrupt_msi_pending_status_data_enable; +wire [3:0] cfg_interrupt_msi_pending_status_function_num; +wire cfg_interrupt_msi_sent; +wire cfg_interrupt_msi_fail; +wire [2:0] cfg_interrupt_msi_attr; +wire cfg_interrupt_msi_tph_present; +wire [1:0] cfg_interrupt_msi_tph_type; +wire [8:0] cfg_interrupt_msi_tph_st_tag; +wire [3:0] cfg_interrupt_msi_function_number; + +wire status_error_cor; +wire status_error_uncor; + +pcie4_uscale_plus_0 +pcie4_uscale_plus_inst ( + .pci_exp_txn(pcie_tx_n), + .pci_exp_txp(pcie_tx_p), + .pci_exp_rxn(pcie_rx_n), + .pci_exp_rxp(pcie_rx_p), + .user_clk(pcie_user_clk), + .user_reset(pcie_user_reset), + .user_lnk_up(), + + .s_axis_rq_tdata(axis_rq_tdata), + .s_axis_rq_tkeep(axis_rq_tkeep), + .s_axis_rq_tlast(axis_rq_tlast), + .s_axis_rq_tready(axis_rq_tready), + .s_axis_rq_tuser(axis_rq_tuser), + .s_axis_rq_tvalid(axis_rq_tvalid), + + .m_axis_rc_tdata(axis_rc_tdata), + .m_axis_rc_tkeep(axis_rc_tkeep), + .m_axis_rc_tlast(axis_rc_tlast), + .m_axis_rc_tready(axis_rc_tready), + .m_axis_rc_tuser(axis_rc_tuser), + .m_axis_rc_tvalid(axis_rc_tvalid), + + .m_axis_cq_tdata(axis_cq_tdata), + .m_axis_cq_tkeep(axis_cq_tkeep), + .m_axis_cq_tlast(axis_cq_tlast), + .m_axis_cq_tready(axis_cq_tready), + .m_axis_cq_tuser(axis_cq_tuser), + .m_axis_cq_tvalid(axis_cq_tvalid), + + .s_axis_cc_tdata(axis_cc_tdata), + .s_axis_cc_tkeep(axis_cc_tkeep), + .s_axis_cc_tlast(axis_cc_tlast), + .s_axis_cc_tready(axis_cc_tready), + .s_axis_cc_tuser(axis_cc_tuser), + .s_axis_cc_tvalid(axis_cc_tvalid), + + .pcie_rq_seq_num0(pcie_rq_seq_num0), + .pcie_rq_seq_num_vld0(pcie_rq_seq_num_vld0), + .pcie_rq_seq_num1(pcie_rq_seq_num1), + .pcie_rq_seq_num_vld1(pcie_rq_seq_num_vld1), + .pcie_rq_tag0(), + .pcie_rq_tag1(), + .pcie_rq_tag_av(), + .pcie_rq_tag_vld0(), + .pcie_rq_tag_vld1(), + + .pcie_tfc_nph_av(), + .pcie_tfc_npd_av(), + + .pcie_cq_np_req(1'b1), + .pcie_cq_np_req_count(), + + .cfg_phy_link_down(), + .cfg_phy_link_status(), + .cfg_negotiated_width(), + .cfg_current_speed(), + .cfg_max_payload(cfg_max_payload), + .cfg_max_read_req(cfg_max_read_req), + .cfg_function_status(), + .cfg_function_power_state(), + .cfg_vf_status(), + .cfg_vf_power_state(), + .cfg_link_power_state(), + + .cfg_mgmt_addr(cfg_mgmt_addr), + .cfg_mgmt_function_number(cfg_mgmt_function_number), + .cfg_mgmt_write(cfg_mgmt_write), + .cfg_mgmt_write_data(cfg_mgmt_write_data), + .cfg_mgmt_byte_enable(cfg_mgmt_byte_enable), + .cfg_mgmt_read(cfg_mgmt_read), + .cfg_mgmt_read_data(cfg_mgmt_read_data), + .cfg_mgmt_read_write_done(cfg_mgmt_read_write_done), + .cfg_mgmt_debug_access(1'b0), + + .cfg_err_cor_out(), + .cfg_err_nonfatal_out(), + .cfg_err_fatal_out(), + .cfg_local_error_valid(), + .cfg_local_error_out(), + .cfg_ltssm_state(), + .cfg_rx_pm_state(), + .cfg_tx_pm_state(), + .cfg_rcb_status(), + .cfg_obff_enable(), + .cfg_pl_status_change(), + .cfg_tph_requester_enable(), + .cfg_tph_st_mode(), + .cfg_vf_tph_requester_enable(), + .cfg_vf_tph_st_mode(), + + .cfg_msg_received(), + .cfg_msg_received_data(), + .cfg_msg_received_type(), + .cfg_msg_transmit(1'b0), + .cfg_msg_transmit_type(3'd0), + .cfg_msg_transmit_data(32'd0), + .cfg_msg_transmit_done(), + + .cfg_fc_ph(cfg_fc_ph), + .cfg_fc_pd(cfg_fc_pd), + .cfg_fc_nph(cfg_fc_nph), + .cfg_fc_npd(cfg_fc_npd), + .cfg_fc_cplh(cfg_fc_cplh), + .cfg_fc_cpld(cfg_fc_cpld), + .cfg_fc_sel(cfg_fc_sel), + + .cfg_dsn(64'd0), + + .cfg_bus_number(), + + .cfg_power_state_change_ack(1'b1), + .cfg_power_state_change_interrupt(), + + .cfg_err_cor_in(status_error_cor), + .cfg_err_uncor_in(status_error_uncor), + .cfg_flr_in_process(), + .cfg_flr_done(4'd0), + .cfg_vf_flr_in_process(), + .cfg_vf_flr_func_num(8'd0), + .cfg_vf_flr_done(8'd0), + + .cfg_link_training_enable(1'b1), + + .cfg_interrupt_int(4'd0), + .cfg_interrupt_pending(4'd0), + .cfg_interrupt_sent(), + .cfg_interrupt_msi_enable(cfg_interrupt_msi_enable), + .cfg_interrupt_msi_mmenable(cfg_interrupt_msi_mmenable), + .cfg_interrupt_msi_mask_update(cfg_interrupt_msi_mask_update), + .cfg_interrupt_msi_data(cfg_interrupt_msi_data), + .cfg_interrupt_msi_select(cfg_interrupt_msi_select), + .cfg_interrupt_msi_int(cfg_interrupt_msi_int), + .cfg_interrupt_msi_pending_status(cfg_interrupt_msi_pending_status), + .cfg_interrupt_msi_pending_status_data_enable(cfg_interrupt_msi_pending_status_data_enable), + .cfg_interrupt_msi_pending_status_function_num(cfg_interrupt_msi_pending_status_function_num), + .cfg_interrupt_msi_sent(cfg_interrupt_msi_sent), + .cfg_interrupt_msi_fail(cfg_interrupt_msi_fail), + .cfg_interrupt_msi_attr(cfg_interrupt_msi_attr), + .cfg_interrupt_msi_tph_present(cfg_interrupt_msi_tph_present), + .cfg_interrupt_msi_tph_type(cfg_interrupt_msi_tph_type), + .cfg_interrupt_msi_tph_st_tag(cfg_interrupt_msi_tph_st_tag), + .cfg_interrupt_msi_function_number(cfg_interrupt_msi_function_number), + + .cfg_pm_aspm_l1_entry_reject(1'b0), + .cfg_pm_aspm_tx_l0s_entry_disable(1'b0), + + .cfg_hot_reset_out(), + + .cfg_config_space_enable(1'b1), + .cfg_req_pm_transition_l23_ready(1'b0), + .cfg_hot_reset_in(1'b0), + + .cfg_ds_port_number(8'd0), + .cfg_ds_bus_number(8'd0), + .cfg_ds_device_number(5'd0), + + .sys_clk(pcie_sys_clk), + .sys_clk_gt(pcie_sys_clk_gt), + .sys_reset(pcie_reset_n), + + .phy_rdy_out() +); + +fpga_core #( + .AXIS_PCIE_DATA_WIDTH(AXIS_PCIE_DATA_WIDTH), + .AXIS_PCIE_KEEP_WIDTH(AXIS_PCIE_KEEP_WIDTH), + .AXIS_PCIE_RC_USER_WIDTH(AXIS_PCIE_RC_USER_WIDTH), + .AXIS_PCIE_RQ_USER_WIDTH(AXIS_PCIE_RQ_USER_WIDTH), + .AXIS_PCIE_CQ_USER_WIDTH(AXIS_PCIE_CQ_USER_WIDTH), + .AXIS_PCIE_CC_USER_WIDTH(AXIS_PCIE_CC_USER_WIDTH), + .RQ_SEQ_NUM_WIDTH(RQ_SEQ_NUM_WIDTH), + .RQ_SEQ_NUM_ENABLE(RQ_SEQ_NUM_ENABLE), + .PCIE_TAG_COUNT(PCIE_TAG_COUNT), + .BAR0_APERTURE(BAR0_APERTURE), + .BAR2_APERTURE(BAR2_APERTURE) +) +core_inst ( + /* + * Clock: 250 MHz + * Synchronous reset + */ + .clk(pcie_user_clk), + .rst(pcie_user_reset), + /* + * GPIO + */ + .btnu(btnu_int), + .btnl(btnl_int), + .btnd(btnd_int), + .btnr(btnr_int), + .btnc(btnc_int), + .sw(sw_int), + .led(led), + /* + * PCIe + */ + .m_axis_rq_tdata(axis_rq_tdata), + .m_axis_rq_tkeep(axis_rq_tkeep), + .m_axis_rq_tlast(axis_rq_tlast), + .m_axis_rq_tready(axis_rq_tready), + .m_axis_rq_tuser(axis_rq_tuser), + .m_axis_rq_tvalid(axis_rq_tvalid), + + .s_axis_rc_tdata(axis_rc_tdata), + .s_axis_rc_tkeep(axis_rc_tkeep), + .s_axis_rc_tlast(axis_rc_tlast), + .s_axis_rc_tready(axis_rc_tready), + .s_axis_rc_tuser(axis_rc_tuser), + .s_axis_rc_tvalid(axis_rc_tvalid), + + .s_axis_cq_tdata(axis_cq_tdata), + .s_axis_cq_tkeep(axis_cq_tkeep), + .s_axis_cq_tlast(axis_cq_tlast), + .s_axis_cq_tready(axis_cq_tready), + .s_axis_cq_tuser(axis_cq_tuser), + .s_axis_cq_tvalid(axis_cq_tvalid), + + .m_axis_cc_tdata(axis_cc_tdata), + .m_axis_cc_tkeep(axis_cc_tkeep), + .m_axis_cc_tlast(axis_cc_tlast), + .m_axis_cc_tready(axis_cc_tready), + .m_axis_cc_tuser(axis_cc_tuser), + .m_axis_cc_tvalid(axis_cc_tvalid), + + .s_axis_rq_seq_num_0(pcie_rq_seq_num0), + .s_axis_rq_seq_num_valid_0(pcie_rq_seq_num_vld0), + .s_axis_rq_seq_num_1(pcie_rq_seq_num1), + .s_axis_rq_seq_num_valid_1(pcie_rq_seq_num_vld1), + + .cfg_max_payload(cfg_max_payload), + .cfg_max_read_req(cfg_max_read_req), + + .cfg_mgmt_addr(cfg_mgmt_addr), + .cfg_mgmt_function_number(cfg_mgmt_function_number), + .cfg_mgmt_write(cfg_mgmt_write), + .cfg_mgmt_write_data(cfg_mgmt_write_data), + .cfg_mgmt_byte_enable(cfg_mgmt_byte_enable), + .cfg_mgmt_read(cfg_mgmt_read), + .cfg_mgmt_read_data(cfg_mgmt_read_data), + .cfg_mgmt_read_write_done(cfg_mgmt_read_write_done), + + .cfg_fc_ph(cfg_fc_ph), + .cfg_fc_pd(cfg_fc_pd), + .cfg_fc_nph(cfg_fc_nph), + .cfg_fc_npd(cfg_fc_npd), + .cfg_fc_cplh(cfg_fc_cplh), + .cfg_fc_cpld(cfg_fc_cpld), + .cfg_fc_sel(cfg_fc_sel), + + .cfg_interrupt_msi_enable(cfg_interrupt_msi_enable), + .cfg_interrupt_msi_mmenable(cfg_interrupt_msi_mmenable), + .cfg_interrupt_msi_mask_update(cfg_interrupt_msi_mask_update), + .cfg_interrupt_msi_data(cfg_interrupt_msi_data), + .cfg_interrupt_msi_select(cfg_interrupt_msi_select), + .cfg_interrupt_msi_int(cfg_interrupt_msi_int), + .cfg_interrupt_msi_pending_status(cfg_interrupt_msi_pending_status), + .cfg_interrupt_msi_pending_status_data_enable(cfg_interrupt_msi_pending_status_data_enable), + .cfg_interrupt_msi_pending_status_function_num(cfg_interrupt_msi_pending_status_function_num), + .cfg_interrupt_msi_sent(cfg_interrupt_msi_sent), + .cfg_interrupt_msi_fail(cfg_interrupt_msi_fail), + .cfg_interrupt_msi_attr(cfg_interrupt_msi_attr), + .cfg_interrupt_msi_tph_present(cfg_interrupt_msi_tph_present), + .cfg_interrupt_msi_tph_type(cfg_interrupt_msi_tph_type), + .cfg_interrupt_msi_tph_st_tag(cfg_interrupt_msi_tph_st_tag), + .cfg_interrupt_msi_function_number(cfg_interrupt_msi_function_number), + + .status_error_cor(status_error_cor), + .status_error_uncor(status_error_uncor) +); + +endmodule + +`resetall diff --git a/fpga/lib/pcie/example/VCU118/fpga/rtl/fpga_core.v b/fpga/lib/pcie/example/VCU118/fpga/rtl/fpga_core.v new file mode 100644 index 000000000..80a6c287b --- /dev/null +++ b/fpga/lib/pcie/example/VCU118/fpga/rtl/fpga_core.v @@ -0,0 +1,276 @@ +/* + +Copyright (c) 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 1ns / 1ps +`default_nettype none + +/* + * FPGA core logic + */ +module fpga_core # +( + parameter AXIS_PCIE_DATA_WIDTH = 512, + parameter AXIS_PCIE_KEEP_WIDTH = (AXIS_PCIE_DATA_WIDTH/32), + parameter AXIS_PCIE_RC_USER_WIDTH = AXIS_PCIE_DATA_WIDTH < 512 ? 75 : 161, + parameter AXIS_PCIE_RQ_USER_WIDTH = AXIS_PCIE_DATA_WIDTH < 512 ? 60 : 137, + parameter AXIS_PCIE_CQ_USER_WIDTH = AXIS_PCIE_DATA_WIDTH < 512 ? 85 : 183, + parameter AXIS_PCIE_CC_USER_WIDTH = AXIS_PCIE_DATA_WIDTH < 512 ? 33 : 81, + parameter RQ_SEQ_NUM_WIDTH = AXIS_PCIE_RQ_USER_WIDTH == 60 ? 4 : 6, + parameter RQ_SEQ_NUM_ENABLE = 1, + parameter PCIE_TAG_COUNT = 64, + parameter BAR0_APERTURE = 24, + parameter BAR2_APERTURE = 24 +) +( + /* + * Clock: 250 MHz + * Synchronous reset + */ + input wire clk, + input wire rst, + + /* + * GPIO + */ + input wire btnu, + input wire btnl, + input wire btnd, + input wire btnr, + input wire btnc, + input wire [3:0] sw, + output wire [7:0] led, + + /* + * PCIe + */ + output wire [AXIS_PCIE_DATA_WIDTH-1:0] m_axis_rq_tdata, + output wire [AXIS_PCIE_KEEP_WIDTH-1:0] m_axis_rq_tkeep, + output wire m_axis_rq_tlast, + input wire m_axis_rq_tready, + output wire [AXIS_PCIE_RQ_USER_WIDTH-1:0] m_axis_rq_tuser, + output wire m_axis_rq_tvalid, + + input wire [AXIS_PCIE_DATA_WIDTH-1:0] s_axis_rc_tdata, + input wire [AXIS_PCIE_KEEP_WIDTH-1:0] s_axis_rc_tkeep, + input wire s_axis_rc_tlast, + output wire s_axis_rc_tready, + input wire [AXIS_PCIE_RC_USER_WIDTH-1:0] s_axis_rc_tuser, + input wire s_axis_rc_tvalid, + + input wire [AXIS_PCIE_DATA_WIDTH-1:0] s_axis_cq_tdata, + input wire [AXIS_PCIE_KEEP_WIDTH-1:0] s_axis_cq_tkeep, + input wire s_axis_cq_tlast, + output wire s_axis_cq_tready, + input wire [AXIS_PCIE_CQ_USER_WIDTH-1:0] s_axis_cq_tuser, + input wire s_axis_cq_tvalid, + + output wire [AXIS_PCIE_DATA_WIDTH-1:0] m_axis_cc_tdata, + output wire [AXIS_PCIE_KEEP_WIDTH-1:0] m_axis_cc_tkeep, + output wire m_axis_cc_tlast, + input wire m_axis_cc_tready, + output wire [AXIS_PCIE_CC_USER_WIDTH-1:0] m_axis_cc_tuser, + output wire m_axis_cc_tvalid, + + input wire [RQ_SEQ_NUM_WIDTH-1:0] s_axis_rq_seq_num_0, + input wire s_axis_rq_seq_num_valid_0, + input wire [RQ_SEQ_NUM_WIDTH-1:0] s_axis_rq_seq_num_1, + input wire s_axis_rq_seq_num_valid_1, + + input wire [2:0] cfg_max_payload, + input wire [2:0] cfg_max_read_req, + + output wire [9:0] cfg_mgmt_addr, + output wire [7:0] cfg_mgmt_function_number, + output wire cfg_mgmt_write, + output wire [31:0] cfg_mgmt_write_data, + output wire [3:0] cfg_mgmt_byte_enable, + output wire cfg_mgmt_read, + input wire [31:0] cfg_mgmt_read_data, + input wire cfg_mgmt_read_write_done, + + input wire [7:0] cfg_fc_ph, + input wire [11:0] cfg_fc_pd, + input wire [7:0] cfg_fc_nph, + input wire [11:0] cfg_fc_npd, + input wire [7:0] cfg_fc_cplh, + input wire [11:0] cfg_fc_cpld, + output wire [2:0] cfg_fc_sel, + + input wire [3:0] cfg_interrupt_msi_enable, + input wire [11:0] cfg_interrupt_msi_mmenable, + input wire cfg_interrupt_msi_mask_update, + input wire [31:0] cfg_interrupt_msi_data, + output wire [3:0] cfg_interrupt_msi_select, + output wire [31:0] cfg_interrupt_msi_int, + output wire [31:0] cfg_interrupt_msi_pending_status, + output wire cfg_interrupt_msi_pending_status_data_enable, + output wire [3:0] cfg_interrupt_msi_pending_status_function_num, + input wire cfg_interrupt_msi_sent, + input wire cfg_interrupt_msi_fail, + output wire [2:0] cfg_interrupt_msi_attr, + output wire cfg_interrupt_msi_tph_present, + output wire [1:0] cfg_interrupt_msi_tph_type, + output wire [8:0] cfg_interrupt_msi_tph_st_tag, + output wire [3:0] cfg_interrupt_msi_function_number, + + output wire status_error_cor, + output wire status_error_uncor +); + +assign led = 8'd0; + +example_core_pcie_us #( + .AXIS_PCIE_DATA_WIDTH(AXIS_PCIE_DATA_WIDTH), + .AXIS_PCIE_KEEP_WIDTH(AXIS_PCIE_KEEP_WIDTH), + .AXIS_PCIE_RC_USER_WIDTH(AXIS_PCIE_RC_USER_WIDTH), + .AXIS_PCIE_RQ_USER_WIDTH(AXIS_PCIE_RQ_USER_WIDTH), + .AXIS_PCIE_CQ_USER_WIDTH(AXIS_PCIE_CQ_USER_WIDTH), + .AXIS_PCIE_CC_USER_WIDTH(AXIS_PCIE_CC_USER_WIDTH), + .RQ_SEQ_NUM_WIDTH(RQ_SEQ_NUM_WIDTH), + .RQ_SEQ_NUM_ENABLE(RQ_SEQ_NUM_ENABLE), + .PCIE_TAG_COUNT(PCIE_TAG_COUNT), + .READ_OP_TABLE_SIZE(PCIE_TAG_COUNT), + .READ_TX_LIMIT(2**(RQ_SEQ_NUM_WIDTH-1)), + .READ_TX_FC_ENABLE(1), + .WRITE_OP_TABLE_SIZE(2**(RQ_SEQ_NUM_WIDTH-1)), + .WRITE_TX_LIMIT(2**(RQ_SEQ_NUM_WIDTH-1)), + .WRITE_TX_FC_ENABLE(1), + .BAR0_APERTURE(BAR0_APERTURE), + .BAR2_APERTURE(BAR2_APERTURE) +) +example_core_pcie_us_inst ( + .clk(clk), + .rst(rst), + + /* + * AXI input (RC) + */ + .s_axis_rc_tdata(s_axis_rc_tdata), + .s_axis_rc_tkeep(s_axis_rc_tkeep), + .s_axis_rc_tvalid(s_axis_rc_tvalid), + .s_axis_rc_tready(s_axis_rc_tready), + .s_axis_rc_tlast(s_axis_rc_tlast), + .s_axis_rc_tuser(s_axis_rc_tuser), + + /* + * AXI output (RQ) + */ + .m_axis_rq_tdata(m_axis_rq_tdata), + .m_axis_rq_tkeep(m_axis_rq_tkeep), + .m_axis_rq_tvalid(m_axis_rq_tvalid), + .m_axis_rq_tready(m_axis_rq_tready), + .m_axis_rq_tlast(m_axis_rq_tlast), + .m_axis_rq_tuser(m_axis_rq_tuser), + + /* + * AXI input (CQ) + */ + .s_axis_cq_tdata(s_axis_cq_tdata), + .s_axis_cq_tkeep(s_axis_cq_tkeep), + .s_axis_cq_tvalid(s_axis_cq_tvalid), + .s_axis_cq_tready(s_axis_cq_tready), + .s_axis_cq_tlast(s_axis_cq_tlast), + .s_axis_cq_tuser(s_axis_cq_tuser), + + /* + * AXI output (CC) + */ + .m_axis_cc_tdata(m_axis_cc_tdata), + .m_axis_cc_tkeep(m_axis_cc_tkeep), + .m_axis_cc_tvalid(m_axis_cc_tvalid), + .m_axis_cc_tready(m_axis_cc_tready), + .m_axis_cc_tlast(m_axis_cc_tlast), + .m_axis_cc_tuser(m_axis_cc_tuser), + + /* + * Transmit sequence number input + */ + .s_axis_rq_seq_num_0(s_axis_rq_seq_num_0), + .s_axis_rq_seq_num_valid_0(s_axis_rq_seq_num_valid_0), + .s_axis_rq_seq_num_1(s_axis_rq_seq_num_1), + .s_axis_rq_seq_num_valid_1(s_axis_rq_seq_num_valid_1), + + /* + * Flow control + */ + .cfg_fc_ph(cfg_fc_ph), + .cfg_fc_pd(cfg_fc_pd), + .cfg_fc_nph(cfg_fc_nph), + .cfg_fc_npd(cfg_fc_npd), + .cfg_fc_cplh(cfg_fc_cplh), + .cfg_fc_cpld(cfg_fc_cpld), + .cfg_fc_sel(cfg_fc_sel), + + /* + * Configuration interface + */ + .cfg_mgmt_addr(cfg_mgmt_addr), + .cfg_mgmt_function_number(cfg_mgmt_function_number), + .cfg_mgmt_write(cfg_mgmt_write), + .cfg_mgmt_write_data(cfg_mgmt_write_data), + .cfg_mgmt_byte_enable(cfg_mgmt_byte_enable), + .cfg_mgmt_read(cfg_mgmt_read), + .cfg_mgmt_read_data(cfg_mgmt_read_data), + .cfg_mgmt_read_write_done(cfg_mgmt_read_write_done), + + /* + * Interrupt interface + */ + .cfg_interrupt_msi_enable(cfg_interrupt_msi_enable), + .cfg_interrupt_msi_vf_enable(8'd0), + .cfg_interrupt_msi_mmenable(cfg_interrupt_msi_mmenable), + .cfg_interrupt_msi_mask_update(cfg_interrupt_msi_mask_update), + .cfg_interrupt_msi_data(cfg_interrupt_msi_data), + .cfg_interrupt_msi_select(cfg_interrupt_msi_select), + .cfg_interrupt_msi_int(cfg_interrupt_msi_int), + .cfg_interrupt_msi_pending_status(cfg_interrupt_msi_pending_status), + .cfg_interrupt_msi_pending_status_data_enable(cfg_interrupt_msi_pending_status_data_enable), + .cfg_interrupt_msi_pending_status_function_num(cfg_interrupt_msi_pending_status_function_num), + .cfg_interrupt_msi_sent(cfg_interrupt_msi_sent), + .cfg_interrupt_msi_fail(cfg_interrupt_msi_fail), + .cfg_interrupt_msi_attr(cfg_interrupt_msi_attr), + .cfg_interrupt_msi_tph_present(cfg_interrupt_msi_tph_present), + .cfg_interrupt_msi_tph_type(cfg_interrupt_msi_tph_type), + .cfg_interrupt_msi_tph_st_tag(cfg_interrupt_msi_tph_st_tag), + .cfg_interrupt_msi_function_number(cfg_interrupt_msi_function_number), + + /* + * Configuration + */ + .cfg_max_read_req(cfg_max_read_req), + .cfg_max_payload(cfg_max_payload), + + /* + * Status + */ + .status_error_cor(status_error_cor), + .status_error_uncor(status_error_uncor) +); + +endmodule + +`resetall diff --git a/fpga/lib/pcie/example/VCU118/fpga/rtl/sync_reset.v b/fpga/lib/pcie/example/VCU118/fpga/rtl/sync_reset.v new file mode 100644 index 000000000..1fd24d361 --- /dev/null +++ b/fpga/lib/pcie/example/VCU118/fpga/rtl/sync_reset.v @@ -0,0 +1,56 @@ +/* + +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 active-high asynchronous reset signal to a given clock by + * using a pipeline of N registers. + */ +module sync_reset #( + parameter N=2 // depth of synchronizer +)( + input wire clk, + input wire rst, + output wire sync_reset_out +); + +reg [N-1:0] sync_reg = {N{1'b1}}; + +assign sync_reset_out = sync_reg[N-1]; + +always @(posedge clk or posedge rst) begin + if (rst) + sync_reg <= {N{1'b1}}; + else + sync_reg <= {sync_reg[N-2:0], 1'b0}; +end + +endmodule + +`resetall diff --git a/fpga/lib/pcie/example/VCU118/fpga/rtl/sync_signal.v b/fpga/lib/pcie/example/VCU118/fpga/rtl/sync_signal.v new file mode 100644 index 000000000..74b855fa1 --- /dev/null +++ b/fpga/lib/pcie/example/VCU118/fpga/rtl/sync_signal.v @@ -0,0 +1,62 @@ +/* + +Copyright (c) 2014-2018 Alex Forencich + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +*/ + +// Language: Verilog-2001 + +`resetall +`timescale 1 ns / 1 ps +`default_nettype none + +/* + * Synchronizes an asyncronous signal to a given clock by using a pipeline of + * two registers. + */ +module sync_signal #( + parameter WIDTH=1, // width of the input and output signals + parameter N=2 // depth of synchronizer +)( + input wire clk, + input wire [WIDTH-1:0] in, + output wire [WIDTH-1:0] out +); + +reg [WIDTH-1:0] sync_reg[N-1:0]; + +/* + * The synchronized output is the last register in the pipeline. + */ +assign out = sync_reg[N-1]; + +integer k; + +always @(posedge clk) begin + sync_reg[0] <= in; + for (k = 1; k < N; k = k + 1) begin + sync_reg[k] <= sync_reg[k-1]; + end +end + +endmodule + +`resetall diff --git a/fpga/lib/pcie/example/VCU118/fpga/tb/fpga_core/Makefile b/fpga/lib/pcie/example/VCU118/fpga/tb/fpga_core/Makefile new file mode 100644 index 000000000..7c85b6e54 --- /dev/null +++ b/fpga/lib/pcie/example/VCU118/fpga/tb/fpga_core/Makefile @@ -0,0 +1,123 @@ +# Copyright (c) 2020 Alex Forencich +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +TOPLEVEL_LANG = verilog + +SIM ?= icarus +WAVES ?= 0 + +COCOTB_HDL_TIMEUNIT = 1ns +COCOTB_HDL_TIMEPRECISION = 1ps + +DUT = fpga_core +TOPLEVEL = $(DUT) +MODULE = test_$(DUT) +VERILOG_SOURCES += ../../rtl/$(DUT).v +VERILOG_SOURCES += ../../rtl/common/example_core_pcie_us.v +VERILOG_SOURCES += ../../rtl/common/example_core_pcie.v +VERILOG_SOURCES += ../../rtl/common/example_core.v +VERILOG_SOURCES += ../../rtl/common/axi_ram.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_if.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_if_rc.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_if_rq.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_if_cq.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_if_cc.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_cfg.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_msi.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_axil_master.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_axi_master.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_axi_master_rd.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_axi_master_wr.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_tlp_demux_bar.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_tlp_demux.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_tlp_mux.v +VERILOG_SOURCES += ../../lib/pcie/rtl/dma_if_pcie.v +VERILOG_SOURCES += ../../lib/pcie/rtl/dma_if_pcie_rd.v +VERILOG_SOURCES += ../../lib/pcie/rtl/dma_if_pcie_wr.v +VERILOG_SOURCES += ../../lib/pcie/rtl/dma_psdpram.v +VERILOG_SOURCES += ../../lib/pcie/rtl/arbiter.v +VERILOG_SOURCES += ../../lib/pcie/rtl/priority_encoder.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pulse_merge.v + +# module parameters +export PARAM_AXIS_PCIE_DATA_WIDTH ?= 512 +export PARAM_AXIS_PCIE_KEEP_WIDTH ?= $(shell expr $(PARAM_AXIS_PCIE_DATA_WIDTH) / 32 ) +export PARAM_AXIS_PCIE_RQ_USER_WIDTH ?= $(if $(filter-out 512,$(PARAM_AXIS_PCIE_DATA_WIDTH)),62,137) +export PARAM_AXIS_PCIE_RC_USER_WIDTH ?= $(if $(filter-out 512,$(PARAM_AXIS_PCIE_DATA_WIDTH)),75,161) +export PARAM_AXIS_PCIE_CQ_USER_WIDTH ?= $(if $(filter-out 512,$(PARAM_AXIS_PCIE_DATA_WIDTH)),88,183) +export PARAM_AXIS_PCIE_CC_USER_WIDTH ?= $(if $(filter-out 512,$(PARAM_AXIS_PCIE_DATA_WIDTH)),33,81) +export PARAM_RQ_SEQ_NUM_WIDTH ?= 6 +export PARAM_RQ_SEQ_NUM_ENABLE ?= 1 +export PARAM_PCIE_TAG_COUNT ?= 64 +export PARAM_BAR0_APERTURE ?= 24 +export PARAM_BAR2_APERTURE ?= 24 + +ifeq ($(SIM), icarus) + PLUSARGS += -fst + + COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_DATA_WIDTH=$(PARAM_AXIS_PCIE_DATA_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_KEEP_WIDTH=$(PARAM_AXIS_PCIE_KEEP_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_RQ_USER_WIDTH=$(PARAM_AXIS_PCIE_RQ_USER_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_RC_USER_WIDTH=$(PARAM_AXIS_PCIE_RC_USER_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_CQ_USER_WIDTH=$(PARAM_AXIS_PCIE_CQ_USER_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_CC_USER_WIDTH=$(PARAM_AXIS_PCIE_CC_USER_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).RQ_SEQ_NUM_WIDTH=$(PARAM_RQ_SEQ_NUM_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).RQ_SEQ_NUM_ENABLE=$(PARAM_RQ_SEQ_NUM_ENABLE) + COMPILE_ARGS += -P $(TOPLEVEL).PCIE_TAG_COUNT=$(PARAM_PCIE_TAG_COUNT) + COMPILE_ARGS += -P $(TOPLEVEL).BAR0_APERTURE=$(PARAM_BAR0_APERTURE) + COMPILE_ARGS += -P $(TOPLEVEL).BAR2_APERTURE=$(PARAM_BAR2_APERTURE) + + ifeq ($(WAVES), 1) + VERILOG_SOURCES += iverilog_dump.v + COMPILE_ARGS += -s iverilog_dump + endif +else ifeq ($(SIM), verilator) + COMPILE_ARGS += -Wno-SELRANGE -Wno-WIDTH + + COMPILE_ARGS += -GAXIS_PCIE_DATA_WIDTH=$(PARAM_AXIS_PCIE_DATA_WIDTH) + COMPILE_ARGS += -GAXIS_PCIE_KEEP_WIDTH=$(PARAM_AXIS_PCIE_KEEP_WIDTH) + COMPILE_ARGS += -GAXIS_PCIE_RQ_USER_WIDTH=$(PARAM_AXIS_PCIE_RQ_USER_WIDTH) + COMPILE_ARGS += -GAXIS_PCIE_RC_USER_WIDTH=$(PARAM_AXIS_PCIE_RC_USER_WIDTH) + COMPILE_ARGS += -GAXIS_PCIE_CQ_USER_WIDTH=$(PARAM_AXIS_PCIE_CQ_USER_WIDTH) + COMPILE_ARGS += -GAXIS_PCIE_CC_USER_WIDTH=$(PARAM_AXIS_PCIE_CC_USER_WIDTH) + COMPILE_ARGS += -GRQ_SEQ_NUM_WIDTH=$(PARAM_RQ_SEQ_NUM_WIDTH) + COMPILE_ARGS += -GRQ_SEQ_NUM_ENABLE=$(PARAM_RQ_SEQ_NUM_ENABLE) + COMPILE_ARGS += -GPCIE_TAG_COUNT=$(PARAM_PCIE_TAG_COUNT) + COMPILE_ARGS += -GBAR0_APERTURE=$(PARAM_BAR0_APERTURE) + COMPILE_ARGS += -GBAR2_APERTURE=$(PARAM_BAR2_APERTURE) + + ifeq ($(WAVES), 1) + COMPILE_ARGS += --trace-fst + endif +endif + +include $(shell cocotb-config --makefiles)/Makefile.sim + +iverilog_dump.v: + echo 'module iverilog_dump();' > $@ + echo 'initial begin' >> $@ + echo ' $$dumpfile("$(TOPLEVEL).fst");' >> $@ + echo ' $$dumpvars(0, $(TOPLEVEL));' >> $@ + echo 'end' >> $@ + echo 'endmodule' >> $@ + +clean:: + @rm -rf iverilog_dump.v + @rm -rf dump.fst $(TOPLEVEL).fst diff --git a/fpga/lib/pcie/example/VCU118/fpga/tb/fpga_core/test_fpga_core.py b/fpga/lib/pcie/example/VCU118/fpga/tb/fpga_core/test_fpga_core.py new file mode 100644 index 000000000..f526584c4 --- /dev/null +++ b/fpga/lib/pcie/example/VCU118/fpga/tb/fpga_core/test_fpga_core.py @@ -0,0 +1,479 @@ +""" + +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 + +import cocotb_test.simulator + +import cocotb +from cocotb.log import SimLog +from cocotb.triggers import RisingEdge, FallingEdge, Timer + +from cocotbext.axi import AxiStreamBus +from cocotbext.pcie.core import RootComplex +from cocotbext.pcie.xilinx.us import UltraScalePlusPcieDevice + + +class TB(object): + def __init__(self, dut): + self.dut = dut + + self.log = SimLog("cocotb.tb") + self.log.setLevel(logging.DEBUG) + + # PCIe + self.rc = RootComplex() + + self.dev = UltraScalePlusPcieDevice( + # configuration options + pcie_generation=3, + pcie_link_width=16, + user_clk_frequency=250e6, + alignment="dword", + cq_cc_straddle=False, + rq_rc_straddle=False, + rc_4tlp_straddle=False, + enable_pf1=False, + enable_client_tag=True, + enable_extended_tag=True, + enable_parity=False, + enable_rx_msg_interface=False, + enable_sriov=False, + enable_extended_configuration=False, + + enable_pf0_msi=True, + enable_pf1_msi=False, + + # signals + # Clock and Reset Interface + user_clk=dut.clk, + user_reset=dut.rst, + # user_lnk_up + # sys_clk + # sys_clk_gt + # sys_reset + # phy_rdy_out + + # Requester reQuest Interface + rq_bus=AxiStreamBus.from_prefix(dut, "m_axis_rq"), + pcie_rq_seq_num0=dut.s_axis_rq_seq_num_0, + pcie_rq_seq_num_vld0=dut.s_axis_rq_seq_num_valid_0, + pcie_rq_seq_num1=dut.s_axis_rq_seq_num_1, + pcie_rq_seq_num_vld1=dut.s_axis_rq_seq_num_valid_1, + # pcie_rq_tag0 + # pcie_rq_tag1 + # pcie_rq_tag_av + # pcie_rq_tag_vld0 + # pcie_rq_tag_vld1 + + # Requester Completion Interface + rc_bus=AxiStreamBus.from_prefix(dut, "s_axis_rc"), + + # Completer reQuest Interface + cq_bus=AxiStreamBus.from_prefix(dut, "s_axis_cq"), + # pcie_cq_np_req + # pcie_cq_np_req_count + + # Completer Completion Interface + cc_bus=AxiStreamBus.from_prefix(dut, "m_axis_cc"), + + # Transmit Flow Control Interface + # pcie_tfc_nph_av=dut.pcie_tfc_nph_av, + # pcie_tfc_npd_av=dut.pcie_tfc_npd_av, + + # Configuration Management Interface + cfg_mgmt_addr=dut.cfg_mgmt_addr, + cfg_mgmt_function_number=dut.cfg_mgmt_function_number, + cfg_mgmt_write=dut.cfg_mgmt_write, + cfg_mgmt_write_data=dut.cfg_mgmt_write_data, + cfg_mgmt_byte_enable=dut.cfg_mgmt_byte_enable, + cfg_mgmt_read=dut.cfg_mgmt_read, + cfg_mgmt_read_data=dut.cfg_mgmt_read_data, + cfg_mgmt_read_write_done=dut.cfg_mgmt_read_write_done, + # cfg_mgmt_debug_access + + # Configuration Status Interface + # cfg_phy_link_down + # cfg_phy_link_status + # cfg_negotiated_width + # cfg_current_speed + cfg_max_payload=dut.cfg_max_payload, + cfg_max_read_req=dut.cfg_max_read_req, + # cfg_function_status + # cfg_vf_status + # cfg_function_power_state + # cfg_vf_power_state + # cfg_link_power_state + # cfg_err_cor_out + # cfg_err_nonfatal_out + # cfg_err_fatal_out + # cfg_local_error_out + # cfg_local_error_valid + # cfg_rx_pm_state + # cfg_tx_pm_state + # cfg_ltssm_state + # cfg_rcb_status + # cfg_obff_enable + # cfg_pl_status_change + # cfg_tph_requester_enable + # cfg_tph_st_mode + # cfg_vf_tph_requester_enable + # cfg_vf_tph_st_mode + + # Configuration Received Message Interface + # cfg_msg_received + # cfg_msg_received_data + # cfg_msg_received_type + + # Configuration Transmit Message Interface + # cfg_msg_transmit + # cfg_msg_transmit_type + # cfg_msg_transmit_data + # cfg_msg_transmit_done + + # Configuration Flow Control Interface + cfg_fc_ph=dut.cfg_fc_ph, + cfg_fc_pd=dut.cfg_fc_pd, + cfg_fc_nph=dut.cfg_fc_nph, + cfg_fc_npd=dut.cfg_fc_npd, + cfg_fc_cplh=dut.cfg_fc_cplh, + cfg_fc_cpld=dut.cfg_fc_cpld, + cfg_fc_sel=dut.cfg_fc_sel, + + # Configuration Control Interface + # cfg_hot_reset_in + # cfg_hot_reset_out + # cfg_config_space_enable + # cfg_dsn + # cfg_bus_number + # cfg_ds_port_number + # cfg_ds_bus_number + # cfg_ds_device_number + # cfg_ds_function_number + # cfg_power_state_change_ack + # cfg_power_state_change_interrupt + cfg_err_cor_in=dut.status_error_cor, + cfg_err_uncor_in=dut.status_error_uncor, + # cfg_flr_in_process + # cfg_flr_done + # cfg_vf_flr_in_process + # cfg_vf_flr_func_num + # cfg_vf_flr_done + # cfg_pm_aspm_l1_entry_reject + # cfg_pm_aspm_tx_l0s_entry_disable + # cfg_req_pm_transition_l23_ready + # cfg_link_training_enable + + # Configuration Interrupt Controller Interface + # cfg_interrupt_int + # cfg_interrupt_sent + # cfg_interrupt_pending + cfg_interrupt_msi_enable=dut.cfg_interrupt_msi_enable, + cfg_interrupt_msi_mmenable=dut.cfg_interrupt_msi_mmenable, + cfg_interrupt_msi_mask_update=dut.cfg_interrupt_msi_mask_update, + cfg_interrupt_msi_data=dut.cfg_interrupt_msi_data, + # cfg_interrupt_msi_select=dut.cfg_interrupt_msi_select, + cfg_interrupt_msi_int=dut.cfg_interrupt_msi_int, + cfg_interrupt_msi_pending_status=dut.cfg_interrupt_msi_pending_status, + cfg_interrupt_msi_pending_status_data_enable=dut.cfg_interrupt_msi_pending_status_data_enable, + # cfg_interrupt_msi_pending_status_function_num=dut.cfg_interrupt_msi_pending_status_function_num, + cfg_interrupt_msi_sent=dut.cfg_interrupt_msi_sent, + cfg_interrupt_msi_fail=dut.cfg_interrupt_msi_fail, + # cfg_interrupt_msix_enable + # cfg_interrupt_msix_mask + # cfg_interrupt_msix_vf_enable + # cfg_interrupt_msix_vf_mask + # cfg_interrupt_msix_address + # cfg_interrupt_msix_data + # cfg_interrupt_msix_int + # cfg_interrupt_msix_vec_pending + # cfg_interrupt_msix_vec_pending_status + cfg_interrupt_msi_attr=dut.cfg_interrupt_msi_attr, + cfg_interrupt_msi_tph_present=dut.cfg_interrupt_msi_tph_present, + cfg_interrupt_msi_tph_type=dut.cfg_interrupt_msi_tph_type, + # cfg_interrupt_msi_tph_st_tag=dut.cfg_interrupt_msi_tph_st_tag, + # cfg_interrupt_msi_function_number=dut.cfg_interrupt_msi_function_number, + + # Configuration Extend Interface + # cfg_ext_read_received + # cfg_ext_write_received + # cfg_ext_register_number + # cfg_ext_function_number + # cfg_ext_write_data + # cfg_ext_write_byte_enable + # cfg_ext_read_data + # cfg_ext_read_data_valid + ) + + # self.dev.log.setLevel(logging.DEBUG) + + self.rc.make_port().connect(self.dev) + + self.dev.functions[0].msi_multiple_message_capable = 5 + + self.dev.functions[0].configure_bar(0, 2**len(dut.example_core_pcie_us_inst.core_pcie_inst.axil_ctrl_awaddr)) + self.dev.functions[0].configure_bar(2, 2**len(dut.example_core_pcie_us_inst.core_pcie_inst.axi_ram_awaddr)) + + dut.btnu.setimmediatevalue(0) + dut.btnl.setimmediatevalue(0) + dut.btnd.setimmediatevalue(0) + dut.btnr.setimmediatevalue(0) + dut.btnc.setimmediatevalue(0) + dut.sw.setimmediatevalue(0) + + async def init(self): + + await FallingEdge(self.dut.rst) + await Timer(100, 'ns') + + await self.rc.enumerate(enable_bus_mastering=True, configure_msi=True) + + +@cocotb.test() +async def run_test(dut): + + tb = TB(dut) + + await tb.init() + + mem = tb.rc.mem_pool.alloc_region(16*1024*1024) + mem_base = mem.get_absolute_address(0) + + dev_pf0_bar0 = tb.rc.tree[0][0].bar_window[0] + dev_pf0_bar2 = tb.rc.tree[0][0].bar_window[2] + + tb.log.info("Test memory write to BAR 2") + + test_data = b'\x11\x22\x33\x44' + await dev_pf0_bar2.write(0, test_data) + + await Timer(100, 'ns') + + tb.log.info("Test memory read from BAR 2") + + val = await dev_pf0_bar2.read(0, len(test_data), timeout=1000) + tb.log.info("Read data: %s", val) + assert val == test_data + + tb.log.info("Test DMA") + + # write packet data + mem[0:1024] = bytearray([x % 256 for x in range(1024)]) + + # enable DMA + await dev_pf0_bar0.write_dword(0x000000, 1) + + # write pcie read descriptor + await dev_pf0_bar0.write_dword(0x000100, (mem_base+0x0000) & 0xffffffff) + await dev_pf0_bar0.write_dword(0x000104, (mem_base+0x0000 >> 32) & 0xffffffff) + await dev_pf0_bar0.write_dword(0x000108, 0x100) + await dev_pf0_bar0.write_dword(0x000110, 0x400) + await dev_pf0_bar0.write_dword(0x000114, 0xAA) + + await Timer(2000, 'ns') + + # read status + val = await dev_pf0_bar0.read_dword(0x000118) + tb.log.info("Status: 0x%x", val) + assert val == 0x800000AA + + # write pcie write descriptor + await dev_pf0_bar0.write_dword(0x000200, (mem_base+0x1000) & 0xffffffff) + await dev_pf0_bar0.write_dword(0x000204, (mem_base+0x1000 >> 32) & 0xffffffff) + await dev_pf0_bar0.write_dword(0x000208, 0x100) + await dev_pf0_bar0.write_dword(0x000210, 0x400) + await dev_pf0_bar0.write_dword(0x000214, 0x55) + + await Timer(2000, 'ns') + + # read status + val = await dev_pf0_bar0.read_dword(0x000218) + tb.log.info("Status: 0x%x", val) + assert val == 0x80000055 + + tb.log.info("%s", mem.hexdump_str(0x1000, 64)) + + assert mem[0:1024] == mem[0x1000:0x1000+1024] + + tb.log.info("Test DMA block operations") + + # write packet data + mem[0:1024] = bytearray([x % 256 for x in range(1024)]) + + # enable DMA + await dev_pf0_bar0.write_dword(0x000000, 1) + # disable interrupts + await dev_pf0_bar0.write_dword(0x000008, 0) + + # configure operation (read) + # DMA base address + await dev_pf0_bar0.write_dword(0x001080, (mem_base+0x0000) & 0xffffffff) + await dev_pf0_bar0.write_dword(0x001084, (mem_base+0x0000 >> 32) & 0xffffffff) + # DMA offset address + await dev_pf0_bar0.write_dword(0x001088, 0) + await dev_pf0_bar0.write_dword(0x00108c, 0) + # DMA offset mask + await dev_pf0_bar0.write_dword(0x001090, 0x000003ff) + await dev_pf0_bar0.write_dword(0x001094, 0) + # DMA stride + await dev_pf0_bar0.write_dword(0x001098, 256) + await dev_pf0_bar0.write_dword(0x00109c, 0) + # RAM base address + await dev_pf0_bar0.write_dword(0x0010c0, 0) + await dev_pf0_bar0.write_dword(0x0010c4, 0) + # RAM offset address + await dev_pf0_bar0.write_dword(0x0010c8, 0) + await dev_pf0_bar0.write_dword(0x0010cc, 0) + # RAM offset mask + await dev_pf0_bar0.write_dword(0x0010d0, 0x000003ff) + await dev_pf0_bar0.write_dword(0x0010d4, 0) + # RAM stride + await dev_pf0_bar0.write_dword(0x0010d8, 256) + await dev_pf0_bar0.write_dword(0x0010dc, 0) + # clear cycle count + await dev_pf0_bar0.write_dword(0x001008, 0) + await dev_pf0_bar0.write_dword(0x00100c, 0) + # block length + await dev_pf0_bar0.write_dword(0x001010, 256) + # block count + await dev_pf0_bar0.write_dword(0x001018, 32) + await dev_pf0_bar0.write_dword(0x00101c, 0) + # start + await dev_pf0_bar0.write_dword(0x001000, 1) + + await Timer(2000, 'ns') + + # configure operation (write) + # DMA base address + await dev_pf0_bar0.write_dword(0x001180, (mem_base+0x0000) & 0xffffffff) + await dev_pf0_bar0.write_dword(0x001184, (mem_base+0x0000 >> 32) & 0xffffffff) + # DMA offset address + await dev_pf0_bar0.write_dword(0x001188, 0) + await dev_pf0_bar0.write_dword(0x00118c, 0) + # DMA offset mask + await dev_pf0_bar0.write_dword(0x001190, 0x000003ff) + await dev_pf0_bar0.write_dword(0x001194, 0) + # DMA stride + await dev_pf0_bar0.write_dword(0x001198, 256) + await dev_pf0_bar0.write_dword(0x00119c, 0) + # RAM base address + await dev_pf0_bar0.write_dword(0x0011c0, 0) + await dev_pf0_bar0.write_dword(0x0011c4, 0) + # RAM offset address + await dev_pf0_bar0.write_dword(0x0011c8, 0) + await dev_pf0_bar0.write_dword(0x0011cc, 0) + # RAM offset mask + await dev_pf0_bar0.write_dword(0x0011d0, 0x000003ff) + await dev_pf0_bar0.write_dword(0x0011d4, 0) + # RAM stride + await dev_pf0_bar0.write_dword(0x0011d8, 256) + await dev_pf0_bar0.write_dword(0x0011dc, 0) + # clear cycle count + await dev_pf0_bar0.write_dword(0x001108, 0) + await dev_pf0_bar0.write_dword(0x00110c, 0) + # block length + await dev_pf0_bar0.write_dword(0x001110, 256) + # block count + await dev_pf0_bar0.write_dword(0x001118, 32) + await dev_pf0_bar0.write_dword(0x00111c, 0) + # start + await dev_pf0_bar0.write_dword(0x001100, 1) + + await Timer(2000, 'ns') + + await RisingEdge(dut.clk) + await RisingEdge(dut.clk) + + +# cocotb-test + +tests_dir = 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')) +pcie_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'pcie', '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(rtl_dir, "common", "example_core_pcie_us.v"), + os.path.join(rtl_dir, "common", "example_core_pcie.v"), + os.path.join(rtl_dir, "common", "example_core.v"), + os.path.join(rtl_dir, "common", "axi_ram.v"), + os.path.join(pcie_rtl_dir, "pcie_us_if.v"), + os.path.join(pcie_rtl_dir, "pcie_us_if_rc.v"), + os.path.join(pcie_rtl_dir, "pcie_us_if_rq.v"), + os.path.join(pcie_rtl_dir, "pcie_us_if_cq.v"), + os.path.join(pcie_rtl_dir, "pcie_us_if_cc.v"), + os.path.join(pcie_rtl_dir, "pcie_us_cfg.v"), + os.path.join(pcie_rtl_dir, "pcie_us_msi.v"), + os.path.join(pcie_rtl_dir, "pcie_axil_master.v"), + os.path.join(pcie_rtl_dir, "pcie_axi_master.v"), + os.path.join(pcie_rtl_dir, "pcie_axi_master_rd.v"), + os.path.join(pcie_rtl_dir, "pcie_axi_master_wr.v"), + os.path.join(pcie_rtl_dir, "pcie_tlp_demux_bar.v"), + os.path.join(pcie_rtl_dir, "pcie_tlp_demux.v"), + os.path.join(pcie_rtl_dir, "pcie_tlp_mux.v"), + os.path.join(pcie_rtl_dir, "dma_if_pcie.v"), + os.path.join(pcie_rtl_dir, "dma_if_pcie_rd.v"), + os.path.join(pcie_rtl_dir, "dma_if_pcie_wr.v"), + os.path.join(pcie_rtl_dir, "dma_psdpram.v"), + os.path.join(pcie_rtl_dir, "arbiter.v"), + os.path.join(pcie_rtl_dir, "priority_encoder.v"), + os.path.join(pcie_rtl_dir, "pulse_merge.v"), + ] + + parameters = {} + + parameters['AXIS_PCIE_DATA_WIDTH'] = 512 + parameters['AXIS_PCIE_KEEP_WIDTH'] = parameters['AXIS_PCIE_DATA_WIDTH'] // 32 + parameters['AXIS_PCIE_RQ_USER_WIDTH'] = 62 if parameters['AXIS_PCIE_DATA_WIDTH'] < 512 else 137 + parameters['AXIS_PCIE_RC_USER_WIDTH'] = 75 if parameters['AXIS_PCIE_DATA_WIDTH'] < 512 else 161 + parameters['AXIS_PCIE_CQ_USER_WIDTH'] = 88 if parameters['AXIS_PCIE_DATA_WIDTH'] < 512 else 183 + parameters['AXIS_PCIE_CC_USER_WIDTH'] = 33 if parameters['AXIS_PCIE_DATA_WIDTH'] < 512 else 81 + parameters['RQ_SEQ_NUM_WIDTH'] = 6 + parameters['RQ_SEQ_NUM_ENABLE'] = 1 + parameters['PCIE_TAG_COUNT'] = 64 + parameters['BAR0_APERTURE'] = 24 + parameters['BAR2_APERTURE'] = 24 + + 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, + ) diff --git a/fpga/lib/pcie/example/VCU1525/fpga/README.md b/fpga/lib/pcie/example/VCU1525/fpga/README.md new file mode 100644 index 000000000..a8941a192 --- /dev/null +++ b/fpga/lib/pcie/example/VCU1525/fpga/README.md @@ -0,0 +1,19 @@ +# Verilog PCIe VCU1525 Example Design + +## Introduction + +This example design targets the Xilinx VCU1525 FPGA board. + +The design implements the PCIe AXI lite master module, the PCIe AXI master module, and the PCIe DMA module. A very simple Linux driver is included to test the FPGA design. + +* FPGA: xcvu9p-fsgd2104-2L-e + +## How to build + +Run `make` to build. Ensure that the Xilinx Vivado components are in PATH. + +Run `make` to build the driver. Ensure the headers for the running kernel are installed, otherwise the driver cannot be compiled. + +## How to test + +Run `make program` to program the VCU1525 board with Vivado. Then load the driver with `insmod example.ko`. Check dmesg for the output. diff --git a/fpga/lib/pcie/example/VCU1525/fpga/common/vivado.mk b/fpga/lib/pcie/example/VCU1525/fpga/common/vivado.mk new file mode 100644 index 000000000..d47a43947 --- /dev/null +++ b/fpga/lib/pcie/example/VCU1525/fpga/common/vivado.mk @@ -0,0 +1,126 @@ +################################################################### +# +# 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) + +SYN_FILES_REL = $(patsubst %, ../%, $(filter-out /% ./%,$(SYN_FILES))) $(filter /% ./%,$(SYN_FILES)) +INC_FILES_REL = $(patsubst %, ../%, $(filter-out /% ./%,$(INC_FILES))) $(filter /% ./%,$(INC_FILES)) +XCI_FILES_REL = $(patsubst %, ../%, $(filter-out /% ./%,$(XCI_FILES))) $(filter /% ./%,$(XCI_FILES)) +IP_TCL_FILES_REL = $(patsubst %, ../%, $(filter-out /% ./%,$(IP_TCL_FILES))) $(filter /% ./%,$(IP_TCL_FILES)) +CONFIG_TCL_FILES_REL = $(patsubst %, ../%, $(filter-out /% ./%,$(CONFIG_TCL_FILES))) $(filter /% ./%,$(CONFIG_TCL_FILES)) + +ifdef XDC_FILES + XDC_FILES_REL = $(patsubst %, ../%, $(filter-out /% ./%,$(XDC_FILES))) $(filter /% ./%,$(XDC_FILES)) +else + XDC_FILES_REL = $(FPGA_TOP).xdc +endif + +################################################################### +# Main Targets +# +# all: build everything +# clean: remove output files and project files +################################################################### + +all: fpga + +fpga: $(FPGA_TOP).bit + +vivado: $(FPGA_TOP).xpr + vivado $(FPGA_TOP).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 program.tcl generate_mcs.tcl *.mcs *.prm flash.tcl + +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) $(FPGA_TOP)" > $@ + echo "add_files -fileset sources_1 defines.v $(SYN_FILES_REL)" >> $@ + 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) + echo "open_project -quiet $(FPGA_TOP).xpr" > $@ + for x in $(CONFIG_TCL_FILES_REL); do echo "source $$x" >> $@; done + +$(FPGA_TOP).xpr: create_project.tcl update_config.tcl + vivado -nojournal -nolog -mode batch $(foreach x,$?,-source $x) + +# synthesis run +%.runs/synth_1/%.dcp: %.xpr $(SYN_FILES_REL) $(INC_FILES_REL) $(XDC_FILES_REL) $(CONFIG_TCL_FILES_REL) + echo "open_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 +%.runs/impl_1/%_routed.dcp: %.runs/synth_1/%.dcp + echo "open_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 + vivado -nojournal -nolog -mode batch -source run_impl.tcl + +# bit file +%.bit: %.runs/impl_1/%_routed.dcp + echo "open_project $*.xpr" > generate_bit.tcl + echo "open_run impl_1" >> generate_bit.tcl + echo "write_bitstream -force $*.bit" >> generate_bit.tcl + vivado -nojournal -nolog -mode batch -source generate_bit.tcl + mkdir -p rev + EXT=bit; COUNT=100; \ + while [ -e rev/$*_rev$$COUNT.$$EXT ]; \ + do COUNT=$$((COUNT+1)); done; \ + cp $@ rev/$*_rev$$COUNT.$$EXT; \ + echo "Output: rev/$*_rev$$COUNT.$$EXT"; diff --git a/fpga/lib/pcie/example/VCU1525/fpga/driver b/fpga/lib/pcie/example/VCU1525/fpga/driver new file mode 120000 index 000000000..4a54c76b5 --- /dev/null +++ b/fpga/lib/pcie/example/VCU1525/fpga/driver @@ -0,0 +1 @@ +../../common/driver/example/ \ No newline at end of file diff --git a/fpga/lib/pcie/example/VCU1525/fpga/fpga.xdc b/fpga/lib/pcie/example/VCU1525/fpga/fpga.xdc new file mode 100644 index 000000000..835538143 --- /dev/null +++ b/fpga/lib/pcie/example/VCU1525/fpga/fpga.xdc @@ -0,0 +1,244 @@ +# 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] + +# 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_rx1_p] ;# MGTYRXP0_231 GTYE4_CHANNEL_X1Y48 / GTYE4_COMMON_X1Y12 +#set_property -dict {LOC N3 } [get_ports qsfp0_rx1_n] ;# MGTYRXN0_231 GTYE4_CHANNEL_X1Y48 / GTYE4_COMMON_X1Y12 +#set_property -dict {LOC N9 } [get_ports qsfp0_tx1_p] ;# MGTYTXP0_231 GTYE4_CHANNEL_X1Y48 / GTYE4_COMMON_X1Y12 +#set_property -dict {LOC N8 } [get_ports qsfp0_tx1_n] ;# MGTYTXN0_231 GTYE4_CHANNEL_X1Y48 / GTYE4_COMMON_X1Y12 +#set_property -dict {LOC M2 } [get_ports qsfp0_rx2_p] ;# MGTYRXP1_231 GTYE4_CHANNEL_X1Y49 / GTYE4_COMMON_X1Y12 +#set_property -dict {LOC M1 } [get_ports qsfp0_rx2_n] ;# MGTYRXN1_231 GTYE4_CHANNEL_X1Y49 / GTYE4_COMMON_X1Y12 +#set_property -dict {LOC M7 } [get_ports qsfp0_tx2_p] ;# MGTYTXP1_231 GTYE4_CHANNEL_X1Y49 / GTYE4_COMMON_X1Y12 +#set_property -dict {LOC M6 } [get_ports qsfp0_tx2_n] ;# MGTYTXN1_231 GTYE4_CHANNEL_X1Y49 / GTYE4_COMMON_X1Y12 +#set_property -dict {LOC L4 } [get_ports qsfp0_rx3_p] ;# MGTYRXP2_231 GTYE4_CHANNEL_X1Y50 / GTYE4_COMMON_X1Y12 +#set_property -dict {LOC L3 } [get_ports qsfp0_rx3_n] ;# MGTYRXN2_231 GTYE4_CHANNEL_X1Y50 / GTYE4_COMMON_X1Y12 +#set_property -dict {LOC L9 } [get_ports qsfp0_tx3_p] ;# MGTYTXP2_231 GTYE4_CHANNEL_X1Y50 / GTYE4_COMMON_X1Y12 +#set_property -dict {LOC L8 } [get_ports qsfp0_tx3_n] ;# MGTYTXN2_231 GTYE4_CHANNEL_X1Y50 / GTYE4_COMMON_X1Y12 +#set_property -dict {LOC K2 } [get_ports qsfp0_rx4_p] ;# MGTYRXP3_231 GTYE4_CHANNEL_X1Y51 / GTYE4_COMMON_X1Y12 +#set_property -dict {LOC K1 } [get_ports qsfp0_rx4_n] ;# MGTYRXN3_231 GTYE4_CHANNEL_X1Y51 / GTYE4_COMMON_X1Y12 +#set_property -dict {LOC K7 } [get_ports qsfp0_tx4_p] ;# MGTYTXP3_231 GTYE4_CHANNEL_X1Y51 / GTYE4_COMMON_X1Y12 +#set_property -dict {LOC K6 } [get_ports qsfp0_tx4_n] ;# 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_rx1_p] ;# MGTYRXP0_230 GTYE4_CHANNEL_X1Y44 / GTYE4_COMMON_X1Y11 +#set_property -dict {LOC U3 } [get_ports qsfp1_rx1_n] ;# MGTYRXN0_230 GTYE4_CHANNEL_X1Y44 / GTYE4_COMMON_X1Y11 +#set_property -dict {LOC U9 } [get_ports qsfp1_tx1_p] ;# MGTYTXP0_230 GTYE4_CHANNEL_X1Y44 / GTYE4_COMMON_X1Y11 +#set_property -dict {LOC U8 } [get_ports qsfp1_tx1_n] ;# MGTYTXN0_230 GTYE4_CHANNEL_X1Y44 / GTYE4_COMMON_X1Y11 +#set_property -dict {LOC T2 } [get_ports qsfp1_rx2_p] ;# MGTYRXP1_230 GTYE4_CHANNEL_X1Y45 / GTYE4_COMMON_X1Y11 +#set_property -dict {LOC T1 } [get_ports qsfp1_rx2_n] ;# MGTYRXN1_230 GTYE4_CHANNEL_X1Y45 / GTYE4_COMMON_X1Y11 +#set_property -dict {LOC T7 } [get_ports qsfp1_tx2_p] ;# MGTYTXP1_230 GTYE4_CHANNEL_X1Y45 / GTYE4_COMMON_X1Y11 +#set_property -dict {LOC T6 } [get_ports qsfp1_tx2_n] ;# MGTYTXN1_230 GTYE4_CHANNEL_X1Y45 / GTYE4_COMMON_X1Y11 +#set_property -dict {LOC R4 } [get_ports qsfp1_rx3_p] ;# MGTYRXP2_230 GTYE4_CHANNEL_X1Y46 / GTYE4_COMMON_X1Y11 +#set_property -dict {LOC R3 } [get_ports qsfp1_rx3_n] ;# MGTYRXN2_230 GTYE4_CHANNEL_X1Y46 / GTYE4_COMMON_X1Y11 +#set_property -dict {LOC R9 } [get_ports qsfp1_tx3_p] ;# MGTYTXP2_230 GTYE4_CHANNEL_X1Y46 / GTYE4_COMMON_X1Y11 +#set_property -dict {LOC R8 } [get_ports qsfp1_tx3_n] ;# MGTYTXN2_230 GTYE4_CHANNEL_X1Y46 / GTYE4_COMMON_X1Y11 +#set_property -dict {LOC P2 } [get_ports qsfp1_rx4_p] ;# MGTYRXP3_230 GTYE4_CHANNEL_X1Y47 / GTYE4_COMMON_X1Y11 +#set_property -dict {LOC P1 } [get_ports qsfp1_rx4_n] ;# MGTYRXN3_230 GTYE4_CHANNEL_X1Y47 / GTYE4_COMMON_X1Y11 +#set_property -dict {LOC P7 } [get_ports qsfp1_tx4_p] ;# MGTYTXP3_230 GTYE4_CHANNEL_X1Y47 / GTYE4_COMMON_X1Y11 +#set_property -dict {LOC P6 } [get_ports qsfp1_tx4_n] ;# 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}] diff --git a/fpga/lib/pcie/example/VCU1525/fpga/fpga/Makefile b/fpga/lib/pcie/example/VCU1525/fpga/fpga/Makefile new file mode 100644 index 000000000..270dd5c62 --- /dev/null +++ b/fpga/lib/pcie/example/VCU1525/fpga/fpga/Makefile @@ -0,0 +1,94 @@ + +# FPGA settings +FPGA_PART = xcvu9p-fsgd2104-2L-e +FPGA_TOP = fpga +FPGA_ARCH = virtexuplus + +# Files for synthesis +SYN_FILES = rtl/fpga.v +SYN_FILES += rtl/fpga_core.v +SYN_FILES += rtl/debounce_switch.v +SYN_FILES += rtl/sync_reset.v +SYN_FILES += rtl/sync_signal.v +SYN_FILES += rtl/common/example_core_pcie_us.v +SYN_FILES += rtl/common/example_core_pcie.v +SYN_FILES += rtl/common/example_core.v +SYN_FILES += rtl/common/axi_ram.v +SYN_FILES += lib/pcie/rtl/pcie_us_if.v +SYN_FILES += lib/pcie/rtl/pcie_us_if_rc.v +SYN_FILES += lib/pcie/rtl/pcie_us_if_rq.v +SYN_FILES += lib/pcie/rtl/pcie_us_if_cq.v +SYN_FILES += lib/pcie/rtl/pcie_us_if_cc.v +SYN_FILES += lib/pcie/rtl/pcie_us_cfg.v +SYN_FILES += lib/pcie/rtl/pcie_us_msi.v +SYN_FILES += lib/pcie/rtl/pcie_axil_master.v +SYN_FILES += lib/pcie/rtl/pcie_axi_master.v +SYN_FILES += lib/pcie/rtl/pcie_axi_master_rd.v +SYN_FILES += lib/pcie/rtl/pcie_axi_master_wr.v +SYN_FILES += lib/pcie/rtl/pcie_tlp_demux_bar.v +SYN_FILES += lib/pcie/rtl/pcie_tlp_demux.v +SYN_FILES += lib/pcie/rtl/pcie_tlp_mux.v +SYN_FILES += lib/pcie/rtl/dma_if_pcie.v +SYN_FILES += lib/pcie/rtl/dma_if_pcie_rd.v +SYN_FILES += lib/pcie/rtl/dma_if_pcie_wr.v +SYN_FILES += lib/pcie/rtl/dma_psdpram.v +SYN_FILES += lib/pcie/rtl/arbiter.v +SYN_FILES += lib/pcie/rtl/priority_encoder.v +SYN_FILES += lib/pcie/rtl/pulse_merge.v + +# XDC files +XDC_FILES = fpga.xdc + +# IP +IP_TCL_FILES = ip/pcie4_uscale_plus_0.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 + +%.mcs %.prm: %.bit + echo "write_cfgmem -force -format mcs -size 128 -interface SPIx4 -loadbit {up 0x04000000 $*.bit} -checksum -file $*.mcs" > generate_mcs.tcl + echo "exit" >> generate_mcs.tcl + vivado -nojournal -nolog -mode batch -source generate_mcs.tcl + mkdir -p rev + COUNT=100; \ + while [ -e rev/$*_rev$$COUNT.bit ]; \ + do COUNT=$$((COUNT+1)); done; \ + COUNT=$$((COUNT-1)); \ + for x in .mcs .prm; \ + do cp $*$$x rev/$*_rev$$COUNT$$x; \ + echo "Output: rev/$*_rev$$COUNT$$x"; done; + +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 + diff --git a/fpga/lib/pcie/example/VCU1525/fpga/ip/pcie4_uscale_plus_0.tcl b/fpga/lib/pcie/example/VCU1525/fpga/ip/pcie4_uscale_plus_0.tcl new file mode 100644 index 000000000..e54bf9d7b --- /dev/null +++ b/fpga/lib/pcie/example/VCU1525/fpga/ip/pcie4_uscale_plus_0.tcl @@ -0,0 +1,28 @@ + +create_ip -name pcie4_uscale_plus -vendor xilinx.com -library ip -module_name pcie4_uscale_plus_0 + +set_property -dict [list \ + CONFIG.PL_LINK_CAP_MAX_LINK_SPEED {8.0_GT/s} \ + CONFIG.PL_LINK_CAP_MAX_LINK_WIDTH {X16} \ + CONFIG.AXISTEN_IF_EXT_512_RQ_STRADDLE {false} \ + CONFIG.axisten_if_enable_client_tag {true} \ + CONFIG.axisten_if_width {512_bit} \ + CONFIG.axisten_freq {250} \ + CONFIG.PF0_CLASS_CODE {058000} \ + CONFIG.PF0_DEVICE_ID {0001} \ + CONFIG.PF0_MSI_CAP_MULTIMSGCAP {32_vectors} \ + CONFIG.PF0_SUBSYSTEM_ID {95f5} \ + CONFIG.PF0_SUBSYSTEM_VENDOR_ID {10ee} \ + CONFIG.pf0_bar0_64bit {true} \ + CONFIG.pf0_bar0_prefetchable {true} \ + CONFIG.pf0_bar0_scale {Megabytes} \ + CONFIG.pf0_bar0_size {16} \ + CONFIG.pf0_bar2_64bit {true} \ + CONFIG.pf0_bar2_prefetchable {true} \ + CONFIG.pf0_bar2_enabled {true} \ + CONFIG.pf0_bar2_type {Memory} \ + CONFIG.pf0_bar2_scale {Megabytes} \ + CONFIG.pf0_bar2_size {16} \ + CONFIG.vendor_id {1234} \ + CONFIG.en_msi_per_vec_masking {true} \ +] [get_ips pcie4_uscale_plus_0] diff --git a/fpga/lib/pcie/example/VCU1525/fpga/lib/pcie b/fpga/lib/pcie/example/VCU1525/fpga/lib/pcie new file mode 120000 index 000000000..11a54ed36 --- /dev/null +++ b/fpga/lib/pcie/example/VCU1525/fpga/lib/pcie @@ -0,0 +1 @@ +../../../../ \ No newline at end of file diff --git a/fpga/lib/pcie/example/VCU1525/fpga/rtl/common b/fpga/lib/pcie/example/VCU1525/fpga/rtl/common new file mode 120000 index 000000000..e60fada70 --- /dev/null +++ b/fpga/lib/pcie/example/VCU1525/fpga/rtl/common @@ -0,0 +1 @@ +../../../common/rtl/ \ No newline at end of file diff --git a/fpga/lib/pcie/example/VCU1525/fpga/rtl/debounce_switch.v b/fpga/lib/pcie/example/VCU1525/fpga/rtl/debounce_switch.v new file mode 100644 index 000000000..8e93a50c4 --- /dev/null +++ b/fpga/lib/pcie/example/VCU1525/fpga/rtl/debounce_switch.v @@ -0,0 +1,93 @@ +/* + +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 diff --git a/fpga/lib/pcie/example/VCU1525/fpga/rtl/fpga.v b/fpga/lib/pcie/example/VCU1525/fpga/rtl/fpga.v new file mode 100644 index 000000000..da734e647 --- /dev/null +++ b/fpga/lib/pcie/example/VCU1525/fpga/rtl/fpga.v @@ -0,0 +1,463 @@ +/* + +Copyright (c) 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 1ns / 1ps +`default_nettype none + +/* + * FPGA top-level module + */ +module fpga ( + /* + * GPIO + */ + input wire [3:0] sw, + output wire [2:0] led, + + /* + * PCI express + */ + input wire [15:0] pcie_rx_p, + input wire [15:0] pcie_rx_n, + output wire [15:0] pcie_tx_p, + output wire [15:0] pcie_tx_n, + input wire pcie_refclk_p, + input wire pcie_refclk_n, + input wire pcie_reset_n +); + +parameter AXIS_PCIE_DATA_WIDTH = 512; +parameter AXIS_PCIE_KEEP_WIDTH = (AXIS_PCIE_DATA_WIDTH/32); +parameter AXIS_PCIE_RC_USER_WIDTH = AXIS_PCIE_DATA_WIDTH < 512 ? 75 : 161; +parameter AXIS_PCIE_RQ_USER_WIDTH = AXIS_PCIE_DATA_WIDTH < 512 ? 60 : 137; +parameter AXIS_PCIE_CQ_USER_WIDTH = AXIS_PCIE_DATA_WIDTH < 512 ? 85 : 183; +parameter AXIS_PCIE_CC_USER_WIDTH = AXIS_PCIE_DATA_WIDTH < 512 ? 33 : 81; + +parameter RQ_SEQ_NUM_WIDTH = AXIS_PCIE_RQ_USER_WIDTH == 60 ? 4 : 6; +parameter RQ_SEQ_NUM_ENABLE = 1; + +parameter PCIE_TAG_COUNT = 64; +parameter BAR0_APERTURE = 24; +parameter BAR2_APERTURE = 24; + +// Clock and reset +wire pcie_user_clk; +wire pcie_user_reset; + +// GPIO +wire [3:0] sw_int; + +debounce_switch #( + .WIDTH(4), + .N(4), + .RATE(250000) +) +debounce_switch_inst ( + .clk(pcie_user_clk), + .rst(pcie_user_reset), + .in({sw}), + .out({sw_int}) +); + +// PCIe +wire pcie_sys_clk; +wire pcie_sys_clk_gt; + +IBUFDS_GTE4 #( + .REFCLK_HROW_CK_SEL(2'b00) +) +ibufds_gte4_pcie_mgt_refclk_inst ( + .I (pcie_refclk_p), + .IB (pcie_refclk_n), + .CEB (1'b0), + .O (pcie_sys_clk_gt), + .ODIV2 (pcie_sys_clk) +); + +wire [AXIS_PCIE_DATA_WIDTH-1:0] axis_rq_tdata; +wire [AXIS_PCIE_KEEP_WIDTH-1:0] axis_rq_tkeep; +wire axis_rq_tlast; +wire axis_rq_tready; +wire [AXIS_PCIE_RQ_USER_WIDTH-1:0] axis_rq_tuser; +wire axis_rq_tvalid; + +wire [AXIS_PCIE_DATA_WIDTH-1:0] axis_rc_tdata; +wire [AXIS_PCIE_KEEP_WIDTH-1:0] axis_rc_tkeep; +wire axis_rc_tlast; +wire axis_rc_tready; +wire [AXIS_PCIE_RC_USER_WIDTH-1:0] axis_rc_tuser; +wire axis_rc_tvalid; + +wire [AXIS_PCIE_DATA_WIDTH-1:0] axis_cq_tdata; +wire [AXIS_PCIE_KEEP_WIDTH-1:0] axis_cq_tkeep; +wire axis_cq_tlast; +wire axis_cq_tready; +wire [AXIS_PCIE_CQ_USER_WIDTH-1:0] axis_cq_tuser; +wire axis_cq_tvalid; + +wire [AXIS_PCIE_DATA_WIDTH-1:0] axis_cc_tdata; +wire [AXIS_PCIE_KEEP_WIDTH-1:0] axis_cc_tkeep; +wire axis_cc_tlast; +wire axis_cc_tready; +wire [AXIS_PCIE_CC_USER_WIDTH-1:0] axis_cc_tuser; +wire axis_cc_tvalid; + +wire [RQ_SEQ_NUM_WIDTH-1:0] pcie_rq_seq_num0; +wire pcie_rq_seq_num_vld0; +wire [RQ_SEQ_NUM_WIDTH-1:0] pcie_rq_seq_num1; +wire pcie_rq_seq_num_vld1; + +// ila_0 rq_ila ( +// .clk(pcie_user_clk), +// .probe0(axis_rq_tdata), +// .probe1(axis_rq_tkeep), +// .probe2(axis_rq_tlast), +// .probe3(axis_rq_tready), +// .probe4(axis_rq_tuser), +// .probe5(axis_rq_tvalid) +// ); + +// ila_0 rc_ila ( +// .clk(pcie_user_clk), +// .probe0(axis_rc_tdata), +// .probe1(axis_rc_tkeep), +// .probe2(axis_rc_tlast), +// .probe3(axis_rc_tready), +// .probe4(axis_rc_tuser), +// .probe5(axis_rc_tvalid) +// ); + +wire [2:0] cfg_max_payload; +wire [2:0] cfg_max_read_req; + +wire [9:0] cfg_mgmt_addr; +wire [7:0] cfg_mgmt_function_number; +wire cfg_mgmt_write; +wire [31:0] cfg_mgmt_write_data; +wire [3:0] cfg_mgmt_byte_enable; +wire cfg_mgmt_read; +wire [31:0] cfg_mgmt_read_data; +wire cfg_mgmt_read_write_done; + +wire [7:0] cfg_fc_ph; +wire [11:0] cfg_fc_pd; +wire [7:0] cfg_fc_nph; +wire [11:0] cfg_fc_npd; +wire [7:0] cfg_fc_cplh; +wire [11:0] cfg_fc_cpld; +wire [2:0] cfg_fc_sel; + +wire [3:0] cfg_interrupt_msi_enable; +wire [11:0] cfg_interrupt_msi_mmenable; +wire cfg_interrupt_msi_mask_update; +wire [31:0] cfg_interrupt_msi_data; +wire [3:0] cfg_interrupt_msi_select; +wire [31:0] cfg_interrupt_msi_int; +wire [31:0] cfg_interrupt_msi_pending_status; +wire cfg_interrupt_msi_pending_status_data_enable; +wire [3:0] cfg_interrupt_msi_pending_status_function_num; +wire cfg_interrupt_msi_sent; +wire cfg_interrupt_msi_fail; +wire [2:0] cfg_interrupt_msi_attr; +wire cfg_interrupt_msi_tph_present; +wire [1:0] cfg_interrupt_msi_tph_type; +wire [8:0] cfg_interrupt_msi_tph_st_tag; +wire [3:0] cfg_interrupt_msi_function_number; + +wire status_error_cor; +wire status_error_uncor; + +pcie4_uscale_plus_0 +pcie4_uscale_plus_inst ( + .pci_exp_txn(pcie_tx_n), + .pci_exp_txp(pcie_tx_p), + .pci_exp_rxn(pcie_rx_n), + .pci_exp_rxp(pcie_rx_p), + .user_clk(pcie_user_clk), + .user_reset(pcie_user_reset), + .user_lnk_up(), + + .s_axis_rq_tdata(axis_rq_tdata), + .s_axis_rq_tkeep(axis_rq_tkeep), + .s_axis_rq_tlast(axis_rq_tlast), + .s_axis_rq_tready(axis_rq_tready), + .s_axis_rq_tuser(axis_rq_tuser), + .s_axis_rq_tvalid(axis_rq_tvalid), + + .m_axis_rc_tdata(axis_rc_tdata), + .m_axis_rc_tkeep(axis_rc_tkeep), + .m_axis_rc_tlast(axis_rc_tlast), + .m_axis_rc_tready(axis_rc_tready), + .m_axis_rc_tuser(axis_rc_tuser), + .m_axis_rc_tvalid(axis_rc_tvalid), + + .m_axis_cq_tdata(axis_cq_tdata), + .m_axis_cq_tkeep(axis_cq_tkeep), + .m_axis_cq_tlast(axis_cq_tlast), + .m_axis_cq_tready(axis_cq_tready), + .m_axis_cq_tuser(axis_cq_tuser), + .m_axis_cq_tvalid(axis_cq_tvalid), + + .s_axis_cc_tdata(axis_cc_tdata), + .s_axis_cc_tkeep(axis_cc_tkeep), + .s_axis_cc_tlast(axis_cc_tlast), + .s_axis_cc_tready(axis_cc_tready), + .s_axis_cc_tuser(axis_cc_tuser), + .s_axis_cc_tvalid(axis_cc_tvalid), + + .pcie_rq_seq_num0(pcie_rq_seq_num0), + .pcie_rq_seq_num_vld0(pcie_rq_seq_num_vld0), + .pcie_rq_seq_num1(pcie_rq_seq_num1), + .pcie_rq_seq_num_vld1(pcie_rq_seq_num_vld1), + .pcie_rq_tag0(), + .pcie_rq_tag1(), + .pcie_rq_tag_av(), + .pcie_rq_tag_vld0(), + .pcie_rq_tag_vld1(), + + .pcie_tfc_nph_av(), + .pcie_tfc_npd_av(), + + .pcie_cq_np_req(1'b1), + .pcie_cq_np_req_count(), + + .cfg_phy_link_down(), + .cfg_phy_link_status(), + .cfg_negotiated_width(), + .cfg_current_speed(), + .cfg_max_payload(cfg_max_payload), + .cfg_max_read_req(cfg_max_read_req), + .cfg_function_status(), + .cfg_function_power_state(), + .cfg_vf_status(), + .cfg_vf_power_state(), + .cfg_link_power_state(), + + .cfg_mgmt_addr(cfg_mgmt_addr), + .cfg_mgmt_function_number(cfg_mgmt_function_number), + .cfg_mgmt_write(cfg_mgmt_write), + .cfg_mgmt_write_data(cfg_mgmt_write_data), + .cfg_mgmt_byte_enable(cfg_mgmt_byte_enable), + .cfg_mgmt_read(cfg_mgmt_read), + .cfg_mgmt_read_data(cfg_mgmt_read_data), + .cfg_mgmt_read_write_done(cfg_mgmt_read_write_done), + .cfg_mgmt_debug_access(1'b0), + + .cfg_err_cor_out(), + .cfg_err_nonfatal_out(), + .cfg_err_fatal_out(), + .cfg_local_error_valid(), + .cfg_local_error_out(), + .cfg_ltssm_state(), + .cfg_rx_pm_state(), + .cfg_tx_pm_state(), + .cfg_rcb_status(), + .cfg_obff_enable(), + .cfg_pl_status_change(), + .cfg_tph_requester_enable(), + .cfg_tph_st_mode(), + .cfg_vf_tph_requester_enable(), + .cfg_vf_tph_st_mode(), + + .cfg_msg_received(), + .cfg_msg_received_data(), + .cfg_msg_received_type(), + .cfg_msg_transmit(1'b0), + .cfg_msg_transmit_type(3'd0), + .cfg_msg_transmit_data(32'd0), + .cfg_msg_transmit_done(), + + .cfg_fc_ph(cfg_fc_ph), + .cfg_fc_pd(cfg_fc_pd), + .cfg_fc_nph(cfg_fc_nph), + .cfg_fc_npd(cfg_fc_npd), + .cfg_fc_cplh(cfg_fc_cplh), + .cfg_fc_cpld(cfg_fc_cpld), + .cfg_fc_sel(cfg_fc_sel), + + .cfg_dsn(64'd0), + + .cfg_bus_number(), + + .cfg_power_state_change_ack(1'b1), + .cfg_power_state_change_interrupt(), + + .cfg_err_cor_in(status_error_cor), + .cfg_err_uncor_in(status_error_uncor), + .cfg_flr_in_process(), + .cfg_flr_done(4'd0), + .cfg_vf_flr_in_process(), + .cfg_vf_flr_func_num(8'd0), + .cfg_vf_flr_done(8'd0), + + .cfg_link_training_enable(1'b1), + + .cfg_interrupt_int(4'd0), + .cfg_interrupt_pending(4'd0), + .cfg_interrupt_sent(), + .cfg_interrupt_msi_enable(cfg_interrupt_msi_enable), + .cfg_interrupt_msi_mmenable(cfg_interrupt_msi_mmenable), + .cfg_interrupt_msi_mask_update(cfg_interrupt_msi_mask_update), + .cfg_interrupt_msi_data(cfg_interrupt_msi_data), + .cfg_interrupt_msi_select(cfg_interrupt_msi_select), + .cfg_interrupt_msi_int(cfg_interrupt_msi_int), + .cfg_interrupt_msi_pending_status(cfg_interrupt_msi_pending_status), + .cfg_interrupt_msi_pending_status_data_enable(cfg_interrupt_msi_pending_status_data_enable), + .cfg_interrupt_msi_pending_status_function_num(cfg_interrupt_msi_pending_status_function_num), + .cfg_interrupt_msi_sent(cfg_interrupt_msi_sent), + .cfg_interrupt_msi_fail(cfg_interrupt_msi_fail), + .cfg_interrupt_msi_attr(cfg_interrupt_msi_attr), + .cfg_interrupt_msi_tph_present(cfg_interrupt_msi_tph_present), + .cfg_interrupt_msi_tph_type(cfg_interrupt_msi_tph_type), + .cfg_interrupt_msi_tph_st_tag(cfg_interrupt_msi_tph_st_tag), + .cfg_interrupt_msi_function_number(cfg_interrupt_msi_function_number), + + .cfg_pm_aspm_l1_entry_reject(1'b0), + .cfg_pm_aspm_tx_l0s_entry_disable(1'b0), + + .cfg_hot_reset_out(), + + .cfg_config_space_enable(1'b1), + .cfg_req_pm_transition_l23_ready(1'b0), + .cfg_hot_reset_in(1'b0), + + .cfg_ds_port_number(8'd0), + .cfg_ds_bus_number(8'd0), + .cfg_ds_device_number(5'd0), + + .sys_clk(pcie_sys_clk), + .sys_clk_gt(pcie_sys_clk_gt), + .sys_reset(pcie_reset_n), + + .phy_rdy_out() +); + +fpga_core #( + .AXIS_PCIE_DATA_WIDTH(AXIS_PCIE_DATA_WIDTH), + .AXIS_PCIE_KEEP_WIDTH(AXIS_PCIE_KEEP_WIDTH), + .AXIS_PCIE_RC_USER_WIDTH(AXIS_PCIE_RC_USER_WIDTH), + .AXIS_PCIE_RQ_USER_WIDTH(AXIS_PCIE_RQ_USER_WIDTH), + .AXIS_PCIE_CQ_USER_WIDTH(AXIS_PCIE_CQ_USER_WIDTH), + .AXIS_PCIE_CC_USER_WIDTH(AXIS_PCIE_CC_USER_WIDTH), + .RQ_SEQ_NUM_WIDTH(RQ_SEQ_NUM_WIDTH), + .RQ_SEQ_NUM_ENABLE(RQ_SEQ_NUM_ENABLE), + .PCIE_TAG_COUNT(PCIE_TAG_COUNT), + .BAR0_APERTURE(BAR0_APERTURE), + .BAR2_APERTURE(BAR2_APERTURE) +) +core_inst ( + /* + * Clock: 250 MHz + * Synchronous reset + */ + .clk(pcie_user_clk), + .rst(pcie_user_reset), + /* + * GPIO + */ + .sw(sw_int), + .led(led), + /* + * PCIe + */ + .m_axis_rq_tdata(axis_rq_tdata), + .m_axis_rq_tkeep(axis_rq_tkeep), + .m_axis_rq_tlast(axis_rq_tlast), + .m_axis_rq_tready(axis_rq_tready), + .m_axis_rq_tuser(axis_rq_tuser), + .m_axis_rq_tvalid(axis_rq_tvalid), + + .s_axis_rc_tdata(axis_rc_tdata), + .s_axis_rc_tkeep(axis_rc_tkeep), + .s_axis_rc_tlast(axis_rc_tlast), + .s_axis_rc_tready(axis_rc_tready), + .s_axis_rc_tuser(axis_rc_tuser), + .s_axis_rc_tvalid(axis_rc_tvalid), + + .s_axis_cq_tdata(axis_cq_tdata), + .s_axis_cq_tkeep(axis_cq_tkeep), + .s_axis_cq_tlast(axis_cq_tlast), + .s_axis_cq_tready(axis_cq_tready), + .s_axis_cq_tuser(axis_cq_tuser), + .s_axis_cq_tvalid(axis_cq_tvalid), + + .m_axis_cc_tdata(axis_cc_tdata), + .m_axis_cc_tkeep(axis_cc_tkeep), + .m_axis_cc_tlast(axis_cc_tlast), + .m_axis_cc_tready(axis_cc_tready), + .m_axis_cc_tuser(axis_cc_tuser), + .m_axis_cc_tvalid(axis_cc_tvalid), + + .s_axis_rq_seq_num_0(pcie_rq_seq_num0), + .s_axis_rq_seq_num_valid_0(pcie_rq_seq_num_vld0), + .s_axis_rq_seq_num_1(pcie_rq_seq_num1), + .s_axis_rq_seq_num_valid_1(pcie_rq_seq_num_vld1), + + .cfg_max_payload(cfg_max_payload), + .cfg_max_read_req(cfg_max_read_req), + + .cfg_mgmt_addr(cfg_mgmt_addr), + .cfg_mgmt_function_number(cfg_mgmt_function_number), + .cfg_mgmt_write(cfg_mgmt_write), + .cfg_mgmt_write_data(cfg_mgmt_write_data), + .cfg_mgmt_byte_enable(cfg_mgmt_byte_enable), + .cfg_mgmt_read(cfg_mgmt_read), + .cfg_mgmt_read_data(cfg_mgmt_read_data), + .cfg_mgmt_read_write_done(cfg_mgmt_read_write_done), + + .cfg_fc_ph(cfg_fc_ph), + .cfg_fc_pd(cfg_fc_pd), + .cfg_fc_nph(cfg_fc_nph), + .cfg_fc_npd(cfg_fc_npd), + .cfg_fc_cplh(cfg_fc_cplh), + .cfg_fc_cpld(cfg_fc_cpld), + .cfg_fc_sel(cfg_fc_sel), + + .cfg_interrupt_msi_enable(cfg_interrupt_msi_enable), + .cfg_interrupt_msi_mmenable(cfg_interrupt_msi_mmenable), + .cfg_interrupt_msi_mask_update(cfg_interrupt_msi_mask_update), + .cfg_interrupt_msi_data(cfg_interrupt_msi_data), + .cfg_interrupt_msi_select(cfg_interrupt_msi_select), + .cfg_interrupt_msi_int(cfg_interrupt_msi_int), + .cfg_interrupt_msi_pending_status(cfg_interrupt_msi_pending_status), + .cfg_interrupt_msi_pending_status_data_enable(cfg_interrupt_msi_pending_status_data_enable), + .cfg_interrupt_msi_pending_status_function_num(cfg_interrupt_msi_pending_status_function_num), + .cfg_interrupt_msi_sent(cfg_interrupt_msi_sent), + .cfg_interrupt_msi_fail(cfg_interrupt_msi_fail), + .cfg_interrupt_msi_attr(cfg_interrupt_msi_attr), + .cfg_interrupt_msi_tph_present(cfg_interrupt_msi_tph_present), + .cfg_interrupt_msi_tph_type(cfg_interrupt_msi_tph_type), + .cfg_interrupt_msi_tph_st_tag(cfg_interrupt_msi_tph_st_tag), + .cfg_interrupt_msi_function_number(cfg_interrupt_msi_function_number), + + .status_error_cor(status_error_cor), + .status_error_uncor(status_error_uncor) +); + +endmodule + +`resetall diff --git a/fpga/lib/pcie/example/VCU1525/fpga/rtl/fpga_core.v b/fpga/lib/pcie/example/VCU1525/fpga/rtl/fpga_core.v new file mode 100644 index 000000000..a6c947b68 --- /dev/null +++ b/fpga/lib/pcie/example/VCU1525/fpga/rtl/fpga_core.v @@ -0,0 +1,271 @@ +/* + +Copyright (c) 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 1ns / 1ps +`default_nettype none + +/* + * FPGA core logic + */ +module fpga_core # +( + parameter AXIS_PCIE_DATA_WIDTH = 512, + parameter AXIS_PCIE_KEEP_WIDTH = (AXIS_PCIE_DATA_WIDTH/32), + parameter AXIS_PCIE_RC_USER_WIDTH = AXIS_PCIE_DATA_WIDTH < 512 ? 75 : 161, + parameter AXIS_PCIE_RQ_USER_WIDTH = AXIS_PCIE_DATA_WIDTH < 512 ? 60 : 137, + parameter AXIS_PCIE_CQ_USER_WIDTH = AXIS_PCIE_DATA_WIDTH < 512 ? 85 : 183, + parameter AXIS_PCIE_CC_USER_WIDTH = AXIS_PCIE_DATA_WIDTH < 512 ? 33 : 81, + parameter RQ_SEQ_NUM_WIDTH = AXIS_PCIE_RQ_USER_WIDTH == 60 ? 4 : 6, + parameter RQ_SEQ_NUM_ENABLE = 1, + parameter PCIE_TAG_COUNT = 64, + parameter BAR0_APERTURE = 24, + parameter BAR2_APERTURE = 24 +) +( + /* + * Clock: 250 MHz + * Synchronous reset + */ + input wire clk, + input wire rst, + + /* + * GPIO + */ + input wire [3:0] sw, + output wire [2:0] led, + + /* + * PCIe + */ + output wire [AXIS_PCIE_DATA_WIDTH-1:0] m_axis_rq_tdata, + output wire [AXIS_PCIE_KEEP_WIDTH-1:0] m_axis_rq_tkeep, + output wire m_axis_rq_tlast, + input wire m_axis_rq_tready, + output wire [AXIS_PCIE_RQ_USER_WIDTH-1:0] m_axis_rq_tuser, + output wire m_axis_rq_tvalid, + + input wire [AXIS_PCIE_DATA_WIDTH-1:0] s_axis_rc_tdata, + input wire [AXIS_PCIE_KEEP_WIDTH-1:0] s_axis_rc_tkeep, + input wire s_axis_rc_tlast, + output wire s_axis_rc_tready, + input wire [AXIS_PCIE_RC_USER_WIDTH-1:0] s_axis_rc_tuser, + input wire s_axis_rc_tvalid, + + input wire [AXIS_PCIE_DATA_WIDTH-1:0] s_axis_cq_tdata, + input wire [AXIS_PCIE_KEEP_WIDTH-1:0] s_axis_cq_tkeep, + input wire s_axis_cq_tlast, + output wire s_axis_cq_tready, + input wire [AXIS_PCIE_CQ_USER_WIDTH-1:0] s_axis_cq_tuser, + input wire s_axis_cq_tvalid, + + output wire [AXIS_PCIE_DATA_WIDTH-1:0] m_axis_cc_tdata, + output wire [AXIS_PCIE_KEEP_WIDTH-1:0] m_axis_cc_tkeep, + output wire m_axis_cc_tlast, + input wire m_axis_cc_tready, + output wire [AXIS_PCIE_CC_USER_WIDTH-1:0] m_axis_cc_tuser, + output wire m_axis_cc_tvalid, + + input wire [RQ_SEQ_NUM_WIDTH-1:0] s_axis_rq_seq_num_0, + input wire s_axis_rq_seq_num_valid_0, + input wire [RQ_SEQ_NUM_WIDTH-1:0] s_axis_rq_seq_num_1, + input wire s_axis_rq_seq_num_valid_1, + + input wire [2:0] cfg_max_payload, + input wire [2:0] cfg_max_read_req, + + output wire [9:0] cfg_mgmt_addr, + output wire [7:0] cfg_mgmt_function_number, + output wire cfg_mgmt_write, + output wire [31:0] cfg_mgmt_write_data, + output wire [3:0] cfg_mgmt_byte_enable, + output wire cfg_mgmt_read, + input wire [31:0] cfg_mgmt_read_data, + input wire cfg_mgmt_read_write_done, + + input wire [7:0] cfg_fc_ph, + input wire [11:0] cfg_fc_pd, + input wire [7:0] cfg_fc_nph, + input wire [11:0] cfg_fc_npd, + input wire [7:0] cfg_fc_cplh, + input wire [11:0] cfg_fc_cpld, + output wire [2:0] cfg_fc_sel, + + input wire [3:0] cfg_interrupt_msi_enable, + input wire [11:0] cfg_interrupt_msi_mmenable, + input wire cfg_interrupt_msi_mask_update, + input wire [31:0] cfg_interrupt_msi_data, + output wire [3:0] cfg_interrupt_msi_select, + output wire [31:0] cfg_interrupt_msi_int, + output wire [31:0] cfg_interrupt_msi_pending_status, + output wire cfg_interrupt_msi_pending_status_data_enable, + output wire [3:0] cfg_interrupt_msi_pending_status_function_num, + input wire cfg_interrupt_msi_sent, + input wire cfg_interrupt_msi_fail, + output wire [2:0] cfg_interrupt_msi_attr, + output wire cfg_interrupt_msi_tph_present, + output wire [1:0] cfg_interrupt_msi_tph_type, + output wire [8:0] cfg_interrupt_msi_tph_st_tag, + output wire [3:0] cfg_interrupt_msi_function_number, + + output wire status_error_cor, + output wire status_error_uncor +); + +assign led = 3'd0; + +example_core_pcie_us #( + .AXIS_PCIE_DATA_WIDTH(AXIS_PCIE_DATA_WIDTH), + .AXIS_PCIE_KEEP_WIDTH(AXIS_PCIE_KEEP_WIDTH), + .AXIS_PCIE_RC_USER_WIDTH(AXIS_PCIE_RC_USER_WIDTH), + .AXIS_PCIE_RQ_USER_WIDTH(AXIS_PCIE_RQ_USER_WIDTH), + .AXIS_PCIE_CQ_USER_WIDTH(AXIS_PCIE_CQ_USER_WIDTH), + .AXIS_PCIE_CC_USER_WIDTH(AXIS_PCIE_CC_USER_WIDTH), + .RQ_SEQ_NUM_WIDTH(RQ_SEQ_NUM_WIDTH), + .RQ_SEQ_NUM_ENABLE(RQ_SEQ_NUM_ENABLE), + .PCIE_TAG_COUNT(PCIE_TAG_COUNT), + .READ_OP_TABLE_SIZE(PCIE_TAG_COUNT), + .READ_TX_LIMIT(2**(RQ_SEQ_NUM_WIDTH-1)), + .READ_TX_FC_ENABLE(1), + .WRITE_OP_TABLE_SIZE(2**(RQ_SEQ_NUM_WIDTH-1)), + .WRITE_TX_LIMIT(2**(RQ_SEQ_NUM_WIDTH-1)), + .WRITE_TX_FC_ENABLE(1), + .BAR0_APERTURE(BAR0_APERTURE), + .BAR2_APERTURE(BAR2_APERTURE) +) +example_core_pcie_us_inst ( + .clk(clk), + .rst(rst), + + /* + * AXI input (RC) + */ + .s_axis_rc_tdata(s_axis_rc_tdata), + .s_axis_rc_tkeep(s_axis_rc_tkeep), + .s_axis_rc_tvalid(s_axis_rc_tvalid), + .s_axis_rc_tready(s_axis_rc_tready), + .s_axis_rc_tlast(s_axis_rc_tlast), + .s_axis_rc_tuser(s_axis_rc_tuser), + + /* + * AXI output (RQ) + */ + .m_axis_rq_tdata(m_axis_rq_tdata), + .m_axis_rq_tkeep(m_axis_rq_tkeep), + .m_axis_rq_tvalid(m_axis_rq_tvalid), + .m_axis_rq_tready(m_axis_rq_tready), + .m_axis_rq_tlast(m_axis_rq_tlast), + .m_axis_rq_tuser(m_axis_rq_tuser), + + /* + * AXI input (CQ) + */ + .s_axis_cq_tdata(s_axis_cq_tdata), + .s_axis_cq_tkeep(s_axis_cq_tkeep), + .s_axis_cq_tvalid(s_axis_cq_tvalid), + .s_axis_cq_tready(s_axis_cq_tready), + .s_axis_cq_tlast(s_axis_cq_tlast), + .s_axis_cq_tuser(s_axis_cq_tuser), + + /* + * AXI output (CC) + */ + .m_axis_cc_tdata(m_axis_cc_tdata), + .m_axis_cc_tkeep(m_axis_cc_tkeep), + .m_axis_cc_tvalid(m_axis_cc_tvalid), + .m_axis_cc_tready(m_axis_cc_tready), + .m_axis_cc_tlast(m_axis_cc_tlast), + .m_axis_cc_tuser(m_axis_cc_tuser), + + /* + * Transmit sequence number input + */ + .s_axis_rq_seq_num_0(s_axis_rq_seq_num_0), + .s_axis_rq_seq_num_valid_0(s_axis_rq_seq_num_valid_0), + .s_axis_rq_seq_num_1(s_axis_rq_seq_num_1), + .s_axis_rq_seq_num_valid_1(s_axis_rq_seq_num_valid_1), + + /* + * Flow control + */ + .cfg_fc_ph(cfg_fc_ph), + .cfg_fc_pd(cfg_fc_pd), + .cfg_fc_nph(cfg_fc_nph), + .cfg_fc_npd(cfg_fc_npd), + .cfg_fc_cplh(cfg_fc_cplh), + .cfg_fc_cpld(cfg_fc_cpld), + .cfg_fc_sel(cfg_fc_sel), + + /* + * Configuration interface + */ + .cfg_mgmt_addr(cfg_mgmt_addr), + .cfg_mgmt_function_number(cfg_mgmt_function_number), + .cfg_mgmt_write(cfg_mgmt_write), + .cfg_mgmt_write_data(cfg_mgmt_write_data), + .cfg_mgmt_byte_enable(cfg_mgmt_byte_enable), + .cfg_mgmt_read(cfg_mgmt_read), + .cfg_mgmt_read_data(cfg_mgmt_read_data), + .cfg_mgmt_read_write_done(cfg_mgmt_read_write_done), + + /* + * Interrupt interface + */ + .cfg_interrupt_msi_enable(cfg_interrupt_msi_enable), + .cfg_interrupt_msi_vf_enable(8'd0), + .cfg_interrupt_msi_mmenable(cfg_interrupt_msi_mmenable), + .cfg_interrupt_msi_mask_update(cfg_interrupt_msi_mask_update), + .cfg_interrupt_msi_data(cfg_interrupt_msi_data), + .cfg_interrupt_msi_select(cfg_interrupt_msi_select), + .cfg_interrupt_msi_int(cfg_interrupt_msi_int), + .cfg_interrupt_msi_pending_status(cfg_interrupt_msi_pending_status), + .cfg_interrupt_msi_pending_status_data_enable(cfg_interrupt_msi_pending_status_data_enable), + .cfg_interrupt_msi_pending_status_function_num(cfg_interrupt_msi_pending_status_function_num), + .cfg_interrupt_msi_sent(cfg_interrupt_msi_sent), + .cfg_interrupt_msi_fail(cfg_interrupt_msi_fail), + .cfg_interrupt_msi_attr(cfg_interrupt_msi_attr), + .cfg_interrupt_msi_tph_present(cfg_interrupt_msi_tph_present), + .cfg_interrupt_msi_tph_type(cfg_interrupt_msi_tph_type), + .cfg_interrupt_msi_tph_st_tag(cfg_interrupt_msi_tph_st_tag), + .cfg_interrupt_msi_function_number(cfg_interrupt_msi_function_number), + + /* + * Configuration + */ + .cfg_max_read_req(cfg_max_read_req), + .cfg_max_payload(cfg_max_payload), + + /* + * Status + */ + .status_error_cor(status_error_cor), + .status_error_uncor(status_error_uncor) +); + +endmodule + +`resetall diff --git a/fpga/lib/pcie/example/VCU1525/fpga/rtl/sync_reset.v b/fpga/lib/pcie/example/VCU1525/fpga/rtl/sync_reset.v new file mode 100644 index 000000000..1fd24d361 --- /dev/null +++ b/fpga/lib/pcie/example/VCU1525/fpga/rtl/sync_reset.v @@ -0,0 +1,56 @@ +/* + +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 active-high asynchronous reset signal to a given clock by + * using a pipeline of N registers. + */ +module sync_reset #( + parameter N=2 // depth of synchronizer +)( + input wire clk, + input wire rst, + output wire sync_reset_out +); + +reg [N-1:0] sync_reg = {N{1'b1}}; + +assign sync_reset_out = sync_reg[N-1]; + +always @(posedge clk or posedge rst) begin + if (rst) + sync_reg <= {N{1'b1}}; + else + sync_reg <= {sync_reg[N-2:0], 1'b0}; +end + +endmodule + +`resetall diff --git a/fpga/lib/pcie/example/VCU1525/fpga/rtl/sync_signal.v b/fpga/lib/pcie/example/VCU1525/fpga/rtl/sync_signal.v new file mode 100644 index 000000000..74b855fa1 --- /dev/null +++ b/fpga/lib/pcie/example/VCU1525/fpga/rtl/sync_signal.v @@ -0,0 +1,62 @@ +/* + +Copyright (c) 2014-2018 Alex Forencich + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +*/ + +// Language: Verilog-2001 + +`resetall +`timescale 1 ns / 1 ps +`default_nettype none + +/* + * Synchronizes an asyncronous signal to a given clock by using a pipeline of + * two registers. + */ +module sync_signal #( + parameter WIDTH=1, // width of the input and output signals + parameter N=2 // depth of synchronizer +)( + input wire clk, + input wire [WIDTH-1:0] in, + output wire [WIDTH-1:0] out +); + +reg [WIDTH-1:0] sync_reg[N-1:0]; + +/* + * The synchronized output is the last register in the pipeline. + */ +assign out = sync_reg[N-1]; + +integer k; + +always @(posedge clk) begin + sync_reg[0] <= in; + for (k = 1; k < N; k = k + 1) begin + sync_reg[k] <= sync_reg[k-1]; + end +end + +endmodule + +`resetall diff --git a/fpga/lib/pcie/example/VCU1525/fpga/tb/fpga_core/Makefile b/fpga/lib/pcie/example/VCU1525/fpga/tb/fpga_core/Makefile new file mode 100644 index 000000000..7c85b6e54 --- /dev/null +++ b/fpga/lib/pcie/example/VCU1525/fpga/tb/fpga_core/Makefile @@ -0,0 +1,123 @@ +# Copyright (c) 2020 Alex Forencich +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +TOPLEVEL_LANG = verilog + +SIM ?= icarus +WAVES ?= 0 + +COCOTB_HDL_TIMEUNIT = 1ns +COCOTB_HDL_TIMEPRECISION = 1ps + +DUT = fpga_core +TOPLEVEL = $(DUT) +MODULE = test_$(DUT) +VERILOG_SOURCES += ../../rtl/$(DUT).v +VERILOG_SOURCES += ../../rtl/common/example_core_pcie_us.v +VERILOG_SOURCES += ../../rtl/common/example_core_pcie.v +VERILOG_SOURCES += ../../rtl/common/example_core.v +VERILOG_SOURCES += ../../rtl/common/axi_ram.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_if.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_if_rc.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_if_rq.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_if_cq.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_if_cc.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_cfg.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_msi.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_axil_master.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_axi_master.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_axi_master_rd.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_axi_master_wr.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_tlp_demux_bar.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_tlp_demux.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_tlp_mux.v +VERILOG_SOURCES += ../../lib/pcie/rtl/dma_if_pcie.v +VERILOG_SOURCES += ../../lib/pcie/rtl/dma_if_pcie_rd.v +VERILOG_SOURCES += ../../lib/pcie/rtl/dma_if_pcie_wr.v +VERILOG_SOURCES += ../../lib/pcie/rtl/dma_psdpram.v +VERILOG_SOURCES += ../../lib/pcie/rtl/arbiter.v +VERILOG_SOURCES += ../../lib/pcie/rtl/priority_encoder.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pulse_merge.v + +# module parameters +export PARAM_AXIS_PCIE_DATA_WIDTH ?= 512 +export PARAM_AXIS_PCIE_KEEP_WIDTH ?= $(shell expr $(PARAM_AXIS_PCIE_DATA_WIDTH) / 32 ) +export PARAM_AXIS_PCIE_RQ_USER_WIDTH ?= $(if $(filter-out 512,$(PARAM_AXIS_PCIE_DATA_WIDTH)),62,137) +export PARAM_AXIS_PCIE_RC_USER_WIDTH ?= $(if $(filter-out 512,$(PARAM_AXIS_PCIE_DATA_WIDTH)),75,161) +export PARAM_AXIS_PCIE_CQ_USER_WIDTH ?= $(if $(filter-out 512,$(PARAM_AXIS_PCIE_DATA_WIDTH)),88,183) +export PARAM_AXIS_PCIE_CC_USER_WIDTH ?= $(if $(filter-out 512,$(PARAM_AXIS_PCIE_DATA_WIDTH)),33,81) +export PARAM_RQ_SEQ_NUM_WIDTH ?= 6 +export PARAM_RQ_SEQ_NUM_ENABLE ?= 1 +export PARAM_PCIE_TAG_COUNT ?= 64 +export PARAM_BAR0_APERTURE ?= 24 +export PARAM_BAR2_APERTURE ?= 24 + +ifeq ($(SIM), icarus) + PLUSARGS += -fst + + COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_DATA_WIDTH=$(PARAM_AXIS_PCIE_DATA_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_KEEP_WIDTH=$(PARAM_AXIS_PCIE_KEEP_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_RQ_USER_WIDTH=$(PARAM_AXIS_PCIE_RQ_USER_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_RC_USER_WIDTH=$(PARAM_AXIS_PCIE_RC_USER_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_CQ_USER_WIDTH=$(PARAM_AXIS_PCIE_CQ_USER_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_CC_USER_WIDTH=$(PARAM_AXIS_PCIE_CC_USER_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).RQ_SEQ_NUM_WIDTH=$(PARAM_RQ_SEQ_NUM_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).RQ_SEQ_NUM_ENABLE=$(PARAM_RQ_SEQ_NUM_ENABLE) + COMPILE_ARGS += -P $(TOPLEVEL).PCIE_TAG_COUNT=$(PARAM_PCIE_TAG_COUNT) + COMPILE_ARGS += -P $(TOPLEVEL).BAR0_APERTURE=$(PARAM_BAR0_APERTURE) + COMPILE_ARGS += -P $(TOPLEVEL).BAR2_APERTURE=$(PARAM_BAR2_APERTURE) + + ifeq ($(WAVES), 1) + VERILOG_SOURCES += iverilog_dump.v + COMPILE_ARGS += -s iverilog_dump + endif +else ifeq ($(SIM), verilator) + COMPILE_ARGS += -Wno-SELRANGE -Wno-WIDTH + + COMPILE_ARGS += -GAXIS_PCIE_DATA_WIDTH=$(PARAM_AXIS_PCIE_DATA_WIDTH) + COMPILE_ARGS += -GAXIS_PCIE_KEEP_WIDTH=$(PARAM_AXIS_PCIE_KEEP_WIDTH) + COMPILE_ARGS += -GAXIS_PCIE_RQ_USER_WIDTH=$(PARAM_AXIS_PCIE_RQ_USER_WIDTH) + COMPILE_ARGS += -GAXIS_PCIE_RC_USER_WIDTH=$(PARAM_AXIS_PCIE_RC_USER_WIDTH) + COMPILE_ARGS += -GAXIS_PCIE_CQ_USER_WIDTH=$(PARAM_AXIS_PCIE_CQ_USER_WIDTH) + COMPILE_ARGS += -GAXIS_PCIE_CC_USER_WIDTH=$(PARAM_AXIS_PCIE_CC_USER_WIDTH) + COMPILE_ARGS += -GRQ_SEQ_NUM_WIDTH=$(PARAM_RQ_SEQ_NUM_WIDTH) + COMPILE_ARGS += -GRQ_SEQ_NUM_ENABLE=$(PARAM_RQ_SEQ_NUM_ENABLE) + COMPILE_ARGS += -GPCIE_TAG_COUNT=$(PARAM_PCIE_TAG_COUNT) + COMPILE_ARGS += -GBAR0_APERTURE=$(PARAM_BAR0_APERTURE) + COMPILE_ARGS += -GBAR2_APERTURE=$(PARAM_BAR2_APERTURE) + + ifeq ($(WAVES), 1) + COMPILE_ARGS += --trace-fst + endif +endif + +include $(shell cocotb-config --makefiles)/Makefile.sim + +iverilog_dump.v: + echo 'module iverilog_dump();' > $@ + echo 'initial begin' >> $@ + echo ' $$dumpfile("$(TOPLEVEL).fst");' >> $@ + echo ' $$dumpvars(0, $(TOPLEVEL));' >> $@ + echo 'end' >> $@ + echo 'endmodule' >> $@ + +clean:: + @rm -rf iverilog_dump.v + @rm -rf dump.fst $(TOPLEVEL).fst diff --git a/fpga/lib/pcie/example/VCU1525/fpga/tb/fpga_core/test_fpga_core.py b/fpga/lib/pcie/example/VCU1525/fpga/tb/fpga_core/test_fpga_core.py new file mode 100644 index 000000000..429f0383f --- /dev/null +++ b/fpga/lib/pcie/example/VCU1525/fpga/tb/fpga_core/test_fpga_core.py @@ -0,0 +1,474 @@ +""" + +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 + +import cocotb_test.simulator + +import cocotb +from cocotb.log import SimLog +from cocotb.triggers import RisingEdge, FallingEdge, Timer + +from cocotbext.axi import AxiStreamBus +from cocotbext.pcie.core import RootComplex +from cocotbext.pcie.xilinx.us import UltraScalePlusPcieDevice + + +class TB(object): + def __init__(self, dut): + self.dut = dut + + self.log = SimLog("cocotb.tb") + self.log.setLevel(logging.DEBUG) + + # PCIe + self.rc = RootComplex() + + self.dev = UltraScalePlusPcieDevice( + # configuration options + pcie_generation=3, + pcie_link_width=16, + user_clk_frequency=250e6, + alignment="dword", + cq_cc_straddle=False, + rq_rc_straddle=False, + rc_4tlp_straddle=False, + enable_pf1=False, + enable_client_tag=True, + enable_extended_tag=True, + enable_parity=False, + enable_rx_msg_interface=False, + enable_sriov=False, + enable_extended_configuration=False, + + enable_pf0_msi=True, + enable_pf1_msi=False, + + # signals + # Clock and Reset Interface + user_clk=dut.clk, + user_reset=dut.rst, + # user_lnk_up + # sys_clk + # sys_clk_gt + # sys_reset + # phy_rdy_out + + # Requester reQuest Interface + rq_bus=AxiStreamBus.from_prefix(dut, "m_axis_rq"), + pcie_rq_seq_num0=dut.s_axis_rq_seq_num_0, + pcie_rq_seq_num_vld0=dut.s_axis_rq_seq_num_valid_0, + pcie_rq_seq_num1=dut.s_axis_rq_seq_num_1, + pcie_rq_seq_num_vld1=dut.s_axis_rq_seq_num_valid_1, + # pcie_rq_tag0 + # pcie_rq_tag1 + # pcie_rq_tag_av + # pcie_rq_tag_vld0 + # pcie_rq_tag_vld1 + + # Requester Completion Interface + rc_bus=AxiStreamBus.from_prefix(dut, "s_axis_rc"), + + # Completer reQuest Interface + cq_bus=AxiStreamBus.from_prefix(dut, "s_axis_cq"), + # pcie_cq_np_req + # pcie_cq_np_req_count + + # Completer Completion Interface + cc_bus=AxiStreamBus.from_prefix(dut, "m_axis_cc"), + + # Transmit Flow Control Interface + # pcie_tfc_nph_av=dut.pcie_tfc_nph_av, + # pcie_tfc_npd_av=dut.pcie_tfc_npd_av, + + # Configuration Management Interface + cfg_mgmt_addr=dut.cfg_mgmt_addr, + cfg_mgmt_function_number=dut.cfg_mgmt_function_number, + cfg_mgmt_write=dut.cfg_mgmt_write, + cfg_mgmt_write_data=dut.cfg_mgmt_write_data, + cfg_mgmt_byte_enable=dut.cfg_mgmt_byte_enable, + cfg_mgmt_read=dut.cfg_mgmt_read, + cfg_mgmt_read_data=dut.cfg_mgmt_read_data, + cfg_mgmt_read_write_done=dut.cfg_mgmt_read_write_done, + # cfg_mgmt_debug_access + + # Configuration Status Interface + # cfg_phy_link_down + # cfg_phy_link_status + # cfg_negotiated_width + # cfg_current_speed + cfg_max_payload=dut.cfg_max_payload, + cfg_max_read_req=dut.cfg_max_read_req, + # cfg_function_status + # cfg_vf_status + # cfg_function_power_state + # cfg_vf_power_state + # cfg_link_power_state + # cfg_err_cor_out + # cfg_err_nonfatal_out + # cfg_err_fatal_out + # cfg_local_error_out + # cfg_local_error_valid + # cfg_rx_pm_state + # cfg_tx_pm_state + # cfg_ltssm_state + # cfg_rcb_status + # cfg_obff_enable + # cfg_pl_status_change + # cfg_tph_requester_enable + # cfg_tph_st_mode + # cfg_vf_tph_requester_enable + # cfg_vf_tph_st_mode + + # Configuration Received Message Interface + # cfg_msg_received + # cfg_msg_received_data + # cfg_msg_received_type + + # Configuration Transmit Message Interface + # cfg_msg_transmit + # cfg_msg_transmit_type + # cfg_msg_transmit_data + # cfg_msg_transmit_done + + # Configuration Flow Control Interface + cfg_fc_ph=dut.cfg_fc_ph, + cfg_fc_pd=dut.cfg_fc_pd, + cfg_fc_nph=dut.cfg_fc_nph, + cfg_fc_npd=dut.cfg_fc_npd, + cfg_fc_cplh=dut.cfg_fc_cplh, + cfg_fc_cpld=dut.cfg_fc_cpld, + cfg_fc_sel=dut.cfg_fc_sel, + + # Configuration Control Interface + # cfg_hot_reset_in + # cfg_hot_reset_out + # cfg_config_space_enable + # cfg_dsn + # cfg_bus_number + # cfg_ds_port_number + # cfg_ds_bus_number + # cfg_ds_device_number + # cfg_ds_function_number + # cfg_power_state_change_ack + # cfg_power_state_change_interrupt + cfg_err_cor_in=dut.status_error_cor, + cfg_err_uncor_in=dut.status_error_uncor, + # cfg_flr_in_process + # cfg_flr_done + # cfg_vf_flr_in_process + # cfg_vf_flr_func_num + # cfg_vf_flr_done + # cfg_pm_aspm_l1_entry_reject + # cfg_pm_aspm_tx_l0s_entry_disable + # cfg_req_pm_transition_l23_ready + # cfg_link_training_enable + + # Configuration Interrupt Controller Interface + # cfg_interrupt_int + # cfg_interrupt_sent + # cfg_interrupt_pending + cfg_interrupt_msi_enable=dut.cfg_interrupt_msi_enable, + cfg_interrupt_msi_mmenable=dut.cfg_interrupt_msi_mmenable, + cfg_interrupt_msi_mask_update=dut.cfg_interrupt_msi_mask_update, + cfg_interrupt_msi_data=dut.cfg_interrupt_msi_data, + # cfg_interrupt_msi_select=dut.cfg_interrupt_msi_select, + cfg_interrupt_msi_int=dut.cfg_interrupt_msi_int, + cfg_interrupt_msi_pending_status=dut.cfg_interrupt_msi_pending_status, + cfg_interrupt_msi_pending_status_data_enable=dut.cfg_interrupt_msi_pending_status_data_enable, + # cfg_interrupt_msi_pending_status_function_num=dut.cfg_interrupt_msi_pending_status_function_num, + cfg_interrupt_msi_sent=dut.cfg_interrupt_msi_sent, + cfg_interrupt_msi_fail=dut.cfg_interrupt_msi_fail, + # cfg_interrupt_msix_enable + # cfg_interrupt_msix_mask + # cfg_interrupt_msix_vf_enable + # cfg_interrupt_msix_vf_mask + # cfg_interrupt_msix_address + # cfg_interrupt_msix_data + # cfg_interrupt_msix_int + # cfg_interrupt_msix_vec_pending + # cfg_interrupt_msix_vec_pending_status + cfg_interrupt_msi_attr=dut.cfg_interrupt_msi_attr, + cfg_interrupt_msi_tph_present=dut.cfg_interrupt_msi_tph_present, + cfg_interrupt_msi_tph_type=dut.cfg_interrupt_msi_tph_type, + # cfg_interrupt_msi_tph_st_tag=dut.cfg_interrupt_msi_tph_st_tag, + # cfg_interrupt_msi_function_number=dut.cfg_interrupt_msi_function_number, + + # Configuration Extend Interface + # cfg_ext_read_received + # cfg_ext_write_received + # cfg_ext_register_number + # cfg_ext_function_number + # cfg_ext_write_data + # cfg_ext_write_byte_enable + # cfg_ext_read_data + # cfg_ext_read_data_valid + ) + + # self.dev.log.setLevel(logging.DEBUG) + + self.rc.make_port().connect(self.dev) + + self.dev.functions[0].msi_multiple_message_capable = 5 + + self.dev.functions[0].configure_bar(0, 2**len(dut.example_core_pcie_us_inst.core_pcie_inst.axil_ctrl_awaddr)) + self.dev.functions[0].configure_bar(2, 2**len(dut.example_core_pcie_us_inst.core_pcie_inst.axi_ram_awaddr)) + + dut.sw.setimmediatevalue(0) + + async def init(self): + + await FallingEdge(self.dut.rst) + await Timer(100, 'ns') + + await self.rc.enumerate(enable_bus_mastering=True, configure_msi=True) + + +@cocotb.test() +async def run_test(dut): + + tb = TB(dut) + + await tb.init() + + mem = tb.rc.mem_pool.alloc_region(16*1024*1024) + mem_base = mem.get_absolute_address(0) + + dev_pf0_bar0 = tb.rc.tree[0][0].bar_window[0] + dev_pf0_bar2 = tb.rc.tree[0][0].bar_window[2] + + tb.log.info("Test memory write to BAR 2") + + test_data = b'\x11\x22\x33\x44' + await dev_pf0_bar2.write(0, test_data) + + await Timer(100, 'ns') + + tb.log.info("Test memory read from BAR 2") + + val = await dev_pf0_bar2.read(0, len(test_data), timeout=1000) + tb.log.info("Read data: %s", val) + assert val == test_data + + tb.log.info("Test DMA") + + # write packet data + mem[0:1024] = bytearray([x % 256 for x in range(1024)]) + + # enable DMA + await dev_pf0_bar0.write_dword(0x000000, 1) + + # write pcie read descriptor + await dev_pf0_bar0.write_dword(0x000100, (mem_base+0x0000) & 0xffffffff) + await dev_pf0_bar0.write_dword(0x000104, (mem_base+0x0000 >> 32) & 0xffffffff) + await dev_pf0_bar0.write_dword(0x000108, 0x100) + await dev_pf0_bar0.write_dword(0x000110, 0x400) + await dev_pf0_bar0.write_dword(0x000114, 0xAA) + + await Timer(2000, 'ns') + + # read status + val = await dev_pf0_bar0.read_dword(0x000118) + tb.log.info("Status: 0x%x", val) + assert val == 0x800000AA + + # write pcie write descriptor + await dev_pf0_bar0.write_dword(0x000200, (mem_base+0x1000) & 0xffffffff) + await dev_pf0_bar0.write_dword(0x000204, (mem_base+0x1000 >> 32) & 0xffffffff) + await dev_pf0_bar0.write_dword(0x000208, 0x100) + await dev_pf0_bar0.write_dword(0x000210, 0x400) + await dev_pf0_bar0.write_dword(0x000214, 0x55) + + await Timer(2000, 'ns') + + # read status + val = await dev_pf0_bar0.read_dword(0x000218) + tb.log.info("Status: 0x%x", val) + assert val == 0x80000055 + + tb.log.info("%s", mem.hexdump_str(0x1000, 64)) + + assert mem[0:1024] == mem[0x1000:0x1000+1024] + + tb.log.info("Test DMA block operations") + + # write packet data + mem[0:1024] = bytearray([x % 256 for x in range(1024)]) + + # enable DMA + await dev_pf0_bar0.write_dword(0x000000, 1) + # disable interrupts + await dev_pf0_bar0.write_dword(0x000008, 0) + + # configure operation (read) + # DMA base address + await dev_pf0_bar0.write_dword(0x001080, (mem_base+0x0000) & 0xffffffff) + await dev_pf0_bar0.write_dword(0x001084, (mem_base+0x0000 >> 32) & 0xffffffff) + # DMA offset address + await dev_pf0_bar0.write_dword(0x001088, 0) + await dev_pf0_bar0.write_dword(0x00108c, 0) + # DMA offset mask + await dev_pf0_bar0.write_dword(0x001090, 0x000003ff) + await dev_pf0_bar0.write_dword(0x001094, 0) + # DMA stride + await dev_pf0_bar0.write_dword(0x001098, 256) + await dev_pf0_bar0.write_dword(0x00109c, 0) + # RAM base address + await dev_pf0_bar0.write_dword(0x0010c0, 0) + await dev_pf0_bar0.write_dword(0x0010c4, 0) + # RAM offset address + await dev_pf0_bar0.write_dword(0x0010c8, 0) + await dev_pf0_bar0.write_dword(0x0010cc, 0) + # RAM offset mask + await dev_pf0_bar0.write_dword(0x0010d0, 0x000003ff) + await dev_pf0_bar0.write_dword(0x0010d4, 0) + # RAM stride + await dev_pf0_bar0.write_dword(0x0010d8, 256) + await dev_pf0_bar0.write_dword(0x0010dc, 0) + # clear cycle count + await dev_pf0_bar0.write_dword(0x001008, 0) + await dev_pf0_bar0.write_dword(0x00100c, 0) + # block length + await dev_pf0_bar0.write_dword(0x001010, 256) + # block count + await dev_pf0_bar0.write_dword(0x001018, 32) + await dev_pf0_bar0.write_dword(0x00101c, 0) + # start + await dev_pf0_bar0.write_dword(0x001000, 1) + + await Timer(2000, 'ns') + + # configure operation (write) + # DMA base address + await dev_pf0_bar0.write_dword(0x001180, (mem_base+0x0000) & 0xffffffff) + await dev_pf0_bar0.write_dword(0x001184, (mem_base+0x0000 >> 32) & 0xffffffff) + # DMA offset address + await dev_pf0_bar0.write_dword(0x001188, 0) + await dev_pf0_bar0.write_dword(0x00118c, 0) + # DMA offset mask + await dev_pf0_bar0.write_dword(0x001190, 0x000003ff) + await dev_pf0_bar0.write_dword(0x001194, 0) + # DMA stride + await dev_pf0_bar0.write_dword(0x001198, 256) + await dev_pf0_bar0.write_dword(0x00119c, 0) + # RAM base address + await dev_pf0_bar0.write_dword(0x0011c0, 0) + await dev_pf0_bar0.write_dword(0x0011c4, 0) + # RAM offset address + await dev_pf0_bar0.write_dword(0x0011c8, 0) + await dev_pf0_bar0.write_dword(0x0011cc, 0) + # RAM offset mask + await dev_pf0_bar0.write_dword(0x0011d0, 0x000003ff) + await dev_pf0_bar0.write_dword(0x0011d4, 0) + # RAM stride + await dev_pf0_bar0.write_dword(0x0011d8, 256) + await dev_pf0_bar0.write_dword(0x0011dc, 0) + # clear cycle count + await dev_pf0_bar0.write_dword(0x001108, 0) + await dev_pf0_bar0.write_dword(0x00110c, 0) + # block length + await dev_pf0_bar0.write_dword(0x001110, 256) + # block count + await dev_pf0_bar0.write_dword(0x001118, 32) + await dev_pf0_bar0.write_dword(0x00111c, 0) + # start + await dev_pf0_bar0.write_dword(0x001100, 1) + + await Timer(2000, 'ns') + + await RisingEdge(dut.clk) + await RisingEdge(dut.clk) + + +# cocotb-test + +tests_dir = 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')) +pcie_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'pcie', '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(rtl_dir, "common", "example_core_pcie_us.v"), + os.path.join(rtl_dir, "common", "example_core_pcie.v"), + os.path.join(rtl_dir, "common", "example_core.v"), + os.path.join(rtl_dir, "common", "axi_ram.v"), + os.path.join(pcie_rtl_dir, "pcie_us_if.v"), + os.path.join(pcie_rtl_dir, "pcie_us_if_rc.v"), + os.path.join(pcie_rtl_dir, "pcie_us_if_rq.v"), + os.path.join(pcie_rtl_dir, "pcie_us_if_cq.v"), + os.path.join(pcie_rtl_dir, "pcie_us_if_cc.v"), + os.path.join(pcie_rtl_dir, "pcie_us_cfg.v"), + os.path.join(pcie_rtl_dir, "pcie_us_msi.v"), + os.path.join(pcie_rtl_dir, "pcie_axil_master.v"), + os.path.join(pcie_rtl_dir, "pcie_axi_master.v"), + os.path.join(pcie_rtl_dir, "pcie_axi_master_rd.v"), + os.path.join(pcie_rtl_dir, "pcie_axi_master_wr.v"), + os.path.join(pcie_rtl_dir, "pcie_tlp_demux_bar.v"), + os.path.join(pcie_rtl_dir, "pcie_tlp_demux.v"), + os.path.join(pcie_rtl_dir, "pcie_tlp_mux.v"), + os.path.join(pcie_rtl_dir, "dma_if_pcie.v"), + os.path.join(pcie_rtl_dir, "dma_if_pcie_rd.v"), + os.path.join(pcie_rtl_dir, "dma_if_pcie_wr.v"), + os.path.join(pcie_rtl_dir, "dma_psdpram.v"), + os.path.join(pcie_rtl_dir, "arbiter.v"), + os.path.join(pcie_rtl_dir, "priority_encoder.v"), + os.path.join(pcie_rtl_dir, "pulse_merge.v"), + ] + + parameters = {} + + parameters['AXIS_PCIE_DATA_WIDTH'] = 512 + parameters['AXIS_PCIE_KEEP_WIDTH'] = parameters['AXIS_PCIE_DATA_WIDTH'] // 32 + parameters['AXIS_PCIE_RQ_USER_WIDTH'] = 62 if parameters['AXIS_PCIE_DATA_WIDTH'] < 512 else 137 + parameters['AXIS_PCIE_RC_USER_WIDTH'] = 75 if parameters['AXIS_PCIE_DATA_WIDTH'] < 512 else 161 + parameters['AXIS_PCIE_CQ_USER_WIDTH'] = 88 if parameters['AXIS_PCIE_DATA_WIDTH'] < 512 else 183 + parameters['AXIS_PCIE_CC_USER_WIDTH'] = 33 if parameters['AXIS_PCIE_DATA_WIDTH'] < 512 else 81 + parameters['RQ_SEQ_NUM_WIDTH'] = 6 + parameters['RQ_SEQ_NUM_ENABLE'] = 1 + parameters['PCIE_TAG_COUNT'] = 64 + parameters['BAR0_APERTURE'] = 24 + parameters['BAR2_APERTURE'] = 24 + + 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, + ) diff --git a/fpga/lib/pcie/example/ZCU106/fpga/README.md b/fpga/lib/pcie/example/ZCU106/fpga/README.md new file mode 100644 index 000000000..1b4ee2900 --- /dev/null +++ b/fpga/lib/pcie/example/ZCU106/fpga/README.md @@ -0,0 +1,19 @@ +# Verilog PCIe ZCU106 Example Design + +## Introduction + +This example design targets the Xilinx ZCU106 FPGA board. + +The design implements the PCIe AXI lite master module, the PCIe AXI master module, and the PCIe DMA module. A very simple Linux driver is included to test the FPGA design. + +* FPGA: xczu7ev-ffvc1156-2-e + +## How to build + +Run `make` to build. Ensure that the Xilinx Vivado components are in PATH. + +Run `make` to build the driver. Ensure the headers for the running kernel are installed, otherwise the driver cannot be compiled. + +## How to test + +Run `make program` to program the ZCU106 board with Vivado. Then load the driver with `insmod example.ko`. Check dmesg for the output. diff --git a/fpga/lib/pcie/example/ZCU106/fpga/common/vivado.mk b/fpga/lib/pcie/example/ZCU106/fpga/common/vivado.mk new file mode 100644 index 000000000..d47a43947 --- /dev/null +++ b/fpga/lib/pcie/example/ZCU106/fpga/common/vivado.mk @@ -0,0 +1,126 @@ +################################################################### +# +# 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) + +SYN_FILES_REL = $(patsubst %, ../%, $(filter-out /% ./%,$(SYN_FILES))) $(filter /% ./%,$(SYN_FILES)) +INC_FILES_REL = $(patsubst %, ../%, $(filter-out /% ./%,$(INC_FILES))) $(filter /% ./%,$(INC_FILES)) +XCI_FILES_REL = $(patsubst %, ../%, $(filter-out /% ./%,$(XCI_FILES))) $(filter /% ./%,$(XCI_FILES)) +IP_TCL_FILES_REL = $(patsubst %, ../%, $(filter-out /% ./%,$(IP_TCL_FILES))) $(filter /% ./%,$(IP_TCL_FILES)) +CONFIG_TCL_FILES_REL = $(patsubst %, ../%, $(filter-out /% ./%,$(CONFIG_TCL_FILES))) $(filter /% ./%,$(CONFIG_TCL_FILES)) + +ifdef XDC_FILES + XDC_FILES_REL = $(patsubst %, ../%, $(filter-out /% ./%,$(XDC_FILES))) $(filter /% ./%,$(XDC_FILES)) +else + XDC_FILES_REL = $(FPGA_TOP).xdc +endif + +################################################################### +# Main Targets +# +# all: build everything +# clean: remove output files and project files +################################################################### + +all: fpga + +fpga: $(FPGA_TOP).bit + +vivado: $(FPGA_TOP).xpr + vivado $(FPGA_TOP).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 program.tcl generate_mcs.tcl *.mcs *.prm flash.tcl + +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) $(FPGA_TOP)" > $@ + echo "add_files -fileset sources_1 defines.v $(SYN_FILES_REL)" >> $@ + 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) + echo "open_project -quiet $(FPGA_TOP).xpr" > $@ + for x in $(CONFIG_TCL_FILES_REL); do echo "source $$x" >> $@; done + +$(FPGA_TOP).xpr: create_project.tcl update_config.tcl + vivado -nojournal -nolog -mode batch $(foreach x,$?,-source $x) + +# synthesis run +%.runs/synth_1/%.dcp: %.xpr $(SYN_FILES_REL) $(INC_FILES_REL) $(XDC_FILES_REL) $(CONFIG_TCL_FILES_REL) + echo "open_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 +%.runs/impl_1/%_routed.dcp: %.runs/synth_1/%.dcp + echo "open_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 + vivado -nojournal -nolog -mode batch -source run_impl.tcl + +# bit file +%.bit: %.runs/impl_1/%_routed.dcp + echo "open_project $*.xpr" > generate_bit.tcl + echo "open_run impl_1" >> generate_bit.tcl + echo "write_bitstream -force $*.bit" >> generate_bit.tcl + vivado -nojournal -nolog -mode batch -source generate_bit.tcl + mkdir -p rev + EXT=bit; COUNT=100; \ + while [ -e rev/$*_rev$$COUNT.$$EXT ]; \ + do COUNT=$$((COUNT+1)); done; \ + cp $@ rev/$*_rev$$COUNT.$$EXT; \ + echo "Output: rev/$*_rev$$COUNT.$$EXT"; diff --git a/fpga/lib/pcie/example/ZCU106/fpga/driver b/fpga/lib/pcie/example/ZCU106/fpga/driver new file mode 120000 index 000000000..4a54c76b5 --- /dev/null +++ b/fpga/lib/pcie/example/ZCU106/fpga/driver @@ -0,0 +1 @@ +../../common/driver/example/ \ No newline at end of file diff --git a/fpga/lib/pcie/example/ZCU106/fpga/fpga.xdc b/fpga/lib/pcie/example/ZCU106/fpga/fpga.xdc new file mode 100644 index 000000000..f7ca49685 --- /dev/null +++ b/fpga/lib/pcie/example/ZCU106/fpga/fpga.xdc @@ -0,0 +1,128 @@ +# XDC constraints for the Xilinx ZCU106 board +# part: xczu7ev-ffvc1156-2-e + +# General configuration +set_property BITSTREAM.GENERAL.COMPRESS true [current_design] + +# System clocks +# 125 MHz +#set_property -dict {LOC H9 IOSTANDARD LVDS} [get_ports clk_125mhz_p] +#set_property -dict {LOC G9 IOSTANDARD LVDS} [get_ports clk_125mhz_n] +#create_clock -period 8.000 -name clk_125mhz [get_ports clk_125mhz_p] + +# LEDs +set_property -dict {LOC AL11 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {led[0]}] +set_property -dict {LOC AL13 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {led[1]}] +set_property -dict {LOC AK13 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {led[2]}] +set_property -dict {LOC AE15 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {led[3]}] +set_property -dict {LOC AM8 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {led[4]}] +set_property -dict {LOC AM9 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {led[5]}] +set_property -dict {LOC AM10 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {led[6]}] +set_property -dict {LOC AM11 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {led[7]}] + +set_false_path -to [get_ports {led[*]}] +set_output_delay 0 [get_ports {led[*]}] + +# Reset button +#set_property -dict {LOC G13 IOSTANDARD LVCMOS12} [get_ports reset] + +#set_false_path -from [get_ports {reset}] +#set_input_delay 0 [get_ports {reset}] + +# Push buttons +set_property -dict {LOC AG13 IOSTANDARD LVCMOS12} [get_ports btnu] +set_property -dict {LOC AK12 IOSTANDARD LVCMOS12} [get_ports btnl] +set_property -dict {LOC AP20 IOSTANDARD LVCMOS12} [get_ports btnd] +set_property -dict {LOC AC14 IOSTANDARD LVCMOS12} [get_ports btnr] +set_property -dict {LOC AL10 IOSTANDARD LVCMOS12} [get_ports btnc] + +set_false_path -from [get_ports {btnu btnl btnd btnr btnc}] +set_input_delay 0 [get_ports {btnu btnl btnd btnr btnc}] + +# DIP switches +set_property -dict {LOC A17 IOSTANDARD LVCMOS18} [get_ports {sw[0]}] +set_property -dict {LOC A16 IOSTANDARD LVCMOS18} [get_ports {sw[1]}] +set_property -dict {LOC B16 IOSTANDARD LVCMOS18} [get_ports {sw[2]}] +set_property -dict {LOC B15 IOSTANDARD LVCMOS18} [get_ports {sw[3]}] +set_property -dict {LOC A15 IOSTANDARD LVCMOS18} [get_ports {sw[4]}] +set_property -dict {LOC A14 IOSTANDARD LVCMOS18} [get_ports {sw[5]}] +set_property -dict {LOC B14 IOSTANDARD LVCMOS18} [get_ports {sw[6]}] +set_property -dict {LOC B13 IOSTANDARD LVCMOS18} [get_ports {sw[7]}] + +set_false_path -from [get_ports {sw[*]}] +set_input_delay 0 [get_ports {sw[*]}] + +# UART +#set_property -dict {LOC AL17 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports uart_txd] +#set_property -dict {LOC AH17 IOSTANDARD LVCMOS12} [get_ports uart_rxd] +#set_property -dict {LOC AM15 IOSTANDARD LVCMOS12} [get_ports uart_rts] +#set_property -dict {LOC AP17 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports uart_cts] + +#set_false_path -to [get_ports {uart_txd uart_cts}] +#set_output_delay 0 [get_ports {uart_txd uart_cts}] +#set_false_path -from [get_ports {uart_rxd uart_rts}] +#set_input_delay 0 [get_ports {uart_rxd uart_rts}] + +# I2C interfaces +#set_property -dict {LOC AE19 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports i2c0_scl] +#set_property -dict {LOC AH23 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports i2c0_sda] +#set_property -dict {LOC AH19 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports i2c1_scl] +#set_property -dict {LOC AL21 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports i2c1_sda] + +#set_false_path -to [get_ports {i2c1_sda i2c1_scl}] +#set_output_delay 0 [get_ports {i2c1_sda i2c1_scl}] +#set_false_path -from [get_ports {i2c1_sda i2c1_scl}] +#set_input_delay 0 [get_ports {i2c1_sda i2c1_scl}] + +# SFP+ Interface +#set_property -dict {LOC AA2 } [get_ports sfp0_rx_p] ;# MGTHRXP2_225 GTHE4_CHANNEL_X0Y10 / GTHE4_COMMON_X0Y2 +#set_property -dict {LOC AA1 } [get_ports sfp0_rx_n] ;# MGTHRXN2_225 GTHE4_CHANNEL_X0Y10 / GTHE4_COMMON_X0Y2 +#set_property -dict {LOC Y4 } [get_ports sfp0_tx_p] ;# MGTHTXP2_225 GTHE4_CHANNEL_X0Y10 / GTHE4_COMMON_X0Y2 +#set_property -dict {LOC Y3 } [get_ports sfp0_tx_n] ;# MGTHTXN2_225 GTHE4_CHANNEL_X0Y10 / GTHE4_COMMON_X0Y2 +#set_property -dict {LOC W2 } [get_ports sfp1_rx_p] ;# MGTHRXP3_225 GTHE4_CHANNEL_X0Y11 / GTHE4_COMMON_X0Y2 +#set_property -dict {LOC W1 } [get_ports sfp1_rx_n] ;# MGTHRXN3_225 GTHE4_CHANNEL_X0Y11 / GTHE4_COMMON_X0Y2 +#set_property -dict {LOC W6 } [get_ports sfp1_tx_p] ;# MGTHTXP3_225 GTHE4_CHANNEL_X0Y11 / GTHE4_COMMON_X0Y2 +#set_property -dict {LOC W5 } [get_ports sfp1_tx_n] ;# MGTHTXN3_225 GTHE4_CHANNEL_X0Y11 / GTHE4_COMMON_X0Y2 +#set_property -dict {LOC U10 } [get_ports sfp_mgt_refclk_0_p] ;# MGTREFCLK1P_226 from U56 SI570 via U51 SI53340 +#set_property -dict {LOC U9 } [get_ports sfp_mgt_refclk_0_n] ;# MGTREFCLK1N_226 from U56 SI570 via U51 SI53340 +#set_property -dict {LOC W10 } [get_ports sfp_mgt_refclk_1_p] ;# MGTREFCLK1P_225 from U20 CKOUT2 SI5328 +#set_property -dict {LOC W9 } [get_ports sfp_mgt_refclk_1_n] ;# MGTREFCLK1N_225 from U20 CKOUT2 SI5328 +#set_property -dict {LOC H11 IOSTANDARD LVDS} [get_ports sfp_recclk_p] ;# to U20 CKIN1 SI5328 +#set_property -dict {LOC G11 IOSTANDARD LVDS} [get_ports sfp_recclk_n] ;# to U20 CKIN1 SI5328 +#set_property -dict {LOC AE22 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports sfp0_tx_disable_b] +#set_property -dict {LOC AF20 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports sfp1_tx_disable_b] + +# 156.25 MHz MGT reference clock +#create_clock -period 6.400 -name sfp_mgt_refclk_0 [get_ports sfp_mgt_refclk_0_p] + +#set_false_path -to [get_ports {sfp0_tx_disable_b sfp1_tx_disable_b}] +#set_output_delay 0 [get_ports {sfp0_tx_disable_b sfp1_tx_disable_b}] + +# PCIe Interface +set_property -dict {LOC AE2 } [get_ports {pcie_rx_p[0]}] ;# MGTHRXP3_224 GTHE4_CHANNEL_X0Y7 / GTHE4_COMMON_X0Y1 +set_property -dict {LOC AE1 } [get_ports {pcie_rx_n[0]}] ;# MGTHRXN3_224 GTHE4_CHANNEL_X0Y7 / GTHE4_COMMON_X0Y1 +set_property -dict {LOC AD4 } [get_ports {pcie_tx_p[0]}] ;# MGTHTXP3_224 GTHE4_CHANNEL_X0Y7 / GTHE4_COMMON_X0Y1 +set_property -dict {LOC AD3 } [get_ports {pcie_tx_n[0]}] ;# MGTHTXN3_224 GTHE4_CHANNEL_X0Y7 / GTHE4_COMMON_X0Y1 +set_property -dict {LOC AF4 } [get_ports {pcie_rx_p[1]}] ;# MGTHRXP2_224 GTHE4_CHANNEL_X0Y6 / GTHE4_COMMON_X0Y1 +set_property -dict {LOC AF3 } [get_ports {pcie_rx_n[1]}] ;# MGTHRXN2_224 GTHE4_CHANNEL_X0Y6 / GTHE4_COMMON_X0Y1 +set_property -dict {LOC AE6 } [get_ports {pcie_tx_p[1]}] ;# MGTHTXP2_224 GTHE4_CHANNEL_X0Y6 / GTHE4_COMMON_X0Y1 +set_property -dict {LOC AE5 } [get_ports {pcie_tx_n[1]}] ;# MGTHTXN2_224 GTHE4_CHANNEL_X0Y6 / GTHE4_COMMON_X0Y1 +set_property -dict {LOC AG2 } [get_ports {pcie_rx_p[2]}] ;# MGTHRXP1_224 GTHE4_CHANNEL_X0Y5 / GTHE4_COMMON_X0Y1 +set_property -dict {LOC AG1 } [get_ports {pcie_rx_n[2]}] ;# MGTHRXN1_224 GTHE4_CHANNEL_X0Y5 / GTHE4_COMMON_X0Y1 +set_property -dict {LOC AG6 } [get_ports {pcie_tx_p[2]}] ;# MGTHTXP1_224 GTHE4_CHANNEL_X0Y5 / GTHE4_COMMON_X0Y1 +set_property -dict {LOC AG5 } [get_ports {pcie_tx_n[2]}] ;# MGTHTXN1_224 GTHE4_CHANNEL_X0Y5 / GTHE4_COMMON_X0Y1 +set_property -dict {LOC AJ2 } [get_ports {pcie_rx_p[3]}] ;# MGTHRXP0_224 GTHE4_CHANNEL_X0Y4 / GTHE4_COMMON_X0Y1 +set_property -dict {LOC AJ1 } [get_ports {pcie_rx_n[3]}] ;# MGTHRXN0_224 GTHE4_CHANNEL_X0Y4 / GTHE4_COMMON_X0Y1 +set_property -dict {LOC AH4 } [get_ports {pcie_tx_p[3]}] ;# MGTHTXP0_224 GTHE4_CHANNEL_X0Y4 / GTHE4_COMMON_X0Y1 +set_property -dict {LOC AH3 } [get_ports {pcie_tx_n[3]}] ;# MGTHTXN0_224 GTHE4_CHANNEL_X0Y4 / GTHE4_COMMON_X0Y1 +set_property -dict {LOC AB8 } [get_ports pcie_mgt_refclk_p] ;# MGTREFCLK0P_224 +set_property -dict {LOC AB7 } [get_ports pcie_mgt_refclk_n] ;# MGTREFCLK0N_224 +set_property -dict {LOC L8 IOSTANDARD LVCMOS33 PULLUP true} [get_ports pcie_reset_n] + +# 100 MHz MGT reference clock +create_clock -period 10 -name pcie_mgt_refclk [get_ports pcie_mgt_refclk_p] + +set_false_path -from [get_ports {pcie_reset_n}] +set_input_delay 0 [get_ports {pcie_reset_n}] + + diff --git a/fpga/lib/pcie/example/ZCU106/fpga/fpga/Makefile b/fpga/lib/pcie/example/ZCU106/fpga/fpga/Makefile new file mode 100644 index 000000000..1ff1c78e3 --- /dev/null +++ b/fpga/lib/pcie/example/ZCU106/fpga/fpga/Makefile @@ -0,0 +1,57 @@ + +# FPGA settings +FPGA_PART = xczu7ev-ffvc1156-2-e +FPGA_TOP = fpga +FPGA_ARCH = zynquplus + +# Files for synthesis +SYN_FILES = rtl/fpga.v +SYN_FILES += rtl/fpga_core.v +SYN_FILES += rtl/debounce_switch.v +SYN_FILES += rtl/sync_reset.v +SYN_FILES += rtl/sync_signal.v +SYN_FILES += rtl/common/example_core_pcie_us.v +SYN_FILES += rtl/common/example_core_pcie.v +SYN_FILES += rtl/common/example_core.v +SYN_FILES += rtl/common/axi_ram.v +SYN_FILES += lib/pcie/rtl/pcie_us_if.v +SYN_FILES += lib/pcie/rtl/pcie_us_if_rc.v +SYN_FILES += lib/pcie/rtl/pcie_us_if_rq.v +SYN_FILES += lib/pcie/rtl/pcie_us_if_cq.v +SYN_FILES += lib/pcie/rtl/pcie_us_if_cc.v +SYN_FILES += lib/pcie/rtl/pcie_us_cfg.v +SYN_FILES += lib/pcie/rtl/pcie_us_msi.v +SYN_FILES += lib/pcie/rtl/pcie_axil_master.v +SYN_FILES += lib/pcie/rtl/pcie_axi_master.v +SYN_FILES += lib/pcie/rtl/pcie_axi_master_rd.v +SYN_FILES += lib/pcie/rtl/pcie_axi_master_wr.v +SYN_FILES += lib/pcie/rtl/pcie_tlp_demux_bar.v +SYN_FILES += lib/pcie/rtl/pcie_tlp_demux.v +SYN_FILES += lib/pcie/rtl/pcie_tlp_mux.v +SYN_FILES += lib/pcie/rtl/dma_if_pcie.v +SYN_FILES += lib/pcie/rtl/dma_if_pcie_rd.v +SYN_FILES += lib/pcie/rtl/dma_if_pcie_wr.v +SYN_FILES += lib/pcie/rtl/dma_psdpram.v +SYN_FILES += lib/pcie/rtl/arbiter.v +SYN_FILES += lib/pcie/rtl/priority_encoder.v +SYN_FILES += lib/pcie/rtl/pulse_merge.v + +# XDC files +XDC_FILES = fpga.xdc + +# IP +IP_TCL_FILES = ip/pcie4_uscale_plus_0.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 + diff --git a/fpga/lib/pcie/example/ZCU106/fpga/ip/pcie4_uscale_plus_0.tcl b/fpga/lib/pcie/example/ZCU106/fpga/ip/pcie4_uscale_plus_0.tcl new file mode 100644 index 000000000..a0d1e8c3f --- /dev/null +++ b/fpga/lib/pcie/example/ZCU106/fpga/ip/pcie4_uscale_plus_0.tcl @@ -0,0 +1,28 @@ + +create_ip -name pcie4_uscale_plus -vendor xilinx.com -library ip -module_name pcie4_uscale_plus_0 + +set_property -dict [list \ + CONFIG.PL_LINK_CAP_MAX_LINK_SPEED {8.0_GT/s} \ + CONFIG.PL_LINK_CAP_MAX_LINK_WIDTH {X4} \ + CONFIG.AXISTEN_IF_RC_STRADDLE {false} \ + CONFIG.axisten_if_enable_client_tag {true} \ + CONFIG.axisten_if_width {128_bit} \ + CONFIG.axisten_freq {250} \ + CONFIG.PF0_CLASS_CODE {058000} \ + CONFIG.PF0_DEVICE_ID {0001} \ + CONFIG.PF0_MSI_CAP_MULTIMSGCAP {32_vectors} \ + CONFIG.PF0_SUBSYSTEM_ID {906a} \ + CONFIG.PF0_SUBSYSTEM_VENDOR_ID {10ee} \ + CONFIG.pf0_bar0_64bit {true} \ + CONFIG.pf0_bar0_prefetchable {true} \ + CONFIG.pf0_bar0_scale {Megabytes} \ + CONFIG.pf0_bar0_size {16} \ + CONFIG.pf0_bar2_64bit {true} \ + CONFIG.pf0_bar2_prefetchable {true} \ + CONFIG.pf0_bar2_enabled {true} \ + CONFIG.pf0_bar2_type {Memory} \ + CONFIG.pf0_bar2_scale {Megabytes} \ + CONFIG.pf0_bar2_size {16} \ + CONFIG.vendor_id {1234} \ + CONFIG.en_msi_per_vec_masking {true} \ +] [get_ips pcie4_uscale_plus_0] diff --git a/fpga/lib/pcie/example/ZCU106/fpga/lib/pcie b/fpga/lib/pcie/example/ZCU106/fpga/lib/pcie new file mode 120000 index 000000000..11a54ed36 --- /dev/null +++ b/fpga/lib/pcie/example/ZCU106/fpga/lib/pcie @@ -0,0 +1 @@ +../../../../ \ No newline at end of file diff --git a/fpga/lib/pcie/example/ZCU106/fpga/rtl/common b/fpga/lib/pcie/example/ZCU106/fpga/rtl/common new file mode 120000 index 000000000..e60fada70 --- /dev/null +++ b/fpga/lib/pcie/example/ZCU106/fpga/rtl/common @@ -0,0 +1 @@ +../../../common/rtl/ \ No newline at end of file diff --git a/fpga/lib/pcie/example/ZCU106/fpga/rtl/debounce_switch.v b/fpga/lib/pcie/example/ZCU106/fpga/rtl/debounce_switch.v new file mode 100644 index 000000000..8e93a50c4 --- /dev/null +++ b/fpga/lib/pcie/example/ZCU106/fpga/rtl/debounce_switch.v @@ -0,0 +1,93 @@ +/* + +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 diff --git a/fpga/lib/pcie/example/ZCU106/fpga/rtl/fpga.v b/fpga/lib/pcie/example/ZCU106/fpga/rtl/fpga.v new file mode 100644 index 000000000..01e08609a --- /dev/null +++ b/fpga/lib/pcie/example/ZCU106/fpga/rtl/fpga.v @@ -0,0 +1,483 @@ +/* + +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. + +*/ + +// Language: Verilog 2001 + +`resetall +`timescale 1ns / 1ps +`default_nettype none + +/* + * FPGA top-level module + */ +module fpga ( + /* + * GPIO + */ + input wire btnu, + input wire btnl, + input wire btnd, + input wire btnr, + input wire btnc, + input wire [7:0] sw, + output wire [7:0] led, + + /* + * PCI express + */ + input wire [3:0] pcie_rx_p, + input wire [3:0] pcie_rx_n, + output wire [3:0] pcie_tx_p, + output wire [3:0] pcie_tx_n, + input wire pcie_mgt_refclk_p, + input wire pcie_mgt_refclk_n, + input wire pcie_reset_n +); + +parameter AXIS_PCIE_DATA_WIDTH = 128; +parameter AXIS_PCIE_KEEP_WIDTH = (AXIS_PCIE_DATA_WIDTH/32); +parameter AXIS_PCIE_RC_USER_WIDTH = AXIS_PCIE_DATA_WIDTH < 512 ? 75 : 161; +parameter AXIS_PCIE_RQ_USER_WIDTH = AXIS_PCIE_DATA_WIDTH < 512 ? 60 : 137; +parameter AXIS_PCIE_CQ_USER_WIDTH = AXIS_PCIE_DATA_WIDTH < 512 ? 85 : 183; +parameter AXIS_PCIE_CC_USER_WIDTH = AXIS_PCIE_DATA_WIDTH < 512 ? 33 : 81; + +parameter RQ_SEQ_NUM_WIDTH = AXIS_PCIE_RQ_USER_WIDTH == 60 ? 4 : 6; +parameter RQ_SEQ_NUM_ENABLE = 1; + +parameter PCIE_TAG_COUNT = 64; +parameter BAR0_APERTURE = 24; +parameter BAR2_APERTURE = 24; + +// Clock and reset +wire pcie_user_clk; +wire pcie_user_reset; + +// GPIO +wire btnu_int; +wire btnl_int; +wire btnd_int; +wire btnr_int; +wire btnc_int; +wire [7:0] sw_int; + +debounce_switch #( + .WIDTH(13), + .N(4), + .RATE(250000) +) +debounce_switch_inst ( + .clk(pcie_user_clk), + .rst(pcie_user_reset), + .in({btnu, + btnl, + btnd, + btnr, + btnc, + sw}), + .out({btnu_int, + btnl_int, + btnd_int, + btnr_int, + btnc_int, + sw_int}) +); + +// PCIe +wire pcie_sys_clk; +wire pcie_sys_clk_gt; + +IBUFDS_GTE4 #( + .REFCLK_HROW_CK_SEL(2'b00) +) +ibufds_gte4_pcie_mgt_refclk_inst ( + .I (pcie_mgt_refclk_p), + .IB (pcie_mgt_refclk_n), + .CEB (1'b0), + .O (pcie_sys_clk_gt), + .ODIV2 (pcie_sys_clk) +); + +wire [AXIS_PCIE_DATA_WIDTH-1:0] axis_rq_tdata; +wire [AXIS_PCIE_KEEP_WIDTH-1:0] axis_rq_tkeep; +wire axis_rq_tlast; +wire axis_rq_tready; +wire [AXIS_PCIE_RQ_USER_WIDTH-1:0] axis_rq_tuser; +wire axis_rq_tvalid; + +wire [AXIS_PCIE_DATA_WIDTH-1:0] axis_rc_tdata; +wire [AXIS_PCIE_KEEP_WIDTH-1:0] axis_rc_tkeep; +wire axis_rc_tlast; +wire axis_rc_tready; +wire [AXIS_PCIE_RC_USER_WIDTH-1:0] axis_rc_tuser; +wire axis_rc_tvalid; + +wire [AXIS_PCIE_DATA_WIDTH-1:0] axis_cq_tdata; +wire [AXIS_PCIE_KEEP_WIDTH-1:0] axis_cq_tkeep; +wire axis_cq_tlast; +wire axis_cq_tready; +wire [AXIS_PCIE_CQ_USER_WIDTH-1:0] axis_cq_tuser; +wire axis_cq_tvalid; + +wire [AXIS_PCIE_DATA_WIDTH-1:0] axis_cc_tdata; +wire [AXIS_PCIE_KEEP_WIDTH-1:0] axis_cc_tkeep; +wire axis_cc_tlast; +wire axis_cc_tready; +wire [AXIS_PCIE_CC_USER_WIDTH-1:0] axis_cc_tuser; +wire axis_cc_tvalid; + +wire [RQ_SEQ_NUM_WIDTH-1:0] pcie_rq_seq_num0; +wire pcie_rq_seq_num_vld0; +wire [RQ_SEQ_NUM_WIDTH-1:0] pcie_rq_seq_num1; +wire pcie_rq_seq_num_vld1; + +// ila_0 rq_ila ( +// .clk(pcie_user_clk), +// .probe0(axis_rq_tdata), +// .probe1(axis_rq_tkeep), +// .probe2(axis_rq_tlast), +// .probe3(axis_rq_tready), +// .probe4(axis_rq_tuser), +// .probe5(axis_rq_tvalid) +// ); + +// ila_0 rc_ila ( +// .clk(pcie_user_clk), +// .probe0(axis_rc_tdata), +// .probe1(axis_rc_tkeep), +// .probe2(axis_rc_tlast), +// .probe3(axis_rc_tready), +// .probe4(axis_rc_tuser), +// .probe5(axis_rc_tvalid) +// ); + +wire [2:0] cfg_max_payload; +wire [2:0] cfg_max_read_req; + +wire [9:0] cfg_mgmt_addr; +wire [7:0] cfg_mgmt_function_number; +wire cfg_mgmt_write; +wire [31:0] cfg_mgmt_write_data; +wire [3:0] cfg_mgmt_byte_enable; +wire cfg_mgmt_read; +wire [31:0] cfg_mgmt_read_data; +wire cfg_mgmt_read_write_done; + +wire [7:0] cfg_fc_ph; +wire [11:0] cfg_fc_pd; +wire [7:0] cfg_fc_nph; +wire [11:0] cfg_fc_npd; +wire [7:0] cfg_fc_cplh; +wire [11:0] cfg_fc_cpld; +wire [2:0] cfg_fc_sel; + +wire [3:0] cfg_interrupt_msi_enable; +wire [11:0] cfg_interrupt_msi_mmenable; +wire cfg_interrupt_msi_mask_update; +wire [31:0] cfg_interrupt_msi_data; +wire [3:0] cfg_interrupt_msi_select; +wire [31:0] cfg_interrupt_msi_int; +wire [31:0] cfg_interrupt_msi_pending_status; +wire cfg_interrupt_msi_pending_status_data_enable; +wire [3:0] cfg_interrupt_msi_pending_status_function_num; +wire cfg_interrupt_msi_sent; +wire cfg_interrupt_msi_fail; +wire [2:0] cfg_interrupt_msi_attr; +wire cfg_interrupt_msi_tph_present; +wire [1:0] cfg_interrupt_msi_tph_type; +wire [8:0] cfg_interrupt_msi_tph_st_tag; +wire [3:0] cfg_interrupt_msi_function_number; + +wire status_error_cor; +wire status_error_uncor; + +pcie4_uscale_plus_0 +pcie4_uscale_plus_inst ( + .pci_exp_txn(pcie_tx_n), + .pci_exp_txp(pcie_tx_p), + .pci_exp_rxn(pcie_rx_n), + .pci_exp_rxp(pcie_rx_p), + .user_clk(pcie_user_clk), + .user_reset(pcie_user_reset), + .user_lnk_up(), + + .s_axis_rq_tdata(axis_rq_tdata), + .s_axis_rq_tkeep(axis_rq_tkeep), + .s_axis_rq_tlast(axis_rq_tlast), + .s_axis_rq_tready(axis_rq_tready), + .s_axis_rq_tuser(axis_rq_tuser), + .s_axis_rq_tvalid(axis_rq_tvalid), + + .m_axis_rc_tdata(axis_rc_tdata), + .m_axis_rc_tkeep(axis_rc_tkeep), + .m_axis_rc_tlast(axis_rc_tlast), + .m_axis_rc_tready(axis_rc_tready), + .m_axis_rc_tuser(axis_rc_tuser), + .m_axis_rc_tvalid(axis_rc_tvalid), + + .m_axis_cq_tdata(axis_cq_tdata), + .m_axis_cq_tkeep(axis_cq_tkeep), + .m_axis_cq_tlast(axis_cq_tlast), + .m_axis_cq_tready(axis_cq_tready), + .m_axis_cq_tuser(axis_cq_tuser), + .m_axis_cq_tvalid(axis_cq_tvalid), + + .s_axis_cc_tdata(axis_cc_tdata), + .s_axis_cc_tkeep(axis_cc_tkeep), + .s_axis_cc_tlast(axis_cc_tlast), + .s_axis_cc_tready(axis_cc_tready), + .s_axis_cc_tuser(axis_cc_tuser), + .s_axis_cc_tvalid(axis_cc_tvalid), + + .pcie_rq_seq_num0(pcie_rq_seq_num0), + .pcie_rq_seq_num_vld0(pcie_rq_seq_num_vld0), + .pcie_rq_seq_num1(pcie_rq_seq_num1), + .pcie_rq_seq_num_vld1(pcie_rq_seq_num_vld1), + .pcie_rq_tag0(), + .pcie_rq_tag1(), + .pcie_rq_tag_av(), + .pcie_rq_tag_vld0(), + .pcie_rq_tag_vld1(), + + .pcie_tfc_nph_av(), + .pcie_tfc_npd_av(), + + .pcie_cq_np_req(1'b1), + .pcie_cq_np_req_count(), + + .cfg_phy_link_down(), + .cfg_phy_link_status(), + .cfg_negotiated_width(), + .cfg_current_speed(), + .cfg_max_payload(cfg_max_payload), + .cfg_max_read_req(cfg_max_read_req), + .cfg_function_status(), + .cfg_function_power_state(), + .cfg_vf_status(), + .cfg_vf_power_state(), + .cfg_link_power_state(), + + .cfg_mgmt_addr(cfg_mgmt_addr), + .cfg_mgmt_function_number(cfg_mgmt_function_number), + .cfg_mgmt_write(cfg_mgmt_write), + .cfg_mgmt_write_data(cfg_mgmt_write_data), + .cfg_mgmt_byte_enable(cfg_mgmt_byte_enable), + .cfg_mgmt_read(cfg_mgmt_read), + .cfg_mgmt_read_data(cfg_mgmt_read_data), + .cfg_mgmt_read_write_done(cfg_mgmt_read_write_done), + .cfg_mgmt_debug_access(1'b0), + + .cfg_err_cor_out(), + .cfg_err_nonfatal_out(), + .cfg_err_fatal_out(), + .cfg_local_error_valid(), + .cfg_local_error_out(), + .cfg_ltssm_state(), + .cfg_rx_pm_state(), + .cfg_tx_pm_state(), + .cfg_rcb_status(), + .cfg_obff_enable(), + .cfg_pl_status_change(), + .cfg_tph_requester_enable(), + .cfg_tph_st_mode(), + .cfg_vf_tph_requester_enable(), + .cfg_vf_tph_st_mode(), + + .cfg_msg_received(), + .cfg_msg_received_data(), + .cfg_msg_received_type(), + .cfg_msg_transmit(1'b0), + .cfg_msg_transmit_type(3'd0), + .cfg_msg_transmit_data(32'd0), + .cfg_msg_transmit_done(), + + .cfg_fc_ph(cfg_fc_ph), + .cfg_fc_pd(cfg_fc_pd), + .cfg_fc_nph(cfg_fc_nph), + .cfg_fc_npd(cfg_fc_npd), + .cfg_fc_cplh(cfg_fc_cplh), + .cfg_fc_cpld(cfg_fc_cpld), + .cfg_fc_sel(cfg_fc_sel), + + .cfg_dsn(64'd0), + + .cfg_bus_number(), + + .cfg_power_state_change_ack(1'b1), + .cfg_power_state_change_interrupt(), + + .cfg_err_cor_in(status_error_cor), + .cfg_err_uncor_in(status_error_uncor), + .cfg_flr_in_process(), + .cfg_flr_done(4'd0), + .cfg_vf_flr_in_process(), + .cfg_vf_flr_func_num(8'd0), + .cfg_vf_flr_done(8'd0), + + .cfg_link_training_enable(1'b1), + + .cfg_interrupt_int(4'd0), + .cfg_interrupt_pending(4'd0), + .cfg_interrupt_sent(), + .cfg_interrupt_msi_enable(cfg_interrupt_msi_enable), + .cfg_interrupt_msi_mmenable(cfg_interrupt_msi_mmenable), + .cfg_interrupt_msi_mask_update(cfg_interrupt_msi_mask_update), + .cfg_interrupt_msi_data(cfg_interrupt_msi_data), + .cfg_interrupt_msi_select(cfg_interrupt_msi_select), + .cfg_interrupt_msi_int(cfg_interrupt_msi_int), + .cfg_interrupt_msi_pending_status(cfg_interrupt_msi_pending_status), + .cfg_interrupt_msi_pending_status_data_enable(cfg_interrupt_msi_pending_status_data_enable), + .cfg_interrupt_msi_pending_status_function_num(cfg_interrupt_msi_pending_status_function_num), + .cfg_interrupt_msi_sent(cfg_interrupt_msi_sent), + .cfg_interrupt_msi_fail(cfg_interrupt_msi_fail), + .cfg_interrupt_msi_attr(cfg_interrupt_msi_attr), + .cfg_interrupt_msi_tph_present(cfg_interrupt_msi_tph_present), + .cfg_interrupt_msi_tph_type(cfg_interrupt_msi_tph_type), + .cfg_interrupt_msi_tph_st_tag(cfg_interrupt_msi_tph_st_tag), + .cfg_interrupt_msi_function_number(cfg_interrupt_msi_function_number), + + .cfg_pm_aspm_l1_entry_reject(1'b0), + .cfg_pm_aspm_tx_l0s_entry_disable(1'b0), + + .cfg_hot_reset_out(), + + .cfg_config_space_enable(1'b1), + .cfg_req_pm_transition_l23_ready(1'b0), + .cfg_hot_reset_in(1'b0), + + .cfg_ds_port_number(8'd0), + .cfg_ds_bus_number(8'd0), + .cfg_ds_device_number(5'd0), + + .sys_clk(pcie_sys_clk), + .sys_clk_gt(pcie_sys_clk_gt), + .sys_reset(pcie_reset_n), + + .phy_rdy_out() +); + +fpga_core #( + .AXIS_PCIE_DATA_WIDTH(AXIS_PCIE_DATA_WIDTH), + .AXIS_PCIE_KEEP_WIDTH(AXIS_PCIE_KEEP_WIDTH), + .AXIS_PCIE_RC_USER_WIDTH(AXIS_PCIE_RC_USER_WIDTH), + .AXIS_PCIE_RQ_USER_WIDTH(AXIS_PCIE_RQ_USER_WIDTH), + .AXIS_PCIE_CQ_USER_WIDTH(AXIS_PCIE_CQ_USER_WIDTH), + .AXIS_PCIE_CC_USER_WIDTH(AXIS_PCIE_CC_USER_WIDTH) +) +core_inst ( + /* + * Clock: 250 MHz + * Synchronous reset + */ + .clk(pcie_user_clk), + .rst(pcie_user_reset), + /* + * GPIO + */ + .btnu(btnu_int), + .btnl(btnl_int), + .btnd(btnd_int), + .btnr(btnr_int), + .btnc(btnc_int), + .sw(sw_int), + .led(led), + /* + * PCIe + */ + .m_axis_rq_tdata(axis_rq_tdata), + .m_axis_rq_tkeep(axis_rq_tkeep), + .m_axis_rq_tlast(axis_rq_tlast), + .m_axis_rq_tready(axis_rq_tready), + .m_axis_rq_tuser(axis_rq_tuser), + .m_axis_rq_tvalid(axis_rq_tvalid), + + .s_axis_rc_tdata(axis_rc_tdata), + .s_axis_rc_tkeep(axis_rc_tkeep), + .s_axis_rc_tlast(axis_rc_tlast), + .s_axis_rc_tready(axis_rc_tready), + .s_axis_rc_tuser(axis_rc_tuser), + .s_axis_rc_tvalid(axis_rc_tvalid), + + .s_axis_cq_tdata(axis_cq_tdata), + .s_axis_cq_tkeep(axis_cq_tkeep), + .s_axis_cq_tlast(axis_cq_tlast), + .s_axis_cq_tready(axis_cq_tready), + .s_axis_cq_tuser(axis_cq_tuser), + .s_axis_cq_tvalid(axis_cq_tvalid), + + .m_axis_cc_tdata(axis_cc_tdata), + .m_axis_cc_tkeep(axis_cc_tkeep), + .m_axis_cc_tlast(axis_cc_tlast), + .m_axis_cc_tready(axis_cc_tready), + .m_axis_cc_tuser(axis_cc_tuser), + .m_axis_cc_tvalid(axis_cc_tvalid), + + .s_axis_rq_seq_num_0(pcie_rq_seq_num0), + .s_axis_rq_seq_num_valid_0(pcie_rq_seq_num_vld0), + .s_axis_rq_seq_num_1(pcie_rq_seq_num1), + .s_axis_rq_seq_num_valid_1(pcie_rq_seq_num_vld1), + + .cfg_max_payload(cfg_max_payload), + .cfg_max_read_req(cfg_max_read_req), + + .cfg_mgmt_addr(cfg_mgmt_addr), + .cfg_mgmt_function_number(cfg_mgmt_function_number), + .cfg_mgmt_write(cfg_mgmt_write), + .cfg_mgmt_write_data(cfg_mgmt_write_data), + .cfg_mgmt_byte_enable(cfg_mgmt_byte_enable), + .cfg_mgmt_read(cfg_mgmt_read), + .cfg_mgmt_read_data(cfg_mgmt_read_data), + .cfg_mgmt_read_write_done(cfg_mgmt_read_write_done), + + .cfg_fc_ph(cfg_fc_ph), + .cfg_fc_pd(cfg_fc_pd), + .cfg_fc_nph(cfg_fc_nph), + .cfg_fc_npd(cfg_fc_npd), + .cfg_fc_cplh(cfg_fc_cplh), + .cfg_fc_cpld(cfg_fc_cpld), + .cfg_fc_sel(cfg_fc_sel), + + .cfg_interrupt_msi_enable(cfg_interrupt_msi_enable), + .cfg_interrupt_msi_mmenable(cfg_interrupt_msi_mmenable), + .cfg_interrupt_msi_mask_update(cfg_interrupt_msi_mask_update), + .cfg_interrupt_msi_data(cfg_interrupt_msi_data), + .cfg_interrupt_msi_select(cfg_interrupt_msi_select), + .cfg_interrupt_msi_int(cfg_interrupt_msi_int), + .cfg_interrupt_msi_pending_status(cfg_interrupt_msi_pending_status), + .cfg_interrupt_msi_pending_status_data_enable(cfg_interrupt_msi_pending_status_data_enable), + .cfg_interrupt_msi_pending_status_function_num(cfg_interrupt_msi_pending_status_function_num), + .cfg_interrupt_msi_sent(cfg_interrupt_msi_sent), + .cfg_interrupt_msi_fail(cfg_interrupt_msi_fail), + .cfg_interrupt_msi_attr(cfg_interrupt_msi_attr), + .cfg_interrupt_msi_tph_present(cfg_interrupt_msi_tph_present), + .cfg_interrupt_msi_tph_type(cfg_interrupt_msi_tph_type), + .cfg_interrupt_msi_tph_st_tag(cfg_interrupt_msi_tph_st_tag), + .cfg_interrupt_msi_function_number(cfg_interrupt_msi_function_number), + + .status_error_cor(status_error_cor), + .status_error_uncor(status_error_uncor) +); + +endmodule + +`resetall diff --git a/fpga/lib/pcie/example/ZCU106/fpga/rtl/fpga_core.v b/fpga/lib/pcie/example/ZCU106/fpga/rtl/fpga_core.v new file mode 100644 index 000000000..75eef1b52 --- /dev/null +++ b/fpga/lib/pcie/example/ZCU106/fpga/rtl/fpga_core.v @@ -0,0 +1,276 @@ +/* + +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. + +*/ + +// Language: Verilog 2001 + +`resetall +`timescale 1ns / 1ps +`default_nettype none + +/* + * FPGA core logic + */ +module fpga_core # +( + parameter AXIS_PCIE_DATA_WIDTH = 128, + parameter AXIS_PCIE_KEEP_WIDTH = (AXIS_PCIE_DATA_WIDTH/32), + parameter AXIS_PCIE_RC_USER_WIDTH = AXIS_PCIE_DATA_WIDTH < 512 ? 75 : 161, + parameter AXIS_PCIE_RQ_USER_WIDTH = AXIS_PCIE_DATA_WIDTH < 512 ? 60 : 137, + parameter AXIS_PCIE_CQ_USER_WIDTH = AXIS_PCIE_DATA_WIDTH < 512 ? 85 : 183, + parameter AXIS_PCIE_CC_USER_WIDTH = AXIS_PCIE_DATA_WIDTH < 512 ? 33 : 81, + parameter RQ_SEQ_NUM_WIDTH = AXIS_PCIE_RQ_USER_WIDTH == 60 ? 4 : 6, + parameter RQ_SEQ_NUM_ENABLE = 1, + parameter PCIE_TAG_COUNT = 64, + parameter BAR0_APERTURE = 24, + parameter BAR2_APERTURE = 24 +) +( + /* + * Clock: 250 MHz + * Synchronous reset + */ + input wire clk, + input wire rst, + + /* + * GPIO + */ + input wire btnu, + input wire btnl, + input wire btnd, + input wire btnr, + input wire btnc, + input wire [7:0] sw, + output wire [7:0] led, + + /* + * PCIe + */ + output wire [AXIS_PCIE_DATA_WIDTH-1:0] m_axis_rq_tdata, + output wire [AXIS_PCIE_KEEP_WIDTH-1:0] m_axis_rq_tkeep, + output wire m_axis_rq_tlast, + input wire m_axis_rq_tready, + output wire [AXIS_PCIE_RQ_USER_WIDTH-1:0] m_axis_rq_tuser, + output wire m_axis_rq_tvalid, + + input wire [AXIS_PCIE_DATA_WIDTH-1:0] s_axis_rc_tdata, + input wire [AXIS_PCIE_KEEP_WIDTH-1:0] s_axis_rc_tkeep, + input wire s_axis_rc_tlast, + output wire s_axis_rc_tready, + input wire [AXIS_PCIE_RC_USER_WIDTH-1:0] s_axis_rc_tuser, + input wire s_axis_rc_tvalid, + + input wire [AXIS_PCIE_DATA_WIDTH-1:0] s_axis_cq_tdata, + input wire [AXIS_PCIE_KEEP_WIDTH-1:0] s_axis_cq_tkeep, + input wire s_axis_cq_tlast, + output wire s_axis_cq_tready, + input wire [AXIS_PCIE_CQ_USER_WIDTH-1:0] s_axis_cq_tuser, + input wire s_axis_cq_tvalid, + + output wire [AXIS_PCIE_DATA_WIDTH-1:0] m_axis_cc_tdata, + output wire [AXIS_PCIE_KEEP_WIDTH-1:0] m_axis_cc_tkeep, + output wire m_axis_cc_tlast, + input wire m_axis_cc_tready, + output wire [AXIS_PCIE_CC_USER_WIDTH-1:0] m_axis_cc_tuser, + output wire m_axis_cc_tvalid, + + input wire [RQ_SEQ_NUM_WIDTH-1:0] s_axis_rq_seq_num_0, + input wire s_axis_rq_seq_num_valid_0, + input wire [RQ_SEQ_NUM_WIDTH-1:0] s_axis_rq_seq_num_1, + input wire s_axis_rq_seq_num_valid_1, + + input wire [2:0] cfg_max_payload, + input wire [2:0] cfg_max_read_req, + + output wire [9:0] cfg_mgmt_addr, + output wire [7:0] cfg_mgmt_function_number, + output wire cfg_mgmt_write, + output wire [31:0] cfg_mgmt_write_data, + output wire [3:0] cfg_mgmt_byte_enable, + output wire cfg_mgmt_read, + input wire [31:0] cfg_mgmt_read_data, + input wire cfg_mgmt_read_write_done, + + input wire [7:0] cfg_fc_ph, + input wire [11:0] cfg_fc_pd, + input wire [7:0] cfg_fc_nph, + input wire [11:0] cfg_fc_npd, + input wire [7:0] cfg_fc_cplh, + input wire [11:0] cfg_fc_cpld, + output wire [2:0] cfg_fc_sel, + + input wire [3:0] cfg_interrupt_msi_enable, + input wire [11:0] cfg_interrupt_msi_mmenable, + input wire cfg_interrupt_msi_mask_update, + input wire [31:0] cfg_interrupt_msi_data, + output wire [3:0] cfg_interrupt_msi_select, + output wire [31:0] cfg_interrupt_msi_int, + output wire [31:0] cfg_interrupt_msi_pending_status, + output wire cfg_interrupt_msi_pending_status_data_enable, + output wire [3:0] cfg_interrupt_msi_pending_status_function_num, + input wire cfg_interrupt_msi_sent, + input wire cfg_interrupt_msi_fail, + output wire [2:0] cfg_interrupt_msi_attr, + output wire cfg_interrupt_msi_tph_present, + output wire [1:0] cfg_interrupt_msi_tph_type, + output wire [8:0] cfg_interrupt_msi_tph_st_tag, + output wire [3:0] cfg_interrupt_msi_function_number, + + output wire status_error_cor, + output wire status_error_uncor +); + +assign led = 8'd0; + +example_core_pcie_us #( + .AXIS_PCIE_DATA_WIDTH(AXIS_PCIE_DATA_WIDTH), + .AXIS_PCIE_KEEP_WIDTH(AXIS_PCIE_KEEP_WIDTH), + .AXIS_PCIE_RC_USER_WIDTH(AXIS_PCIE_RC_USER_WIDTH), + .AXIS_PCIE_RQ_USER_WIDTH(AXIS_PCIE_RQ_USER_WIDTH), + .AXIS_PCIE_CQ_USER_WIDTH(AXIS_PCIE_CQ_USER_WIDTH), + .AXIS_PCIE_CC_USER_WIDTH(AXIS_PCIE_CC_USER_WIDTH), + .RQ_SEQ_NUM_WIDTH(RQ_SEQ_NUM_WIDTH), + .RQ_SEQ_NUM_ENABLE(RQ_SEQ_NUM_ENABLE), + .PCIE_TAG_COUNT(PCIE_TAG_COUNT), + .READ_OP_TABLE_SIZE(PCIE_TAG_COUNT), + .READ_TX_LIMIT(2**(RQ_SEQ_NUM_WIDTH-1)), + .READ_TX_FC_ENABLE(1), + .WRITE_OP_TABLE_SIZE(2**(RQ_SEQ_NUM_WIDTH-1)), + .WRITE_TX_LIMIT(2**(RQ_SEQ_NUM_WIDTH-1)), + .WRITE_TX_FC_ENABLE(1), + .BAR0_APERTURE(BAR0_APERTURE), + .BAR2_APERTURE(BAR2_APERTURE) +) +example_core_pcie_us_inst ( + .clk(clk), + .rst(rst), + + /* + * AXI input (RC) + */ + .s_axis_rc_tdata(s_axis_rc_tdata), + .s_axis_rc_tkeep(s_axis_rc_tkeep), + .s_axis_rc_tvalid(s_axis_rc_tvalid), + .s_axis_rc_tready(s_axis_rc_tready), + .s_axis_rc_tlast(s_axis_rc_tlast), + .s_axis_rc_tuser(s_axis_rc_tuser), + + /* + * AXI output (RQ) + */ + .m_axis_rq_tdata(m_axis_rq_tdata), + .m_axis_rq_tkeep(m_axis_rq_tkeep), + .m_axis_rq_tvalid(m_axis_rq_tvalid), + .m_axis_rq_tready(m_axis_rq_tready), + .m_axis_rq_tlast(m_axis_rq_tlast), + .m_axis_rq_tuser(m_axis_rq_tuser), + + /* + * AXI input (CQ) + */ + .s_axis_cq_tdata(s_axis_cq_tdata), + .s_axis_cq_tkeep(s_axis_cq_tkeep), + .s_axis_cq_tvalid(s_axis_cq_tvalid), + .s_axis_cq_tready(s_axis_cq_tready), + .s_axis_cq_tlast(s_axis_cq_tlast), + .s_axis_cq_tuser(s_axis_cq_tuser), + + /* + * AXI output (CC) + */ + .m_axis_cc_tdata(m_axis_cc_tdata), + .m_axis_cc_tkeep(m_axis_cc_tkeep), + .m_axis_cc_tvalid(m_axis_cc_tvalid), + .m_axis_cc_tready(m_axis_cc_tready), + .m_axis_cc_tlast(m_axis_cc_tlast), + .m_axis_cc_tuser(m_axis_cc_tuser), + + /* + * Transmit sequence number input + */ + .s_axis_rq_seq_num_0(s_axis_rq_seq_num_0), + .s_axis_rq_seq_num_valid_0(s_axis_rq_seq_num_valid_0), + .s_axis_rq_seq_num_1(s_axis_rq_seq_num_1), + .s_axis_rq_seq_num_valid_1(s_axis_rq_seq_num_valid_1), + + /* + * Flow control + */ + .cfg_fc_ph(cfg_fc_ph), + .cfg_fc_pd(cfg_fc_pd), + .cfg_fc_nph(cfg_fc_nph), + .cfg_fc_npd(cfg_fc_npd), + .cfg_fc_cplh(cfg_fc_cplh), + .cfg_fc_cpld(cfg_fc_cpld), + .cfg_fc_sel(cfg_fc_sel), + + /* + * Configuration interface + */ + .cfg_mgmt_addr(cfg_mgmt_addr), + .cfg_mgmt_function_number(cfg_mgmt_function_number), + .cfg_mgmt_write(cfg_mgmt_write), + .cfg_mgmt_write_data(cfg_mgmt_write_data), + .cfg_mgmt_byte_enable(cfg_mgmt_byte_enable), + .cfg_mgmt_read(cfg_mgmt_read), + .cfg_mgmt_read_data(cfg_mgmt_read_data), + .cfg_mgmt_read_write_done(cfg_mgmt_read_write_done), + + /* + * Interrupt interface + */ + .cfg_interrupt_msi_enable(cfg_interrupt_msi_enable), + .cfg_interrupt_msi_vf_enable(8'd0), + .cfg_interrupt_msi_mmenable(cfg_interrupt_msi_mmenable), + .cfg_interrupt_msi_mask_update(cfg_interrupt_msi_mask_update), + .cfg_interrupt_msi_data(cfg_interrupt_msi_data), + .cfg_interrupt_msi_select(cfg_interrupt_msi_select), + .cfg_interrupt_msi_int(cfg_interrupt_msi_int), + .cfg_interrupt_msi_pending_status(cfg_interrupt_msi_pending_status), + .cfg_interrupt_msi_pending_status_data_enable(cfg_interrupt_msi_pending_status_data_enable), + .cfg_interrupt_msi_pending_status_function_num(cfg_interrupt_msi_pending_status_function_num), + .cfg_interrupt_msi_sent(cfg_interrupt_msi_sent), + .cfg_interrupt_msi_fail(cfg_interrupt_msi_fail), + .cfg_interrupt_msi_attr(cfg_interrupt_msi_attr), + .cfg_interrupt_msi_tph_present(cfg_interrupt_msi_tph_present), + .cfg_interrupt_msi_tph_type(cfg_interrupt_msi_tph_type), + .cfg_interrupt_msi_tph_st_tag(cfg_interrupt_msi_tph_st_tag), + .cfg_interrupt_msi_function_number(cfg_interrupt_msi_function_number), + + /* + * Configuration + */ + .cfg_max_read_req(cfg_max_read_req), + .cfg_max_payload(cfg_max_payload), + + /* + * Status + */ + .status_error_cor(status_error_cor), + .status_error_uncor(status_error_uncor) +); + +endmodule + +`resetall diff --git a/fpga/lib/pcie/example/ZCU106/fpga/rtl/sync_reset.v b/fpga/lib/pcie/example/ZCU106/fpga/rtl/sync_reset.v new file mode 100644 index 000000000..1fd24d361 --- /dev/null +++ b/fpga/lib/pcie/example/ZCU106/fpga/rtl/sync_reset.v @@ -0,0 +1,56 @@ +/* + +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 active-high asynchronous reset signal to a given clock by + * using a pipeline of N registers. + */ +module sync_reset #( + parameter N=2 // depth of synchronizer +)( + input wire clk, + input wire rst, + output wire sync_reset_out +); + +reg [N-1:0] sync_reg = {N{1'b1}}; + +assign sync_reset_out = sync_reg[N-1]; + +always @(posedge clk or posedge rst) begin + if (rst) + sync_reg <= {N{1'b1}}; + else + sync_reg <= {sync_reg[N-2:0], 1'b0}; +end + +endmodule + +`resetall diff --git a/fpga/lib/pcie/example/ZCU106/fpga/rtl/sync_signal.v b/fpga/lib/pcie/example/ZCU106/fpga/rtl/sync_signal.v new file mode 100644 index 000000000..74b855fa1 --- /dev/null +++ b/fpga/lib/pcie/example/ZCU106/fpga/rtl/sync_signal.v @@ -0,0 +1,62 @@ +/* + +Copyright (c) 2014-2018 Alex Forencich + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +*/ + +// Language: Verilog-2001 + +`resetall +`timescale 1 ns / 1 ps +`default_nettype none + +/* + * Synchronizes an asyncronous signal to a given clock by using a pipeline of + * two registers. + */ +module sync_signal #( + parameter WIDTH=1, // width of the input and output signals + parameter N=2 // depth of synchronizer +)( + input wire clk, + input wire [WIDTH-1:0] in, + output wire [WIDTH-1:0] out +); + +reg [WIDTH-1:0] sync_reg[N-1:0]; + +/* + * The synchronized output is the last register in the pipeline. + */ +assign out = sync_reg[N-1]; + +integer k; + +always @(posedge clk) begin + sync_reg[0] <= in; + for (k = 1; k < N; k = k + 1) begin + sync_reg[k] <= sync_reg[k-1]; + end +end + +endmodule + +`resetall diff --git a/fpga/lib/pcie/example/ZCU106/fpga/tb/fpga_core/Makefile b/fpga/lib/pcie/example/ZCU106/fpga/tb/fpga_core/Makefile new file mode 100644 index 000000000..98bf8cb63 --- /dev/null +++ b/fpga/lib/pcie/example/ZCU106/fpga/tb/fpga_core/Makefile @@ -0,0 +1,123 @@ +# Copyright (c) 2020 Alex Forencich +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +TOPLEVEL_LANG = verilog + +SIM ?= icarus +WAVES ?= 0 + +COCOTB_HDL_TIMEUNIT = 1ns +COCOTB_HDL_TIMEPRECISION = 1ps + +DUT = fpga_core +TOPLEVEL = $(DUT) +MODULE = test_$(DUT) +VERILOG_SOURCES += ../../rtl/$(DUT).v +VERILOG_SOURCES += ../../rtl/common/example_core_pcie_us.v +VERILOG_SOURCES += ../../rtl/common/example_core_pcie.v +VERILOG_SOURCES += ../../rtl/common/example_core.v +VERILOG_SOURCES += ../../rtl/common/axi_ram.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_if.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_if_rc.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_if_rq.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_if_cq.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_if_cc.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_cfg.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_msi.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_axil_master.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_axi_master.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_axi_master_rd.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_axi_master_wr.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_tlp_demux_bar.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_tlp_demux.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_tlp_mux.v +VERILOG_SOURCES += ../../lib/pcie/rtl/dma_if_pcie.v +VERILOG_SOURCES += ../../lib/pcie/rtl/dma_if_pcie_rd.v +VERILOG_SOURCES += ../../lib/pcie/rtl/dma_if_pcie_wr.v +VERILOG_SOURCES += ../../lib/pcie/rtl/dma_psdpram.v +VERILOG_SOURCES += ../../lib/pcie/rtl/arbiter.v +VERILOG_SOURCES += ../../lib/pcie/rtl/priority_encoder.v +VERILOG_SOURCES += ../../lib/pcie/rtl/pulse_merge.v + +# module parameters +export PARAM_AXIS_PCIE_DATA_WIDTH ?= 128 +export PARAM_AXIS_PCIE_KEEP_WIDTH ?= $(shell expr $(PARAM_AXIS_PCIE_DATA_WIDTH) / 32 ) +export PARAM_AXIS_PCIE_RQ_USER_WIDTH ?= $(if $(filter-out 512,$(PARAM_AXIS_PCIE_DATA_WIDTH)),62,137) +export PARAM_AXIS_PCIE_RC_USER_WIDTH ?= $(if $(filter-out 512,$(PARAM_AXIS_PCIE_DATA_WIDTH)),75,161) +export PARAM_AXIS_PCIE_CQ_USER_WIDTH ?= $(if $(filter-out 512,$(PARAM_AXIS_PCIE_DATA_WIDTH)),88,183) +export PARAM_AXIS_PCIE_CC_USER_WIDTH ?= $(if $(filter-out 512,$(PARAM_AXIS_PCIE_DATA_WIDTH)),33,81) +export PARAM_RQ_SEQ_NUM_WIDTH ?= 6 +export PARAM_RQ_SEQ_NUM_ENABLE ?= 1 +export PARAM_PCIE_TAG_COUNT ?= 64 +export PARAM_BAR0_APERTURE ?= 24 +export PARAM_BAR2_APERTURE ?= 24 + +ifeq ($(SIM), icarus) + PLUSARGS += -fst + + COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_DATA_WIDTH=$(PARAM_AXIS_PCIE_DATA_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_KEEP_WIDTH=$(PARAM_AXIS_PCIE_KEEP_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_RQ_USER_WIDTH=$(PARAM_AXIS_PCIE_RQ_USER_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_RC_USER_WIDTH=$(PARAM_AXIS_PCIE_RC_USER_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_CQ_USER_WIDTH=$(PARAM_AXIS_PCIE_CQ_USER_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_CC_USER_WIDTH=$(PARAM_AXIS_PCIE_CC_USER_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).RQ_SEQ_NUM_WIDTH=$(PARAM_RQ_SEQ_NUM_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).RQ_SEQ_NUM_ENABLE=$(PARAM_RQ_SEQ_NUM_ENABLE) + COMPILE_ARGS += -P $(TOPLEVEL).PCIE_TAG_COUNT=$(PARAM_PCIE_TAG_COUNT) + COMPILE_ARGS += -P $(TOPLEVEL).BAR0_APERTURE=$(PARAM_BAR0_APERTURE) + COMPILE_ARGS += -P $(TOPLEVEL).BAR2_APERTURE=$(PARAM_BAR2_APERTURE) + + ifeq ($(WAVES), 1) + VERILOG_SOURCES += iverilog_dump.v + COMPILE_ARGS += -s iverilog_dump + endif +else ifeq ($(SIM), verilator) + COMPILE_ARGS += -Wno-SELRANGE -Wno-WIDTH + + COMPILE_ARGS += -GAXIS_PCIE_DATA_WIDTH=$(PARAM_AXIS_PCIE_DATA_WIDTH) + COMPILE_ARGS += -GAXIS_PCIE_KEEP_WIDTH=$(PARAM_AXIS_PCIE_KEEP_WIDTH) + COMPILE_ARGS += -GAXIS_PCIE_RQ_USER_WIDTH=$(PARAM_AXIS_PCIE_RQ_USER_WIDTH) + COMPILE_ARGS += -GAXIS_PCIE_RC_USER_WIDTH=$(PARAM_AXIS_PCIE_RC_USER_WIDTH) + COMPILE_ARGS += -GAXIS_PCIE_CQ_USER_WIDTH=$(PARAM_AXIS_PCIE_CQ_USER_WIDTH) + COMPILE_ARGS += -GAXIS_PCIE_CC_USER_WIDTH=$(PARAM_AXIS_PCIE_CC_USER_WIDTH) + COMPILE_ARGS += -GRQ_SEQ_NUM_WIDTH=$(PARAM_RQ_SEQ_NUM_WIDTH) + COMPILE_ARGS += -GRQ_SEQ_NUM_ENABLE=$(PARAM_RQ_SEQ_NUM_ENABLE) + COMPILE_ARGS += -GPCIE_TAG_COUNT=$(PARAM_PCIE_TAG_COUNT) + COMPILE_ARGS += -GBAR0_APERTURE=$(PARAM_BAR0_APERTURE) + COMPILE_ARGS += -GBAR2_APERTURE=$(PARAM_BAR2_APERTURE) + + ifeq ($(WAVES), 1) + COMPILE_ARGS += --trace-fst + endif +endif + +include $(shell cocotb-config --makefiles)/Makefile.sim + +iverilog_dump.v: + echo 'module iverilog_dump();' > $@ + echo 'initial begin' >> $@ + echo ' $$dumpfile("$(TOPLEVEL).fst");' >> $@ + echo ' $$dumpvars(0, $(TOPLEVEL));' >> $@ + echo 'end' >> $@ + echo 'endmodule' >> $@ + +clean:: + @rm -rf iverilog_dump.v + @rm -rf dump.fst $(TOPLEVEL).fst diff --git a/fpga/lib/pcie/example/ZCU106/fpga/tb/fpga_core/test_fpga_core.py b/fpga/lib/pcie/example/ZCU106/fpga/tb/fpga_core/test_fpga_core.py new file mode 100644 index 000000000..aee89ee1d --- /dev/null +++ b/fpga/lib/pcie/example/ZCU106/fpga/tb/fpga_core/test_fpga_core.py @@ -0,0 +1,479 @@ +""" + +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 + +import cocotb_test.simulator + +import cocotb +from cocotb.log import SimLog +from cocotb.triggers import RisingEdge, FallingEdge, Timer + +from cocotbext.axi import AxiStreamBus +from cocotbext.pcie.core import RootComplex +from cocotbext.pcie.xilinx.us import UltraScalePlusPcieDevice + + +class TB(object): + def __init__(self, dut): + self.dut = dut + + self.log = SimLog("cocotb.tb") + self.log.setLevel(logging.DEBUG) + + # PCIe + self.rc = RootComplex() + + self.dev = UltraScalePlusPcieDevice( + # configuration options + pcie_generation=3, + pcie_link_width=4, + user_clk_frequency=250e6, + alignment="dword", + cq_cc_straddle=False, + rq_rc_straddle=False, + rc_4tlp_straddle=False, + enable_pf1=False, + enable_client_tag=True, + enable_extended_tag=True, + enable_parity=False, + enable_rx_msg_interface=False, + enable_sriov=False, + enable_extended_configuration=False, + + enable_pf0_msi=True, + enable_pf1_msi=False, + + # signals + # Clock and Reset Interface + user_clk=dut.clk, + user_reset=dut.rst, + # user_lnk_up + # sys_clk + # sys_clk_gt + # sys_reset + # phy_rdy_out + + # Requester reQuest Interface + rq_bus=AxiStreamBus.from_prefix(dut, "m_axis_rq"), + pcie_rq_seq_num0=dut.s_axis_rq_seq_num_0, + pcie_rq_seq_num_vld0=dut.s_axis_rq_seq_num_valid_0, + pcie_rq_seq_num1=dut.s_axis_rq_seq_num_1, + pcie_rq_seq_num_vld1=dut.s_axis_rq_seq_num_valid_1, + # pcie_rq_tag0 + # pcie_rq_tag1 + # pcie_rq_tag_av + # pcie_rq_tag_vld0 + # pcie_rq_tag_vld1 + + # Requester Completion Interface + rc_bus=AxiStreamBus.from_prefix(dut, "s_axis_rc"), + + # Completer reQuest Interface + cq_bus=AxiStreamBus.from_prefix(dut, "s_axis_cq"), + # pcie_cq_np_req + # pcie_cq_np_req_count + + # Completer Completion Interface + cc_bus=AxiStreamBus.from_prefix(dut, "m_axis_cc"), + + # Transmit Flow Control Interface + # pcie_tfc_nph_av=dut.pcie_tfc_nph_av, + # pcie_tfc_npd_av=dut.pcie_tfc_npd_av, + + # Configuration Management Interface + cfg_mgmt_addr=dut.cfg_mgmt_addr, + cfg_mgmt_function_number=dut.cfg_mgmt_function_number, + cfg_mgmt_write=dut.cfg_mgmt_write, + cfg_mgmt_write_data=dut.cfg_mgmt_write_data, + cfg_mgmt_byte_enable=dut.cfg_mgmt_byte_enable, + cfg_mgmt_read=dut.cfg_mgmt_read, + cfg_mgmt_read_data=dut.cfg_mgmt_read_data, + cfg_mgmt_read_write_done=dut.cfg_mgmt_read_write_done, + # cfg_mgmt_debug_access + + # Configuration Status Interface + # cfg_phy_link_down + # cfg_phy_link_status + # cfg_negotiated_width + # cfg_current_speed + cfg_max_payload=dut.cfg_max_payload, + cfg_max_read_req=dut.cfg_max_read_req, + # cfg_function_status + # cfg_vf_status + # cfg_function_power_state + # cfg_vf_power_state + # cfg_link_power_state + # cfg_err_cor_out + # cfg_err_nonfatal_out + # cfg_err_fatal_out + # cfg_local_error_out + # cfg_local_error_valid + # cfg_rx_pm_state + # cfg_tx_pm_state + # cfg_ltssm_state + # cfg_rcb_status + # cfg_obff_enable + # cfg_pl_status_change + # cfg_tph_requester_enable + # cfg_tph_st_mode + # cfg_vf_tph_requester_enable + # cfg_vf_tph_st_mode + + # Configuration Received Message Interface + # cfg_msg_received + # cfg_msg_received_data + # cfg_msg_received_type + + # Configuration Transmit Message Interface + # cfg_msg_transmit + # cfg_msg_transmit_type + # cfg_msg_transmit_data + # cfg_msg_transmit_done + + # Configuration Flow Control Interface + cfg_fc_ph=dut.cfg_fc_ph, + cfg_fc_pd=dut.cfg_fc_pd, + cfg_fc_nph=dut.cfg_fc_nph, + cfg_fc_npd=dut.cfg_fc_npd, + cfg_fc_cplh=dut.cfg_fc_cplh, + cfg_fc_cpld=dut.cfg_fc_cpld, + cfg_fc_sel=dut.cfg_fc_sel, + + # Configuration Control Interface + # cfg_hot_reset_in + # cfg_hot_reset_out + # cfg_config_space_enable + # cfg_dsn + # cfg_bus_number + # cfg_ds_port_number + # cfg_ds_bus_number + # cfg_ds_device_number + # cfg_ds_function_number + # cfg_power_state_change_ack + # cfg_power_state_change_interrupt + cfg_err_cor_in=dut.status_error_cor, + cfg_err_uncor_in=dut.status_error_uncor, + # cfg_flr_in_process + # cfg_flr_done + # cfg_vf_flr_in_process + # cfg_vf_flr_func_num + # cfg_vf_flr_done + # cfg_pm_aspm_l1_entry_reject + # cfg_pm_aspm_tx_l0s_entry_disable + # cfg_req_pm_transition_l23_ready + # cfg_link_training_enable + + # Configuration Interrupt Controller Interface + # cfg_interrupt_int + # cfg_interrupt_sent + # cfg_interrupt_pending + cfg_interrupt_msi_enable=dut.cfg_interrupt_msi_enable, + cfg_interrupt_msi_mmenable=dut.cfg_interrupt_msi_mmenable, + cfg_interrupt_msi_mask_update=dut.cfg_interrupt_msi_mask_update, + cfg_interrupt_msi_data=dut.cfg_interrupt_msi_data, + # cfg_interrupt_msi_select=dut.cfg_interrupt_msi_select, + cfg_interrupt_msi_int=dut.cfg_interrupt_msi_int, + cfg_interrupt_msi_pending_status=dut.cfg_interrupt_msi_pending_status, + cfg_interrupt_msi_pending_status_data_enable=dut.cfg_interrupt_msi_pending_status_data_enable, + # cfg_interrupt_msi_pending_status_function_num=dut.cfg_interrupt_msi_pending_status_function_num, + cfg_interrupt_msi_sent=dut.cfg_interrupt_msi_sent, + cfg_interrupt_msi_fail=dut.cfg_interrupt_msi_fail, + # cfg_interrupt_msix_enable + # cfg_interrupt_msix_mask + # cfg_interrupt_msix_vf_enable + # cfg_interrupt_msix_vf_mask + # cfg_interrupt_msix_address + # cfg_interrupt_msix_data + # cfg_interrupt_msix_int + # cfg_interrupt_msix_vec_pending + # cfg_interrupt_msix_vec_pending_status + cfg_interrupt_msi_attr=dut.cfg_interrupt_msi_attr, + cfg_interrupt_msi_tph_present=dut.cfg_interrupt_msi_tph_present, + cfg_interrupt_msi_tph_type=dut.cfg_interrupt_msi_tph_type, + # cfg_interrupt_msi_tph_st_tag=dut.cfg_interrupt_msi_tph_st_tag, + # cfg_interrupt_msi_function_number=dut.cfg_interrupt_msi_function_number, + + # Configuration Extend Interface + # cfg_ext_read_received + # cfg_ext_write_received + # cfg_ext_register_number + # cfg_ext_function_number + # cfg_ext_write_data + # cfg_ext_write_byte_enable + # cfg_ext_read_data + # cfg_ext_read_data_valid + ) + + # self.dev.log.setLevel(logging.DEBUG) + + self.rc.make_port().connect(self.dev) + + self.dev.functions[0].msi_multiple_message_capable = 5 + + self.dev.functions[0].configure_bar(0, 2**len(dut.example_core_pcie_us_inst.core_pcie_inst.axil_ctrl_awaddr)) + self.dev.functions[0].configure_bar(2, 2**len(dut.example_core_pcie_us_inst.core_pcie_inst.axi_ram_awaddr)) + + dut.btnu.setimmediatevalue(0) + dut.btnl.setimmediatevalue(0) + dut.btnd.setimmediatevalue(0) + dut.btnr.setimmediatevalue(0) + dut.btnc.setimmediatevalue(0) + dut.sw.setimmediatevalue(0) + + async def init(self): + + await FallingEdge(self.dut.rst) + await Timer(100, 'ns') + + await self.rc.enumerate(enable_bus_mastering=True, configure_msi=True) + + +@cocotb.test() +async def run_test(dut): + + tb = TB(dut) + + await tb.init() + + mem = tb.rc.mem_pool.alloc_region(16*1024*1024) + mem_base = mem.get_absolute_address(0) + + dev_pf0_bar0 = tb.rc.tree[0][0].bar_window[0] + dev_pf0_bar2 = tb.rc.tree[0][0].bar_window[2] + + tb.log.info("Test memory write to BAR 2") + + test_data = b'\x11\x22\x33\x44' + await dev_pf0_bar2.write(0, test_data) + + await Timer(100, 'ns') + + tb.log.info("Test memory read from BAR 2") + + val = await dev_pf0_bar2.read(0, len(test_data), timeout=1000) + tb.log.info("Read data: %s", val) + assert val == test_data + + tb.log.info("Test DMA") + + # write packet data + mem[0:1024] = bytearray([x % 256 for x in range(1024)]) + + # enable DMA + await dev_pf0_bar0.write_dword(0x000000, 1) + + # write pcie read descriptor + await dev_pf0_bar0.write_dword(0x000100, (mem_base+0x0000) & 0xffffffff) + await dev_pf0_bar0.write_dword(0x000104, (mem_base+0x0000 >> 32) & 0xffffffff) + await dev_pf0_bar0.write_dword(0x000108, 0x100) + await dev_pf0_bar0.write_dword(0x000110, 0x400) + await dev_pf0_bar0.write_dword(0x000114, 0xAA) + + await Timer(2000, 'ns') + + # read status + val = await dev_pf0_bar0.read_dword(0x000118) + tb.log.info("Status: 0x%x", val) + assert val == 0x800000AA + + # write pcie write descriptor + await dev_pf0_bar0.write_dword(0x000200, (mem_base+0x1000) & 0xffffffff) + await dev_pf0_bar0.write_dword(0x000204, (mem_base+0x1000 >> 32) & 0xffffffff) + await dev_pf0_bar0.write_dword(0x000208, 0x100) + await dev_pf0_bar0.write_dword(0x000210, 0x400) + await dev_pf0_bar0.write_dword(0x000214, 0x55) + + await Timer(2000, 'ns') + + # read status + val = await dev_pf0_bar0.read_dword(0x000218) + tb.log.info("Status: 0x%x", val) + assert val == 0x80000055 + + tb.log.info("%s", mem.hexdump_str(0x1000, 64)) + + assert mem[0:1024] == mem[0x1000:0x1000+1024] + + tb.log.info("Test DMA block operations") + + # write packet data + mem[0:1024] = bytearray([x % 256 for x in range(1024)]) + + # enable DMA + await dev_pf0_bar0.write_dword(0x000000, 1) + # disable interrupts + await dev_pf0_bar0.write_dword(0x000008, 0) + + # configure operation (read) + # DMA base address + await dev_pf0_bar0.write_dword(0x001080, (mem_base+0x0000) & 0xffffffff) + await dev_pf0_bar0.write_dword(0x001084, (mem_base+0x0000 >> 32) & 0xffffffff) + # DMA offset address + await dev_pf0_bar0.write_dword(0x001088, 0) + await dev_pf0_bar0.write_dword(0x00108c, 0) + # DMA offset mask + await dev_pf0_bar0.write_dword(0x001090, 0x000003ff) + await dev_pf0_bar0.write_dword(0x001094, 0) + # DMA stride + await dev_pf0_bar0.write_dword(0x001098, 256) + await dev_pf0_bar0.write_dword(0x00109c, 0) + # RAM base address + await dev_pf0_bar0.write_dword(0x0010c0, 0) + await dev_pf0_bar0.write_dword(0x0010c4, 0) + # RAM offset address + await dev_pf0_bar0.write_dword(0x0010c8, 0) + await dev_pf0_bar0.write_dword(0x0010cc, 0) + # RAM offset mask + await dev_pf0_bar0.write_dword(0x0010d0, 0x000003ff) + await dev_pf0_bar0.write_dword(0x0010d4, 0) + # RAM stride + await dev_pf0_bar0.write_dword(0x0010d8, 256) + await dev_pf0_bar0.write_dword(0x0010dc, 0) + # clear cycle count + await dev_pf0_bar0.write_dword(0x001008, 0) + await dev_pf0_bar0.write_dword(0x00100c, 0) + # block length + await dev_pf0_bar0.write_dword(0x001010, 256) + # block count + await dev_pf0_bar0.write_dword(0x001018, 32) + await dev_pf0_bar0.write_dword(0x00101c, 0) + # start + await dev_pf0_bar0.write_dword(0x001000, 1) + + await Timer(2000, 'ns') + + # configure operation (write) + # DMA base address + await dev_pf0_bar0.write_dword(0x001180, (mem_base+0x0000) & 0xffffffff) + await dev_pf0_bar0.write_dword(0x001184, (mem_base+0x0000 >> 32) & 0xffffffff) + # DMA offset address + await dev_pf0_bar0.write_dword(0x001188, 0) + await dev_pf0_bar0.write_dword(0x00118c, 0) + # DMA offset mask + await dev_pf0_bar0.write_dword(0x001190, 0x000003ff) + await dev_pf0_bar0.write_dword(0x001194, 0) + # DMA stride + await dev_pf0_bar0.write_dword(0x001198, 256) + await dev_pf0_bar0.write_dword(0x00119c, 0) + # RAM base address + await dev_pf0_bar0.write_dword(0x0011c0, 0) + await dev_pf0_bar0.write_dword(0x0011c4, 0) + # RAM offset address + await dev_pf0_bar0.write_dword(0x0011c8, 0) + await dev_pf0_bar0.write_dword(0x0011cc, 0) + # RAM offset mask + await dev_pf0_bar0.write_dword(0x0011d0, 0x000003ff) + await dev_pf0_bar0.write_dword(0x0011d4, 0) + # RAM stride + await dev_pf0_bar0.write_dword(0x0011d8, 256) + await dev_pf0_bar0.write_dword(0x0011dc, 0) + # clear cycle count + await dev_pf0_bar0.write_dword(0x001108, 0) + await dev_pf0_bar0.write_dword(0x00110c, 0) + # block length + await dev_pf0_bar0.write_dword(0x001110, 256) + # block count + await dev_pf0_bar0.write_dword(0x001118, 32) + await dev_pf0_bar0.write_dword(0x00111c, 0) + # start + await dev_pf0_bar0.write_dword(0x001100, 1) + + await Timer(2000, 'ns') + + await RisingEdge(dut.clk) + await RisingEdge(dut.clk) + + +# cocotb-test + +tests_dir = 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')) +pcie_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'pcie', '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(rtl_dir, "common", "example_core_pcie_us.v"), + os.path.join(rtl_dir, "common", "example_core_pcie.v"), + os.path.join(rtl_dir, "common", "example_core.v"), + os.path.join(rtl_dir, "common", "axi_ram.v"), + os.path.join(pcie_rtl_dir, "pcie_us_if.v"), + os.path.join(pcie_rtl_dir, "pcie_us_if_rc.v"), + os.path.join(pcie_rtl_dir, "pcie_us_if_rq.v"), + os.path.join(pcie_rtl_dir, "pcie_us_if_cq.v"), + os.path.join(pcie_rtl_dir, "pcie_us_if_cc.v"), + os.path.join(pcie_rtl_dir, "pcie_us_cfg.v"), + os.path.join(pcie_rtl_dir, "pcie_us_msi.v"), + os.path.join(pcie_rtl_dir, "pcie_axil_master.v"), + os.path.join(pcie_rtl_dir, "pcie_axi_master.v"), + os.path.join(pcie_rtl_dir, "pcie_axi_master_rd.v"), + os.path.join(pcie_rtl_dir, "pcie_axi_master_wr.v"), + os.path.join(pcie_rtl_dir, "pcie_tlp_demux_bar.v"), + os.path.join(pcie_rtl_dir, "pcie_tlp_demux.v"), + os.path.join(pcie_rtl_dir, "pcie_tlp_mux.v"), + os.path.join(pcie_rtl_dir, "dma_if_pcie.v"), + os.path.join(pcie_rtl_dir, "dma_if_pcie_rd.v"), + os.path.join(pcie_rtl_dir, "dma_if_pcie_wr.v"), + os.path.join(pcie_rtl_dir, "dma_psdpram.v"), + os.path.join(pcie_rtl_dir, "arbiter.v"), + os.path.join(pcie_rtl_dir, "priority_encoder.v"), + os.path.join(pcie_rtl_dir, "pulse_merge.v"), + ] + + parameters = {} + + parameters['AXIS_PCIE_DATA_WIDTH'] = 128 + parameters['AXIS_PCIE_KEEP_WIDTH'] = parameters['AXIS_PCIE_DATA_WIDTH'] // 32 + parameters['AXIS_PCIE_RQ_USER_WIDTH'] = 62 if parameters['AXIS_PCIE_DATA_WIDTH'] < 512 else 137 + parameters['AXIS_PCIE_RC_USER_WIDTH'] = 75 if parameters['AXIS_PCIE_DATA_WIDTH'] < 512 else 161 + parameters['AXIS_PCIE_CQ_USER_WIDTH'] = 88 if parameters['AXIS_PCIE_DATA_WIDTH'] < 512 else 183 + parameters['AXIS_PCIE_CC_USER_WIDTH'] = 33 if parameters['AXIS_PCIE_DATA_WIDTH'] < 512 else 81 + parameters['RQ_SEQ_NUM_WIDTH'] = 6 + parameters['RQ_SEQ_NUM_ENABLE'] = 1 + parameters['PCIE_TAG_COUNT'] = 64 + parameters['BAR0_APERTURE'] = 24 + parameters['BAR2_APERTURE'] = 24 + + 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, + ) diff --git a/fpga/lib/pcie/example/common/rtl/example_core_pcie_s10.v b/fpga/lib/pcie/example/common/rtl/example_core_pcie_s10.v index bae5a6e0d..710db45af 100644 --- a/fpga/lib/pcie/example/common/rtl/example_core_pcie_s10.v +++ b/fpga/lib/pcie/example/common/rtl/example_core_pcie_s10.v @@ -208,7 +208,7 @@ pcie_s10_if #( .MSI_ENABLE(1), .MSI_COUNT(MSI_COUNT) ) -pcie_us_if_inst ( +pcie_s10_if_inst ( .clk(clk), .rst(rst), diff --git a/fpga/lib/pcie/example/common/tb/example_core_pcie/test_example_core_pcie.py b/fpga/lib/pcie/example/common/tb/example_core_pcie/test_example_core_pcie.py index 2c5256c05..e3f7fcaf0 100644 --- a/fpga/lib/pcie/example/common/tb/example_core_pcie/test_example_core_pcie.py +++ b/fpga/lib/pcie/example/common/tb/example_core_pcie/test_example_core_pcie.py @@ -35,7 +35,6 @@ from cocotb.clock import Clock from cocotb.triggers import RisingEdge, Timer from cocotbext.pcie.core import RootComplex -from cocotbext.axi.utils import hexdump_str try: from pcie_if import PcieIfDevice, PcieIfRxBus, PcieIfTxBus @@ -76,9 +75,9 @@ class TB(object): rd_req_tx_seq_num=dut.s_axis_rd_req_tx_seq_num, rd_req_tx_seq_num_valid=dut.s_axis_rd_req_tx_seq_num_valid, - cfg_max_payload=dut.max_payload_size, rx_cpl_tlp_bus=PcieIfRxBus.from_prefix(dut, "rx_cpl_tlp"), + cfg_max_payload=dut.max_payload_size, cfg_max_read_req=dut.max_read_request_size, cfg_ext_tag_enable=dut.ext_tag_enable, @@ -93,8 +92,8 @@ class TB(object): self.dev.functions[0].msi_multiple_message_capable = 5 - self.dev.functions[0].configure_bar(0, 2**24) - self.dev.functions[0].configure_bar(2, 2**24) + self.dev.functions[0].configure_bar(0, 2**len(dut.axil_ctrl_awaddr)) + self.dev.functions[0].configure_bar(2, 2**len(dut.axi_ram_awaddr)) dut.bus_num.setimmediatevalue(0) diff --git a/fpga/lib/pcie/example/common/tb/example_core_pcie_s10/test_example_core_pcie_s10.py b/fpga/lib/pcie/example/common/tb/example_core_pcie_s10/test_example_core_pcie_s10.py index 76212fb9e..9680b297e 100644 --- a/fpga/lib/pcie/example/common/tb/example_core_pcie_s10/test_example_core_pcie_s10.py +++ b/fpga/lib/pcie/example/common/tb/example_core_pcie_s10/test_example_core_pcie_s10.py @@ -34,7 +34,6 @@ from cocotb.triggers import RisingEdge, FallingEdge, Timer from cocotbext.pcie.core import RootComplex from cocotbext.pcie.intel.s10 import S10PcieDevice, S10RxBus, S10TxBus -from cocotbext.axi.utils import hexdump_str class TB(object): @@ -159,8 +158,8 @@ class TB(object): self.dev.functions[0].msi_multiple_message_capable = 5 - self.dev.functions[0].configure_bar(0, 2**24) - self.dev.functions[0].configure_bar(2, 2**24) + self.dev.functions[0].configure_bar(0, 2**len(dut.core_pcie_inst.axil_ctrl_awaddr)) + self.dev.functions[0].configure_bar(2, 2**len(dut.core_pcie_inst.axi_ram_awaddr)) async def init(self): diff --git a/fpga/lib/pcie/example/common/tb/example_core_pcie_us/test_example_core_pcie_us.py b/fpga/lib/pcie/example/common/tb/example_core_pcie_us/test_example_core_pcie_us.py index 4ba7dd0ce..f1d4c8e08 100644 --- a/fpga/lib/pcie/example/common/tb/example_core_pcie_us/test_example_core_pcie_us.py +++ b/fpga/lib/pcie/example/common/tb/example_core_pcie_us/test_example_core_pcie_us.py @@ -35,7 +35,6 @@ from cocotb.triggers import RisingEdge, FallingEdge, Timer from cocotbext.axi import AxiStreamBus from cocotbext.pcie.core import RootComplex from cocotbext.pcie.xilinx.us import UltraScalePlusPcieDevice -from cocotbext.axi.utils import hexdump_str class TB(object): @@ -235,8 +234,8 @@ class TB(object): self.dev.functions[0].msi_multiple_message_capable = 5 - self.dev.functions[0].configure_bar(0, 2**24) - self.dev.functions[0].configure_bar(2, 2**24) + self.dev.functions[0].configure_bar(0, 2**len(dut.core_pcie_inst.axil_ctrl_awaddr)) + self.dev.functions[0].configure_bar(2, 2**len(dut.core_pcie_inst.axi_ram_awaddr)) # monitor error outputs self.status_error_cor_asserted = False diff --git a/fpga/lib/pcie/example/fb2CG/fpga/rtl/fpga.v b/fpga/lib/pcie/example/fb2CG/fpga/rtl/fpga.v index 29740ca85..cb700bf49 100644 --- a/fpga/lib/pcie/example/fb2CG/fpga/rtl/fpga.v +++ b/fpga/lib/pcie/example/fb2CG/fpga/rtl/fpga.v @@ -55,10 +55,10 @@ module fpga ( parameter AXIS_PCIE_DATA_WIDTH = 512; parameter AXIS_PCIE_KEEP_WIDTH = (AXIS_PCIE_DATA_WIDTH/32); -parameter AXIS_PCIE_RC_USER_WIDTH = 161; -parameter AXIS_PCIE_RQ_USER_WIDTH = 137; -parameter AXIS_PCIE_CQ_USER_WIDTH = 183; -parameter AXIS_PCIE_CC_USER_WIDTH = 81; +parameter AXIS_PCIE_RC_USER_WIDTH = AXIS_PCIE_DATA_WIDTH < 512 ? 75 : 161; +parameter AXIS_PCIE_RQ_USER_WIDTH = AXIS_PCIE_DATA_WIDTH < 512 ? 60 : 137; +parameter AXIS_PCIE_CQ_USER_WIDTH = AXIS_PCIE_DATA_WIDTH < 512 ? 85 : 183; +parameter AXIS_PCIE_CC_USER_WIDTH = AXIS_PCIE_DATA_WIDTH < 512 ? 33 : 81; parameter RQ_SEQ_NUM_WIDTH = AXIS_PCIE_RQ_USER_WIDTH == 60 ? 4 : 6; parameter RQ_SEQ_NUM_ENABLE = 1; diff --git a/fpga/lib/pcie/example/fb2CG/fpga/rtl/fpga_core.v b/fpga/lib/pcie/example/fb2CG/fpga/rtl/fpga_core.v index 37065c74a..5b363b04c 100644 --- a/fpga/lib/pcie/example/fb2CG/fpga/rtl/fpga_core.v +++ b/fpga/lib/pcie/example/fb2CG/fpga/rtl/fpga_core.v @@ -35,10 +35,10 @@ module fpga_core # ( parameter AXIS_PCIE_DATA_WIDTH = 512, parameter AXIS_PCIE_KEEP_WIDTH = (AXIS_PCIE_DATA_WIDTH/32), - parameter AXIS_PCIE_RC_USER_WIDTH = 161, - parameter AXIS_PCIE_RQ_USER_WIDTH = 137, - parameter AXIS_PCIE_CQ_USER_WIDTH = 183, - parameter AXIS_PCIE_CC_USER_WIDTH = 81, + parameter AXIS_PCIE_RC_USER_WIDTH = AXIS_PCIE_DATA_WIDTH < 512 ? 75 : 161, + parameter AXIS_PCIE_RQ_USER_WIDTH = AXIS_PCIE_DATA_WIDTH < 512 ? 60 : 137, + parameter AXIS_PCIE_CQ_USER_WIDTH = AXIS_PCIE_DATA_WIDTH < 512 ? 85 : 183, + parameter AXIS_PCIE_CC_USER_WIDTH = AXIS_PCIE_DATA_WIDTH < 512 ? 33 : 81, parameter RQ_SEQ_NUM_WIDTH = AXIS_PCIE_RQ_USER_WIDTH == 60 ? 4 : 6, parameter RQ_SEQ_NUM_ENABLE = 1, parameter PCIE_TAG_COUNT = 64, diff --git a/fpga/lib/pcie/example/fb2CG/fpga/tb/fpga_core/test_fpga_core.py b/fpga/lib/pcie/example/fb2CG/fpga/tb/fpga_core/test_fpga_core.py index 6a421b60a..6c5b428d1 100644 --- a/fpga/lib/pcie/example/fb2CG/fpga/tb/fpga_core/test_fpga_core.py +++ b/fpga/lib/pcie/example/fb2CG/fpga/tb/fpga_core/test_fpga_core.py @@ -34,7 +34,6 @@ from cocotb.triggers import RisingEdge, FallingEdge, Timer from cocotbext.axi import AxiStreamBus from cocotbext.pcie.core import RootComplex from cocotbext.pcie.xilinx.us import UltraScalePlusPcieDevice -from cocotbext.axi.utils import hexdump_str class TB(object): @@ -234,8 +233,8 @@ class TB(object): self.dev.functions[0].msi_multiple_message_capable = 5 - self.dev.functions[0].configure_bar(0, 2**22) - self.dev.functions[0].configure_bar(2, 2**22) + self.dev.functions[0].configure_bar(0, 2**len(dut.example_core_pcie_us_inst.core_pcie_inst.axil_ctrl_awaddr)) + self.dev.functions[0].configure_bar(2, 2**len(dut.example_core_pcie_us_inst.core_pcie_inst.axi_ram_awaddr)) async def init(self): diff --git a/fpga/lib/pcie/rtl/dma_if_desc_mux.v b/fpga/lib/pcie/rtl/dma_if_desc_mux.v index 714d2dfe9..253c6c92b 100644 --- a/fpga/lib/pcie/rtl/dma_if_desc_mux.v +++ b/fpga/lib/pcie/rtl/dma_if_desc_mux.v @@ -177,10 +177,9 @@ assign acknowledge = grant & s_axis_desc_valid & s_axis_desc_ready; always @* begin // pass through selected packet data m_axis_desc_dma_addr_int = current_s_desc_dma_addr; - if (S_RAM_SEL_WIDTH > 0) begin - m_axis_desc_ram_sel_int = {grant_encoded, current_s_desc_ram_sel}; - end else begin - m_axis_desc_ram_sel_int = grant_encoded; + m_axis_desc_ram_sel_int = current_s_desc_ram_sel; + if (PORTS > 1) begin + m_axis_desc_ram_sel_int[M_RAM_SEL_WIDTH-1:M_RAM_SEL_WIDTH-CL_PORTS] = grant_encoded; end m_axis_desc_ram_addr_int = current_s_desc_ram_addr; m_axis_desc_len_int = current_s_desc_len; @@ -293,7 +292,7 @@ assign m_axis_desc_status_valid = m_axis_desc_status_valid_reg; always @(posedge clk) begin m_axis_desc_status_tag_reg <= s_axis_desc_status_tag; m_axis_desc_status_error_reg <= s_axis_desc_status_error; - m_axis_desc_status_valid_reg <= s_axis_desc_status_valid << (PORTS > 1 ? s_axis_desc_status_tag[S_TAG_WIDTH+CL_PORTS-1:S_TAG_WIDTH] : 0); + m_axis_desc_status_valid_reg <= s_axis_desc_status_valid << (PORTS > 1 ? s_axis_desc_status_tag[M_TAG_WIDTH-1:M_TAG_WIDTH-CL_PORTS] : 0); if (rst) begin m_axis_desc_status_valid_reg <= {PORTS{1'b0}}; diff --git a/fpga/lib/pcie/rtl/dma_ram_demux_rd.v b/fpga/lib/pcie/rtl/dma_ram_demux_rd.v index a4ee6202c..815c3f175 100644 --- a/fpga/lib/pcie/rtl/dma_ram_demux_rd.v +++ b/fpga/lib/pcie/rtl/dma_ram_demux_rd.v @@ -127,12 +127,18 @@ for (n = 0; n < SEG_COUNT; n = n + 1) begin wire [PORTS-1:0] seg_ram_rd_cmd_ready; for (p = 0; p < PORTS; p = p + 1) begin - assign ram_rd_cmd_sel[(p*SEG_COUNT+n)*S_RAM_SEL_WIDTH +: S_RAM_SEL_WIDTH_INT] = seg_ram_rd_cmd_sel[p*S_RAM_SEL_WIDTH +: S_RAM_SEL_WIDTH_INT]; + if (S_RAM_SEL_WIDTH > 0) begin + assign ram_rd_cmd_sel[(p*SEG_COUNT+n)*S_RAM_SEL_WIDTH +: S_RAM_SEL_WIDTH_INT] = seg_ram_rd_cmd_sel[p*S_RAM_SEL_WIDTH +: S_RAM_SEL_WIDTH_INT]; + end assign ram_rd_cmd_addr[(p*SEG_COUNT+n)*SEG_ADDR_WIDTH +: SEG_ADDR_WIDTH] = seg_ram_rd_cmd_addr[p*SEG_ADDR_WIDTH +: SEG_ADDR_WIDTH]; assign ram_rd_cmd_valid[p*SEG_COUNT+n] = seg_ram_rd_cmd_valid[p]; assign seg_ram_rd_cmd_ready[p] = ram_rd_cmd_ready[p*SEG_COUNT+n]; end + if (S_RAM_SEL_WIDTH == 0) begin + assign ram_rd_cmd_sel = 0; + end + // internal datapath reg [S_RAM_SEL_WIDTH-1:0] seg_ram_rd_cmd_sel_int; reg [SEG_ADDR_WIDTH-1:0] seg_ram_rd_cmd_addr_int; diff --git a/fpga/lib/pcie/rtl/pcie_axi_dma_desc_mux.v b/fpga/lib/pcie/rtl/pcie_axi_dma_desc_mux.v index 4957afce8..0a120ddd2 100644 --- a/fpga/lib/pcie/rtl/pcie_axi_dma_desc_mux.v +++ b/fpga/lib/pcie/rtl/pcie_axi_dma_desc_mux.v @@ -152,7 +152,10 @@ always @* begin m_axis_desc_pcie_addr_int = current_s_desc_pcie_addr; m_axis_desc_axi_addr_int = current_s_desc_axi_addr; m_axis_desc_len_int = current_s_desc_len; - m_axis_desc_tag_int = {grant_encoded, current_s_desc_tag}; + m_axis_desc_tag_int = current_s_desc_tag; + if (PORTS > 1) begin + m_axis_desc_tag_int[M_TAG_WIDTH-1:M_TAG_WIDTH-CL_PORTS] = grant_encoded; + end m_axis_desc_valid_int = current_s_desc_valid && m_axis_desc_ready_int_reg && grant_valid; end @@ -255,7 +258,7 @@ assign m_axis_desc_status_valid = m_axis_desc_status_valid_reg; always @* begin m_axis_desc_status_tag_next = s_axis_desc_status_tag; m_axis_desc_status_error_next = s_axis_desc_status_error; - m_axis_desc_status_valid_next = s_axis_desc_status_valid << (PORTS > 1 ? s_axis_desc_status_tag[S_TAG_WIDTH+CL_PORTS-1:S_TAG_WIDTH] : 0); + m_axis_desc_status_valid_next = s_axis_desc_status_valid << (PORTS > 1 ? s_axis_desc_status_tag[M_TAG_WIDTH-1:M_TAG_WIDTH-CL_PORTS] : 0); end always @(posedge clk) begin