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

Add fb2CG AXI example design

This commit is contained in:
Alex Forencich 2020-09-20 01:17:52 -07:00
parent 722222a01c
commit c7594c77ab
21 changed files with 3663 additions and 0 deletions

View File

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

View File

@ -0,0 +1,26 @@
# Verilog PCIe fb2CG@KU15P Example Design
## Introduction
This example design targets the Silicom fb2CG@KU15P FPGA board.
The design implements the PCIe AXI lite master module, the PCIe AXI master
module, and the PCIe AXI DMA module. A very simple Linux driver is included
to test the FPGA design.
FPGA: xcku15p-ffve1760-2-e
## How to build
Run make to build. Ensure that the Xilinx Vivado toolchain 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 fb2CG@KU15P board with Vivado. Then load the
driver with insmod example.ko. Check dmesg for the output.

View File

@ -0,0 +1,123 @@
###################################################################
#
# 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: clean fpga
# prevent make from deleting intermediate files and reports
.PRECIOUS: %.xpr %.bit %.mcs %.prm
.SECONDARY:
CONFIG ?= config.mk
-include ../$(CONFIG)
SYN_FILES_REL = $(patsubst %, ../%, $(SYN_FILES))
INC_FILES_REL = $(patsubst %, ../%, $(INC_FILES))
XCI_FILES_REL = $(patsubst %, ../%, $(XCI_FILES))
IP_TCL_FILES_REL = $(patsubst %, ../%, $(IP_TCL_FILES))
ifdef XDC_FILES
XDC_FILES_REL = $(patsubst %, ../%, $(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 *.hbs *.hw *.ip_user_files *.runs *.xpr *.html *.xml *.sim *.srcs *.str .Xil defines.v
-rm -rf create_project.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
%.xpr: 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) $*" > create_project.tcl
echo "add_files -fileset sources_1 defines.v" >> create_project.tcl
for x in $(SYN_FILES_REL); do echo "add_files -fileset sources_1 $$x" >> create_project.tcl; done
for x in $(XDC_FILES_REL); do echo "add_files -fileset constrs_1 $$x" >> create_project.tcl; done
for x in $(XCI_FILES_REL); do echo "import_ip $$x" >> create_project.tcl; done
for x in $(IP_TCL_FILES_REL); do echo "source $$x" >> create_project.tcl; done
echo "exit" >> create_project.tcl
vivado -nojournal -nolog -mode batch -source create_project.tcl
# synthesis run
%.runs/synth_1/%.dcp: %.xpr $(SYN_FILES_REL) $(INC_FILES_REL) $(XDC_FILES_REL)
echo "open_project $*.xpr" > run_synth.tcl
echo "reset_run synth_1" >> run_synth.tcl
echo "launch_runs synth_1" >> run_synth.tcl
echo "wait_on_run synth_1" >> run_synth.tcl
echo "exit" >> 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 impl_1" >> run_impl.tcl
echo "wait_on_run impl_1" >> run_impl.tcl
echo "exit" >> 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
echo "exit" >> 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";

View File

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

View File

@ -0,0 +1,227 @@
# XDC constraints for the fb2CG@KU15P
# part: xcku15p-ffve1760-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 disable [current_design]
set_property BITSTREAM.CONFIG.SPI_32BIT_ADDR YES [current_design]
set_property BITSTREAM.CONFIG.SPI_BUSWIDTH 4 [current_design]
set_property BITSTREAM.CONFIG.SPI_FALL_EDGE YES [current_design]
set_property BITSTREAM.CONFIG.CONFIGRATE 85.0 [current_design]
set_property CONFIG_MODE SPIx4 [current_design]
set_property BITSTREAM.CONFIG.OVERTEMPSHUTDOWN Enable [current_design]
# System clocks
# init clock 100 MHz
#set_property -dict {LOC E7 IOSTANDARD LVCMOS18} [get_ports init_clk]
#create_clock -period 10.000 -name init_clk [get_ports init_clk]
# E7 is not a global clock capable input, so need to set CLOCK_DEDICATED_ROUTE to satisfy DRC
#set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets init_clk_ibuf_inst/O]
#set_property CLOCK_DEDICATED_ROUTE ANY_CMT_COLUMN [get_nets init_clk_bufg]
# DDR4 refclk1
#set_property -dict {LOC AT32 IOSTANDARD DIFF_SSTL12} [get_ports clk_ddr4_refclk1_p]
#set_property -dict {LOC AU32 IOSTANDARD DIFF_SSTL12} [get_ports clk_ddr4_refclk1_n]
#create_clock -period 3.750 -name clk_ddr4_refclk1 [get_ports clk_ddr4_refclk1_p]
# DDR4 refclk2
#set_property -dict {LOC G29 IOSTANDARD DIFF_SSTL12} [get_ports clk_ddr4_refclk2_p]
#set_property -dict {LOC G28 IOSTANDARD DIFF_SSTL12} [get_ports clk_ddr4_refclk2_n]
#create_clock -period 3.750 -name clk_ddr4_refclk2 [get_ports clk_ddr4_refclk1_p]
# LEDs
set_property -dict {LOC C4 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 4} [get_ports led_sreg_d]
set_property -dict {LOC B3 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 4} [get_ports led_sreg_ld]
set_property -dict {LOC G3 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 4} [get_ports led_sreg_clk]
set_property -dict {LOC C5 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 4} [get_ports {led_bmc[0]}]
set_property -dict {LOC C6 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 4} [get_ports {led_bmc[1]}]
set_property -dict {LOC D3 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 4} [get_ports {led_exp[0]}]
set_property -dict {LOC D4 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 4} [get_ports {led_exp[1]}]
# GPIO
#set_property -dict {LOC B4 IOSTANDARD LVCMOS33} [get_ports pps_in] ;# from SMA J6 via Q1 (inverted)
#set_property -dict {LOC A4 IOSTANDARD LVCMOS33 SLEW FAST DRIVE 4} [get_ports pps_out] ;# to SMA J6 via U4 and U5, and u.FL J7 (PPS OUT) via U3
#set_property -dict {LOC A3 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 4} [get_ports pps_out_en] ; # to U5 IN (connects pps_out to SMA J6 when high)
#set_property -dict {LOC H2 IOSTANDARD LVCMOS33} [get_ports misc_ucoax] ; from u.FL J5 (PPS IN)
# BMC interface
#set_property -dict {LOC D7 IOSTANDARD LVCMOS18} [get_ports bmc_miso]
#set_property -dict {LOC J4 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 4} [get_ports bmc_nss]
#set_property -dict {LOC B6 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 4} [get_ports bmc_clk]
#set_property -dict {LOC D5 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 4} [get_ports bmc_mosi]
#set_property -dict {LOC H4 IOSTANDARD LVCMOS18} [get_ports bmc_int]
# Board status
#set_property -dict {LOC J2 IOSTANDARD LVCMOS33} [get_ports {fan_tacho[0]}]
#set_property -dict {LOC J3 IOSTANDARD LVCMOS33} [get_ports {fan_tacho[1]}]
#set_property -dict {LOC A6 IOSTANDARD LVCMOS18} [get_ports {pg[0]}]
#set_property -dict {LOC C7 IOSTANDARD LVCMOS18} [get_ports {pg[1]}]
#set_property -dict {LOC E2 IOSTANDARD LVCMOS33} [get_ports pwrbrk]
# QSFP28 Interfaces
#set_property -dict {LOC Y39 } [get_ports qsfp_0_rx_0_p] ;# MGTYRXP0_130 GTYE4_CHANNEL_X0Y12 / GTYE4_COMMON_X0Y3
#set_property -dict {LOC Y40 } [get_ports qsfp_0_rx_0_n] ;# MGTYRXN0_130 GTYE4_CHANNEL_X0Y12 / GTYE4_COMMON_X0Y3
#set_property -dict {LOC Y34 } [get_ports qsfp_0_tx_0_p] ;# MGTYTXP0_130 GTYE4_CHANNEL_X0Y12 / GTYE4_COMMON_X0Y3
#set_property -dict {LOC Y35 } [get_ports qsfp_0_tx_0_n] ;# MGTYTXN0_130 GTYE4_CHANNEL_X0Y12 / GTYE4_COMMON_X0Y3
#set_property -dict {LOC W41 } [get_ports qsfp_0_rx_1_p] ;# MGTYRXP1_130 GTYE4_CHANNEL_X0Y13 / GTYE4_COMMON_X0Y3
#set_property -dict {LOC W42 } [get_ports qsfp_0_rx_1_n] ;# MGTYRXN1_130 GTYE4_CHANNEL_X0Y13 / GTYE4_COMMON_X0Y3
#set_property -dict {LOC W36 } [get_ports qsfp_0_tx_1_p] ;# MGTYTXP1_130 GTYE4_CHANNEL_X0Y13 / GTYE4_COMMON_X0Y3
#set_property -dict {LOC W37 } [get_ports qsfp_0_tx_1_n] ;# MGTYTXN1_130 GTYE4_CHANNEL_X0Y13 / GTYE4_COMMON_X0Y3
#set_property -dict {LOC V39 } [get_ports qsfp_0_rx_2_p] ;# MGTYRXP2_130 GTYE4_CHANNEL_X0Y14 / GTYE4_COMMON_X0Y3
#set_property -dict {LOC V40 } [get_ports qsfp_0_rx_2_n] ;# MGTYRXN2_130 GTYE4_CHANNEL_X0Y14 / GTYE4_COMMON_X0Y3
#set_property -dict {LOC V34 } [get_ports qsfp_0_tx_2_p] ;# MGTYTXP2_130 GTYE4_CHANNEL_X0Y14 / GTYE4_COMMON_X0Y3
#set_property -dict {LOC V35 } [get_ports qsfp_0_tx_2_n] ;# MGTYTXN2_130 GTYE4_CHANNEL_X0Y14 / GTYE4_COMMON_X0Y3
#set_property -dict {LOC U41 } [get_ports qsfp_0_rx_3_p] ;# MGTYRXP3_130 GTYE4_CHANNEL_X0Y15 / GTYE4_COMMON_X0Y3
#set_property -dict {LOC U42 } [get_ports qsfp_0_rx_3_n] ;# MGTYRXN3_130 GTYE4_CHANNEL_X0Y15 / GTYE4_COMMON_X0Y3
#set_property -dict {LOC U36 } [get_ports qsfp_0_tx_3_p] ;# MGTYTXP3_130 GTYE4_CHANNEL_X0Y15 / GTYE4_COMMON_X0Y3
#set_property -dict {LOC U37 } [get_ports qsfp_0_tx_3_n] ;# MGTYTXN3_130 GTYE4_CHANNEL_X0Y15 / GTYE4_COMMON_X0Y3
#set_property -dict {LOC W32 } [get_ports qsfp_0_mgt_refclk_p] ;# MGTREFCLK0P_130 from U28
#set_property -dict {LOC W33 } [get_ports qsfp_0_mgt_refclk_n] ;# MGTREFCLK0N_130 from U28
#set_property -dict {LOC B9 IOSTANDARD LVCMOS33 PULLUP true} [get_ports qsfp_0_mod_prsnt_n]
#set_property -dict {LOC A8 IOSTANDARD LVCMOS33 PULLUP true} [get_ports qsfp_0_reset_n]
#set_property -dict {LOC A9 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 4} [get_ports qsfp_0_lp_mode]
#set_property -dict {LOC A10 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 4} [get_ports qsfp_0_intr_n]
#set_property -dict {LOC B8 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 4} [get_ports qsfp_0_i2c_scl]
#set_property -dict {LOC B7 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 4} [get_ports qsfp_0_i2c_sda]
# 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 M39 } [get_ports qsfp_1_rx_0_p] ;# MGTYRXP0_132 GTYE4_CHANNEL_X0Y20 / GTYE4_COMMON_X0Y5
#set_property -dict {LOC M40 } [get_ports qsfp_1_rx_0_n] ;# MGTYRXN0_132 GTYE4_CHANNEL_X0Y20 / GTYE4_COMMON_X0Y5
#set_property -dict {LOC M34 } [get_ports qsfp_1_tx_0_p] ;# MGTYTXP0_132 GTYE4_CHANNEL_X0Y20 / GTYE4_COMMON_X0Y5
#set_property -dict {LOC M35 } [get_ports qsfp_1_tx_0_n] ;# MGTYTXN0_132 GTYE4_CHANNEL_X0Y20 / GTYE4_COMMON_X0Y5
#set_property -dict {LOC L41 } [get_ports qsfp_1_rx_1_p] ;# MGTYRXP1_132 GTYE4_CHANNEL_X0Y21 / GTYE4_COMMON_X0Y5
#set_property -dict {LOC L42 } [get_ports qsfp_1_rx_1_n] ;# MGTYRXN1_132 GTYE4_CHANNEL_X0Y21 / GTYE4_COMMON_X0Y5
#set_property -dict {LOC L36 } [get_ports qsfp_1_tx_1_p] ;# MGTYTXP1_132 GTYE4_CHANNEL_X0Y21 / GTYE4_COMMON_X0Y5
#set_property -dict {LOC L37 } [get_ports qsfp_1_tx_1_n] ;# MGTYTXN1_132 GTYE4_CHANNEL_X0Y21 / GTYE4_COMMON_X0Y5
#set_property -dict {LOC K39 } [get_ports qsfp_1_rx_2_p] ;# MGTYRXP2_132 GTYE4_CHANNEL_X0Y22 / GTYE4_COMMON_X0Y5
#set_property -dict {LOC K40 } [get_ports qsfp_1_rx_2_n] ;# MGTYRXN2_132 GTYE4_CHANNEL_X0Y22 / GTYE4_COMMON_X0Y5
#set_property -dict {LOC K34 } [get_ports qsfp_1_tx_2_p] ;# MGTYTXP2_132 GTYE4_CHANNEL_X0Y22 / GTYE4_COMMON_X0Y5
#set_property -dict {LOC K35 } [get_ports qsfp_1_tx_2_n] ;# MGTYTXN2_132 GTYE4_CHANNEL_X0Y22 / GTYE4_COMMON_X0Y5
#set_property -dict {LOC J41 } [get_ports qsfp_1_rx_3_p] ;# MGTYRXP3_132 GTYE4_CHANNEL_X0Y23 / GTYE4_COMMON_X0Y5
#set_property -dict {LOC J42 } [get_ports qsfp_1_rx_3_n] ;# MGTYRXN3_132 GTYE4_CHANNEL_X0Y23 / GTYE4_COMMON_X0Y5
#set_property -dict {LOC J36 } [get_ports qsfp_1_tx_3_p] ;# MGTYTXP3_132 GTYE4_CHANNEL_X0Y23 / GTYE4_COMMON_X0Y5
#set_property -dict {LOC J37 } [get_ports qsfp_1_tx_3_n] ;# MGTYTXN3_132 GTYE4_CHANNEL_X0Y23 / GTYE4_COMMON_X0Y5
#set_property -dict {LOC P30 } [get_ports qsfp_1_mgt_refclk_p] ;# MGTREFCLK0P_132 from U28
#set_property -dict {LOC P31 } [get_ports qsfp_1_mgt_refclk_n] ;# MGTREFCLK0N_132 from U28
#set_property -dict {LOC E10 IOSTANDARD LVCMOS33 PULLUP true} [get_ports qsfp_1_mod_prsnt_n]
#set_property -dict {LOC C10 IOSTANDARD LVCMOS33 PULLUP true} [get_ports qsfp_1_reset_n]
#set_property -dict {LOC D9 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 4} [get_ports qsfp_1_lp_mode]
#set_property -dict {LOC D10 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 4} [get_ports qsfp_1_intr_n]
#set_property -dict {LOC C9 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 4} [get_ports qsfp_1_i2c_scl]
#set_property -dict {LOC D8 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 4} [get_ports qsfp_1_i2c_sda]
# 161.1328125 MHz MGT reference clock
#create_clock -period 6.206 -name qsfp_1_mgt_refclk [get_ports qsfp_1_mgt_refclk_p]
# Expansion connector
#set_property -dict {LOC AG41} [get_ports {exp_rx_p[0]}] ;# MGTYRXP0_128 GTYE4_CHANNEL_X0Y5 / GTYE4_COMMON_X0Y1
#set_property -dict {LOC AG42} [get_ports {exp_rx_n[0]}] ;# MGTYRXN0_128 GTYE4_CHANNEL_X0Y5 / GTYE4_COMMON_X0Y1
#set_property -dict {LOC AG36} [get_ports {exp_tx_p[0]}] ;# MGTYTXP0_128 GTYE4_CHANNEL_X0Y5 / GTYE4_COMMON_X0Y1
#set_property -dict {LOC AG37} [get_ports {exp_tx_n[0]}] ;# MGTYTXN0_128 GTYE4_CHANNEL_X0Y5 / GTYE4_COMMON_X0Y1
#set_property -dict {LOC AH39} [get_ports {exp_rx_p[1]}] ;# MGTYRXP0_128 GTYE4_CHANNEL_X0Y4 / GTYE4_COMMON_X0Y1
#set_property -dict {LOC AH40} [get_ports {exp_rx_n[1]}] ;# MGTYRXN0_128 GTYE4_CHANNEL_X0Y4 / GTYE4_COMMON_X0Y1
#set_property -dict {LOC AH34} [get_ports {exp_tx_p[1]}] ;# MGTYTXP0_128 GTYE4_CHANNEL_X0Y4 / GTYE4_COMMON_X0Y1
#set_property -dict {LOC AH35} [get_ports {exp_tx_n[1]}] ;# MGTYTXN0_128 GTYE4_CHANNEL_X0Y4 / GTYE4_COMMON_X0Y1
#set_property -dict {LOC AJ41} [get_ports {exp_rx_p[2]}] ;# MGTYRXP0_127 GTYE4_CHANNEL_X0Y3 / GTYE4_COMMON_X0Y0
#set_property -dict {LOC AJ42} [get_ports {exp_rx_n[2]}] ;# MGTYRXN0_127 GTYE4_CHANNEL_X0Y3 / GTYE4_COMMON_X0Y0
#set_property -dict {LOC AJ36} [get_ports {exp_tx_p[2]}] ;# MGTYTXP0_127 GTYE4_CHANNEL_X0Y3 / GTYE4_COMMON_X0Y0
#set_property -dict {LOC AJ37} [get_ports {exp_tx_n[2]}] ;# MGTYTXN0_127 GTYE4_CHANNEL_X0Y3 / GTYE4_COMMON_X0Y0
#set_property -dict {LOC AK39} [get_ports {exp_rx_p[3]}] ;# MGTYRXP0_127 GTYE4_CHANNEL_X0Y2 / GTYE4_COMMON_X0Y0
#set_property -dict {LOC AK40} [get_ports {exp_rx_n[3]}] ;# MGTYRXN0_127 GTYE4_CHANNEL_X0Y2 / GTYE4_COMMON_X0Y0
#set_property -dict {LOC AK34} [get_ports {exp_tx_p[3]}] ;# MGTYTXP0_127 GTYE4_CHANNEL_X0Y2 / GTYE4_COMMON_X0Y0
#set_property -dict {LOC AK35} [get_ports {exp_tx_n[3]}] ;# MGTYTXN0_127 GTYE4_CHANNEL_X0Y2 / GTYE4_COMMON_X0Y0
#set_property -dict {LOC AL41} [get_ports {exp_rx_p[4]}] ;# MGTYRXP0_127 GTYE4_CHANNEL_X0Y1 / GTYE4_COMMON_X0Y0
#set_property -dict {LOC AL42} [get_ports {exp_rx_n[4]}] ;# MGTYRXN0_127 GTYE4_CHANNEL_X0Y1 / GTYE4_COMMON_X0Y0
#set_property -dict {LOC AL36} [get_ports {exp_tx_p[4]}] ;# MGTYTXP0_127 GTYE4_CHANNEL_X0Y1 / GTYE4_COMMON_X0Y0
#set_property -dict {LOC AL37} [get_ports {exp_tx_n[4]}] ;# MGTYTXN0_127 GTYE4_CHANNEL_X0Y1 / GTYE4_COMMON_X0Y0
#set_property -dict {LOC AM39} [get_ports {exp_rx_p[5]}] ;# MGTYRXP0_127 GTYE4_CHANNEL_X0Y0 / GTYE4_COMMON_X0Y0
#set_property -dict {LOC AM40} [get_ports {exp_rx_n[5]}] ;# MGTYRXN0_127 GTYE4_CHANNEL_X0Y0 / GTYE4_COMMON_X0Y0
#set_property -dict {LOC AM34} [get_ports {exp_tx_p[5]}] ;# MGTYTXP0_127 GTYE4_CHANNEL_X0Y0 / GTYE4_COMMON_X0Y0
#set_property -dict {LOC AM35} [get_ports {exp_tx_n[5]}] ;# MGTYTXN0_127 GTYE4_CHANNEL_X0Y0 / GTYE4_COMMON_X0Y0
#set_property -dict {LOC AL32} [get_ports exp_refclk_0_p] ;# MGTREFCLK0P_128 from U28
#set_property -dict {LOC AL33} [get_ports exp_refclk_0_n] ;# MGTREFCLK0N_128 from U28
#set_property -dict {LOC AG32} [get_ports exp_refclk_1_p] ;# MGTREFCLK0P_127 from U28
#set_property -dict {LOC AG33} [get_ports exp_refclk_1_n] ;# MGTREFCLK0N_127 from U28
#set_property -dict {LOC E3 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 4} [get_ports {exp_gpio[0]}]
#set_property -dict {LOC F3 IOSTANDARD LVCMOS33 SLEW SLOW DRIVE 4} [get_ports {exp_gpio[1]}]
# 161.1328125 MHz MGT reference clock
#create_clock -period 6.206 -name exp_refclk_0 [get_ports exp_refclk_0_p]
#create_clock -period 6.206 -name exp_refclk_1 [get_ports exp_refclk_1_p]
# PCIe Interface
set_property -dict {LOC AG2 } [get_ports {pcie_rx_p[0]}] ;# MGTHRXP3_227 GTHE4_CHANNEL_X0Y15 / GTHE4_COMMON_X0Y3
#set_property -dict {LOC AG1 } [get_ports {pcie_rx_n[0]}] ;# MGTHRXN3_227 GTHE4_CHANNEL_X0Y15 / GTHE4_COMMON_X0Y3
set_property -dict {LOC AG6 } [get_ports {pcie_tx_p[0]}] ;# MGTHTXP3_227 GTHE4_CHANNEL_X0Y15 / GTHE4_COMMON_X0Y3
#set_property -dict {LOC AG5 } [get_ports {pcie_tx_n[0]}] ;# MGTHTXN3_227 GTHE4_CHANNEL_X0Y15 / GTHE4_COMMON_X0Y3
set_property -dict {LOC AH4 } [get_ports {pcie_rx_p[1]}] ;# MGTHRXP2_227 GTHE4_CHANNEL_X0Y14 / GTHE4_COMMON_X0Y3
#set_property -dict {LOC AH3 } [get_ports {pcie_rx_n[1]}] ;# MGTHRXN2_227 GTHE4_CHANNEL_X0Y14 / GTHE4_COMMON_X0Y3
set_property -dict {LOC AH8 } [get_ports {pcie_tx_p[1]}] ;# MGTHTXP2_227 GTHE4_CHANNEL_X0Y14 / GTHE4_COMMON_X0Y3
#set_property -dict {LOC AH7 } [get_ports {pcie_tx_n[1]}] ;# MGTHTXN2_227 GTHE4_CHANNEL_X0Y14 / GTHE4_COMMON_X0Y3
set_property -dict {LOC AJ2 } [get_ports {pcie_rx_p[2]}] ;# MGTHRXP1_227 GTHE4_CHANNEL_X0Y13 / GTHE4_COMMON_X0Y3
#set_property -dict {LOC AJ1 } [get_ports {pcie_rx_n[2]}] ;# MGTHRXN1_227 GTHE4_CHANNEL_X0Y13 / GTHE4_COMMON_X0Y3
set_property -dict {LOC AJ6 } [get_ports {pcie_tx_p[2]}] ;# MGTHTXP1_227 GTHE4_CHANNEL_X0Y13 / GTHE4_COMMON_X0Y3
#set_property -dict {LOC AJ5 } [get_ports {pcie_tx_n[2]}] ;# MGTHTXN1_227 GTHE4_CHANNEL_X0Y13 / GTHE4_COMMON_X0Y3
set_property -dict {LOC AK4 } [get_ports {pcie_rx_p[3]}] ;# MGTHRXP0_227 GTHE4_CHANNEL_X0Y12 / GTHE4_COMMON_X0Y3
#set_property -dict {LOC AK3 } [get_ports {pcie_rx_n[3]}] ;# MGTHRXN0_227 GTHE4_CHANNEL_X0Y12 / GTHE4_COMMON_X0Y3
set_property -dict {LOC AK8 } [get_ports {pcie_tx_p[3]}] ;# MGTHTXP0_227 GTHE4_CHANNEL_X0Y12 / GTHE4_COMMON_X0Y3
#set_property -dict {LOC AK7 } [get_ports {pcie_tx_n[3]}] ;# MGTHTXN0_227 GTHE4_CHANNEL_X0Y12 / GTHE4_COMMON_X0Y3
set_property -dict {LOC AL2 } [get_ports {pcie_rx_p[4]}] ;# MGTHRXP3_226 GTHE4_CHANNEL_X0Y11 / GTHE4_COMMON_X0Y2
#set_property -dict {LOC AL1 } [get_ports {pcie_rx_n[4]}] ;# MGTHRXN3_226 GTHE4_CHANNEL_X0Y11 / GTHE4_COMMON_X0Y2
set_property -dict {LOC AL6 } [get_ports {pcie_tx_p[4]}] ;# MGTHTXP3_226 GTHE4_CHANNEL_X0Y11 / GTHE4_COMMON_X0Y2
#set_property -dict {LOC AL5 } [get_ports {pcie_tx_n[4]}] ;# MGTHTXN3_226 GTHE4_CHANNEL_X0Y11 / GTHE4_COMMON_X0Y2
set_property -dict {LOC AM4 } [get_ports {pcie_rx_p[5]}] ;# MGTHRXP2_226 GTHE4_CHANNEL_X0Y10 / GTHE4_COMMON_X0Y2
#set_property -dict {LOC AM3 } [get_ports {pcie_rx_n[5]}] ;# MGTHRXN2_226 GTHE4_CHANNEL_X0Y10 / GTHE4_COMMON_X0Y2
set_property -dict {LOC AM8 } [get_ports {pcie_tx_p[5]}] ;# MGTHTXP2_226 GTHE4_CHANNEL_X0Y10 / GTHE4_COMMON_X0Y2
#set_property -dict {LOC AM7 } [get_ports {pcie_tx_n[5]}] ;# MGTHTXN2_226 GTHE4_CHANNEL_X0Y10 / GTHE4_COMMON_X0Y2
set_property -dict {LOC AN2 } [get_ports {pcie_rx_p[6]}] ;# MGTHRXP1_226 GTHE4_CHANNEL_X0Y9 / GTHE4_COMMON_X0Y2
#set_property -dict {LOC AN1 } [get_ports {pcie_rx_n[6]}] ;# MGTHRXN1_226 GTHE4_CHANNEL_X0Y9 / GTHE4_COMMON_X0Y2
set_property -dict {LOC AN6 } [get_ports {pcie_tx_p[6]}] ;# MGTHTXP1_226 GTHE4_CHANNEL_X0Y9 / GTHE4_COMMON_X0Y2
#set_property -dict {LOC AN5 } [get_ports {pcie_tx_n[6]}] ;# MGTHTXN1_226 GTHE4_CHANNEL_X0Y9 / GTHE4_COMMON_X0Y2
set_property -dict {LOC AP4 } [get_ports {pcie_rx_p[7]}] ;# MGTHRXP0_226 GTHE4_CHANNEL_X0Y8 / GTHE4_COMMON_X0Y2
#set_property -dict {LOC AP3 } [get_ports {pcie_rx_n[7]}] ;# MGTHRXN0_226 GTHE4_CHANNEL_X0Y8 / GTHE4_COMMON_X0Y2
set_property -dict {LOC AP8 } [get_ports {pcie_tx_p[7]}] ;# MGTHTXP0_226 GTHE4_CHANNEL_X0Y8 / GTHE4_COMMON_X0Y2
#set_property -dict {LOC AP7 } [get_ports {pcie_tx_n[7]}] ;# MGTHTXN0_226 GTHE4_CHANNEL_X0Y8 / GTHE4_COMMON_X0Y2
set_property -dict {LOC AR2 } [get_ports {pcie_rx_p[8]}] ;# MGTHRXP3_225 GTHE4_CHANNEL_X0Y7 / GTHE4_COMMON_X0Y1
#set_property -dict {LOC AR1 } [get_ports {pcie_rx_n[8]}] ;# MGTHRXN3_225 GTHE4_CHANNEL_X0Y7 / GTHE4_COMMON_X0Y1
set_property -dict {LOC AR6 } [get_ports {pcie_tx_p[8]}] ;# MGTHTXP3_225 GTHE4_CHANNEL_X0Y7 / GTHE4_COMMON_X0Y1
#set_property -dict {LOC AR5 } [get_ports {pcie_tx_n[8]}] ;# MGTHTXN3_225 GTHE4_CHANNEL_X0Y7 / GTHE4_COMMON_X0Y1
set_property -dict {LOC AT4 } [get_ports {pcie_rx_p[9]}] ;# MGTHRXP2_225 GTHE4_CHANNEL_X0Y6 / GTHE4_COMMON_X0Y1
#set_property -dict {LOC AT3 } [get_ports {pcie_rx_n[9]}] ;# MGTHRXN2_225 GTHE4_CHANNEL_X0Y6 / GTHE4_COMMON_X0Y1
set_property -dict {LOC AT8 } [get_ports {pcie_tx_p[9]}] ;# MGTHTXP2_225 GTHE4_CHANNEL_X0Y6 / GTHE4_COMMON_X0Y1
#set_property -dict {LOC AT7 } [get_ports {pcie_tx_n[9]}] ;# MGTHTXN2_225 GTHE4_CHANNEL_X0Y6 / GTHE4_COMMON_X0Y1
set_property -dict {LOC AU2 } [get_ports {pcie_rx_p[10]}] ;# MGTHRXP1_225 GTHE4_CHANNEL_X0Y5 / GTHE4_COMMON_X0Y1
#set_property -dict {LOC AU1 } [get_ports {pcie_rx_n[10]}] ;# MGTHRXN1_225 GTHE4_CHANNEL_X0Y5 / GTHE4_COMMON_X0Y1
set_property -dict {LOC AU6 } [get_ports {pcie_tx_p[10]}] ;# MGTHTXP1_225 GTHE4_CHANNEL_X0Y5 / GTHE4_COMMON_X0Y1
#set_property -dict {LOC AU5 } [get_ports {pcie_tx_n[10]}] ;# MGTHTXN1_225 GTHE4_CHANNEL_X0Y5 / GTHE4_COMMON_X0Y1
set_property -dict {LOC AV4 } [get_ports {pcie_rx_p[11]}] ;# MGTHRXP0_225 GTHE4_CHANNEL_X0Y4 / GTHE4_COMMON_X0Y1
#set_property -dict {LOC AV3 } [get_ports {pcie_rx_n[11]}] ;# MGTHRXN0_225 GTHE4_CHANNEL_X0Y4 / GTHE4_COMMON_X0Y1
set_property -dict {LOC AV8 } [get_ports {pcie_tx_p[11]}] ;# MGTHTXP0_225 GTHE4_CHANNEL_X0Y4 / GTHE4_COMMON_X0Y1
#set_property -dict {LOC AV7 } [get_ports {pcie_tx_n[11]}] ;# MGTHTXN0_225 GTHE4_CHANNEL_X0Y4 / GTHE4_COMMON_X0Y1
set_property -dict {LOC AW2 } [get_ports {pcie_rx_p[12]}] ;# MGTHRXP3_224 GTHE4_CHANNEL_X0Y3 / GTHE4_COMMON_X0Y0
#set_property -dict {LOC AW1 } [get_ports {pcie_rx_n[12]}] ;# MGTHRXN3_224 GTHE4_CHANNEL_X0Y3 / GTHE4_COMMON_X0Y0
set_property -dict {LOC AW6 } [get_ports {pcie_tx_p[12]}] ;# MGTHTXP3_224 GTHE4_CHANNEL_X0Y3 / GTHE4_COMMON_X0Y0
#set_property -dict {LOC AW5 } [get_ports {pcie_tx_n[12]}] ;# MGTHTXN3_224 GTHE4_CHANNEL_X0Y3 / GTHE4_COMMON_X0Y0
set_property -dict {LOC AY4 } [get_ports {pcie_rx_p[13]}] ;# MGTHRXP2_224 GTHE4_CHANNEL_X0Y2 / GTHE4_COMMON_X0Y0
#set_property -dict {LOC AY3 } [get_ports {pcie_rx_n[13]}] ;# MGTHRXN2_224 GTHE4_CHANNEL_X0Y2 / GTHE4_COMMON_X0Y0
set_property -dict {LOC AY8 } [get_ports {pcie_tx_p[13]}] ;# MGTHTXP2_224 GTHE4_CHANNEL_X0Y2 / GTHE4_COMMON_X0Y0
#set_property -dict {LOC AY7 } [get_ports {pcie_tx_n[13]}] ;# MGTHTXN2_224 GTHE4_CHANNEL_X0Y2 / GTHE4_COMMON_X0Y0
set_property -dict {LOC BA2 } [get_ports {pcie_rx_p[14]}] ;# MGTHRXP1_224 GTHE4_CHANNEL_X0Y1 / GTHE4_COMMON_X0Y0
#set_property -dict {LOC BA1 } [get_ports {pcie_rx_n[14]}] ;# MGTHRXN1_224 GTHE4_CHANNEL_X0Y1 / GTHE4_COMMON_X0Y0
set_property -dict {LOC BA6 } [get_ports {pcie_tx_p[14]}] ;# MGTHTXP1_224 GTHE4_CHANNEL_X0Y1 / GTHE4_COMMON_X0Y0
#set_property -dict {LOC BA5 } [get_ports {pcie_tx_n[14]}] ;# MGTHTXN1_224 GTHE4_CHANNEL_X0Y1 / GTHE4_COMMON_X0Y0
set_property -dict {LOC BB4 } [get_ports {pcie_rx_p[15]}] ;# MGTHRXP0_224 GTHE4_CHANNEL_X0Y0 / GTHE4_COMMON_X0Y0
#set_property -dict {LOC BB3 } [get_ports {pcie_rx_n[15]}] ;# MGTHRXN0_224 GTHE4_CHANNEL_X0Y0 / GTHE4_COMMON_X0Y0
set_property -dict {LOC BB8 } [get_ports {pcie_tx_p[15]}] ;# MGTHTXP0_224 GTHE4_CHANNEL_X0Y0 / GTHE4_COMMON_X0Y0
#set_property -dict {LOC BB7 } [get_ports {pcie_tx_n[15]}] ;# MGTHTXN0_224 GTHE4_CHANNEL_X0Y0 / GTHE4_COMMON_X0Y0
set_property -dict {LOC AN10} [get_ports pcie_refclk_p] ;# MGTREFCLK0P_226
#set_property -dict {LOC AN9 } [get_ports pcie_refclk_n] ;# MGTREFCLK0N_226
set_property -dict {LOC G1 IOSTANDARD LVCMOS33 PULLUP true} [get_ports pcie_rst_n]
# 100 MHz MGT reference clock
create_clock -period 10 -name pcie_mgt_refclk [get_ports pcie_refclk_p]

View File

@ -0,0 +1,49 @@
# FPGA settings
FPGA_PART = xcku15p-ffve1760-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/sync_reset.v
SYN_FILES += rtl/sync_signal.v
SYN_FILES += rtl/led_sreg_driver.v
SYN_FILES += rtl/axi_ram.v
SYN_FILES += rtl/axis_register.v
SYN_FILES += lib/pcie/rtl/axis_arb_mux.v
SYN_FILES += lib/pcie/rtl/pcie_us_axil_master.v
SYN_FILES += lib/pcie/rtl/pcie_us_axi_dma.v
SYN_FILES += lib/pcie/rtl/pcie_us_axi_dma_rd.v
SYN_FILES += lib/pcie/rtl/pcie_us_axi_dma_wr.v
SYN_FILES += lib/pcie/rtl/pcie_tag_manager.v
SYN_FILES += lib/pcie/rtl/pcie_us_axi_master.v
SYN_FILES += lib/pcie/rtl/pcie_us_axi_master_rd.v
SYN_FILES += lib/pcie/rtl/pcie_us_axi_master_wr.v
SYN_FILES += lib/pcie/rtl/pcie_us_axis_cq_demux.v
SYN_FILES += lib/pcie/rtl/pcie_us_cfg.v
SYN_FILES += lib/pcie/rtl/pcie_us_msi.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

View File

@ -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 {020000} \
CONFIG.PF0_DEVICE_ID {0001} \
CONFIG.PF0_MSI_CAP_MULTIMSGCAP {32_vectors} \
CONFIG.PF0_SUBSYSTEM_ID {0001} \
CONFIG.PF0_SUBSYSTEM_VENDOR_ID {1234} \
CONFIG.PF0_Use_Class_Code_Lookup_Assistant {true} \
CONFIG.pf0_class_code_sub {00} \
CONFIG.pf0_base_class_menu {Network_controller} \
CONFIG.pf0_sub_class_interface_menu {Ethernet_controller} \
CONFIG.pf0_bar0_scale {Megabytes} \
CONFIG.pf0_bar0_size {16} \
CONFIG.pf0_bar1_enabled {true} \
CONFIG.pf0_bar1_type {Memory} \
CONFIG.pf0_bar1_scale {Megabytes} \
CONFIG.pf0_bar1_size {16} \
CONFIG.vendor_id {1234} \
CONFIG.en_msi_per_vec_masking {true} \
] [get_ips pcie4_uscale_plus_0]

