Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions example/VMK180/fpga/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Verilog PCIe VMK180 Example Design

## Introduction

This example design targets the Xilinx VMK180 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: xcvm1802-vsva2197-2MP-e-S

## 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 VCU180 board with Vivado. Then load the driver with `insmod example.ko`. Check dmesg for the output.
127 changes: 127 additions & 0 deletions example/VMK180/fpga/common/vivado.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
###################################################################
#
# Xilinx Vivado FPGA Makefile
#
# Copyright (c) 2016 Alex Forencich
# Copyright (c) 2025 Jonathan Drolet
#
###################################################################
#
# 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).pdi

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 *.bif *.rcdo *.rnpi gen_files static_files .Xil defines.v
-rm -rf create_project.tcl update_config.tcl run_synth.tcl run_impl.tcl generate_pdi.tcl

clean:: tmpclean
-rm -rf *.pdi 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

# pdi file
%.pdi: %.runs/impl_1/%_routed.dcp
echo "open_project $*.xpr" > generate_pdi.tcl
echo "open_run impl_1" >> generate_pdi.tcl
echo "write_device_image -force $*.pdi" >> generate_pdi.tcl
vivado -nojournal -nolog -mode batch -source generate_pdi.tcl
mkdir -p rev
EXT=pdi; COUNT=100; \
while [ -e rev/$*_rev$$COUNT.$$EXT ]; \
do COUNT=$$((COUNT+1)); done; \
cp $@ rev/$*_rev$$COUNT.$$EXT; \
echo "Output: rev/$*_rev$$COUNT.$$EXT";
1 change: 1 addition & 0 deletions example/VMK180/fpga/driver
61 changes: 61 additions & 0 deletions example/VMK180/fpga/fpga.xdc
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# XDC constraints for the Xilinx VMK180 board
# part: xcvm1802-vsva2197-2MP-e-S



# LEDs
set_property -dict {LOC H34 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports {led[0]}]
set_property -dict {LOC J33 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports {led[1]}]
set_property -dict {LOC K36 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports {led[2]}]
set_property -dict {LOC L35 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports {led[3]}]

set_false_path -to [get_ports {led[*]}]
set_output_delay 0 [get_ports {led[*]}]

# DIP switches
set_property -dict {LOC J35 IOSTANDARD LVCMOS18} [get_ports {sw[0]}]
set_property -dict {LOC J34 IOSTANDARD LVCMOS18} [get_ports {sw[1]}]
set_property -dict {LOC H37 IOSTANDARD LVCMOS18} [get_ports {sw[2]}]
set_property -dict {LOC H36 IOSTANDARD LVCMOS18} [get_ports {sw[3]}]

set_false_path -from [get_ports {sw[*]}]
set_input_delay 0 [get_ports {sw[*]}]

# PCIe clock
set_property -dict {LOC W39 } [get_ports pcie_clk0_p] ;# GTY_REFCLKP0_103
set_property -dict {LOC W40 } [get_ports pcie_clk0_n] ;# GTY_REFCLKN0_103
create_clock -period 10.000 -name pcie_clk [get_ports pcie_clk0_p]

