mirror of
https://github.com/corundum/corundum.git
synced 2025-01-30 08:32:52 +08:00
added pcie as a subproject
git-subtree-dir: fpga/lib/pcie git-subtree-mainline: 5ad725bd0ff04fe7fe7ab9983c0c3e64355e0dd2 git-subtree-split: 1d79a4375b42a8dad274b3e0a757f833400d556e
This commit is contained in:
commit
dcea219303
6
fpga/lib/pcie/.gitignore
vendored
Normal file
6
fpga/lib/pcie/.gitignore
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
*~
|
||||
*.lxt
|
||||
*.pyc
|
||||
*.vvp
|
||||
*.kate-swp
|
||||
|
1
fpga/lib/pcie/AUTHORS
Normal file
1
fpga/lib/pcie/AUTHORS
Normal file
@ -0,0 +1 @@
|
||||
Alex Forencich <alex@alexforencich.com>
|
19
fpga/lib/pcie/COPYING
Normal file
19
fpga/lib/pcie/COPYING
Normal file
@ -0,0 +1,19 @@
|
||||
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.
|
1
fpga/lib/pcie/README
Symbolic link
1
fpga/lib/pcie/README
Symbolic link
@ -0,0 +1 @@
|
||||
README.md
|
146
fpga/lib/pcie/README.md
Normal file
146
fpga/lib/pcie/README.md
Normal file
@ -0,0 +1,146 @@
|
||||
# Verilog PCI Express Components Readme
|
||||
|
||||
For more information and updates: http://alexforencich.com/wiki/en/verilog/pcie/start
|
||||
|
||||
GitHub repository: https://github.com/alexforencich/verilog-pcie
|
||||
|
||||
## Introduction
|
||||
|
||||
Collection of PCI express related components. Includes full MyHDL testbench
|
||||
with intelligent bus cosimulation endpoints.
|
||||
|
||||
## Documentation
|
||||
|
||||
### PCIe BFM
|
||||
|
||||
A MyHDL transaction layer PCI Express bus functional model (BFM) is included
|
||||
in pcie.py. This BFM implements an extensive event driven simulation of a
|
||||
complete PCI express system, including root complex, switches, devices, and
|
||||
functions, including support for configuration spaces, capabilities and
|
||||
extended capabilities, and memory and IO operations between devices. The BFM
|
||||
includes code to enumerate the bus, initialize configuration space registers
|
||||
and allocate BARs, route messages between devices, perform memory read and
|
||||
write operations, allocate DMA accessible memory regions in the root complex,
|
||||
and handle message signaled interrupts. Any module can be connected to a
|
||||
cosimulated design, enabling testing of not only isolated components and
|
||||
host-device communication but also communication between multiple components
|
||||
such as device-to-device DMA and message passing.
|
||||
|
||||
A MyHDL model of the Xilinx Ultrascale PCIe hard core is included in
|
||||
pcie_us.py. This module can be used in combination with the PCIe BFM to test
|
||||
a MyHDL or Verilog design that targets a Xilinx Ultrascale FPGA. The model
|
||||
currently only supports operation as a device, not as a root port.
|
||||
|
||||
### arbiter module
|
||||
|
||||
General-purpose parametrizable arbiter. Supports priority and round-robin
|
||||
arbitration. Supports blocking until request release or acknowledge.
|
||||
|
||||
### axis_arb_mux module
|
||||
|
||||
Frame-aware AXI stream arbitrated muliplexer with parametrizable data width
|
||||
and port count. Supports priority and round-robin arbitration.
|
||||
|
||||
### pcie_axi_dma_desc_mux module
|
||||
|
||||
Descriptor multiplexer/demultiplexer for PCIe AXI DMA module. Enables sharing
|
||||
the PCIe AXI DMA module between multiple request sources, interleaving
|
||||
requests and distributing responses.
|
||||
|
||||
### pcie_tag_manager module
|
||||
|
||||
PCIe in-flight tag manager.
|
||||
|
||||
### pcie_us_axi_dma module
|
||||
|
||||
PCIe AXI DMA module for Xilinx Ultrascale series FPGAs. Supports 64, 128, and 256 bit datapaths. Parametrizable AXI burst length. Wrapper for pcie_us_axi_dma_rd and pcie_us_axi_dma_wr
|
||||
|
||||
### pcie_us_axi_dma_rd module
|
||||
|
||||
PCIe AXI DMA module for Xilinx Ultrascale series FPGAs. Supports 64, 128, and 256 bit datapaths. Parametrizable AXI burst length.
|
||||
|
||||
### pcie_us_axi_dma_wr module
|
||||
|
||||
PCIe AXI DMA module for Xilinx Ultrascale series FPGAs. Supports 64, 128, and 256 bit datapaths. Parametrizable AXI burst length.
|
||||
|
||||
### pcie_us_axi_master module
|
||||
|
||||
PCIe AXI master module for Xilinx Ultrascale series FPGAs. Supports 64, 128, and 256 bit datapaths. Parametrizable AXI burst length. Wrapper for pcie_us_axi_master_rd and pcie_us_axi_master_wr.
|
||||
|
||||
### pcie_us_axi_master_rd module
|
||||
|
||||
PCIe AXI master module for Xilinx Ultrascale series FPGAs. Supports 64, 128, and 256 bit datapaths. Parametrizable AXI burst length.
|
||||
|
||||
### pcie_us_axi_master_wr module
|
||||
|
||||
PCIe AXI master module for Xilinx Ultrascale series FPGAs. Supports 64, 128, and 256 bit datapaths. Parametrizable AXI burst length.
|
||||
|
||||
### pcie_us_axil_master module
|
||||
|
||||
PCIe AXI lite master module for Xilinx Ultrascale series FPGAs. Supports 64, 128, and 256 bit PCIe interfaces.
|
||||
|
||||
### pcie_us_axis_cq_demux module
|
||||
|
||||
Demux module for Xilinx Ultrascale CQ interface. Can be used to route
|
||||
incoming requests based on function, BAR, and other fields. Supports 64, 128,
|
||||
and 256 bit datapaths.
|
||||
|
||||
### pcie_us_axis_rc_demux module
|
||||
|
||||
Demux module for Xilinx Ultrascale RC interface. Can be used to route
|
||||
incoming completions based on the requester ID (function). Supports 64, 128,
|
||||
and 256 bit datapaths.
|
||||
|
||||
### pcie_us_cfg module
|
||||
|
||||
Configuration shim for Xilinx Ultrascale series FPGAs.
|
||||
|
||||
### pcie_us_msi module
|
||||
|
||||
MSI shim for Xilinx Ultrascale series FPGAs.
|
||||
|
||||
### priority_encoder module
|
||||
|
||||
Parametrizable priority encoder.
|
||||
|
||||
### pulse_merge module
|
||||
|
||||
Parametrizable pulse merge module. Combines several single-cycle pulse status
|
||||
signals together.
|
||||
|
||||
### Common signals
|
||||
|
||||
### Common parameters
|
||||
|
||||
### Source Files
|
||||
|
||||
arbiter.v : Parametrizable arbiter
|
||||
axis_arb_mux.v : Parametrizable AXI stream mux
|
||||
pcie_axi_dma_desc_mux.v : Descriptor mux for DMA engine
|
||||
pcie_tag_manager.v : PCIe in-flight tag manager
|
||||
pcie_us_axi_dma.v : PCIe AXI DMA module with Xilinx Ultrascale interface
|
||||
pcie_us_axi_dma_rd.v : PCIe AXI DMA read module with Xilinx Ultrascale interface
|
||||
pcie_us_axi_dma_wr.v : PCIe AXI DMA write module with Xilinx Ultrascale interface
|
||||
pcie_us_axi_master.v : AXI Master module with Xilinx Ultrascale interface
|
||||
pcie_us_axi_master_rd.v : AXI Master read module with Xilinx Ultrascale interface
|
||||
pcie_us_axi_master_wr.v : AXI Master write module with Xilinx Ultrascale interface
|
||||
pcie_us_axil_master.v : AXI Lite Master module with Xilinx Ultrascale interface
|
||||
pcie_us_axis_cq_demux.v : Parametrizable AXI stream CQ demux
|
||||
pcie_us_axis_rc_demux.v : Parametrizable AXI stream RC demux
|
||||
pcie_us_cfg.v : Configuration shim for Xilinx Ultrascale devices
|
||||
pcie_us_msi.v : MSI shim for Xilinx Ultrascale devices
|
||||
priority_encoder.v : Parametrizable priority encoder
|
||||
pulse_merge : Parametrizable pulse merge module
|
||||
|
||||
## Testing
|
||||
|
||||
Running the included testbenches requires MyHDL and Icarus Verilog. Make sure
|
||||
that myhdl.vpi is installed properly for cosimulation to work correctly. The
|
||||
testbenches can be run with a Python test runner like nose or py.test, or the
|
||||
individual test scripts can be run with python directly.
|
||||
|
||||
### Testbench Files
|
||||
|
||||
tb/axis_ep.py : MyHDL AXI Stream endpoints
|
||||
tb/pcie.py : MyHDL PCI Express BFM
|
||||
tb/pcie_us.py : MyHDL Xilinx Ultrascale PCIe core model
|
25
fpga/lib/pcie/example/ExaNIC_X10/fpga/Makefile
Normal file
25
fpga/lib/pcie/example/ExaNIC_X10/fpga/Makefile
Normal 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
|
26
fpga/lib/pcie/example/ExaNIC_X10/fpga/README.md
Normal file
26
fpga/lib/pcie/example/ExaNIC_X10/fpga/README.md
Normal file
@ -0,0 +1,26 @@
|
||||
# Verilog Ethernet ExaNIC X10 Example Design
|
||||
|
||||
## Introduction
|
||||
|
||||
This example design targets the Exablaze ExaNIC X10 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: xcku035-fbva676-2-c
|
||||
|
||||
## 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 ExaNIC X10 board with Vivado. Then load the
|
||||
driver with insmod example.ko. Check dmesg for the output.
|
||||
|
||||
|
118
fpga/lib/pcie/example/ExaNIC_X10/fpga/common/vivado.mk
Normal file
118
fpga/lib/pcie/example/ExaNIC_X10/fpga/common/vivado.mk
Normal file
@ -0,0 +1,118 @@
|
||||
###################################################################
|
||||
#
|
||||
# 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))
|
||||
|
||||
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
|
||||
|
||||
tmpclean:
|
||||
-rm -rf *.log *.jou *.cache *.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)
|
||||
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
|
||||
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";
|
11
fpga/lib/pcie/example/ExaNIC_X10/fpga/driver/Makefile
Normal file
11
fpga/lib/pcie/example/ExaNIC_X10/fpga/driver/Makefile
Normal file
@ -0,0 +1,11 @@
|
||||
|
||||
# object files to build
|
||||
obj-m += example.o
|
||||
example-objs += example_driver.o
|
||||
|
||||
all:
|
||||
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
|
||||
|
||||
clean:
|
||||
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
|
||||
|
371
fpga/lib/pcie/example/ExaNIC_X10/fpga/driver/example_driver.c
Normal file
371
fpga/lib/pcie/example/ExaNIC_X10/fpga/driver/example_driver.c
Normal file
@ -0,0 +1,371 @@
|
||||
/*
|
||||
|
||||
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.
|
||||
|
||||
*/
|
||||
|
||||
#include "example_driver.h"
|
||||
#include <linux/module.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/pci-aspm.h>
|
||||
#include <linux/delay.h>
|
||||
|
||||
MODULE_DESCRIPTION("verilog-pcie example driver");
|
||||
MODULE_AUTHOR("Alex Forencich");
|
||||
MODULE_LICENSE("Dual MIT/GPL");
|
||||
MODULE_VERSION(DRIVER_VERSION);
|
||||
MODULE_SUPPORTED_DEVICE(DRIVER_NAME);
|
||||
|
||||
static int edev_probe(struct pci_dev *pdev, const struct pci_device_id *ent);
|
||||
static void edev_remove(struct pci_dev *pdev);
|
||||
static void edev_shutdown(struct pci_dev *pdev);
|
||||
|
||||
static int enumerate_bars(struct example_dev *edev, struct pci_dev *pdev);
|
||||
static int map_bars(struct example_dev *edev, struct pci_dev *pdev);
|
||||
static void free_bars(struct example_dev *edev, struct pci_dev *pdev);
|
||||
|
||||
static const struct pci_device_id pci_ids[] = {
|
||||
{ PCI_DEVICE(0x1234, 0x0001) },
|
||||
{ 0 /* end */ }
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(pci, pci_ids);
|
||||
|
||||
static irqreturn_t edev_intr(int irq, void *data)
|
||||
{
|
||||
struct example_dev *edev = data;
|
||||
struct device *dev = &edev->pdev->dev;
|
||||
|
||||
edev->irqcount++;
|
||||
|
||||
dev_info(dev, "Interrupt");
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int edev_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
{
|
||||
int ret = 0;
|
||||
struct example_dev *edev;
|
||||
struct device *dev = &pdev->dev;
|
||||
|
||||
int k;
|
||||
|
||||
dev_info(dev, "edev probe");
|
||||
dev_info(dev, " vendor: 0x%04x", pdev->vendor);
|
||||
dev_info(dev, " device: 0x%04x", pdev->device);
|
||||
dev_info(dev, " class: 0x%06x", pdev->class);
|
||||
dev_info(dev, " pci id: %02x:%02x.%02x", pdev->bus->number, PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn));
|
||||
|
||||
if (!(edev = devm_kzalloc(dev, sizeof(struct example_dev), GFP_KERNEL))) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
edev->pdev = pdev;
|
||||
pci_set_drvdata(pdev, edev);
|
||||
|
||||
// Allocate DMA buffer
|
||||
edev->dma_region_len = 16*1024;
|
||||
edev->dma_region = dma_alloc_coherent(dev, edev->dma_region_len, &edev->dma_region_addr, GFP_KERNEL | __GFP_ZERO);
|
||||
if (!edev->dma_region)
|
||||
{
|
||||
dev_err(dev, "Failed to allocate DMA buffer");
|
||||
ret = -ENOMEM;
|
||||
goto fail_dma_alloc;
|
||||
}
|
||||
|
||||
dev_info(dev, "Allocated DMA region virt %p, phys %p", edev->dma_region, (void *)edev->dma_region_addr);
|
||||
|
||||
// Disable ASPM
|
||||
pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1 | PCIE_LINK_STATE_CLKPM);
|
||||
|
||||
// Enable device
|
||||
ret = pci_enable_device_mem(pdev);
|
||||
if (ret)
|
||||
{
|
||||
dev_err(dev, "Failed to enable PCI device");
|
||||
//ret = -ENODEV;
|
||||
goto fail_enable_device;
|
||||
}
|
||||
|
||||
// Enable bus mastering for DMA
|
||||
pci_set_master(pdev);
|
||||
|
||||
// Reserve regions
|
||||
ret = pci_request_regions(pdev, DRIVER_NAME);
|
||||
if (ret)
|
||||
{
|
||||
dev_err(dev, "Failed to reserve regions");
|
||||
//ret = -EBUSY;
|
||||
goto fail_regions;
|
||||
}
|
||||
|
||||
// Enumerate BARs
|
||||
enumerate_bars(edev, pdev);
|
||||
|
||||
// Map BARs
|
||||
ret = map_bars(edev, pdev);
|
||||
if (ret)
|
||||
{
|
||||
dev_err(dev, "Failed to map BARs");
|
||||
goto fail_map_bars;
|
||||
}
|
||||
|
||||
// Allocate MSI IRQs
|
||||
ret = pci_alloc_irq_vectors(pdev, 1, 32, PCI_IRQ_MSI);
|
||||
if (ret < 0)
|
||||
{
|
||||
dev_err(dev, "Failed to allocate IRQs");
|
||||
goto fail_map_bars;
|
||||
}
|
||||
|
||||
// Set up interrupt
|
||||
ret = pci_request_irq(pdev, 0, edev_intr, 0, edev, "edev");
|
||||
if (ret < 0)
|
||||
{
|
||||
dev_err(dev, "Failed to request IRQ");
|
||||
goto fail_irq;
|
||||
}
|
||||
|
||||
// Dump counters
|
||||
dev_info(dev, "TLP counters");
|
||||
dev_info(dev, "RQ: %d", ioread32(edev->bar[0]+0x000400));
|
||||
dev_info(dev, "RC: %d", ioread32(edev->bar[0]+0x000404));
|
||||
dev_info(dev, "CQ: %d", ioread32(edev->bar[0]+0x000408));
|
||||
dev_info(dev, "CC: %d", ioread32(edev->bar[0]+0x00040C));
|
||||
|
||||
// Read/write test
|
||||
dev_info(dev, "write to BAR1");
|
||||
iowrite32(0x11223344, edev->bar[1]);
|
||||
|
||||
dev_info(dev, "read from BAR1");
|
||||
dev_info(dev, "%08x", ioread32(edev->bar[1]));
|
||||
|
||||
// Dump counters
|
||||
dev_info(dev, "TLP counters");
|
||||
dev_info(dev, "RQ: %d", ioread32(edev->bar[0]+0x000400));
|
||||
dev_info(dev, "RC: %d", ioread32(edev->bar[0]+0x000404));
|
||||
dev_info(dev, "CQ: %d", ioread32(edev->bar[0]+0x000408));
|
||||
dev_info(dev, "CC: %d", ioread32(edev->bar[0]+0x00040C));
|
||||
|
||||
// PCIe DMA test
|
||||
dev_info(dev, "write test data");
|
||||
for (k = 0; k < 256; k++)
|
||||
{
|
||||
((char *)edev->dma_region)[k] = k;
|
||||
}
|
||||
|
||||
dev_info(dev, "read test data");
|
||||
print_hex_dump(KERN_INFO, "", DUMP_PREFIX_NONE, 16, 1, edev->dma_region, 256, true);
|
||||
|
||||
dev_info(dev, "check DMA enable");
|
||||
dev_info(dev, "%08x", ioread32(edev->bar[0]+0x000000));
|
||||
|
||||
dev_info(dev, "enable DMA");
|
||||
iowrite32(0x1, edev->bar[0]+0x000000);
|
||||
|
||||
dev_info(dev, "check DMA enable");
|
||||
dev_info(dev, "%08x", ioread32(edev->bar[0]+0x000000));
|
||||
|
||||
dev_info(dev, "start copy to card");
|
||||
iowrite32((edev->dma_region_addr+0x0000)&0xffffffff, edev->bar[0]+0x000100);
|
||||
iowrite32(((edev->dma_region_addr+0x0000) >> 32)&0xffffffff, edev->bar[0]+0x000104);
|
||||
iowrite32(0x100, edev->bar[0]+0x000108);
|
||||
iowrite32(0, edev->bar[0]+0x00010C);
|
||||
iowrite32(0x100, edev->bar[0]+0x000110);
|
||||
iowrite32(0xAA, edev->bar[0]+0x000114);
|
||||
|
||||
msleep(1);
|
||||
|
||||
dev_info(dev, "Read status");
|
||||
dev_info(dev, "%08x", ioread32(edev->bar[0]+0x000118));
|
||||
|
||||
dev_info(dev, "start copy to host");
|
||||
iowrite32((edev->dma_region_addr+0x0200)&0xffffffff, edev->bar[0]+0x000200);
|
||||
iowrite32(((edev->dma_region_addr+0x0200) >> 32)&0xffffffff, edev->bar[0]+0x000204);
|
||||
iowrite32(0x100, edev->bar[0]+0x000208);
|
||||
iowrite32(0, edev->bar[0]+0x00020C);
|
||||
iowrite32(0x100, edev->bar[0]+0x000210);
|
||||
iowrite32(0x55, edev->bar[0]+0x000214);
|
||||
|
||||
msleep(1);
|
||||
|
||||
dev_info(dev, "Read status");
|
||||
dev_info(dev, "%08x", ioread32(edev->bar[0]+0x000218));
|
||||
|
||||
dev_info(dev, "read test data");
|
||||
print_hex_dump(KERN_INFO, "", DUMP_PREFIX_NONE, 16, 1, edev->dma_region+0x0200, 256, true);
|
||||
|
||||
// Dump counters
|
||||
dev_info(dev, "TLP counters");
|
||||
dev_info(dev, "RQ: %d", ioread32(edev->bar[0]+0x000400));
|
||||
dev_info(dev, "RC: %d", ioread32(edev->bar[0]+0x000404));
|
||||
dev_info(dev, "CQ: %d", ioread32(edev->bar[0]+0x000408));
|
||||
dev_info(dev, "CC: %d", ioread32(edev->bar[0]+0x00040C));
|
||||
|
||||
// probe complete
|
||||
return 0;
|
||||
|
||||
// error handling
|
||||
fail_irq:
|
||||
pci_free_irq_vectors(pdev);
|
||||
fail_map_bars:
|
||||
free_bars(edev, pdev);
|
||||
pci_release_regions(pdev);
|
||||
fail_regions:
|
||||
pci_clear_master(pdev);
|
||||
pci_disable_device(pdev);
|
||||
fail_enable_device:
|
||||
dma_free_coherent(dev, edev->dma_region_len, edev->dma_region, edev->dma_region_addr);
|
||||
fail_dma_alloc:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void edev_remove(struct pci_dev *pdev)
|
||||
{
|
||||
struct example_dev *edev;
|
||||
struct device *dev = &pdev->dev;
|
||||
|
||||
dev_info(dev, "edev remove");
|
||||
|
||||
if (!(edev = pci_get_drvdata(pdev))) {
|
||||
return;
|
||||
}
|
||||
|
||||
pci_free_irq(pdev, 0, edev);
|
||||
pci_free_irq_vectors(pdev);
|
||||
free_bars(edev, pdev);
|
||||
pci_release_regions(pdev);
|
||||
pci_clear_master(pdev);
|
||||
pci_disable_device(pdev);
|
||||
dma_free_coherent(dev, edev->dma_region_len, edev->dma_region, edev->dma_region_addr);
|
||||
}
|
||||
|
||||
static void edev_shutdown(struct pci_dev *pdev)
|
||||
{
|
||||
struct example_dev *edev = pci_get_drvdata(pdev);
|
||||
struct device *dev = &pdev->dev;
|
||||
|
||||
dev_info(dev, "edev shutdown");
|
||||
|
||||
if (!edev) {
|
||||
return;
|
||||
}
|
||||
|
||||
// ensure DMA is disabled on shutdown
|
||||
pci_clear_master(pdev);
|
||||
}
|
||||
|
||||
static int enumerate_bars(struct example_dev *edev, struct pci_dev *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < DEV_BAR_CNT; i++)
|
||||
{
|
||||
resource_size_t bar_start = pci_resource_start(pdev, i);
|
||||
if (bar_start)
|
||||
{
|
||||
resource_size_t bar_end = pci_resource_end(pdev, i);
|
||||
unsigned long bar_flags = pci_resource_flags(pdev, i);
|
||||
dev_info(dev, "BAR[%d] 0x%08llx-0x%08llx flags 0x%08lx",
|
||||
i, bar_start, bar_end, bar_flags);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int map_bars(struct example_dev *edev, struct pci_dev *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < DEV_BAR_CNT; i++)
|
||||
{
|
||||
resource_size_t bar_start = pci_resource_start(pdev, i);
|
||||
resource_size_t bar_end = pci_resource_end(pdev, i);
|
||||
resource_size_t bar_len = bar_end - bar_start + 1;
|
||||
edev->bar_len[i] = bar_len;
|
||||
|
||||
if (!bar_start || !bar_end)
|
||||
{
|
||||
edev->bar_len[i] = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (bar_len < 1)
|
||||
{
|
||||
dev_warn(dev, "BAR[%d] is less than 1 byte", i);
|
||||
continue;
|
||||
}
|
||||
|
||||
edev->bar[i] = pci_ioremap_bar(pdev, i);
|
||||
|
||||
if (!edev->bar[i])
|
||||
{
|
||||
dev_err(dev, "Could not map BAR[%d]", i);
|
||||
return -1;
|
||||
}
|
||||
|
||||
dev_info(dev, "BAR[%d] mapped at 0x%p with length %llu", i, edev->bar[i], bar_len);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void free_bars(struct example_dev *edev, struct pci_dev *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < DEV_BAR_CNT; i++)
|
||||
{
|
||||
if (edev->bar[i])
|
||||
{
|
||||
pci_iounmap(pdev, edev->bar[i]);
|
||||
edev->bar[i] = NULL;
|
||||
dev_info(dev, "Unmapped BAR[%d]", i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static struct pci_driver pci_driver = {
|
||||
.name = DRIVER_NAME,
|
||||
.id_table = pci_ids,
|
||||
.probe = edev_probe,
|
||||
.remove = edev_remove,
|
||||
.shutdown = edev_shutdown
|
||||
};
|
||||
|
||||
static int __init edev_init(void)
|
||||
{
|
||||
return pci_register_driver(&pci_driver);
|
||||
}
|
||||
|
||||
static void __exit edev_exit(void)
|
||||
{
|
||||
pci_unregister_driver(&pci_driver);
|
||||
}
|
||||
|
||||
module_init(edev_init);
|
||||
module_exit(edev_exit);
|
||||
|
@ -0,0 +1,50 @@
|
||||
/*
|
||||
|
||||
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.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef EXAMPLE_DRIVER_H
|
||||
#define EXAMPLE_DRIVER_H
|
||||
|
||||
#include <linux/kernel.h>
|
||||
|
||||
#define DRIVER_NAME "edev"
|
||||
#define DRIVER_VERSION "0.1"
|
||||
|
||||
#define DEV_BAR_CNT 2
|
||||
|
||||
struct example_dev {
|
||||
struct pci_dev *pdev;
|
||||
|
||||
// BAR pointers
|
||||
void * __iomem bar[DEV_BAR_CNT];
|
||||
resource_size_t bar_len[DEV_BAR_CNT];
|
||||
|
||||
// DMA buffer
|
||||
size_t dma_region_len;
|
||||
void *dma_region;
|
||||
dma_addr_t dma_region_addr;
|
||||
|
||||
int irqcount;
|
||||
};
|
||||
|
||||
#endif /* EXAMPLE_DRIVER_H */
|
153
fpga/lib/pcie/example/ExaNIC_X10/fpga/fpga.xdc
Normal file
153
fpga/lib/pcie/example/ExaNIC_X10/fpga/fpga.xdc
Normal file
@ -0,0 +1,153 @@
|
||||
# XDC constraints for the ExaNIC X10
|
||||
# part: xcku035-fbva676-2-e
|
||||
|
||||
# General configuration
|
||||
set_property CFGBVS GND [current_design]
|
||||
set_property CONFIG_VOLTAGE 1.8 [current_design]
|
||||
set_property BITSTREAM.GENERAL.COMPRESS true [current_design]
|
||||
set_property BITSTREAM.CONFIG.UNUSEDPIN Pullup [current_design]
|
||||
set_property BITSTREAM.CONFIG.CONFIGRATE 50 [current_design]
|
||||
set_property BITSTREAM.CONFIG.BPI_SYNC_MODE Type2 [current_design]
|
||||
set_property CONFIG_MODE BPI16 [current_design]
|
||||
|
||||
# 100 MHz system clock
|
||||
#set_property -dict {LOC D18 IOSTANDARD LVDS} [get_ports clk_100mhz_p]
|
||||
#set_property -dict {LOC C18 IOSTANDARD LVDS} [get_ports clk_100mhz_n]
|
||||
#create_clock -period 10 -name clk_100mhz [get_ports clk_100mhz_p]
|
||||
|
||||
# LEDs
|
||||
set_property -dict {LOC A25 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 12} [get_ports {sfp_1_led[0]}]
|
||||
set_property -dict {LOC A24 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 12} [get_ports {sfp_1_led[1]}]
|
||||
set_property -dict {LOC E23 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 12} [get_ports {sfp_2_led[0]}]
|
||||
set_property -dict {LOC D26 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 12} [get_ports {sfp_2_led[1]}]
|
||||
set_property -dict {LOC C23 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 12} [get_ports {sma_led[0]}]
|
||||
set_property -dict {LOC D23 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 12} [get_ports {sma_led[1]}]
|
||||
|
||||
# GPIO
|
||||
#set_property -dict {LOC W26 IOSTANDARD LVCMOS18} [get_ports gpio[0]]
|
||||
#set_property -dict {LOC Y26 IOSTANDARD LVCMOS18} [get_ports gpio[1]]
|
||||
#set_property -dict {LOC AB26 IOSTANDARD LVCMOS18} [get_ports gpio[2]]
|
||||
#set_property -dict {LOC AC26 IOSTANDARD LVCMOS18} [get_ports gpio[3]]
|
||||
|
||||
# SMA
|
||||
#set_property -dict {LOC B17 IOSTANDARD LVCMOS18} [get_ports sma_in]
|
||||
#set_property -dict {LOC B16 IOSTANDARD LVCMOS18} [get_ports sma_out]
|
||||
#set_property -dict {LOC B19 IOSTANDARD LVCMOS18} [get_ports sma_out_en]
|
||||
#set_property -dict {LOC C16 IOSTANDARD LVCMOS18} [get_ports sma_term_en]
|
||||
|
||||
# SFP+ Interface
|
||||
#set_property -dict {LOC D2 } [get_ports sfp_1_rx_p] ;# MGTHTXN0_227 GTHE3_CHANNEL_X0Y12 / GTHE3_COMMON_X0Y3
|
||||
#set_property -dict {LOC D1 } [get_ports sfp_1_rx_n] ;# MGTHTXP0_227 GTHE3_CHANNEL_X0Y12 / GTHE3_COMMON_X0Y3
|
||||
#set_property -dict {LOC E4 } [get_ports sfp_1_tx_p] ;# MGTHTXN0_227 GTHE3_CHANNEL_X0Y12 / GTHE3_COMMON_X0Y3
|
||||
#set_property -dict {LOC E3 } [get_ports sfp_1_tx_n] ;# MGTHTXP0_227 GTHE3_CHANNEL_X0Y12 / GTHE3_COMMON_X0Y3
|
||||
#set_property -dict {LOC C4 } [get_ports sfp_2_rx_p] ;# MGTHTXN1_227 GTHE3_CHANNEL_X0Y13 / GTHE3_COMMON_X0Y3
|
||||
#set_property -dict {LOC C3 } [get_ports sfp_2_rx_n] ;# MGTHTXP1_227 GTHE3_CHANNEL_X0Y13 / GTHE3_COMMON_X0Y3
|
||||
#set_property -dict {LOC D6 } [get_ports sfp_2_tx_p] ;# MGTHTXN1_227 GTHE3_CHANNEL_X0Y13 / GTHE3_COMMON_X0Y3
|
||||
#set_property -dict {LOC D5 } [get_ports sfp_2_tx_n] ;# MGTHTXP1_227 GTHE3_CHANNEL_X0Y13 / GTHE3_COMMON_X0Y3
|
||||
#set_property -dict {LOC H6 } [get_ports sfp_mgt_refclk_p] ;# MGTREFCLK0P_227 from X2
|
||||
#set_property -dict {LOC H5 } [get_ports sfp_mgt_refclk_n] ;# MGTREFCLK0N_227 from X2
|
||||
#set_property -dict {LOC AA12 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 12} [get_ports sfp_1_tx_disable]
|
||||
#set_property -dict {LOC W14 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 12} [get_ports sfp_2_tx_disable]
|
||||
#set_property -dict {LOC C24 IOSTANDARD LVCMOS18 PULLUP true} [get_ports sfp_1_npres]
|
||||
#set_property -dict {LOC D24 IOSTANDARD LVCMOS18 PULLUP true} [get_ports sfp_2_npres]
|
||||
#set_property -dict {LOC W13 IOSTANDARD LVCMOS18 PULLUP true} [get_ports sfp_1_los]
|
||||
#set_property -dict {LOC AB12 IOSTANDARD LVCMOS18 PULLUP true} [get_ports sfp_2_los]
|
||||
#set_property -dict {LOC B25 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 12} [get_ports sfp_1_rs]
|
||||
#set_property -dict {LOC D25 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 12} [get_ports sfp_2_rs]
|
||||
#set_property -dict {LOC W11 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 12 PULLUP true} [get_ports sfp_i2c_scl]
|
||||
#set_property -dict {LOC Y11 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 12 PULLUP true} [get_ports sfp_1_i2c_sda]
|
||||
#set_property -dict {LOC Y13 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 12 PULLUP true} [get_ports sfp_2_i2c_sda]
|
||||
|
||||
# 161.1328125 MHz MGT reference clock
|
||||
#create_clock -period 6.206 -name sfp_mgt_refclk [get_ports sfp_mgt_refclk_p]
|
||||
|
||||
# I2C interface
|
||||
#set_property -dict {LOC B26 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 12 PULLUP true} [get_ports eeprom_i2c_scl]
|
||||
#set_property -dict {LOC C26 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 12 PULLUP true} [get_ports eeprom_i2c_sda]
|
||||
|
||||
# PCIe Interface
|
||||
set_property -dict {LOC AF2 } [get_ports {pcie_rx_p[7]}] ;# MGTHTXN0_224 GTHE3_CHANNEL_X0Y0 / GTHE3_COMMON_X0Y0
|
||||
#set_property -dict {LOC AF1 } [get_ports {pcie_rx_n[7]}] ;# MGTHTXP0_224 GTHE3_CHANNEL_X0Y0 / GTHE3_COMMON_X0Y0
|
||||
set_property -dict {LOC AF6 } [get_ports {pcie_tx_p[7]}] ;# MGTHTXN0_224 GTHE3_CHANNEL_X0Y0 / GTHE3_COMMON_X0Y0
|
||||
#set_property -dict {LOC AF5 } [get_ports {pcie_tx_n[7]}] ;# MGTHTXP0_224 GTHE3_CHANNEL_X0Y0 / GTHE3_COMMON_X0Y0
|
||||
set_property -dict {LOC AE4 } [get_ports {pcie_rx_p[6]}] ;# MGTHTXN1_224 GTHE3_CHANNEL_X0Y1 / GTHE3_COMMON_X0Y0
|
||||
#set_property -dict {LOC AE3 } [get_ports {pcie_rx_n[6]}] ;# MGTHTXP1_224 GTHE3_CHANNEL_X0Y1 / GTHE3_COMMON_X0Y0
|
||||
set_property -dict {LOC AD6 } [get_ports {pcie_tx_p[6]}] ;# MGTHTXN1_224 GTHE3_CHANNEL_X0Y1 / GTHE3_COMMON_X0Y0
|
||||
#set_property -dict {LOC AD5 } [get_ports {pcie_tx_n[6]}] ;# MGTHTXP1_224 GTHE3_CHANNEL_X0Y1 / GTHE3_COMMON_X0Y0
|
||||
set_property -dict {LOC AD2 } [get_ports {pcie_rx_p[5]}] ;# MGTHTXN2_224 GTHE3_CHANNEL_X0Y2 / GTHE3_COMMON_X0Y0
|
||||
#set_property -dict {LOC AD1 } [get_ports {pcie_rx_n[5]}] ;# MGTHTXP2_224 GTHE3_CHANNEL_X0Y2 / GTHE3_COMMON_X0Y0
|
||||
set_property -dict {LOC AC4 } [get_ports {pcie_tx_p[5]}] ;# MGTHTXN2_224 GTHE3_CHANNEL_X0Y2 / GTHE3_COMMON_X0Y0
|
||||
#set_property -dict {LOC AC3 } [get_ports {pcie_tx_n[5]}] ;# MGTHTXP2_224 GTHE3_CHANNEL_X0Y2 / GTHE3_COMMON_X0Y0
|
||||
set_property -dict {LOC AB2 } [get_ports {pcie_rx_p[4]}] ;# MGTHTXN3_224 GTHE3_CHANNEL_X0Y3 / GTHE3_COMMON_X0Y0
|
||||
#set_property -dict {LOC AB1 } [get_ports {pcie_rx_n[4]}] ;# MGTHTXP3_224 GTHE3_CHANNEL_X0Y3 / GTHE3_COMMON_X0Y0
|
||||
set_property -dict {LOC AB6 } [get_ports {pcie_tx_p[4]}] ;# MGTHTXN3_224 GTHE3_CHANNEL_X0Y3 / GTHE3_COMMON_X0Y0
|
||||
#set_property -dict {LOC AB5 } [get_ports {pcie_tx_n[4]}] ;# MGTHTXP3_224 GTHE3_CHANNEL_X0Y3 / GTHE3_COMMON_X0Y0
|
||||
set_property -dict {LOC Y2 } [get_ports {pcie_rx_p[3]}] ;# MGTHTXN0_225 GTHE3_CHANNEL_X0Y4 / GTHE3_COMMON_X0Y1
|
||||
#set_property -dict {LOC Y1 } [get_ports {pcie_rx_n[3]}] ;# MGTHTXP0_225 GTHE3_CHANNEL_X0Y4 / GTHE3_COMMON_X0Y1
|
||||
set_property -dict {LOC AA4 } [get_ports {pcie_tx_p[3]}] ;# MGTHTXN0_225 GTHE3_CHANNEL_X0Y4 / GTHE3_COMMON_X0Y1
|
||||
#set_property -dict {LOC AA3 } [get_ports {pcie_tx_n[3]}] ;# MGTHTXP0_225 GTHE3_CHANNEL_X0Y4 / GTHE3_COMMON_X0Y1
|
||||
set_property -dict {LOC V2 } [get_ports {pcie_rx_p[2]}] ;# MGTHTXN1_225 GTHE3_CHANNEL_X0Y5 / GTHE3_COMMON_X0Y1
|
||||
#set_property -dict {LOC V1 } [get_ports {pcie_rx_n[2]}] ;# MGTHTXP1_225 GTHE3_CHANNEL_X0Y5 / GTHE3_COMMON_X0Y1
|
||||
set_property -dict {LOC W4 } [get_ports {pcie_tx_p[2]}] ;# MGTHTXN1_225 GTHE3_CHANNEL_X0Y5 / GTHE3_COMMON_X0Y1
|
||||
#set_property -dict {LOC W3 } [get_ports {pcie_tx_n[2]}] ;# MGTHTXP1_225 GTHE3_CHANNEL_X0Y5 / GTHE3_COMMON_X0Y1
|
||||
set_property -dict {LOC T2 } [get_ports {pcie_rx_p[1]}] ;# MGTHTXN2_225 GTHE3_CHANNEL_X0Y6 / GTHE3_COMMON_X0Y1
|
||||
#set_property -dict {LOC T1 } [get_ports {pcie_rx_n[1]}] ;# MGTHTXP2_225 GTHE3_CHANNEL_X0Y6 / GTHE3_COMMON_X0Y1
|
||||
set_property -dict {LOC U4 } [get_ports {pcie_tx_p[1]}] ;# MGTHTXN2_225 GTHE3_CHANNEL_X0Y6 / GTHE3_COMMON_X0Y1
|
||||
#set_property -dict {LOC U3 } [get_ports {pcie_tx_n[1]}] ;# MGTHTXP2_225 GTHE3_CHANNEL_X0Y6 / GTHE3_COMMON_X0Y1
|
||||
set_property -dict {LOC P2 } [get_ports {pcie_rx_p[0]}] ;# MGTHTXN3_225 GTHE3_CHANNEL_X0Y7 / GTHE3_COMMON_X0Y1
|
||||
#set_property -dict {LOC P1 } [get_ports {pcie_rx_n[0]}] ;# MGTHTXP3_225 GTHE3_CHANNEL_X0Y7 / GTHE3_COMMON_X0Y1
|
||||
set_property -dict {LOC R4 } [get_ports {pcie_tx_p[0]}] ;# MGTHTXN3_225 GTHE3_CHANNEL_X0Y7 / GTHE3_COMMON_X0Y1
|
||||
#set_property -dict {LOC R3 } [get_ports {pcie_tx_n[0]}] ;# MGTHTXP3_225 GTHE3_CHANNEL_X0Y7 / GTHE3_COMMON_X0Y1
|
||||
set_property -dict {LOC T6 } [get_ports pcie_mgt_refclk_p] ;# MGTREFCLK0P_225
|
||||
#set_property -dict {LOC T5 } [get_ports pcie_mgt_refclk_n] ;# MGTREFCLK0N_225
|
||||
set_property -dict {LOC AC22 IOSTANDARD LVCMOS18 PULLUP true} [get_ports pcie_reset_n]
|
||||
|
||||
# 100 MHz MGT reference clock
|
||||
create_clock -period 10 -name pcie_mgt_refclk [get_ports pcie_mgt_refclk_p]
|
||||
|
||||
# Flash
|
||||
#set_property -dict {LOC AE10 IOSTANDARD LVCMOS18 DRIVE 16} [get_ports {flash_dq[0]}]
|
||||
#set_property -dict {LOC AC8 IOSTANDARD LVCMOS18 DRIVE 16} [get_ports {flash_dq[1]}]
|
||||
#set_property -dict {LOC AD10 IOSTANDARD LVCMOS18 DRIVE 16} [get_ports {flash_dq[2]}]
|
||||
#set_property -dict {LOC AD9 IOSTANDARD LVCMOS18 DRIVE 16} [get_ports {flash_dq[3]}]
|
||||
#set_property -dict {LOC AC11 IOSTANDARD LVCMOS18 DRIVE 16} [get_ports {flash_dq[4]}]
|
||||
#set_property -dict {LOC AF10 IOSTANDARD LVCMOS18 DRIVE 16} [get_ports {flash_dq[5]}]
|
||||
#set_property -dict {LOC AF14 IOSTANDARD LVCMOS18 DRIVE 16} [get_ports {flash_dq[6]}]
|
||||
#set_property -dict {LOC AE12 IOSTANDARD LVCMOS18 DRIVE 16} [get_ports {flash_dq[7]}]
|
||||
#set_property -dict {LOC AD14 IOSTANDARD LVCMOS18 DRIVE 16} [get_ports {flash_dq[8]}]
|
||||
#set_property -dict {LOC AF13 IOSTANDARD LVCMOS18 DRIVE 16} [get_ports {flash_dq[9]}]
|
||||
#set_property -dict {LOC AE13 IOSTANDARD LVCMOS18 DRIVE 16} [get_ports {flash_dq[10]}]
|
||||
#set_property -dict {LOC AD8 IOSTANDARD LVCMOS18 DRIVE 16} [get_ports {flash_dq[11]}]
|
||||
#set_property -dict {LOC AC13 IOSTANDARD LVCMOS18 DRIVE 16} [get_ports {flash_dq[12]}]
|
||||
#set_property -dict {LOC AD13 IOSTANDARD LVCMOS18 DRIVE 16} [get_ports {flash_dq[13]}]
|
||||
#set_property -dict {LOC AA14 IOSTANDARD LVCMOS18 DRIVE 16} [get_ports {flash_dq[14]}]
|
||||
#set_property -dict {LOC AB15 IOSTANDARD LVCMOS18 DRIVE 16} [get_ports {flash_dq[15]}]
|
||||
#set_property -dict {LOC AD11 IOSTANDARD LVCMOS18 DRIVE 16} [get_ports {flash_addr[0]}]
|
||||
#set_property -dict {LOC AE11 IOSTANDARD LVCMOS18 DRIVE 16} [get_ports {flash_addr[1]}]
|
||||
#set_property -dict {LOC AF12 IOSTANDARD LVCMOS18 DRIVE 16} [get_ports {flash_addr[2]}]
|
||||
#set_property -dict {LOC AB11 IOSTANDARD LVCMOS18 DRIVE 16} [get_ports {flash_addr[3]}]
|
||||
#set_property -dict {LOC AB9 IOSTANDARD LVCMOS18 DRIVE 16} [get_ports {flash_addr[4]}]
|
||||
#set_property -dict {LOC AB14 IOSTANDARD LVCMOS18 DRIVE 16} [get_ports {flash_addr[5]}]
|
||||
#set_property -dict {LOC AA10 IOSTANDARD LVCMOS18 DRIVE 16} [get_ports {flash_addr[6]}]
|
||||
#set_property -dict {LOC AA9 IOSTANDARD LVCMOS18 DRIVE 16} [get_ports {flash_addr[7]}]
|
||||
#set_property -dict {LOC W10 IOSTANDARD LVCMOS18 DRIVE 16} [get_ports {flash_addr[8]}]
|
||||
#set_property -dict {LOC AA13 IOSTANDARD LVCMOS18 DRIVE 16} [get_ports {flash_addr[9]}]
|
||||
#set_property -dict {LOC Y15 IOSTANDARD LVCMOS18 DRIVE 16} [get_ports {flash_addr[10]}]
|
||||
#set_property -dict {LOC AC12 IOSTANDARD LVCMOS18 DRIVE 16} [get_ports {flash_addr[11]}]
|
||||
#set_property -dict {LOC V12 IOSTANDARD LVCMOS18 DRIVE 16} [get_ports {flash_addr[12]}]
|
||||
#set_property -dict {LOC V11 IOSTANDARD LVCMOS18 DRIVE 16} [get_ports {flash_addr[13]}]
|
||||
#set_property -dict {LOC Y12 IOSTANDARD LVCMOS18 DRIVE 16} [get_ports {flash_addr[14]}]
|
||||
#set_property -dict {LOC W9 IOSTANDARD LVCMOS18 DRIVE 16} [get_ports {flash_addr[15]}]
|
||||
#set_property -dict {LOC Y8 IOSTANDARD LVCMOS18 DRIVE 16} [get_ports {flash_addr[16]}]
|
||||
#set_property -dict {LOC W8 IOSTANDARD LVCMOS18 DRIVE 16} [get_ports {flash_addr[17]}]
|
||||
#set_property -dict {LOC W15 IOSTANDARD LVCMOS18 DRIVE 16} [get_ports {flash_addr[18]}]
|
||||
#set_property -dict {LOC AA15 IOSTANDARD LVCMOS18 DRIVE 16} [get_ports {flash_addr[19]}]
|
||||
#set_property -dict {LOC AE16 IOSTANDARD LVCMOS18 DRIVE 16} [get_ports {flash_addr[20]}]
|
||||
#set_property -dict {LOC AF15 IOSTANDARD LVCMOS18 DRIVE 16} [get_ports {flash_addr[21]}]
|
||||
#set_property -dict {LOC AE15 IOSTANDARD LVCMOS18 DRIVE 16} [get_ports {flash_addr[22]}]
|
||||
#set_property -dict {LOC AD15 IOSTANDARD LVCMOS18 PULLUP true} [get_ports {flash_region}]
|
||||
#set_property -dict {LOC AC9 IOSTANDARD LVCMOS18 DRIVE 16} [get_ports {flash_ce_n}]
|
||||
#set_property -dict {LOC AC14 IOSTANDARD LVCMOS18 DRIVE 16} [get_ports {flash_oe_n}]
|
||||
#set_property -dict {LOC AB10 IOSTANDARD LVCMOS18 DRIVE 16} [get_ports {flash_we_n}]
|
||||
#set_property -dict {LOC Y10 IOSTANDARD LVCMOS18 DRIVE 16} [get_ports {flash_adv_n}]
|
||||
|
87
fpga/lib/pcie/example/ExaNIC_X10/fpga/fpga/Makefile
Normal file
87
fpga/lib/pcie/example/ExaNIC_X10/fpga/fpga/Makefile
Normal file
@ -0,0 +1,87 @@
|
||||
|
||||
# FPGA settings
|
||||
FPGA_PART = xcku035-fbva676-2-e
|
||||
FPGA_TOP = fpga
|
||||
FPGA_ARCH = kintexu
|
||||
|
||||
# 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/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
|
||||
XCI_FILES = ip/pcie3_ultrascale_0.xci
|
||||
|
||||
include ../common/vivado.mk
|
||||
|
||||
program: $(FPGA_TOP).bit
|
||||
echo "open_hw" > program.tcl
|
||||
echo "connect_hw_server" >> program.tcl
|
||||
echo "open_hw_target" >> program.tcl
|
||||
echo "current_hw_device [lindex [get_hw_devices] 0]" >> program.tcl
|
||||
echo "refresh_hw_device -update_hw_probes false [current_hw_device]" >> program.tcl
|
||||
echo "set_property PROGRAM.FILE {$(FPGA_TOP).bit} [current_hw_device]" >> program.tcl
|
||||
echo "program_hw_devices [current_hw_device]" >> program.tcl
|
||||
echo "exit" >> program.tcl
|
||||
vivado -nojournal -nolog -mode batch -source program.tcl
|
||||
|
||||
%.mcs %.prm: %.bit
|
||||
echo "write_cfgmem -force -format mcs -size 32 -interface BPIx16 -loadbit {up 0x0000000 $*.bit} -checksum -file $*.mcs" > generate_mcs.tcl
|
||||
echo "exit" >> generate_mcs.tcl
|
||||
vivado -nojournal -nolog -mode batch -source generate_mcs.tcl
|
||||
mkdir -p rev
|
||||
COUNT=100; \
|
||||
while [ -e rev/$*_rev$$COUNT.bit ]; \
|
||||
do COUNT=$$((COUNT+1)); done; \
|
||||
COUNT=$$((COUNT-1)); \
|
||||
for x in .mcs .prm; \
|
||||
do cp $*$$x rev/$*_rev$$COUNT$$x; \
|
||||
echo "Output: rev/$*_rev$$COUNT$$x"; done;
|
||||
|
||||
flash: $(FPGA_TOP).mcs $(FPGA_TOP).prm
|
||||
echo "open_hw" > flash.tcl
|
||||
echo "connect_hw_server" >> flash.tcl
|
||||
echo "open_hw_target" >> flash.tcl
|
||||
echo "current_hw_device [lindex [get_hw_devices] 0]" >> flash.tcl
|
||||
echo "refresh_hw_device -update_hw_probes false [current_hw_device]" >> flash.tcl
|
||||
echo "create_hw_cfgmem -hw_device [current_hw_device] [lindex [get_cfgmem_parts {28f256p30t-bpi-x16}] 0]" >> flash.tcl
|
||||
echo "current_hw_cfgmem -hw_device [current_hw_device] [get_property PROGRAM.HW_CFGMEM [current_hw_device]]" >> flash.tcl
|
||||
echo "set_property PROGRAM.FILES [list \"$(FPGA_TOP).mcs\"] [current_hw_cfgmem]" >> flash.tcl
|
||||
echo "set_property PROGRAM.PRM_FILES [list \"$(FPGA_TOP).prm\"] [current_hw_cfgmem]" >> flash.tcl
|
||||
echo "set_property PROGRAM.ERASE 1 [current_hw_cfgmem]" >> flash.tcl
|
||||
echo "set_property PROGRAM.CFG_PROGRAM 1 [current_hw_cfgmem]" >> flash.tcl
|
||||
echo "set_property PROGRAM.VERIFY 1 [current_hw_cfgmem]" >> flash.tcl
|
||||
echo "set_property PROGRAM.CHECKSUM 0 [current_hw_cfgmem]" >> flash.tcl
|
||||
echo "set_property PROGRAM.ADDRESS_RANGE {use_file} [current_hw_cfgmem]" >> flash.tcl
|
||||
echo "set_property PROGRAM.BPI_RS_PINS {none} [current_hw_cfgmem]" >> flash.tcl
|
||||
echo "set_property PROGRAM.UNUSED_PIN_TERMINATION {pull-none} [current_hw_cfgmem]" >> flash.tcl
|
||||
echo "create_hw_bitstream -hw_device [current_hw_device] [get_property PROGRAM.HW_CFGMEM_BITFILE [current_hw_device]]" >> flash.tcl
|
||||
echo "program_hw_devices [current_hw_device]" >> flash.tcl
|
||||
echo "refresh_hw_device [current_hw_device]" >> flash.tcl
|
||||
echo "program_hw_cfgmem -hw_cfgmem [current_hw_cfgmem]" >> flash.tcl
|
||||
echo "boot_hw_device [current_hw_device]" >> flash.tcl
|
||||
echo "exit" >> flash.tcl
|
||||
vivado -nojournal -nolog -mode batch -source flash.tcl
|
||||
|
899
fpga/lib/pcie/example/ExaNIC_X10/fpga/ip/pcie3_ultrascale_0.xci
Normal file
899
fpga/lib/pcie/example/ExaNIC_X10/fpga/ip/pcie3_ultrascale_0.xci
Normal file
@ -0,0 +1,899 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<spirit:design xmlns:xilinx="http://www.xilinx.com" xmlns:spirit="http://www.spiritconsortium.org/XMLSchema/SPIRIT/1685-2009" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<spirit:vendor>xilinx.com</spirit:vendor>
|
||||
<spirit:library>xci</spirit:library>
|
||||
<spirit:name>unknown</spirit:name>
|
||||
<spirit:version>1.0</spirit:version>
|
||||
<spirit:componentInstances>
|
||||
<spirit:componentInstance>
|
||||
<spirit:instanceName>pcie3_ultrascale_0</spirit:instanceName>
|
||||
<spirit:componentRef spirit:vendor="xilinx.com" spirit:library="ip" spirit:name="pcie3_ultrascale" spirit:version="4.4"/>
|
||||
<spirit:configurableElementValues>
|
||||
<spirit:configurableElementValue spirit:referenceId="BUSIFPARAM_VALUE.CLK.SYS_CLK.ASSOCIATED_BUSIF"/>
|
||||
<spirit:configurableElementValue spirit:referenceId="BUSIFPARAM_VALUE.CLK.SYS_CLK.ASSOCIATED_RESET"/>
|
||||
<spirit:configurableElementValue spirit:referenceId="BUSIFPARAM_VALUE.CLK.SYS_CLK.CLK_DOMAIN"/>
|
||||
<spirit:configurableElementValue spirit:referenceId="BUSIFPARAM_VALUE.CLK.SYS_CLK.FREQ_HZ">100000000</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="BUSIFPARAM_VALUE.CLK.SYS_CLK.INSERT_VIP">0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="BUSIFPARAM_VALUE.CLK.SYS_CLK.PHASE">0.000</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="BUSIFPARAM_VALUE.CLK.SYS_CLK_GT.ASSOCIATED_BUSIF"/>
|
||||
<spirit:configurableElementValue spirit:referenceId="BUSIFPARAM_VALUE.CLK.SYS_CLK_GT.ASSOCIATED_RESET"/>
|
||||
<spirit:configurableElementValue spirit:referenceId="BUSIFPARAM_VALUE.CLK.SYS_CLK_GT.CLK_DOMAIN"/>
|
||||
<spirit:configurableElementValue spirit:referenceId="BUSIFPARAM_VALUE.CLK.SYS_CLK_GT.FREQ_HZ">100000000</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="BUSIFPARAM_VALUE.CLK.SYS_CLK_GT.INSERT_VIP">0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="BUSIFPARAM_VALUE.CLK.SYS_CLK_GT.PHASE">0.000</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="BUSIFPARAM_VALUE.CLK.USER_CLK.CLK_DOMAIN"/>
|
||||
<spirit:configurableElementValue spirit:referenceId="BUSIFPARAM_VALUE.CLK.USER_CLK.INSERT_VIP">0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="BUSIFPARAM_VALUE.CLK.USER_CLK.PHASE">0.000</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="BUSIFPARAM_VALUE.M_AXIS_CQ.CLK_DOMAIN"/>
|
||||
<spirit:configurableElementValue spirit:referenceId="BUSIFPARAM_VALUE.M_AXIS_CQ.FREQ_HZ">100000000</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="BUSIFPARAM_VALUE.M_AXIS_CQ.HAS_TKEEP">1</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="BUSIFPARAM_VALUE.M_AXIS_CQ.HAS_TLAST">1</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="BUSIFPARAM_VALUE.M_AXIS_CQ.HAS_TREADY">1</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="BUSIFPARAM_VALUE.M_AXIS_CQ.HAS_TSTRB">0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="BUSIFPARAM_VALUE.M_AXIS_CQ.INSERT_VIP">0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="BUSIFPARAM_VALUE.M_AXIS_CQ.LAYERED_METADATA">undef</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="BUSIFPARAM_VALUE.M_AXIS_CQ.PHASE">0.000</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="BUSIFPARAM_VALUE.M_AXIS_CQ.TDATA_NUM_BYTES">32</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="BUSIFPARAM_VALUE.M_AXIS_CQ.TDEST_WIDTH">0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="BUSIFPARAM_VALUE.M_AXIS_CQ.TID_WIDTH">0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="BUSIFPARAM_VALUE.M_AXIS_CQ.TUSER_WIDTH">85</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="BUSIFPARAM_VALUE.M_AXIS_RC.CLK_DOMAIN"/>
|
||||
<spirit:configurableElementValue spirit:referenceId="BUSIFPARAM_VALUE.M_AXIS_RC.FREQ_HZ">100000000</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="BUSIFPARAM_VALUE.M_AXIS_RC.HAS_TKEEP">1</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="BUSIFPARAM_VALUE.M_AXIS_RC.HAS_TLAST">1</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="BUSIFPARAM_VALUE.M_AXIS_RC.HAS_TREADY">1</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="BUSIFPARAM_VALUE.M_AXIS_RC.HAS_TSTRB">0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="BUSIFPARAM_VALUE.M_AXIS_RC.INSERT_VIP">0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="BUSIFPARAM_VALUE.M_AXIS_RC.LAYERED_METADATA">undef</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="BUSIFPARAM_VALUE.M_AXIS_RC.PHASE">0.000</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="BUSIFPARAM_VALUE.M_AXIS_RC.TDATA_NUM_BYTES">32</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="BUSIFPARAM_VALUE.M_AXIS_RC.TDEST_WIDTH">0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="BUSIFPARAM_VALUE.M_AXIS_RC.TID_WIDTH">0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="BUSIFPARAM_VALUE.M_AXIS_RC.TUSER_WIDTH">75</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="BUSIFPARAM_VALUE.RST.SYS_RST.INSERT_VIP">0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="BUSIFPARAM_VALUE.RST.SYS_RST.POLARITY">ACTIVE_LOW</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="BUSIFPARAM_VALUE.RST.USER_RESET.INSERT_VIP">0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="BUSIFPARAM_VALUE.S_AXIS_CC.CLK_DOMAIN"/>
|
||||
<spirit:configurableElementValue spirit:referenceId="BUSIFPARAM_VALUE.S_AXIS_CC.FREQ_HZ">100000000</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="BUSIFPARAM_VALUE.S_AXIS_CC.HAS_TKEEP">1</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="BUSIFPARAM_VALUE.S_AXIS_CC.HAS_TLAST">1</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="BUSIFPARAM_VALUE.S_AXIS_CC.HAS_TREADY">1</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="BUSIFPARAM_VALUE.S_AXIS_CC.HAS_TSTRB">0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="BUSIFPARAM_VALUE.S_AXIS_CC.INSERT_VIP">0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="BUSIFPARAM_VALUE.S_AXIS_CC.LAYERED_METADATA">undef</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="BUSIFPARAM_VALUE.S_AXIS_CC.PHASE">0.000</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="BUSIFPARAM_VALUE.S_AXIS_CC.TDATA_NUM_BYTES">32</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="BUSIFPARAM_VALUE.S_AXIS_CC.TDEST_WIDTH">0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="BUSIFPARAM_VALUE.S_AXIS_CC.TID_WIDTH">0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="BUSIFPARAM_VALUE.S_AXIS_CC.TUSER_WIDTH">33</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="BUSIFPARAM_VALUE.S_AXIS_RQ.CLK_DOMAIN"/>
|
||||
<spirit:configurableElementValue spirit:referenceId="BUSIFPARAM_VALUE.S_AXIS_RQ.FREQ_HZ">100000000</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="BUSIFPARAM_VALUE.S_AXIS_RQ.HAS_TKEEP">1</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="BUSIFPARAM_VALUE.S_AXIS_RQ.HAS_TLAST">1</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="BUSIFPARAM_VALUE.S_AXIS_RQ.HAS_TREADY">1</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="BUSIFPARAM_VALUE.S_AXIS_RQ.HAS_TSTRB">0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="BUSIFPARAM_VALUE.S_AXIS_RQ.INSERT_VIP">0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="BUSIFPARAM_VALUE.S_AXIS_RQ.LAYERED_METADATA">undef</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="BUSIFPARAM_VALUE.S_AXIS_RQ.PHASE">0.000</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="BUSIFPARAM_VALUE.S_AXIS_RQ.TDATA_NUM_BYTES">32</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="BUSIFPARAM_VALUE.S_AXIS_RQ.TDEST_WIDTH">0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="BUSIFPARAM_VALUE.S_AXIS_RQ.TID_WIDTH">0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="BUSIFPARAM_VALUE.S_AXIS_RQ.TUSER_WIDTH">60</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.ACS_CAP_NEXTPTR">0x000</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.ACS_EXT_CAP_ENABLE">FALSE</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.ARI_CAP_ENABLE">FALSE</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.AXISTEN_IF_CC_ALIGNMENT_MODE">FALSE</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.AXISTEN_IF_CC_PARITY_CHK">FALSE</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.AXISTEN_IF_CQ_ALIGNMENT_MODE">FALSE</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.AXISTEN_IF_ENABLE_CLIENT_TAG">TRUE</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.AXISTEN_IF_ENABLE_MSG_ROUTE">0x00000</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.AXISTEN_IF_ENABLE_RX_MSG_INTFC">FALSE</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.AXISTEN_IF_RC_ALIGNMENT_MODE">FALSE</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.AXISTEN_IF_RC_STRADDLE">FALSE</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.AXISTEN_IF_RQ_ALIGNMENT_MODE">FALSE</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.AXISTEN_IF_RQ_PARITY_CHK">FALSE</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.BMD_PIO_MODE">FALSE</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.CFG_CTL_IF">TRUE</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.CFG_EXT_IF">TRUE</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.CFG_FC_IF">TRUE</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.CFG_MGMT_IF">TRUE</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.CFG_STATUS_IF">TRUE</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.CFG_TX_MSG_IF">TRUE</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.COMPLETION_SPACE">16KB</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.CORE_CLK_FREQ">2</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.C_DATA_WIDTH">256</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.DBG_DESCRAMBLE_EN">FALSE</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.DEDICATE_PERST">TRUE</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.DEV_PORT_TYPE">0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.DIS_GT_WIZARD">FALSE</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.ENABLE_AUTO_RXEQ">FALSE</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.ENABLE_GT_V1_5">FALSE</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.ENABLE_IBERT">FALSE</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.ENABLE_JTAG_DBG">FALSE</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.EN_GT_SELECTION">FALSE</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.EXT_CH_GT_DRP">FALSE</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.EXT_STARTUP_PRIMITIVE">FALSE</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.EXT_XVC_VSEC_ENABLE">FALSE</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.FREE_RUN_FREQ">0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.GTWIZ_IN_CORE">1</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.GT_DRP_CLK_SRC">0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.INS_LOSS_PROFILE">Add-in_Card</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.MCAP_CAP_NEXTPTR">0x000</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.MCAP_ENABLEMENT">NONE</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.MCAP_FPGA_BITSTREAM_VERSION">0x00000000</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.MSIX_EN">FALSE</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.MSI_EN">TRUE</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.MULT_PF_DES">FALSE</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PCIE3_DRP">FALSE</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PCIE_CONFIGURATION">FALSE</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PCIE_FAST_CONFIG">NONE</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PCIE_LINK_SPEED">3</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PCIE_USE_MODE">2.0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PER_FUNC_STATUS_IF">TRUE</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF0_AER_CAP_ECRC_CHECK_CAPABLE">FALSE</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF0_AER_CAP_ECRC_GEN_CAPABLE">FALSE</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF0_AER_CAP_NEXTPTR">0x300</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF0_ARI_CAP_NEXTPTR">0x000</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF0_ARI_CAP_NEXT_FUNC">0x00</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF0_BAR0_APERTURE_SIZE">0x11</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF0_BAR0_CONTROL">0x4</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF0_BAR1_APERTURE_SIZE">0x11</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF0_BAR1_CONTROL">0x4</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF0_BAR2_APERTURE_SIZE">0x00</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF0_BAR2_CONTROL">0x0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF0_BAR3_APERTURE_SIZE">0x00</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF0_BAR3_CONTROL">0x0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF0_BAR4_APERTURE_SIZE">0x00</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF0_BAR4_CONTROL">0x0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF0_BAR5_APERTURE_SIZE">0x00</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF0_BAR5_CONTROL">0x0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF0_CAPABILITY_POINTER">0x80</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF0_CLASS_CODE">0x020000</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF0_DEVICE_ID">0x0001</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF0_DEV_CAP2_128B_CAS_ATOMIC_COMPLETER_SUPPORT">FALSE</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF0_DEV_CAP2_32B_ATOMIC_COMPLETER_SUPPORT">FALSE</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF0_DEV_CAP2_64B_ATOMIC_COMPLETER_SUPPORT">FALSE</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF0_DEV_CAP2_LTR_SUPPORT">FALSE</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF0_DEV_CAP2_OBFF_SUPPORT">0x0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF0_DEV_CAP2_TPH_COMPLETER_SUPPORT">FALSE</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF0_DEV_CAP_EXT_TAG_SUPPORTED">TRUE</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF0_DEV_CAP_FUNCTION_LEVEL_RESET_CAPABLE">FALSE</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF0_DEV_CAP_MAX_PAYLOAD_SIZE">0x2</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF0_DPA_CAP_NEXTPTR">0x300</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF0_DPA_CAP_SUB_STATE_POWER_ALLOCATION0">0x00</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF0_DPA_CAP_SUB_STATE_POWER_ALLOCATION1">0x00</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF0_DPA_CAP_SUB_STATE_POWER_ALLOCATION2">0x00</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF0_DPA_CAP_SUB_STATE_POWER_ALLOCATION3">0x00</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF0_DPA_CAP_SUB_STATE_POWER_ALLOCATION4">0x00</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF0_DPA_CAP_SUB_STATE_POWER_ALLOCATION5">0x00</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF0_DPA_CAP_SUB_STATE_POWER_ALLOCATION6">0x00</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF0_DPA_CAP_SUB_STATE_POWER_ALLOCATION7">0x00</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF0_DSN_CAP_NEXTPTR">0x300</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF0_EXPANSION_ROM_APERTURE_SIZE">0x00</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF0_EXPANSION_ROM_ENABLE">FALSE</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF0_INTERRUPT_PIN">0x1</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF0_LINK_CAP_ASPM_SUPPORT">0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF0_LINK_STATUS_SLOT_CLOCK_CONFIG">TRUE</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF0_LTR_CAP_NEXTPTR">0x300</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF0_MSIX_CAP_NEXTPTR">0x00</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF0_MSIX_CAP_PBA_BIR">0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF0_MSIX_CAP_PBA_OFFSET">0x00000000</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF0_MSIX_CAP_TABLE_BIR">0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF0_MSIX_CAP_TABLE_OFFSET">0x00000000</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF0_MSIX_CAP_TABLE_SIZE">0x000</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF0_MSI_CAP_MULTIMSGCAP">5</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF0_MSI_CAP_NEXTPTR">0xC0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF0_PB_CAP_NEXTPTR">0x274</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF0_PM_CAP_NEXTPTR">0x90</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF0_PM_CAP_PMESUPPORT_D0">FALSE</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF0_PM_CAP_PMESUPPORT_D1">FALSE</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF0_PM_CAP_PMESUPPORT_D3HOT">FALSE</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF0_PM_CAP_SUPP_D1_STATE">FALSE</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF0_RBAR_CAP_ENABLE">FALSE</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF0_RBAR_CAP_NEXTPTR">0x300</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF0_RBAR_CAP_SIZE0">0x00000</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF0_RBAR_CAP_SIZE1">0x00000</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF0_RBAR_CAP_SIZE2">0x00000</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF0_REVISION_ID">0x00</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF0_SECONDARY_PCIE_CAP_NEXTPTR">0x000</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF0_SRIOV_BAR0_APERTURE_SIZE">0x00</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF0_SRIOV_BAR0_CONTROL">0x0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF0_SRIOV_BAR1_APERTURE_SIZE">0x00</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF0_SRIOV_BAR1_CONTROL">0x0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF0_SRIOV_BAR2_APERTURE_SIZE">0x00</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF0_SRIOV_BAR2_CONTROL">0x0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF0_SRIOV_BAR3_APERTURE_SIZE">0x00</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF0_SRIOV_BAR3_CONTROL">0x0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF0_SRIOV_BAR4_APERTURE_SIZE">0x00</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF0_SRIOV_BAR4_CONTROL">0x0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF0_SRIOV_BAR5_APERTURE_SIZE">0x00</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF0_SRIOV_BAR5_CONTROL">0x0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF0_SRIOV_CAP_INITIAL_VF">0x0000</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF0_SRIOV_CAP_NEXTPTR">0x300</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF0_SRIOV_CAP_TOTAL_VF">0x0000</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF0_SRIOV_CAP_VER">0x0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF0_SRIOV_FIRST_VF_OFFSET">0x0000</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF0_SRIOV_FUNC_DEP_LINK">0x0000</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF0_SRIOV_SUPPORTED_PAGE_SIZE">0x00000553</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF0_SRIOV_VF_DEVICE_ID">0x0000</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF0_SUBSYSTEM_ID">0x0001</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF0_SUBSYSTEM_VENDOR_ID">0x1234</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF0_TPHR_CAP_DEV_SPECIFIC_MODE">TRUE</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF0_TPHR_CAP_ENABLE">FALSE</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF0_TPHR_CAP_INT_VEC_MODE">FALSE</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF0_TPHR_CAP_NEXTPTR">0x300</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF0_TPHR_CAP_ST_MODE_SEL">0x0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF0_TPHR_CAP_ST_TABLE_LOC">0x0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF0_TPHR_CAP_ST_TABLE_SIZE">0x000</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF0_TPHR_CAP_VER">0x1</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF0_VC_CAP_NEXTPTR">0x000</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF0_VENDOR_ID">0x1234</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF1_AER_CAP_ECRC_CHECK_CAPABLE">FALSE</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF1_AER_CAP_ECRC_GEN_CAPABLE">FALSE</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF1_AER_CAP_NEXTPTR">0x000</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF1_ARI_CAP_NEXTPTR">0x000</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF1_BAR0_APERTURE_SIZE">0x00</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF1_BAR0_CONTROL">0x0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF1_BAR1_APERTURE_SIZE">0x00</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF1_BAR1_CONTROL">0x0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF1_BAR2_APERTURE_SIZE">0x00</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF1_BAR2_CONTROL">0x0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF1_BAR3_APERTURE_SIZE">0x00</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF1_BAR3_CONTROL">0x0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF1_BAR4_APERTURE_SIZE">0x00</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF1_BAR4_CONTROL">0x0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF1_BAR5_APERTURE_SIZE">0x00</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF1_BAR5_CONTROL">0x0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF1_CAPABILITY_POINTER">0x80</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF1_CLASS_CODE">0x058000</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF1_DEVICE_ID">0x8011</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF1_DEV_CAP_MAX_PAYLOAD_SIZE">0x2</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF1_DPA_CAP_NEXTPTR">0x000</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF1_DPA_CAP_SUB_STATE_POWER_ALLOCATION0">0x00</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF1_DPA_CAP_SUB_STATE_POWER_ALLOCATION1">0x00</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF1_DPA_CAP_SUB_STATE_POWER_ALLOCATION2">0x00</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF1_DPA_CAP_SUB_STATE_POWER_ALLOCATION3">0x00</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF1_DPA_CAP_SUB_STATE_POWER_ALLOCATION4">0x00</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF1_DPA_CAP_SUB_STATE_POWER_ALLOCATION5">0x00</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF1_DPA_CAP_SUB_STATE_POWER_ALLOCATION6">0x00</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF1_DPA_CAP_SUB_STATE_POWER_ALLOCATION7">0x00</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF1_DSN_CAP_NEXTPTR">0x000</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF1_EXPANSION_ROM_APERTURE_SIZE">0x00</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF1_EXPANSION_ROM_ENABLE">FALSE</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF1_INTERRUPT_PIN">0x0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF1_MSIX_CAP_NEXTPTR">0x00</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF1_MSIX_CAP_PBA_BIR">0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF1_MSIX_CAP_PBA_OFFSET">0x00000000</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF1_MSIX_CAP_TABLE_BIR">0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF1_MSIX_CAP_TABLE_OFFSET">0x00000000</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF1_MSIX_CAP_TABLE_SIZE">0x000</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF1_MSI_CAP_MULTIMSGCAP">0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF1_MSI_CAP_NEXTPTR">0x00</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF1_PB_CAP_NEXTPTR">0x000</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF1_PM_CAP_NEXTPTR">0x00</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF1_RBAR_CAP_ENABLE">FALSE</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF1_RBAR_CAP_NEXTPTR">0x000</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF1_RBAR_CAP_SIZE0">0x00000</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF1_RBAR_CAP_SIZE1">0x00000</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF1_RBAR_CAP_SIZE2">0x00000</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF1_REVISION_ID">0x00</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF1_SRIOV_BAR0_APERTURE_SIZE">0x00</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF1_SRIOV_BAR0_CONTROL">0x0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF1_SRIOV_BAR1_APERTURE_SIZE">0x00</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF1_SRIOV_BAR1_CONTROL">0x0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF1_SRIOV_BAR2_APERTURE_SIZE">0x00</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF1_SRIOV_BAR2_CONTROL">0x0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF1_SRIOV_BAR3_APERTURE_SIZE">0x00</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF1_SRIOV_BAR3_CONTROL">0x0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF1_SRIOV_BAR4_APERTURE_SIZE">0x00</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF1_SRIOV_BAR4_CONTROL">0x0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF1_SRIOV_BAR5_APERTURE_SIZE">0x00</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF1_SRIOV_BAR5_CONTROL">0x0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF1_SRIOV_CAP_INITIAL_VF">0x0000</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF1_SRIOV_CAP_NEXTPTR">0x000</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF1_SRIOV_CAP_TOTAL_VF">0x0000</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF1_SRIOV_CAP_VER">0x0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF1_SRIOV_FIRST_VF_OFFSET">0x0000</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF1_SRIOV_FUNC_DEP_LINK">0x0001</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF1_SRIOV_SUPPORTED_PAGE_SIZE">0x00000553</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF1_SRIOV_VF_DEVICE_ID">0x0000</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF1_SUBSYSTEM_ID">0x0007</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF1_TPHR_CAP_DEV_SPECIFIC_MODE">TRUE</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF1_TPHR_CAP_ENABLE">FALSE</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF1_TPHR_CAP_INT_VEC_MODE">FALSE</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF1_TPHR_CAP_NEXTPTR">0x000</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF1_TPHR_CAP_ST_MODE_SEL">0x0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF1_TPHR_CAP_ST_TABLE_LOC">0x0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF1_TPHR_CAP_ST_TABLE_SIZE">0x000</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PF1_TPHR_CAP_VER">0x1</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PHY_LP_TXPRESET">4</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PIPE_SIM">FALSE</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PLL_TYPE">2</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PL_INTERFACE">FALSE</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PL_LINK_CAP_MAX_LINK_SPEED">4</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PL_LINK_CAP_MAX_LINK_WIDTH">8</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PL_UPSTREAM_FACING">TRUE</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.PM_ENABLE_L23_ENTRY">FALSE</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.RCV_MSG_IF">TRUE</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.REF_CLK_FREQ">0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.RX_DETECT">0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.SELECT_QUAD">GTH_Quad_225</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.SHARED_LOGIC">1</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.SPARE_WORD1">0x00000000</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.SRIOV_CAP_ENABLE">FALSE</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.SYS_RESET_POLARITY">0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.TL_CREDITS_CD">0x000</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.TL_CREDITS_CH">0x00</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.TL_CREDITS_NPD">0x028</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.TL_CREDITS_NPH">0x20</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.TL_CREDITS_PD">0x198</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.TL_CREDITS_PH">0x20</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.TL_EXTENDED_CFG_EXTEND_INTERFACE_ENABLE">FALSE</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.TL_LEGACY_MODE_ENABLE">FALSE</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.TL_PF_ENABLE_REG">0x0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.TRANSCEIVER_CTRL_STATUS_PORTS">FALSE</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.TX_FC_IF">TRUE</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.USER_CLK_FREQ">3</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.VF0_ARI_CAP_NEXTPTR">0x000</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.VF0_CAPABILITY_POINTER">0x80</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.VF0_MSIX_CAP_PBA_BIR">0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.VF0_MSIX_CAP_PBA_OFFSET">0x00000000</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.VF0_MSIX_CAP_TABLE_BIR">0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.VF0_MSIX_CAP_TABLE_OFFSET">0x00000000</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.VF0_MSIX_CAP_TABLE_SIZE">0x000</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.VF0_MSI_CAP_MULTIMSGCAP">0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.VF0_PM_CAP_NEXTPTR">0x00</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.VF0_TPHR_CAP_DEV_SPECIFIC_MODE">TRUE</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.VF0_TPHR_CAP_INT_VEC_MODE">FALSE</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.VF0_TPHR_CAP_NEXTPTR">0x000</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.VF0_TPHR_CAP_ST_MODE_SEL">0x0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.VF0_TPHR_CAP_ST_TABLE_LOC">0x0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.VF0_TPHR_CAP_ST_TABLE_SIZE">0x000</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.VF0_TPHR_CAP_VER">0x1</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.VF1_ARI_CAP_NEXTPTR">0x000</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.VF1_MSIX_CAP_PBA_BIR">0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.VF1_MSIX_CAP_PBA_OFFSET">0x00000000</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.VF1_MSIX_CAP_TABLE_BIR">0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.VF1_MSIX_CAP_TABLE_OFFSET">0x00000000</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.VF1_MSIX_CAP_TABLE_SIZE">0x000</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.VF1_MSI_CAP_MULTIMSGCAP">0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.VF1_PM_CAP_NEXTPTR">0x00</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.VF1_TPHR_CAP_DEV_SPECIFIC_MODE">TRUE</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.VF1_TPHR_CAP_INT_VEC_MODE">FALSE</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.VF1_TPHR_CAP_NEXTPTR">0x000</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.VF1_TPHR_CAP_ST_MODE_SEL">0x0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.VF1_TPHR_CAP_ST_TABLE_LOC">0x0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.VF1_TPHR_CAP_ST_TABLE_SIZE">0x000</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.VF1_TPHR_CAP_VER">0x1</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.VF2_ARI_CAP_NEXTPTR">0x000</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.VF2_MSIX_CAP_PBA_BIR">0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.VF2_MSIX_CAP_PBA_OFFSET">0x00000000</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.VF2_MSIX_CAP_TABLE_BIR">0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.VF2_MSIX_CAP_TABLE_OFFSET">0x00000000</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.VF2_MSIX_CAP_TABLE_SIZE">0x000</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.VF2_MSI_CAP_MULTIMSGCAP">0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.VF2_PM_CAP_NEXTPTR">0x00</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.VF2_TPHR_CAP_DEV_SPECIFIC_MODE">TRUE</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.VF2_TPHR_CAP_INT_VEC_MODE">FALSE</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.VF2_TPHR_CAP_NEXTPTR">0x000</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.VF2_TPHR_CAP_ST_MODE_SEL">0x0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.VF2_TPHR_CAP_ST_TABLE_LOC">0x0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.VF2_TPHR_CAP_ST_TABLE_SIZE">0x000</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.VF2_TPHR_CAP_VER">0x1</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.VF3_ARI_CAP_NEXTPTR">0x000</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.VF3_MSIX_CAP_PBA_BIR">0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.VF3_MSIX_CAP_PBA_OFFSET">0x00000000</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.VF3_MSIX_CAP_TABLE_BIR">0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.VF3_MSIX_CAP_TABLE_OFFSET">0x00000000</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.VF3_MSIX_CAP_TABLE_SIZE">0x000</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.VF3_MSI_CAP_MULTIMSGCAP">0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.VF3_PM_CAP_NEXTPTR">0x00</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.VF3_TPHR_CAP_DEV_SPECIFIC_MODE">TRUE</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.VF3_TPHR_CAP_INT_VEC_MODE">FALSE</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.VF3_TPHR_CAP_NEXTPTR">0x000</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.VF3_TPHR_CAP_ST_MODE_SEL">0x0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.VF3_TPHR_CAP_ST_TABLE_LOC">0x0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.VF3_TPHR_CAP_ST_TABLE_SIZE">0x000</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.VF3_TPHR_CAP_VER">0x1</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.VF4_ARI_CAP_NEXTPTR">0x000</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.VF4_MSIX_CAP_PBA_BIR">0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.VF4_MSIX_CAP_PBA_OFFSET">0x00000000</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.VF4_MSIX_CAP_TABLE_BIR">0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.VF4_MSIX_CAP_TABLE_OFFSET">0x00000000</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.VF4_MSIX_CAP_TABLE_SIZE">0x000</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.VF4_MSI_CAP_MULTIMSGCAP">0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.VF4_PM_CAP_NEXTPTR">0x00</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.VF4_TPHR_CAP_DEV_SPECIFIC_MODE">TRUE</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.VF4_TPHR_CAP_INT_VEC_MODE">FALSE</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.VF4_TPHR_CAP_NEXTPTR">0x000</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.VF4_TPHR_CAP_ST_MODE_SEL">0x0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.VF4_TPHR_CAP_ST_TABLE_LOC">0x0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.VF4_TPHR_CAP_ST_TABLE_SIZE">0x000</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.VF4_TPHR_CAP_VER">0x1</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.VF5_ARI_CAP_NEXTPTR">0x000</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.VF5_MSIX_CAP_PBA_BIR">0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.VF5_MSIX_CAP_PBA_OFFSET">0x00000000</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.VF5_MSIX_CAP_TABLE_BIR">0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.VF5_MSIX_CAP_TABLE_OFFSET">0x00000000</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.VF5_MSIX_CAP_TABLE_SIZE">0x000</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.VF5_MSI_CAP_MULTIMSGCAP">0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.VF5_PM_CAP_NEXTPTR">0x00</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.VF5_TPHR_CAP_DEV_SPECIFIC_MODE">TRUE</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.VF5_TPHR_CAP_INT_VEC_MODE">FALSE</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.VF5_TPHR_CAP_NEXTPTR">0x000</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.VF5_TPHR_CAP_ST_MODE_SEL">0x0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.VF5_TPHR_CAP_ST_TABLE_LOC">0x0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.VF5_TPHR_CAP_ST_TABLE_SIZE">0x000</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.VF5_TPHR_CAP_VER">0x1</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.en_msi_per_vec_masking">FALSE</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.gen_x0y0_xdc">1</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.gen_x0y1_xdc">0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.gen_x0y2_xdc">0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.gen_x0y3_xdc">0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.gen_x0y4_xdc">0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.gen_x0y5_xdc">0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.pcie_blk_locn">0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.silicon_revision">Production</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.xlnx_ref_board">0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_ENABLEMENT.xlnx_ref_board">true</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.AXISTEN_IF_RC_STRADDLE">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.Component_Name">pcie3_ultrascale_0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.INS_LOSS_NYQ">15</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.PF0_AER_CAP_ECRC_CHECK_CAPABLE">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.PF0_AER_CAP_ECRC_GEN_CAPABLE">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.PF0_CLASS_CODE">020000</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.PF0_DEVICE_ID">0001</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.PF0_DEV_CAP2_128B_CAS_ATOMIC_COMPLETER_SUPPORT">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.PF0_DEV_CAP2_32B_ATOMIC_COMPLETER_SUPPORT">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.PF0_DEV_CAP2_64B_ATOMIC_COMPLETER_SUPPORT">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.PF0_DEV_CAP2_OBFF_SUPPORT">00_Not_Supported</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.PF0_DEV_CAP2_TPH_COMPLETER_SUPPORT">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.PF0_DEV_CAP_FUNCTION_LEVEL_RESET_CAPABLE">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.PF0_INTERRUPT_PIN">INTA</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.PF0_LINK_STATUS_SLOT_CLOCK_CONFIG">true</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.PF0_MSIX_CAP_PBA_BIR">BAR_0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.PF0_MSIX_CAP_PBA_OFFSET">00000000</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.PF0_MSIX_CAP_TABLE_BIR">BAR_0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.PF0_MSIX_CAP_TABLE_OFFSET">00000000</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.PF0_MSIX_CAP_TABLE_SIZE">000</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.PF0_MSI_CAP_MULTIMSGCAP">32_vectors</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.PF0_PM_CAP_PMESUPPORT_D0">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.PF0_PM_CAP_PMESUPPORT_D1">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.PF0_PM_CAP_PMESUPPORT_D3HOT">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.PF0_PM_CAP_SUPP_D1_STATE">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.PF0_REVISION_ID">00</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.PF0_SRIOV_CAP_INITIAL_VF">0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.PF0_SRIOV_FIRST_VF_OFFSET">N/A</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.PF0_SRIOV_FUNC_DEP_LINK">0000</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.PF0_SRIOV_SUPPORTED_PAGE_SIZE">00000553</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.PF0_SRIOV_VF_DEVICE_ID">0000</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.PF0_SUBSYSTEM_ID">0001</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.PF0_SUBSYSTEM_VENDOR_ID">1234</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.PF0_Use_Class_Code_Lookup_Assistant">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.PF1_AER_CAP_ECRC_CHECK_CAPABLE">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.PF1_AER_CAP_ECRC_GEN_CAPABLE">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.PF1_CLASS_CODE">058000</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.PF1_DEVICE_ID">8011</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.PF1_INTERRUPT_PIN">NONE</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.PF1_MSIX_CAP_PBA_BIR">BAR_0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.PF1_MSIX_CAP_PBA_OFFSET">00000000</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.PF1_MSIX_CAP_TABLE_BIR">BAR_0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.PF1_MSIX_CAP_TABLE_OFFSET">00000000</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.PF1_MSIX_CAP_TABLE_SIZE">000</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.PF1_MSI_CAP_MULTIMSGCAP">1_vector</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.PF1_REVISION_ID">00</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.PF1_SRIOV_CAP_INITIAL_VF">0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.PF1_SRIOV_CAP_VER">0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.PF1_SRIOV_FIRST_VF_OFFSET">N/A</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.PF1_SRIOV_FUNC_DEP_LINK">0001</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.PF1_SRIOV_SUPPORTED_PAGE_SIZE">00000553</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.PF1_SRIOV_VF_DEVICE_ID">0000</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.PF1_SUBSYSTEM_ID">0007</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.PF1_Use_Class_Code_Lookup_Assistant">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.PHY_LP_TXPRESET">4</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.PL_LINK_CAP_MAX_LINK_SPEED">8.0_GT/s</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.PL_LINK_CAP_MAX_LINK_WIDTH">X8</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.REF_CLK_FREQ">100_MHz</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.RX_DETECT">Default</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.RX_PPM_OFFSET">0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.RX_SSC_PPM">0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.SRIOV_CAP_ENABLE">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.SRIOV_CAP_ENABLE_EXT">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.Shared_Logic">1</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.TL_PF_ENABLE_REG">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.VF0_MSIX_CAP_PBA_BIR">BAR_0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.VF0_MSIX_CAP_PBA_OFFSET">00000000</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.VF0_MSIX_CAP_TABLE_BIR">BAR_0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.VF0_MSIX_CAP_TABLE_OFFSET">00000000</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.VF0_MSIX_CAP_TABLE_SIZE">000</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.VF0_MSI_CAP_MULTIMSGCAP">1_vector</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.VF1_MSIX_CAP_PBA_BIR">BAR_0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.VF1_MSIX_CAP_PBA_OFFSET">00000000</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.VF1_MSIX_CAP_TABLE_BIR">BAR_0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.VF1_MSIX_CAP_TABLE_OFFSET">00000000</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.VF1_MSIX_CAP_TABLE_SIZE">000</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.VF1_MSI_CAP_MULTIMSGCAP">1_vector</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.VF2_MSIX_CAP_PBA_BIR">BAR_0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.VF2_MSIX_CAP_PBA_OFFSET">00000000</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.VF2_MSIX_CAP_TABLE_BIR">BAR_0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.VF2_MSIX_CAP_TABLE_OFFSET">00000000</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.VF2_MSIX_CAP_TABLE_SIZE">000</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.VF2_MSI_CAP_MULTIMSGCAP">1_vector</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.VF3_MSIX_CAP_PBA_BIR">BAR_0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.VF3_MSIX_CAP_PBA_OFFSET">00000000</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.VF3_MSIX_CAP_TABLE_BIR">BAR_0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.VF3_MSIX_CAP_TABLE_OFFSET">00000000</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.VF3_MSIX_CAP_TABLE_SIZE">000</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.VF3_MSI_CAP_MULTIMSGCAP">1_vector</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.VF4_MSIX_CAP_PBA_BIR">BAR_0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.VF4_MSIX_CAP_PBA_OFFSET">00000000</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.VF4_MSIX_CAP_TABLE_BIR">BAR_0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.VF4_MSIX_CAP_TABLE_OFFSET">00000000</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.VF4_MSIX_CAP_TABLE_SIZE">000</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.VF4_MSI_CAP_MULTIMSGCAP">1_vector</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.VF5_MSIX_CAP_PBA_BIR">BAR_0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.VF5_MSIX_CAP_PBA_OFFSET">00000000</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.VF5_MSIX_CAP_TABLE_BIR">BAR_0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.VF5_MSIX_CAP_TABLE_OFFSET">00000000</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.VF5_MSIX_CAP_TABLE_SIZE">000</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.VF5_MSI_CAP_MULTIMSGCAP">1_vector</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.acs_ext_cap_enable">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.alignment_mode">DWORD_Aligned</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.aspm_support">No_ASPM</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.axisten_freq">250</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.axisten_if_enable_client_tag">true</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.axisten_if_enable_msg_route">2FFFF</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.axisten_if_enable_msg_route_override">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.axisten_if_enable_rx_msg_intfc">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.axisten_if_width">256_bit</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.bmd_pio_mode">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.cc_cq_alignment">None</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.cfg_ctl_if">true</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.cfg_ext_if">true</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.cfg_fc_if">true</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.cfg_mgmt_if">true</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.cfg_status_if">true</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.cfg_tx_msg_if">true</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.coreclk_freq">500</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.dedicate_perst">true</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.device_port_type">PCI_Express_Endpoint_device</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.dis_gt_wizard">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.disable_gt_loc">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.en_dbg_descramble">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.en_ext_ch_gt_drp">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.en_ext_clk">true</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.en_gt_selection">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.en_l23_entry">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.en_msi_per_vec_masking">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.en_parity">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.en_pcie_conf">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.en_pcie_drp">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.en_pl_ifc">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.en_transceiver_status_ports">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.enable_auto_rxeq">False</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.enable_gt_v1_5">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.enable_ibert">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.enable_jtag_dbg">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.ext_pcie_cfg_space_enabled">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.ext_startup_primitive">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.ext_xvc_vsec_enable">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.extended_tag_field">true</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.free_run_freq">100_MHz</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.gen_x0y0">true</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.gen_x0y1">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.gen_x0y2">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.gen_x0y3">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.gen_x0y4">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.gen_x0y5">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.gt_drp_clk_src">Internal</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.gtwiz_in_core">1</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.ins_loss_profile">Add-in_Card</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.mcap_enablement">None</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.mcap_fpga_bitstream_version">00000000</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.mode_selection">Basic</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.mult_pf_des">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pcie_blk_locn">X0Y0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.per_func_status_if">true</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.perf_level">Extreme</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.performance">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf0_aer_enabled">true</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf0_ari_enabled">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf0_bar0_64bit">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf0_bar0_enabled">true</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf0_bar0_prefetchable">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf0_bar0_scale">Megabytes</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf0_bar0_size">16</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf0_bar0_type">Memory</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf0_bar1_64bit">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf0_bar1_enabled">true</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf0_bar1_prefetchable">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf0_bar1_scale">Megabytes</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf0_bar1_size">16</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf0_bar1_type">Memory</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf0_bar2_64bit">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf0_bar2_enabled">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf0_bar2_prefetchable">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf0_bar2_scale">Kilobytes</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf0_bar2_size">2</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf0_bar2_type">N/A</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf0_bar3_64bit">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf0_bar3_enabled">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf0_bar3_prefetchable">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf0_bar3_scale">Kilobytes</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf0_bar3_size">2</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf0_bar3_type">N/A</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf0_bar4_64bit">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf0_bar4_enabled">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf0_bar4_prefetchable">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf0_bar4_scale">Kilobytes</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf0_bar4_size">2</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf0_bar4_type">N/A</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf0_bar5_enabled">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf0_bar5_prefetchable">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf0_bar5_scale">Kilobytes</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf0_bar5_size">2</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf0_bar5_type">N/A</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf0_base_class_menu">Network_controller</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf0_class_code_base">02</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf0_class_code_interface">00</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf0_class_code_sub">00</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf0_dev_cap_max_payload">512_bytes</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf0_dpa_enabled">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf0_dsn_enabled">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf0_expansion_rom_enabled">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf0_expansion_rom_scale">Kilobytes</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf0_expansion_rom_size">2</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf0_ltr_enabled">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf0_msi_enabled">true</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf0_msix_enabled">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf0_pb_enabled">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf0_rbar_enabled">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf0_sriov_bar0_64bit">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf0_sriov_bar0_enabled">true</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf0_sriov_bar0_prefetchable">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf0_sriov_bar0_scale">Kilobytes</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf0_sriov_bar0_size">2</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf0_sriov_bar0_type">Memory</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf0_sriov_bar1_64bit">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf0_sriov_bar1_enabled">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf0_sriov_bar1_prefetchable">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf0_sriov_bar1_scale">Kilobytes</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf0_sriov_bar1_size">2</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf0_sriov_bar1_type">N/A</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf0_sriov_bar2_64bit">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf0_sriov_bar2_enabled">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf0_sriov_bar2_prefetchable">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf0_sriov_bar2_scale">Kilobytes</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf0_sriov_bar2_size">2</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf0_sriov_bar2_type">N/A</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf0_sriov_bar3_64bit">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf0_sriov_bar3_enabled">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf0_sriov_bar3_prefetchable">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf0_sriov_bar3_scale">Kilobytes</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf0_sriov_bar3_size">2</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf0_sriov_bar3_type">N/A</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf0_sriov_bar4_64bit">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf0_sriov_bar4_enabled">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf0_sriov_bar4_prefetchable">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf0_sriov_bar4_scale">Kilobytes</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf0_sriov_bar4_size">2</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf0_sriov_bar4_type">N/A</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf0_sriov_bar5_enabled">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf0_sriov_bar5_prefetchable">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf0_sriov_bar5_scale">Kilobytes</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf0_sriov_bar5_size">2</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf0_sriov_bar5_type">N/A</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf0_sriov_cap_ver">0</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf0_sub_class_interface_menu">Ethernet_controller</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf0_tphr_enable">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf0_vc_cap_enabled">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf1_aer_enabled">true</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf1_ari_enabled">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf1_bar0_64bit">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf1_bar0_enabled">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf1_bar0_prefetchable">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf1_bar0_scale">Kilobytes</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf1_bar0_size">2</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf1_bar0_type">N/A</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf1_bar1_64bit">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf1_bar1_enabled">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf1_bar1_prefetchable">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf1_bar1_scale">Kilobytes</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf1_bar1_size">2</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf1_bar1_type">N/A</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf1_bar2_64bit">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf1_bar2_enabled">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf1_bar2_prefetchable">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf1_bar2_scale">Kilobytes</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf1_bar2_size">2</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf1_bar2_type">N/A</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf1_bar3_64bit">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf1_bar3_enabled">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf1_bar3_prefetchable">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf1_bar3_scale">Kilobytes</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf1_bar3_size">2</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf1_bar3_type">N/A</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf1_bar4_64bit">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf1_bar4_enabled">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf1_bar4_prefetchable">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf1_bar4_scale">Kilobytes</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf1_bar4_size">2</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf1_bar4_type">N/A</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf1_bar5_enabled">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf1_bar5_prefetchable">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf1_bar5_scale">Kilobytes</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf1_bar5_size">2</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf1_bar5_type">N/A</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf1_base_class_menu">Memory_controller</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf1_class_code_base">05</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf1_class_code_interface">00</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf1_class_code_sub">80</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf1_dev_cap_max_payload">512_bytes</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf1_dpa_enabled">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf1_dsn_enabled">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf1_expansion_rom_enabled">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf1_expansion_rom_scale">Kilobytes</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf1_expansion_rom_size">2</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf1_msi_enabled">true</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf1_msix_enabled">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf1_pb_enabled">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf1_rbar_enabled">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf1_sriov_bar0_64bit">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf1_sriov_bar0_enabled">true</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf1_sriov_bar0_prefetchable">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf1_sriov_bar0_scale">Kilobytes</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf1_sriov_bar0_size">2</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf1_sriov_bar0_type">Memory</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf1_sriov_bar1_64bit">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf1_sriov_bar1_enabled">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf1_sriov_bar1_prefetchable">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf1_sriov_bar1_scale">Kilobytes</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf1_sriov_bar1_size">2</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf1_sriov_bar1_type">N/A</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf1_sriov_bar2_64bit">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf1_sriov_bar2_enabled">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf1_sriov_bar2_prefetchable">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf1_sriov_bar2_scale">Kilobytes</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf1_sriov_bar2_size">2</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf1_sriov_bar2_type">N/A</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf1_sriov_bar3_64bit">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf1_sriov_bar3_enabled">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf1_sriov_bar3_prefetchable">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf1_sriov_bar3_scale">Kilobytes</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf1_sriov_bar3_size">2</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf1_sriov_bar3_type">N/A</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf1_sriov_bar4_64bit">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf1_sriov_bar4_enabled">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf1_sriov_bar4_prefetchable">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf1_sriov_bar4_scale">Kilobytes</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf1_sriov_bar4_size">2</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf1_sriov_bar4_type">N/A</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf1_sriov_bar5_enabled">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf1_sriov_bar5_prefetchable">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf1_sriov_bar5_scale">Kilobytes</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf1_sriov_bar5_size">2</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf1_sriov_bar5_type">N/A</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf1_sub_class_interface_menu">Other_memory_controller</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pf1_tphr_enable">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.pipe_sim">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.plltype">QPLL1</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.rc_rq_alignment">None</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.rcv_msg_if">true</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.select_quad">GTH_Quad_225</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.special_gui">false</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.sys_reset_polarity">ACTIVE_LOW</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.tandem_mode">None</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.tl_pf0_enable_reg">true</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.tx_fc_if">true</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.vendor_id">1234</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.xlnx_ref_board">None</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PROJECT_PARAM.ARCHITECTURE">kintexu</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PROJECT_PARAM.BASE_BOARD_PART"/>
|
||||
<spirit:configurableElementValue spirit:referenceId="PROJECT_PARAM.BOARD_CONNECTIONS"/>
|
||||
<spirit:configurableElementValue spirit:referenceId="PROJECT_PARAM.DEVICE">xcku035</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PROJECT_PARAM.PACKAGE">fbva676</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PROJECT_PARAM.PREFHDL">VERILOG</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PROJECT_PARAM.SILICON_REVISION"/>
|
||||
<spirit:configurableElementValue spirit:referenceId="PROJECT_PARAM.SIMULATOR_LANGUAGE">MIXED</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PROJECT_PARAM.SPEEDGRADE">-2</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PROJECT_PARAM.STATIC_POWER"/>
|
||||
<spirit:configurableElementValue spirit:referenceId="PROJECT_PARAM.TEMPERATURE_GRADE">E</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PROJECT_PARAM.USE_RDI_CUSTOMIZATION">TRUE</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="PROJECT_PARAM.USE_RDI_GENERATION">TRUE</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="RUNTIME_PARAM.IPCONTEXT">IP_Flow</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="RUNTIME_PARAM.IPREVISION">5</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="RUNTIME_PARAM.MANAGED">TRUE</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="RUNTIME_PARAM.OUTPUTDIR">.</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="RUNTIME_PARAM.SELECTEDSIMMODEL"/>
|
||||
<spirit:configurableElementValue spirit:referenceId="RUNTIME_PARAM.SHAREDDIR">.</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="RUNTIME_PARAM.SWVERSION">2019.1</spirit:configurableElementValue>
|
||||
<spirit:configurableElementValue spirit:referenceId="RUNTIME_PARAM.SYNTHESISFLOW">OUT_OF_CONTEXT</spirit:configurableElementValue>
|
||||
</spirit:configurableElementValues>
|
||||
<spirit:vendorExtensions>
|
||||
<xilinx:componentInstanceExtensions>
|
||||
<xilinx:configElementInfos>
|
||||
<xilinx:configElementInfo xilinx:referenceId="BUSIFPARAM_VALUE.M_AXIS_CQ.HAS_TKEEP" xilinx:valueSource="auto"/>
|
||||
<xilinx:configElementInfo xilinx:referenceId="BUSIFPARAM_VALUE.M_AXIS_CQ.HAS_TLAST" xilinx:valueSource="constant"/>
|
||||
<xilinx:configElementInfo xilinx:referenceId="BUSIFPARAM_VALUE.M_AXIS_CQ.HAS_TREADY" xilinx:valueSource="constant"/>
|
||||
<xilinx:configElementInfo xilinx:referenceId="BUSIFPARAM_VALUE.M_AXIS_CQ.HAS_TSTRB" xilinx:valueSource="constant"/>
|
||||
<xilinx:configElementInfo xilinx:referenceId="BUSIFPARAM_VALUE.M_AXIS_CQ.TDATA_NUM_BYTES" xilinx:valueSource="auto"/>
|
||||
<xilinx:configElementInfo xilinx:referenceId="BUSIFPARAM_VALUE.M_AXIS_CQ.TDEST_WIDTH" xilinx:valueSource="constant"/>
|
||||
<xilinx:configElementInfo xilinx:referenceId="BUSIFPARAM_VALUE.M_AXIS_CQ.TID_WIDTH" xilinx:valueSource="constant"/>
|
||||
<xilinx:configElementInfo xilinx:referenceId="BUSIFPARAM_VALUE.M_AXIS_CQ.TUSER_WIDTH" xilinx:valueSource="constant"/>
|
||||
<xilinx:configElementInfo xilinx:referenceId="BUSIFPARAM_VALUE.M_AXIS_RC.HAS_TKEEP" xilinx:valueSource="auto"/>
|
||||
<xilinx:configElementInfo xilinx:referenceId="BUSIFPARAM_VALUE.M_AXIS_RC.HAS_TLAST" xilinx:valueSource="constant"/>
|
||||
<xilinx:configElementInfo xilinx:referenceId="BUSIFPARAM_VALUE.M_AXIS_RC.HAS_TREADY" xilinx:valueSource="constant"/>
|
||||
<xilinx:configElementInfo xilinx:referenceId="BUSIFPARAM_VALUE.M_AXIS_RC.HAS_TSTRB" xilinx:valueSource="constant"/>
|
||||
<xilinx:configElementInfo xilinx:referenceId="BUSIFPARAM_VALUE.M_AXIS_RC.TDATA_NUM_BYTES" xilinx:valueSource="auto"/>
|
||||
<xilinx:configElementInfo xilinx:referenceId="BUSIFPARAM_VALUE.M_AXIS_RC.TDEST_WIDTH" xilinx:valueSource="constant"/>
|
||||
<xilinx:configElementInfo xilinx:referenceId="BUSIFPARAM_VALUE.M_AXIS_RC.TID_WIDTH" xilinx:valueSource="constant"/>
|
||||
<xilinx:configElementInfo xilinx:referenceId="BUSIFPARAM_VALUE.M_AXIS_RC.TUSER_WIDTH" xilinx:valueSource="constant"/>
|
||||
<xilinx:configElementInfo xilinx:referenceId="BUSIFPARAM_VALUE.S_AXIS_CC.HAS_TKEEP" xilinx:valueSource="auto"/>
|
||||
<xilinx:configElementInfo xilinx:referenceId="BUSIFPARAM_VALUE.S_AXIS_CC.HAS_TLAST" xilinx:valueSource="constant"/>
|
||||
<xilinx:configElementInfo xilinx:referenceId="BUSIFPARAM_VALUE.S_AXIS_CC.HAS_TREADY" xilinx:valueSource="constant"/>
|
||||
<xilinx:configElementInfo xilinx:referenceId="BUSIFPARAM_VALUE.S_AXIS_CC.HAS_TSTRB" xilinx:valueSource="constant"/>
|
||||
<xilinx:configElementInfo xilinx:referenceId="BUSIFPARAM_VALUE.S_AXIS_CC.TDATA_NUM_BYTES" xilinx:valueSource="auto"/>
|
||||
<xilinx:configElementInfo xilinx:referenceId="BUSIFPARAM_VALUE.S_AXIS_CC.TDEST_WIDTH" xilinx:valueSource="constant"/>
|
||||
<xilinx:configElementInfo xilinx:referenceId="BUSIFPARAM_VALUE.S_AXIS_CC.TID_WIDTH" xilinx:valueSource="constant"/>
|
||||
<xilinx:configElementInfo xilinx:referenceId="BUSIFPARAM_VALUE.S_AXIS_CC.TUSER_WIDTH" xilinx:valueSource="constant"/>
|
||||
<xilinx:configElementInfo xilinx:referenceId="BUSIFPARAM_VALUE.S_AXIS_RQ.HAS_TKEEP" xilinx:valueSource="auto"/>
|
||||
<xilinx:configElementInfo xilinx:referenceId="BUSIFPARAM_VALUE.S_AXIS_RQ.HAS_TLAST" xilinx:valueSource="constant"/>
|
||||
<xilinx:configElementInfo xilinx:referenceId="BUSIFPARAM_VALUE.S_AXIS_RQ.HAS_TREADY" xilinx:valueSource="constant"/>
|
||||
<xilinx:configElementInfo xilinx:referenceId="BUSIFPARAM_VALUE.S_AXIS_RQ.HAS_TSTRB" xilinx:valueSource="constant"/>
|
||||
<xilinx:configElementInfo xilinx:referenceId="BUSIFPARAM_VALUE.S_AXIS_RQ.TDATA_NUM_BYTES" xilinx:valueSource="auto"/>
|
||||
<xilinx:configElementInfo xilinx:referenceId="BUSIFPARAM_VALUE.S_AXIS_RQ.TDEST_WIDTH" xilinx:valueSource="constant"/>
|
||||
<xilinx:configElementInfo xilinx:referenceId="BUSIFPARAM_VALUE.S_AXIS_RQ.TID_WIDTH" xilinx:valueSource="constant"/>
|
||||
<xilinx:configElementInfo xilinx:referenceId="BUSIFPARAM_VALUE.S_AXIS_RQ.TUSER_WIDTH" xilinx:valueSource="constant"/>
|
||||
<xilinx:configElementInfo xilinx:referenceId="PARAM_VALUE.AXISTEN_IF_RC_STRADDLE" xilinx:valueSource="user"/>
|
||||
<xilinx:configElementInfo xilinx:referenceId="PARAM_VALUE.PF0_CLASS_CODE" xilinx:valueSource="user"/>
|
||||
<xilinx:configElementInfo xilinx:referenceId="PARAM_VALUE.PF0_DEVICE_ID" xilinx:valueSource="user"/>
|
||||
<xilinx:configElementInfo xilinx:referenceId="PARAM_VALUE.PF0_MSIX_CAP_PBA_BIR" xilinx:valueSource="user"/>
|
||||
<xilinx:configElementInfo xilinx:referenceId="PARAM_VALUE.PF0_MSIX_CAP_TABLE_BIR" xilinx:valueSource="user"/>
|
||||
<xilinx:configElementInfo xilinx:referenceId="PARAM_VALUE.PF0_MSI_CAP_MULTIMSGCAP" xilinx:valueSource="user"/>
|
||||
<xilinx:configElementInfo xilinx:referenceId="PARAM_VALUE.PF0_SRIOV_CAP_INITIAL_VF" xilinx:valueSource="user"/>
|
||||
<xilinx:configElementInfo xilinx:referenceId="PARAM_VALUE.PF0_SUBSYSTEM_ID" xilinx:valueSource="user"/>
|
||||
<xilinx:configElementInfo xilinx:referenceId="PARAM_VALUE.PF0_SUBSYSTEM_VENDOR_ID" xilinx:valueSource="user"/>
|
||||
<xilinx:configElementInfo xilinx:referenceId="PARAM_VALUE.PF0_Use_Class_Code_Lookup_Assistant" xilinx:valueSource="user"/>
|
||||
<xilinx:configElementInfo xilinx:referenceId="PARAM_VALUE.PF1_DEVICE_ID" xilinx:valueSource="user"/>
|
||||
<xilinx:configElementInfo xilinx:referenceId="PARAM_VALUE.PF1_MSIX_CAP_PBA_BIR" xilinx:valueSource="user"/>
|
||||
<xilinx:configElementInfo xilinx:referenceId="PARAM_VALUE.PF1_MSIX_CAP_TABLE_BIR" xilinx:valueSource="user"/>
|
||||
<xilinx:configElementInfo xilinx:referenceId="PARAM_VALUE.PF1_SRIOV_CAP_INITIAL_VF" xilinx:valueSource="user"/>
|
||||
<xilinx:configElementInfo xilinx:referenceId="PARAM_VALUE.PL_LINK_CAP_MAX_LINK_SPEED" xilinx:valueSource="user"/>
|
||||
<xilinx:configElementInfo xilinx:referenceId="PARAM_VALUE.PL_LINK_CAP_MAX_LINK_WIDTH" xilinx:valueSource="user"/>
|
||||
<xilinx:configElementInfo xilinx:referenceId="PARAM_VALUE.TL_PF_ENABLE_REG" xilinx:valueSource="user"/>
|
||||
<xilinx:configElementInfo xilinx:referenceId="PARAM_VALUE.aspm_support" xilinx:valueSource="user"/>
|
||||
<xilinx:configElementInfo xilinx:referenceId="PARAM_VALUE.axisten_freq" xilinx:valueSource="user"/>
|
||||
<xilinx:configElementInfo xilinx:referenceId="PARAM_VALUE.axisten_if_width" xilinx:valueSource="user"/>
|
||||
<xilinx:configElementInfo xilinx:referenceId="PARAM_VALUE.coreclk_freq" xilinx:valueSource="user"/>
|
||||
<xilinx:configElementInfo xilinx:referenceId="PARAM_VALUE.dedicate_perst" xilinx:valueSource="user"/>
|
||||
<xilinx:configElementInfo xilinx:referenceId="PARAM_VALUE.extended_tag_field" xilinx:valueSource="user"/>
|
||||
<xilinx:configElementInfo xilinx:referenceId="PARAM_VALUE.gen_x0y0" xilinx:valueSource="user"/>
|
||||
<xilinx:configElementInfo xilinx:referenceId="PARAM_VALUE.gen_x0y1" xilinx:valueSource="user"/>
|
||||
<xilinx:configElementInfo xilinx:referenceId="PARAM_VALUE.mcap_enablement" xilinx:valueSource="user"/>
|
||||
<xilinx:configElementInfo xilinx:referenceId="PARAM_VALUE.mult_pf_des" xilinx:valueSource="user"/>
|
||||
<xilinx:configElementInfo xilinx:referenceId="PARAM_VALUE.pcie_blk_locn" xilinx:valueSource="user"/>
|
||||
<xilinx:configElementInfo xilinx:referenceId="PARAM_VALUE.pf0_bar0_64bit" xilinx:valueSource="user"/>
|
||||
<xilinx:configElementInfo xilinx:referenceId="PARAM_VALUE.pf0_bar0_scale" xilinx:valueSource="user"/>
|
||||
<xilinx:configElementInfo xilinx:referenceId="PARAM_VALUE.pf0_bar0_size" xilinx:valueSource="user"/>
|
||||
<xilinx:configElementInfo xilinx:referenceId="PARAM_VALUE.pf0_bar1_enabled" xilinx:valueSource="user"/>
|
||||
<xilinx:configElementInfo xilinx:referenceId="PARAM_VALUE.pf0_bar1_scale" xilinx:valueSource="user"/>
|
||||
<xilinx:configElementInfo xilinx:referenceId="PARAM_VALUE.pf0_bar1_size" xilinx:valueSource="user"/>
|
||||
<xilinx:configElementInfo xilinx:referenceId="PARAM_VALUE.pf0_bar1_type" xilinx:valueSource="user"/>
|
||||
<xilinx:configElementInfo xilinx:referenceId="PARAM_VALUE.pf0_base_class_menu" xilinx:valueSource="user"/>
|
||||
<xilinx:configElementInfo xilinx:referenceId="PARAM_VALUE.pf0_class_code_base" xilinx:valueSource="user"/>
|
||||
<xilinx:configElementInfo xilinx:referenceId="PARAM_VALUE.pf0_class_code_interface" xilinx:valueSource="user"/>
|
||||
<xilinx:configElementInfo xilinx:referenceId="PARAM_VALUE.pf0_class_code_sub" xilinx:valueSource="user"/>
|
||||
<xilinx:configElementInfo xilinx:referenceId="PARAM_VALUE.pf0_sub_class_interface_menu" xilinx:valueSource="user"/>
|
||||
<xilinx:configElementInfo xilinx:referenceId="PARAM_VALUE.pf1_bar0_enabled" xilinx:valueSource="user"/>
|
||||
<xilinx:configElementInfo xilinx:referenceId="PARAM_VALUE.pf1_bar0_size" xilinx:valueSource="user"/>
|
||||
<xilinx:configElementInfo xilinx:referenceId="PARAM_VALUE.pf1_bar0_type" xilinx:valueSource="user"/>
|
||||
<xilinx:configElementInfo xilinx:referenceId="PARAM_VALUE.pipe_sim" xilinx:valueSource="user"/>
|
||||
<xilinx:configElementInfo xilinx:referenceId="PARAM_VALUE.plltype" xilinx:valueSource="user"/>
|
||||
<xilinx:configElementInfo xilinx:referenceId="PARAM_VALUE.select_quad" xilinx:valueSource="user"/>
|
||||
<xilinx:configElementInfo xilinx:referenceId="PARAM_VALUE.vendor_id" xilinx:valueSource="user"/>
|
||||
</xilinx:configElementInfos>
|
||||
</xilinx:componentInstanceExtensions>
|
||||
</spirit:vendorExtensions>
|
||||
</spirit:componentInstance>
|
||||
</spirit:componentInstances>
|
||||
</spirit:design>
|
1
fpga/lib/pcie/example/ExaNIC_X10/fpga/lib/pcie
Symbolic link
1
fpga/lib/pcie/example/ExaNIC_X10/fpga/lib/pcie
Symbolic link
@ -0,0 +1 @@
|
||||
../../../../
|
365
fpga/lib/pcie/example/ExaNIC_X10/fpga/rtl/axi_ram.v
Normal file
365
fpga/lib/pcie/example/ExaNIC_X10/fpga/rtl/axi_ram.v
Normal 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
|
264
fpga/lib/pcie/example/ExaNIC_X10/fpga/rtl/axis_register.v
Normal file
264
fpga/lib/pcie/example/ExaNIC_X10/fpga/rtl/axis_register.v
Normal 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
|
89
fpga/lib/pcie/example/ExaNIC_X10/fpga/rtl/debounce_switch.v
Normal file
89
fpga/lib/pcie/example/ExaNIC_X10/fpga/rtl/debounce_switch.v
Normal file
@ -0,0 +1,89 @@
|
||||
/*
|
||||
|
||||
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 switch and button inputs with a slow sampled shift register
|
||||
*/
|
||||
module debounce_switch #(
|
||||
parameter WIDTH=1, // width of the input and output signals
|
||||
parameter N=3, // length of shift register
|
||||
parameter RATE=125000 // clock division factor
|
||||
)(
|
||||
input wire clk,
|
||||
input wire rst,
|
||||
input wire [WIDTH-1:0] in,
|
||||
output wire [WIDTH-1:0] out
|
||||
);
|
||||
|
||||
reg [23:0] cnt_reg = 24'd0;
|
||||
|
||||
reg [N-1:0] debounce_reg[WIDTH-1:0];
|
||||
|
||||
reg [WIDTH-1:0] state;
|
||||
|
||||
/*
|
||||
* The synchronized output is the state register
|
||||
*/
|
||||
assign out = state;
|
||||
|
||||
integer k;
|
||||
|
||||
always @(posedge clk or posedge rst) begin
|
||||
if (rst) begin
|
||||
cnt_reg <= 0;
|
||||
state <= 0;
|
||||
|
||||
for (k = 0; k < WIDTH; k = k + 1) begin
|
||||
debounce_reg[k] <= 0;
|
||||
end
|
||||
end else begin
|
||||
if (cnt_reg < RATE) begin
|
||||
cnt_reg <= cnt_reg + 24'd1;
|
||||
end else begin
|
||||
cnt_reg <= 24'd0;
|
||||
end
|
||||
|
||||
if (cnt_reg == 24'd0) begin
|
||||
for (k = 0; k < WIDTH; k = k + 1) begin
|
||||
debounce_reg[k] <= {debounce_reg[k][N-2:0], in[k]};
|
||||
end
|
||||
end
|
||||
|
||||
for (k = 0; k < WIDTH; k = k + 1) begin
|
||||
if (|debounce_reg[k] == 0) begin
|
||||
state[k] <= 0;
|
||||
end else if (&debounce_reg[k] == 1) begin
|
||||
state[k] <= 1;
|
||||
end else begin
|
||||
state[k] <= state[k];
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
402
fpga/lib/pcie/example/ExaNIC_X10/fpga/rtl/fpga.v
Normal file
402
fpga/lib/pcie/example/ExaNIC_X10/fpga/rtl/fpga.v
Normal file
@ -0,0 +1,402 @@
|
||||
/*
|
||||
|
||||
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 [1:0] sfp_1_led,
|
||||
output wire [1:0] sfp_2_led,
|
||||
output wire [1:0] sma_led,
|
||||
|
||||
/*
|
||||
* PCI express
|
||||
*/
|
||||
input wire [7:0] pcie_rx_p,
|
||||
input wire [7:0] pcie_rx_n,
|
||||
output wire [7:0] pcie_tx_p,
|
||||
output wire [7:0] pcie_tx_n,
|
||||
input wire pcie_mgt_refclk_p,
|
||||
input wire pcie_mgt_refclk_n,
|
||||
input wire pcie_reset_n
|
||||
);
|
||||
|
||||
parameter AXIS_PCIE_DATA_WIDTH = 256;
|
||||
parameter AXIS_PCIE_KEEP_WIDTH = (AXIS_PCIE_DATA_WIDTH/32);
|
||||
|
||||
// PCIe
|
||||
wire pcie_user_clk;
|
||||
wire pcie_user_reset;
|
||||
|
||||
wire pcie_sys_clk;
|
||||
wire pcie_sys_clk_gt;
|
||||
|
||||
IBUFDS_GTE3 #(
|
||||
.REFCLK_HROW_CK_SEL(2'b00)
|
||||
)
|
||||
ibufds_gte3_pcie_mgt_refclk_inst (
|
||||
.I (pcie_mgt_refclk_p),
|
||||
.IB (pcie_mgt_refclk_n),
|
||||
.CEB (1'b0),
|
||||
.O (pcie_sys_clk_gt),
|
||||
.ODIV2 (pcie_sys_clk)
|
||||
);
|
||||
|
||||
wire [AXIS_PCIE_DATA_WIDTH-1:0] axis_rq_tdata;
|
||||
wire [AXIS_PCIE_KEEP_WIDTH-1:0] axis_rq_tkeep;
|
||||
wire axis_rq_tlast;
|
||||
wire axis_rq_tready;
|
||||
wire [59: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 [74: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 [84: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 [32: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 [18:0] cfg_mgmt_addr;
|
||||
wire cfg_mgmt_write;
|
||||
wire [31:0] cfg_mgmt_write_data;
|
||||
wire [3:0] cfg_mgmt_byte_enable;
|
||||
wire cfg_mgmt_read;
|
||||
wire [31:0] cfg_mgmt_read_data;
|
||||
wire cfg_mgmt_read_write_done;
|
||||
|
||||
wire [3:0] cfg_interrupt_msi_enable;
|
||||
wire [7:0] cfg_interrupt_msi_vf_enable;
|
||||
wire [11:0] cfg_interrupt_msi_mmenable;
|
||||
wire cfg_interrupt_msi_mask_update;
|
||||
wire [31:0] cfg_interrupt_msi_data;
|
||||
wire [3:0] cfg_interrupt_msi_select;
|
||||
wire [31:0] cfg_interrupt_msi_int;
|
||||
wire [31:0] cfg_interrupt_msi_pending_status;
|
||||
wire cfg_interrupt_msi_pending_status_data_enable;
|
||||
wire [3:0] cfg_interrupt_msi_pending_status_function_num;
|
||||
wire cfg_interrupt_msi_sent;
|
||||
wire cfg_interrupt_msi_fail;
|
||||
wire [2:0] cfg_interrupt_msi_attr;
|
||||
wire cfg_interrupt_msi_tph_present;
|
||||
wire [1:0] cfg_interrupt_msi_tph_type;
|
||||
wire [8:0] cfg_interrupt_msi_tph_st_tag;
|
||||
wire [3:0] cfg_interrupt_msi_function_number;
|
||||
|
||||
wire status_error_cor;
|
||||
wire status_error_uncor;
|
||||
|
||||
pcie3_ultrascale_0
|
||||
pcie3_ultrascale_inst (
|
||||
.pci_exp_txn(pcie_tx_n),
|
||||
.pci_exp_txp(pcie_tx_p),
|
||||
.pci_exp_rxn(pcie_rx_n),
|
||||
.pci_exp_rxp(pcie_rx_p),
|
||||
.user_clk(pcie_user_clk),
|
||||
.user_reset(pcie_user_reset),
|
||||
.user_lnk_up(),
|
||||
|
||||
.s_axis_rq_tdata(axis_rq_tdata),
|
||||
.s_axis_rq_tkeep(axis_rq_tkeep),
|
||||
.s_axis_rq_tlast(axis_rq_tlast),
|
||||
.s_axis_rq_tready(axis_rq_tready),
|
||||
.s_axis_rq_tuser(axis_rq_tuser),
|
||||
.s_axis_rq_tvalid(axis_rq_tvalid),
|
||||
|
||||
.m_axis_rc_tdata(axis_rc_tdata),
|
||||
.m_axis_rc_tkeep(axis_rc_tkeep),
|
||||
.m_axis_rc_tlast(axis_rc_tlast),
|
||||
.m_axis_rc_tready(axis_rc_tready),
|
||||
.m_axis_rc_tuser(axis_rc_tuser),
|
||||
.m_axis_rc_tvalid(axis_rc_tvalid),
|
||||
|
||||
.m_axis_cq_tdata(axis_cq_tdata),
|
||||
.m_axis_cq_tkeep(axis_cq_tkeep),
|
||||
.m_axis_cq_tlast(axis_cq_tlast),
|
||||
.m_axis_cq_tready(axis_cq_tready),
|
||||
.m_axis_cq_tuser(axis_cq_tuser),
|
||||
.m_axis_cq_tvalid(axis_cq_tvalid),
|
||||
|
||||
.s_axis_cc_tdata(axis_cc_tdata),
|
||||
.s_axis_cc_tkeep(axis_cc_tkeep),
|
||||
.s_axis_cc_tlast(axis_cc_tlast),
|
||||
.s_axis_cc_tready(axis_cc_tready),
|
||||
.s_axis_cc_tuser(axis_cc_tuser),
|
||||
.s_axis_cc_tvalid(axis_cc_tvalid),
|
||||
|
||||
.pcie_rq_seq_num(),
|
||||
.pcie_rq_seq_num_vld(),
|
||||
.pcie_rq_tag(),
|
||||
.pcie_rq_tag_av(),
|
||||
.pcie_rq_tag_vld(),
|
||||
|
||||
.pcie_tfc_nph_av(),
|
||||
.pcie_tfc_npd_av(),
|
||||
|
||||
.pcie_cq_np_req(1'b1),
|
||||
.pcie_cq_np_req_count(),
|
||||
|
||||
.cfg_phy_link_down(),
|
||||
.cfg_phy_link_status(),
|
||||
.cfg_negotiated_width(),
|
||||
.cfg_current_speed(),
|
||||
.cfg_max_payload(cfg_max_payload),
|
||||
.cfg_max_read_req(cfg_max_read_req),
|
||||
.cfg_function_status(),
|
||||
.cfg_function_power_state(),
|
||||
.cfg_vf_status(),
|
||||
.cfg_vf_power_state(),
|
||||
.cfg_link_power_state(),
|
||||
|
||||
.cfg_mgmt_addr(cfg_mgmt_addr),
|
||||
.cfg_mgmt_write(cfg_mgmt_write),
|
||||
.cfg_mgmt_write_data(cfg_mgmt_write_data),
|
||||
.cfg_mgmt_byte_enable(cfg_mgmt_byte_enable),
|
||||
.cfg_mgmt_read(cfg_mgmt_read),
|
||||
.cfg_mgmt_read_data(cfg_mgmt_read_data),
|
||||
.cfg_mgmt_read_write_done(cfg_mgmt_read_write_done),
|
||||
.cfg_mgmt_type1_cfg_reg_access(1'b0),
|
||||
|
||||
.cfg_err_cor_out(),
|
||||
.cfg_err_nonfatal_out(),
|
||||
.cfg_err_fatal_out(),
|
||||
.cfg_local_error(),
|
||||
.cfg_ltr_enable(),
|
||||
.cfg_ltssm_state(),
|
||||
.cfg_rcb_status(),
|
||||
.cfg_dpa_substate_change(),
|
||||
.cfg_obff_enable(),
|
||||
.cfg_pl_status_change(),
|
||||
.cfg_tph_requester_enable(),
|
||||
.cfg_tph_st_mode(),
|
||||
.cfg_vf_tph_requester_enable(),
|
||||
.cfg_vf_tph_st_mode(),
|
||||
|
||||
.cfg_msg_received(),
|
||||
.cfg_msg_received_data(),
|
||||
.cfg_msg_received_type(),
|
||||
.cfg_msg_transmit(1'b0),
|
||||
.cfg_msg_transmit_type(3'd0),
|
||||
.cfg_msg_transmit_data(32'd0),
|
||||
.cfg_msg_transmit_done(),
|
||||
|
||||
.cfg_fc_ph(),
|
||||
.cfg_fc_pd(),
|
||||
.cfg_fc_nph(),
|
||||
.cfg_fc_npd(),
|
||||
.cfg_fc_cplh(),
|
||||
.cfg_fc_cpld(),
|
||||
.cfg_fc_sel(3'd0),
|
||||
|
||||
.cfg_per_func_status_control(3'd0),
|
||||
.cfg_per_func_status_data(),
|
||||
.cfg_per_function_number(4'd0),
|
||||
.cfg_per_function_output_request(1'b0),
|
||||
.cfg_per_function_update_done(),
|
||||
|
||||
.cfg_dsn(64'd0),
|
||||
|
||||
.cfg_power_state_change_ack(1'b1),
|
||||
.cfg_power_state_change_interrupt(),
|
||||
|
||||
.cfg_err_cor_in(status_error_cor),
|
||||
.cfg_err_uncor_in(status_error_uncor),
|
||||
.cfg_flr_in_process(),
|
||||
.cfg_flr_done(4'd0),
|
||||
.cfg_vf_flr_in_process(),
|
||||
.cfg_vf_flr_done(8'd0),
|
||||
|
||||
.cfg_link_training_enable(1'b1),
|
||||
|
||||
.cfg_interrupt_int(4'd0),
|
||||
.cfg_interrupt_pending(4'd0),
|
||||
.cfg_interrupt_sent(),
|
||||
.cfg_interrupt_msi_enable(cfg_interrupt_msi_enable),
|
||||
.cfg_interrupt_msi_vf_enable(cfg_interrupt_msi_vf_enable),
|
||||
.cfg_interrupt_msi_mmenable(cfg_interrupt_msi_mmenable),
|
||||
.cfg_interrupt_msi_mask_update(cfg_interrupt_msi_mask_update),
|
||||
.cfg_interrupt_msi_data(cfg_interrupt_msi_data),
|
||||
.cfg_interrupt_msi_select(cfg_interrupt_msi_select),
|
||||
.cfg_interrupt_msi_int(cfg_interrupt_msi_int),
|
||||
.cfg_interrupt_msi_pending_status(cfg_interrupt_msi_pending_status),
|
||||
.cfg_interrupt_msi_pending_status_data_enable(cfg_interrupt_msi_pending_status_data_enable),
|
||||
.cfg_interrupt_msi_pending_status_function_num(cfg_interrupt_msi_pending_status_function_num),
|
||||
.cfg_interrupt_msi_sent(cfg_interrupt_msi_sent),
|
||||
.cfg_interrupt_msi_fail(cfg_interrupt_msi_fail),
|
||||
.cfg_interrupt_msi_attr(cfg_interrupt_msi_attr),
|
||||
.cfg_interrupt_msi_tph_present(cfg_interrupt_msi_tph_present),
|
||||
.cfg_interrupt_msi_tph_type(cfg_interrupt_msi_tph_type),
|
||||
.cfg_interrupt_msi_tph_st_tag(cfg_interrupt_msi_tph_st_tag),
|
||||
.cfg_interrupt_msi_function_number(cfg_interrupt_msi_function_number),
|
||||
|
||||
.cfg_hot_reset_out(),
|
||||
|
||||
.cfg_config_space_enable(1'b1),
|
||||
.cfg_req_pm_transition_l23_ready(1'b0),
|
||||
.cfg_hot_reset_in(1'b0),
|
||||
|
||||
.cfg_ds_port_number(8'd0),
|
||||
.cfg_ds_bus_number(8'd0),
|
||||
.cfg_ds_device_number(5'd0),
|
||||
.cfg_ds_function_number(3'd0),
|
||||
|
||||
.cfg_subsys_vend_id(16'h1234),
|
||||
|
||||
.sys_clk(pcie_sys_clk),
|
||||
.sys_clk_gt(pcie_sys_clk_gt),
|
||||
.sys_reset(pcie_reset_n),
|
||||
.pcie_perstn1_in(1'b0),
|
||||
.pcie_perstn0_out(),
|
||||
.pcie_perstn1_out(),
|
||||
|
||||
.int_qpll1lock_out(),
|
||||
.int_qpll1outrefclk_out(),
|
||||
.int_qpll1outclk_out(),
|
||||
.phy_rdy_out()
|
||||
);
|
||||
|
||||
fpga_core #(
|
||||
.AXIS_PCIE_DATA_WIDTH(AXIS_PCIE_DATA_WIDTH)
|
||||
)
|
||||
core_inst (
|
||||
/*
|
||||
* Clock: 250 MHz
|
||||
* Synchronous reset
|
||||
*/
|
||||
.clk(pcie_user_clk),
|
||||
.rst(pcie_user_reset),
|
||||
/*
|
||||
* GPIO
|
||||
*/
|
||||
.sfp_1_led(sfp_1_led),
|
||||
.sfp_2_led(sfp_2_led),
|
||||
.sma_led(sma_led),
|
||||
/*
|
||||
* PCIe
|
||||
*/
|
||||
.m_axis_rq_tdata(axis_rq_tdata),
|
||||
.m_axis_rq_tkeep(axis_rq_tkeep),
|
||||
.m_axis_rq_tlast(axis_rq_tlast),
|
||||
.m_axis_rq_tready(axis_rq_tready),
|
||||
.m_axis_rq_tuser(axis_rq_tuser),
|
||||
.m_axis_rq_tvalid(axis_rq_tvalid),
|
||||
|
||||
.s_axis_rc_tdata(axis_rc_tdata),
|
||||
.s_axis_rc_tkeep(axis_rc_tkeep),
|
||||
.s_axis_rc_tlast(axis_rc_tlast),
|
||||
.s_axis_rc_tready(axis_rc_tready),
|
||||
.s_axis_rc_tuser(axis_rc_tuser),
|
||||
.s_axis_rc_tvalid(axis_rc_tvalid),
|
||||
|
||||
.s_axis_cq_tdata(axis_cq_tdata),
|
||||
.s_axis_cq_tkeep(axis_cq_tkeep),
|
||||
.s_axis_cq_tlast(axis_cq_tlast),
|
||||
.s_axis_cq_tready(axis_cq_tready),
|
||||
.s_axis_cq_tuser(axis_cq_tuser),
|
||||
.s_axis_cq_tvalid(axis_cq_tvalid),
|
||||
|
||||
.m_axis_cc_tdata(axis_cc_tdata),
|
||||
.m_axis_cc_tkeep(axis_cc_tkeep),
|
||||
.m_axis_cc_tlast(axis_cc_tlast),
|
||||
.m_axis_cc_tready(axis_cc_tready),
|
||||
.m_axis_cc_tuser(axis_cc_tuser),
|
||||
.m_axis_cc_tvalid(axis_cc_tvalid),
|
||||
|
||||
.cfg_max_payload(cfg_max_payload),
|
||||
.cfg_max_read_req(cfg_max_read_req),
|
||||
|
||||
.cfg_mgmt_addr(cfg_mgmt_addr),
|
||||
.cfg_mgmt_write(cfg_mgmt_write),
|
||||
.cfg_mgmt_write_data(cfg_mgmt_write_data),
|
||||
.cfg_mgmt_byte_enable(cfg_mgmt_byte_enable),
|
||||
.cfg_mgmt_read(cfg_mgmt_read),
|
||||
.cfg_mgmt_read_data(cfg_mgmt_read_data),
|
||||
.cfg_mgmt_read_write_done(cfg_mgmt_read_write_done),
|
||||
|
||||
.cfg_interrupt_msi_enable(cfg_interrupt_msi_enable),
|
||||
.cfg_interrupt_msi_vf_enable(cfg_interrupt_msi_vf_enable),
|
||||
.cfg_interrupt_msi_mmenable(cfg_interrupt_msi_mmenable),
|
||||
.cfg_interrupt_msi_mask_update(cfg_interrupt_msi_mask_update),
|
||||
.cfg_interrupt_msi_data(cfg_interrupt_msi_data),
|
||||
.cfg_interrupt_msi_select(cfg_interrupt_msi_select),
|
||||
.cfg_interrupt_msi_int(cfg_interrupt_msi_int),
|
||||
.cfg_interrupt_msi_pending_status(cfg_interrupt_msi_pending_status),
|
||||
.cfg_interrupt_msi_pending_status_data_enable(cfg_interrupt_msi_pending_status_data_enable),
|
||||
.cfg_interrupt_msi_pending_status_function_num(cfg_interrupt_msi_pending_status_function_num),
|
||||
.cfg_interrupt_msi_sent(cfg_interrupt_msi_sent),
|
||||
.cfg_interrupt_msi_fail(cfg_interrupt_msi_fail),
|
||||
.cfg_interrupt_msi_attr(cfg_interrupt_msi_attr),
|
||||
.cfg_interrupt_msi_tph_present(cfg_interrupt_msi_tph_present),
|
||||
.cfg_interrupt_msi_tph_type(cfg_interrupt_msi_tph_type),
|
||||
.cfg_interrupt_msi_tph_st_tag(cfg_interrupt_msi_tph_st_tag),
|
||||
.cfg_interrupt_msi_function_number(cfg_interrupt_msi_function_number),
|
||||
|
||||
.status_error_cor(status_error_cor),
|
||||
.status_error_uncor(status_error_uncor)
|
||||
);
|
||||
|
||||
endmodule
|
1089
fpga/lib/pcie/example/ExaNIC_X10/fpga/rtl/fpga_core.v
Normal file
1089
fpga/lib/pcie/example/ExaNIC_X10/fpga/rtl/fpga_core.v
Normal file
File diff suppressed because it is too large
Load Diff
52
fpga/lib/pcie/example/ExaNIC_X10/fpga/rtl/sync_reset.v
Normal file
52
fpga/lib/pcie/example/ExaNIC_X10/fpga/rtl/sync_reset.v
Normal 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
|
58
fpga/lib/pcie/example/ExaNIC_X10/fpga/rtl/sync_signal.v
Normal file
58
fpga/lib/pcie/example/ExaNIC_X10/fpga/rtl/sync_signal.v
Normal 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
|
1
fpga/lib/pcie/example/ExaNIC_X10/fpga/tb/axis_ep.py
Symbolic link
1
fpga/lib/pcie/example/ExaNIC_X10/fpga/tb/axis_ep.py
Symbolic link
@ -0,0 +1 @@
|
||||
../lib/pcie/tb/axis_ep.py
|
1
fpga/lib/pcie/example/ExaNIC_X10/fpga/tb/pcie.py
Symbolic link
1
fpga/lib/pcie/example/ExaNIC_X10/fpga/tb/pcie.py
Symbolic link
@ -0,0 +1 @@
|
||||
../lib/pcie/tb/pcie.py
|
1
fpga/lib/pcie/example/ExaNIC_X10/fpga/tb/pcie_us.py
Symbolic link
1
fpga/lib/pcie/example/ExaNIC_X10/fpga/tb/pcie_us.py
Symbolic link
@ -0,0 +1 @@
|
||||
../lib/pcie/tb/pcie_us.py
|
507
fpga/lib/pcie/example/ExaNIC_X10/fpga/tb/test_fpga_core.py
Executable file
507
fpga/lib/pcie/example/ExaNIC_X10/fpga/tb/test_fpga_core.py
Executable file
@ -0,0 +1,507 @@
|
||||
#!/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_us
|
||||
|
||||
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
|
||||
|
||||
|
||||
# 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)[256:])
|
||||
s_axis_rc_tkeep = Signal(intbv(0)[8:])
|
||||
s_axis_rc_tlast = Signal(bool(0))
|
||||
s_axis_rc_tuser = Signal(intbv(0)[75:])
|
||||
s_axis_rc_tvalid = Signal(bool(0))
|
||||
s_axis_cq_tdata = Signal(intbv(0)[256:])
|
||||
s_axis_cq_tkeep = Signal(intbv(0)[8:])
|
||||
s_axis_cq_tlast = Signal(bool(0))
|
||||
s_axis_cq_tuser = Signal(intbv(0)[85:])
|
||||
s_axis_cq_tvalid = Signal(bool(0))
|
||||
m_axis_cc_tready = Signal(bool(0))
|
||||
cfg_max_payload = Signal(intbv(0)[3:])
|
||||
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_vf_enable = Signal(intbv(0)[8:])
|
||||
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
|
||||
sfp_1_led = Signal(intbv(0)[2:])
|
||||
sfp_2_led = Signal(intbv(0)[2:])
|
||||
sma_led = Signal(intbv(0)[2:])
|
||||
m_axis_rq_tdata = Signal(intbv(0)[256:])
|
||||
m_axis_rq_tkeep = Signal(intbv(0)[8:])
|
||||
m_axis_rq_tlast = Signal(bool(0))
|
||||
m_axis_rq_tuser = Signal(intbv(0)[60:])
|
||||
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)[256:])
|
||||
m_axis_cc_tkeep = Signal(intbv(0)[8:])
|
||||
m_axis_cc_tlast = Signal(bool(0))
|
||||
m_axis_cc_tuser = Signal(intbv(0)[33:])
|
||||
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)[19:])
|
||||
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)[4:])
|
||||
cfg_interrupt_msi_pending_status_function_num = Signal(intbv(0)[4:])
|
||||
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)[9:])
|
||||
cfg_interrupt_msi_function_number = Signal(intbv(0)[4:])
|
||||
|
||||
# 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_us.UltrascalePCIe()
|
||||
|
||||
dev.pcie_generation = 3
|
||||
dev.pcie_link_width = 8
|
||||
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(bool(1)),
|
||||
#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_num=pcie_rq_seq_num,
|
||||
#pcie_rq_seq_num_vld=pcie_rq_seq_num_vld,
|
||||
#pcie_rq_tag=pcie_rq_tag,
|
||||
#pcie_rq_tag_vld=pcie_rq_tag_vld,
|
||||
|
||||
# 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_write=cfg_mgmt_write,
|
||||
cfg_mgmt_write_data=cfg_mgmt_write_data,
|
||||
cfg_mgmt_byte_enable=cfg_mgmt_byte_enable,
|
||||
cfg_mgmt_read=cfg_mgmt_read,
|
||||
cfg_mgmt_read_data=cfg_mgmt_read_data,
|
||||
cfg_mgmt_read_write_done=cfg_mgmt_read_write_done,
|
||||
#cfg_mgmt_type1_cfg_reg_access=cfg_mgmt_type1_cfg_reg_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_ltr_enable=cfg_ltr_enable,
|
||||
#cfg_ltssm_state=cfg_ltssm_state,
|
||||
#cfg_rcb_status=cfg_rcb_status,
|
||||
#cfg_dpa_substate_change=cfg_dpa_substate_change,
|
||||
#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,
|
||||
|
||||
# Per-Function Status Interface
|
||||
#cfg_per_func_status_control=cfg_per_func_status_control,
|
||||
#cfg_per_func_status_data=cfg_per_func_status_data,
|
||||
|
||||
# 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_per_function_update_done=cfg_per_function_update_done,
|
||||
#cfg_per_function_number=cfg_per_function_number,
|
||||
#cfg_per_function_output_request=cfg_per_function_output_request,
|
||||
#cfg_dsn=cfg_dsn,
|
||||
#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_vf_enable=cfg_interrupt_msi_vf_enable,
|
||||
cfg_interrupt_msi_mmenable=cfg_interrupt_msi_mmenable,
|
||||
cfg_interrupt_msi_mask_update=cfg_interrupt_msi_mask_update,
|
||||
cfg_interrupt_msi_data=cfg_interrupt_msi_data,
|
||||
cfg_interrupt_msi_select=cfg_interrupt_msi_select,
|
||||
cfg_interrupt_msi_int=cfg_interrupt_msi_int,
|
||||
cfg_interrupt_msi_pending_status=cfg_interrupt_msi_pending_status,
|
||||
cfg_interrupt_msi_pending_status_data_enable=cfg_interrupt_msi_pending_status_data_enable,
|
||||
cfg_interrupt_msi_pending_status_function_num=cfg_interrupt_msi_pending_status_function_num,
|
||||
cfg_interrupt_msi_sent=cfg_interrupt_msi_sent,
|
||||
cfg_interrupt_msi_fail=cfg_interrupt_msi_fail,
|
||||
#cfg_interrupt_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_sent=cfg_interrupt_msix_sent,
|
||||
#cfg_interrupt_msix_fail=cfg_interrupt_msix_fail,
|
||||
cfg_interrupt_msi_attr=cfg_interrupt_msi_attr,
|
||||
cfg_interrupt_msi_tph_present=cfg_interrupt_msi_tph_present,
|
||||
cfg_interrupt_msi_tph_type=cfg_interrupt_msi_tph_type,
|
||||
cfg_interrupt_msi_tph_st_tag=cfg_interrupt_msi_tph_st_tag,
|
||||
cfg_interrupt_msi_function_number=cfg_interrupt_msi_function_number,
|
||||
|
||||
# Configuration 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,
|
||||
sys_clk=sys_clk,
|
||||
sys_clk_gt=sys_clk,
|
||||
sys_reset=sys_reset,
|
||||
#pcie_perstn0_out=pcie_perstn0_out,
|
||||
#pcie_perstn1_in=pcie_perstn1_in,
|
||||
#pcie_perstn1_out=pcie_perstn1_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,
|
||||
sfp_1_led=sfp_1_led,
|
||||
sfp_2_led=sfp_2_led,
|
||||
sma_led=sma_led,
|
||||
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_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_vf_enable=cfg_interrupt_msi_vf_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()
|
230
fpga/lib/pcie/example/ExaNIC_X10/fpga/tb/test_fpga_core.v
Normal file
230
fpga/lib/pcie/example/ExaNIC_X10/fpga/tb/test_fpga_core.v
Normal file
@ -0,0 +1,230 @@
|
||||
/*
|
||||
|
||||
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
|
||||
|
||||
// Inputs
|
||||
reg clk = 0;
|
||||
reg rst = 0;
|
||||
reg [7:0] current_test = 0;
|
||||
|
||||
reg m_axis_rq_tready = 0;
|
||||
reg [255:0] s_axis_rc_tdata = 0;
|
||||
reg [7:0] s_axis_rc_tkeep = 0;
|
||||
reg s_axis_rc_tlast = 0;
|
||||
reg [74:0] s_axis_rc_tuser = 0;
|
||||
reg s_axis_rc_tvalid = 0;
|
||||
reg [255:0] s_axis_cq_tdata = 0;
|
||||
reg [7:0] s_axis_cq_tkeep = 0;
|
||||
reg s_axis_cq_tlast = 0;
|
||||
reg [84: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 [7:0] cfg_interrupt_msi_vf_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 [1:0] sfp_1_led;
|
||||
wire [1:0] sfp_2_led;
|
||||
wire [1:0] sma_led;
|
||||
wire [255:0] m_axis_rq_tdata;
|
||||
wire [7:0] m_axis_rq_tkeep;
|
||||
wire m_axis_rq_tlast;
|
||||
wire [59:0] m_axis_rq_tuser;
|
||||
wire m_axis_rq_tvalid;
|
||||
wire s_axis_rc_tready;
|
||||
wire s_axis_cq_tready;
|
||||
wire [255:0] m_axis_cc_tdata;
|
||||
wire [7:0] m_axis_cc_tkeep;
|
||||
wire m_axis_cc_tlast;
|
||||
wire [32:0] m_axis_cc_tuser;
|
||||
wire m_axis_cc_tvalid;
|
||||
wire [18:0] cfg_mgmt_addr;
|
||||
wire cfg_mgmt_write;
|
||||
wire [31:0] cfg_mgmt_write_data;
|
||||
wire [3:0] cfg_mgmt_byte_enable;
|
||||
wire cfg_mgmt_read;
|
||||
wire [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_vf_enable,
|
||||
cfg_interrupt_msi_mmenable,
|
||||
cfg_interrupt_msi_mask_update,
|
||||
cfg_interrupt_msi_data,
|
||||
cfg_interrupt_msi_sent,
|
||||
cfg_interrupt_msi_fail
|
||||
);
|
||||
$to_myhdl(
|
||||
sfp_1_led,
|
||||
sfp_2_led,
|
||||
sma_led,
|
||||
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_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
|
||||
UUT (
|
||||
.clk(clk),
|
||||
.rst(rst),
|
||||
.sfp_1_led(sfp_1_led),
|
||||
.sfp_2_led(sfp_2_led),
|
||||
.sma_led(sma_led),
|
||||
.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_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_vf_enable(cfg_interrupt_msi_vf_enable),
|
||||
.cfg_interrupt_msi_mmenable(cfg_interrupt_msi_mmenable),
|
||||
.cfg_interrupt_msi_mask_update(cfg_interrupt_msi_mask_update),
|
||||
.cfg_interrupt_msi_data(cfg_interrupt_msi_data),
|
||||
.cfg_interrupt_msi_select(cfg_interrupt_msi_select),
|
||||
.cfg_interrupt_msi_int(cfg_interrupt_msi_int),
|
||||
.cfg_interrupt_msi_pending_status(cfg_interrupt_msi_pending_status),
|
||||
.cfg_interrupt_msi_pending_status_data_enable(cfg_interrupt_msi_pending_status_data_enable),
|
||||
.cfg_interrupt_msi_pending_status_function_num(cfg_interrupt_msi_pending_status_function_num),
|
||||
.cfg_interrupt_msi_sent(cfg_interrupt_msi_sent),
|
||||
.cfg_interrupt_msi_fail(cfg_interrupt_msi_fail),
|
||||
.cfg_interrupt_msi_attr(cfg_interrupt_msi_attr),
|
||||
.cfg_interrupt_msi_tph_present(cfg_interrupt_msi_tph_present),
|
||||
.cfg_interrupt_msi_tph_type(cfg_interrupt_msi_tph_type),
|
||||
.cfg_interrupt_msi_tph_st_tag(cfg_interrupt_msi_tph_st_tag),
|
||||
.cfg_interrupt_msi_function_number(cfg_interrupt_msi_function_number),
|
||||
.status_error_cor(status_error_cor),
|
||||
.status_error_uncor(status_error_uncor)
|
||||
);
|
||||
|
||||
endmodule
|
153
fpga/lib/pcie/rtl/arbiter.v
Normal file
153
fpga/lib/pcie/rtl/arbiter.v
Normal file
@ -0,0 +1,153 @@
|
||||
/*
|
||||
|
||||
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
|
||||
|
||||
/*
|
||||
* Arbiter module
|
||||
*/
|
||||
module arbiter #
|
||||
(
|
||||
parameter PORTS = 4,
|
||||
// arbitration type: "PRIORITY" or "ROUND_ROBIN"
|
||||
parameter TYPE = "PRIORITY",
|
||||
// block type: "NONE", "REQUEST", "ACKNOWLEDGE"
|
||||
parameter BLOCK = "NONE",
|
||||
// LSB priority: "LOW", "HIGH"
|
||||
parameter LSB_PRIORITY = "LOW"
|
||||
)
|
||||
(
|
||||
input wire clk,
|
||||
input wire rst,
|
||||
|
||||
input wire [PORTS-1:0] request,
|
||||
input wire [PORTS-1:0] acknowledge,
|
||||
|
||||
output wire [PORTS-1:0] grant,
|
||||
output wire grant_valid,
|
||||
output wire [$clog2(PORTS)-1:0] grant_encoded
|
||||
);
|
||||
|
||||
reg [PORTS-1:0] grant_reg = 0, grant_next;
|
||||
reg grant_valid_reg = 0, grant_valid_next;
|
||||
reg [$clog2(PORTS)-1:0] grant_encoded_reg = 0, grant_encoded_next;
|
||||
|
||||
assign grant_valid = grant_valid_reg;
|
||||
assign grant = grant_reg;
|
||||
assign grant_encoded = grant_encoded_reg;
|
||||
|
||||
wire request_valid;
|
||||
wire [$clog2(PORTS)-1:0] request_index;
|
||||
wire [PORTS-1:0] request_mask;
|
||||
|
||||
priority_encoder #(
|
||||
.WIDTH(PORTS),
|
||||
.LSB_PRIORITY(LSB_PRIORITY)
|
||||
)
|
||||
priority_encoder_inst (
|
||||
.input_unencoded(request),
|
||||
.output_valid(request_valid),
|
||||
.output_encoded(request_index),
|
||||
.output_unencoded(request_mask)
|
||||
);
|
||||
|
||||
reg [PORTS-1:0] mask_reg = 0, mask_next;
|
||||
|
||||
wire masked_request_valid;
|
||||
wire [$clog2(PORTS)-1:0] masked_request_index;
|
||||
wire [PORTS-1:0] masked_request_mask;
|
||||
|
||||
priority_encoder #(
|
||||
.WIDTH(PORTS),
|
||||
.LSB_PRIORITY(LSB_PRIORITY)
|
||||
)
|
||||
priority_encoder_masked (
|
||||
.input_unencoded(request & mask_reg),
|
||||
.output_valid(masked_request_valid),
|
||||
.output_encoded(masked_request_index),
|
||||
.output_unencoded(masked_request_mask)
|
||||
);
|
||||
|
||||
always @* begin
|
||||
grant_next = 0;
|
||||
grant_valid_next = 0;
|
||||
grant_encoded_next = 0;
|
||||
mask_next = mask_reg;
|
||||
|
||||
if (BLOCK == "REQUEST" && grant_reg & request) begin
|
||||
// granted request still asserted; hold it
|
||||
grant_valid_next = grant_valid_reg;
|
||||
grant_next = grant_reg;
|
||||
grant_encoded_next = grant_encoded_reg;
|
||||
end else if (BLOCK == "ACKNOWLEDGE" && grant_valid && !(grant_reg & acknowledge)) begin
|
||||
// granted request not yet acknowledged; hold it
|
||||
grant_valid_next = grant_valid_reg;
|
||||
grant_next = grant_reg;
|
||||
grant_encoded_next = grant_encoded_reg;
|
||||
end else if (request_valid) begin
|
||||
if (TYPE == "PRIORITY") begin
|
||||
grant_valid_next = 1;
|
||||
grant_next = request_mask;
|
||||
grant_encoded_next = request_index;
|
||||
end else if (TYPE == "ROUND_ROBIN") begin
|
||||
if (masked_request_valid) begin
|
||||
grant_valid_next = 1;
|
||||
grant_next = masked_request_mask;
|
||||
grant_encoded_next = masked_request_index;
|
||||
if (LSB_PRIORITY == "LOW") begin
|
||||
mask_next = {PORTS{1'b1}} >> (PORTS - masked_request_index);
|
||||
end else begin
|
||||
mask_next = {PORTS{1'b1}} << (masked_request_index + 1);
|
||||
end
|
||||
end else begin
|
||||
grant_valid_next = 1;
|
||||
grant_next = request_mask;
|
||||
grant_encoded_next = request_index;
|
||||
if (LSB_PRIORITY == "LOW") begin
|
||||
mask_next = {PORTS{1'b1}} >> (PORTS - request_index);
|
||||
end else begin
|
||||
mask_next = {PORTS{1'b1}} << (request_index + 1);
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (rst) begin
|
||||
grant_reg <= 0;
|
||||
grant_valid_reg <= 0;
|
||||
grant_encoded_reg <= 0;
|
||||
mask_reg <= 0;
|
||||
end else begin
|
||||
grant_reg <= grant_next;
|
||||
grant_valid_reg <= grant_valid_next;
|
||||
grant_encoded_reg <= grant_encoded_next;
|
||||
mask_reg <= mask_next;
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
245
fpga/lib/pcie/rtl/axis_arb_mux.v
Normal file
245
fpga/lib/pcie/rtl/axis_arb_mux.v
Normal file
@ -0,0 +1,245 @@
|
||||
/*
|
||||
|
||||
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 arbitrated multiplexer
|
||||
*/
|
||||
module axis_arb_mux #
|
||||
(
|
||||
parameter S_COUNT = 4,
|
||||
parameter DATA_WIDTH = 8,
|
||||
parameter KEEP_ENABLE = (DATA_WIDTH>8),
|
||||
parameter KEEP_WIDTH = (DATA_WIDTH/8),
|
||||
parameter ID_ENABLE = 0,
|
||||
parameter ID_WIDTH = 8,
|
||||
parameter DEST_ENABLE = 0,
|
||||
parameter DEST_WIDTH = 8,
|
||||
parameter USER_ENABLE = 1,
|
||||
parameter USER_WIDTH = 1,
|
||||
// arbitration type: "PRIORITY" or "ROUND_ROBIN"
|
||||
parameter ARB_TYPE = "PRIORITY",
|
||||
// LSB priority: "LOW", "HIGH"
|
||||
parameter LSB_PRIORITY = "HIGH"
|
||||
)
|
||||
(
|
||||
input wire clk,
|
||||
input wire rst,
|
||||
|
||||
/*
|
||||
* AXI Stream inputs
|
||||
*/
|
||||
input wire [S_COUNT*DATA_WIDTH-1:0] s_axis_tdata,
|
||||
input wire [S_COUNT*KEEP_WIDTH-1:0] s_axis_tkeep,
|
||||
input wire [S_COUNT-1:0] s_axis_tvalid,
|
||||
output wire [S_COUNT-1:0] s_axis_tready,
|
||||
input wire [S_COUNT-1:0] s_axis_tlast,
|
||||
input wire [S_COUNT*ID_WIDTH-1:0] s_axis_tid,
|
||||
input wire [S_COUNT*DEST_WIDTH-1:0] s_axis_tdest,
|
||||
input wire [S_COUNT*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
|
||||
);
|
||||
|
||||
parameter CL_S_COUNT = $clog2(S_COUNT);
|
||||
|
||||
wire [S_COUNT-1:0] request;
|
||||
wire [S_COUNT-1:0] acknowledge;
|
||||
wire [S_COUNT-1:0] grant;
|
||||
wire grant_valid;
|
||||
wire [CL_S_COUNT-1:0] grant_encoded;
|
||||
|
||||
// internal datapath
|
||||
reg [DATA_WIDTH-1:0] m_axis_tdata_int;
|
||||
reg [KEEP_WIDTH-1:0] m_axis_tkeep_int;
|
||||
reg m_axis_tvalid_int;
|
||||
reg m_axis_tready_int_reg = 1'b0;
|
||||
reg m_axis_tlast_int;
|
||||
reg [ID_WIDTH-1:0] m_axis_tid_int;
|
||||
reg [DEST_WIDTH-1:0] m_axis_tdest_int;
|
||||
reg [USER_WIDTH-1:0] m_axis_tuser_int;
|
||||
wire m_axis_tready_int_early;
|
||||
|
||||
assign s_axis_tready = (m_axis_tready_int_reg && grant_valid) << grant_encoded;
|
||||
|
||||
// mux for incoming packet
|
||||
wire [DATA_WIDTH-1:0] current_s_tdata = s_axis_tdata[grant_encoded*DATA_WIDTH +: DATA_WIDTH];
|
||||
wire [KEEP_WIDTH-1:0] current_s_tkeep = s_axis_tkeep[grant_encoded*KEEP_WIDTH +: KEEP_WIDTH];
|
||||
wire current_s_tvalid = s_axis_tvalid[grant_encoded];
|
||||
wire current_s_tready = s_axis_tready[grant_encoded];
|
||||
wire current_s_tlast = s_axis_tlast[grant_encoded];
|
||||
wire [ID_WIDTH-1:0] current_s_tid = s_axis_tid[grant_encoded*ID_WIDTH +: ID_WIDTH];
|
||||
wire [DEST_WIDTH-1:0] current_s_tdest = s_axis_tdest[grant_encoded*DEST_WIDTH +: DEST_WIDTH];
|
||||
wire [USER_WIDTH-1:0] current_s_tuser = s_axis_tuser[grant_encoded*USER_WIDTH +: USER_WIDTH];
|
||||
|
||||
// arbiter instance
|
||||
arbiter #(
|
||||
.PORTS(S_COUNT),
|
||||
.TYPE(ARB_TYPE),
|
||||
.BLOCK("ACKNOWLEDGE"),
|
||||
.LSB_PRIORITY(LSB_PRIORITY)
|
||||
)
|
||||
arb_inst (
|
||||
.clk(clk),
|
||||
.rst(rst),
|
||||
.request(request),
|
||||
.acknowledge(acknowledge),
|
||||
.grant(grant),
|
||||
.grant_valid(grant_valid),
|
||||
.grant_encoded(grant_encoded)
|
||||
);
|
||||
|
||||
generate
|
||||
genvar n;
|
||||
|
||||
for (n = 0; n < S_COUNT; n = n + 1) begin
|
||||
assign request[n] = s_axis_tvalid[n] && !grant[n];
|
||||
assign acknowledge[n] = grant[n] && s_axis_tvalid[n] && s_axis_tready[n] && s_axis_tlast[n];
|
||||
end
|
||||
endgenerate
|
||||
|
||||
always @* begin
|
||||
// pass through selected packet data
|
||||
m_axis_tdata_int = current_s_tdata;
|
||||
m_axis_tkeep_int = current_s_tkeep;
|
||||
m_axis_tvalid_int = current_s_tvalid && m_axis_tready_int_reg && grant_valid;
|
||||
m_axis_tlast_int = current_s_tlast;
|
||||
m_axis_tid_int = current_s_tid;
|
||||
m_axis_tdest_int = current_s_tdest;
|
||||
m_axis_tuser_int = current_s_tuser;
|
||||
end
|
||||
|
||||
// output datapath logic
|
||||
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_int_to_output;
|
||||
reg store_axis_int_to_temp;
|
||||
reg store_axis_temp_to_output;
|
||||
|
||||
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 = m_axis_tlast_reg;
|
||||
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)
|
||||
assign m_axis_tready_int_early = m_axis_tready || (!temp_m_axis_tvalid_reg && (!m_axis_tvalid_reg || !m_axis_tvalid_int));
|
||||
|
||||
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_int_to_output = 1'b0;
|
||||
store_axis_int_to_temp = 1'b0;
|
||||
store_axis_temp_to_output = 1'b0;
|
||||
|
||||
if (m_axis_tready_int_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 = m_axis_tvalid_int;
|
||||
store_axis_int_to_output = 1'b1;
|
||||
end else begin
|
||||
// output is not ready, store input in temp
|
||||
temp_m_axis_tvalid_next = m_axis_tvalid_int;
|
||||
store_axis_int_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
|
||||
m_axis_tvalid_reg <= 1'b0;
|
||||
m_axis_tready_int_reg <= 1'b0;
|
||||
temp_m_axis_tvalid_reg <= 1'b0;
|
||||
end else begin
|
||||
m_axis_tvalid_reg <= m_axis_tvalid_next;
|
||||
m_axis_tready_int_reg <= m_axis_tready_int_early;
|
||||
temp_m_axis_tvalid_reg <= temp_m_axis_tvalid_next;
|
||||
end
|
||||
|
||||
// datapath
|
||||
if (store_axis_int_to_output) begin
|
||||
m_axis_tdata_reg <= m_axis_tdata_int;
|
||||
m_axis_tkeep_reg <= m_axis_tkeep_int;
|
||||
m_axis_tlast_reg <= m_axis_tlast_int;
|
||||
m_axis_tid_reg <= m_axis_tid_int;
|
||||
m_axis_tdest_reg <= m_axis_tdest_int;
|
||||
m_axis_tuser_reg <= m_axis_tuser_int;
|
||||
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_int_to_temp) begin
|
||||
temp_m_axis_tdata_reg <= m_axis_tdata_int;
|
||||
temp_m_axis_tkeep_reg <= m_axis_tkeep_int;
|
||||
temp_m_axis_tlast_reg <= m_axis_tlast_int;
|
||||
temp_m_axis_tid_reg <= m_axis_tid_int;
|
||||
temp_m_axis_tdest_reg <= m_axis_tdest_int;
|
||||
temp_m_axis_tuser_reg <= m_axis_tuser_int;
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
256
fpga/lib/pcie/rtl/pcie_axi_dma_desc_mux.v
Normal file
256
fpga/lib/pcie/rtl/pcie_axi_dma_desc_mux.v
Normal file
@ -0,0 +1,256 @@
|
||||
/*
|
||||
|
||||
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
|
||||
|
||||
/*
|
||||
* PCIe AXI DMA descriptor mux
|
||||
*/
|
||||
module pcie_axi_dma_desc_mux #
|
||||
(
|
||||
parameter PORTS = 2,
|
||||
parameter PCIE_ADDR_WIDTH = 64,
|
||||
parameter AXI_ADDR_WIDTH = 16,
|
||||
parameter LEN_WIDTH = 20,
|
||||
parameter S_TAG_WIDTH = 8,
|
||||
parameter M_TAG_WIDTH = S_TAG_WIDTH+$clog2(PORTS),
|
||||
// arbitration type: "PRIORITY" or "ROUND_ROBIN"
|
||||
parameter ARB_TYPE = "PRIORITY",
|
||||
// LSB priority: "LOW", "HIGH"
|
||||
parameter LSB_PRIORITY = "HIGH"
|
||||
)
|
||||
(
|
||||
input wire clk,
|
||||
input wire rst,
|
||||
|
||||
/*
|
||||
* Descriptor output (to PCIe DMA core)
|
||||
*/
|
||||
output wire [PCIE_ADDR_WIDTH-1:0] m_axis_desc_pcie_addr,
|
||||
output wire [AXI_ADDR_WIDTH-1:0] m_axis_desc_axi_addr,
|
||||
output wire [LEN_WIDTH-1:0] m_axis_desc_len,
|
||||
output wire [M_TAG_WIDTH-1:0] m_axis_desc_tag,
|
||||
output wire m_axis_desc_valid,
|
||||
input wire m_axis_desc_ready,
|
||||
|
||||
/*
|
||||
* Descriptor status input (from PCIe DMA core)
|
||||
*/
|
||||
input wire [M_TAG_WIDTH-1:0] s_axis_desc_status_tag,
|
||||
input wire s_axis_desc_status_valid,
|
||||
|
||||
/*
|
||||
* Descriptor input
|
||||
*/
|
||||
input wire [PORTS*PCIE_ADDR_WIDTH-1:0] s_axis_desc_pcie_addr,
|
||||
input wire [PORTS*AXI_ADDR_WIDTH-1:0] s_axis_desc_axi_addr,
|
||||
input wire [PORTS*LEN_WIDTH-1:0] s_axis_desc_len,
|
||||
input wire [PORTS*S_TAG_WIDTH-1:0] s_axis_desc_tag,
|
||||
input wire [PORTS-1:0] s_axis_desc_valid,
|
||||
output wire [PORTS-1:0] s_axis_desc_ready,
|
||||
|
||||
/*
|
||||
* Descriptor status output
|
||||
*/
|
||||
output wire [PORTS*S_TAG_WIDTH-1:0] m_axis_desc_status_tag,
|
||||
output wire [PORTS-1:0] m_axis_desc_status_valid
|
||||
);
|
||||
|
||||
parameter CL_PORTS = $clog2(PORTS);
|
||||
|
||||
// check configuration
|
||||
initial begin
|
||||
if (M_TAG_WIDTH < S_TAG_WIDTH+$clog2(PORTS)) begin
|
||||
$error("Error: M_TAG_WIDTH must be at least $clog2(PORTS) larger than S_TAG_WIDTH");
|
||||
$finish;
|
||||
end
|
||||
end
|
||||
|
||||
// descriptor mux
|
||||
wire [PORTS-1:0] request;
|
||||
wire [PORTS-1:0] acknowledge;
|
||||
wire [PORTS-1:0] grant;
|
||||
wire grant_valid;
|
||||
wire [CL_PORTS-1:0] grant_encoded;
|
||||
|
||||
// internal datapath
|
||||
reg [PCIE_ADDR_WIDTH-1:0] m_axis_desc_pcie_addr_int;
|
||||
reg [AXI_ADDR_WIDTH-1:0] m_axis_desc_axi_addr_int;
|
||||
reg [LEN_WIDTH-1:0] m_axis_desc_len_int;
|
||||
reg [M_TAG_WIDTH-1:0] m_axis_desc_tag_int;
|
||||
reg m_axis_desc_valid_int;
|
||||
reg m_axis_desc_ready_int_reg = 1'b0;
|
||||
wire m_axis_desc_ready_int_early;
|
||||
|
||||
assign s_axis_desc_ready = (m_axis_desc_ready_int_reg && grant_valid) << grant_encoded;
|
||||
|
||||
// mux for incoming packet
|
||||
wire [PCIE_ADDR_WIDTH-1:0] current_s_desc_pcie_addr = s_axis_desc_pcie_addr[grant_encoded*PCIE_ADDR_WIDTH +: PCIE_ADDR_WIDTH];
|
||||
wire [AXI_ADDR_WIDTH-1:0] current_s_desc_axi_addr = s_axis_desc_axi_addr[grant_encoded*AXI_ADDR_WIDTH +: AXI_ADDR_WIDTH];
|
||||
wire [LEN_WIDTH-1:0] current_s_desc_len = s_axis_desc_len[grant_encoded*LEN_WIDTH +: LEN_WIDTH];
|
||||
wire [S_TAG_WIDTH-1:0] current_s_desc_tag = s_axis_desc_tag[grant_encoded*S_TAG_WIDTH +: S_TAG_WIDTH];
|
||||
wire current_s_desc_valid = s_axis_desc_valid[grant_encoded];
|
||||
wire current_s_desc_ready = s_axis_desc_ready[grant_encoded];
|
||||
|
||||
// arbiter instance
|
||||
arbiter #(
|
||||
.PORTS(PORTS),
|
||||
.TYPE(ARB_TYPE),
|
||||
.BLOCK("ACKNOWLEDGE"),
|
||||
.LSB_PRIORITY(LSB_PRIORITY)
|
||||
)
|
||||
arb_inst (
|
||||
.clk(clk),
|
||||
.rst(rst),
|
||||
.request(request),
|
||||
.acknowledge(acknowledge),
|
||||
.grant(grant),
|
||||
.grant_valid(grant_valid),
|
||||
.grant_encoded(grant_encoded)
|
||||
);
|
||||
|
||||
assign request = s_axis_desc_valid & ~grant;
|
||||
assign acknowledge = grant & s_axis_desc_valid & s_axis_desc_ready;
|
||||
|
||||
always @* begin
|
||||
// pass through selected packet data
|
||||
m_axis_desc_pcie_addr_int = current_s_desc_pcie_addr;
|
||||
m_axis_desc_axi_addr_int = current_s_desc_axi_addr;
|
||||
m_axis_desc_len_int = current_s_desc_len;
|
||||
m_axis_desc_tag_int = {grant_encoded, current_s_desc_tag};
|
||||
m_axis_desc_valid_int = current_s_desc_valid && m_axis_desc_ready_int_reg && grant_valid;
|
||||
end
|
||||
|
||||
// output datapath logic
|
||||
reg [PCIE_ADDR_WIDTH-1:0] m_axis_desc_pcie_addr_reg = {PCIE_ADDR_WIDTH{1'b0}};
|
||||
reg [AXI_ADDR_WIDTH-1:0] m_axis_desc_axi_addr_reg = {AXI_ADDR_WIDTH{1'b0}};
|
||||
reg [LEN_WIDTH-1:0] m_axis_desc_len_reg = {LEN_WIDTH{1'b0}};
|
||||
reg [M_TAG_WIDTH-1:0] m_axis_desc_tag_reg = {M_TAG_WIDTH{1'b0}};
|
||||
reg m_axis_desc_valid_reg = 1'b0, m_axis_desc_valid_next;
|
||||
|
||||
reg [PCIE_ADDR_WIDTH-1:0] temp_m_axis_desc_pcie_addr_reg = {PCIE_ADDR_WIDTH{1'b0}};
|
||||
reg [AXI_ADDR_WIDTH-1:0] temp_m_axis_desc_axi_addr_reg = {AXI_ADDR_WIDTH{1'b0}};
|
||||
reg [LEN_WIDTH-1:0] temp_m_axis_desc_len_reg = {LEN_WIDTH{1'b0}};
|
||||
reg [M_TAG_WIDTH-1:0] temp_m_axis_desc_tag_reg = {M_TAG_WIDTH{1'b0}};
|
||||
reg temp_m_axis_desc_valid_reg = 1'b0, temp_m_axis_desc_valid_next;
|
||||
|
||||
// datapath control
|
||||
reg store_axis_int_to_output;
|
||||
reg store_axis_int_to_temp;
|
||||
reg store_axis_temp_to_output;
|
||||
|
||||
assign m_axis_desc_pcie_addr = m_axis_desc_pcie_addr_reg;
|
||||
assign m_axis_desc_axi_addr = m_axis_desc_axi_addr_reg;
|
||||
assign m_axis_desc_len = m_axis_desc_len_reg;
|
||||
assign m_axis_desc_tag = m_axis_desc_tag_reg;
|
||||
assign m_axis_desc_valid = m_axis_desc_valid_reg;
|
||||
|
||||
// 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)
|
||||
assign m_axis_desc_ready_int_early = m_axis_desc_ready || (!temp_m_axis_desc_valid_reg && (!m_axis_desc_valid_reg || !m_axis_desc_valid_int));
|
||||
|
||||
always @* begin
|
||||
// transfer sink ready state to source
|
||||
m_axis_desc_valid_next = m_axis_desc_valid_reg;
|
||||
temp_m_axis_desc_valid_next = temp_m_axis_desc_valid_reg;
|
||||
|
||||
store_axis_int_to_output = 1'b0;
|
||||
store_axis_int_to_temp = 1'b0;
|
||||
store_axis_temp_to_output = 1'b0;
|
||||
|
||||
if (m_axis_desc_ready_int_reg) begin
|
||||
// input is ready
|
||||
if (m_axis_desc_ready || !m_axis_desc_valid_reg) begin
|
||||
// output is ready or currently not valid, transfer data to output
|
||||
m_axis_desc_valid_next = m_axis_desc_valid_int;
|
||||
store_axis_int_to_output = 1'b1;
|
||||
end else begin
|
||||
// output is not ready, store input in temp
|
||||
temp_m_axis_desc_valid_next = m_axis_desc_valid_int;
|
||||
store_axis_int_to_temp = 1'b1;
|
||||
end
|
||||
end else if (m_axis_desc_ready) begin
|
||||
// input is not ready, but output is ready
|
||||
m_axis_desc_valid_next = temp_m_axis_desc_valid_reg;
|
||||
temp_m_axis_desc_valid_next = 1'b0;
|
||||
store_axis_temp_to_output = 1'b1;
|
||||
end
|
||||
end
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (rst) begin
|
||||
m_axis_desc_valid_reg <= 1'b0;
|
||||
m_axis_desc_ready_int_reg <= 1'b0;
|
||||
temp_m_axis_desc_valid_reg <= 1'b0;
|
||||
end else begin
|
||||
m_axis_desc_valid_reg <= m_axis_desc_valid_next;
|
||||
m_axis_desc_ready_int_reg <= m_axis_desc_ready_int_early;
|
||||
temp_m_axis_desc_valid_reg <= temp_m_axis_desc_valid_next;
|
||||
end
|
||||
|
||||
// datapath
|
||||
if (store_axis_int_to_output) begin
|
||||
m_axis_desc_pcie_addr_reg <= m_axis_desc_pcie_addr_int;
|
||||
m_axis_desc_axi_addr_reg <= m_axis_desc_axi_addr_int;
|
||||
m_axis_desc_len_reg <= m_axis_desc_len_int;
|
||||
m_axis_desc_tag_reg <= m_axis_desc_tag_int;
|
||||
end else if (store_axis_temp_to_output) begin
|
||||
m_axis_desc_pcie_addr_reg <= temp_m_axis_desc_pcie_addr_reg;
|
||||
m_axis_desc_axi_addr_reg <= temp_m_axis_desc_axi_addr_reg;
|
||||
m_axis_desc_len_reg <= temp_m_axis_desc_len_reg;
|
||||
m_axis_desc_tag_reg <= temp_m_axis_desc_tag_reg;
|
||||
end
|
||||
|
||||
if (store_axis_int_to_temp) begin
|
||||
temp_m_axis_desc_pcie_addr_reg <= m_axis_desc_pcie_addr_int;
|
||||
temp_m_axis_desc_axi_addr_reg <= m_axis_desc_axi_addr_int;
|
||||
temp_m_axis_desc_len_reg <= m_axis_desc_len_int;
|
||||
temp_m_axis_desc_tag_reg <= m_axis_desc_tag_int;
|
||||
end
|
||||
end
|
||||
|
||||
// descriptor status demux
|
||||
reg [S_TAG_WIDTH-1:0] m_axis_desc_status_tag_reg = {S_TAG_WIDTH{1'b0}}, m_axis_desc_status_tag_next;
|
||||
reg [PORTS-1:0] m_axis_desc_status_valid_reg = {PORTS{1'b0}}, m_axis_desc_status_valid_next;
|
||||
|
||||
assign m_axis_desc_status_tag = {PORTS{m_axis_desc_status_tag_reg}};
|
||||
assign m_axis_desc_status_valid = m_axis_desc_status_valid_reg;
|
||||
|
||||
always @* begin
|
||||
m_axis_desc_status_tag_next = s_axis_desc_status_tag;
|
||||
m_axis_desc_status_valid_next = s_axis_desc_status_valid << (PORTS > 1 ? s_axis_desc_status_tag[S_TAG_WIDTH+CL_PORTS-1:S_TAG_WIDTH] : 0);
|
||||
end
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (rst) begin
|
||||
m_axis_desc_status_valid_reg <= {PORTS{1'b0}};
|
||||
end else begin
|
||||
m_axis_desc_status_valid_reg <= m_axis_desc_status_valid_next;
|
||||
end
|
||||
|
||||
m_axis_desc_status_tag_reg <= m_axis_desc_status_tag_next;
|
||||
end
|
||||
|
||||
endmodule
|
168
fpga/lib/pcie/rtl/pcie_tag_manager.v
Normal file
168
fpga/lib/pcie/rtl/pcie_tag_manager.v
Normal file
@ -0,0 +1,168 @@
|
||||
/*
|
||||
|
||||
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
|
||||
|
||||
/*
|
||||
* PCIe tag manager
|
||||
*/
|
||||
module pcie_tag_manager #
|
||||
(
|
||||
parameter PCIE_TAG_COUNT = 256,
|
||||
parameter PCIE_TAG_WIDTH = $clog2(PCIE_TAG_COUNT),
|
||||
parameter PCIE_EXT_TAG_ENABLE = 1
|
||||
)
|
||||
(
|
||||
input wire clk,
|
||||
input wire rst,
|
||||
|
||||
/*
|
||||
* AXIS tag output
|
||||
*/
|
||||
output wire [PCIE_TAG_WIDTH-1:0] m_axis_tag,
|
||||
output wire m_axis_tag_valid,
|
||||
input wire m_axis_tag_ready,
|
||||
|
||||
/*
|
||||
* AXIS tag output
|
||||
*/
|
||||
input wire [PCIE_TAG_WIDTH-1:0] s_axis_tag,
|
||||
input wire s_axis_tag_valid,
|
||||
|
||||
/*
|
||||
* Configuration
|
||||
*/
|
||||
input wire ext_tag_enable,
|
||||
|
||||
/*
|
||||
* Status
|
||||
*/
|
||||
output wire [PCIE_TAG_COUNT-1:0] active_tags
|
||||
);
|
||||
|
||||
// parameter assertions
|
||||
initial begin
|
||||
if (PCIE_TAG_WIDTH < $clog2(PCIE_TAG_COUNT)) begin
|
||||
$error("Error: PCIe tag width insufficient for requested tag count");
|
||||
$finish;
|
||||
end
|
||||
|
||||
if (PCIE_TAG_COUNT < 1 || PCIE_TAG_COUNT > 256) begin
|
||||
$error("Error: PCIe tag count must be between 1 and 256");
|
||||
$finish;
|
||||
end
|
||||
|
||||
if (PCIE_TAG_COUNT > 32 && !PCIE_EXT_TAG_ENABLE) begin
|
||||
$warning("Warning: PCIe tag count set larger than 32, but extended tag support is disabled");
|
||||
end
|
||||
|
||||
if (PCIE_TAG_COUNT <= 32 && PCIE_EXT_TAG_ENABLE) begin
|
||||
$warning("Warning: PCIe tag count set to 32 or less, but extended tag support is enabled");
|
||||
end
|
||||
end
|
||||
|
||||
reg [PCIE_TAG_COUNT-1:0] tag_active_reg = {PCIE_TAG_COUNT{1'b0}}, tag_active_next;
|
||||
reg [PCIE_TAG_COUNT-1:0] tag_mask_reg = {PCIE_TAG_COUNT{1'b0}}, tag_mask_next;
|
||||
|
||||
reg [PCIE_TAG_WIDTH-1:0] m_axis_tag_reg = {PCIE_TAG_WIDTH{1'b0}}, m_axis_tag_next;
|
||||
reg m_axis_tag_valid_reg = 1'b0, m_axis_tag_valid_next;
|
||||
|
||||
assign m_axis_tag = m_axis_tag_reg;
|
||||
assign m_axis_tag_valid = m_axis_tag_valid_reg;
|
||||
|
||||
assign active_tags = tag_active_reg;
|
||||
|
||||
wire tag_valid;
|
||||
wire [PCIE_TAG_WIDTH-1:0] tag_index;
|
||||
|
||||
priority_encoder #(
|
||||
.WIDTH(PCIE_TAG_COUNT),
|
||||
.LSB_PRIORITY("HIGH")
|
||||
)
|
||||
priority_encoder_inst (
|
||||
.input_unencoded(~tag_active_reg & (ext_tag_enable && PCIE_EXT_TAG_ENABLE ? {256{1'b1}} : {32{1'b1}})),
|
||||
.output_valid(tag_valid),
|
||||
.output_encoded(tag_index),
|
||||
.output_unencoded()
|
||||
);
|
||||
|
||||
wire masked_tag_valid;
|
||||
wire [PCIE_TAG_WIDTH-1:0] masked_tag_index;
|
||||
|
||||
priority_encoder #(
|
||||
.WIDTH(PCIE_TAG_COUNT),
|
||||
.LSB_PRIORITY("HIGH")
|
||||
)
|
||||
priority_encoder_masked (
|
||||
.input_unencoded(~tag_active_reg & tag_mask_reg & (ext_tag_enable && PCIE_EXT_TAG_ENABLE ? {256{1'b1}} : {32{1'b1}})),
|
||||
.output_valid(masked_tag_valid),
|
||||
.output_encoded(masked_tag_index),
|
||||
.output_unencoded()
|
||||
);
|
||||
|
||||
always @* begin
|
||||
tag_active_next = tag_active_reg;
|
||||
tag_mask_next = tag_mask_reg;
|
||||
|
||||
m_axis_tag_next = m_axis_tag_reg;
|
||||
m_axis_tag_valid_next = m_axis_tag_valid_reg && !m_axis_tag_ready;
|
||||
|
||||
if (s_axis_tag_valid) begin
|
||||
tag_active_next[s_axis_tag] = 1'b0;
|
||||
end
|
||||
|
||||
if (!m_axis_tag_valid || m_axis_tag_ready) begin
|
||||
if (tag_valid) begin
|
||||
if (masked_tag_valid) begin
|
||||
m_axis_tag_next = masked_tag_index;
|
||||
m_axis_tag_valid_next = 1'b1;
|
||||
tag_active_next[masked_tag_index] = 1'b1;
|
||||
tag_mask_next = {PCIE_TAG_COUNT{1'b1}} << (masked_tag_index + 1);
|
||||
end else begin
|
||||
m_axis_tag_next = tag_index;
|
||||
m_axis_tag_valid_next = 1'b1;
|
||||
tag_active_next[tag_index] = 1'b1;
|
||||
tag_mask_next = {PCIE_TAG_COUNT{1'b1}} << (tag_index + 1);
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (rst) begin
|
||||
tag_active_reg <= {PCIE_TAG_COUNT{1'b0}};
|
||||
tag_mask_reg <= {PCIE_TAG_COUNT{1'b0}};
|
||||
m_axis_tag_valid_reg <= 1'b0;
|
||||
end else begin
|
||||
tag_active_reg <= tag_active_next;
|
||||
tag_mask_reg <= tag_mask_next;
|
||||
m_axis_tag_valid_reg <= m_axis_tag_valid_next;
|
||||
end
|
||||
|
||||
m_axis_tag_reg <= m_axis_tag_next;
|
||||
end
|
||||
|
||||
endmodule
|
387
fpga/lib/pcie/rtl/pcie_us_axi_dma.v
Normal file
387
fpga/lib/pcie/rtl/pcie_us_axi_dma.v
Normal file
@ -0,0 +1,387 @@
|
||||
/*
|
||||
|
||||
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
|
||||
|
||||
/*
|
||||
* Ultrascale PCIe AXI DMA
|
||||
*/
|
||||
module pcie_us_axi_dma #
|
||||
(
|
||||
parameter AXIS_PCIE_DATA_WIDTH = 256,
|
||||
parameter AXIS_PCIE_KEEP_WIDTH = (AXIS_PCIE_DATA_WIDTH/32),
|
||||
parameter AXI_DATA_WIDTH = AXIS_PCIE_DATA_WIDTH,
|
||||
parameter AXI_ADDR_WIDTH = 64,
|
||||
parameter AXI_STRB_WIDTH = (AXI_DATA_WIDTH/8),
|
||||
parameter AXI_ID_WIDTH = 8,
|
||||
parameter AXI_MAX_BURST_LEN = 256,
|
||||
parameter PCIE_ADDR_WIDTH = 64,
|
||||
parameter PCIE_CLIENT_TAG = 1,
|
||||
parameter PCIE_TAG_COUNT = 32,
|
||||
parameter PCIE_TAG_WIDTH = $clog2(PCIE_TAG_COUNT),
|
||||
parameter PCIE_EXT_TAG_ENABLE = (PCIE_TAG_COUNT>32),
|
||||
parameter LEN_WIDTH = 20,
|
||||
parameter TAG_WIDTH = 8
|
||||
)
|
||||
(
|
||||
input wire clk,
|
||||
input wire rst,
|
||||
|
||||
/*
|
||||
* AXI input (RC)
|
||||
*/
|
||||
input wire [AXIS_PCIE_DATA_WIDTH-1:0] s_axis_rc_tdata,
|
||||
input wire [AXIS_PCIE_KEEP_WIDTH-1:0] s_axis_rc_tkeep,
|
||||
input wire s_axis_rc_tvalid,
|
||||
output wire s_axis_rc_tready,
|
||||
input wire s_axis_rc_tlast,
|
||||
input wire [74:0] s_axis_rc_tuser,
|
||||
|
||||
/*
|
||||
* AXI output (RQ)
|
||||
*/
|
||||
output wire [AXIS_PCIE_DATA_WIDTH-1:0] m_axis_rq_tdata,
|
||||
output wire [AXIS_PCIE_KEEP_WIDTH-1:0] m_axis_rq_tkeep,
|
||||
output wire m_axis_rq_tvalid,
|
||||
input wire m_axis_rq_tready,
|
||||
output wire m_axis_rq_tlast,
|
||||
output wire [59:0] m_axis_rq_tuser,
|
||||
|
||||
/*
|
||||
* Tag input
|
||||
*/
|
||||
input wire [PCIE_TAG_WIDTH-1:0] s_axis_pcie_rq_tag,
|
||||
input wire s_axis_pcie_rq_tag_valid,
|
||||
|
||||
/*
|
||||
* AXI read descriptor input
|
||||
*/
|
||||
input wire [PCIE_ADDR_WIDTH-1:0] s_axis_read_desc_pcie_addr,
|
||||
input wire [AXI_ADDR_WIDTH-1:0] s_axis_read_desc_axi_addr,
|
||||
input wire [LEN_WIDTH-1:0] s_axis_read_desc_len,
|
||||
input wire [TAG_WIDTH-1:0] s_axis_read_desc_tag,
|
||||
input wire s_axis_read_desc_valid,
|
||||
output wire s_axis_read_desc_ready,
|
||||
|
||||
/*
|
||||
* AXI read descriptor status output
|
||||
*/
|
||||
output wire [TAG_WIDTH-1:0] m_axis_read_desc_status_tag,
|
||||
output wire m_axis_read_desc_status_valid,
|
||||
|
||||
/*
|
||||
* AXI write descriptor input
|
||||
*/
|
||||
input wire [PCIE_ADDR_WIDTH-1:0] s_axis_write_desc_pcie_addr,
|
||||
input wire [AXI_ADDR_WIDTH-1:0] s_axis_write_desc_axi_addr,
|
||||
input wire [LEN_WIDTH-1:0] s_axis_write_desc_len,
|
||||
input wire [TAG_WIDTH-1:0] s_axis_write_desc_tag,
|
||||
input wire s_axis_write_desc_valid,
|
||||
output wire s_axis_write_desc_ready,
|
||||
|
||||
/*
|
||||
* AXI write descriptor status output
|
||||
*/
|
||||
output wire [TAG_WIDTH-1:0] m_axis_write_desc_status_tag,
|
||||
output wire m_axis_write_desc_status_valid,
|
||||
|
||||
/*
|
||||
* AXI master interface
|
||||
*/
|
||||
output wire [AXI_ID_WIDTH-1:0] m_axi_awid,
|
||||
output wire [AXI_ADDR_WIDTH-1:0] m_axi_awaddr,
|
||||
output wire [7:0] m_axi_awlen,
|
||||
output wire [2:0] m_axi_awsize,
|
||||
output wire [1:0] m_axi_awburst,
|
||||
output wire m_axi_awlock,
|
||||
output wire [3:0] m_axi_awcache,
|
||||
output wire [2:0] m_axi_awprot,
|
||||
output wire m_axi_awvalid,
|
||||
input wire m_axi_awready,
|
||||
output wire [AXI_DATA_WIDTH-1:0] m_axi_wdata,
|
||||
output wire [AXI_STRB_WIDTH-1:0] m_axi_wstrb,
|
||||
output wire m_axi_wlast,
|
||||
output wire m_axi_wvalid,
|
||||
input wire m_axi_wready,
|
||||
input wire [AXI_ID_WIDTH-1:0] m_axi_bid,
|
||||
input wire [1:0] m_axi_bresp,
|
||||
input wire m_axi_bvalid,
|
||||
output wire m_axi_bready,
|
||||
output wire [AXI_ID_WIDTH-1:0] m_axi_arid,
|
||||
output wire [AXI_ADDR_WIDTH-1:0] m_axi_araddr,
|
||||
output wire [7:0] m_axi_arlen,
|
||||
output wire [2:0] m_axi_arsize,
|
||||
output wire [1:0] m_axi_arburst,
|
||||
output wire m_axi_arlock,
|
||||
output wire [3:0] m_axi_arcache,
|
||||
output wire [2:0] m_axi_arprot,
|
||||
output wire m_axi_arvalid,
|
||||
input wire m_axi_arready,
|
||||
input wire [AXI_ID_WIDTH-1:0] m_axi_rid,
|
||||
input wire [AXI_DATA_WIDTH-1:0] m_axi_rdata,
|
||||
input wire [1:0] m_axi_rresp,
|
||||
input wire m_axi_rlast,
|
||||
input wire m_axi_rvalid,
|
||||
output wire m_axi_rready,
|
||||
|
||||
/*
|
||||
* Configuration
|
||||
*/
|
||||
input wire read_enable,
|
||||
input wire write_enable,
|
||||
input wire ext_tag_enable,
|
||||
input wire [15:0] requester_id,
|
||||
input wire requester_id_enable,
|
||||
input wire [2:0] max_read_request_size,
|
||||
input wire [2:0] max_payload_size,
|
||||
|
||||
/*
|
||||
* Status
|
||||
*/
|
||||
output wire status_error_cor,
|
||||
output wire status_error_uncor
|
||||
);
|
||||
|
||||
wire [AXIS_PCIE_DATA_WIDTH-1:0] axis_rq_tdata_read;
|
||||
wire [AXIS_PCIE_KEEP_WIDTH-1:0] axis_rq_tkeep_read;
|
||||
wire axis_rq_tvalid_read;
|
||||
wire axis_rq_tready_read;
|
||||
wire axis_rq_tlast_read;
|
||||
wire [59:0] axis_rq_tuser_read;
|
||||
|
||||
wire [AXIS_PCIE_DATA_WIDTH-1:0] axis_rq_tdata_write;
|
||||
wire [AXIS_PCIE_KEEP_WIDTH-1:0] axis_rq_tkeep_write;
|
||||
wire axis_rq_tvalid_write;
|
||||
wire axis_rq_tready_write;
|
||||
wire axis_rq_tlast_write;
|
||||
wire [59:0] axis_rq_tuser_write;
|
||||
|
||||
pcie_us_axi_dma_rd #(
|
||||
.AXIS_PCIE_DATA_WIDTH(AXIS_PCIE_DATA_WIDTH),
|
||||
.AXIS_PCIE_KEEP_WIDTH(AXIS_PCIE_KEEP_WIDTH),
|
||||
.AXI_DATA_WIDTH(AXI_DATA_WIDTH),
|
||||
.AXI_ADDR_WIDTH(AXI_ADDR_WIDTH),
|
||||
.AXI_STRB_WIDTH(AXI_STRB_WIDTH),
|
||||
.AXI_ID_WIDTH(AXI_ID_WIDTH),
|
||||
.AXI_MAX_BURST_LEN(AXI_MAX_BURST_LEN),
|
||||
.PCIE_ADDR_WIDTH(PCIE_ADDR_WIDTH),
|
||||
.PCIE_CLIENT_TAG(PCIE_CLIENT_TAG),
|
||||
.PCIE_TAG_COUNT(PCIE_TAG_COUNT),
|
||||
.PCIE_TAG_WIDTH(PCIE_TAG_WIDTH),
|
||||
.PCIE_EXT_TAG_ENABLE(PCIE_EXT_TAG_ENABLE),
|
||||
.LEN_WIDTH(LEN_WIDTH),
|
||||
.TAG_WIDTH(TAG_WIDTH)
|
||||
)
|
||||
pcie_us_axi_dma_rd_inst (
|
||||
.clk(clk),
|
||||
.rst(rst),
|
||||
|
||||
/*
|
||||
* AXI input (RC)
|
||||
*/
|
||||
.s_axis_rc_tdata(s_axis_rc_tdata),
|
||||
.s_axis_rc_tkeep(s_axis_rc_tkeep),
|
||||
.s_axis_rc_tvalid(s_axis_rc_tvalid),
|
||||
.s_axis_rc_tready(s_axis_rc_tready),
|
||||
.s_axis_rc_tlast(s_axis_rc_tlast),
|
||||
.s_axis_rc_tuser(s_axis_rc_tuser),
|
||||
|
||||
/*
|
||||
* AXI output (RQ)
|
||||
*/
|
||||
.m_axis_rq_tdata(axis_rq_tdata_read),
|
||||
.m_axis_rq_tkeep(axis_rq_tkeep_read),
|
||||
.m_axis_rq_tvalid(axis_rq_tvalid_read),
|
||||
.m_axis_rq_tready(axis_rq_tready_read),
|
||||
.m_axis_rq_tlast(axis_rq_tlast_read),
|
||||
.m_axis_rq_tuser(axis_rq_tuser_read),
|
||||
|
||||
/*
|
||||
* Tag input
|
||||
*/
|
||||
.s_axis_pcie_rq_tag(s_axis_pcie_rq_tag),
|
||||
.s_axis_pcie_rq_tag_valid(s_axis_pcie_rq_tag_valid),
|
||||
|
||||
/*
|
||||
* AXI read descriptor input
|
||||
*/
|
||||
.s_axis_read_desc_pcie_addr(s_axis_read_desc_pcie_addr),
|
||||
.s_axis_read_desc_axi_addr(s_axis_read_desc_axi_addr),
|
||||
.s_axis_read_desc_len(s_axis_read_desc_len),
|
||||
.s_axis_read_desc_tag(s_axis_read_desc_tag),
|
||||
.s_axis_read_desc_valid(s_axis_read_desc_valid),
|
||||
.s_axis_read_desc_ready(s_axis_read_desc_ready),
|
||||
|
||||
/*
|
||||
* AXI read descriptor status output
|
||||
*/
|
||||
.m_axis_read_desc_status_tag(m_axis_read_desc_status_tag),
|
||||
.m_axis_read_desc_status_valid(m_axis_read_desc_status_valid),
|
||||
|
||||
/*
|
||||
* AXI master interface
|
||||
*/
|
||||
.m_axi_awid(m_axi_awid),
|
||||
.m_axi_awaddr(m_axi_awaddr),
|
||||
.m_axi_awlen(m_axi_awlen),
|
||||
.m_axi_awsize(m_axi_awsize),
|
||||
.m_axi_awburst(m_axi_awburst),
|
||||
.m_axi_awlock(m_axi_awlock),
|
||||
.m_axi_awcache(m_axi_awcache),
|
||||
.m_axi_awprot(m_axi_awprot),
|
||||
.m_axi_awvalid(m_axi_awvalid),
|
||||
.m_axi_awready(m_axi_awready),
|
||||
.m_axi_wdata(m_axi_wdata),
|
||||
.m_axi_wstrb(m_axi_wstrb),
|
||||
.m_axi_wlast(m_axi_wlast),
|
||||
.m_axi_wvalid(m_axi_wvalid),
|
||||
.m_axi_wready(m_axi_wready),
|
||||
.m_axi_bid(m_axi_bid),
|
||||
.m_axi_bresp(m_axi_bresp),
|
||||
.m_axi_bvalid(m_axi_bvalid),
|
||||
.m_axi_bready(m_axi_bready),
|
||||
|
||||
/*
|
||||
* Configuration
|
||||
*/
|
||||
.enable(read_enable),
|
||||
.ext_tag_enable(ext_tag_enable),
|
||||
.requester_id(requester_id),
|
||||
.requester_id_enable(requester_id_enable),
|
||||
.max_read_request_size(max_read_request_size),
|
||||
|
||||
/*
|
||||
* Status
|
||||
*/
|
||||
.status_error_cor(status_error_cor),
|
||||
.status_error_uncor(status_error_uncor)
|
||||
);
|
||||
|
||||
pcie_us_axi_dma_wr #(
|
||||
.AXIS_PCIE_DATA_WIDTH(AXIS_PCIE_DATA_WIDTH),
|
||||
.AXIS_PCIE_KEEP_WIDTH(AXIS_PCIE_KEEP_WIDTH),
|
||||
.AXI_DATA_WIDTH(AXI_DATA_WIDTH),
|
||||
.AXI_ADDR_WIDTH(AXI_ADDR_WIDTH),
|
||||
.AXI_STRB_WIDTH(AXI_STRB_WIDTH),
|
||||
.AXI_ID_WIDTH(AXI_ID_WIDTH),
|
||||
.AXI_MAX_BURST_LEN(AXI_MAX_BURST_LEN),
|
||||
.PCIE_ADDR_WIDTH(PCIE_ADDR_WIDTH),
|
||||
.LEN_WIDTH(LEN_WIDTH),
|
||||
.TAG_WIDTH(TAG_WIDTH)
|
||||
)
|
||||
pcie_us_axi_dma_wr_inst (
|
||||
.clk(clk),
|
||||
.rst(rst),
|
||||
|
||||
/*
|
||||
* AXI output (RQ)
|
||||
*/
|
||||
.m_axis_rq_tdata(axis_rq_tdata_write),
|
||||
.m_axis_rq_tkeep(axis_rq_tkeep_write),
|
||||
.m_axis_rq_tvalid(axis_rq_tvalid_write),
|
||||
.m_axis_rq_tready(axis_rq_tready_write),
|
||||
.m_axis_rq_tlast(axis_rq_tlast_write),
|
||||
.m_axis_rq_tuser(axis_rq_tuser_write),
|
||||
|
||||
/*
|
||||
* AXI write descriptor input
|
||||
*/
|
||||
.s_axis_write_desc_pcie_addr(s_axis_write_desc_pcie_addr),
|
||||
.s_axis_write_desc_axi_addr(s_axis_write_desc_axi_addr),
|
||||
.s_axis_write_desc_len(s_axis_write_desc_len),
|
||||
.s_axis_write_desc_tag(s_axis_write_desc_tag),
|
||||
.s_axis_write_desc_valid(s_axis_write_desc_valid),
|
||||
.s_axis_write_desc_ready(s_axis_write_desc_ready),
|
||||
|
||||
/*
|
||||
* AXI write descriptor status output
|
||||
*/
|
||||
.m_axis_write_desc_status_tag(m_axis_write_desc_status_tag),
|
||||
.m_axis_write_desc_status_valid(m_axis_write_desc_status_valid),
|
||||
|
||||
/*
|
||||
* AXI master interface
|
||||
*/
|
||||
.m_axi_arid(m_axi_arid),
|
||||
.m_axi_araddr(m_axi_araddr),
|
||||
.m_axi_arlen(m_axi_arlen),
|
||||
.m_axi_arsize(m_axi_arsize),
|
||||
.m_axi_arburst(m_axi_arburst),
|
||||
.m_axi_arlock(m_axi_arlock),
|
||||
.m_axi_arcache(m_axi_arcache),
|
||||
.m_axi_arprot(m_axi_arprot),
|
||||
.m_axi_arvalid(m_axi_arvalid),
|
||||
.m_axi_arready(m_axi_arready),
|
||||
.m_axi_rid(m_axi_rid),
|
||||
.m_axi_rdata(m_axi_rdata),
|
||||
.m_axi_rresp(m_axi_rresp),
|
||||
.m_axi_rlast(m_axi_rlast),
|
||||
.m_axi_rvalid(m_axi_rvalid),
|
||||
.m_axi_rready(m_axi_rready),
|
||||
|
||||
/*
|
||||
* Configuration
|
||||
*/
|
||||
.enable(write_enable),
|
||||
.requester_id(requester_id),
|
||||
.requester_id_enable(requester_id_enable),
|
||||
.max_payload_size(max_payload_size)
|
||||
);
|
||||
|
||||
axis_arb_mux #(
|
||||
.S_COUNT(2),
|
||||
.DATA_WIDTH(AXIS_PCIE_DATA_WIDTH),
|
||||
.KEEP_ENABLE(1),
|
||||
.KEEP_WIDTH(AXIS_PCIE_KEEP_WIDTH),
|
||||
.ID_ENABLE(0),
|
||||
.DEST_ENABLE(0),
|
||||
.USER_ENABLE(1),
|
||||
.USER_WIDTH(60),
|
||||
.ARB_TYPE("PRIORITY"),
|
||||
.LSB_PRIORITY("HIGH")
|
||||
)
|
||||
request_mux_inst (
|
||||
.clk(clk),
|
||||
.rst(rst),
|
||||
.s_axis_tdata({axis_rq_tdata_write, axis_rq_tdata_read}),
|
||||
.s_axis_tkeep({axis_rq_tkeep_write, axis_rq_tkeep_read}),
|
||||
.s_axis_tvalid({axis_rq_tvalid_write, axis_rq_tvalid_read}),
|
||||
.s_axis_tready({axis_rq_tready_write, axis_rq_tready_read}),
|
||||
.s_axis_tlast({axis_rq_tlast_write, axis_rq_tlast_read}),
|
||||
.s_axis_tid(0),
|
||||
.s_axis_tdest(0),
|
||||
.s_axis_tuser({axis_rq_tuser_write, axis_rq_tuser_read}),
|
||||
.m_axis_tdata(m_axis_rq_tdata),
|
||||
.m_axis_tkeep(m_axis_rq_tkeep),
|
||||
.m_axis_tvalid(m_axis_rq_tvalid),
|
||||
.m_axis_tready(m_axis_rq_tready),
|
||||
.m_axis_tlast(m_axis_rq_tlast),
|
||||
.m_axis_tid(),
|
||||
.m_axis_tdest(),
|
||||
.m_axis_tuser(m_axis_rq_tuser)
|
||||
);
|
||||
|
||||
endmodule
|
1319
fpga/lib/pcie/rtl/pcie_us_axi_dma_rd.v
Normal file
1319
fpga/lib/pcie/rtl/pcie_us_axi_dma_rd.v
Normal file
File diff suppressed because it is too large
Load Diff
858
fpga/lib/pcie/rtl/pcie_us_axi_dma_wr.v
Normal file
858
fpga/lib/pcie/rtl/pcie_us_axi_dma_wr.v
Normal file
@ -0,0 +1,858 @@
|
||||
/*
|
||||
|
||||
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
|
||||
|
||||
/*
|
||||
* Ultrascale PCIe AXI DMA Write
|
||||
*/
|
||||
module pcie_us_axi_dma_wr #
|
||||
(
|
||||
parameter AXIS_PCIE_DATA_WIDTH = 256,
|
||||
parameter AXIS_PCIE_KEEP_WIDTH = (AXIS_PCIE_DATA_WIDTH/32),
|
||||
parameter AXI_DATA_WIDTH = AXIS_PCIE_DATA_WIDTH,
|
||||
parameter AXI_ADDR_WIDTH = 64,
|
||||
parameter AXI_STRB_WIDTH = (AXI_DATA_WIDTH/8),
|
||||
parameter AXI_ID_WIDTH = 8,
|
||||
parameter AXI_MAX_BURST_LEN = 256,
|
||||
parameter PCIE_ADDR_WIDTH = 64,
|
||||
parameter LEN_WIDTH = 20,
|
||||
parameter TAG_WIDTH = 8
|
||||
)
|
||||
(
|
||||
input wire clk,
|
||||
input wire rst,
|
||||
|
||||
/*
|
||||
* AXI output (RQ)
|
||||
*/
|
||||
output wire [AXIS_PCIE_DATA_WIDTH-1:0] m_axis_rq_tdata,
|
||||
output wire [AXIS_PCIE_KEEP_WIDTH-1:0] m_axis_rq_tkeep,
|
||||
output wire m_axis_rq_tvalid,
|
||||
input wire m_axis_rq_tready,
|
||||
output wire m_axis_rq_tlast,
|
||||
output wire [59:0] m_axis_rq_tuser,
|
||||
|
||||
/*
|
||||
* AXI write descriptor input
|
||||
*/
|
||||
input wire [PCIE_ADDR_WIDTH-1:0] s_axis_write_desc_pcie_addr,
|
||||
input wire [AXI_ADDR_WIDTH-1:0] s_axis_write_desc_axi_addr,
|
||||
input wire [LEN_WIDTH-1:0] s_axis_write_desc_len,
|
||||
input wire [TAG_WIDTH-1:0] s_axis_write_desc_tag,
|
||||
input wire s_axis_write_desc_valid,
|
||||
output wire s_axis_write_desc_ready,
|
||||
|
||||
/*
|
||||
* AXI write descriptor status output
|
||||
*/
|
||||
output wire [TAG_WIDTH-1:0] m_axis_write_desc_status_tag,
|
||||
output wire m_axis_write_desc_status_valid,
|
||||
|
||||
/*
|
||||
* AXI master interface
|
||||
*/
|
||||
output wire [AXI_ID_WIDTH-1:0] m_axi_arid,
|
||||
output wire [AXI_ADDR_WIDTH-1:0] m_axi_araddr,
|
||||
output wire [7:0] m_axi_arlen,
|
||||
output wire [2:0] m_axi_arsize,
|
||||
output wire [1:0] m_axi_arburst,
|
||||
output wire m_axi_arlock,
|
||||
output wire [3:0] m_axi_arcache,
|
||||
output wire [2:0] m_axi_arprot,
|
||||
output wire m_axi_arvalid,
|
||||
input wire m_axi_arready,
|
||||
input wire [AXI_ID_WIDTH-1:0] m_axi_rid,
|
||||
input wire [AXI_DATA_WIDTH-1:0] m_axi_rdata,
|
||||
input wire [1:0] m_axi_rresp,
|
||||
input wire m_axi_rlast,
|
||||
input wire m_axi_rvalid,
|
||||
output wire m_axi_rready,
|
||||
|
||||
/*
|
||||
* Configuration
|
||||
*/
|
||||
input wire enable,
|
||||
input wire [15:0] requester_id,
|
||||
input wire requester_id_enable,
|
||||
input wire [2:0] max_payload_size
|
||||
);
|
||||
|
||||
parameter AXI_WORD_WIDTH = AXI_STRB_WIDTH;
|
||||
parameter AXI_WORD_SIZE = AXI_DATA_WIDTH/AXI_WORD_WIDTH;
|
||||
parameter AXI_BURST_SIZE = $clog2(AXI_STRB_WIDTH);
|
||||
parameter AXI_MAX_BURST_SIZE = AXI_MAX_BURST_LEN*AXI_WORD_WIDTH;
|
||||
|
||||
parameter AXIS_PCIE_WORD_WIDTH = AXIS_PCIE_KEEP_WIDTH;
|
||||
parameter AXIS_PCIE_WORD_SIZE = AXIS_PCIE_DATA_WIDTH/AXIS_PCIE_WORD_WIDTH;
|
||||
|
||||
parameter OFFSET_WIDTH = $clog2(AXI_DATA_WIDTH/8);
|
||||
parameter WORD_LEN_WIDTH = LEN_WIDTH - $clog2(AXIS_PCIE_KEEP_WIDTH);
|
||||
parameter CYCLE_COUNT_WIDTH = 13-AXI_BURST_SIZE;
|
||||
|
||||
// bus width assertions
|
||||
initial begin
|
||||
if (AXIS_PCIE_DATA_WIDTH != 64 && AXIS_PCIE_DATA_WIDTH != 128 && AXIS_PCIE_DATA_WIDTH != 256) begin
|
||||
$error("Error: PCIe interface width must be 64, 128, or 256");
|
||||
$finish;
|
||||
end
|
||||
|
||||
if (AXIS_PCIE_KEEP_WIDTH * 32 != AXIS_PCIE_DATA_WIDTH) begin
|
||||
$error("Error: PCIe interface requires dword (32-bit) granularity");
|
||||
$finish;
|
||||
end
|
||||
|
||||
if (AXI_DATA_WIDTH != AXIS_PCIE_DATA_WIDTH) begin
|
||||
$error("Error: AXI interface width must match PCIe interface width");
|
||||
$finish;
|
||||
end
|
||||
|
||||
if (AXI_STRB_WIDTH * 8 != AXI_DATA_WIDTH) begin
|
||||
$error("Error: AXI interface requires byte (8-bit) granularity");
|
||||
$finish;
|
||||
end
|
||||
|
||||
if (AXI_MAX_BURST_LEN < 1 || AXI_MAX_BURST_LEN > 256) begin
|
||||
$error("Error: AXI_MAX_BURST_LEN must be between 1 and 256");
|
||||
$finish;
|
||||
end
|
||||
end
|
||||
|
||||
localparam [3:0]
|
||||
REQ_MEM_READ = 4'b0000,
|
||||
REQ_MEM_WRITE = 4'b0001,
|
||||
REQ_IO_READ = 4'b0010,
|
||||
REQ_IO_WRITE = 4'b0011,
|
||||
REQ_MEM_FETCH_ADD = 4'b0100,
|
||||
REQ_MEM_SWAP = 4'b0101,
|
||||
REQ_MEM_CAS = 4'b0110,
|
||||
REQ_MEM_READ_LOCKED = 4'b0111,
|
||||
REQ_CFG_READ_0 = 4'b1000,
|
||||
REQ_CFG_READ_1 = 4'b1001,
|
||||
REQ_CFG_WRITE_0 = 4'b1010,
|
||||
REQ_CFG_WRITE_1 = 4'b1011,
|
||||
REQ_MSG = 4'b1100,
|
||||
REQ_MSG_VENDOR = 4'b1101,
|
||||
REQ_MSG_ATS = 4'b1110;
|
||||
|
||||
localparam [2:0]
|
||||
CPL_STATUS_SC = 3'b000, // successful completion
|
||||
CPL_STATUS_UR = 3'b001, // unsupported request
|
||||
CPL_STATUS_CRS = 3'b010, // configuration request retry status
|
||||
CPL_STATUS_CA = 3'b100; // completer abort
|
||||
|
||||
localparam [1:0]
|
||||
AXI_STATE_IDLE = 2'd0,
|
||||
AXI_STATE_START = 2'd1,
|
||||
AXI_STATE_REQ = 2'd2;
|
||||
|
||||
reg [1:0] axi_state_reg = AXI_STATE_IDLE, axi_state_next;
|
||||
|
||||
localparam [1:0]
|
||||
TLP_STATE_IDLE = 2'd0,
|
||||
TLP_STATE_HEADER_1 = 2'd1,
|
||||
TLP_STATE_HEADER_2 = 2'd2,
|
||||
TLP_STATE_TRANSFER = 2'd3;
|
||||
|
||||
reg [1:0] tlp_state_reg = TLP_STATE_IDLE, tlp_state_next;
|
||||
|
||||
// datapath control signals
|
||||
reg transfer_in_save;
|
||||
|
||||
reg tlp_cmd_ready;
|
||||
|
||||
reg [PCIE_ADDR_WIDTH-1:0] pcie_addr_reg = {PCIE_ADDR_WIDTH{1'b0}}, pcie_addr_next;
|
||||
reg [AXI_ADDR_WIDTH-1:0] axi_addr_reg = {AXI_ADDR_WIDTH{1'b0}}, axi_addr_next;
|
||||
reg [LEN_WIDTH-1:0] op_count_reg = {LEN_WIDTH{1'b0}}, op_count_next;
|
||||
reg [LEN_WIDTH-1:0] tr_count_reg = {LEN_WIDTH{1'b0}}, tr_count_next;
|
||||
reg [LEN_WIDTH-1:0] tlp_count_reg = {LEN_WIDTH{1'b0}}, tlp_count_next;
|
||||
|
||||
reg [PCIE_ADDR_WIDTH-1:0] tlp_addr_reg = {PCIE_ADDR_WIDTH{1'b0}}, tlp_addr_next;
|
||||
reg [11:0] tlp_len_reg = 12'd0, tlp_len_next;
|
||||
reg [OFFSET_WIDTH-1:0] offset_reg = {OFFSET_WIDTH{1'b0}}, offset_next;
|
||||
reg [9:0] dword_count_reg = 10'd0, dword_count_next;
|
||||
reg [CYCLE_COUNT_WIDTH-1:0] input_cycle_count_reg = {CYCLE_COUNT_WIDTH{1'b0}}, input_cycle_count_next;
|
||||
reg [CYCLE_COUNT_WIDTH-1:0] output_cycle_count_reg = {CYCLE_COUNT_WIDTH{1'b0}}, output_cycle_count_next;
|
||||
reg input_active_reg = 1'b0, input_active_next;
|
||||
reg bubble_cycle_reg = 1'b0, bubble_cycle_next;
|
||||
reg last_cycle_reg = 1'b0, last_cycle_next;
|
||||
reg last_tlp_reg = 1'b0, last_tlp_next;
|
||||
reg [TAG_WIDTH-1:0] tag_reg = {TAG_WIDTH{1'b0}}, tag_next;
|
||||
|
||||
reg [PCIE_ADDR_WIDTH-1:0] tlp_cmd_addr_reg = {PCIE_ADDR_WIDTH{1'b0}}, tlp_cmd_addr_next;
|
||||
reg [11:0] tlp_cmd_len_reg = 12'd0, tlp_cmd_len_next;
|
||||
reg [9:0] tlp_cmd_dword_len_reg = 10'd0, tlp_cmd_dword_len_next;
|
||||
reg [CYCLE_COUNT_WIDTH-1:0] tlp_cmd_input_cycle_len_reg = {CYCLE_COUNT_WIDTH{1'b0}}, tlp_cmd_input_cycle_len_next;
|
||||
reg [CYCLE_COUNT_WIDTH-1:0] tlp_cmd_output_cycle_len_reg = {CYCLE_COUNT_WIDTH{1'b0}}, tlp_cmd_output_cycle_len_next;
|
||||
reg [OFFSET_WIDTH-1:0] tlp_cmd_offset_reg = {OFFSET_WIDTH{1'b0}}, tlp_cmd_offset_next;
|
||||
reg [TAG_WIDTH-1:0] tlp_cmd_tag_reg = {TAG_WIDTH{1'b0}}, tlp_cmd_tag_next;
|
||||
reg tlp_cmd_bubble_cycle_reg = 1'b0, tlp_cmd_bubble_cycle_next;
|
||||
reg tlp_cmd_last_reg = 1'b0, tlp_cmd_last_next;
|
||||
reg tlp_cmd_valid_reg = 1'b0, tlp_cmd_valid_next;
|
||||
|
||||
reg [10:0] max_payload_size_dw_reg = 11'd0;
|
||||
|
||||
reg s_axis_write_desc_ready_reg = 1'b0, s_axis_write_desc_ready_next;
|
||||
|
||||
reg [TAG_WIDTH-1:0] m_axis_write_desc_status_tag_reg = {TAG_WIDTH{1'b0}}, m_axis_write_desc_status_tag_next;
|
||||
reg m_axis_write_desc_status_valid_reg = 1'b0, m_axis_write_desc_status_valid_next;
|
||||
|
||||
reg [AXI_ADDR_WIDTH-1:0] m_axi_araddr_reg = {AXI_ADDR_WIDTH{1'b0}}, m_axi_araddr_next;
|
||||
reg [7:0] m_axi_arlen_reg = 8'd0, m_axi_arlen_next;
|
||||
reg m_axi_arvalid_reg = 1'b0, m_axi_arvalid_next;
|
||||
reg m_axi_rready_reg = 1'b0, m_axi_rready_next;
|
||||
|
||||
reg [AXI_DATA_WIDTH-1:0] save_axi_rdata_reg = {AXI_DATA_WIDTH{1'b0}};
|
||||
|
||||
wire [AXI_DATA_WIDTH-1:0] shift_axi_rdata = {m_axi_rdata, save_axi_rdata_reg} >> ((AXI_STRB_WIDTH-offset_reg)*AXI_WORD_SIZE);
|
||||
|
||||
// internal datapath
|
||||
reg [AXIS_PCIE_DATA_WIDTH-1:0] m_axis_rq_tdata_int;
|
||||
reg [AXIS_PCIE_KEEP_WIDTH-1:0] m_axis_rq_tkeep_int;
|
||||
reg m_axis_rq_tvalid_int;
|
||||
reg m_axis_rq_tready_int_reg = 1'b0;
|
||||
reg m_axis_rq_tlast_int;
|
||||
reg [59:0] m_axis_rq_tuser_int;
|
||||
wire m_axis_rq_tready_int_early;
|
||||
|
||||
assign s_axis_write_desc_ready = s_axis_write_desc_ready_reg;
|
||||
|
||||
assign m_axis_write_desc_status_tag = m_axis_write_desc_status_tag_reg;
|
||||
assign m_axis_write_desc_status_valid = m_axis_write_desc_status_valid_reg;
|
||||
|
||||
assign m_axi_arid = {AXI_ID_WIDTH{1'b0}};
|
||||
assign m_axi_araddr = m_axi_araddr_reg;
|
||||
assign m_axi_arlen = m_axi_arlen_reg;
|
||||
assign m_axi_arsize = AXI_BURST_SIZE;
|
||||
assign m_axi_arburst = 2'b01;
|
||||
assign m_axi_arlock = 1'b0;
|
||||
assign m_axi_arcache = 4'b0011;
|
||||
assign m_axi_arprot = 3'b010;
|
||||
assign m_axi_arvalid = m_axi_arvalid_reg;
|
||||
assign m_axi_rready = m_axi_rready_reg;
|
||||
|
||||
wire [PCIE_ADDR_WIDTH-1:0] pcie_addr_plus_max_payload = pcie_addr_reg + {max_payload_size_dw_reg, 2'b00};
|
||||
wire [PCIE_ADDR_WIDTH-1:0] pcie_addr_plus_op_count = pcie_addr_reg + op_count_reg;
|
||||
wire [PCIE_ADDR_WIDTH-1:0] pcie_addr_plus_tlp_count = pcie_addr_reg + tlp_count_reg;
|
||||
|
||||
wire [AXI_ADDR_WIDTH-1:0] axi_addr_plus_max_burst = axi_addr_reg + AXI_MAX_BURST_SIZE;
|
||||
wire [AXI_ADDR_WIDTH-1:0] axi_addr_plus_op_count = axi_addr_reg + op_count_reg;
|
||||
wire [AXI_ADDR_WIDTH-1:0] axi_addr_plus_tlp_count = axi_addr_reg + tlp_count_reg;
|
||||
|
||||
always @* begin
|
||||
axi_state_next = AXI_STATE_IDLE;
|
||||
|
||||
s_axis_write_desc_ready_next = 1'b0;
|
||||
|
||||
m_axi_araddr_next = m_axi_araddr_reg;
|
||||
m_axi_arlen_next = m_axi_arlen_reg;
|
||||
m_axi_arvalid_next = m_axi_arvalid_reg && !m_axi_arready;
|
||||
|
||||
pcie_addr_next = pcie_addr_reg;
|
||||
axi_addr_next = axi_addr_reg;
|
||||
op_count_next = op_count_reg;
|
||||
tr_count_next = tr_count_reg;
|
||||
tlp_count_next = tlp_count_reg;
|
||||
|
||||
tlp_cmd_addr_next = tlp_cmd_addr_reg;
|
||||
tlp_cmd_len_next = tlp_cmd_len_reg;
|
||||
tlp_cmd_dword_len_next = tlp_cmd_dword_len_reg;
|
||||
tlp_cmd_input_cycle_len_next = tlp_cmd_input_cycle_len_reg;
|
||||
tlp_cmd_output_cycle_len_next = tlp_cmd_output_cycle_len_reg;
|
||||
tlp_cmd_offset_next = tlp_cmd_offset_reg;
|
||||
tlp_cmd_tag_next = tlp_cmd_tag_reg;
|
||||
tlp_cmd_bubble_cycle_next = tlp_cmd_bubble_cycle_reg;
|
||||
tlp_cmd_last_next = tlp_cmd_last_reg;
|
||||
tlp_cmd_valid_next = tlp_cmd_valid_reg && !tlp_cmd_ready;
|
||||
|
||||
// TLP segmentation and AXI read request generation
|
||||
case (axi_state_reg)
|
||||
AXI_STATE_IDLE: begin
|
||||
// idle state, wait for incoming descriptor
|
||||
s_axis_write_desc_ready_next = !tlp_cmd_valid_reg && enable;
|
||||
|
||||
if (s_axis_write_desc_ready & s_axis_write_desc_valid) begin
|
||||
s_axis_write_desc_ready_next = 1'b0;
|
||||
pcie_addr_next = s_axis_write_desc_pcie_addr;
|
||||
axi_addr_next = s_axis_write_desc_axi_addr;
|
||||
op_count_next = s_axis_write_desc_len;
|
||||
tlp_cmd_tag_next = s_axis_write_desc_tag;
|
||||
axi_state_next = AXI_STATE_START;
|
||||
end else begin
|
||||
axi_state_next = AXI_STATE_IDLE;
|
||||
end
|
||||
end
|
||||
AXI_STATE_START: begin
|
||||
// start state, compute TLP length
|
||||
if (!tlp_cmd_valid_reg) begin
|
||||
if (op_count_reg <= {max_payload_size_dw_reg, 2'b00}-pcie_addr_reg[1:0]) begin
|
||||
// packet smaller than max payload size
|
||||
if (pcie_addr_reg[12] != pcie_addr_plus_op_count[12]) begin
|
||||
// crosses 4k boundary
|
||||
tlp_count_next = 13'h1000 - pcie_addr_reg[11:0];
|
||||
end else begin
|
||||
// does not cross 4k boundary, send one TLP
|
||||
tlp_count_next = op_count_reg;
|
||||
end
|
||||
end else begin
|
||||
// packet larger than max payload size
|
||||
if (pcie_addr_reg[12] != pcie_addr_plus_max_payload[12]) begin
|
||||
// crosses 4k boundary
|
||||
tlp_count_next = 13'h1000 - pcie_addr_reg[11:0];
|
||||
end else begin
|
||||
// does not cross 4k boundary, send one TLP
|
||||
tlp_count_next = {max_payload_size_dw_reg, 2'b00}-pcie_addr_reg[1:0];
|
||||
end
|
||||
end
|
||||
|
||||
tlp_cmd_input_cycle_len_next = (tlp_count_next + axi_addr_reg[OFFSET_WIDTH-1:0] - 1) >> AXI_BURST_SIZE;
|
||||
if (AXIS_PCIE_DATA_WIDTH == 256) begin
|
||||
tlp_cmd_output_cycle_len_next = (tlp_count_next + 16+pcie_addr_reg[1:0] - 1) >> AXI_BURST_SIZE;
|
||||
end else begin
|
||||
tlp_cmd_output_cycle_len_next = (tlp_count_next + pcie_addr_reg[1:0] - 1) >> AXI_BURST_SIZE;
|
||||
end
|
||||
|
||||
pcie_addr_next = pcie_addr_reg + tlp_count_next;
|
||||
op_count_next = op_count_reg - tlp_count_next;
|
||||
|
||||
tlp_cmd_addr_next = pcie_addr_reg;
|
||||
tlp_cmd_len_next = tlp_count_next;
|
||||
tlp_cmd_dword_len_next = (tlp_count_next + pcie_addr_reg[1:0] + 3) >> 2;
|
||||
if (AXIS_PCIE_DATA_WIDTH == 256) begin
|
||||
tlp_cmd_offset_next = 16+pcie_addr_reg[1:0]-axi_addr_reg[OFFSET_WIDTH-1:0];
|
||||
tlp_cmd_bubble_cycle_next = axi_addr_reg[OFFSET_WIDTH-1:0] > 16+pcie_addr_reg[1:0];
|
||||
end else begin
|
||||
tlp_cmd_offset_next = pcie_addr_reg[1:0]-axi_addr_reg[OFFSET_WIDTH-1:0];
|
||||
tlp_cmd_bubble_cycle_next = axi_addr_reg[OFFSET_WIDTH-1:0] > pcie_addr_reg[1:0];
|
||||
end
|
||||
tlp_cmd_last_next = op_count_next == 0;
|
||||
tlp_cmd_valid_next = 1'b1;
|
||||
|
||||
axi_state_next = AXI_STATE_REQ;
|
||||
end else begin
|
||||
axi_state_next = AXI_STATE_START;
|
||||
end
|
||||
end
|
||||
AXI_STATE_REQ: begin
|
||||
// request state, generate AXI read requests
|
||||
if (!m_axi_arvalid) begin
|
||||
if (tlp_count_reg <= AXI_MAX_BURST_SIZE-axi_addr_reg[1:0]) begin
|
||||
// packet smaller than max burst size
|
||||
if (axi_addr_reg[12] != axi_addr_plus_tlp_count[12]) begin
|
||||
// crosses 4k boundary
|
||||
tr_count_next = 13'h1000 - axi_addr_reg[11:0];
|
||||
end else begin
|
||||
// does not cross 4k boundary, send one request
|
||||
tr_count_next = tlp_count_reg;
|
||||
end
|
||||
end else begin
|
||||
// packet larger than max burst size
|
||||
if (axi_addr_reg[12] != axi_addr_plus_max_burst[12]) begin
|
||||
// crosses 4k boundary
|
||||
tr_count_next = 13'h1000 - axi_addr_reg[11:0];
|
||||
end else begin
|
||||
// does not cross 4k boundary, send one request
|
||||
tr_count_next = AXI_MAX_BURST_SIZE - axi_addr_reg[OFFSET_WIDTH-1:0];
|
||||
end
|
||||
end
|
||||
|
||||
m_axi_araddr_next = axi_addr_reg;
|
||||
m_axi_arlen_next = (tr_count_next + axi_addr_reg[OFFSET_WIDTH-1:0] - 1) >> AXI_BURST_SIZE;
|
||||
m_axi_arvalid_next = 1;
|
||||
|
||||
axi_addr_next = axi_addr_reg + tr_count_next;
|
||||
tlp_count_next = tlp_count_reg - tr_count_next;
|
||||
|
||||
if (tlp_count_next != 0) begin
|
||||
axi_state_next = AXI_STATE_REQ;
|
||||
end else if (op_count_next != 0) begin
|
||||
axi_state_next = AXI_STATE_START;
|
||||
end else begin
|
||||
s_axis_write_desc_ready_next = !tlp_cmd_valid_reg && enable;
|
||||
axi_state_next = AXI_STATE_IDLE;
|
||||
end
|
||||
end else begin
|
||||
axi_state_next = AXI_STATE_REQ;
|
||||
end
|
||||
end
|
||||
endcase
|
||||
end
|
||||
|
||||
wire [3:0] first_be = 4'b1111 << tlp_addr_reg[1:0];
|
||||
wire [3:0] last_be = 4'b1111 >> (3 - ((tlp_addr_reg[1:0] + tlp_len_reg[1:0] - 1) & 3));
|
||||
|
||||
always @* begin
|
||||
tlp_state_next = TLP_STATE_IDLE;
|
||||
|
||||
transfer_in_save = 1'b0;
|
||||
|
||||
tlp_cmd_ready = 1'b0;
|
||||
|
||||
m_axis_write_desc_status_tag_next = m_axis_write_desc_status_tag_reg;
|
||||
m_axis_write_desc_status_valid_next = 1'b0;
|
||||
|
||||
m_axi_rready_next = 1'b0;
|
||||
|
||||
tlp_addr_next = tlp_addr_reg;
|
||||
tlp_len_next = tlp_len_reg;
|
||||
dword_count_next = dword_count_reg;
|
||||
offset_next = offset_reg;
|
||||
input_cycle_count_next = input_cycle_count_reg;
|
||||
output_cycle_count_next = output_cycle_count_reg;
|
||||
input_active_next = input_active_reg;
|
||||
bubble_cycle_next = bubble_cycle_reg;
|
||||
last_cycle_next = last_cycle_reg;
|
||||
last_tlp_next = last_tlp_reg;
|
||||
tag_next = tag_reg;
|
||||
|
||||
m_axis_rq_tdata_int = {AXIS_PCIE_DATA_WIDTH{1'b0}};
|
||||
m_axis_rq_tkeep_int = {AXIS_PCIE_KEEP_WIDTH{1'b0}};
|
||||
m_axis_rq_tvalid_int = 1'b0;
|
||||
m_axis_rq_tlast_int = 1'b0;
|
||||
m_axis_rq_tuser_int = 60'd0;
|
||||
|
||||
m_axis_rq_tdata_int[1:0] = 2'b0; // address type
|
||||
m_axis_rq_tdata_int[63:2] = tlp_addr_reg[PCIE_ADDR_WIDTH-1:2]; // address
|
||||
if (AXIS_PCIE_DATA_WIDTH > 64) begin
|
||||
m_axis_rq_tdata_int[74:64] = dword_count_reg; // DWORD count
|
||||
m_axis_rq_tdata_int[78:75] = REQ_MEM_WRITE; // request type - memory write
|
||||
m_axis_rq_tdata_int[79] = 1'b0; // poisoned request
|
||||
m_axis_rq_tdata_int[95:80] = requester_id;
|
||||
m_axis_rq_tdata_int[103:96] = 8'd0; // tag
|
||||
m_axis_rq_tdata_int[119:104] = 16'd0; // completer ID
|
||||
m_axis_rq_tdata_int[120] = requester_id_enable; // requester ID enable
|
||||
m_axis_rq_tdata_int[123:121] = 3'b000; // traffic class
|
||||
m_axis_rq_tdata_int[126:124] = 3'b000; // attr
|
||||
m_axis_rq_tdata_int[127] = 1'b0; // force ECRC
|
||||
end
|
||||
|
||||
if (AXIS_PCIE_DATA_WIDTH == 256) begin
|
||||
m_axis_rq_tkeep_int = 8'b00001111;
|
||||
end else if (AXIS_PCIE_DATA_WIDTH == 128) begin
|
||||
m_axis_rq_tkeep_int = 4'b1111;
|
||||
end else if (AXIS_PCIE_DATA_WIDTH == 64) begin
|
||||
m_axis_rq_tkeep_int = 2'b11;
|
||||
end
|
||||
|
||||
m_axis_rq_tuser_int[3:0] = dword_count_reg == 1 ? first_be & last_be : first_be; // first BE
|
||||
m_axis_rq_tuser_int[7:4] = dword_count_reg == 1 ? 4'b0000 : last_be; // last BE
|
||||
m_axis_rq_tuser_int[10:8] = 3'd0; // addr_offset
|
||||
m_axis_rq_tuser_int[11] = 1'b0; // discontinue
|
||||
m_axis_rq_tuser_int[12] = 1'b0; // tph_present
|
||||
m_axis_rq_tuser_int[14:13] = 2'b00; // tph_type
|
||||
m_axis_rq_tuser_int[15] = 1'b0; // tph_indirect_tag_en
|
||||
m_axis_rq_tuser_int[23:16] = 8'd0; // tph_st_tag
|
||||
m_axis_rq_tuser_int[27:24] = 4'd0; // seq_num
|
||||
m_axis_rq_tuser_int[59:28] = 32'd0; // parity
|
||||
|
||||
// AXI read response processing and TLP generation
|
||||
case (tlp_state_reg)
|
||||
TLP_STATE_IDLE: begin
|
||||
// idle state, wait for command
|
||||
m_axi_rready_next = 1'b0;
|
||||
|
||||
tlp_addr_next = tlp_cmd_addr_reg;
|
||||
tlp_len_next = tlp_cmd_len_reg;
|
||||
dword_count_next = tlp_cmd_dword_len_reg;
|
||||
offset_next = tlp_cmd_offset_reg;
|
||||
input_cycle_count_next = tlp_cmd_input_cycle_len_reg;
|
||||
output_cycle_count_next = tlp_cmd_output_cycle_len_reg;
|
||||
input_active_next = 1'b1;
|
||||
bubble_cycle_next = tlp_cmd_bubble_cycle_reg;
|
||||
last_cycle_next = tlp_cmd_output_cycle_len_reg == 0;
|
||||
last_tlp_next = tlp_cmd_last_reg;
|
||||
tag_next = tlp_cmd_tag_reg;
|
||||
|
||||
if (tlp_cmd_valid_reg) begin
|
||||
tlp_cmd_ready = 1'b1;
|
||||
if (AXIS_PCIE_DATA_WIDTH == 256) begin
|
||||
m_axi_rready_next = m_axis_rq_tready_int_early;
|
||||
end else if (AXIS_PCIE_DATA_WIDTH == 128) begin
|
||||
m_axi_rready_next = m_axis_rq_tready_int_early && bubble_cycle_next;
|
||||
end else begin
|
||||
m_axi_rready_next = 1'b0;
|
||||
end
|
||||
tlp_state_next = TLP_STATE_HEADER_1;
|
||||
end else begin
|
||||
tlp_state_next = TLP_STATE_IDLE;
|
||||
end
|
||||
end
|
||||
TLP_STATE_HEADER_1: begin
|
||||
// header 1 state, send TLP header
|
||||
if (AXIS_PCIE_DATA_WIDTH == 256) begin
|
||||
m_axi_rready_next = m_axis_rq_tready_int_early && input_active_reg;
|
||||
|
||||
if (m_axis_rq_tready_int_reg && ((m_axi_rready && m_axi_rvalid) || !input_active_reg)) begin
|
||||
transfer_in_save = m_axi_rready && m_axi_rvalid;
|
||||
|
||||
if (bubble_cycle_reg) begin
|
||||
if (input_active_reg) begin
|
||||
input_cycle_count_next = input_cycle_count_reg - 1;
|
||||
input_active_next = input_cycle_count_reg != 0;
|
||||
end
|
||||
bubble_cycle_next = 1'b0;
|
||||
m_axi_rready_next = m_axis_rq_tready_int_early && input_active_next;
|
||||
tlp_state_next = TLP_STATE_HEADER_1;
|
||||
end else begin
|
||||
dword_count_next = dword_count_reg - 4;
|
||||
if (input_active_reg) begin
|
||||
input_cycle_count_next = input_cycle_count_reg - 1;
|
||||
input_active_next = input_cycle_count_reg != 0;
|
||||
end
|
||||
output_cycle_count_next = output_cycle_count_reg - 1;
|
||||
last_cycle_next = output_cycle_count_next == 0;
|
||||
|
||||
m_axis_rq_tdata_int[255:128] = shift_axi_rdata[255:128];
|
||||
m_axis_rq_tvalid_int = 1'b1;
|
||||
if (dword_count_reg >= 4) begin
|
||||
m_axis_rq_tkeep_int = 8'b11111111;
|
||||
end else begin
|
||||
m_axis_rq_tkeep_int = 8'b11111111 >> (4 - dword_count_reg);
|
||||
end
|
||||
|
||||
if (last_cycle_reg) begin
|
||||
m_axis_rq_tlast_int = 1'b1;
|
||||
if (last_tlp_reg) begin
|
||||
m_axis_write_desc_status_tag_next = tag_reg;
|
||||
m_axis_write_desc_status_valid_next = 1'b1;
|
||||
end
|
||||
|
||||
// skip idle state if possible
|
||||
tlp_addr_next = tlp_cmd_addr_reg;
|
||||
tlp_len_next = tlp_cmd_len_reg;
|
||||
dword_count_next = tlp_cmd_dword_len_reg;
|
||||
offset_next = tlp_cmd_offset_reg;
|
||||
input_cycle_count_next = tlp_cmd_input_cycle_len_reg;
|
||||
output_cycle_count_next = tlp_cmd_output_cycle_len_reg;
|
||||
input_active_next = 1'b1;
|
||||
bubble_cycle_next = tlp_cmd_bubble_cycle_reg;
|
||||
last_cycle_next = tlp_cmd_output_cycle_len_reg == 0;
|
||||
last_tlp_next = tlp_cmd_last_reg;
|
||||
tag_next = tlp_cmd_tag_reg;
|
||||
|
||||
if (tlp_cmd_valid_reg) begin
|
||||
tlp_cmd_ready = 1'b1;
|
||||
if (AXIS_PCIE_DATA_WIDTH == 256) begin
|
||||
m_axi_rready_next = m_axis_rq_tready_int_early;
|
||||
end else if (AXIS_PCIE_DATA_WIDTH == 128) begin
|
||||
m_axi_rready_next = m_axis_rq_tready_int_early && bubble_cycle_next;
|
||||
end else begin
|
||||
m_axi_rready_next = 1'b0;
|
||||
end
|
||||
tlp_state_next = TLP_STATE_HEADER_1;
|
||||
end else begin
|
||||
m_axi_rready_next = 0;
|
||||
tlp_state_next = TLP_STATE_IDLE;
|
||||
end
|
||||
end else begin
|
||||
m_axi_rready_next = m_axis_rq_tready_int_early && input_active_next;
|
||||
tlp_state_next = TLP_STATE_TRANSFER;
|
||||
end
|
||||
end
|
||||
end else begin
|
||||
tlp_state_next = TLP_STATE_HEADER_1;
|
||||
end
|
||||
end else begin
|
||||
if (m_axis_rq_tready_int_reg) begin
|
||||
m_axis_rq_tvalid_int = 1'b1;
|
||||
|
||||
if (AXIS_PCIE_DATA_WIDTH == 128) begin
|
||||
m_axi_rready_next = m_axis_rq_tready_int_early;
|
||||
if ((m_axi_rready && m_axi_rvalid) && bubble_cycle_reg) begin
|
||||
transfer_in_save = 1'b1;
|
||||
if (input_active_reg) begin
|
||||
input_cycle_count_next = input_cycle_count_reg - 1;
|
||||
input_active_next = input_cycle_count_reg != 0;
|
||||
end
|
||||
bubble_cycle_next = 1'b0;
|
||||
m_axi_rready_next = m_axis_rq_tready_int_early && input_active_next;
|
||||
end
|
||||
tlp_state_next = TLP_STATE_TRANSFER;
|
||||
end else begin
|
||||
m_axi_rready_next = m_axis_rq_tready_int_early && bubble_cycle_reg;
|
||||
tlp_state_next = TLP_STATE_HEADER_2;
|
||||
end
|
||||
end else begin
|
||||
tlp_state_next = TLP_STATE_HEADER_1;
|
||||
end
|
||||
end
|
||||
end
|
||||
TLP_STATE_HEADER_2: begin
|
||||
// header 2 state, send rest of TLP header (64 bit interface only)
|
||||
if (m_axis_rq_tready_int_reg) begin
|
||||
m_axis_rq_tdata_int[10:0] = dword_count_reg; // DWORD count
|
||||
m_axis_rq_tdata_int[14:11] = 4'b0001; // request type - memory write
|
||||
m_axis_rq_tdata_int[15] = 1'b0; // poisoned request
|
||||
m_axis_rq_tdata_int[31:16] = requester_id;
|
||||
m_axis_rq_tdata_int[39:32] = 8'd0; // tag
|
||||
m_axis_rq_tdata_int[55:40] = 16'd0; // completer ID
|
||||
m_axis_rq_tdata_int[56] = requester_id_enable; // requester ID enable
|
||||
m_axis_rq_tdata_int[59:57] = 3'b000; // traffic class
|
||||
m_axis_rq_tdata_int[62:60] = 3'b000; // attr
|
||||
m_axis_rq_tdata_int[63] = 1'b0; // force ECRC
|
||||
m_axis_rq_tvalid_int = 1'b1;
|
||||
m_axis_rq_tkeep_int = 2'b11;
|
||||
|
||||
m_axi_rready_next = m_axis_rq_tready_int_early;
|
||||
if ((m_axi_rready && m_axi_rvalid) && bubble_cycle_reg) begin
|
||||
transfer_in_save = 1'b1;
|
||||
if (input_active_reg) begin
|
||||
input_cycle_count_next = input_cycle_count_reg - 1;
|
||||
input_active_next = input_cycle_count_reg != 0;
|
||||
end
|
||||
bubble_cycle_next = 1'b0;
|
||||
m_axi_rready_next = m_axis_rq_tready_int_early && input_active_next;
|
||||
end
|
||||
tlp_state_next = TLP_STATE_TRANSFER;
|
||||
end else begin
|
||||
tlp_state_next = TLP_STATE_HEADER_2;
|
||||
end
|
||||
end
|
||||
TLP_STATE_TRANSFER: begin
|
||||
// transfer state, transfer data
|
||||
m_axi_rready_next = m_axis_rq_tready_int_early && input_active_reg;
|
||||
|
||||
if (m_axis_rq_tready_int_reg && ((m_axi_rready && m_axi_rvalid) || !input_active_reg)) begin
|
||||
transfer_in_save = 1'b1;
|
||||
|
||||
if (bubble_cycle_reg) begin
|
||||
if (input_active_reg) begin
|
||||
input_cycle_count_next = input_cycle_count_reg - 1;
|
||||
input_active_next = input_cycle_count_reg != 0;
|
||||
end
|
||||
bubble_cycle_next = 1'b0;
|
||||
m_axi_rready_next = m_axis_rq_tready_int_early && input_active_next;
|
||||
tlp_state_next = TLP_STATE_TRANSFER;
|
||||
end else begin
|
||||
dword_count_next = dword_count_reg - AXI_STRB_WIDTH/4;
|
||||
if (input_active_reg) begin
|
||||
input_cycle_count_next = input_cycle_count_reg - 1;
|
||||
input_active_next = input_cycle_count_reg != 0;
|
||||
end
|
||||
output_cycle_count_next = output_cycle_count_reg - 1;
|
||||
last_cycle_next = output_cycle_count_next == 0;
|
||||
|
||||
m_axis_rq_tdata_int = shift_axi_rdata;
|
||||
m_axis_rq_tvalid_int = 1'b1;
|
||||
if (dword_count_reg >= AXI_STRB_WIDTH/4) begin
|
||||
m_axis_rq_tkeep_int = {AXI_STRB_WIDTH{1'b1}};
|
||||
end else begin
|
||||
m_axis_rq_tkeep_int = {AXI_STRB_WIDTH{1'b1}} >> (AXI_STRB_WIDTH - dword_count_reg);
|
||||
end
|
||||
|
||||
if (last_cycle_reg) begin
|
||||
m_axis_rq_tlast_int = 1'b1;
|
||||
if (last_tlp_reg) begin
|
||||
m_axis_write_desc_status_tag_next = tag_reg;
|
||||
m_axis_write_desc_status_valid_next = 1'b1;
|
||||
end
|
||||
|
||||
// skip idle state if possible
|
||||
tlp_addr_next = tlp_cmd_addr_reg;
|
||||
tlp_len_next = tlp_cmd_len_reg;
|
||||
dword_count_next = tlp_cmd_dword_len_reg;
|
||||
offset_next = tlp_cmd_offset_reg;
|
||||
input_cycle_count_next = tlp_cmd_input_cycle_len_reg;
|
||||
output_cycle_count_next = tlp_cmd_output_cycle_len_reg;
|
||||
input_active_next = 1'b1;
|
||||
bubble_cycle_next = tlp_cmd_bubble_cycle_reg;
|
||||
last_cycle_next = tlp_cmd_output_cycle_len_reg == 0;
|
||||
last_tlp_next = tlp_cmd_last_reg;
|
||||
tag_next = tlp_cmd_tag_reg;
|
||||
|
||||
if (tlp_cmd_valid_reg) begin
|
||||
tlp_cmd_ready = 1'b1;
|
||||
if (AXIS_PCIE_DATA_WIDTH == 256) begin
|
||||
m_axi_rready_next = m_axis_rq_tready_int_early;
|
||||
end else if (AXIS_PCIE_DATA_WIDTH == 128) begin
|
||||
m_axi_rready_next = m_axis_rq_tready_int_early && bubble_cycle_next;
|
||||
end else begin
|
||||
m_axi_rready_next = 1'b0;
|
||||
end
|
||||
tlp_state_next = TLP_STATE_HEADER_1;
|
||||
end else begin
|
||||
m_axi_rready_next = 0;
|
||||
tlp_state_next = TLP_STATE_IDLE;
|
||||
end
|
||||
end else begin
|
||||
m_axi_rready_next = m_axis_rq_tready_int_early && input_active_next;
|
||||
tlp_state_next = TLP_STATE_TRANSFER;
|
||||
end
|
||||
end
|
||||
end else begin
|
||||
tlp_state_next = TLP_STATE_TRANSFER;
|
||||
end
|
||||
end
|
||||
endcase
|
||||
end
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (rst) begin
|
||||
axi_state_reg <= AXI_STATE_IDLE;
|
||||
tlp_state_reg <= TLP_STATE_IDLE;
|
||||
tlp_cmd_valid_reg <= 1'b0;
|
||||
s_axis_write_desc_ready_reg <= 1'b0;
|
||||
m_axis_write_desc_status_valid_reg <= 1'b0;
|
||||
m_axi_arvalid_reg <= 1'b0;
|
||||
m_axi_rready_reg <= 1'b0;
|
||||
end else begin
|
||||
axi_state_reg <= axi_state_next;
|
||||
tlp_state_reg <= tlp_state_next;
|
||||
tlp_cmd_valid_reg <= tlp_cmd_valid_next;
|
||||
s_axis_write_desc_ready_reg <= s_axis_write_desc_ready_next;
|
||||
m_axis_write_desc_status_valid_reg <= m_axis_write_desc_status_valid_next;
|
||||
m_axi_arvalid_reg <= m_axi_arvalid_next;
|
||||
m_axi_rready_reg <= m_axi_rready_next;
|
||||
end
|
||||
|
||||
pcie_addr_reg <= pcie_addr_next;
|
||||
axi_addr_reg <= axi_addr_next;
|
||||
op_count_reg <= op_count_next;
|
||||
tr_count_reg <= tr_count_next;
|
||||
tlp_count_reg <= tlp_count_next;
|
||||
|
||||
tlp_addr_reg <= tlp_addr_next;
|
||||
tlp_len_reg <= tlp_len_next;
|
||||
dword_count_reg <= dword_count_next;
|
||||
offset_reg <= offset_next;
|
||||
input_cycle_count_reg <= input_cycle_count_next;
|
||||
output_cycle_count_reg <= output_cycle_count_next;
|
||||
input_active_reg <= input_active_next;
|
||||
bubble_cycle_reg <= bubble_cycle_next;
|
||||
last_cycle_reg <= last_cycle_next;
|
||||
last_tlp_reg <= last_tlp_next;
|
||||
tag_reg <= tag_next;
|
||||
|
||||
tlp_cmd_addr_reg <= tlp_cmd_addr_next;
|
||||
tlp_cmd_len_reg <= tlp_cmd_len_next;
|
||||
tlp_cmd_dword_len_reg <= tlp_cmd_dword_len_next;
|
||||
tlp_cmd_input_cycle_len_reg <= tlp_cmd_input_cycle_len_next;
|
||||
tlp_cmd_output_cycle_len_reg <= tlp_cmd_output_cycle_len_next;
|
||||
tlp_cmd_offset_reg <= tlp_cmd_offset_next;
|
||||
tlp_cmd_bubble_cycle_reg <= tlp_cmd_bubble_cycle_next;
|
||||
tlp_cmd_tag_reg <= tlp_cmd_tag_next;
|
||||
tlp_cmd_last_reg <= tlp_cmd_last_next;
|
||||
|
||||
m_axis_write_desc_status_tag_reg <= m_axis_write_desc_status_tag_next;
|
||||
|
||||
m_axi_araddr_reg <= m_axi_araddr_next;
|
||||
m_axi_arlen_reg <= m_axi_arlen_next;
|
||||
|
||||
max_payload_size_dw_reg <= 11'd32 << (max_payload_size > 5 ? 5 : max_payload_size);
|
||||
|
||||
if (transfer_in_save) begin
|
||||
save_axi_rdata_reg <= m_axi_rdata;
|
||||
end
|
||||
end
|
||||
|
||||
// output datapath logic (PCIe TLP)
|
||||
reg [AXIS_PCIE_DATA_WIDTH-1:0] m_axis_rq_tdata_reg = {AXIS_PCIE_DATA_WIDTH{1'b0}};
|
||||
reg [AXIS_PCIE_KEEP_WIDTH-1:0] m_axis_rq_tkeep_reg = {AXIS_PCIE_KEEP_WIDTH{1'b0}};
|
||||
reg m_axis_rq_tvalid_reg = 1'b0, m_axis_rq_tvalid_next;
|
||||
reg m_axis_rq_tlast_reg = 1'b0;
|
||||
reg [59:0] m_axis_rq_tuser_reg = 60'd0;
|
||||
|
||||
reg [AXIS_PCIE_DATA_WIDTH-1:0] temp_m_axis_rq_tdata_reg = {AXIS_PCIE_DATA_WIDTH{1'b0}};
|
||||
reg [AXIS_PCIE_KEEP_WIDTH-1:0] temp_m_axis_rq_tkeep_reg = {AXIS_PCIE_KEEP_WIDTH{1'b0}};
|
||||
reg temp_m_axis_rq_tvalid_reg = 1'b0, temp_m_axis_rq_tvalid_next;
|
||||
reg temp_m_axis_rq_tlast_reg = 1'b0;
|
||||
reg [59:0] temp_m_axis_rq_tuser_reg = 60'd0;
|
||||
|
||||
// datapath control
|
||||
reg store_axis_rq_int_to_output;
|
||||
reg store_axis_rq_int_to_temp;
|
||||
reg store_axis_rq_temp_to_output;
|
||||
|
||||
assign m_axis_rq_tdata = m_axis_rq_tdata_reg;
|
||||
assign m_axis_rq_tkeep = m_axis_rq_tkeep_reg;
|
||||
assign m_axis_rq_tvalid = m_axis_rq_tvalid_reg;
|
||||
assign m_axis_rq_tlast = m_axis_rq_tlast_reg;
|
||||
assign m_axis_rq_tuser = m_axis_rq_tuser_reg;
|
||||
|
||||
// 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)
|
||||
assign m_axis_rq_tready_int_early = m_axis_rq_tready || (!temp_m_axis_rq_tvalid_reg && (!m_axis_rq_tvalid_reg || !m_axis_rq_tvalid_int));
|
||||
|
||||
always @* begin
|
||||
// transfer sink ready state to source
|
||||
m_axis_rq_tvalid_next = m_axis_rq_tvalid_reg;
|
||||
temp_m_axis_rq_tvalid_next = temp_m_axis_rq_tvalid_reg;
|
||||
|
||||
store_axis_rq_int_to_output = 1'b0;
|
||||
store_axis_rq_int_to_temp = 1'b0;
|
||||
store_axis_rq_temp_to_output = 1'b0;
|
||||
|
||||
if (m_axis_rq_tready_int_reg) begin
|
||||
// input is ready
|
||||
if (m_axis_rq_tready || !m_axis_rq_tvalid_reg) begin
|
||||
// output is ready or currently not valid, transfer data to output
|
||||
m_axis_rq_tvalid_next = m_axis_rq_tvalid_int;
|
||||
store_axis_rq_int_to_output = 1'b1;
|
||||
end else begin
|
||||
// output is not ready, store input in temp
|
||||
temp_m_axis_rq_tvalid_next = m_axis_rq_tvalid_int;
|
||||
store_axis_rq_int_to_temp = 1'b1;
|
||||
end
|
||||
end else if (m_axis_rq_tready) begin
|
||||
// input is not ready, but output is ready
|
||||
m_axis_rq_tvalid_next = temp_m_axis_rq_tvalid_reg;
|
||||
temp_m_axis_rq_tvalid_next = 1'b0;
|
||||
store_axis_rq_temp_to_output = 1'b1;
|
||||
end
|
||||
end
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (rst) begin
|
||||
m_axis_rq_tvalid_reg <= 1'b0;
|
||||
m_axis_rq_tready_int_reg <= 1'b0;
|
||||
temp_m_axis_rq_tvalid_reg <= 1'b0;
|
||||
end else begin
|
||||
m_axis_rq_tvalid_reg <= m_axis_rq_tvalid_next;
|
||||
m_axis_rq_tready_int_reg <= m_axis_rq_tready_int_early;
|
||||
temp_m_axis_rq_tvalid_reg <= temp_m_axis_rq_tvalid_next;
|
||||
end
|
||||
|
||||
// datapath
|
||||
if (store_axis_rq_int_to_output) begin
|
||||
m_axis_rq_tdata_reg <= m_axis_rq_tdata_int;
|
||||
m_axis_rq_tkeep_reg <= m_axis_rq_tkeep_int;
|
||||
m_axis_rq_tlast_reg <= m_axis_rq_tlast_int;
|
||||
m_axis_rq_tuser_reg <= m_axis_rq_tuser_int;
|
||||
end else if (store_axis_rq_temp_to_output) begin
|
||||
m_axis_rq_tdata_reg <= temp_m_axis_rq_tdata_reg;
|
||||
m_axis_rq_tkeep_reg <= temp_m_axis_rq_tkeep_reg;
|
||||
m_axis_rq_tlast_reg <= temp_m_axis_rq_tlast_reg;
|
||||
m_axis_rq_tuser_reg <= temp_m_axis_rq_tuser_reg;
|
||||
end
|
||||
|
||||
if (store_axis_rq_int_to_temp) begin
|
||||
temp_m_axis_rq_tdata_reg <= m_axis_rq_tdata_int;
|
||||
temp_m_axis_rq_tkeep_reg <= m_axis_rq_tkeep_int;
|
||||
temp_m_axis_rq_tlast_reg <= m_axis_rq_tlast_int;
|
||||
temp_m_axis_rq_tuser_reg <= m_axis_rq_tuser_int;
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
307
fpga/lib/pcie/rtl/pcie_us_axi_master.v
Normal file
307
fpga/lib/pcie/rtl/pcie_us_axi_master.v
Normal file
@ -0,0 +1,307 @@
|
||||
/*
|
||||
|
||||
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
|
||||
|
||||
/*
|
||||
* Ultrascale PCIe AXI Master
|
||||
*/
|
||||
module pcie_us_axi_master #
|
||||
(
|
||||
parameter AXIS_PCIE_DATA_WIDTH = 256,
|
||||
parameter AXIS_PCIE_KEEP_WIDTH = (AXIS_PCIE_DATA_WIDTH/32),
|
||||
parameter AXI_DATA_WIDTH = AXIS_PCIE_DATA_WIDTH,
|
||||
parameter AXI_ADDR_WIDTH = 64,
|
||||
parameter AXI_STRB_WIDTH = (AXI_DATA_WIDTH/8),
|
||||
parameter AXI_ID_WIDTH = 8,
|
||||
parameter AXI_MAX_BURST_LEN = 256
|
||||
)
|
||||
(
|
||||
input wire clk,
|
||||
input wire rst,
|
||||
|
||||
/*
|
||||
* AXI input (CQ)
|
||||
*/
|
||||
input wire [AXIS_PCIE_DATA_WIDTH-1:0] s_axis_cq_tdata,
|
||||
input wire [AXIS_PCIE_KEEP_WIDTH-1:0] s_axis_cq_tkeep,
|
||||
input wire s_axis_cq_tvalid,
|
||||
output wire s_axis_cq_tready,
|
||||
input wire s_axis_cq_tlast,
|
||||
input wire [84:0] s_axis_cq_tuser,
|
||||
|
||||
/*
|
||||
* AXI output (CC)
|
||||
*/
|
||||
output wire [AXIS_PCIE_DATA_WIDTH-1:0] m_axis_cc_tdata,
|
||||
output wire [AXIS_PCIE_KEEP_WIDTH-1:0] m_axis_cc_tkeep,
|
||||
output wire m_axis_cc_tvalid,
|
||||
input wire m_axis_cc_tready,
|
||||
output wire m_axis_cc_tlast,
|
||||
output wire [32:0] m_axis_cc_tuser,
|
||||
|
||||
/*
|
||||
* AXI Master output
|
||||
*/
|
||||
output wire [AXI_ID_WIDTH-1:0] m_axi_awid,
|
||||
output wire [AXI_ADDR_WIDTH-1:0] m_axi_awaddr,
|
||||
output wire [7:0] m_axi_awlen,
|
||||
output wire [2:0] m_axi_awsize,
|
||||
output wire [1:0] m_axi_awburst,
|
||||
output wire m_axi_awlock,
|
||||
output wire [3:0] m_axi_awcache,
|
||||
output wire [2:0] m_axi_awprot,
|
||||
output wire m_axi_awvalid,
|
||||
input wire m_axi_awready,
|
||||
output wire [AXI_DATA_WIDTH-1:0] m_axi_wdata,
|
||||
output wire [AXI_STRB_WIDTH-1:0] m_axi_wstrb,
|
||||
output wire m_axi_wlast,
|
||||
output wire m_axi_wvalid,
|
||||
input wire m_axi_wready,
|
||||
input wire [AXI_ID_WIDTH-1:0] m_axi_bid,
|
||||
input wire [1:0] m_axi_bresp,
|
||||
input wire m_axi_bvalid,
|
||||
output wire m_axi_bready,
|
||||
output wire [AXI_ID_WIDTH-1:0] m_axi_arid,
|
||||
output wire [AXI_ADDR_WIDTH-1:0] m_axi_araddr,
|
||||
output wire [7:0] m_axi_arlen,
|
||||
output wire [2:0] m_axi_arsize,
|
||||
output wire [1:0] m_axi_arburst,
|
||||
output wire m_axi_arlock,
|
||||
output wire [3:0] m_axi_arcache,
|
||||
output wire [2:0] m_axi_arprot,
|
||||
output wire m_axi_arvalid,
|
||||
input wire m_axi_arready,
|
||||
input wire [AXI_ID_WIDTH-1:0] m_axi_rid,
|
||||
input wire [AXI_DATA_WIDTH-1:0] m_axi_rdata,
|
||||
input wire [1:0] m_axi_rresp,
|
||||
input wire m_axi_rlast,
|
||||
input wire m_axi_rvalid,
|
||||
output wire m_axi_rready,
|
||||
|
||||
/*
|
||||
* Configuration
|
||||
*/
|
||||
input wire [15:0] completer_id,
|
||||
input wire completer_id_enable,
|
||||
input wire [2:0] max_payload_size,
|
||||
|
||||
/*
|
||||
* Status
|
||||
*/
|
||||
output wire status_error_cor,
|
||||
output wire status_error_uncor
|
||||
);
|
||||
|
||||
wire [AXIS_PCIE_DATA_WIDTH-1:0] axis_cq_tdata_read;
|
||||
wire [AXIS_PCIE_KEEP_WIDTH-1:0] axis_cq_tkeep_read;
|
||||
wire axis_cq_tvalid_read;
|
||||
wire axis_cq_tready_read;
|
||||
wire axis_cq_tlast_read;
|
||||
wire [84:0] axis_cq_tuser_read;
|
||||
|
||||
wire [AXIS_PCIE_DATA_WIDTH-1:0] axis_cq_tdata_write;
|
||||
wire [AXIS_PCIE_KEEP_WIDTH-1:0] axis_cq_tkeep_write;
|
||||
wire axis_cq_tvalid_write;
|
||||
wire axis_cq_tready_write;
|
||||
wire axis_cq_tlast_write;
|
||||
wire [84:0] axis_cq_tuser_write;
|
||||
|
||||
wire [3:0] req_type;
|
||||
wire [1:0] select;
|
||||
|
||||
wire [1:0] status_error_uncor_int;
|
||||
|
||||
pcie_us_axis_cq_demux #(
|
||||
.M_COUNT(2),
|
||||
.AXIS_PCIE_DATA_WIDTH(AXIS_PCIE_DATA_WIDTH),
|
||||
.AXIS_PCIE_KEEP_WIDTH(AXIS_PCIE_KEEP_WIDTH)
|
||||
)
|
||||
cq_demux_inst (
|
||||
.clk(clk),
|
||||
.rst(rst),
|
||||
|
||||
.s_axis_cq_tdata(s_axis_cq_tdata),
|
||||
.s_axis_cq_tkeep(s_axis_cq_tkeep),
|
||||
.s_axis_cq_tvalid(s_axis_cq_tvalid),
|
||||
.s_axis_cq_tready(s_axis_cq_tready),
|
||||
.s_axis_cq_tlast(s_axis_cq_tlast),
|
||||
.s_axis_cq_tuser(s_axis_cq_tuser),
|
||||
|
||||
.m_axis_cq_tdata({axis_cq_tdata_write, axis_cq_tdata_read}),
|
||||
.m_axis_cq_tkeep({axis_cq_tkeep_write, axis_cq_tkeep_read}),
|
||||
.m_axis_cq_tvalid({axis_cq_tvalid_write, axis_cq_tvalid_read}),
|
||||
.m_axis_cq_tready({axis_cq_tready_write, axis_cq_tready_read}),
|
||||
.m_axis_cq_tlast({axis_cq_tlast_write, axis_cq_tlast_read}),
|
||||
.m_axis_cq_tuser({axis_cq_tuser_write, axis_cq_tuser_read}),
|
||||
|
||||
.req_type(req_type),
|
||||
.target_function(),
|
||||
.bar_id(),
|
||||
.msg_code(),
|
||||
.msg_routing(),
|
||||
|
||||
.enable(1'b1),
|
||||
.drop(1'b0),
|
||||
.select(select)
|
||||
);
|
||||
|
||||
assign select[1] = req_type == 4'b0001;
|
||||
assign select[0] = ~select[1];
|
||||
|
||||
pcie_us_axi_master_rd #(
|
||||
.AXIS_PCIE_DATA_WIDTH(AXIS_PCIE_DATA_WIDTH),
|
||||
.AXIS_PCIE_KEEP_WIDTH(AXIS_PCIE_KEEP_WIDTH),
|
||||
.AXI_DATA_WIDTH(AXI_DATA_WIDTH),
|
||||
.AXI_ADDR_WIDTH(AXI_ADDR_WIDTH),
|
||||
.AXI_STRB_WIDTH(AXI_STRB_WIDTH),
|
||||
.AXI_ID_WIDTH(AXI_ID_WIDTH),
|
||||
.AXI_MAX_BURST_LEN(AXI_MAX_BURST_LEN)
|
||||
)
|
||||
pcie_us_axi_master_rd_inst (
|
||||
.clk(clk),
|
||||
.rst(rst),
|
||||
|
||||
/*
|
||||
* AXI input (CQ)
|
||||
*/
|
||||
.s_axis_cq_tdata(axis_cq_tdata_read),
|
||||
.s_axis_cq_tkeep(axis_cq_tkeep_read),
|
||||
.s_axis_cq_tvalid(axis_cq_tvalid_read),
|
||||
.s_axis_cq_tready(axis_cq_tready_read),
|
||||
.s_axis_cq_tlast(axis_cq_tlast_read),
|
||||
.s_axis_cq_tuser(axis_cq_tuser_read),
|
||||
|
||||
/*
|
||||
* AXI output (CC)
|
||||
*/
|
||||
.m_axis_cc_tdata(m_axis_cc_tdata),
|
||||
.m_axis_cc_tkeep(m_axis_cc_tkeep),
|
||||
.m_axis_cc_tvalid(m_axis_cc_tvalid),
|
||||
.m_axis_cc_tready(m_axis_cc_tready),
|
||||
.m_axis_cc_tlast(m_axis_cc_tlast),
|
||||
.m_axis_cc_tuser(m_axis_cc_tuser),
|
||||
|
||||
/*
|
||||
* AXI master interface
|
||||
*/
|
||||
.m_axi_arid(m_axi_arid),
|
||||
.m_axi_araddr(m_axi_araddr),
|
||||
.m_axi_arlen(m_axi_arlen),
|
||||
.m_axi_arsize(m_axi_arsize),
|
||||
.m_axi_arburst(m_axi_arburst),
|
||||
.m_axi_arlock(m_axi_arlock),
|
||||
.m_axi_arcache(m_axi_arcache),
|
||||
.m_axi_arprot(m_axi_arprot),
|
||||
.m_axi_arvalid(m_axi_arvalid),
|
||||
.m_axi_arready(m_axi_arready),
|
||||
.m_axi_rid(m_axi_rid),
|
||||
.m_axi_rdata(m_axi_rdata),
|
||||
.m_axi_rresp(m_axi_rresp),
|
||||
.m_axi_rlast(m_axi_rlast),
|
||||
.m_axi_rvalid(m_axi_rvalid),
|
||||
.m_axi_rready(m_axi_rready),
|
||||
|
||||
/*
|
||||
* Configuration
|
||||
*/
|
||||
.completer_id(completer_id),
|
||||
.completer_id_enable(completer_id_enable),
|
||||
.max_payload_size(max_payload_size),
|
||||
|
||||
/*
|
||||
* Status
|
||||
*/
|
||||
.status_error_cor(status_error_cor),
|
||||
.status_error_uncor(status_error_uncor_int[0])
|
||||
);
|
||||
|
||||
pcie_us_axi_master_wr #(
|
||||
.AXIS_PCIE_DATA_WIDTH(AXIS_PCIE_DATA_WIDTH),
|
||||
.AXIS_PCIE_KEEP_WIDTH(AXIS_PCIE_KEEP_WIDTH),
|
||||
.AXI_DATA_WIDTH(AXI_DATA_WIDTH),
|
||||
.AXI_ADDR_WIDTH(AXI_ADDR_WIDTH),
|
||||
.AXI_STRB_WIDTH(AXI_STRB_WIDTH),
|
||||
.AXI_ID_WIDTH(AXI_ID_WIDTH),
|
||||
.AXI_MAX_BURST_LEN(AXI_MAX_BURST_LEN)
|
||||
)
|
||||
pcie_us_axi_master_wr_inst (
|
||||
.clk(clk),
|
||||
.rst(rst),
|
||||
|
||||
/*
|
||||
* AXI input (CQ)
|
||||
*/
|
||||
.s_axis_cq_tdata(axis_cq_tdata_write),
|
||||
.s_axis_cq_tkeep(axis_cq_tkeep_write),
|
||||
.s_axis_cq_tvalid(axis_cq_tvalid_write),
|
||||
.s_axis_cq_tready(axis_cq_tready_write),
|
||||
.s_axis_cq_tlast(axis_cq_tlast_write),
|
||||
.s_axis_cq_tuser(axis_cq_tuser_write),
|
||||
|
||||
/*
|
||||
* AXI master interface
|
||||
*/
|
||||
.m_axi_awid(m_axi_awid),
|
||||
.m_axi_awaddr(m_axi_awaddr),
|
||||
.m_axi_awlen(m_axi_awlen),
|
||||
.m_axi_awsize(m_axi_awsize),
|
||||
.m_axi_awburst(m_axi_awburst),
|
||||
.m_axi_awlock(m_axi_awlock),
|
||||
.m_axi_awcache(m_axi_awcache),
|
||||
.m_axi_awprot(m_axi_awprot),
|
||||
.m_axi_awvalid(m_axi_awvalid),
|
||||
.m_axi_awready(m_axi_awready),
|
||||
.m_axi_wdata(m_axi_wdata),
|
||||
.m_axi_wstrb(m_axi_wstrb),
|
||||
.m_axi_wlast(m_axi_wlast),
|
||||
.m_axi_wvalid(m_axi_wvalid),
|
||||
.m_axi_wready(m_axi_wready),
|
||||
.m_axi_bid(m_axi_bid),
|
||||
.m_axi_bresp(m_axi_bresp),
|
||||
.m_axi_bvalid(m_axi_bvalid),
|
||||
.m_axi_bready(m_axi_bready),
|
||||
|
||||
/*
|
||||
* Status
|
||||
*/
|
||||
.status_error_uncor(status_error_uncor_int[1])
|
||||
);
|
||||
|
||||
pulse_merge #(
|
||||
.INPUT_WIDTH(2),
|
||||
.COUNT_WIDTH(4)
|
||||
)
|
||||
status_error_uncor_pm_inst (
|
||||
.clk(clk),
|
||||
.rst(rst),
|
||||
|
||||
.pulse_in(status_error_uncor_int),
|
||||
.count_out(),
|
||||
.pulse_out(status_error_uncor)
|
||||
);
|
||||
|
||||
endmodule
|
1185
fpga/lib/pcie/rtl/pcie_us_axi_master_rd.v
Normal file
1185
fpga/lib/pcie/rtl/pcie_us_axi_master_rd.v
Normal file
File diff suppressed because it is too large
Load Diff
650
fpga/lib/pcie/rtl/pcie_us_axi_master_wr.v
Normal file
650
fpga/lib/pcie/rtl/pcie_us_axi_master_wr.v
Normal file
@ -0,0 +1,650 @@
|
||||
/*
|
||||
|
||||
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
|
||||
|
||||
/*
|
||||
* Ultrascale PCIe AXI Master (write)
|
||||
*/
|
||||
module pcie_us_axi_master_wr #
|
||||
(
|
||||
parameter AXIS_PCIE_DATA_WIDTH = 256,
|
||||
parameter AXIS_PCIE_KEEP_WIDTH = (AXIS_PCIE_DATA_WIDTH/32),
|
||||
parameter AXI_DATA_WIDTH = AXIS_PCIE_DATA_WIDTH,
|
||||
parameter AXI_ADDR_WIDTH = 64,
|
||||
parameter AXI_STRB_WIDTH = (AXI_DATA_WIDTH/8),
|
||||
parameter AXI_ID_WIDTH = 8,
|
||||
parameter AXI_MAX_BURST_LEN = 256
|
||||
)
|
||||
(
|
||||
input wire clk,
|
||||
input wire rst,
|
||||
|
||||
/*
|
||||
* AXI input (CQ)
|
||||
*/
|
||||
input wire [AXIS_PCIE_DATA_WIDTH-1:0] s_axis_cq_tdata,
|
||||
input wire [AXIS_PCIE_KEEP_WIDTH-1:0] s_axis_cq_tkeep,
|
||||
input wire s_axis_cq_tvalid,
|
||||
output wire s_axis_cq_tready,
|
||||
input wire s_axis_cq_tlast,
|
||||
input wire [84:0] s_axis_cq_tuser,
|
||||
|
||||
/*
|
||||
* AXI Master output
|
||||
*/
|
||||
output wire [AXI_ID_WIDTH-1:0] m_axi_awid,
|
||||
output wire [AXI_ADDR_WIDTH-1:0] m_axi_awaddr,
|
||||
output wire [7:0] m_axi_awlen,
|
||||
output wire [2:0] m_axi_awsize,
|
||||
output wire [1:0] m_axi_awburst,
|
||||
output wire m_axi_awlock,
|
||||
output wire [3:0] m_axi_awcache,
|
||||
output wire [2:0] m_axi_awprot,
|
||||
output wire m_axi_awvalid,
|
||||
input wire m_axi_awready,
|
||||
output wire [AXI_DATA_WIDTH-1:0] m_axi_wdata,
|
||||
output wire [AXI_STRB_WIDTH-1:0] m_axi_wstrb,
|
||||
output wire m_axi_wlast,
|
||||
output wire m_axi_wvalid,
|
||||
input wire m_axi_wready,
|
||||
input wire [AXI_ID_WIDTH-1:0] m_axi_bid,
|
||||
input wire [1:0] m_axi_bresp,
|
||||
input wire m_axi_bvalid,
|
||||
output wire m_axi_bready,
|
||||
|
||||
/*
|
||||
* Status
|
||||
*/
|
||||
output wire status_error_uncor
|
||||
);
|
||||
|
||||
parameter AXI_WORD_WIDTH = AXI_STRB_WIDTH;
|
||||
parameter AXI_WORD_SIZE = AXI_DATA_WIDTH/AXI_WORD_WIDTH;
|
||||
parameter AXI_BURST_SIZE = $clog2(AXI_STRB_WIDTH);
|
||||
parameter AXI_MAX_BURST_SIZE = AXI_MAX_BURST_LEN*AXI_WORD_WIDTH;
|
||||
|
||||
parameter AXIS_PCIE_WORD_WIDTH = AXIS_PCIE_KEEP_WIDTH;
|
||||
parameter AXIS_PCIE_WORD_SIZE = AXIS_PCIE_DATA_WIDTH/AXIS_PCIE_WORD_WIDTH;
|
||||
|
||||
parameter OFFSET_WIDTH = $clog2(AXIS_PCIE_DATA_WIDTH/32);
|
||||
|
||||
// bus width assertions
|
||||
initial begin
|
||||
if (AXIS_PCIE_DATA_WIDTH != 64 && AXIS_PCIE_DATA_WIDTH != 128 && AXIS_PCIE_DATA_WIDTH != 256) begin
|
||||
$error("Error: PCIe interface width must be 64, 128, or 256");
|
||||
$finish;
|
||||
end
|
||||
|
||||
if (AXIS_PCIE_KEEP_WIDTH * 32 != AXIS_PCIE_DATA_WIDTH) begin
|
||||
$error("Error: PCIe interface requires dword (32-bit) granularity");
|
||||
$finish;
|
||||
end
|
||||
|
||||
if (AXI_DATA_WIDTH != AXIS_PCIE_DATA_WIDTH) begin
|
||||
$error("Error: AXI interface width must match PCIe interface width");
|
||||
$finish;
|
||||
end
|
||||
|
||||
if (AXI_STRB_WIDTH * 8 != AXI_DATA_WIDTH) begin
|
||||
$error("Error: AXI interface requires byte (8-bit) granularity");
|
||||
$finish;
|
||||
end
|
||||
|
||||
if (AXI_MAX_BURST_LEN < 1 || AXI_MAX_BURST_LEN > 256) begin
|
||||
$error("Error: AXI_MAX_BURST_LEN must be between 1 and 256");
|
||||
$finish;
|
||||
end
|
||||
end
|
||||
|
||||
localparam [3:0]
|
||||
REQ_MEM_READ = 4'b0000,
|
||||
REQ_MEM_WRITE = 4'b0001,
|
||||
REQ_IO_READ = 4'b0010,
|
||||
REQ_IO_WRITE = 4'b0011,
|
||||
REQ_MEM_FETCH_ADD = 4'b0100,
|
||||
REQ_MEM_SWAP = 4'b0101,
|
||||
REQ_MEM_CAS = 4'b0110,
|
||||
REQ_MEM_READ_LOCKED = 4'b0111,
|
||||
REQ_CFG_READ_0 = 4'b1000,
|
||||
REQ_CFG_READ_1 = 4'b1001,
|
||||
REQ_CFG_WRITE_0 = 4'b1010,
|
||||
REQ_CFG_WRITE_1 = 4'b1011,
|
||||
REQ_MSG = 4'b1100,
|
||||
REQ_MSG_VENDOR = 4'b1101,
|
||||
REQ_MSG_ATS = 4'b1110;
|
||||
|
||||
localparam [2:0]
|
||||
CPL_STATUS_SC = 3'b000, // successful completion
|
||||
CPL_STATUS_UR = 3'b001, // unsupported request
|
||||
CPL_STATUS_CRS = 3'b010, // configuration request retry status
|
||||
CPL_STATUS_CA = 3'b100; // completer abort
|
||||
|
||||
localparam [1:0]
|
||||
STATE_IDLE = 2'd0,
|
||||
STATE_HEADER = 3'd1,
|
||||
STATE_TRANSFER = 2'd2,
|
||||
STATE_WAIT_END = 2'd3;
|
||||
|
||||
reg [1:0] state_reg = STATE_IDLE, state_next;
|
||||
|
||||
// datapath control signals
|
||||
reg transfer_in_save;
|
||||
reg flush_save;
|
||||
|
||||
reg [AXI_ADDR_WIDTH-1:0] axi_addr_reg = {AXI_ADDR_WIDTH{1'b0}}, axi_addr_next;
|
||||
reg [9:0] op_dword_count_reg = 10'd0, op_dword_count_next;
|
||||
reg [9:0] tr_dword_count_reg = 10'd0, tr_dword_count_next;
|
||||
reg [11:0] input_cycle_count_reg = 12'd0, input_cycle_count_next;
|
||||
reg [11:0] output_cycle_count_reg = 12'd0, output_cycle_count_next;
|
||||
reg input_active_reg = 1'b0, input_active_next;
|
||||
reg bubble_cycle_reg = 1'b0, bubble_cycle_next;
|
||||
reg first_cycle_reg = 1'b0, first_cycle_next;
|
||||
reg last_cycle_reg = 1'b0, last_cycle_next;
|
||||
|
||||
reg [3:0] type_reg = 4'd0, type_next;
|
||||
reg [3:0] first_be_reg = 4'd0, first_be_next;
|
||||
reg [3:0] last_be_reg = 4'd0, last_be_next;
|
||||
reg [OFFSET_WIDTH-1:0] offset_reg = {OFFSET_WIDTH{1'b0}}, offset_next;
|
||||
reg [OFFSET_WIDTH-1:0] first_cycle_offset_reg = {OFFSET_WIDTH{1'b0}}, first_cycle_offset_next;
|
||||
reg [OFFSET_WIDTH-1:0] last_cycle_offset_reg = {OFFSET_WIDTH{1'b0}}, last_cycle_offset_next;
|
||||
|
||||
reg s_axis_cq_tready_reg = 1'b0, s_axis_cq_tready_next;
|
||||
|
||||
reg [AXI_ADDR_WIDTH-1:0] m_axi_awaddr_reg = {AXI_ADDR_WIDTH{1'b0}}, m_axi_awaddr_next;
|
||||
reg [7:0] m_axi_awlen_reg = 8'd0, m_axi_awlen_next;
|
||||
reg m_axi_awvalid_reg = 1'b0, m_axi_awvalid_next;
|
||||
|
||||
reg [AXI_DATA_WIDTH-1:0] save_axis_tdata_reg = {AXI_DATA_WIDTH{1'b0}};
|
||||
|
||||
wire [AXI_DATA_WIDTH-1:0] shift_axis_tdata = {s_axis_cq_tdata, save_axis_tdata_reg} >> ((AXI_STRB_WIDTH/4-offset_reg)*32);
|
||||
|
||||
reg status_error_uncor_reg = 1'b0, status_error_uncor_next;
|
||||
|
||||
// internal datapath
|
||||
reg [AXI_DATA_WIDTH-1:0] m_axi_wdata_int;
|
||||
reg [AXI_STRB_WIDTH-1:0] m_axi_wstrb_int;
|
||||
reg m_axi_wvalid_int;
|
||||
reg m_axi_wready_int_reg = 1'b0;
|
||||
reg m_axi_wlast_int;
|
||||
wire m_axi_wready_int_early;
|
||||
|
||||
assign s_axis_cq_tready = s_axis_cq_tready_reg;
|
||||
|
||||
assign m_axi_awid = {AXI_ID_WIDTH{1'b0}};
|
||||
assign m_axi_awaddr = m_axi_awaddr_reg;
|
||||
assign m_axi_awlen = m_axi_awlen_reg;
|
||||
assign m_axi_awsize = $clog2(AXI_STRB_WIDTH);
|
||||
assign m_axi_awburst = 2'b01;
|
||||
assign m_axi_awlock = 1'b0;
|
||||
assign m_axi_awcache = 4'b0011;
|
||||
assign m_axi_awprot = 3'b010;
|
||||
assign m_axi_awvalid = m_axi_awvalid_reg;
|
||||
|
||||
assign m_axi_bready = 1'b1;
|
||||
|
||||
assign status_error_uncor = status_error_uncor_reg;
|
||||
|
||||
always @* begin
|
||||
state_next = STATE_IDLE;
|
||||
|
||||
transfer_in_save = 1'b0;
|
||||
|
||||
s_axis_cq_tready_next = 1'b0;
|
||||
|
||||
type_next = type_reg;
|
||||
axi_addr_next = axi_addr_reg;
|
||||
op_dword_count_next = op_dword_count_reg;
|
||||
tr_dword_count_next = tr_dword_count_reg;
|
||||
input_cycle_count_next = input_cycle_count_reg;
|
||||
output_cycle_count_next = output_cycle_count_reg;
|
||||
input_active_next = input_active_reg;
|
||||
bubble_cycle_next = bubble_cycle_reg;
|
||||
first_cycle_next = first_cycle_reg;
|
||||
last_cycle_next = last_cycle_reg;
|
||||
first_be_next = first_be_reg;
|
||||
last_be_next = last_be_reg;
|
||||
offset_next = offset_reg;
|
||||
first_cycle_offset_next = first_cycle_offset_reg;
|
||||
last_cycle_offset_next = last_cycle_offset_reg;
|
||||
|
||||
m_axi_awaddr_next = m_axi_awaddr_reg;
|
||||
m_axi_awlen_next = m_axi_awlen_reg;
|
||||
m_axi_awvalid_next = m_axi_awvalid_reg && !m_axi_awready;
|
||||
|
||||
m_axi_wdata_int = shift_axis_tdata;
|
||||
m_axi_wstrb_int = {AXI_STRB_WIDTH{1'b1}};
|
||||
m_axi_wvalid_int = 1'b0;
|
||||
m_axi_wlast_int = 1'b0;
|
||||
|
||||
status_error_uncor_next = 1'b0;
|
||||
|
||||
case (state_reg)
|
||||
STATE_IDLE: begin
|
||||
// idle state, wait for completion request
|
||||
if (AXIS_PCIE_DATA_WIDTH > 64) begin
|
||||
s_axis_cq_tready_next = m_axi_wready_int_early && (!m_axi_awvalid || m_axi_awready);
|
||||
|
||||
if (s_axis_cq_tready && s_axis_cq_tvalid) begin
|
||||
transfer_in_save = 1'b1;
|
||||
|
||||
// header fields
|
||||
axi_addr_next = {s_axis_cq_tdata[63:2], 2'b00};
|
||||
op_dword_count_next = s_axis_cq_tdata[74:64];
|
||||
type_next = s_axis_cq_tdata[78:75];
|
||||
|
||||
// tuser fields
|
||||
first_be_next = s_axis_cq_tuser[3:0];
|
||||
last_be_next = s_axis_cq_tuser[7:4];
|
||||
|
||||
if (op_dword_count_next == 1) begin
|
||||
// use first_be for both byte enables for single DWORD transfers
|
||||
last_be_next = first_be_next;
|
||||
end
|
||||
|
||||
if (op_dword_count_next <= AXI_MAX_BURST_SIZE/4) begin
|
||||
// packet smaller than max burst size
|
||||
// assumed to not cross 4k boundary, send one request
|
||||
tr_dword_count_next = op_dword_count_next;
|
||||
m_axi_awlen_next = (tr_dword_count_next + axi_addr_next[OFFSET_WIDTH+2-1:2] - 1) >> (AXI_BURST_SIZE-2);
|
||||
end else begin
|
||||
// packet larger than max burst size
|
||||
// assumed to not cross 4k boundary, send one request
|
||||
tr_dword_count_next = AXI_MAX_BURST_SIZE/4 - axi_addr_next[OFFSET_WIDTH+2-1:2];
|
||||
m_axi_awlen_next = (tr_dword_count_next - 1) >> (AXI_BURST_SIZE-2);
|
||||
end
|
||||
|
||||
m_axi_awaddr_next = axi_addr_next;
|
||||
|
||||
// required DWORD shift to place first DWORD from the TLP payload into proper position on AXI interface
|
||||
// bubble cycle required if first TLP payload transfer does not fill first AXI transfer
|
||||
if (AXIS_PCIE_DATA_WIDTH == 256) begin
|
||||
offset_next = axi_addr_next[OFFSET_WIDTH+2-1:2] - 4;
|
||||
bubble_cycle_next = axi_addr_next[OFFSET_WIDTH+2-1:2] < 4;
|
||||
end else begin
|
||||
offset_next = axi_addr_next[OFFSET_WIDTH+2-1:2];
|
||||
bubble_cycle_next = 1'b0;
|
||||
end
|
||||
first_cycle_offset_next = axi_addr_next[OFFSET_WIDTH+2-1:2];
|
||||
first_cycle_next = 1'b1;
|
||||
|
||||
// number of bus transfers in TLP, DOWRD count plus payload start DWORD offset, divided by bus width in DWORDS
|
||||
if (AXIS_PCIE_DATA_WIDTH == 256) begin
|
||||
input_cycle_count_next = (tr_dword_count_next + 4 - 1) >> (AXI_BURST_SIZE-2);
|
||||
end else begin
|
||||
input_cycle_count_next = (tr_dword_count_next - 1) >> (AXI_BURST_SIZE-2);
|
||||
end
|
||||
// number of bus transfers to AXI, DWORD count plus DWORD offset, divided by bus width in DWORDS
|
||||
output_cycle_count_next = (tr_dword_count_next + axi_addr_next[OFFSET_WIDTH+2-1:2] - 1) >> (AXI_BURST_SIZE-2);
|
||||
last_cycle_offset_next = axi_addr_next[OFFSET_WIDTH+2-1:2] + tr_dword_count_next;
|
||||
last_cycle_next = output_cycle_count_next == 0;
|
||||
input_active_next = 1'b1;
|
||||
|
||||
axi_addr_next = axi_addr_next + (tr_dword_count_next << 2);
|
||||
op_dword_count_next = op_dword_count_next - tr_dword_count_next;
|
||||
|
||||
if (type_next == REQ_MEM_WRITE) begin
|
||||
// write request
|
||||
m_axi_awvalid_next = 1'b1;
|
||||
if (AXIS_PCIE_DATA_WIDTH == 256) begin
|
||||
// some data is transferred with header
|
||||
input_active_next = input_cycle_count_next > 0;
|
||||
input_cycle_count_next = input_cycle_count_next - 1;
|
||||
s_axis_cq_tready_next = 1'b0;
|
||||
state_next = STATE_TRANSFER;
|
||||
end else begin
|
||||
s_axis_cq_tready_next = m_axi_wready_int_early;
|
||||
state_next = STATE_TRANSFER;
|
||||
end
|
||||
end else begin
|
||||
// invalid request
|
||||
status_error_uncor_next = 1'b1;
|
||||
if (s_axis_cq_tlast) begin
|
||||
state_next = STATE_IDLE;
|
||||
end else begin
|
||||
s_axis_cq_tready_next = 1'b1;
|
||||
state_next = STATE_WAIT_END;
|
||||
end
|
||||
end
|
||||
end else begin
|
||||
state_next = STATE_IDLE;
|
||||
end
|
||||
end else begin
|
||||
s_axis_cq_tready_next = !m_axi_awvalid || m_axi_awready;
|
||||
|
||||
if (s_axis_cq_tready & s_axis_cq_tvalid) begin
|
||||
// header fields
|
||||
axi_addr_next = {s_axis_cq_tdata[63:2], 2'b00};
|
||||
|
||||
// tuser fields
|
||||
first_be_next = s_axis_cq_tuser[3:0];
|
||||
last_be_next = s_axis_cq_tuser[7:4];
|
||||
|
||||
state_next = STATE_HEADER;
|
||||
end else begin
|
||||
state_next = STATE_IDLE;
|
||||
end
|
||||
end
|
||||
end
|
||||
STATE_HEADER: begin
|
||||
// header state, store rest of header (64 bit interface only)
|
||||
s_axis_cq_tready_next = m_axi_wready_int_early;
|
||||
|
||||
if (s_axis_cq_tready && s_axis_cq_tvalid) begin
|
||||
transfer_in_save = 1'b1;
|
||||
|
||||
// header fields
|
||||
op_dword_count_next = s_axis_cq_tdata[10:0];
|
||||
type_next = s_axis_cq_tdata[14:11];
|
||||
|
||||
if (op_dword_count_next == 1) begin
|
||||
// use first_be for both byte enables for single DWORD transfers
|
||||
last_be_next = first_be_reg;
|
||||
end
|
||||
|
||||
if (op_dword_count_next <= AXI_MAX_BURST_SIZE/4) begin
|
||||
// packet smaller than max burst size (only for 64 bits)
|
||||
// assumed to not cross 4k boundary, send one request
|
||||
tr_dword_count_next = op_dword_count_next;
|
||||
end else begin
|
||||
// packet larger than max burst size
|
||||
// assumed to not cross 4k boundary, send one request
|
||||
tr_dword_count_next = AXI_MAX_BURST_SIZE/4 - axi_addr_reg[OFFSET_WIDTH+2-1:2];
|
||||
end
|
||||
|
||||
// required DWORD shift to place first DWORD from the TLP payload into proper position on AXI interface
|
||||
// bubble cycle required if first TLP payload transfer does not fill first AXI transfer
|
||||
offset_next = axi_addr_reg[OFFSET_WIDTH+2-1:2];
|
||||
bubble_cycle_next = 1'b0;
|
||||
first_cycle_offset_next = axi_addr_reg[OFFSET_WIDTH+2-1:2];
|
||||
first_cycle_next = 1'b1;
|
||||
|
||||
// number of bus transfers in TLP, DOWRD count plus payload start DWORD offset, divided by bus width in DWORDS
|
||||
input_cycle_count_next = (tr_dword_count_next - 1) >> (AXI_BURST_SIZE-2);
|
||||
// number of bus transfers to AXI, DWORD count plus DWORD offset, divided by bus width in DWORDS
|
||||
output_cycle_count_next = (tr_dword_count_next + axi_addr_reg[OFFSET_WIDTH+2-1:2] - 1) >> (AXI_BURST_SIZE-2);
|
||||
last_cycle_offset_next = axi_addr_reg[OFFSET_WIDTH+2-1:2] + tr_dword_count_next;
|
||||
last_cycle_next = output_cycle_count_next == 0;
|
||||
input_active_next = 1'b1;
|
||||
|
||||
m_axi_awaddr_next = axi_addr_reg;
|
||||
m_axi_awlen_next = output_cycle_count_next;
|
||||
|
||||
axi_addr_next = axi_addr_reg + (tr_dword_count_next << 2);
|
||||
op_dword_count_next = op_dword_count_next - tr_dword_count_next;
|
||||
|
||||
if (type_next == REQ_MEM_WRITE) begin
|
||||
// write request
|
||||
m_axi_awvalid_next = 1'b1;
|
||||
s_axis_cq_tready_next = m_axi_wready_int_early;
|
||||
state_next = STATE_TRANSFER;
|
||||
end else begin
|
||||
// invalid request
|
||||
status_error_uncor_next = 1'b1;
|
||||
if (s_axis_cq_tlast) begin
|
||||
state_next = STATE_IDLE;
|
||||
end else begin
|
||||
s_axis_cq_tready_next = 1'b1;
|
||||
state_next = STATE_WAIT_END;
|
||||
end
|
||||
end
|
||||
end else begin
|
||||
state_next = STATE_HEADER;
|
||||
end
|
||||
end
|
||||
STATE_TRANSFER: begin
|
||||
// transfer state, transfer data
|
||||
s_axis_cq_tready_next = m_axi_wready_int_early && input_active_reg && !(AXIS_PCIE_DATA_WIDTH == 256 && first_cycle_reg && !bubble_cycle_reg);
|
||||
|
||||
if (m_axi_wready_int_reg && ((s_axis_cq_tready && s_axis_cq_tvalid) || !input_active_reg || (AXIS_PCIE_DATA_WIDTH == 256 && first_cycle_reg && !bubble_cycle_reg))) begin
|
||||
transfer_in_save = s_axis_cq_tready && s_axis_cq_tvalid;
|
||||
|
||||
// transfer data
|
||||
if (AXIS_PCIE_DATA_WIDTH == 256 && first_cycle_reg && !bubble_cycle_reg) begin
|
||||
m_axi_wdata_int = {save_axis_tdata_reg, {AXIS_PCIE_DATA_WIDTH{1'b0}}} >> ((AXI_STRB_WIDTH/4-offset_reg)*32);
|
||||
s_axis_cq_tready_next = m_axi_wready_int_early && input_active_reg;
|
||||
end else begin
|
||||
m_axi_wdata_int = shift_axis_tdata;
|
||||
end
|
||||
// generate strb signal
|
||||
if (first_cycle_reg) begin
|
||||
m_axi_wstrb_int = {{AXI_STRB_WIDTH-4{1'b1}}, first_be_reg} << (first_cycle_offset_reg*4);
|
||||
end else begin
|
||||
m_axi_wstrb_int = {AXI_STRB_WIDTH{1'b1}};
|
||||
end
|
||||
|
||||
// update cycle counters
|
||||
if (input_active_reg && !(AXIS_PCIE_DATA_WIDTH == 256 && first_cycle_reg && !bubble_cycle_reg)) begin
|
||||
input_cycle_count_next = input_cycle_count_reg - 1;
|
||||
input_active_next = input_cycle_count_reg > 0;
|
||||
end
|
||||
output_cycle_count_next = output_cycle_count_reg - 1;
|
||||
last_cycle_next = output_cycle_count_next == 0;
|
||||
|
||||
// modify strb signal at end of transfer
|
||||
if (last_cycle_reg) begin
|
||||
if (op_dword_count_reg == 0) begin
|
||||
if (last_cycle_offset_reg > 0) begin
|
||||
m_axi_wstrb_int = m_axi_wstrb_int & {last_be_reg, {AXI_STRB_WIDTH-4{1'b1}}} >> (AXI_STRB_WIDTH-last_cycle_offset_reg*4);
|
||||
end else begin
|
||||
m_axi_wstrb_int = m_axi_wstrb_int & {last_be_reg, {AXI_STRB_WIDTH-4{1'b1}}};
|
||||
end
|
||||
end
|
||||
m_axi_wlast_int = 1'b1;
|
||||
end
|
||||
m_axi_wvalid_int = 1'b1;
|
||||
first_cycle_next = 1'b0;
|
||||
if (!last_cycle_reg) begin
|
||||
s_axis_cq_tready_next = m_axi_wready_int_early && input_active_next;
|
||||
state_next = STATE_TRANSFER;
|
||||
end else if (op_dword_count_reg > 0) begin
|
||||
// current transfer done, but operation not finished yet
|
||||
if (op_dword_count_reg <= AXI_MAX_BURST_SIZE/4) begin
|
||||
// packet smaller than max burst size
|
||||
// assumed to not cross 4k boundary, send one request
|
||||
tr_dword_count_next = op_dword_count_reg;
|
||||
m_axi_awlen_next = (tr_dword_count_next + axi_addr_reg[OFFSET_WIDTH+2-1:2] - 1) >> (AXI_BURST_SIZE-2);
|
||||
end else begin
|
||||
// packet larger than max burst size
|
||||
// assumed to not cross 4k boundary, send one request
|
||||
tr_dword_count_next = AXI_MAX_BURST_SIZE/4 - axi_addr_reg[OFFSET_WIDTH+2-1:2];
|
||||
m_axi_awlen_next = (tr_dword_count_next - 1) >> (AXI_BURST_SIZE-2);
|
||||
end
|
||||
|
||||
m_axi_awaddr_next = axi_addr_reg;
|
||||
|
||||
// keep offset, no bubble cycles, not first cycle
|
||||
bubble_cycle_next = 1'b0;
|
||||
first_cycle_next = 1'b0;
|
||||
|
||||
// number of bus transfers in TLP, DOWRD count minus payload start DWORD offset, divided by bus width in DWORDS
|
||||
input_cycle_count_next = (tr_dword_count_next - offset_reg - 1) >> (AXI_BURST_SIZE-2);
|
||||
// number of bus transfers to AXI, DWORD count plus DWORD offset, divided by bus width in DWORDS
|
||||
output_cycle_count_next = (tr_dword_count_next + axi_addr_reg[OFFSET_WIDTH+2-1:2] - 1) >> (AXI_BURST_SIZE-2);
|
||||
last_cycle_offset_next = axi_addr_reg[OFFSET_WIDTH+2-1:2] + tr_dword_count_next;
|
||||
last_cycle_next = output_cycle_count_next == 0;
|
||||
input_active_next = tr_dword_count_next > offset_reg;
|
||||
|
||||
axi_addr_next = axi_addr_reg + (tr_dword_count_next << 2);
|
||||
op_dword_count_next = op_dword_count_reg - tr_dword_count_next;
|
||||
|
||||
m_axi_awvalid_next = 1'b1;
|
||||
s_axis_cq_tready_next = m_axi_wready_int_early && input_active_next;
|
||||
state_next = STATE_TRANSFER;
|
||||
end else begin
|
||||
s_axis_cq_tready_next = m_axi_wready_int_early && (!m_axi_awvalid || m_axi_awready);
|
||||
state_next = STATE_IDLE;
|
||||
end
|
||||
end else begin
|
||||
state_next = STATE_TRANSFER;
|
||||
end
|
||||
end
|
||||
STATE_WAIT_END: begin
|
||||
// wait end state, wait for end of TLP
|
||||
s_axis_cq_tready_next = 1'b1;
|
||||
|
||||
if (s_axis_cq_tready & s_axis_cq_tvalid) begin
|
||||
if (s_axis_cq_tlast) begin
|
||||
if (AXIS_PCIE_DATA_WIDTH > 64) begin
|
||||
s_axis_cq_tready_next = m_axi_wready_int_early && (!m_axi_awvalid || m_axi_awready);
|
||||
end else begin
|
||||
s_axis_cq_tready_next = 1'b1;
|
||||
end
|
||||
state_next = STATE_IDLE;
|
||||
end else begin
|
||||
state_next = STATE_WAIT_END;
|
||||
end
|
||||
end else begin
|
||||
state_next = STATE_WAIT_END;
|
||||
end
|
||||
end
|
||||
endcase
|
||||
end
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (rst) begin
|
||||
state_reg <= STATE_IDLE;
|
||||
s_axis_cq_tready_reg <= 1'b0;
|
||||
|
||||
m_axi_awvalid_reg <= 1'b0;
|
||||
|
||||
status_error_uncor_reg <= 1'b0;
|
||||
end else begin
|
||||
state_reg <= state_next;
|
||||
s_axis_cq_tready_reg <= s_axis_cq_tready_next;
|
||||
|
||||
m_axi_awvalid_reg <= m_axi_awvalid_next;
|
||||
|
||||
status_error_uncor_reg <= status_error_uncor_next;
|
||||
end
|
||||
|
||||
axi_addr_reg <= axi_addr_next;
|
||||
op_dword_count_reg <= op_dword_count_next;
|
||||
tr_dword_count_reg <= tr_dword_count_next;
|
||||
input_cycle_count_reg <= input_cycle_count_next;
|
||||
output_cycle_count_reg <= output_cycle_count_next;
|
||||
input_active_reg <= input_active_next;
|
||||
bubble_cycle_reg <= bubble_cycle_next;
|
||||
first_cycle_reg <= first_cycle_next;
|
||||
last_cycle_reg <= last_cycle_next;
|
||||
|
||||
type_reg <= type_next;
|
||||
first_be_reg <= first_be_next;
|
||||
last_be_reg <= last_be_next;
|
||||
offset_reg <= offset_next;
|
||||
first_cycle_offset_reg <= first_cycle_offset_next;
|
||||
last_cycle_offset_reg <= last_cycle_offset_next;
|
||||
|
||||
m_axi_awaddr_reg <= m_axi_awaddr_next;
|
||||
m_axi_awlen_reg <= m_axi_awlen_next;
|
||||
|
||||
if (transfer_in_save) begin
|
||||
save_axis_tdata_reg <= s_axis_cq_tdata;
|
||||
end
|
||||
end
|
||||
|
||||
// output datapath logic (AXI write data)
|
||||
reg [AXI_DATA_WIDTH-1:0] m_axi_wdata_reg = {AXI_DATA_WIDTH{1'b0}};
|
||||
reg [AXI_STRB_WIDTH-1:0] m_axi_wstrb_reg = {AXI_STRB_WIDTH{1'b0}};
|
||||
reg m_axi_wvalid_reg = 1'b0, m_axi_wvalid_next;
|
||||
reg m_axi_wlast_reg = 1'b0;
|
||||
|
||||
reg [AXI_DATA_WIDTH-1:0] temp_m_axi_wdata_reg = {AXI_DATA_WIDTH{1'b0}};
|
||||
reg [AXI_STRB_WIDTH-1:0] temp_m_axi_wstrb_reg = {AXI_STRB_WIDTH{1'b0}};
|
||||
reg temp_m_axi_wvalid_reg = 1'b0, temp_m_axi_wvalid_next;
|
||||
reg temp_m_axi_wlast_reg = 1'b0;
|
||||
|
||||
// datapath control
|
||||
reg store_axi_w_int_to_output;
|
||||
reg store_axi_w_int_to_temp;
|
||||
reg store_axi_w_temp_to_output;
|
||||
|
||||
assign m_axi_wdata = m_axi_wdata_reg;
|
||||
assign m_axi_wstrb = m_axi_wstrb_reg;
|
||||
assign m_axi_wvalid = m_axi_wvalid_reg;
|
||||
assign m_axi_wlast = m_axi_wlast_reg;
|
||||
|
||||
// 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)
|
||||
assign m_axi_wready_int_early = m_axi_wready || (!temp_m_axi_wvalid_reg && (!m_axi_wvalid_reg || !m_axi_wvalid_int));
|
||||
|
||||
always @* begin
|
||||
// transfer sink ready state to source
|
||||
m_axi_wvalid_next = m_axi_wvalid_reg;
|
||||
temp_m_axi_wvalid_next = temp_m_axi_wvalid_reg;
|
||||
|
||||
store_axi_w_int_to_output = 1'b0;
|
||||
store_axi_w_int_to_temp = 1'b0;
|
||||
store_axi_w_temp_to_output = 1'b0;
|
||||
|
||||
if (m_axi_wready_int_reg) begin
|
||||
// input is ready
|
||||
if (m_axi_wready || !m_axi_wvalid_reg) begin
|
||||
// output is ready or currently not valid, transfer data to output
|
||||
m_axi_wvalid_next = m_axi_wvalid_int;
|
||||
store_axi_w_int_to_output = 1'b1;
|
||||
end else begin
|
||||
// output is not ready, store input in temp
|
||||
temp_m_axi_wvalid_next = m_axi_wvalid_int;
|
||||
store_axi_w_int_to_temp = 1'b1;
|
||||
end
|
||||
end else if (m_axi_wready) begin
|
||||
// input is not ready, but output is ready
|
||||
m_axi_wvalid_next = temp_m_axi_wvalid_reg;
|
||||
temp_m_axi_wvalid_next = 1'b0;
|
||||
store_axi_w_temp_to_output = 1'b1;
|
||||
end
|
||||
end
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (rst) begin
|
||||
m_axi_wvalid_reg <= 1'b0;
|
||||
m_axi_wready_int_reg <= 1'b0;
|
||||
temp_m_axi_wvalid_reg <= 1'b0;
|
||||
end else begin
|
||||
m_axi_wvalid_reg <= m_axi_wvalid_next;
|
||||
m_axi_wready_int_reg <= m_axi_wready_int_early;
|
||||
temp_m_axi_wvalid_reg <= temp_m_axi_wvalid_next;
|
||||
end
|
||||
|
||||
// datapath
|
||||
if (store_axi_w_int_to_output) begin
|
||||
m_axi_wdata_reg <= m_axi_wdata_int;
|
||||
m_axi_wstrb_reg <= m_axi_wstrb_int;
|
||||
m_axi_wlast_reg <= m_axi_wlast_int;
|
||||
end else if (store_axi_w_temp_to_output) begin
|
||||
m_axi_wdata_reg <= temp_m_axi_wdata_reg;
|
||||
m_axi_wstrb_reg <= temp_m_axi_wstrb_reg;
|
||||
m_axi_wlast_reg <= temp_m_axi_wlast_reg;
|
||||
end
|
||||
|
||||
if (store_axi_w_int_to_temp) begin
|
||||
temp_m_axi_wdata_reg <= m_axi_wdata_int;
|
||||
temp_m_axi_wstrb_reg <= m_axi_wstrb_int;
|
||||
temp_m_axi_wlast_reg <= m_axi_wlast_int;
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
846
fpga/lib/pcie/rtl/pcie_us_axil_master.v
Normal file
846
fpga/lib/pcie/rtl/pcie_us_axil_master.v
Normal file
@ -0,0 +1,846 @@
|
||||
/*
|
||||
|
||||
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
|
||||
|
||||
/*
|
||||
* Ultrascale PCIe AXI Lite Master
|
||||
*/
|
||||
module pcie_us_axil_master #
|
||||
(
|
||||
parameter AXIS_PCIE_DATA_WIDTH = 256,
|
||||
parameter AXIS_PCIE_KEEP_WIDTH = (AXIS_PCIE_DATA_WIDTH/32),
|
||||
parameter AXI_DATA_WIDTH = 32,
|
||||
parameter AXI_ADDR_WIDTH = 64,
|
||||
parameter AXI_STRB_WIDTH = (AXI_DATA_WIDTH/8),
|
||||
parameter ENABLE_PARITY = 0
|
||||
)
|
||||
(
|
||||
input wire clk,
|
||||
input wire rst,
|
||||
|
||||
/*
|
||||
* AXI input (CQ)
|
||||
*/
|
||||
input wire [AXIS_PCIE_DATA_WIDTH-1:0] s_axis_cq_tdata,
|
||||
input wire [AXIS_PCIE_KEEP_WIDTH-1:0] s_axis_cq_tkeep,
|
||||
input wire s_axis_cq_tvalid,
|
||||
output wire s_axis_cq_tready,
|
||||
input wire s_axis_cq_tlast,
|
||||
input wire [84:0] s_axis_cq_tuser,
|
||||
|
||||
/*
|
||||
* AXI output (CC)
|
||||
*/
|
||||
output wire [AXIS_PCIE_DATA_WIDTH-1:0] m_axis_cc_tdata,
|
||||
output wire [AXIS_PCIE_KEEP_WIDTH-1:0] m_axis_cc_tkeep,
|
||||
output wire m_axis_cc_tvalid,
|
||||
input wire m_axis_cc_tready,
|
||||
output wire m_axis_cc_tlast,
|
||||
output wire [32:0] m_axis_cc_tuser,
|
||||
|
||||
/*
|
||||
* AXI Lite Master output
|
||||
*/
|
||||
output wire [AXI_ADDR_WIDTH-1:0] m_axil_awaddr,
|
||||
output wire [2:0] m_axil_awprot,
|
||||
output wire m_axil_awvalid,
|
||||
input wire m_axil_awready,
|
||||
output wire [AXI_DATA_WIDTH-1:0] m_axil_wdata,
|
||||
output wire [AXI_STRB_WIDTH-1:0] m_axil_wstrb,
|
||||
output wire m_axil_wvalid,
|
||||
input wire m_axil_wready,
|
||||
input wire [1:0] m_axil_bresp,
|
||||
input wire m_axil_bvalid,
|
||||
output wire m_axil_bready,
|
||||
output wire [AXI_ADDR_WIDTH-1:0] m_axil_araddr,
|
||||
output wire [2:0] m_axil_arprot,
|
||||
output wire m_axil_arvalid,
|
||||
input wire m_axil_arready,
|
||||
input wire [AXI_DATA_WIDTH-1:0] m_axil_rdata,
|
||||
input wire [1:0] m_axil_rresp,
|
||||
input wire m_axil_rvalid,
|
||||
output wire m_axil_rready,
|
||||
|
||||
/*
|
||||
* Configuration
|
||||
*/
|
||||
input wire [15:0] completer_id,
|
||||
input wire completer_id_enable,
|
||||
|
||||
/*
|
||||
* Status
|
||||
*/
|
||||
output wire status_error_cor,
|
||||
output wire status_error_uncor
|
||||
);
|
||||
|
||||
// bus width assertions
|
||||
initial begin
|
||||
if (AXIS_PCIE_DATA_WIDTH != 64 && AXIS_PCIE_DATA_WIDTH != 128 && AXIS_PCIE_DATA_WIDTH != 256) begin
|
||||
$error("Error: PCIe interface width must be 64, 128, or 256");
|
||||
$finish;
|
||||
end
|
||||
|
||||
if (AXIS_PCIE_KEEP_WIDTH * 32 != AXIS_PCIE_DATA_WIDTH) begin
|
||||
$error("Error: PCIe interface requires dword (32-bit) granularity");
|
||||
$finish;
|
||||
end
|
||||
|
||||
if (AXI_DATA_WIDTH != 32) begin
|
||||
$error("Error: AXI interface width must be 32");
|
||||
$finish;
|
||||
end
|
||||
|
||||
if (AXI_STRB_WIDTH * 8 != AXI_DATA_WIDTH) begin
|
||||
$error("Error: AXI interface requires byte (8-bit) granularity");
|
||||
$finish;
|
||||
end
|
||||
end
|
||||
|
||||
localparam [3:0]
|
||||
REQ_MEM_READ = 4'b0000,
|
||||
REQ_MEM_WRITE = 4'b0001,
|
||||
REQ_IO_READ = 4'b0010,
|
||||
REQ_IO_WRITE = 4'b0011,
|
||||
REQ_MEM_FETCH_ADD = 4'b0100,
|
||||
REQ_MEM_SWAP = 4'b0101,
|
||||
REQ_MEM_CAS = 4'b0110,
|
||||
REQ_MEM_READ_LOCKED = 4'b0111,
|
||||
REQ_CFG_READ_0 = 4'b1000,
|
||||
REQ_CFG_READ_1 = 4'b1001,
|
||||
REQ_CFG_WRITE_0 = 4'b1010,
|
||||
REQ_CFG_WRITE_1 = 4'b1011,
|
||||
REQ_MSG = 4'b1100,
|
||||
REQ_MSG_VENDOR = 4'b1101,
|
||||
REQ_MSG_ATS = 4'b1110;
|
||||
|
||||
localparam [2:0]
|
||||
CPL_STATUS_SC = 3'b000, // successful completion
|
||||
CPL_STATUS_UR = 3'b001, // unsupported request
|
||||
CPL_STATUS_CRS = 3'b010, // configuration request retry status
|
||||
CPL_STATUS_CA = 3'b100; // completer abort
|
||||
|
||||
localparam [2:0]
|
||||
STATE_IDLE = 3'd0,
|
||||
STATE_HEADER = 3'd1,
|
||||
STATE_READ = 3'd2,
|
||||
STATE_WRITE_1 = 3'd3,
|
||||
STATE_WRITE_2 = 3'd4,
|
||||
STATE_WAIT_END = 3'd5,
|
||||
STATE_CPL_1 = 3'd6,
|
||||
STATE_CPL_2 = 3'd7;
|
||||
|
||||
reg [2:0] state_reg = STATE_IDLE, state_next;
|
||||
|
||||
reg [1:0] at_reg = 2'd0, at_next;
|
||||
reg [10:0] dword_count_reg = 11'd0, dword_count_next;
|
||||
reg [3:0] type_reg = 4'd0, type_next;
|
||||
reg [2:0] status_reg = 3'b000, status_next;
|
||||
reg [15:0] requester_id_reg = 16'd0, requester_id_next;
|
||||
reg [7:0] tag_reg = 7'd0, tag_next;
|
||||
reg [2:0] tc_reg = 3'd0, tc_next;
|
||||
reg [2:0] attr_reg = 3'd0, attr_next;
|
||||
reg [3:0] first_be_reg = 4'd0, first_be_next;
|
||||
reg [3:0] last_be_reg = 4'd0, last_be_next;
|
||||
reg cpl_data_reg = 1'b0, cpl_data_next;
|
||||
|
||||
reg s_axis_cq_tready_reg = 1'b0, s_axis_cq_tready_next;
|
||||
|
||||
reg [AXI_ADDR_WIDTH-1:0] m_axil_addr_reg = {AXI_ADDR_WIDTH{1'b0}}, m_axil_addr_next;
|
||||
reg m_axil_awvalid_reg = 1'b0, m_axil_awvalid_next;
|
||||
reg [AXI_DATA_WIDTH-1:0] m_axil_wdata_reg = {AXI_DATA_WIDTH{1'b0}}, m_axil_wdata_next;
|
||||
reg [AXI_STRB_WIDTH-1:0] m_axil_wstrb_reg = {AXI_STRB_WIDTH{1'b0}}, m_axil_wstrb_next;
|
||||
reg m_axil_wvalid_reg = 1'b0, m_axil_wvalid_next;
|
||||
reg m_axil_bready_reg = 1'b0, m_axil_bready_next;
|
||||
reg m_axil_arvalid_reg = 1'b0, m_axil_arvalid_next;
|
||||
reg m_axil_rready_reg = 1'b0, m_axil_rready_next;
|
||||
|
||||
reg status_error_cor_reg = 1'b0, status_error_cor_next;
|
||||
reg status_error_uncor_reg = 1'b0, status_error_uncor_next;
|
||||
|
||||
// internal datapath
|
||||
reg [AXIS_PCIE_DATA_WIDTH-1:0] m_axis_cc_tdata_int;
|
||||
reg [AXIS_PCIE_KEEP_WIDTH-1:0] m_axis_cc_tkeep_int;
|
||||
reg m_axis_cc_tvalid_int;
|
||||
reg m_axis_cc_tready_int_reg = 1'b0;
|
||||
reg m_axis_cc_tlast_int;
|
||||
reg [32:0] m_axis_cc_tuser_int;
|
||||
wire m_axis_cc_tready_int_early;
|
||||
|
||||
assign s_axis_cq_tready = s_axis_cq_tready_reg;
|
||||
|
||||
assign m_axil_awaddr = m_axil_addr_reg;
|
||||
assign m_axil_awprot = 3'b010;
|
||||
assign m_axil_awvalid = m_axil_awvalid_reg;
|
||||
assign m_axil_wdata = m_axil_wdata_reg;
|
||||
assign m_axil_wstrb = m_axil_wstrb_reg;
|
||||
assign m_axil_wvalid = m_axil_wvalid_reg;
|
||||
assign m_axil_bready = m_axil_bready_reg;
|
||||
assign m_axil_araddr = m_axil_addr_reg;
|
||||
assign m_axil_arprot = 3'b010;
|
||||
assign m_axil_arvalid = m_axil_arvalid_reg;
|
||||
assign m_axil_rready = m_axil_rready_reg;
|
||||
|
||||
assign status_error_cor = status_error_cor_reg;
|
||||
assign status_error_uncor = status_error_uncor_reg;
|
||||
|
||||
always @* begin
|
||||
state_next = STATE_IDLE;
|
||||
|
||||
s_axis_cq_tready_next = 1'b0;
|
||||
|
||||
at_next = at_reg;
|
||||
dword_count_next = dword_count_reg;
|
||||
type_next = type_reg;
|
||||
status_next = status_reg;
|
||||
requester_id_next = requester_id_reg;
|
||||
tag_next = tag_reg;
|
||||
tc_next = tc_reg;
|
||||
attr_next = attr_reg;
|
||||
first_be_next = first_be_reg;
|
||||
last_be_next = last_be_reg;
|
||||
cpl_data_next = cpl_data_reg;
|
||||
|
||||
m_axis_cc_tdata_int = {AXIS_PCIE_DATA_WIDTH{1'b0}};
|
||||
m_axis_cc_tkeep_int = {AXIS_PCIE_KEEP_WIDTH{1'b0}};
|
||||
m_axis_cc_tvalid_int = 1'b0;
|
||||
m_axis_cc_tlast_int = 1'b0;
|
||||
m_axis_cc_tuser_int = 33'd0;
|
||||
|
||||
casez (first_be_reg)
|
||||
4'b0000: m_axis_cc_tdata_int[6:0] = {m_axil_addr_reg[6:2], 2'b00}; // lower address
|
||||
4'bzzz1: m_axis_cc_tdata_int[6:0] = {m_axil_addr_reg[6:2], 2'b00}; // lower address
|
||||
4'bzz10: m_axis_cc_tdata_int[6:0] = {m_axil_addr_reg[6:2], 2'b01}; // lower address
|
||||
4'bz100: m_axis_cc_tdata_int[6:0] = {m_axil_addr_reg[6:2], 2'b10}; // lower address
|
||||
4'b1000: m_axis_cc_tdata_int[6:0] = {m_axil_addr_reg[6:2], 2'b11}; // lower address
|
||||
endcase
|
||||
m_axis_cc_tdata_int[9:8] = at_reg;
|
||||
casez (first_be_reg)
|
||||
4'b0000: m_axis_cc_tdata_int[28:16] = 13'd0; // Byte count
|
||||
4'b0001: m_axis_cc_tdata_int[28:16] = 13'd1; // Byte count
|
||||
4'b0010: m_axis_cc_tdata_int[28:16] = 13'd1; // Byte count
|
||||
4'b0100: m_axis_cc_tdata_int[28:16] = 13'd1; // Byte count
|
||||
4'b1000: m_axis_cc_tdata_int[28:16] = 13'd1; // Byte count
|
||||
4'b0011: m_axis_cc_tdata_int[28:16] = 13'd2; // Byte count
|
||||
4'b0110: m_axis_cc_tdata_int[28:16] = 13'd2; // Byte count
|
||||
4'b1100: m_axis_cc_tdata_int[28:16] = 13'd2; // Byte count
|
||||
4'b01z1: m_axis_cc_tdata_int[28:16] = 13'd3; // Byte count
|
||||
4'b1z10: m_axis_cc_tdata_int[28:16] = 13'd3; // Byte count
|
||||
4'b1zz1: m_axis_cc_tdata_int[28:16] = 13'd4; // Byte count
|
||||
endcase
|
||||
m_axis_cc_tdata_int[42:32] = 11'd1; // DWORD count
|
||||
m_axis_cc_tdata_int[45:43] = status_reg;
|
||||
m_axis_cc_tdata_int[63:48] = requester_id_reg;
|
||||
if (AXIS_PCIE_DATA_WIDTH > 64) begin
|
||||
m_axis_cc_tdata_int[71:64] = tag_reg;
|
||||
m_axis_cc_tdata_int[87:72] = completer_id;
|
||||
m_axis_cc_tdata_int[88] = completer_id_enable;
|
||||
m_axis_cc_tdata_int[91:89] = tc_reg;
|
||||
m_axis_cc_tdata_int[94:92] = attr_reg;
|
||||
m_axis_cc_tdata_int[95] = 1'b0; // force ECRC
|
||||
m_axis_cc_tdata_int[127:96] = m_axil_rdata;
|
||||
end
|
||||
|
||||
m_axis_cc_tuser_int[0] = 1'b0; // discontinue
|
||||
m_axis_cc_tuser_int[32:1] = 32'd0; // parity
|
||||
if (AXIS_PCIE_DATA_WIDTH == 256) begin
|
||||
m_axis_cc_tkeep_int = 8'b00001111;
|
||||
end else if (AXIS_PCIE_DATA_WIDTH == 128) begin
|
||||
m_axis_cc_tkeep_int = 4'b1111;
|
||||
end else if (AXIS_PCIE_DATA_WIDTH == 64) begin
|
||||
m_axis_cc_tkeep_int = 2'b11;
|
||||
end
|
||||
|
||||
m_axil_addr_next = m_axil_addr_reg;
|
||||
m_axil_awvalid_next = m_axil_awvalid_reg && !m_axil_awready;
|
||||
m_axil_wdata_next = m_axil_wdata_reg;
|
||||
m_axil_wstrb_next = m_axil_wstrb_reg;
|
||||
m_axil_wvalid_next = m_axil_wvalid_reg && !m_axil_wready;
|
||||
m_axil_bready_next = 1'b0;
|
||||
m_axil_arvalid_next = m_axil_arvalid_reg && !m_axil_arready;
|
||||
m_axil_rready_next = 1'b0;
|
||||
|
||||
status_error_cor_next = 1'b0;
|
||||
status_error_uncor_next = 1'b0;
|
||||
|
||||
case (state_reg)
|
||||
STATE_IDLE: begin
|
||||
// idle state, wait for completion request
|
||||
s_axis_cq_tready_next = m_axis_cc_tready_int_early;
|
||||
|
||||
if (s_axis_cq_tready && s_axis_cq_tvalid) begin
|
||||
// header fields
|
||||
at_next = s_axis_cq_tdata[1:0];
|
||||
m_axil_addr_next = {s_axis_cq_tdata[63:2], 2'b00};
|
||||
if (AXIS_PCIE_DATA_WIDTH > 64) begin
|
||||
dword_count_next = s_axis_cq_tdata[74:64];
|
||||
type_next = s_axis_cq_tdata[78:75];
|
||||
requester_id_next = s_axis_cq_tdata[95:80];
|
||||
tag_next = s_axis_cq_tdata[103:96];
|
||||
tc_next = s_axis_cq_tdata[123:121];
|
||||
attr_next = s_axis_cq_tdata[126:124];
|
||||
|
||||
// data
|
||||
if (AXIS_PCIE_DATA_WIDTH == 256) begin
|
||||
m_axil_wdata_next = s_axis_cq_tdata[159:128];
|
||||
end
|
||||
end
|
||||
|
||||
// tuser fields
|
||||
first_be_next = s_axis_cq_tuser[3:0];
|
||||
last_be_next = s_axis_cq_tuser[7:4];
|
||||
|
||||
m_axil_wstrb_next = first_be_next;
|
||||
|
||||
status_next = CPL_STATUS_SC; // successful completion
|
||||
|
||||
if (AXIS_PCIE_DATA_WIDTH == 64) begin
|
||||
if (s_axis_cq_tlast) begin
|
||||
// truncated packet
|
||||
// report uncorrectable error
|
||||
status_error_uncor_next = 1'b1;
|
||||
state_next = STATE_IDLE;
|
||||
end else begin
|
||||
state_next = STATE_HEADER;
|
||||
end
|
||||
end else begin
|
||||
if (type_next == REQ_MEM_READ || type_next == REQ_IO_READ) begin
|
||||
// read request
|
||||
if (s_axis_cq_tlast && dword_count_next == 11'd1) begin
|
||||
m_axil_arvalid_next = 1'b1;
|
||||
m_axil_rready_next = m_axis_cc_tready_int_early;
|
||||
s_axis_cq_tready_next = 1'b0;
|
||||
state_next = STATE_READ;
|
||||
end else begin
|
||||
// bad length
|
||||
status_next = CPL_STATUS_CA; // completer abort
|
||||
// report correctable error
|
||||
status_error_cor_next = 1'b1;
|
||||
if (s_axis_cq_tlast) begin
|
||||
s_axis_cq_tready_next = 1'b0;
|
||||
state_next = STATE_CPL_1;
|
||||
end else begin
|
||||
s_axis_cq_tready_next = 1'b1;
|
||||
state_next = STATE_WAIT_END;
|
||||
end
|
||||
end
|
||||
end else if (type_next == REQ_MEM_WRITE || type_next == REQ_IO_WRITE) begin
|
||||
// write request
|
||||
if (AXIS_PCIE_DATA_WIDTH == 256 && s_axis_cq_tlast && dword_count_next == 11'd1) begin
|
||||
m_axil_awvalid_next = 1'b1;
|
||||
m_axil_wvalid_next = 1'b1;
|
||||
m_axil_bready_next = 1'b1;
|
||||
s_axis_cq_tready_next = 1'b0;
|
||||
state_next = STATE_WRITE_2;
|
||||
end else if (AXIS_PCIE_DATA_WIDTH < 256 && dword_count_next == 11'd1) begin
|
||||
s_axis_cq_tready_next = 1'b1;
|
||||
state_next = STATE_WRITE_1;
|
||||
end else begin
|
||||
// bad length
|
||||
status_next = CPL_STATUS_CA; // completer abort
|
||||
if (type_next == REQ_MEM_WRITE) begin
|
||||
// memory write - posted, no completion
|
||||
// report uncorrectable error
|
||||
status_error_uncor_next = 1'b1;
|
||||
if (s_axis_cq_tlast) begin
|
||||
s_axis_cq_tready_next = m_axis_cc_tready_int_early;
|
||||
state_next = STATE_IDLE;
|
||||
end else begin
|
||||
s_axis_cq_tready_next = 1'b1;
|
||||
state_next = STATE_WAIT_END;
|
||||
end
|
||||
end else begin
|
||||
// IO write - non-posted, send completion
|
||||
// report correctable error
|
||||
status_error_cor_next = 1'b1;
|
||||
if (s_axis_cq_tlast) begin
|
||||
s_axis_cq_tready_next = 1'b0;
|
||||
state_next = STATE_CPL_1;
|
||||
end else begin
|
||||
s_axis_cq_tready_next = 1'b1;
|
||||
state_next = STATE_WAIT_END;
|
||||
end
|
||||
end
|
||||
end
|
||||
end else begin
|
||||
// other request
|
||||
status_next = CPL_STATUS_UR; // unsupported request
|
||||
if (type_next == REQ_MEM_WRITE || (type_next & 4'b1100) == 4'b1100) begin
|
||||
// memory write or message - posted, no completion
|
||||
// report uncorrectable error
|
||||
status_error_uncor_next = 1'b1;
|
||||
if (s_axis_cq_tlast) begin
|
||||
s_axis_cq_tready_next = m_axis_cc_tready_int_early;
|
||||
state_next = STATE_IDLE;
|
||||
end else begin
|
||||
s_axis_cq_tready_next = 1'b1;
|
||||
state_next = STATE_WAIT_END;
|
||||
end
|
||||
end else begin
|
||||
// other non-posted request, send UR completion
|
||||
// report correctable error
|
||||
status_error_cor_next = 1'b1;
|
||||
if (s_axis_cq_tlast) begin
|
||||
s_axis_cq_tready_next = 1'b0;
|
||||
state_next = STATE_CPL_1;
|
||||
end else begin
|
||||
s_axis_cq_tready_next = 1'b1;
|
||||
state_next = STATE_WAIT_END;
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end else begin
|
||||
state_next = STATE_IDLE;
|
||||
end
|
||||
end
|
||||
STATE_HEADER: begin
|
||||
// header state, handle header (64 bit interface only)
|
||||
s_axis_cq_tready_next = m_axis_cc_tready_int_early;
|
||||
|
||||
// header fields
|
||||
dword_count_next = s_axis_cq_tdata[10:0];
|
||||
type_next = s_axis_cq_tdata[14:11];
|
||||
requester_id_next = s_axis_cq_tdata[31:16];
|
||||
tag_next = s_axis_cq_tdata[39:32];
|
||||
tc_next = s_axis_cq_tdata[59:57];
|
||||
attr_next = s_axis_cq_tdata[62:60];
|
||||
|
||||
// data
|
||||
m_axil_wstrb_next = first_be_reg;
|
||||
|
||||
if (s_axis_cq_tready && s_axis_cq_tvalid) begin
|
||||
if (type_next == REQ_MEM_READ || type_next == REQ_IO_READ) begin
|
||||
// read request
|
||||
if (s_axis_cq_tlast && dword_count_next == 11'd1) begin
|
||||
m_axil_arvalid_next = 1'b1;
|
||||
m_axil_rready_next = m_axis_cc_tready_int_early;
|
||||
s_axis_cq_tready_next = 1'b0;
|
||||
state_next = STATE_READ;
|
||||
end else begin
|
||||
// bad length
|
||||
status_next = CPL_STATUS_CA; // completer abort
|
||||
// report correctable error
|
||||
status_error_cor_next = 1'b1;
|
||||
if (s_axis_cq_tlast) begin
|
||||
s_axis_cq_tready_next = 1'b0;
|
||||
state_next = STATE_CPL_1;
|
||||
end else begin
|
||||
s_axis_cq_tready_next = 1'b1;
|
||||
state_next = STATE_WAIT_END;
|
||||
end
|
||||
end
|
||||
end else if (type_next == REQ_MEM_WRITE || type_next == REQ_IO_WRITE) begin
|
||||
// write request
|
||||
if (dword_count_next == 11'd1) begin
|
||||
s_axis_cq_tready_next = 1'b1;
|
||||
state_next = STATE_WRITE_1;
|
||||
end else begin
|
||||
// bad length
|
||||
status_next = CPL_STATUS_CA; // completer abort
|
||||
if (type_next == REQ_MEM_WRITE) begin
|
||||
// memory write - posted, no completion
|
||||
// report uncorrectable error
|
||||
status_error_uncor_next = 1'b1;
|
||||
if (s_axis_cq_tlast) begin
|
||||
s_axis_cq_tready_next = m_axis_cc_tready_int_early;
|
||||
state_next = STATE_IDLE;
|
||||
end else begin
|
||||
s_axis_cq_tready_next = 1'b1;
|
||||
state_next = STATE_WAIT_END;
|
||||
end
|
||||
end else begin
|
||||
// other non-posted request, send UR completion
|
||||
// report correctable error
|
||||
status_error_cor_next = 1'b1;
|
||||
if (s_axis_cq_tlast) begin
|
||||
s_axis_cq_tready_next = 1'b0;
|
||||
state_next = STATE_CPL_1;
|
||||
end else begin
|
||||
s_axis_cq_tready_next = 1'b1;
|
||||
state_next = STATE_WAIT_END;
|
||||
end
|
||||
end
|
||||
end
|
||||
end else begin
|
||||
// other request
|
||||
status_next = CPL_STATUS_UR; // unsupported request
|
||||
if (type_next == REQ_MEM_WRITE || (type_next & 4'b1100) == 4'b1100) begin
|
||||
// memory write or message - posted, no completion
|
||||
// report uncorrectable error
|
||||
status_error_uncor_next = 1'b1;
|
||||
if (s_axis_cq_tlast) begin
|
||||
s_axis_cq_tready_next = m_axis_cc_tready_int_early;
|
||||
state_next = STATE_IDLE;
|
||||
end else begin
|
||||
s_axis_cq_tready_next = 1'b1;
|
||||
state_next = STATE_WAIT_END;
|
||||
end
|
||||
end else begin
|
||||
// other non-posted request, send UR completion
|
||||
// report correctable error
|
||||
status_error_cor_next = 1'b1;
|
||||
if (s_axis_cq_tlast) begin
|
||||
s_axis_cq_tready_next = 1'b0;
|
||||
state_next = STATE_CPL_1;
|
||||
end else begin
|
||||
s_axis_cq_tready_next = 1'b1;
|
||||
state_next = STATE_WAIT_END;
|
||||
end
|
||||
end
|
||||
end
|
||||
end else begin
|
||||
state_next = STATE_HEADER;
|
||||
end
|
||||
end
|
||||
STATE_READ: begin
|
||||
// read state, wait for read response
|
||||
m_axil_rready_next = m_axis_cc_tready_int_early;
|
||||
|
||||
m_axis_cc_tdata_int[42:32] = 11'd1; // DWORD count
|
||||
m_axis_cc_tdata_int[45:43] = CPL_STATUS_SC; // status: successful completion
|
||||
m_axis_cc_tdata_int[127:96] = m_axil_rdata;
|
||||
|
||||
if (AXIS_PCIE_DATA_WIDTH == 256) begin
|
||||
m_axis_cc_tkeep_int = 8'b00001111;
|
||||
m_axis_cc_tlast_int = 1'b1;
|
||||
end else if (AXIS_PCIE_DATA_WIDTH == 128) begin
|
||||
m_axis_cc_tkeep_int = 4'b1111;
|
||||
m_axis_cc_tlast_int = 1'b1;
|
||||
end else if (AXIS_PCIE_DATA_WIDTH == 64) begin
|
||||
m_axis_cc_tkeep_int = 2'b11;
|
||||
m_axis_cc_tlast_int = 1'b0;
|
||||
end
|
||||
|
||||
if (m_axil_rready && m_axil_rvalid) begin
|
||||
// send completion
|
||||
m_axis_cc_tvalid_int = 1'b1;
|
||||
|
||||
m_axil_rready_next = 1'b0;
|
||||
if (AXIS_PCIE_DATA_WIDTH == 64) begin
|
||||
cpl_data_next = 1'b1;
|
||||
state_next = STATE_CPL_2;
|
||||
end else begin
|
||||
s_axis_cq_tready_next = m_axis_cc_tready_int_early;
|
||||
state_next = STATE_IDLE;
|
||||
end
|
||||
end else begin
|
||||
state_next = STATE_READ;
|
||||
end
|
||||
end
|
||||
STATE_WRITE_1: begin
|
||||
// write 1 state, store write data and initiate write
|
||||
s_axis_cq_tready_next = 1'b1;
|
||||
|
||||
// data
|
||||
m_axil_wdata_next = s_axis_cq_tdata[31:0];
|
||||
|
||||
if (s_axis_cq_tready && s_axis_cq_tvalid) begin
|
||||
if (s_axis_cq_tlast) begin
|
||||
m_axil_awvalid_next = 1'b1;
|
||||
m_axil_wvalid_next = 1'b1;
|
||||
m_axil_bready_next = m_axis_cc_tready_int_early;
|
||||
s_axis_cq_tready_next = 1'b0;
|
||||
state_next = STATE_WRITE_2;
|
||||
end else begin
|
||||
s_axis_cq_tready_next = 1'b1;
|
||||
state_next = STATE_WAIT_END;
|
||||
end
|
||||
end else begin
|
||||
state_next = STATE_WRITE_1;
|
||||
end
|
||||
end
|
||||
STATE_WRITE_2: begin
|
||||
// write 2 state, handle write response
|
||||
m_axil_bready_next = m_axis_cc_tready_int_early;
|
||||
|
||||
if (m_axil_bready && m_axil_bvalid) begin
|
||||
m_axil_bready_next = 1'b0;
|
||||
if (type_reg == REQ_MEM_WRITE) begin
|
||||
// memory write - posted, no completion
|
||||
s_axis_cq_tready_next = m_axis_cc_tready_int_early;
|
||||
state_next = STATE_IDLE;
|
||||
end else begin
|
||||
// IO write - non-posted, send completion
|
||||
m_axis_cc_tvalid_int = 1'b1;
|
||||
m_axis_cc_tdata_int[42:32] = 11'd0; // DWORD count
|
||||
m_axis_cc_tdata_int[45:43] = CPL_STATUS_SC; // status: successful completion
|
||||
|
||||
if (AXIS_PCIE_DATA_WIDTH == 256) begin
|
||||
m_axis_cc_tkeep_int = 8'b00000111;
|
||||
m_axis_cc_tlast_int = 1'b1;
|
||||
end else if (AXIS_PCIE_DATA_WIDTH == 128) begin
|
||||
m_axis_cc_tkeep_int = 4'b0111;
|
||||
m_axis_cc_tlast_int = 1'b1;
|
||||
end else if (AXIS_PCIE_DATA_WIDTH == 64) begin
|
||||
m_axis_cc_tkeep_int = 2'b11;
|
||||
m_axis_cc_tlast_int = 1'b0;
|
||||
end
|
||||
|
||||
if (AXIS_PCIE_DATA_WIDTH == 64) begin
|
||||
cpl_data_next = 1'b0;
|
||||
state_next = STATE_CPL_2;
|
||||
end else begin
|
||||
s_axis_cq_tready_next = m_axis_cc_tready_int_early;
|
||||
state_next = STATE_IDLE;
|
||||
end
|
||||
end
|
||||
end else begin
|
||||
state_next = STATE_WRITE_2;
|
||||
end
|
||||
end
|
||||
STATE_WAIT_END: begin
|
||||
// wait end state, wait for end of completion request
|
||||
s_axis_cq_tready_next = 1'b1;
|
||||
|
||||
if (s_axis_cq_tready && s_axis_cq_tvalid) begin
|
||||
if (s_axis_cq_tlast) begin
|
||||
// completion
|
||||
if (type_reg == REQ_MEM_WRITE || (type_reg & 4'b1100) == 4'b1100) begin
|
||||
// memory write or message - posted, no completion
|
||||
s_axis_cq_tready_next = m_axis_cc_tready_int_early;
|
||||
state_next = STATE_IDLE;
|
||||
end else begin
|
||||
// IO write - non-posted, send completion
|
||||
m_axis_cc_tvalid_int = 1'b1;
|
||||
m_axis_cc_tdata_int[42:32] = 11'd0; // DWORD count
|
||||
|
||||
if (AXIS_PCIE_DATA_WIDTH == 256) begin
|
||||
m_axis_cc_tkeep_int = 8'b00000111;
|
||||
m_axis_cc_tlast_int = 1'b1;
|
||||
end else if (AXIS_PCIE_DATA_WIDTH == 128) begin
|
||||
m_axis_cc_tkeep_int = 4'b0111;
|
||||
m_axis_cc_tlast_int = 1'b1;
|
||||
end else if (AXIS_PCIE_DATA_WIDTH == 64) begin
|
||||
m_axis_cc_tkeep_int = 2'b11;
|
||||
m_axis_cc_tlast_int = 1'b0;
|
||||
end
|
||||
|
||||
if (m_axis_cc_tready_int_reg) begin
|
||||
if (AXIS_PCIE_DATA_WIDTH == 64) begin
|
||||
cpl_data_next = 1'b0;
|
||||
state_next = STATE_CPL_2;
|
||||
end else begin
|
||||
s_axis_cq_tready_next = m_axis_cc_tready_int_early;
|
||||
state_next = STATE_IDLE;
|
||||
end
|
||||
end else begin
|
||||
state_next = STATE_CPL_1;
|
||||
end
|
||||
end
|
||||
end else begin
|
||||
state_next = STATE_WAIT_END;
|
||||
end
|
||||
end else begin
|
||||
state_next = STATE_WAIT_END;
|
||||
end
|
||||
end
|
||||
STATE_CPL_1: begin
|
||||
// send completion
|
||||
m_axis_cc_tvalid_int = 1'b1;
|
||||
m_axis_cc_tdata_int[28:16] = 13'd0; // byte count
|
||||
m_axis_cc_tdata_int[42:32] = 11'd0; // DWORD count
|
||||
m_axis_cc_tdata_int[45:43] = status_reg;
|
||||
|
||||
if (AXIS_PCIE_DATA_WIDTH == 256) begin
|
||||
m_axis_cc_tkeep_int = 8'b00000111;
|
||||
m_axis_cc_tlast_int = 1'b1;
|
||||
end else if (AXIS_PCIE_DATA_WIDTH == 128) begin
|
||||
m_axis_cc_tkeep_int = 4'b0111;
|
||||
m_axis_cc_tlast_int = 1'b1;
|
||||
end else if (AXIS_PCIE_DATA_WIDTH == 64) begin
|
||||
m_axis_cc_tkeep_int = 2'b11;
|
||||
m_axis_cc_tlast_int = 1'b0;
|
||||
end
|
||||
|
||||
if (m_axis_cc_tready_int_reg) begin
|
||||
if (AXIS_PCIE_DATA_WIDTH == 64) begin
|
||||
cpl_data_next = 1'b0;
|
||||
state_next = STATE_CPL_2;
|
||||
end else begin
|
||||
s_axis_cq_tready_next = m_axis_cc_tready_int_early;
|
||||
state_next = STATE_IDLE;
|
||||
end
|
||||
end else begin
|
||||
state_next = STATE_CPL_1;
|
||||
end
|
||||
end
|
||||
STATE_CPL_2: begin
|
||||
// send rest of completion
|
||||
m_axis_cc_tvalid_int = 1'b1;
|
||||
m_axis_cc_tdata_int[7:0] = tag_reg;
|
||||
m_axis_cc_tdata_int[23:8] = completer_id;
|
||||
m_axis_cc_tdata_int[24] = completer_id_enable;
|
||||
m_axis_cc_tdata_int[27:25] = tc_reg;
|
||||
m_axis_cc_tdata_int[30:28] = attr_reg;
|
||||
m_axis_cc_tdata_int[31] = 1'b0; // force ECRC
|
||||
m_axis_cc_tdata_int[63:32] = m_axil_rdata;
|
||||
m_axis_cc_tkeep_int = {cpl_data_reg, 1'b1};
|
||||
m_axis_cc_tlast_int = 1'b1;
|
||||
|
||||
if (m_axis_cc_tready_int_reg) begin
|
||||
s_axis_cq_tready_next = m_axis_cc_tready_int_early;
|
||||
state_next = STATE_IDLE;
|
||||
end else begin
|
||||
state_next = STATE_CPL_2;
|
||||
end
|
||||
end
|
||||
endcase
|
||||
end
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (rst) begin
|
||||
state_reg <= STATE_IDLE;
|
||||
s_axis_cq_tready_reg <= 1'b0;
|
||||
|
||||
m_axil_awvalid_reg <= 1'b0;
|
||||
m_axil_wvalid_reg <= 1'b0;
|
||||
m_axil_bready_reg <= 1'b0;
|
||||
m_axil_arvalid_reg <= 1'b0;
|
||||
m_axil_rready_reg <= 1'b0;
|
||||
|
||||
status_error_cor_reg <= 1'b0;
|
||||
status_error_uncor_reg <= 1'b0;
|
||||
end else begin
|
||||
state_reg <= state_next;
|
||||
s_axis_cq_tready_reg <= s_axis_cq_tready_next;
|
||||
|
||||
m_axil_awvalid_reg <= m_axil_awvalid_next;
|
||||
m_axil_wvalid_reg <= m_axil_wvalid_next;
|
||||
m_axil_bready_reg <= m_axil_bready_next;
|
||||
m_axil_arvalid_reg <= m_axil_arvalid_next;
|
||||
m_axil_rready_reg <= m_axil_rready_next;
|
||||
|
||||
status_error_cor_reg <= status_error_cor_next;
|
||||
status_error_uncor_reg <= status_error_uncor_next;
|
||||
end
|
||||
|
||||
at_reg <= at_next;
|
||||
dword_count_reg <= dword_count_next;
|
||||
type_reg <= type_next;
|
||||
tag_reg <= tag_next;
|
||||
status_reg <= status_next;
|
||||
requester_id_reg <= requester_id_next;
|
||||
tc_reg <= tc_next;
|
||||
attr_reg <= attr_next;
|
||||
first_be_reg <= first_be_next;
|
||||
last_be_reg <= last_be_next;
|
||||
cpl_data_reg <= cpl_data_next;
|
||||
|
||||
m_axil_addr_reg <= m_axil_addr_next;
|
||||
m_axil_wdata_reg <= m_axil_wdata_next;
|
||||
m_axil_wstrb_reg <= m_axil_wstrb_next;
|
||||
end
|
||||
|
||||
// output datapath logic
|
||||
reg [AXIS_PCIE_DATA_WIDTH-1:0] m_axis_cc_tdata_reg = {AXIS_PCIE_DATA_WIDTH{1'b0}};
|
||||
reg [AXIS_PCIE_KEEP_WIDTH-1:0] m_axis_cc_tkeep_reg = {AXIS_PCIE_KEEP_WIDTH{1'b0}};
|
||||
reg m_axis_cc_tvalid_reg = 1'b0, m_axis_cc_tvalid_next;
|
||||
reg m_axis_cc_tlast_reg = 1'b0;
|
||||
reg [32:0] m_axis_cc_tuser_reg = 33'd0;
|
||||
|
||||
reg [AXIS_PCIE_DATA_WIDTH-1:0] temp_m_axis_cc_tdata_reg = {AXIS_PCIE_DATA_WIDTH{1'b0}};
|
||||
reg [AXIS_PCIE_KEEP_WIDTH-1:0] temp_m_axis_cc_tkeep_reg = {AXIS_PCIE_KEEP_WIDTH{1'b0}};
|
||||
reg temp_m_axis_cc_tvalid_reg = 1'b0, temp_m_axis_cc_tvalid_next;
|
||||
reg temp_m_axis_cc_tlast_reg = 1'b0;
|
||||
reg [32:0] temp_m_axis_cc_tuser_reg = 33'd0;
|
||||
|
||||
// datapath control
|
||||
reg store_axis_int_to_output;
|
||||
reg store_axis_int_to_temp;
|
||||
reg store_axis_temp_to_output;
|
||||
|
||||
assign m_axis_cc_tdata = m_axis_cc_tdata_reg;
|
||||
assign m_axis_cc_tkeep = m_axis_cc_tkeep_reg;
|
||||
assign m_axis_cc_tvalid = m_axis_cc_tvalid_reg;
|
||||
assign m_axis_cc_tlast = m_axis_cc_tlast_reg;
|
||||
assign m_axis_cc_tuser = m_axis_cc_tuser_reg;
|
||||
|
||||
// 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)
|
||||
assign m_axis_cc_tready_int_early = m_axis_cc_tready || (!temp_m_axis_cc_tvalid_reg && (!m_axis_cc_tvalid_reg || !m_axis_cc_tvalid_int));
|
||||
|
||||
always @* begin
|
||||
// transfer sink ready state to source
|
||||
m_axis_cc_tvalid_next = m_axis_cc_tvalid_reg;
|
||||
temp_m_axis_cc_tvalid_next = temp_m_axis_cc_tvalid_reg;
|
||||
|
||||
store_axis_int_to_output = 1'b0;
|
||||
store_axis_int_to_temp = 1'b0;
|
||||
store_axis_temp_to_output = 1'b0;
|
||||
|
||||
if (m_axis_cc_tready_int_reg) begin
|
||||
// input is ready
|
||||
if (m_axis_cc_tready || !m_axis_cc_tvalid_reg) begin
|
||||
// output is ready or currently not valid, transfer data to output
|
||||
m_axis_cc_tvalid_next = m_axis_cc_tvalid_int;
|
||||
store_axis_int_to_output = 1'b1;
|
||||
end else begin
|
||||
// output is not ready, store input in temp
|
||||
temp_m_axis_cc_tvalid_next = m_axis_cc_tvalid_int;
|
||||
store_axis_int_to_temp = 1'b1;
|
||||
end
|
||||
end else if (m_axis_cc_tready) begin
|
||||
// input is not ready, but output is ready
|
||||
m_axis_cc_tvalid_next = temp_m_axis_cc_tvalid_reg;
|
||||
temp_m_axis_cc_tvalid_next = 1'b0;
|
||||
store_axis_temp_to_output = 1'b1;
|
||||
end
|
||||
end
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (rst) begin
|
||||
m_axis_cc_tvalid_reg <= 1'b0;
|
||||
m_axis_cc_tready_int_reg <= 1'b0;
|
||||
temp_m_axis_cc_tvalid_reg <= 1'b0;
|
||||
end else begin
|
||||
m_axis_cc_tvalid_reg <= m_axis_cc_tvalid_next;
|
||||
m_axis_cc_tready_int_reg <= m_axis_cc_tready_int_early;
|
||||
temp_m_axis_cc_tvalid_reg <= temp_m_axis_cc_tvalid_next;
|
||||
end
|
||||
|
||||
// datapath
|
||||
if (store_axis_int_to_output) begin
|
||||
m_axis_cc_tdata_reg <= m_axis_cc_tdata_int;
|
||||
m_axis_cc_tkeep_reg <= m_axis_cc_tkeep_int;
|
||||
m_axis_cc_tlast_reg <= m_axis_cc_tlast_int;
|
||||
m_axis_cc_tuser_reg <= m_axis_cc_tuser_int;
|
||||
end else if (store_axis_temp_to_output) begin
|
||||
m_axis_cc_tdata_reg <= temp_m_axis_cc_tdata_reg;
|
||||
m_axis_cc_tkeep_reg <= temp_m_axis_cc_tkeep_reg;
|
||||
m_axis_cc_tlast_reg <= temp_m_axis_cc_tlast_reg;
|
||||
m_axis_cc_tuser_reg <= temp_m_axis_cc_tuser_reg;
|
||||
end
|
||||
|
||||
if (store_axis_int_to_temp) begin
|
||||
temp_m_axis_cc_tdata_reg <= m_axis_cc_tdata_int;
|
||||
temp_m_axis_cc_tkeep_reg <= m_axis_cc_tkeep_int;
|
||||
temp_m_axis_cc_tlast_reg <= m_axis_cc_tlast_int;
|
||||
temp_m_axis_cc_tuser_reg <= m_axis_cc_tuser_int;
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
306
fpga/lib/pcie/rtl/pcie_us_axis_cq_demux.v
Normal file
306
fpga/lib/pcie/rtl/pcie_us_axis_cq_demux.v
Normal file
@ -0,0 +1,306 @@
|
||||
/*
|
||||
|
||||
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
|
||||
|
||||
/*
|
||||
* Ultrascale PCIe CQ demultiplexer
|
||||
*/
|
||||
module pcie_us_axis_cq_demux #
|
||||
(
|
||||
parameter M_COUNT = 2,
|
||||
parameter AXIS_PCIE_DATA_WIDTH = 256,
|
||||
parameter AXIS_PCIE_KEEP_WIDTH = (AXIS_PCIE_DATA_WIDTH/32)
|
||||
)
|
||||
(
|
||||
input wire clk,
|
||||
input wire rst,
|
||||
|
||||
/*
|
||||
* AXI input (CQ)
|
||||
*/
|
||||
input wire [AXIS_PCIE_DATA_WIDTH-1:0] s_axis_cq_tdata,
|
||||
input wire [AXIS_PCIE_KEEP_WIDTH-1:0] s_axis_cq_tkeep,
|
||||
input wire s_axis_cq_tvalid,
|
||||
output wire s_axis_cq_tready,
|
||||
input wire s_axis_cq_tlast,
|
||||
input wire [84:0] s_axis_cq_tuser,
|
||||
|
||||
/*
|
||||
* AXI output (CQ)
|
||||
*/
|
||||
output wire [M_COUNT*AXIS_PCIE_DATA_WIDTH-1:0] m_axis_cq_tdata,
|
||||
output wire [M_COUNT*AXIS_PCIE_KEEP_WIDTH-1:0] m_axis_cq_tkeep,
|
||||
output wire [M_COUNT-1:0] m_axis_cq_tvalid,
|
||||
input wire [M_COUNT-1:0] m_axis_cq_tready,
|
||||
output wire [M_COUNT-1:0] m_axis_cq_tlast,
|
||||
output wire [M_COUNT*85-1:0] m_axis_cq_tuser,
|
||||
|
||||
/*
|
||||
* Fields
|
||||
*/
|
||||
output wire [3:0] req_type,
|
||||
output wire [7:0] target_function,
|
||||
output wire [2:0] bar_id,
|
||||
output wire [7:0] msg_code,
|
||||
output wire [2:0] msg_routing,
|
||||
|
||||
/*
|
||||
* Control
|
||||
*/
|
||||
input wire enable,
|
||||
input wire drop,
|
||||
input wire [M_COUNT-1:0] select
|
||||
);
|
||||
|
||||
parameter CL_M_COUNT = $clog2(M_COUNT);
|
||||
|
||||
// bus width assertions
|
||||
initial begin
|
||||
if (AXIS_PCIE_DATA_WIDTH != 64 && AXIS_PCIE_DATA_WIDTH != 128 && AXIS_PCIE_DATA_WIDTH != 256) begin
|
||||
$error("Error: PCIe interface width must be 64, 128, or 256");
|
||||
$finish;
|
||||
end
|
||||
|
||||
if (AXIS_PCIE_KEEP_WIDTH * 32 != AXIS_PCIE_DATA_WIDTH) begin
|
||||
$error("Error: PCIe interface requires dword (32-bit) granularity");
|
||||
$finish;
|
||||
end
|
||||
end
|
||||
|
||||
reg [CL_M_COUNT-1:0] select_reg = {CL_M_COUNT{1'b0}}, select_ctl, select_next;
|
||||
reg drop_reg = 1'b0, drop_ctl, drop_next;
|
||||
reg frame_reg = 1'b0, frame_ctl, frame_next;
|
||||
|
||||
reg s_axis_cq_tready_reg = 1'b0, s_axis_cq_tready_next;
|
||||
|
||||
reg [AXIS_PCIE_DATA_WIDTH-1:0] temp_s_axis_cq_tdata = {AXIS_PCIE_DATA_WIDTH{1'b0}};
|
||||
reg [AXIS_PCIE_KEEP_WIDTH-1:0] temp_s_axis_cq_tkeep = {AXIS_PCIE_KEEP_WIDTH{1'b0}};
|
||||
reg temp_s_axis_cq_tvalid = 1'b0;
|
||||
reg temp_s_axis_cq_tlast = 1'b0;
|
||||
reg [84:0] temp_s_axis_cq_tuser = 85'b0;
|
||||
|
||||
// internal datapath
|
||||
reg [AXIS_PCIE_DATA_WIDTH-1:0] m_axis_cq_tdata_int;
|
||||
reg [AXIS_PCIE_KEEP_WIDTH-1:0] m_axis_cq_tkeep_int;
|
||||
reg [M_COUNT-1:0] m_axis_cq_tvalid_int;
|
||||
reg m_axis_cq_tready_int_reg = 1'b0;
|
||||
reg m_axis_cq_tlast_int;
|
||||
reg [84:0] m_axis_cq_tuser_int;
|
||||
wire m_axis_cq_tready_int_early;
|
||||
|
||||
assign s_axis_cq_tready = (s_axis_cq_tready_reg || (AXIS_PCIE_DATA_WIDTH == 64 && !temp_s_axis_cq_tvalid)) && enable;
|
||||
|
||||
assign req_type = AXIS_PCIE_DATA_WIDTH > 64 ? s_axis_cq_tdata[78:75] : s_axis_cq_tdata[14:11];
|
||||
assign target_function = AXIS_PCIE_DATA_WIDTH > 64 ? s_axis_cq_tdata[111:104] : s_axis_cq_tdata[47:40];
|
||||
assign bar_id = AXIS_PCIE_DATA_WIDTH > 64 ? s_axis_cq_tdata[114:112] : s_axis_cq_tdata[50:48];
|
||||
assign msg_code = AXIS_PCIE_DATA_WIDTH > 64 ? s_axis_cq_tdata[111:104] : s_axis_cq_tdata[47:40];
|
||||
assign msg_routing = AXIS_PCIE_DATA_WIDTH > 64 ? s_axis_cq_tdata[114:112] : s_axis_cq_tdata[50:48];
|
||||
|
||||
integer i;
|
||||
|
||||
always @* begin
|
||||
select_next = select_reg;
|
||||
select_ctl = select_reg;
|
||||
drop_next = drop_reg;
|
||||
drop_ctl = drop_reg;
|
||||
frame_next = frame_reg;
|
||||
frame_ctl = frame_reg;
|
||||
|
||||
s_axis_cq_tready_next = 1'b0;
|
||||
|
||||
if (AXIS_PCIE_DATA_WIDTH == 64) begin
|
||||
if (temp_s_axis_cq_tvalid && s_axis_cq_tready) begin
|
||||
// end of frame detection
|
||||
if (temp_s_axis_cq_tlast) begin
|
||||
frame_next = 1'b0;
|
||||
drop_next = 1'b0;
|
||||
end
|
||||
end
|
||||
end else begin
|
||||
if (s_axis_cq_tvalid && s_axis_cq_tready) begin
|
||||
// end of frame detection
|
||||
if (s_axis_cq_tlast) begin
|
||||
frame_next = 1'b0;
|
||||
drop_next = 1'b0;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if (!frame_reg && (AXIS_PCIE_DATA_WIDTH == 64 ? temp_s_axis_cq_tvalid : s_axis_cq_tvalid) && s_axis_cq_tready) begin
|
||||
// start of frame, grab select value
|
||||
select_ctl = 0;
|
||||
drop_ctl = 1'b1;
|
||||
frame_ctl = 1'b1;
|
||||
for (i = M_COUNT-1; i >= 0; i = i - 1) begin
|
||||
if (select[i]) begin
|
||||
select_ctl = i;
|
||||
drop_ctl = 1'b0;
|
||||
end
|
||||
end
|
||||
drop_ctl = drop_ctl || drop;
|
||||
if (AXIS_PCIE_DATA_WIDTH == 64) begin
|
||||
if (!(s_axis_cq_tready && temp_s_axis_cq_tvalid && temp_s_axis_cq_tlast)) begin
|
||||
select_next = select_ctl;
|
||||
drop_next = drop_ctl;
|
||||
frame_next = 1'b1;
|
||||
end
|
||||
end else begin
|
||||
if (!(s_axis_cq_tready && s_axis_cq_tvalid && s_axis_cq_tlast)) begin
|
||||
select_next = select_ctl;
|
||||
drop_next = drop_ctl;
|
||||
frame_next = 1'b1;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
s_axis_cq_tready_next = m_axis_cq_tready_int_early || drop_ctl;
|
||||
|
||||
if (AXIS_PCIE_DATA_WIDTH == 64) begin
|
||||
m_axis_cq_tdata_int = temp_s_axis_cq_tdata;
|
||||
m_axis_cq_tkeep_int = temp_s_axis_cq_tkeep;
|
||||
m_axis_cq_tvalid_int = (temp_s_axis_cq_tvalid && s_axis_cq_tready && !drop_ctl) << select_ctl;
|
||||
m_axis_cq_tlast_int = temp_s_axis_cq_tlast;
|
||||
m_axis_cq_tuser_int = temp_s_axis_cq_tuser;
|
||||
end else begin
|
||||
m_axis_cq_tdata_int = s_axis_cq_tdata;
|
||||
m_axis_cq_tkeep_int = s_axis_cq_tkeep;
|
||||
m_axis_cq_tvalid_int = (s_axis_cq_tvalid && s_axis_cq_tready && !drop_ctl) << select_ctl;
|
||||
m_axis_cq_tlast_int = s_axis_cq_tlast;
|
||||
m_axis_cq_tuser_int = s_axis_cq_tuser;
|
||||
end
|
||||
end
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (rst) begin
|
||||
select_reg <= 2'd0;
|
||||
drop_reg <= 1'b0;
|
||||
frame_reg <= 1'b0;
|
||||
s_axis_cq_tready_reg <= 1'b0;
|
||||
end else begin
|
||||
select_reg <= select_next;
|
||||
drop_reg <= drop_next;
|
||||
frame_reg <= frame_next;
|
||||
s_axis_cq_tready_reg <= s_axis_cq_tready_next;
|
||||
end
|
||||
|
||||
if (s_axis_cq_tready && AXIS_PCIE_DATA_WIDTH == 64) begin
|
||||
temp_s_axis_cq_tdata <= s_axis_cq_tdata;
|
||||
temp_s_axis_cq_tkeep <= s_axis_cq_tkeep;
|
||||
temp_s_axis_cq_tvalid <= s_axis_cq_tvalid;
|
||||
temp_s_axis_cq_tlast <= s_axis_cq_tlast;
|
||||
temp_s_axis_cq_tuser <= s_axis_cq_tuser;
|
||||
end
|
||||
end
|
||||
|
||||
// output datapath logic
|
||||
reg [AXIS_PCIE_DATA_WIDTH-1:0] m_axis_cq_tdata_reg = {AXIS_PCIE_DATA_WIDTH{1'b0}};
|
||||
reg [AXIS_PCIE_KEEP_WIDTH-1:0] m_axis_cq_tkeep_reg = {AXIS_PCIE_KEEP_WIDTH{1'b0}};
|
||||
reg [M_COUNT-1:0] m_axis_cq_tvalid_reg = {M_COUNT{1'b0}}, m_axis_cq_tvalid_next;
|
||||
reg m_axis_cq_tlast_reg = 1'b0;
|
||||
reg [84:0] m_axis_cq_tuser_reg = 85'd0;
|
||||
|
||||
reg [AXIS_PCIE_DATA_WIDTH-1:0] temp_m_axis_cq_tdata_reg = {AXIS_PCIE_DATA_WIDTH{1'b0}};
|
||||
reg [AXIS_PCIE_KEEP_WIDTH-1:0] temp_m_axis_cq_tkeep_reg = {AXIS_PCIE_KEEP_WIDTH{1'b0}};
|
||||
reg [M_COUNT-1:0] temp_m_axis_cq_tvalid_reg = {M_COUNT{1'b0}}, temp_m_axis_cq_tvalid_next;
|
||||
reg temp_m_axis_cq_tlast_reg = 1'b0;
|
||||
reg [84:0] temp_m_axis_cq_tuser_reg = 85'd0;
|
||||
|
||||
// datapath control
|
||||
reg store_axis_int_to_output;
|
||||
reg store_axis_int_to_temp;
|
||||
reg store_axis_cq_temp_to_output;
|
||||
|
||||
assign m_axis_cq_tdata = {M_COUNT{m_axis_cq_tdata_reg}};
|
||||
assign m_axis_cq_tkeep = {M_COUNT{m_axis_cq_tkeep_reg}};
|
||||
assign m_axis_cq_tvalid = m_axis_cq_tvalid_reg;
|
||||
assign m_axis_cq_tlast = {M_COUNT{m_axis_cq_tlast_reg}};
|
||||
assign m_axis_cq_tuser = {M_COUNT{m_axis_cq_tuser_reg}};
|
||||
|
||||
// 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)
|
||||
assign m_axis_cq_tready_int_early = (m_axis_cq_tready & m_axis_cq_tvalid) || (!temp_m_axis_cq_tvalid_reg && (!m_axis_cq_tvalid || !m_axis_cq_tvalid_int));
|
||||
|
||||
always @* begin
|
||||
// transfer sink ready state to source
|
||||
m_axis_cq_tvalid_next = m_axis_cq_tvalid_reg;
|
||||
temp_m_axis_cq_tvalid_next = temp_m_axis_cq_tvalid_reg;
|
||||
|
||||
store_axis_int_to_output = 1'b0;
|
||||
store_axis_int_to_temp = 1'b0;
|
||||
store_axis_cq_temp_to_output = 1'b0;
|
||||
|
||||
if (m_axis_cq_tready_int_reg) begin
|
||||
// input is ready
|
||||
if ((m_axis_cq_tready & m_axis_cq_tvalid) || !m_axis_cq_tvalid) begin
|
||||
// output is ready or currently not valid, transfer data to output
|
||||
m_axis_cq_tvalid_next = m_axis_cq_tvalid_int;
|
||||
store_axis_int_to_output = 1'b1;
|
||||
end else begin
|
||||
// output is not ready, store input in temp
|
||||
temp_m_axis_cq_tvalid_next = m_axis_cq_tvalid_int;
|
||||
store_axis_int_to_temp = 1'b1;
|
||||
end
|
||||
end else if (m_axis_cq_tready & m_axis_cq_tvalid) begin
|
||||
// input is not ready, but output is ready
|
||||
m_axis_cq_tvalid_next = temp_m_axis_cq_tvalid_reg;
|
||||
temp_m_axis_cq_tvalid_next = 1'b0;
|
||||
store_axis_cq_temp_to_output = 1'b1;
|
||||
end
|
||||
end
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (rst) begin
|
||||
m_axis_cq_tvalid_reg <= {M_COUNT{1'b0}};
|
||||
m_axis_cq_tready_int_reg <= 1'b0;
|
||||
temp_m_axis_cq_tvalid_reg <= 1'b0;
|
||||
end else begin
|
||||
m_axis_cq_tvalid_reg <= m_axis_cq_tvalid_next;
|
||||
m_axis_cq_tready_int_reg <= m_axis_cq_tready_int_early;
|
||||
temp_m_axis_cq_tvalid_reg <= temp_m_axis_cq_tvalid_next;
|
||||
end
|
||||
|
||||
// datapath
|
||||
if (store_axis_int_to_output) begin
|
||||
m_axis_cq_tdata_reg <= m_axis_cq_tdata_int;
|
||||
m_axis_cq_tkeep_reg <= m_axis_cq_tkeep_int;
|
||||
m_axis_cq_tlast_reg <= m_axis_cq_tlast_int;
|
||||
m_axis_cq_tuser_reg <= m_axis_cq_tuser_int;
|
||||
end else if (store_axis_cq_temp_to_output) begin
|
||||
m_axis_cq_tdata_reg <= temp_m_axis_cq_tdata_reg;
|
||||
m_axis_cq_tkeep_reg <= temp_m_axis_cq_tkeep_reg;
|
||||
m_axis_cq_tlast_reg <= temp_m_axis_cq_tlast_reg;
|
||||
m_axis_cq_tuser_reg <= temp_m_axis_cq_tuser_reg;
|
||||
end
|
||||
|
||||
if (store_axis_int_to_temp) begin
|
||||
temp_m_axis_cq_tdata_reg <= m_axis_cq_tdata_int;
|
||||
temp_m_axis_cq_tkeep_reg <= m_axis_cq_tkeep_int;
|
||||
temp_m_axis_cq_tlast_reg <= m_axis_cq_tlast_int;
|
||||
temp_m_axis_cq_tuser_reg <= m_axis_cq_tuser_int;
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
258
fpga/lib/pcie/rtl/pcie_us_axis_rc_demux.v
Normal file
258
fpga/lib/pcie/rtl/pcie_us_axis_rc_demux.v
Normal file
@ -0,0 +1,258 @@
|
||||
/*
|
||||
|
||||
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
|
||||
|
||||
/*
|
||||
* Ultrascale PCIe RC demultiplexer
|
||||
*/
|
||||
module pcie_us_axis_rc_demux #
|
||||
(
|
||||
parameter M_COUNT = 2,
|
||||
parameter AXIS_PCIE_DATA_WIDTH = 256,
|
||||
parameter AXIS_PCIE_KEEP_WIDTH = (AXIS_PCIE_DATA_WIDTH/32)
|
||||
)
|
||||
(
|
||||
input wire clk,
|
||||
input wire rst,
|
||||
|
||||
/*
|
||||
* AXI input (RC)
|
||||
*/
|
||||
input wire [AXIS_PCIE_DATA_WIDTH-1:0] s_axis_rc_tdata,
|
||||
input wire [AXIS_PCIE_KEEP_WIDTH-1:0] s_axis_rc_tkeep,
|
||||
input wire s_axis_rc_tvalid,
|
||||
output wire s_axis_rc_tready,
|
||||
input wire s_axis_rc_tlast,
|
||||
input wire [74:0] s_axis_rc_tuser,
|
||||
|
||||
/*
|
||||
* AXI output (RC)
|
||||
*/
|
||||
output wire [M_COUNT*AXIS_PCIE_DATA_WIDTH-1:0] m_axis_rc_tdata,
|
||||
output wire [M_COUNT*AXIS_PCIE_KEEP_WIDTH-1:0] m_axis_rc_tkeep,
|
||||
output wire [M_COUNT-1:0] m_axis_rc_tvalid,
|
||||
input wire [M_COUNT-1:0] m_axis_rc_tready,
|
||||
output wire [M_COUNT-1:0] m_axis_rc_tlast,
|
||||
output wire [M_COUNT*75-1:0] m_axis_rc_tuser,
|
||||
|
||||
/*
|
||||
* Fields
|
||||
*/
|
||||
output wire [15:0] requester_id,
|
||||
|
||||
/*
|
||||
* Control
|
||||
*/
|
||||
input wire enable,
|
||||
input wire drop,
|
||||
input wire [M_COUNT-1:0] select
|
||||
);
|
||||
|
||||
parameter CL_M_COUNT = $clog2(M_COUNT);
|
||||
|
||||
// bus width assertions
|
||||
initial begin
|
||||
if (AXIS_PCIE_DATA_WIDTH != 64 && AXIS_PCIE_DATA_WIDTH != 128 && AXIS_PCIE_DATA_WIDTH != 256) begin
|
||||
$error("Error: PCIe interface width must be 64, 128, or 256");
|
||||
$finish;
|
||||
end
|
||||
|
||||
if (AXIS_PCIE_KEEP_WIDTH * 32 != AXIS_PCIE_DATA_WIDTH) begin
|
||||
$error("Error: PCIe interface requires dword (32-bit) granularity");
|
||||
$finish;
|
||||
end
|
||||
end
|
||||
|
||||
reg [CL_M_COUNT-1:0] select_reg = {CL_M_COUNT{1'b0}}, select_ctl, select_next;
|
||||
reg drop_reg = 1'b0, drop_ctl, drop_next;
|
||||
reg frame_reg = 1'b0, frame_ctl, frame_next;
|
||||
|
||||
reg s_axis_rc_tready_reg = 1'b0, s_axis_rc_tready_next;
|
||||
|
||||
// internal datapath
|
||||
reg [AXIS_PCIE_DATA_WIDTH-1:0] m_axis_rc_tdata_int;
|
||||
reg [AXIS_PCIE_KEEP_WIDTH-1:0] m_axis_rc_tkeep_int;
|
||||
reg [M_COUNT-1:0] m_axis_rc_tvalid_int;
|
||||
reg m_axis_rc_tready_int_reg = 1'b0;
|
||||
reg m_axis_rc_tlast_int;
|
||||
reg [74:0] m_axis_rc_tuser_int;
|
||||
wire m_axis_rc_tready_int_early;
|
||||
|
||||
assign s_axis_rc_tready = s_axis_rc_tready_reg && enable;
|
||||
|
||||
assign requester_id = s_axis_rc_tdata[63:48];
|
||||
|
||||
integer i;
|
||||
|
||||
always @* begin
|
||||
select_next = select_reg;
|
||||
select_ctl = select_reg;
|
||||
drop_next = drop_reg;
|
||||
drop_ctl = drop_reg;
|
||||
frame_next = frame_reg;
|
||||
frame_ctl = frame_reg;
|
||||
|
||||
s_axis_rc_tready_next = 1'b0;
|
||||
|
||||
if (s_axis_rc_tvalid && s_axis_rc_tready) begin
|
||||
// end of frame detection
|
||||
if (s_axis_rc_tlast) begin
|
||||
frame_next = 1'b0;
|
||||
drop_next = 1'b0;
|
||||
end
|
||||
end
|
||||
|
||||
if (!frame_reg && s_axis_rc_tvalid && s_axis_rc_tready) begin
|
||||
// start of frame, grab select value
|
||||
select_ctl = 0;
|
||||
drop_ctl = 1'b1;
|
||||
frame_ctl = 1'b1;
|
||||
for (i = M_COUNT-1; i >= 0; i = i - 1) begin
|
||||
if (select[i]) begin
|
||||
select_ctl = i;
|
||||
drop_ctl = 1'b0;
|
||||
end
|
||||
end
|
||||
drop_ctl = drop_ctl || drop;
|
||||
if (!(s_axis_rc_tready && s_axis_rc_tvalid && s_axis_rc_tlast)) begin
|
||||
select_next = select_ctl;
|
||||
drop_next = drop_ctl;
|
||||
frame_next = 1'b1;
|
||||
end
|
||||
end
|
||||
|
||||
s_axis_rc_tready_next = m_axis_rc_tready_int_early || drop_ctl;
|
||||
|
||||
m_axis_rc_tdata_int = s_axis_rc_tdata;
|
||||
m_axis_rc_tkeep_int = s_axis_rc_tkeep;
|
||||
m_axis_rc_tvalid_int = (s_axis_rc_tvalid && s_axis_rc_tready && !drop_ctl) << select_ctl;
|
||||
m_axis_rc_tlast_int = s_axis_rc_tlast;
|
||||
m_axis_rc_tuser_int = s_axis_rc_tuser;
|
||||
end
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (rst) begin
|
||||
select_reg <= 2'd0;
|
||||
drop_reg <= 1'b0;
|
||||
frame_reg <= 1'b0;
|
||||
s_axis_rc_tready_reg <= 1'b0;
|
||||
end else begin
|
||||
select_reg <= select_next;
|
||||
drop_reg <= drop_next;
|
||||
frame_reg <= frame_next;
|
||||
s_axis_rc_tready_reg <= s_axis_rc_tready_next;
|
||||
end
|
||||
end
|
||||
|
||||
// output datapath logic
|
||||
reg [AXIS_PCIE_DATA_WIDTH-1:0] m_axis_rc_tdata_reg = {AXIS_PCIE_DATA_WIDTH{1'b0}};
|
||||
reg [AXIS_PCIE_KEEP_WIDTH-1:0] m_axis_rc_tkeep_reg = {AXIS_PCIE_KEEP_WIDTH{1'b0}};
|
||||
reg [M_COUNT-1:0] m_axis_rc_tvalid_reg = {M_COUNT{1'b0}}, m_axis_rc_tvalid_next;
|
||||
reg m_axis_rc_tlast_reg = 1'b0;
|
||||
reg [74:0] m_axis_rc_tuser_reg = 75'd0;
|
||||
|
||||
reg [AXIS_PCIE_DATA_WIDTH-1:0] temp_m_axis_rc_tdata_reg = {AXIS_PCIE_DATA_WIDTH{1'b0}};
|
||||
reg [AXIS_PCIE_KEEP_WIDTH-1:0] temp_m_axis_rc_tkeep_reg = {AXIS_PCIE_KEEP_WIDTH{1'b0}};
|
||||
reg [M_COUNT-1:0] temp_m_axis_rc_tvalid_reg = {M_COUNT{1'b0}}, temp_m_axis_rc_tvalid_next;
|
||||
reg temp_m_axis_rc_tlast_reg = 1'b0;
|
||||
reg [74:0] temp_m_axis_rc_tuser_reg = 75'd0;
|
||||
|
||||
// datapath control
|
||||
reg store_axis_int_to_output;
|
||||
reg store_axis_int_to_temp;
|
||||
reg store_axis_rc_temp_to_output;
|
||||
|
||||
assign m_axis_rc_tdata = {M_COUNT{m_axis_rc_tdata_reg}};
|
||||
assign m_axis_rc_tkeep = {M_COUNT{m_axis_rc_tkeep_reg}};
|
||||
assign m_axis_rc_tvalid = m_axis_rc_tvalid_reg;
|
||||
assign m_axis_rc_tlast = {M_COUNT{m_axis_rc_tlast_reg}};
|
||||
assign m_axis_rc_tuser = {M_COUNT{m_axis_rc_tuser_reg}};
|
||||
|
||||
// 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)
|
||||
assign m_axis_rc_tready_int_early = (m_axis_rc_tready & m_axis_rc_tvalid) || (!temp_m_axis_rc_tvalid_reg && (!m_axis_rc_tvalid || !m_axis_rc_tvalid_int));
|
||||
|
||||
always @* begin
|
||||
// transfer sink ready state to source
|
||||
m_axis_rc_tvalid_next = m_axis_rc_tvalid_reg;
|
||||
temp_m_axis_rc_tvalid_next = temp_m_axis_rc_tvalid_reg;
|
||||
|
||||
store_axis_int_to_output = 1'b0;
|
||||
store_axis_int_to_temp = 1'b0;
|
||||
store_axis_rc_temp_to_output = 1'b0;
|
||||
|
||||
if (m_axis_rc_tready_int_reg) begin
|
||||
// input is ready
|
||||
if ((m_axis_rc_tready & m_axis_rc_tvalid) || !m_axis_rc_tvalid) begin
|
||||
// output is ready or currently not valid, transfer data to output
|
||||
m_axis_rc_tvalid_next = m_axis_rc_tvalid_int;
|
||||
store_axis_int_to_output = 1'b1;
|
||||
end else begin
|
||||
// output is not ready, store input in temp
|
||||
temp_m_axis_rc_tvalid_next = m_axis_rc_tvalid_int;
|
||||
store_axis_int_to_temp = 1'b1;
|
||||
end
|
||||
end else if (m_axis_rc_tready & m_axis_rc_tvalid) begin
|
||||
// input is not ready, but output is ready
|
||||
m_axis_rc_tvalid_next = temp_m_axis_rc_tvalid_reg;
|
||||
temp_m_axis_rc_tvalid_next = 1'b0;
|
||||
store_axis_rc_temp_to_output = 1'b1;
|
||||
end
|
||||
end
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (rst) begin
|
||||
m_axis_rc_tvalid_reg <= {M_COUNT{1'b0}};
|
||||
m_axis_rc_tready_int_reg <= 1'b0;
|
||||
temp_m_axis_rc_tvalid_reg <= 1'b0;
|
||||
end else begin
|
||||
m_axis_rc_tvalid_reg <= m_axis_rc_tvalid_next;
|
||||
m_axis_rc_tready_int_reg <= m_axis_rc_tready_int_early;
|
||||
temp_m_axis_rc_tvalid_reg <= temp_m_axis_rc_tvalid_next;
|
||||
end
|
||||
|
||||
// datapath
|
||||
if (store_axis_int_to_output) begin
|
||||
m_axis_rc_tdata_reg <= m_axis_rc_tdata_int;
|
||||
m_axis_rc_tkeep_reg <= m_axis_rc_tkeep_int;
|
||||
m_axis_rc_tlast_reg <= m_axis_rc_tlast_int;
|
||||
m_axis_rc_tuser_reg <= m_axis_rc_tuser_int;
|
||||
end else if (store_axis_rc_temp_to_output) begin
|
||||
m_axis_rc_tdata_reg <= temp_m_axis_rc_tdata_reg;
|
||||
m_axis_rc_tkeep_reg <= temp_m_axis_rc_tkeep_reg;
|
||||
m_axis_rc_tlast_reg <= temp_m_axis_rc_tlast_reg;
|
||||
m_axis_rc_tuser_reg <= temp_m_axis_rc_tuser_reg;
|
||||
end
|
||||
|
||||
if (store_axis_int_to_temp) begin
|
||||
temp_m_axis_rc_tdata_reg <= m_axis_rc_tdata_int;
|
||||
temp_m_axis_rc_tkeep_reg <= m_axis_rc_tkeep_int;
|
||||
temp_m_axis_rc_tlast_reg <= m_axis_rc_tlast_int;
|
||||
temp_m_axis_rc_tuser_reg <= m_axis_rc_tuser_int;
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
171
fpga/lib/pcie/rtl/pcie_us_cfg.v
Normal file
171
fpga/lib/pcie/rtl/pcie_us_cfg.v
Normal file
@ -0,0 +1,171 @@
|
||||
/*
|
||||
|
||||
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
|
||||
|
||||
/*
|
||||
* Ultrascale PCIe configuration shim
|
||||
*/
|
||||
module pcie_us_cfg #
|
||||
(
|
||||
parameter PF_COUNT = 1,
|
||||
parameter VF_COUNT = 0,
|
||||
parameter VF_OFFSET = 64,
|
||||
parameter F_COUNT = PF_COUNT+VF_COUNT,
|
||||
parameter READ_EXT_TAG_ENABLE = 1,
|
||||
parameter READ_MAX_READ_REQ_SIZE = 1,
|
||||
parameter READ_MAX_PAYLOAD_SIZE = 1,
|
||||
parameter PCIE_CAP_OFFSET = 12'h0C0
|
||||
)
|
||||
(
|
||||
input wire clk,
|
||||
input wire rst,
|
||||
|
||||
/*
|
||||
* Configuration outputs
|
||||
*/
|
||||
output wire [F_COUNT-1:0] ext_tag_enable,
|
||||
output wire [F_COUNT*3-1:0] max_read_request_size,
|
||||
output wire [F_COUNT*3-1:0] max_payload_size,
|
||||
|
||||
/*
|
||||
* Interface to Ultrascale PCIe IP core
|
||||
*/
|
||||
output wire [9:0] cfg_mgmt_addr,
|
||||
output wire [7:0] cfg_mgmt_function_number,
|
||||
output wire cfg_mgmt_write,
|
||||
output wire [31:0] cfg_mgmt_write_data,
|
||||
output wire [3:0] cfg_mgmt_byte_enable,
|
||||
output wire cfg_mgmt_read,
|
||||
input wire [31:0] cfg_mgmt_read_data,
|
||||
input wire cfg_mgmt_read_write_done
|
||||
);
|
||||
|
||||
localparam READ_REV_CTRL = READ_EXT_TAG_ENABLE || READ_MAX_READ_REQ_SIZE || READ_MAX_PAYLOAD_SIZE;
|
||||
|
||||
localparam DEV_CTRL_OFFSET = PCIE_CAP_OFFSET + 12'h008;
|
||||
|
||||
reg [F_COUNT-1:0] ext_tag_enable_reg = {F_COUNT{1'b0}}, ext_tag_enable_next;
|
||||
reg [F_COUNT*3-1:0] max_read_request_size_reg = {F_COUNT{3'd0}}, max_read_request_size_next;
|
||||
reg [F_COUNT*3-1:0] max_payload_size_reg = {F_COUNT{3'd0}}, max_payload_size_next;
|
||||
|
||||
reg [9:0] cfg_mgmt_addr_reg = 10'd0, cfg_mgmt_addr_next;
|
||||
reg [7:0] cfg_mgmt_function_number_reg = 8'd0, cfg_mgmt_function_number_next;
|
||||
reg cfg_mgmt_write_reg = 1'b0, cfg_mgmt_write_next;
|
||||
reg [31:0] cfg_mgmt_write_data_reg = 32'd0, cfg_mgmt_write_data_next;
|
||||
reg [3:0] cfg_mgmt_byte_enable_reg = 4'd0, cfg_mgmt_byte_enable_next;
|
||||
reg cfg_mgmt_read_reg = 1'b0, cfg_mgmt_read_next;
|
||||
|
||||
reg [7:0] delay_reg = 8'hff, delay_next;
|
||||
reg [7:0] func_cnt_reg = 8'd0, func_cnt_next;
|
||||
|
||||
assign ext_tag_enable = ext_tag_enable_reg;
|
||||
assign max_read_request_size = max_read_request_size_reg;
|
||||
assign max_payload_size = max_payload_size_reg;
|
||||
|
||||
assign cfg_mgmt_addr = cfg_mgmt_addr_reg;
|
||||
assign cfg_mgmt_function_number = cfg_mgmt_function_number_reg;
|
||||
assign cfg_mgmt_write = cfg_mgmt_write_reg;
|
||||
assign cfg_mgmt_write_data = cfg_mgmt_write_data_reg;
|
||||
assign cfg_mgmt_byte_enable = cfg_mgmt_byte_enable_reg;
|
||||
assign cfg_mgmt_read = cfg_mgmt_read_reg;
|
||||
|
||||
always @* begin
|
||||
ext_tag_enable_next = ext_tag_enable_reg;
|
||||
max_read_request_size_next = max_read_request_size_reg;
|
||||
max_payload_size_next = max_payload_size_reg;
|
||||
|
||||
cfg_mgmt_addr_next = cfg_mgmt_addr_reg;
|
||||
cfg_mgmt_function_number_next = cfg_mgmt_function_number_reg;
|
||||
cfg_mgmt_write_next = cfg_mgmt_write_reg && !cfg_mgmt_read_write_done;
|
||||
cfg_mgmt_write_data_next = cfg_mgmt_write_data_reg;
|
||||
cfg_mgmt_byte_enable_next = cfg_mgmt_byte_enable_reg;
|
||||
cfg_mgmt_read_next = cfg_mgmt_read_reg && !cfg_mgmt_read_write_done;
|
||||
|
||||
delay_next = delay_reg;
|
||||
func_cnt_next = func_cnt_reg;
|
||||
|
||||
if (delay_reg > 0) begin
|
||||
delay_next = delay_reg - 1;
|
||||
end else begin
|
||||
cfg_mgmt_addr_next = DEV_CTRL_OFFSET >> 2;
|
||||
cfg_mgmt_read_next = 1'b1;
|
||||
if (cfg_mgmt_read_write_done) begin
|
||||
cfg_mgmt_read_next = 1'b0;
|
||||
|
||||
ext_tag_enable_next[func_cnt_reg] = cfg_mgmt_read_data[8];
|
||||
max_read_request_size_next[func_cnt_reg*3 +: 3] = cfg_mgmt_read_data[14:12];
|
||||
max_payload_size_next[func_cnt_reg*3 +: 3] = cfg_mgmt_read_data[7:5];
|
||||
|
||||
if (func_cnt_reg == F_COUNT-1) begin
|
||||
func_cnt_next = 0;
|
||||
cfg_mgmt_function_number_next = 0;
|
||||
end else if (func_cnt_reg == PF_COUNT-1) begin
|
||||
func_cnt_next = func_cnt_reg + 1;
|
||||
cfg_mgmt_function_number_next = VF_OFFSET;
|
||||
end else begin
|
||||
func_cnt_next = func_cnt_reg + 1;
|
||||
cfg_mgmt_function_number_next = cfg_mgmt_function_number_reg + 1;
|
||||
end
|
||||
|
||||
delay_next = 8'hff;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (rst) begin
|
||||
ext_tag_enable_reg <= {F_COUNT{1'b0}};
|
||||
max_read_request_size_reg <= {F_COUNT{3'd0}};
|
||||
max_payload_size_reg <= {F_COUNT{3'd0}};
|
||||
|
||||
cfg_mgmt_addr_reg <= 10'd0;
|
||||
cfg_mgmt_function_number_reg <= 8'd0;
|
||||
cfg_mgmt_write_reg <= 1'b0;
|
||||
cfg_mgmt_read_reg <= 1'b0;
|
||||
|
||||
delay_reg <= 8'hff;
|
||||
func_cnt_reg <= 8'd0;
|
||||
end else begin
|
||||
ext_tag_enable_reg <= ext_tag_enable_next;
|
||||
max_read_request_size_reg <= max_read_request_size_next;
|
||||
max_payload_size_reg <= max_payload_size_next;
|
||||
|
||||
cfg_mgmt_addr_reg <= cfg_mgmt_addr_next;
|
||||
cfg_mgmt_function_number_reg <= cfg_mgmt_function_number_next;
|
||||
cfg_mgmt_write_reg <= cfg_mgmt_write_next;
|
||||
cfg_mgmt_read_reg <= cfg_mgmt_read_next;
|
||||
|
||||
delay_reg <= delay_next;
|
||||
func_cnt_reg <= func_cnt_next;
|
||||
end
|
||||
|
||||
cfg_mgmt_write_data_reg <= cfg_mgmt_write_data_next;
|
||||
cfg_mgmt_byte_enable_reg <= cfg_mgmt_byte_enable_next;
|
||||
|
||||
end
|
||||
|
||||
endmodule
|
156
fpga/lib/pcie/rtl/pcie_us_msi.v
Normal file
156
fpga/lib/pcie/rtl/pcie_us_msi.v
Normal file
@ -0,0 +1,156 @@
|
||||
/*
|
||||
|
||||
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
|
||||
|
||||
/*
|
||||
* Ultrascale PCIe MSI shim
|
||||
*/
|
||||
module pcie_us_msi #
|
||||
(
|
||||
parameter MSI_COUNT = 32
|
||||
)
|
||||
(
|
||||
input wire clk,
|
||||
input wire rst,
|
||||
|
||||
/*
|
||||
* Interrupt request inputs
|
||||
*/
|
||||
input wire [MSI_COUNT-1:0] msi_irq,
|
||||
|
||||
/*
|
||||
* Interface to Ultrascale PCIe IP core
|
||||
*/
|
||||
input wire [3:0] cfg_interrupt_msi_enable,
|
||||
input wire [7:0] cfg_interrupt_msi_vf_enable,
|
||||
input wire [11:0] cfg_interrupt_msi_mmenable,
|
||||
input wire cfg_interrupt_msi_mask_update,
|
||||
input wire [31:0] cfg_interrupt_msi_data,
|
||||
output wire [3:0] cfg_interrupt_msi_select,
|
||||
output wire [31:0] cfg_interrupt_msi_int,
|
||||
output wire [31:0] cfg_interrupt_msi_pending_status,
|
||||
output wire cfg_interrupt_msi_pending_status_data_enable,
|
||||
output wire [3:0] cfg_interrupt_msi_pending_status_function_num,
|
||||
input wire cfg_interrupt_msi_sent,
|
||||
input wire cfg_interrupt_msi_fail,
|
||||
output wire [2:0] cfg_interrupt_msi_attr,
|
||||
output wire cfg_interrupt_msi_tph_present,
|
||||
output wire [1:0] cfg_interrupt_msi_tph_type,
|
||||
output wire [8:0] cfg_interrupt_msi_tph_st_tag,
|
||||
output wire [3:0] cfg_interrupt_msi_function_number
|
||||
);
|
||||
|
||||
reg active_reg = 1'b0, active_next;
|
||||
|
||||
reg [MSI_COUNT-1:0] msi_irq_reg = {MSI_COUNT{1'b0}};
|
||||
reg [MSI_COUNT-1:0] msi_irq_last_reg = {MSI_COUNT{1'b0}};
|
||||
reg [MSI_COUNT-1:0] msi_irq_active_reg = {MSI_COUNT{1'b0}}, msi_irq_active_next;
|
||||
|
||||
reg [MSI_COUNT-1:0] msi_irq_mask_reg = {MSI_COUNT{1'b0}}, msi_irq_mask_next;
|
||||
|
||||
reg [MSI_COUNT-1:0] msi_int_reg = {MSI_COUNT{1'b0}}, msi_int_next;
|
||||
|
||||
assign cfg_interrupt_msi_select = 4'd0; // request PF0 mask on cfg_interrupt_msi_data
|
||||
assign cfg_interrupt_msi_int = msi_int_reg;
|
||||
assign cfg_interrupt_msi_pending_status = msi_irq_reg;
|
||||
assign cfg_interrupt_msi_pending_status_data_enable = 1'b1; // set PF0 pending status
|
||||
assign cfg_interrupt_msi_pending_status_function_num = 4'd0; // set PF0 pending status
|
||||
assign cfg_interrupt_msi_attr = 3'd0;
|
||||
assign cfg_interrupt_msi_tph_present = 1'b0; // no TPH
|
||||
assign cfg_interrupt_msi_tph_type = 2'd0;
|
||||
assign cfg_interrupt_msi_tph_st_tag = 9'd0;
|
||||
assign cfg_interrupt_msi_function_number = 4'd0; // send MSI for PF0
|
||||
|
||||
wire [MSI_COUNT-1:0] message_enable_mask = cfg_interrupt_msi_mmenable[2:0] > 3'd4 ? {32{1'b1}} : {32{1'b1}} >> (32 - (1 << cfg_interrupt_msi_mmenable[2:0]));
|
||||
|
||||
reg [MSI_COUNT-1:0] acknowledge;
|
||||
wire [MSI_COUNT-1:0] grant;
|
||||
wire grant_valid;
|
||||
|
||||
// arbiter instance
|
||||
arbiter #(
|
||||
.PORTS(MSI_COUNT),
|
||||
.TYPE("ROUND_ROBIN"),
|
||||
.BLOCK("ACKNOWLEDGE"),
|
||||
.LSB_PRIORITY("HIGH")
|
||||
)
|
||||
arb_inst (
|
||||
.clk(clk),
|
||||
.rst(rst),
|
||||
.request(msi_irq_active_reg & msi_irq_mask_reg & ~grant),
|
||||
.acknowledge(acknowledge),
|
||||
.grant(grant),
|
||||
.grant_valid(grant_valid),
|
||||
.grant_encoded()
|
||||
);
|
||||
|
||||
always @* begin
|
||||
active_next = active_reg;
|
||||
|
||||
msi_irq_active_next = (msi_irq_active_reg | (msi_irq_reg & ~msi_irq_last_reg));
|
||||
|
||||
msi_irq_mask_next = ~cfg_interrupt_msi_data & message_enable_mask & {32{cfg_interrupt_msi_enable[0]}};
|
||||
|
||||
msi_int_next = {MSI_COUNT{1'b0}};
|
||||
|
||||
acknowledge = {MSI_COUNT{1'b0}};
|
||||
|
||||
if (!active_reg) begin
|
||||
if (cfg_interrupt_msi_enable && grant_valid) begin
|
||||
msi_int_next = grant;
|
||||
active_next = 1'b1;
|
||||
end
|
||||
end else begin
|
||||
if (cfg_interrupt_msi_sent || cfg_interrupt_msi_fail) begin
|
||||
if (cfg_interrupt_msi_sent) begin
|
||||
msi_irq_active_next = msi_irq_active_next & ~grant;
|
||||
end
|
||||
acknowledge = grant;
|
||||
active_next = 1'b0;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (rst) begin
|
||||
active_reg <= 1'b0;
|
||||
msi_irq_reg <= {MSI_COUNT{1'b0}};
|
||||
msi_irq_last_reg <= {MSI_COUNT{1'b0}};
|
||||
msi_irq_active_reg <= {MSI_COUNT{1'b0}};
|
||||
msi_irq_mask_reg <= {MSI_COUNT{1'b0}};
|
||||
msi_int_reg <= {MSI_COUNT{1'b0}};
|
||||
end else begin
|
||||
active_reg <= active_next;
|
||||
msi_irq_reg <= msi_irq;
|
||||
msi_irq_last_reg <= msi_irq_reg;
|
||||
msi_irq_active_reg <= msi_irq_active_next;
|
||||
msi_irq_mask_reg <= msi_irq_mask_next;
|
||||
msi_int_reg <= msi_int_next;
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
94
fpga/lib/pcie/rtl/priority_encoder.v
Normal file
94
fpga/lib/pcie/rtl/priority_encoder.v
Normal file
@ -0,0 +1,94 @@
|
||||
/*
|
||||
|
||||
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
|
||||
|
||||
/*
|
||||
* Priority encoder module
|
||||
*/
|
||||
module priority_encoder #
|
||||
(
|
||||
parameter WIDTH = 4,
|
||||
// LSB priority: "LOW", "HIGH"
|
||||
parameter LSB_PRIORITY = "LOW"
|
||||
)
|
||||
(
|
||||
input wire [WIDTH-1:0] input_unencoded,
|
||||
output wire output_valid,
|
||||
output wire [$clog2(WIDTH)-1:0] output_encoded,
|
||||
output wire [WIDTH-1:0] output_unencoded
|
||||
);
|
||||
|
||||
// power-of-two width
|
||||
parameter W1 = 2**$clog2(WIDTH);
|
||||
parameter W2 = W1/2;
|
||||
|
||||
generate
|
||||
if (WIDTH == 2) begin
|
||||
// two inputs - just an OR gate
|
||||
assign output_valid = |input_unencoded;
|
||||
if (LSB_PRIORITY == "LOW") begin
|
||||
assign output_encoded = input_unencoded[1];
|
||||
end else begin
|
||||
assign output_encoded = ~input_unencoded[0];
|
||||
end
|
||||
end else begin
|
||||
// more than two inputs - split into two parts and recurse
|
||||
// also pad input to correct power-of-two width
|
||||
wire [$clog2(W2)-1:0] out1, out2;
|
||||
wire valid1, valid2;
|
||||
priority_encoder #(
|
||||
.WIDTH(W2),
|
||||
.LSB_PRIORITY(LSB_PRIORITY)
|
||||
)
|
||||
priority_encoder_inst1 (
|
||||
.input_unencoded(input_unencoded[W2-1:0]),
|
||||
.output_valid(valid1),
|
||||
.output_encoded(out1)
|
||||
);
|
||||
priority_encoder #(
|
||||
.WIDTH(W2),
|
||||
.LSB_PRIORITY(LSB_PRIORITY)
|
||||
)
|
||||
priority_encoder_inst2 (
|
||||
.input_unencoded({{W1-WIDTH{1'b0}}, input_unencoded[WIDTH-1:W2]}),
|
||||
.output_valid(valid2),
|
||||
.output_encoded(out2)
|
||||
);
|
||||
// multiplexer to select part
|
||||
assign output_valid = valid1 | valid2;
|
||||
if (LSB_PRIORITY == "LOW") begin
|
||||
assign output_encoded = valid2 ? {1'b1, out2} : {1'b0, out1};
|
||||
end else begin
|
||||
assign output_encoded = valid1 ? {1'b0, out1} : {1'b1, out2};
|
||||
end
|
||||
end
|
||||
endgenerate
|
||||
|
||||
// unencoded output
|
||||
assign output_unencoded = 1 << output_encoded;
|
||||
|
||||
endmodule
|
77
fpga/lib/pcie/rtl/pulse_merge.v
Normal file
77
fpga/lib/pcie/rtl/pulse_merge.v
Normal file
@ -0,0 +1,77 @@
|
||||
/*
|
||||
|
||||
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
|
||||
|
||||
/*
|
||||
* Pulse merge module
|
||||
*/
|
||||
module pulse_merge #
|
||||
(
|
||||
parameter INPUT_WIDTH = 2,
|
||||
parameter COUNT_WIDTH = 4
|
||||
)
|
||||
(
|
||||
input wire clk,
|
||||
input wire rst,
|
||||
|
||||
input wire [INPUT_WIDTH-1:0] pulse_in,
|
||||
output wire [COUNT_WIDTH-1:0] count_out,
|
||||
output wire pulse_out
|
||||
);
|
||||
|
||||
reg [COUNT_WIDTH-1:0] count_reg = {COUNT_WIDTH{1'b0}}, count_next;
|
||||
reg pulse_reg = 1'b0, pulse_next;
|
||||
|
||||
assign count_out = count_reg;
|
||||
assign pulse_out = pulse_reg;
|
||||
|
||||
integer i;
|
||||
|
||||
always @* begin
|
||||
count_next = count_reg;
|
||||
pulse_next = count_reg > 0;
|
||||
|
||||
if (count_reg > 0) begin
|
||||
count_next = count_reg - 1;
|
||||
end
|
||||
|
||||
for (i = 0; i < INPUT_WIDTH; i = i + 1) begin
|
||||
count_next = count_next + pulse_in[i];
|
||||
end
|
||||
end
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (rst) begin
|
||||
count_reg <= {COUNT_WIDTH{1'b0}};
|
||||
pulse_reg <= 1'b0;
|
||||
end else begin
|
||||
count_reg <= count_next;
|
||||
pulse_reg <= pulse_next;
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
41
fpga/lib/pcie/scripts/pcie_disable_fatal_err.sh
Executable file
41
fpga/lib/pcie/scripts/pcie_disable_fatal_err.sh
Executable file
@ -0,0 +1,41 @@
|
||||
#!/bin/bash
|
||||
|
||||
dev=$1
|
||||
|
||||
if [ -z "$dev" ]; then
|
||||
echo "Error: no device specified"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -e "/sys/bus/pci/devices/$dev" ]; then
|
||||
dev="0000:$dev"
|
||||
fi
|
||||
|
||||
if [ ! -e "/sys/bus/pci/devices/$dev" ]; then
|
||||
echo "Error: device $dev not found"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
port=$(basename $(dirname $(readlink "/sys/bus/pci/devices/$dev")))
|
||||
|
||||
if [ ! -e "/sys/bus/pci/devices/$port" ]; then
|
||||
echo "Error: device $port not found"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Disabling fatal error reporting on port $port..."
|
||||
|
||||
cmd=$(setpci -s $port COMMAND)
|
||||
|
||||
echo "Command:" $cmd
|
||||
|
||||
# clear SERR bit in command register
|
||||
setpci -s $port COMMAND=$(printf "%04x" $(("0x$cmd" & ~0x0100)))
|
||||
|
||||
ctrl=$(setpci -s $port CAP_EXP+8.w)
|
||||
|
||||
echo "Device control:" $ctrl
|
||||
|
||||
# clear fatal error reporting enable bit in device control register
|
||||
setpci -s $port CAP_EXP+8.w=$(printf "%04x" $(("0x$ctrl" & ~0x0004)))
|
||||
|
44
fpga/lib/pcie/scripts/pcie_ext_tag.sh
Executable file
44
fpga/lib/pcie/scripts/pcie_ext_tag.sh
Executable file
@ -0,0 +1,44 @@
|
||||
#!/bin/bash
|
||||
|
||||
dev=$1
|
||||
en=$2
|
||||
|
||||
if [ -z "$dev" ]; then
|
||||
echo "Error: no device specified"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -z "$en" ]; then
|
||||
echo "Error: must specify operation"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -e "/sys/bus/pci/devices/$dev" ]; then
|
||||
dev="0000:$dev"
|
||||
fi
|
||||
|
||||
if [ ! -e "/sys/bus/pci/devices/$dev" ]; then
|
||||
echo "Error: device $dev not found"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
ctrl=$(setpci -s $dev CAP_EXP+8.w)
|
||||
|
||||
if (($en > 0)); then
|
||||
|
||||
echo "Enabling ext tag on $dev..."
|
||||
|
||||
echo "Device control:" $ctrl
|
||||
|
||||
setpci -s $dev CAP_EXP+8.w=$(printf "%04x" $(("0x$ctrl" | 0x0100)))
|
||||
|
||||
else
|
||||
|
||||
echo "Disabling ext tag on $dev..."
|
||||
|
||||
echo "Device control:" $ctrl
|
||||
|
||||
setpci -s $dev CAP_EXP+8.w=$(printf "%04x" $(("0x$ctrl" & ~0x0100)))
|
||||
|
||||
fi
|
||||
|
23
fpga/lib/pcie/scripts/pcie_flr.sh
Executable file
23
fpga/lib/pcie/scripts/pcie_flr.sh
Executable file
@ -0,0 +1,23 @@
|
||||
#!/bin/bash
|
||||
|
||||
dev=$1
|
||||
|
||||
if [ -z "$dev" ]; then
|
||||
echo "Error: no device specified"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -e "/sys/bus/pci/devices/$dev" ]; then
|
||||
dev="0000:$dev"
|
||||
fi
|
||||
|
||||
if [ ! -e "/sys/bus/pci/devices/$dev" ]; then
|
||||
echo "Error: device $dev not found"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Resetting function $dev..."
|
||||
|
||||
echo 1 > "/sys/bus/pci/devices/$dev/reset"
|
||||
|
||||
|
49
fpga/lib/pcie/scripts/pcie_force_gen2.sh
Executable file
49
fpga/lib/pcie/scripts/pcie_force_gen2.sh
Executable file
@ -0,0 +1,49 @@
|
||||
#!/bin/bash
|
||||
|
||||
dev=$1
|
||||
|
||||
if [ -z "$dev" ]; then
|
||||
echo "Error: no device specified"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -e "/sys/bus/pci/devices/$dev" ]; then
|
||||
dev="0000:$dev"
|
||||
fi
|
||||
|
||||
if [ ! -e "/sys/bus/pci/devices/$dev" ]; then
|
||||
echo "Error: device $dev not found"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
port=$(basename $(dirname $(readlink "/sys/bus/pci/devices/$dev")))
|
||||
|
||||
if [[ $port != pci* ]]; then
|
||||
echo "Note: it may be necessary to run this on the corresponding upstream port"
|
||||
echo "Device $dev is connected to upstream port $port"
|
||||
fi
|
||||
|
||||
echo "Configuring $dev..."
|
||||
|
||||
lc2=$(setpci -s $dev CAP_EXP+30.L)
|
||||
|
||||
echo "Original link control 2:" $lc2
|
||||
echo "Original link target speed:" $(("0x$lc2" & 0xF))
|
||||
|
||||
lc2n=$(printf "%08x" $((("0x$lc2" & 0xFFFFFFF0) | 0x2)))
|
||||
|
||||
echo "New link control 2:" $lc2n
|
||||
|
||||
setpci -s $dev CAP_EXP+30.L=$lc2n
|
||||
|
||||
echo "Triggering link retraining..."
|
||||
|
||||
lc=$(setpci -s $dev CAP_EXP+10.L)
|
||||
|
||||
echo "Original link control:" $lc
|
||||
|
||||
lcn=$(printf "%08x" $(("0x$lc" | 0x20)))
|
||||
|
||||
echo "New link control:" $lcn
|
||||
|
||||
setpci -s $dev CAP_EXP+10.L=$lcn
|
45
fpga/lib/pcie/scripts/pcie_hot_reset.sh
Executable file
45
fpga/lib/pcie/scripts/pcie_hot_reset.sh
Executable file
@ -0,0 +1,45 @@
|
||||
#!/bin/bash
|
||||
|
||||
dev=$1
|
||||
|
||||
if [ -z "$dev" ]; then
|
||||
echo "Error: no device specified"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -e "/sys/bus/pci/devices/$dev" ]; then
|
||||
dev="0000:$dev"
|
||||
fi
|
||||
|
||||
if [ ! -e "/sys/bus/pci/devices/$dev" ]; then
|
||||
echo "Error: device $dev not found"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
port=$(basename $(dirname $(readlink "/sys/bus/pci/devices/$dev")))
|
||||
|
||||
if [ ! -e "/sys/bus/pci/devices/$port" ]; then
|
||||
echo "Error: device $port not found"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Removing $dev..."
|
||||
|
||||
echo 1 > "/sys/bus/pci/devices/$dev/remove"
|
||||
|
||||
echo "Performing hot reset of port $port..."
|
||||
|
||||
bc=$(setpci -s $port BRIDGE_CONTROL)
|
||||
|
||||
echo "Bridge control:" $bc
|
||||
|
||||
setpci -s $port BRIDGE_CONTROL=$(printf "%04x" $(("0x$bc" | 0x40)))
|
||||
sleep 0.01
|
||||
setpci -s $port BRIDGE_CONTROL=$bc
|
||||
sleep 0.5
|
||||
|
||||
echo "Rescanning bus..."
|
||||
|
||||
echo 1 > "/sys/bus/pci/devices/$port/rescan"
|
||||
|
||||
|
5
fpga/lib/pcie/scripts/pcie_rescan.sh
Executable file
5
fpga/lib/pcie/scripts/pcie_rescan.sh
Executable file
@ -0,0 +1,5 @@
|
||||
#!/bin/bash
|
||||
|
||||
echo 1 > /sys/bus/pci/rescan
|
||||
|
||||
|
27
fpga/lib/pcie/scripts/pcie_reset.sh
Executable file
27
fpga/lib/pcie/scripts/pcie_reset.sh
Executable file
@ -0,0 +1,27 @@
|
||||
#!/bin/bash
|
||||
|
||||
dev=$1
|
||||
|
||||
if [ -z "$dev" ]; then
|
||||
echo "Error: no device specified"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -e "/sys/bus/pci/devices/$dev" ]; then
|
||||
dev="0000:$dev"
|
||||
fi
|
||||
|
||||
if [ ! -e "/sys/bus/pci/devices/$dev" ]; then
|
||||
echo "Error: device $dev not found"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Removing $dev..."
|
||||
|
||||
echo 1 > "/sys/bus/pci/devices/$dev/remove"
|
||||
|
||||
echo "Rescanning bus..."
|
||||
|
||||
echo 1 > "/sys/bus/pci/rescan"
|
||||
|
||||
|
788
fpga/lib/pcie/tb/axi.py
Normal file
788
fpga/lib/pcie/tb/axi.py
Normal file
@ -0,0 +1,788 @@
|
||||
"""
|
||||
|
||||
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 math
|
||||
import mmap
|
||||
|
||||
BURST_FIXED = 0b00
|
||||
BURST_INCR = 0b01
|
||||
BURST_WRAP = 0b10
|
||||
|
||||
BURST_SIZE_1 = 0b000
|
||||
BURST_SIZE_2 = 0b001
|
||||
BURST_SIZE_4 = 0b010
|
||||
BURST_SIZE_8 = 0b011
|
||||
BURST_SIZE_16 = 0b100
|
||||
BURST_SIZE_32 = 0b101
|
||||
BURST_SIZE_64 = 0b110
|
||||
BURST_SIZE_128 = 0b111
|
||||
|
||||
LOCK_NORMAL = 0b0
|
||||
LOCK_EXCLUSIVE = 0b1
|
||||
|
||||
CACHE_B = 0b0001
|
||||
CACHE_M = 0b0010
|
||||
CACHE_RA = 0b0100
|
||||
CACHE_WA = 0b1000
|
||||
|
||||
ARCACHE_DEVICE_NON_BUFFERABLE = 0b0000
|
||||
ARCACHE_DEVICE_BUFFERABLE = 0b0001
|
||||
ARCACHE_NORMAL_NON_CACHEABLE_NON_BUFFERABLE = 0b0010
|
||||
ARCACHE_NORMAL_NON_CACHEABLE_BUFFERABLE = 0b0011
|
||||
ARCACHE_WRITE_THROUGH_NO_ALLOC = 0b1010
|
||||
ARCACHE_WRITE_THROUGH_READ_ALLOC = 0b1110
|
||||
ARCACHE_WRITE_THROUGH_WRITE_ALLOC = 0b1010
|
||||
ARCACHE_WRITE_THROUGH_READ_AND_WRITE_ALLOC = 0b1110
|
||||
ARCACHE_WRITE_BACK_NO_ALLOC = 0b1011
|
||||
ARCACHE_WRITE_BACK_READ_ALLOC = 0b1111
|
||||
ARCACHE_WRITE_BACK_WRITE_ALLOC = 0b1011
|
||||
ARCACHE_WRITE_BACK_READ_AND_WRIE_ALLOC = 0b1111
|
||||
|
||||
AWCACHE_DEVICE_NON_BUFFERABLE = 0b0000
|
||||
AWCACHE_DEVICE_BUFFERABLE = 0b0001
|
||||
AWCACHE_NORMAL_NON_CACHEABLE_NON_BUFFERABLE = 0b0010
|
||||
AWCACHE_NORMAL_NON_CACHEABLE_BUFFERABLE = 0b0011
|
||||
AWCACHE_WRITE_THROUGH_NO_ALLOC = 0b0110
|
||||
AWCACHE_WRITE_THROUGH_READ_ALLOC = 0b0110
|
||||
AWCACHE_WRITE_THROUGH_WRITE_ALLOC = 0b1110
|
||||
AWCACHE_WRITE_THROUGH_READ_AND_WRITE_ALLOC = 0b1110
|
||||
AWCACHE_WRITE_BACK_NO_ALLOC = 0b0111
|
||||
AWCACHE_WRITE_BACK_READ_ALLOC = 0b0111
|
||||
AWCACHE_WRITE_BACK_WRITE_ALLOC = 0b1111
|
||||
AWCACHE_WRITE_BACK_READ_AND_WRIE_ALLOC = 0b1111
|
||||
|
||||
class AXIMaster(object):
|
||||
def __init__(self):
|
||||
self.write_command_queue = []
|
||||
self.write_command_sync = Signal(False)
|
||||
self.write_resp_queue = []
|
||||
self.write_resp_sync = Signal(False)
|
||||
|
||||
self.read_command_queue = []
|
||||
self.read_command_sync = Signal(False)
|
||||
self.read_data_queue = []
|
||||
self.read_data_sync = Signal(False)
|
||||
|
||||
self.cur_write_id = 0
|
||||
self.cur_read_id = 0
|
||||
|
||||
self.int_write_addr_queue = []
|
||||
self.int_write_addr_sync = Signal(False)
|
||||
self.int_write_data_queue = []
|
||||
self.int_write_data_sync = Signal(False)
|
||||
self.int_write_resp_command_queue = []
|
||||
self.int_write_resp_command_sync = Signal(False)
|
||||
self.int_write_resp_queue = []
|
||||
self.int_write_resp_sync = Signal(False)
|
||||
|
||||
self.int_read_addr_queue = []
|
||||
self.int_read_addr_sync = Signal(False)
|
||||
self.int_read_resp_command_queue = []
|
||||
self.int_read_resp_command_sync = Signal(False)
|
||||
self.int_read_resp_queue = []
|
||||
self.int_read_resp_sync = Signal(False)
|
||||
|
||||
self.in_flight_operations = 0
|
||||
|
||||
self.has_logic = False
|
||||
self.clk = None
|
||||
|
||||
def init_read(self, address, length, burst=0b01, size=None, lock=0b0, cache=0b0000, prot=0b010, qos=0b0000, region=0b0000, user=None):
|
||||
self.read_command_queue.append((address, length, burst, size, lock, cache, prot, qos, region, user))
|
||||
self.read_command_sync.next = not self.read_command_sync
|
||||
|
||||
def init_write(self, address, data, burst=0b01, size=None, lock=0b0, cache=0b0000, prot=0b010, qos=0b0000, region=0b0000, user=None):
|
||||
self.write_command_queue.append((address, data, burst, size, lock, cache, prot, qos, region, user))
|
||||
self.write_command_sync.next = not self.write_command_sync
|
||||
|
||||
def idle(self):
|
||||
return not self.write_command_queue and not self.read_command_queue and not self.in_flight_operations
|
||||
|
||||
def wait(self):
|
||||
while not self.idle():
|
||||
yield self.clk.posedge
|
||||
|
||||
def read_data_ready(self):
|
||||
return bool(self.read_data_queue)
|
||||
|
||||
def get_read_data(self):
|
||||
if self.read_data_queue:
|
||||
return self.read_data_queue.pop(0)
|
||||
return None
|
||||
|
||||
def create_logic(self,
|
||||
clk,
|
||||
rst,
|
||||
m_axi_awid=None,
|
||||
m_axi_awaddr=None,
|
||||
m_axi_awlen=Signal(intbv(0)[8:]),
|
||||
m_axi_awsize=Signal(intbv(0)[3:]),
|
||||
m_axi_awburst=Signal(intbv(0)[2:]),
|
||||
m_axi_awlock=Signal(intbv(0)[1:]),
|
||||
m_axi_awcache=Signal(intbv(0)[4:]),
|
||||
m_axi_awprot=Signal(intbv(0)[3:]),
|
||||
m_axi_awqos=Signal(intbv(0)[4:]),
|
||||
m_axi_awregion=Signal(intbv(0)[4:]),
|
||||
m_axi_awuser=None,
|
||||
m_axi_awvalid=Signal(bool(False)),
|
||||
m_axi_awready=Signal(bool(True)),
|
||||
m_axi_wdata=None,
|
||||
m_axi_wstrb=Signal(intbv(1)[1:]),
|
||||
m_axi_wlast=Signal(bool(True)),
|
||||
m_axi_wuser=None,
|
||||
m_axi_wvalid=Signal(bool(False)),
|
||||
m_axi_wready=Signal(bool(True)),
|
||||
m_axi_bid=None,
|
||||
m_axi_bresp=Signal(intbv(0)[2:]),
|
||||
m_axi_buser=None,
|
||||
m_axi_bvalid=Signal(bool(False)),
|
||||
m_axi_bready=Signal(bool(False)),
|
||||
m_axi_arid=None,
|
||||
m_axi_araddr=None,
|
||||
m_axi_arlen=Signal(intbv(0)[8:]),
|
||||
m_axi_arsize=Signal(intbv(0)[3:]),
|
||||
m_axi_arburst=Signal(intbv(0)[2:]),
|
||||
m_axi_arlock=Signal(intbv(0)[1:]),
|
||||
m_axi_arcache=Signal(intbv(0)[4:]),
|
||||
m_axi_arprot=Signal(intbv(0)[3:]),
|
||||
m_axi_arqos=Signal(intbv(0)[4:]),
|
||||
m_axi_arregion=Signal(intbv(0)[4:]),
|
||||
m_axi_aruser=None,
|
||||
m_axi_arvalid=Signal(bool(False)),
|
||||
m_axi_arready=Signal(bool(True)),
|
||||
m_axi_rid=None,
|
||||
m_axi_rdata=None,
|
||||
m_axi_rresp=Signal(intbv(0)[2:]),
|
||||
m_axi_rlast=Signal(bool(True)),
|
||||
m_axi_ruser=None,
|
||||
m_axi_rvalid=Signal(bool(False)),
|
||||
m_axi_rready=Signal(bool(False)),
|
||||
name=None
|
||||
):
|
||||
|
||||
if self.has_logic:
|
||||
raise Exception("Logic already instantiated!")
|
||||
|
||||
if m_axi_wdata is not None:
|
||||
assert m_axi_awid is not None
|
||||
assert m_axi_bid is not None
|
||||
assert len(m_axi_awid) == len(m_axi_bid)
|
||||
assert m_axi_awaddr is not None
|
||||
assert len(m_axi_wdata) % 8 == 0
|
||||
assert len(m_axi_wdata) / 8 == len(m_axi_wstrb)
|
||||
w = len(m_axi_wdata)
|
||||
|
||||
if m_axi_rdata is not None:
|
||||
assert m_axi_arid is not None
|
||||
assert m_axi_rid is not None
|
||||
assert len(m_axi_arid) == len(m_axi_rid)
|
||||
assert m_axi_araddr is not None
|
||||
assert len(m_axi_rdata) % 8 == 0
|
||||
w = len(m_axi_rdata)
|
||||
|
||||
if m_axi_wdata is not None:
|
||||
assert len(m_axi_wdata) == len(m_axi_rdata)
|
||||
assert len(m_axi_awid) == len(m_axi_arid)
|
||||
assert len(m_axi_awaddr) == len(m_axi_araddr)
|
||||
|
||||
bw = int(w/8)
|
||||
|
||||
assert bw in (1, 2, 4, 8, 16, 32, 64, 128)
|
||||
|
||||
self.has_logic = True
|
||||
self.clk = clk
|
||||
|
||||
@instance
|
||||
def write_logic():
|
||||
while True:
|
||||
if not self.write_command_queue:
|
||||
yield self.write_command_sync
|
||||
|
||||
addr, data, burst, size, lock, cache, prot, qos, region, user = self.write_command_queue.pop(0)
|
||||
self.in_flight_operations += 1
|
||||
|
||||
num_bytes = bw
|
||||
|
||||
if size is None:
|
||||
size = int(math.log(bw, 2))
|
||||
else:
|
||||
num_bytes = 2**size
|
||||
assert 0 < num_bytes <= bw
|
||||
|
||||
aligned_addr = int(addr/num_bytes)*num_bytes
|
||||
word_addr = int(addr/bw)*bw
|
||||
|
||||
start_offset = addr % bw
|
||||
end_offset = ((addr + len(data) - 1) % bw) + 1
|
||||
|
||||
cycles = int((len(data) + num_bytes-1 + (addr % num_bytes)) / num_bytes)
|
||||
|
||||
cur_addr = aligned_addr
|
||||
offset = 0
|
||||
cycle_offset = aligned_addr-word_addr
|
||||
n = 0
|
||||
transfer_count = 0
|
||||
|
||||
burst_length = 0
|
||||
|
||||
if name is not None:
|
||||
print("[%s] Write data addr: 0x%08x prot: 0x%x data: %s" % (name, addr, prot, " ".join(("{:02x}".format(c) for c in bytearray(data)))))
|
||||
|
||||
for k in range(cycles):
|
||||
start = cycle_offset
|
||||
stop = cycle_offset+num_bytes
|
||||
|
||||
if k == 0:
|
||||
start = start_offset
|
||||
if k == cycles-1:
|
||||
stop = end_offset
|
||||
|
||||
strb = ((2**bw-1) << start) & (2**bw-1) & (2**bw-1) >> (bw - stop)
|
||||
|
||||
val = 0
|
||||
for j in range(start, stop):
|
||||
val |= bytearray(data)[offset] << j*8
|
||||
offset += 1
|
||||
|
||||
if n >= burst_length:
|
||||
transfer_count += 1
|
||||
n = 0
|
||||
burst_length = min(cycles-k, 256) # max len
|
||||
burst_length = min(burst_length, 0x1000-(cur_addr&0xfff)) # 4k align
|
||||
awid = self.cur_write_id
|
||||
self.cur_write_id = (self.cur_write_id + 1) % 2**len(m_axi_awid)
|
||||
self.int_write_addr_queue.append((cur_addr, awid, burst_length-1, size, burst, lock, cache, prot, qos, region, user))
|
||||
self.int_write_addr_sync.next = not self.int_write_addr_sync
|
||||
n += 1
|
||||
self.int_write_data_queue.append((val, strb, n >= burst_length))
|
||||
self.int_write_data_sync.next = not self.int_write_data_sync
|
||||
|
||||
cur_addr += num_bytes
|
||||
cycle_offset = (cycle_offset + num_bytes) % bw
|
||||
|
||||
self.int_write_resp_command_queue.append((addr, len(data), transfer_count, prot))
|
||||
self.int_write_resp_command_sync.next = not self.int_write_resp_command_sync
|
||||
|
||||
@instance
|
||||
def write_resp_logic():
|
||||
while True:
|
||||
if not self.int_write_resp_command_queue:
|
||||
yield self.int_write_resp_command_sync
|
||||
|
||||
addr, length, transfer_count, prot = self.int_write_resp_command_queue.pop(0)
|
||||
|
||||
resp = 0
|
||||
|
||||
for k in range(transfer_count):
|
||||
while not self.int_write_resp_queue:
|
||||
yield clk.posedge
|
||||
|
||||
cycle_resp = self.int_write_resp_queue.pop(0)
|
||||
|
||||
if cycle_resp != 0:
|
||||
resp = cycle_resp
|
||||
|
||||
self.write_resp_queue.append((addr, length, prot, resp))
|
||||
self.write_resp_sync.next = not self.write_resp_sync
|
||||
self.in_flight_operations -= 1
|
||||
|
||||
@instance
|
||||
def write_addr_interface_logic():
|
||||
while True:
|
||||
while not self.int_write_addr_queue:
|
||||
yield clk.posedge
|
||||
|
||||
addr, awid, length, size, burst, lock, cache, prot, qos, region, user = self.int_write_addr_queue.pop(0)
|
||||
m_axi_awaddr.next = addr
|
||||
m_axi_awid.next = awid
|
||||
m_axi_awlen.next = length
|
||||
m_axi_awsize.next = size
|
||||
m_axi_awburst.next = burst
|
||||
m_axi_awlock.next = lock
|
||||
m_axi_awcache.next = cache
|
||||
m_axi_awprot.next = prot
|
||||
m_axi_awqos.next = qos
|
||||
m_axi_awregion.next = region
|
||||
if m_axi_awuser is not None:
|
||||
m_axi_awuser.next = user
|
||||
m_axi_awvalid.next = True
|
||||
|
||||
yield clk.posedge
|
||||
|
||||
while m_axi_awvalid and not m_axi_awready:
|
||||
yield clk.posedge
|
||||
|
||||
m_axi_awvalid.next = False
|
||||
|
||||
@instance
|
||||
def write_data_interface_logic():
|
||||
while True:
|
||||
while not self.int_write_data_queue:
|
||||
yield clk.posedge
|
||||
|
||||
m_axi_wdata.next, m_axi_wstrb.next, m_axi_wlast.next = self.int_write_data_queue.pop(0)
|
||||
m_axi_wvalid.next = True
|
||||
|
||||
yield clk.posedge
|
||||
|
||||
while m_axi_wvalid and not m_axi_wready:
|
||||
yield clk.posedge
|
||||
|
||||
m_axi_wvalid.next = False
|
||||
|
||||
@instance
|
||||
def write_resp_interface_logic():
|
||||
while True:
|
||||
m_axi_bready.next = True
|
||||
|
||||
yield clk.posedge
|
||||
|
||||
if m_axi_bready & m_axi_bvalid:
|
||||
self.int_write_resp_queue.append(int(m_axi_bresp))
|
||||
self.int_write_resp_sync.next = not self.int_write_resp_sync
|
||||
|
||||
@instance
|
||||
def read_logic():
|
||||
while True:
|
||||
if not self.read_command_queue:
|
||||
yield self.read_command_sync
|
||||
|
||||
addr, length, burst, size, lock, cache, prot, qos, region, user = self.read_command_queue.pop(0)
|
||||
self.in_flight_operations += 1
|
||||
|
||||
num_bytes = bw
|
||||
|
||||
if size is None:
|
||||
size = int(math.log(bw, 2))
|
||||
else:
|
||||
num_bytes = 2**size
|
||||
assert 0 < num_bytes <= bw
|
||||
|
||||
aligned_addr = int(addr/num_bytes)*num_bytes
|
||||
word_addr = int(addr/bw)*bw
|
||||
|
||||
cycles = int((length + num_bytes-1 + (addr % num_bytes)) / num_bytes)
|
||||
|
||||
self.int_read_resp_command_queue.append((addr, length, size, cycles, prot))
|
||||
self.int_read_resp_command_sync.next = not self.int_read_resp_command_sync
|
||||
|
||||
cur_addr = aligned_addr
|
||||
n = 0
|
||||
|
||||
burst_length = 0
|
||||
|
||||
for k in range(cycles):
|
||||
|
||||
n += 1
|
||||
if n >= burst_length:
|
||||
n = 0
|
||||
burst_length = min(cycles-k, 256) # max len
|
||||
burst_length = min(burst_length, 0x1000-((aligned_addr+k*num_bytes)&0xfff))# 4k align
|
||||
arid = self.cur_read_id
|
||||
self.cur_read_id = (self.cur_read_id + 1) % 2**len(m_axi_arid)
|
||||
self.int_read_addr_queue.append((cur_addr, arid, burst_length-1, size, burst, lock, cache, prot, qos, region, user))
|
||||
self.int_read_addr_sync.next = not self.int_read_addr_sync
|
||||
|
||||
cur_addr += num_bytes
|
||||
|
||||
@instance
|
||||
def read_resp_logic():
|
||||
while True:
|
||||
if not self.int_read_resp_command_queue:
|
||||
yield self.int_read_resp_command_sync
|
||||
|
||||
addr, length, size, cycles, prot = self.int_read_resp_command_queue.pop(0)
|
||||
|
||||
num_bytes = 2**size
|
||||
assert 0 <= size <= int(math.log(bw, 2))
|
||||
|
||||
aligned_addr = int(addr/num_bytes)*num_bytes
|
||||
word_addr = int(addr/bw)*bw
|
||||
|
||||
start_offset = addr % bw
|
||||
end_offset = ((addr + length - 1) % bw) + 1
|
||||
|
||||
cycle_offset = aligned_addr-word_addr
|
||||
data = b''
|
||||
|
||||
resp = 0
|
||||
|
||||
for k in range(cycles):
|
||||
if not self.int_read_resp_queue:
|
||||
yield self.int_read_resp_sync
|
||||
|
||||
cycle_data, cycle_resp, cycle_last = self.int_read_resp_queue.pop(0)
|
||||
|
||||
if cycle_resp != 0:
|
||||
resp = cycle_resp
|
||||
|
||||
start = cycle_offset
|
||||
stop = cycle_offset+num_bytes
|
||||
|
||||
if k == 0:
|
||||
start = start_offset
|
||||
if k == cycles-1:
|
||||
stop = end_offset
|
||||
|
||||
assert cycle_last == (k == cycles - 1)
|
||||
|
||||
for j in range(start, stop):
|
||||
data += bytearray([(cycle_data >> j*8) & 0xff])
|
||||
|
||||
cycle_offset = (cycle_offset + num_bytes) % bw
|
||||
|
||||
if name is not None:
|
||||
print("[%s] Read data addr: 0x%08x prot: 0x%x data: %s" % (name, addr, prot, " ".join(("{:02x}".format(c) for c in bytearray(data)))))
|
||||
|
||||
self.read_data_queue.append((addr, data, prot, resp))
|
||||
self.read_data_sync.next = not self.read_data_sync
|
||||
self.in_flight_operations -= 1
|
||||
|
||||
@instance
|
||||
def read_addr_interface_logic():
|
||||
while True:
|
||||
while not self.int_read_addr_queue:
|
||||
yield clk.posedge
|
||||
|
||||
addr, arid, length, size, burst, lock, cache, prot, qos, region, user = self.int_read_addr_queue.pop(0)
|
||||
m_axi_araddr.next = addr
|
||||
m_axi_arid.next = arid
|
||||
m_axi_arlen.next = length
|
||||
m_axi_arsize.next = size
|
||||
m_axi_arburst.next = burst
|
||||
m_axi_arlock.next = lock
|
||||
m_axi_arcache.next = cache
|
||||
m_axi_arprot.next = prot
|
||||
m_axi_arqos.next = qos
|
||||
m_axi_arregion.next = region
|
||||
if m_axi_aruser is not None:
|
||||
m_axi_aruser.next = user
|
||||
m_axi_arvalid.next = True
|
||||
|
||||
yield clk.posedge
|
||||
|
||||
while m_axi_arvalid and not m_axi_arready:
|
||||
yield clk.posedge
|
||||
|
||||
m_axi_arvalid.next = False
|
||||
|
||||
@instance
|
||||
def read_resp_interface_logic():
|
||||
while True:
|
||||
m_axi_rready.next = True
|
||||
|
||||
yield clk.posedge
|
||||
|
||||
if m_axi_rready & m_axi_rvalid:
|
||||
self.int_read_resp_queue.append((int(m_axi_rdata), int(m_axi_rresp), int(m_axi_rlast)))
|
||||
self.int_read_resp_sync.next = not self.int_read_resp_sync
|
||||
|
||||
return instances()
|
||||
|
||||
|
||||
class AXIRam(object):
|
||||
def __init__(self, size = 1024):
|
||||
self.size = size
|
||||
self.mem = mmap.mmap(-1, size)
|
||||
|
||||
self.int_write_addr_queue = []
|
||||
self.int_write_addr_sync = Signal(False)
|
||||
self.int_write_data_queue = []
|
||||
self.int_write_data_sync = Signal(False)
|
||||
self.int_write_resp_queue = []
|
||||
self.int_write_resp_sync = Signal(False)
|
||||
|
||||
self.int_read_addr_queue = []
|
||||
self.int_read_addr_sync = Signal(False)
|
||||
self.int_read_resp_queue = []
|
||||
self.int_read_resp_sync = Signal(False)
|
||||
|
||||
def read_mem(self, address, length):
|
||||
self.mem.seek(address % self.size)
|
||||
return self.mem.read(length)
|
||||
|
||||
def write_mem(self, address, data):
|
||||
self.mem.seek(address % self.size)
|
||||
self.mem.write(data)
|
||||
|
||||
def create_port(self,
|
||||
clk,
|
||||
s_axi_awid=None,
|
||||
s_axi_awaddr=None,
|
||||
s_axi_awlen=Signal(intbv(0)[8:]),
|
||||
s_axi_awsize=Signal(intbv(0)[3:]),
|
||||
s_axi_awburst=Signal(intbv(0)[2:]),
|
||||
s_axi_awlock=Signal(intbv(0)[1:]),
|
||||
s_axi_awcache=Signal(intbv(0)[4:]),
|
||||
s_axi_awprot=Signal(intbv(0)[3:]),
|
||||
s_axi_awvalid=Signal(bool(False)),
|
||||
s_axi_awready=Signal(bool(True)),
|
||||
s_axi_wdata=None,
|
||||
s_axi_wstrb=Signal(intbv(1)[1:]),
|
||||
s_axi_wlast=Signal(bool(True)),
|
||||
s_axi_wvalid=Signal(bool(False)),
|
||||
s_axi_wready=Signal(bool(True)),
|
||||
s_axi_bid=None,
|
||||
s_axi_bresp=Signal(intbv(0)[2:]),
|
||||
s_axi_bvalid=Signal(bool(False)),
|
||||
s_axi_bready=Signal(bool(False)),
|
||||
s_axi_arid=None,
|
||||
s_axi_araddr=None,
|
||||
s_axi_arlen=Signal(intbv(0)[8:]),
|
||||
s_axi_arsize=Signal(intbv(0)[3:]),
|
||||
s_axi_arburst=Signal(intbv(0)[2:]),
|
||||
s_axi_arlock=Signal(intbv(0)[1:]),
|
||||
s_axi_arcache=Signal(intbv(0)[4:]),
|
||||
s_axi_arprot=Signal(intbv(0)[3:]),
|
||||
s_axi_arvalid=Signal(bool(False)),
|
||||
s_axi_arready=Signal(bool(True)),
|
||||
s_axi_rid=None,
|
||||
s_axi_rdata=None,
|
||||
s_axi_rresp=Signal(intbv(0)[2:]),
|
||||
s_axi_rlast=Signal(bool(True)),
|
||||
s_axi_rvalid=Signal(bool(False)),
|
||||
s_axi_rready=Signal(bool(False)),
|
||||
name=None
|
||||
):
|
||||
|
||||
if s_axi_wdata is not None:
|
||||
assert s_axi_awid is not None
|
||||
assert s_axi_bid is not None
|
||||
assert len(s_axi_awid) == len(s_axi_bid)
|
||||
assert s_axi_awaddr is not None
|
||||
assert len(s_axi_wdata) % 8 == 0
|
||||
assert len(s_axi_wdata) / 8 == len(s_axi_wstrb)
|
||||
w = len(s_axi_wdata)
|
||||
|
||||
if s_axi_rdata is not None:
|
||||
assert s_axi_arid is not None
|
||||
assert s_axi_rid is not None
|
||||
assert len(s_axi_arid) == len(s_axi_rid)
|
||||
assert s_axi_araddr is not None
|
||||
assert len(s_axi_rdata) % 8 == 0
|
||||
w = len(s_axi_rdata)
|
||||
|
||||
if s_axi_wdata is not None:
|
||||
assert len(s_axi_wdata) == len(s_axi_rdata)
|
||||
assert len(s_axi_awid) == len(s_axi_arid)
|
||||
assert len(s_axi_awaddr) == len(s_axi_araddr)
|
||||
|
||||
bw = int(w/8)
|
||||
|
||||
assert bw in (1, 2, 4, 8, 16, 32, 64, 128)
|
||||
|
||||
@instance
|
||||
def write_logic():
|
||||
while True:
|
||||
if not self.int_write_addr_queue:
|
||||
yield self.int_write_addr_sync
|
||||
|
||||
addr, awid, length, size, burst, lock, cache, prot = self.int_write_addr_queue.pop(0)
|
||||
|
||||
num_bytes = 2**size
|
||||
assert 0 < num_bytes <= bw
|
||||
|
||||
aligned_addr = int(addr/num_bytes)*num_bytes
|
||||
length = length+1
|
||||
|
||||
transfer_size = num_bytes*length
|
||||
|
||||
if burst == BURST_WRAP:
|
||||
lower_wrap_boundary = int(addr/transfer_size)*transfer_size
|
||||
upper_wrap_boundary = lower_wrap_boundary+transfer_size
|
||||
|
||||
if burst == BURST_INCR:
|
||||
# check for 4k boundary crossing
|
||||
assert 0x1000-(aligned_addr&0xfff) >= transfer_size
|
||||
|
||||
cur_addr = aligned_addr
|
||||
|
||||
for n in range(length):
|
||||
cur_word_addr = int(cur_addr/bw)*bw
|
||||
|
||||
self.mem.seek(cur_word_addr % self.size)
|
||||
|
||||
if not self.int_write_data_queue:
|
||||
yield self.int_write_data_sync
|
||||
|
||||
wdata, strb, last = self.int_write_data_queue.pop(0)
|
||||
|
||||
data = bytearray()
|
||||
for i in range(bw):
|
||||
data.extend(bytearray([wdata & 0xff]))
|
||||
wdata >>= 8
|
||||
for i in range(bw):
|
||||
if strb & (1 << i):
|
||||
self.mem.write(data[i:i+1])
|
||||
else:
|
||||
self.mem.seek(1, 1)
|
||||
if n == length-1:
|
||||
self.int_write_resp_queue.append((awid, 0b00))
|
||||
self.int_write_resp_sync.next = not self.int_write_resp_sync
|
||||
assert last == (n == length-1)
|
||||
if name is not None:
|
||||
print("[%s] Write word id: %d addr: 0x%08x prot: 0x%x wstrb: 0x%02x data: %s" % (name, awid, cur_addr, prot, s_axi_wstrb, " ".join(("{:02x}".format(c) for c in bytearray(data)))))
|
||||
|
||||
if burst != BURST_FIXED:
|
||||
cur_addr += num_bytes
|
||||
|
||||
if burst == BURST_WRAP:
|
||||
if cur_addr == upper_wrap_boundary:
|
||||
cur_addr = lower_wrap_boundary
|
||||
|
||||
@instance
|
||||
def write_addr_interface_logic():
|
||||
while True:
|
||||
s_axi_awready.next = True
|
||||
|
||||
yield clk.posedge
|
||||
|
||||
if s_axi_awready & s_axi_awvalid:
|
||||
addr = int(s_axi_awaddr)
|
||||
awid = int(s_axi_awid)
|
||||
length = int(s_axi_awlen)
|
||||
size = int(s_axi_awsize)
|
||||
burst = int(s_axi_awburst)
|
||||
lock = int(s_axi_awlock)
|
||||
cache = int(s_axi_awcache)
|
||||
prot = int(s_axi_awprot)
|
||||
self.int_write_addr_queue.append((addr, awid, length, size, burst, lock, cache, prot))
|
||||
self.int_write_addr_sync.next = not self.int_write_addr_sync
|
||||
|
||||
@instance
|
||||
def write_data_interface_logic():
|
||||
while True:
|
||||
s_axi_wready.next = True
|
||||
|
||||
yield clk.posedge
|
||||
|
||||
if s_axi_wready & s_axi_wvalid:
|
||||
data = int(s_axi_wdata)
|
||||
strb = int(s_axi_wstrb)
|
||||
last = bool(s_axi_wlast)
|
||||
self.int_write_data_queue.append((data, strb, last))
|
||||
self.int_write_data_sync.next = not self.int_write_data_sync
|
||||
|
||||
@instance
|
||||
def write_resp_interface_logic():
|
||||
while True:
|
||||
while not self.int_write_resp_queue:
|
||||
yield clk.posedge
|
||||
|
||||
s_axi_bid.next, s_axi_bresp.next = self.int_write_resp_queue.pop(0)
|
||||
s_axi_bvalid.next = True
|
||||
|
||||
yield clk.posedge
|
||||
|
||||
while s_axi_bvalid and not s_axi_bready:
|
||||
yield clk.posedge
|
||||
|
||||
s_axi_bvalid.next = False
|
||||
|
||||
@instance
|
||||
def read_logic():
|
||||
while True:
|
||||
if not self.int_read_addr_queue:
|
||||
yield self.int_read_addr_sync
|
||||
|
||||
addr, arid, length, size, burst, lock, cache, prot = self.int_read_addr_queue.pop(0)
|
||||
|
||||
num_bytes = 2**size
|
||||
assert 0 < num_bytes <= bw
|
||||
|
||||
aligned_addr = int(addr/num_bytes)*num_bytes
|
||||
length = length+1
|
||||
|
||||
transfer_size = num_bytes*length
|
||||
|
||||
if burst == BURST_WRAP:
|
||||
lower_wrap_boundary = int(addr/transfer_size)*transfer_size
|
||||
upper_wrap_boundary = lower_wrap_boundary+transfer_size
|
||||
|
||||
if burst == BURST_INCR:
|
||||
# check for 4k boundary crossing
|
||||
assert 0x1000-(aligned_addr&0xfff) >= transfer_size
|
||||
|
||||
cur_addr = aligned_addr
|
||||
|
||||
for n in range(length):
|
||||
cur_word_addr = int(cur_addr/bw)*bw
|
||||
|
||||
self.mem.seek(cur_word_addr % self.size)
|
||||
|
||||
data = bytearray(self.mem.read(bw))
|
||||
val = 0
|
||||
for i in range(bw-1,-1,-1):
|
||||
val <<= 8
|
||||
val += data[i]
|
||||
self.int_read_resp_queue.append((arid, val, 0x00, n == length-1))
|
||||
self.int_read_resp_sync.next = not self.int_read_resp_sync
|
||||
if name is not None:
|
||||
print("[%s] Read word id: %d addr: 0x%08x prot: 0x%x data: %s" % (name, arid, cur_addr, prot, " ".join(("{:02x}".format(c) for c in bytearray(data)))))
|
||||
|
||||
if burst != BURST_FIXED:
|
||||
cur_addr += num_bytes
|
||||
|
||||
if burst == BURST_WRAP:
|
||||
if cur_addr == upper_wrap_boundary:
|
||||
cur_addr = lower_wrap_boundary
|
||||
|
||||
@instance
|
||||
def read_addr_interface_logic():
|
||||
while True:
|
||||
s_axi_arready.next = True
|
||||
|
||||
yield clk.posedge
|
||||
|
||||
if s_axi_arready & s_axi_arvalid:
|
||||
addr = int(s_axi_araddr)
|
||||
arid = int(s_axi_arid)
|
||||
length = int(s_axi_arlen)
|
||||
size = int(s_axi_arsize)
|
||||
burst = int(s_axi_arburst)
|
||||
lock = int(s_axi_arlock)
|
||||
cache = int(s_axi_arcache)
|
||||
prot = int(s_axi_arprot)
|
||||
self.int_read_addr_queue.append((addr, arid, length, size, burst, lock, cache, prot))
|
||||
self.int_read_addr_sync.next = not self.int_read_addr_sync
|
||||
|
||||
@instance
|
||||
def read_resp_interface_logic():
|
||||
while True:
|
||||
while not self.int_read_resp_queue:
|
||||
yield clk.posedge
|
||||
|
||||
s_axi_rid.next, s_axi_rdata.next, s_axi_rresp.next, s_axi_rlast.next = self.int_read_resp_queue.pop(0)
|
||||
s_axi_rvalid.next = True
|
||||
|
||||
yield clk.posedge
|
||||
|
||||
while s_axi_rvalid and not s_axi_rready:
|
||||
yield clk.posedge
|
||||
|
||||
s_axi_rvalid.next = False
|
||||
|
||||
return instances()
|
||||
|
470
fpga/lib/pcie/tb/axil.py
Normal file
470
fpga/lib/pcie/tb/axil.py
Normal file
@ -0,0 +1,470 @@
|
||||
"""
|
||||
|
||||
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 mmap
|
||||
|
||||
class AXILiteMaster(object):
|
||||
def __init__(self):
|
||||
self.write_command_queue = []
|
||||
self.write_resp_queue = []
|
||||
|
||||
self.read_command_queue = []
|
||||
self.read_data_queue = []
|
||||
|
||||
self.int_write_addr_queue = []
|
||||
self.int_write_data_queue = []
|
||||
self.int_write_resp_command_queue = []
|
||||
self.int_write_resp_queue = []
|
||||
|
||||
self.int_read_addr_queue = []
|
||||
self.int_read_resp_command_queue = []
|
||||
self.int_read_resp_queue = []
|
||||
|
||||
self.in_flight_operations = 0
|
||||
|
||||
self.has_logic = False
|
||||
self.clk = None
|
||||
|
||||
def init_read(self, address, length, prot=0b010):
|
||||
self.read_command_queue.append((address, length, prot))
|
||||
|
||||
def init_write(self, address, data, prot=0b010):
|
||||
self.write_command_queue.append((address, data, prot))
|
||||
|
||||
def idle(self):
|
||||
return not self.write_command_queue and not self.read_command_queue and not self.in_flight_operations
|
||||
|
||||
def wait(self):
|
||||
while not self.idle():
|
||||
yield self.clk.posedge
|
||||
|
||||
def read_data_ready(self):
|
||||
return bool(self.read_data_queue)
|
||||
|
||||
def get_read_data(self):
|
||||
if self.read_data_queue:
|
||||
return self.read_data_queue.pop(0)
|
||||
return None
|
||||
|
||||
def create_logic(self,
|
||||
clk,
|
||||
rst,
|
||||
m_axil_awaddr=None,
|
||||
m_axil_awprot=Signal(intbv(0)[3:]),
|
||||
m_axil_awvalid=Signal(bool(False)),
|
||||
m_axil_awready=Signal(bool(True)),
|
||||
m_axil_wdata=None,
|
||||
m_axil_wstrb=Signal(intbv(1)[1:]),
|
||||
m_axil_wvalid=Signal(bool(False)),
|
||||
m_axil_wready=Signal(bool(True)),
|
||||
m_axil_bresp=Signal(intbv(0)[2:]),
|
||||
m_axil_bvalid=Signal(bool(False)),
|
||||
m_axil_bready=Signal(bool(False)),
|
||||
m_axil_araddr=None,
|
||||
m_axil_arprot=Signal(intbv(0)[3:]),
|
||||
m_axil_arvalid=Signal(bool(False)),
|
||||
m_axil_arready=Signal(bool(True)),
|
||||
m_axil_rdata=None,
|
||||
m_axil_rresp=Signal(intbv(0)[2:]),
|
||||
m_axil_rvalid=Signal(bool(False)),
|
||||
m_axil_rready=Signal(bool(False)),
|
||||
name=None
|
||||
):
|
||||
|
||||
if self.has_logic:
|
||||
raise Exception("Logic already instantiated!")
|
||||
|
||||
if m_axil_wdata is not None:
|
||||
assert m_axil_awaddr is not None
|
||||
assert len(m_axil_wdata) % 8 == 0
|
||||
assert len(m_axil_wdata) / 8 == len(m_axil_wstrb)
|
||||
w = len(m_axil_wdata)
|
||||
|
||||
if m_axil_rdata is not None:
|
||||
assert m_axil_araddr is not None
|
||||
assert len(m_axil_rdata) % 8 == 0
|
||||
w = len(m_axil_rdata)
|
||||
|
||||
if m_axil_wdata is not None:
|
||||
assert len(m_axil_wdata) == len(m_axil_rdata)
|
||||
assert len(m_axil_awaddr) == len(m_axil_araddr)
|
||||
|
||||
bw = int(w/8)
|
||||
|
||||
assert bw in (1, 2, 4, 8, 16, 32, 64, 128)
|
||||
|
||||
self.has_logic = True
|
||||
self.clk = clk
|
||||
|
||||
@instance
|
||||
def write_logic():
|
||||
while True:
|
||||
while not self.write_command_queue:
|
||||
yield clk.posedge
|
||||
|
||||
addr, data, prot = self.write_command_queue.pop(0)
|
||||
self.in_flight_operations += 1
|
||||
|
||||
word_addr = int(addr/bw)*bw
|
||||
|
||||
start_offset = addr % bw
|
||||
end_offset = ((addr + len(data) - 1) % bw) + 1
|
||||
|
||||
strb_start = ((2**bw-1) << start_offset) & (2**bw-1)
|
||||
strb_end = (2**bw-1) >> (bw - end_offset)
|
||||
|
||||
cycles = int((len(data) + bw-1 + (addr % bw)) / bw)
|
||||
|
||||
self.int_write_resp_command_queue.append((addr, len(data), cycles, prot))
|
||||
|
||||
offset = 0
|
||||
|
||||
if name is not None:
|
||||
print("[%s] Write data addr: 0x%08x prot: 0x%x data: %s" % (name, addr, prot, " ".join(("{:02x}".format(c) for c in bytearray(data)))))
|
||||
|
||||
for k in range(cycles):
|
||||
start = 0
|
||||
stop = bw
|
||||
strb = 2**bw-1
|
||||
|
||||
if k == 0:
|
||||
start = start_offset
|
||||
strb &= strb_start
|
||||
if k == cycles-1:
|
||||
stop = end_offset
|
||||
strb &= strb_end
|
||||
|
||||
val = 0
|
||||
for j in range(start, stop):
|
||||
val |= bytearray(data)[offset] << j*8
|
||||
offset += 1
|
||||
|
||||
self.int_write_addr_queue.append((word_addr + start + k*bw, prot))
|
||||
self.int_write_data_queue.append((val, strb))
|
||||
|
||||
@instance
|
||||
def write_resp_logic():
|
||||
while True:
|
||||
while not self.int_write_resp_command_queue:
|
||||
yield clk.posedge
|
||||
|
||||
addr, length, cycles, prot = self.int_write_resp_command_queue.pop(0)
|
||||
|
||||
resp = 0
|
||||
|
||||
for k in range(cycles):
|
||||
while not self.int_write_resp_queue:
|
||||
yield clk.posedge
|
||||
|
||||
cycle_resp = self.int_write_resp_queue.pop(0)
|
||||
|
||||
if cycle_resp != 0:
|
||||
resp = cycle_resp
|
||||
|
||||
self.write_resp_queue.append((addr, length, prot, resp))
|
||||
self.in_flight_operations -= 1
|
||||
|
||||
@instance
|
||||
def write_addr_interface_logic():
|
||||
while True:
|
||||
while not self.int_write_addr_queue:
|
||||
yield clk.posedge
|
||||
|
||||
m_axil_awaddr.next, m_axil_awprot.next = self.int_write_addr_queue.pop(0)
|
||||
m_axil_awvalid.next = True
|
||||
|
||||
yield clk.posedge
|
||||
|
||||
while m_axil_awvalid and not m_axil_awready:
|
||||
yield clk.posedge
|
||||
|
||||
m_axil_awvalid.next = False
|
||||
|
||||
@instance
|
||||
def write_data_interface_logic():
|
||||
while True:
|
||||
while not self.int_write_data_queue:
|
||||
yield clk.posedge
|
||||
|
||||
m_axil_wdata.next, m_axil_wstrb.next = self.int_write_data_queue.pop(0)
|
||||
m_axil_wvalid.next = True
|
||||
|
||||
yield clk.posedge
|
||||
|
||||
while m_axil_wvalid and not m_axil_wready:
|
||||
yield clk.posedge
|
||||
|
||||
m_axil_wvalid.next = False
|
||||
|
||||
@instance
|
||||
def write_resp_interface_logic():
|
||||
while True:
|
||||
m_axil_bready.next = True
|
||||
|
||||
yield clk.posedge
|
||||
|
||||
if m_axil_bready & m_axil_bvalid:
|
||||
self.int_write_resp_queue.append(int(m_axil_bresp))
|
||||
|
||||
@instance
|
||||
def read_logic():
|
||||
while True:
|
||||
while not self.read_command_queue:
|
||||
yield clk.posedge
|
||||
|
||||
addr, length, prot = self.read_command_queue.pop(0)
|
||||
self.in_flight_operations += 1
|
||||
|
||||
word_addr = int(addr/bw)*bw
|
||||
|
||||
start_offset = addr % bw
|
||||
|
||||
cycles = int((length + bw-1 + (addr % bw)) / bw)
|
||||
|
||||
self.int_read_resp_command_queue.append((addr, length, cycles, prot))
|
||||
|
||||
# first cycle
|
||||
self.int_read_addr_queue.append((word_addr+start_offset, prot))
|
||||
|
||||
for k in range(1, cycles):
|
||||
# middle and last cycles
|
||||
self.int_read_addr_queue.append((word_addr + k*bw, prot))
|
||||
|
||||
@instance
|
||||
def read_resp_logic():
|
||||
while True:
|
||||
while not self.int_read_resp_command_queue:
|
||||
yield clk.posedge
|
||||
|
||||
addr, length, cycles, prot = self.int_read_resp_command_queue.pop(0)
|
||||
|
||||
word_addr = int(addr/bw)*bw
|
||||
|
||||
start_offset = addr % bw
|
||||
end_offset = ((addr + length - 1) % bw) + 1
|
||||
|
||||
data = b''
|
||||
|
||||
resp = 0
|
||||
|
||||
for k in range(cycles):
|
||||
while not self.int_read_resp_queue:
|
||||
yield clk.posedge
|
||||
|
||||
cycle_data, cycle_resp = self.int_read_resp_queue.pop(0)
|
||||
|
||||
if cycle_resp != 0:
|
||||
resp = cycle_resp
|
||||
|
||||
start = 0
|
||||
stop = bw
|
||||
|
||||
if k == 0:
|
||||
start = start_offset
|
||||
if k == cycles-1:
|
||||
stop = end_offset
|
||||
|
||||
for j in range(start, stop):
|
||||
data += bytearray([(cycle_data >> j*8) & 0xff])
|
||||
|
||||
if name is not None:
|
||||
print("[%s] Read data addr: 0x%08x prot: 0x%x data: %s" % (name, addr, prot, " ".join(("{:02x}".format(c) for c in bytearray(data)))))
|
||||
|
||||
self.read_data_queue.append((addr, data, prot, resp))
|
||||
self.in_flight_operations -= 1
|
||||
|
||||
@instance
|
||||
def read_addr_interface_logic():
|
||||
while True:
|
||||
while not self.int_read_addr_queue:
|
||||
yield clk.posedge
|
||||
|
||||
m_axil_araddr.next, m_axil_arprot.next = self.int_read_addr_queue.pop(0)
|
||||
m_axil_arvalid.next = True
|
||||
|
||||
yield clk.posedge
|
||||
|
||||
while m_axil_arvalid and not m_axil_arready:
|
||||
yield clk.posedge
|
||||
|
||||
m_axil_arvalid.next = False
|
||||
|
||||
@instance
|
||||
def read_resp_interface_logic():
|
||||
while True:
|
||||
m_axil_rready.next = True
|
||||
|
||||
yield clk.posedge
|
||||
|
||||
if m_axil_rready & m_axil_rvalid:
|
||||
self.int_read_resp_queue.append((int(m_axil_rdata), int(m_axil_rresp)))
|
||||
|
||||
return instances()
|
||||
|
||||
|
||||
class AXILiteRam(object):
|
||||
def __init__(self, size = 1024):
|
||||
self.size = size
|
||||
self.mem = mmap.mmap(-1, size)
|
||||
|
||||
def read_mem(self, address, length):
|
||||
self.mem.seek(address)
|
||||
return self.mem.read(length)
|
||||
|
||||
def write_mem(self, address, data):
|
||||
self.mem.seek(address)
|
||||
self.mem.write(bytes(data))
|
||||
|
||||
def create_port(self,
|
||||
clk,
|
||||
s_axil_awaddr=None,
|
||||
s_axil_awprot=Signal(intbv(0)[3:]),
|
||||
s_axil_awvalid=Signal(bool(False)),
|
||||
s_axil_awready=Signal(bool(True)),
|
||||
s_axil_wdata=None,
|
||||
s_axil_wstrb=Signal(intbv(1)[1:]),
|
||||
s_axil_wvalid=Signal(bool(False)),
|
||||
s_axil_wready=Signal(bool(True)),
|
||||
s_axil_bresp=Signal(intbv(0)[2:]),
|
||||
s_axil_bvalid=Signal(bool(False)),
|
||||
s_axil_bready=Signal(bool(False)),
|
||||
s_axil_araddr=None,
|
||||
s_axil_arprot=Signal(intbv(0)[3:]),
|
||||
s_axil_arvalid=Signal(bool(False)),
|
||||
s_axil_arready=Signal(bool(True)),
|
||||
s_axil_rdata=None,
|
||||
s_axil_rresp=Signal(intbv(0)[2:]),
|
||||
s_axil_rvalid=Signal(bool(False)),
|
||||
s_axil_rready=Signal(bool(False)),
|
||||
latency=1,
|
||||
name=None
|
||||
):
|
||||
|
||||
if s_axil_wdata is not None:
|
||||
assert s_axil_awaddr is not None
|
||||
assert len(s_axil_wdata) % 8 == 0
|
||||
assert len(s_axil_wdata) / 8 == len(s_axil_wstrb)
|
||||
w = len(s_axil_wdata)
|
||||
|
||||
if s_axil_rdata is not None:
|
||||
assert s_axil_araddr is not None
|
||||
assert len(s_axil_rdata) % 8 == 0
|
||||
w = len(s_axil_rdata)
|
||||
|
||||
if s_axil_wdata is not None:
|
||||
assert len(s_axil_wdata) == len(s_axil_rdata)
|
||||
assert len(s_axil_awaddr) == len(s_axil_araddr)
|
||||
|
||||
bw = int(w/8)
|
||||
|
||||
assert bw in (1, 2, 4, 8, 16, 32, 64, 128)
|
||||
|
||||
@instance
|
||||
def write_logic():
|
||||
while True:
|
||||
s_axil_awready.next = True
|
||||
|
||||
yield clk.posedge
|
||||
|
||||
addr = int(int(s_axil_awaddr)/bw)*bw
|
||||
prot = int(s_axil_awprot)
|
||||
|
||||
if s_axil_awready & s_axil_awvalid:
|
||||
s_axil_awready.next = False
|
||||
|
||||
for i in range(latency):
|
||||
yield clk.posedge
|
||||
|
||||
self.mem.seek(addr % self.size)
|
||||
|
||||
s_axil_wready.next = True
|
||||
|
||||
yield clk.posedge
|
||||
|
||||
while not s_axil_wvalid:
|
||||
yield clk.posedge
|
||||
|
||||
s_axil_wready.next = False
|
||||
|
||||
data = bytearray()
|
||||
val = int(s_axil_wdata)
|
||||
for i in range(bw):
|
||||
data.extend(bytearray([val & 0xff]))
|
||||
val >>= 8
|
||||
for i in range(bw):
|
||||
if s_axil_wstrb & (1 << i):
|
||||
self.mem.write(bytes(data[i:i+1]))
|
||||
else:
|
||||
self.mem.seek(1, 1)
|
||||
s_axil_bresp.next = 0b00
|
||||
s_axil_bvalid.next = True
|
||||
if name is not None:
|
||||
print("[%s] Write word addr: 0x%08x prot: 0x%x wstrb: 0x%02x data: %s" % (name, addr, prot, s_axil_wstrb, " ".join(("{:02x}".format(c) for c in bytearray(data)))))
|
||||
|
||||
yield clk.posedge
|
||||
|
||||
while not s_axil_bready:
|
||||
yield clk.posedge
|
||||
|
||||
s_axil_bvalid.next = False
|
||||
|
||||
@instance
|
||||
def read_logic():
|
||||
while True:
|
||||
s_axil_arready.next = True
|
||||
|
||||
yield clk.posedge
|
||||
|
||||
addr = int(int(s_axil_araddr)/bw)*bw
|
||||
prot = int(s_axil_arprot)
|
||||
|
||||
if s_axil_arready & s_axil_arvalid:
|
||||
s_axil_arready.next = False
|
||||
|
||||
for i in range(latency):
|
||||
yield clk.posedge
|
||||
|
||||
self.mem.seek(addr % self.size)
|
||||
|
||||
data = bytearray(self.mem.read(bw))
|
||||
val = 0
|
||||
for i in range(bw-1,-1,-1):
|
||||
val <<= 8
|
||||
val += data[i]
|
||||
s_axil_rdata.next = val
|
||||
s_axil_rresp.next = 0b00
|
||||
s_axil_rvalid.next = True
|
||||
if name is not None:
|
||||
print("[%s] Read word addr: 0x%08x prot: 0x%x data: %s" % (name, addr, prot, " ".join(("{:02x}".format(c) for c in bytearray(data)))))
|
||||
|
||||
yield clk.posedge
|
||||
|
||||
while not s_axil_rready:
|
||||
yield clk.posedge
|
||||
|
||||
s_axil_rvalid.next = False
|
||||
|
||||
return instances()
|
||||
|
522
fpga/lib/pcie/tb/axis_ep.py
Normal file
522
fpga/lib/pcie/tb/axis_ep.py
Normal file
@ -0,0 +1,522 @@
|
||||
"""
|
||||
|
||||
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.
|
||||
|
||||
"""
|
||||
|
||||
from myhdl import *
|
||||
|
||||
skip_asserts = False
|
||||
|
||||
class AXIStreamFrame(object):
|
||||
def __init__(self, data=b'', keep=None, id=None, dest=None, user=None, last_cycle_user=None):
|
||||
self.B = 0
|
||||
self.N = 8
|
||||
self.M = 1
|
||||
self.WL = 8
|
||||
self.data = b''
|
||||
self.keep = None
|
||||
self.id = 0
|
||||
self.dest = 0
|
||||
self.user = None
|
||||
self.last_cycle_user = None
|
||||
|
||||
if type(data) in (bytes, bytearray):
|
||||
self.data = bytearray(data)
|
||||
self.keep = keep
|
||||
self.id = id
|
||||
self.dest = dest
|
||||
self.user = user
|
||||
self.last_cycle_user = last_cycle_user
|
||||
elif type(data) is AXIStreamFrame:
|
||||
self.N = data.N
|
||||
self.WL = data.WL
|
||||
if type(data.data) is bytearray:
|
||||
self.data = bytearray(data.data)
|
||||
else:
|
||||
self.data = list(data.data)
|
||||
if data.keep is not None:
|
||||
self.keep = list(data.keep)
|
||||
if data.id is not None:
|
||||
if type(data.id) in (int, bool):
|
||||
self.id = data.id
|
||||
else:
|
||||
self.id = list(data.id)
|
||||
if data.dest is not None:
|
||||
if type(data.dest) in (int, bool):
|
||||
self.dest = data.dest
|
||||
else:
|
||||
self.dest = list(data.dest)
|
||||
if data.user is not None:
|
||||
if type(data.user) in (int, bool):
|
||||
self.user = data.user
|
||||
else:
|
||||
self.user = list(data.user)
|
||||
self.last_cycle_user = data.last_cycle_user
|
||||
else:
|
||||
self.data = list(data)
|
||||
self.keep = keep
|
||||
self.id = id
|
||||
self.dest = dest
|
||||
self.user = user
|
||||
self.last_cycle_user = last_cycle_user
|
||||
|
||||
def build(self):
|
||||
if self.data is None:
|
||||
return
|
||||
|
||||
f = list(self.data)
|
||||
tdata = []
|
||||
tkeep = []
|
||||
tid = []
|
||||
tdest = []
|
||||
tuser = []
|
||||
i = 0
|
||||
|
||||
while len(f) > 0:
|
||||
if self.B == 0:
|
||||
data = 0
|
||||
keep = 0
|
||||
for j in range(self.M):
|
||||
data = data | (f.pop(0) << (j*self.WL))
|
||||
keep = keep | (1 << j)
|
||||
if len(f) == 0: break
|
||||
tdata.append(data)
|
||||
|
||||
if self.keep is None:
|
||||
tkeep.append(keep)
|
||||
else:
|
||||
tkeep.append(self.keep[i])
|
||||
else:
|
||||
# multiple tdata signals
|
||||
data = 0
|
||||
tdata.append(f.pop(0))
|
||||
tkeep.append(0)
|
||||
|
||||
if self.id is None:
|
||||
tid.append(0)
|
||||
elif type(self.id) is int:
|
||||
tid.append(self.id)
|
||||
else:
|
||||
tid.append(self.id[i])
|
||||
|
||||
if self.dest is None:
|
||||
tdest.append(0)
|
||||
elif type(self.dest) is int:
|
||||
tdest.append(self.dest)
|
||||
else:
|
||||
tdest.append(self.dest[i])
|
||||
|
||||
if self.user is None:
|
||||
tuser.append(0)
|
||||
elif type(self.user) is int:
|
||||
tuser.append(self.user)
|
||||
else:
|
||||
tuser.append(self.user[i])
|
||||
i += 1
|
||||
|
||||
if self.last_cycle_user:
|
||||
tuser[-1] = self.last_cycle_user
|
||||
|
||||
return tdata, tkeep, tid, tdest, tuser
|
||||
|
||||
def parse(self, tdata, tkeep, tid, tdest, tuser):
|
||||
if tdata is None or tkeep is None or tuser is None:
|
||||
return
|
||||
if len(tdata) != len(tkeep) or len(tdata) != len(tid) or len(tdata) != len(tdest) or len(tdata) != len(tuser):
|
||||
raise Exception("Invalid data")
|
||||
|
||||
self.data = []
|
||||
self.keep = []
|
||||
self.id = []
|
||||
self.dest = []
|
||||
self.user = []
|
||||
|
||||
if self.B == 0:
|
||||
mask = 2**self.WL-1
|
||||
|
||||
for i in range(len(tdata)):
|
||||
for j in range(self.M):
|
||||
if tkeep[i] & (1 << j):
|
||||
self.data.append((tdata[i] >> (j*self.WL)) & mask)
|
||||
self.keep.append(tkeep[i])
|
||||
self.id.append(tid[i])
|
||||
self.dest.append(tdest[i])
|
||||
self.user.append(tuser[i])
|
||||
else:
|
||||
for i in range(len(tdata)):
|
||||
self.data.append(tdata[i])
|
||||
self.keep.append(tkeep[i])
|
||||
self.id.append(tid[i])
|
||||
self.dest.append(tdest[i])
|
||||
self.user.append(tuser[i])
|
||||
|
||||
if self.WL == 8:
|
||||
self.data = bytearray(self.data)
|
||||
|
||||
self.last_cycle_user = self.user[-1]
|
||||
|
||||
def __eq__(self, other):
|
||||
if not isinstance(other, AXIStreamFrame):
|
||||
return False
|
||||
if self.data != other.data:
|
||||
return False
|
||||
if self.keep is not None and other.keep is not None:
|
||||
if self.keep != other.keep:
|
||||
return False
|
||||
if self.id is not None and other.id is not None:
|
||||
if type(self.id) in (int, bool) and type(other.id) is list:
|
||||
for k in other.id:
|
||||
if self.id != k:
|
||||
return False
|
||||
elif type(other.id) in (int, bool) and type(self.id) is list:
|
||||
for k in self.id:
|
||||
if other.id != k:
|
||||
return False
|
||||
elif self.id != other.id:
|
||||
return False
|
||||
if self.dest is not None and other.dest is not None:
|
||||
if type(self.dest) in (int, bool) and type(other.dest) is list:
|
||||
for k in other.dest:
|
||||
if self.dest != k:
|
||||
return False
|
||||
elif type(other.dest) in (int, bool) and type(self.dest) is list:
|
||||
for k in self.dest:
|
||||
if other.dest != k:
|
||||
return False
|
||||
elif self.dest != other.dest:
|
||||
return False
|
||||
if self.last_cycle_user is not None and other.last_cycle_user is not None:
|
||||
if self.last_cycle_user != other.last_cycle_user:
|
||||
return False
|
||||
if self.user is not None and other.user is not None:
|
||||
if type(self.user) in (int, bool) and type(other.user) is list:
|
||||
for k in other.user[:-1]:
|
||||
if self.user != k:
|
||||
return False
|
||||
elif type(other.user) in (int, bool) and type(self.user) is list:
|
||||
for k in self.user[:-1]:
|
||||
if other.user != k:
|
||||
return False
|
||||
elif self.user != other.user:
|
||||
return False
|
||||
else:
|
||||
if self.user is not None and other.user is not None:
|
||||
if type(self.user) in (int, bool) and type(other.user) is list:
|
||||
for k in other.user:
|
||||
if self.user != k:
|
||||
return False
|
||||
elif type(other.user) in (int, bool) and type(self.user) is list:
|
||||
for k in self.user:
|
||||
if other.user != k:
|
||||
return False
|
||||
elif self.user != other.user:
|
||||
return False
|
||||
return True
|
||||
|
||||
def __repr__(self):
|
||||
return (
|
||||
('AXIStreamFrame(data=%s, ' % repr(self.data)) +
|
||||
('keep=%s, ' % repr(self.keep)) +
|
||||
('id=%s, ' % repr(self.id)) +
|
||||
('dest=%s, ' % repr(self.dest)) +
|
||||
('user=%s, ' % repr(self.user)) +
|
||||
('last_cycle_user=%s)' % repr(self.last_cycle_user))
|
||||
)
|
||||
|
||||
def __iter__(self):
|
||||
return self.data.__iter__()
|
||||
|
||||
|
||||
class AXIStreamSource(object):
|
||||
def __init__(self):
|
||||
self.has_logic = False
|
||||
self.queue = []
|
||||
|
||||
def send(self, frame):
|
||||
self.queue.append(AXIStreamFrame(frame))
|
||||
|
||||
def write(self, data):
|
||||
self.send(data)
|
||||
|
||||
def count(self):
|
||||
return len(self.queue)
|
||||
|
||||
def empty(self):
|
||||
return not self.queue
|
||||
|
||||
def create_logic(self,
|
||||
clk,
|
||||
rst,
|
||||
tdata=None,
|
||||
tkeep=Signal(bool(True)),
|
||||
tvalid=Signal(bool(False)),
|
||||
tready=Signal(bool(True)),
|
||||
tlast=Signal(bool(False)),
|
||||
tid=Signal(intbv(0)),
|
||||
tdest=Signal(intbv(0)),
|
||||
tuser=Signal(intbv(0)),
|
||||
pause=0,
|
||||
name=None
|
||||
):
|
||||
|
||||
assert not self.has_logic
|
||||
|
||||
self.has_logic = True
|
||||
|
||||
tready_int = Signal(bool(False))
|
||||
tvalid_int = Signal(bool(False))
|
||||
|
||||
@always_comb
|
||||
def pause_logic():
|
||||
tready_int.next = tready and not pause
|
||||
tvalid.next = tvalid_int and not pause
|
||||
|
||||
@instance
|
||||
def logic():
|
||||
frame = AXIStreamFrame()
|
||||
data = []
|
||||
keep = []
|
||||
id = []
|
||||
dest = []
|
||||
user = []
|
||||
B = 0
|
||||
N = len(tdata)
|
||||
M = len(tkeep)
|
||||
WL = int((len(tdata)+M-1)/M)
|
||||
|
||||
if type(tdata) is list or type(tdata) is tuple:
|
||||
# multiple tdata signals
|
||||
B = len(tdata)
|
||||
N = [len(b) for b in tdata]
|
||||
M = 1
|
||||
WL = [1]*B
|
||||
|
||||
while True:
|
||||
yield clk.posedge, rst.posedge
|
||||
|
||||
if rst:
|
||||
if B > 0:
|
||||
for s in tdata:
|
||||
s.next = 0
|
||||
else:
|
||||
tdata.next = 0
|
||||
tkeep.next = 0
|
||||
tid.next = 0
|
||||
tdest.next = 0
|
||||
tuser.next = False
|
||||
tvalid_int.next = False
|
||||
tlast.next = False
|
||||
else:
|
||||
if tready_int and tvalid:
|
||||
if len(data) > 0:
|
||||
if B > 0:
|
||||
l = data.pop(0)
|
||||
for i in range(B):
|
||||
tdata[i].next = l[i]
|
||||
else:
|
||||
tdata.next = data.pop(0)
|
||||
tkeep.next = keep.pop(0)
|
||||
tid.next = id.pop(0)
|
||||
tdest.next = dest.pop(0)
|
||||
tuser.next = user.pop(0)
|
||||
tvalid_int.next = True
|
||||
tlast.next = len(data) == 0
|
||||
else:
|
||||
tvalid_int.next = False
|
||||
tlast.next = False
|
||||
if (tlast and tready_int and tvalid) or not tvalid_int:
|
||||
if self.queue:
|
||||
frame = self.queue.pop(0)
|
||||
frame.B = B
|
||||
frame.N = N
|
||||
frame.M = M
|
||||
frame.WL = WL
|
||||
data, keep, id, dest, user = frame.build()
|
||||
if name is not None:
|
||||
print("[%s] Sending frame %s" % (name, repr(frame)))
|
||||
if B > 0:
|
||||
l = data.pop(0)
|
||||
for i in range(B):
|
||||
tdata[i].next = l[i]
|
||||
else:
|
||||
tdata.next = data.pop(0)
|
||||
tkeep.next = keep.pop(0)
|
||||
tid.next = id.pop(0)
|
||||
tdest.next = dest.pop(0)
|
||||
tuser.next = user.pop(0)
|
||||
tvalid_int.next = True
|
||||
tlast.next = len(data) == 0
|
||||
|
||||
return instances()
|
||||
|
||||
|
||||
class AXIStreamSink(object):
|
||||
def __init__(self):
|
||||
self.has_logic = False
|
||||
self.queue = []
|
||||
self.read_queue = []
|
||||
self.sync = Signal(intbv(0))
|
||||
|
||||
def recv(self):
|
||||
if self.queue:
|
||||
return self.queue.pop(0)
|
||||
return None
|
||||
|
||||
def read(self, count=-1):
|
||||
while self.queue:
|
||||
self.read_queue.extend(self.queue.pop(0).data)
|
||||
if count < 0:
|
||||
count = len(self.read_queue)
|
||||
data = self.read_queue[:count]
|
||||
del self.read_queue[:count]
|
||||
return data
|
||||
|
||||
def count(self):
|
||||
return len(self.queue)
|
||||
|
||||
def empty(self):
|
||||
return not self.queue
|
||||
|
||||
def wait(self, timeout=0):
|
||||
if self.queue:
|
||||
return
|
||||
if timeout:
|
||||
yield self.sync, delay(timeout)
|
||||
else:
|
||||
yield self.sync
|
||||
|
||||
def create_logic(self,
|
||||
clk,
|
||||
rst,
|
||||
tdata=None,
|
||||
tkeep=Signal(bool(True)),
|
||||
tvalid=Signal(bool(False)),
|
||||
tready=Signal(bool(True)),
|
||||
tlast=Signal(bool(True)),
|
||||
tid=Signal(intbv(0)),
|
||||
tdest=Signal(intbv(0)),
|
||||
tuser=Signal(intbv(0)),
|
||||
pause=0,
|
||||
name=None
|
||||
):
|
||||
|
||||
assert not self.has_logic
|
||||
|
||||
self.has_logic = True
|
||||
|
||||
tready_int = Signal(bool(False))
|
||||
tvalid_int = Signal(bool(False))
|
||||
|
||||
@always_comb
|
||||
def pause_logic():
|
||||
tready.next = tready_int and not pause
|
||||
tvalid_int.next = tvalid and not pause
|
||||
|
||||
@instance
|
||||
def logic():
|
||||
frame = AXIStreamFrame()
|
||||
data = []
|
||||
keep = []
|
||||
id = []
|
||||
dest = []
|
||||
user = []
|
||||
B = 0
|
||||
N = len(tdata)
|
||||
M = len(tkeep)
|
||||
WL = int((len(tdata)+M-1)/M)
|
||||
first = True
|
||||
|
||||
if type(tdata) is list or type(tdata) is tuple:
|
||||
# multiple tdata signals
|
||||
B = len(tdata)
|
||||
N = [len(b) for b in tdata]
|
||||
M = 1
|
||||
WL = [1]*B
|
||||
|
||||
while True:
|
||||
yield clk.posedge, rst.posedge
|
||||
|
||||
if rst:
|
||||
tready_int.next = False
|
||||
frame = AXIStreamFrame()
|
||||
data = []
|
||||
keep = []
|
||||
id = []
|
||||
dest = []
|
||||
user = []
|
||||
first = True
|
||||
else:
|
||||
tready_int.next = True
|
||||
|
||||
if tvalid_int:
|
||||
|
||||
if not skip_asserts:
|
||||
# zero tkeep not allowed
|
||||
assert int(tkeep) != 0
|
||||
# tkeep must be contiguous
|
||||
# i.e. 0b00011110 allowed, but 0b00011010 not allowed
|
||||
b = int(tkeep)
|
||||
while b & 1 == 0:
|
||||
b = b >> 1
|
||||
while b & 1 == 1:
|
||||
b = b >> 1
|
||||
assert b == 0
|
||||
# tkeep must not have gaps across cycles
|
||||
if not first:
|
||||
# not first cycle; lowest bit must be set
|
||||
assert int(tkeep) & 1
|
||||
if not tlast:
|
||||
# not last cycle; highest bit must be set
|
||||
assert int(tkeep) & (1 << len(tkeep)-1)
|
||||
|
||||
if B > 0:
|
||||
l = []
|
||||
for i in range(B):
|
||||
l.append(int(tdata[i]))
|
||||
data.append(l)
|
||||
else:
|
||||
data.append(int(tdata))
|
||||
keep.append(int(tkeep))
|
||||
id.append(int(tid))
|
||||
dest.append(int(tdest))
|
||||
user.append(int(tuser))
|
||||
first = False
|
||||
if tlast:
|
||||
frame.B = B
|
||||
frame.N = N
|
||||
frame.M = M
|
||||
frame.WL = WL
|
||||
frame.parse(data, keep, id, dest, user)
|
||||
self.queue.append(frame)
|
||||
self.sync.next = not self.sync
|
||||
if name is not None:
|
||||
print("[%s] Got frame %s" % (name, repr(frame)))
|
||||
frame = AXIStreamFrame()
|
||||
data = []
|
||||
keep = []
|
||||
id = []
|
||||
dest = []
|
||||
user = []
|
||||
first = True
|
||||
|
||||
return instances()
|
||||
|
4489
fpga/lib/pcie/tb/pcie.py
Normal file
4489
fpga/lib/pcie/tb/pcie.py
Normal file
File diff suppressed because it is too large
Load Diff
1629
fpga/lib/pcie/tb/pcie_us.py
Normal file
1629
fpga/lib/pcie/tb/pcie_us.py
Normal file
File diff suppressed because it is too large
Load Diff
260
fpga/lib/pcie/tb/test_pcie.py
Executable file
260
fpga/lib/pcie/tb/test_pcie.py
Executable file
@ -0,0 +1,260 @@
|
||||
#!/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 struct
|
||||
import os
|
||||
|
||||
import pcie
|
||||
|
||||
class TestEP(pcie.MemoryEndpoint, pcie.MSICapability):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(TestEP, self).__init__(*args, **kwargs)
|
||||
|
||||
self.vendor_id = 0x1234
|
||||
self.device_id = 0x5678
|
||||
|
||||
self.msi_multiple_message_capable = 5
|
||||
self.msi_64bit_address_capable = 1
|
||||
self.msi_per_vector_mask_capable = 1
|
||||
|
||||
self.add_mem_region(1024)
|
||||
self.add_prefetchable_mem_region(1024*1024)
|
||||
self.add_io_region(32)
|
||||
|
||||
def bench():
|
||||
|
||||
# Inputs
|
||||
clk = Signal(bool(0))
|
||||
rst = Signal(bool(0))
|
||||
current_test = Signal(intbv(0)[8:])
|
||||
|
||||
# Outputs
|
||||
|
||||
# PCIe devices
|
||||
rc = pcie.RootComplex()
|
||||
|
||||
ep = TestEP()
|
||||
dev = pcie.Device(ep)
|
||||
|
||||
rc.make_port().connect(dev)
|
||||
|
||||
sw = pcie.Switch()
|
||||
|
||||
rc.make_port().connect(sw)
|
||||
|
||||
ep2 = TestEP()
|
||||
dev2 = pcie.Device(ep2)
|
||||
|
||||
sw.make_port().connect(dev2)
|
||||
|
||||
ep3 = TestEP()
|
||||
dev3 = pcie.Device(ep3)
|
||||
|
||||
sw.make_port().connect(dev3)
|
||||
|
||||
ep4 = TestEP()
|
||||
dev4 = pcie.Device(ep4)
|
||||
|
||||
rc.make_port().connect(dev4)
|
||||
|
||||
@always(delay(2))
|
||||
def clkgen():
|
||||
clk.next = not clk
|
||||
|
||||
@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
|
||||
|
||||
yield clk.posedge
|
||||
print("test 1: enumeration")
|
||||
current_test.next = 1
|
||||
|
||||
yield from rc.enumerate(enable_bus_mastering=True, configure_msi=True)
|
||||
|
||||
# val = yield from rc.config_read((0, 1, 0), 0x000, 4)
|
||||
|
||||
# print(val)
|
||||
|
||||
# val = yield from rc.config_read((1, 0, 0), 0x000, 4)
|
||||
|
||||
# print(val)
|
||||
|
||||
# yield from rc.config_write((1, 0, 0), 0x010, b'\xff'*4*6)
|
||||
|
||||
# val = yield from rc.config_read((1, 0, 0), 0x010, 4*6)
|
||||
|
||||
# print(val)
|
||||
|
||||
for k in range(6):
|
||||
print("0x%08x / 0x%08x" %(ep.bar[k], ep.bar_mask[k]))
|
||||
|
||||
print(sw.upstream_bridge.pri_bus_num)
|
||||
print(sw.upstream_bridge.sec_bus_num)
|
||||
print(sw.upstream_bridge.sub_bus_num)
|
||||
print("0x%08x" % sw.upstream_bridge.io_base)
|
||||
print("0x%08x" % sw.upstream_bridge.io_limit)
|
||||
print("0x%08x" % sw.upstream_bridge.mem_base)
|
||||
print("0x%08x" % sw.upstream_bridge.mem_limit)
|
||||
print("0x%016x" % sw.upstream_bridge.prefetchable_mem_base)
|
||||
print("0x%016x" % sw.upstream_bridge.prefetchable_mem_limit)
|
||||
|
||||
yield delay(100)
|
||||
|
||||
yield clk.posedge
|
||||
print("test 2: IO and memory read/write")
|
||||
current_test.next = 2
|
||||
|
||||
yield from rc.io_write(0x80000000, bytearray(range(16)), 1000)
|
||||
assert ep.read_region(3, 0, 16) == bytearray(range(16))
|
||||
|
||||
val = yield from rc.io_read(0x80000000, 16, 1000)
|
||||
assert val == bytearray(range(16))
|
||||
|
||||
yield from rc.mem_write(0x80000000, bytearray(range(16)), 1000)
|
||||
yield delay(1000)
|
||||
assert ep.read_region(0, 0, 16) == bytearray(range(16))
|
||||
|
||||
val = yield from rc.mem_read(0x80000000, 16, 1000)
|
||||
assert val == bytearray(range(16))
|
||||
|
||||
yield from rc.mem_write(0x8000000000000000, bytearray(range(16)), 1000)
|
||||
yield delay(1000)
|
||||
assert ep.read_region(1, 0, 16) == bytearray(range(16))
|
||||
|
||||
val = yield from rc.mem_read(0x8000000000000000, 16, 1000)
|
||||
assert val == bytearray(range(16))
|
||||
|
||||
yield delay(100)
|
||||
|
||||
# yield clk.posedge
|
||||
# print("test 3: Large read/write")
|
||||
# current_test.next = 3
|
||||
|
||||
# yield from rc.mem_write(0x8000000000000000, bytearray(range(256))*32, 100)
|
||||
# yield delay(1000)
|
||||
# assert ep.read_region(1, 0, 256*32) == bytearray(range(256))*32
|
||||
|
||||
# val = yield from rc.mem_read(0x8000000000000000, 256*32, 100)
|
||||
# assert val == bytearray(range(256))*32
|
||||
|
||||
# yield delay(100)
|
||||
|
||||
yield clk.posedge
|
||||
print("test 4: Root complex memory")
|
||||
current_test.next = 4
|
||||
|
||||
mem_base, mem_data = rc.alloc_region(1024*1024)
|
||||
io_base, io_data = rc.alloc_io_region(1024)
|
||||
|
||||
yield from rc.io_write(io_base, bytearray(range(16)))
|
||||
assert io_data[0:16] == bytearray(range(16))
|
||||
|
||||
val = yield from rc.io_read(io_base, 16)
|
||||
assert val == bytearray(range(16))
|
||||
|
||||
yield from rc.mem_write(mem_base, bytearray(range(16)))
|
||||
assert mem_data[0:16] == bytearray(range(16))
|
||||
|
||||
val = yield from rc.mem_read(mem_base, 16)
|
||||
assert val == bytearray(range(16))
|
||||
|
||||
yield delay(100)
|
||||
|
||||
yield clk.posedge
|
||||
print("test 5: device-to-device DMA")
|
||||
current_test.next = 5
|
||||
|
||||
yield from ep.io_write(0x80001000, bytearray(range(16)), 10000)
|
||||
assert ep2.read_region(3, 0, 16) == bytearray(range(16))
|
||||
|
||||
val = yield from ep.io_read(0x80001000, 16, 10000)
|
||||
assert val == bytearray(range(16))
|
||||
|
||||
yield from ep.mem_write(0x80100000, bytearray(range(16)), 10000)
|
||||
yield delay(1000)
|
||||
assert ep2.read_region(0, 0, 16) == bytearray(range(16))
|
||||
|
||||
val = yield from ep.mem_read(0x80100000, 16, 10000)
|
||||
assert val == bytearray(range(16))
|
||||
|
||||
yield from ep.mem_write(0x8000000000100000, bytearray(range(16)), 10000)
|
||||
yield delay(1000)
|
||||
assert ep2.read_region(1, 0, 16) == bytearray(range(16))
|
||||
|
||||
val = yield from ep.mem_read(0x8000000000100000, 16, 10000)
|
||||
assert val == bytearray(range(16))
|
||||
|
||||
yield delay(100)
|
||||
|
||||
yield clk.posedge
|
||||
print("test 6: device-to-root DMA")
|
||||
current_test.next = 6
|
||||
|
||||
yield from ep.io_write(io_base, bytearray(range(16)), 1000)
|
||||
assert io_data[0:16] == bytearray(range(16))
|
||||
|
||||
val = yield from ep.io_read(io_base, 16, 1000)
|
||||
assert val == bytearray(range(16))
|
||||
|
||||
yield from ep.mem_write(mem_base, bytearray(range(16)), 1000)
|
||||
yield delay(1000)
|
||||
assert mem_data[0:16] == bytearray(range(16))
|
||||
|
||||
val = yield from ep.mem_read(mem_base, 16, 1000)
|
||||
assert val == bytearray(range(16))
|
||||
|
||||
yield delay(100)
|
||||
|
||||
yield clk.posedge
|
||||
print("test 7: MSI")
|
||||
current_test.next = 7
|
||||
|
||||
yield from ep.issue_msi_interrupt(4)
|
||||
|
||||
yield rc.msi_get_signal(ep.get_id(), 4)
|
||||
|
||||
yield delay(100)
|
||||
|
||||
raise StopSimulation
|
||||
|
||||
return instances()
|
||||
|
||||
def test_bench():
|
||||
os.chdir(os.path.dirname(os.path.abspath(__file__)))
|
||||
sim = Simulation(bench())
|
||||
sim.run()
|
||||
|
||||
if __name__ == '__main__':
|
||||
print("Running test...")
|
||||
test_bench()
|
||||
|
209
fpga/lib/pcie/tb/test_pcie_tag_manager.py
Executable file
209
fpga/lib/pcie/tb/test_pcie_tag_manager.py
Executable file
@ -0,0 +1,209 @@
|
||||
#!/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 axis_ep
|
||||
|
||||
module = 'pcie_tag_manager'
|
||||
testbench = 'test_%s' % module
|
||||
|
||||
srcs = []
|
||||
|
||||
srcs.append("../rtl/%s.v" % module)
|
||||
srcs.append("../rtl/priority_encoder.v")
|
||||
srcs.append("%s.v" % testbench)
|
||||
|
||||
src = ' '.join(srcs)
|
||||
|
||||
build_cmd = "iverilog -o %s.vvp %s" % (testbench, src)
|
||||
|
||||
def bench():
|
||||
|
||||
# Parameters
|
||||
PCIE_TAG_COUNT = 256
|
||||
PCIE_TAG_WIDTH = (PCIE_TAG_COUNT-1).bit_length()
|
||||
PCIE_EXT_TAG_ENABLE = 1
|
||||
|
||||
# Inputs
|
||||
clk = Signal(bool(0))
|
||||
rst = Signal(bool(0))
|
||||
current_test = Signal(intbv(0)[8:])
|
||||
|
||||
m_axis_tag_ready = Signal(bool(0))
|
||||
s_axis_tag = Signal(intbv(0)[PCIE_TAG_WIDTH:])
|
||||
s_axis_tag_valid = Signal(bool(0))
|
||||
ext_tag_enable = Signal(bool(0))
|
||||
|
||||
# Outputs
|
||||
m_axis_tag = Signal(intbv(0)[PCIE_TAG_WIDTH:])
|
||||
m_axis_tag_valid = Signal(bool(0))
|
||||
active_tags = Signal(intbv(0)[PCIE_TAG_COUNT:])
|
||||
|
||||
# sources and sinks
|
||||
tag_sink_pause = Signal(bool(1))
|
||||
|
||||
tag_source = axis_ep.AXIStreamSource()
|
||||
|
||||
tag_source_logic = tag_source.create_logic(
|
||||
clk,
|
||||
rst,
|
||||
tdata=s_axis_tag,
|
||||
tvalid=s_axis_tag_valid,
|
||||
name='tag_source'
|
||||
)
|
||||
|
||||
tag_sink = axis_ep.AXIStreamSink()
|
||||
|
||||
tag_sink_logic = tag_sink.create_logic(
|
||||
clk,
|
||||
rst,
|
||||
tdata=m_axis_tag,
|
||||
tvalid=m_axis_tag_valid,
|
||||
tready=m_axis_tag_ready,
|
||||
pause=tag_sink_pause,
|
||||
name='tag_sink'
|
||||
)
|
||||
|
||||
# DUT
|
||||
if os.system(build_cmd):
|
||||
raise Exception("Error running build command")
|
||||
|
||||
dut = Cosimulation(
|
||||
"vvp -m myhdl %s.vvp -lxt2" % testbench,
|
||||
clk=clk,
|
||||
rst=rst,
|
||||
current_test=current_test,
|
||||
m_axis_tag=m_axis_tag,
|
||||
m_axis_tag_valid=m_axis_tag_valid,
|
||||
m_axis_tag_ready=m_axis_tag_ready,
|
||||
s_axis_tag=s_axis_tag,
|
||||
s_axis_tag_valid=s_axis_tag_valid,
|
||||
ext_tag_enable=ext_tag_enable,
|
||||
active_tags=active_tags
|
||||
)
|
||||
|
||||
@always(delay(4))
|
||||
def clkgen():
|
||||
clk.next = not clk
|
||||
|
||||
@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
|
||||
|
||||
ext_tag_enable.next = 0
|
||||
|
||||
yield clk.posedge
|
||||
print("test 1: activate all tags")
|
||||
current_test.next = 1
|
||||
|
||||
tag_sink_pause.next = 0
|
||||
|
||||
yield delay(300)
|
||||
|
||||
tag_sink_pause.next = 1
|
||||
|
||||
for k in range(32):
|
||||
assert tag_sink.recv().data[0] == k
|
||||
|
||||
yield delay(100)
|
||||
|
||||
yield clk.posedge
|
||||
print("test 2: return and reissue some tags")
|
||||
current_test.next = 2
|
||||
|
||||
for k in [2, 4, 6, 8]:
|
||||
tag_source.send([k])
|
||||
|
||||
tag_sink_pause.next = 0
|
||||
|
||||
yield delay(100)
|
||||
|
||||
tag_sink_pause.next = 1
|
||||
|
||||
for k in [2, 4, 6, 8]:
|
||||
assert tag_sink.recv().data[0] == k
|
||||
|
||||
yield delay(100)
|
||||
|
||||
yield clk.posedge
|
||||
print("test 3: activate all extended tags")
|
||||
current_test.next = 3
|
||||
|
||||
rst.next = 1
|
||||
ext_tag_enable.next = 1
|
||||
yield clk.posedge
|
||||
rst.next = 0
|
||||
|
||||
tag_sink_pause.next = 0
|
||||
|
||||
yield delay(2100)
|
||||
|
||||
tag_sink_pause.next = 1
|
||||
|
||||
for k in range(256):
|
||||
assert tag_sink.recv().data[0] == k
|
||||
|
||||
yield delay(100)
|
||||
|
||||
yield clk.posedge
|
||||
print("test 4: return and reissue some tags")
|
||||
current_test.next = 4
|
||||
|
||||
for k in [10, 20, 30, 40, 50, 60]:
|
||||
tag_source.send([k])
|
||||
|
||||
tag_sink_pause.next = 0
|
||||
|
||||
yield delay(100)
|
||||
|
||||
tag_sink_pause.next = 1
|
||||
|
||||
for k in [10, 20, 30, 40, 50, 60]:
|
||||
assert tag_sink.recv().data[0] == k
|
||||
|
||||
yield delay(100)
|
||||
|
||||
raise StopSimulation
|
||||
|
||||
return instances()
|
||||
|
||||
def test_bench():
|
||||
sim = Simulation(bench())
|
||||
sim.run()
|
||||
|
||||
if __name__ == '__main__':
|
||||
print("Running test...")
|
||||
test_bench()
|
93
fpga/lib/pcie/tb/test_pcie_tag_manager.v
Normal file
93
fpga/lib/pcie/tb/test_pcie_tag_manager.v
Normal file
@ -0,0 +1,93 @@
|
||||
/*
|
||||
|
||||
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 pcie_tag_manager
|
||||
*/
|
||||
module test_pcie_tag_manager;
|
||||
|
||||
// Parameters
|
||||
parameter PCIE_TAG_COUNT = 256;
|
||||
parameter PCIE_TAG_WIDTH = $clog2(PCIE_TAG_COUNT);
|
||||
parameter PCIE_EXT_TAG_ENABLE = 1;
|
||||
|
||||
// Inputs
|
||||
reg clk = 0;
|
||||
reg rst = 0;
|
||||
reg [7:0] current_test = 0;
|
||||
|
||||
reg m_axis_tag_ready = 0;
|
||||
reg [PCIE_TAG_WIDTH-1:0] s_axis_tag = 0;
|
||||
reg s_axis_tag_valid = 0;
|
||||
reg ext_tag_enable = 0;
|
||||
|
||||
// Outputs
|
||||
wire [PCIE_TAG_WIDTH-1:0] m_axis_tag;
|
||||
wire m_axis_tag_valid;
|
||||
wire [PCIE_TAG_COUNT-1:0] active_tags;
|
||||
|
||||
initial begin
|
||||
// myhdl integration
|
||||
$from_myhdl(
|
||||
clk,
|
||||
rst,
|
||||
current_test,
|
||||
m_axis_tag_ready,
|
||||
s_axis_tag,
|
||||
s_axis_tag_valid,
|
||||
ext_tag_enable
|
||||
);
|
||||
$to_myhdl(
|
||||
m_axis_tag,
|
||||
m_axis_tag_valid,
|
||||
active_tags
|
||||
);
|
||||
|
||||
// dump file
|
||||
$dumpfile("test_pcie_tag_manager.lxt");
|
||||
$dumpvars(0, test_pcie_tag_manager);
|
||||
end
|
||||
|
||||
pcie_tag_manager #(
|
||||
.PCIE_TAG_COUNT(PCIE_TAG_COUNT),
|
||||
.PCIE_TAG_WIDTH(PCIE_TAG_WIDTH),
|
||||
.PCIE_EXT_TAG_ENABLE(PCIE_EXT_TAG_ENABLE)
|
||||
)
|
||||
UUT (
|
||||
.clk(clk),
|
||||
.rst(rst),
|
||||
.m_axis_tag(m_axis_tag),
|
||||
.m_axis_tag_valid(m_axis_tag_valid),
|
||||
.m_axis_tag_ready(m_axis_tag_ready),
|
||||
.s_axis_tag(s_axis_tag),
|
||||
.s_axis_tag_valid(s_axis_tag_valid),
|
||||
.ext_tag_enable(ext_tag_enable),
|
||||
.active_tags(active_tags)
|
||||
);
|
||||
|
||||
endmodule
|
929
fpga/lib/pcie/tb/test_pcie_us.py
Executable file
929
fpga/lib/pcie/tb/test_pcie_us.py
Executable file
@ -0,0 +1,929 @@
|
||||
#!/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 struct
|
||||
import os
|
||||
|
||||
import axis_ep
|
||||
import pcie
|
||||
import pcie_us
|
||||
|
||||
#pcie.trace_routing = True
|
||||
|
||||
def bench():
|
||||
|
||||
# Parameters
|
||||
dw = 128
|
||||
|
||||
# Inputs
|
||||
clk = Signal(bool(0))
|
||||
rst = Signal(bool(0))
|
||||
current_test = Signal(intbv(0)[8:])
|
||||
|
||||
# Outputs
|
||||
|
||||
|
||||
# Completer reQuest Interface
|
||||
m_axis_cq_tdata=Signal(intbv(0)[dw:])
|
||||
m_axis_cq_tuser=Signal(intbv(0)[85:])
|
||||
m_axis_cq_tlast=Signal(bool(0))
|
||||
m_axis_cq_tkeep=Signal(intbv(0)[int(dw/32):])
|
||||
m_axis_cq_tvalid=Signal(bool(0))
|
||||
m_axis_cq_tready=Signal(bool(0))
|
||||
pcie_cq_np_req=Signal(bool(1))
|
||||
pcie_cq_np_req_count=Signal(intbv(0)[6:])
|
||||
|
||||
# Completer Completion Interface
|
||||
s_axis_cc_tdata=Signal(intbv(0)[dw:])
|
||||
s_axis_cc_tuser=Signal(intbv(0)[33:])
|
||||
s_axis_cc_tlast=Signal(bool(0))
|
||||
s_axis_cc_tkeep=Signal(intbv(0)[int(dw/32):])
|
||||
s_axis_cc_tvalid=Signal(bool(0))
|
||||
s_axis_cc_tready=Signal(bool(0))
|
||||
|
||||
# Requester reQuest Interface
|
||||
s_axis_rq_tdata=Signal(intbv(0)[dw:])
|
||||
s_axis_rq_tuser=Signal(intbv(0)[60:])
|
||||
s_axis_rq_tlast=Signal(bool(0))
|
||||
s_axis_rq_tkeep=Signal(intbv(0)[int(dw/32):])
|
||||
s_axis_rq_tvalid=Signal(bool(0))
|
||||
s_axis_rq_tready=Signal(bool(0))
|
||||
pcie_rq_seq_num=Signal(intbv(0)[4:])
|
||||
pcie_rq_seq_num_vld=Signal(bool(0))
|
||||
pcie_rq_tag=Signal(intbv(0)[6:])
|
||||
pcie_rq_tag_av=Signal(intbv(0)[2:])
|
||||
pcie_rq_tag_vld=Signal(bool(0))
|
||||
|
||||
# Requester Completion Interface
|
||||
m_axis_rc_tdata=Signal(intbv(0)[dw:])
|
||||
m_axis_rc_tuser=Signal(intbv(0)[75:])
|
||||
m_axis_rc_tlast=Signal(bool(0))
|
||||
m_axis_rc_tkeep=Signal(intbv(0)[int(dw/32):])
|
||||
m_axis_rc_tvalid=Signal(bool(0))
|
||||
m_axis_rc_tready=Signal(bool(0))
|
||||
|
||||
# Transmit Flow Control Interface
|
||||
pcie_tfc_nph_av=Signal(intbv(0)[2:])
|
||||
pcie_tfc_npd_av=Signal(intbv(0)[2:])
|
||||
|
||||
# Configuration Management Interface
|
||||
cfg_mgmt_addr=Signal(intbv(0)[19:])
|
||||
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_mgmt_read_data=Signal(intbv(0)[32:])
|
||||
cfg_mgmt_read_write_done=Signal(bool(0))
|
||||
cfg_mgmt_type1_cfg_reg_access=Signal(bool(0))
|
||||
|
||||
# Configuration Status Interface
|
||||
cfg_phy_link_down=Signal(bool(0))
|
||||
cfg_phy_link_status=Signal(intbv(0)[2:])
|
||||
cfg_negotiated_width=Signal(intbv(0)[4:])
|
||||
cfg_current_speed=Signal(intbv(0)[3:])
|
||||
cfg_max_payload=Signal(intbv(0)[3:])
|
||||
cfg_max_read_req=Signal(intbv(0)[3:])
|
||||
cfg_function_status=Signal(intbv(0)[8:])
|
||||
cfg_vf_status=Signal(intbv(0)[12:])
|
||||
cfg_function_power_state=Signal(intbv(0)[6:])
|
||||
cfg_vf_power_state=Signal(intbv(0)[18:])
|
||||
cfg_link_power_state=Signal(intbv(0)[2:])
|
||||
cfg_err_cor_out=Signal(bool(0))
|
||||
cfg_err_nonfatal_out=Signal(bool(0))
|
||||
cfg_err_fatal_out=Signal(bool(0))
|
||||
cfg_ltr_enable=Signal(bool(0))
|
||||
cfg_ltssm_state=Signal(intbv(0)[6:])
|
||||
cfg_rcb_status=Signal(intbv(0)[2:])
|
||||
cfg_dpa_substate_change=Signal(intbv(0)[2:])
|
||||
cfg_obff_enable=Signal(intbv(0)[2:])
|
||||
cfg_pl_status_change=Signal(bool(0))
|
||||
cfg_tph_requester_enable=Signal(intbv(0)[2:])
|
||||
cfg_tph_st_mode=Signal(intbv(0)[6:])
|
||||
cfg_vf_tph_requester_enable=Signal(intbv(0)[6:])
|
||||
cfg_vf_tph_st_mode=Signal(intbv(0)[18:])
|
||||
|
||||
# Configuration Received Message Interface
|
||||
cfg_msg_received=Signal(bool(0))
|
||||
cfg_msg_received_data=Signal(intbv(0)[8:])
|
||||
cfg_msg_received_type=Signal(intbv(0)[5:])
|
||||
|
||||
# Configuration Transmit Message Interface
|
||||
cfg_msg_transmit=Signal(bool(0))
|
||||
cfg_msg_transmit_type=Signal(intbv(0)[3:])
|
||||
cfg_msg_transmit_data=Signal(intbv(0)[32:])
|
||||
cfg_msg_transmit_done=Signal(bool(0))
|
||||
|
||||
# Configuration Flow Control Interface
|
||||
cfg_fc_ph=Signal(intbv(0)[8:])
|
||||
cfg_fc_pd=Signal(intbv(0)[12:])
|
||||
cfg_fc_nph=Signal(intbv(0)[8:])
|
||||
cfg_fc_npd=Signal(intbv(0)[12:])
|
||||
cfg_fc_cplh=Signal(intbv(0)[8:])
|
||||
cfg_fc_cpld=Signal(intbv(0)[12:])
|
||||
cfg_fc_sel=Signal(intbv(0)[3:])
|
||||
|
||||
# Per-Function Status Interface
|
||||
cfg_per_func_status_control=Signal(intbv(0)[3:])
|
||||
cfg_per_func_status_data=Signal(intbv(0)[16:])
|
||||
|
||||
# Configuration Control Interface
|
||||
cfg_hot_reset_in=Signal(bool(0))
|
||||
cfg_hot_reset_out=Signal(bool(0))
|
||||
cfg_config_space_enable=Signal(bool(1))
|
||||
cfg_per_function_update_done=Signal(bool(0))
|
||||
cfg_per_function_number=Signal(intbv(0)[3:])
|
||||
cfg_per_function_output_request=Signal(bool(0))
|
||||
cfg_dsn=Signal(intbv(0)[64:])
|
||||
cfg_ds_bus_number=Signal(intbv(0)[8:])
|
||||
cfg_ds_device_number=Signal(intbv(0)[5:])
|
||||
cfg_ds_function_number=Signal(intbv(0)[3:])
|
||||
cfg_power_state_change_ack=Signal(bool(0))
|
||||
cfg_power_state_change_interrupt=Signal(bool(0))
|
||||
cfg_err_cor_in=Signal(bool(0))
|
||||
cfg_err_uncor_in=Signal(bool(0))
|
||||
cfg_flr_done=Signal(intbv(0)[2:])
|
||||
cfg_vf_flr_done=Signal(intbv(0)[6:])
|
||||
cfg_flr_in_process=Signal(intbv(0)[2:])
|
||||
cfg_vf_flr_in_process=Signal(intbv(0)[6:])
|
||||
cfg_req_pm_transition_l23_ready=Signal(bool(0))
|
||||
cfg_link_training_enable=Signal(bool(1))
|
||||
|
||||
# Configuration Interrupt Controller Interface
|
||||
cfg_interrupt_int=Signal(intbv(0)[4:])
|
||||
cfg_interrupt_sent=Signal(bool(0))
|
||||
cfg_interrupt_pending=Signal(intbv(0)[2:])
|
||||
cfg_interrupt_msi_enable=Signal(intbv(0)[4:])
|
||||
cfg_interrupt_msi_vf_enable=Signal(intbv(0)[8:])
|
||||
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_select=Signal(intbv(0)[4:])
|
||||
cfg_interrupt_msi_int=Signal(intbv(0)[32:])
|
||||
cfg_interrupt_msi_pending_status=Signal(intbv(0)[32:])
|
||||
cfg_interrupt_msi_pending_status_data_enable=Signal(bool(0))
|
||||
cfg_interrupt_msi_pending_status_function_num=Signal(intbv(0)[4:])
|
||||
cfg_interrupt_msi_sent=Signal(bool(0))
|
||||
cfg_interrupt_msi_fail=Signal(bool(0))
|
||||
cfg_interrupt_msix_enable=Signal(intbv(0)[4:])
|
||||
cfg_interrupt_msix_mask=Signal(intbv(0)[4:])
|
||||
cfg_interrupt_msix_vf_enable=Signal(intbv(0)[8:])
|
||||
cfg_interrupt_msix_vf_mask=Signal(intbv(0)[8:])
|
||||
cfg_interrupt_msix_address=Signal(intbv(0)[64:])
|
||||
cfg_interrupt_msix_data=Signal(intbv(0)[32:])
|
||||
cfg_interrupt_msix_int=Signal(bool(0))
|
||||
cfg_interrupt_msix_sent=Signal(bool(0))
|
||||
cfg_interrupt_msix_fail=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)[9:])
|
||||
cfg_interrupt_msi_function_number=Signal(intbv(0)[4:])
|
||||
|
||||
# Configuration Extend Interface
|
||||
cfg_ext_read_received=Signal(bool(0))
|
||||
cfg_ext_write_received=Signal(bool(0))
|
||||
cfg_ext_register_number=Signal(intbv(0)[10:])
|
||||
cfg_ext_function_number=Signal(intbv(0)[8:])
|
||||
cfg_ext_write_data=Signal(intbv(0)[32:])
|
||||
cfg_ext_write_byte_enable=Signal(intbv(0)[4:])
|
||||
cfg_ext_read_data=Signal(intbv(0)[32:])
|
||||
cfg_ext_read_data_valid=Signal(bool(0))
|
||||
|
||||
# Clock and Reset Interface
|
||||
user_clk=Signal(bool(0))
|
||||
user_reset=Signal(bool(0))
|
||||
user_lnk_up=Signal(bool(0))
|
||||
sys_clk=Signal(bool(0))
|
||||
sys_reset=Signal(bool(0))
|
||||
pcie_perstn0_out=Signal(bool(0))
|
||||
pcie_perstn1_in=Signal(bool(0))
|
||||
pcie_perstn1_out=Signal(bool(0))
|
||||
|
||||
# sources and sinks
|
||||
cq_sink = axis_ep.AXIStreamSink()
|
||||
|
||||
cq_sink_logic = cq_sink.create_logic(
|
||||
user_clk,
|
||||
user_reset,
|
||||
tdata=m_axis_cq_tdata,
|
||||
tuser=m_axis_cq_tuser,
|
||||
tlast=m_axis_cq_tlast,
|
||||
tkeep=m_axis_cq_tkeep,
|
||||
tvalid=m_axis_cq_tvalid,
|
||||
tready=m_axis_cq_tready,
|
||||
name='cq_sink'
|
||||
)
|
||||
|
||||
cc_source = axis_ep.AXIStreamSource()
|
||||
|
||||
cc_source_logic = cc_source.create_logic(
|
||||
user_clk,
|
||||
user_reset,
|
||||
tdata=s_axis_cc_tdata,
|
||||
tuser=s_axis_cc_tuser,
|
||||
tlast=s_axis_cc_tlast,
|
||||
tkeep=s_axis_cc_tkeep,
|
||||
tvalid=s_axis_cc_tvalid,
|
||||
tready=s_axis_cc_tready,
|
||||
name='cc_source'
|
||||
)
|
||||
|
||||
rq_source = axis_ep.AXIStreamSource()
|
||||
|
||||
rq_source_logic = rq_source.create_logic(
|
||||
user_clk,
|
||||
user_reset,
|
||||
tdata=s_axis_rq_tdata,
|
||||
tuser=s_axis_rq_tuser,
|
||||
tlast=s_axis_rq_tlast,
|
||||
tkeep=s_axis_rq_tkeep,
|
||||
tvalid=s_axis_rq_tvalid,
|
||||
tready=s_axis_rq_tready,
|
||||
name='rq_source'
|
||||
)
|
||||
|
||||
rc_sink = axis_ep.AXIStreamSink()
|
||||
|
||||
rc_sink_logic = rc_sink.create_logic(
|
||||
user_clk,
|
||||
user_reset,
|
||||
tdata=m_axis_rc_tdata,
|
||||
tuser=m_axis_rc_tuser,
|
||||
tlast=m_axis_rc_tlast,
|
||||
tkeep=m_axis_rc_tkeep,
|
||||
tvalid=m_axis_rc_tvalid,
|
||||
tready=m_axis_rc_tready,
|
||||
name='rc_sink'
|
||||
)
|
||||
|
||||
# PCIe devices
|
||||
rc = pcie.RootComplex()
|
||||
|
||||
mem_base, mem_data = rc.alloc_region(1024*1024)
|
||||
io_base, io_data = rc.alloc_io_region(1024)
|
||||
|
||||
dev = pcie_us.UltrascalePCIe()
|
||||
|
||||
dev.pcie_generation = 3
|
||||
dev.pcie_link_width = 4
|
||||
dev.user_clock_frequency = 256e6
|
||||
|
||||
regions = [None]*6
|
||||
regions[0] = bytearray(1024)
|
||||
regions[1] = bytearray(1024*1024)
|
||||
regions[3] = bytearray(1024)
|
||||
|
||||
dev.functions[0].msi_multiple_message_capable = 5
|
||||
|
||||
dev.functions[0].configure_bar(0, len(regions[0]))
|
||||
dev.functions[0].configure_bar(1, len(regions[1]), True, True)
|
||||
dev.functions[0].configure_bar(3, len(regions[3]), False, False, True)
|
||||
|
||||
rc.make_port().connect(dev)
|
||||
|
||||
pcie_logic = dev.create_logic(
|
||||
# Completer reQuest Interface
|
||||
m_axis_cq_tdata=m_axis_cq_tdata,
|
||||
m_axis_cq_tuser=m_axis_cq_tuser,
|
||||
m_axis_cq_tlast=m_axis_cq_tlast,
|
||||
m_axis_cq_tkeep=m_axis_cq_tkeep,
|
||||
m_axis_cq_tvalid=m_axis_cq_tvalid,
|
||||
m_axis_cq_tready=m_axis_cq_tready,
|
||||
pcie_cq_np_req=pcie_cq_np_req,
|
||||
pcie_cq_np_req_count=pcie_cq_np_req_count,
|
||||
|
||||
# Completer Completion Interface
|
||||
s_axis_cc_tdata=s_axis_cc_tdata,
|
||||
s_axis_cc_tuser=s_axis_cc_tuser,
|
||||
s_axis_cc_tlast=s_axis_cc_tlast,
|
||||
s_axis_cc_tkeep=s_axis_cc_tkeep,
|
||||
s_axis_cc_tvalid=s_axis_cc_tvalid,
|
||||
s_axis_cc_tready=s_axis_cc_tready,
|
||||
|
||||
# Requester reQuest Interface
|
||||
s_axis_rq_tdata=s_axis_rq_tdata,
|
||||
s_axis_rq_tuser=s_axis_rq_tuser,
|
||||
s_axis_rq_tlast=s_axis_rq_tlast,
|
||||
s_axis_rq_tkeep=s_axis_rq_tkeep,
|
||||
s_axis_rq_tvalid=s_axis_rq_tvalid,
|
||||
s_axis_rq_tready=s_axis_rq_tready,
|
||||
pcie_rq_seq_num=pcie_rq_seq_num,
|
||||
pcie_rq_seq_num_vld=pcie_rq_seq_num_vld,
|
||||
pcie_rq_tag=pcie_rq_tag,
|
||||
pcie_rq_tag_av=pcie_rq_tag_av,
|
||||
pcie_rq_tag_vld=pcie_rq_tag_vld,
|
||||
|
||||
# Requester Completion Interface
|
||||
m_axis_rc_tdata=m_axis_rc_tdata,
|
||||
m_axis_rc_tuser=m_axis_rc_tuser,
|
||||
m_axis_rc_tlast=m_axis_rc_tlast,
|
||||
m_axis_rc_tkeep=m_axis_rc_tkeep,
|
||||
m_axis_rc_tvalid=m_axis_rc_tvalid,
|
||||
m_axis_rc_tready=m_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_write=cfg_mgmt_write,
|
||||
cfg_mgmt_write_data=cfg_mgmt_write_data,
|
||||
cfg_mgmt_byte_enable=cfg_mgmt_byte_enable,
|
||||
cfg_mgmt_read=cfg_mgmt_read,
|
||||
cfg_mgmt_read_data=cfg_mgmt_read_data,
|
||||
cfg_mgmt_read_write_done=cfg_mgmt_read_write_done,
|
||||
cfg_mgmt_type1_cfg_reg_access=cfg_mgmt_type1_cfg_reg_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_ltr_enable=cfg_ltr_enable,
|
||||
cfg_ltssm_state=cfg_ltssm_state,
|
||||
cfg_rcb_status=cfg_rcb_status,
|
||||
cfg_dpa_substate_change=cfg_dpa_substate_change,
|
||||
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,
|
||||
|
||||
# Per-Function Status Interface
|
||||
cfg_per_func_status_control=cfg_per_func_status_control,
|
||||
cfg_per_func_status_data=cfg_per_func_status_data,
|
||||
|
||||
# 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_per_function_update_done=cfg_per_function_update_done,
|
||||
cfg_per_function_number=cfg_per_function_number,
|
||||
cfg_per_function_output_request=cfg_per_function_output_request,
|
||||
cfg_dsn=cfg_dsn,
|
||||
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=cfg_err_cor_in,
|
||||
cfg_err_uncor_in=cfg_err_uncor_in,
|
||||
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_vf_enable=cfg_interrupt_msi_vf_enable,
|
||||
cfg_interrupt_msi_mmenable=cfg_interrupt_msi_mmenable,
|
||||
cfg_interrupt_msi_mask_update=cfg_interrupt_msi_mask_update,
|
||||
cfg_interrupt_msi_data=cfg_interrupt_msi_data,
|
||||
cfg_interrupt_msi_select=cfg_interrupt_msi_select,
|
||||
cfg_interrupt_msi_int=cfg_interrupt_msi_int,
|
||||
cfg_interrupt_msi_pending_status=cfg_interrupt_msi_pending_status,
|
||||
cfg_interrupt_msi_pending_status_data_enable=cfg_interrupt_msi_pending_status_data_enable,
|
||||
cfg_interrupt_msi_pending_status_function_num=cfg_interrupt_msi_pending_status_function_num,
|
||||
cfg_interrupt_msi_sent=cfg_interrupt_msi_sent,
|
||||
cfg_interrupt_msi_fail=cfg_interrupt_msi_fail,
|
||||
cfg_interrupt_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_sent=cfg_interrupt_msix_sent,
|
||||
cfg_interrupt_msix_fail=cfg_interrupt_msix_fail,
|
||||
cfg_interrupt_msi_attr=cfg_interrupt_msi_attr,
|
||||
cfg_interrupt_msi_tph_present=cfg_interrupt_msi_tph_present,
|
||||
cfg_interrupt_msi_tph_type=cfg_interrupt_msi_tph_type,
|
||||
cfg_interrupt_msi_tph_st_tag=cfg_interrupt_msi_tph_st_tag,
|
||||
cfg_interrupt_msi_function_number=cfg_interrupt_msi_function_number,
|
||||
|
||||
# Configuration 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,
|
||||
pcie_perstn0_out=pcie_perstn0_out,
|
||||
pcie_perstn1_in=pcie_perstn1_in,
|
||||
pcie_perstn1_out=pcie_perstn1_out
|
||||
)
|
||||
|
||||
@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 user_logic():
|
||||
while True:
|
||||
yield clk.posedge
|
||||
|
||||
# handle completer request
|
||||
if not cq_sink.empty():
|
||||
pkt = cq_sink.recv()
|
||||
|
||||
tlp = pcie_us.TLP_us().unpack_us_cq(pkt, dw)
|
||||
|
||||
print(tlp)
|
||||
|
||||
if (tlp.fmt_type == pcie.TLP_IO_READ):
|
||||
print("IO read")
|
||||
|
||||
cpl = pcie_us.TLP_us()
|
||||
cpl.set_completion(tlp, pcie_us.PcieId(0, 0, 0))
|
||||
cpl.fmt_type = pcie.TLP_CPL_DATA
|
||||
|
||||
region = tlp.bar_id
|
||||
addr = tlp.address & 0xffff # TODO
|
||||
offset = 0
|
||||
start_offset = None
|
||||
mask = tlp.first_be
|
||||
|
||||
# perform operation
|
||||
data = bytearray(4)
|
||||
|
||||
for k in range(4):
|
||||
if mask & (1 << k):
|
||||
if start_offset is None:
|
||||
start_offset = offset
|
||||
else:
|
||||
if start_offset is not None and offset != start_offset:
|
||||
data[start_offset:offset] = regions[region][addr+start_offset:addr+offset]
|
||||
start_offset = None
|
||||
|
||||
offset += 1
|
||||
|
||||
if start_offset is not None and offset != start_offset:
|
||||
data[start_offset:offset] = regions[region][addr+start_offset:addr+offset]
|
||||
|
||||
cpl.set_data(data)
|
||||
cpl.byte_count = 4
|
||||
cpl.length = 1
|
||||
|
||||
cc_source.send(cpl.pack_us_cc(dw))
|
||||
elif (tlp.fmt_type == pcie.TLP_IO_WRITE):
|
||||
print("IO write")
|
||||
|
||||
cpl = pcie_us.TLP_us()
|
||||
cpl.set_completion(tlp, pcie_us.PcieId(0, 0, 0))
|
||||
|
||||
region = tlp.bar_id
|
||||
addr = tlp.address & 0xffff # TODO
|
||||
offset = 0
|
||||
start_offset = None
|
||||
mask = tlp.first_be
|
||||
|
||||
# perform operation
|
||||
data = tlp.get_data()
|
||||
|
||||
for k in range(4):
|
||||
if mask & (1 << k):
|
||||
if start_offset is None:
|
||||
start_offset = offset
|
||||
else:
|
||||
if start_offset is not None and offset != start_offset:
|
||||
regions[region][addr+start_offset:addr+offset] = data[start_offset:offset]
|
||||
start_offset = None
|
||||
|
||||
offset += 1
|
||||
|
||||
if start_offset is not None and offset != start_offset:
|
||||
regions[region][addr+start_offset:addr+offset] = data[start_offset:offset]
|
||||
|
||||
cc_source.send(cpl.pack_us_cc(dw))
|
||||
if (tlp.fmt_type == pcie.TLP_MEM_READ or tlp.fmt_type == pcie.TLP_MEM_READ_64):
|
||||
print("Memory read")
|
||||
|
||||
# perform operation
|
||||
region = tlp.bar_id
|
||||
addr = tlp.address & 0xffff # TODO
|
||||
offset = 0
|
||||
length = tlp.length
|
||||
|
||||
# perform read
|
||||
data = regions[region][addr:addr+length*4]
|
||||
|
||||
# prepare completion TLP(s)
|
||||
n = 0
|
||||
offset = 0
|
||||
addr = tlp.address + offset
|
||||
length = tlp.length*4
|
||||
|
||||
while n < length:
|
||||
cpl = pcie_us.TLP_us()
|
||||
cpl.set_completion(tlp, pcie_us.PcieId(0, 0, 0))
|
||||
|
||||
byte_length = length-n
|
||||
cpl.byte_count = byte_length
|
||||
byte_length = min(byte_length, 128 << dev.functions[0].max_payload_size) # max payload size
|
||||
if byte_length > 128:
|
||||
byte_length -= (addr + byte_length) % 128 # RCB align
|
||||
byte_length = min(byte_length, 0x1000 - (addr & 0xfff)) # 4k align
|
||||
|
||||
cpl.lower_address = addr & 0x7f
|
||||
|
||||
cpl.set_data(data[offset+n:offset+n+byte_length])
|
||||
|
||||
print("Completion: %s" % (repr(cpl)))
|
||||
cc_source.send(cpl.pack_us_cc(dw))
|
||||
|
||||
n += byte_length
|
||||
addr += byte_length
|
||||
if (tlp.fmt_type == pcie.TLP_MEM_WRITE or tlp.fmt_type == pcie.TLP_MEM_WRITE_64):
|
||||
print("Memory write")
|
||||
|
||||
# perform operation
|
||||
region = tlp.bar_id
|
||||
addr = tlp.address & 0xffff # TODO
|
||||
offset = 0
|
||||
start_offset = None
|
||||
mask = tlp.first_be
|
||||
length = tlp.length
|
||||
|
||||
# perform write
|
||||
data = tlp.get_data()
|
||||
|
||||
# first dword
|
||||
for k in range(4):
|
||||
if mask & (1 << k):
|
||||
if start_offset is None:
|
||||
start_offset = offset
|
||||
else:
|
||||
if start_offset is not None and offset != start_offset:
|
||||
regions[region][addr+start_offset:addr+offset] = data[start_offset:offset]
|
||||
start_offset = None
|
||||
|
||||
offset += 1
|
||||
|
||||
if length > 1:
|
||||
# middle dwords
|
||||
if start_offset is None:
|
||||
start_offset = offset
|
||||
offset += length*4
|
||||
|
||||
# last dword
|
||||
mask = tlp.last_be
|
||||
|
||||
for k in range(4):
|
||||
if mask & (1 << k):
|
||||
if start_offset is None:
|
||||
start_offset = offset
|
||||
else:
|
||||
if start_offset is not None and offset != start_offset:
|
||||
regions[region][addr+start_offset:addr+offset] = data[start_offset:offset]
|
||||
start_offset = None
|
||||
|
||||
offset += 1
|
||||
|
||||
if start_offset is not None and offset != start_offset:
|
||||
regions[region][addr+start_offset:addr+offset] = data[start_offset:offset]
|
||||
|
||||
# haldle requester completion
|
||||
#if not rc_sink.empty():
|
||||
# pkt = rc_sink.recv()
|
||||
|
||||
@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
|
||||
|
||||
current_tag = 1
|
||||
|
||||
yield clk.posedge
|
||||
print("test 1: enumeration")
|
||||
current_test.next = 1
|
||||
|
||||
yield rc.enumerate(enable_bus_mastering=True, configure_msi=True)
|
||||
|
||||
yield delay(100)
|
||||
|
||||
yield clk.posedge
|
||||
print("test 2: IO and memory read/write")
|
||||
current_test.next = 2
|
||||
|
||||
yield from rc.io_write(0x80000000, bytearray(range(16)), 100)
|
||||
assert regions[3][0:16] == bytearray(range(16))
|
||||
|
||||
val = yield from rc.io_read(0x80000000, 16, 100)
|
||||
assert val == bytearray(range(16))
|
||||
|
||||
yield from rc.mem_write(0x80000000, bytearray(range(16)), 100)
|
||||
yield delay(100)
|
||||
assert regions[0][0:16] == bytearray(range(16))
|
||||
|
||||
val = yield from rc.mem_read(0x80000000, 16, 100)
|
||||
assert val == bytearray(range(16))
|
||||
|
||||
yield from rc.mem_write(0x8000000000000000, bytearray(range(16)), 100)
|
||||
yield delay(100)
|
||||
assert regions[1][0:16] == bytearray(range(16))
|
||||
|
||||
val = yield from rc.mem_read(0x8000000000000000, 16, 100)
|
||||
assert val == bytearray(range(16))
|
||||
|
||||
yield delay(100)
|
||||
|
||||
# yield clk.posedge
|
||||
# print("test 3: Large read/write")
|
||||
# current_test.next = 3
|
||||
|
||||
# yield from rc.mem_write(0x8000000000000000, bytearray(range(256))*32, 100)
|
||||
# yield delay(100)
|
||||
# assert ep.read_region(1, 0, 256*32) == bytearray(range(256))*32
|
||||
|
||||
# val = yield from rc.mem_read(0x8000000000000000, 256*32, 100)
|
||||
# assert val == bytearray(range(256))*32
|
||||
|
||||
# yield delay(100)
|
||||
|
||||
yield clk.posedge
|
||||
print("test 4: DMA")
|
||||
current_test.next = 4
|
||||
|
||||
#yield ep.io_write(io_base, bytearray(range(16)), 100)
|
||||
|
||||
data = bytearray(range(16))
|
||||
addr = io_base
|
||||
n = 0
|
||||
|
||||
while n < len(data):
|
||||
tlp = pcie_us.TLP_us()
|
||||
tlp.fmt_type = pcie.TLP_IO_WRITE
|
||||
tlp.requester_id = pcie_us.PcieId(dev.bus_num, dev.device_num, 0)
|
||||
tlp.tag = current_tag
|
||||
|
||||
first_pad = addr % 4
|
||||
byte_length = min(len(data)-n, 4-first_pad)
|
||||
tlp.set_be_data(addr, data[n:n+byte_length])
|
||||
|
||||
tlp.address = addr & ~3
|
||||
|
||||
current_tag = (current_tag % 31) + 1
|
||||
|
||||
rq_source.send(tlp.pack_us_rq(dw))
|
||||
yield rc_sink.wait(100)
|
||||
pkt = rc_sink.recv()
|
||||
|
||||
if not pkt:
|
||||
raise Exception("Timeout")
|
||||
|
||||
cpl = pcie_us.TLP_us().unpack_us_rc(pkt, dw)
|
||||
|
||||
if cpl.status != pcie.CPL_STATUS_SC:
|
||||
raise Exception("Unsuccessful completion")
|
||||
|
||||
n += byte_length
|
||||
addr += byte_length
|
||||
|
||||
assert io_data[0:16] == bytearray(range(16))
|
||||
|
||||
#val = yield from ep.io_read(io_base, 16, 100)
|
||||
|
||||
length = 16
|
||||
data = b''
|
||||
addr = io_base
|
||||
n = 0
|
||||
|
||||
while n < length:
|
||||
tlp = pcie_us.TLP_us()
|
||||
tlp.fmt_type = pcie.TLP_IO_READ
|
||||
tlp.requester_id = pcie_us.PcieId(dev.bus_num, dev.device_num, 0)
|
||||
tlp.tag = current_tag
|
||||
|
||||
first_pad = addr % 4
|
||||
byte_length = min(length-n, 4-first_pad)
|
||||
tlp.set_be(addr, byte_length)
|
||||
|
||||
tlp.address = addr & ~3
|
||||
|
||||
current_tag = (current_tag % 31) + 1
|
||||
|
||||
rq_source.send(tlp.pack_us_rq(dw))
|
||||
yield rc_sink.wait(100)
|
||||
pkt = rc_sink.recv()
|
||||
|
||||
if not pkt:
|
||||
raise Exception("Timeout")
|
||||
|
||||
cpl = pcie_us.TLP_us().unpack_us_rc(pkt, dw)
|
||||
|
||||
if cpl.status != pcie.CPL_STATUS_SC:
|
||||
raise Exception("Unsuccessful completion")
|
||||
else:
|
||||
d = struct.pack('<L', cpl.data[0])
|
||||
|
||||
data += d[first_pad:]
|
||||
|
||||
n += byte_length
|
||||
addr += byte_length
|
||||
|
||||
data = data[:length]
|
||||
|
||||
assert val == bytearray(range(16))
|
||||
|
||||
#yield ep.mem_write(mem_base, bytearray(range(16)), 100)
|
||||
|
||||
data = bytearray(range(16))
|
||||
addr = io_base
|
||||
n = 0
|
||||
|
||||
while n < len(data):
|
||||
tlp = pcie_us.TLP_us()
|
||||
if addr > 0xffffffff:
|
||||
tlp.fmt_type = pcie.TLP_MEM_WRITE_64
|
||||
else:
|
||||
tlp.fmt_type = pcie.TLP_MEM_WRITE
|
||||
tlp.requester_id = pcie_us.PcieId(dev.bus_num, dev.device_num, 0)
|
||||
tlp.tag = current_tag
|
||||
|
||||
first_pad = addr % 4
|
||||
byte_length = len(data)-n
|
||||
byte_length = min(byte_length, (128 << dev.functions[0].max_payload_size)-first_pad) # max payload size
|
||||
byte_length = min(byte_length, 0x1000 - (addr & 0xfff)) # 4k align
|
||||
tlp.set_be_data(addr, data[n:n+byte_length])
|
||||
|
||||
tlp.address = addr & ~3
|
||||
|
||||
current_tag = (current_tag % 31) + 1
|
||||
|
||||
rq_source.send(tlp.pack_us_rq(dw))
|
||||
|
||||
n += byte_length
|
||||
addr += byte_length
|
||||
|
||||
yield delay(100)
|
||||
assert mem_data[0:16] == bytearray(range(16))
|
||||
|
||||
#val = yield from ep.mem_read(mem_base, 16, 100)
|
||||
|
||||
length = 16
|
||||
data = b''
|
||||
addr = mem_base
|
||||
n = 0
|
||||
|
||||
while n < length:
|
||||
tlp = pcie_us.TLP_us()
|
||||
if addr > 0xffffffff:
|
||||
tlp.fmt_type = pcie.TLP_MEM_READ_64
|
||||
else:
|
||||
tlp.fmt_type = pcie.TLP_MEM_READ
|
||||
tlp.requester_id = pcie_us.PcieId(dev.bus_num, dev.device_num, 0)
|
||||
tlp.tag = current_tag
|
||||
|
||||
first_pad = addr % 4
|
||||
byte_length = length-n
|
||||
byte_length = min(byte_length, (128 << dev.functions[0].max_read_request_size)-first_pad) # max read request size
|
||||
byte_length = min(byte_length, 0x1000 - (addr & 0xfff)) # 4k align
|
||||
tlp.set_be(addr, byte_length)
|
||||
|
||||
tlp.address = addr & ~3
|
||||
|
||||
current_tag = (current_tag % 31) + 1
|
||||
|
||||
rq_source.send(tlp.pack_us_rq(dw))
|
||||
|
||||
m = 0
|
||||
|
||||
while m < byte_length:
|
||||
yield rc_sink.wait(100)
|
||||
pkt = rc_sink.recv()
|
||||
|
||||
if not pkt:
|
||||
raise Exception("Timeout")
|
||||
|
||||
cpl = pcie_us.TLP_us().unpack_us_rc(pkt, dw)
|
||||
|
||||
if cpl.status != pcie.CPL_STATUS_SC:
|
||||
raise Exception("Unsuccessful completion")
|
||||
else:
|
||||
dw_len = cpl.length
|
||||
if dw_len == 0:
|
||||
dw_len = 1024
|
||||
d = bytearray()
|
||||
|
||||
for k in range(dw_len):
|
||||
d.extend(struct.pack('<L', cpl.data[k]))
|
||||
|
||||
offset = cpl.lower_address&3
|
||||
data += d[offset:offset+cpl.byte_count]
|
||||
|
||||
m += len(d)-offset
|
||||
|
||||
n += byte_length
|
||||
addr += byte_length
|
||||
|
||||
assert val == bytearray(range(16))
|
||||
|
||||
yield delay(100)
|
||||
|
||||
yield clk.posedge
|
||||
print("test 5: MSI")
|
||||
current_test.next = 5
|
||||
|
||||
yield user_clk.posedge
|
||||
cfg_interrupt_msi_int.next = 1 << 4
|
||||
yield user_clk.posedge
|
||||
cfg_interrupt_msi_int.next = 0
|
||||
|
||||
yield rc.msi_get_signal(dev.functions[0].get_id(), 4)
|
||||
|
||||
yield delay(100)
|
||||
|
||||
raise StopSimulation
|
||||
|
||||
return instances()
|
||||
|
||||
def test_bench():
|
||||
os.chdir(os.path.dirname(os.path.abspath(__file__)))
|
||||
sim = Simulation(bench())
|
||||
sim.run()
|
||||
|
||||
if __name__ == '__main__':
|
||||
print("Running test...")
|
||||
test_bench()
|
||||
|
532
fpga/lib/pcie/tb/test_pcie_us_axi_dma_256.py
Executable file
532
fpga/lib/pcie/tb/test_pcie_us_axi_dma_256.py
Executable file
@ -0,0 +1,532 @@
|
||||
#!/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 pcie
|
||||
import pcie_us
|
||||
import axi
|
||||
import axis_ep
|
||||
|
||||
module = 'pcie_us_axi_dma'
|
||||
testbench = 'test_%s_256' % module
|
||||
|
||||
srcs = []
|
||||
|
||||
srcs.append("../rtl/%s.v" % module)
|
||||
srcs.append("../rtl/pcie_us_axi_dma_rd.v")
|
||||
srcs.append("../rtl/pcie_us_axi_dma_wr.v")
|
||||
srcs.append("../rtl/pcie_tag_manager.v")
|
||||
srcs.append("../rtl/axis_arb_mux.v")
|
||||
srcs.append("../rtl/arbiter.v")
|
||||
srcs.append("../rtl/priority_encoder.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 = 256
|
||||
AXIS_PCIE_KEEP_WIDTH = (AXIS_PCIE_DATA_WIDTH/32)
|
||||
AXI_DATA_WIDTH = AXIS_PCIE_DATA_WIDTH
|
||||
AXI_ADDR_WIDTH = 64
|
||||
AXI_STRB_WIDTH = (AXI_DATA_WIDTH/8)
|
||||
AXI_ID_WIDTH = 8
|
||||
AXI_MAX_BURST_LEN = 256
|
||||
PCIE_ADDR_WIDTH = 64
|
||||
PCIE_CLIENT_TAG = 1
|
||||
PCIE_TAG_WIDTH = 8
|
||||
PCIE_TAG_COUNT = 256
|
||||
PCIE_EXT_TAG_ENABLE = 1
|
||||
LEN_WIDTH = 20
|
||||
TAG_WIDTH = 8
|
||||
|
||||
# Inputs
|
||||
clk = Signal(bool(0))
|
||||
rst = Signal(bool(0))
|
||||
current_test = Signal(intbv(0)[8:])
|
||||
|
||||
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_tvalid = Signal(bool(0))
|
||||
s_axis_rc_tlast = Signal(bool(0))
|
||||
s_axis_rc_tuser = Signal(intbv(0)[75:])
|
||||
m_axis_rq_tready = Signal(bool(0))
|
||||
s_axis_pcie_rq_tag = Signal(intbv(0)[PCIE_TAG_WIDTH:])
|
||||
s_axis_pcie_rq_tag_valid = Signal(bool(0))
|
||||
s_axis_read_desc_pcie_addr = Signal(intbv(0)[PCIE_ADDR_WIDTH:])
|
||||
s_axis_read_desc_axi_addr = Signal(intbv(0)[AXI_ADDR_WIDTH:])
|
||||
s_axis_read_desc_len = Signal(intbv(0)[LEN_WIDTH:])
|
||||
s_axis_read_desc_tag = Signal(intbv(0)[TAG_WIDTH:])
|
||||
s_axis_read_desc_valid = Signal(bool(0))
|
||||
s_axis_write_desc_pcie_addr = Signal(intbv(0)[PCIE_ADDR_WIDTH:])
|
||||
s_axis_write_desc_axi_addr = Signal(intbv(0)[AXI_ADDR_WIDTH:])
|
||||
s_axis_write_desc_len = Signal(intbv(0)[LEN_WIDTH:])
|
||||
s_axis_write_desc_tag = Signal(intbv(0)[TAG_WIDTH:])
|
||||
s_axis_write_desc_valid = Signal(bool(0))
|
||||
m_axi_awready = Signal(bool(0))
|
||||
m_axi_wready = Signal(bool(0))
|
||||
m_axi_bid = Signal(intbv(0)[AXI_ID_WIDTH:])
|
||||
m_axi_bresp = Signal(intbv(0)[2:])
|
||||
m_axi_bvalid = Signal(bool(0))
|
||||
m_axi_arready = Signal(bool(0))
|
||||
m_axi_rid = Signal(intbv(0)[AXI_ID_WIDTH:])
|
||||
m_axi_rdata = Signal(intbv(0)[AXI_DATA_WIDTH:])
|
||||
m_axi_rresp = Signal(intbv(0)[2:])
|
||||
m_axi_rlast = Signal(bool(0))
|
||||
m_axi_rvalid = Signal(bool(0))
|
||||
read_enable = Signal(bool(0))
|
||||
write_enable = Signal(bool(0))
|
||||
ext_tag_enable = Signal(bool(0))
|
||||
requester_id = Signal(intbv(0)[16:])
|
||||
requester_id_enable = Signal(bool(0))
|
||||
max_read_request_size = Signal(intbv(0)[3:])
|
||||
max_payload_size = Signal(intbv(0)[3:])
|
||||
|
||||
# Outputs
|
||||
s_axis_rc_tready = Signal(bool(0))
|
||||
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_tvalid = Signal(bool(0))
|
||||
m_axis_rq_tlast = Signal(bool(0))
|
||||
m_axis_rq_tuser = Signal(intbv(0)[60:])
|
||||
s_axis_read_desc_ready = Signal(bool(0))
|
||||
m_axis_read_desc_status_tag = Signal(intbv(0)[TAG_WIDTH:])
|
||||
m_axis_read_desc_status_valid = Signal(bool(0))
|
||||
s_axis_write_desc_ready = Signal(bool(0))
|
||||
m_axis_write_desc_status_tag = Signal(intbv(0)[TAG_WIDTH:])
|
||||
m_axis_write_desc_status_valid = Signal(bool(0))
|
||||
m_axi_awid = Signal(intbv(0)[AXI_ID_WIDTH:])
|
||||
m_axi_awaddr = Signal(intbv(0)[AXI_ADDR_WIDTH:])
|
||||
m_axi_awlen = Signal(intbv(0)[8:])
|
||||
m_axi_awsize = Signal(intbv(5)[3:])
|
||||
m_axi_awburst = Signal(intbv(1)[2:])
|
||||
m_axi_awlock = Signal(bool(0))
|
||||
m_axi_awcache = Signal(intbv(3)[4:])
|
||||
m_axi_awprot = Signal(intbv(2)[3:])
|
||||
m_axi_awvalid = Signal(bool(0))
|
||||
m_axi_wdata = Signal(intbv(0)[AXI_DATA_WIDTH:])
|
||||
m_axi_wstrb = Signal(intbv(0)[AXI_STRB_WIDTH:])
|
||||
m_axi_wlast = Signal(bool(0))
|
||||
m_axi_wvalid = Signal(bool(0))
|
||||
m_axi_bready = Signal(bool(0))
|
||||
m_axi_arid = Signal(intbv(0)[AXI_ID_WIDTH:])
|
||||
m_axi_araddr = Signal(intbv(0)[AXI_ADDR_WIDTH:])
|
||||
m_axi_arlen = Signal(intbv(0)[8:])
|
||||
m_axi_arsize = Signal(intbv(5)[3:])
|
||||
m_axi_arburst = Signal(intbv(1)[2:])
|
||||
m_axi_arlock = Signal(bool(0))
|
||||
m_axi_arcache = Signal(intbv(3)[4:])
|
||||
m_axi_arprot = Signal(intbv(2)[3:])
|
||||
m_axi_arvalid = Signal(bool(0))
|
||||
m_axi_rready = Signal(bool(0))
|
||||
status_error_cor = Signal(bool(0))
|
||||
status_error_uncor = Signal(bool(0))
|
||||
|
||||
# Clock and Reset Interface
|
||||
user_clk=Signal(bool(0))
|
||||
user_reset=Signal(bool(0))
|
||||
sys_clk=Signal(bool(0))
|
||||
sys_reset=Signal(bool(0))
|
||||
|
||||
# AXI4 RAM model
|
||||
axi_ram_inst = axi.AXIRam(2**16)
|
||||
|
||||
axi_ram_port0 = axi_ram_inst.create_port(
|
||||
user_clk,
|
||||
s_axi_awid=m_axi_awid,
|
||||
s_axi_awaddr=m_axi_awaddr,
|
||||
s_axi_awlen=m_axi_awlen,
|
||||
s_axi_awsize=m_axi_awsize,
|
||||
s_axi_awburst=m_axi_awburst,
|
||||
s_axi_awlock=m_axi_awlock,
|
||||
s_axi_awcache=m_axi_awcache,
|
||||
s_axi_awprot=m_axi_awprot,
|
||||
s_axi_awvalid=m_axi_awvalid,
|
||||
s_axi_awready=m_axi_awready,
|
||||
s_axi_wdata=m_axi_wdata,
|
||||
s_axi_wstrb=m_axi_wstrb,
|
||||
s_axi_wlast=m_axi_wlast,
|
||||
s_axi_wvalid=m_axi_wvalid,
|
||||
s_axi_wready=m_axi_wready,
|
||||
s_axi_bid=m_axi_bid,
|
||||
s_axi_bresp=m_axi_bresp,
|
||||
s_axi_bvalid=m_axi_bvalid,
|
||||
s_axi_bready=m_axi_bready,
|
||||
s_axi_arid=m_axi_arid,
|
||||
s_axi_araddr=m_axi_araddr,
|
||||
s_axi_arlen=m_axi_arlen,
|
||||
s_axi_arsize=m_axi_arsize,
|
||||
s_axi_arburst=m_axi_arburst,
|
||||
s_axi_arlock=m_axi_arlock,
|
||||
s_axi_arcache=m_axi_arcache,
|
||||
s_axi_arprot=m_axi_arprot,
|
||||
s_axi_arvalid=m_axi_arvalid,
|
||||
s_axi_arready=m_axi_arready,
|
||||
s_axi_rid=m_axi_rid,
|
||||
s_axi_rdata=m_axi_rdata,
|
||||
s_axi_rresp=m_axi_rresp,
|
||||
s_axi_rlast=m_axi_rlast,
|
||||
s_axi_rvalid=m_axi_rvalid,
|
||||
s_axi_rready=m_axi_rready,
|
||||
name='port0'
|
||||
)
|
||||
|
||||
# sources and sinks
|
||||
read_desc_source = axis_ep.AXIStreamSource()
|
||||
|
||||
read_desc_source_logic = read_desc_source.create_logic(
|
||||
user_clk,
|
||||
user_reset,
|
||||
tdata=(s_axis_read_desc_pcie_addr, s_axis_read_desc_axi_addr, s_axis_read_desc_len, s_axis_read_desc_tag),
|
||||
tvalid=s_axis_read_desc_valid,
|
||||
tready=s_axis_read_desc_ready,
|
||||
name='read_desc_source'
|
||||
)
|
||||
|
||||
read_desc_status_sink = axis_ep.AXIStreamSink()
|
||||
|
||||
read_desc_status_sink_logic = read_desc_status_sink.create_logic(
|
||||
user_clk,
|
||||
user_reset,
|
||||
tdata=(m_axis_read_desc_status_tag,),
|
||||
tvalid=m_axis_read_desc_status_valid,
|
||||
name='read_desc_status_sink'
|
||||
)
|
||||
|
||||
write_desc_source = axis_ep.AXIStreamSource()
|
||||
|
||||
write_desc_source_logic = write_desc_source.create_logic(
|
||||
user_clk,
|
||||
user_reset,
|
||||
tdata=(s_axis_write_desc_pcie_addr, s_axis_write_desc_axi_addr, s_axis_write_desc_len, s_axis_write_desc_tag),
|
||||
tvalid=s_axis_write_desc_valid,
|
||||
tready=s_axis_write_desc_ready,
|
||||
name='write_desc_source'
|
||||
)
|
||||
|
||||
write_desc_status_sink = axis_ep.AXIStreamSink()
|
||||
|
||||
write_desc_status_sink_logic = write_desc_status_sink.create_logic(
|
||||
user_clk,
|
||||
user_reset,
|
||||
tdata=(m_axis_write_desc_status_tag,),
|
||||
tvalid=m_axis_write_desc_status_valid,
|
||||
name='write_desc_status_sink'
|
||||
)
|
||||
|
||||
# PCIe devices
|
||||
rc = pcie.RootComplex()
|
||||
|
||||
mem_base, mem_data = rc.alloc_region(16*1024*1024)
|
||||
|
||||
dev = pcie_us.UltrascalePCIe()
|
||||
|
||||
dev.pcie_generation = 3
|
||||
dev.pcie_link_width = 8
|
||||
dev.user_clock_frequency = 256e6
|
||||
|
||||
rc.make_port().connect(dev)
|
||||
|
||||
pcie_logic = dev.create_logic(
|
||||
# Completer reQuest Interface
|
||||
m_axis_cq_tdata=Signal(intbv(0)[AXIS_PCIE_DATA_WIDTH:]),
|
||||
m_axis_cq_tuser=Signal(intbv(0)[85:]),
|
||||
m_axis_cq_tlast=Signal(bool(0)),
|
||||
m_axis_cq_tkeep=Signal(intbv(0)[AXIS_PCIE_KEEP_WIDTH:]),
|
||||
m_axis_cq_tvalid=Signal(bool(0)),
|
||||
m_axis_cq_tready=Signal(bool(1)),
|
||||
pcie_cq_np_req=Signal(bool(1)),
|
||||
pcie_cq_np_req_count=Signal(intbv(0)[6:]),
|
||||
|
||||
# Completer Completion Interface
|
||||
s_axis_cc_tdata=Signal(intbv(0)[AXIS_PCIE_DATA_WIDTH:]),
|
||||
s_axis_cc_tuser=Signal(intbv(0)[33:]),
|
||||
s_axis_cc_tlast=Signal(bool(0)),
|
||||
s_axis_cc_tkeep=Signal(intbv(0)[AXIS_PCIE_KEEP_WIDTH:]),
|
||||
s_axis_cc_tvalid=Signal(bool(0)),
|
||||
s_axis_cc_tready=Signal(bool(0)),
|
||||
|
||||
# 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_num=pcie_rq_seq_num,
|
||||
# pcie_rq_seq_num_vld=pcie_rq_seq_num_vld,
|
||||
# pcie_rq_tag=pcie_rq_tag,
|
||||
# pcie_rq_tag_av=pcie_rq_tag_av,
|
||||
# pcie_rq_tag_vld=pcie_rq_tag_vld,
|
||||
|
||||
# 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 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_per_function_update_done=cfg_per_function_update_done,
|
||||
# cfg_per_function_number=cfg_per_function_number,
|
||||
# cfg_per_function_output_request=cfg_per_function_output_request,
|
||||
# cfg_dsn=cfg_dsn,
|
||||
# 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=cfg_err_cor_in,
|
||||
# cfg_err_uncor_in=cfg_err_uncor_in,
|
||||
# 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,
|
||||
|
||||
# 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
|
||||
)
|
||||
|
||||
# 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,
|
||||
s_axis_rc_tdata=s_axis_rc_tdata,
|
||||
s_axis_rc_tkeep=s_axis_rc_tkeep,
|
||||
s_axis_rc_tvalid=s_axis_rc_tvalid,
|
||||
s_axis_rc_tready=s_axis_rc_tready,
|
||||
s_axis_rc_tlast=s_axis_rc_tlast,
|
||||
s_axis_rc_tuser=s_axis_rc_tuser,
|
||||
m_axis_rq_tdata=m_axis_rq_tdata,
|
||||
m_axis_rq_tkeep=m_axis_rq_tkeep,
|
||||
m_axis_rq_tvalid=m_axis_rq_tvalid,
|
||||
m_axis_rq_tready=m_axis_rq_tready,
|
||||
m_axis_rq_tlast=m_axis_rq_tlast,
|
||||
m_axis_rq_tuser=m_axis_rq_tuser,
|
||||
s_axis_pcie_rq_tag=s_axis_pcie_rq_tag,
|
||||
s_axis_pcie_rq_tag_valid=s_axis_pcie_rq_tag_valid,
|
||||
s_axis_read_desc_pcie_addr=s_axis_read_desc_pcie_addr,
|
||||
s_axis_read_desc_axi_addr=s_axis_read_desc_axi_addr,
|
||||
s_axis_read_desc_len=s_axis_read_desc_len,
|
||||
s_axis_read_desc_tag=s_axis_read_desc_tag,
|
||||
s_axis_read_desc_valid=s_axis_read_desc_valid,
|
||||
s_axis_read_desc_ready=s_axis_read_desc_ready,
|
||||
m_axis_read_desc_status_tag=m_axis_read_desc_status_tag,
|
||||
m_axis_read_desc_status_valid=m_axis_read_desc_status_valid,
|
||||
s_axis_write_desc_pcie_addr=s_axis_write_desc_pcie_addr,
|
||||
s_axis_write_desc_axi_addr=s_axis_write_desc_axi_addr,
|
||||
s_axis_write_desc_len=s_axis_write_desc_len,
|
||||
s_axis_write_desc_tag=s_axis_write_desc_tag,
|
||||
s_axis_write_desc_valid=s_axis_write_desc_valid,
|
||||
s_axis_write_desc_ready=s_axis_write_desc_ready,
|
||||
m_axis_write_desc_status_tag=m_axis_write_desc_status_tag,
|
||||
m_axis_write_desc_status_valid=m_axis_write_desc_status_valid,
|
||||
m_axi_awid=m_axi_awid,
|
||||
m_axi_awaddr=m_axi_awaddr,
|
||||
m_axi_awlen=m_axi_awlen,
|
||||
m_axi_awsize=m_axi_awsize,
|
||||
m_axi_awburst=m_axi_awburst,
|
||||
m_axi_awlock=m_axi_awlock,
|
||||
m_axi_awcache=m_axi_awcache,
|
||||
m_axi_awprot=m_axi_awprot,
|
||||
m_axi_awvalid=m_axi_awvalid,
|
||||
m_axi_awready=m_axi_awready,
|
||||
m_axi_wdata=m_axi_wdata,
|
||||
m_axi_wstrb=m_axi_wstrb,
|
||||
m_axi_wlast=m_axi_wlast,
|
||||
m_axi_wvalid=m_axi_wvalid,
|
||||
m_axi_wready=m_axi_wready,
|
||||
m_axi_bid=m_axi_bid,
|
||||
m_axi_bresp=m_axi_bresp,
|
||||
m_axi_bvalid=m_axi_bvalid,
|
||||
m_axi_bready=m_axi_bready,
|
||||
m_axi_arid=m_axi_arid,
|
||||
m_axi_araddr=m_axi_araddr,
|
||||
m_axi_arlen=m_axi_arlen,
|
||||
m_axi_arsize=m_axi_arsize,
|
||||
m_axi_arburst=m_axi_arburst,
|
||||
m_axi_arlock=m_axi_arlock,
|
||||
m_axi_arcache=m_axi_arcache,
|
||||
m_axi_arprot=m_axi_arprot,
|
||||
m_axi_arvalid=m_axi_arvalid,
|
||||
m_axi_arready=m_axi_arready,
|
||||
m_axi_rid=m_axi_rid,
|
||||
m_axi_rdata=m_axi_rdata,
|
||||
m_axi_rresp=m_axi_rresp,
|
||||
m_axi_rlast=m_axi_rlast,
|
||||
m_axi_rvalid=m_axi_rvalid,
|
||||
m_axi_rready=m_axi_rready,
|
||||
read_enable=read_enable,
|
||||
write_enable=write_enable,
|
||||
ext_tag_enable=ext_tag_enable,
|
||||
requester_id=requester_id,
|
||||
requester_id_enable=requester_id_enable,
|
||||
max_read_request_size=max_read_request_size,
|
||||
max_payload_size=max_payload_size,
|
||||
status_error_cor=status_error_cor,
|
||||
status_error_uncor=status_error_uncor
|
||||
)
|
||||
|
||||
@always(delay(4))
|
||||
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
|
||||
|
||||
cur_tag = 1
|
||||
|
||||
max_payload_size.next = 0
|
||||
max_read_request_size.next = 2
|
||||
|
||||
read_enable.next = 1
|
||||
write_enable.next = 1
|
||||
|
||||
yield user_clk.posedge
|
||||
print("test 1: enumeration")
|
||||
current_test.next = 1
|
||||
|
||||
yield rc.enumerate(enable_bus_mastering=True)
|
||||
|
||||
yield delay(100)
|
||||
|
||||
yield user_clk.posedge
|
||||
print("test 2: PCIe write")
|
||||
current_test.next = 2
|
||||
|
||||
pcie_addr = 0x00000000
|
||||
axi_addr = 0x00000000
|
||||
test_data = b'\x11\x22\x33\x44'
|
||||
|
||||
axi_ram_inst.write_mem(axi_addr, test_data)
|
||||
|
||||
data = axi_ram_inst.read_mem(axi_addr, 32)
|
||||
for i in range(0, len(data), 16):
|
||||
print(" ".join(("{:02x}".format(c) for c in bytearray(data[i:i+16]))))
|
||||
|
||||
write_desc_source.send([(mem_base+pcie_addr, axi_addr, len(test_data), cur_tag)])
|
||||
|
||||
yield write_desc_status_sink.wait(1000)
|
||||
yield delay(50)
|
||||
|
||||
status = write_desc_status_sink.recv()
|
||||
|
||||
print(status)
|
||||
|
||||
assert status.data[0][0] == cur_tag
|
||||
|
||||
data = mem_data[pcie_addr:pcie_addr+32]
|
||||
for i in range(0, len(data), 16):
|
||||
print(" ".join(("{:02x}".format(c) for c in bytearray(data[i:i+16]))))
|
||||
|
||||
assert mem_data[pcie_addr:pcie_addr+len(test_data)] == test_data
|
||||
|
||||
cur_tag = (cur_tag + 1) % 256
|
||||
|
||||
yield delay(100)
|
||||
|
||||
yield user_clk.posedge
|
||||
print("test 3: PCIe read")
|
||||
current_test.next = 3
|
||||
|
||||
pcie_addr = 0x00000000
|
||||
axi_addr = 0x00000000
|
||||
test_data = b'\x11\x22\x33\x44'
|
||||
|
||||
mem_data[pcie_addr:pcie_addr+len(test_data)] = test_data
|
||||
|
||||
data = mem_data[pcie_addr:pcie_addr+32]
|
||||
for i in range(0, len(data), 16):
|
||||
print(" ".join(("{:02x}".format(c) for c in bytearray(data[i:i+16]))))
|
||||
|
||||
read_desc_source.send([(pcie_addr, axi_addr, len(test_data), cur_tag)])
|
||||
|
||||
yield read_desc_status_sink.wait(2000)
|
||||
|
||||
status = read_desc_status_sink.recv()
|
||||
|
||||
print(status)
|
||||
|
||||
data = axi_ram_inst.read_mem(axi_addr, 32)
|
||||
for i in range(0, len(data), 16):
|
||||
print(" ".join(("{:02x}".format(c) for c in bytearray(data[i:i+16]))))
|
||||
|
||||
assert axi_ram_inst.read_mem(axi_addr, len(test_data)) == test_data
|
||||
|
||||
cur_tag = (cur_tag + 1) % 256
|
||||
|
||||
yield delay(100)
|
||||
|
||||
raise StopSimulation
|
||||
|
||||
return instances()
|
||||
|
||||
def test_bench():
|
||||
sim = Simulation(bench())
|
||||
sim.run()
|
||||
|
||||
if __name__ == '__main__':
|
||||
print("Running test...")
|
||||
test_bench()
|
316
fpga/lib/pcie/tb/test_pcie_us_axi_dma_256.v
Normal file
316
fpga/lib/pcie/tb/test_pcie_us_axi_dma_256.v
Normal file
@ -0,0 +1,316 @@
|
||||
/*
|
||||
|
||||
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 pcie_us_axi_dma
|
||||
*/
|
||||
module test_pcie_us_axi_dma_256;
|
||||
|
||||
// Parameters
|
||||
parameter AXIS_PCIE_DATA_WIDTH = 256;
|
||||
parameter AXIS_PCIE_KEEP_WIDTH = (AXIS_PCIE_DATA_WIDTH/32);
|
||||
parameter AXI_DATA_WIDTH = AXIS_PCIE_DATA_WIDTH;
|
||||
parameter AXI_ADDR_WIDTH = 64;
|
||||
parameter AXI_STRB_WIDTH = (AXI_DATA_WIDTH/8);
|
||||
parameter AXI_ID_WIDTH = 8;
|
||||
parameter AXI_MAX_BURST_LEN = 256;
|
||||
parameter PCIE_ADDR_WIDTH = 64;
|
||||
parameter PCIE_CLIENT_TAG = 1;
|
||||
parameter PCIE_TAG_WIDTH = 8;
|
||||
parameter PCIE_TAG_COUNT = 256;
|
||||
parameter PCIE_EXT_TAG_ENABLE = 1;
|
||||
parameter LEN_WIDTH = 20;
|
||||
parameter TAG_WIDTH = 8;
|
||||
|
||||
// Inputs
|
||||
reg clk = 0;
|
||||
reg rst = 0;
|
||||
reg [7:0] current_test = 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_tvalid = 0;
|
||||
reg s_axis_rc_tlast = 0;
|
||||
reg [74:0] s_axis_rc_tuser = 0;
|
||||
reg m_axis_rq_tready = 0;
|
||||
reg [PCIE_TAG_WIDTH-1:0] s_axis_pcie_rq_tag = 0;
|
||||
reg s_axis_pcie_rq_tag_valid = 0;
|
||||
reg [PCIE_ADDR_WIDTH-1:0] s_axis_read_desc_pcie_addr = 0;
|
||||
reg [AXI_ADDR_WIDTH-1:0] s_axis_read_desc_axi_addr = 0;
|
||||
reg [LEN_WIDTH-1:0] s_axis_read_desc_len = 0;
|
||||
reg [TAG_WIDTH-1:0] s_axis_read_desc_tag = 0;
|
||||
reg s_axis_read_desc_valid = 0;
|
||||
reg [PCIE_ADDR_WIDTH-1:0] s_axis_write_desc_pcie_addr = 0;
|
||||
reg [AXI_ADDR_WIDTH-1:0] s_axis_write_desc_axi_addr = 0;
|
||||
reg [LEN_WIDTH-1:0] s_axis_write_desc_len = 0;
|
||||
reg [TAG_WIDTH-1:0] s_axis_write_desc_tag = 0;
|
||||
reg s_axis_write_desc_valid = 0;
|
||||
reg m_axi_awready = 0;
|
||||
reg m_axi_wready = 0;
|
||||
reg [AXI_ID_WIDTH-1:0] m_axi_bid = 0;
|
||||
reg [1:0] m_axi_bresp = 0;
|
||||
reg m_axi_bvalid = 0;
|
||||
reg m_axi_arready = 0;
|
||||
reg [AXI_ID_WIDTH-1:0] m_axi_rid = 0;
|
||||
reg [AXI_DATA_WIDTH-1:0] m_axi_rdata = 0;
|
||||
reg [1:0] m_axi_rresp = 0;
|
||||
reg m_axi_rlast = 0;
|
||||
reg m_axi_rvalid = 0;
|
||||
reg read_enable = 0;
|
||||
reg write_enable = 0;
|
||||
reg ext_tag_enable = 0;
|
||||
reg [15:0] requester_id = 0;
|
||||
reg requester_id_enable = 0;
|
||||
reg [2:0] max_read_request_size = 0;
|
||||
reg [2:0] max_payload_size = 0;
|
||||
|
||||
// Outputs
|
||||
wire s_axis_rc_tready;
|
||||
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_tvalid;
|
||||
wire m_axis_rq_tlast;
|
||||
wire [59:0] m_axis_rq_tuser;
|
||||
wire s_axis_read_desc_ready;
|
||||
wire [TAG_WIDTH-1:0] m_axis_read_desc_status_tag;
|
||||
wire m_axis_read_desc_status_valid;
|
||||
wire s_axis_write_desc_ready;
|
||||
wire [TAG_WIDTH-1:0] m_axis_write_desc_status_tag;
|
||||
wire m_axis_write_desc_status_valid;
|
||||
wire [AXI_ID_WIDTH-1:0] m_axi_awid;
|
||||
wire [AXI_ADDR_WIDTH-1:0] m_axi_awaddr;
|
||||
wire [7:0] m_axi_awlen;
|
||||
wire [2:0] m_axi_awsize;
|
||||
wire [1:0] m_axi_awburst;
|
||||
wire m_axi_awlock;
|
||||
wire [3:0] m_axi_awcache;
|
||||
wire [2:0] m_axi_awprot;
|
||||
wire m_axi_awvalid;
|
||||
wire [AXI_DATA_WIDTH-1:0] m_axi_wdata;
|
||||
wire [AXI_STRB_WIDTH-1:0] m_axi_wstrb;
|
||||
wire m_axi_wlast;
|
||||
wire m_axi_wvalid;
|
||||
wire m_axi_bready;
|
||||
wire [AXI_ID_WIDTH-1:0] m_axi_arid;
|
||||
wire [AXI_ADDR_WIDTH-1:0] m_axi_araddr;
|
||||
wire [7:0] m_axi_arlen;
|
||||
wire [2:0] m_axi_arsize;
|
||||
wire [1:0] m_axi_arburst;
|
||||
wire m_axi_arlock;
|
||||
wire [3:0] m_axi_arcache;
|
||||
wire [2:0] m_axi_arprot;
|
||||
wire m_axi_arvalid;
|
||||
wire m_axi_rready;
|
||||
wire status_error_cor;
|
||||
wire status_error_uncor;
|
||||
|
||||
initial begin
|
||||
// myhdl integration
|
||||
$from_myhdl(
|
||||
clk,
|
||||
rst,
|
||||
current_test,
|
||||
s_axis_rc_tdata,
|
||||
s_axis_rc_tkeep,
|
||||
s_axis_rc_tvalid,
|
||||
s_axis_rc_tlast,
|
||||
s_axis_rc_tuser,
|
||||
m_axis_rq_tready,
|
||||
s_axis_pcie_rq_tag,
|
||||
s_axis_pcie_rq_tag_valid,
|
||||
s_axis_read_desc_pcie_addr,
|
||||
s_axis_read_desc_axi_addr,
|
||||
s_axis_read_desc_len,
|
||||
s_axis_read_desc_tag,
|
||||
s_axis_read_desc_valid,
|
||||
s_axis_write_desc_pcie_addr,
|
||||
s_axis_write_desc_axi_addr,
|
||||
s_axis_write_desc_len,
|
||||
s_axis_write_desc_tag,
|
||||
s_axis_write_desc_valid,
|
||||
m_axi_awready,
|
||||
m_axi_wready,
|
||||
m_axi_bid,
|
||||
m_axi_bresp,
|
||||
m_axi_bvalid,
|
||||
m_axi_arready,
|
||||
m_axi_rid,
|
||||
m_axi_rdata,
|
||||
m_axi_rresp,
|
||||
m_axi_rlast,
|
||||
m_axi_rvalid,
|
||||
read_enable,
|
||||
write_enable,
|
||||
ext_tag_enable,
|
||||
requester_id,
|
||||
requester_id_enable,
|
||||
max_read_request_size,
|
||||
max_payload_size
|
||||
);
|
||||
$to_myhdl(
|
||||
s_axis_rc_tready,
|
||||
m_axis_rq_tdata,
|
||||
m_axis_rq_tkeep,
|
||||
m_axis_rq_tvalid,
|
||||
m_axis_rq_tlast,
|
||||
m_axis_rq_tuser,
|
||||
s_axis_read_desc_ready,
|
||||
m_axis_read_desc_status_tag,
|
||||
m_axis_read_desc_status_valid,
|
||||
s_axis_write_desc_ready,
|
||||
m_axis_write_desc_status_tag,
|
||||
m_axis_write_desc_status_valid,
|
||||
m_axi_awid,
|
||||
m_axi_awaddr,
|
||||
m_axi_awlen,
|
||||
m_axi_awsize,
|
||||
m_axi_awburst,
|
||||
m_axi_awlock,
|
||||
m_axi_awcache,
|
||||
m_axi_awprot,
|
||||
m_axi_awvalid,
|
||||
m_axi_wdata,
|
||||
m_axi_wstrb,
|
||||
m_axi_wlast,
|
||||
m_axi_wvalid,
|
||||
m_axi_bready,
|
||||
m_axi_arid,
|
||||
m_axi_araddr,
|
||||
m_axi_arlen,
|
||||
m_axi_arsize,
|
||||
m_axi_arburst,
|
||||
m_axi_arlock,
|
||||
m_axi_arcache,
|
||||
m_axi_arprot,
|
||||
m_axi_arvalid,
|
||||
m_axi_rready,
|
||||
status_error_cor,
|
||||
status_error_uncor
|
||||
);
|
||||
|
||||
// dump file
|
||||
$dumpfile("test_pcie_us_axi_dma_256.lxt");
|
||||
$dumpvars(0, test_pcie_us_axi_dma_256);
|
||||
end
|
||||
|
||||
pcie_us_axi_dma #(
|
||||
.AXIS_PCIE_DATA_WIDTH(AXIS_PCIE_DATA_WIDTH),
|
||||
.AXIS_PCIE_KEEP_WIDTH(AXIS_PCIE_KEEP_WIDTH),
|
||||
.AXI_DATA_WIDTH(AXI_DATA_WIDTH),
|
||||
.AXI_ADDR_WIDTH(AXI_ADDR_WIDTH),
|
||||
.AXI_STRB_WIDTH(AXI_STRB_WIDTH),
|
||||
.AXI_ID_WIDTH(AXI_ID_WIDTH),
|
||||
.AXI_MAX_BURST_LEN(AXI_MAX_BURST_LEN),
|
||||
.PCIE_ADDR_WIDTH(PCIE_ADDR_WIDTH),
|
||||
.PCIE_CLIENT_TAG(PCIE_CLIENT_TAG),
|
||||
.PCIE_TAG_WIDTH(PCIE_TAG_WIDTH),
|
||||
.PCIE_TAG_COUNT(PCIE_TAG_COUNT),
|
||||
.PCIE_EXT_TAG_ENABLE(PCIE_EXT_TAG_ENABLE),
|
||||
.LEN_WIDTH(LEN_WIDTH),
|
||||
.TAG_WIDTH(TAG_WIDTH)
|
||||
)
|
||||
UUT (
|
||||
.clk(clk),
|
||||
.rst(rst),
|
||||
.s_axis_rc_tdata(s_axis_rc_tdata),
|
||||
.s_axis_rc_tkeep(s_axis_rc_tkeep),
|
||||
.s_axis_rc_tvalid(s_axis_rc_tvalid),
|
||||
.s_axis_rc_tready(s_axis_rc_tready),
|
||||
.s_axis_rc_tlast(s_axis_rc_tlast),
|
||||
.s_axis_rc_tuser(s_axis_rc_tuser),
|
||||
.m_axis_rq_tdata(m_axis_rq_tdata),
|
||||
.m_axis_rq_tkeep(m_axis_rq_tkeep),
|
||||
.m_axis_rq_tvalid(m_axis_rq_tvalid),
|
||||
.m_axis_rq_tready(m_axis_rq_tready),
|
||||
.m_axis_rq_tlast(m_axis_rq_tlast),
|
||||
.m_axis_rq_tuser(m_axis_rq_tuser),
|
||||
.s_axis_pcie_rq_tag(s_axis_pcie_rq_tag),
|
||||
.s_axis_pcie_rq_tag_valid(s_axis_pcie_rq_tag_valid),
|
||||
.s_axis_read_desc_pcie_addr(s_axis_read_desc_pcie_addr),
|
||||
.s_axis_read_desc_axi_addr(s_axis_read_desc_axi_addr),
|
||||
.s_axis_read_desc_len(s_axis_read_desc_len),
|
||||
.s_axis_read_desc_tag(s_axis_read_desc_tag),
|
||||
.s_axis_read_desc_valid(s_axis_read_desc_valid),
|
||||
.s_axis_read_desc_ready(s_axis_read_desc_ready),
|
||||
.m_axis_read_desc_status_tag(m_axis_read_desc_status_tag),
|
||||
.m_axis_read_desc_status_valid(m_axis_read_desc_status_valid),
|
||||
.s_axis_write_desc_pcie_addr(s_axis_write_desc_pcie_addr),
|
||||
.s_axis_write_desc_axi_addr(s_axis_write_desc_axi_addr),
|
||||
.s_axis_write_desc_len(s_axis_write_desc_len),
|
||||
.s_axis_write_desc_tag(s_axis_write_desc_tag),
|
||||
.s_axis_write_desc_valid(s_axis_write_desc_valid),
|
||||
.s_axis_write_desc_ready(s_axis_write_desc_ready),
|
||||
.m_axis_write_desc_status_tag(m_axis_write_desc_status_tag),
|
||||
.m_axis_write_desc_status_valid(m_axis_write_desc_status_valid),
|
||||
.m_axi_awid(m_axi_awid),
|
||||
.m_axi_awaddr(m_axi_awaddr),
|
||||
.m_axi_awlen(m_axi_awlen),
|
||||
.m_axi_awsize(m_axi_awsize),
|
||||
.m_axi_awburst(m_axi_awburst),
|
||||
.m_axi_awlock(m_axi_awlock),
|
||||
.m_axi_awcache(m_axi_awcache),
|
||||
.m_axi_awprot(m_axi_awprot),
|
||||
.m_axi_awvalid(m_axi_awvalid),
|
||||
.m_axi_awready(m_axi_awready),
|
||||
.m_axi_wdata(m_axi_wdata),
|
||||
.m_axi_wstrb(m_axi_wstrb),
|
||||
.m_axi_wlast(m_axi_wlast),
|
||||
.m_axi_wvalid(m_axi_wvalid),
|
||||
.m_axi_wready(m_axi_wready),
|
||||
.m_axi_bid(m_axi_bid),
|
||||
.m_axi_bresp(m_axi_bresp),
|
||||
.m_axi_bvalid(m_axi_bvalid),
|
||||
.m_axi_bready(m_axi_bready),
|
||||
.m_axi_arid(m_axi_arid),
|
||||
.m_axi_araddr(m_axi_araddr),
|
||||
.m_axi_arlen(m_axi_arlen),
|
||||
.m_axi_arsize(m_axi_arsize),
|
||||
.m_axi_arburst(m_axi_arburst),
|
||||
.m_axi_arlock(m_axi_arlock),
|
||||
.m_axi_arcache(m_axi_arcache),
|
||||
.m_axi_arprot(m_axi_arprot),
|
||||
.m_axi_arvalid(m_axi_arvalid),
|
||||
.m_axi_arready(m_axi_arready),
|
||||
.m_axi_rid(m_axi_rid),
|
||||
.m_axi_rdata(m_axi_rdata),
|
||||
.m_axi_rresp(m_axi_rresp),
|
||||
.m_axi_rlast(m_axi_rlast),
|
||||
.m_axi_rvalid(m_axi_rvalid),
|
||||
.m_axi_rready(m_axi_rready),
|
||||
.read_enable(read_enable),
|
||||
.write_enable(write_enable),
|
||||
.ext_tag_enable(ext_tag_enable),
|
||||
.requester_id(requester_id),
|
||||
.requester_id_enable(requester_id_enable),
|
||||
.max_read_request_size(max_read_request_size),
|
||||
.max_payload_size(max_payload_size),
|
||||
.status_error_cor(status_error_cor),
|
||||
.status_error_uncor(status_error_uncor)
|
||||
);
|
||||
|
||||
endmodule
|
496
fpga/lib/pcie/tb/test_pcie_us_axi_dma_rd_128.py
Executable file
496
fpga/lib/pcie/tb/test_pcie_us_axi_dma_rd_128.py
Executable file
@ -0,0 +1,496 @@
|
||||
#!/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_us
|
||||
import axi
|
||||
import axis_ep
|
||||
|
||||
module = 'pcie_us_axi_dma_rd'
|
||||
testbench = 'test_%s_128' % module
|
||||
|
||||
srcs = []
|
||||
|
||||
srcs.append("../rtl/%s.v" % module)
|
||||
srcs.append("../rtl/pcie_tag_manager.v")
|
||||
srcs.append("../rtl/priority_encoder.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 = 128
|
||||
AXIS_PCIE_KEEP_WIDTH = (AXIS_PCIE_DATA_WIDTH/32)
|
||||
AXI_DATA_WIDTH = AXIS_PCIE_DATA_WIDTH
|
||||
AXI_ADDR_WIDTH = 64
|
||||
AXI_STRB_WIDTH = (AXI_DATA_WIDTH/8)
|
||||
AXI_ID_WIDTH = 8
|
||||
AXI_MAX_BURST_LEN = 256
|
||||
PCIE_ADDR_WIDTH = 64
|
||||
PCIE_CLIENT_TAG = 1
|
||||
PCIE_TAG_WIDTH = 8
|
||||
PCIE_TAG_COUNT = 256
|
||||
PCIE_EXT_TAG_ENABLE = 1
|
||||
LEN_WIDTH = 20
|
||||
TAG_WIDTH = 8
|
||||
|
||||
# Inputs
|
||||
clk = Signal(bool(0))
|
||||
rst = Signal(bool(0))
|
||||
current_test = Signal(intbv(0)[8:])
|
||||
|
||||
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_tvalid = Signal(bool(0))
|
||||
s_axis_rc_tlast = Signal(bool(0))
|
||||
s_axis_rc_tuser = Signal(intbv(0)[75:])
|
||||
m_axis_rq_tready = Signal(bool(0))
|
||||
s_axis_pcie_rq_tag = Signal(intbv(0)[PCIE_TAG_WIDTH:])
|
||||
s_axis_pcie_rq_tag_valid = Signal(bool(0))
|
||||
s_axis_read_desc_pcie_addr = Signal(intbv(0)[PCIE_ADDR_WIDTH:])
|
||||
s_axis_read_desc_axi_addr = Signal(intbv(0)[AXI_ADDR_WIDTH:])
|
||||
s_axis_read_desc_len = Signal(intbv(0)[LEN_WIDTH:])
|
||||
s_axis_read_desc_tag = Signal(intbv(0)[TAG_WIDTH:])
|
||||
s_axis_read_desc_valid = Signal(bool(0))
|
||||
m_axi_awready = Signal(bool(0))
|
||||
m_axi_wready = Signal(bool(0))
|
||||
m_axi_bid = Signal(intbv(0)[AXI_ID_WIDTH:])
|
||||
m_axi_bresp = Signal(intbv(0)[2:])
|
||||
m_axi_bvalid = Signal(bool(0))
|
||||
enable = Signal(bool(0))
|
||||
ext_tag_enable = Signal(bool(0))
|
||||
requester_id = Signal(intbv(0)[16:])
|
||||
requester_id_enable = Signal(bool(0))
|
||||
max_read_request_size = Signal(intbv(0)[3:])
|
||||
|
||||
# Outputs
|
||||
s_axis_rc_tready = Signal(bool(0))
|
||||
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_tvalid = Signal(bool(0))
|
||||
m_axis_rq_tlast = Signal(bool(0))
|
||||
m_axis_rq_tuser = Signal(intbv(0)[60:])
|
||||
s_axis_read_desc_ready = Signal(bool(0))
|
||||
m_axis_read_desc_status_tag = Signal(intbv(0)[TAG_WIDTH:])
|
||||
m_axis_read_desc_status_valid = Signal(bool(0))
|
||||
m_axi_awid = Signal(intbv(0)[AXI_ID_WIDTH:])
|
||||
m_axi_awaddr = Signal(intbv(0)[AXI_ADDR_WIDTH:])
|
||||
m_axi_awlen = Signal(intbv(0)[8:])
|
||||
m_axi_awsize = Signal(intbv(4)[3:])
|
||||
m_axi_awburst = Signal(intbv(1)[2:])
|
||||
m_axi_awlock = Signal(bool(0))
|
||||
m_axi_awcache = Signal(intbv(3)[4:])
|
||||
m_axi_awprot = Signal(intbv(2)[3:])
|
||||
m_axi_awvalid = Signal(bool(0))
|
||||
m_axi_wdata = Signal(intbv(0)[AXI_DATA_WIDTH:])
|
||||
m_axi_wstrb = Signal(intbv(0)[AXI_STRB_WIDTH:])
|
||||
m_axi_wlast = Signal(bool(0))
|
||||
m_axi_wvalid = Signal(bool(0))
|
||||
m_axi_bready = Signal(bool(0))
|
||||
status_error_cor = Signal(bool(0))
|
||||
status_error_uncor = Signal(bool(0))
|
||||
|
||||
# Clock and Reset Interface
|
||||
user_clk=Signal(bool(0))
|
||||
user_reset=Signal(bool(0))
|
||||
sys_clk=Signal(bool(0))
|
||||
sys_reset=Signal(bool(0))
|
||||
|
||||
# AXI4 RAM model
|
||||
axi_ram_inst = axi.AXIRam(2**16)
|
||||
|
||||
axi_ram_port0 = axi_ram_inst.create_port(
|
||||
user_clk,
|
||||
s_axi_awid=m_axi_awid,
|
||||
s_axi_awaddr=m_axi_awaddr,
|
||||
s_axi_awlen=m_axi_awlen,
|
||||
s_axi_awsize=m_axi_awsize,
|
||||
s_axi_awburst=m_axi_awburst,
|
||||
s_axi_awlock=m_axi_awlock,
|
||||
s_axi_awcache=m_axi_awcache,
|
||||
s_axi_awprot=m_axi_awprot,
|
||||
s_axi_awvalid=m_axi_awvalid,
|
||||
s_axi_awready=m_axi_awready,
|
||||
s_axi_wdata=m_axi_wdata,
|
||||
s_axi_wstrb=m_axi_wstrb,
|
||||
s_axi_wlast=m_axi_wlast,
|
||||
s_axi_wvalid=m_axi_wvalid,
|
||||
s_axi_wready=m_axi_wready,
|
||||
s_axi_bid=m_axi_bid,
|
||||
s_axi_bresp=m_axi_bresp,
|
||||
s_axi_bvalid=m_axi_bvalid,
|
||||
s_axi_bready=m_axi_bready,
|
||||
name='port0'
|
||||
)
|
||||
|
||||
# sources and sinks
|
||||
read_desc_source = axis_ep.AXIStreamSource()
|
||||
|
||||
read_desc_source_logic = read_desc_source.create_logic(
|
||||
user_clk,
|
||||
user_reset,
|
||||
tdata=(s_axis_read_desc_pcie_addr, s_axis_read_desc_axi_addr, s_axis_read_desc_len, s_axis_read_desc_tag),
|
||||
tvalid=s_axis_read_desc_valid,
|
||||
tready=s_axis_read_desc_ready,
|
||||
name='read_desc_source'
|
||||
)
|
||||
|
||||
read_desc_status_sink = axis_ep.AXIStreamSink()
|
||||
|
||||
read_desc_status_sink_logic = read_desc_status_sink.create_logic(
|
||||
user_clk,
|
||||
user_reset,
|
||||
tdata=(m_axis_read_desc_status_tag,),
|
||||
tvalid=m_axis_read_desc_status_valid,
|
||||
name='read_desc_status_sink'
|
||||
)
|
||||
|
||||
# PCIe devices
|
||||
rc = pcie.RootComplex()
|
||||
|
||||
mem_base, mem_data = rc.alloc_region(16*1024*1024)
|
||||
|
||||
dev = pcie_us.UltrascalePCIe()
|
||||
|
||||
dev.pcie_generation = 3
|
||||
dev.pcie_link_width = 4
|
||||
dev.user_clock_frequency = 256e6
|
||||
|
||||
rc.make_port().connect(dev)
|
||||
|
||||
cq_pause = Signal(bool(0))
|
||||
cc_pause = Signal(bool(0))
|
||||
rq_pause = Signal(bool(0))
|
||||
rc_pause = Signal(bool(0))
|
||||
|
||||
pcie_logic = dev.create_logic(
|
||||
# Completer reQuest Interface
|
||||
m_axis_cq_tdata=Signal(intbv(0)[AXIS_PCIE_DATA_WIDTH:]),
|
||||
m_axis_cq_tuser=Signal(intbv(0)[85:]),
|
||||
m_axis_cq_tlast=Signal(bool(0)),
|
||||
m_axis_cq_tkeep=Signal(intbv(0)[AXIS_PCIE_KEEP_WIDTH:]),
|
||||
m_axis_cq_tvalid=Signal(bool(0)),
|
||||
m_axis_cq_tready=Signal(bool(1)),
|
||||
pcie_cq_np_req=Signal(bool(1)),
|
||||
pcie_cq_np_req_count=Signal(intbv(0)[6:]),
|
||||
|
||||
# Completer Completion Interface
|
||||
s_axis_cc_tdata=Signal(intbv(0)[AXIS_PCIE_DATA_WIDTH:]),
|
||||
s_axis_cc_tuser=Signal(intbv(0)[33:]),
|
||||
s_axis_cc_tlast=Signal(bool(0)),
|
||||
s_axis_cc_tkeep=Signal(intbv(0)[AXIS_PCIE_KEEP_WIDTH:]),
|
||||
s_axis_cc_tvalid=Signal(bool(0)),
|
||||
s_axis_cc_tready=Signal(bool(0)),
|
||||
|
||||
# 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_num=pcie_rq_seq_num,
|
||||
# pcie_rq_seq_num_vld=pcie_rq_seq_num_vld,
|
||||
# pcie_rq_tag=pcie_rq_tag,
|
||||
# pcie_rq_tag_av=pcie_rq_tag_av,
|
||||
# pcie_rq_tag_vld=pcie_rq_tag_vld,
|
||||
|
||||
# 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 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_per_function_update_done=cfg_per_function_update_done,
|
||||
# cfg_per_function_number=cfg_per_function_number,
|
||||
# cfg_per_function_output_request=cfg_per_function_output_request,
|
||||
# cfg_dsn=cfg_dsn,
|
||||
# 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=cfg_err_cor_in,
|
||||
# cfg_err_uncor_in=cfg_err_uncor_in,
|
||||
# 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,
|
||||
|
||||
# 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,
|
||||
|
||||
cq_pause=cq_pause,
|
||||
cc_pause=cc_pause,
|
||||
rq_pause=rq_pause,
|
||||
rc_pause=rc_pause
|
||||
)
|
||||
|
||||
# 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,
|
||||
s_axis_rc_tdata=s_axis_rc_tdata,
|
||||
s_axis_rc_tkeep=s_axis_rc_tkeep,
|
||||
s_axis_rc_tvalid=s_axis_rc_tvalid,
|
||||
s_axis_rc_tready=s_axis_rc_tready,
|
||||
s_axis_rc_tlast=s_axis_rc_tlast,
|
||||
s_axis_rc_tuser=s_axis_rc_tuser,
|
||||
m_axis_rq_tdata=m_axis_rq_tdata,
|
||||
m_axis_rq_tkeep=m_axis_rq_tkeep,
|
||||
m_axis_rq_tvalid=m_axis_rq_tvalid,
|
||||
m_axis_rq_tready=m_axis_rq_tready,
|
||||
m_axis_rq_tlast=m_axis_rq_tlast,
|
||||
m_axis_rq_tuser=m_axis_rq_tuser,
|
||||
s_axis_pcie_rq_tag=s_axis_pcie_rq_tag,
|
||||
s_axis_pcie_rq_tag_valid=s_axis_pcie_rq_tag_valid,
|
||||
s_axis_read_desc_pcie_addr=s_axis_read_desc_pcie_addr,
|
||||
s_axis_read_desc_axi_addr=s_axis_read_desc_axi_addr,
|
||||
s_axis_read_desc_len=s_axis_read_desc_len,
|
||||
s_axis_read_desc_tag=s_axis_read_desc_tag,
|
||||
s_axis_read_desc_valid=s_axis_read_desc_valid,
|
||||
s_axis_read_desc_ready=s_axis_read_desc_ready,
|
||||
m_axis_read_desc_status_tag=m_axis_read_desc_status_tag,
|
||||
m_axis_read_desc_status_valid=m_axis_read_desc_status_valid,
|
||||
m_axi_awid=m_axi_awid,
|
||||
m_axi_awaddr=m_axi_awaddr,
|
||||
m_axi_awlen=m_axi_awlen,
|
||||
m_axi_awsize=m_axi_awsize,
|
||||
m_axi_awburst=m_axi_awburst,
|
||||
m_axi_awlock=m_axi_awlock,
|
||||
m_axi_awcache=m_axi_awcache,
|
||||
m_axi_awprot=m_axi_awprot,
|
||||
m_axi_awvalid=m_axi_awvalid,
|
||||
m_axi_awready=m_axi_awready,
|
||||
m_axi_wdata=m_axi_wdata,
|
||||
m_axi_wstrb=m_axi_wstrb,
|
||||
m_axi_wlast=m_axi_wlast,
|
||||
m_axi_wvalid=m_axi_wvalid,
|
||||
m_axi_wready=m_axi_wready,
|
||||
m_axi_bid=m_axi_bid,
|
||||
m_axi_bresp=m_axi_bresp,
|
||||
m_axi_bvalid=m_axi_bvalid,
|
||||
m_axi_bready=m_axi_bready,
|
||||
enable=enable,
|
||||
ext_tag_enable=ext_tag_enable,
|
||||
requester_id=requester_id,
|
||||
requester_id_enable=requester_id_enable,
|
||||
max_read_request_size=max_read_request_size,
|
||||
status_error_cor=status_error_cor,
|
||||
status_error_uncor=status_error_uncor
|
||||
)
|
||||
|
||||
@always(delay(4))
|
||||
def clkgen():
|
||||
clk.next = not clk
|
||||
|
||||
@always_comb
|
||||
def clk_logic():
|
||||
sys_clk.next = clk
|
||||
sys_reset.next = not rst
|
||||
|
||||
status_error_cor_asserted = Signal(bool(0))
|
||||
status_error_uncor_asserted = Signal(bool(0))
|
||||
|
||||
@always(clk.posedge)
|
||||
def monitor():
|
||||
if (status_error_cor):
|
||||
status_error_cor_asserted.next = 1
|
||||
if (status_error_uncor):
|
||||
status_error_uncor_asserted.next = 1
|
||||
|
||||
cq_pause_toggle = Signal(bool(0))
|
||||
cc_pause_toggle = Signal(bool(0))
|
||||
rq_pause_toggle = Signal(bool(0))
|
||||
rc_pause_toggle = Signal(bool(0))
|
||||
|
||||
@instance
|
||||
def pause_toggle():
|
||||
while True:
|
||||
if (cq_pause_toggle or cc_pause_toggle or rq_pause_toggle or rc_pause_toggle):
|
||||
cq_pause.next = cq_pause_toggle
|
||||
cc_pause.next = cc_pause_toggle
|
||||
rq_pause.next = rq_pause_toggle
|
||||
rc_pause.next = rc_pause_toggle
|
||||
|
||||
yield user_clk.posedge
|
||||
yield user_clk.posedge
|
||||
yield user_clk.posedge
|
||||
|
||||
cq_pause.next = 0
|
||||
cc_pause.next = 0
|
||||
rq_pause.next = 0
|
||||
rc_pause.next = 0
|
||||
|
||||
yield user_clk.posedge
|
||||
|
||||
@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
|
||||
|
||||
cur_tag = 1
|
||||
|
||||
max_read_request_size.next = 2
|
||||
|
||||
enable.next = 1
|
||||
|
||||
yield user_clk.posedge
|
||||
print("test 1: enumeration")
|
||||
current_test.next = 1
|
||||
|
||||
yield rc.enumerate(enable_bus_mastering=True)
|
||||
|
||||
yield delay(100)
|
||||
|
||||
yield user_clk.posedge
|
||||
print("test 2: PCIe read")
|
||||
current_test.next = 2
|
||||
|
||||
pcie_addr = 0x00000000
|
||||
axi_addr = 0x00000000
|
||||
test_data = b'\x11\x22\x33\x44'
|
||||
|
||||
mem_data[pcie_addr:pcie_addr+len(test_data)] = test_data
|
||||
|
||||
data = mem_data[pcie_addr:pcie_addr+32]
|
||||
for i in range(0, len(data), 16):
|
||||
print(" ".join(("{:02x}".format(c) for c in bytearray(data[i:i+16]))))
|
||||
|
||||
read_desc_source.send([(pcie_addr, axi_addr, len(test_data), cur_tag)])
|
||||
|
||||
yield read_desc_status_sink.wait(2000)
|
||||
|
||||
yield delay(50)
|
||||
|
||||
status = read_desc_status_sink.recv()
|
||||
|
||||
print(status)
|
||||
|
||||
data = axi_ram_inst.read_mem(axi_addr, 32)
|
||||
for i in range(0, len(data), 16):
|
||||
print(" ".join(("{:02x}".format(c) for c in bytearray(data[i:i+16]))))
|
||||
|
||||
assert axi_ram_inst.read_mem(axi_addr, len(test_data)) == test_data
|
||||
|
||||
cur_tag = (cur_tag + 1) % 256
|
||||
|
||||
yield delay(100)
|
||||
|
||||
yield user_clk.posedge
|
||||
print("test 3: various reads")
|
||||
current_test.next = 3
|
||||
|
||||
for length in list(range(1,19))+list(range(128-4,128+4))+[1024]:
|
||||
for pcie_offset in list(range(8,13))+list(range(4096-4,4096+4)):
|
||||
for axi_offset in list(range(8,25))+list(range(4096-16,4096)):
|
||||
for pause in [False, True]:
|
||||
print("length %d, pcie_offset %d, axi_offset %d"% (length, pcie_offset, axi_offset))
|
||||
#pcie_addr = length * 0x100000000 + pcie_offset * 0x10000 + offset
|
||||
pcie_addr = pcie_offset
|
||||
axi_addr = axi_offset
|
||||
test_data = bytearray([x%256 for x in range(length)])
|
||||
|
||||
mem_data[pcie_addr:pcie_addr+len(test_data)] = test_data
|
||||
|
||||
data = mem_data[pcie_addr&0xffff80:(pcie_addr&0xffff80)+64]
|
||||
for i in range(0, len(data), 16):
|
||||
print(" ".join(("{:02x}".format(c) for c in bytearray(data[i:i+16]))))
|
||||
|
||||
axi_ram_inst.write_mem(axi_addr & 0xffff80, b'\xaa'*(len(test_data)+256))
|
||||
|
||||
rq_pause_toggle.next = pause
|
||||
rc_pause_toggle.next = pause
|
||||
|
||||
read_desc_source.send([(pcie_addr, axi_addr, len(test_data), cur_tag)])
|
||||
|
||||
yield read_desc_status_sink.wait(2000)
|
||||
|
||||
rq_pause_toggle.next = 0
|
||||
rc_pause_toggle.next = 0
|
||||
|
||||
status = read_desc_status_sink.recv()
|
||||
|
||||
print(status)
|
||||
|
||||
data = axi_ram_inst.read_mem(axi_addr&0xfffff0, 64)
|
||||
for i in range(0, len(data), 16):
|
||||
print(" ".join(("{:02x}".format(c) for c in bytearray(data[i:i+16]))))
|
||||
|
||||
assert axi_ram_inst.read_mem(axi_addr-8, len(test_data)+16) == b'\xaa'*8+test_data+b'\xaa'*8
|
||||
|
||||
cur_tag = (cur_tag + 1) % 256
|
||||
|
||||
yield delay(50)
|
||||
|
||||
raise StopSimulation
|
||||
|
||||
return instances()
|
||||
|
||||
def test_bench():
|
||||
sim = Simulation(bench())
|
||||
sim.run()
|
||||
|
||||
if __name__ == '__main__':
|
||||
print("Running test...")
|
||||
test_bench()
|
238
fpga/lib/pcie/tb/test_pcie_us_axi_dma_rd_128.v
Normal file
238
fpga/lib/pcie/tb/test_pcie_us_axi_dma_rd_128.v
Normal file
@ -0,0 +1,238 @@
|
||||
/*
|
||||
|
||||
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 pcie_us_axi_dma_rd
|
||||
*/
|
||||
module test_pcie_us_axi_dma_rd_128;
|
||||
|
||||
// Parameters
|
||||
parameter AXIS_PCIE_DATA_WIDTH = 128;
|
||||
parameter AXIS_PCIE_KEEP_WIDTH = (AXIS_PCIE_DATA_WIDTH/32);
|
||||
parameter AXI_DATA_WIDTH = AXIS_PCIE_DATA_WIDTH;
|
||||
parameter AXI_ADDR_WIDTH = 64;
|
||||
parameter AXI_STRB_WIDTH = (AXI_DATA_WIDTH/8);
|
||||
parameter AXI_ID_WIDTH = 8;
|
||||
parameter AXI_MAX_BURST_LEN = 256;
|
||||
parameter PCIE_ADDR_WIDTH = 64;
|
||||
parameter PCIE_CLIENT_TAG = 1;
|
||||
parameter PCIE_TAG_WIDTH = 8;
|
||||
parameter PCIE_TAG_COUNT = 256;
|
||||
parameter PCIE_EXT_TAG_ENABLE = 1;
|
||||
parameter LEN_WIDTH = 20;
|
||||
parameter TAG_WIDTH = 8;
|
||||
|
||||
// Inputs
|
||||
reg clk = 0;
|
||||
reg rst = 0;
|
||||
reg [7:0] current_test = 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_tvalid = 0;
|
||||
reg s_axis_rc_tlast = 0;
|
||||
reg [74:0] s_axis_rc_tuser = 0;
|
||||
reg m_axis_rq_tready = 0;
|
||||
reg [PCIE_TAG_WIDTH-1:0] s_axis_pcie_rq_tag = 0;
|
||||
reg s_axis_pcie_rq_tag_valid = 0;
|
||||
reg [PCIE_ADDR_WIDTH-1:0] s_axis_read_desc_pcie_addr = 0;
|
||||
reg [AXI_ADDR_WIDTH-1:0] s_axis_read_desc_axi_addr = 0;
|
||||
reg [LEN_WIDTH-1:0] s_axis_read_desc_len = 0;
|
||||
reg [TAG_WIDTH-1:0] s_axis_read_desc_tag = 0;
|
||||
reg s_axis_read_desc_valid = 0;
|
||||
reg m_axi_awready = 0;
|
||||
reg m_axi_wready = 0;
|
||||
reg [AXI_ID_WIDTH-1:0] m_axi_bid = 0;
|
||||
reg [1:0] m_axi_bresp = 0;
|
||||
reg m_axi_bvalid = 0;
|
||||
reg enable = 0;
|
||||
reg ext_tag_enable = 0;
|
||||
reg [15:0] requester_id = 0;
|
||||
reg requester_id_enable = 0;
|
||||
reg [2:0] max_read_request_size = 0;
|
||||
|
||||
// Outputs
|
||||
wire s_axis_rc_tready;
|
||||
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_tvalid;
|
||||
wire m_axis_rq_tlast;
|
||||
wire [59:0] m_axis_rq_tuser;
|
||||
wire s_axis_read_desc_ready;
|
||||
wire [TAG_WIDTH-1:0] m_axis_read_desc_status_tag;
|
||||
wire m_axis_read_desc_status_valid;
|
||||
wire [AXI_ID_WIDTH-1:0] m_axi_awid;
|
||||
wire [AXI_ADDR_WIDTH-1:0] m_axi_awaddr;
|
||||
wire [7:0] m_axi_awlen;
|
||||
wire [2:0] m_axi_awsize;
|
||||
wire [1:0] m_axi_awburst;
|
||||
wire m_axi_awlock;
|
||||
wire [3:0] m_axi_awcache;
|
||||
wire [2:0] m_axi_awprot;
|
||||
wire m_axi_awvalid;
|
||||
wire [AXI_DATA_WIDTH-1:0] m_axi_wdata;
|
||||
wire [AXI_STRB_WIDTH-1:0] m_axi_wstrb;
|
||||
wire m_axi_wlast;
|
||||
wire m_axi_wvalid;
|
||||
wire m_axi_bready;
|
||||
wire status_error_cor;
|
||||
wire status_error_uncor;
|
||||
|
||||
initial begin
|
||||
// myhdl integration
|
||||
$from_myhdl(
|
||||
clk,
|
||||
rst,
|
||||
current_test,
|
||||
s_axis_rc_tdata,
|
||||
s_axis_rc_tkeep,
|
||||
s_axis_rc_tvalid,
|
||||
s_axis_rc_tlast,
|
||||
s_axis_rc_tuser,
|
||||
m_axis_rq_tready,
|
||||
s_axis_pcie_rq_tag,
|
||||
s_axis_pcie_rq_tag_valid,
|
||||
s_axis_read_desc_pcie_addr,
|
||||
s_axis_read_desc_axi_addr,
|
||||
s_axis_read_desc_len,
|
||||
s_axis_read_desc_tag,
|
||||
s_axis_read_desc_valid,
|
||||
m_axi_awready,
|
||||
m_axi_wready,
|
||||
m_axi_bid,
|
||||
m_axi_bresp,
|
||||
m_axi_bvalid,
|
||||
enable,
|
||||
ext_tag_enable,
|
||||
requester_id,
|
||||
requester_id_enable,
|
||||
max_read_request_size
|
||||
);
|
||||
$to_myhdl(
|
||||
s_axis_rc_tready,
|
||||
m_axis_rq_tdata,
|
||||
m_axis_rq_tkeep,
|
||||
m_axis_rq_tvalid,
|
||||
m_axis_rq_tlast,
|
||||
m_axis_rq_tuser,
|
||||
s_axis_read_desc_ready,
|
||||
m_axis_read_desc_status_tag,
|
||||
m_axis_read_desc_status_valid,
|
||||
m_axi_awid,
|
||||
m_axi_awaddr,
|
||||
m_axi_awlen,
|
||||
m_axi_awsize,
|
||||
m_axi_awburst,
|
||||
m_axi_awlock,
|
||||
m_axi_awcache,
|
||||
m_axi_awprot,
|
||||
m_axi_awvalid,
|
||||
m_axi_wdata,
|
||||
m_axi_wstrb,
|
||||
m_axi_wlast,
|
||||
m_axi_wvalid,
|
||||
m_axi_bready,
|
||||
status_error_cor,
|
||||
status_error_uncor
|
||||
);
|
||||
|
||||
// dump file
|
||||
$dumpfile("test_pcie_us_axi_dma_rd_128.lxt");
|
||||
$dumpvars(0, test_pcie_us_axi_dma_rd_128);
|
||||
end
|
||||
|
||||
pcie_us_axi_dma_rd #(
|
||||
.AXIS_PCIE_DATA_WIDTH(AXIS_PCIE_DATA_WIDTH),
|
||||
.AXIS_PCIE_KEEP_WIDTH(AXIS_PCIE_KEEP_WIDTH),
|
||||
.AXI_DATA_WIDTH(AXI_DATA_WIDTH),
|
||||
.AXI_ADDR_WIDTH(AXI_ADDR_WIDTH),
|
||||
.AXI_STRB_WIDTH(AXI_STRB_WIDTH),
|
||||
.AXI_ID_WIDTH(AXI_ID_WIDTH),
|
||||
.AXI_MAX_BURST_LEN(AXI_MAX_BURST_LEN),
|
||||
.PCIE_ADDR_WIDTH(PCIE_ADDR_WIDTH),
|
||||
.PCIE_CLIENT_TAG(PCIE_CLIENT_TAG),
|
||||
.PCIE_TAG_WIDTH(PCIE_TAG_WIDTH),
|
||||
.PCIE_TAG_COUNT(PCIE_TAG_COUNT),
|
||||
.PCIE_EXT_TAG_ENABLE(PCIE_EXT_TAG_ENABLE),
|
||||
.LEN_WIDTH(LEN_WIDTH),
|
||||
.TAG_WIDTH(TAG_WIDTH)
|
||||
)
|
||||
UUT (
|
||||
.clk(clk),
|
||||
.rst(rst),
|
||||
.s_axis_rc_tdata(s_axis_rc_tdata),
|
||||
.s_axis_rc_tkeep(s_axis_rc_tkeep),
|
||||
.s_axis_rc_tvalid(s_axis_rc_tvalid),
|
||||
.s_axis_rc_tready(s_axis_rc_tready),
|
||||
.s_axis_rc_tlast(s_axis_rc_tlast),
|
||||
.s_axis_rc_tuser(s_axis_rc_tuser),
|
||||
.m_axis_rq_tdata(m_axis_rq_tdata),
|
||||
.m_axis_rq_tkeep(m_axis_rq_tkeep),
|
||||
.m_axis_rq_tvalid(m_axis_rq_tvalid),
|
||||
.m_axis_rq_tready(m_axis_rq_tready),
|
||||
.m_axis_rq_tlast(m_axis_rq_tlast),
|
||||
.m_axis_rq_tuser(m_axis_rq_tuser),
|
||||
.s_axis_pcie_rq_tag(s_axis_pcie_rq_tag),
|
||||
.s_axis_pcie_rq_tag_valid(s_axis_pcie_rq_tag_valid),
|
||||
.s_axis_read_desc_pcie_addr(s_axis_read_desc_pcie_addr),
|
||||
.s_axis_read_desc_axi_addr(s_axis_read_desc_axi_addr),
|
||||
.s_axis_read_desc_len(s_axis_read_desc_len),
|
||||
.s_axis_read_desc_tag(s_axis_read_desc_tag),
|
||||
.s_axis_read_desc_valid(s_axis_read_desc_valid),
|
||||
.s_axis_read_desc_ready(s_axis_read_desc_ready),
|
||||
.m_axis_read_desc_status_tag(m_axis_read_desc_status_tag),
|
||||
.m_axis_read_desc_status_valid(m_axis_read_desc_status_valid),
|
||||
.m_axi_awid(m_axi_awid),
|
||||
.m_axi_awaddr(m_axi_awaddr),
|
||||
.m_axi_awlen(m_axi_awlen),
|
||||
.m_axi_awsize(m_axi_awsize),
|
||||
.m_axi_awburst(m_axi_awburst),
|
||||
.m_axi_awlock(m_axi_awlock),
|
||||
.m_axi_awcache(m_axi_awcache),
|
||||
.m_axi_awprot(m_axi_awprot),
|
||||
.m_axi_awvalid(m_axi_awvalid),
|
||||
.m_axi_awready(m_axi_awready),
|
||||
.m_axi_wdata(m_axi_wdata),
|
||||
.m_axi_wstrb(m_axi_wstrb),
|
||||
.m_axi_wlast(m_axi_wlast),
|
||||
.m_axi_wvalid(m_axi_wvalid),
|
||||
.m_axi_wready(m_axi_wready),
|
||||
.m_axi_bid(m_axi_bid),
|
||||
.m_axi_bresp(m_axi_bresp),
|
||||
.m_axi_bvalid(m_axi_bvalid),
|
||||
.m_axi_bready(m_axi_bready),
|
||||
.enable(enable),
|
||||
.ext_tag_enable(ext_tag_enable),
|
||||
.requester_id(requester_id),
|
||||
.requester_id_enable(requester_id_enable),
|
||||
.max_read_request_size(max_read_request_size),
|
||||
.status_error_cor(status_error_cor),
|
||||
.status_error_uncor(status_error_uncor)
|
||||
);
|
||||
|
||||
endmodule
|
496
fpga/lib/pcie/tb/test_pcie_us_axi_dma_rd_256.py
Executable file
496
fpga/lib/pcie/tb/test_pcie_us_axi_dma_rd_256.py
Executable file
@ -0,0 +1,496 @@
|
||||
#!/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_us
|
||||
import axi
|
||||
import axis_ep
|
||||
|
||||
module = 'pcie_us_axi_dma_rd'
|
||||
testbench = 'test_%s_256' % module
|
||||
|
||||
srcs = []
|
||||
|
||||
srcs.append("../rtl/%s.v" % module)
|
||||
srcs.append("../rtl/pcie_tag_manager.v")
|
||||
srcs.append("../rtl/priority_encoder.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 = 256
|
||||
AXIS_PCIE_KEEP_WIDTH = (AXIS_PCIE_DATA_WIDTH/32)
|
||||
AXI_DATA_WIDTH = AXIS_PCIE_DATA_WIDTH
|
||||
AXI_ADDR_WIDTH = 64
|
||||
AXI_STRB_WIDTH = (AXI_DATA_WIDTH/8)
|
||||
AXI_ID_WIDTH = 8
|
||||
AXI_MAX_BURST_LEN = 256
|
||||
PCIE_ADDR_WIDTH = 64
|
||||
PCIE_CLIENT_TAG = 1
|
||||
PCIE_TAG_WIDTH = 8
|
||||
PCIE_TAG_COUNT = 256
|
||||
PCIE_EXT_TAG_ENABLE = 1
|
||||
LEN_WIDTH = 20
|
||||
TAG_WIDTH = 8
|
||||
|
||||
# Inputs
|
||||
clk = Signal(bool(0))
|
||||
rst = Signal(bool(0))
|
||||
current_test = Signal(intbv(0)[8:])
|
||||
|
||||
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_tvalid = Signal(bool(0))
|
||||
s_axis_rc_tlast = Signal(bool(0))
|
||||
s_axis_rc_tuser = Signal(intbv(0)[75:])
|
||||
m_axis_rq_tready = Signal(bool(0))
|
||||
s_axis_pcie_rq_tag = Signal(intbv(0)[PCIE_TAG_WIDTH:])
|
||||
s_axis_pcie_rq_tag_valid = Signal(bool(0))
|
||||
s_axis_read_desc_pcie_addr = Signal(intbv(0)[PCIE_ADDR_WIDTH:])
|
||||
s_axis_read_desc_axi_addr = Signal(intbv(0)[AXI_ADDR_WIDTH:])
|
||||
s_axis_read_desc_len = Signal(intbv(0)[LEN_WIDTH:])
|
||||
s_axis_read_desc_tag = Signal(intbv(0)[TAG_WIDTH:])
|
||||
s_axis_read_desc_valid = Signal(bool(0))
|
||||
m_axi_awready = Signal(bool(0))
|
||||
m_axi_wready = Signal(bool(0))
|
||||
m_axi_bid = Signal(intbv(0)[AXI_ID_WIDTH:])
|
||||
m_axi_bresp = Signal(intbv(0)[2:])
|
||||
m_axi_bvalid = Signal(bool(0))
|
||||
enable = Signal(bool(0))
|
||||
ext_tag_enable = Signal(bool(0))
|
||||
requester_id = Signal(intbv(0)[16:])
|
||||
requester_id_enable = Signal(bool(0))
|
||||
max_read_request_size = Signal(intbv(0)[3:])
|
||||
|
||||
# Outputs
|
||||
s_axis_rc_tready = Signal(bool(0))
|
||||
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_tvalid = Signal(bool(0))
|
||||
m_axis_rq_tlast = Signal(bool(0))
|
||||
m_axis_rq_tuser = Signal(intbv(0)[60:])
|
||||
s_axis_read_desc_ready = Signal(bool(0))
|
||||
m_axis_read_desc_status_tag = Signal(intbv(0)[TAG_WIDTH:])
|
||||
m_axis_read_desc_status_valid = Signal(bool(0))
|
||||
m_axi_awid = Signal(intbv(0)[AXI_ID_WIDTH:])
|
||||
m_axi_awaddr = Signal(intbv(0)[AXI_ADDR_WIDTH:])
|
||||
m_axi_awlen = Signal(intbv(0)[8:])
|
||||
m_axi_awsize = Signal(intbv(5)[3:])
|
||||
m_axi_awburst = Signal(intbv(1)[2:])
|
||||
m_axi_awlock = Signal(bool(0))
|
||||
m_axi_awcache = Signal(intbv(3)[4:])
|
||||
m_axi_awprot = Signal(intbv(2)[3:])
|
||||
m_axi_awvalid = Signal(bool(0))
|
||||
m_axi_wdata = Signal(intbv(0)[AXI_DATA_WIDTH:])
|
||||
m_axi_wstrb = Signal(intbv(0)[AXI_STRB_WIDTH:])
|
||||
m_axi_wlast = Signal(bool(0))
|
||||
m_axi_wvalid = Signal(bool(0))
|
||||
m_axi_bready = Signal(bool(0))
|
||||
status_error_cor = Signal(bool(0))
|
||||
status_error_uncor = Signal(bool(0))
|
||||
|
||||
# Clock and Reset Interface
|
||||
user_clk=Signal(bool(0))
|
||||
user_reset=Signal(bool(0))
|
||||
sys_clk=Signal(bool(0))
|
||||
sys_reset=Signal(bool(0))
|
||||
|
||||
# AXI4 RAM model
|
||||
axi_ram_inst = axi.AXIRam(2**16)
|
||||
|
||||
axi_ram_port0 = axi_ram_inst.create_port(
|
||||
user_clk,
|
||||
s_axi_awid=m_axi_awid,
|
||||
s_axi_awaddr=m_axi_awaddr,
|
||||
s_axi_awlen=m_axi_awlen,
|
||||
s_axi_awsize=m_axi_awsize,
|
||||
s_axi_awburst=m_axi_awburst,
|
||||
s_axi_awlock=m_axi_awlock,
|
||||
s_axi_awcache=m_axi_awcache,
|
||||
s_axi_awprot=m_axi_awprot,
|
||||
s_axi_awvalid=m_axi_awvalid,
|
||||
s_axi_awready=m_axi_awready,
|
||||
s_axi_wdata=m_axi_wdata,
|
||||
s_axi_wstrb=m_axi_wstrb,
|
||||
s_axi_wlast=m_axi_wlast,
|
||||
s_axi_wvalid=m_axi_wvalid,
|
||||
s_axi_wready=m_axi_wready,
|
||||
s_axi_bid=m_axi_bid,
|
||||
s_axi_bresp=m_axi_bresp,
|
||||
s_axi_bvalid=m_axi_bvalid,
|
||||
s_axi_bready=m_axi_bready,
|
||||
name='port0'
|
||||
)
|
||||
|
||||
# sources and sinks
|
||||
read_desc_source = axis_ep.AXIStreamSource()
|
||||
|
||||
read_desc_source_logic = read_desc_source.create_logic(
|
||||
user_clk,
|
||||
user_reset,
|
||||
tdata=(s_axis_read_desc_pcie_addr, s_axis_read_desc_axi_addr, s_axis_read_desc_len, s_axis_read_desc_tag),
|
||||
tvalid=s_axis_read_desc_valid,
|
||||
tready=s_axis_read_desc_ready,
|
||||
name='read_desc_source'
|
||||
)
|
||||
|
||||
read_desc_status_sink = axis_ep.AXIStreamSink()
|
||||
|
||||
read_desc_status_sink_logic = read_desc_status_sink.create_logic(
|
||||
user_clk,
|
||||
user_reset,
|
||||
tdata=(m_axis_read_desc_status_tag,),
|
||||
tvalid=m_axis_read_desc_status_valid,
|
||||
name='read_desc_status_sink'
|
||||
)
|
||||
|
||||
# PCIe devices
|
||||
rc = pcie.RootComplex()
|
||||
|
||||
mem_base, mem_data = rc.alloc_region(16*1024*1024)
|
||||
|
||||
dev = pcie_us.UltrascalePCIe()
|
||||
|
||||
dev.pcie_generation = 3
|
||||
dev.pcie_link_width = 8
|
||||
dev.user_clock_frequency = 256e6
|
||||
|
||||
rc.make_port().connect(dev)
|
||||
|
||||
cq_pause = Signal(bool(0))
|
||||
cc_pause = Signal(bool(0))
|
||||
rq_pause = Signal(bool(0))
|
||||
rc_pause = Signal(bool(0))
|
||||
|
||||
pcie_logic = dev.create_logic(
|
||||
# Completer reQuest Interface
|
||||
m_axis_cq_tdata=Signal(intbv(0)[AXIS_PCIE_DATA_WIDTH:]),
|
||||
m_axis_cq_tuser=Signal(intbv(0)[85:]),
|
||||
m_axis_cq_tlast=Signal(bool(0)),
|
||||
m_axis_cq_tkeep=Signal(intbv(0)[AXIS_PCIE_KEEP_WIDTH:]),
|
||||
m_axis_cq_tvalid=Signal(bool(0)),
|
||||
m_axis_cq_tready=Signal(bool(1)),
|
||||
pcie_cq_np_req=Signal(bool(1)),
|
||||
pcie_cq_np_req_count=Signal(intbv(0)[6:]),
|
||||
|
||||
# Completer Completion Interface
|
||||
s_axis_cc_tdata=Signal(intbv(0)[AXIS_PCIE_DATA_WIDTH:]),
|
||||
s_axis_cc_tuser=Signal(intbv(0)[33:]),
|
||||
s_axis_cc_tlast=Signal(bool(0)),
|
||||
s_axis_cc_tkeep=Signal(intbv(0)[AXIS_PCIE_KEEP_WIDTH:]),
|
||||
s_axis_cc_tvalid=Signal(bool(0)),
|
||||
s_axis_cc_tready=Signal(bool(0)),
|
||||
|
||||
# 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_num=pcie_rq_seq_num,
|
||||
# pcie_rq_seq_num_vld=pcie_rq_seq_num_vld,
|
||||
# pcie_rq_tag=pcie_rq_tag,
|
||||
# pcie_rq_tag_av=pcie_rq_tag_av,
|
||||
# pcie_rq_tag_vld=pcie_rq_tag_vld,
|
||||
|
||||
# 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 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_per_function_update_done=cfg_per_function_update_done,
|
||||
# cfg_per_function_number=cfg_per_function_number,
|
||||
# cfg_per_function_output_request=cfg_per_function_output_request,
|
||||
# cfg_dsn=cfg_dsn,
|
||||
# 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=cfg_err_cor_in,
|
||||
# cfg_err_uncor_in=cfg_err_uncor_in,
|
||||
# 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,
|
||||
|
||||
# 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,
|
||||
|
||||
cq_pause=cq_pause,
|
||||
cc_pause=cc_pause,
|
||||
rq_pause=rq_pause,
|
||||
rc_pause=rc_pause
|
||||
)
|
||||
|
||||
# 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,
|
||||
s_axis_rc_tdata=s_axis_rc_tdata,
|
||||
s_axis_rc_tkeep=s_axis_rc_tkeep,
|
||||
s_axis_rc_tvalid=s_axis_rc_tvalid,
|
||||
s_axis_rc_tready=s_axis_rc_tready,
|
||||
s_axis_rc_tlast=s_axis_rc_tlast,
|
||||
s_axis_rc_tuser=s_axis_rc_tuser,
|
||||
m_axis_rq_tdata=m_axis_rq_tdata,
|
||||
m_axis_rq_tkeep=m_axis_rq_tkeep,
|
||||
m_axis_rq_tvalid=m_axis_rq_tvalid,
|
||||
m_axis_rq_tready=m_axis_rq_tready,
|
||||
m_axis_rq_tlast=m_axis_rq_tlast,
|
||||
m_axis_rq_tuser=m_axis_rq_tuser,
|
||||
s_axis_pcie_rq_tag=s_axis_pcie_rq_tag,
|
||||
s_axis_pcie_rq_tag_valid=s_axis_pcie_rq_tag_valid,
|
||||
s_axis_read_desc_pcie_addr=s_axis_read_desc_pcie_addr,
|
||||
s_axis_read_desc_axi_addr=s_axis_read_desc_axi_addr,
|
||||
s_axis_read_desc_len=s_axis_read_desc_len,
|
||||
s_axis_read_desc_tag=s_axis_read_desc_tag,
|
||||
s_axis_read_desc_valid=s_axis_read_desc_valid,
|
||||
s_axis_read_desc_ready=s_axis_read_desc_ready,
|
||||
m_axis_read_desc_status_tag=m_axis_read_desc_status_tag,
|
||||
m_axis_read_desc_status_valid=m_axis_read_desc_status_valid,
|
||||
m_axi_awid=m_axi_awid,
|
||||
m_axi_awaddr=m_axi_awaddr,
|
||||
m_axi_awlen=m_axi_awlen,
|
||||
m_axi_awsize=m_axi_awsize,
|
||||
m_axi_awburst=m_axi_awburst,
|
||||
m_axi_awlock=m_axi_awlock,
|
||||
m_axi_awcache=m_axi_awcache,
|
||||
m_axi_awprot=m_axi_awprot,
|
||||
m_axi_awvalid=m_axi_awvalid,
|
||||
m_axi_awready=m_axi_awready,
|
||||
m_axi_wdata=m_axi_wdata,
|
||||
m_axi_wstrb=m_axi_wstrb,
|
||||
m_axi_wlast=m_axi_wlast,
|
||||
m_axi_wvalid=m_axi_wvalid,
|
||||
m_axi_wready=m_axi_wready,
|
||||
m_axi_bid=m_axi_bid,
|
||||
m_axi_bresp=m_axi_bresp,
|
||||
m_axi_bvalid=m_axi_bvalid,
|
||||
m_axi_bready=m_axi_bready,
|
||||
enable=enable,
|
||||
ext_tag_enable=ext_tag_enable,
|
||||
requester_id=requester_id,
|
||||
requester_id_enable=requester_id_enable,
|
||||
max_read_request_size=max_read_request_size,
|
||||
status_error_cor=status_error_cor,
|
||||
status_error_uncor=status_error_uncor
|
||||
)
|
||||
|
||||
@always(delay(4))
|
||||
def clkgen():
|
||||
clk.next = not clk
|
||||
|
||||
@always_comb
|
||||
def clk_logic():
|
||||
sys_clk.next = clk
|
||||
sys_reset.next = not rst
|
||||
|
||||
status_error_cor_asserted = Signal(bool(0))
|
||||
status_error_uncor_asserted = Signal(bool(0))
|
||||
|
||||
@always(clk.posedge)
|
||||
def monitor():
|
||||
if (status_error_cor):
|
||||
status_error_cor_asserted.next = 1
|
||||
if (status_error_uncor):
|
||||
status_error_uncor_asserted.next = 1
|
||||
|
||||
cq_pause_toggle = Signal(bool(0))
|
||||
cc_pause_toggle = Signal(bool(0))
|
||||
rq_pause_toggle = Signal(bool(0))
|
||||
rc_pause_toggle = Signal(bool(0))
|
||||
|
||||
@instance
|
||||
def pause_toggle():
|
||||
while True:
|
||||
if (cq_pause_toggle or cc_pause_toggle or rq_pause_toggle or rc_pause_toggle):
|
||||
cq_pause.next = cq_pause_toggle
|
||||
cc_pause.next = cc_pause_toggle
|
||||
rq_pause.next = rq_pause_toggle
|
||||
rc_pause.next = rc_pause_toggle
|
||||
|
||||
yield user_clk.posedge
|
||||
yield user_clk.posedge
|
||||
yield user_clk.posedge
|
||||
|
||||
cq_pause.next = 0
|
||||
cc_pause.next = 0
|
||||
rq_pause.next = 0
|
||||
rc_pause.next = 0
|
||||
|
||||
yield user_clk.posedge
|
||||
|
||||
@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
|
||||
|
||||
cur_tag = 1
|
||||
|
||||
max_read_request_size.next = 2
|
||||
|
||||
enable.next = 1
|
||||
|
||||
yield user_clk.posedge
|
||||
print("test 1: enumeration")
|
||||
current_test.next = 1
|
||||
|
||||
yield rc.enumerate(enable_bus_mastering=True)
|
||||
|
||||
yield delay(100)
|
||||
|
||||
yield user_clk.posedge
|
||||
print("test 2: PCIe read")
|
||||
current_test.next = 2
|
||||
|
||||
pcie_addr = 0x00000000
|
||||
axi_addr = 0x00000000
|
||||
test_data = b'\x11\x22\x33\x44'
|
||||
|
||||
mem_data[pcie_addr:pcie_addr+len(test_data)] = test_data
|
||||
|
||||
data = mem_data[pcie_addr:pcie_addr+32]
|
||||
for i in range(0, len(data), 16):
|
||||
print(" ".join(("{:02x}".format(c) for c in bytearray(data[i:i+16]))))
|
||||
|
||||
read_desc_source.send([(pcie_addr, axi_addr, len(test_data), cur_tag)])
|
||||
|
||||
yield read_desc_status_sink.wait(2000)
|
||||
|
||||
yield delay(50)
|
||||
|
||||
status = read_desc_status_sink.recv()
|
||||
|
||||
print(status)
|
||||
|
||||
data = axi_ram_inst.read_mem(axi_addr, 32)
|
||||
for i in range(0, len(data), 16):
|
||||
print(" ".join(("{:02x}".format(c) for c in bytearray(data[i:i+16]))))
|
||||
|
||||
assert axi_ram_inst.read_mem(axi_addr, len(test_data)) == test_data
|
||||
|
||||
cur_tag = (cur_tag + 1) % 256
|
||||
|
||||
yield delay(100)
|
||||
|
||||
yield user_clk.posedge
|
||||
print("test 3: various reads")
|
||||
current_test.next = 3
|
||||
|
||||
for length in list(range(1,35))+list(range(128-4,128+4))+[1024]:
|
||||
for pcie_offset in list(range(8,13))+list(range(4096-4,4096+4)):
|
||||
for axi_offset in list(range(8,41))+list(range(4096-32,4096)):
|
||||
for pause in [False, True]:
|
||||
print("length %d, pcie_offset %d, axi_offset %d"% (length, pcie_offset, axi_offset))
|
||||
#pcie_addr = length * 0x100000000 + pcie_offset * 0x10000 + offset
|
||||
pcie_addr = pcie_offset
|
||||
axi_addr = axi_offset
|
||||
test_data = bytearray([x%256 for x in range(length)])
|
||||
|
||||
mem_data[pcie_addr:pcie_addr+len(test_data)] = test_data
|
||||
|
||||
data = mem_data[pcie_addr&0xffff80:(pcie_addr&0xffff80)+64]
|
||||
for i in range(0, len(data), 16):
|
||||
print(" ".join(("{:02x}".format(c) for c in bytearray(data[i:i+16]))))
|
||||
|
||||
axi_ram_inst.write_mem(axi_addr & 0xffff80, b'\xaa'*(len(test_data)+256))
|
||||
|
||||
rq_pause_toggle.next = pause
|
||||
rc_pause_toggle.next = pause
|
||||
|
||||
read_desc_source.send([(pcie_addr, axi_addr, len(test_data), cur_tag)])
|
||||
|
||||
yield read_desc_status_sink.wait(2000)
|
||||
|
||||
rq_pause_toggle.next = 0
|
||||
rc_pause_toggle.next = 0
|
||||
|
||||
status = read_desc_status_sink.recv()
|
||||
|
||||
print(status)
|
||||
|
||||
data = axi_ram_inst.read_mem(axi_addr&0xfffff0, 64)
|
||||
for i in range(0, len(data), 16):
|
||||
print(" ".join(("{:02x}".format(c) for c in bytearray(data[i:i+16]))))
|
||||
|
||||
assert axi_ram_inst.read_mem(axi_addr-8, len(test_data)+16) == b'\xaa'*8+test_data+b'\xaa'*8
|
||||
|
||||
cur_tag = (cur_tag + 1) % 256
|
||||
|
||||
yield delay(50)
|
||||
|
||||
raise StopSimulation
|
||||
|
||||
return instances()
|
||||
|
||||
def test_bench():
|
||||
sim = Simulation(bench())
|
||||
sim.run()
|
||||
|
||||
if __name__ == '__main__':
|
||||
print("Running test...")
|
||||
test_bench()
|
238
fpga/lib/pcie/tb/test_pcie_us_axi_dma_rd_256.v
Normal file
238
fpga/lib/pcie/tb/test_pcie_us_axi_dma_rd_256.v
Normal file
@ -0,0 +1,238 @@
|
||||
/*
|
||||
|
||||
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 pcie_us_axi_dma_rd
|
||||
*/
|
||||
module test_pcie_us_axi_dma_rd_256;
|
||||
|
||||
// Parameters
|
||||
parameter AXIS_PCIE_DATA_WIDTH = 256;
|
||||
parameter AXIS_PCIE_KEEP_WIDTH = (AXIS_PCIE_DATA_WIDTH/32);
|
||||
parameter AXI_DATA_WIDTH = AXIS_PCIE_DATA_WIDTH;
|
||||
parameter AXI_ADDR_WIDTH = 64;
|
||||
parameter AXI_STRB_WIDTH = (AXI_DATA_WIDTH/8);
|
||||
parameter AXI_ID_WIDTH = 8;
|
||||
parameter AXI_MAX_BURST_LEN = 256;
|
||||
parameter PCIE_ADDR_WIDTH = 64;
|
||||
parameter PCIE_CLIENT_TAG = 1;
|
||||
parameter PCIE_TAG_WIDTH = 8;
|
||||
parameter PCIE_TAG_COUNT = 256;
|
||||
parameter PCIE_EXT_TAG_ENABLE = 1;
|
||||
parameter LEN_WIDTH = 20;
|
||||
parameter TAG_WIDTH = 8;
|
||||
|
||||
// Inputs
|
||||
reg clk = 0;
|
||||
reg rst = 0;
|
||||
reg [7:0] current_test = 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_tvalid = 0;
|
||||
reg s_axis_rc_tlast = 0;
|
||||
reg [74:0] s_axis_rc_tuser = 0;
|
||||
reg m_axis_rq_tready = 0;
|
||||
reg [PCIE_TAG_WIDTH-1:0] s_axis_pcie_rq_tag = 0;
|
||||
reg s_axis_pcie_rq_tag_valid = 0;
|
||||
reg [PCIE_ADDR_WIDTH-1:0] s_axis_read_desc_pcie_addr = 0;
|
||||
reg [AXI_ADDR_WIDTH-1:0] s_axis_read_desc_axi_addr = 0;
|
||||
reg [LEN_WIDTH-1:0] s_axis_read_desc_len = 0;
|
||||
reg [TAG_WIDTH-1:0] s_axis_read_desc_tag = 0;
|
||||
reg s_axis_read_desc_valid = 0;
|
||||
reg m_axi_awready = 0;
|
||||
reg m_axi_wready = 0;
|
||||
reg [AXI_ID_WIDTH-1:0] m_axi_bid = 0;
|
||||
reg [1:0] m_axi_bresp = 0;
|
||||
reg m_axi_bvalid = 0;
|
||||
reg enable = 0;
|
||||
reg ext_tag_enable = 0;
|
||||
reg [15:0] requester_id = 0;
|
||||
reg requester_id_enable = 0;
|
||||
reg [2:0] max_read_request_size = 0;
|
||||
|
||||
// Outputs
|
||||
wire s_axis_rc_tready;
|
||||
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_tvalid;
|
||||
wire m_axis_rq_tlast;
|
||||
wire [59:0] m_axis_rq_tuser;
|
||||
wire s_axis_read_desc_ready;
|
||||
wire [TAG_WIDTH-1:0] m_axis_read_desc_status_tag;
|
||||
wire m_axis_read_desc_status_valid;
|
||||
wire [AXI_ID_WIDTH-1:0] m_axi_awid;
|
||||
wire [AXI_ADDR_WIDTH-1:0] m_axi_awaddr;
|
||||
wire [7:0] m_axi_awlen;
|
||||
wire [2:0] m_axi_awsize;
|
||||
wire [1:0] m_axi_awburst;
|
||||
wire m_axi_awlock;
|
||||
wire [3:0] m_axi_awcache;
|
||||
wire [2:0] m_axi_awprot;
|
||||
wire m_axi_awvalid;
|
||||
wire [AXI_DATA_WIDTH-1:0] m_axi_wdata;
|
||||
wire [AXI_STRB_WIDTH-1:0] m_axi_wstrb;
|
||||
wire m_axi_wlast;
|
||||
wire m_axi_wvalid;
|
||||
wire m_axi_bready;
|
||||
wire status_error_cor;
|
||||
wire status_error_uncor;
|
||||
|
||||
initial begin
|
||||
// myhdl integration
|
||||
$from_myhdl(
|
||||
clk,
|
||||
rst,
|
||||
current_test,
|
||||
s_axis_rc_tdata,
|
||||
s_axis_rc_tkeep,
|
||||
s_axis_rc_tvalid,
|
||||
s_axis_rc_tlast,
|
||||
s_axis_rc_tuser,
|
||||
m_axis_rq_tready,
|
||||
s_axis_pcie_rq_tag,
|
||||
s_axis_pcie_rq_tag_valid,
|
||||
s_axis_read_desc_pcie_addr,
|
||||
s_axis_read_desc_axi_addr,
|
||||
s_axis_read_desc_len,
|
||||
s_axis_read_desc_tag,
|
||||
s_axis_read_desc_valid,
|
||||
m_axi_awready,
|
||||
m_axi_wready,
|
||||
m_axi_bid,
|
||||
m_axi_bresp,
|
||||
m_axi_bvalid,
|
||||
enable,
|
||||
ext_tag_enable,
|
||||
requester_id,
|
||||
requester_id_enable,
|
||||
max_read_request_size
|
||||
);
|
||||
$to_myhdl(
|
||||
s_axis_rc_tready,
|
||||
m_axis_rq_tdata,
|
||||
m_axis_rq_tkeep,
|
||||
m_axis_rq_tvalid,
|
||||
m_axis_rq_tlast,
|
||||
m_axis_rq_tuser,
|
||||
s_axis_read_desc_ready,
|
||||
m_axis_read_desc_status_tag,
|
||||
m_axis_read_desc_status_valid,
|
||||
m_axi_awid,
|
||||
m_axi_awaddr,
|
||||
m_axi_awlen,
|
||||
m_axi_awsize,
|
||||
m_axi_awburst,
|
||||
m_axi_awlock,
|
||||
m_axi_awcache,
|
||||
m_axi_awprot,
|
||||
m_axi_awvalid,
|
||||
m_axi_wdata,
|
||||
m_axi_wstrb,
|
||||
m_axi_wlast,
|
||||
m_axi_wvalid,
|
||||
m_axi_bready,
|
||||
status_error_cor,
|
||||
status_error_uncor
|
||||
);
|
||||
|
||||
// dump file
|
||||
$dumpfile("test_pcie_us_axi_dma_rd_256.lxt");
|
||||
$dumpvars(0, test_pcie_us_axi_dma_rd_256);
|
||||
end
|
||||
|
||||
pcie_us_axi_dma_rd #(
|
||||
.AXIS_PCIE_DATA_WIDTH(AXIS_PCIE_DATA_WIDTH),
|
||||
.AXIS_PCIE_KEEP_WIDTH(AXIS_PCIE_KEEP_WIDTH),
|
||||
.AXI_DATA_WIDTH(AXI_DATA_WIDTH),
|
||||
.AXI_ADDR_WIDTH(AXI_ADDR_WIDTH),
|
||||
.AXI_STRB_WIDTH(AXI_STRB_WIDTH),
|
||||
.AXI_ID_WIDTH(AXI_ID_WIDTH),
|
||||
.AXI_MAX_BURST_LEN(AXI_MAX_BURST_LEN),
|
||||
.PCIE_ADDR_WIDTH(PCIE_ADDR_WIDTH),
|
||||
.PCIE_CLIENT_TAG(PCIE_CLIENT_TAG),
|
||||
.PCIE_TAG_WIDTH(PCIE_TAG_WIDTH),
|
||||
.PCIE_TAG_COUNT(PCIE_TAG_COUNT),
|
||||
.PCIE_EXT_TAG_ENABLE(PCIE_EXT_TAG_ENABLE),
|
||||
.LEN_WIDTH(LEN_WIDTH),
|
||||
.TAG_WIDTH(TAG_WIDTH)
|
||||
)
|
||||
UUT (
|
||||
.clk(clk),
|
||||
.rst(rst),
|
||||
.s_axis_rc_tdata(s_axis_rc_tdata),
|
||||
.s_axis_rc_tkeep(s_axis_rc_tkeep),
|
||||
.s_axis_rc_tvalid(s_axis_rc_tvalid),
|
||||
.s_axis_rc_tready(s_axis_rc_tready),
|
||||
.s_axis_rc_tlast(s_axis_rc_tlast),
|
||||
.s_axis_rc_tuser(s_axis_rc_tuser),
|
||||
.m_axis_rq_tdata(m_axis_rq_tdata),
|
||||
.m_axis_rq_tkeep(m_axis_rq_tkeep),
|
||||
.m_axis_rq_tvalid(m_axis_rq_tvalid),
|
||||
.m_axis_rq_tready(m_axis_rq_tready),
|
||||
.m_axis_rq_tlast(m_axis_rq_tlast),
|
||||
.m_axis_rq_tuser(m_axis_rq_tuser),
|
||||
.s_axis_pcie_rq_tag(s_axis_pcie_rq_tag),
|
||||
.s_axis_pcie_rq_tag_valid(s_axis_pcie_rq_tag_valid),
|
||||
.s_axis_read_desc_pcie_addr(s_axis_read_desc_pcie_addr),
|
||||
.s_axis_read_desc_axi_addr(s_axis_read_desc_axi_addr),
|
||||
.s_axis_read_desc_len(s_axis_read_desc_len),
|
||||
.s_axis_read_desc_tag(s_axis_read_desc_tag),
|
||||
.s_axis_read_desc_valid(s_axis_read_desc_valid),
|
||||
.s_axis_read_desc_ready(s_axis_read_desc_ready),
|
||||
.m_axis_read_desc_status_tag(m_axis_read_desc_status_tag),
|
||||
.m_axis_read_desc_status_valid(m_axis_read_desc_status_valid),
|
||||
.m_axi_awid(m_axi_awid),
|
||||
.m_axi_awaddr(m_axi_awaddr),
|
||||
.m_axi_awlen(m_axi_awlen),
|
||||
.m_axi_awsize(m_axi_awsize),
|
||||
.m_axi_awburst(m_axi_awburst),
|
||||
.m_axi_awlock(m_axi_awlock),
|
||||
.m_axi_awcache(m_axi_awcache),
|
||||
.m_axi_awprot(m_axi_awprot),
|
||||
.m_axi_awvalid(m_axi_awvalid),
|
||||
.m_axi_awready(m_axi_awready),
|
||||
.m_axi_wdata(m_axi_wdata),
|
||||
.m_axi_wstrb(m_axi_wstrb),
|
||||
.m_axi_wlast(m_axi_wlast),
|
||||
.m_axi_wvalid(m_axi_wvalid),
|
||||
.m_axi_wready(m_axi_wready),
|
||||
.m_axi_bid(m_axi_bid),
|
||||
.m_axi_bresp(m_axi_bresp),
|
||||
.m_axi_bvalid(m_axi_bvalid),
|
||||
.m_axi_bready(m_axi_bready),
|
||||
.enable(enable),
|
||||
.ext_tag_enable(ext_tag_enable),
|
||||
.requester_id(requester_id),
|
||||
.requester_id_enable(requester_id_enable),
|
||||
.max_read_request_size(max_read_request_size),
|
||||
.status_error_cor(status_error_cor),
|
||||
.status_error_uncor(status_error_uncor)
|
||||
);
|
||||
|
||||
endmodule
|
496
fpga/lib/pcie/tb/test_pcie_us_axi_dma_rd_64.py
Executable file
496
fpga/lib/pcie/tb/test_pcie_us_axi_dma_rd_64.py
Executable file
@ -0,0 +1,496 @@
|
||||
#!/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_us
|
||||
import axi
|
||||
import axis_ep
|
||||
|
||||
module = 'pcie_us_axi_dma_rd'
|
||||
testbench = 'test_%s_64' % module
|
||||
|
||||
srcs = []
|
||||
|
||||
srcs.append("../rtl/%s.v" % module)
|
||||
srcs.append("../rtl/pcie_tag_manager.v")
|
||||
srcs.append("../rtl/priority_encoder.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 = 64
|
||||
AXIS_PCIE_KEEP_WIDTH = (AXIS_PCIE_DATA_WIDTH/32)
|
||||
AXI_DATA_WIDTH = AXIS_PCIE_DATA_WIDTH
|
||||
AXI_ADDR_WIDTH = 64
|
||||
AXI_STRB_WIDTH = (AXI_DATA_WIDTH/8)
|
||||
AXI_ID_WIDTH = 8
|
||||
AXI_MAX_BURST_LEN = 256
|
||||
PCIE_ADDR_WIDTH = 64
|
||||
PCIE_CLIENT_TAG = 1
|
||||
PCIE_TAG_WIDTH = 8
|
||||
PCIE_TAG_COUNT = 256
|
||||
PCIE_EXT_TAG_ENABLE = 1
|
||||
LEN_WIDTH = 20
|
||||
TAG_WIDTH = 8
|
||||
|
||||
# Inputs
|
||||
clk = Signal(bool(0))
|
||||
rst = Signal(bool(0))
|
||||
current_test = Signal(intbv(0)[8:])
|
||||
|
||||
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_tvalid = Signal(bool(0))
|
||||
s_axis_rc_tlast = Signal(bool(0))
|
||||
s_axis_rc_tuser = Signal(intbv(0)[75:])
|
||||
m_axis_rq_tready = Signal(bool(0))
|
||||
s_axis_pcie_rq_tag = Signal(intbv(0)[PCIE_TAG_WIDTH:])
|
||||
s_axis_pcie_rq_tag_valid = Signal(bool(0))
|
||||
s_axis_read_desc_pcie_addr = Signal(intbv(0)[PCIE_ADDR_WIDTH:])
|
||||
s_axis_read_desc_axi_addr = Signal(intbv(0)[AXI_ADDR_WIDTH:])
|
||||
s_axis_read_desc_len = Signal(intbv(0)[LEN_WIDTH:])
|
||||
s_axis_read_desc_tag = Signal(intbv(0)[TAG_WIDTH:])
|
||||
s_axis_read_desc_valid = Signal(bool(0))
|
||||
m_axi_awready = Signal(bool(0))
|
||||
m_axi_wready = Signal(bool(0))
|
||||
m_axi_bid = Signal(intbv(0)[AXI_ID_WIDTH:])
|
||||
m_axi_bresp = Signal(intbv(0)[2:])
|
||||
m_axi_bvalid = Signal(bool(0))
|
||||
enable = Signal(bool(0))
|
||||
ext_tag_enable = Signal(bool(0))
|
||||
requester_id = Signal(intbv(0)[16:])
|
||||
requester_id_enable = Signal(bool(0))
|
||||
max_read_request_size = Signal(intbv(0)[3:])
|
||||
|
||||
# Outputs
|
||||
s_axis_rc_tready = Signal(bool(0))
|
||||
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_tvalid = Signal(bool(0))
|
||||
m_axis_rq_tlast = Signal(bool(0))
|
||||
m_axis_rq_tuser = Signal(intbv(0)[60:])
|
||||
s_axis_read_desc_ready = Signal(bool(0))
|
||||
m_axis_read_desc_status_tag = Signal(intbv(0)[TAG_WIDTH:])
|
||||
m_axis_read_desc_status_valid = Signal(bool(0))
|
||||
m_axi_awid = Signal(intbv(0)[AXI_ID_WIDTH:])
|
||||
m_axi_awaddr = Signal(intbv(0)[AXI_ADDR_WIDTH:])
|
||||
m_axi_awlen = Signal(intbv(0)[8:])
|
||||
m_axi_awsize = Signal(intbv(3)[3:])
|
||||
m_axi_awburst = Signal(intbv(1)[2:])
|
||||
m_axi_awlock = Signal(bool(0))
|
||||
m_axi_awcache = Signal(intbv(3)[4:])
|
||||
m_axi_awprot = Signal(intbv(2)[3:])
|
||||
m_axi_awvalid = Signal(bool(0))
|
||||
m_axi_wdata = Signal(intbv(0)[AXI_DATA_WIDTH:])
|
||||
m_axi_wstrb = Signal(intbv(0)[AXI_STRB_WIDTH:])
|
||||
m_axi_wlast = Signal(bool(0))
|
||||
m_axi_wvalid = Signal(bool(0))
|
||||
m_axi_bready = Signal(bool(0))
|
||||
status_error_cor = Signal(bool(0))
|
||||
status_error_uncor = Signal(bool(0))
|
||||
|
||||
# Clock and Reset Interface
|
||||
user_clk=Signal(bool(0))
|
||||
user_reset=Signal(bool(0))
|
||||
sys_clk=Signal(bool(0))
|
||||
sys_reset=Signal(bool(0))
|
||||
|
||||
# AXI4 RAM model
|
||||
axi_ram_inst = axi.AXIRam(2**16)
|
||||
|
||||
axi_ram_port0 = axi_ram_inst.create_port(
|
||||
user_clk,
|
||||
s_axi_awid=m_axi_awid,
|
||||
s_axi_awaddr=m_axi_awaddr,
|
||||
s_axi_awlen=m_axi_awlen,
|
||||
s_axi_awsize=m_axi_awsize,
|
||||
s_axi_awburst=m_axi_awburst,
|
||||
s_axi_awlock=m_axi_awlock,
|
||||
s_axi_awcache=m_axi_awcache,
|
||||
s_axi_awprot=m_axi_awprot,
|
||||
s_axi_awvalid=m_axi_awvalid,
|
||||
s_axi_awready=m_axi_awready,
|
||||
s_axi_wdata=m_axi_wdata,
|
||||
s_axi_wstrb=m_axi_wstrb,
|
||||
s_axi_wlast=m_axi_wlast,
|
||||
s_axi_wvalid=m_axi_wvalid,
|
||||
s_axi_wready=m_axi_wready,
|
||||
s_axi_bid=m_axi_bid,
|
||||
s_axi_bresp=m_axi_bresp,
|
||||
s_axi_bvalid=m_axi_bvalid,
|
||||
s_axi_bready=m_axi_bready,
|
||||
name='port0'
|
||||
)
|
||||
|
||||
# sources and sinks
|
||||
read_desc_source = axis_ep.AXIStreamSource()
|
||||
|
||||
read_desc_source_logic = read_desc_source.create_logic(
|
||||
user_clk,
|
||||
user_reset,
|
||||
tdata=(s_axis_read_desc_pcie_addr, s_axis_read_desc_axi_addr, s_axis_read_desc_len, s_axis_read_desc_tag),
|
||||
tvalid=s_axis_read_desc_valid,
|
||||
tready=s_axis_read_desc_ready,
|
||||
name='read_desc_source'
|
||||
)
|
||||
|
||||
read_desc_status_sink = axis_ep.AXIStreamSink()
|
||||
|
||||
read_desc_status_sink_logic = read_desc_status_sink.create_logic(
|
||||
user_clk,
|
||||
user_reset,
|
||||
tdata=(m_axis_read_desc_status_tag,),
|
||||
tvalid=m_axis_read_desc_status_valid,
|
||||
name='read_desc_status_sink'
|
||||
)
|
||||
|
||||
# PCIe devices
|
||||
rc = pcie.RootComplex()
|
||||
|
||||
mem_base, mem_data = rc.alloc_region(16*1024*1024)
|
||||
|
||||
dev = pcie_us.UltrascalePCIe()
|
||||
|
||||
dev.pcie_generation = 3
|
||||
dev.pcie_link_width = 2
|
||||
dev.user_clock_frequency = 256e6
|
||||
|
||||
rc.make_port().connect(dev)
|
||||
|
||||
cq_pause = Signal(bool(0))
|
||||
cc_pause = Signal(bool(0))
|
||||
rq_pause = Signal(bool(0))
|
||||
rc_pause = Signal(bool(0))
|
||||
|
||||
pcie_logic = dev.create_logic(
|
||||
# Completer reQuest Interface
|
||||
m_axis_cq_tdata=Signal(intbv(0)[AXIS_PCIE_DATA_WIDTH:]),
|
||||
m_axis_cq_tuser=Signal(intbv(0)[85:]),
|
||||
m_axis_cq_tlast=Signal(bool(0)),
|
||||
m_axis_cq_tkeep=Signal(intbv(0)[AXIS_PCIE_KEEP_WIDTH:]),
|
||||
m_axis_cq_tvalid=Signal(bool(0)),
|
||||
m_axis_cq_tready=Signal(bool(1)),
|
||||
pcie_cq_np_req=Signal(bool(1)),
|
||||
pcie_cq_np_req_count=Signal(intbv(0)[6:]),
|
||||
|
||||
# Completer Completion Interface
|
||||
s_axis_cc_tdata=Signal(intbv(0)[AXIS_PCIE_DATA_WIDTH:]),
|
||||
s_axis_cc_tuser=Signal(intbv(0)[33:]),
|
||||
s_axis_cc_tlast=Signal(bool(0)),
|
||||
s_axis_cc_tkeep=Signal(intbv(0)[AXIS_PCIE_KEEP_WIDTH:]),
|
||||
s_axis_cc_tvalid=Signal(bool(0)),
|
||||
s_axis_cc_tready=Signal(bool(0)),
|
||||
|
||||
# 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_num=pcie_rq_seq_num,
|
||||
# pcie_rq_seq_num_vld=pcie_rq_seq_num_vld,
|
||||
# pcie_rq_tag=pcie_rq_tag,
|
||||
# pcie_rq_tag_av=pcie_rq_tag_av,
|
||||
# pcie_rq_tag_vld=pcie_rq_tag_vld,
|
||||
|
||||
# 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 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_per_function_update_done=cfg_per_function_update_done,
|
||||
# cfg_per_function_number=cfg_per_function_number,
|
||||
# cfg_per_function_output_request=cfg_per_function_output_request,
|
||||
# cfg_dsn=cfg_dsn,
|
||||
# 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=cfg_err_cor_in,
|
||||
# cfg_err_uncor_in=cfg_err_uncor_in,
|
||||
# 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,
|
||||
|
||||
# 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,
|
||||
|
||||
cq_pause=cq_pause,
|
||||
cc_pause=cc_pause,
|
||||
rq_pause=rq_pause,
|
||||
rc_pause=rc_pause
|
||||
)
|
||||
|
||||
# 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,
|
||||
s_axis_rc_tdata=s_axis_rc_tdata,
|
||||
s_axis_rc_tkeep=s_axis_rc_tkeep,
|
||||
s_axis_rc_tvalid=s_axis_rc_tvalid,
|
||||
s_axis_rc_tready=s_axis_rc_tready,
|
||||
s_axis_rc_tlast=s_axis_rc_tlast,
|
||||
s_axis_rc_tuser=s_axis_rc_tuser,
|
||||
m_axis_rq_tdata=m_axis_rq_tdata,
|
||||
m_axis_rq_tkeep=m_axis_rq_tkeep,
|
||||
m_axis_rq_tvalid=m_axis_rq_tvalid,
|
||||
m_axis_rq_tready=m_axis_rq_tready,
|
||||
m_axis_rq_tlast=m_axis_rq_tlast,
|
||||
m_axis_rq_tuser=m_axis_rq_tuser,
|
||||
s_axis_pcie_rq_tag=s_axis_pcie_rq_tag,
|
||||
s_axis_pcie_rq_tag_valid=s_axis_pcie_rq_tag_valid,
|
||||
s_axis_read_desc_pcie_addr=s_axis_read_desc_pcie_addr,
|
||||
s_axis_read_desc_axi_addr=s_axis_read_desc_axi_addr,
|
||||
s_axis_read_desc_len=s_axis_read_desc_len,
|
||||
s_axis_read_desc_tag=s_axis_read_desc_tag,
|
||||
s_axis_read_desc_valid=s_axis_read_desc_valid,
|
||||
s_axis_read_desc_ready=s_axis_read_desc_ready,
|
||||
m_axis_read_desc_status_tag=m_axis_read_desc_status_tag,
|
||||
m_axis_read_desc_status_valid=m_axis_read_desc_status_valid,
|
||||
m_axi_awid=m_axi_awid,
|
||||
m_axi_awaddr=m_axi_awaddr,
|
||||
m_axi_awlen=m_axi_awlen,
|
||||
m_axi_awsize=m_axi_awsize,
|
||||
m_axi_awburst=m_axi_awburst,
|
||||
m_axi_awlock=m_axi_awlock,
|
||||
m_axi_awcache=m_axi_awcache,
|
||||
m_axi_awprot=m_axi_awprot,
|
||||
m_axi_awvalid=m_axi_awvalid,
|
||||
m_axi_awready=m_axi_awready,
|
||||
m_axi_wdata=m_axi_wdata,
|
||||
m_axi_wstrb=m_axi_wstrb,
|
||||
m_axi_wlast=m_axi_wlast,
|
||||
m_axi_wvalid=m_axi_wvalid,
|
||||
m_axi_wready=m_axi_wready,
|
||||
m_axi_bid=m_axi_bid,
|
||||
m_axi_bresp=m_axi_bresp,
|
||||
m_axi_bvalid=m_axi_bvalid,
|
||||
m_axi_bready=m_axi_bready,
|
||||
enable=enable,
|
||||
ext_tag_enable=ext_tag_enable,
|
||||
requester_id=requester_id,
|
||||
requester_id_enable=requester_id_enable,
|
||||
max_read_request_size=max_read_request_size,
|
||||
status_error_cor=status_error_cor,
|
||||
status_error_uncor=status_error_uncor
|
||||
)
|
||||
|
||||
@always(delay(4))
|
||||
def clkgen():
|
||||
clk.next = not clk
|
||||
|
||||
@always_comb
|
||||
def clk_logic():
|
||||
sys_clk.next = clk
|
||||
sys_reset.next = not rst
|
||||
|
||||
status_error_cor_asserted = Signal(bool(0))
|
||||
status_error_uncor_asserted = Signal(bool(0))
|
||||
|
||||
@always(clk.posedge)
|
||||
def monitor():
|
||||
if (status_error_cor):
|
||||
status_error_cor_asserted.next = 1
|
||||
if (status_error_uncor):
|
||||
status_error_uncor_asserted.next = 1
|
||||
|
||||
cq_pause_toggle = Signal(bool(0))
|
||||
cc_pause_toggle = Signal(bool(0))
|
||||
rq_pause_toggle = Signal(bool(0))
|
||||
rc_pause_toggle = Signal(bool(0))
|
||||
|
||||
@instance
|
||||
def pause_toggle():
|
||||
while True:
|
||||
if (cq_pause_toggle or cc_pause_toggle or rq_pause_toggle or rc_pause_toggle):
|
||||
cq_pause.next = cq_pause_toggle
|
||||
cc_pause.next = cc_pause_toggle
|
||||
rq_pause.next = rq_pause_toggle
|
||||
rc_pause.next = rc_pause_toggle
|
||||
|
||||
yield user_clk.posedge
|
||||
yield user_clk.posedge
|
||||
yield user_clk.posedge
|
||||
|
||||
cq_pause.next = 0
|
||||
cc_pause.next = 0
|
||||
rq_pause.next = 0
|
||||
rc_pause.next = 0
|
||||
|
||||
yield user_clk.posedge
|
||||
|
||||
@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
|
||||
|
||||
cur_tag = 1
|
||||
|
||||
max_read_request_size.next = 2
|
||||
|
||||
enable.next = 1
|
||||
|
||||
yield user_clk.posedge
|
||||
print("test 1: enumeration")
|
||||
current_test.next = 1
|
||||
|
||||
yield rc.enumerate(enable_bus_mastering=True)
|
||||
|
||||
yield delay(100)
|
||||
|
||||
yield user_clk.posedge
|
||||
print("test 2: PCIe read")
|
||||
current_test.next = 2
|
||||
|
||||
pcie_addr = 0x00000000
|
||||
axi_addr = 0x00000000
|
||||
test_data = b'\x11\x22\x33\x44'
|
||||
|
||||
mem_data[pcie_addr:pcie_addr+len(test_data)] = test_data
|
||||
|
||||
data = mem_data[pcie_addr:pcie_addr+32]
|
||||
for i in range(0, len(data), 16):
|
||||
print(" ".join(("{:02x}".format(c) for c in bytearray(data[i:i+16]))))
|
||||
|
||||
read_desc_source.send([(pcie_addr, axi_addr, len(test_data), cur_tag)])
|
||||
|
||||
yield read_desc_status_sink.wait(2000)
|
||||
|
||||
yield delay(50)
|
||||
|
||||
status = read_desc_status_sink.recv()
|
||||
|
||||
print(status)
|
||||
|
||||
data = axi_ram_inst.read_mem(axi_addr, 32)
|
||||
for i in range(0, len(data), 16):
|
||||
print(" ".join(("{:02x}".format(c) for c in bytearray(data[i:i+16]))))
|
||||
|
||||
assert axi_ram_inst.read_mem(axi_addr, len(test_data)) == test_data
|
||||
|
||||
cur_tag = (cur_tag + 1) % 256
|
||||
|
||||
yield delay(100)
|
||||
|
||||
yield user_clk.posedge
|
||||
print("test 3: various reads")
|
||||
current_test.next = 3
|
||||
|
||||
for length in list(range(1,11))+list(range(128-4,128+4))+[1024]:
|
||||
for pcie_offset in list(range(8,13))+list(range(4096-4,4096+4)):
|
||||
for axi_offset in list(range(8,17))+list(range(4096-8,4096)):
|
||||
for pause in [False, True]:
|
||||
print("length %d, pcie_offset %d, axi_offset %d"% (length, pcie_offset, axi_offset))
|
||||
#pcie_addr = length * 0x100000000 + pcie_offset * 0x10000 + offset
|
||||
pcie_addr = pcie_offset
|
||||
axi_addr = axi_offset
|
||||
test_data = bytearray([x%256 for x in range(length)])
|
||||
|
||||
mem_data[pcie_addr:pcie_addr+len(test_data)] = test_data
|
||||
|
||||
data = mem_data[pcie_addr&0xffff80:(pcie_addr&0xffff80)+64]
|
||||
for i in range(0, len(data), 16):
|
||||
print(" ".join(("{:02x}".format(c) for c in bytearray(data[i:i+16]))))
|
||||
|
||||
axi_ram_inst.write_mem(axi_addr & 0xffff80, b'\xaa'*(len(test_data)+256))
|
||||
|
||||
rq_pause_toggle.next = pause
|
||||
rc_pause_toggle.next = pause
|
||||
|
||||
read_desc_source.send([(pcie_addr, axi_addr, len(test_data), cur_tag)])
|
||||
|
||||
yield read_desc_status_sink.wait(4000)
|
||||
|
||||
rq_pause_toggle.next = 0
|
||||
rc_pause_toggle.next = 0
|
||||
|
||||
status = read_desc_status_sink.recv()
|
||||
|
||||
print(status)
|
||||
|
||||
data = axi_ram_inst.read_mem(axi_addr&0xfffff0, 64)
|
||||
for i in range(0, len(data), 16):
|
||||
print(" ".join(("{:02x}".format(c) for c in bytearray(data[i:i+16]))))
|
||||
|
||||
assert axi_ram_inst.read_mem(axi_addr-8, len(test_data)+16) == b'\xaa'*8+test_data+b'\xaa'*8
|
||||
|
||||
cur_tag = (cur_tag + 1) % 256
|
||||
|
||||
yield delay(50)
|
||||
|
||||
raise StopSimulation
|
||||
|
||||
return instances()
|
||||
|
||||
def test_bench():
|
||||
sim = Simulation(bench())
|
||||
sim.run()
|
||||
|
||||
if __name__ == '__main__':
|
||||
print("Running test...")
|
||||
test_bench()
|
238
fpga/lib/pcie/tb/test_pcie_us_axi_dma_rd_64.v
Normal file
238
fpga/lib/pcie/tb/test_pcie_us_axi_dma_rd_64.v
Normal file
@ -0,0 +1,238 @@
|
||||
/*
|
||||
|
||||
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 pcie_us_axi_dma_rd
|
||||
*/
|
||||
module test_pcie_us_axi_dma_rd_64;
|
||||
|
||||
// Parameters
|
||||
parameter AXIS_PCIE_DATA_WIDTH = 64;
|
||||
parameter AXIS_PCIE_KEEP_WIDTH = (AXIS_PCIE_DATA_WIDTH/32);
|
||||
parameter AXI_DATA_WIDTH = AXIS_PCIE_DATA_WIDTH;
|
||||
parameter AXI_ADDR_WIDTH = 64;
|
||||
parameter AXI_STRB_WIDTH = (AXI_DATA_WIDTH/8);
|
||||
parameter AXI_ID_WIDTH = 8;
|
||||
parameter AXI_MAX_BURST_LEN = 256;
|
||||
parameter PCIE_ADDR_WIDTH = 64;
|
||||
parameter PCIE_CLIENT_TAG = 1;
|
||||
parameter PCIE_TAG_WIDTH = 8;
|
||||
parameter PCIE_TAG_COUNT = 256;
|
||||
parameter PCIE_EXT_TAG_ENABLE = 1;
|
||||
parameter LEN_WIDTH = 20;
|
||||
parameter TAG_WIDTH = 8;
|
||||
|
||||
// Inputs
|
||||
reg clk = 0;
|
||||
reg rst = 0;
|
||||
reg [7:0] current_test = 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_tvalid = 0;
|
||||
reg s_axis_rc_tlast = 0;
|
||||
reg [74:0] s_axis_rc_tuser = 0;
|
||||
reg m_axis_rq_tready = 0;
|
||||
reg [PCIE_TAG_WIDTH-1:0] s_axis_pcie_rq_tag = 0;
|
||||
reg s_axis_pcie_rq_tag_valid = 0;
|
||||
reg [PCIE_ADDR_WIDTH-1:0] s_axis_read_desc_pcie_addr = 0;
|
||||
reg [AXI_ADDR_WIDTH-1:0] s_axis_read_desc_axi_addr = 0;
|
||||
reg [LEN_WIDTH-1:0] s_axis_read_desc_len = 0;
|
||||
reg [TAG_WIDTH-1:0] s_axis_read_desc_tag = 0;
|
||||
reg s_axis_read_desc_valid = 0;
|
||||
reg m_axi_awready = 0;
|
||||
reg m_axi_wready = 0;
|
||||
reg [AXI_ID_WIDTH-1:0] m_axi_bid = 0;
|
||||
reg [1:0] m_axi_bresp = 0;
|
||||
reg m_axi_bvalid = 0;
|
||||
reg enable = 0;
|
||||
reg ext_tag_enable = 0;
|
||||
reg [15:0] requester_id = 0;
|
||||
reg requester_id_enable = 0;
|
||||
reg [2:0] max_read_request_size = 0;
|
||||
|
||||
// Outputs
|
||||
wire s_axis_rc_tready;
|
||||
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_tvalid;
|
||||
wire m_axis_rq_tlast;
|
||||
wire [59:0] m_axis_rq_tuser;
|
||||
wire s_axis_read_desc_ready;
|
||||
wire [TAG_WIDTH-1:0] m_axis_read_desc_status_tag;
|
||||
wire m_axis_read_desc_status_valid;
|
||||
wire [AXI_ID_WIDTH-1:0] m_axi_awid;
|
||||
wire [AXI_ADDR_WIDTH-1:0] m_axi_awaddr;
|
||||
wire [7:0] m_axi_awlen;
|
||||
wire [2:0] m_axi_awsize;
|
||||
wire [1:0] m_axi_awburst;
|
||||
wire m_axi_awlock;
|
||||
wire [3:0] m_axi_awcache;
|
||||
wire [2:0] m_axi_awprot;
|
||||
wire m_axi_awvalid;
|
||||
wire [AXI_DATA_WIDTH-1:0] m_axi_wdata;
|
||||
wire [AXI_STRB_WIDTH-1:0] m_axi_wstrb;
|
||||
wire m_axi_wlast;
|
||||
wire m_axi_wvalid;
|
||||
wire m_axi_bready;
|
||||
wire status_error_cor;
|
||||
wire status_error_uncor;
|
||||
|
||||
initial begin
|
||||
// myhdl integration
|
||||
$from_myhdl(
|
||||
clk,
|
||||
rst,
|
||||
current_test,
|
||||
s_axis_rc_tdata,
|
||||
s_axis_rc_tkeep,
|
||||
s_axis_rc_tvalid,
|
||||
s_axis_rc_tlast,
|
||||
s_axis_rc_tuser,
|
||||
m_axis_rq_tready,
|
||||
s_axis_pcie_rq_tag,
|
||||
s_axis_pcie_rq_tag_valid,
|
||||
s_axis_read_desc_pcie_addr,
|
||||
s_axis_read_desc_axi_addr,
|
||||
s_axis_read_desc_len,
|
||||
s_axis_read_desc_tag,
|
||||
s_axis_read_desc_valid,
|
||||
m_axi_awready,
|
||||
m_axi_wready,
|
||||
m_axi_bid,
|
||||
m_axi_bresp,
|
||||
m_axi_bvalid,
|
||||
enable,
|
||||
ext_tag_enable,
|
||||
requester_id,
|
||||
requester_id_enable,
|
||||
max_read_request_size
|
||||
);
|
||||
$to_myhdl(
|
||||
s_axis_rc_tready,
|
||||
m_axis_rq_tdata,
|
||||
m_axis_rq_tkeep,
|
||||
m_axis_rq_tvalid,
|
||||
m_axis_rq_tlast,
|
||||
m_axis_rq_tuser,
|
||||
s_axis_read_desc_ready,
|
||||
m_axis_read_desc_status_tag,
|
||||
m_axis_read_desc_status_valid,
|
||||
m_axi_awid,
|
||||
m_axi_awaddr,
|
||||
m_axi_awlen,
|
||||
m_axi_awsize,
|
||||
m_axi_awburst,
|
||||
m_axi_awlock,
|
||||
m_axi_awcache,
|
||||
m_axi_awprot,
|
||||
m_axi_awvalid,
|
||||
m_axi_wdata,
|
||||
m_axi_wstrb,
|
||||
m_axi_wlast,
|
||||
m_axi_wvalid,
|
||||
m_axi_bready,
|
||||
status_error_cor,
|
||||
status_error_uncor
|
||||
);
|
||||
|
||||
// dump file
|
||||
$dumpfile("test_pcie_us_axi_dma_rd_64.lxt");
|
||||
$dumpvars(0, test_pcie_us_axi_dma_rd_64);
|
||||
end
|
||||
|
||||
pcie_us_axi_dma_rd #(
|
||||
.AXIS_PCIE_DATA_WIDTH(AXIS_PCIE_DATA_WIDTH),
|
||||
.AXIS_PCIE_KEEP_WIDTH(AXIS_PCIE_KEEP_WIDTH),
|
||||
.AXI_DATA_WIDTH(AXI_DATA_WIDTH),
|
||||
.AXI_ADDR_WIDTH(AXI_ADDR_WIDTH),
|
||||
.AXI_STRB_WIDTH(AXI_STRB_WIDTH),
|
||||
.AXI_ID_WIDTH(AXI_ID_WIDTH),
|
||||
.AXI_MAX_BURST_LEN(AXI_MAX_BURST_LEN),
|
||||
.PCIE_ADDR_WIDTH(PCIE_ADDR_WIDTH),
|
||||
.PCIE_CLIENT_TAG(PCIE_CLIENT_TAG),
|
||||
.PCIE_TAG_WIDTH(PCIE_TAG_WIDTH),
|
||||
.PCIE_TAG_COUNT(PCIE_TAG_COUNT),
|
||||
.PCIE_EXT_TAG_ENABLE(PCIE_EXT_TAG_ENABLE),
|
||||
.LEN_WIDTH(LEN_WIDTH),
|
||||
.TAG_WIDTH(TAG_WIDTH)
|
||||
)
|
||||
UUT (
|
||||
.clk(clk),
|
||||
.rst(rst),
|
||||
.s_axis_rc_tdata(s_axis_rc_tdata),
|
||||
.s_axis_rc_tkeep(s_axis_rc_tkeep),
|
||||
.s_axis_rc_tvalid(s_axis_rc_tvalid),
|
||||
.s_axis_rc_tready(s_axis_rc_tready),
|
||||
.s_axis_rc_tlast(s_axis_rc_tlast),
|
||||
.s_axis_rc_tuser(s_axis_rc_tuser),
|
||||
.m_axis_rq_tdata(m_axis_rq_tdata),
|
||||
.m_axis_rq_tkeep(m_axis_rq_tkeep),
|
||||
.m_axis_rq_tvalid(m_axis_rq_tvalid),
|
||||
.m_axis_rq_tready(m_axis_rq_tready),
|
||||
.m_axis_rq_tlast(m_axis_rq_tlast),
|
||||
.m_axis_rq_tuser(m_axis_rq_tuser),
|
||||
.s_axis_pcie_rq_tag(s_axis_pcie_rq_tag),
|
||||
.s_axis_pcie_rq_tag_valid(s_axis_pcie_rq_tag_valid),
|
||||
.s_axis_read_desc_pcie_addr(s_axis_read_desc_pcie_addr),
|
||||
.s_axis_read_desc_axi_addr(s_axis_read_desc_axi_addr),
|
||||
.s_axis_read_desc_len(s_axis_read_desc_len),
|
||||
.s_axis_read_desc_tag(s_axis_read_desc_tag),
|
||||
.s_axis_read_desc_valid(s_axis_read_desc_valid),
|
||||
.s_axis_read_desc_ready(s_axis_read_desc_ready),
|
||||
.m_axis_read_desc_status_tag(m_axis_read_desc_status_tag),
|
||||
.m_axis_read_desc_status_valid(m_axis_read_desc_status_valid),
|
||||
.m_axi_awid(m_axi_awid),
|
||||
.m_axi_awaddr(m_axi_awaddr),
|
||||
.m_axi_awlen(m_axi_awlen),
|
||||
.m_axi_awsize(m_axi_awsize),
|
||||
.m_axi_awburst(m_axi_awburst),
|
||||
.m_axi_awlock(m_axi_awlock),
|
||||
.m_axi_awcache(m_axi_awcache),
|
||||
.m_axi_awprot(m_axi_awprot),
|
||||
.m_axi_awvalid(m_axi_awvalid),
|
||||
.m_axi_awready(m_axi_awready),
|
||||
.m_axi_wdata(m_axi_wdata),
|
||||
.m_axi_wstrb(m_axi_wstrb),
|
||||
.m_axi_wlast(m_axi_wlast),
|
||||
.m_axi_wvalid(m_axi_wvalid),
|
||||
.m_axi_wready(m_axi_wready),
|
||||
.m_axi_bid(m_axi_bid),
|
||||
.m_axi_bresp(m_axi_bresp),
|
||||
.m_axi_bvalid(m_axi_bvalid),
|
||||
.m_axi_bready(m_axi_bready),
|
||||
.enable(enable),
|
||||
.ext_tag_enable(ext_tag_enable),
|
||||
.requester_id(requester_id),
|
||||
.requester_id_enable(requester_id_enable),
|
||||
.max_read_request_size(max_read_request_size),
|
||||
.status_error_cor(status_error_cor),
|
||||
.status_error_uncor(status_error_uncor)
|
||||
);
|
||||
|
||||
endmodule
|
449
fpga/lib/pcie/tb/test_pcie_us_axi_dma_wr_128.py
Executable file
449
fpga/lib/pcie/tb/test_pcie_us_axi_dma_wr_128.py
Executable file
@ -0,0 +1,449 @@
|
||||
#!/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 pcie
|
||||
import pcie_us
|
||||
import axi
|
||||
import axis_ep
|
||||
|
||||
module = 'pcie_us_axi_dma_wr'
|
||||
testbench = 'test_%s_128' % module
|
||||
|
||||
srcs = []
|
||||
|
||||
srcs.append("../rtl/%s.v" % module)
|
||||
srcs.append("%s.v" % testbench)
|
||||
|
||||
src = ' '.join(srcs)
|
||||
|
||||
build_cmd = "iverilog -o %s.vvp %s" % (testbench, src)
|
||||
|
||||
def bench():
|
||||
|
||||
# Parameters
|
||||
AXIS_PCIE_DATA_WIDTH = 128
|
||||
AXIS_PCIE_KEEP_WIDTH = (AXIS_PCIE_DATA_WIDTH/32)
|
||||
AXI_DATA_WIDTH = AXIS_PCIE_DATA_WIDTH
|
||||
AXI_ADDR_WIDTH = 64
|
||||
AXI_STRB_WIDTH = (AXI_DATA_WIDTH/8)
|
||||
AXI_ID_WIDTH = 8
|
||||
AXI_MAX_BURST_LEN = 256
|
||||
PCIE_ADDR_WIDTH = 64
|
||||
LEN_WIDTH = 20
|
||||
TAG_WIDTH = 8
|
||||
|
||||
# Inputs
|
||||
clk = Signal(bool(0))
|
||||
rst = Signal(bool(0))
|
||||
current_test = Signal(intbv(0)[8:])
|
||||
|
||||
m_axis_rq_tready = Signal(bool(0))
|
||||
s_axis_write_desc_pcie_addr = Signal(intbv(0)[PCIE_ADDR_WIDTH:])
|
||||
s_axis_write_desc_axi_addr = Signal(intbv(0)[AXI_ADDR_WIDTH:])
|
||||
s_axis_write_desc_len = Signal(intbv(0)[LEN_WIDTH:])
|
||||
s_axis_write_desc_tag = Signal(intbv(0)[TAG_WIDTH:])
|
||||
s_axis_write_desc_valid = Signal(bool(0))
|
||||
m_axi_arready = Signal(bool(0))
|
||||
m_axi_rid = Signal(intbv(0)[AXI_ID_WIDTH:])
|
||||
m_axi_rdata = Signal(intbv(0)[AXI_DATA_WIDTH:])
|
||||
m_axi_rresp = Signal(intbv(0)[2:])
|
||||
m_axi_rlast = Signal(bool(0))
|
||||
m_axi_rvalid = Signal(bool(0))
|
||||
enable = Signal(bool(0))
|
||||
requester_id = Signal(intbv(0)[16:])
|
||||
requester_id_enable = Signal(bool(0))
|
||||
max_payload_size = Signal(intbv(0)[3:])
|
||||
|
||||
# Outputs
|
||||
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_tvalid = Signal(bool(0))
|
||||
m_axis_rq_tlast = Signal(bool(0))
|
||||
m_axis_rq_tuser = Signal(intbv(0)[60:])
|
||||
s_axis_write_desc_ready = Signal(bool(0))
|
||||
m_axis_write_desc_status_tag = Signal(intbv(0)[TAG_WIDTH:])
|
||||
m_axis_write_desc_status_valid = Signal(bool(0))
|
||||
m_axi_arid = Signal(intbv(0)[AXI_ID_WIDTH:])
|
||||
m_axi_araddr = Signal(intbv(0)[AXI_ADDR_WIDTH:])
|
||||
m_axi_arlen = Signal(intbv(0)[8:])
|
||||
m_axi_arsize = Signal(intbv(4)[3:])
|
||||
m_axi_arburst = Signal(intbv(1)[2:])
|
||||
m_axi_arlock = Signal(bool(0))
|
||||
m_axi_arcache = Signal(intbv(3)[4:])
|
||||
m_axi_arprot = Signal(intbv(2)[3:])
|
||||
m_axi_arvalid = Signal(bool(0))
|
||||
m_axi_rready = Signal(bool(0))
|
||||
|
||||
# Clock and Reset Interface
|
||||
user_clk=Signal(bool(0))
|
||||
user_reset=Signal(bool(0))
|
||||
sys_clk=Signal(bool(0))
|
||||
sys_reset=Signal(bool(0))
|
||||
|
||||
# AXI4 RAM model
|
||||
axi_ram_inst = axi.AXIRam(2**16)
|
||||
|
||||
axi_ram_port0 = axi_ram_inst.create_port(
|
||||
user_clk,
|
||||
s_axi_arid=m_axi_arid,
|
||||
s_axi_araddr=m_axi_araddr,
|
||||
s_axi_arlen=m_axi_arlen,
|
||||
s_axi_arsize=m_axi_arsize,
|
||||
s_axi_arburst=m_axi_arburst,
|
||||
s_axi_arlock=m_axi_arlock,
|
||||
s_axi_arcache=m_axi_arcache,
|
||||
s_axi_arprot=m_axi_arprot,
|
||||
s_axi_arvalid=m_axi_arvalid,
|
||||
s_axi_arready=m_axi_arready,
|
||||
s_axi_rid=m_axi_rid,
|
||||
s_axi_rdata=m_axi_rdata,
|
||||
s_axi_rresp=m_axi_rresp,
|
||||
s_axi_rlast=m_axi_rlast,
|
||||
s_axi_rvalid=m_axi_rvalid,
|
||||
s_axi_rready=m_axi_rready,
|
||||
name='port0'
|
||||
)
|
||||
|
||||
write_desc_source = axis_ep.AXIStreamSource()
|
||||
|
||||
write_desc_source_logic = write_desc_source.create_logic(
|
||||
user_clk,
|
||||
user_reset,
|
||||
tdata=(s_axis_write_desc_pcie_addr, s_axis_write_desc_axi_addr, s_axis_write_desc_len, s_axis_write_desc_tag),
|
||||
tvalid=s_axis_write_desc_valid,
|
||||
tready=s_axis_write_desc_ready,
|
||||
name='write_desc_source'
|
||||
)
|
||||
|
||||
write_desc_status_sink = axis_ep.AXIStreamSink()
|
||||
|
||||
write_desc_status_sink_logic = write_desc_status_sink.create_logic(
|
||||
user_clk,
|
||||
user_reset,
|
||||
tdata=(m_axis_write_desc_status_tag,),
|
||||
tvalid=m_axis_write_desc_status_valid,
|
||||
name='write_desc_status_sink'
|
||||
)
|
||||
|
||||
# PCIe devices
|
||||
rc = pcie.RootComplex()
|
||||
|
||||
mem_base, mem_data = rc.alloc_region(16*1024*1024)
|
||||
|
||||
dev = pcie_us.UltrascalePCIe()
|
||||
|
||||
dev.pcie_generation = 3
|
||||
dev.pcie_link_width = 4
|
||||
dev.user_clock_frequency = 250e6
|
||||
|
||||
rc.make_port().connect(dev)
|
||||
|
||||
cq_pause = Signal(bool(0))
|
||||
cc_pause = Signal(bool(0))
|
||||
rq_pause = Signal(bool(0))
|
||||
rc_pause = Signal(bool(0))
|
||||
|
||||
pcie_logic = dev.create_logic(
|
||||
# Completer reQuest Interface
|
||||
m_axis_cq_tdata=Signal(intbv(0)[AXIS_PCIE_DATA_WIDTH:]),
|
||||
m_axis_cq_tuser=Signal(intbv(0)[85:]),
|
||||
m_axis_cq_tlast=Signal(bool(0)),
|
||||
m_axis_cq_tkeep=Signal(intbv(0)[AXIS_PCIE_KEEP_WIDTH:]),
|
||||
m_axis_cq_tvalid=Signal(bool(0)),
|
||||
m_axis_cq_tready=Signal(bool(1)),
|
||||
#pcie_cq_np_req=pcie_cq_np_req,
|
||||
#pcie_cq_np_req_count=pcie_cq_np_req_count,
|
||||
|
||||
# Completer Completion Interface
|
||||
s_axis_cc_tdata=Signal(intbv(0)[AXIS_PCIE_DATA_WIDTH:]),
|
||||
s_axis_cc_tuser=Signal(intbv(0)[33:]),
|
||||
s_axis_cc_tlast=Signal(bool(0)),
|
||||
s_axis_cc_tkeep=Signal(intbv(0)[AXIS_PCIE_KEEP_WIDTH:]),
|
||||
s_axis_cc_tvalid=Signal(bool(0)),
|
||||
s_axis_cc_tready=Signal(bool(0)),
|
||||
|
||||
# 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_num=pcie_rq_seq_num,
|
||||
# pcie_rq_seq_num_vld=pcie_rq_seq_num_vld,
|
||||
# pcie_rq_tag=pcie_rq_tag,
|
||||
# pcie_rq_tag_av=pcie_rq_tag_av,
|
||||
# pcie_rq_tag_vld=pcie_rq_tag_vld,
|
||||
|
||||
# Requester Completion Interface
|
||||
m_axis_rc_tdata=Signal(intbv(0)[AXIS_PCIE_DATA_WIDTH:]),
|
||||
m_axis_rc_tuser=Signal(intbv(0)[75:]),
|
||||
m_axis_rc_tlast=Signal(bool(0)),
|
||||
m_axis_rc_tkeep=Signal(intbv(0)[AXIS_PCIE_KEEP_WIDTH:]),
|
||||
m_axis_rc_tvalid=Signal(bool(0)),
|
||||
m_axis_rc_tready=Signal(bool(0)),
|
||||
|
||||
# Transmit Flow Control Interface
|
||||
# pcie_tfc_nph_av=pcie_tfc_nph_av,
|
||||
# pcie_tfc_npd_av=pcie_tfc_npd_av,
|
||||
|
||||
# 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_per_function_update_done=cfg_per_function_update_done,
|
||||
# cfg_per_function_number=cfg_per_function_number,
|
||||
# cfg_per_function_output_request=cfg_per_function_output_request,
|
||||
# cfg_dsn=cfg_dsn,
|
||||
# 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=cfg_err_cor_in,
|
||||
# cfg_err_uncor_in=cfg_err_uncor_in,
|
||||
# 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,
|
||||
|
||||
# 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,
|
||||
|
||||
cq_pause=cq_pause,
|
||||
cc_pause=cc_pause,
|
||||
rq_pause=rq_pause,
|
||||
rc_pause=rc_pause
|
||||
)
|
||||
|
||||
# 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,
|
||||
m_axis_rq_tdata=m_axis_rq_tdata,
|
||||
m_axis_rq_tkeep=m_axis_rq_tkeep,
|
||||
m_axis_rq_tvalid=m_axis_rq_tvalid,
|
||||
m_axis_rq_tready=m_axis_rq_tready,
|
||||
m_axis_rq_tlast=m_axis_rq_tlast,
|
||||
m_axis_rq_tuser=m_axis_rq_tuser,
|
||||
s_axis_write_desc_pcie_addr=s_axis_write_desc_pcie_addr,
|
||||
s_axis_write_desc_axi_addr=s_axis_write_desc_axi_addr,
|
||||
s_axis_write_desc_len=s_axis_write_desc_len,
|
||||
s_axis_write_desc_tag=s_axis_write_desc_tag,
|
||||
s_axis_write_desc_valid=s_axis_write_desc_valid,
|
||||
s_axis_write_desc_ready=s_axis_write_desc_ready,
|
||||
m_axis_write_desc_status_tag=m_axis_write_desc_status_tag,
|
||||
m_axis_write_desc_status_valid=m_axis_write_desc_status_valid,
|
||||
m_axi_arid=m_axi_arid,
|
||||
m_axi_araddr=m_axi_araddr,
|
||||
m_axi_arlen=m_axi_arlen,
|
||||
m_axi_arsize=m_axi_arsize,
|
||||
m_axi_arburst=m_axi_arburst,
|
||||
m_axi_arlock=m_axi_arlock,
|
||||
m_axi_arcache=m_axi_arcache,
|
||||
m_axi_arprot=m_axi_arprot,
|
||||
m_axi_arvalid=m_axi_arvalid,
|
||||
m_axi_arready=m_axi_arready,
|
||||
m_axi_rid=m_axi_rid,
|
||||
m_axi_rdata=m_axi_rdata,
|
||||
m_axi_rresp=m_axi_rresp,
|
||||
m_axi_rlast=m_axi_rlast,
|
||||
m_axi_rvalid=m_axi_rvalid,
|
||||
m_axi_rready=m_axi_rready,
|
||||
enable=enable,
|
||||
requester_id=requester_id,
|
||||
requester_id_enable=requester_id_enable,
|
||||
max_payload_size=max_payload_size
|
||||
)
|
||||
|
||||
@always(delay(4))
|
||||
def clkgen():
|
||||
clk.next = not clk
|
||||
|
||||
@always_comb
|
||||
def clk_logic():
|
||||
sys_clk.next = clk
|
||||
sys_reset.next = not rst
|
||||
|
||||
cq_pause_toggle = Signal(bool(0))
|
||||
cc_pause_toggle = Signal(bool(0))
|
||||
rq_pause_toggle = Signal(bool(0))
|
||||
rc_pause_toggle = Signal(bool(0))
|
||||
|
||||
@instance
|
||||
def pause_toggle():
|
||||
while True:
|
||||
if (cq_pause_toggle or cc_pause_toggle or rq_pause_toggle or rc_pause_toggle):
|
||||
cq_pause.next = cq_pause_toggle
|
||||
cc_pause.next = cc_pause_toggle
|
||||
rq_pause.next = rq_pause_toggle
|
||||
rc_pause.next = rc_pause_toggle
|
||||
|
||||
yield user_clk.posedge
|
||||
yield user_clk.posedge
|
||||
yield user_clk.posedge
|
||||
|
||||
cq_pause.next = 0
|
||||
cc_pause.next = 0
|
||||
rq_pause.next = 0
|
||||
rc_pause.next = 0
|
||||
|
||||
yield user_clk.posedge
|
||||
|
||||
@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
|
||||
|
||||
cur_tag = 1
|
||||
|
||||
max_payload_size.next = 0
|
||||
|
||||
enable.next = 1
|
||||
|
||||
yield user_clk.posedge
|
||||
print("test 1: enumeration")
|
||||
current_test.next = 1
|
||||
|
||||
yield rc.enumerate(enable_bus_mastering=True)
|
||||
|
||||
yield delay(100)
|
||||
|
||||
yield user_clk.posedge
|
||||
print("test 2: PCIe write")
|
||||
current_test.next = 2
|
||||
|
||||
pcie_addr = 0x00000000
|
||||
axi_addr = 0x00000000
|
||||
test_data = b'\x11\x22\x33\x44'
|
||||
|
||||
axi_ram_inst.write_mem(axi_addr, test_data)
|
||||
|
||||
data = axi_ram_inst.read_mem(axi_addr, 32)
|
||||
for i in range(0, len(data), 16):
|
||||
print(" ".join(("{:02x}".format(c) for c in bytearray(data[i:i+16]))))
|
||||
|
||||
write_desc_source.send([(mem_base+pcie_addr, axi_addr, len(test_data), cur_tag)])
|
||||
|
||||
yield write_desc_status_sink.wait(1000)
|
||||
yield delay(50)
|
||||
|
||||
status = write_desc_status_sink.recv()
|
||||
|
||||
print(status)
|
||||
|
||||
assert status.data[0][0] == cur_tag
|
||||
|
||||
data = mem_data[pcie_addr:pcie_addr+32]
|
||||
for i in range(0, len(data), 16):
|
||||
print(" ".join(("{:02x}".format(c) for c in bytearray(data[i:i+16]))))
|
||||
|
||||
assert mem_data[pcie_addr:pcie_addr+len(test_data)] == test_data
|
||||
|
||||
cur_tag = (cur_tag + 1) % 256
|
||||
|
||||
yield delay(100)
|
||||
|
||||
yield user_clk.posedge
|
||||
print("test 3: various writes")
|
||||
current_test.next = 3
|
||||
|
||||
for length in list(range(1,19))+list(range(128-4,128+4))+[1024]:
|
||||
for pcie_offset in list(range(8,13))+list(range(4096-4,4096+4)):
|
||||
for axi_offset in list(range(8,25))+list(range(4096-16,4096)):
|
||||
for pause in [False, True]:
|
||||
print("length %d, pcie_offset %d, axi_offset %d"% (length, pcie_offset, axi_offset))
|
||||
#pcie_addr = length * 0x100000000 + pcie_offset * 0x10000 + offset
|
||||
pcie_addr = pcie_offset
|
||||
axi_addr = axi_offset
|
||||
test_data = bytearray([x%256 for x in range(length)])
|
||||
|
||||
axi_ram_inst.write_mem(axi_addr & 0xffff80, b'\x55'*(len(test_data)+256))
|
||||
mem_data[(pcie_addr-1) & 0xffff80:((pcie_addr-1) & 0xffff80)+len(test_data)+256] = b'\xaa'*(len(test_data)+256)
|
||||
axi_ram_inst.write_mem(axi_addr, test_data)
|
||||
|
||||
data = axi_ram_inst.read_mem(axi_addr&0xfffff0, 64)
|
||||
for i in range(0, len(data), 16):
|
||||
print(" ".join(("{:02x}".format(c) for c in bytearray(data[i:i+16]))))
|
||||
|
||||
rq_pause_toggle.next = pause
|
||||
|
||||
write_desc_source.send([(mem_base+pcie_addr, axi_addr, len(test_data), cur_tag)])
|
||||
|
||||
yield write_desc_status_sink.wait(4000)
|
||||
yield delay(50)
|
||||
|
||||
rq_pause_toggle.next = 0
|
||||
|
||||
status = write_desc_status_sink.recv()
|
||||
|
||||
print(status)
|
||||
|
||||
assert status.data[0][0] == cur_tag
|
||||
|
||||
data = mem_data[pcie_addr&0xfffff0:(pcie_addr&0xfffff0)+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[pcie_addr-1:pcie_addr+len(test_data)+1] == b'\xaa'+test_data+b'\xaa'
|
||||
|
||||
cur_tag = (cur_tag + 1) % 256
|
||||
|
||||
yield delay(100)
|
||||
|
||||
raise StopSimulation
|
||||
|
||||
return instances()
|
||||
|
||||
def test_bench():
|
||||
sim = Simulation(bench())
|
||||
sim.run()
|
||||
|
||||
if __name__ == '__main__':
|
||||
print("Running test...")
|
||||
test_bench()
|
188
fpga/lib/pcie/tb/test_pcie_us_axi_dma_wr_128.v
Normal file
188
fpga/lib/pcie/tb/test_pcie_us_axi_dma_wr_128.v
Normal file
@ -0,0 +1,188 @@
|
||||
/*
|
||||
|
||||
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 pcie_us_axi_dma_wr
|
||||
*/
|
||||
module test_pcie_us_axi_dma_wr_128;
|
||||
|
||||
// Parameters
|
||||
parameter AXIS_PCIE_DATA_WIDTH = 128;
|
||||
parameter AXIS_PCIE_KEEP_WIDTH = (AXIS_PCIE_DATA_WIDTH/32);
|
||||
parameter AXI_DATA_WIDTH = AXIS_PCIE_DATA_WIDTH;
|
||||
parameter AXI_ADDR_WIDTH = 64;
|
||||
parameter AXI_STRB_WIDTH = (AXI_DATA_WIDTH/8);
|
||||
parameter AXI_ID_WIDTH = 8;
|
||||
parameter AXI_MAX_BURST_LEN = 256;
|
||||
parameter PCIE_ADDR_WIDTH = 64;
|
||||
parameter LEN_WIDTH = 20;
|
||||
parameter TAG_WIDTH = 8;
|
||||
|
||||
// Inputs
|
||||
reg clk = 0;
|
||||
reg rst = 0;
|
||||
reg [7:0] current_test = 0;
|
||||
|
||||
reg m_axis_rq_tready = 0;
|
||||
reg [PCIE_ADDR_WIDTH-1:0] s_axis_write_desc_pcie_addr = 0;
|
||||
reg [AXI_ADDR_WIDTH-1:0] s_axis_write_desc_axi_addr = 0;
|
||||
reg [LEN_WIDTH-1:0] s_axis_write_desc_len = 0;
|
||||
reg [TAG_WIDTH-1:0] s_axis_write_desc_tag = 0;
|
||||
reg s_axis_write_desc_valid = 0;
|
||||
reg m_axi_arready = 0;
|
||||
reg [AXI_ID_WIDTH-1:0] m_axi_rid = 0;
|
||||
reg [AXI_DATA_WIDTH-1:0] m_axi_rdata = 0;
|
||||
reg [1:0] m_axi_rresp = 0;
|
||||
reg m_axi_rlast = 0;
|
||||
reg m_axi_rvalid = 0;
|
||||
reg enable = 0;
|
||||
reg [15:0] requester_id = 0;
|
||||
reg requester_id_enable = 0;
|
||||
reg [2:0] max_payload_size = 0;
|
||||
|
||||
// Outputs
|
||||
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_tvalid;
|
||||
wire m_axis_rq_tlast;
|
||||
wire [59:0] m_axis_rq_tuser;
|
||||
wire s_axis_write_desc_ready;
|
||||
wire [TAG_WIDTH-1:0] m_axis_write_desc_status_tag;
|
||||
wire m_axis_write_desc_status_valid;
|
||||
wire [AXI_ID_WIDTH-1:0] m_axi_arid;
|
||||
wire [AXI_ADDR_WIDTH-1:0] m_axi_araddr;
|
||||
wire [7:0] m_axi_arlen;
|
||||
wire [2:0] m_axi_arsize;
|
||||
wire [1:0] m_axi_arburst;
|
||||
wire m_axi_arlock;
|
||||
wire [3:0] m_axi_arcache;
|
||||
wire [2:0] m_axi_arprot;
|
||||
wire m_axi_arvalid;
|
||||
wire m_axi_rready;
|
||||
|
||||
initial begin
|
||||
// myhdl integration
|
||||
$from_myhdl(
|
||||
clk,
|
||||
rst,
|
||||
current_test,
|
||||
m_axis_rq_tready,
|
||||
s_axis_write_desc_pcie_addr,
|
||||
s_axis_write_desc_axi_addr,
|
||||
s_axis_write_desc_len,
|
||||
s_axis_write_desc_tag,
|
||||
s_axis_write_desc_valid,
|
||||
m_axi_arready,
|
||||
m_axi_rid,
|
||||
m_axi_rdata,
|
||||
m_axi_rresp,
|
||||
m_axi_rlast,
|
||||
m_axi_rvalid,
|
||||
enable,
|
||||
requester_id,
|
||||
requester_id_enable,
|
||||
max_payload_size
|
||||
);
|
||||
$to_myhdl(
|
||||
m_axis_rq_tdata,
|
||||
m_axis_rq_tkeep,
|
||||
m_axis_rq_tvalid,
|
||||
m_axis_rq_tlast,
|
||||
m_axis_rq_tuser,
|
||||
s_axis_write_desc_ready,
|
||||
m_axis_write_desc_status_tag,
|
||||
m_axis_write_desc_status_valid,
|
||||
m_axi_arid,
|
||||
m_axi_araddr,
|
||||
m_axi_arlen,
|
||||
m_axi_arsize,
|
||||
m_axi_arburst,
|
||||
m_axi_arlock,
|
||||
m_axi_arcache,
|
||||
m_axi_arprot,
|
||||
m_axi_arvalid,
|
||||
m_axi_rready
|
||||
);
|
||||
|
||||
// dump file
|
||||
$dumpfile("test_pcie_us_axi_dma_wr_128.lxt");
|
||||
$dumpvars(0, test_pcie_us_axi_dma_wr_128);
|
||||
end
|
||||
|
||||
pcie_us_axi_dma_wr #(
|
||||
.AXIS_PCIE_DATA_WIDTH(AXIS_PCIE_DATA_WIDTH),
|
||||
.AXIS_PCIE_KEEP_WIDTH(AXIS_PCIE_KEEP_WIDTH),
|
||||
.AXI_DATA_WIDTH(AXI_DATA_WIDTH),
|
||||
.AXI_ADDR_WIDTH(AXI_ADDR_WIDTH),
|
||||
.AXI_STRB_WIDTH(AXI_STRB_WIDTH),
|
||||
.AXI_ID_WIDTH(AXI_ID_WIDTH),
|
||||
.AXI_MAX_BURST_LEN(AXI_MAX_BURST_LEN),
|
||||
.PCIE_ADDR_WIDTH(PCIE_ADDR_WIDTH),
|
||||
.LEN_WIDTH(LEN_WIDTH),
|
||||
.TAG_WIDTH(TAG_WIDTH)
|
||||
)
|
||||
UUT (
|
||||
.clk(clk),
|
||||
.rst(rst),
|
||||
.m_axis_rq_tdata(m_axis_rq_tdata),
|
||||
.m_axis_rq_tkeep(m_axis_rq_tkeep),
|
||||
.m_axis_rq_tvalid(m_axis_rq_tvalid),
|
||||
.m_axis_rq_tready(m_axis_rq_tready),
|
||||
.m_axis_rq_tlast(m_axis_rq_tlast),
|
||||
.m_axis_rq_tuser(m_axis_rq_tuser),
|
||||
.s_axis_write_desc_pcie_addr(s_axis_write_desc_pcie_addr),
|
||||
.s_axis_write_desc_axi_addr(s_axis_write_desc_axi_addr),
|
||||
.s_axis_write_desc_len(s_axis_write_desc_len),
|
||||
.s_axis_write_desc_tag(s_axis_write_desc_tag),
|
||||
.s_axis_write_desc_valid(s_axis_write_desc_valid),
|
||||
.s_axis_write_desc_ready(s_axis_write_desc_ready),
|
||||
.m_axis_write_desc_status_tag(m_axis_write_desc_status_tag),
|
||||
.m_axis_write_desc_status_valid(m_axis_write_desc_status_valid),
|
||||
.m_axi_arid(m_axi_arid),
|
||||
.m_axi_araddr(m_axi_araddr),
|
||||
.m_axi_arlen(m_axi_arlen),
|
||||
.m_axi_arsize(m_axi_arsize),
|
||||
.m_axi_arburst(m_axi_arburst),
|
||||
.m_axi_arlock(m_axi_arlock),
|
||||
.m_axi_arcache(m_axi_arcache),
|
||||
.m_axi_arprot(m_axi_arprot),
|
||||
.m_axi_arvalid(m_axi_arvalid),
|
||||
.m_axi_arready(m_axi_arready),
|
||||
.m_axi_rid(m_axi_rid),
|
||||
.m_axi_rdata(m_axi_rdata),
|
||||
.m_axi_rresp(m_axi_rresp),
|
||||
.m_axi_rlast(m_axi_rlast),
|
||||
.m_axi_rvalid(m_axi_rvalid),
|
||||
.m_axi_rready(m_axi_rready),
|
||||
.enable(enable),
|
||||
.requester_id(requester_id),
|
||||
.requester_id_enable(requester_id_enable),
|
||||
.max_payload_size(max_payload_size)
|
||||
);
|
||||
|
||||
endmodule
|
449
fpga/lib/pcie/tb/test_pcie_us_axi_dma_wr_256.py
Executable file
449
fpga/lib/pcie/tb/test_pcie_us_axi_dma_wr_256.py
Executable file
@ -0,0 +1,449 @@
|
||||
#!/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 pcie
|
||||
import pcie_us
|
||||
import axi
|
||||
import axis_ep
|
||||
|
||||
module = 'pcie_us_axi_dma_wr'
|
||||
testbench = 'test_%s_256' % module
|
||||
|
||||
srcs = []
|
||||
|
||||
srcs.append("../rtl/%s.v" % module)
|
||||
srcs.append("%s.v" % testbench)
|
||||
|
||||
src = ' '.join(srcs)
|
||||
|
||||
build_cmd = "iverilog -o %s.vvp %s" % (testbench, src)
|
||||
|
||||
def bench():
|
||||
|
||||
# Parameters
|
||||
AXIS_PCIE_DATA_WIDTH = 256
|
||||
AXIS_PCIE_KEEP_WIDTH = (AXIS_PCIE_DATA_WIDTH/32)
|
||||
AXI_DATA_WIDTH = AXIS_PCIE_DATA_WIDTH
|
||||
AXI_ADDR_WIDTH = 64
|
||||
AXI_STRB_WIDTH = (AXI_DATA_WIDTH/8)
|
||||
AXI_ID_WIDTH = 8
|
||||
AXI_MAX_BURST_LEN = 256
|
||||
PCIE_ADDR_WIDTH = 64
|
||||
LEN_WIDTH = 20
|
||||
TAG_WIDTH = 8
|
||||
|
||||
# Inputs
|
||||
clk = Signal(bool(0))
|
||||
rst = Signal(bool(0))
|
||||
current_test = Signal(intbv(0)[8:])
|
||||
|
||||
m_axis_rq_tready = Signal(bool(0))
|
||||
s_axis_write_desc_pcie_addr = Signal(intbv(0)[PCIE_ADDR_WIDTH:])
|
||||
s_axis_write_desc_axi_addr = Signal(intbv(0)[AXI_ADDR_WIDTH:])
|
||||
s_axis_write_desc_len = Signal(intbv(0)[LEN_WIDTH:])
|
||||
s_axis_write_desc_tag = Signal(intbv(0)[TAG_WIDTH:])
|
||||
s_axis_write_desc_valid = Signal(bool(0))
|
||||
m_axi_arready = Signal(bool(0))
|
||||
m_axi_rid = Signal(intbv(0)[AXI_ID_WIDTH:])
|
||||
m_axi_rdata = Signal(intbv(0)[AXI_DATA_WIDTH:])
|
||||
m_axi_rresp = Signal(intbv(0)[2:])
|
||||
m_axi_rlast = Signal(bool(0))
|
||||
m_axi_rvalid = Signal(bool(0))
|
||||
enable = Signal(bool(0))
|
||||
requester_id = Signal(intbv(0)[16:])
|
||||
requester_id_enable = Signal(bool(0))
|
||||
max_payload_size = Signal(intbv(0)[3:])
|
||||
|
||||
# Outputs
|
||||
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_tvalid = Signal(bool(0))
|
||||
m_axis_rq_tlast = Signal(bool(0))
|
||||
m_axis_rq_tuser = Signal(intbv(0)[60:])
|
||||
s_axis_write_desc_ready = Signal(bool(0))
|
||||
m_axis_write_desc_status_tag = Signal(intbv(0)[TAG_WIDTH:])
|
||||
m_axis_write_desc_status_valid = Signal(bool(0))
|
||||
m_axi_arid = Signal(intbv(0)[AXI_ID_WIDTH:])
|
||||
m_axi_araddr = Signal(intbv(0)[AXI_ADDR_WIDTH:])
|
||||
m_axi_arlen = Signal(intbv(0)[8:])
|
||||
m_axi_arsize = Signal(intbv(5)[3:])
|
||||
m_axi_arburst = Signal(intbv(1)[2:])
|
||||
m_axi_arlock = Signal(bool(0))
|
||||
m_axi_arcache = Signal(intbv(3)[4:])
|
||||
m_axi_arprot = Signal(intbv(2)[3:])
|
||||
m_axi_arvalid = Signal(bool(0))
|
||||
m_axi_rready = Signal(bool(0))
|
||||
|
||||
# Clock and Reset Interface
|
||||
user_clk=Signal(bool(0))
|
||||
user_reset=Signal(bool(0))
|
||||
sys_clk=Signal(bool(0))
|
||||
sys_reset=Signal(bool(0))
|
||||
|
||||
# AXI4 RAM model
|
||||
axi_ram_inst = axi.AXIRam(2**16)
|
||||
|
||||
axi_ram_port0 = axi_ram_inst.create_port(
|
||||
user_clk,
|
||||
s_axi_arid=m_axi_arid,
|
||||
s_axi_araddr=m_axi_araddr,
|
||||
s_axi_arlen=m_axi_arlen,
|
||||
s_axi_arsize=m_axi_arsize,
|
||||
s_axi_arburst=m_axi_arburst,
|
||||
s_axi_arlock=m_axi_arlock,
|
||||
s_axi_arcache=m_axi_arcache,
|
||||
s_axi_arprot=m_axi_arprot,
|
||||
s_axi_arvalid=m_axi_arvalid,
|
||||
s_axi_arready=m_axi_arready,
|
||||
s_axi_rid=m_axi_rid,
|
||||
s_axi_rdata=m_axi_rdata,
|
||||
s_axi_rresp=m_axi_rresp,
|
||||
s_axi_rlast=m_axi_rlast,
|
||||
s_axi_rvalid=m_axi_rvalid,
|
||||
s_axi_rready=m_axi_rready,
|
||||
name='port0'
|
||||
)
|
||||
|
||||
write_desc_source = axis_ep.AXIStreamSource()
|
||||
|
||||
write_desc_source_logic = write_desc_source.create_logic(
|
||||
user_clk,
|
||||
user_reset,
|
||||
tdata=(s_axis_write_desc_pcie_addr, s_axis_write_desc_axi_addr, s_axis_write_desc_len, s_axis_write_desc_tag),
|
||||
tvalid=s_axis_write_desc_valid,
|
||||
tready=s_axis_write_desc_ready,
|
||||
name='write_desc_source'
|
||||
)
|
||||
|
||||
write_desc_status_sink = axis_ep.AXIStreamSink()
|
||||
|
||||
write_desc_status_sink_logic = write_desc_status_sink.create_logic(
|
||||
user_clk,
|
||||
user_reset,
|
||||
tdata=(m_axis_write_desc_status_tag,),
|
||||
tvalid=m_axis_write_desc_status_valid,
|
||||
name='write_desc_status_sink'
|
||||
)
|
||||
|
||||
# PCIe devices
|
||||
rc = pcie.RootComplex()
|
||||
|
||||
mem_base, mem_data = rc.alloc_region(16*1024*1024)
|
||||
|
||||
dev = pcie_us.UltrascalePCIe()
|
||||
|
||||
dev.pcie_generation = 3
|
||||
dev.pcie_link_width = 8
|
||||
dev.user_clock_frequency = 250e6
|
||||
|
||||
rc.make_port().connect(dev)
|
||||
|
||||
cq_pause = Signal(bool(0))
|
||||
cc_pause = Signal(bool(0))
|
||||
rq_pause = Signal(bool(0))
|
||||
rc_pause = Signal(bool(0))
|
||||
|
||||
pcie_logic = dev.create_logic(
|
||||
# Completer reQuest Interface
|
||||
m_axis_cq_tdata=Signal(intbv(0)[AXIS_PCIE_DATA_WIDTH:]),
|
||||
m_axis_cq_tuser=Signal(intbv(0)[85:]),
|
||||
m_axis_cq_tlast=Signal(bool(0)),
|
||||
m_axis_cq_tkeep=Signal(intbv(0)[AXIS_PCIE_KEEP_WIDTH:]),
|
||||
m_axis_cq_tvalid=Signal(bool(0)),
|
||||
m_axis_cq_tready=Signal(bool(1)),
|
||||
#pcie_cq_np_req=pcie_cq_np_req,
|
||||
#pcie_cq_np_req_count=pcie_cq_np_req_count,
|
||||
|
||||
# Completer Completion Interface
|
||||
s_axis_cc_tdata=Signal(intbv(0)[AXIS_PCIE_DATA_WIDTH:]),
|
||||
s_axis_cc_tuser=Signal(intbv(0)[33:]),
|
||||
s_axis_cc_tlast=Signal(bool(0)),
|
||||
s_axis_cc_tkeep=Signal(intbv(0)[AXIS_PCIE_KEEP_WIDTH:]),
|
||||
s_axis_cc_tvalid=Signal(bool(0)),
|
||||
s_axis_cc_tready=Signal(bool(0)),
|
||||
|
||||
# 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_num=pcie_rq_seq_num,
|
||||
# pcie_rq_seq_num_vld=pcie_rq_seq_num_vld,
|
||||
# pcie_rq_tag=pcie_rq_tag,
|
||||
# pcie_rq_tag_av=pcie_rq_tag_av,
|
||||
# pcie_rq_tag_vld=pcie_rq_tag_vld,
|
||||
|
||||
# Requester Completion Interface
|
||||
m_axis_rc_tdata=Signal(intbv(0)[AXIS_PCIE_DATA_WIDTH:]),
|
||||
m_axis_rc_tuser=Signal(intbv(0)[75:]),
|
||||
m_axis_rc_tlast=Signal(bool(0)),
|
||||
m_axis_rc_tkeep=Signal(intbv(0)[AXIS_PCIE_KEEP_WIDTH:]),
|
||||
m_axis_rc_tvalid=Signal(bool(0)),
|
||||
m_axis_rc_tready=Signal(bool(0)),
|
||||
|
||||
# Transmit Flow Control Interface
|
||||
# pcie_tfc_nph_av=pcie_tfc_nph_av,
|
||||
# pcie_tfc_npd_av=pcie_tfc_npd_av,
|
||||
|
||||
# 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_per_function_update_done=cfg_per_function_update_done,
|
||||
# cfg_per_function_number=cfg_per_function_number,
|
||||
# cfg_per_function_output_request=cfg_per_function_output_request,
|
||||
# cfg_dsn=cfg_dsn,
|
||||
# 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=cfg_err_cor_in,
|
||||
# cfg_err_uncor_in=cfg_err_uncor_in,
|
||||
# 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,
|
||||
|
||||
# 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,
|
||||
|
||||
cq_pause=cq_pause,
|
||||
cc_pause=cc_pause,
|
||||
rq_pause=rq_pause,
|
||||
rc_pause=rc_pause
|
||||
)
|
||||
|
||||
# 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,
|
||||
m_axis_rq_tdata=m_axis_rq_tdata,
|
||||
m_axis_rq_tkeep=m_axis_rq_tkeep,
|
||||
m_axis_rq_tvalid=m_axis_rq_tvalid,
|
||||
m_axis_rq_tready=m_axis_rq_tready,
|
||||
m_axis_rq_tlast=m_axis_rq_tlast,
|
||||
m_axis_rq_tuser=m_axis_rq_tuser,
|
||||
s_axis_write_desc_pcie_addr=s_axis_write_desc_pcie_addr,
|
||||
s_axis_write_desc_axi_addr=s_axis_write_desc_axi_addr,
|
||||
s_axis_write_desc_len=s_axis_write_desc_len,
|
||||
s_axis_write_desc_tag=s_axis_write_desc_tag,
|
||||
s_axis_write_desc_valid=s_axis_write_desc_valid,
|
||||
s_axis_write_desc_ready=s_axis_write_desc_ready,
|
||||
m_axis_write_desc_status_tag=m_axis_write_desc_status_tag,
|
||||
m_axis_write_desc_status_valid=m_axis_write_desc_status_valid,
|
||||
m_axi_arid=m_axi_arid,
|
||||
m_axi_araddr=m_axi_araddr,
|
||||
m_axi_arlen=m_axi_arlen,
|
||||
m_axi_arsize=m_axi_arsize,
|
||||
m_axi_arburst=m_axi_arburst,
|
||||
m_axi_arlock=m_axi_arlock,
|
||||
m_axi_arcache=m_axi_arcache,
|
||||
m_axi_arprot=m_axi_arprot,
|
||||
m_axi_arvalid=m_axi_arvalid,
|
||||
m_axi_arready=m_axi_arready,
|
||||
m_axi_rid=m_axi_rid,
|
||||
m_axi_rdata=m_axi_rdata,
|
||||
m_axi_rresp=m_axi_rresp,
|
||||
m_axi_rlast=m_axi_rlast,
|
||||
m_axi_rvalid=m_axi_rvalid,
|
||||
m_axi_rready=m_axi_rready,
|
||||
enable=enable,
|
||||
requester_id=requester_id,
|
||||
requester_id_enable=requester_id_enable,
|
||||
max_payload_size=max_payload_size
|
||||
)
|
||||
|
||||
@always(delay(4))
|
||||
def clkgen():
|
||||
clk.next = not clk
|
||||
|
||||
@always_comb
|
||||
def clk_logic():
|
||||
sys_clk.next = clk
|
||||
sys_reset.next = not rst
|
||||
|
||||
cq_pause_toggle = Signal(bool(0))
|
||||
cc_pause_toggle = Signal(bool(0))
|
||||
rq_pause_toggle = Signal(bool(0))
|
||||
rc_pause_toggle = Signal(bool(0))
|
||||
|
||||
@instance
|
||||
def pause_toggle():
|
||||
while True:
|
||||
if (cq_pause_toggle or cc_pause_toggle or rq_pause_toggle or rc_pause_toggle):
|
||||
cq_pause.next = cq_pause_toggle
|
||||
cc_pause.next = cc_pause_toggle
|
||||
rq_pause.next = rq_pause_toggle
|
||||
rc_pause.next = rc_pause_toggle
|
||||
|
||||
yield user_clk.posedge
|
||||
yield user_clk.posedge
|
||||
yield user_clk.posedge
|
||||
|
||||
cq_pause.next = 0
|
||||
cc_pause.next = 0
|
||||
rq_pause.next = 0
|
||||
rc_pause.next = 0
|
||||
|
||||
yield user_clk.posedge
|
||||
|
||||
@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
|
||||
|
||||
cur_tag = 1
|
||||
|
||||
max_payload_size.next = 0
|
||||
|
||||
enable.next = 1
|
||||
|
||||
yield user_clk.posedge
|
||||
print("test 1: enumeration")
|
||||
current_test.next = 1
|
||||
|
||||
yield rc.enumerate(enable_bus_mastering=True)
|
||||
|
||||
yield delay(100)
|
||||
|
||||
yield user_clk.posedge
|
||||
print("test 2: PCIe write")
|
||||
current_test.next = 2
|
||||
|
||||
pcie_addr = 0x00000000
|
||||
axi_addr = 0x00000000
|
||||
test_data = b'\x11\x22\x33\x44'
|
||||
|
||||
axi_ram_inst.write_mem(axi_addr, test_data)
|
||||
|
||||
data = axi_ram_inst.read_mem(axi_addr, 32)
|
||||
for i in range(0, len(data), 16):
|
||||
print(" ".join(("{:02x}".format(c) for c in bytearray(data[i:i+16]))))
|
||||
|
||||
write_desc_source.send([(mem_base+pcie_addr, axi_addr, len(test_data), cur_tag)])
|
||||
|
||||
yield write_desc_status_sink.wait(1000)
|
||||
yield delay(50)
|
||||
|
||||
status = write_desc_status_sink.recv()
|
||||
|
||||
print(status)
|
||||
|
||||
assert status.data[0][0] == cur_tag
|
||||
|
||||
data = mem_data[pcie_addr:pcie_addr+32]
|
||||
for i in range(0, len(data), 16):
|
||||
print(" ".join(("{:02x}".format(c) for c in bytearray(data[i:i+16]))))
|
||||
|
||||
assert mem_data[pcie_addr:pcie_addr+len(test_data)] == test_data
|
||||
|
||||
cur_tag = (cur_tag + 1) % 256
|
||||
|
||||
yield delay(100)
|
||||
|
||||
yield user_clk.posedge
|
||||
print("test 3: various writes")
|
||||
current_test.next = 3
|
||||
|
||||
for length in list(range(1,35))+list(range(128-4,128+4))+[1024]:
|
||||
for pcie_offset in list(range(8,13))+list(range(4096-4,4096+4)):
|
||||
for axi_offset in list(range(8,41))+list(range(4096-32,4096)):
|
||||
for pause in [False, True]:
|
||||
print("length %d, pcie_offset %d, axi_offset %d"% (length, pcie_offset, axi_offset))
|
||||
#pcie_addr = length * 0x100000000 + pcie_offset * 0x10000 + offset
|
||||
pcie_addr = pcie_offset
|
||||
axi_addr = axi_offset
|
||||
test_data = bytearray([x%256 for x in range(length)])
|
||||
|
||||
axi_ram_inst.write_mem(axi_addr & 0xffff80, b'\x55'*(len(test_data)+256))
|
||||
mem_data[(pcie_addr-1) & 0xffff80:((pcie_addr-1) & 0xffff80)+len(test_data)+256] = b'\xaa'*(len(test_data)+256)
|
||||
axi_ram_inst.write_mem(axi_addr, test_data)
|
||||
|
||||
data = axi_ram_inst.read_mem(axi_addr&0xfffff0, 64)
|
||||
for i in range(0, len(data), 16):
|
||||
print(" ".join(("{:02x}".format(c) for c in bytearray(data[i:i+16]))))
|
||||
|
||||
rq_pause_toggle.next = pause
|
||||
|
||||
write_desc_source.send([(mem_base+pcie_addr, axi_addr, len(test_data), cur_tag)])
|
||||
|
||||
yield write_desc_status_sink.wait(4000)
|
||||
yield delay(50)
|
||||
|
||||
rq_pause_toggle.next = 0
|
||||
|
||||
status = write_desc_status_sink.recv()
|
||||
|
||||
print(status)
|
||||
|
||||
assert status.data[0][0] == cur_tag
|
||||
|
||||
data = mem_data[pcie_addr&0xfffff0:(pcie_addr&0xfffff0)+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[pcie_addr-1:pcie_addr+len(test_data)+1] == b'\xaa'+test_data+b'\xaa'
|
||||
|
||||
cur_tag = (cur_tag + 1) % 256
|
||||
|
||||
yield delay(100)
|
||||
|
||||
raise StopSimulation
|
||||
|
||||
return instances()
|
||||
|
||||
def test_bench():
|
||||
sim = Simulation(bench())
|
||||
sim.run()
|
||||
|
||||
if __name__ == '__main__':
|
||||
print("Running test...")
|
||||
test_bench()
|
188
fpga/lib/pcie/tb/test_pcie_us_axi_dma_wr_256.v
Normal file
188
fpga/lib/pcie/tb/test_pcie_us_axi_dma_wr_256.v
Normal file
@ -0,0 +1,188 @@
|
||||
/*
|
||||
|
||||
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 pcie_us_axi_dma_wr
|
||||
*/
|
||||
module test_pcie_us_axi_dma_wr_256;
|
||||
|
||||
// Parameters
|
||||
parameter AXIS_PCIE_DATA_WIDTH = 256;
|
||||
parameter AXIS_PCIE_KEEP_WIDTH = (AXIS_PCIE_DATA_WIDTH/32);
|
||||
parameter AXI_DATA_WIDTH = AXIS_PCIE_DATA_WIDTH;
|
||||
parameter AXI_ADDR_WIDTH = 64;
|
||||
parameter AXI_STRB_WIDTH = (AXI_DATA_WIDTH/8);
|
||||
parameter AXI_ID_WIDTH = 8;
|
||||
parameter AXI_MAX_BURST_LEN = 256;
|
||||
parameter PCIE_ADDR_WIDTH = 64;
|
||||
parameter LEN_WIDTH = 20;
|
||||
parameter TAG_WIDTH = 8;
|
||||
|
||||
// Inputs
|
||||
reg clk = 0;
|
||||
reg rst = 0;
|
||||
reg [7:0] current_test = 0;
|
||||
|
||||
reg m_axis_rq_tready = 0;
|
||||
reg [PCIE_ADDR_WIDTH-1:0] s_axis_write_desc_pcie_addr = 0;
|
||||
reg [AXI_ADDR_WIDTH-1:0] s_axis_write_desc_axi_addr = 0;
|
||||
reg [LEN_WIDTH-1:0] s_axis_write_desc_len = 0;
|
||||
reg [TAG_WIDTH-1:0] s_axis_write_desc_tag = 0;
|
||||
reg s_axis_write_desc_valid = 0;
|
||||
reg m_axi_arready = 0;
|
||||
reg [AXI_ID_WIDTH-1:0] m_axi_rid = 0;
|
||||
reg [AXI_DATA_WIDTH-1:0] m_axi_rdata = 0;
|
||||
reg [1:0] m_axi_rresp = 0;
|
||||
reg m_axi_rlast = 0;
|
||||
reg m_axi_rvalid = 0;
|
||||
reg enable = 0;
|
||||
reg [15:0] requester_id = 0;
|
||||
reg requester_id_enable = 0;
|
||||
reg [2:0] max_payload_size = 0;
|
||||
|
||||
// Outputs
|
||||
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_tvalid;
|
||||
wire m_axis_rq_tlast;
|
||||
wire [59:0] m_axis_rq_tuser;
|
||||
wire s_axis_write_desc_ready;
|
||||
wire [TAG_WIDTH-1:0] m_axis_write_desc_status_tag;
|
||||
wire m_axis_write_desc_status_valid;
|
||||
wire [AXI_ID_WIDTH-1:0] m_axi_arid;
|
||||
wire [AXI_ADDR_WIDTH-1:0] m_axi_araddr;
|
||||
wire [7:0] m_axi_arlen;
|
||||
wire [2:0] m_axi_arsize;
|
||||
wire [1:0] m_axi_arburst;
|
||||
wire m_axi_arlock;
|
||||
wire [3:0] m_axi_arcache;
|
||||
wire [2:0] m_axi_arprot;
|
||||
wire m_axi_arvalid;
|
||||
wire m_axi_rready;
|
||||
|
||||
initial begin
|
||||
// myhdl integration
|
||||
$from_myhdl(
|
||||
clk,
|
||||
rst,
|
||||
current_test,
|
||||
m_axis_rq_tready,
|
||||
s_axis_write_desc_pcie_addr,
|
||||
s_axis_write_desc_axi_addr,
|
||||
s_axis_write_desc_len,
|
||||
s_axis_write_desc_tag,
|
||||
s_axis_write_desc_valid,
|
||||
m_axi_arready,
|
||||
m_axi_rid,
|
||||
m_axi_rdata,
|
||||
m_axi_rresp,
|
||||
m_axi_rlast,
|
||||
m_axi_rvalid,
|
||||
enable,
|
||||
requester_id,
|
||||
requester_id_enable,
|
||||
max_payload_size
|
||||
);
|
||||
$to_myhdl(
|
||||
m_axis_rq_tdata,
|
||||
m_axis_rq_tkeep,
|
||||
m_axis_rq_tvalid,
|
||||
m_axis_rq_tlast,
|
||||
m_axis_rq_tuser,
|
||||
s_axis_write_desc_ready,
|
||||
m_axis_write_desc_status_tag,
|
||||
m_axis_write_desc_status_valid,
|
||||
m_axi_arid,
|
||||
m_axi_araddr,
|
||||
m_axi_arlen,
|
||||
m_axi_arsize,
|
||||
m_axi_arburst,
|
||||
m_axi_arlock,
|
||||
m_axi_arcache,
|
||||
m_axi_arprot,
|
||||
m_axi_arvalid,
|
||||
m_axi_rready
|
||||
);
|
||||
|
||||
// dump file
|
||||
$dumpfile("test_pcie_us_axi_dma_wr_256.lxt");
|
||||
$dumpvars(0, test_pcie_us_axi_dma_wr_256);
|
||||
end
|
||||
|
||||
pcie_us_axi_dma_wr #(
|
||||
.AXIS_PCIE_DATA_WIDTH(AXIS_PCIE_DATA_WIDTH),
|
||||
.AXIS_PCIE_KEEP_WIDTH(AXIS_PCIE_KEEP_WIDTH),
|
||||
.AXI_DATA_WIDTH(AXI_DATA_WIDTH),
|
||||
.AXI_ADDR_WIDTH(AXI_ADDR_WIDTH),
|
||||
.AXI_STRB_WIDTH(AXI_STRB_WIDTH),
|
||||
.AXI_ID_WIDTH(AXI_ID_WIDTH),
|
||||
.AXI_MAX_BURST_LEN(AXI_MAX_BURST_LEN),
|
||||
.PCIE_ADDR_WIDTH(PCIE_ADDR_WIDTH),
|
||||
.LEN_WIDTH(LEN_WIDTH),
|
||||
.TAG_WIDTH(TAG_WIDTH)
|
||||
)
|
||||
UUT (
|
||||
.clk(clk),
|
||||
.rst(rst),
|
||||
.m_axis_rq_tdata(m_axis_rq_tdata),
|
||||
.m_axis_rq_tkeep(m_axis_rq_tkeep),
|
||||
.m_axis_rq_tvalid(m_axis_rq_tvalid),
|
||||
.m_axis_rq_tready(m_axis_rq_tready),
|
||||
.m_axis_rq_tlast(m_axis_rq_tlast),
|
||||
.m_axis_rq_tuser(m_axis_rq_tuser),
|
||||
.s_axis_write_desc_pcie_addr(s_axis_write_desc_pcie_addr),
|
||||
.s_axis_write_desc_axi_addr(s_axis_write_desc_axi_addr),
|
||||
.s_axis_write_desc_len(s_axis_write_desc_len),
|
||||
.s_axis_write_desc_tag(s_axis_write_desc_tag),
|
||||
.s_axis_write_desc_valid(s_axis_write_desc_valid),
|
||||
.s_axis_write_desc_ready(s_axis_write_desc_ready),
|
||||
.m_axis_write_desc_status_tag(m_axis_write_desc_status_tag),
|
||||
.m_axis_write_desc_status_valid(m_axis_write_desc_status_valid),
|
||||
.m_axi_arid(m_axi_arid),
|
||||
.m_axi_araddr(m_axi_araddr),
|
||||
.m_axi_arlen(m_axi_arlen),
|
||||
.m_axi_arsize(m_axi_arsize),
|
||||
.m_axi_arburst(m_axi_arburst),
|
||||
.m_axi_arlock(m_axi_arlock),
|
||||
.m_axi_arcache(m_axi_arcache),
|
||||
.m_axi_arprot(m_axi_arprot),
|
||||
.m_axi_arvalid(m_axi_arvalid),
|
||||
.m_axi_arready(m_axi_arready),
|
||||
.m_axi_rid(m_axi_rid),
|
||||
.m_axi_rdata(m_axi_rdata),
|
||||
.m_axi_rresp(m_axi_rresp),
|
||||
.m_axi_rlast(m_axi_rlast),
|
||||
.m_axi_rvalid(m_axi_rvalid),
|
||||
.m_axi_rready(m_axi_rready),
|
||||
.enable(enable),
|
||||
.requester_id(requester_id),
|
||||
.requester_id_enable(requester_id_enable),
|
||||
.max_payload_size(max_payload_size)
|
||||
);
|
||||
|
||||
endmodule
|
450
fpga/lib/pcie/tb/test_pcie_us_axi_dma_wr_64.py
Executable file
450
fpga/lib/pcie/tb/test_pcie_us_axi_dma_wr_64.py
Executable file
@ -0,0 +1,450 @@
|
||||
#!/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 pcie
|
||||
import pcie_us
|
||||
import axi
|
||||
import axis_ep
|
||||
|
||||
module = 'pcie_us_axi_dma_wr'
|
||||
testbench = 'test_%s_64' % module
|
||||
|
||||
srcs = []
|
||||
|
||||
srcs.append("../rtl/%s.v" % module)
|
||||
srcs.append("%s.v" % testbench)
|
||||
|
||||
src = ' '.join(srcs)
|
||||
|
||||
build_cmd = "iverilog -o %s.vvp %s" % (testbench, src)
|
||||
|
||||
def bench():
|
||||
|
||||
# Parameters
|
||||
AXIS_PCIE_DATA_WIDTH = 64
|
||||
AXIS_PCIE_KEEP_WIDTH = (AXIS_PCIE_DATA_WIDTH/32)
|
||||
AXI_DATA_WIDTH = AXIS_PCIE_DATA_WIDTH
|
||||
AXI_ADDR_WIDTH = 64
|
||||
AXI_STRB_WIDTH = (AXI_DATA_WIDTH/8)
|
||||
AXI_ID_WIDTH = 8
|
||||
AXI_MAX_BURST_LEN = 256
|
||||
PCIE_ADDR_WIDTH = 64
|
||||
LEN_WIDTH = 20
|
||||
TAG_WIDTH = 8
|
||||
|
||||
# Inputs
|
||||
clk = Signal(bool(0))
|
||||
rst = Signal(bool(0))
|
||||
current_test = Signal(intbv(0)[8:])
|
||||
|
||||
m_axis_rq_tready = Signal(bool(0))
|
||||
s_axis_write_desc_pcie_addr = Signal(intbv(0)[PCIE_ADDR_WIDTH:])
|
||||
s_axis_write_desc_axi_addr = Signal(intbv(0)[AXI_ADDR_WIDTH:])
|
||||
s_axis_write_desc_len = Signal(intbv(0)[LEN_WIDTH:])
|
||||
s_axis_write_desc_tag = Signal(intbv(0)[TAG_WIDTH:])
|
||||
s_axis_write_desc_valid = Signal(bool(0))
|
||||
m_axi_arready = Signal(bool(0))
|
||||
m_axi_rid = Signal(intbv(0)[AXI_ID_WIDTH:])
|
||||
m_axi_rdata = Signal(intbv(0)[AXI_DATA_WIDTH:])
|
||||
m_axi_rresp = Signal(intbv(0)[2:])
|
||||
m_axi_rlast = Signal(bool(0))
|
||||
m_axi_rvalid = Signal(bool(0))
|
||||
enable = Signal(bool(0))
|
||||
requester_id = Signal(intbv(0)[16:])
|
||||
requester_id_enable = Signal(bool(0))
|
||||
max_payload_size = Signal(intbv(0)[3:])
|
||||
|
||||
# Outputs
|
||||
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_tvalid = Signal(bool(0))
|
||||
m_axis_rq_tlast = Signal(bool(0))
|
||||
m_axis_rq_tuser = Signal(intbv(0)[60:])
|
||||
s_axis_write_desc_ready = Signal(bool(0))
|
||||
m_axis_write_desc_status_tag = Signal(intbv(0)[TAG_WIDTH:])
|
||||
m_axis_write_desc_status_valid = Signal(bool(0))
|
||||
m_axi_arid = Signal(intbv(0)[AXI_ID_WIDTH:])
|
||||
m_axi_araddr = Signal(intbv(0)[AXI_ADDR_WIDTH:])
|
||||
m_axi_arlen = Signal(intbv(0)[8:])
|
||||
m_axi_arsize = Signal(intbv(3)[3:])
|
||||
m_axi_arburst = Signal(intbv(1)[2:])
|
||||
m_axi_arlock = Signal(bool(0))
|
||||
m_axi_arcache = Signal(intbv(3)[4:])
|
||||
m_axi_arprot = Signal(intbv(2)[3:])
|
||||
m_axi_arvalid = Signal(bool(0))
|
||||
m_axi_rready = Signal(bool(0))
|
||||
|
||||
# Clock and Reset Interface
|
||||
user_clk=Signal(bool(0))
|
||||
user_reset=Signal(bool(0))
|
||||
sys_clk=Signal(bool(0))
|
||||
sys_reset=Signal(bool(0))
|
||||
|
||||
# AXI4 RAM model
|
||||
axi_ram_inst = axi.AXIRam(2**16)
|
||||
|
||||
axi_ram_port0 = axi_ram_inst.create_port(
|
||||
user_clk,
|
||||
s_axi_arid=m_axi_arid,
|
||||
s_axi_araddr=m_axi_araddr,
|
||||
s_axi_arlen=m_axi_arlen,
|
||||
s_axi_arsize=m_axi_arsize,
|
||||
s_axi_arburst=m_axi_arburst,
|
||||
s_axi_arlock=m_axi_arlock,
|
||||
s_axi_arcache=m_axi_arcache,
|
||||
s_axi_arprot=m_axi_arprot,
|
||||
s_axi_arvalid=m_axi_arvalid,
|
||||
s_axi_arready=m_axi_arready,
|
||||
s_axi_rid=m_axi_rid,
|
||||
s_axi_rdata=m_axi_rdata,
|
||||
s_axi_rresp=m_axi_rresp,
|
||||
s_axi_rlast=m_axi_rlast,
|
||||
s_axi_rvalid=m_axi_rvalid,
|
||||
s_axi_rready=m_axi_rready,
|
||||
name='port0'
|
||||
)
|
||||
|
||||
write_desc_source = axis_ep.AXIStreamSource()
|
||||
|
||||
write_desc_source_logic = write_desc_source.create_logic(
|
||||
user_clk,
|
||||
user_reset,
|
||||
tdata=(s_axis_write_desc_pcie_addr, s_axis_write_desc_axi_addr, s_axis_write_desc_len, s_axis_write_desc_tag),
|
||||
tvalid=s_axis_write_desc_valid,
|
||||
tready=s_axis_write_desc_ready,
|
||||
name='write_desc_source'
|
||||
)
|
||||
|
||||
write_desc_status_sink = axis_ep.AXIStreamSink()
|
||||
|
||||
write_desc_status_sink_logic = write_desc_status_sink.create_logic(
|
||||
user_clk,
|
||||
user_reset,
|
||||
tdata=(m_axis_write_desc_status_tag,),
|
||||
tvalid=m_axis_write_desc_status_valid,
|
||||
name='write_desc_status_sink'
|
||||
)
|
||||
|
||||
# PCIe devices
|
||||
rc = pcie.RootComplex()
|
||||
|
||||
mem_base, mem_data = rc.alloc_region(16*1024*1024)
|
||||
|
||||
dev = pcie_us.UltrascalePCIe()
|
||||
|
||||
dev.pcie_generation = 3
|
||||
dev.pcie_link_width = 2
|
||||
dev.user_clock_frequency = 250e6
|
||||
|
||||
rc.make_port().connect(dev)
|
||||
|
||||
cq_pause = Signal(bool(0))
|
||||
cc_pause = Signal(bool(0))
|
||||
rq_pause = Signal(bool(0))
|
||||
rc_pause = Signal(bool(0))
|
||||
|
||||
pcie_logic = dev.create_logic(
|
||||
# Completer reQuest Interface
|
||||
m_axis_cq_tdata=Signal(intbv(0)[AXIS_PCIE_DATA_WIDTH:]),
|
||||
m_axis_cq_tuser=Signal(intbv(0)[85:]),
|
||||
m_axis_cq_tlast=Signal(bool(0)),
|
||||
m_axis_cq_tkeep=Signal(intbv(0)[AXIS_PCIE_KEEP_WIDTH:]),
|
||||
m_axis_cq_tvalid=Signal(bool(0)),
|
||||
m_axis_cq_tready=Signal(bool(1)),
|
||||
#pcie_cq_np_req=pcie_cq_np_req,
|
||||
#pcie_cq_np_req_count=pcie_cq_np_req_count,
|
||||
|
||||
# Completer Completion Interface
|
||||
s_axis_cc_tdata=Signal(intbv(0)[AXIS_PCIE_DATA_WIDTH:]),
|
||||
s_axis_cc_tuser=Signal(intbv(0)[33:]),
|
||||
s_axis_cc_tlast=Signal(bool(0)),
|
||||
s_axis_cc_tkeep=Signal(intbv(0)[AXIS_PCIE_KEEP_WIDTH:]),
|
||||
s_axis_cc_tvalid=Signal(bool(0)),
|
||||
s_axis_cc_tready=Signal(bool(0)),
|
||||
|
||||
# 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_num=pcie_rq_seq_num,
|
||||
# pcie_rq_seq_num_vld=pcie_rq_seq_num_vld,
|
||||
# pcie_rq_tag=pcie_rq_tag,
|
||||
# pcie_rq_tag_av=pcie_rq_tag_av,
|
||||
# pcie_rq_tag_vld=pcie_rq_tag_vld,
|
||||
|
||||
# Requester Completion Interface
|
||||
m_axis_rc_tdata=Signal(intbv(0)[AXIS_PCIE_DATA_WIDTH:]),
|
||||
m_axis_rc_tuser=Signal(intbv(0)[75:]),
|
||||
m_axis_rc_tlast=Signal(bool(0)),
|
||||
m_axis_rc_tkeep=Signal(intbv(0)[AXIS_PCIE_KEEP_WIDTH:]),
|
||||
m_axis_rc_tvalid=Signal(bool(0)),
|
||||
m_axis_rc_tready=Signal(bool(0)),
|
||||
|
||||
# Transmit Flow Control Interface
|
||||
# pcie_tfc_nph_av=pcie_tfc_nph_av,
|
||||
# pcie_tfc_npd_av=pcie_tfc_npd_av,
|
||||
|
||||
# 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_per_function_update_done=cfg_per_function_update_done,
|
||||
# cfg_per_function_number=cfg_per_function_number,
|
||||
# cfg_per_function_output_request=cfg_per_function_output_request,
|
||||
# cfg_dsn=cfg_dsn,
|
||||
# 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=cfg_err_cor_in,
|
||||
# cfg_err_uncor_in=cfg_err_uncor_in,
|
||||
# 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,
|
||||
|
||||
# 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,
|
||||
|
||||
cq_pause=cq_pause,
|
||||
cc_pause=cc_pause,
|
||||
rq_pause=rq_pause,
|
||||
rc_pause=rc_pause
|
||||
)
|
||||
|
||||
# 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,
|
||||
m_axis_rq_tdata=m_axis_rq_tdata,
|
||||
m_axis_rq_tkeep=m_axis_rq_tkeep,
|
||||
m_axis_rq_tvalid=m_axis_rq_tvalid,
|
||||
m_axis_rq_tready=m_axis_rq_tready,
|
||||
m_axis_rq_tlast=m_axis_rq_tlast,
|
||||
m_axis_rq_tuser=m_axis_rq_tuser,
|
||||
s_axis_write_desc_pcie_addr=s_axis_write_desc_pcie_addr,
|
||||
s_axis_write_desc_axi_addr=s_axis_write_desc_axi_addr,
|
||||
s_axis_write_desc_len=s_axis_write_desc_len,
|
||||
s_axis_write_desc_tag=s_axis_write_desc_tag,
|
||||
s_axis_write_desc_valid=s_axis_write_desc_valid,
|
||||
s_axis_write_desc_ready=s_axis_write_desc_ready,
|
||||
m_axis_write_desc_status_tag=m_axis_write_desc_status_tag,
|
||||
m_axis_write_desc_status_valid=m_axis_write_desc_status_valid,
|
||||
m_axi_arid=m_axi_arid,
|
||||
m_axi_araddr=m_axi_araddr,
|
||||
m_axi_arlen=m_axi_arlen,
|
||||
m_axi_arsize=m_axi_arsize,
|
||||
m_axi_arburst=m_axi_arburst,
|
||||
m_axi_arlock=m_axi_arlock,
|
||||
m_axi_arcache=m_axi_arcache,
|
||||
m_axi_arprot=m_axi_arprot,
|
||||
m_axi_arvalid=m_axi_arvalid,
|
||||
m_axi_arready=m_axi_arready,
|
||||
m_axi_rid=m_axi_rid,
|
||||
m_axi_rdata=m_axi_rdata,
|
||||
m_axi_rresp=m_axi_rresp,
|
||||
m_axi_rlast=m_axi_rlast,
|
||||
m_axi_rvalid=m_axi_rvalid,
|
||||
m_axi_rready=m_axi_rready,
|
||||
enable=enable,
|
||||
requester_id=requester_id,
|
||||
requester_id_enable=requester_id_enable,
|
||||
max_payload_size=max_payload_size
|
||||
)
|
||||
|
||||
@always(delay(4))
|
||||
def clkgen():
|
||||
clk.next = not clk
|
||||
|
||||
@always_comb
|
||||
def clk_logic():
|
||||
sys_clk.next = clk
|
||||
sys_reset.next = not rst
|
||||
|
||||
cq_pause_toggle = Signal(bool(0))
|
||||
cc_pause_toggle = Signal(bool(0))
|
||||
rq_pause_toggle = Signal(bool(0))
|
||||
rc_pause_toggle = Signal(bool(0))
|
||||
|
||||
@instance
|
||||
def pause_toggle():
|
||||
while True:
|
||||
if (cq_pause_toggle or cc_pause_toggle or rq_pause_toggle or rc_pause_toggle):
|
||||
cq_pause.next = cq_pause_toggle
|
||||
cc_pause.next = cc_pause_toggle
|
||||
rq_pause.next = rq_pause_toggle
|
||||
rc_pause.next = rc_pause_toggle
|
||||
|
||||
yield user_clk.posedge
|
||||
yield user_clk.posedge
|
||||
yield user_clk.posedge
|
||||
|
||||
cq_pause.next = 0
|
||||
cc_pause.next = 0
|
||||
rq_pause.next = 0
|
||||
rc_pause.next = 0
|
||||
|
||||
yield user_clk.posedge
|
||||
|
||||
@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
|
||||
|
||||
cur_tag = 1
|
||||
|
||||
max_payload_size.next = 0
|
||||
|
||||
enable.next = 1
|
||||
|
||||
yield user_clk.posedge
|
||||
print("test 1: enumeration")
|
||||
current_test.next = 1
|
||||
|
||||
yield rc.enumerate(enable_bus_mastering=True)
|
||||
|
||||
yield delay(100)
|
||||
|
||||
yield user_clk.posedge
|
||||
print("test 2: PCIe write")
|
||||
current_test.next = 2
|
||||
|
||||
pcie_addr = 0x00000000
|
||||
axi_addr = 0x00000000
|
||||
test_data = b'\x11\x22\x33\x44'
|
||||
|
||||
axi_ram_inst.write_mem(axi_addr, test_data)
|
||||
|
||||
data = axi_ram_inst.read_mem(axi_addr, 32)
|
||||
for i in range(0, len(data), 16):
|
||||
print(" ".join(("{:02x}".format(c) for c in bytearray(data[i:i+16]))))
|
||||
|
||||
write_desc_source.send([(mem_base+pcie_addr, axi_addr, len(test_data), cur_tag)])
|
||||
|
||||
yield write_desc_status_sink.wait(1000)
|
||||
yield delay(50)
|
||||
|
||||
status = write_desc_status_sink.recv()
|
||||
|
||||
print(status)
|
||||
|
||||
assert status.data[0][0] == cur_tag
|
||||
|
||||
data = mem_data[pcie_addr:pcie_addr+32]
|
||||
for i in range(0, len(data), 16):
|
||||
print(" ".join(("{:02x}".format(c) for c in bytearray(data[i:i+16]))))
|
||||
|
||||
assert mem_data[pcie_addr:pcie_addr+len(test_data)] == test_data
|
||||
|
||||
cur_tag = (cur_tag + 1) % 256
|
||||
|
||||
yield delay(100)
|
||||
|
||||
yield user_clk.posedge
|
||||
print("test 3: various writes")
|
||||
current_test.next = 3
|
||||
|
||||
for length in list(range(1,11))+list(range(128-4,128+4))+[1024]:
|
||||
for pcie_offset in list(range(8,13))+list(range(4096-4,4096+4)):
|
||||
for axi_offset in list(range(8,17))+list(range(4096-8,4096)):
|
||||
for pause in [False, True]:
|
||||
print("length %d, pcie_offset %d, axi_offset %d"% (length, pcie_offset, axi_offset))
|
||||
#pcie_addr = length * 0x100000000 + pcie_offset * 0x10000 + offset
|
||||
pcie_addr = pcie_offset
|
||||
axi_addr = axi_offset
|
||||
test_data = bytearray([x%256 for x in range(length)])
|
||||
|
||||
axi_ram_inst.write_mem(axi_addr & 0xffff80, b'\x55'*(len(test_data)+256))
|
||||
mem_data[(pcie_addr-1) & 0xffff80:((pcie_addr-1) & 0xffff80)+len(test_data)+256] = b'\xaa'*(len(test_data)+256)
|
||||
axi_ram_inst.write_mem(axi_addr, test_data)
|
||||
|
||||
data = axi_ram_inst.read_mem(axi_addr&0xfffff0, 64)
|
||||
for i in range(0, len(data), 16):
|
||||
print(" ".join(("{:02x}".format(c) for c in bytearray(data[i:i+16]))))
|
||||
|
||||
rq_pause_toggle.next = pause
|
||||
|
||||
write_desc_source.send([(mem_base+pcie_addr, axi_addr, len(test_data), cur_tag)])
|
||||
|
||||
yield write_desc_status_sink.wait(4000)
|
||||
yield delay(50)
|
||||
|
||||
rq_pause_toggle.next = 0
|
||||
|
||||
status = write_desc_status_sink.recv()
|
||||
|
||||
print(status)
|
||||
|
||||
assert status.data[0][0] == cur_tag
|
||||
|
||||
data = mem_data[pcie_addr&0xfffff0:(pcie_addr&0xfffff0)+64]
|
||||
for i in range(0, len(data), 16):
|
||||
print(" ".join(("{:02x}".format(c) for c in bytearray(data[i:i+16]))))
|
||||
|
||||
print(mem_data[pcie_addr-1:pcie_addr+len(test_data)+1])
|
||||
assert mem_data[pcie_addr-1:pcie_addr+len(test_data)+1] == b'\xaa'+test_data+b'\xaa'
|
||||
|
||||
cur_tag = (cur_tag + 1) % 256
|
||||
|
||||
yield delay(100)
|
||||
|
||||
raise StopSimulation
|
||||
|
||||
return instances()
|
||||
|
||||
def test_bench():
|
||||
sim = Simulation(bench())
|
||||
sim.run()
|
||||
|
||||
if __name__ == '__main__':
|
||||
print("Running test...")
|
||||
test_bench()
|
188
fpga/lib/pcie/tb/test_pcie_us_axi_dma_wr_64.v
Normal file
188
fpga/lib/pcie/tb/test_pcie_us_axi_dma_wr_64.v
Normal file
@ -0,0 +1,188 @@
|
||||
/*
|
||||
|
||||
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 pcie_us_axi_dma_wr
|
||||
*/
|
||||
module test_pcie_us_axi_dma_wr_64;
|
||||
|
||||
// Parameters
|
||||
parameter AXIS_PCIE_DATA_WIDTH = 64;
|
||||
parameter AXIS_PCIE_KEEP_WIDTH = (AXIS_PCIE_DATA_WIDTH/32);
|
||||
parameter AXI_DATA_WIDTH = AXIS_PCIE_DATA_WIDTH;
|
||||
parameter AXI_ADDR_WIDTH = 64;
|
||||
parameter AXI_STRB_WIDTH = (AXI_DATA_WIDTH/8);
|
||||
parameter AXI_ID_WIDTH = 8;
|
||||
parameter AXI_MAX_BURST_LEN = 256;
|
||||
parameter PCIE_ADDR_WIDTH = 64;
|
||||
parameter LEN_WIDTH = 20;
|
||||
parameter TAG_WIDTH = 8;
|
||||
|
||||
// Inputs
|
||||
reg clk = 0;
|
||||
reg rst = 0;
|
||||
reg [7:0] current_test = 0;
|
||||
|
||||
reg m_axis_rq_tready = 0;
|
||||
reg [PCIE_ADDR_WIDTH-1:0] s_axis_write_desc_pcie_addr = 0;
|
||||
reg [AXI_ADDR_WIDTH-1:0] s_axis_write_desc_axi_addr = 0;
|
||||
reg [LEN_WIDTH-1:0] s_axis_write_desc_len = 0;
|
||||
reg [TAG_WIDTH-1:0] s_axis_write_desc_tag = 0;
|
||||
reg s_axis_write_desc_valid = 0;
|
||||
reg m_axi_arready = 0;
|
||||
reg [AXI_ID_WIDTH-1:0] m_axi_rid = 0;
|
||||
reg [AXI_DATA_WIDTH-1:0] m_axi_rdata = 0;
|
||||
reg [1:0] m_axi_rresp = 0;
|
||||
reg m_axi_rlast = 0;
|
||||
reg m_axi_rvalid = 0;
|
||||
reg enable = 0;
|
||||
reg [15:0] requester_id = 0;
|
||||
reg requester_id_enable = 0;
|
||||
reg [2:0] max_payload_size = 0;
|
||||
|
||||
// Outputs
|
||||
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_tvalid;
|
||||
wire m_axis_rq_tlast;
|
||||
wire [59:0] m_axis_rq_tuser;
|
||||
wire s_axis_write_desc_ready;
|
||||
wire [TAG_WIDTH-1:0] m_axis_write_desc_status_tag;
|
||||
wire m_axis_write_desc_status_valid;
|
||||
wire [AXI_ID_WIDTH-1:0] m_axi_arid;
|
||||
wire [AXI_ADDR_WIDTH-1:0] m_axi_araddr;
|
||||
wire [7:0] m_axi_arlen;
|
||||
wire [2:0] m_axi_arsize;
|
||||
wire [1:0] m_axi_arburst;
|
||||
wire m_axi_arlock;
|
||||
wire [3:0] m_axi_arcache;
|
||||
wire [2:0] m_axi_arprot;
|
||||
wire m_axi_arvalid;
|
||||
wire m_axi_rready;
|
||||
|
||||
initial begin
|
||||
// myhdl integration
|
||||
$from_myhdl(
|
||||
clk,
|
||||
rst,
|
||||
current_test,
|
||||
m_axis_rq_tready,
|
||||
s_axis_write_desc_pcie_addr,
|
||||
s_axis_write_desc_axi_addr,
|
||||
s_axis_write_desc_len,
|
||||
s_axis_write_desc_tag,
|
||||
s_axis_write_desc_valid,
|
||||
m_axi_arready,
|
||||
m_axi_rid,
|
||||
m_axi_rdata,
|
||||
m_axi_rresp,
|
||||
m_axi_rlast,
|
||||
m_axi_rvalid,
|
||||
enable,
|
||||
requester_id,
|
||||
requester_id_enable,
|
||||
max_payload_size
|
||||
);
|
||||
$to_myhdl(
|
||||
m_axis_rq_tdata,
|
||||
m_axis_rq_tkeep,
|
||||
m_axis_rq_tvalid,
|
||||
m_axis_rq_tlast,
|
||||
m_axis_rq_tuser,
|
||||
s_axis_write_desc_ready,
|
||||
m_axis_write_desc_status_tag,
|
||||
m_axis_write_desc_status_valid,
|
||||
m_axi_arid,
|
||||
m_axi_araddr,
|
||||
m_axi_arlen,
|
||||
m_axi_arsize,
|
||||
m_axi_arburst,
|
||||
m_axi_arlock,
|
||||
m_axi_arcache,
|
||||
m_axi_arprot,
|
||||
m_axi_arvalid,
|
||||
m_axi_rready
|
||||
);
|
||||
|
||||
// dump file
|
||||
$dumpfile("test_pcie_us_axi_dma_wr_64.lxt");
|
||||
$dumpvars(0, test_pcie_us_axi_dma_wr_64);
|
||||
end
|
||||
|
||||
pcie_us_axi_dma_wr #(
|
||||
.AXIS_PCIE_DATA_WIDTH(AXIS_PCIE_DATA_WIDTH),
|
||||
.AXIS_PCIE_KEEP_WIDTH(AXIS_PCIE_KEEP_WIDTH),
|
||||
.AXI_DATA_WIDTH(AXI_DATA_WIDTH),
|
||||
.AXI_ADDR_WIDTH(AXI_ADDR_WIDTH),
|
||||
.AXI_STRB_WIDTH(AXI_STRB_WIDTH),
|
||||
.AXI_ID_WIDTH(AXI_ID_WIDTH),
|
||||
.AXI_MAX_BURST_LEN(AXI_MAX_BURST_LEN),
|
||||
.PCIE_ADDR_WIDTH(PCIE_ADDR_WIDTH),
|
||||
.LEN_WIDTH(LEN_WIDTH),
|
||||
.TAG_WIDTH(TAG_WIDTH)
|
||||
)
|
||||
UUT (
|
||||
.clk(clk),
|
||||
.rst(rst),
|
||||
.m_axis_rq_tdata(m_axis_rq_tdata),
|
||||
.m_axis_rq_tkeep(m_axis_rq_tkeep),
|
||||
.m_axis_rq_tvalid(m_axis_rq_tvalid),
|
||||
.m_axis_rq_tready(m_axis_rq_tready),
|
||||
.m_axis_rq_tlast(m_axis_rq_tlast),
|
||||
.m_axis_rq_tuser(m_axis_rq_tuser),
|
||||
.s_axis_write_desc_pcie_addr(s_axis_write_desc_pcie_addr),
|
||||
.s_axis_write_desc_axi_addr(s_axis_write_desc_axi_addr),
|
||||
.s_axis_write_desc_len(s_axis_write_desc_len),
|
||||
.s_axis_write_desc_tag(s_axis_write_desc_tag),
|
||||
.s_axis_write_desc_valid(s_axis_write_desc_valid),
|
||||
.s_axis_write_desc_ready(s_axis_write_desc_ready),
|
||||
.m_axis_write_desc_status_tag(m_axis_write_desc_status_tag),
|
||||
.m_axis_write_desc_status_valid(m_axis_write_desc_status_valid),
|
||||
.m_axi_arid(m_axi_arid),
|
||||
.m_axi_araddr(m_axi_araddr),
|
||||
.m_axi_arlen(m_axi_arlen),
|
||||
.m_axi_arsize(m_axi_arsize),
|
||||
.m_axi_arburst(m_axi_arburst),
|
||||
.m_axi_arlock(m_axi_arlock),
|
||||
.m_axi_arcache(m_axi_arcache),
|
||||
.m_axi_arprot(m_axi_arprot),
|
||||
.m_axi_arvalid(m_axi_arvalid),
|
||||
.m_axi_arready(m_axi_arready),
|
||||
.m_axi_rid(m_axi_rid),
|
||||
.m_axi_rdata(m_axi_rdata),
|
||||
.m_axi_rresp(m_axi_rresp),
|
||||
.m_axi_rlast(m_axi_rlast),
|
||||
.m_axi_rvalid(m_axi_rvalid),
|
||||
.m_axi_rready(m_axi_rready),
|
||||
.enable(enable),
|
||||
.requester_id(requester_id),
|
||||
.requester_id_enable(requester_id_enable),
|
||||
.max_payload_size(max_payload_size)
|
||||
);
|
||||
|
||||
endmodule
|
420
fpga/lib/pcie/tb/test_pcie_us_axi_master_128.py
Executable file
420
fpga/lib/pcie/tb/test_pcie_us_axi_master_128.py
Executable file
@ -0,0 +1,420 @@
|
||||
#!/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 pcie
|
||||
import pcie_us
|
||||
import axi
|
||||
|
||||
module = 'pcie_us_axi_master'
|
||||
testbench = 'test_%s_128' % module
|
||||
|
||||
srcs = []
|
||||
|
||||
srcs.append("../rtl/%s.v" % module)
|
||||
srcs.append("../rtl/pcie_us_axi_master_wr.v")
|
||||
srcs.append("../rtl/pcie_us_axi_master_rd.v")
|
||||
srcs.append("../rtl/pcie_us_axis_cq_demux.v")
|
||||
srcs.append("../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 = 128
|
||||
AXIS_PCIE_KEEP_WIDTH = (AXIS_PCIE_DATA_WIDTH/32)
|
||||
AXI_DATA_WIDTH = AXIS_PCIE_DATA_WIDTH
|
||||
AXI_ADDR_WIDTH = 64
|
||||
AXI_STRB_WIDTH = (AXI_DATA_WIDTH/8)
|
||||
AXI_ID_WIDTH = 8
|
||||
AXI_MAX_BURST_LEN = 256
|
||||
|
||||
# Inputs
|
||||
clk = Signal(bool(0))
|
||||
rst = Signal(bool(0))
|
||||
current_test = Signal(intbv(0)[8:])
|
||||
|
||||
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_tvalid = Signal(bool(0))
|
||||
s_axis_cq_tlast = Signal(bool(0))
|
||||
s_axis_cq_tuser = Signal(intbv(0)[85:])
|
||||
m_axis_cc_tready = Signal(bool(0))
|
||||
m_axi_awready = Signal(bool(0))
|
||||
m_axi_wready = Signal(bool(0))
|
||||
m_axi_bid = Signal(intbv(0)[AXI_ID_WIDTH:])
|
||||
m_axi_bresp = Signal(intbv(0)[2:])
|
||||
m_axi_bvalid = Signal(bool(0))
|
||||
m_axi_arready = Signal(bool(0))
|
||||
m_axi_rid = Signal(intbv(0)[AXI_ID_WIDTH:])
|
||||
m_axi_rdata = Signal(intbv(0)[AXI_DATA_WIDTH:])
|
||||
m_axi_rresp = Signal(intbv(0)[2:])
|
||||
m_axi_rlast = Signal(bool(0))
|
||||
m_axi_rvalid = Signal(bool(0))
|
||||
completer_id = Signal(intbv(0)[16:])
|
||||
completer_id_enable = Signal(bool(0))
|
||||
max_payload_size = Signal(intbv(0)[3:])
|
||||
|
||||
# Outputs
|
||||
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_tvalid = Signal(bool(0))
|
||||
m_axis_cc_tlast = Signal(bool(0))
|
||||
m_axis_cc_tuser = Signal(intbv(0)[33:])
|
||||
m_axi_awid = Signal(intbv(0)[AXI_ID_WIDTH:])
|
||||
m_axi_awaddr = Signal(intbv(0)[AXI_ADDR_WIDTH:])
|
||||
m_axi_awlen = Signal(intbv(0)[8:])
|
||||
m_axi_awsize = Signal(intbv(4)[3:])
|
||||
m_axi_awburst = Signal(intbv(1)[2:])
|
||||
m_axi_awlock = Signal(bool(0))
|
||||
m_axi_awcache = Signal(intbv(3)[4:])
|
||||
m_axi_awprot = Signal(intbv(2)[3:])
|
||||
m_axi_awvalid = Signal(bool(0))
|
||||
m_axi_wdata = Signal(intbv(0)[AXI_DATA_WIDTH:])
|
||||
m_axi_wstrb = Signal(intbv(0)[AXI_STRB_WIDTH:])
|
||||
m_axi_wlast = Signal(bool(0))
|
||||
m_axi_wvalid = Signal(bool(0))
|
||||
m_axi_bready = Signal(bool(0))
|
||||
m_axi_arid = Signal(intbv(0)[AXI_ID_WIDTH:])
|
||||
m_axi_araddr = Signal(intbv(0)[AXI_ADDR_WIDTH:])
|
||||
m_axi_arlen = Signal(intbv(0)[8:])
|
||||
m_axi_arsize = Signal(intbv(4)[3:])
|
||||
m_axi_arburst = Signal(intbv(1)[2:])
|
||||
m_axi_arlock = Signal(bool(0))
|
||||
m_axi_arcache = Signal(intbv(3)[4:])
|
||||
m_axi_arprot = Signal(intbv(2)[3:])
|
||||
m_axi_arvalid = Signal(bool(0))
|
||||
m_axi_rready = Signal(bool(0))
|
||||
status_error_cor = Signal(bool(0))
|
||||
status_error_uncor = Signal(bool(0))
|
||||
|
||||
# Clock and Reset Interface
|
||||
user_clk=Signal(bool(0))
|
||||
user_reset=Signal(bool(0))
|
||||
sys_clk=Signal(bool(0))
|
||||
sys_reset=Signal(bool(0))
|
||||
|
||||
# AXI4 RAM model
|
||||
axi_ram_inst = axi.AXIRam(2**16)
|
||||
|
||||
axi_ram_port0 = axi_ram_inst.create_port(
|
||||
user_clk,
|
||||
s_axi_awid=m_axi_awid,
|
||||
s_axi_awaddr=m_axi_awaddr,
|
||||
s_axi_awlen=m_axi_awlen,
|
||||
s_axi_awsize=m_axi_awsize,
|
||||
s_axi_awburst=m_axi_awburst,
|
||||
s_axi_awlock=m_axi_awlock,
|
||||
s_axi_awcache=m_axi_awcache,
|
||||
s_axi_awprot=m_axi_awprot,
|
||||
s_axi_awvalid=m_axi_awvalid,
|
||||
s_axi_awready=m_axi_awready,
|
||||
s_axi_wdata=m_axi_wdata,
|
||||
s_axi_wstrb=m_axi_wstrb,
|
||||
s_axi_wlast=m_axi_wlast,
|
||||
s_axi_wvalid=m_axi_wvalid,
|
||||
s_axi_wready=m_axi_wready,
|
||||
s_axi_bid=m_axi_bid,
|
||||
s_axi_bresp=m_axi_bresp,
|
||||
s_axi_bvalid=m_axi_bvalid,
|
||||
s_axi_bready=m_axi_bready,
|
||||
s_axi_arid=m_axi_arid,
|
||||
s_axi_araddr=m_axi_araddr,
|
||||
s_axi_arlen=m_axi_arlen,
|
||||
s_axi_arsize=m_axi_arsize,
|
||||
s_axi_arburst=m_axi_arburst,
|
||||
s_axi_arlock=m_axi_arlock,
|
||||
s_axi_arcache=m_axi_arcache,
|
||||
s_axi_arprot=m_axi_arprot,
|
||||
s_axi_arvalid=m_axi_arvalid,
|
||||
s_axi_arready=m_axi_arready,
|
||||
s_axi_rid=m_axi_rid,
|
||||
s_axi_rdata=m_axi_rdata,
|
||||
s_axi_rresp=m_axi_rresp,
|
||||
s_axi_rlast=m_axi_rlast,
|
||||
s_axi_rvalid=m_axi_rvalid,
|
||||
s_axi_rready=m_axi_rready,
|
||||
name='port0'
|
||||
)
|
||||
|
||||
# PCIe devices
|
||||
rc = pcie.RootComplex()
|
||||
|
||||
dev = pcie_us.UltrascalePCIe()
|
||||
|
||||
dev.pcie_generation = 3
|
||||
dev.pcie_link_width = 4
|
||||
dev.user_clock_frequency = 250e6
|
||||
|
||||
dev.functions[0].configure_bar(0, 16*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_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=Signal(intbv(0)[AXIS_PCIE_DATA_WIDTH:]),
|
||||
s_axis_rq_tuser=Signal(intbv(0)[60:]),
|
||||
s_axis_rq_tlast=Signal(bool(0)),
|
||||
s_axis_rq_tkeep=Signal(intbv(0)[AXIS_PCIE_KEEP_WIDTH:]),
|
||||
s_axis_rq_tvalid=Signal(bool(0)),
|
||||
s_axis_rq_tready=Signal(bool(1)),
|
||||
# pcie_rq_seq_num=pcie_rq_seq_num,
|
||||
# pcie_rq_seq_num_vld=pcie_rq_seq_num_vld,
|
||||
# pcie_rq_tag=pcie_rq_tag,
|
||||
# pcie_rq_tag_av=pcie_rq_tag_av,
|
||||
# pcie_rq_tag_vld=pcie_rq_tag_vld,
|
||||
|
||||
# Requester Completion Interface
|
||||
m_axis_rc_tdata=Signal(intbv(0)[AXIS_PCIE_DATA_WIDTH:]),
|
||||
m_axis_rc_tuser=Signal(intbv(0)[75:]),
|
||||
m_axis_rc_tlast=Signal(bool(0)),
|
||||
m_axis_rc_tkeep=Signal(intbv(0)[AXIS_PCIE_KEEP_WIDTH:]),
|
||||
m_axis_rc_tvalid=Signal(bool(0)),
|
||||
m_axis_rc_tready=Signal(bool(0)),
|
||||
|
||||
# Transmit Flow Control Interface
|
||||
# pcie_tfc_nph_av=pcie_tfc_nph_av,
|
||||
# pcie_tfc_npd_av=pcie_tfc_npd_av,
|
||||
|
||||
# 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_per_function_update_done=cfg_per_function_update_done,
|
||||
# cfg_per_function_number=cfg_per_function_number,
|
||||
# cfg_per_function_output_request=cfg_per_function_output_request,
|
||||
# cfg_dsn=cfg_dsn,
|
||||
# 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=cfg_err_cor_in,
|
||||
# cfg_err_uncor_in=cfg_err_uncor_in,
|
||||
# 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,
|
||||
|
||||
# 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
|
||||
)
|
||||
|
||||
# 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,
|
||||
s_axis_cq_tdata=s_axis_cq_tdata,
|
||||
s_axis_cq_tkeep=s_axis_cq_tkeep,
|
||||
s_axis_cq_tvalid=s_axis_cq_tvalid,
|
||||
s_axis_cq_tready=s_axis_cq_tready,
|
||||
s_axis_cq_tlast=s_axis_cq_tlast,
|
||||
s_axis_cq_tuser=s_axis_cq_tuser,
|
||||
m_axis_cc_tdata=m_axis_cc_tdata,
|
||||
m_axis_cc_tkeep=m_axis_cc_tkeep,
|
||||
m_axis_cc_tvalid=m_axis_cc_tvalid,
|
||||
m_axis_cc_tready=m_axis_cc_tready,
|
||||
m_axis_cc_tlast=m_axis_cc_tlast,
|
||||
m_axis_cc_tuser=m_axis_cc_tuser,
|
||||
m_axi_awid=m_axi_awid,
|
||||
m_axi_awaddr=m_axi_awaddr,
|
||||
m_axi_awlen=m_axi_awlen,
|
||||
m_axi_awsize=m_axi_awsize,
|
||||
m_axi_awburst=m_axi_awburst,
|
||||
m_axi_awlock=m_axi_awlock,
|
||||
m_axi_awcache=m_axi_awcache,
|
||||
m_axi_awprot=m_axi_awprot,
|
||||
m_axi_awvalid=m_axi_awvalid,
|
||||
m_axi_awready=m_axi_awready,
|
||||
m_axi_wdata=m_axi_wdata,
|
||||
m_axi_wstrb=m_axi_wstrb,
|
||||
m_axi_wlast=m_axi_wlast,
|
||||
m_axi_wvalid=m_axi_wvalid,
|
||||
m_axi_wready=m_axi_wready,
|
||||
m_axi_bid=m_axi_bid,
|
||||
m_axi_bresp=m_axi_bresp,
|
||||
m_axi_bvalid=m_axi_bvalid,
|
||||
m_axi_bready=m_axi_bready,
|
||||
m_axi_arid=m_axi_arid,
|
||||
m_axi_araddr=m_axi_araddr,
|
||||
m_axi_arlen=m_axi_arlen,
|
||||
m_axi_arsize=m_axi_arsize,
|
||||
m_axi_arburst=m_axi_arburst,
|
||||
m_axi_arlock=m_axi_arlock,
|
||||
m_axi_arcache=m_axi_arcache,
|
||||
m_axi_arprot=m_axi_arprot,
|
||||
m_axi_arvalid=m_axi_arvalid,
|
||||
m_axi_arready=m_axi_arready,
|
||||
m_axi_rid=m_axi_rid,
|
||||
m_axi_rdata=m_axi_rdata,
|
||||
m_axi_rresp=m_axi_rresp,
|
||||
m_axi_rlast=m_axi_rlast,
|
||||
m_axi_rvalid=m_axi_rvalid,
|
||||
m_axi_rready=m_axi_rready,
|
||||
completer_id=completer_id,
|
||||
completer_id_enable=completer_id_enable,
|
||||
max_payload_size=max_payload_size,
|
||||
status_error_cor=status_error_cor,
|
||||
status_error_uncor=status_error_uncor
|
||||
)
|
||||
|
||||
@always(delay(4))
|
||||
def clkgen():
|
||||
clk.next = not clk
|
||||
|
||||
@always_comb
|
||||
def clk_logic():
|
||||
sys_clk.next = clk
|
||||
sys_reset.next = not rst
|
||||
|
||||
status_error_cor_asserted = Signal(bool(0))
|
||||
status_error_uncor_asserted = Signal(bool(0))
|
||||
|
||||
@always(user_clk.posedge)
|
||||
def monitor():
|
||||
if (status_error_cor):
|
||||
status_error_cor_asserted.next = 1
|
||||
if (status_error_uncor):
|
||||
status_error_uncor_asserted.next = 1
|
||||
|
||||
@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
|
||||
|
||||
max_payload_size.next = 0
|
||||
|
||||
yield user_clk.posedge
|
||||
print("test 1: enumeration")
|
||||
current_test.next = 1
|
||||
|
||||
yield rc.enumerate()
|
||||
|
||||
dev_bar0 = rc.tree[0][0].bar[0]
|
||||
|
||||
yield delay(100)
|
||||
|
||||
yield clk.posedge
|
||||
print("test 2: memory write")
|
||||
current_test.next = 2
|
||||
|
||||
pcie_addr = 0x00000000
|
||||
test_data = b'\x11\x22\x33\x44'
|
||||
|
||||
yield rc.mem_write(dev_bar0+pcie_addr, test_data)
|
||||
|
||||
yield delay(300)
|
||||
|
||||
data = axi_ram_inst.read_mem(pcie_addr, 32)
|
||||
for i in range(0, len(data), 16):
|
||||
print(" ".join(("{:02x}".format(c) for c in bytearray(data[i:i+16]))))
|
||||
|
||||
assert axi_ram_inst.read_mem(pcie_addr, len(test_data)) == test_data
|
||||
|
||||
assert not status_error_cor_asserted
|
||||
assert not status_error_uncor_asserted
|
||||
|
||||
yield delay(100)
|
||||
|
||||
yield clk.posedge
|
||||
print("test 3: memory read")
|
||||
current_test.next = 3
|
||||
|
||||
pcie_addr = 0x00000000
|
||||
test_data = b'\x11\x22\x33\x44'
|
||||
|
||||
axi_ram_inst.write_mem(pcie_addr, test_data)
|
||||
|
||||
data = axi_ram_inst.read_mem(0, 32)
|
||||
for i in range(0, len(data), 16):
|
||||
print(" ".join(("{:02x}".format(c) for c in bytearray(data[i:i+16]))))
|
||||
|
||||
val = yield from rc.mem_read(dev_bar0+pcie_addr, len(test_data), 1000)
|
||||
|
||||
print(val)
|
||||
|
||||
assert val == test_data
|
||||
|
||||
assert not status_error_cor_asserted
|
||||
assert not status_error_uncor_asserted
|
||||
|
||||
yield delay(100)
|
||||
|
||||
raise StopSimulation
|
||||
|
||||
return instances()
|
||||
|
||||
def test_bench():
|
||||
sim = Simulation(bench())
|
||||
sim.run()
|
||||
|
||||
if __name__ == '__main__':
|
||||
print("Running test...")
|
||||
test_bench()
|
236
fpga/lib/pcie/tb/test_pcie_us_axi_master_128.v
Normal file
236
fpga/lib/pcie/tb/test_pcie_us_axi_master_128.v
Normal file
@ -0,0 +1,236 @@
|
||||
/*
|
||||
|
||||
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 pcie_us_axi_master
|
||||
*/
|
||||
module test_pcie_us_axi_master_128;
|
||||
|
||||
// Parameters
|
||||
parameter AXIS_PCIE_DATA_WIDTH = 128;
|
||||
parameter AXIS_PCIE_KEEP_WIDTH = (AXIS_PCIE_DATA_WIDTH/32);
|
||||
parameter AXI_DATA_WIDTH = AXIS_PCIE_DATA_WIDTH;
|
||||
parameter AXI_ADDR_WIDTH = 64;
|
||||
parameter AXI_STRB_WIDTH = (AXI_DATA_WIDTH/8);
|
||||
parameter AXI_ID_WIDTH = 8;
|
||||
parameter AXI_MAX_BURST_LEN = 256;
|
||||
|
||||
// Inputs
|
||||
reg clk = 0;
|
||||
reg rst = 0;
|
||||
reg [7:0] current_test = 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_tvalid = 0;
|
||||
reg s_axis_cq_tlast = 0;
|
||||
reg [84:0] s_axis_cq_tuser = 0;
|
||||
reg m_axis_cc_tready = 0;
|
||||
reg m_axi_awready = 0;
|
||||
reg m_axi_wready = 0;
|
||||
reg [AXI_ID_WIDTH-1:0] m_axi_bid = 0;
|
||||
reg [1:0] m_axi_bresp = 0;
|
||||
reg m_axi_bvalid = 0;
|
||||
reg m_axi_arready = 0;
|
||||
reg [AXI_ID_WIDTH-1:0] m_axi_rid = 0;
|
||||
reg [AXI_DATA_WIDTH-1:0] m_axi_rdata = 0;
|
||||
reg [1:0] m_axi_rresp = 0;
|
||||
reg m_axi_rlast = 0;
|
||||
reg m_axi_rvalid = 0;
|
||||
reg [15:0] completer_id = 0;
|
||||
reg completer_id_enable = 0;
|
||||
reg [2:0] max_payload_size = 0;
|
||||
|
||||
// Outputs
|
||||
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_tvalid;
|
||||
wire m_axis_cc_tlast;
|
||||
wire [32:0] m_axis_cc_tuser;
|
||||
wire [AXI_ID_WIDTH-1:0] m_axi_awid;
|
||||
wire [AXI_ADDR_WIDTH-1:0] m_axi_awaddr;
|
||||
wire [7:0] m_axi_awlen;
|
||||
wire [2:0] m_axi_awsize;
|
||||
wire [1:0] m_axi_awburst;
|
||||
wire m_axi_awlock;
|
||||
wire [3:0] m_axi_awcache;
|
||||
wire [2:0] m_axi_awprot;
|
||||
wire m_axi_awvalid;
|
||||
wire [AXI_DATA_WIDTH-1:0] m_axi_wdata;
|
||||
wire [AXI_STRB_WIDTH-1:0] m_axi_wstrb;
|
||||
wire m_axi_wlast;
|
||||
wire m_axi_wvalid;
|
||||
wire m_axi_bready;
|
||||
wire [AXI_ID_WIDTH-1:0] m_axi_arid;
|
||||
wire [AXI_ADDR_WIDTH-1:0] m_axi_araddr;
|
||||
wire [7:0] m_axi_arlen;
|
||||
wire [2:0] m_axi_arsize;
|
||||
wire [1:0] m_axi_arburst;
|
||||
wire m_axi_arlock;
|
||||
wire [3:0] m_axi_arcache;
|
||||
wire [2:0] m_axi_arprot;
|
||||
wire m_axi_arvalid;
|
||||
wire m_axi_rready;
|
||||
wire status_error_cor;
|
||||
wire status_error_uncor;
|
||||
|
||||
initial begin
|
||||
// myhdl integration
|
||||
$from_myhdl(
|
||||
clk,
|
||||
rst,
|
||||
current_test,
|
||||
s_axis_cq_tdata,
|
||||
s_axis_cq_tkeep,
|
||||
s_axis_cq_tvalid,
|
||||
s_axis_cq_tlast,
|
||||
s_axis_cq_tuser,
|
||||
m_axis_cc_tready,
|
||||
m_axi_awready,
|
||||
m_axi_wready,
|
||||
m_axi_bid,
|
||||
m_axi_bresp,
|
||||
m_axi_bvalid,
|
||||
m_axi_arready,
|
||||
m_axi_rid,
|
||||
m_axi_rdata,
|
||||
m_axi_rresp,
|
||||
m_axi_rlast,
|
||||
m_axi_rvalid,
|
||||
completer_id,
|
||||
completer_id_enable,
|
||||
max_payload_size
|
||||
);
|
||||
$to_myhdl(
|
||||
s_axis_cq_tready,
|
||||
m_axis_cc_tdata,
|
||||
m_axis_cc_tkeep,
|
||||
m_axis_cc_tvalid,
|
||||
m_axis_cc_tlast,
|
||||
m_axis_cc_tuser,
|
||||
m_axi_awid,
|
||||
m_axi_awaddr,
|
||||
m_axi_awlen,
|
||||
m_axi_awsize,
|
||||
m_axi_awburst,
|
||||
m_axi_awlock,
|
||||
m_axi_awcache,
|
||||
m_axi_awprot,
|
||||
m_axi_awvalid,
|
||||
m_axi_wdata,
|
||||
m_axi_wstrb,
|
||||
m_axi_wlast,
|
||||
m_axi_wvalid,
|
||||
m_axi_bready,
|
||||
m_axi_arid,
|
||||
m_axi_araddr,
|
||||
m_axi_arlen,
|
||||
m_axi_arsize,
|
||||
m_axi_arburst,
|
||||
m_axi_arlock,
|
||||
m_axi_arcache,
|
||||
m_axi_arprot,
|
||||
m_axi_arvalid,
|
||||
m_axi_rready,
|
||||
status_error_cor,
|
||||
status_error_uncor
|
||||
);
|
||||
|
||||
// dump file
|
||||
$dumpfile("test_pcie_us_axi_master_128.lxt");
|
||||
$dumpvars(0, test_pcie_us_axi_master_128);
|
||||
end
|
||||
|
||||
pcie_us_axi_master #(
|
||||
.AXIS_PCIE_DATA_WIDTH(AXIS_PCIE_DATA_WIDTH),
|
||||
.AXIS_PCIE_KEEP_WIDTH(AXIS_PCIE_KEEP_WIDTH),
|
||||
.AXI_DATA_WIDTH(AXI_DATA_WIDTH),
|
||||
.AXI_ADDR_WIDTH(AXI_ADDR_WIDTH),
|
||||
.AXI_STRB_WIDTH(AXI_STRB_WIDTH),
|
||||
.AXI_ID_WIDTH(AXI_ID_WIDTH),
|
||||
.AXI_MAX_BURST_LEN(AXI_MAX_BURST_LEN)
|
||||
)
|
||||
UUT (
|
||||
.clk(clk),
|
||||
.rst(rst),
|
||||
.s_axis_cq_tdata(s_axis_cq_tdata),
|
||||
.s_axis_cq_tkeep(s_axis_cq_tkeep),
|
||||
.s_axis_cq_tvalid(s_axis_cq_tvalid),
|
||||
.s_axis_cq_tready(s_axis_cq_tready),
|
||||
.s_axis_cq_tlast(s_axis_cq_tlast),
|
||||
.s_axis_cq_tuser(s_axis_cq_tuser),
|
||||
.m_axis_cc_tdata(m_axis_cc_tdata),
|
||||
.m_axis_cc_tkeep(m_axis_cc_tkeep),
|
||||
.m_axis_cc_tvalid(m_axis_cc_tvalid),
|
||||
.m_axis_cc_tready(m_axis_cc_tready),
|
||||
.m_axis_cc_tlast(m_axis_cc_tlast),
|
||||
.m_axis_cc_tuser(m_axis_cc_tuser),
|
||||
.m_axi_awid(m_axi_awid),
|
||||
.m_axi_awaddr(m_axi_awaddr),
|
||||
.m_axi_awlen(m_axi_awlen),
|
||||
.m_axi_awsize(m_axi_awsize),
|
||||
.m_axi_awburst(m_axi_awburst),
|
||||
.m_axi_awlock(m_axi_awlock),
|
||||
.m_axi_awcache(m_axi_awcache),
|
||||
.m_axi_awprot(m_axi_awprot),
|
||||
.m_axi_awvalid(m_axi_awvalid),
|
||||
.m_axi_awready(m_axi_awready),
|
||||
.m_axi_wdata(m_axi_wdata),
|
||||
.m_axi_wstrb(m_axi_wstrb),
|
||||
.m_axi_wlast(m_axi_wlast),
|
||||
.m_axi_wvalid(m_axi_wvalid),
|
||||
.m_axi_wready(m_axi_wready),
|
||||
.m_axi_bid(m_axi_bid),
|
||||
.m_axi_bresp(m_axi_bresp),
|
||||
.m_axi_bvalid(m_axi_bvalid),
|
||||
.m_axi_bready(m_axi_bready),
|
||||
.m_axi_arid(m_axi_arid),
|
||||
.m_axi_araddr(m_axi_araddr),
|
||||
.m_axi_arlen(m_axi_arlen),
|
||||
.m_axi_arsize(m_axi_arsize),
|
||||
.m_axi_arburst(m_axi_arburst),
|
||||
.m_axi_arlock(m_axi_arlock),
|
||||
.m_axi_arcache(m_axi_arcache),
|
||||
.m_axi_arprot(m_axi_arprot),
|
||||
.m_axi_arvalid(m_axi_arvalid),
|
||||
.m_axi_arready(m_axi_arready),
|
||||
.m_axi_rid(m_axi_rid),
|
||||
.m_axi_rdata(m_axi_rdata),
|
||||
.m_axi_rresp(m_axi_rresp),
|
||||
.m_axi_rlast(m_axi_rlast),
|
||||
.m_axi_rvalid(m_axi_rvalid),
|
||||
.m_axi_rready(m_axi_rready),
|
||||
.completer_id(completer_id),
|
||||
.completer_id_enable(completer_id_enable),
|
||||
.max_payload_size(max_payload_size),
|
||||
.status_error_cor(status_error_cor),
|
||||
.status_error_uncor(status_error_uncor)
|
||||
);
|
||||
|
||||
endmodule
|
420
fpga/lib/pcie/tb/test_pcie_us_axi_master_256.py
Executable file
420
fpga/lib/pcie/tb/test_pcie_us_axi_master_256.py
Executable file
@ -0,0 +1,420 @@
|
||||
#!/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 pcie
|
||||
import pcie_us
|
||||
import axi
|
||||
|
||||
module = 'pcie_us_axi_master'
|
||||
testbench = 'test_%s_256' % module
|
||||
|
||||
srcs = []
|
||||
|
||||
srcs.append("../rtl/%s.v" % module)
|
||||
srcs.append("../rtl/pcie_us_axi_master_wr.v")
|
||||
srcs.append("../rtl/pcie_us_axi_master_rd.v")
|
||||
srcs.append("../rtl/pcie_us_axis_cq_demux.v")
|
||||
srcs.append("../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 = 256
|
||||
AXIS_PCIE_KEEP_WIDTH = (AXIS_PCIE_DATA_WIDTH/32)
|
||||
AXI_DATA_WIDTH = AXIS_PCIE_DATA_WIDTH
|
||||
AXI_ADDR_WIDTH = 64
|
||||
AXI_STRB_WIDTH = (AXI_DATA_WIDTH/8)
|
||||
AXI_ID_WIDTH = 8
|
||||
AXI_MAX_BURST_LEN = 256
|
||||
|
||||
# Inputs
|
||||
clk = Signal(bool(0))
|
||||
rst = Signal(bool(0))
|
||||
current_test = Signal(intbv(0)[8:])
|
||||
|
||||
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_tvalid = Signal(bool(0))
|
||||
s_axis_cq_tlast = Signal(bool(0))
|
||||
s_axis_cq_tuser = Signal(intbv(0)[85:])
|
||||
m_axis_cc_tready = Signal(bool(0))
|
||||
m_axi_awready = Signal(bool(0))
|
||||
m_axi_wready = Signal(bool(0))
|
||||
m_axi_bid = Signal(intbv(0)[AXI_ID_WIDTH:])
|
||||
m_axi_bresp = Signal(intbv(0)[2:])
|
||||
m_axi_bvalid = Signal(bool(0))
|
||||
m_axi_arready = Signal(bool(0))
|
||||
m_axi_rid = Signal(intbv(0)[AXI_ID_WIDTH:])
|
||||
m_axi_rdata = Signal(intbv(0)[AXI_DATA_WIDTH:])
|
||||
m_axi_rresp = Signal(intbv(0)[2:])
|
||||
m_axi_rlast = Signal(bool(0))
|
||||
m_axi_rvalid = Signal(bool(0))
|
||||
completer_id = Signal(intbv(0)[16:])
|
||||
completer_id_enable = Signal(bool(0))
|
||||
max_payload_size = Signal(intbv(0)[3:])
|
||||
|
||||
# Outputs
|
||||
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_tvalid = Signal(bool(0))
|
||||
m_axis_cc_tlast = Signal(bool(0))
|
||||
m_axis_cc_tuser = Signal(intbv(0)[33:])
|
||||
m_axi_awid = Signal(intbv(0)[AXI_ID_WIDTH:])
|
||||
m_axi_awaddr = Signal(intbv(0)[AXI_ADDR_WIDTH:])
|
||||
m_axi_awlen = Signal(intbv(0)[8:])
|
||||
m_axi_awsize = Signal(intbv(5)[3:])
|
||||
m_axi_awburst = Signal(intbv(1)[2:])
|
||||
m_axi_awlock = Signal(bool(0))
|
||||
m_axi_awcache = Signal(intbv(3)[4:])
|
||||
m_axi_awprot = Signal(intbv(2)[3:])
|
||||
m_axi_awvalid = Signal(bool(0))
|
||||
m_axi_wdata = Signal(intbv(0)[AXI_DATA_WIDTH:])
|
||||
m_axi_wstrb = Signal(intbv(0)[AXI_STRB_WIDTH:])
|
||||
m_axi_wlast = Signal(bool(0))
|
||||
m_axi_wvalid = Signal(bool(0))
|
||||
m_axi_bready = Signal(bool(0))
|
||||
m_axi_arid = Signal(intbv(0)[AXI_ID_WIDTH:])
|
||||
m_axi_araddr = Signal(intbv(0)[AXI_ADDR_WIDTH:])
|
||||
m_axi_arlen = Signal(intbv(0)[8:])
|
||||
m_axi_arsize = Signal(intbv(5)[3:])
|
||||
m_axi_arburst = Signal(intbv(1)[2:])
|
||||
m_axi_arlock = Signal(bool(0))
|
||||
m_axi_arcache = Signal(intbv(3)[4:])
|
||||
m_axi_arprot = Signal(intbv(2)[3:])
|
||||
m_axi_arvalid = Signal(bool(0))
|
||||
m_axi_rready = Signal(bool(0))
|
||||
status_error_cor = Signal(bool(0))
|
||||
status_error_uncor = Signal(bool(0))
|
||||
|
||||
# Clock and Reset Interface
|
||||
user_clk=Signal(bool(0))
|
||||
user_reset=Signal(bool(0))
|
||||
sys_clk=Signal(bool(0))
|
||||
sys_reset=Signal(bool(0))
|
||||
|
||||
# AXI4 RAM model
|
||||
axi_ram_inst = axi.AXIRam(2**16)
|
||||
|
||||
axi_ram_port0 = axi_ram_inst.create_port(
|
||||
user_clk,
|
||||
s_axi_awid=m_axi_awid,
|
||||
s_axi_awaddr=m_axi_awaddr,
|
||||
s_axi_awlen=m_axi_awlen,
|
||||
s_axi_awsize=m_axi_awsize,
|
||||
s_axi_awburst=m_axi_awburst,
|
||||
s_axi_awlock=m_axi_awlock,
|
||||
s_axi_awcache=m_axi_awcache,
|
||||
s_axi_awprot=m_axi_awprot,
|
||||
s_axi_awvalid=m_axi_awvalid,
|
||||
s_axi_awready=m_axi_awready,
|
||||
s_axi_wdata=m_axi_wdata,
|
||||
s_axi_wstrb=m_axi_wstrb,
|
||||
s_axi_wlast=m_axi_wlast,
|
||||
s_axi_wvalid=m_axi_wvalid,
|
||||
s_axi_wready=m_axi_wready,
|
||||
s_axi_bid=m_axi_bid,
|
||||
s_axi_bresp=m_axi_bresp,
|
||||
s_axi_bvalid=m_axi_bvalid,
|
||||
s_axi_bready=m_axi_bready,
|
||||
s_axi_arid=m_axi_arid,
|
||||
s_axi_araddr=m_axi_araddr,
|
||||
s_axi_arlen=m_axi_arlen,
|
||||
s_axi_arsize=m_axi_arsize,
|
||||
s_axi_arburst=m_axi_arburst,
|
||||
s_axi_arlock=m_axi_arlock,
|
||||
s_axi_arcache=m_axi_arcache,
|
||||
s_axi_arprot=m_axi_arprot,
|
||||
s_axi_arvalid=m_axi_arvalid,
|
||||
s_axi_arready=m_axi_arready,
|
||||
s_axi_rid=m_axi_rid,
|
||||
s_axi_rdata=m_axi_rdata,
|
||||
s_axi_rresp=m_axi_rresp,
|
||||
s_axi_rlast=m_axi_rlast,
|
||||
s_axi_rvalid=m_axi_rvalid,
|
||||
s_axi_rready=m_axi_rready,
|
||||
name='port0'
|
||||
)
|
||||
|
||||
# PCIe devices
|
||||
rc = pcie.RootComplex()
|
||||
|
||||
dev = pcie_us.UltrascalePCIe()
|
||||
|
||||
dev.pcie_generation = 3
|
||||
dev.pcie_link_width = 8
|
||||
dev.user_clock_frequency = 250e6
|
||||
|
||||
dev.functions[0].configure_bar(0, 16*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_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=Signal(intbv(0)[AXIS_PCIE_DATA_WIDTH:]),
|
||||
s_axis_rq_tuser=Signal(intbv(0)[60:]),
|
||||
s_axis_rq_tlast=Signal(bool(0)),
|
||||
s_axis_rq_tkeep=Signal(intbv(0)[AXIS_PCIE_KEEP_WIDTH:]),
|
||||
s_axis_rq_tvalid=Signal(bool(0)),
|
||||
s_axis_rq_tready=Signal(bool(1)),
|
||||
# pcie_rq_seq_num=pcie_rq_seq_num,
|
||||
# pcie_rq_seq_num_vld=pcie_rq_seq_num_vld,
|
||||
# pcie_rq_tag=pcie_rq_tag,
|
||||
# pcie_rq_tag_av=pcie_rq_tag_av,
|
||||
# pcie_rq_tag_vld=pcie_rq_tag_vld,
|
||||
|
||||
# Requester Completion Interface
|
||||
m_axis_rc_tdata=Signal(intbv(0)[AXIS_PCIE_DATA_WIDTH:]),
|
||||
m_axis_rc_tuser=Signal(intbv(0)[75:]),
|
||||
m_axis_rc_tlast=Signal(bool(0)),
|
||||
m_axis_rc_tkeep=Signal(intbv(0)[AXIS_PCIE_KEEP_WIDTH:]),
|
||||
m_axis_rc_tvalid=Signal(bool(0)),
|
||||
m_axis_rc_tready=Signal(bool(0)),
|
||||
|
||||
# Transmit Flow Control Interface
|
||||
# pcie_tfc_nph_av=pcie_tfc_nph_av,
|
||||
# pcie_tfc_npd_av=pcie_tfc_npd_av,
|
||||
|
||||
# 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_per_function_update_done=cfg_per_function_update_done,
|
||||
# cfg_per_function_number=cfg_per_function_number,
|
||||
# cfg_per_function_output_request=cfg_per_function_output_request,
|
||||
# cfg_dsn=cfg_dsn,
|
||||
# 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=cfg_err_cor_in,
|
||||
# cfg_err_uncor_in=cfg_err_uncor_in,
|
||||
# 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,
|
||||
|
||||
# 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
|
||||
)
|
||||
|
||||
# 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,
|
||||
s_axis_cq_tdata=s_axis_cq_tdata,
|
||||
s_axis_cq_tkeep=s_axis_cq_tkeep,
|
||||
s_axis_cq_tvalid=s_axis_cq_tvalid,
|
||||
s_axis_cq_tready=s_axis_cq_tready,
|
||||
s_axis_cq_tlast=s_axis_cq_tlast,
|
||||
s_axis_cq_tuser=s_axis_cq_tuser,
|
||||
m_axis_cc_tdata=m_axis_cc_tdata,
|
||||
m_axis_cc_tkeep=m_axis_cc_tkeep,
|
||||
m_axis_cc_tvalid=m_axis_cc_tvalid,
|
||||
m_axis_cc_tready=m_axis_cc_tready,
|
||||
m_axis_cc_tlast=m_axis_cc_tlast,
|
||||
m_axis_cc_tuser=m_axis_cc_tuser,
|
||||
m_axi_awid=m_axi_awid,
|
||||
m_axi_awaddr=m_axi_awaddr,
|
||||
m_axi_awlen=m_axi_awlen,
|
||||
m_axi_awsize=m_axi_awsize,
|
||||
m_axi_awburst=m_axi_awburst,
|
||||
m_axi_awlock=m_axi_awlock,
|
||||
m_axi_awcache=m_axi_awcache,
|
||||
m_axi_awprot=m_axi_awprot,
|
||||
m_axi_awvalid=m_axi_awvalid,
|
||||
m_axi_awready=m_axi_awready,
|
||||
m_axi_wdata=m_axi_wdata,
|
||||
m_axi_wstrb=m_axi_wstrb,
|
||||
m_axi_wlast=m_axi_wlast,
|
||||
m_axi_wvalid=m_axi_wvalid,
|
||||
m_axi_wready=m_axi_wready,
|
||||
m_axi_bid=m_axi_bid,
|
||||
m_axi_bresp=m_axi_bresp,
|
||||
m_axi_bvalid=m_axi_bvalid,
|
||||
m_axi_bready=m_axi_bready,
|
||||
m_axi_arid=m_axi_arid,
|
||||
m_axi_araddr=m_axi_araddr,
|
||||
m_axi_arlen=m_axi_arlen,
|
||||
m_axi_arsize=m_axi_arsize,
|
||||
m_axi_arburst=m_axi_arburst,
|
||||
m_axi_arlock=m_axi_arlock,
|
||||
m_axi_arcache=m_axi_arcache,
|
||||
m_axi_arprot=m_axi_arprot,
|
||||
m_axi_arvalid=m_axi_arvalid,
|
||||
m_axi_arready=m_axi_arready,
|
||||
m_axi_rid=m_axi_rid,
|
||||
m_axi_rdata=m_axi_rdata,
|
||||
m_axi_rresp=m_axi_rresp,
|
||||
m_axi_rlast=m_axi_rlast,
|
||||
m_axi_rvalid=m_axi_rvalid,
|
||||
m_axi_rready=m_axi_rready,
|
||||
completer_id=completer_id,
|
||||
completer_id_enable=completer_id_enable,
|
||||
max_payload_size=max_payload_size,
|
||||
status_error_cor=status_error_cor,
|
||||
status_error_uncor=status_error_uncor
|
||||
)
|
||||
|
||||
@always(delay(4))
|
||||
def clkgen():
|
||||
clk.next = not clk
|
||||
|
||||
@always_comb
|
||||
def clk_logic():
|
||||
sys_clk.next = clk
|
||||
sys_reset.next = not rst
|
||||
|
||||
status_error_cor_asserted = Signal(bool(0))
|
||||
status_error_uncor_asserted = Signal(bool(0))
|
||||
|
||||
@always(user_clk.posedge)
|
||||
def monitor():
|
||||
if (status_error_cor):
|
||||
status_error_cor_asserted.next = 1
|
||||
if (status_error_uncor):
|
||||
status_error_uncor_asserted.next = 1
|
||||
|
||||
@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
|
||||
|
||||
max_payload_size.next = 0
|
||||
|
||||
yield user_clk.posedge
|
||||
print("test 1: enumeration")
|
||||
current_test.next = 1
|
||||
|
||||
yield rc.enumerate()
|
||||
|
||||
dev_bar0 = rc.tree[0][0].bar[0]
|
||||
|
||||
yield delay(100)
|
||||
|
||||
yield clk.posedge
|
||||
print("test 2: memory write")
|
||||
current_test.next = 2
|
||||
|
||||
pcie_addr = 0x00000000
|
||||
test_data = b'\x11\x22\x33\x44'
|
||||
|
||||
yield rc.mem_write(dev_bar0+pcie_addr, test_data)
|
||||
|
||||
yield delay(300)
|
||||
|
||||
data = axi_ram_inst.read_mem(pcie_addr, 32)
|
||||
for i in range(0, len(data), 16):
|
||||
print(" ".join(("{:02x}".format(c) for c in bytearray(data[i:i+16]))))
|
||||
|
||||
assert axi_ram_inst.read_mem(pcie_addr, len(test_data)) == test_data
|
||||
|
||||
assert not status_error_cor_asserted
|
||||
assert not status_error_uncor_asserted
|
||||
|
||||
yield delay(100)
|
||||
|
||||
yield clk.posedge
|
||||
print("test 3: memory read")
|
||||
current_test.next = 3
|
||||
|
||||
pcie_addr = 0x00000000
|
||||
test_data = b'\x11\x22\x33\x44'
|
||||
|
||||
axi_ram_inst.write_mem(pcie_addr, test_data)
|
||||
|
||||
data = axi_ram_inst.read_mem(0, 32)
|
||||
for i in range(0, len(data), 16):
|
||||
print(" ".join(("{:02x}".format(c) for c in bytearray(data[i:i+16]))))
|
||||
|
||||
val = yield from rc.mem_read(dev_bar0+pcie_addr, len(test_data), 1000)
|
||||
|
||||
print(val)
|
||||
|
||||
assert val == test_data
|
||||
|
||||
assert not status_error_cor_asserted
|
||||
assert not status_error_uncor_asserted
|
||||
|
||||
yield delay(100)
|
||||
|
||||
raise StopSimulation
|
||||
|
||||
return instances()
|
||||
|
||||
def test_bench():
|
||||
sim = Simulation(bench())
|
||||
sim.run()
|
||||
|
||||
if __name__ == '__main__':
|
||||
print("Running test...")
|
||||
test_bench()
|
236
fpga/lib/pcie/tb/test_pcie_us_axi_master_256.v
Normal file
236
fpga/lib/pcie/tb/test_pcie_us_axi_master_256.v
Normal file
@ -0,0 +1,236 @@
|
||||
/*
|
||||
|
||||
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 pcie_us_axi_master
|
||||
*/
|
||||
module test_pcie_us_axi_master_256;
|
||||
|
||||
// Parameters
|
||||
parameter AXIS_PCIE_DATA_WIDTH = 256;
|
||||
parameter AXIS_PCIE_KEEP_WIDTH = (AXIS_PCIE_DATA_WIDTH/32);
|
||||
parameter AXI_DATA_WIDTH = AXIS_PCIE_DATA_WIDTH;
|
||||
parameter AXI_ADDR_WIDTH = 64;
|
||||
parameter AXI_STRB_WIDTH = (AXI_DATA_WIDTH/8);
|
||||
parameter AXI_ID_WIDTH = 8;
|
||||
parameter AXI_MAX_BURST_LEN = 256;
|
||||
|
||||
// Inputs
|
||||
reg clk = 0;
|
||||
reg rst = 0;
|
||||
reg [7:0] current_test = 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_tvalid = 0;
|
||||
reg s_axis_cq_tlast = 0;
|
||||
reg [84:0] s_axis_cq_tuser = 0;
|
||||
reg m_axis_cc_tready = 0;
|
||||
reg m_axi_awready = 0;
|
||||
reg m_axi_wready = 0;
|
||||
reg [AXI_ID_WIDTH-1:0] m_axi_bid = 0;
|
||||
reg [1:0] m_axi_bresp = 0;
|
||||
reg m_axi_bvalid = 0;
|
||||
reg m_axi_arready = 0;
|
||||
reg [AXI_ID_WIDTH-1:0] m_axi_rid = 0;
|
||||
reg [AXI_DATA_WIDTH-1:0] m_axi_rdata = 0;
|
||||
reg [1:0] m_axi_rresp = 0;
|
||||
reg m_axi_rlast = 0;
|
||||
reg m_axi_rvalid = 0;
|
||||
reg [15:0] completer_id = 0;
|
||||
reg completer_id_enable = 0;
|
||||
reg [2:0] max_payload_size = 0;
|
||||
|
||||
// Outputs
|
||||
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_tvalid;
|
||||
wire m_axis_cc_tlast;
|
||||
wire [32:0] m_axis_cc_tuser;
|
||||
wire [AXI_ID_WIDTH-1:0] m_axi_awid;
|
||||
wire [AXI_ADDR_WIDTH-1:0] m_axi_awaddr;
|
||||
wire [7:0] m_axi_awlen;
|
||||
wire [2:0] m_axi_awsize;
|
||||
wire [1:0] m_axi_awburst;
|
||||
wire m_axi_awlock;
|
||||
wire [3:0] m_axi_awcache;
|
||||
wire [2:0] m_axi_awprot;
|
||||
wire m_axi_awvalid;
|
||||
wire [AXI_DATA_WIDTH-1:0] m_axi_wdata;
|
||||
wire [AXI_STRB_WIDTH-1:0] m_axi_wstrb;
|
||||
wire m_axi_wlast;
|
||||
wire m_axi_wvalid;
|
||||
wire m_axi_bready;
|
||||
wire [AXI_ID_WIDTH-1:0] m_axi_arid;
|
||||
wire [AXI_ADDR_WIDTH-1:0] m_axi_araddr;
|
||||
wire [7:0] m_axi_arlen;
|
||||
wire [2:0] m_axi_arsize;
|
||||
wire [1:0] m_axi_arburst;
|
||||
wire m_axi_arlock;
|
||||
wire [3:0] m_axi_arcache;
|
||||
wire [2:0] m_axi_arprot;
|
||||
wire m_axi_arvalid;
|
||||
wire m_axi_rready;
|
||||
wire status_error_cor;
|
||||
wire status_error_uncor;
|
||||
|
||||
initial begin
|
||||
// myhdl integration
|
||||
$from_myhdl(
|
||||
clk,
|
||||
rst,
|
||||
current_test,
|
||||
s_axis_cq_tdata,
|
||||
s_axis_cq_tkeep,
|
||||
s_axis_cq_tvalid,
|
||||
s_axis_cq_tlast,
|
||||
s_axis_cq_tuser,
|
||||
m_axis_cc_tready,
|
||||
m_axi_awready,
|
||||
m_axi_wready,
|
||||
m_axi_bid,
|
||||
m_axi_bresp,
|
||||
m_axi_bvalid,
|
||||
m_axi_arready,
|
||||
m_axi_rid,
|
||||
m_axi_rdata,
|
||||
m_axi_rresp,
|
||||
m_axi_rlast,
|
||||
m_axi_rvalid,
|
||||
completer_id,
|
||||
completer_id_enable,
|
||||
max_payload_size
|
||||
);
|
||||
$to_myhdl(
|
||||
s_axis_cq_tready,
|
||||
m_axis_cc_tdata,
|
||||
m_axis_cc_tkeep,
|
||||
m_axis_cc_tvalid,
|
||||
m_axis_cc_tlast,
|
||||
m_axis_cc_tuser,
|
||||
m_axi_awid,
|
||||
m_axi_awaddr,
|
||||
m_axi_awlen,
|
||||
m_axi_awsize,
|
||||
m_axi_awburst,
|
||||
m_axi_awlock,
|
||||
m_axi_awcache,
|
||||
m_axi_awprot,
|
||||
m_axi_awvalid,
|
||||
m_axi_wdata,
|
||||
m_axi_wstrb,
|
||||
m_axi_wlast,
|
||||
m_axi_wvalid,
|
||||
m_axi_bready,
|
||||
m_axi_arid,
|
||||
m_axi_araddr,
|
||||
m_axi_arlen,
|
||||
m_axi_arsize,
|
||||
m_axi_arburst,
|
||||
m_axi_arlock,
|
||||
m_axi_arcache,
|
||||
m_axi_arprot,
|
||||
m_axi_arvalid,
|
||||
m_axi_rready,
|
||||
status_error_cor,
|
||||
status_error_uncor
|
||||
);
|
||||
|
||||
// dump file
|
||||
$dumpfile("test_pcie_us_axi_master_256.lxt");
|
||||
$dumpvars(0, test_pcie_us_axi_master_256);
|
||||
end
|
||||
|
||||
pcie_us_axi_master #(
|
||||
.AXIS_PCIE_DATA_WIDTH(AXIS_PCIE_DATA_WIDTH),
|
||||
.AXIS_PCIE_KEEP_WIDTH(AXIS_PCIE_KEEP_WIDTH),
|
||||
.AXI_DATA_WIDTH(AXI_DATA_WIDTH),
|
||||
.AXI_ADDR_WIDTH(AXI_ADDR_WIDTH),
|
||||
.AXI_STRB_WIDTH(AXI_STRB_WIDTH),
|
||||
.AXI_ID_WIDTH(AXI_ID_WIDTH),
|
||||
.AXI_MAX_BURST_LEN(AXI_MAX_BURST_LEN)
|
||||
)
|
||||
UUT (
|
||||
.clk(clk),
|
||||
.rst(rst),
|
||||
.s_axis_cq_tdata(s_axis_cq_tdata),
|
||||
.s_axis_cq_tkeep(s_axis_cq_tkeep),
|
||||
.s_axis_cq_tvalid(s_axis_cq_tvalid),
|
||||
.s_axis_cq_tready(s_axis_cq_tready),
|
||||
.s_axis_cq_tlast(s_axis_cq_tlast),
|
||||
.s_axis_cq_tuser(s_axis_cq_tuser),
|
||||
.m_axis_cc_tdata(m_axis_cc_tdata),
|
||||
.m_axis_cc_tkeep(m_axis_cc_tkeep),
|
||||
.m_axis_cc_tvalid(m_axis_cc_tvalid),
|
||||
.m_axis_cc_tready(m_axis_cc_tready),
|
||||
.m_axis_cc_tlast(m_axis_cc_tlast),
|
||||
.m_axis_cc_tuser(m_axis_cc_tuser),
|
||||
.m_axi_awid(m_axi_awid),
|
||||
.m_axi_awaddr(m_axi_awaddr),
|
||||
.m_axi_awlen(m_axi_awlen),
|
||||
.m_axi_awsize(m_axi_awsize),
|
||||
.m_axi_awburst(m_axi_awburst),
|
||||
.m_axi_awlock(m_axi_awlock),
|
||||
.m_axi_awcache(m_axi_awcache),
|
||||
.m_axi_awprot(m_axi_awprot),
|
||||
.m_axi_awvalid(m_axi_awvalid),
|
||||
.m_axi_awready(m_axi_awready),
|
||||
.m_axi_wdata(m_axi_wdata),
|
||||
.m_axi_wstrb(m_axi_wstrb),
|
||||
.m_axi_wlast(m_axi_wlast),
|
||||
.m_axi_wvalid(m_axi_wvalid),
|
||||
.m_axi_wready(m_axi_wready),
|
||||
.m_axi_bid(m_axi_bid),
|
||||
.m_axi_bresp(m_axi_bresp),
|
||||
.m_axi_bvalid(m_axi_bvalid),
|
||||
.m_axi_bready(m_axi_bready),
|
||||
.m_axi_arid(m_axi_arid),
|
||||
.m_axi_araddr(m_axi_araddr),
|
||||
.m_axi_arlen(m_axi_arlen),
|
||||
.m_axi_arsize(m_axi_arsize),
|
||||
.m_axi_arburst(m_axi_arburst),
|
||||
.m_axi_arlock(m_axi_arlock),
|
||||
.m_axi_arcache(m_axi_arcache),
|
||||
.m_axi_arprot(m_axi_arprot),
|
||||
.m_axi_arvalid(m_axi_arvalid),
|
||||
.m_axi_arready(m_axi_arready),
|
||||
.m_axi_rid(m_axi_rid),
|
||||
.m_axi_rdata(m_axi_rdata),
|
||||
.m_axi_rresp(m_axi_rresp),
|
||||
.m_axi_rlast(m_axi_rlast),
|
||||
.m_axi_rvalid(m_axi_rvalid),
|
||||
.m_axi_rready(m_axi_rready),
|
||||
.completer_id(completer_id),
|
||||
.completer_id_enable(completer_id_enable),
|
||||
.max_payload_size(max_payload_size),
|
||||
.status_error_cor(status_error_cor),
|
||||
.status_error_uncor(status_error_uncor)
|
||||
);
|
||||
|
||||
endmodule
|
420
fpga/lib/pcie/tb/test_pcie_us_axi_master_64.py
Executable file
420
fpga/lib/pcie/tb/test_pcie_us_axi_master_64.py
Executable file
@ -0,0 +1,420 @@
|
||||
#!/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 pcie
|
||||
import pcie_us
|
||||
import axi
|
||||
|
||||
module = 'pcie_us_axi_master'
|
||||
testbench = 'test_%s_64' % module
|
||||
|
||||
srcs = []
|
||||
|
||||
srcs.append("../rtl/%s.v" % module)
|
||||
srcs.append("../rtl/pcie_us_axi_master_wr.v")
|
||||
srcs.append("../rtl/pcie_us_axi_master_rd.v")
|
||||
srcs.append("../rtl/pcie_us_axis_cq_demux.v")
|
||||
srcs.append("../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 = 64
|
||||
AXIS_PCIE_KEEP_WIDTH = (AXIS_PCIE_DATA_WIDTH/32)
|
||||
AXI_DATA_WIDTH = AXIS_PCIE_DATA_WIDTH
|
||||
AXI_ADDR_WIDTH = 64
|
||||
AXI_STRB_WIDTH = (AXI_DATA_WIDTH/8)
|
||||
AXI_ID_WIDTH = 8
|
||||
AXI_MAX_BURST_LEN = 256
|
||||
|
||||
# Inputs
|
||||
clk = Signal(bool(0))
|
||||
rst = Signal(bool(0))
|
||||
current_test = Signal(intbv(0)[8:])
|
||||
|
||||
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_tvalid = Signal(bool(0))
|
||||
s_axis_cq_tlast = Signal(bool(0))
|
||||
s_axis_cq_tuser = Signal(intbv(0)[85:])
|
||||
m_axis_cc_tready = Signal(bool(0))
|
||||
m_axi_awready = Signal(bool(0))
|
||||
m_axi_wready = Signal(bool(0))
|
||||
m_axi_bid = Signal(intbv(0)[AXI_ID_WIDTH:])
|
||||
m_axi_bresp = Signal(intbv(0)[2:])
|
||||
m_axi_bvalid = Signal(bool(0))
|
||||
m_axi_arready = Signal(bool(0))
|
||||
m_axi_rid = Signal(intbv(0)[AXI_ID_WIDTH:])
|
||||
m_axi_rdata = Signal(intbv(0)[AXI_DATA_WIDTH:])
|
||||
m_axi_rresp = Signal(intbv(0)[2:])
|
||||
m_axi_rlast = Signal(bool(0))
|
||||
m_axi_rvalid = Signal(bool(0))
|
||||
completer_id = Signal(intbv(0)[16:])
|
||||
completer_id_enable = Signal(bool(0))
|
||||
max_payload_size = Signal(intbv(0)[3:])
|
||||
|
||||
# Outputs
|
||||
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_tvalid = Signal(bool(0))
|
||||
m_axis_cc_tlast = Signal(bool(0))
|
||||
m_axis_cc_tuser = Signal(intbv(0)[33:])
|
||||
m_axi_awid = Signal(intbv(0)[AXI_ID_WIDTH:])
|
||||
m_axi_awaddr = Signal(intbv(0)[AXI_ADDR_WIDTH:])
|
||||
m_axi_awlen = Signal(intbv(0)[8:])
|
||||
m_axi_awsize = Signal(intbv(3)[3:])
|
||||
m_axi_awburst = Signal(intbv(1)[2:])
|
||||
m_axi_awlock = Signal(bool(0))
|
||||
m_axi_awcache = Signal(intbv(3)[4:])
|
||||
m_axi_awprot = Signal(intbv(2)[3:])
|
||||
m_axi_awvalid = Signal(bool(0))
|
||||
m_axi_wdata = Signal(intbv(0)[AXI_DATA_WIDTH:])
|
||||
m_axi_wstrb = Signal(intbv(0)[AXI_STRB_WIDTH:])
|
||||
m_axi_wlast = Signal(bool(0))
|
||||
m_axi_wvalid = Signal(bool(0))
|
||||
m_axi_bready = Signal(bool(0))
|
||||
m_axi_arid = Signal(intbv(0)[AXI_ID_WIDTH:])
|
||||
m_axi_araddr = Signal(intbv(0)[AXI_ADDR_WIDTH:])
|
||||
m_axi_arlen = Signal(intbv(0)[8:])
|
||||
m_axi_arsize = Signal(intbv(3)[3:])
|
||||
m_axi_arburst = Signal(intbv(1)[2:])
|
||||
m_axi_arlock = Signal(bool(0))
|
||||
m_axi_arcache = Signal(intbv(3)[4:])
|
||||
m_axi_arprot = Signal(intbv(2)[3:])
|
||||
m_axi_arvalid = Signal(bool(0))
|
||||
m_axi_rready = Signal(bool(0))
|
||||
status_error_cor = Signal(bool(0))
|
||||
status_error_uncor = Signal(bool(0))
|
||||
|
||||
# Clock and Reset Interface
|
||||
user_clk=Signal(bool(0))
|
||||
user_reset=Signal(bool(0))
|
||||
sys_clk=Signal(bool(0))
|
||||
sys_reset=Signal(bool(0))
|
||||
|
||||
# AXI4 RAM model
|
||||
axi_ram_inst = axi.AXIRam(2**16)
|
||||
|
||||
axi_ram_port0 = axi_ram_inst.create_port(
|
||||
user_clk,
|
||||
s_axi_awid=m_axi_awid,
|
||||
s_axi_awaddr=m_axi_awaddr,
|
||||
s_axi_awlen=m_axi_awlen,
|
||||
s_axi_awsize=m_axi_awsize,
|
||||
s_axi_awburst=m_axi_awburst,
|
||||
s_axi_awlock=m_axi_awlock,
|
||||
s_axi_awcache=m_axi_awcache,
|
||||
s_axi_awprot=m_axi_awprot,
|
||||
s_axi_awvalid=m_axi_awvalid,
|
||||
s_axi_awready=m_axi_awready,
|
||||
s_axi_wdata=m_axi_wdata,
|
||||
s_axi_wstrb=m_axi_wstrb,
|
||||
s_axi_wlast=m_axi_wlast,
|
||||
s_axi_wvalid=m_axi_wvalid,
|
||||
s_axi_wready=m_axi_wready,
|
||||
s_axi_bid=m_axi_bid,
|
||||
s_axi_bresp=m_axi_bresp,
|
||||
s_axi_bvalid=m_axi_bvalid,
|
||||
s_axi_bready=m_axi_bready,
|
||||
s_axi_arid=m_axi_arid,
|
||||
s_axi_araddr=m_axi_araddr,
|
||||
s_axi_arlen=m_axi_arlen,
|
||||
s_axi_arsize=m_axi_arsize,
|
||||
s_axi_arburst=m_axi_arburst,
|
||||
s_axi_arlock=m_axi_arlock,
|
||||
s_axi_arcache=m_axi_arcache,
|
||||
s_axi_arprot=m_axi_arprot,
|
||||
s_axi_arvalid=m_axi_arvalid,
|
||||
s_axi_arready=m_axi_arready,
|
||||
s_axi_rid=m_axi_rid,
|
||||
s_axi_rdata=m_axi_rdata,
|
||||
s_axi_rresp=m_axi_rresp,
|
||||
s_axi_rlast=m_axi_rlast,
|
||||
s_axi_rvalid=m_axi_rvalid,
|
||||
s_axi_rready=m_axi_rready,
|
||||
name='port0'
|
||||
)
|
||||
|
||||
# PCIe devices
|
||||
rc = pcie.RootComplex()
|
||||
|
||||
dev = pcie_us.UltrascalePCIe()
|
||||
|
||||
dev.pcie_generation = 3
|
||||
dev.pcie_link_width = 2
|
||||
dev.user_clock_frequency = 250e6
|
||||
|
||||
dev.functions[0].configure_bar(0, 16*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_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=Signal(intbv(0)[AXIS_PCIE_DATA_WIDTH:]),
|
||||
s_axis_rq_tuser=Signal(intbv(0)[60:]),
|
||||
s_axis_rq_tlast=Signal(bool(0)),
|
||||
s_axis_rq_tkeep=Signal(intbv(0)[AXIS_PCIE_KEEP_WIDTH:]),
|
||||
s_axis_rq_tvalid=Signal(bool(0)),
|
||||
s_axis_rq_tready=Signal(bool(1)),
|
||||
# pcie_rq_seq_num=pcie_rq_seq_num,
|
||||
# pcie_rq_seq_num_vld=pcie_rq_seq_num_vld,
|
||||
# pcie_rq_tag=pcie_rq_tag,
|
||||
# pcie_rq_tag_av=pcie_rq_tag_av,
|
||||
# pcie_rq_tag_vld=pcie_rq_tag_vld,
|
||||
|
||||
# Requester Completion Interface
|
||||
m_axis_rc_tdata=Signal(intbv(0)[AXIS_PCIE_DATA_WIDTH:]),
|
||||
m_axis_rc_tuser=Signal(intbv(0)[75:]),
|
||||
m_axis_rc_tlast=Signal(bool(0)),
|
||||
m_axis_rc_tkeep=Signal(intbv(0)[AXIS_PCIE_KEEP_WIDTH:]),
|
||||
m_axis_rc_tvalid=Signal(bool(0)),
|
||||
m_axis_rc_tready=Signal(bool(0)),
|
||||
|
||||
# Transmit Flow Control Interface
|
||||
# pcie_tfc_nph_av=pcie_tfc_nph_av,
|
||||
# pcie_tfc_npd_av=pcie_tfc_npd_av,
|
||||
|
||||
# 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_per_function_update_done=cfg_per_function_update_done,
|
||||
# cfg_per_function_number=cfg_per_function_number,
|
||||
# cfg_per_function_output_request=cfg_per_function_output_request,
|
||||
# cfg_dsn=cfg_dsn,
|
||||
# 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=cfg_err_cor_in,
|
||||
# cfg_err_uncor_in=cfg_err_uncor_in,
|
||||
# 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,
|
||||
|
||||
# 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
|
||||
)
|
||||
|
||||
# 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,
|
||||
s_axis_cq_tdata=s_axis_cq_tdata,
|
||||
s_axis_cq_tkeep=s_axis_cq_tkeep,
|
||||
s_axis_cq_tvalid=s_axis_cq_tvalid,
|
||||
s_axis_cq_tready=s_axis_cq_tready,
|
||||
s_axis_cq_tlast=s_axis_cq_tlast,
|
||||
s_axis_cq_tuser=s_axis_cq_tuser,
|
||||
m_axis_cc_tdata=m_axis_cc_tdata,
|
||||
m_axis_cc_tkeep=m_axis_cc_tkeep,
|
||||
m_axis_cc_tvalid=m_axis_cc_tvalid,
|
||||
m_axis_cc_tready=m_axis_cc_tready,
|
||||
m_axis_cc_tlast=m_axis_cc_tlast,
|
||||
m_axis_cc_tuser=m_axis_cc_tuser,
|
||||
m_axi_awid=m_axi_awid,
|
||||
m_axi_awaddr=m_axi_awaddr,
|
||||
m_axi_awlen=m_axi_awlen,
|
||||
m_axi_awsize=m_axi_awsize,
|
||||
m_axi_awburst=m_axi_awburst,
|
||||
m_axi_awlock=m_axi_awlock,
|
||||
m_axi_awcache=m_axi_awcache,
|
||||
m_axi_awprot=m_axi_awprot,
|
||||
m_axi_awvalid=m_axi_awvalid,
|
||||
m_axi_awready=m_axi_awready,
|
||||
m_axi_wdata=m_axi_wdata,
|
||||
m_axi_wstrb=m_axi_wstrb,
|
||||
m_axi_wlast=m_axi_wlast,
|
||||
m_axi_wvalid=m_axi_wvalid,
|
||||
m_axi_wready=m_axi_wready,
|
||||
m_axi_bid=m_axi_bid,
|
||||
m_axi_bresp=m_axi_bresp,
|
||||
m_axi_bvalid=m_axi_bvalid,
|
||||
m_axi_bready=m_axi_bready,
|
||||
m_axi_arid=m_axi_arid,
|
||||
m_axi_araddr=m_axi_araddr,
|
||||
m_axi_arlen=m_axi_arlen,
|
||||
m_axi_arsize=m_axi_arsize,
|
||||
m_axi_arburst=m_axi_arburst,
|
||||
m_axi_arlock=m_axi_arlock,
|
||||
m_axi_arcache=m_axi_arcache,
|
||||
m_axi_arprot=m_axi_arprot,
|
||||
m_axi_arvalid=m_axi_arvalid,
|
||||
m_axi_arready=m_axi_arready,
|
||||
m_axi_rid=m_axi_rid,
|
||||
m_axi_rdata=m_axi_rdata,
|
||||
m_axi_rresp=m_axi_rresp,
|
||||
m_axi_rlast=m_axi_rlast,
|
||||
m_axi_rvalid=m_axi_rvalid,
|
||||
m_axi_rready=m_axi_rready,
|
||||
completer_id=completer_id,
|
||||
completer_id_enable=completer_id_enable,
|
||||
max_payload_size=max_payload_size,
|
||||
status_error_cor=status_error_cor,
|
||||
status_error_uncor=status_error_uncor
|
||||
)
|
||||
|
||||
@always(delay(4))
|
||||
def clkgen():
|
||||
clk.next = not clk
|
||||
|
||||
@always_comb
|
||||
def clk_logic():
|
||||
sys_clk.next = clk
|
||||
sys_reset.next = not rst
|
||||
|
||||
status_error_cor_asserted = Signal(bool(0))
|
||||
status_error_uncor_asserted = Signal(bool(0))
|
||||
|
||||
@always(user_clk.posedge)
|
||||
def monitor():
|
||||
if (status_error_cor):
|
||||
status_error_cor_asserted.next = 1
|
||||
if (status_error_uncor):
|
||||
status_error_uncor_asserted.next = 1
|
||||
|
||||
@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
|
||||
|
||||
max_payload_size.next = 0
|
||||
|
||||
yield user_clk.posedge
|
||||
print("test 1: enumeration")
|
||||
current_test.next = 1
|
||||
|
||||
yield rc.enumerate()
|
||||
|
||||
dev_bar0 = rc.tree[0][0].bar[0]
|
||||
|
||||
yield delay(100)
|
||||
|
||||
yield clk.posedge
|
||||
print("test 2: memory write")
|
||||
current_test.next = 2
|
||||
|
||||
pcie_addr = 0x00000000
|
||||
test_data = b'\x11\x22\x33\x44'
|
||||
|
||||
yield rc.mem_write(dev_bar0+pcie_addr, test_data)
|
||||
|
||||
yield delay(300)
|
||||
|
||||
data = axi_ram_inst.read_mem(pcie_addr, 32)
|
||||
for i in range(0, len(data), 16):
|
||||
print(" ".join(("{:02x}".format(c) for c in bytearray(data[i:i+16]))))
|
||||
|
||||
assert axi_ram_inst.read_mem(pcie_addr, len(test_data)) == test_data
|
||||
|
||||
assert not status_error_cor_asserted
|
||||
assert not status_error_uncor_asserted
|
||||
|
||||
yield delay(100)
|
||||
|
||||
yield clk.posedge
|
||||
print("test 3: memory read")
|
||||
current_test.next = 3
|
||||
|
||||
pcie_addr = 0x00000000
|
||||
test_data = b'\x11\x22\x33\x44'
|
||||
|
||||
axi_ram_inst.write_mem(pcie_addr, test_data)
|
||||
|
||||
data = axi_ram_inst.read_mem(0, 32)
|
||||
for i in range(0, len(data), 16):
|
||||
print(" ".join(("{:02x}".format(c) for c in bytearray(data[i:i+16]))))
|
||||
|
||||
val = yield from rc.mem_read(dev_bar0+pcie_addr, len(test_data), 1000)
|
||||
|
||||
print(val)
|
||||
|
||||
assert val == test_data
|
||||
|
||||
assert not status_error_cor_asserted
|
||||
assert not status_error_uncor_asserted
|
||||
|
||||
yield delay(100)
|
||||
|
||||
raise StopSimulation
|
||||
|
||||
return instances()
|
||||
|
||||
def test_bench():
|
||||
sim = Simulation(bench())
|
||||
sim.run()
|
||||
|
||||
if __name__ == '__main__':
|
||||
print("Running test...")
|
||||
test_bench()
|
236
fpga/lib/pcie/tb/test_pcie_us_axi_master_64.v
Normal file
236
fpga/lib/pcie/tb/test_pcie_us_axi_master_64.v
Normal file
@ -0,0 +1,236 @@
|
||||
/*
|
||||
|
||||
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 pcie_us_axi_master
|
||||
*/
|
||||
module test_pcie_us_axi_master_64;
|
||||
|
||||
// Parameters
|
||||
parameter AXIS_PCIE_DATA_WIDTH = 64;
|
||||
parameter AXIS_PCIE_KEEP_WIDTH = (AXIS_PCIE_DATA_WIDTH/32);
|
||||
parameter AXI_DATA_WIDTH = AXIS_PCIE_DATA_WIDTH;
|
||||
parameter AXI_ADDR_WIDTH = 64;
|
||||
parameter AXI_STRB_WIDTH = (AXI_DATA_WIDTH/8);
|
||||
parameter AXI_ID_WIDTH = 8;
|
||||
parameter AXI_MAX_BURST_LEN = 256;
|
||||
|
||||
// Inputs
|
||||
reg clk = 0;
|
||||
reg rst = 0;
|
||||
reg [7:0] current_test = 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_tvalid = 0;
|
||||
reg s_axis_cq_tlast = 0;
|
||||
reg [84:0] s_axis_cq_tuser = 0;
|
||||
reg m_axis_cc_tready = 0;
|
||||
reg m_axi_awready = 0;
|
||||
reg m_axi_wready = 0;
|
||||
reg [AXI_ID_WIDTH-1:0] m_axi_bid = 0;
|
||||
reg [1:0] m_axi_bresp = 0;
|
||||
reg m_axi_bvalid = 0;
|
||||
reg m_axi_arready = 0;
|
||||
reg [AXI_ID_WIDTH-1:0] m_axi_rid = 0;
|
||||
reg [AXI_DATA_WIDTH-1:0] m_axi_rdata = 0;
|
||||
reg [1:0] m_axi_rresp = 0;
|
||||
reg m_axi_rlast = 0;
|
||||
reg m_axi_rvalid = 0;
|
||||
reg [15:0] completer_id = 0;
|
||||
reg completer_id_enable = 0;
|
||||
reg [2:0] max_payload_size = 0;
|
||||
|
||||
// Outputs
|
||||
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_tvalid;
|
||||
wire m_axis_cc_tlast;
|
||||
wire [32:0] m_axis_cc_tuser;
|
||||
wire [AXI_ID_WIDTH-1:0] m_axi_awid;
|
||||
wire [AXI_ADDR_WIDTH-1:0] m_axi_awaddr;
|
||||
wire [7:0] m_axi_awlen;
|
||||
wire [2:0] m_axi_awsize;
|
||||
wire [1:0] m_axi_awburst;
|
||||
wire m_axi_awlock;
|
||||
wire [3:0] m_axi_awcache;
|
||||
wire [2:0] m_axi_awprot;
|
||||
wire m_axi_awvalid;
|
||||
wire [AXI_DATA_WIDTH-1:0] m_axi_wdata;
|
||||
wire [AXI_STRB_WIDTH-1:0] m_axi_wstrb;
|
||||
wire m_axi_wlast;
|
||||
wire m_axi_wvalid;
|
||||
wire m_axi_bready;
|
||||
wire [AXI_ID_WIDTH-1:0] m_axi_arid;
|
||||
wire [AXI_ADDR_WIDTH-1:0] m_axi_araddr;
|
||||
wire [7:0] m_axi_arlen;
|
||||
wire [2:0] m_axi_arsize;
|
||||
wire [1:0] m_axi_arburst;
|
||||
wire m_axi_arlock;
|
||||
wire [3:0] m_axi_arcache;
|
||||
wire [2:0] m_axi_arprot;
|
||||
wire m_axi_arvalid;
|
||||
wire m_axi_rready;
|
||||
wire status_error_cor;
|
||||
wire status_error_uncor;
|
||||
|
||||
initial begin
|
||||
// myhdl integration
|
||||
$from_myhdl(
|
||||
clk,
|
||||
rst,
|
||||
current_test,
|
||||
s_axis_cq_tdata,
|
||||
s_axis_cq_tkeep,
|
||||
s_axis_cq_tvalid,
|
||||
s_axis_cq_tlast,
|
||||
s_axis_cq_tuser,
|
||||
m_axis_cc_tready,
|
||||
m_axi_awready,
|
||||
m_axi_wready,
|
||||
m_axi_bid,
|
||||
m_axi_bresp,
|
||||
m_axi_bvalid,
|
||||
m_axi_arready,
|
||||
m_axi_rid,
|
||||
m_axi_rdata,
|
||||
m_axi_rresp,
|
||||
m_axi_rlast,
|
||||
m_axi_rvalid,
|
||||
completer_id,
|
||||
completer_id_enable,
|
||||
max_payload_size
|
||||
);
|
||||
$to_myhdl(
|
||||
s_axis_cq_tready,
|
||||
m_axis_cc_tdata,
|
||||
m_axis_cc_tkeep,
|
||||
m_axis_cc_tvalid,
|
||||
m_axis_cc_tlast,
|
||||
m_axis_cc_tuser,
|
||||
m_axi_awid,
|
||||
m_axi_awaddr,
|
||||
m_axi_awlen,
|
||||
m_axi_awsize,
|
||||
m_axi_awburst,
|
||||
m_axi_awlock,
|
||||
m_axi_awcache,
|
||||
m_axi_awprot,
|
||||
m_axi_awvalid,
|
||||
m_axi_wdata,
|
||||
m_axi_wstrb,
|
||||
m_axi_wlast,
|
||||
m_axi_wvalid,
|
||||
m_axi_bready,
|
||||
m_axi_arid,
|
||||
m_axi_araddr,
|
||||
m_axi_arlen,
|
||||
m_axi_arsize,
|
||||
m_axi_arburst,
|
||||
m_axi_arlock,
|
||||
m_axi_arcache,
|
||||
m_axi_arprot,
|
||||
m_axi_arvalid,
|
||||
m_axi_rready,
|
||||
status_error_cor,
|
||||
status_error_uncor
|
||||
);
|
||||
|
||||
// dump file
|
||||
$dumpfile("test_pcie_us_axi_master_64.lxt");
|
||||
$dumpvars(0, test_pcie_us_axi_master_64);
|
||||
end
|
||||
|
||||
pcie_us_axi_master #(
|
||||
.AXIS_PCIE_DATA_WIDTH(AXIS_PCIE_DATA_WIDTH),
|
||||
.AXIS_PCIE_KEEP_WIDTH(AXIS_PCIE_KEEP_WIDTH),
|
||||
.AXI_DATA_WIDTH(AXI_DATA_WIDTH),
|
||||
.AXI_ADDR_WIDTH(AXI_ADDR_WIDTH),
|
||||
.AXI_STRB_WIDTH(AXI_STRB_WIDTH),
|
||||
.AXI_ID_WIDTH(AXI_ID_WIDTH),
|
||||
.AXI_MAX_BURST_LEN(AXI_MAX_BURST_LEN)
|
||||
)
|
||||
UUT (
|
||||
.clk(clk),
|
||||
.rst(rst),
|
||||
.s_axis_cq_tdata(s_axis_cq_tdata),
|
||||
.s_axis_cq_tkeep(s_axis_cq_tkeep),
|
||||
.s_axis_cq_tvalid(s_axis_cq_tvalid),
|
||||
.s_axis_cq_tready(s_axis_cq_tready),
|
||||
.s_axis_cq_tlast(s_axis_cq_tlast),
|
||||
.s_axis_cq_tuser(s_axis_cq_tuser),
|
||||
.m_axis_cc_tdata(m_axis_cc_tdata),
|
||||
.m_axis_cc_tkeep(m_axis_cc_tkeep),
|
||||
.m_axis_cc_tvalid(m_axis_cc_tvalid),
|
||||
.m_axis_cc_tready(m_axis_cc_tready),
|
||||
.m_axis_cc_tlast(m_axis_cc_tlast),
|
||||
.m_axis_cc_tuser(m_axis_cc_tuser),
|
||||
.m_axi_awid(m_axi_awid),
|
||||
.m_axi_awaddr(m_axi_awaddr),
|
||||
.m_axi_awlen(m_axi_awlen),
|
||||
.m_axi_awsize(m_axi_awsize),
|
||||
.m_axi_awburst(m_axi_awburst),
|
||||
.m_axi_awlock(m_axi_awlock),
|
||||
.m_axi_awcache(m_axi_awcache),
|
||||
.m_axi_awprot(m_axi_awprot),
|
||||
.m_axi_awvalid(m_axi_awvalid),
|
||||
.m_axi_awready(m_axi_awready),
|
||||
.m_axi_wdata(m_axi_wdata),
|
||||
.m_axi_wstrb(m_axi_wstrb),
|
||||
.m_axi_wlast(m_axi_wlast),
|
||||
.m_axi_wvalid(m_axi_wvalid),
|
||||
.m_axi_wready(m_axi_wready),
|
||||
.m_axi_bid(m_axi_bid),
|
||||
.m_axi_bresp(m_axi_bresp),
|
||||
.m_axi_bvalid(m_axi_bvalid),
|
||||
.m_axi_bready(m_axi_bready),
|
||||
.m_axi_arid(m_axi_arid),
|
||||
.m_axi_araddr(m_axi_araddr),
|
||||
.m_axi_arlen(m_axi_arlen),
|
||||
.m_axi_arsize(m_axi_arsize),
|
||||
.m_axi_arburst(m_axi_arburst),
|
||||
.m_axi_arlock(m_axi_arlock),
|
||||
.m_axi_arcache(m_axi_arcache),
|
||||
.m_axi_arprot(m_axi_arprot),
|
||||
.m_axi_arvalid(m_axi_arvalid),
|
||||
.m_axi_arready(m_axi_arready),
|
||||
.m_axi_rid(m_axi_rid),
|
||||
.m_axi_rdata(m_axi_rdata),
|
||||
.m_axi_rresp(m_axi_rresp),
|
||||
.m_axi_rlast(m_axi_rlast),
|
||||
.m_axi_rvalid(m_axi_rvalid),
|
||||
.m_axi_rready(m_axi_rready),
|
||||
.completer_id(completer_id),
|
||||
.completer_id_enable(completer_id_enable),
|
||||
.max_payload_size(max_payload_size),
|
||||
.status_error_cor(status_error_cor),
|
||||
.status_error_uncor(status_error_uncor)
|
||||
);
|
||||
|
||||
endmodule
|
440
fpga/lib/pcie/tb/test_pcie_us_axi_master_rd_128.py
Executable file
440
fpga/lib/pcie/tb/test_pcie_us_axi_master_rd_128.py
Executable file
@ -0,0 +1,440 @@
|
||||
#!/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 pcie
|
||||
import pcie_us
|
||||
import axi
|
||||
|
||||
module = 'pcie_us_axi_master_rd'
|
||||
testbench = 'test_%s_128' % module
|
||||
|
||||
srcs = []
|
||||
|
||||
srcs.append("../rtl/%s.v" % module)
|
||||
srcs.append("%s.v" % testbench)
|
||||
|
||||
src = ' '.join(srcs)
|
||||
|
||||
build_cmd = "iverilog -o %s.vvp %s" % (testbench, src)
|
||||
|
||||
def bench():
|
||||
|
||||
# Parameters
|
||||
AXIS_PCIE_DATA_WIDTH = 128
|
||||
AXIS_PCIE_KEEP_WIDTH = (AXIS_PCIE_DATA_WIDTH/32)
|
||||
AXI_DATA_WIDTH = AXIS_PCIE_DATA_WIDTH
|
||||
AXI_ADDR_WIDTH = 64
|
||||
AXI_STRB_WIDTH = (AXI_DATA_WIDTH/8)
|
||||
AXI_ID_WIDTH = 8
|
||||
AXI_MAX_BURST_LEN = 256
|
||||
|
||||
# Inputs
|
||||
clk = Signal(bool(0))
|
||||
rst = Signal(bool(0))
|
||||
current_test = Signal(intbv(0)[8:])
|
||||
|
||||
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_tvalid = Signal(bool(0))
|
||||
s_axis_cq_tlast = Signal(bool(0))
|
||||
s_axis_cq_tuser = Signal(intbv(0)[85:])
|
||||
m_axis_cc_tready = Signal(bool(0))
|
||||
m_axi_arready = Signal(bool(0))
|
||||
m_axi_rid = Signal(intbv(0)[AXI_ID_WIDTH:])
|
||||
m_axi_rdata = Signal(intbv(0)[AXI_DATA_WIDTH:])
|
||||
m_axi_rresp = Signal(intbv(0)[2:])
|
||||
m_axi_rlast = Signal(bool(0))
|
||||
m_axi_rvalid = Signal(bool(0))
|
||||
completer_id = Signal(intbv(0)[16:])
|
||||
completer_id_enable = Signal(bool(0))
|
||||
max_payload_size = Signal(intbv(0)[3:])
|
||||
|
||||
# Outputs
|
||||
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_tvalid = Signal(bool(0))
|
||||
m_axis_cc_tlast = Signal(bool(0))
|
||||
m_axis_cc_tuser = Signal(intbv(0)[33:])
|
||||
m_axi_arid = Signal(intbv(0)[AXI_ID_WIDTH:])
|
||||
m_axi_araddr = Signal(intbv(0)[AXI_ADDR_WIDTH:])
|
||||
m_axi_arlen = Signal(intbv(0)[8:])
|
||||
m_axi_arsize = Signal(intbv(4)[3:])
|
||||
m_axi_arburst = Signal(intbv(1)[2:])
|
||||
m_axi_arlock = Signal(bool(0))
|
||||
m_axi_arcache = Signal(intbv(3)[4:])
|
||||
m_axi_arprot = Signal(intbv(2)[3:])
|
||||
m_axi_arvalid = Signal(bool(0))
|
||||
m_axi_rready = Signal(bool(0))
|
||||
status_error_cor = Signal(bool(0))
|
||||
status_error_uncor = Signal(bool(0))
|
||||
|
||||
# Clock and Reset Interface
|
||||
user_clk=Signal(bool(0))
|
||||
user_reset=Signal(bool(0))
|
||||
sys_clk=Signal(bool(0))
|
||||
sys_reset=Signal(bool(0))
|
||||
|
||||
# AXI4 RAM model
|
||||
axi_ram_inst = axi.AXIRam(2**16)
|
||||
|
||||
axi_ram_port0 = axi_ram_inst.create_port(
|
||||
user_clk,
|
||||
s_axi_arid=m_axi_arid,
|
||||
s_axi_araddr=m_axi_araddr,
|
||||
s_axi_arlen=m_axi_arlen,
|
||||
s_axi_arsize=m_axi_arsize,
|
||||
s_axi_arburst=m_axi_arburst,
|
||||
s_axi_arlock=m_axi_arlock,
|
||||
s_axi_arcache=m_axi_arcache,
|
||||
s_axi_arprot=m_axi_arprot,
|
||||
s_axi_arvalid=m_axi_arvalid,
|
||||
s_axi_arready=m_axi_arready,
|
||||
s_axi_rid=m_axi_rid,
|
||||
s_axi_rdata=m_axi_rdata,
|
||||
s_axi_rresp=m_axi_rresp,
|
||||
s_axi_rlast=m_axi_rlast,
|
||||
s_axi_rvalid=m_axi_rvalid,
|
||||
s_axi_rready=m_axi_rready,
|
||||
name='port0'
|
||||
)
|
||||
|
||||
# PCIe devices
|
||||
rc = pcie.RootComplex()
|
||||
|
||||
dev = pcie_us.UltrascalePCIe()
|
||||
|
||||
dev.pcie_generation = 3
|
||||
dev.pcie_link_width = 4
|
||||
dev.user_clock_frequency = 250e6
|
||||
|
||||
dev.functions[0].configure_bar(0, 16*1024*1024)
|
||||
dev.functions[0].configure_bar(1, 32, io=True)
|
||||
|
||||
rc.make_port().connect(dev)
|
||||
|
||||
cq_pause = Signal(bool(0))
|
||||
cc_pause = Signal(bool(0))
|
||||
rq_pause = Signal(bool(0))
|
||||
rc_pause = Signal(bool(0))
|
||||
|
||||
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_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=Signal(intbv(0)[AXIS_PCIE_DATA_WIDTH:]),
|
||||
s_axis_rq_tuser=Signal(intbv(0)[60:]),
|
||||
s_axis_rq_tlast=Signal(bool(0)),
|
||||
s_axis_rq_tkeep=Signal(intbv(0)[AXIS_PCIE_KEEP_WIDTH:]),
|
||||
s_axis_rq_tvalid=Signal(bool(0)),
|
||||
s_axis_rq_tready=Signal(bool(1)),
|
||||
# pcie_rq_seq_num=pcie_rq_seq_num,
|
||||
# pcie_rq_seq_num_vld=pcie_rq_seq_num_vld,
|
||||
# pcie_rq_tag=pcie_rq_tag,
|
||||
# pcie_rq_tag_av=pcie_rq_tag_av,
|
||||
# pcie_rq_tag_vld=pcie_rq_tag_vld,
|
||||
|
||||
# Requester Completion Interface
|
||||
m_axis_rc_tdata=Signal(intbv(0)[AXIS_PCIE_DATA_WIDTH:]),
|
||||
m_axis_rc_tuser=Signal(intbv(0)[75:]),
|
||||
m_axis_rc_tlast=Signal(bool(0)),
|
||||
m_axis_rc_tkeep=Signal(intbv(0)[AXIS_PCIE_KEEP_WIDTH:]),
|
||||
m_axis_rc_tvalid=Signal(bool(0)),
|
||||
m_axis_rc_tready=Signal(bool(0)),
|
||||
|
||||
# Transmit Flow Control Interface
|
||||
# pcie_tfc_nph_av=pcie_tfc_nph_av,
|
||||
# pcie_tfc_npd_av=pcie_tfc_npd_av,
|
||||
|
||||
# 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_per_function_update_done=cfg_per_function_update_done,
|
||||
# cfg_per_function_number=cfg_per_function_number,
|
||||
# cfg_per_function_output_request=cfg_per_function_output_request,
|
||||
# cfg_dsn=cfg_dsn,
|
||||
# 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=cfg_err_cor_in,
|
||||
# cfg_err_uncor_in=cfg_err_uncor_in,
|
||||
# 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,
|
||||
|
||||
# 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,
|
||||
|
||||
cq_pause=cq_pause,
|
||||
cc_pause=cc_pause,
|
||||
rq_pause=rq_pause,
|
||||
rc_pause=rc_pause
|
||||
)
|
||||
|
||||
# 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,
|
||||
s_axis_cq_tdata=s_axis_cq_tdata,
|
||||
s_axis_cq_tkeep=s_axis_cq_tkeep,
|
||||
s_axis_cq_tvalid=s_axis_cq_tvalid,
|
||||
s_axis_cq_tready=s_axis_cq_tready,
|
||||
s_axis_cq_tlast=s_axis_cq_tlast,
|
||||
s_axis_cq_tuser=s_axis_cq_tuser,
|
||||
m_axis_cc_tdata=m_axis_cc_tdata,
|
||||
m_axis_cc_tkeep=m_axis_cc_tkeep,
|
||||
m_axis_cc_tvalid=m_axis_cc_tvalid,
|
||||
m_axis_cc_tready=m_axis_cc_tready,
|
||||
m_axis_cc_tlast=m_axis_cc_tlast,
|
||||
m_axis_cc_tuser=m_axis_cc_tuser,
|
||||
m_axi_arid=m_axi_arid,
|
||||
m_axi_araddr=m_axi_araddr,
|
||||
m_axi_arlen=m_axi_arlen,
|
||||
m_axi_arsize=m_axi_arsize,
|
||||
m_axi_arburst=m_axi_arburst,
|
||||
m_axi_arlock=m_axi_arlock,
|
||||
m_axi_arcache=m_axi_arcache,
|
||||
m_axi_arprot=m_axi_arprot,
|
||||
m_axi_arvalid=m_axi_arvalid,
|
||||
m_axi_arready=m_axi_arready,
|
||||
m_axi_rid=m_axi_rid,
|
||||
m_axi_rdata=m_axi_rdata,
|
||||
m_axi_rresp=m_axi_rresp,
|
||||
m_axi_rlast=m_axi_rlast,
|
||||
m_axi_rvalid=m_axi_rvalid,
|
||||
m_axi_rready=m_axi_rready,
|
||||
completer_id=completer_id,
|
||||
completer_id_enable=completer_id_enable,
|
||||
max_payload_size=max_payload_size,
|
||||
status_error_cor=status_error_cor,
|
||||
status_error_uncor=status_error_uncor
|
||||
)
|
||||
|
||||
@always(delay(4))
|
||||
def clkgen():
|
||||
clk.next = not clk
|
||||
|
||||
@always_comb
|
||||
def clk_logic():
|
||||
sys_clk.next = clk
|
||||
sys_reset.next = not rst
|
||||
|
||||
status_error_cor_asserted = Signal(bool(0))
|
||||
status_error_uncor_asserted = Signal(bool(0))
|
||||
|
||||
@always(user_clk.posedge)
|
||||
def monitor():
|
||||
if (status_error_cor):
|
||||
status_error_cor_asserted.next = 1
|
||||
if (status_error_uncor):
|
||||
status_error_uncor_asserted.next = 1
|
||||
|
||||
cq_pause_toggle = Signal(bool(0))
|
||||
cc_pause_toggle = Signal(bool(0))
|
||||
rq_pause_toggle = Signal(bool(0))
|
||||
rc_pause_toggle = Signal(bool(0))
|
||||
|
||||
@instance
|
||||
def pause_toggle():
|
||||
while True:
|
||||
if (cq_pause_toggle or cc_pause_toggle or rq_pause_toggle or rc_pause_toggle):
|
||||
cq_pause.next = cq_pause_toggle
|
||||
cc_pause.next = cc_pause_toggle
|
||||
rq_pause.next = rq_pause_toggle
|
||||
rc_pause.next = rc_pause_toggle
|
||||
|
||||
yield user_clk.posedge
|
||||
yield user_clk.posedge
|
||||
yield user_clk.posedge
|
||||
|
||||
cq_pause.next = 0
|
||||
cc_pause.next = 0
|
||||
rq_pause.next = 0
|
||||
rc_pause.next = 0
|
||||
|
||||
yield user_clk.posedge
|
||||
|
||||
@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
|
||||
|
||||
max_payload_size.next = 0
|
||||
|
||||
yield user_clk.posedge
|
||||
print("test 1: enumeration")
|
||||
current_test.next = 1
|
||||
|
||||
yield rc.enumerate()
|
||||
|
||||
dev_bar0 = rc.tree[0][0].bar[0]
|
||||
dev_bar1 = rc.tree[0][0].bar[1]
|
||||
|
||||
yield delay(100)
|
||||
|
||||
yield clk.posedge
|
||||
print("test 2: memory read")
|
||||
current_test.next = 2
|
||||
|
||||
pcie_addr = 0x00000000
|
||||
test_data = b'\x11\x22\x33\x44'
|
||||
|
||||
axi_ram_inst.write_mem(pcie_addr, test_data)
|
||||
|
||||
data = axi_ram_inst.read_mem(0, 32)
|
||||
for i in range(0, len(data), 16):
|
||||
print(" ".join(("{:02x}".format(c) for c in bytearray(data[i:i+16]))))
|
||||
|
||||
val = yield from rc.mem_read(dev_bar0+pcie_addr, len(test_data), 1000)
|
||||
|
||||
print(val)
|
||||
|
||||
assert val == test_data
|
||||
|
||||
assert not status_error_cor_asserted
|
||||
assert not status_error_uncor_asserted
|
||||
|
||||
yield delay(100)
|
||||
|
||||
yield user_clk.posedge
|
||||
print("test 3: various reads")
|
||||
current_test.next = 3
|
||||
|
||||
for length in list(range(1,34))+[1024]:
|
||||
for pcie_offset in list(range(8,25))+list(range(4096-16,4096)):
|
||||
for pause in [False, True]:
|
||||
print("length %d, pcie_offset %d"% (length, pcie_offset))
|
||||
#pcie_addr = length * 0x100000000 + pcie_offset * 0x10000 + offset
|
||||
pcie_addr = pcie_offset
|
||||
test_data = bytearray([x%256 for x in range(length)])
|
||||
|
||||
axi_ram_inst.write_mem(pcie_addr & 0xffff80, b'\x55'*(len(test_data)+256))
|
||||
axi_ram_inst.write_mem(pcie_addr, test_data)
|
||||
|
||||
data = axi_ram_inst.read_mem(pcie_addr&0xfffff0, 64)
|
||||
for i in range(0, len(data), 16):
|
||||
print(" ".join(("{:02x}".format(c) for c in bytearray(data[i:i+16]))))
|
||||
|
||||
cq_pause_toggle.next = pause
|
||||
cc_pause_toggle.next = pause
|
||||
|
||||
val = yield from rc.mem_read(dev_bar0+pcie_addr, len(test_data), 1000)
|
||||
|
||||
cq_pause_toggle.next = 0
|
||||
cc_pause_toggle.next = 0
|
||||
|
||||
print(val)
|
||||
|
||||
assert val == test_data
|
||||
|
||||
assert not status_error_cor_asserted
|
||||
assert not status_error_uncor_asserted
|
||||
|
||||
yield delay(100)
|
||||
|
||||
yield clk.posedge
|
||||
print("test 4: bad requests")
|
||||
current_test.next = 4
|
||||
|
||||
yield from rc.mem_write(dev_bar0, b'\x11\x22\x33\x44')
|
||||
|
||||
yield delay(100)
|
||||
|
||||
assert not status_error_cor_asserted
|
||||
assert status_error_uncor_asserted
|
||||
|
||||
status_error_cor_asserted.next = False
|
||||
status_error_uncor_asserted.next = False
|
||||
|
||||
try:
|
||||
yield from rc.io_write(dev_bar1, b'\x11\x22\x33\x44')
|
||||
except:
|
||||
print("Caught unsuccessful completion exception")
|
||||
pass
|
||||
else:
|
||||
assert False
|
||||
|
||||
assert status_error_cor_asserted
|
||||
assert not status_error_uncor_asserted
|
||||
|
||||
status_error_cor_asserted.next = False
|
||||
status_error_uncor_asserted.next = False
|
||||
|
||||
yield delay(100)
|
||||
|
||||
raise StopSimulation
|
||||
|
||||
return instances()
|
||||
|
||||
def test_bench():
|
||||
sim = Simulation(bench())
|
||||
sim.run()
|
||||
|
||||
if __name__ == '__main__':
|
||||
print("Running test...")
|
||||
test_bench()
|
179
fpga/lib/pcie/tb/test_pcie_us_axi_master_rd_128.v
Normal file
179
fpga/lib/pcie/tb/test_pcie_us_axi_master_rd_128.v
Normal file
@ -0,0 +1,179 @@
|
||||
/*
|
||||
|
||||
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 pcie_us_axi_master_rd
|
||||
*/
|
||||
module test_pcie_us_axi_master_rd_128;
|
||||
|
||||
// Parameters
|
||||
parameter AXIS_PCIE_DATA_WIDTH = 128;
|
||||
parameter AXIS_PCIE_KEEP_WIDTH = (AXIS_PCIE_DATA_WIDTH/32);
|
||||
parameter AXI_DATA_WIDTH = AXIS_PCIE_DATA_WIDTH;
|
||||
parameter AXI_ADDR_WIDTH = 64;
|
||||
parameter AXI_STRB_WIDTH = (AXI_DATA_WIDTH/8);
|
||||
parameter AXI_ID_WIDTH = 8;
|
||||
parameter AXI_MAX_BURST_LEN = 256;
|
||||
|
||||
// Inputs
|
||||
reg clk = 0;
|
||||
reg rst = 0;
|
||||
reg [7:0] current_test = 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_tvalid = 0;
|
||||
reg s_axis_cq_tlast = 0;
|
||||
reg [84:0] s_axis_cq_tuser = 0;
|
||||
reg m_axis_cc_tready = 0;
|
||||
reg m_axi_arready = 0;
|
||||
reg [AXI_ID_WIDTH-1:0] m_axi_rid = 0;
|
||||
reg [AXI_DATA_WIDTH-1:0] m_axi_rdata = 0;
|
||||
reg [1:0] m_axi_rresp = 0;
|
||||
reg m_axi_rlast = 0;
|
||||
reg m_axi_rvalid = 0;
|
||||
reg [15:0] completer_id = 0;
|
||||
reg completer_id_enable = 0;
|
||||
reg [2:0] max_payload_size = 0;
|
||||
|
||||
// Outputs
|
||||
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_tvalid;
|
||||
wire m_axis_cc_tlast;
|
||||
wire [32:0] m_axis_cc_tuser;
|
||||
wire [AXI_ID_WIDTH-1:0] m_axi_arid;
|
||||
wire [AXI_ADDR_WIDTH-1:0] m_axi_araddr;
|
||||
wire [7:0] m_axi_arlen;
|
||||
wire [2:0] m_axi_arsize;
|
||||
wire [1:0] m_axi_arburst;
|
||||
wire m_axi_arlock;
|
||||
wire [3:0] m_axi_arcache;
|
||||
wire [2:0] m_axi_arprot;
|
||||
wire m_axi_arvalid;
|
||||
wire m_axi_rready;
|
||||
wire status_error_cor;
|
||||
wire status_error_uncor;
|
||||
|
||||
initial begin
|
||||
// myhdl integration
|
||||
$from_myhdl(
|
||||
clk,
|
||||
rst,
|
||||
current_test,
|
||||
s_axis_cq_tdata,
|
||||
s_axis_cq_tkeep,
|
||||
s_axis_cq_tvalid,
|
||||
s_axis_cq_tlast,
|
||||
s_axis_cq_tuser,
|
||||
m_axis_cc_tready,
|
||||
m_axi_arready,
|
||||
m_axi_rid,
|
||||
m_axi_rdata,
|
||||
m_axi_rresp,
|
||||
m_axi_rlast,
|
||||
m_axi_rvalid,
|
||||
completer_id,
|
||||
completer_id_enable,
|
||||
max_payload_size
|
||||
);
|
||||
$to_myhdl(
|
||||
s_axis_cq_tready,
|
||||
m_axis_cc_tdata,
|
||||
m_axis_cc_tkeep,
|
||||
m_axis_cc_tvalid,
|
||||
m_axis_cc_tlast,
|
||||
m_axis_cc_tuser,
|
||||
m_axi_arid,
|
||||
m_axi_araddr,
|
||||
m_axi_arlen,
|
||||
m_axi_arsize,
|
||||
m_axi_arburst,
|
||||
m_axi_arlock,
|
||||
m_axi_arcache,
|
||||
m_axi_arprot,
|
||||
m_axi_arvalid,
|
||||
m_axi_rready,
|
||||
status_error_cor,
|
||||
status_error_uncor
|
||||
);
|
||||
|
||||
// dump file
|
||||
$dumpfile("test_pcie_us_axi_master_rd_128.lxt");
|
||||
$dumpvars(0, test_pcie_us_axi_master_rd_128);
|
||||
end
|
||||
|
||||
pcie_us_axi_master_rd #(
|
||||
.AXIS_PCIE_DATA_WIDTH(AXIS_PCIE_DATA_WIDTH),
|
||||
.AXIS_PCIE_KEEP_WIDTH(AXIS_PCIE_KEEP_WIDTH),
|
||||
.AXI_DATA_WIDTH(AXI_DATA_WIDTH),
|
||||
.AXI_ADDR_WIDTH(AXI_ADDR_WIDTH),
|
||||
.AXI_STRB_WIDTH(AXI_STRB_WIDTH),
|
||||
.AXI_ID_WIDTH(AXI_ID_WIDTH),
|
||||
.AXI_MAX_BURST_LEN(AXI_MAX_BURST_LEN)
|
||||
)
|
||||
UUT (
|
||||
.clk(clk),
|
||||
.rst(rst),
|
||||
.s_axis_cq_tdata(s_axis_cq_tdata),
|
||||
.s_axis_cq_tkeep(s_axis_cq_tkeep),
|
||||
.s_axis_cq_tvalid(s_axis_cq_tvalid),
|
||||
.s_axis_cq_tready(s_axis_cq_tready),
|
||||
.s_axis_cq_tlast(s_axis_cq_tlast),
|
||||
.s_axis_cq_tuser(s_axis_cq_tuser),
|
||||
.m_axis_cc_tdata(m_axis_cc_tdata),
|
||||
.m_axis_cc_tkeep(m_axis_cc_tkeep),
|
||||
.m_axis_cc_tvalid(m_axis_cc_tvalid),
|
||||
.m_axis_cc_tready(m_axis_cc_tready),
|
||||
.m_axis_cc_tlast(m_axis_cc_tlast),
|
||||
.m_axis_cc_tuser(m_axis_cc_tuser),
|
||||
.m_axi_arid(m_axi_arid),
|
||||
.m_axi_araddr(m_axi_araddr),
|
||||
.m_axi_arlen(m_axi_arlen),
|
||||
.m_axi_arsize(m_axi_arsize),
|
||||
.m_axi_arburst(m_axi_arburst),
|
||||
.m_axi_arlock(m_axi_arlock),
|
||||
.m_axi_arcache(m_axi_arcache),
|
||||
.m_axi_arprot(m_axi_arprot),
|
||||
.m_axi_arvalid(m_axi_arvalid),
|
||||
.m_axi_arready(m_axi_arready),
|
||||
.m_axi_rid(m_axi_rid),
|
||||
.m_axi_rdata(m_axi_rdata),
|
||||
.m_axi_rresp(m_axi_rresp),
|
||||
.m_axi_rlast(m_axi_rlast),
|
||||
.m_axi_rvalid(m_axi_rvalid),
|
||||
.m_axi_rready(m_axi_rready),
|
||||
.completer_id(completer_id),
|
||||
.completer_id_enable(completer_id_enable),
|
||||
.max_payload_size(max_payload_size),
|
||||
.status_error_cor(status_error_cor),
|
||||
.status_error_uncor(status_error_uncor)
|
||||
);
|
||||
|
||||
endmodule
|
440
fpga/lib/pcie/tb/test_pcie_us_axi_master_rd_256.py
Executable file
440
fpga/lib/pcie/tb/test_pcie_us_axi_master_rd_256.py
Executable file
@ -0,0 +1,440 @@
|
||||
#!/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 pcie
|
||||
import pcie_us
|
||||
import axi
|
||||
|
||||
module = 'pcie_us_axi_master_rd'
|
||||
testbench = 'test_%s_256' % module
|
||||
|
||||
srcs = []
|
||||
|
||||
srcs.append("../rtl/%s.v" % module)
|
||||
srcs.append("%s.v" % testbench)
|
||||
|
||||
src = ' '.join(srcs)
|
||||
|
||||
build_cmd = "iverilog -o %s.vvp %s" % (testbench, src)
|
||||
|
||||
def bench():
|
||||
|
||||
# Parameters
|
||||
AXIS_PCIE_DATA_WIDTH = 256
|
||||
AXIS_PCIE_KEEP_WIDTH = (AXIS_PCIE_DATA_WIDTH/32)
|
||||
AXI_DATA_WIDTH = AXIS_PCIE_DATA_WIDTH
|
||||
AXI_ADDR_WIDTH = 64
|
||||
AXI_STRB_WIDTH = (AXI_DATA_WIDTH/8)
|
||||
AXI_ID_WIDTH = 8
|
||||
AXI_MAX_BURST_LEN = 256
|
||||
|
||||
# Inputs
|
||||
clk = Signal(bool(0))
|
||||
rst = Signal(bool(0))
|
||||
current_test = Signal(intbv(0)[8:])
|
||||
|
||||
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_tvalid = Signal(bool(0))
|
||||
s_axis_cq_tlast = Signal(bool(0))
|
||||
s_axis_cq_tuser = Signal(intbv(0)[85:])
|
||||
m_axis_cc_tready = Signal(bool(0))
|
||||
m_axi_arready = Signal(bool(0))
|
||||
m_axi_rid = Signal(intbv(0)[AXI_ID_WIDTH:])
|
||||
m_axi_rdata = Signal(intbv(0)[AXI_DATA_WIDTH:])
|
||||
m_axi_rresp = Signal(intbv(0)[2:])
|
||||
m_axi_rlast = Signal(bool(0))
|
||||
m_axi_rvalid = Signal(bool(0))
|
||||
completer_id = Signal(intbv(0)[16:])
|
||||
completer_id_enable = Signal(bool(0))
|
||||
max_payload_size = Signal(intbv(0)[3:])
|
||||
|
||||
# Outputs
|
||||
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_tvalid = Signal(bool(0))
|
||||
m_axis_cc_tlast = Signal(bool(0))
|
||||
m_axis_cc_tuser = Signal(intbv(0)[33:])
|
||||
m_axi_arid = Signal(intbv(0)[AXI_ID_WIDTH:])
|
||||
m_axi_araddr = Signal(intbv(0)[AXI_ADDR_WIDTH:])
|
||||
m_axi_arlen = Signal(intbv(0)[8:])
|
||||
m_axi_arsize = Signal(intbv(5)[3:])
|
||||
m_axi_arburst = Signal(intbv(1)[2:])
|
||||
m_axi_arlock = Signal(bool(0))
|
||||
m_axi_arcache = Signal(intbv(3)[4:])
|
||||
m_axi_arprot = Signal(intbv(2)[3:])
|
||||
m_axi_arvalid = Signal(bool(0))
|
||||
m_axi_rready = Signal(bool(0))
|
||||
status_error_cor = Signal(bool(0))
|
||||
status_error_uncor = Signal(bool(0))
|
||||
|
||||
# Clock and Reset Interface
|
||||
user_clk=Signal(bool(0))
|
||||
user_reset=Signal(bool(0))
|
||||
sys_clk=Signal(bool(0))
|
||||
sys_reset=Signal(bool(0))
|
||||
|
||||
# AXI4 RAM model
|
||||
axi_ram_inst = axi.AXIRam(2**16)
|
||||
|
||||
axi_ram_port0 = axi_ram_inst.create_port(
|
||||
user_clk,
|
||||
s_axi_arid=m_axi_arid,
|
||||
s_axi_araddr=m_axi_araddr,
|
||||
s_axi_arlen=m_axi_arlen,
|
||||
s_axi_arsize=m_axi_arsize,
|
||||
s_axi_arburst=m_axi_arburst,
|
||||
s_axi_arlock=m_axi_arlock,
|
||||
s_axi_arcache=m_axi_arcache,
|
||||
s_axi_arprot=m_axi_arprot,
|
||||
s_axi_arvalid=m_axi_arvalid,
|
||||
s_axi_arready=m_axi_arready,
|
||||
s_axi_rid=m_axi_rid,
|
||||
s_axi_rdata=m_axi_rdata,
|
||||
s_axi_rresp=m_axi_rresp,
|
||||
s_axi_rlast=m_axi_rlast,
|
||||
s_axi_rvalid=m_axi_rvalid,
|
||||
s_axi_rready=m_axi_rready,
|
||||
name='port0'
|
||||
)
|
||||
|
||||
# PCIe devices
|
||||
rc = pcie.RootComplex()
|
||||
|
||||
dev = pcie_us.UltrascalePCIe()
|
||||
|
||||
dev.pcie_generation = 3
|
||||
dev.pcie_link_width = 8
|
||||
dev.user_clock_frequency = 250e6
|
||||
|
||||
dev.functions[0].configure_bar(0, 16*1024*1024)
|
||||
dev.functions[0].configure_bar(1, 32, io=True)
|
||||
|
||||
rc.make_port().connect(dev)
|
||||
|
||||
cq_pause = Signal(bool(0))
|
||||
cc_pause = Signal(bool(0))
|
||||
rq_pause = Signal(bool(0))
|
||||
rc_pause = Signal(bool(0))
|
||||
|
||||
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_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=Signal(intbv(0)[AXIS_PCIE_DATA_WIDTH:]),
|
||||
s_axis_rq_tuser=Signal(intbv(0)[60:]),
|
||||
s_axis_rq_tlast=Signal(bool(0)),
|
||||
s_axis_rq_tkeep=Signal(intbv(0)[AXIS_PCIE_KEEP_WIDTH:]),
|
||||
s_axis_rq_tvalid=Signal(bool(0)),
|
||||
s_axis_rq_tready=Signal(bool(1)),
|
||||
# pcie_rq_seq_num=pcie_rq_seq_num,
|
||||
# pcie_rq_seq_num_vld=pcie_rq_seq_num_vld,
|
||||
# pcie_rq_tag=pcie_rq_tag,
|
||||
# pcie_rq_tag_av=pcie_rq_tag_av,
|
||||
# pcie_rq_tag_vld=pcie_rq_tag_vld,
|
||||
|
||||
# Requester Completion Interface
|
||||
m_axis_rc_tdata=Signal(intbv(0)[AXIS_PCIE_DATA_WIDTH:]),
|
||||
m_axis_rc_tuser=Signal(intbv(0)[75:]),
|
||||
m_axis_rc_tlast=Signal(bool(0)),
|
||||
m_axis_rc_tkeep=Signal(intbv(0)[AXIS_PCIE_KEEP_WIDTH:]),
|
||||
m_axis_rc_tvalid=Signal(bool(0)),
|
||||
m_axis_rc_tready=Signal(bool(0)),
|
||||
|
||||
# Transmit Flow Control Interface
|
||||
# pcie_tfc_nph_av=pcie_tfc_nph_av,
|
||||
# pcie_tfc_npd_av=pcie_tfc_npd_av,
|
||||
|
||||
# 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_per_function_update_done=cfg_per_function_update_done,
|
||||
# cfg_per_function_number=cfg_per_function_number,
|
||||
# cfg_per_function_output_request=cfg_per_function_output_request,
|
||||
# cfg_dsn=cfg_dsn,
|
||||
# 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=cfg_err_cor_in,
|
||||
# cfg_err_uncor_in=cfg_err_uncor_in,
|
||||
# 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,
|
||||
|
||||
# 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,
|
||||
|
||||
cq_pause=cq_pause,
|
||||
cc_pause=cc_pause,
|
||||
rq_pause=rq_pause,
|
||||
rc_pause=rc_pause
|
||||
)
|
||||
|
||||
# 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,
|
||||
s_axis_cq_tdata=s_axis_cq_tdata,
|
||||
s_axis_cq_tkeep=s_axis_cq_tkeep,
|
||||
s_axis_cq_tvalid=s_axis_cq_tvalid,
|
||||
s_axis_cq_tready=s_axis_cq_tready,
|
||||
s_axis_cq_tlast=s_axis_cq_tlast,
|
||||
s_axis_cq_tuser=s_axis_cq_tuser,
|
||||
m_axis_cc_tdata=m_axis_cc_tdata,
|
||||
m_axis_cc_tkeep=m_axis_cc_tkeep,
|
||||
m_axis_cc_tvalid=m_axis_cc_tvalid,
|
||||
m_axis_cc_tready=m_axis_cc_tready,
|
||||
m_axis_cc_tlast=m_axis_cc_tlast,
|
||||
m_axis_cc_tuser=m_axis_cc_tuser,
|
||||
m_axi_arid=m_axi_arid,
|
||||
m_axi_araddr=m_axi_araddr,
|
||||
m_axi_arlen=m_axi_arlen,
|
||||
m_axi_arsize=m_axi_arsize,
|
||||
m_axi_arburst=m_axi_arburst,
|
||||
m_axi_arlock=m_axi_arlock,
|
||||
m_axi_arcache=m_axi_arcache,
|
||||
m_axi_arprot=m_axi_arprot,
|
||||
m_axi_arvalid=m_axi_arvalid,
|
||||
m_axi_arready=m_axi_arready,
|
||||
m_axi_rid=m_axi_rid,
|
||||
m_axi_rdata=m_axi_rdata,
|
||||
m_axi_rresp=m_axi_rresp,
|
||||
m_axi_rlast=m_axi_rlast,
|
||||
m_axi_rvalid=m_axi_rvalid,
|
||||
m_axi_rready=m_axi_rready,
|
||||
completer_id=completer_id,
|
||||
completer_id_enable=completer_id_enable,
|
||||
max_payload_size=max_payload_size,
|
||||
status_error_cor=status_error_cor,
|
||||
status_error_uncor=status_error_uncor
|
||||
)
|
||||
|
||||
@always(delay(4))
|
||||
def clkgen():
|
||||
clk.next = not clk
|
||||
|
||||
@always_comb
|
||||
def clk_logic():
|
||||
sys_clk.next = clk
|
||||
sys_reset.next = not rst
|
||||
|
||||
status_error_cor_asserted = Signal(bool(0))
|
||||
status_error_uncor_asserted = Signal(bool(0))
|
||||
|
||||
@always(user_clk.posedge)
|
||||
def monitor():
|
||||
if (status_error_cor):
|
||||
status_error_cor_asserted.next = 1
|
||||
if (status_error_uncor):
|
||||
status_error_uncor_asserted.next = 1
|
||||
|
||||
cq_pause_toggle = Signal(bool(0))
|
||||
cc_pause_toggle = Signal(bool(0))
|
||||
rq_pause_toggle = Signal(bool(0))
|
||||
rc_pause_toggle = Signal(bool(0))
|
||||
|
||||
@instance
|
||||
def pause_toggle():
|
||||
while True:
|
||||
if (cq_pause_toggle or cc_pause_toggle or rq_pause_toggle or rc_pause_toggle):
|
||||
cq_pause.next = cq_pause_toggle
|
||||
cc_pause.next = cc_pause_toggle
|
||||
rq_pause.next = rq_pause_toggle
|
||||
rc_pause.next = rc_pause_toggle
|
||||
|
||||
yield user_clk.posedge
|
||||
yield user_clk.posedge
|
||||
yield user_clk.posedge
|
||||
|
||||
cq_pause.next = 0
|
||||
cc_pause.next = 0
|
||||
rq_pause.next = 0
|
||||
rc_pause.next = 0
|
||||
|
||||
yield user_clk.posedge
|
||||
|
||||
@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
|
||||
|
||||
max_payload_size.next = 0
|
||||
|
||||
yield user_clk.posedge
|
||||
print("test 1: enumeration")
|
||||
current_test.next = 1
|
||||
|
||||
yield rc.enumerate()
|
||||
|
||||
dev_bar0 = rc.tree[0][0].bar[0]
|
||||
dev_bar1 = rc.tree[0][0].bar[1]
|
||||
|
||||
yield delay(100)
|
||||
|
||||
yield clk.posedge
|
||||
print("test 2: memory read")
|
||||
current_test.next = 2
|
||||
|
||||
pcie_addr = 0x00000000
|
||||
test_data = b'\x11\x22\x33\x44'
|
||||
|
||||
axi_ram_inst.write_mem(pcie_addr, test_data)
|
||||
|
||||
data = axi_ram_inst.read_mem(0, 32)
|
||||
for i in range(0, len(data), 16):
|
||||
print(" ".join(("{:02x}".format(c) for c in bytearray(data[i:i+16]))))
|
||||
|
||||
val = yield from rc.mem_read(dev_bar0+pcie_addr, len(test_data), 1000)
|
||||
|
||||
print(val)
|
||||
|
||||
assert val == test_data
|
||||
|
||||
assert not status_error_cor_asserted
|
||||
assert not status_error_uncor_asserted
|
||||
|
||||
yield delay(100)
|
||||
|
||||
yield user_clk.posedge
|
||||
print("test 3: various reads")
|
||||
current_test.next = 3
|
||||
|
||||
for length in list(range(1,34))+[1024]:
|
||||
for pcie_offset in list(range(8,41))+list(range(4096-32,4096)):
|
||||
for pause in [False, True]:
|
||||
print("length %d, pcie_offset %d"% (length, pcie_offset))
|
||||
#pcie_addr = length * 0x100000000 + pcie_offset * 0x10000 + offset
|
||||
pcie_addr = pcie_offset
|
||||
test_data = bytearray([x%256 for x in range(length)])
|
||||
|
||||
axi_ram_inst.write_mem(pcie_addr & 0xffff80, b'\x55'*(len(test_data)+256))
|
||||
axi_ram_inst.write_mem(pcie_addr, test_data)
|
||||
|
||||
data = axi_ram_inst.read_mem(pcie_addr&0xfffff0, 64)
|
||||
for i in range(0, len(data), 16):
|
||||
print(" ".join(("{:02x}".format(c) for c in bytearray(data[i:i+16]))))
|
||||
|
||||
cq_pause_toggle.next = pause
|
||||
cc_pause_toggle.next = pause
|
||||
|
||||
val = yield from rc.mem_read(dev_bar0+pcie_addr, len(test_data), 1000)
|
||||
|
||||
cq_pause_toggle.next = 0
|
||||
cc_pause_toggle.next = 0
|
||||
|
||||
print(val)
|
||||
|
||||
assert val == test_data
|
||||
|
||||
assert not status_error_cor_asserted
|
||||
assert not status_error_uncor_asserted
|
||||
|
||||
yield delay(100)
|
||||
|
||||
yield clk.posedge
|
||||
print("test 4: bad requests")
|
||||
current_test.next = 4
|
||||
|
||||
yield from rc.mem_write(dev_bar0, b'\x11\x22\x33\x44')
|
||||
|
||||
yield delay(100)
|
||||
|
||||
assert not status_error_cor_asserted
|
||||
assert status_error_uncor_asserted
|
||||
|
||||
status_error_cor_asserted.next = False
|
||||
status_error_uncor_asserted.next = False
|
||||
|
||||
try:
|
||||
yield from rc.io_write(dev_bar1, b'\x11\x22\x33\x44')
|
||||
except:
|
||||
print("Caught unsuccessful completion exception")
|
||||
pass
|
||||
else:
|
||||
assert False
|
||||
|
||||
assert status_error_cor_asserted
|
||||
assert not status_error_uncor_asserted
|
||||
|
||||
status_error_cor_asserted.next = False
|
||||
status_error_uncor_asserted.next = False
|
||||
|
||||
yield delay(100)
|
||||
|
||||
raise StopSimulation
|
||||
|
||||
return instances()
|
||||
|
||||
def test_bench():
|
||||
sim = Simulation(bench())
|
||||
sim.run()
|
||||
|
||||
if __name__ == '__main__':
|
||||
print("Running test...")
|
||||
test_bench()
|
179
fpga/lib/pcie/tb/test_pcie_us_axi_master_rd_256.v
Normal file
179
fpga/lib/pcie/tb/test_pcie_us_axi_master_rd_256.v
Normal file
@ -0,0 +1,179 @@
|
||||
/*
|
||||
|
||||
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 pcie_us_axi_master_rd
|
||||
*/
|
||||
module test_pcie_us_axi_master_rd_256;
|
||||
|
||||
// Parameters
|
||||
parameter AXIS_PCIE_DATA_WIDTH = 256;
|
||||
parameter AXIS_PCIE_KEEP_WIDTH = (AXIS_PCIE_DATA_WIDTH/32);
|
||||
parameter AXI_DATA_WIDTH = AXIS_PCIE_DATA_WIDTH;
|
||||
parameter AXI_ADDR_WIDTH = 64;
|
||||
parameter AXI_STRB_WIDTH = (AXI_DATA_WIDTH/8);
|
||||
parameter AXI_ID_WIDTH = 8;
|
||||
parameter AXI_MAX_BURST_LEN = 256;
|
||||
|
||||
// Inputs
|
||||
reg clk = 0;
|
||||
reg rst = 0;
|
||||
reg [7:0] current_test = 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_tvalid = 0;
|
||||
reg s_axis_cq_tlast = 0;
|
||||
reg [84:0] s_axis_cq_tuser = 0;
|
||||
reg m_axis_cc_tready = 0;
|
||||
reg m_axi_arready = 0;
|
||||
reg [AXI_ID_WIDTH-1:0] m_axi_rid = 0;
|
||||
reg [AXI_DATA_WIDTH-1:0] m_axi_rdata = 0;
|
||||
reg [1:0] m_axi_rresp = 0;
|
||||
reg m_axi_rlast = 0;
|
||||
reg m_axi_rvalid = 0;
|
||||
reg [15:0] completer_id = 0;
|
||||
reg completer_id_enable = 0;
|
||||
reg [2:0] max_payload_size = 0;
|
||||
|
||||
// Outputs
|
||||
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_tvalid;
|
||||
wire m_axis_cc_tlast;
|
||||
wire [32:0] m_axis_cc_tuser;
|
||||
wire [AXI_ID_WIDTH-1:0] m_axi_arid;
|
||||
wire [AXI_ADDR_WIDTH-1:0] m_axi_araddr;
|
||||
wire [7:0] m_axi_arlen;
|
||||
wire [2:0] m_axi_arsize;
|
||||
wire [1:0] m_axi_arburst;
|
||||
wire m_axi_arlock;
|
||||
wire [3:0] m_axi_arcache;
|
||||
wire [2:0] m_axi_arprot;
|
||||
wire m_axi_arvalid;
|
||||
wire m_axi_rready;
|
||||
wire status_error_cor;
|
||||
wire status_error_uncor;
|
||||
|
||||
initial begin
|
||||
// myhdl integration
|
||||
$from_myhdl(
|
||||
clk,
|
||||
rst,
|
||||
current_test,
|
||||
s_axis_cq_tdata,
|
||||
s_axis_cq_tkeep,
|
||||
s_axis_cq_tvalid,
|
||||
s_axis_cq_tlast,
|
||||
s_axis_cq_tuser,
|
||||
m_axis_cc_tready,
|
||||
m_axi_arready,
|
||||
m_axi_rid,
|
||||
m_axi_rdata,
|
||||
m_axi_rresp,
|
||||
m_axi_rlast,
|
||||
m_axi_rvalid,
|
||||
completer_id,
|
||||
completer_id_enable,
|
||||
max_payload_size
|
||||
);
|
||||
$to_myhdl(
|
||||
s_axis_cq_tready,
|
||||
m_axis_cc_tdata,
|
||||
m_axis_cc_tkeep,
|
||||
m_axis_cc_tvalid,
|
||||
m_axis_cc_tlast,
|
||||
m_axis_cc_tuser,
|
||||
m_axi_arid,
|
||||
m_axi_araddr,
|
||||
m_axi_arlen,
|
||||
m_axi_arsize,
|
||||
m_axi_arburst,
|
||||
m_axi_arlock,
|
||||
m_axi_arcache,
|
||||
m_axi_arprot,
|
||||
m_axi_arvalid,
|
||||
m_axi_rready,
|
||||
status_error_cor,
|
||||
status_error_uncor
|
||||
);
|
||||
|
||||
// dump file
|
||||
$dumpfile("test_pcie_us_axi_master_rd_256.lxt");
|
||||
$dumpvars(0, test_pcie_us_axi_master_rd_256);
|
||||
end
|
||||
|
||||
pcie_us_axi_master_rd #(
|
||||
.AXIS_PCIE_DATA_WIDTH(AXIS_PCIE_DATA_WIDTH),
|
||||
.AXIS_PCIE_KEEP_WIDTH(AXIS_PCIE_KEEP_WIDTH),
|
||||
.AXI_DATA_WIDTH(AXI_DATA_WIDTH),
|
||||
.AXI_ADDR_WIDTH(AXI_ADDR_WIDTH),
|
||||
.AXI_STRB_WIDTH(AXI_STRB_WIDTH),
|
||||
.AXI_ID_WIDTH(AXI_ID_WIDTH),
|
||||
.AXI_MAX_BURST_LEN(AXI_MAX_BURST_LEN)
|
||||
)
|
||||
UUT (
|
||||
.clk(clk),
|
||||
.rst(rst),
|
||||
.s_axis_cq_tdata(s_axis_cq_tdata),
|
||||
.s_axis_cq_tkeep(s_axis_cq_tkeep),
|
||||
.s_axis_cq_tvalid(s_axis_cq_tvalid),
|
||||
.s_axis_cq_tready(s_axis_cq_tready),
|
||||
.s_axis_cq_tlast(s_axis_cq_tlast),
|
||||
.s_axis_cq_tuser(s_axis_cq_tuser),
|
||||
.m_axis_cc_tdata(m_axis_cc_tdata),
|
||||
.m_axis_cc_tkeep(m_axis_cc_tkeep),
|
||||
.m_axis_cc_tvalid(m_axis_cc_tvalid),
|
||||
.m_axis_cc_tready(m_axis_cc_tready),
|
||||
.m_axis_cc_tlast(m_axis_cc_tlast),
|
||||
.m_axis_cc_tuser(m_axis_cc_tuser),
|
||||
.m_axi_arid(m_axi_arid),
|
||||
.m_axi_araddr(m_axi_araddr),
|
||||
.m_axi_arlen(m_axi_arlen),
|
||||
.m_axi_arsize(m_axi_arsize),
|
||||
.m_axi_arburst(m_axi_arburst),
|
||||
.m_axi_arlock(m_axi_arlock),
|
||||
.m_axi_arcache(m_axi_arcache),
|
||||
.m_axi_arprot(m_axi_arprot),
|
||||
.m_axi_arvalid(m_axi_arvalid),
|
||||
.m_axi_arready(m_axi_arready),
|
||||
.m_axi_rid(m_axi_rid),
|
||||
.m_axi_rdata(m_axi_rdata),
|
||||
.m_axi_rresp(m_axi_rresp),
|
||||
.m_axi_rlast(m_axi_rlast),
|
||||
.m_axi_rvalid(m_axi_rvalid),
|
||||
.m_axi_rready(m_axi_rready),
|
||||
.completer_id(completer_id),
|
||||
.completer_id_enable(completer_id_enable),
|
||||
.max_payload_size(max_payload_size),
|
||||
.status_error_cor(status_error_cor),
|
||||
.status_error_uncor(status_error_uncor)
|
||||
);
|
||||
|
||||
endmodule
|
440
fpga/lib/pcie/tb/test_pcie_us_axi_master_rd_64.py
Executable file
440
fpga/lib/pcie/tb/test_pcie_us_axi_master_rd_64.py
Executable file
@ -0,0 +1,440 @@
|
||||
#!/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 pcie
|
||||
import pcie_us
|
||||
import axi
|
||||
|
||||
module = 'pcie_us_axi_master_rd'
|
||||
testbench = 'test_%s_64' % module
|
||||
|
||||
srcs = []
|
||||
|
||||
srcs.append("../rtl/%s.v" % module)
|
||||
srcs.append("%s.v" % testbench)
|
||||
|
||||
src = ' '.join(srcs)
|
||||
|
||||
build_cmd = "iverilog -o %s.vvp %s" % (testbench, src)
|
||||
|
||||
def bench():
|
||||
|
||||
# Parameters
|
||||
AXIS_PCIE_DATA_WIDTH = 64
|
||||
AXIS_PCIE_KEEP_WIDTH = (AXIS_PCIE_DATA_WIDTH/32)
|
||||
AXI_DATA_WIDTH = AXIS_PCIE_DATA_WIDTH
|
||||
AXI_ADDR_WIDTH = 64
|
||||
AXI_STRB_WIDTH = (AXI_DATA_WIDTH/8)
|
||||
AXI_ID_WIDTH = 8
|
||||
AXI_MAX_BURST_LEN = 256
|
||||
|
||||
# Inputs
|
||||
clk = Signal(bool(0))
|
||||
rst = Signal(bool(0))
|
||||
current_test = Signal(intbv(0)[8:])
|
||||
|
||||
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_tvalid = Signal(bool(0))
|
||||
s_axis_cq_tlast = Signal(bool(0))
|
||||
s_axis_cq_tuser = Signal(intbv(0)[85:])
|
||||
m_axis_cc_tready = Signal(bool(0))
|
||||
m_axi_arready = Signal(bool(0))
|
||||
m_axi_rid = Signal(intbv(0)[AXI_ID_WIDTH:])
|
||||
m_axi_rdata = Signal(intbv(0)[AXI_DATA_WIDTH:])
|
||||
m_axi_rresp = Signal(intbv(0)[2:])
|
||||
m_axi_rlast = Signal(bool(0))
|
||||
m_axi_rvalid = Signal(bool(0))
|
||||
completer_id = Signal(intbv(0)[16:])
|
||||
completer_id_enable = Signal(bool(0))
|
||||
max_payload_size = Signal(intbv(0)[3:])
|
||||
|
||||
# Outputs
|
||||
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_tvalid = Signal(bool(0))
|
||||
m_axis_cc_tlast = Signal(bool(0))
|
||||
m_axis_cc_tuser = Signal(intbv(0)[33:])
|
||||
m_axi_arid = Signal(intbv(0)[AXI_ID_WIDTH:])
|
||||
m_axi_araddr = Signal(intbv(0)[AXI_ADDR_WIDTH:])
|
||||
m_axi_arlen = Signal(intbv(0)[8:])
|
||||
m_axi_arsize = Signal(intbv(3)[3:])
|
||||
m_axi_arburst = Signal(intbv(1)[2:])
|
||||
m_axi_arlock = Signal(bool(0))
|
||||
m_axi_arcache = Signal(intbv(3)[4:])
|
||||
m_axi_arprot = Signal(intbv(2)[3:])
|
||||
m_axi_arvalid = Signal(bool(0))
|
||||
m_axi_rready = Signal(bool(0))
|
||||
status_error_cor = Signal(bool(0))
|
||||
status_error_uncor = Signal(bool(0))
|
||||
|
||||
# Clock and Reset Interface
|
||||
user_clk=Signal(bool(0))
|
||||
user_reset=Signal(bool(0))
|
||||
sys_clk=Signal(bool(0))
|
||||
sys_reset=Signal(bool(0))
|
||||
|
||||
# AXI4 RAM model
|
||||
axi_ram_inst = axi.AXIRam(2**16)
|
||||
|
||||
axi_ram_port0 = axi_ram_inst.create_port(
|
||||
user_clk,
|
||||
s_axi_arid=m_axi_arid,
|
||||
s_axi_araddr=m_axi_araddr,
|
||||
s_axi_arlen=m_axi_arlen,
|
||||
s_axi_arsize=m_axi_arsize,
|
||||
s_axi_arburst=m_axi_arburst,
|
||||
s_axi_arlock=m_axi_arlock,
|
||||
s_axi_arcache=m_axi_arcache,
|
||||
s_axi_arprot=m_axi_arprot,
|
||||
s_axi_arvalid=m_axi_arvalid,
|
||||
s_axi_arready=m_axi_arready,
|
||||
s_axi_rid=m_axi_rid,
|
||||
s_axi_rdata=m_axi_rdata,
|
||||
s_axi_rresp=m_axi_rresp,
|
||||
s_axi_rlast=m_axi_rlast,
|
||||
s_axi_rvalid=m_axi_rvalid,
|
||||
s_axi_rready=m_axi_rready,
|
||||
name='port0'
|
||||
)
|
||||
|
||||
# PCIe devices
|
||||
rc = pcie.RootComplex()
|
||||
|
||||
dev = pcie_us.UltrascalePCIe()
|
||||
|
||||
dev.pcie_generation = 3
|
||||
dev.pcie_link_width = 2
|
||||
dev.user_clock_frequency = 250e6
|
||||
|
||||
dev.functions[0].configure_bar(0, 16*1024*1024)
|
||||
dev.functions[0].configure_bar(1, 32, io=True)
|
||||
|
||||
rc.make_port().connect(dev)
|
||||
|
||||
cq_pause = Signal(bool(0))
|
||||
cc_pause = Signal(bool(0))
|
||||
rq_pause = Signal(bool(0))
|
||||
rc_pause = Signal(bool(0))
|
||||
|
||||
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_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=Signal(intbv(0)[AXIS_PCIE_DATA_WIDTH:]),
|
||||
s_axis_rq_tuser=Signal(intbv(0)[60:]),
|
||||
s_axis_rq_tlast=Signal(bool(0)),
|
||||
s_axis_rq_tkeep=Signal(intbv(0)[AXIS_PCIE_KEEP_WIDTH:]),
|
||||
s_axis_rq_tvalid=Signal(bool(0)),
|
||||
s_axis_rq_tready=Signal(bool(1)),
|
||||
# pcie_rq_seq_num=pcie_rq_seq_num,
|
||||
# pcie_rq_seq_num_vld=pcie_rq_seq_num_vld,
|
||||
# pcie_rq_tag=pcie_rq_tag,
|
||||
# pcie_rq_tag_av=pcie_rq_tag_av,
|
||||
# pcie_rq_tag_vld=pcie_rq_tag_vld,
|
||||
|
||||
# Requester Completion Interface
|
||||
m_axis_rc_tdata=Signal(intbv(0)[AXIS_PCIE_DATA_WIDTH:]),
|
||||
m_axis_rc_tuser=Signal(intbv(0)[75:]),
|
||||
m_axis_rc_tlast=Signal(bool(0)),
|
||||
m_axis_rc_tkeep=Signal(intbv(0)[AXIS_PCIE_KEEP_WIDTH:]),
|
||||
m_axis_rc_tvalid=Signal(bool(0)),
|
||||
m_axis_rc_tready=Signal(bool(0)),
|
||||
|
||||
# Transmit Flow Control Interface
|
||||
# pcie_tfc_nph_av=pcie_tfc_nph_av,
|
||||
# pcie_tfc_npd_av=pcie_tfc_npd_av,
|
||||
|
||||
# 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_per_function_update_done=cfg_per_function_update_done,
|
||||
# cfg_per_function_number=cfg_per_function_number,
|
||||
# cfg_per_function_output_request=cfg_per_function_output_request,
|
||||
# cfg_dsn=cfg_dsn,
|
||||
# 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=cfg_err_cor_in,
|
||||
# cfg_err_uncor_in=cfg_err_uncor_in,
|
||||
# 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,
|
||||
|
||||
# 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,
|
||||
|
||||
cq_pause=cq_pause,
|
||||
cc_pause=cc_pause,
|
||||
rq_pause=rq_pause,
|
||||
rc_pause=rc_pause
|
||||
)
|
||||
|
||||
# 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,
|
||||
s_axis_cq_tdata=s_axis_cq_tdata,
|
||||
s_axis_cq_tkeep=s_axis_cq_tkeep,
|
||||
s_axis_cq_tvalid=s_axis_cq_tvalid,
|
||||
s_axis_cq_tready=s_axis_cq_tready,
|
||||
s_axis_cq_tlast=s_axis_cq_tlast,
|
||||
s_axis_cq_tuser=s_axis_cq_tuser,
|
||||
m_axis_cc_tdata=m_axis_cc_tdata,
|
||||
m_axis_cc_tkeep=m_axis_cc_tkeep,
|
||||
m_axis_cc_tvalid=m_axis_cc_tvalid,
|
||||
m_axis_cc_tready=m_axis_cc_tready,
|
||||
m_axis_cc_tlast=m_axis_cc_tlast,
|
||||
m_axis_cc_tuser=m_axis_cc_tuser,
|
||||
m_axi_arid=m_axi_arid,
|
||||
m_axi_araddr=m_axi_araddr,
|
||||
m_axi_arlen=m_axi_arlen,
|
||||
m_axi_arsize=m_axi_arsize,
|
||||
m_axi_arburst=m_axi_arburst,
|
||||
m_axi_arlock=m_axi_arlock,
|
||||
m_axi_arcache=m_axi_arcache,
|
||||
m_axi_arprot=m_axi_arprot,
|
||||
m_axi_arvalid=m_axi_arvalid,
|
||||
m_axi_arready=m_axi_arready,
|
||||
m_axi_rid=m_axi_rid,
|
||||
m_axi_rdata=m_axi_rdata,
|
||||
m_axi_rresp=m_axi_rresp,
|
||||
m_axi_rlast=m_axi_rlast,
|
||||
m_axi_rvalid=m_axi_rvalid,
|
||||
m_axi_rready=m_axi_rready,
|
||||
completer_id=completer_id,
|
||||
completer_id_enable=completer_id_enable,
|
||||
max_payload_size=max_payload_size,
|
||||
status_error_cor=status_error_cor,
|
||||
status_error_uncor=status_error_uncor
|
||||
)
|
||||
|
||||
@always(delay(4))
|
||||
def clkgen():
|
||||
clk.next = not clk
|
||||
|
||||
@always_comb
|
||||
def clk_logic():
|
||||
sys_clk.next = clk
|
||||
sys_reset.next = not rst
|
||||
|
||||
status_error_cor_asserted = Signal(bool(0))
|
||||
status_error_uncor_asserted = Signal(bool(0))
|
||||
|
||||
@always(user_clk.posedge)
|
||||
def monitor():
|
||||
if (status_error_cor):
|
||||
status_error_cor_asserted.next = 1
|
||||
if (status_error_uncor):
|
||||
status_error_uncor_asserted.next = 1
|
||||
|
||||
cq_pause_toggle = Signal(bool(0))
|
||||
cc_pause_toggle = Signal(bool(0))
|
||||
rq_pause_toggle = Signal(bool(0))
|
||||
rc_pause_toggle = Signal(bool(0))
|
||||
|
||||
@instance
|
||||
def pause_toggle():
|
||||
while True:
|
||||
if (cq_pause_toggle or cc_pause_toggle or rq_pause_toggle or rc_pause_toggle):
|
||||
cq_pause.next = cq_pause_toggle
|
||||
cc_pause.next = cc_pause_toggle
|
||||
rq_pause.next = rq_pause_toggle
|
||||
rc_pause.next = rc_pause_toggle
|
||||
|
||||
yield user_clk.posedge
|
||||
yield user_clk.posedge
|
||||
yield user_clk.posedge
|
||||
|
||||
cq_pause.next = 0
|
||||
cc_pause.next = 0
|
||||
rq_pause.next = 0
|
||||
rc_pause.next = 0
|
||||
|
||||
yield user_clk.posedge
|
||||
|
||||
@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
|
||||
|
||||
max_payload_size.next = 0
|
||||
|
||||
yield user_clk.posedge
|
||||
print("test 1: enumeration")
|
||||
current_test.next = 1
|
||||
|
||||
yield rc.enumerate()
|
||||
|
||||
dev_bar0 = rc.tree[0][0].bar[0]
|
||||
dev_bar1 = rc.tree[0][0].bar[1]
|
||||
|
||||
yield delay(100)
|
||||
|
||||
yield clk.posedge
|
||||
print("test 2: memory read")
|
||||
current_test.next = 2
|
||||
|
||||
pcie_addr = 0x00000000
|
||||
test_data = b'\x11\x22\x33\x44'
|
||||
|
||||
axi_ram_inst.write_mem(pcie_addr, test_data)
|
||||
|
||||
data = axi_ram_inst.read_mem(0, 32)
|
||||
for i in range(0, len(data), 16):
|
||||
print(" ".join(("{:02x}".format(c) for c in bytearray(data[i:i+16]))))
|
||||
|
||||
val = yield from rc.mem_read(dev_bar0+pcie_addr, len(test_data), 1000)
|
||||
|
||||
print(val)
|
||||
|
||||
assert val == test_data
|
||||
|
||||
assert not status_error_cor_asserted
|
||||
assert not status_error_uncor_asserted
|
||||
|
||||
yield delay(100)
|
||||
|
||||
yield user_clk.posedge
|
||||
print("test 3: various reads")
|
||||
current_test.next = 3
|
||||
|
||||
for length in list(range(1,34))+[1024]:
|
||||
for pcie_offset in list(range(8,17))+list(range(4096-8,4096)):
|
||||
for pause in [False, True]:
|
||||
print("length %d, pcie_offset %d"% (length, pcie_offset))
|
||||
#pcie_addr = length * 0x100000000 + pcie_offset * 0x10000 + offset
|
||||
pcie_addr = pcie_offset
|
||||
test_data = bytearray([x%256 for x in range(length)])
|
||||
|
||||
axi_ram_inst.write_mem(pcie_addr & 0xffff80, b'\x55'*(len(test_data)+256))
|
||||
axi_ram_inst.write_mem(pcie_addr, test_data)
|
||||
|
||||
data = axi_ram_inst.read_mem(pcie_addr&0xfffff0, 64)
|
||||
for i in range(0, len(data), 16):
|
||||
print(" ".join(("{:02x}".format(c) for c in bytearray(data[i:i+16]))))
|
||||
|
||||
cq_pause_toggle.next = pause
|
||||
cc_pause_toggle.next = pause
|
||||
|
||||
val = yield from rc.mem_read(dev_bar0+pcie_addr, len(test_data), 1000)
|
||||
|
||||
cq_pause_toggle.next = 0
|
||||
cc_pause_toggle.next = 0
|
||||
|
||||
print(val)
|
||||
|
||||
assert val == test_data
|
||||
|
||||
assert not status_error_cor_asserted
|
||||
assert not status_error_uncor_asserted
|
||||
|
||||
yield delay(100)
|
||||
|
||||
yield clk.posedge
|
||||
print("test 4: bad requests")
|
||||
current_test.next = 4
|
||||
|
||||
yield from rc.mem_write(dev_bar0, b'\x11\x22\x33\x44')
|
||||
|
||||
yield delay(100)
|
||||
|
||||
assert not status_error_cor_asserted
|
||||
assert status_error_uncor_asserted
|
||||
|
||||
status_error_cor_asserted.next = False
|
||||
status_error_uncor_asserted.next = False
|
||||
|
||||
try:
|
||||
yield from rc.io_write(dev_bar1, b'\x11\x22\x33\x44')
|
||||
except:
|
||||
print("Caught unsuccessful completion exception")
|
||||
pass
|
||||
else:
|
||||
assert False
|
||||
|
||||
assert status_error_cor_asserted
|
||||
assert not status_error_uncor_asserted
|
||||
|
||||
status_error_cor_asserted.next = False
|
||||
status_error_uncor_asserted.next = False
|
||||
|
||||
yield delay(100)
|
||||
|
||||
raise StopSimulation
|
||||
|
||||
return instances()
|
||||
|
||||
def test_bench():
|
||||
sim = Simulation(bench())
|
||||
sim.run()
|
||||
|
||||
if __name__ == '__main__':
|
||||
print("Running test...")
|
||||
test_bench()
|
179
fpga/lib/pcie/tb/test_pcie_us_axi_master_rd_64.v
Normal file
179
fpga/lib/pcie/tb/test_pcie_us_axi_master_rd_64.v
Normal file
@ -0,0 +1,179 @@
|
||||
/*
|
||||
|
||||
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 pcie_us_axi_master_rd
|
||||
*/
|
||||
module test_pcie_us_axi_master_rd_64;
|
||||
|
||||
// Parameters
|
||||
parameter AXIS_PCIE_DATA_WIDTH = 64;
|
||||
parameter AXIS_PCIE_KEEP_WIDTH = (AXIS_PCIE_DATA_WIDTH/32);
|
||||
parameter AXI_DATA_WIDTH = AXIS_PCIE_DATA_WIDTH;
|
||||
parameter AXI_ADDR_WIDTH = 64;
|
||||
parameter AXI_STRB_WIDTH = (AXI_DATA_WIDTH/8);
|
||||
parameter AXI_ID_WIDTH = 8;
|
||||
parameter AXI_MAX_BURST_LEN = 256;
|
||||
|
||||
// Inputs
|
||||
reg clk = 0;
|
||||
reg rst = 0;
|
||||
reg [7:0] current_test = 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_tvalid = 0;
|
||||
reg s_axis_cq_tlast = 0;
|
||||
reg [84:0] s_axis_cq_tuser = 0;
|
||||
reg m_axis_cc_tready = 0;
|
||||
reg m_axi_arready = 0;
|
||||
reg [AXI_ID_WIDTH-1:0] m_axi_rid = 0;
|
||||
reg [AXI_DATA_WIDTH-1:0] m_axi_rdata = 0;
|
||||
reg [1:0] m_axi_rresp = 0;
|
||||
reg m_axi_rlast = 0;
|
||||
reg m_axi_rvalid = 0;
|
||||
reg [15:0] completer_id = 0;
|
||||
reg completer_id_enable = 0;
|
||||
reg [2:0] max_payload_size = 0;
|
||||
|
||||
// Outputs
|
||||
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_tvalid;
|
||||
wire m_axis_cc_tlast;
|
||||
wire [32:0] m_axis_cc_tuser;
|
||||
wire [AXI_ID_WIDTH-1:0] m_axi_arid;
|
||||
wire [AXI_ADDR_WIDTH-1:0] m_axi_araddr;
|
||||
wire [7:0] m_axi_arlen;
|
||||
wire [2:0] m_axi_arsize;
|
||||
wire [1:0] m_axi_arburst;
|
||||
wire m_axi_arlock;
|
||||
wire [3:0] m_axi_arcache;
|
||||
wire [2:0] m_axi_arprot;
|
||||
wire m_axi_arvalid;
|
||||
wire m_axi_rready;
|
||||
wire status_error_cor;
|
||||
wire status_error_uncor;
|
||||
|
||||
initial begin
|
||||
// myhdl integration
|
||||
$from_myhdl(
|
||||
clk,
|
||||
rst,
|
||||
current_test,
|
||||
s_axis_cq_tdata,
|
||||
s_axis_cq_tkeep,
|
||||
s_axis_cq_tvalid,
|
||||
s_axis_cq_tlast,
|
||||
s_axis_cq_tuser,
|
||||
m_axis_cc_tready,
|
||||
m_axi_arready,
|
||||
m_axi_rid,
|
||||
m_axi_rdata,
|
||||
m_axi_rresp,
|
||||
m_axi_rlast,
|
||||
m_axi_rvalid,
|
||||
completer_id,
|
||||
completer_id_enable,
|
||||
max_payload_size
|
||||
);
|
||||
$to_myhdl(
|
||||
s_axis_cq_tready,
|
||||
m_axis_cc_tdata,
|
||||
m_axis_cc_tkeep,
|
||||
m_axis_cc_tvalid,
|
||||
m_axis_cc_tlast,
|
||||
m_axis_cc_tuser,
|
||||
m_axi_arid,
|
||||
m_axi_araddr,
|
||||
m_axi_arlen,
|
||||
m_axi_arsize,
|
||||
m_axi_arburst,
|
||||
m_axi_arlock,
|
||||
m_axi_arcache,
|
||||
m_axi_arprot,
|
||||
m_axi_arvalid,
|
||||
m_axi_rready,
|
||||
status_error_cor,
|
||||
status_error_uncor
|
||||
);
|
||||
|
||||
// dump file
|
||||
$dumpfile("test_pcie_us_axi_master_rd_64.lxt");
|
||||
$dumpvars(0, test_pcie_us_axi_master_rd_64);
|
||||
end
|
||||
|
||||
pcie_us_axi_master_rd #(
|
||||
.AXIS_PCIE_DATA_WIDTH(AXIS_PCIE_DATA_WIDTH),
|
||||
.AXIS_PCIE_KEEP_WIDTH(AXIS_PCIE_KEEP_WIDTH),
|
||||
.AXI_DATA_WIDTH(AXI_DATA_WIDTH),
|
||||
.AXI_ADDR_WIDTH(AXI_ADDR_WIDTH),
|
||||
.AXI_STRB_WIDTH(AXI_STRB_WIDTH),
|
||||
.AXI_ID_WIDTH(AXI_ID_WIDTH),
|
||||
.AXI_MAX_BURST_LEN(AXI_MAX_BURST_LEN)
|
||||
)
|
||||
UUT (
|
||||
.clk(clk),
|
||||
.rst(rst),
|
||||
.s_axis_cq_tdata(s_axis_cq_tdata),
|
||||
.s_axis_cq_tkeep(s_axis_cq_tkeep),
|
||||
.s_axis_cq_tvalid(s_axis_cq_tvalid),
|
||||
.s_axis_cq_tready(s_axis_cq_tready),
|
||||
.s_axis_cq_tlast(s_axis_cq_tlast),
|
||||
.s_axis_cq_tuser(s_axis_cq_tuser),
|
||||
.m_axis_cc_tdata(m_axis_cc_tdata),
|
||||
.m_axis_cc_tkeep(m_axis_cc_tkeep),
|
||||
.m_axis_cc_tvalid(m_axis_cc_tvalid),
|
||||
.m_axis_cc_tready(m_axis_cc_tready),
|
||||
.m_axis_cc_tlast(m_axis_cc_tlast),
|
||||
.m_axis_cc_tuser(m_axis_cc_tuser),
|
||||
.m_axi_arid(m_axi_arid),
|
||||
.m_axi_araddr(m_axi_araddr),
|
||||
.m_axi_arlen(m_axi_arlen),
|
||||
.m_axi_arsize(m_axi_arsize),
|
||||
.m_axi_arburst(m_axi_arburst),
|
||||
.m_axi_arlock(m_axi_arlock),
|
||||
.m_axi_arcache(m_axi_arcache),
|
||||
.m_axi_arprot(m_axi_arprot),
|
||||
.m_axi_arvalid(m_axi_arvalid),
|
||||
.m_axi_arready(m_axi_arready),
|
||||
.m_axi_rid(m_axi_rid),
|
||||
.m_axi_rdata(m_axi_rdata),
|
||||
.m_axi_rresp(m_axi_rresp),
|
||||
.m_axi_rlast(m_axi_rlast),
|
||||
.m_axi_rvalid(m_axi_rvalid),
|
||||
.m_axi_rready(m_axi_rready),
|
||||
.completer_id(completer_id),
|
||||
.completer_id_enable(completer_id_enable),
|
||||
.max_payload_size(max_payload_size),
|
||||
.status_error_cor(status_error_cor),
|
||||
.status_error_uncor(status_error_uncor)
|
||||
);
|
||||
|
||||
endmodule
|
403
fpga/lib/pcie/tb/test_pcie_us_axi_master_wr_128.py
Executable file
403
fpga/lib/pcie/tb/test_pcie_us_axi_master_wr_128.py
Executable file
@ -0,0 +1,403 @@
|
||||
#!/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 pcie
|
||||
import pcie_us
|
||||
import axi
|
||||
|
||||
module = 'pcie_us_axi_master_wr'
|
||||
testbench = 'test_%s_128' % module
|
||||
|
||||
srcs = []
|
||||
|
||||
srcs.append("../rtl/%s.v" % module)
|
||||
srcs.append("%s.v" % testbench)
|
||||
|
||||
src = ' '.join(srcs)
|
||||
|
||||
build_cmd = "iverilog -o %s.vvp %s" % (testbench, src)
|
||||
|
||||
def bench():
|
||||
|
||||
# Parameters
|
||||
AXIS_PCIE_DATA_WIDTH = 128
|
||||
AXIS_PCIE_KEEP_WIDTH = (AXIS_PCIE_DATA_WIDTH/32)
|
||||
AXI_DATA_WIDTH = AXIS_PCIE_DATA_WIDTH
|
||||
AXI_ADDR_WIDTH = 64
|
||||
AXI_STRB_WIDTH = (AXI_DATA_WIDTH/8)
|
||||
AXI_ID_WIDTH = 8
|
||||
AXI_MAX_BURST_LEN = 256
|
||||
|
||||
# Inputs
|
||||
clk = Signal(bool(0))
|
||||
rst = Signal(bool(0))
|
||||
current_test = Signal(intbv(0)[8:])
|
||||
|
||||
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_tvalid = Signal(bool(0))
|
||||
s_axis_cq_tlast = Signal(bool(0))
|
||||
s_axis_cq_tuser = Signal(intbv(0)[85:])
|
||||
m_axi_awready = Signal(bool(0))
|
||||
m_axi_wready = Signal(bool(0))
|
||||
m_axi_bid = Signal(intbv(0)[AXI_ID_WIDTH:])
|
||||
m_axi_bresp = Signal(intbv(0)[2:])
|
||||
m_axi_bvalid = Signal(bool(0))
|
||||
|
||||
# Outputs
|
||||
s_axis_cq_tready = Signal(bool(0))
|
||||
m_axi_awid = Signal(intbv(0)[AXI_ID_WIDTH:])
|
||||
m_axi_awaddr = Signal(intbv(0)[AXI_ADDR_WIDTH:])
|
||||
m_axi_awlen = Signal(intbv(0)[8:])
|
||||
m_axi_awsize = Signal(intbv(4)[3:])
|
||||
m_axi_awburst = Signal(intbv(1)[2:])
|
||||
m_axi_awlock = Signal(bool(0))
|
||||
m_axi_awcache = Signal(intbv(3)[4:])
|
||||
m_axi_awprot = Signal(intbv(2)[3:])
|
||||
m_axi_awvalid = Signal(bool(0))
|
||||
m_axi_wdata = Signal(intbv(0)[AXI_DATA_WIDTH:])
|
||||
m_axi_wstrb = Signal(intbv(0)[AXI_STRB_WIDTH:])
|
||||
m_axi_wlast = Signal(bool(0))
|
||||
m_axi_wvalid = Signal(bool(0))
|
||||
m_axi_bready = Signal(bool(1))
|
||||
status_error_uncor = Signal(bool(0))
|
||||
|
||||
# Clock and Reset Interface
|
||||
user_clk=Signal(bool(0))
|
||||
user_reset=Signal(bool(0))
|
||||
sys_clk=Signal(bool(0))
|
||||
sys_reset=Signal(bool(0))
|
||||
|
||||
# AXI4 RAM model
|
||||
axi_ram_inst = axi.AXIRam(2**16)
|
||||
|
||||
axi_ram_port0 = axi_ram_inst.create_port(
|
||||
user_clk,
|
||||
s_axi_awid=m_axi_awid,
|
||||
s_axi_awaddr=m_axi_awaddr,
|
||||
s_axi_awlen=m_axi_awlen,
|
||||
s_axi_awsize=m_axi_awsize,
|
||||
s_axi_awburst=m_axi_awburst,
|
||||
s_axi_awlock=m_axi_awlock,
|
||||
s_axi_awcache=m_axi_awcache,
|
||||
s_axi_awprot=m_axi_awprot,
|
||||
s_axi_awvalid=m_axi_awvalid,
|
||||
s_axi_awready=m_axi_awready,
|
||||
s_axi_wdata=m_axi_wdata,
|
||||
s_axi_wstrb=m_axi_wstrb,
|
||||
s_axi_wlast=m_axi_wlast,
|
||||
s_axi_wvalid=m_axi_wvalid,
|
||||
s_axi_wready=m_axi_wready,
|
||||
s_axi_bid=m_axi_bid,
|
||||
s_axi_bresp=m_axi_bresp,
|
||||
s_axi_bvalid=m_axi_bvalid,
|
||||
s_axi_bready=m_axi_bready,
|
||||
name='port0'
|
||||
)
|
||||
|
||||
# PCIe devices
|
||||
rc = pcie.RootComplex()
|
||||
|
||||
dev = pcie_us.UltrascalePCIe()
|
||||
|
||||
dev.pcie_generation = 3
|
||||
dev.pcie_link_width = 4
|
||||
dev.user_clock_frequency = 250e6
|
||||
|
||||
dev.functions[0].configure_bar(0, 16*1024*1024)
|
||||
|
||||
rc.make_port().connect(dev)
|
||||
|
||||
cq_pause = Signal(bool(0))
|
||||
cc_pause = Signal(bool(0))
|
||||
rq_pause = Signal(bool(0))
|
||||
rc_pause = Signal(bool(0))
|
||||
|
||||
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_count=pcie_cq_np_req_count,
|
||||
|
||||
# Completer Completion Interface
|
||||
s_axis_cc_tdata=Signal(intbv(0)[AXIS_PCIE_DATA_WIDTH:]),
|
||||
s_axis_cc_tuser=Signal(intbv(0)[33:]),
|
||||
s_axis_cc_tlast=Signal(bool(0)),
|
||||
s_axis_cc_tkeep=Signal(intbv(0)[AXIS_PCIE_KEEP_WIDTH:]),
|
||||
s_axis_cc_tvalid=Signal(bool(0)),
|
||||
s_axis_cc_tready=Signal(bool(0)),
|
||||
|
||||
# Requester reQuest Interface
|
||||
s_axis_rq_tdata=Signal(intbv(0)[AXIS_PCIE_DATA_WIDTH:]),
|
||||
s_axis_rq_tuser=Signal(intbv(0)[60:]),
|
||||
s_axis_rq_tlast=Signal(bool(0)),
|
||||
s_axis_rq_tkeep=Signal(intbv(0)[AXIS_PCIE_KEEP_WIDTH:]),
|
||||
s_axis_rq_tvalid=Signal(bool(0)),
|
||||
s_axis_rq_tready=Signal(bool(1)),
|
||||
# pcie_rq_seq_num=pcie_rq_seq_num,
|
||||
# pcie_rq_seq_num_vld=pcie_rq_seq_num_vld,
|
||||
# pcie_rq_tag=pcie_rq_tag,
|
||||
# pcie_rq_tag_av=pcie_rq_tag_av,
|
||||
# pcie_rq_tag_vld=pcie_rq_tag_vld,
|
||||
|
||||
# Requester Completion Interface
|
||||
m_axis_rc_tdata=Signal(intbv(0)[AXIS_PCIE_DATA_WIDTH:]),
|
||||
m_axis_rc_tuser=Signal(intbv(0)[75:]),
|
||||
m_axis_rc_tlast=Signal(bool(0)),
|
||||
m_axis_rc_tkeep=Signal(intbv(0)[AXIS_PCIE_KEEP_WIDTH:]),
|
||||
m_axis_rc_tvalid=Signal(bool(0)),
|
||||
m_axis_rc_tready=Signal(bool(0)),
|
||||
|
||||
# Transmit Flow Control Interface
|
||||
# pcie_tfc_nph_av=pcie_tfc_nph_av,
|
||||
# pcie_tfc_npd_av=pcie_tfc_npd_av,
|
||||
|
||||
# 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_per_function_update_done=cfg_per_function_update_done,
|
||||
# cfg_per_function_number=cfg_per_function_number,
|
||||
# cfg_per_function_output_request=cfg_per_function_output_request,
|
||||
# cfg_dsn=cfg_dsn,
|
||||
# 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=cfg_err_cor_in,
|
||||
# cfg_err_uncor_in=cfg_err_uncor_in,
|
||||
# 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,
|
||||
|
||||
# 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,
|
||||
|
||||
cq_pause=cq_pause,
|
||||
cc_pause=cc_pause,
|
||||
rq_pause=rq_pause,
|
||||
rc_pause=rc_pause
|
||||
)
|
||||
|
||||
# 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,
|
||||
s_axis_cq_tdata=s_axis_cq_tdata,
|
||||
s_axis_cq_tkeep=s_axis_cq_tkeep,
|
||||
s_axis_cq_tvalid=s_axis_cq_tvalid,
|
||||
s_axis_cq_tready=s_axis_cq_tready,
|
||||
s_axis_cq_tlast=s_axis_cq_tlast,
|
||||
s_axis_cq_tuser=s_axis_cq_tuser,
|
||||
m_axi_awid=m_axi_awid,
|
||||
m_axi_awaddr=m_axi_awaddr,
|
||||
m_axi_awlen=m_axi_awlen,
|
||||
m_axi_awsize=m_axi_awsize,
|
||||
m_axi_awburst=m_axi_awburst,
|
||||
m_axi_awlock=m_axi_awlock,
|
||||
m_axi_awcache=m_axi_awcache,
|
||||
m_axi_awprot=m_axi_awprot,
|
||||
m_axi_awvalid=m_axi_awvalid,
|
||||
m_axi_awready=m_axi_awready,
|
||||
m_axi_wdata=m_axi_wdata,
|
||||
m_axi_wstrb=m_axi_wstrb,
|
||||
m_axi_wlast=m_axi_wlast,
|
||||
m_axi_wvalid=m_axi_wvalid,
|
||||
m_axi_wready=m_axi_wready,
|
||||
m_axi_bid=m_axi_bid,
|
||||
m_axi_bresp=m_axi_bresp,
|
||||
m_axi_bvalid=m_axi_bvalid,
|
||||
m_axi_bready=m_axi_bready,
|
||||
status_error_uncor=status_error_uncor
|
||||
)
|
||||
|
||||
@always(delay(4))
|
||||
def clkgen():
|
||||
clk.next = not clk
|
||||
|
||||
@always_comb
|
||||
def clk_logic():
|
||||
sys_clk.next = clk
|
||||
sys_reset.next = not rst
|
||||
|
||||
status_error_uncor_asserted = Signal(bool(0))
|
||||
|
||||
@always(user_clk.posedge)
|
||||
def monitor():
|
||||
if (status_error_uncor):
|
||||
status_error_uncor_asserted.next = 1
|
||||
|
||||
cq_pause_toggle = Signal(bool(0))
|
||||
cc_pause_toggle = Signal(bool(0))
|
||||
rq_pause_toggle = Signal(bool(0))
|
||||
rc_pause_toggle = Signal(bool(0))
|
||||
|
||||
@instance
|
||||
def pause_toggle():
|
||||
while True:
|
||||
if (cq_pause_toggle or cc_pause_toggle or rq_pause_toggle or rc_pause_toggle):
|
||||
cq_pause.next = cq_pause_toggle
|
||||
cc_pause.next = cc_pause_toggle
|
||||
rq_pause.next = rq_pause_toggle
|
||||
rc_pause.next = rc_pause_toggle
|
||||
|
||||
yield user_clk.posedge
|
||||
yield user_clk.posedge
|
||||
yield user_clk.posedge
|
||||
|
||||
cq_pause.next = 0
|
||||
cc_pause.next = 0
|
||||
rq_pause.next = 0
|
||||
rc_pause.next = 0
|
||||
|
||||
yield user_clk.posedge
|
||||
|
||||
@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
|
||||
|
||||
yield user_clk.posedge
|
||||
print("test 1: enumeration")
|
||||
current_test.next = 1
|
||||
|
||||
yield rc.enumerate()
|
||||
|
||||
dev_bar0 = rc.tree[0][0].bar[0]
|
||||
|
||||
yield delay(100)
|
||||
|
||||
yield clk.posedge
|
||||
print("test 2: memory write")
|
||||
current_test.next = 2
|
||||
|
||||
pcie_addr = 0x00000000
|
||||
test_data = b'\x11\x22\x33\x44'
|
||||
|
||||
yield rc.mem_write(dev_bar0+pcie_addr, test_data)
|
||||
|
||||
yield delay(300)
|
||||
|
||||
data = axi_ram_inst.read_mem(pcie_addr, 32)
|
||||
for i in range(0, len(data), 16):
|
||||
print(" ".join(("{:02x}".format(c) for c in bytearray(data[i:i+16]))))
|
||||
|
||||
assert axi_ram_inst.read_mem(pcie_addr, len(test_data)) == test_data
|
||||
|
||||
assert not status_error_uncor_asserted
|
||||
|
||||
yield delay(100)
|
||||
|
||||
yield user_clk.posedge
|
||||
print("test 3: various writes")
|
||||
current_test.next = 3
|
||||
|
||||
for length in list(range(1,34))+[1024]:
|
||||
for pcie_offset in list(range(8,41))+list(range(4096-32,4096)):
|
||||
for pause in [False, True]:
|
||||
print("length %d, pcie_offset %d"% (length, pcie_offset))
|
||||
#pcie_addr = length * 0x100000000 + pcie_offset * 0x10000 + offset
|
||||
pcie_addr = pcie_offset
|
||||
test_data = bytearray([x%256 for x in range(length)])
|
||||
|
||||
axi_ram_inst.write_mem(pcie_addr & 0xffff80, b'\x55'*(len(test_data)+256))
|
||||
|
||||
cq_pause_toggle.next = pause
|
||||
|
||||
yield from rc.mem_write(dev_bar0+pcie_addr, test_data)
|
||||
|
||||
yield delay(int(length*4+120))
|
||||
|
||||
cq_pause_toggle.next = 0
|
||||
|
||||
data = axi_ram_inst.read_mem(pcie_addr&0xfffff0, 64)
|
||||
for i in range(0, len(data), 16):
|
||||
print(" ".join(("{:02x}".format(c) for c in bytearray(data[i:i+16]))))
|
||||
|
||||
assert axi_ram_inst.read_mem(pcie_addr-1, len(test_data)+2) == b'\x55'+test_data+b'\x55'
|
||||
|
||||
assert not status_error_uncor_asserted
|
||||
|
||||
yield delay(100)
|
||||
|
||||
yield clk.posedge
|
||||
print("test 4: bad request")
|
||||
current_test.next = 4
|
||||
|
||||
try:
|
||||
yield from rc.mem_read(dev_bar0, 4, 100)
|
||||
except:
|
||||
print("Caught timeout exception")
|
||||
pass
|
||||
else:
|
||||
assert False
|
||||
|
||||
assert status_error_uncor_asserted
|
||||
|
||||
status_error_uncor_asserted.next = False
|
||||
|
||||
yield delay(100)
|
||||
|
||||
raise StopSimulation
|
||||
|
||||
return instances()
|
||||
|
||||
def test_bench():
|
||||
sim = Simulation(bench())
|
||||
sim.run()
|
||||
|
||||
if __name__ == '__main__':
|
||||
print("Running test...")
|
||||
test_bench()
|
158
fpga/lib/pcie/tb/test_pcie_us_axi_master_wr_128.v
Normal file
158
fpga/lib/pcie/tb/test_pcie_us_axi_master_wr_128.v
Normal file
@ -0,0 +1,158 @@
|
||||
/*
|
||||
|
||||
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 pcie_us_axi_master_wr
|
||||
*/
|
||||
module test_pcie_us_axi_master_wr_128;
|
||||
|
||||
// Parameters
|
||||
parameter AXIS_PCIE_DATA_WIDTH = 128;
|
||||
parameter AXIS_PCIE_KEEP_WIDTH = (AXIS_PCIE_DATA_WIDTH/32);
|
||||
parameter AXI_DATA_WIDTH = AXIS_PCIE_DATA_WIDTH;
|
||||
parameter AXI_ADDR_WIDTH = 64;
|
||||
parameter AXI_STRB_WIDTH = (AXI_DATA_WIDTH/8);
|
||||
parameter AXI_ID_WIDTH = 8;
|
||||
parameter AXI_MAX_BURST_LEN = 256;
|
||||
|
||||
// Inputs
|
||||
reg clk = 0;
|
||||
reg rst = 0;
|
||||
reg [7:0] current_test = 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_tvalid = 0;
|
||||
reg s_axis_cq_tlast = 0;
|
||||
reg [84:0] s_axis_cq_tuser = 0;
|
||||
reg m_axi_awready = 0;
|
||||
reg m_axi_wready = 0;
|
||||
reg [AXI_ID_WIDTH-1:0] m_axi_bid = 0;
|
||||
reg [1:0] m_axi_bresp = 0;
|
||||
reg m_axi_bvalid = 0;
|
||||
|
||||
// Outputs
|
||||
wire s_axis_cq_tready;
|
||||
wire [AXI_ID_WIDTH-1:0] m_axi_awid;
|
||||
wire [AXI_ADDR_WIDTH-1:0] m_axi_awaddr;
|
||||
wire [7:0] m_axi_awlen;
|
||||
wire [2:0] m_axi_awsize;
|
||||
wire [1:0] m_axi_awburst;
|
||||
wire m_axi_awlock;
|
||||
wire [3:0] m_axi_awcache;
|
||||
wire [2:0] m_axi_awprot;
|
||||
wire m_axi_awvalid;
|
||||
wire [AXI_DATA_WIDTH-1:0] m_axi_wdata;
|
||||
wire [AXI_STRB_WIDTH-1:0] m_axi_wstrb;
|
||||
wire m_axi_wlast;
|
||||
wire m_axi_wvalid;
|
||||
wire m_axi_bready;
|
||||
wire status_error_uncor;
|
||||
|
||||
initial begin
|
||||
// myhdl integration
|
||||
$from_myhdl(
|
||||
clk,
|
||||
rst,
|
||||
current_test,
|
||||
s_axis_cq_tdata,
|
||||
s_axis_cq_tkeep,
|
||||
s_axis_cq_tvalid,
|
||||
s_axis_cq_tlast,
|
||||
s_axis_cq_tuser,
|
||||
m_axi_awready,
|
||||
m_axi_wready,
|
||||
m_axi_bid,
|
||||
m_axi_bresp,
|
||||
m_axi_bvalid
|
||||
);
|
||||
$to_myhdl(
|
||||
s_axis_cq_tready,
|
||||
m_axi_awid,
|
||||
m_axi_awaddr,
|
||||
m_axi_awlen,
|
||||
m_axi_awsize,
|
||||
m_axi_awburst,
|
||||
m_axi_awlock,
|
||||
m_axi_awcache,
|
||||
m_axi_awprot,
|
||||
m_axi_awvalid,
|
||||
m_axi_wdata,
|
||||
m_axi_wstrb,
|
||||
m_axi_wlast,
|
||||
m_axi_wvalid,
|
||||
m_axi_bready,
|
||||
status_error_uncor
|
||||
);
|
||||
|
||||
// dump file
|
||||
$dumpfile("test_pcie_us_axi_master_wr_128.lxt");
|
||||
$dumpvars(0, test_pcie_us_axi_master_wr_128);
|
||||
end
|
||||
|
||||
pcie_us_axi_master_wr #(
|
||||
.AXIS_PCIE_DATA_WIDTH(AXIS_PCIE_DATA_WIDTH),
|
||||
.AXIS_PCIE_KEEP_WIDTH(AXIS_PCIE_KEEP_WIDTH),
|
||||
.AXI_DATA_WIDTH(AXI_DATA_WIDTH),
|
||||
.AXI_ADDR_WIDTH(AXI_ADDR_WIDTH),
|
||||
.AXI_STRB_WIDTH(AXI_STRB_WIDTH),
|
||||
.AXI_ID_WIDTH(AXI_ID_WIDTH),
|
||||
.AXI_MAX_BURST_LEN(AXI_MAX_BURST_LEN)
|
||||
)
|
||||
UUT (
|
||||
.clk(clk),
|
||||
.rst(rst),
|
||||
.s_axis_cq_tdata(s_axis_cq_tdata),
|
||||
.s_axis_cq_tkeep(s_axis_cq_tkeep),
|
||||
.s_axis_cq_tvalid(s_axis_cq_tvalid),
|
||||
.s_axis_cq_tready(s_axis_cq_tready),
|
||||
.s_axis_cq_tlast(s_axis_cq_tlast),
|
||||
.s_axis_cq_tuser(s_axis_cq_tuser),
|
||||
.m_axi_awid(m_axi_awid),
|
||||
.m_axi_awaddr(m_axi_awaddr),
|
||||
.m_axi_awlen(m_axi_awlen),
|
||||
.m_axi_awsize(m_axi_awsize),
|
||||
.m_axi_awburst(m_axi_awburst),
|
||||
.m_axi_awlock(m_axi_awlock),
|
||||
.m_axi_awcache(m_axi_awcache),
|
||||
.m_axi_awprot(m_axi_awprot),
|
||||
.m_axi_awvalid(m_axi_awvalid),
|
||||
.m_axi_awready(m_axi_awready),
|
||||
.m_axi_wdata(m_axi_wdata),
|
||||
.m_axi_wstrb(m_axi_wstrb),
|
||||
.m_axi_wlast(m_axi_wlast),
|
||||
.m_axi_wvalid(m_axi_wvalid),
|
||||
.m_axi_wready(m_axi_wready),
|
||||
.m_axi_bid(m_axi_bid),
|
||||
.m_axi_bresp(m_axi_bresp),
|
||||
.m_axi_bvalid(m_axi_bvalid),
|
||||
.m_axi_bready(m_axi_bready),
|
||||
.status_error_uncor(status_error_uncor)
|
||||
);
|
||||
|
||||
endmodule
|
403
fpga/lib/pcie/tb/test_pcie_us_axi_master_wr_256.py
Executable file
403
fpga/lib/pcie/tb/test_pcie_us_axi_master_wr_256.py
Executable file
@ -0,0 +1,403 @@
|
||||
#!/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 pcie
|
||||
import pcie_us
|
||||
import axi
|
||||
|
||||
module = 'pcie_us_axi_master_wr'
|
||||
testbench = 'test_%s_256' % module
|
||||
|
||||
srcs = []
|
||||
|
||||
srcs.append("../rtl/%s.v" % module)
|
||||
srcs.append("%s.v" % testbench)
|
||||
|
||||
src = ' '.join(srcs)
|
||||
|
||||
build_cmd = "iverilog -o %s.vvp %s" % (testbench, src)
|
||||
|
||||
def bench():
|
||||
|
||||
# Parameters
|
||||
AXIS_PCIE_DATA_WIDTH = 256
|
||||
AXIS_PCIE_KEEP_WIDTH = (AXIS_PCIE_DATA_WIDTH/32)
|
||||
AXI_DATA_WIDTH = AXIS_PCIE_DATA_WIDTH
|
||||
AXI_ADDR_WIDTH = 64
|
||||
AXI_STRB_WIDTH = (AXI_DATA_WIDTH/8)
|
||||
AXI_ID_WIDTH = 8
|
||||
AXI_MAX_BURST_LEN = 256
|
||||
|
||||
# Inputs
|
||||
clk = Signal(bool(0))
|
||||
rst = Signal(bool(0))
|
||||
current_test = Signal(intbv(0)[8:])
|
||||
|
||||
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_tvalid = Signal(bool(0))
|
||||
s_axis_cq_tlast = Signal(bool(0))
|
||||
s_axis_cq_tuser = Signal(intbv(0)[85:])
|
||||
m_axi_awready = Signal(bool(0))
|
||||
m_axi_wready = Signal(bool(0))
|
||||
m_axi_bid = Signal(intbv(0)[AXI_ID_WIDTH:])
|
||||
m_axi_bresp = Signal(intbv(0)[2:])
|
||||
m_axi_bvalid = Signal(bool(0))
|
||||
|
||||
# Outputs
|
||||
s_axis_cq_tready = Signal(bool(0))
|
||||
m_axi_awid = Signal(intbv(0)[AXI_ID_WIDTH:])
|
||||
m_axi_awaddr = Signal(intbv(0)[AXI_ADDR_WIDTH:])
|
||||
m_axi_awlen = Signal(intbv(0)[8:])
|
||||
m_axi_awsize = Signal(intbv(5)[3:])
|
||||
m_axi_awburst = Signal(intbv(1)[2:])
|
||||
m_axi_awlock = Signal(bool(0))
|
||||
m_axi_awcache = Signal(intbv(3)[4:])
|
||||
m_axi_awprot = Signal(intbv(2)[3:])
|
||||
m_axi_awvalid = Signal(bool(0))
|
||||
m_axi_wdata = Signal(intbv(0)[AXI_DATA_WIDTH:])
|
||||
m_axi_wstrb = Signal(intbv(0)[AXI_STRB_WIDTH:])
|
||||
m_axi_wlast = Signal(bool(0))
|
||||
m_axi_wvalid = Signal(bool(0))
|
||||
m_axi_bready = Signal(bool(1))
|
||||
status_error_uncor = Signal(bool(0))
|
||||
|
||||
# Clock and Reset Interface
|
||||
user_clk=Signal(bool(0))
|
||||
user_reset=Signal(bool(0))
|
||||
sys_clk=Signal(bool(0))
|
||||
sys_reset=Signal(bool(0))
|
||||
|
||||
# AXI4 RAM model
|
||||
axi_ram_inst = axi.AXIRam(2**16)
|
||||
|
||||
axi_ram_port0 = axi_ram_inst.create_port(
|
||||
user_clk,
|
||||
s_axi_awid=m_axi_awid,
|
||||
s_axi_awaddr=m_axi_awaddr,
|
||||
s_axi_awlen=m_axi_awlen,
|
||||
s_axi_awsize=m_axi_awsize,
|
||||
s_axi_awburst=m_axi_awburst,
|
||||
s_axi_awlock=m_axi_awlock,
|
||||
s_axi_awcache=m_axi_awcache,
|
||||
s_axi_awprot=m_axi_awprot,
|
||||
s_axi_awvalid=m_axi_awvalid,
|
||||
s_axi_awready=m_axi_awready,
|
||||
s_axi_wdata=m_axi_wdata,
|
||||
s_axi_wstrb=m_axi_wstrb,
|
||||
s_axi_wlast=m_axi_wlast,
|
||||
s_axi_wvalid=m_axi_wvalid,
|
||||
s_axi_wready=m_axi_wready,
|
||||
s_axi_bid=m_axi_bid,
|
||||
s_axi_bresp=m_axi_bresp,
|
||||
s_axi_bvalid=m_axi_bvalid,
|
||||
s_axi_bready=m_axi_bready,
|
||||
name='port0'
|
||||
)
|
||||
|
||||
# PCIe devices
|
||||
rc = pcie.RootComplex()
|
||||
|
||||
dev = pcie_us.UltrascalePCIe()
|
||||
|
||||
dev.pcie_generation = 3
|
||||
dev.pcie_link_width = 8
|
||||
dev.user_clock_frequency = 250e6
|
||||
|
||||
dev.functions[0].configure_bar(0, 16*1024*1024)
|
||||
|
||||
rc.make_port().connect(dev)
|
||||
|
||||
cq_pause = Signal(bool(0))
|
||||
cc_pause = Signal(bool(0))
|
||||
rq_pause = Signal(bool(0))
|
||||
rc_pause = Signal(bool(0))
|
||||
|
||||
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_count=pcie_cq_np_req_count,
|
||||
|
||||
# Completer Completion Interface
|
||||
s_axis_cc_tdata=Signal(intbv(0)[AXIS_PCIE_DATA_WIDTH:]),
|
||||
s_axis_cc_tuser=Signal(intbv(0)[33:]),
|
||||
s_axis_cc_tlast=Signal(bool(0)),
|
||||
s_axis_cc_tkeep=Signal(intbv(0)[AXIS_PCIE_KEEP_WIDTH:]),
|
||||
s_axis_cc_tvalid=Signal(bool(0)),
|
||||
s_axis_cc_tready=Signal(bool(0)),
|
||||
|
||||
# Requester reQuest Interface
|
||||
s_axis_rq_tdata=Signal(intbv(0)[AXIS_PCIE_DATA_WIDTH:]),
|
||||
s_axis_rq_tuser=Signal(intbv(0)[60:]),
|
||||
s_axis_rq_tlast=Signal(bool(0)),
|
||||
s_axis_rq_tkeep=Signal(intbv(0)[AXIS_PCIE_KEEP_WIDTH:]),
|
||||
s_axis_rq_tvalid=Signal(bool(0)),
|
||||
s_axis_rq_tready=Signal(bool(1)),
|
||||
# pcie_rq_seq_num=pcie_rq_seq_num,
|
||||
# pcie_rq_seq_num_vld=pcie_rq_seq_num_vld,
|
||||
# pcie_rq_tag=pcie_rq_tag,
|
||||
# pcie_rq_tag_av=pcie_rq_tag_av,
|
||||
# pcie_rq_tag_vld=pcie_rq_tag_vld,
|
||||
|
||||
# Requester Completion Interface
|
||||
m_axis_rc_tdata=Signal(intbv(0)[AXIS_PCIE_DATA_WIDTH:]),
|
||||
m_axis_rc_tuser=Signal(intbv(0)[75:]),
|
||||
m_axis_rc_tlast=Signal(bool(0)),
|
||||
m_axis_rc_tkeep=Signal(intbv(0)[AXIS_PCIE_KEEP_WIDTH:]),
|
||||
m_axis_rc_tvalid=Signal(bool(0)),
|
||||
m_axis_rc_tready=Signal(bool(0)),
|
||||
|
||||
# Transmit Flow Control Interface
|
||||
# pcie_tfc_nph_av=pcie_tfc_nph_av,
|
||||
# pcie_tfc_npd_av=pcie_tfc_npd_av,
|
||||
|
||||
# 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_per_function_update_done=cfg_per_function_update_done,
|
||||
# cfg_per_function_number=cfg_per_function_number,
|
||||
# cfg_per_function_output_request=cfg_per_function_output_request,
|
||||
# cfg_dsn=cfg_dsn,
|
||||
# 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=cfg_err_cor_in,
|
||||
# cfg_err_uncor_in=cfg_err_uncor_in,
|
||||
# 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,
|
||||
|
||||
# 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,
|
||||
|
||||
cq_pause=cq_pause,
|
||||
cc_pause=cc_pause,
|
||||
rq_pause=rq_pause,
|
||||
rc_pause=rc_pause
|
||||
)
|
||||
|
||||
# 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,
|
||||
s_axis_cq_tdata=s_axis_cq_tdata,
|
||||
s_axis_cq_tkeep=s_axis_cq_tkeep,
|
||||
s_axis_cq_tvalid=s_axis_cq_tvalid,
|
||||
s_axis_cq_tready=s_axis_cq_tready,
|
||||
s_axis_cq_tlast=s_axis_cq_tlast,
|
||||
s_axis_cq_tuser=s_axis_cq_tuser,
|
||||
m_axi_awid=m_axi_awid,
|
||||
m_axi_awaddr=m_axi_awaddr,
|
||||
m_axi_awlen=m_axi_awlen,
|
||||
m_axi_awsize=m_axi_awsize,
|
||||
m_axi_awburst=m_axi_awburst,
|
||||
m_axi_awlock=m_axi_awlock,
|
||||
m_axi_awcache=m_axi_awcache,
|
||||
m_axi_awprot=m_axi_awprot,
|
||||
m_axi_awvalid=m_axi_awvalid,
|
||||
m_axi_awready=m_axi_awready,
|
||||
m_axi_wdata=m_axi_wdata,
|
||||
m_axi_wstrb=m_axi_wstrb,
|
||||
m_axi_wlast=m_axi_wlast,
|
||||
m_axi_wvalid=m_axi_wvalid,
|
||||
m_axi_wready=m_axi_wready,
|
||||
m_axi_bid=m_axi_bid,
|
||||
m_axi_bresp=m_axi_bresp,
|
||||
m_axi_bvalid=m_axi_bvalid,
|
||||
m_axi_bready=m_axi_bready,
|
||||
status_error_uncor=status_error_uncor
|
||||
)
|
||||
|
||||
@always(delay(4))
|
||||
def clkgen():
|
||||
clk.next = not clk
|
||||
|
||||
@always_comb
|
||||
def clk_logic():
|
||||
sys_clk.next = clk
|
||||
sys_reset.next = not rst
|
||||
|
||||
status_error_uncor_asserted = Signal(bool(0))
|
||||
|
||||
@always(user_clk.posedge)
|
||||
def monitor():
|
||||
if (status_error_uncor):
|
||||
status_error_uncor_asserted.next = 1
|
||||
|
||||
cq_pause_toggle = Signal(bool(0))
|
||||
cc_pause_toggle = Signal(bool(0))
|
||||
rq_pause_toggle = Signal(bool(0))
|
||||
rc_pause_toggle = Signal(bool(0))
|
||||
|
||||
@instance
|
||||
def pause_toggle():
|
||||
while True:
|
||||
if (cq_pause_toggle or cc_pause_toggle or rq_pause_toggle or rc_pause_toggle):
|
||||
cq_pause.next = cq_pause_toggle
|
||||
cc_pause.next = cc_pause_toggle
|
||||
rq_pause.next = rq_pause_toggle
|
||||
rc_pause.next = rc_pause_toggle
|
||||
|
||||
yield user_clk.posedge
|
||||
yield user_clk.posedge
|
||||
yield user_clk.posedge
|
||||
|
||||
cq_pause.next = 0
|
||||
cc_pause.next = 0
|
||||
rq_pause.next = 0
|
||||
rc_pause.next = 0
|
||||
|
||||
yield user_clk.posedge
|
||||
|
||||
@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
|
||||
|
||||
yield user_clk.posedge
|
||||
print("test 1: enumeration")
|
||||
current_test.next = 1
|
||||
|
||||
yield rc.enumerate()
|
||||
|
||||
dev_bar0 = rc.tree[0][0].bar[0]
|
||||
|
||||
yield delay(100)
|
||||
|
||||
yield clk.posedge
|
||||
print("test 2: memory write")
|
||||
current_test.next = 2
|
||||
|
||||
pcie_addr = 0x00000000
|
||||
test_data = b'\x11\x22\x33\x44'
|
||||
|
||||
yield rc.mem_write(dev_bar0+pcie_addr, test_data)
|
||||
|
||||
yield delay(300)
|
||||
|
||||
data = axi_ram_inst.read_mem(pcie_addr, 32)
|
||||
for i in range(0, len(data), 16):
|
||||
print(" ".join(("{:02x}".format(c) for c in bytearray(data[i:i+16]))))
|
||||
|
||||
assert axi_ram_inst.read_mem(pcie_addr, len(test_data)) == test_data
|
||||
|
||||
assert not status_error_uncor_asserted
|
||||
|
||||
yield delay(100)
|
||||
|
||||
yield user_clk.posedge
|
||||
print("test 3: various writes")
|
||||
current_test.next = 3
|
||||
|
||||
for length in list(range(1,34))+[1024]:
|
||||
for pcie_offset in list(range(8,41))+list(range(4096-32,4096)):
|
||||
for pause in [False, True]:
|
||||
print("length %d, pcie_offset %d"% (length, pcie_offset))
|
||||
#pcie_addr = length * 0x100000000 + pcie_offset * 0x10000 + offset
|
||||
pcie_addr = pcie_offset
|
||||
test_data = bytearray([x%256 for x in range(length)])
|
||||
|
||||
axi_ram_inst.write_mem(pcie_addr & 0xffff80, b'\x55'*(len(test_data)+256))
|
||||
|
||||
cq_pause_toggle.next = pause
|
||||
|
||||
yield from rc.mem_write(dev_bar0+pcie_addr, test_data)
|
||||
|
||||
yield delay(int(length*4+60))
|
||||
|
||||
cq_pause_toggle.next = 0
|
||||
|
||||
data = axi_ram_inst.read_mem(pcie_addr&0xfffff0, 64)
|
||||
for i in range(0, len(data), 16):
|
||||
print(" ".join(("{:02x}".format(c) for c in bytearray(data[i:i+16]))))
|
||||
|
||||
assert axi_ram_inst.read_mem(pcie_addr-1, len(test_data)+2) == b'\x55'+test_data+b'\x55'
|
||||
|
||||
assert not status_error_uncor_asserted
|
||||
|
||||
yield delay(100)
|
||||
|
||||
yield clk.posedge
|
||||
print("test 4: bad request")
|
||||
current_test.next = 4
|
||||
|
||||
try:
|
||||
yield from rc.mem_read(dev_bar0, 4, 100)
|
||||
except:
|
||||
print("Caught timeout exception")
|
||||
pass
|
||||
else:
|
||||
assert False
|
||||
|
||||
assert status_error_uncor_asserted
|
||||
|
||||
status_error_uncor_asserted.next = False
|
||||
|
||||
yield delay(100)
|
||||
|
||||
raise StopSimulation
|
||||
|
||||
return instances()
|
||||
|
||||
def test_bench():
|
||||
sim = Simulation(bench())
|
||||
sim.run()
|
||||
|
||||
if __name__ == '__main__':
|
||||
print("Running test...")
|
||||
test_bench()
|
158
fpga/lib/pcie/tb/test_pcie_us_axi_master_wr_256.v
Normal file
158
fpga/lib/pcie/tb/test_pcie_us_axi_master_wr_256.v
Normal file
@ -0,0 +1,158 @@
|
||||
/*
|
||||
|
||||
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 pcie_us_axi_master_wr
|
||||
*/
|
||||
module test_pcie_us_axi_master_wr_256;
|
||||
|
||||
// Parameters
|
||||
parameter AXIS_PCIE_DATA_WIDTH = 256;
|
||||
parameter AXIS_PCIE_KEEP_WIDTH = (AXIS_PCIE_DATA_WIDTH/32);
|
||||
parameter AXI_DATA_WIDTH = AXIS_PCIE_DATA_WIDTH;
|
||||
parameter AXI_ADDR_WIDTH = 64;
|
||||
parameter AXI_STRB_WIDTH = (AXI_DATA_WIDTH/8);
|
||||
parameter AXI_ID_WIDTH = 8;
|
||||
parameter AXI_MAX_BURST_LEN = 256;
|
||||
|
||||
// Inputs
|
||||
reg clk = 0;
|
||||
reg rst = 0;
|
||||
reg [7:0] current_test = 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_tvalid = 0;
|
||||
reg s_axis_cq_tlast = 0;
|
||||
reg [84:0] s_axis_cq_tuser = 0;
|
||||
reg m_axi_awready = 0;
|
||||
reg m_axi_wready = 0;
|
||||
reg [AXI_ID_WIDTH-1:0] m_axi_bid = 0;
|
||||
reg [1:0] m_axi_bresp = 0;
|
||||
reg m_axi_bvalid = 0;
|
||||
|
||||
// Outputs
|
||||
wire s_axis_cq_tready;
|
||||
wire [AXI_ID_WIDTH-1:0] m_axi_awid;
|
||||
wire [AXI_ADDR_WIDTH-1:0] m_axi_awaddr;
|
||||
wire [7:0] m_axi_awlen;
|
||||
wire [2:0] m_axi_awsize;
|
||||
wire [1:0] m_axi_awburst;
|
||||
wire m_axi_awlock;
|
||||
wire [3:0] m_axi_awcache;
|
||||
wire [2:0] m_axi_awprot;
|
||||
wire m_axi_awvalid;
|
||||
wire [AXI_DATA_WIDTH-1:0] m_axi_wdata;
|
||||
wire [AXI_STRB_WIDTH-1:0] m_axi_wstrb;
|
||||
wire m_axi_wlast;
|
||||
wire m_axi_wvalid;
|
||||
wire m_axi_bready;
|
||||
wire status_error_uncor;
|
||||
|
||||
initial begin
|
||||
// myhdl integration
|
||||
$from_myhdl(
|
||||
clk,
|
||||
rst,
|
||||
current_test,
|
||||
s_axis_cq_tdata,
|
||||
s_axis_cq_tkeep,
|
||||
s_axis_cq_tvalid,
|
||||
s_axis_cq_tlast,
|
||||
s_axis_cq_tuser,
|
||||
m_axi_awready,
|
||||
m_axi_wready,
|
||||
m_axi_bid,
|
||||
m_axi_bresp,
|
||||
m_axi_bvalid
|
||||
);
|
||||
$to_myhdl(
|
||||
s_axis_cq_tready,
|
||||
m_axi_awid,
|
||||
m_axi_awaddr,
|
||||
m_axi_awlen,
|
||||
m_axi_awsize,
|
||||
m_axi_awburst,
|
||||
m_axi_awlock,
|
||||
m_axi_awcache,
|
||||
m_axi_awprot,
|
||||
m_axi_awvalid,
|
||||
m_axi_wdata,
|
||||
m_axi_wstrb,
|
||||
m_axi_wlast,
|
||||
m_axi_wvalid,
|
||||
m_axi_bready,
|
||||
status_error_uncor
|
||||
);
|
||||
|
||||
// dump file
|
||||
$dumpfile("test_pcie_us_axi_master_wr_256.lxt");
|
||||
$dumpvars(0, test_pcie_us_axi_master_wr_256);
|
||||
end
|
||||
|
||||
pcie_us_axi_master_wr #(
|
||||
.AXIS_PCIE_DATA_WIDTH(AXIS_PCIE_DATA_WIDTH),
|
||||
.AXIS_PCIE_KEEP_WIDTH(AXIS_PCIE_KEEP_WIDTH),
|
||||
.AXI_DATA_WIDTH(AXI_DATA_WIDTH),
|
||||
.AXI_ADDR_WIDTH(AXI_ADDR_WIDTH),
|
||||
.AXI_STRB_WIDTH(AXI_STRB_WIDTH),
|
||||
.AXI_ID_WIDTH(AXI_ID_WIDTH),
|
||||
.AXI_MAX_BURST_LEN(AXI_MAX_BURST_LEN)
|
||||
)
|
||||
UUT (
|
||||
.clk(clk),
|
||||
.rst(rst),
|
||||
.s_axis_cq_tdata(s_axis_cq_tdata),
|
||||
.s_axis_cq_tkeep(s_axis_cq_tkeep),
|
||||
.s_axis_cq_tvalid(s_axis_cq_tvalid),
|
||||
.s_axis_cq_tready(s_axis_cq_tready),
|
||||
.s_axis_cq_tlast(s_axis_cq_tlast),
|
||||
.s_axis_cq_tuser(s_axis_cq_tuser),
|
||||
.m_axi_awid(m_axi_awid),
|
||||
.m_axi_awaddr(m_axi_awaddr),
|
||||
.m_axi_awlen(m_axi_awlen),
|
||||
.m_axi_awsize(m_axi_awsize),
|
||||
.m_axi_awburst(m_axi_awburst),
|
||||
.m_axi_awlock(m_axi_awlock),
|
||||
.m_axi_awcache(m_axi_awcache),
|
||||
.m_axi_awprot(m_axi_awprot),
|
||||
.m_axi_awvalid(m_axi_awvalid),
|
||||
.m_axi_awready(m_axi_awready),
|
||||
.m_axi_wdata(m_axi_wdata),
|
||||
.m_axi_wstrb(m_axi_wstrb),
|
||||
.m_axi_wlast(m_axi_wlast),
|
||||
.m_axi_wvalid(m_axi_wvalid),
|
||||
.m_axi_wready(m_axi_wready),
|
||||
.m_axi_bid(m_axi_bid),
|
||||
.m_axi_bresp(m_axi_bresp),
|
||||
.m_axi_bvalid(m_axi_bvalid),
|
||||
.m_axi_bready(m_axi_bready),
|
||||
.status_error_uncor(status_error_uncor)
|
||||
);
|
||||
|
||||
endmodule
|
403
fpga/lib/pcie/tb/test_pcie_us_axi_master_wr_64.py
Executable file
403
fpga/lib/pcie/tb/test_pcie_us_axi_master_wr_64.py
Executable file
@ -0,0 +1,403 @@
|
||||
#!/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 pcie
|
||||
import pcie_us
|
||||
import axi
|
||||
|
||||
module = 'pcie_us_axi_master_wr'
|
||||
testbench = 'test_%s_64' % module
|
||||
|
||||
srcs = []
|
||||
|
||||
srcs.append("../rtl/%s.v" % module)
|
||||
srcs.append("%s.v" % testbench)
|
||||
|
||||
src = ' '.join(srcs)
|
||||
|
||||
build_cmd = "iverilog -o %s.vvp %s" % (testbench, src)
|
||||
|
||||
def bench():
|
||||
|
||||
# Parameters
|
||||
AXIS_PCIE_DATA_WIDTH = 64
|
||||
AXIS_PCIE_KEEP_WIDTH = (AXIS_PCIE_DATA_WIDTH/32)
|
||||
AXI_DATA_WIDTH = AXIS_PCIE_DATA_WIDTH
|
||||
AXI_ADDR_WIDTH = 64
|
||||
AXI_STRB_WIDTH = (AXI_DATA_WIDTH/8)
|
||||
AXI_ID_WIDTH = 8
|
||||
AXI_MAX_BURST_LEN = 256
|
||||
|
||||
# Inputs
|
||||
clk = Signal(bool(0))
|
||||
rst = Signal(bool(0))
|
||||
current_test = Signal(intbv(0)[8:])
|
||||
|
||||
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_tvalid = Signal(bool(0))
|
||||
s_axis_cq_tlast = Signal(bool(0))
|
||||
s_axis_cq_tuser = Signal(intbv(0)[85:])
|
||||
m_axi_awready = Signal(bool(0))
|
||||
m_axi_wready = Signal(bool(0))
|
||||
m_axi_bid = Signal(intbv(0)[AXI_ID_WIDTH:])
|
||||
m_axi_bresp = Signal(intbv(0)[2:])
|
||||
m_axi_bvalid = Signal(bool(0))
|
||||
|
||||
# Outputs
|
||||
s_axis_cq_tready = Signal(bool(0))
|
||||
m_axi_awid = Signal(intbv(0)[AXI_ID_WIDTH:])
|
||||
m_axi_awaddr = Signal(intbv(0)[AXI_ADDR_WIDTH:])
|
||||
m_axi_awlen = Signal(intbv(0)[8:])
|
||||
m_axi_awsize = Signal(intbv(3)[3:])
|
||||
m_axi_awburst = Signal(intbv(1)[2:])
|
||||
m_axi_awlock = Signal(bool(0))
|
||||
m_axi_awcache = Signal(intbv(3)[4:])
|
||||
m_axi_awprot = Signal(intbv(2)[3:])
|
||||
m_axi_awvalid = Signal(bool(0))
|
||||
m_axi_wdata = Signal(intbv(0)[AXI_DATA_WIDTH:])
|
||||
m_axi_wstrb = Signal(intbv(0)[AXI_STRB_WIDTH:])
|
||||
m_axi_wlast = Signal(bool(0))
|
||||
m_axi_wvalid = Signal(bool(0))
|
||||
m_axi_bready = Signal(bool(1))
|
||||
status_error_uncor = Signal(bool(0))
|
||||
|
||||
# Clock and Reset Interface
|
||||
user_clk=Signal(bool(0))
|
||||
user_reset=Signal(bool(0))
|
||||
sys_clk=Signal(bool(0))
|
||||
sys_reset=Signal(bool(0))
|
||||
|
||||
# AXI4 RAM model
|
||||
axi_ram_inst = axi.AXIRam(2**16)
|
||||
|
||||
axi_ram_port0 = axi_ram_inst.create_port(
|
||||
user_clk,
|
||||
s_axi_awid=m_axi_awid,
|
||||
s_axi_awaddr=m_axi_awaddr,
|
||||
s_axi_awlen=m_axi_awlen,
|
||||
s_axi_awsize=m_axi_awsize,
|
||||
s_axi_awburst=m_axi_awburst,
|
||||
s_axi_awlock=m_axi_awlock,
|
||||
s_axi_awcache=m_axi_awcache,
|
||||
s_axi_awprot=m_axi_awprot,
|
||||
s_axi_awvalid=m_axi_awvalid,
|
||||
s_axi_awready=m_axi_awready,
|
||||
s_axi_wdata=m_axi_wdata,
|
||||
s_axi_wstrb=m_axi_wstrb,
|
||||
s_axi_wlast=m_axi_wlast,
|
||||
s_axi_wvalid=m_axi_wvalid,
|
||||
s_axi_wready=m_axi_wready,
|
||||
s_axi_bid=m_axi_bid,
|
||||
s_axi_bresp=m_axi_bresp,
|
||||
s_axi_bvalid=m_axi_bvalid,
|
||||
s_axi_bready=m_axi_bready,
|
||||
name='port0'
|
||||
)
|
||||
|
||||
# PCIe devices
|
||||
rc = pcie.RootComplex()
|
||||
|
||||
dev = pcie_us.UltrascalePCIe()
|
||||
|
||||
dev.pcie_generation = 3
|
||||
dev.pcie_link_width = 2
|
||||
dev.user_clock_frequency = 250e6
|
||||
|
||||
dev.functions[0].configure_bar(0, 16*1024*1024)
|
||||
|
||||
rc.make_port().connect(dev)
|
||||
|
||||
cq_pause = Signal(bool(0))
|
||||
cc_pause = Signal(bool(0))
|
||||
rq_pause = Signal(bool(0))
|
||||
rc_pause = Signal(bool(0))
|
||||
|
||||
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_count=pcie_cq_np_req_count,
|
||||
|
||||
# Completer Completion Interface
|
||||
s_axis_cc_tdata=Signal(intbv(0)[AXIS_PCIE_DATA_WIDTH:]),
|
||||
s_axis_cc_tuser=Signal(intbv(0)[33:]),
|
||||
s_axis_cc_tlast=Signal(bool(0)),
|
||||
s_axis_cc_tkeep=Signal(intbv(0)[AXIS_PCIE_KEEP_WIDTH:]),
|
||||
s_axis_cc_tvalid=Signal(bool(0)),
|
||||
s_axis_cc_tready=Signal(bool(0)),
|
||||
|
||||
# Requester reQuest Interface
|
||||
s_axis_rq_tdata=Signal(intbv(0)[AXIS_PCIE_DATA_WIDTH:]),
|
||||
s_axis_rq_tuser=Signal(intbv(0)[60:]),
|
||||
s_axis_rq_tlast=Signal(bool(0)),
|
||||
s_axis_rq_tkeep=Signal(intbv(0)[AXIS_PCIE_KEEP_WIDTH:]),
|
||||
s_axis_rq_tvalid=Signal(bool(0)),
|
||||
s_axis_rq_tready=Signal(bool(1)),
|
||||
# pcie_rq_seq_num=pcie_rq_seq_num,
|
||||
# pcie_rq_seq_num_vld=pcie_rq_seq_num_vld,
|
||||
# pcie_rq_tag=pcie_rq_tag,
|
||||
# pcie_rq_tag_av=pcie_rq_tag_av,
|
||||
# pcie_rq_tag_vld=pcie_rq_tag_vld,
|
||||
|
||||
# Requester Completion Interface
|
||||
m_axis_rc_tdata=Signal(intbv(0)[AXIS_PCIE_DATA_WIDTH:]),
|
||||
m_axis_rc_tuser=Signal(intbv(0)[75:]),
|
||||
m_axis_rc_tlast=Signal(bool(0)),
|
||||
m_axis_rc_tkeep=Signal(intbv(0)[AXIS_PCIE_KEEP_WIDTH:]),
|
||||
m_axis_rc_tvalid=Signal(bool(0)),
|
||||
m_axis_rc_tready=Signal(bool(0)),
|
||||
|
||||
# Transmit Flow Control Interface
|
||||
# pcie_tfc_nph_av=pcie_tfc_nph_av,
|
||||
# pcie_tfc_npd_av=pcie_tfc_npd_av,
|
||||
|
||||
# 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_per_function_update_done=cfg_per_function_update_done,
|
||||
# cfg_per_function_number=cfg_per_function_number,
|
||||
# cfg_per_function_output_request=cfg_per_function_output_request,
|
||||
# cfg_dsn=cfg_dsn,
|
||||
# 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=cfg_err_cor_in,
|
||||
# cfg_err_uncor_in=cfg_err_uncor_in,
|
||||
# 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,
|
||||
|
||||
# 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,
|
||||
|
||||
cq_pause=cq_pause,
|
||||
cc_pause=cc_pause,
|
||||
rq_pause=rq_pause,
|
||||
rc_pause=rc_pause
|
||||
)
|
||||
|
||||
# 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,
|
||||
s_axis_cq_tdata=s_axis_cq_tdata,
|
||||
s_axis_cq_tkeep=s_axis_cq_tkeep,
|
||||
s_axis_cq_tvalid=s_axis_cq_tvalid,
|
||||
s_axis_cq_tready=s_axis_cq_tready,
|
||||
s_axis_cq_tlast=s_axis_cq_tlast,
|
||||
s_axis_cq_tuser=s_axis_cq_tuser,
|
||||
m_axi_awid=m_axi_awid,
|
||||
m_axi_awaddr=m_axi_awaddr,
|
||||
m_axi_awlen=m_axi_awlen,
|
||||
m_axi_awsize=m_axi_awsize,
|
||||
m_axi_awburst=m_axi_awburst,
|
||||
m_axi_awlock=m_axi_awlock,
|
||||
m_axi_awcache=m_axi_awcache,
|
||||
m_axi_awprot=m_axi_awprot,
|
||||
m_axi_awvalid=m_axi_awvalid,
|
||||
m_axi_awready=m_axi_awready,
|
||||
m_axi_wdata=m_axi_wdata,
|
||||
m_axi_wstrb=m_axi_wstrb,
|
||||
m_axi_wlast=m_axi_wlast,
|
||||
m_axi_wvalid=m_axi_wvalid,
|
||||
m_axi_wready=m_axi_wready,
|
||||
m_axi_bid=m_axi_bid,
|
||||
m_axi_bresp=m_axi_bresp,
|
||||
m_axi_bvalid=m_axi_bvalid,
|
||||
m_axi_bready=m_axi_bready,
|
||||
status_error_uncor=status_error_uncor
|
||||
)
|
||||
|
||||
@always(delay(4))
|
||||
def clkgen():
|
||||
clk.next = not clk
|
||||
|
||||
@always_comb
|
||||
def clk_logic():
|
||||
sys_clk.next = clk
|
||||
sys_reset.next = not rst
|
||||
|
||||
status_error_uncor_asserted = Signal(bool(0))
|
||||
|
||||
@always(user_clk.posedge)
|
||||
def monitor():
|
||||
if (status_error_uncor):
|
||||
status_error_uncor_asserted.next = 1
|
||||
|
||||
cq_pause_toggle = Signal(bool(0))
|
||||
cc_pause_toggle = Signal(bool(0))
|
||||
rq_pause_toggle = Signal(bool(0))
|
||||
rc_pause_toggle = Signal(bool(0))
|
||||
|
||||
@instance
|
||||
def pause_toggle():
|
||||
while True:
|
||||
if (cq_pause_toggle or cc_pause_toggle or rq_pause_toggle or rc_pause_toggle):
|
||||
cq_pause.next = cq_pause_toggle
|
||||
cc_pause.next = cc_pause_toggle
|
||||
rq_pause.next = rq_pause_toggle
|
||||
rc_pause.next = rc_pause_toggle
|
||||
|
||||
yield user_clk.posedge
|
||||
yield user_clk.posedge
|
||||
yield user_clk.posedge
|
||||
|
||||
cq_pause.next = 0
|
||||
cc_pause.next = 0
|
||||
rq_pause.next = 0
|
||||
rc_pause.next = 0
|
||||
|
||||
yield user_clk.posedge
|
||||
|
||||
@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
|
||||
|
||||
yield user_clk.posedge
|
||||
print("test 1: enumeration")
|
||||
current_test.next = 1
|
||||
|
||||
yield rc.enumerate()
|
||||
|
||||
dev_bar0 = rc.tree[0][0].bar[0]
|
||||
|
||||
yield delay(100)
|
||||
|
||||
yield clk.posedge
|
||||
print("test 2: memory write")
|
||||
current_test.next = 2
|
||||
|
||||
pcie_addr = 0x00000000
|
||||
test_data = b'\x11\x22\x33\x44'
|
||||
|
||||
yield rc.mem_write(dev_bar0+pcie_addr, test_data)
|
||||
|
||||
yield delay(300)
|
||||
|
||||
data = axi_ram_inst.read_mem(pcie_addr, 32)
|
||||
for i in range(0, len(data), 16):
|
||||
print(" ".join(("{:02x}".format(c) for c in bytearray(data[i:i+16]))))
|
||||
|
||||
assert axi_ram_inst.read_mem(pcie_addr, len(test_data)) == test_data
|
||||
|
||||
assert not status_error_uncor_asserted
|
||||
|
||||
yield delay(100)
|
||||
|
||||
yield user_clk.posedge
|
||||
print("test 3: various writes")
|
||||
current_test.next = 3
|
||||
|
||||
for length in list(range(1,34))+[1024]:
|
||||
for pcie_offset in list(range(8,41))+list(range(4096-32,4096)):
|
||||
for pause in [False, True]:
|
||||
print("length %d, pcie_offset %d"% (length, pcie_offset))
|
||||
#pcie_addr = length * 0x100000000 + pcie_offset * 0x10000 + offset
|
||||
pcie_addr = pcie_offset
|
||||
test_data = bytearray([x%256 for x in range(length)])
|
||||
|
||||
axi_ram_inst.write_mem(pcie_addr & 0xffff80, b'\x55'*(len(test_data)+256))
|
||||
|
||||
cq_pause_toggle.next = pause
|
||||
|
||||
yield from rc.mem_write(dev_bar0+pcie_addr, test_data)
|
||||
|
||||
yield delay(length*4+120)
|
||||
|
||||
cq_pause_toggle.next = 0
|
||||
|
||||
data = axi_ram_inst.read_mem(pcie_addr&0xfffff0, 64)
|
||||
for i in range(0, len(data), 16):
|
||||
print(" ".join(("{:02x}".format(c) for c in bytearray(data[i:i+16]))))
|
||||
|
||||
assert axi_ram_inst.read_mem(pcie_addr-1, len(test_data)+2) == b'\x55'+test_data+b'\x55'
|
||||
|
||||
assert not status_error_uncor_asserted
|
||||
|
||||
yield delay(100)
|
||||
|
||||
yield clk.posedge
|
||||
print("test 4: bad request")
|
||||
current_test.next = 4
|
||||
|
||||
try:
|
||||
yield from rc.mem_read(dev_bar0, 4, 100)
|
||||
except:
|
||||
print("Caught timeout exception")
|
||||
pass
|
||||
else:
|
||||
assert False
|
||||
|
||||
assert status_error_uncor_asserted
|
||||
|
||||
status_error_uncor_asserted.next = False
|
||||
|
||||
yield delay(100)
|
||||
|
||||
raise StopSimulation
|
||||
|
||||
return instances()
|
||||
|
||||
def test_bench():
|
||||
sim = Simulation(bench())
|
||||
sim.run()
|
||||
|
||||
if __name__ == '__main__':
|
||||
print("Running test...")
|
||||
test_bench()
|
158
fpga/lib/pcie/tb/test_pcie_us_axi_master_wr_64.v
Normal file
158
fpga/lib/pcie/tb/test_pcie_us_axi_master_wr_64.v
Normal file
@ -0,0 +1,158 @@
|
||||
/*
|
||||
|
||||
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 pcie_us_axi_master_wr
|
||||
*/
|
||||
module test_pcie_us_axi_master_wr_64;
|
||||
|
||||
// Parameters
|
||||
parameter AXIS_PCIE_DATA_WIDTH = 64;
|
||||
parameter AXIS_PCIE_KEEP_WIDTH = (AXIS_PCIE_DATA_WIDTH/32);
|
||||
parameter AXI_DATA_WIDTH = AXIS_PCIE_DATA_WIDTH;
|
||||
parameter AXI_ADDR_WIDTH = 64;
|
||||
parameter AXI_STRB_WIDTH = (AXI_DATA_WIDTH/8);
|
||||
parameter AXI_ID_WIDTH = 8;
|
||||
parameter AXI_MAX_BURST_LEN = 256;
|
||||
|
||||
// Inputs
|
||||
reg clk = 0;
|
||||
reg rst = 0;
|
||||
reg [7:0] current_test = 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_tvalid = 0;
|
||||
reg s_axis_cq_tlast = 0;
|
||||
reg [84:0] s_axis_cq_tuser = 0;
|
||||
reg m_axi_awready = 0;
|
||||
reg m_axi_wready = 0;
|
||||
reg [AXI_ID_WIDTH-1:0] m_axi_bid = 0;
|
||||
reg [1:0] m_axi_bresp = 0;
|
||||
reg m_axi_bvalid = 0;
|
||||
|
||||
// Outputs
|
||||
wire s_axis_cq_tready;
|
||||
wire [AXI_ID_WIDTH-1:0] m_axi_awid;
|
||||
wire [AXI_ADDR_WIDTH-1:0] m_axi_awaddr;
|
||||
wire [7:0] m_axi_awlen;
|
||||
wire [2:0] m_axi_awsize;
|
||||
wire [1:0] m_axi_awburst;
|
||||
wire m_axi_awlock;
|
||||
wire [3:0] m_axi_awcache;
|
||||
wire [2:0] m_axi_awprot;
|
||||
wire m_axi_awvalid;
|
||||
wire [AXI_DATA_WIDTH-1:0] m_axi_wdata;
|
||||
wire [AXI_STRB_WIDTH-1:0] m_axi_wstrb;
|
||||
wire m_axi_wlast;
|
||||
wire m_axi_wvalid;
|
||||
wire m_axi_bready;
|
||||
wire status_error_uncor;
|
||||
|
||||
initial begin
|
||||
// myhdl integration
|
||||
$from_myhdl(
|
||||
clk,
|
||||
rst,
|
||||
current_test,
|
||||
s_axis_cq_tdata,
|
||||
s_axis_cq_tkeep,
|
||||
s_axis_cq_tvalid,
|
||||
s_axis_cq_tlast,
|
||||
s_axis_cq_tuser,
|
||||
m_axi_awready,
|
||||
m_axi_wready,
|
||||
m_axi_bid,
|
||||
m_axi_bresp,
|
||||
m_axi_bvalid
|
||||
);
|
||||
$to_myhdl(
|
||||
s_axis_cq_tready,
|
||||
m_axi_awid,
|
||||
m_axi_awaddr,
|
||||
m_axi_awlen,
|
||||
m_axi_awsize,
|
||||
m_axi_awburst,
|
||||
m_axi_awlock,
|
||||
m_axi_awcache,
|
||||
m_axi_awprot,
|
||||
m_axi_awvalid,
|
||||
m_axi_wdata,
|
||||
m_axi_wstrb,
|
||||
m_axi_wlast,
|
||||
m_axi_wvalid,
|
||||
m_axi_bready,
|
||||
status_error_uncor
|
||||
);
|
||||
|
||||
// dump file
|
||||
$dumpfile("test_pcie_us_axi_master_wr_64.lxt");
|
||||
$dumpvars(0, test_pcie_us_axi_master_wr_64);
|
||||
end
|
||||
|
||||
pcie_us_axi_master_wr #(
|
||||
.AXIS_PCIE_DATA_WIDTH(AXIS_PCIE_DATA_WIDTH),
|
||||
.AXIS_PCIE_KEEP_WIDTH(AXIS_PCIE_KEEP_WIDTH),
|
||||
.AXI_DATA_WIDTH(AXI_DATA_WIDTH),
|
||||
.AXI_ADDR_WIDTH(AXI_ADDR_WIDTH),
|
||||
.AXI_STRB_WIDTH(AXI_STRB_WIDTH),
|
||||
.AXI_ID_WIDTH(AXI_ID_WIDTH),
|
||||
.AXI_MAX_BURST_LEN(AXI_MAX_BURST_LEN)
|
||||
)
|
||||
UUT (
|
||||
.clk(clk),
|
||||
.rst(rst),
|
||||
.s_axis_cq_tdata(s_axis_cq_tdata),
|
||||
.s_axis_cq_tkeep(s_axis_cq_tkeep),
|
||||
.s_axis_cq_tvalid(s_axis_cq_tvalid),
|
||||
.s_axis_cq_tready(s_axis_cq_tready),
|
||||
.s_axis_cq_tlast(s_axis_cq_tlast),
|
||||
.s_axis_cq_tuser(s_axis_cq_tuser),
|
||||
.m_axi_awid(m_axi_awid),
|
||||
.m_axi_awaddr(m_axi_awaddr),
|
||||
.m_axi_awlen(m_axi_awlen),
|
||||
.m_axi_awsize(m_axi_awsize),
|
||||
.m_axi_awburst(m_axi_awburst),
|
||||
.m_axi_awlock(m_axi_awlock),
|
||||
.m_axi_awcache(m_axi_awcache),
|
||||
.m_axi_awprot(m_axi_awprot),
|
||||
.m_axi_awvalid(m_axi_awvalid),
|
||||
.m_axi_awready(m_axi_awready),
|
||||
.m_axi_wdata(m_axi_wdata),
|
||||
.m_axi_wstrb(m_axi_wstrb),
|
||||
.m_axi_wlast(m_axi_wlast),
|
||||
.m_axi_wvalid(m_axi_wvalid),
|
||||
.m_axi_wready(m_axi_wready),
|
||||
.m_axi_bid(m_axi_bid),
|
||||
.m_axi_bresp(m_axi_bresp),
|
||||
.m_axi_bvalid(m_axi_bvalid),
|
||||
.m_axi_bready(m_axi_bready),
|
||||
.status_error_uncor(status_error_uncor)
|
||||
);
|
||||
|
||||
endmodule
|
532
fpga/lib/pcie/tb/test_pcie_us_axil_master_128.py
Executable file
532
fpga/lib/pcie/tb/test_pcie_us_axil_master_128.py
Executable file
@ -0,0 +1,532 @@
|
||||
#!/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 axis_ep
|
||||
import axil
|
||||
import pcie_us
|
||||
|
||||
module = 'pcie_us_axil_master'
|
||||
testbench = 'test_%s_128' % module
|
||||
|
||||
srcs = []
|
||||
|
||||
srcs.append("../rtl/%s.v" % module)
|
||||
srcs.append("%s.v" % testbench)
|
||||
|
||||
src = ' '.join(srcs)
|
||||
|
||||
build_cmd = "iverilog -o %s.vvp %s" % (testbench, src)
|
||||
|
||||
def bench():
|
||||
|
||||
# Parameters
|
||||
AXIS_PCIE_DATA_WIDTH = 128
|
||||
AXIS_PCIE_KEEP_WIDTH = (AXIS_PCIE_DATA_WIDTH/32)
|
||||
AXI_DATA_WIDTH = 32
|
||||
AXI_ADDR_WIDTH = 64
|
||||
AXI_STRB_WIDTH = (AXI_DATA_WIDTH/8)
|
||||
ENABLE_PARITY = 0
|
||||
|
||||
# Inputs
|
||||
clk = Signal(bool(0))
|
||||
rst = Signal(bool(0))
|
||||
current_test = Signal(intbv(0)[8:])
|
||||
|
||||
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_tvalid = Signal(bool(0))
|
||||
s_axis_cq_tlast = Signal(bool(0))
|
||||
s_axis_cq_tuser = Signal(intbv(0)[85:])
|
||||
m_axis_cc_tready = Signal(bool(0))
|
||||
m_axil_awready = Signal(bool(0))
|
||||
m_axil_wready = Signal(bool(0))
|
||||
m_axil_bresp = Signal(intbv(0)[2:])
|
||||
m_axil_bvalid = Signal(bool(0))
|
||||
m_axil_arready = Signal(bool(0))
|
||||
m_axil_rdata = Signal(intbv(0)[AXI_DATA_WIDTH:])
|
||||
m_axil_rresp = Signal(intbv(0)[2:])
|
||||
m_axil_rvalid = Signal(bool(0))
|
||||
completer_id = Signal(intbv(0)[16:])
|
||||
completer_id_enable = Signal(bool(0))
|
||||
|
||||
# Outputs
|
||||
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_tvalid = Signal(bool(0))
|
||||
m_axis_cc_tlast = Signal(bool(0))
|
||||
m_axis_cc_tuser = Signal(intbv(0)[33:])
|
||||
m_axil_awaddr = Signal(intbv(0)[AXI_ADDR_WIDTH:])
|
||||
m_axil_awprot = Signal(intbv(0)[3:])
|
||||
m_axil_awvalid = Signal(bool(0))
|
||||
m_axil_wdata = Signal(intbv(0)[AXI_DATA_WIDTH:])
|
||||
m_axil_wstrb = Signal(intbv(0)[AXI_STRB_WIDTH:])
|
||||
m_axil_wvalid = Signal(bool(0))
|
||||
m_axil_bready = Signal(bool(0))
|
||||
m_axil_araddr = Signal(intbv(0)[AXI_ADDR_WIDTH:])
|
||||
m_axil_arprot = Signal(intbv(2)[3:])
|
||||
m_axil_arvalid = Signal(bool(0))
|
||||
m_axil_rready = Signal(bool(0))
|
||||
status_error_cor = Signal(bool(0))
|
||||
status_error_uncor = Signal(bool(0))
|
||||
|
||||
# sources and sinks
|
||||
cq_source = axis_ep.AXIStreamSource()
|
||||
|
||||
cq_source_logic = cq_source.create_logic(
|
||||
clk,
|
||||
rst,
|
||||
tdata=s_axis_cq_tdata,
|
||||
tkeep=s_axis_cq_tkeep,
|
||||
tvalid=s_axis_cq_tvalid,
|
||||
tready=s_axis_cq_tready,
|
||||
tlast=s_axis_cq_tlast,
|
||||
tuser=s_axis_cq_tuser,
|
||||
name='cq_source'
|
||||
)
|
||||
|
||||
cc_sink = axis_ep.AXIStreamSink()
|
||||
|
||||
cc_sink_logic = cc_sink.create_logic(
|
||||
clk,
|
||||
rst,
|
||||
tdata=m_axis_cc_tdata,
|
||||
tkeep=m_axis_cc_tkeep,
|
||||
tvalid=m_axis_cc_tvalid,
|
||||
tready=m_axis_cc_tready,
|
||||
tlast=m_axis_cc_tlast,
|
||||
tuser=m_axis_cc_tuser,
|
||||
name='cc_sink'
|
||||
)
|
||||
|
||||
# AXI4-Lite RAM model
|
||||
axil_ram_inst = axil.AXILiteRam(2**16)
|
||||
|
||||
axil_ram_port0 = axil_ram_inst.create_port(
|
||||
clk,
|
||||
s_axil_awaddr=m_axil_awaddr,
|
||||
s_axil_awprot=m_axil_awprot,
|
||||
s_axil_awvalid=m_axil_awvalid,
|
||||
s_axil_awready=m_axil_awready,
|
||||
s_axil_wdata=m_axil_wdata,
|
||||
s_axil_wstrb=m_axil_wstrb,
|
||||
s_axil_wvalid=m_axil_wvalid,
|
||||
s_axil_wready=m_axil_wready,
|
||||
s_axil_bresp=m_axil_bresp,
|
||||
s_axil_bvalid=m_axil_bvalid,
|
||||
s_axil_bready=m_axil_bready,
|
||||
s_axil_araddr=m_axil_araddr,
|
||||
s_axil_arprot=m_axil_arprot,
|
||||
s_axil_arvalid=m_axil_arvalid,
|
||||
s_axil_arready=m_axil_arready,
|
||||
s_axil_rdata=m_axil_rdata,
|
||||
s_axil_rresp=m_axil_rresp,
|
||||
s_axil_rvalid=m_axil_rvalid,
|
||||
s_axil_rready=m_axil_rready,
|
||||
latency=1,
|
||||
name='ram'
|
||||
)
|
||||
|
||||
# DUT
|
||||
if os.system(build_cmd):
|
||||
raise Exception("Error running build command")
|
||||
|
||||
dut = Cosimulation(
|
||||
"vvp -m myhdl %s.vvp -lxt2" % testbench,
|
||||
clk=clk,
|
||||
rst=rst,
|
||||
current_test=current_test,
|
||||
|
||||
s_axis_cq_tdata=s_axis_cq_tdata,
|
||||
s_axis_cq_tkeep=s_axis_cq_tkeep,
|
||||
s_axis_cq_tvalid=s_axis_cq_tvalid,
|
||||
s_axis_cq_tready=s_axis_cq_tready,
|
||||
s_axis_cq_tlast=s_axis_cq_tlast,
|
||||
s_axis_cq_tuser=s_axis_cq_tuser,
|
||||
|
||||
m_axis_cc_tdata=m_axis_cc_tdata,
|
||||
m_axis_cc_tkeep=m_axis_cc_tkeep,
|
||||
m_axis_cc_tvalid=m_axis_cc_tvalid,
|
||||
m_axis_cc_tready=m_axis_cc_tready,
|
||||
m_axis_cc_tlast=m_axis_cc_tlast,
|
||||
m_axis_cc_tuser=m_axis_cc_tuser,
|
||||
|
||||
m_axil_awaddr=m_axil_awaddr,
|
||||
m_axil_awprot=m_axil_awprot,
|
||||
m_axil_awvalid=m_axil_awvalid,
|
||||
m_axil_awready=m_axil_awready,
|
||||
m_axil_wdata=m_axil_wdata,
|
||||
m_axil_wstrb=m_axil_wstrb,
|
||||
m_axil_wvalid=m_axil_wvalid,
|
||||
m_axil_wready=m_axil_wready,
|
||||
m_axil_bresp=m_axil_bresp,
|
||||
m_axil_bvalid=m_axil_bvalid,
|
||||
m_axil_bready=m_axil_bready,
|
||||
m_axil_araddr=m_axil_araddr,
|
||||
m_axil_arprot=m_axil_arprot,
|
||||
m_axil_arvalid=m_axil_arvalid,
|
||||
m_axil_arready=m_axil_arready,
|
||||
m_axil_rdata=m_axil_rdata,
|
||||
m_axil_rresp=m_axil_rresp,
|
||||
m_axil_rvalid=m_axil_rvalid,
|
||||
m_axil_rready=m_axil_rready,
|
||||
|
||||
completer_id=completer_id,
|
||||
completer_id_enable=completer_id_enable,
|
||||
|
||||
status_error_cor=status_error_cor,
|
||||
status_error_uncor=status_error_uncor
|
||||
)
|
||||
|
||||
@always(delay(4))
|
||||
def clkgen():
|
||||
clk.next = not clk
|
||||
|
||||
status_error_cor_asserted = Signal(bool(0))
|
||||
status_error_uncor_asserted = Signal(bool(0))
|
||||
|
||||
@always(clk.posedge)
|
||||
def monitor():
|
||||
if (status_error_cor):
|
||||
status_error_cor_asserted.next = 1
|
||||
if (status_error_uncor):
|
||||
status_error_uncor_asserted.next = 1
|
||||
|
||||
@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
|
||||
|
||||
cur_tag = 1
|
||||
|
||||
completer_id.next = int(pcie_us.PcieId(4, 5, 6))
|
||||
|
||||
yield clk.posedge
|
||||
print("test 1: baseline")
|
||||
current_test.next = 1
|
||||
|
||||
data = axil_ram_inst.read_mem(0, 32)
|
||||
for i in range(0, len(data), 16):
|
||||
print(" ".join(("{:02x}".format(c) for c in bytearray(data[i:i+16]))))
|
||||
|
||||
yield delay(100)
|
||||
|
||||
yield clk.posedge
|
||||
print("test 2: memory write")
|
||||
current_test.next = 2
|
||||
|
||||
tlp = pcie_us.TLP_us()
|
||||
tlp.fmt_type = pcie_us.TLP_MEM_WRITE
|
||||
tlp.requester_id = pcie_us.PcieId(1, 2, 3)
|
||||
tlp.tag = cur_tag
|
||||
tlp.tc = 0
|
||||
tlp.set_be_data(0x0000, b'\x11\x22\x33\x44')
|
||||
tlp.address = 0x0000
|
||||
|
||||
cq_source.send(tlp.pack_us_cq(AXIS_PCIE_DATA_WIDTH))
|
||||
|
||||
yield delay(100)
|
||||
|
||||
data = axil_ram_inst.read_mem(0, 32)
|
||||
for i in range(0, len(data), 16):
|
||||
print(" ".join(("{:02x}".format(c) for c in bytearray(data[i:i+16]))))
|
||||
|
||||
assert axil_ram_inst.read_mem(0, 4) == b'\x11\x22\x33\x44'
|
||||
|
||||
assert not status_error_cor_asserted
|
||||
assert not status_error_uncor_asserted
|
||||
|
||||
cur_tag = (cur_tag + 1) % 32
|
||||
|
||||
yield delay(100)
|
||||
|
||||
yield clk.posedge
|
||||
print("test 3: IO write")
|
||||
current_test.next = 3
|
||||
|
||||
tlp = pcie_us.TLP_us()
|
||||
tlp.fmt_type = pcie_us.TLP_IO_WRITE
|
||||
tlp.requester_id = pcie_us.PcieId(1, 2, 3)
|
||||
tlp.tag = cur_tag
|
||||
tlp.tc = 0
|
||||
tlp.set_be_data(0x0000, b'\x11\x22\x33\x44')
|
||||
tlp.address = 0x0000
|
||||
|
||||
cq_source.send(tlp.pack_us_cq(AXIS_PCIE_DATA_WIDTH))
|
||||
|
||||
yield cc_sink.wait(500)
|
||||
pkt = cc_sink.recv()
|
||||
|
||||
rx_tlp = pcie_us.TLP_us().unpack_us_cc(pkt, AXIS_PCIE_DATA_WIDTH)
|
||||
|
||||
print(rx_tlp)
|
||||
|
||||
assert rx_tlp.status == pcie_us.CPL_STATUS_SC
|
||||
assert rx_tlp.tag == cur_tag
|
||||
assert rx_tlp.completer_id == pcie_us.PcieId(4, 5, 6)
|
||||
|
||||
data = axil_ram_inst.read_mem(0, 32)
|
||||
for i in range(0, len(data), 16):
|
||||
print(" ".join(("{:02x}".format(c) for c in bytearray(data[i:i+16]))))
|
||||
|
||||
assert axil_ram_inst.read_mem(0, 4) == b'\x11\x22\x33\x44'
|
||||
|
||||
assert not status_error_cor_asserted
|
||||
assert not status_error_uncor_asserted
|
||||
|
||||
cur_tag = (cur_tag + 1) % 32
|
||||
|
||||
yield delay(100)
|
||||
|
||||
yield clk.posedge
|
||||
print("test 4: memory read")
|
||||
current_test.next = 4
|
||||
|
||||
tlp = pcie_us.TLP_us()
|
||||
tlp.fmt_type = pcie_us.TLP_MEM_READ
|
||||
tlp.requester_id = pcie_us.PcieId(1, 2, 3)
|
||||
tlp.tag = cur_tag
|
||||
tlp.tc = 0
|
||||
tlp.length = 1
|
||||
tlp.set_be(0x0000, 4)
|
||||
tlp.address = 0x0000
|
||||
|
||||
cq_source.send(tlp.pack_us_cq(AXIS_PCIE_DATA_WIDTH))
|
||||
|
||||
yield cc_sink.wait(500)
|
||||
pkt = cc_sink.recv()
|
||||
|
||||
rx_tlp = pcie_us.TLP_us().unpack_us_cc(pkt, AXIS_PCIE_DATA_WIDTH)
|
||||
|
||||
print(rx_tlp)
|
||||
|
||||
data = rx_tlp.get_data()
|
||||
|
||||
print(data)
|
||||
|
||||
assert data == b'\x11\x22\x33\x44'
|
||||
assert rx_tlp.status == pcie_us.CPL_STATUS_SC
|
||||
assert rx_tlp.tag == cur_tag
|
||||
assert rx_tlp.completer_id == pcie_us.PcieId(4, 5, 6)
|
||||
|
||||
assert not status_error_cor_asserted
|
||||
assert not status_error_uncor_asserted
|
||||
|
||||
cur_tag = (cur_tag + 1) % 32
|
||||
|
||||
yield delay(100)
|
||||
|
||||
yield clk.posedge
|
||||
print("test 5: IO read")
|
||||
current_test.next = 5
|
||||
|
||||
tlp = pcie_us.TLP_us()
|
||||
tlp.fmt_type = pcie_us.TLP_IO_READ
|
||||
tlp.requester_id = pcie_us.PcieId(1, 2, 3)
|
||||
tlp.tag = cur_tag
|
||||
tlp.tc = 0
|
||||
tlp.length = 1
|
||||
tlp.set_be(0x0000, 4)
|
||||
tlp.address = 0x0000
|
||||
|
||||
cq_source.send(tlp.pack_us_cq(AXIS_PCIE_DATA_WIDTH))
|
||||
|
||||
yield cc_sink.wait(500)
|
||||
pkt = cc_sink.recv()
|
||||
|
||||
rx_tlp = pcie_us.TLP_us().unpack_us_cc(pkt, AXIS_PCIE_DATA_WIDTH)
|
||||
|
||||
print(rx_tlp)
|
||||
|
||||
data = rx_tlp.get_data()
|
||||
|
||||
print(data)
|
||||
|
||||
assert data == b'\x11\x22\x33\x44'
|
||||
assert rx_tlp.status == pcie_us.CPL_STATUS_SC
|
||||
assert rx_tlp.tag == cur_tag
|
||||
assert rx_tlp.completer_id == pcie_us.PcieId(4, 5, 6)
|
||||
|
||||
assert not status_error_cor_asserted
|
||||
assert not status_error_uncor_asserted
|
||||
|
||||
cur_tag = (cur_tag + 1) % 32
|
||||
|
||||
yield delay(100)
|
||||
|
||||
yield clk.posedge
|
||||
print("test 6: various writes")
|
||||
current_test.next = 6
|
||||
|
||||
for length in range(1,5):
|
||||
for offset in range(4,8-length+1):
|
||||
axil_ram_inst.write_mem(256*(16*offset+length), b'\xAA'*32)
|
||||
|
||||
tlp = pcie_us.TLP_us()
|
||||
tlp.fmt_type = pcie_us.TLP_MEM_WRITE
|
||||
tlp.requester_id = pcie_us.PcieId(1, 2, 3)
|
||||
tlp.tag = cur_tag
|
||||
tlp.tc = 0
|
||||
tlp.set_be_data(256*(16*offset+length)+offset, b'\x11\x22\x33\x44'[0:length])
|
||||
tlp.address = 256*(16*offset+length)+offset
|
||||
|
||||
cq_source.send(tlp.pack_us_cq(AXIS_PCIE_DATA_WIDTH))
|
||||
|
||||
yield delay(100)
|
||||
|
||||
data = axil_ram_inst.read_mem(256*(16*offset+length), 32)
|
||||
for i in range(0, len(data), 16):
|
||||
print(" ".join(("{:02x}".format(c) for c in bytearray(data[i:i+16]))))
|
||||
|
||||
assert axil_ram_inst.read_mem(256*(16*offset+length)+offset, length) == b'\x11\x22\x33\x44'[0:length]
|
||||
assert axil_ram_inst.read_mem(256*(16*offset+length)+offset-1, 1) == b'\xAA'
|
||||
assert axil_ram_inst.read_mem(256*(16*offset+length)+offset+length, 1) == b'\xAA'
|
||||
|
||||
assert not status_error_cor_asserted
|
||||
assert not status_error_uncor_asserted
|
||||
|
||||
cur_tag = (cur_tag + 1) % 32
|
||||
|
||||
yield delay(100)
|
||||
|
||||
yield clk.posedge
|
||||
print("test 7: various reads")
|
||||
current_test.next = 7
|
||||
|
||||
for length in range(1,5):
|
||||
for offset in range(4,8-length+1):
|
||||
tlp = pcie_us.TLP_us()
|
||||
tlp.fmt_type = pcie_us.TLP_MEM_READ
|
||||
tlp.requester_id = pcie_us.PcieId(1, 2, 3)
|
||||
tlp.tag = cur_tag
|
||||
tlp.tc = 0
|
||||
tlp.length = 1
|
||||
tlp.set_be(256*(16*offset+length)+offset, length)
|
||||
tlp.address = 256*(16*offset+length)+offset
|
||||
|
||||
cq_source.send(tlp.pack_us_cq(AXIS_PCIE_DATA_WIDTH))
|
||||
|
||||
yield cc_sink.wait(500)
|
||||
pkt = cc_sink.recv()
|
||||
|
||||
rx_tlp = pcie_us.TLP_us().unpack_us_cc(pkt, AXIS_PCIE_DATA_WIDTH)
|
||||
|
||||
print(rx_tlp)
|
||||
|
||||
data = rx_tlp.get_data()
|
||||
|
||||
print(data)
|
||||
|
||||
assert data == b'\xAA'*(offset-4)+b'\x11\x22\x33\x44'[0:length]+b'\xAA'*(8-offset-length)
|
||||
assert rx_tlp.status == pcie_us.CPL_STATUS_SC
|
||||
assert rx_tlp.tag == cur_tag
|
||||
assert rx_tlp.completer_id == pcie_us.PcieId(4, 5, 6)
|
||||
|
||||
assert not status_error_cor_asserted
|
||||
assert not status_error_uncor_asserted
|
||||
|
||||
cur_tag = (cur_tag + 1) % 32
|
||||
|
||||
yield delay(100)
|
||||
|
||||
yield clk.posedge
|
||||
print("test 8: bad memory write")
|
||||
current_test.next = 8
|
||||
|
||||
tlp = pcie_us.TLP_us()
|
||||
tlp.fmt_type = pcie_us.TLP_MEM_WRITE
|
||||
tlp.requester_id = pcie_us.PcieId(1, 2, 3)
|
||||
tlp.tag = cur_tag
|
||||
tlp.tc = 0
|
||||
tlp.set_be_data(0x0000, bytearray(range(64)))
|
||||
tlp.address = 0x0000
|
||||
|
||||
cq_source.send(tlp.pack_us_cq(AXIS_PCIE_DATA_WIDTH))
|
||||
|
||||
yield delay(100)
|
||||
|
||||
assert not status_error_cor_asserted
|
||||
assert status_error_uncor_asserted
|
||||
|
||||
status_error_uncor_asserted.next = 0
|
||||
|
||||
cur_tag = (cur_tag + 1) % 32
|
||||
|
||||
yield delay(100)
|
||||
|
||||
yield clk.posedge
|
||||
print("test 9: bad memory read")
|
||||
current_test.next = 9
|
||||
|
||||
tlp = pcie_us.TLP_us()
|
||||
tlp.fmt_type = pcie_us.TLP_MEM_READ
|
||||
tlp.requester_id = pcie_us.PcieId(1, 2, 3)
|
||||
tlp.tag = cur_tag
|
||||
tlp.tc = 0
|
||||
tlp.set_be(0x0000, 64)
|
||||
tlp.address = 0x0000
|
||||
|
||||
cq_source.send(tlp.pack_us_cq(AXIS_PCIE_DATA_WIDTH))
|
||||
|
||||
yield cc_sink.wait(500)
|
||||
pkt = cc_sink.recv()
|
||||
|
||||
rx_tlp = pcie_us.TLP_us().unpack_us_cc(pkt, AXIS_PCIE_DATA_WIDTH)
|
||||
|
||||
print(rx_tlp)
|
||||
|
||||
assert rx_tlp.status == pcie_us.CPL_STATUS_CA
|
||||
assert rx_tlp.tag == cur_tag
|
||||
assert rx_tlp.completer_id == pcie_us.PcieId(4, 5, 6)
|
||||
|
||||
assert status_error_cor_asserted
|
||||
assert not status_error_uncor_asserted
|
||||
|
||||
cur_tag = (cur_tag + 1) % 32
|
||||
|
||||
yield delay(100)
|
||||
|
||||
raise StopSimulation
|
||||
|
||||
return instances()
|
||||
|
||||
def test_bench():
|
||||
sim = Simulation(bench())
|
||||
sim.run()
|
||||
|
||||
if __name__ == '__main__':
|
||||
print("Running test...")
|
||||
test_bench()
|
183
fpga/lib/pcie/tb/test_pcie_us_axil_master_128.v
Normal file
183
fpga/lib/pcie/tb/test_pcie_us_axil_master_128.v
Normal file
@ -0,0 +1,183 @@
|
||||
/*
|
||||
|
||||
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 pcie_us_axil_master
|
||||
*/
|
||||
module test_pcie_us_axil_master_128;
|
||||
|
||||
// Parameters
|
||||
parameter AXIS_PCIE_DATA_WIDTH = 128;
|
||||
parameter AXIS_PCIE_KEEP_WIDTH = (AXIS_PCIE_DATA_WIDTH/32);
|
||||
parameter AXI_DATA_WIDTH = 32;
|
||||
parameter AXI_ADDR_WIDTH = 64;
|
||||
parameter AXI_STRB_WIDTH = (AXI_DATA_WIDTH/8);
|
||||
parameter ENABLE_PARITY = 0;
|
||||
|
||||
// Inputs
|
||||
reg clk = 0;
|
||||
reg rst = 0;
|
||||
reg [7:0] current_test = 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_tvalid = 0;
|
||||
reg s_axis_cq_tlast = 0;
|
||||
reg [84:0] s_axis_cq_tuser = 0;
|
||||
reg m_axis_cc_tready = 0;
|
||||
reg m_axil_awready = 0;
|
||||
reg m_axil_wready = 0;
|
||||
reg [1:0] m_axil_bresp = 0;
|
||||
reg m_axil_bvalid = 0;
|
||||
reg m_axil_arready = 0;
|
||||
reg [AXI_DATA_WIDTH-1:0] m_axil_rdata = 0;
|
||||
reg [1:0] m_axil_rresp = 0;
|
||||
reg m_axil_rvalid = 0;
|
||||
reg [15:0] completer_id = 0;
|
||||
reg completer_id_enable = 0;
|
||||
|
||||
// Outputs
|
||||
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_tvalid;
|
||||
wire m_axis_cc_tlast;
|
||||
wire [32:0] m_axis_cc_tuser;
|
||||
wire [AXI_ADDR_WIDTH-1:0] m_axil_awaddr;
|
||||
wire [2:0] m_axil_awprot;
|
||||
wire m_axil_awvalid;
|
||||
wire [AXI_DATA_WIDTH-1:0] m_axil_wdata;
|
||||
wire [AXI_STRB_WIDTH-1:0] m_axil_wstrb;
|
||||
wire m_axil_wvalid;
|
||||
wire m_axil_bready;
|
||||
wire [AXI_ADDR_WIDTH-1:0] m_axil_araddr;
|
||||
wire [2:0] m_axil_arprot;
|
||||
wire m_axil_arvalid;
|
||||
wire m_axil_rready;
|
||||
wire status_error_cor;
|
||||
wire status_error_uncor;
|
||||
|
||||
initial begin
|
||||
// myhdl integration
|
||||
$from_myhdl(
|
||||
clk,
|
||||
rst,
|
||||
current_test,
|
||||
s_axis_cq_tdata,
|
||||
s_axis_cq_tkeep,
|
||||
s_axis_cq_tvalid,
|
||||
s_axis_cq_tlast,
|
||||
s_axis_cq_tuser,
|
||||
m_axis_cc_tready,
|
||||
m_axil_awready,
|
||||
m_axil_wready,
|
||||
m_axil_bresp,
|
||||
m_axil_bvalid,
|
||||
m_axil_arready,
|
||||
m_axil_rdata,
|
||||
m_axil_rresp,
|
||||
m_axil_rvalid,
|
||||
completer_id,
|
||||
completer_id_enable
|
||||
);
|
||||
$to_myhdl(
|
||||
s_axis_cq_tready,
|
||||
m_axis_cc_tdata,
|
||||
m_axis_cc_tkeep,
|
||||
m_axis_cc_tvalid,
|
||||
m_axis_cc_tlast,
|
||||
m_axis_cc_tuser,
|
||||
m_axil_awaddr,
|
||||
m_axil_awprot,
|
||||
m_axil_awvalid,
|
||||
m_axil_wdata,
|
||||
m_axil_wstrb,
|
||||
m_axil_wvalid,
|
||||
m_axil_bready,
|
||||
m_axil_araddr,
|
||||
m_axil_arprot,
|
||||
m_axil_arvalid,
|
||||
m_axil_rready,
|
||||
status_error_cor,
|
||||
status_error_uncor
|
||||
);
|
||||
|
||||
// dump file
|
||||
$dumpfile("test_pcie_us_axil_master_128.lxt");
|
||||
$dumpvars(0, test_pcie_us_axil_master_128);
|
||||
end
|
||||
|
||||
pcie_us_axil_master #(
|
||||
.AXIS_PCIE_DATA_WIDTH(AXIS_PCIE_DATA_WIDTH),
|
||||
.AXIS_PCIE_KEEP_WIDTH(AXIS_PCIE_KEEP_WIDTH),
|
||||
.AXI_DATA_WIDTH(AXI_DATA_WIDTH),
|
||||
.AXI_ADDR_WIDTH(AXI_ADDR_WIDTH),
|
||||
.AXI_STRB_WIDTH(AXI_STRB_WIDTH),
|
||||
.ENABLE_PARITY(ENABLE_PARITY)
|
||||
)
|
||||
UUT (
|
||||
.clk(clk),
|
||||
.rst(rst),
|
||||
.s_axis_cq_tdata(s_axis_cq_tdata),
|
||||
.s_axis_cq_tkeep(s_axis_cq_tkeep),
|
||||
.s_axis_cq_tvalid(s_axis_cq_tvalid),
|
||||
.s_axis_cq_tready(s_axis_cq_tready),
|
||||
.s_axis_cq_tlast(s_axis_cq_tlast),
|
||||
.s_axis_cq_tuser(s_axis_cq_tuser),
|
||||
.m_axis_cc_tdata(m_axis_cc_tdata),
|
||||
.m_axis_cc_tkeep(m_axis_cc_tkeep),
|
||||
.m_axis_cc_tvalid(m_axis_cc_tvalid),
|
||||
.m_axis_cc_tready(m_axis_cc_tready),
|
||||
.m_axis_cc_tlast(m_axis_cc_tlast),
|
||||
.m_axis_cc_tuser(m_axis_cc_tuser),
|
||||
.m_axil_awaddr(m_axil_awaddr),
|
||||
.m_axil_awprot(m_axil_awprot),
|
||||
.m_axil_awvalid(m_axil_awvalid),
|
||||
.m_axil_awready(m_axil_awready),
|
||||
.m_axil_wdata(m_axil_wdata),
|
||||
.m_axil_wstrb(m_axil_wstrb),
|
||||
.m_axil_wvalid(m_axil_wvalid),
|
||||
.m_axil_wready(m_axil_wready),
|
||||
.m_axil_bresp(m_axil_bresp),
|
||||
.m_axil_bvalid(m_axil_bvalid),
|
||||
.m_axil_bready(m_axil_bready),
|
||||
.m_axil_araddr(m_axil_araddr),
|
||||
.m_axil_arprot(m_axil_arprot),
|
||||
.m_axil_arvalid(m_axil_arvalid),
|
||||
.m_axil_arready(m_axil_arready),
|
||||
.m_axil_rdata(m_axil_rdata),
|
||||
.m_axil_rresp(m_axil_rresp),
|
||||
.m_axil_rvalid(m_axil_rvalid),
|
||||
.m_axil_rready(m_axil_rready),
|
||||
.completer_id(completer_id),
|
||||
.completer_id_enable(completer_id_enable),
|
||||
.status_error_cor(status_error_cor),
|
||||
.status_error_uncor(status_error_uncor)
|
||||
);
|
||||
|
||||
endmodule
|
532
fpga/lib/pcie/tb/test_pcie_us_axil_master_256.py
Executable file
532
fpga/lib/pcie/tb/test_pcie_us_axil_master_256.py
Executable file
@ -0,0 +1,532 @@
|
||||
#!/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 axis_ep
|
||||
import axil
|
||||
import pcie_us
|
||||
|
||||
module = 'pcie_us_axil_master'
|
||||
testbench = 'test_%s_256' % module
|
||||
|
||||
srcs = []
|
||||
|
||||
srcs.append("../rtl/%s.v" % module)
|
||||
srcs.append("%s.v" % testbench)
|
||||
|
||||
src = ' '.join(srcs)
|
||||
|
||||
build_cmd = "iverilog -o %s.vvp %s" % (testbench, src)
|
||||
|
||||
def bench():
|
||||
|
||||
# Parameters
|
||||
AXIS_PCIE_DATA_WIDTH = 256
|
||||
AXIS_PCIE_KEEP_WIDTH = (AXIS_PCIE_DATA_WIDTH/32)
|
||||
AXI_DATA_WIDTH = 32
|
||||
AXI_ADDR_WIDTH = 64
|
||||
AXI_STRB_WIDTH = (AXI_DATA_WIDTH/8)
|
||||
ENABLE_PARITY = 0
|
||||
|
||||
# Inputs
|
||||
clk = Signal(bool(0))
|
||||
rst = Signal(bool(0))
|
||||
current_test = Signal(intbv(0)[8:])
|
||||
|
||||
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_tvalid = Signal(bool(0))
|
||||
s_axis_cq_tlast = Signal(bool(0))
|
||||
s_axis_cq_tuser = Signal(intbv(0)[85:])
|
||||
m_axis_cc_tready = Signal(bool(0))
|
||||
m_axil_awready = Signal(bool(0))
|
||||
m_axil_wready = Signal(bool(0))
|
||||
m_axil_bresp = Signal(intbv(0)[2:])
|
||||
m_axil_bvalid = Signal(bool(0))
|
||||
m_axil_arready = Signal(bool(0))
|
||||
m_axil_rdata = Signal(intbv(0)[AXI_DATA_WIDTH:])
|
||||
m_axil_rresp = Signal(intbv(0)[2:])
|
||||
m_axil_rvalid = Signal(bool(0))
|
||||
completer_id = Signal(intbv(0)[16:])
|
||||
completer_id_enable = Signal(bool(0))
|
||||
|
||||
# Outputs
|
||||
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_tvalid = Signal(bool(0))
|
||||
m_axis_cc_tlast = Signal(bool(0))
|
||||
m_axis_cc_tuser = Signal(intbv(0)[33:])
|
||||
m_axil_awaddr = Signal(intbv(0)[AXI_ADDR_WIDTH:])
|
||||
m_axil_awprot = Signal(intbv(0)[3:])
|
||||
m_axil_awvalid = Signal(bool(0))
|
||||
m_axil_wdata = Signal(intbv(0)[AXI_DATA_WIDTH:])
|
||||
m_axil_wstrb = Signal(intbv(0)[AXI_STRB_WIDTH:])
|
||||
m_axil_wvalid = Signal(bool(0))
|
||||
m_axil_bready = Signal(bool(0))
|
||||
m_axil_araddr = Signal(intbv(0)[AXI_ADDR_WIDTH:])
|
||||
m_axil_arprot = Signal(intbv(2)[3:])
|
||||
m_axil_arvalid = Signal(bool(0))
|
||||
m_axil_rready = Signal(bool(0))
|
||||
status_error_cor = Signal(bool(0))
|
||||
status_error_uncor = Signal(bool(0))
|
||||
|
||||
# sources and sinks
|
||||
cq_source = axis_ep.AXIStreamSource()
|
||||
|
||||
cq_source_logic = cq_source.create_logic(
|
||||
clk,
|
||||
rst,
|
||||
tdata=s_axis_cq_tdata,
|
||||
tkeep=s_axis_cq_tkeep,
|
||||
tvalid=s_axis_cq_tvalid,
|
||||
tready=s_axis_cq_tready,
|
||||
tlast=s_axis_cq_tlast,
|
||||
tuser=s_axis_cq_tuser,
|
||||
name='cq_source'
|
||||
)
|
||||
|
||||
cc_sink = axis_ep.AXIStreamSink()
|
||||
|
||||
cc_sink_logic = cc_sink.create_logic(
|
||||
clk,
|
||||
rst,
|
||||
tdata=m_axis_cc_tdata,
|
||||
tkeep=m_axis_cc_tkeep,
|
||||
tvalid=m_axis_cc_tvalid,
|
||||
tready=m_axis_cc_tready,
|
||||
tlast=m_axis_cc_tlast,
|
||||
tuser=m_axis_cc_tuser,
|
||||
name='cc_sink'
|
||||
)
|
||||
|
||||
# AXI4-Lite RAM model
|
||||
axil_ram_inst = axil.AXILiteRam(2**16)
|
||||
|
||||
axil_ram_port0 = axil_ram_inst.create_port(
|
||||
clk,
|
||||
s_axil_awaddr=m_axil_awaddr,
|
||||
s_axil_awprot=m_axil_awprot,
|
||||
s_axil_awvalid=m_axil_awvalid,
|
||||
s_axil_awready=m_axil_awready,
|
||||
s_axil_wdata=m_axil_wdata,
|
||||
s_axil_wstrb=m_axil_wstrb,
|
||||
s_axil_wvalid=m_axil_wvalid,
|
||||
s_axil_wready=m_axil_wready,
|
||||
s_axil_bresp=m_axil_bresp,
|
||||
s_axil_bvalid=m_axil_bvalid,
|
||||
s_axil_bready=m_axil_bready,
|
||||
s_axil_araddr=m_axil_araddr,
|
||||
s_axil_arprot=m_axil_arprot,
|
||||
s_axil_arvalid=m_axil_arvalid,
|
||||
s_axil_arready=m_axil_arready,
|
||||
s_axil_rdata=m_axil_rdata,
|
||||
s_axil_rresp=m_axil_rresp,
|
||||
s_axil_rvalid=m_axil_rvalid,
|
||||
s_axil_rready=m_axil_rready,
|
||||
latency=1,
|
||||
name='ram'
|
||||
)
|
||||
|
||||
# DUT
|
||||
if os.system(build_cmd):
|
||||
raise Exception("Error running build command")
|
||||
|
||||
dut = Cosimulation(
|
||||
"vvp -m myhdl %s.vvp -lxt2" % testbench,
|
||||
clk=clk,
|
||||
rst=rst,
|
||||
current_test=current_test,
|
||||
|
||||
s_axis_cq_tdata=s_axis_cq_tdata,
|
||||
s_axis_cq_tkeep=s_axis_cq_tkeep,
|
||||
s_axis_cq_tvalid=s_axis_cq_tvalid,
|
||||
s_axis_cq_tready=s_axis_cq_tready,
|
||||
s_axis_cq_tlast=s_axis_cq_tlast,
|
||||
s_axis_cq_tuser=s_axis_cq_tuser,
|
||||
|
||||
m_axis_cc_tdata=m_axis_cc_tdata,
|
||||
m_axis_cc_tkeep=m_axis_cc_tkeep,
|
||||
m_axis_cc_tvalid=m_axis_cc_tvalid,
|
||||
m_axis_cc_tready=m_axis_cc_tready,
|
||||
m_axis_cc_tlast=m_axis_cc_tlast,
|
||||
m_axis_cc_tuser=m_axis_cc_tuser,
|
||||
|
||||
m_axil_awaddr=m_axil_awaddr,
|
||||
m_axil_awprot=m_axil_awprot,
|
||||
m_axil_awvalid=m_axil_awvalid,
|
||||
m_axil_awready=m_axil_awready,
|
||||
m_axil_wdata=m_axil_wdata,
|
||||
m_axil_wstrb=m_axil_wstrb,
|
||||
m_axil_wvalid=m_axil_wvalid,
|
||||
m_axil_wready=m_axil_wready,
|
||||
m_axil_bresp=m_axil_bresp,
|
||||
m_axil_bvalid=m_axil_bvalid,
|
||||
m_axil_bready=m_axil_bready,
|
||||
m_axil_araddr=m_axil_araddr,
|
||||
m_axil_arprot=m_axil_arprot,
|
||||
m_axil_arvalid=m_axil_arvalid,
|
||||
m_axil_arready=m_axil_arready,
|
||||
m_axil_rdata=m_axil_rdata,
|
||||
m_axil_rresp=m_axil_rresp,
|
||||
m_axil_rvalid=m_axil_rvalid,
|
||||
m_axil_rready=m_axil_rready,
|
||||
|
||||
completer_id=completer_id,
|
||||
completer_id_enable=completer_id_enable,
|
||||
|
||||
status_error_cor=status_error_cor,
|
||||
status_error_uncor=status_error_uncor
|
||||
)
|
||||
|
||||
@always(delay(4))
|
||||
def clkgen():
|
||||
clk.next = not clk
|
||||
|
||||
status_error_cor_asserted = Signal(bool(0))
|
||||
status_error_uncor_asserted = Signal(bool(0))
|
||||
|
||||
@always(clk.posedge)
|
||||
def monitor():
|
||||
if (status_error_cor):
|
||||
status_error_cor_asserted.next = 1
|
||||
if (status_error_uncor):
|
||||
status_error_uncor_asserted.next = 1
|
||||
|
||||
@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
|
||||
|
||||
cur_tag = 1
|
||||
|
||||
completer_id.next = int(pcie_us.PcieId(4, 5, 6))
|
||||
|
||||
yield clk.posedge
|
||||
print("test 1: baseline")
|
||||
current_test.next = 1
|
||||
|
||||
data = axil_ram_inst.read_mem(0, 32)
|
||||
for i in range(0, len(data), 16):
|
||||
print(" ".join(("{:02x}".format(c) for c in bytearray(data[i:i+16]))))
|
||||
|
||||
yield delay(100)
|
||||
|
||||
yield clk.posedge
|
||||
print("test 2: memory write")
|
||||
current_test.next = 2
|
||||
|
||||
tlp = pcie_us.TLP_us()
|
||||
tlp.fmt_type = pcie_us.TLP_MEM_WRITE
|
||||
tlp.requester_id = pcie_us.PcieId(1, 2, 3)
|
||||
tlp.tag = cur_tag
|
||||
tlp.tc = 0
|
||||
tlp.set_be_data(0x0000, b'\x11\x22\x33\x44')
|
||||
tlp.address = 0x0000
|
||||
|
||||
cq_source.send(tlp.pack_us_cq(AXIS_PCIE_DATA_WIDTH))
|
||||
|
||||
yield delay(100)
|
||||
|
||||
data = axil_ram_inst.read_mem(0, 32)
|
||||
for i in range(0, len(data), 16):
|
||||
print(" ".join(("{:02x}".format(c) for c in bytearray(data[i:i+16]))))
|
||||
|
||||
assert axil_ram_inst.read_mem(0, 4) == b'\x11\x22\x33\x44'
|
||||
|
||||
assert not status_error_cor_asserted
|
||||
assert not status_error_uncor_asserted
|
||||
|
||||
cur_tag = (cur_tag + 1) % 32
|
||||
|
||||
yield delay(100)
|
||||
|
||||
yield clk.posedge
|
||||
print("test 3: IO write")
|
||||
current_test.next = 3
|
||||
|
||||
tlp = pcie_us.TLP_us()
|
||||
tlp.fmt_type = pcie_us.TLP_IO_WRITE
|
||||
tlp.requester_id = pcie_us.PcieId(1, 2, 3)
|
||||
tlp.tag = cur_tag
|
||||
tlp.tc = 0
|
||||
tlp.set_be_data(0x0000, b'\x11\x22\x33\x44')
|
||||
tlp.address = 0x0000
|
||||
|
||||
cq_source.send(tlp.pack_us_cq(AXIS_PCIE_DATA_WIDTH))
|
||||
|
||||
yield cc_sink.wait(500)
|
||||
pkt = cc_sink.recv()
|
||||
|
||||
rx_tlp = pcie_us.TLP_us().unpack_us_cc(pkt, AXIS_PCIE_DATA_WIDTH)
|
||||
|
||||
print(rx_tlp)
|
||||
|
||||
assert rx_tlp.status == pcie_us.CPL_STATUS_SC
|
||||
assert rx_tlp.tag == cur_tag
|
||||
assert rx_tlp.completer_id == pcie_us.PcieId(4, 5, 6)
|
||||
|
||||
data = axil_ram_inst.read_mem(0, 32)
|
||||
for i in range(0, len(data), 16):
|
||||
print(" ".join(("{:02x}".format(c) for c in bytearray(data[i:i+16]))))
|
||||
|
||||
assert axil_ram_inst.read_mem(0, 4) == b'\x11\x22\x33\x44'
|
||||
|
||||
assert not status_error_cor_asserted
|
||||
assert not status_error_uncor_asserted
|
||||
|
||||
cur_tag = (cur_tag + 1) % 32
|
||||
|
||||
yield delay(100)
|
||||
|
||||
yield clk.posedge
|
||||
print("test 4: memory read")
|
||||
current_test.next = 4
|
||||
|
||||
tlp = pcie_us.TLP_us()
|
||||
tlp.fmt_type = pcie_us.TLP_MEM_READ
|
||||
tlp.requester_id = pcie_us.PcieId(1, 2, 3)
|
||||
tlp.tag = cur_tag
|
||||
tlp.tc = 0
|
||||
tlp.length = 1
|
||||
tlp.set_be(0x0000, 4)
|
||||
tlp.address = 0x0000
|
||||
|
||||
cq_source.send(tlp.pack_us_cq(AXIS_PCIE_DATA_WIDTH))
|
||||
|
||||
yield cc_sink.wait(500)
|
||||
pkt = cc_sink.recv()
|
||||
|
||||
rx_tlp = pcie_us.TLP_us().unpack_us_cc(pkt, AXIS_PCIE_DATA_WIDTH)
|
||||
|
||||
print(rx_tlp)
|
||||
|
||||
data = rx_tlp.get_data()
|
||||
|
||||
print(data)
|
||||
|
||||
assert data == b'\x11\x22\x33\x44'
|
||||
assert rx_tlp.status == pcie_us.CPL_STATUS_SC
|
||||
assert rx_tlp.tag == cur_tag
|
||||
assert rx_tlp.completer_id == pcie_us.PcieId(4, 5, 6)
|
||||
|
||||
assert not status_error_cor_asserted
|
||||
assert not status_error_uncor_asserted
|
||||
|
||||
cur_tag = (cur_tag + 1) % 32
|
||||
|
||||
yield delay(100)
|
||||
|
||||
yield clk.posedge
|
||||
print("test 5: IO read")
|
||||
current_test.next = 5
|
||||
|
||||
tlp = pcie_us.TLP_us()
|
||||
tlp.fmt_type = pcie_us.TLP_IO_READ
|
||||
tlp.requester_id = pcie_us.PcieId(1, 2, 3)
|
||||
tlp.tag = cur_tag
|
||||
tlp.tc = 0
|
||||
tlp.length = 1
|
||||
tlp.set_be(0x0000, 4)
|
||||
tlp.address = 0x0000
|
||||
|
||||
cq_source.send(tlp.pack_us_cq(AXIS_PCIE_DATA_WIDTH))
|
||||
|
||||
yield cc_sink.wait(500)
|
||||
pkt = cc_sink.recv()
|
||||
|
||||
rx_tlp = pcie_us.TLP_us().unpack_us_cc(pkt, AXIS_PCIE_DATA_WIDTH)
|
||||
|
||||
print(rx_tlp)
|
||||
|
||||
data = rx_tlp.get_data()
|
||||
|
||||
print(data)
|
||||
|
||||
assert data == b'\x11\x22\x33\x44'
|
||||
assert rx_tlp.status == pcie_us.CPL_STATUS_SC
|
||||
assert rx_tlp.tag == cur_tag
|
||||
assert rx_tlp.completer_id == pcie_us.PcieId(4, 5, 6)
|
||||
|
||||
assert not status_error_cor_asserted
|
||||
assert not status_error_uncor_asserted
|
||||
|
||||
cur_tag = (cur_tag + 1) % 32
|
||||
|
||||
yield delay(100)
|
||||
|
||||
yield clk.posedge
|
||||
print("test 6: various writes")
|
||||
current_test.next = 6
|
||||
|
||||
for length in range(1,5):
|
||||
for offset in range(4,8-length+1):
|
||||
axil_ram_inst.write_mem(256*(16*offset+length), b'\xAA'*32)
|
||||
|
||||
tlp = pcie_us.TLP_us()
|
||||
tlp.fmt_type = pcie_us.TLP_MEM_WRITE
|
||||
tlp.requester_id = pcie_us.PcieId(1, 2, 3)
|
||||
tlp.tag = cur_tag
|
||||
tlp.tc = 0
|
||||
tlp.set_be_data(256*(16*offset+length)+offset, b'\x11\x22\x33\x44'[0:length])
|
||||
tlp.address = 256*(16*offset+length)+offset
|
||||
|
||||
cq_source.send(tlp.pack_us_cq(AXIS_PCIE_DATA_WIDTH))
|
||||
|
||||
yield delay(100)
|
||||
|
||||
data = axil_ram_inst.read_mem(256*(16*offset+length), 32)
|
||||
for i in range(0, len(data), 16):
|
||||
print(" ".join(("{:02x}".format(c) for c in bytearray(data[i:i+16]))))
|
||||
|
||||
assert axil_ram_inst.read_mem(256*(16*offset+length)+offset, length) == b'\x11\x22\x33\x44'[0:length]
|
||||
assert axil_ram_inst.read_mem(256*(16*offset+length)+offset-1, 1) == b'\xAA'
|
||||
assert axil_ram_inst.read_mem(256*(16*offset+length)+offset+length, 1) == b'\xAA'
|
||||
|
||||
assert not status_error_cor_asserted
|
||||
assert not status_error_uncor_asserted
|
||||
|
||||
cur_tag = (cur_tag + 1) % 32
|
||||
|
||||
yield delay(100)
|
||||
|
||||
yield clk.posedge
|
||||
print("test 7: various reads")
|
||||
current_test.next = 7
|
||||
|
||||
for length in range(1,5):
|
||||
for offset in range(4,8-length+1):
|
||||
tlp = pcie_us.TLP_us()
|
||||
tlp.fmt_type = pcie_us.TLP_MEM_READ
|
||||
tlp.requester_id = pcie_us.PcieId(1, 2, 3)
|
||||
tlp.tag = cur_tag
|
||||
tlp.tc = 0
|
||||
tlp.length = 1
|
||||
tlp.set_be(256*(16*offset+length)+offset, length)
|
||||
tlp.address = 256*(16*offset+length)+offset
|
||||
|
||||
cq_source.send(tlp.pack_us_cq(AXIS_PCIE_DATA_WIDTH))
|
||||
|
||||
yield cc_sink.wait(500)
|
||||
pkt = cc_sink.recv()
|
||||
|
||||
rx_tlp = pcie_us.TLP_us().unpack_us_cc(pkt, AXIS_PCIE_DATA_WIDTH)
|
||||
|
||||
print(rx_tlp)
|
||||
|
||||
data = rx_tlp.get_data()
|
||||
|
||||
print(data)
|
||||
|
||||
assert data == b'\xAA'*(offset-4)+b'\x11\x22\x33\x44'[0:length]+b'\xAA'*(8-offset-length)
|
||||
assert rx_tlp.status == pcie_us.CPL_STATUS_SC
|
||||
assert rx_tlp.tag == cur_tag
|
||||
assert rx_tlp.completer_id == pcie_us.PcieId(4, 5, 6)
|
||||
|
||||
assert not status_error_cor_asserted
|
||||
assert not status_error_uncor_asserted
|
||||
|
||||
cur_tag = (cur_tag + 1) % 32
|
||||
|
||||
yield delay(100)
|
||||
|
||||
yield clk.posedge
|
||||
print("test 8: bad memory write")
|
||||
current_test.next = 8
|
||||
|
||||
tlp = pcie_us.TLP_us()
|
||||
tlp.fmt_type = pcie_us.TLP_MEM_WRITE
|
||||
tlp.requester_id = pcie_us.PcieId(1, 2, 3)
|
||||
tlp.tag = cur_tag
|
||||
tlp.tc = 0
|
||||
tlp.set_be_data(0x0000, bytearray(range(64)))
|
||||
tlp.address = 0x0000
|
||||
|
||||
cq_source.send(tlp.pack_us_cq(AXIS_PCIE_DATA_WIDTH))
|
||||
|
||||
yield delay(100)
|
||||
|
||||
assert not status_error_cor_asserted
|
||||
assert status_error_uncor_asserted
|
||||
|
||||
status_error_uncor_asserted.next = 0
|
||||
|
||||
cur_tag = (cur_tag + 1) % 32
|
||||
|
||||
yield delay(100)
|
||||
|
||||
yield clk.posedge
|
||||
print("test 9: bad memory read")
|
||||
current_test.next = 9
|
||||
|
||||
tlp = pcie_us.TLP_us()
|
||||
tlp.fmt_type = pcie_us.TLP_MEM_READ
|
||||
tlp.requester_id = pcie_us.PcieId(1, 2, 3)
|
||||
tlp.tag = cur_tag
|
||||
tlp.tc = 0
|
||||
tlp.set_be(0x0000, 64)
|
||||
tlp.address = 0x0000
|
||||
|
||||
cq_source.send(tlp.pack_us_cq(AXIS_PCIE_DATA_WIDTH))
|
||||
|
||||
yield cc_sink.wait(500)
|
||||
pkt = cc_sink.recv()
|
||||
|
||||
rx_tlp = pcie_us.TLP_us().unpack_us_cc(pkt, AXIS_PCIE_DATA_WIDTH)
|
||||
|
||||
print(rx_tlp)
|
||||
|
||||
assert rx_tlp.status == pcie_us.CPL_STATUS_CA
|
||||
assert rx_tlp.tag == cur_tag
|
||||
assert rx_tlp.completer_id == pcie_us.PcieId(4, 5, 6)
|
||||
|
||||
assert status_error_cor_asserted
|
||||
assert not status_error_uncor_asserted
|
||||
|
||||
cur_tag = (cur_tag + 1) % 32
|
||||
|
||||
yield delay(100)
|
||||
|
||||
raise StopSimulation
|
||||
|
||||
return instances()
|
||||
|
||||
def test_bench():
|
||||
sim = Simulation(bench())
|
||||
sim.run()
|
||||
|
||||
if __name__ == '__main__':
|
||||
print("Running test...")
|
||||
test_bench()
|
183
fpga/lib/pcie/tb/test_pcie_us_axil_master_256.v
Normal file
183
fpga/lib/pcie/tb/test_pcie_us_axil_master_256.v
Normal file
@ -0,0 +1,183 @@
|
||||
/*
|
||||
|
||||
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 pcie_us_axil_master
|
||||
*/
|
||||
module test_pcie_us_axil_master_256;
|
||||
|
||||
// Parameters
|
||||
parameter AXIS_PCIE_DATA_WIDTH = 256;
|
||||
parameter AXIS_PCIE_KEEP_WIDTH = (AXIS_PCIE_DATA_WIDTH/32);
|
||||
parameter AXI_DATA_WIDTH = 32;
|
||||
parameter AXI_ADDR_WIDTH = 64;
|
||||
parameter AXI_STRB_WIDTH = (AXI_DATA_WIDTH/8);
|
||||
parameter ENABLE_PARITY = 0;
|
||||
|
||||
// Inputs
|
||||
reg clk = 0;
|
||||
reg rst = 0;
|
||||
reg [7:0] current_test = 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_tvalid = 0;
|
||||
reg s_axis_cq_tlast = 0;
|
||||
reg [84:0] s_axis_cq_tuser = 0;
|
||||
reg m_axis_cc_tready = 0;
|
||||
reg m_axil_awready = 0;
|
||||
reg m_axil_wready = 0;
|
||||
reg [1:0] m_axil_bresp = 0;
|
||||
reg m_axil_bvalid = 0;
|
||||
reg m_axil_arready = 0;
|
||||
reg [AXI_DATA_WIDTH-1:0] m_axil_rdata = 0;
|
||||
reg [1:0] m_axil_rresp = 0;
|
||||
reg m_axil_rvalid = 0;
|
||||
reg [15:0] completer_id = 0;
|
||||
reg completer_id_enable = 0;
|
||||
|
||||
// Outputs
|
||||
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_tvalid;
|
||||
wire m_axis_cc_tlast;
|
||||
wire [32:0] m_axis_cc_tuser;
|
||||
wire [AXI_ADDR_WIDTH-1:0] m_axil_awaddr;
|
||||
wire [2:0] m_axil_awprot;
|
||||
wire m_axil_awvalid;
|
||||
wire [AXI_DATA_WIDTH-1:0] m_axil_wdata;
|
||||
wire [AXI_STRB_WIDTH-1:0] m_axil_wstrb;
|
||||
wire m_axil_wvalid;
|
||||
wire m_axil_bready;
|
||||
wire [AXI_ADDR_WIDTH-1:0] m_axil_araddr;
|
||||
wire [2:0] m_axil_arprot;
|
||||
wire m_axil_arvalid;
|
||||
wire m_axil_rready;
|
||||
wire status_error_cor;
|
||||
wire status_error_uncor;
|
||||
|
||||
initial begin
|
||||
// myhdl integration
|
||||
$from_myhdl(
|
||||
clk,
|
||||
rst,
|
||||
current_test,
|
||||
s_axis_cq_tdata,
|
||||
s_axis_cq_tkeep,
|
||||
s_axis_cq_tvalid,
|
||||
s_axis_cq_tlast,
|
||||
s_axis_cq_tuser,
|
||||
m_axis_cc_tready,
|
||||
m_axil_awready,
|
||||
m_axil_wready,
|
||||
m_axil_bresp,
|
||||
m_axil_bvalid,
|
||||
m_axil_arready,
|
||||
m_axil_rdata,
|
||||
m_axil_rresp,
|
||||
m_axil_rvalid,
|
||||
completer_id,
|
||||
completer_id_enable
|
||||
);
|
||||
$to_myhdl(
|
||||
s_axis_cq_tready,
|
||||
m_axis_cc_tdata,
|
||||
m_axis_cc_tkeep,
|
||||
m_axis_cc_tvalid,
|
||||
m_axis_cc_tlast,
|
||||
m_axis_cc_tuser,
|
||||
m_axil_awaddr,
|
||||
m_axil_awprot,
|
||||
m_axil_awvalid,
|
||||
m_axil_wdata,
|
||||
m_axil_wstrb,
|
||||
m_axil_wvalid,
|
||||
m_axil_bready,
|
||||
m_axil_araddr,
|
||||
m_axil_arprot,
|
||||
m_axil_arvalid,
|
||||
m_axil_rready,
|
||||
status_error_cor,
|
||||
status_error_uncor
|
||||
);
|
||||
|
||||
// dump file
|
||||
$dumpfile("test_pcie_us_axil_master_256.lxt");
|
||||
$dumpvars(0, test_pcie_us_axil_master_256);
|
||||
end
|
||||
|
||||
pcie_us_axil_master #(
|
||||
.AXIS_PCIE_DATA_WIDTH(AXIS_PCIE_DATA_WIDTH),
|
||||
.AXIS_PCIE_KEEP_WIDTH(AXIS_PCIE_KEEP_WIDTH),
|
||||
.AXI_DATA_WIDTH(AXI_DATA_WIDTH),
|
||||
.AXI_ADDR_WIDTH(AXI_ADDR_WIDTH),
|
||||
.AXI_STRB_WIDTH(AXI_STRB_WIDTH),
|
||||
.ENABLE_PARITY(ENABLE_PARITY)
|
||||
)
|
||||
UUT (
|
||||
.clk(clk),
|
||||
.rst(rst),
|
||||
.s_axis_cq_tdata(s_axis_cq_tdata),
|
||||
.s_axis_cq_tkeep(s_axis_cq_tkeep),
|
||||
.s_axis_cq_tvalid(s_axis_cq_tvalid),
|
||||
.s_axis_cq_tready(s_axis_cq_tready),
|
||||
.s_axis_cq_tlast(s_axis_cq_tlast),
|
||||
.s_axis_cq_tuser(s_axis_cq_tuser),
|
||||
.m_axis_cc_tdata(m_axis_cc_tdata),
|
||||
.m_axis_cc_tkeep(m_axis_cc_tkeep),
|
||||
.m_axis_cc_tvalid(m_axis_cc_tvalid),
|
||||
.m_axis_cc_tready(m_axis_cc_tready),
|
||||
.m_axis_cc_tlast(m_axis_cc_tlast),
|
||||
.m_axis_cc_tuser(m_axis_cc_tuser),
|
||||
.m_axil_awaddr(m_axil_awaddr),
|
||||
.m_axil_awprot(m_axil_awprot),
|
||||
.m_axil_awvalid(m_axil_awvalid),
|
||||
.m_axil_awready(m_axil_awready),
|
||||
.m_axil_wdata(m_axil_wdata),
|
||||
.m_axil_wstrb(m_axil_wstrb),
|
||||
.m_axil_wvalid(m_axil_wvalid),
|
||||
.m_axil_wready(m_axil_wready),
|
||||
.m_axil_bresp(m_axil_bresp),
|
||||
.m_axil_bvalid(m_axil_bvalid),
|
||||
.m_axil_bready(m_axil_bready),
|
||||
.m_axil_araddr(m_axil_araddr),
|
||||
.m_axil_arprot(m_axil_arprot),
|
||||
.m_axil_arvalid(m_axil_arvalid),
|
||||
.m_axil_arready(m_axil_arready),
|
||||
.m_axil_rdata(m_axil_rdata),
|
||||
.m_axil_rresp(m_axil_rresp),
|
||||
.m_axil_rvalid(m_axil_rvalid),
|
||||
.m_axil_rready(m_axil_rready),
|
||||
.completer_id(completer_id),
|
||||
.completer_id_enable(completer_id_enable),
|
||||
.status_error_cor(status_error_cor),
|
||||
.status_error_uncor(status_error_uncor)
|
||||
);
|
||||
|
||||
endmodule
|
532
fpga/lib/pcie/tb/test_pcie_us_axil_master_64.py
Executable file
532
fpga/lib/pcie/tb/test_pcie_us_axil_master_64.py
Executable file
@ -0,0 +1,532 @@
|
||||
#!/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 axis_ep
|
||||
import axil
|
||||
import pcie_us
|
||||
|
||||
module = 'pcie_us_axil_master'
|
||||
testbench = 'test_%s_64' % module
|
||||
|
||||
srcs = []
|
||||
|
||||
srcs.append("../rtl/%s.v" % module)
|
||||
srcs.append("%s.v" % testbench)
|
||||
|
||||
src = ' '.join(srcs)
|
||||
|
||||
build_cmd = "iverilog -o %s.vvp %s" % (testbench, src)
|
||||
|
||||
def bench():
|
||||
|
||||
# Parameters
|
||||
AXIS_PCIE_DATA_WIDTH = 64
|
||||
AXIS_PCIE_KEEP_WIDTH = (AXIS_PCIE_DATA_WIDTH/32)
|
||||
AXI_DATA_WIDTH = 32
|
||||
AXI_ADDR_WIDTH = 64
|
||||
AXI_STRB_WIDTH = (AXI_DATA_WIDTH/8)
|
||||
ENABLE_PARITY = 0
|
||||
|
||||
# Inputs
|
||||
clk = Signal(bool(0))
|
||||
rst = Signal(bool(0))
|
||||
current_test = Signal(intbv(0)[8:])
|
||||
|
||||
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_tvalid = Signal(bool(0))
|
||||
s_axis_cq_tlast = Signal(bool(0))
|
||||
s_axis_cq_tuser = Signal(intbv(0)[85:])
|
||||
m_axis_cc_tready = Signal(bool(0))
|
||||
m_axil_awready = Signal(bool(0))
|
||||
m_axil_wready = Signal(bool(0))
|
||||
m_axil_bresp = Signal(intbv(0)[2:])
|
||||
m_axil_bvalid = Signal(bool(0))
|
||||
m_axil_arready = Signal(bool(0))
|
||||
m_axil_rdata = Signal(intbv(0)[AXI_DATA_WIDTH:])
|
||||
m_axil_rresp = Signal(intbv(0)[2:])
|
||||
m_axil_rvalid = Signal(bool(0))
|
||||
completer_id = Signal(intbv(0)[16:])
|
||||
completer_id_enable = Signal(bool(0))
|
||||
|
||||
# Outputs
|
||||
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_tvalid = Signal(bool(0))
|
||||
m_axis_cc_tlast = Signal(bool(0))
|
||||
m_axis_cc_tuser = Signal(intbv(0)[33:])
|
||||
m_axil_awaddr = Signal(intbv(0)[AXI_ADDR_WIDTH:])
|
||||
m_axil_awprot = Signal(intbv(0)[3:])
|
||||
m_axil_awvalid = Signal(bool(0))
|
||||
m_axil_wdata = Signal(intbv(0)[AXI_DATA_WIDTH:])
|
||||
m_axil_wstrb = Signal(intbv(0)[AXI_STRB_WIDTH:])
|
||||
m_axil_wvalid = Signal(bool(0))
|
||||
m_axil_bready = Signal(bool(0))
|
||||
m_axil_araddr = Signal(intbv(0)[AXI_ADDR_WIDTH:])
|
||||
m_axil_arprot = Signal(intbv(2)[3:])
|
||||
m_axil_arvalid = Signal(bool(0))
|
||||
m_axil_rready = Signal(bool(0))
|
||||
status_error_cor = Signal(bool(0))
|
||||
status_error_uncor = Signal(bool(0))
|
||||
|
||||
# sources and sinks
|
||||
cq_source = axis_ep.AXIStreamSource()
|
||||
|
||||
cq_source_logic = cq_source.create_logic(
|
||||
clk,
|
||||
rst,
|
||||
tdata=s_axis_cq_tdata,
|
||||
tkeep=s_axis_cq_tkeep,
|
||||
tvalid=s_axis_cq_tvalid,
|
||||
tready=s_axis_cq_tready,
|
||||
tlast=s_axis_cq_tlast,
|
||||
tuser=s_axis_cq_tuser,
|
||||
name='cq_source'
|
||||
)
|
||||
|
||||
cc_sink = axis_ep.AXIStreamSink()
|
||||
|
||||
cc_sink_logic = cc_sink.create_logic(
|
||||
clk,
|
||||
rst,
|
||||
tdata=m_axis_cc_tdata,
|
||||
tkeep=m_axis_cc_tkeep,
|
||||
tvalid=m_axis_cc_tvalid,
|
||||
tready=m_axis_cc_tready,
|
||||
tlast=m_axis_cc_tlast,
|
||||
tuser=m_axis_cc_tuser,
|
||||
name='cc_sink'
|
||||
)
|
||||
|
||||
# AXI4-Lite RAM model
|
||||
axil_ram_inst = axil.AXILiteRam(2**16)
|
||||
|
||||
axil_ram_port0 = axil_ram_inst.create_port(
|
||||
clk,
|
||||
s_axil_awaddr=m_axil_awaddr,
|
||||
s_axil_awprot=m_axil_awprot,
|
||||
s_axil_awvalid=m_axil_awvalid,
|
||||
s_axil_awready=m_axil_awready,
|
||||
s_axil_wdata=m_axil_wdata,
|
||||
s_axil_wstrb=m_axil_wstrb,
|
||||
s_axil_wvalid=m_axil_wvalid,
|
||||
s_axil_wready=m_axil_wready,
|
||||
s_axil_bresp=m_axil_bresp,
|
||||
s_axil_bvalid=m_axil_bvalid,
|
||||
s_axil_bready=m_axil_bready,
|
||||
s_axil_araddr=m_axil_araddr,
|
||||
s_axil_arprot=m_axil_arprot,
|
||||
s_axil_arvalid=m_axil_arvalid,
|
||||
s_axil_arready=m_axil_arready,
|
||||
s_axil_rdata=m_axil_rdata,
|
||||
s_axil_rresp=m_axil_rresp,
|
||||
s_axil_rvalid=m_axil_rvalid,
|
||||
s_axil_rready=m_axil_rready,
|
||||
latency=1,
|
||||
name='ram'
|
||||
)
|
||||
|
||||
# DUT
|
||||
if os.system(build_cmd):
|
||||
raise Exception("Error running build command")
|
||||
|
||||
dut = Cosimulation(
|
||||
"vvp -m myhdl %s.vvp -lxt2" % testbench,
|
||||
clk=clk,
|
||||
rst=rst,
|
||||
current_test=current_test,
|
||||
|
||||
s_axis_cq_tdata=s_axis_cq_tdata,
|
||||
s_axis_cq_tkeep=s_axis_cq_tkeep,
|
||||
s_axis_cq_tvalid=s_axis_cq_tvalid,
|
||||
s_axis_cq_tready=s_axis_cq_tready,
|
||||
s_axis_cq_tlast=s_axis_cq_tlast,
|
||||
s_axis_cq_tuser=s_axis_cq_tuser,
|
||||
|
||||
m_axis_cc_tdata=m_axis_cc_tdata,
|
||||
m_axis_cc_tkeep=m_axis_cc_tkeep,
|
||||
m_axis_cc_tvalid=m_axis_cc_tvalid,
|
||||
m_axis_cc_tready=m_axis_cc_tready,
|
||||
m_axis_cc_tlast=m_axis_cc_tlast,
|
||||
m_axis_cc_tuser=m_axis_cc_tuser,
|
||||
|
||||
m_axil_awaddr=m_axil_awaddr,
|
||||
m_axil_awprot=m_axil_awprot,
|
||||
m_axil_awvalid=m_axil_awvalid,
|
||||
m_axil_awready=m_axil_awready,
|
||||
m_axil_wdata=m_axil_wdata,
|
||||
m_axil_wstrb=m_axil_wstrb,
|
||||
m_axil_wvalid=m_axil_wvalid,
|
||||
m_axil_wready=m_axil_wready,
|
||||
m_axil_bresp=m_axil_bresp,
|
||||
m_axil_bvalid=m_axil_bvalid,
|
||||
m_axil_bready=m_axil_bready,
|
||||
m_axil_araddr=m_axil_araddr,
|
||||
m_axil_arprot=m_axil_arprot,
|
||||
m_axil_arvalid=m_axil_arvalid,
|
||||
m_axil_arready=m_axil_arready,
|
||||
m_axil_rdata=m_axil_rdata,
|
||||
m_axil_rresp=m_axil_rresp,
|
||||
m_axil_rvalid=m_axil_rvalid,
|
||||
m_axil_rready=m_axil_rready,
|
||||
|
||||
completer_id=completer_id,
|
||||
completer_id_enable=completer_id_enable,
|
||||
|
||||
status_error_cor=status_error_cor,
|
||||
status_error_uncor=status_error_uncor
|
||||
)
|
||||
|
||||
@always(delay(4))
|
||||
def clkgen():
|
||||
clk.next = not clk
|
||||
|
||||
status_error_cor_asserted = Signal(bool(0))
|
||||
status_error_uncor_asserted = Signal(bool(0))
|
||||
|
||||
@always(clk.posedge)
|
||||
def monitor():
|
||||
if (status_error_cor):
|
||||
status_error_cor_asserted.next = 1
|
||||
if (status_error_uncor):
|
||||
status_error_uncor_asserted.next = 1
|
||||
|
||||
@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
|
||||
|
||||
cur_tag = 1
|
||||
|
||||
completer_id.next = int(pcie_us.PcieId(4, 5, 6))
|
||||
|
||||
yield clk.posedge
|
||||
print("test 1: baseline")
|
||||
current_test.next = 1
|
||||
|
||||
data = axil_ram_inst.read_mem(0, 32)
|
||||
for i in range(0, len(data), 16):
|
||||
print(" ".join(("{:02x}".format(c) for c in bytearray(data[i:i+16]))))
|
||||
|
||||
yield delay(100)
|
||||
|
||||
yield clk.posedge
|
||||
print("test 2: memory write")
|
||||
current_test.next = 2
|
||||
|
||||
tlp = pcie_us.TLP_us()
|
||||
tlp.fmt_type = pcie_us.TLP_MEM_WRITE
|
||||
tlp.requester_id = pcie_us.PcieId(1, 2, 3)
|
||||
tlp.tag = cur_tag
|
||||
tlp.tc = 0
|
||||
tlp.set_be_data(0x0000, b'\x11\x22\x33\x44')
|
||||
tlp.address = 0x0000
|
||||
|
||||
cq_source.send(tlp.pack_us_cq(AXIS_PCIE_DATA_WIDTH))
|
||||
|
||||
yield delay(100)
|
||||
|
||||
data = axil_ram_inst.read_mem(0, 32)
|
||||
for i in range(0, len(data), 16):
|
||||
print(" ".join(("{:02x}".format(c) for c in bytearray(data[i:i+16]))))
|
||||
|
||||
assert axil_ram_inst.read_mem(0, 4) == b'\x11\x22\x33\x44'
|
||||
|
||||
assert not status_error_cor_asserted
|
||||
assert not status_error_uncor_asserted
|
||||
|
||||
cur_tag = (cur_tag + 1) % 32
|
||||
|
||||
yield delay(100)
|
||||
|
||||
yield clk.posedge
|
||||
print("test 3: IO write")
|
||||
current_test.next = 3
|
||||
|
||||
tlp = pcie_us.TLP_us()
|
||||
tlp.fmt_type = pcie_us.TLP_IO_WRITE
|
||||
tlp.requester_id = pcie_us.PcieId(1, 2, 3)
|
||||
tlp.tag = cur_tag
|
||||
tlp.tc = 0
|
||||
tlp.set_be_data(0x0000, b'\x11\x22\x33\x44')
|
||||
tlp.address = 0x0000
|
||||
|
||||
cq_source.send(tlp.pack_us_cq(AXIS_PCIE_DATA_WIDTH))
|
||||
|
||||
yield cc_sink.wait(500)
|
||||
pkt = cc_sink.recv()
|
||||
|
||||
rx_tlp = pcie_us.TLP_us().unpack_us_cc(pkt, AXIS_PCIE_DATA_WIDTH)
|
||||
|
||||
print(rx_tlp)
|
||||
|
||||
assert rx_tlp.status == pcie_us.CPL_STATUS_SC
|
||||
assert rx_tlp.tag == cur_tag
|
||||
assert rx_tlp.completer_id == pcie_us.PcieId(4, 5, 6)
|
||||
|
||||
data = axil_ram_inst.read_mem(0, 32)
|
||||
for i in range(0, len(data), 16):
|
||||
print(" ".join(("{:02x}".format(c) for c in bytearray(data[i:i+16]))))
|
||||
|
||||
assert axil_ram_inst.read_mem(0, 4) == b'\x11\x22\x33\x44'
|
||||
|
||||
assert not status_error_cor_asserted
|
||||
assert not status_error_uncor_asserted
|
||||
|
||||
cur_tag = (cur_tag + 1) % 32
|
||||
|
||||
yield delay(100)
|
||||
|
||||
yield clk.posedge
|
||||
print("test 4: memory read")
|
||||
current_test.next = 4
|
||||
|
||||
tlp = pcie_us.TLP_us()
|
||||
tlp.fmt_type = pcie_us.TLP_MEM_READ
|
||||
tlp.requester_id = pcie_us.PcieId(1, 2, 3)
|
||||
tlp.tag = cur_tag
|
||||
tlp.tc = 0
|
||||
tlp.length = 1
|
||||
tlp.set_be(0x0000, 4)
|
||||
tlp.address = 0x0000
|
||||
|
||||
cq_source.send(tlp.pack_us_cq(AXIS_PCIE_DATA_WIDTH))
|
||||
|
||||
yield cc_sink.wait(500)
|
||||
pkt = cc_sink.recv()
|
||||
|
||||
rx_tlp = pcie_us.TLP_us().unpack_us_cc(pkt, AXIS_PCIE_DATA_WIDTH)
|
||||
|
||||
print(rx_tlp)
|
||||
|
||||
data = rx_tlp.get_data()
|
||||
|
||||
print(data)
|
||||
|
||||
assert data == b'\x11\x22\x33\x44'
|
||||
assert rx_tlp.status == pcie_us.CPL_STATUS_SC
|
||||
assert rx_tlp.tag == cur_tag
|
||||
assert rx_tlp.completer_id == pcie_us.PcieId(4, 5, 6)
|
||||
|
||||
assert not status_error_cor_asserted
|
||||
assert not status_error_uncor_asserted
|
||||
|
||||
cur_tag = (cur_tag + 1) % 32
|
||||
|
||||
yield delay(100)
|
||||
|
||||
yield clk.posedge
|
||||
print("test 5: IO read")
|
||||
current_test.next = 5
|
||||
|
||||
tlp = pcie_us.TLP_us()
|
||||
tlp.fmt_type = pcie_us.TLP_IO_READ
|
||||
tlp.requester_id = pcie_us.PcieId(1, 2, 3)
|
||||
tlp.tag = cur_tag
|
||||
tlp.tc = 0
|
||||
tlp.length = 1
|
||||
tlp.set_be(0x0000, 4)
|
||||
tlp.address = 0x0000
|
||||
|
||||
cq_source.send(tlp.pack_us_cq(AXIS_PCIE_DATA_WIDTH))
|
||||
|
||||
yield cc_sink.wait(500)
|
||||
pkt = cc_sink.recv()
|
||||
|
||||
rx_tlp = pcie_us.TLP_us().unpack_us_cc(pkt, AXIS_PCIE_DATA_WIDTH)
|
||||
|
||||
print(rx_tlp)
|
||||
|
||||
data = rx_tlp.get_data()
|
||||
|
||||
print(data)
|
||||
|
||||
assert data == b'\x11\x22\x33\x44'
|
||||
assert rx_tlp.status == pcie_us.CPL_STATUS_SC
|
||||
assert rx_tlp.tag == cur_tag
|
||||
assert rx_tlp.completer_id == pcie_us.PcieId(4, 5, 6)
|
||||
|
||||
assert not status_error_cor_asserted
|
||||
assert not status_error_uncor_asserted
|
||||
|
||||
cur_tag = (cur_tag + 1) % 32
|
||||
|
||||
yield delay(100)
|
||||
|
||||
yield clk.posedge
|
||||
print("test 6: various writes")
|
||||
current_test.next = 6
|
||||
|
||||
for length in range(1,5):
|
||||
for offset in range(4,8-length+1):
|
||||
axil_ram_inst.write_mem(256*(16*offset+length), b'\xAA'*32)
|
||||
|
||||
tlp = pcie_us.TLP_us()
|
||||
tlp.fmt_type = pcie_us.TLP_MEM_WRITE
|
||||
tlp.requester_id = pcie_us.PcieId(1, 2, 3)
|
||||
tlp.tag = cur_tag
|
||||
tlp.tc = 0
|
||||
tlp.set_be_data(256*(16*offset+length)+offset, b'\x11\x22\x33\x44'[0:length])
|
||||
tlp.address = 256*(16*offset+length)+offset
|
||||
|
||||
cq_source.send(tlp.pack_us_cq(AXIS_PCIE_DATA_WIDTH))
|
||||
|
||||
yield delay(100)
|
||||
|
||||
data = axil_ram_inst.read_mem(256*(16*offset+length), 32)
|
||||
for i in range(0, len(data), 16):
|
||||
print(" ".join(("{:02x}".format(c) for c in bytearray(data[i:i+16]))))
|
||||
|
||||
assert axil_ram_inst.read_mem(256*(16*offset+length)+offset, length) == b'\x11\x22\x33\x44'[0:length]
|
||||
assert axil_ram_inst.read_mem(256*(16*offset+length)+offset-1, 1) == b'\xAA'
|
||||
assert axil_ram_inst.read_mem(256*(16*offset+length)+offset+length, 1) == b'\xAA'
|
||||
|
||||
assert not status_error_cor_asserted
|
||||
assert not status_error_uncor_asserted
|
||||
|
||||
cur_tag = (cur_tag + 1) % 32
|
||||
|
||||
yield delay(100)
|
||||
|
||||
yield clk.posedge
|
||||
print("test 7: various reads")
|
||||
current_test.next = 7
|
||||
|
||||
for length in range(1,5):
|
||||
for offset in range(4,8-length+1):
|
||||
tlp = pcie_us.TLP_us()
|
||||
tlp.fmt_type = pcie_us.TLP_MEM_READ
|
||||
tlp.requester_id = pcie_us.PcieId(1, 2, 3)
|
||||
tlp.tag = cur_tag
|
||||
tlp.tc = 0
|
||||
tlp.length = 1
|
||||
tlp.set_be(256*(16*offset+length)+offset, length)
|
||||
tlp.address = 256*(16*offset+length)+offset
|
||||
|
||||
cq_source.send(tlp.pack_us_cq(AXIS_PCIE_DATA_WIDTH))
|
||||
|
||||
yield cc_sink.wait(500)
|
||||
pkt = cc_sink.recv()
|
||||
|
||||
rx_tlp = pcie_us.TLP_us().unpack_us_cc(pkt, AXIS_PCIE_DATA_WIDTH)
|
||||
|
||||
print(rx_tlp)
|
||||
|
||||
data = rx_tlp.get_data()
|
||||
|
||||
print(data)
|
||||
|
||||
assert data == b'\xAA'*(offset-4)+b'\x11\x22\x33\x44'[0:length]+b'\xAA'*(8-offset-length)
|
||||
assert rx_tlp.status == pcie_us.CPL_STATUS_SC
|
||||
assert rx_tlp.tag == cur_tag
|
||||
assert rx_tlp.completer_id == pcie_us.PcieId(4, 5, 6)
|
||||
|
||||
assert not status_error_cor_asserted
|
||||
assert not status_error_uncor_asserted
|
||||
|
||||
cur_tag = (cur_tag + 1) % 32
|
||||
|
||||
yield delay(100)
|
||||
|
||||
yield clk.posedge
|
||||
print("test 8: bad memory write")
|
||||
current_test.next = 8
|
||||
|
||||
tlp = pcie_us.TLP_us()
|
||||
tlp.fmt_type = pcie_us.TLP_MEM_WRITE
|
||||
tlp.requester_id = pcie_us.PcieId(1, 2, 3)
|
||||
tlp.tag = cur_tag
|
||||
tlp.tc = 0
|
||||
tlp.set_be_data(0x0000, bytearray(range(64)))
|
||||
tlp.address = 0x0000
|
||||
|
||||
cq_source.send(tlp.pack_us_cq(AXIS_PCIE_DATA_WIDTH))
|
||||
|
||||
yield delay(100)
|
||||
|
||||
assert not status_error_cor_asserted
|
||||
assert status_error_uncor_asserted
|
||||
|
||||
status_error_uncor_asserted.next = 0
|
||||
|
||||
cur_tag = (cur_tag + 1) % 32
|
||||
|
||||
yield delay(100)
|
||||
|
||||
yield clk.posedge
|
||||
print("test 9: bad memory read")
|
||||
current_test.next = 9
|
||||
|
||||
tlp = pcie_us.TLP_us()
|
||||
tlp.fmt_type = pcie_us.TLP_MEM_READ
|
||||
tlp.requester_id = pcie_us.PcieId(1, 2, 3)
|
||||
tlp.tag = cur_tag
|
||||
tlp.tc = 0
|
||||
tlp.set_be(0x0000, 64)
|
||||
tlp.address = 0x0000
|
||||
|
||||
cq_source.send(tlp.pack_us_cq(AXIS_PCIE_DATA_WIDTH))
|
||||
|
||||
yield cc_sink.wait(500)
|
||||
pkt = cc_sink.recv()
|
||||
|
||||
rx_tlp = pcie_us.TLP_us().unpack_us_cc(pkt, AXIS_PCIE_DATA_WIDTH)
|
||||
|
||||
print(rx_tlp)
|
||||
|
||||
assert rx_tlp.status == pcie_us.CPL_STATUS_CA
|
||||
assert rx_tlp.tag == cur_tag
|
||||
assert rx_tlp.completer_id == pcie_us.PcieId(4, 5, 6)
|
||||
|
||||
assert status_error_cor_asserted
|
||||
assert not status_error_uncor_asserted
|
||||
|
||||
cur_tag = (cur_tag + 1) % 32
|
||||
|
||||
yield delay(100)
|
||||
|
||||
raise StopSimulation
|
||||
|
||||
return instances()
|
||||
|
||||
def test_bench():
|
||||
sim = Simulation(bench())
|
||||
sim.run()
|
||||
|
||||
if __name__ == '__main__':
|
||||
print("Running test...")
|
||||
test_bench()
|
183
fpga/lib/pcie/tb/test_pcie_us_axil_master_64.v
Normal file
183
fpga/lib/pcie/tb/test_pcie_us_axil_master_64.v
Normal file
@ -0,0 +1,183 @@
|
||||
/*
|
||||
|
||||
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 pcie_us_axil_master
|
||||
*/
|
||||
module test_pcie_us_axil_master_64;
|
||||
|
||||
// Parameters
|
||||
parameter AXIS_PCIE_DATA_WIDTH = 64;
|
||||
parameter AXIS_PCIE_KEEP_WIDTH = (AXIS_PCIE_DATA_WIDTH/32);
|
||||
parameter AXI_DATA_WIDTH = 32;
|
||||
parameter AXI_ADDR_WIDTH = 64;
|
||||
parameter AXI_STRB_WIDTH = (AXI_DATA_WIDTH/8);
|
||||
parameter ENABLE_PARITY = 0;
|
||||
|
||||
// Inputs
|
||||
reg clk = 0;
|
||||
reg rst = 0;
|
||||
reg [7:0] current_test = 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_tvalid = 0;
|
||||
reg s_axis_cq_tlast = 0;
|
||||
reg [84:0] s_axis_cq_tuser = 0;
|
||||
reg m_axis_cc_tready = 0;
|
||||
reg m_axil_awready = 0;
|
||||
reg m_axil_wready = 0;
|
||||
reg [1:0] m_axil_bresp = 0;
|
||||
reg m_axil_bvalid = 0;
|
||||
reg m_axil_arready = 0;
|
||||
reg [AXI_DATA_WIDTH-1:0] m_axil_rdata = 0;
|
||||
reg [1:0] m_axil_rresp = 0;
|
||||
reg m_axil_rvalid = 0;
|
||||
reg [15:0] completer_id = 0;
|
||||
reg completer_id_enable = 0;
|
||||
|
||||
// Outputs
|
||||
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_tvalid;
|
||||
wire m_axis_cc_tlast;
|
||||
wire [32:0] m_axis_cc_tuser;
|
||||
wire [AXI_ADDR_WIDTH-1:0] m_axil_awaddr;
|
||||
wire [2:0] m_axil_awprot;
|
||||
wire m_axil_awvalid;
|
||||
wire [AXI_DATA_WIDTH-1:0] m_axil_wdata;
|
||||
wire [AXI_STRB_WIDTH-1:0] m_axil_wstrb;
|
||||
wire m_axil_wvalid;
|
||||
wire m_axil_bready;
|
||||
wire [AXI_ADDR_WIDTH-1:0] m_axil_araddr;
|
||||
wire [2:0] m_axil_arprot;
|
||||
wire m_axil_arvalid;
|
||||
wire m_axil_rready;
|
||||
wire status_error_cor;
|
||||
wire status_error_uncor;
|
||||
|
||||
initial begin
|
||||
// myhdl integration
|
||||
$from_myhdl(
|
||||
clk,
|
||||
rst,
|
||||
current_test,
|
||||
s_axis_cq_tdata,
|
||||
s_axis_cq_tkeep,
|
||||
s_axis_cq_tvalid,
|
||||
s_axis_cq_tlast,
|
||||
s_axis_cq_tuser,
|
||||
m_axis_cc_tready,
|
||||
m_axil_awready,
|
||||
m_axil_wready,
|
||||
m_axil_bresp,
|
||||
m_axil_bvalid,
|
||||
m_axil_arready,
|
||||
m_axil_rdata,
|
||||
m_axil_rresp,
|
||||
m_axil_rvalid,
|
||||
completer_id,
|
||||
completer_id_enable
|
||||
);
|
||||
$to_myhdl(
|
||||
s_axis_cq_tready,
|
||||
m_axis_cc_tdata,
|
||||
m_axis_cc_tkeep,
|
||||
m_axis_cc_tvalid,
|
||||
m_axis_cc_tlast,
|
||||
m_axis_cc_tuser,
|
||||
m_axil_awaddr,
|
||||
m_axil_awprot,
|
||||
m_axil_awvalid,
|
||||
m_axil_wdata,
|
||||
m_axil_wstrb,
|
||||
m_axil_wvalid,
|
||||
m_axil_bready,
|
||||
m_axil_araddr,
|
||||
m_axil_arprot,
|
||||
m_axil_arvalid,
|
||||
m_axil_rready,
|
||||
status_error_cor,
|
||||
status_error_uncor
|
||||
);
|
||||
|
||||
// dump file
|
||||
$dumpfile("test_pcie_us_axil_master_64.lxt");
|
||||
$dumpvars(0, test_pcie_us_axil_master_64);
|
||||
end
|
||||
|
||||
pcie_us_axil_master #(
|
||||
.AXIS_PCIE_DATA_WIDTH(AXIS_PCIE_DATA_WIDTH),
|
||||
.AXIS_PCIE_KEEP_WIDTH(AXIS_PCIE_KEEP_WIDTH),
|
||||
.AXI_DATA_WIDTH(AXI_DATA_WIDTH),
|
||||
.AXI_ADDR_WIDTH(AXI_ADDR_WIDTH),
|
||||
.AXI_STRB_WIDTH(AXI_STRB_WIDTH),
|
||||
.ENABLE_PARITY(ENABLE_PARITY)
|
||||
)
|
||||
UUT (
|
||||
.clk(clk),
|
||||
.rst(rst),
|
||||
.s_axis_cq_tdata(s_axis_cq_tdata),
|
||||
.s_axis_cq_tkeep(s_axis_cq_tkeep),
|
||||
.s_axis_cq_tvalid(s_axis_cq_tvalid),
|
||||
.s_axis_cq_tready(s_axis_cq_tready),
|
||||
.s_axis_cq_tlast(s_axis_cq_tlast),
|
||||
.s_axis_cq_tuser(s_axis_cq_tuser),
|
||||
.m_axis_cc_tdata(m_axis_cc_tdata),
|
||||
.m_axis_cc_tkeep(m_axis_cc_tkeep),
|
||||
.m_axis_cc_tvalid(m_axis_cc_tvalid),
|
||||
.m_axis_cc_tready(m_axis_cc_tready),
|
||||
.m_axis_cc_tlast(m_axis_cc_tlast),
|
||||
.m_axis_cc_tuser(m_axis_cc_tuser),
|
||||
.m_axil_awaddr(m_axil_awaddr),
|
||||
.m_axil_awprot(m_axil_awprot),
|
||||
.m_axil_awvalid(m_axil_awvalid),
|
||||
.m_axil_awready(m_axil_awready),
|
||||
.m_axil_wdata(m_axil_wdata),
|
||||
.m_axil_wstrb(m_axil_wstrb),
|
||||
.m_axil_wvalid(m_axil_wvalid),
|
||||
.m_axil_wready(m_axil_wready),
|
||||
.m_axil_bresp(m_axil_bresp),
|
||||
.m_axil_bvalid(m_axil_bvalid),
|
||||
.m_axil_bready(m_axil_bready),
|
||||
.m_axil_araddr(m_axil_araddr),
|
||||
.m_axil_arprot(m_axil_arprot),
|
||||
.m_axil_arvalid(m_axil_arvalid),
|
||||
.m_axil_arready(m_axil_arready),
|
||||
.m_axil_rdata(m_axil_rdata),
|
||||
.m_axil_rresp(m_axil_rresp),
|
||||
.m_axil_rvalid(m_axil_rvalid),
|
||||
.m_axil_rready(m_axil_rready),
|
||||
.completer_id(completer_id),
|
||||
.completer_id_enable(completer_id_enable),
|
||||
.status_error_cor(status_error_cor),
|
||||
.status_error_uncor(status_error_uncor)
|
||||
);
|
||||
|
||||
endmodule
|
Loading…
x
Reference in New Issue
Block a user