View File

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

View File

@ -0,0 +1,365 @@
/*
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
`timescale 1ns / 1ps
/*
* AXI4 RAM
*/
module axi_ram #
(
parameter DATA_WIDTH = 32, // width of data bus in bits
parameter ADDR_WIDTH = 16, // width of address bus in bits
parameter STRB_WIDTH = (DATA_WIDTH/8),
parameter ID_WIDTH = 8,
parameter PIPELINE_OUTPUT = 0
)
(
input wire clk,
input wire rst,
input wire [ID_WIDTH-1:0] s_axi_awid,
input wire [ADDR_WIDTH-1:0] s_axi_awaddr,
input wire [7:0] s_axi_awlen,
input wire [2:0] s_axi_awsize,
input wire [1:0] s_axi_awburst,
input wire s_axi_awlock,
input wire [3:0] s_axi_awcache,
input wire [2:0] s_axi_awprot,
input wire s_axi_awvalid,
output wire s_axi_awready,
input wire [DATA_WIDTH-1:0] s_axi_wdata,
input wire [STRB_WIDTH-1:0] s_axi_wstrb,
input wire s_axi_wlast,
input wire s_axi_wvalid,
output wire s_axi_wready,
output wire [ID_WIDTH-1:0] s_axi_bid,
output wire [1:0] s_axi_bresp,
output wire s_axi_bvalid,
input wire s_axi_bready,
input wire [ID_WIDTH-1:0] s_axi_arid,
input wire [ADDR_WIDTH-1:0] s_axi_araddr,
input wire [7:0] s_axi_arlen,
input wire [2:0] s_axi_arsize,
input wire [1:0] s_axi_arburst,
input wire s_axi_arlock,
input wire [3:0] s_axi_arcache,
input wire [2:0] s_axi_arprot,
input wire s_axi_arvalid,
output wire s_axi_arready,
output wire [ID_WIDTH-1:0] s_axi_rid,
output wire [DATA_WIDTH-1:0] s_axi_rdata,
output wire [1:0] s_axi_rresp,
output wire s_axi_rlast,
output wire s_axi_rvalid,
input wire s_axi_rready
);
parameter VALID_ADDR_WIDTH = ADDR_WIDTH - $clog2(STRB_WIDTH);
parameter WORD_WIDTH = STRB_WIDTH;
parameter WORD_SIZE = DATA_WIDTH/WORD_WIDTH;
// bus width assertions
initial begin
if (WORD_SIZE * STRB_WIDTH != DATA_WIDTH) begin
$error("Error: AXI data width not evenly divisble");
$finish;
end
if (2**$clog2(WORD_WIDTH) != WORD_WIDTH) begin
$error("Error: AXI word width must be even power of two");
$finish;
end
end
localparam [0:0]
READ_STATE_IDLE = 1'd0,
READ_STATE_BURST = 1'd1;
reg [0:0] read_state_reg = READ_STATE_IDLE, read_state_next;
localparam [1:0]
WRITE_STATE_IDLE = 2'd0,
WRITE_STATE_BURST = 2'd1,
WRITE_STATE_RESP = 2'd2;
reg [1:0] write_state_reg = WRITE_STATE_IDLE, write_state_next;
reg mem_wr_en;
reg mem_rd_en;
reg [ID_WIDTH-1:0] read_id_reg = {ID_WIDTH{1'b0}}, read_id_next;
reg [ADDR_WIDTH-1:0] read_addr_reg = {ADDR_WIDTH{1'b0}}, read_addr_next;
reg [7:0] read_count_reg = 8'd0, read_count_next;
reg [2:0] read_size_reg = 3'd0, read_size_next;
reg [1:0] read_burst_reg = 2'd0, read_burst_next;
reg [ID_WIDTH-1:0] write_id_reg = {ID_WIDTH{1'b0}}, write_id_next;
reg [ADDR_WIDTH-1:0] write_addr_reg = {ADDR_WIDTH{1'b0}}, write_addr_next;
reg [7:0] write_count_reg = 8'd0, write_count_next;
reg [2:0] write_size_reg = 3'd0, write_size_next;
reg [1:0] write_burst_reg = 2'd0, write_burst_next;
reg s_axi_awready_reg = 1'b0, s_axi_awready_next;
reg s_axi_wready_reg = 1'b0, s_axi_wready_next;
reg [ID_WIDTH-1:0] s_axi_bid_reg = {ID_WIDTH{1'b0}}, s_axi_bid_next;
reg s_axi_bvalid_reg = 1'b0, s_axi_bvalid_next;
reg s_axi_arready_reg = 1'b0, s_axi_arready_next;
reg [ID_WIDTH-1:0] s_axi_rid_reg = {ID_WIDTH{1'b0}}, s_axi_rid_next;
reg [DATA_WIDTH-1:0] s_axi_rdata_reg = {DATA_WIDTH{1'b0}}, s_axi_rdata_next;
reg s_axi_rlast_reg = 1'b0, s_axi_rlast_next;
reg s_axi_rvalid_reg = 1'b0, s_axi_rvalid_next;
reg [ID_WIDTH-1:0] s_axi_rid_pipe_reg = {ID_WIDTH{1'b0}};
reg [DATA_WIDTH-1:0] s_axi_rdata_pipe_reg = {DATA_WIDTH{1'b0}};
reg s_axi_rlast_pipe_reg = 1'b0;
reg s_axi_rvalid_pipe_reg = 1'b0;
// (* RAM_STYLE="BLOCK" *)
reg [DATA_WIDTH-1:0] mem[(2**VALID_ADDR_WIDTH)-1:0];
wire [VALID_ADDR_WIDTH-1:0] s_axi_awaddr_valid = s_axi_awaddr >> (ADDR_WIDTH - VALID_ADDR_WIDTH);
wire [VALID_ADDR_WIDTH-1:0] s_axi_araddr_valid = s_axi_araddr >> (ADDR_WIDTH - VALID_ADDR_WIDTH);
wire [VALID_ADDR_WIDTH-1:0] read_addr_valid = read_addr_reg >> (ADDR_WIDTH - VALID_ADDR_WIDTH);
wire [VALID_ADDR_WIDTH-1:0] write_addr_valid = write_addr_reg >> (ADDR_WIDTH - VALID_ADDR_WIDTH);
assign s_axi_awready = s_axi_awready_reg;
assign s_axi_wready = s_axi_wready_reg;
assign s_axi_bid = s_axi_bid_reg;
assign s_axi_bresp = 2'b00;
assign s_axi_bvalid = s_axi_bvalid_reg;
assign s_axi_arready = s_axi_arready_reg;
assign s_axi_rid = PIPELINE_OUTPUT ? s_axi_rid_pipe_reg : s_axi_rid_reg;
assign s_axi_rdata = PIPELINE_OUTPUT ? s_axi_rdata_pipe_reg : s_axi_rdata_reg;
assign s_axi_rresp = 2'b00;
assign s_axi_rlast = PIPELINE_OUTPUT ? s_axi_rlast_pipe_reg : s_axi_rlast_reg;
assign s_axi_rvalid = PIPELINE_OUTPUT ? s_axi_rvalid_pipe_reg : s_axi_rvalid_reg;
integer i, j;
initial begin
// two nested loops for smaller number of iterations per loop
// workaround for synthesizer complaints about large loop counts
for (i = 0; i < 2**ADDR_WIDTH; i = i + 2**(ADDR_WIDTH/2)) begin
for (j = i; j < i + 2**(ADDR_WIDTH/2); j = j + 1) begin
mem[j] = 0;
end
end
end
always @* begin
write_state_next = WRITE_STATE_IDLE;
mem_wr_en = 1'b0;
write_id_next = write_id_reg;
write_addr_next = write_addr_reg;
write_count_next = write_count_reg;
write_size_next = write_size_reg;
write_burst_next = write_burst_reg;
s_axi_awready_next = 1'b0;
s_axi_wready_next = 1'b0;
s_axi_bid_next = s_axi_bid_reg;
s_axi_bvalid_next = s_axi_bvalid_reg && !s_axi_bready;
case (write_state_reg)
WRITE_STATE_IDLE: begin
s_axi_awready_next = 1'b1;
if (s_axi_awready && s_axi_awvalid) begin
write_id_next = s_axi_awid;
write_addr_next = s_axi_awaddr;
write_count_next = s_axi_awlen;
write_size_next = s_axi_awsize < $clog2(STRB_WIDTH) ? s_axi_awsize : $clog2(STRB_WIDTH);
write_burst_next = s_axi_awburst;
s_axi_awready_next = 1'b0;
s_axi_wready_next = 1'b1;
write_state_next = WRITE_STATE_BURST;
end else begin
write_state_next = WRITE_STATE_IDLE;
end
end
WRITE_STATE_BURST: begin
s_axi_wready_next = 1'b1;
if (s_axi_wready && s_axi_wvalid) begin
mem_wr_en = 1'b1;
if (write_burst_reg != 2'b00) begin
write_addr_next = write_addr_reg + (1 << write_size_reg);
end
write_count_next = write_count_reg - 1;
if (write_count_reg > 0) begin
write_state_next = WRITE_STATE_BURST;
end else begin
s_axi_wready_next = 1'b0;
if (s_axi_bready || !s_axi_bvalid) begin
s_axi_bid_next = write_id_reg;
s_axi_bvalid_next = 1'b1;
s_axi_awready_next = 1'b1;
write_state_next = WRITE_STATE_IDLE;
end else begin
write_state_next = WRITE_STATE_RESP;
end
end
end else begin
write_state_next = WRITE_STATE_BURST;
end
end
WRITE_STATE_RESP: begin
if (s_axi_bready || !s_axi_bvalid) begin
s_axi_bid_next = write_id_reg;
s_axi_bvalid_next = 1'b1;
s_axi_awready_next = 1'b1;
write_state_next = WRITE_STATE_IDLE;
end else begin
write_state_next = WRITE_STATE_RESP;
end
end
endcase
end
always @(posedge clk) begin
if (rst) begin
write_state_reg <= WRITE_STATE_IDLE;
s_axi_awready_reg <= 1'b0;
s_axi_wready_reg <= 1'b0;
s_axi_bvalid_reg <= 1'b0;
end else begin
write_state_reg <= write_state_next;
s_axi_awready_reg <= s_axi_awready_next;
s_axi_wready_reg <= s_axi_wready_next;
s_axi_bvalid_reg <= s_axi_bvalid_next;
end
write_id_reg <= write_id_next;
write_addr_reg <= write_addr_next;
write_count_reg <= write_count_next;
write_size_reg <= write_size_next;
write_burst_reg <= write_burst_next;
s_axi_bid_reg <= s_axi_bid_next;
for (i = 0; i < WORD_WIDTH; i = i + 1) begin
if (mem_wr_en & s_axi_wstrb[i]) begin
mem[write_addr_valid][WORD_SIZE*i +: WORD_SIZE] <= s_axi_wdata[WORD_SIZE*i +: WORD_SIZE];
end
end
end
always @* begin
read_state_next = READ_STATE_IDLE;
mem_rd_en = 1'b0;
s_axi_rid_next = s_axi_rid_reg;
s_axi_rlast_next = s_axi_rlast_reg;
s_axi_rvalid_next = s_axi_rvalid_reg && !(s_axi_rready || (PIPELINE_OUTPUT && !s_axi_rvalid_pipe_reg));
read_id_next = read_id_reg;
read_addr_next = read_addr_reg;
read_count_next = read_count_reg;
read_size_next = read_size_reg;
read_burst_next = read_burst_reg;
s_axi_arready_next = 1'b0;
case (read_state_reg)
READ_STATE_IDLE: begin
s_axi_arready_next = 1'b1;
if (s_axi_arready && s_axi_arvalid) begin
read_id_next = s_axi_arid;
read_addr_next = s_axi_araddr;
read_count_next = s_axi_arlen;
read_size_next = s_axi_arsize < $clog2(STRB_WIDTH) ? s_axi_arsize : $clog2(STRB_WIDTH);
read_burst_next = s_axi_arburst;
s_axi_arready_next = 1'b0;
read_state_next = READ_STATE_BURST;
end else begin
read_state_next = READ_STATE_IDLE;
end
end
READ_STATE_BURST: begin
if (s_axi_rready || (PIPELINE_OUTPUT && !s_axi_rvalid_pipe_reg) || !s_axi_rvalid_reg) begin
mem_rd_en = 1'b1;
s_axi_rvalid_next = 1'b1;
s_axi_rid_next = read_id_reg;
s_axi_rlast_next = read_count_reg == 0;
if (read_burst_reg != 2'b00) begin
read_addr_next = read_addr_reg + (1 << read_size_reg);
end
read_count_next = read_count_reg - 1;
if (read_count_reg > 0) begin
read_state_next = READ_STATE_BURST;
end else begin
s_axi_arready_next = 1'b1;
read_state_next = READ_STATE_IDLE;
end
end else begin
read_state_next = READ_STATE_BURST;
end
end
endcase
end
always @(posedge clk) begin
if (rst) begin
read_state_reg <= READ_STATE_IDLE;
s_axi_arready_reg <= 1'b0;
s_axi_rvalid_reg <= 1'b0;
s_axi_rvalid_pipe_reg <= 1'b0;
end else begin
read_state_reg <= read_state_next;
s_axi_arready_reg <= s_axi_arready_next;
s_axi_rvalid_reg <= s_axi_rvalid_next;
if (!s_axi_rvalid_pipe_reg || s_axi_rready) begin
s_axi_rvalid_pipe_reg <= s_axi_rvalid_reg;
end
end
read_id_reg <= read_id_next;
read_addr_reg <= read_addr_next;
read_count_reg <= read_count_next;
read_size_reg <= read_size_next;
read_burst_reg <= read_burst_next;
s_axi_rid_reg <= s_axi_rid_next;
s_axi_rlast_reg <= s_axi_rlast_next;
if (mem_rd_en) begin
s_axi_rdata_reg <= mem[read_addr_valid];
end
if (!s_axi_rvalid_pipe_reg || s_axi_rready) begin
s_axi_rid_pipe_reg <= s_axi_rid_reg;
s_axi_rdata_pipe_reg <= s_axi_rdata_reg;
s_axi_rlast_pipe_reg <= s_axi_rlast_reg;
end
end
endmodule

View File

@ -0,0 +1,264 @@
/*
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
`timescale 1ns / 1ps
/*
* AXI4-Stream register
*/
module axis_register #
(
parameter DATA_WIDTH = 8,
parameter KEEP_ENABLE = (DATA_WIDTH>8),
parameter KEEP_WIDTH = (DATA_WIDTH/8),
parameter LAST_ENABLE = 1,
parameter ID_ENABLE = 0,
parameter ID_WIDTH = 8,
parameter DEST_ENABLE = 0,
parameter DEST_WIDTH = 8,
parameter USER_ENABLE = 1,
parameter USER_WIDTH = 1,
parameter REG_TYPE = 2
)
(
input wire clk,
input wire rst,
/*
* AXI Stream input
*/
input wire [DATA_WIDTH-1:0] s_axis_tdata,
input wire [KEEP_WIDTH-1:0] s_axis_tkeep,
input wire s_axis_tvalid,
output wire s_axis_tready,
input wire s_axis_tlast,
input wire [ID_WIDTH-1:0] s_axis_tid,
input wire [DEST_WIDTH-1:0] s_axis_tdest,
input wire [USER_WIDTH-1:0] s_axis_tuser,
/*
* AXI Stream output
*/
output wire [DATA_WIDTH-1:0] m_axis_tdata,
output wire [KEEP_WIDTH-1:0] m_axis_tkeep,
output wire m_axis_tvalid,
input wire m_axis_tready,
output wire m_axis_tlast,
output wire [ID_WIDTH-1:0] m_axis_tid,
output wire [DEST_WIDTH-1:0] m_axis_tdest,
output wire [USER_WIDTH-1:0] m_axis_tuser
);
generate
if (REG_TYPE > 1) begin
// skid buffer, no bubble cycles
// datapath registers
reg s_axis_tready_reg = 1'b0;
reg [DATA_WIDTH-1:0] m_axis_tdata_reg = {DATA_WIDTH{1'b0}};
reg [KEEP_WIDTH-1:0] m_axis_tkeep_reg = {KEEP_WIDTH{1'b0}};
reg m_axis_tvalid_reg = 1'b0, m_axis_tvalid_next;
reg m_axis_tlast_reg = 1'b0;
reg [ID_WIDTH-1:0] m_axis_tid_reg = {ID_WIDTH{1'b0}};
reg [DEST_WIDTH-1:0] m_axis_tdest_reg = {DEST_WIDTH{1'b0}};
reg [USER_WIDTH-1:0] m_axis_tuser_reg = {USER_WIDTH{1'b0}};
reg [DATA_WIDTH-1:0] temp_m_axis_tdata_reg = {DATA_WIDTH{1'b0}};
reg [KEEP_WIDTH-1:0] temp_m_axis_tkeep_reg = {KEEP_WIDTH{1'b0}};
reg temp_m_axis_tvalid_reg = 1'b0, temp_m_axis_tvalid_next;
reg temp_m_axis_tlast_reg = 1'b0;
reg [ID_WIDTH-1:0] temp_m_axis_tid_reg = {ID_WIDTH{1'b0}};
reg [DEST_WIDTH-1:0] temp_m_axis_tdest_reg = {DEST_WIDTH{1'b0}};
reg [USER_WIDTH-1:0] temp_m_axis_tuser_reg = {USER_WIDTH{1'b0}};
// datapath control
reg store_axis_input_to_output;
reg store_axis_input_to_temp;
reg store_axis_temp_to_output;
assign s_axis_tready = s_axis_tready_reg;
assign m_axis_tdata = m_axis_tdata_reg;
assign m_axis_tkeep = KEEP_ENABLE ? m_axis_tkeep_reg : {KEEP_WIDTH{1'b1}};
assign m_axis_tvalid = m_axis_tvalid_reg;
assign m_axis_tlast = LAST_ENABLE ? m_axis_tlast_reg : 1'b1;
assign m_axis_tid = ID_ENABLE ? m_axis_tid_reg : {ID_WIDTH{1'b0}};
assign m_axis_tdest = DEST_ENABLE ? m_axis_tdest_reg : {DEST_WIDTH{1'b0}};
assign m_axis_tuser = USER_ENABLE ? m_axis_tuser_reg : {USER_WIDTH{1'b0}};
// enable ready input next cycle if output is ready or the temp reg will not be filled on the next cycle (output reg empty or no input)
wire s_axis_tready_early = m_axis_tready || (!temp_m_axis_tvalid_reg && (!m_axis_tvalid_reg || !s_axis_tvalid));
always @* begin
// transfer sink ready state to source
m_axis_tvalid_next = m_axis_tvalid_reg;
temp_m_axis_tvalid_next = temp_m_axis_tvalid_reg;
store_axis_input_to_output = 1'b0;
store_axis_input_to_temp = 1'b0;
store_axis_temp_to_output = 1'b0;
if (s_axis_tready_reg) begin
// input is ready
if (m_axis_tready || !m_axis_tvalid_reg) begin
// output is ready or currently not valid, transfer data to output
m_axis_tvalid_next = s_axis_tvalid;
store_axis_input_to_output = 1'b1;
end else begin
// output is not ready, store input in temp
temp_m_axis_tvalid_next = s_axis_tvalid;
store_axis_input_to_temp = 1'b1;
end
end else if (m_axis_tready) begin
// input is not ready, but output is ready
m_axis_tvalid_next = temp_m_axis_tvalid_reg;
temp_m_axis_tvalid_next = 1'b0;
store_axis_temp_to_output = 1'b1;
end
end
always @(posedge clk) begin
if (rst) begin
s_axis_tready_reg <= 1'b0;
m_axis_tvalid_reg <= 1'b0;
temp_m_axis_tvalid_reg <= 1'b0;
end else begin
s_axis_tready_reg <= s_axis_tready_early;
m_axis_tvalid_reg <= m_axis_tvalid_next;
temp_m_axis_tvalid_reg <= temp_m_axis_tvalid_next;
end
// datapath
if (store_axis_input_to_output) begin
m_axis_tdata_reg <= s_axis_tdata;
m_axis_tkeep_reg <= s_axis_tkeep;
m_axis_tlast_reg <= s_axis_tlast;
m_axis_tid_reg <= s_axis_tid;
m_axis_tdest_reg <= s_axis_tdest;
m_axis_tuser_reg <= s_axis_tuser;
end else if (store_axis_temp_to_output) begin
m_axis_tdata_reg <= temp_m_axis_tdata_reg;
m_axis_tkeep_reg <= temp_m_axis_tkeep_reg;
m_axis_tlast_reg <= temp_m_axis_tlast_reg;
m_axis_tid_reg <= temp_m_axis_tid_reg;
m_axis_tdest_reg <= temp_m_axis_tdest_reg;
m_axis_tuser_reg <= temp_m_axis_tuser_reg;
end
if (store_axis_input_to_temp) begin
temp_m_axis_tdata_reg <= s_axis_tdata;
temp_m_axis_tkeep_reg <= s_axis_tkeep;
temp_m_axis_tlast_reg <= s_axis_tlast;
temp_m_axis_tid_reg <= s_axis_tid;
temp_m_axis_tdest_reg <= s_axis_tdest;
temp_m_axis_tuser_reg <= s_axis_tuser;
end
end
end else if (REG_TYPE == 1) begin
// simple register, inserts bubble cycles
// datapath registers
reg s_axis_tready_reg = 1'b0;
reg [DATA_WIDTH-1:0] m_axis_tdata_reg = {DATA_WIDTH{1'b0}};
reg [KEEP_WIDTH-1:0] m_axis_tkeep_reg = {KEEP_WIDTH{1'b0}};
reg m_axis_tvalid_reg = 1'b0, m_axis_tvalid_next;
reg m_axis_tlast_reg = 1'b0;
reg [ID_WIDTH-1:0] m_axis_tid_reg = {ID_WIDTH{1'b0}};
reg [DEST_WIDTH-1:0] m_axis_tdest_reg = {DEST_WIDTH{1'b0}};
reg [USER_WIDTH-1:0] m_axis_tuser_reg = {USER_WIDTH{1'b0}};
// datapath control
reg store_axis_input_to_output;
assign s_axis_tready = s_axis_tready_reg;
assign m_axis_tdata = m_axis_tdata_reg;
assign m_axis_tkeep = KEEP_ENABLE ? m_axis_tkeep_reg : {KEEP_WIDTH{1'b1}};
assign m_axis_tvalid = m_axis_tvalid_reg;
assign m_axis_tlast = LAST_ENABLE ? m_axis_tlast_reg : 1'b1;
assign m_axis_tid = ID_ENABLE ? m_axis_tid_reg : {ID_WIDTH{1'b0}};
assign m_axis_tdest = DEST_ENABLE ? m_axis_tdest_reg : {DEST_WIDTH{1'b0}};
assign m_axis_tuser = USER_ENABLE ? m_axis_tuser_reg : {USER_WIDTH{1'b0}};
// enable ready input next cycle if output buffer will be empty
wire s_axis_tready_early = !m_axis_tvalid_next;
always @* begin
// transfer sink ready state to source
m_axis_tvalid_next = m_axis_tvalid_reg;
store_axis_input_to_output = 1'b0;
if (s_axis_tready_reg) begin
m_axis_tvalid_next = s_axis_tvalid;
store_axis_input_to_output = 1'b1;
end else if (m_axis_tready) begin
m_axis_tvalid_next = 1'b0;
end
end
always @(posedge clk) begin
if (rst) begin
s_axis_tready_reg <= 1'b0;
m_axis_tvalid_reg <= 1'b0;
end else begin
s_axis_tready_reg <= s_axis_tready_early;
m_axis_tvalid_reg <= m_axis_tvalid_next;
end
// datapath
if (store_axis_input_to_output) begin
m_axis_tdata_reg <= s_axis_tdata;
m_axis_tkeep_reg <= s_axis_tkeep;
m_axis_tlast_reg <= s_axis_tlast;
m_axis_tid_reg <= s_axis_tid;
m_axis_tdest_reg <= s_axis_tdest;
m_axis_tuser_reg <= s_axis_tuser;
end
end
end else begin
// bypass
assign m_axis_tdata = s_axis_tdata;
assign m_axis_tkeep = KEEP_ENABLE ? s_axis_tkeep : {KEEP_WIDTH{1'b1}};
assign m_axis_tvalid = s_axis_tvalid;
assign m_axis_tlast = LAST_ENABLE ? s_axis_tlast : 1'b1;
assign m_axis_tid = ID_ENABLE ? s_axis_tid : {ID_WIDTH{1'b0}};
assign m_axis_tdest = DEST_ENABLE ? s_axis_tdest : {DEST_WIDTH{1'b0}};
assign m_axis_tuser = USER_ENABLE ? s_axis_tuser : {USER_WIDTH{1'b0}};
assign s_axis_tready = m_axis_tready;
end
endgenerate
endmodule

View File

@ -0,0 +1,451 @@
/*
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
`timescale 1ns / 1ps
/*
* FPGA top-level module
*/
module fpga (
/*
* GPIO
*/
output wire led_sreg_d,
output wire led_sreg_ld,
output wire led_sreg_clk,
output wire [1:0] led_bmc,
output wire [1:0] led_exp,
/*
* 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_rst_n
);
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;
// 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;
// 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 [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_num_vld0(),
.pcie_rq_seq_num1(),
.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_pd(),
.cfg_fc_nph(),
.cfg_fc_npd(),
.cfg_fc_cplh(),
.cfg_fc_cpld(),
.cfg_fc_sel(3'd0),
.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),
//.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_rst_n),
.phy_rdy_out()
);
// GPIO
wire [7:0] led_red;
wire [7:0] led_green;
wire [15:0] led_merged;
assign led_merged[0] = led_red[0];
assign led_merged[1] = led_green[0];
assign led_merged[2] = led_red[1];
assign led_merged[3] = led_green[1];
assign led_merged[4] = led_red[2];
assign led_merged[5] = led_green[2];
assign led_merged[6] = led_red[3];
assign led_merged[7] = led_green[3];
assign led_merged[8] = led_red[4];
assign led_merged[9] = led_green[4];
assign led_merged[10] = led_red[5];
assign led_merged[11] = led_green[5];
assign led_merged[12] = led_red[6];
assign led_merged[13] = led_green[6];
assign led_merged[14] = led_red[7];
assign led_merged[15] = led_green[7];
led_sreg_driver #(
.COUNT(16),
.INVERT(1),
.PRESCALE(63)
)
led_sreg_driver_inst (
.clk(pcie_user_clk),
.rst(pcie_user_reset),
.led(led_merged),
.sreg_d(led_sreg_d),
.sreg_ld(led_sreg_ld),
.sreg_clk(led_sreg_clk)
);
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
*/
.led_red(led_red),
.led_green(led_green),
.led_bmc(led_bmc),
.led_exp(led_exp),
/*
* 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),
.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_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

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,135 @@
/*
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
`timescale 1ns / 1ps
/*
* LED shift register driver
*/
module led_sreg_driver #(
// number of LEDs
parameter COUNT = 8,
// invert output
parameter INVERT = 0,
// clock prescale
parameter PRESCALE = 31
)
(
input wire clk,
input wire rst,
input wire [COUNT-1:0] led,
output wire sreg_d,
output wire sreg_ld,
output wire sreg_clk
);
localparam CL_COUNT = $clog2(COUNT+1);
localparam CL_PRESCALE = $clog2(PRESCALE+1);
reg [CL_COUNT-1:0] count_reg = 0;
reg [CL_PRESCALE-1:0] prescale_count_reg = 0;
reg enable_reg = 1'b0;
reg update_reg = 1'b1;
reg cycle_reg = 1'b0;
reg [COUNT-1:0] led_sync_reg_1 = 0;
reg [COUNT-1:0] led_sync_reg_2 = 0;
reg [COUNT-1:0] led_reg = 0;
reg sreg_d_reg = 1'b0;
reg sreg_ld_reg = 1'b0;
reg sreg_clk_reg = 1'b0;
assign sreg_d = INVERT ? !sreg_d_reg : sreg_d_reg;
assign sreg_ld = sreg_ld_reg;
assign sreg_clk = sreg_clk_reg;
always @(posedge clk) begin
led_sync_reg_1 <= led;
led_sync_reg_2 <= led_sync_reg_1;
enable_reg <= 1'b0;
if (prescale_count_reg) begin
prescale_count_reg <= prescale_count_reg - 1;
end else begin
enable_reg <= 1'b1;
prescale_count_reg <= PRESCALE;
end
if (enable_reg) begin
if (cycle_reg) begin
cycle_reg <= 1'b0;
sreg_clk_reg <= 1'b1;
end else if (count_reg) begin
sreg_clk_reg <= 1'b0;
sreg_ld_reg <= 1'b0;
if (count_reg < COUNT) begin
count_reg <= count_reg + 1;
cycle_reg <= 1'b1;
sreg_d_reg <= led_reg[count_reg];
end else begin
count_reg <= 0;
cycle_reg <= 1'b0;
sreg_d_reg <= 1'b0;
sreg_ld_reg <= 1'b1;
end
end else begin
sreg_clk_reg <= 1'b0;
sreg_ld_reg <= 1'b0;
if (update_reg) begin
update_reg <= 1'b0;
count_reg <= 1;
cycle_reg <= 1'b1;
sreg_d_reg <= led_reg[0];
end
end
end
if (led_sync_reg_2 != led_reg) begin
led_reg <= led_sync_reg_2;
update_reg <= 1'b1;
end
if (rst) begin
count_reg <= 0;
prescale_count_reg <= 0;
enable_reg <= 1'b0;
update_reg <= 1'b1;
cycle_reg <= 1'b0;
led_reg <= 0;
sreg_d_reg <= 1'b0;
sreg_ld_reg <= 1'b0;
sreg_clk_reg <= 1'b0;
end
end
endmodule

View File

@ -0,0 +1,52 @@
/*
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
`timescale 1 ns / 1 ps
/*
* 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

View File

@ -0,0 +1,58 @@
/*
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
`timescale 1 ns / 1 ps
/*
* 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

View File

@ -0,0 +1 @@
../lib/pcie/tb/axis_ep.py

View File

@ -0,0 +1 @@
../lib/pcie/tb/pcie.py

View File

@ -0,0 +1 @@
../lib/pcie/tb/pcie_us.py

View File

@ -0,0 +1 @@
../lib/pcie/tb/pcie_usp.py

View File

@ -0,0 +1,514 @@
#!/usr/bin/env python
"""
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.
"""
from myhdl import *
import os
import struct
import pcie
import pcie_usp
module = 'fpga_core'
testbench = 'test_%s' % module
srcs = []
srcs.append("../rtl/%s.v" % module)
srcs.append("../rtl/axi_ram.v")
srcs.append("../rtl/axis_register.v")
srcs.append("../lib/pcie/rtl/axis_arb_mux.v")
srcs.append("../lib/pcie/rtl/pcie_us_axil_master.v")
srcs.append("../lib/pcie/rtl/pcie_us_axi_dma.v")
srcs.append("../lib/pcie/rtl/pcie_us_axi_dma_rd.v")
srcs.append("../lib/pcie/rtl/pcie_us_axi_dma_wr.v")
srcs.append("../lib/pcie/rtl/pcie_tag_manager.v")
srcs.append("../lib/pcie/rtl/pcie_us_axi_master.v")
srcs.append("../lib/pcie/rtl/pcie_us_axi_master_rd.v")
srcs.append("../lib/pcie/rtl/pcie_us_axi_master_wr.v")
srcs.append("../lib/pcie/rtl/pcie_us_axis_cq_demux.v")
srcs.append("../lib/pcie/rtl/pcie_us_cfg.v")
srcs.append("../lib/pcie/rtl/pcie_us_msi.v")
srcs.append("../lib/pcie/rtl/arbiter.v")
srcs.append("../lib/pcie/rtl/priority_encoder.v")
srcs.append("../lib/pcie/rtl/pulse_merge.v")
srcs.append("%s.v" % testbench)
src = ' '.join(srcs)
build_cmd = "iverilog -o %s.vvp %s" % (testbench, src)
def bench():
# Parameters
AXIS_PCIE_DATA_WIDTH = 512
AXIS_PCIE_KEEP_WIDTH = (AXIS_PCIE_DATA_WIDTH/32)
AXIS_PCIE_RC_USER_WIDTH = 161
AXIS_PCIE_RQ_USER_WIDTH = 137
AXIS_PCIE_CQ_USER_WIDTH = 183
AXIS_PCIE_CC_USER_WIDTH = 81
# Inputs
clk = Signal(bool(0))
rst = Signal(bool(0))
current_test = Signal(intbv(0)[8:])
m_axis_rq_tready = Signal(bool(0))
s_axis_rc_tdata = Signal(intbv(0)[AXIS_PCIE_DATA_WIDTH:])
s_axis_rc_tkeep = Signal(intbv(0)[AXIS_PCIE_KEEP_WIDTH:])
s_axis_rc_tlast = Signal(bool(0))
s_axis_rc_tuser = Signal(intbv(0)[AXIS_PCIE_RC_USER_WIDTH:])
s_axis_rc_tvalid = Signal(bool(0))
s_axis_cq_tdata = Signal(intbv(0)[AXIS_PCIE_DATA_WIDTH:])
s_axis_cq_tkeep = Signal(intbv(0)[AXIS_PCIE_KEEP_WIDTH:])
s_axis_cq_tlast = Signal(bool(0))
s_axis_cq_tuser = Signal(intbv(0)[AXIS_PCIE_CQ_USER_WIDTH:])
s_axis_cq_tvalid = Signal(bool(0))
m_axis_cc_tready = Signal(bool(0))
cfg_max_payload = Signal(intbv(0)[2:])
cfg_max_read_req = Signal(intbv(0)[3:])
cfg_mgmt_read_data = Signal(intbv(0)[32:])
cfg_mgmt_read_write_done = Signal(bool(0))
cfg_interrupt_msi_enable = Signal(intbv(0)[4:])
cfg_interrupt_msi_mmenable = Signal(intbv(0)[12:])
cfg_interrupt_msi_mask_update = Signal(bool(0))
cfg_interrupt_msi_data = Signal(intbv(0)[32:])
cfg_interrupt_msi_sent = Signal(bool(0))
cfg_interrupt_msi_fail = Signal(bool(0))
# Outputs
led_red = Signal(intbv(0)[8:])
led_green = Signal(intbv(0)[8:])
led_bmc = Signal(intbv(0)[2:])
led_exp = Signal(intbv(0)[2:])
m_axis_rq_tdata = Signal(intbv(0)[AXIS_PCIE_DATA_WIDTH:])
m_axis_rq_tkeep = Signal(intbv(0)[AXIS_PCIE_KEEP_WIDTH:])
m_axis_rq_tlast = Signal(bool(0))
m_axis_rq_tuser = Signal(intbv(0)[AXIS_PCIE_RQ_USER_WIDTH:])
m_axis_rq_tvalid = Signal(bool(0))
s_axis_rc_tready = Signal(bool(0))
s_axis_cq_tready = Signal(bool(0))
m_axis_cc_tdata = Signal(intbv(0)[AXIS_PCIE_DATA_WIDTH:])
m_axis_cc_tkeep = Signal(intbv(0)[AXIS_PCIE_KEEP_WIDTH:])
m_axis_cc_tlast = Signal(bool(0))
m_axis_cc_tuser = Signal(intbv(0)[AXIS_PCIE_CC_USER_WIDTH:])
m_axis_cc_tvalid = Signal(bool(0))
status_error_cor = Signal(bool(0))
status_error_uncor = Signal(bool(0))
cfg_mgmt_addr = Signal(intbv(0)[10:])
cfg_mgmt_function_number = Signal(intbv(0)[8:])
cfg_mgmt_write = Signal(bool(0))
cfg_mgmt_write_data = Signal(intbv(0)[32:])
cfg_mgmt_byte_enable = Signal(intbv(0)[4:])
cfg_mgmt_read = Signal(bool(0))
cfg_interrupt_msi_int = Signal(intbv(0)[32:])
cfg_interrupt_msi_pending_status = Signal(intbv(0)[32:])
cfg_interrupt_msi_select = Signal(intbv(0)[2:])
cfg_interrupt_msi_pending_status_function_num = Signal(intbv(0)[2:])
cfg_interrupt_msi_pending_status_data_enable = Signal(bool(0))
cfg_interrupt_msi_attr = Signal(intbv(0)[3:])
cfg_interrupt_msi_tph_present = Signal(bool(0))
cfg_interrupt_msi_tph_type = Signal(intbv(0)[2:])
cfg_interrupt_msi_tph_st_tag = Signal(intbv(0)[8:])
cfg_interrupt_msi_function_number = Signal(intbv(0)[8:])
# Clock and Reset Interface
user_clk=Signal(bool(0))
user_reset=Signal(bool(0))
sys_clk=Signal(bool(0))
sys_reset=Signal(bool(0))
# PCIe devices
rc = pcie.RootComplex()
mem_base, mem_data = rc.alloc_region(16*1024*1024)
dev = pcie_usp.UltrascalePlusPCIe()
dev.pcie_generation = 3
dev.pcie_link_width = 16
dev.user_clock_frequency = 256e6
dev.functions[0].msi_multiple_message_capable = 5
dev.functions[0].configure_bar(0, 4*1024*1024)
dev.functions[0].configure_bar(1, 4*1024*1024)
rc.make_port().connect(dev)
pcie_logic = dev.create_logic(
# Completer reQuest Interface
m_axis_cq_tdata=s_axis_cq_tdata,
m_axis_cq_tuser=s_axis_cq_tuser,
m_axis_cq_tlast=s_axis_cq_tlast,
m_axis_cq_tkeep=s_axis_cq_tkeep,
m_axis_cq_tvalid=s_axis_cq_tvalid,
m_axis_cq_tready=s_axis_cq_tready,
#pcie_cq_np_req=pcie_cq_np_req,
pcie_cq_np_req=Signal(intbv(1)[2:]),
#pcie_cq_np_req_count=pcie_cq_np_req_count,
# Completer Completion Interface
s_axis_cc_tdata=m_axis_cc_tdata,
s_axis_cc_tuser=m_axis_cc_tuser,
s_axis_cc_tlast=m_axis_cc_tlast,
s_axis_cc_tkeep=m_axis_cc_tkeep,
s_axis_cc_tvalid=m_axis_cc_tvalid,
s_axis_cc_tready=m_axis_cc_tready,
# Requester reQuest Interface
s_axis_rq_tdata=m_axis_rq_tdata,
s_axis_rq_tuser=m_axis_rq_tuser,
s_axis_rq_tlast=m_axis_rq_tlast,
s_axis_rq_tkeep=m_axis_rq_tkeep,
s_axis_rq_tvalid=m_axis_rq_tvalid,
s_axis_rq_tready=m_axis_rq_tready,
#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_tag0,
#pcie_rq_tag1=pcie_rq_tag1,
#pcie_rq_tag_av=pcie_rq_tag_av,
#pcie_rq_tag_vld0=pcie_rq_tag_vld0,
#pcie_rq_tag_vld1=pcie_rq_tag_vld1,
# Requester Completion Interface
m_axis_rc_tdata=s_axis_rc_tdata,
m_axis_rc_tuser=s_axis_rc_tuser,
m_axis_rc_tlast=s_axis_rc_tlast,
m_axis_rc_tkeep=s_axis_rc_tkeep,
m_axis_rc_tvalid=s_axis_rc_tvalid,
m_axis_rc_tready=s_axis_rc_tready,
# Transmit Flow Control Interface
#pcie_tfc_nph_av=pcie_tfc_nph_av,
#pcie_tfc_npd_av=pcie_tfc_npd_av,
# Configuration Management 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,
#cfg_mgmt_debug_access=cfg_mgmt_debug_access,
# Configuration Status Interface
#cfg_phy_link_down=cfg_phy_link_down,
#cfg_phy_link_status=cfg_phy_link_status,
#cfg_negotiated_width=cfg_negotiated_width,
#cfg_current_speed=cfg_current_speed,
cfg_max_payload=cfg_max_payload,
cfg_max_read_req=cfg_max_read_req,
#cfg_function_status=cfg_function_status,
#cfg_vf_status=cfg_vf_status,
#cfg_function_power_state=cfg_function_power_state,
#cfg_vf_power_state=cfg_vf_power_state,
#cfg_link_power_state=cfg_link_power_state,
#cfg_err_cor_out=cfg_err_cor_out,
#cfg_err_nonfatal_out=cfg_err_nonfatal_out,
#cfg_err_fatal_out=cfg_err_fatal_out,
#cfg_local_err_out=cfg_local_err_out,
#cfg_local_err_valid=cfg_local_err_valid,
#cfg_rx_pm_state=cfg_rx_pm_state,
#cfg_tx_pm_state=cfg_tx_pm_state,
#cfg_ltssm_state=cfg_ltssm_state,
#cfg_rcb_status=cfg_rcb_status,
#cfg_obff_enable=cfg_obff_enable,
#cfg_pl_status_change=cfg_pl_status_change,
#cfg_tph_requester_enable=cfg_tph_requester_enable,
#cfg_tph_st_mode=cfg_tph_st_mode,
#cfg_vf_tph_requester_enable=cfg_vf_tph_requester_enable,
#cfg_vf_tph_st_mode=cfg_vf_tph_st_mode,
# Configuration Received Message Interface
#cfg_msg_received=cfg_msg_received,
#cfg_msg_received_data=cfg_msg_received_data,
#cfg_msg_received_type=cfg_msg_received_type,
# Configuration Transmit Message Interface
#cfg_msg_transmit=cfg_msg_transmit,
#cfg_msg_transmit_type=cfg_msg_transmit_type,
#cfg_msg_transmit_data=cfg_msg_transmit_data,
#cfg_msg_transmit_done=cfg_msg_transmit_done,
# Configuration Flow Control Interface
#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 Control Interface
#cfg_hot_reset_in=cfg_hot_reset_in,
#cfg_hot_reset_out=cfg_hot_reset_out,
#cfg_config_space_enable=cfg_config_space_enable,
#cfg_dsn=cfg_dsn,
#cfg_ds_port_number=cfg_ds_port_number,
#cfg_ds_bus_number=cfg_ds_bus_number,
#cfg_ds_device_number=cfg_ds_device_number,
#cfg_ds_function_number=cfg_ds_function_number,
#cfg_power_state_change_ack=cfg_power_state_change_ack,
#cfg_power_state_change_interrupt=cfg_power_state_change_interrupt,
cfg_err_cor_in=status_error_cor,
cfg_err_uncor_in=status_error_uncor,
#cfg_flr_done=cfg_flr_done,
#cfg_vf_flr_done=cfg_vf_flr_done,
#cfg_flr_in_process=cfg_flr_in_process,
#cfg_vf_flr_in_process=cfg_vf_flr_in_process,
#cfg_req_pm_transition_l23_ready=cfg_req_pm_transition_l23_ready,
#cfg_link_training_enable=cfg_link_training_enable,
# Configuration Interrupt Controller Interface
#cfg_interrupt_int=cfg_interrupt_int,
#cfg_interrupt_sent=cfg_interrupt_sent,
#cfg_interrupt_pending=cfg_interrupt_pending,
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_msix_enable=cfg_interrupt_msix_enable,
#cfg_interrupt_msix_mask=cfg_interrupt_msix_mask,
#cfg_interrupt_msix_vf_enable=cfg_interrupt_msix_vf_enable,
#cfg_interrupt_msix_vf_mask=cfg_interrupt_msix_vf_mask,
#cfg_interrupt_msix_address=cfg_interrupt_msix_address,
#cfg_interrupt_msix_data=cfg_interrupt_msix_data,
#cfg_interrupt_msix_int=cfg_interrupt_msix_int,
#cfg_interrupt_msix_vec_pending=cfg_interrupt_msix_vec_pending,
#cfg_interrupt_msix_vec_pending_status=cfg_interrupt_msix_vec_pending_status,
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 Extend Interface
#cfg_ext_read_received=cfg_ext_read_received,
#cfg_ext_write_received=cfg_ext_write_received,
#cfg_ext_register_number=cfg_ext_register_number,
#cfg_ext_function_number=cfg_ext_function_number,
#cfg_ext_write_data=cfg_ext_write_data,
#cfg_ext_write_byte_enable=cfg_ext_write_byte_enable,
#cfg_ext_read_data=cfg_ext_read_data,
#cfg_ext_read_data_valid=cfg_ext_read_data_valid,
# Clock and Reset Interface
user_clk=user_clk,
user_reset=user_reset,
#user_lnk_up=user_lnk_up,
sys_clk=sys_clk,
sys_clk_gt=sys_clk,
sys_reset=sys_reset,
#phy_rdy_out=phy_rdy_out
)
# DUT
if os.system(build_cmd):
raise Exception("Error running build command")
dut = Cosimulation(
"vvp -m myhdl %s.vvp -lxt2" % testbench,
clk=user_clk,
rst=user_reset,
current_test=current_test,
led_red=led_red,
led_green=led_green,
led_bmc=led_bmc,
led_exp=led_exp,
m_axis_rq_tdata=m_axis_rq_tdata,
m_axis_rq_tkeep=m_axis_rq_tkeep,
m_axis_rq_tlast=m_axis_rq_tlast,
m_axis_rq_tready=m_axis_rq_tready,
m_axis_rq_tuser=m_axis_rq_tuser,
m_axis_rq_tvalid=m_axis_rq_tvalid,
s_axis_rc_tdata=s_axis_rc_tdata,
s_axis_rc_tkeep=s_axis_rc_tkeep,
s_axis_rc_tlast=s_axis_rc_tlast,
s_axis_rc_tready=s_axis_rc_tready,
s_axis_rc_tuser=s_axis_rc_tuser,
s_axis_rc_tvalid=s_axis_rc_tvalid,
s_axis_cq_tdata=s_axis_cq_tdata,
s_axis_cq_tkeep=s_axis_cq_tkeep,
s_axis_cq_tlast=s_axis_cq_tlast,
s_axis_cq_tready=s_axis_cq_tready,
s_axis_cq_tuser=s_axis_cq_tuser,
s_axis_cq_tvalid=s_axis_cq_tvalid,
m_axis_cc_tdata=m_axis_cc_tdata,
m_axis_cc_tkeep=m_axis_cc_tkeep,
m_axis_cc_tlast=m_axis_cc_tlast,
m_axis_cc_tready=m_axis_cc_tready,
m_axis_cc_tuser=m_axis_cc_tuser,
m_axis_cc_tvalid=m_axis_cc_tvalid,
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_interrupt_msi_enable=cfg_interrupt_msi_enable,
cfg_interrupt_msi_int=cfg_interrupt_msi_int,
cfg_interrupt_msi_sent=cfg_interrupt_msi_sent,
cfg_interrupt_msi_fail=cfg_interrupt_msi_fail,
cfg_interrupt_msi_mmenable=cfg_interrupt_msi_mmenable,
cfg_interrupt_msi_pending_status=cfg_interrupt_msi_pending_status,
cfg_interrupt_msi_mask_update=cfg_interrupt_msi_mask_update,
cfg_interrupt_msi_select=cfg_interrupt_msi_select,
cfg_interrupt_msi_data=cfg_interrupt_msi_data,
cfg_interrupt_msi_pending_status_function_num=cfg_interrupt_msi_pending_status_function_num,
cfg_interrupt_msi_pending_status_data_enable=cfg_interrupt_msi_pending_status_data_enable,
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
)
@always(delay(5))
def clkgen():
clk.next = not clk
@always_comb
def clk_logic():
sys_clk.next = clk
sys_reset.next = not rst
@instance
def check():
yield delay(100)
yield clk.posedge
rst.next = 1
yield clk.posedge
rst.next = 0
yield clk.posedge
yield delay(100)
yield clk.posedge
# testbench stimulus
current_tag = 1
yield clk.posedge
print("test 1: enumeration")
current_test.next = 1
yield rc.enumerate(enable_bus_mastering=True, configure_msi=True)
dev_pf0_bar0 = dev.functions[0].bar[0] & 0xfffffffc
dev_pf0_bar1 = dev.functions[0].bar[1] & 0xfffffffc
yield delay(100)
yield clk.posedge
print("test 2: memory write to bar 1")
current_test.next = 2
yield rc.mem_write(dev_pf0_bar1, b'\x11\x22\x33\x44')
yield delay(100)
yield clk.posedge
print("test 3: memory read from bar 1")
current_test.next = 3
val = yield from rc.mem_read(dev_pf0_bar1, 4, 1000)
print(val)
assert val == b'\x11\x22\x33\x44'
yield delay(100)
yield clk.posedge
print("test 4: test DMA")
current_test.next = 4
# write packet data
mem_data[0:1024] = bytearray([x%256 for x in range(1024)])
# enable DMA
yield rc.mem_write(dev_pf0_bar0+0x100000, struct.pack('<L', 1))
# write pcie read descriptor
yield rc.mem_write(dev_pf0_bar0+0x100100, struct.pack('<L', (mem_base+0x0000) & 0xffffffff))
yield rc.mem_write(dev_pf0_bar0+0x100104, struct.pack('<L', (mem_base+0x0000 >> 32) & 0xffffffff))
yield rc.mem_write(dev_pf0_bar0+0x100108, struct.pack('<L', (0x100) & 0xffffffff))
yield rc.mem_write(dev_pf0_bar0+0x10010C, struct.pack('<L', (0x100 >> 32) & 0xffffffff))
yield rc.mem_write(dev_pf0_bar0+0x100110, struct.pack('<L', 0x400))
yield rc.mem_write(dev_pf0_bar0+0x100114, struct.pack('<L', 0xAA))
yield delay(2000)
# read status
val = yield from rc.mem_read(dev_pf0_bar0+0x100118, 4)
print(val)
# write pcie write descriptor
yield rc.mem_write(dev_pf0_bar0+0x100200, struct.pack('<L', (mem_base+0x1000) & 0xffffffff))
yield rc.mem_write(dev_pf0_bar0+0x100204, struct.pack('<L', (mem_base+0x1000 >> 32) & 0xffffffff))
yield rc.mem_write(dev_pf0_bar0+0x100208, struct.pack('<L', (0x100) & 0xffffffff))
yield rc.mem_write(dev_pf0_bar0+0x10020C, struct.pack('<L', (0x100 >> 32) & 0xffffffff))
yield rc.mem_write(dev_pf0_bar0+0x100210, struct.pack('<L', 0x400))
yield rc.mem_write(dev_pf0_bar0+0x100214, struct.pack('<L', 0x55))
yield delay(2000)
# read status
val = yield from rc.mem_read(dev_pf0_bar0+0x100218, 4)
print(val)
data = mem_data[0x1000:(0x1000)+64]
for i in range(0, len(data), 16):
print(" ".join(("{:02x}".format(c) for c in bytearray(data[i:i+16]))))
assert mem_data[0:1024] == mem_data[0x1000:0x1000+1024]
yield delay(100)
raise StopSimulation
return instances()
def test_bench():
sim = Simulation(bench())
sim.run()
if __name__ == '__main__':
print("Running test...")
test_bench()

View File

@ -0,0 +1,246 @@
/*
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
`timescale 1ns / 1ps
/*
* Testbench for fpga_core
*/
module test_fpga_core;
// Parameters
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;
// Inputs
reg clk = 0;
reg rst = 0;
reg [7:0] current_test = 0;
reg m_axis_rq_tready = 0;
reg [AXIS_PCIE_DATA_WIDTH-1:0] s_axis_rc_tdata = 0;
reg [AXIS_PCIE_KEEP_WIDTH-1:0] s_axis_rc_tkeep = 0;
reg s_axis_rc_tlast = 0;
reg [AXIS_PCIE_RC_USER_WIDTH-1:0] s_axis_rc_tuser = 0;
reg s_axis_rc_tvalid = 0;
reg [AXIS_PCIE_DATA_WIDTH-1:0] s_axis_cq_tdata = 0;
reg [AXIS_PCIE_KEEP_WIDTH-1:0] s_axis_cq_tkeep = 0;
reg s_axis_cq_tlast = 0;
reg [AXIS_PCIE_CQ_USER_WIDTH-1:0] s_axis_cq_tuser = 0;
reg s_axis_cq_tvalid = 0;
reg m_axis_cc_tready = 0;
reg [2:0] cfg_max_payload = 0;
reg [2:0] cfg_max_read_req = 0;
reg [31:0] cfg_mgmt_read_data = 0;
reg cfg_mgmt_read_write_done = 0;
reg [3:0] cfg_interrupt_msi_enable = 0;
reg [11:0] cfg_interrupt_msi_mmenable = 0;
reg cfg_interrupt_msi_mask_update = 0;
reg [31:0] cfg_interrupt_msi_data = 0;
reg cfg_interrupt_msi_sent = 0;
reg cfg_interrupt_msi_fail = 0;
// Outputs
wire [7:0] led_red;
wire [7:0] led_green;
wire [1:0] led_bmc;
wire [1:0] led_exp;
wire [AXIS_PCIE_DATA_WIDTH-1:0] m_axis_rq_tdata;
wire [AXIS_PCIE_KEEP_WIDTH-1:0] m_axis_rq_tkeep;
wire m_axis_rq_tlast;
wire [AXIS_PCIE_RQ_USER_WIDTH-1:0] m_axis_rq_tuser;
wire m_axis_rq_tvalid;
wire s_axis_rc_tready;
wire s_axis_cq_tready;
wire [AXIS_PCIE_DATA_WIDTH-1:0] m_axis_cc_tdata;
wire [AXIS_PCIE_KEEP_WIDTH-1:0] m_axis_cc_tkeep;
wire m_axis_cc_tlast;
wire [AXIS_PCIE_CC_USER_WIDTH-1:0] m_axis_cc_tuser;
wire m_axis_cc_tvalid;
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 [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 [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;
initial begin
// myhdl integration
$from_myhdl(
clk,
rst,
current_test,
m_axis_rq_tready,
s_axis_rc_tdata,
s_axis_rc_tkeep,
s_axis_rc_tlast,
s_axis_rc_tuser,
s_axis_rc_tvalid,
s_axis_cq_tdata,
s_axis_cq_tkeep,
s_axis_cq_tlast,
s_axis_cq_tuser,
s_axis_cq_tvalid,
m_axis_cc_tready,
cfg_max_payload,
cfg_max_read_req,
cfg_mgmt_read_data,
cfg_mgmt_read_write_done,
cfg_interrupt_msi_enable,
cfg_interrupt_msi_mmenable,
cfg_interrupt_msi_mask_update,
cfg_interrupt_msi_data,
cfg_interrupt_msi_sent,
cfg_interrupt_msi_fail
);
$to_myhdl(
led_red,
led_green,
led_bmc,
led_exp,
m_axis_rq_tdata,
m_axis_rq_tkeep,
m_axis_rq_tlast,
m_axis_rq_tuser,
m_axis_rq_tvalid,
s_axis_rc_tready,
s_axis_cq_tready,
m_axis_cc_tdata,
m_axis_cc_tkeep,
m_axis_cc_tlast,
m_axis_cc_tuser,
m_axis_cc_tvalid,
cfg_mgmt_addr,
cfg_mgmt_function_number,
cfg_mgmt_write,
cfg_mgmt_write_data,
cfg_mgmt_byte_enable,
cfg_mgmt_read,
cfg_interrupt_msi_select,
cfg_interrupt_msi_int,
cfg_interrupt_msi_pending_status,
cfg_interrupt_msi_pending_status_data_enable,
cfg_interrupt_msi_pending_status_function_num,
cfg_interrupt_msi_attr,
cfg_interrupt_msi_tph_present,
cfg_interrupt_msi_tph_type,
cfg_interrupt_msi_tph_st_tag,
cfg_interrupt_msi_function_number,
status_error_cor,
status_error_uncor
);
// dump file
$dumpfile("test_fpga_core.lxt");
$dumpvars(0, test_fpga_core);
end
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)
)
UUT (
.clk(clk),
.rst(rst),
.led_red(led_red),
.led_green(led_green),
.led_bmc(led_bmc),
.led_exp(led_exp),
.m_axis_rq_tdata(m_axis_rq_tdata),
.m_axis_rq_tkeep(m_axis_rq_tkeep),
.m_axis_rq_tlast(m_axis_rq_tlast),
.m_axis_rq_tready(m_axis_rq_tready),
.m_axis_rq_tuser(m_axis_rq_tuser),
.m_axis_rq_tvalid(m_axis_rq_tvalid),
.s_axis_rc_tdata(s_axis_rc_tdata),
.s_axis_rc_tkeep(s_axis_rc_tkeep),
.s_axis_rc_tlast(s_axis_rc_tlast),
.s_axis_rc_tready(s_axis_rc_tready),
.s_axis_rc_tuser(s_axis_rc_tuser),
.s_axis_rc_tvalid(s_axis_rc_tvalid),
.s_axis_cq_tdata(s_axis_cq_tdata),
.s_axis_cq_tkeep(s_axis_cq_tkeep),
.s_axis_cq_tlast(s_axis_cq_tlast),
.s_axis_cq_tready(s_axis_cq_tready),
.s_axis_cq_tuser(s_axis_cq_tuser),
.s_axis_cq_tvalid(s_axis_cq_tvalid),
.m_axis_cc_tdata(m_axis_cc_tdata),
.m_axis_cc_tkeep(m_axis_cc_tkeep),
.m_axis_cc_tlast(m_axis_cc_tlast),
.m_axis_cc_tready(m_axis_cc_tready),
.m_axis_cc_tuser(m_axis_cc_tuser),
.m_axis_cc_tvalid(m_axis_cc_tvalid),
.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_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