# PCIe Interface
set_property -dict {LOC AB46 } [get_ports {pcie_rx_p[0]}] ;# GTY_RXP0_103
set_property -dict {LOC AB47 } [get_ports {pcie_rx_n[0]}] ;# GTY_RXN0_103
set_property -dict {LOC AB41 } [get_ports {pcie_tx_p[0]}] ;# GTY_TXP0_103
set_property -dict {LOC AB42 } [get_ports {pcie_tx_n[0]}] ;# GTY_TXN0_103
set_property -dict {LOC AA44 } [get_ports {pcie_rx_p[1]}] ;# GTY_RXP2_103
set_property -dict {LOC AA45 } [get_ports {pcie_rx_n[1]}] ;# GTY_RXN2_103
set_property -dict {LOC Y41 } [get_ports {pcie_tx_p[1]}] ;# GTY_TXP2_103
set_property -dict {LOC Y42 } [get_ports {pcie_tx_n[1]}] ;# GTY_TXN2_103
set_property -dict {LOC Y46 } [get_ports {pcie_rx_p[2]}] ;# GTY_RXP2_103
set_property -dict {LOC Y47 } [get_ports {pcie_rx_n[2]}] ;# GTY_RXN2_103
set_property -dict {LOC V41 } [get_ports {pcie_tx_p[2]}] ;# GTY_TXN2_103
set_property -dict {LOC V42 } [get_ports {pcie_tx_n[2]}] ;# GTY_TXN2_103
set_property -dict {LOC W44 } [get_ports {pcie_rx_p[3]}] ;# GTY_RXN3_103
set_property -dict {LOC W45 } [get_ports {pcie_rx_n[3]}] ;# GTY_RXN3_103
set_property -dict {LOC U43 } [get_ports {pcie_tx_p[3]}] ;# GTY_TXN3_103
set_property -dict {LOC U44 } [get_ports {pcie_tx_n[3]}] ;# GTY_TXN3_103
set_property -dict {LOC V46 } [get_ports {pcie_rx_p[4]}] ;# GTY_RXN4_104
set_property -dict {LOC V47 } [get_ports {pcie_rx_n[4]}] ;# GTY_RXN4_104
set_property -dict {LOC T41 } [get_ports {pcie_tx_p[4]}] ;# GTY_TXN4_104
set_property -dict {LOC T42 } [get_ports {pcie_tx_n[4]}] ;# GTY_TXN4_104
set_property -dict {LOC T46 } [get_ports {pcie_rx_p[5]}] ;# GTY_RXN5_104
set_property -dict {LOC T47 } [get_ports {pcie_rx_n[5]}] ;# GTY_RXN5_104
set_property -dict {LOC R43 } [get_ports {pcie_tx_p[5]}] ;# GTY_TXN5_104
set_property -dict {LOC R44 } [get_ports {pcie_tx_n[5]}] ;# GTY_TXN5_104
set_property -dict {LOC P46 } [get_ports {pcie_rx_p[6]}] ;# GTY_RXN6_104
set_property -dict {LOC P47 } [get_ports {pcie_rx_n[6]}] ;# GTY_RXN6_104
set_property -dict {LOC P41 } [get_ports {pcie_tx_p[6]}] ;# GTY_TXN6_104
set_property -dict {LOC P42 } [get_ports {pcie_tx_n[6]}] ;# GTY_TXN6_104
set_property -dict {LOC N44 } [get_ports {pcie_rx_p[7]}] ;# GTY_RXN7_104
set_property -dict {LOC N45 } [get_ports {pcie_rx_n[7]}] ;# GTY_RXN7_104
set_property -dict {LOC M41 } [get_ports {pcie_tx_p[7]}] ;# GTY_TXN7_104
set_property -dict {LOC M42 } [get_ports {pcie_tx_n[7]}] ;# GTY_TXN7_104
57 changes: 57 additions & 0 deletions example/VMK180/fpga/fpga/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@

# FPGA settings
FPGA_PART = xcvm1802-vsva2197-2MP-e-S
FPGA_TOP = fpga
FPGA_ARCH = versalprime

# 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_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/pcie_tlp_fifo.v
SYN_FILES += lib/pcie/rtl/pcie_tlp_fifo_raw.v
SYN_FILES += lib/pcie/rtl/pcie_msix.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/priority_encoder.v
SYN_FILES += lib/pcie/rtl/pulse_merge.v

# XDC files
XDC_FILES = fpga.xdc

# IP
IP_TCL_FILES = ip/versal_cips.tcl

include ../common/vivado.mk

program: $(FPGA_TOP).pdi
echo "open_hw_manager" > program.tcl
echo "connect_hw_server" >> program.tcl
echo "open_hw_target" >> program.tcl
echo "current_hw_device [get_hw_devices xcvm1802_1]" >> program.tcl
echo "refresh_hw_device -update_hw_probes false [current_hw_device]" >> program.tcl
echo "set_property PROGRAM.FILE {$(FPGA_TOP).pdi} [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
Loading