Migrate example design testbenches to cocotb
This commit is contained in:
parent
99e91c4d90
commit
cabad17552
@ -1 +0,0 @@
|
||||
../lib/pcie/tb/axis_ep.py
|
107
example/ADM_PCIE_9V3/fpga_axi_x8/tb/fpga_core/Makefile
Normal file
107
example/ADM_PCIE_9V3/fpga_axi_x8/tb/fpga_core/Makefile
Normal file
@ -0,0 +1,107 @@
|
||||
# Copyright (c) 2020 Alex Forencich
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in
|
||||
# all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
# THE SOFTWARE.
|
||||
|
||||
TOPLEVEL_LANG = verilog
|
||||
|
||||
SIM ?= icarus
|
||||
WAVES ?= 0
|
||||
|
||||
COCOTB_HDL_TIMEUNIT = 1ns
|
||||
COCOTB_HDL_TIMEPRECISION = 1ps
|
||||
|
||||
DUT = fpga_core
|
||||
TOPLEVEL = $(DUT)
|
||||
MODULE = test_$(DUT)
|
||||
VERILOG_SOURCES += ../../rtl/$(DUT).v
|
||||
VERILOG_SOURCES += ../../rtl/axi_ram.v
|
||||
VERILOG_SOURCES += ../../rtl/axis_register.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/axis_arb_mux.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_axil_master.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_axi_dma.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_axi_dma_rd.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_axi_dma_wr.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_tag_manager.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_axi_master.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_axi_master_rd.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_axi_master_wr.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_axis_cq_demux.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_cfg.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_msi.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/arbiter.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/priority_encoder.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pulse_merge.v
|
||||
|
||||
# module parameters
|
||||
export PARAM_AXIS_PCIE_DATA_WIDTH ?= 256
|
||||
export PARAM_AXIS_PCIE_KEEP_WIDTH ?= $(shell expr $(PARAM_AXIS_PCIE_DATA_WIDTH) / 32 )
|
||||
export PARAM_AXIS_PCIE_RQ_USER_WIDTH ?= $(if $(filter-out 512,$(PARAM_AXIS_PCIE_DATA_WIDTH)),62,137)
|
||||
export PARAM_AXIS_PCIE_RC_USER_WIDTH ?= $(if $(filter-out 512,$(PARAM_AXIS_PCIE_DATA_WIDTH)),75,161)
|
||||
export PARAM_AXIS_PCIE_CQ_USER_WIDTH ?= $(if $(filter-out 512,$(PARAM_AXIS_PCIE_DATA_WIDTH)),88,183)
|
||||
export PARAM_AXIS_PCIE_CC_USER_WIDTH ?= $(if $(filter-out 512,$(PARAM_AXIS_PCIE_DATA_WIDTH)),33,81)
|
||||
export PARAM_RQ_SEQ_NUM_WIDTH ?= 6
|
||||
|
||||
SIM_BUILD ?= sim_build_$(MODULE)
|
||||
|
||||
ifeq ($(SIM), icarus)
|
||||
PLUSARGS += -fst
|
||||
|
||||
COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_DATA_WIDTH=$(PARAM_AXIS_PCIE_DATA_WIDTH)
|
||||
COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_KEEP_WIDTH=$(PARAM_AXIS_PCIE_KEEP_WIDTH)
|
||||
COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_RQ_USER_WIDTH=$(PARAM_AXIS_PCIE_RQ_USER_WIDTH)
|
||||
COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_RC_USER_WIDTH=$(PARAM_AXIS_PCIE_RC_USER_WIDTH)
|
||||
COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_CQ_USER_WIDTH=$(PARAM_AXIS_PCIE_CQ_USER_WIDTH)
|
||||
COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_CC_USER_WIDTH=$(PARAM_AXIS_PCIE_CC_USER_WIDTH)
|
||||
COMPILE_ARGS += -P $(TOPLEVEL).RQ_SEQ_NUM_WIDTH=$(PARAM_RQ_SEQ_NUM_WIDTH)
|
||||
|
||||
ifeq ($(WAVES), 1)
|
||||
VERILOG_SOURCES += iverilog_dump.v
|
||||
COMPILE_ARGS += -s iverilog_dump
|
||||
endif
|
||||
else ifeq ($(SIM), verilator)
|
||||
COMPILE_ARGS += -Wno-SELRANGE -Wno-WIDTH
|
||||
|
||||
COMPILE_ARGS += -GAXIS_PCIE_DATA_WIDTH=$(PARAM_AXIS_PCIE_DATA_WIDTH)
|
||||
COMPILE_ARGS += -GAXIS_PCIE_KEEP_WIDTH=$(PARAM_AXIS_PCIE_KEEP_WIDTH)
|
||||
COMPILE_ARGS += -GAXIS_PCIE_RQ_USER_WIDTH=$(PARAM_AXIS_PCIE_RQ_USER_WIDTH)
|
||||
COMPILE_ARGS += -GAXIS_PCIE_RC_USER_WIDTH=$(PARAM_AXIS_PCIE_RC_USER_WIDTH)
|
||||
COMPILE_ARGS += -GAXIS_PCIE_CQ_USER_WIDTH=$(PARAM_AXIS_PCIE_CQ_USER_WIDTH)
|
||||
COMPILE_ARGS += -GAXIS_PCIE_CC_USER_WIDTH=$(PARAM_AXIS_PCIE_CC_USER_WIDTH)
|
||||
COMPILE_ARGS += -GRQ_SEQ_NUM_WIDTH=$(PARAM_RQ_SEQ_NUM_WIDTH)
|
||||
|
||||
ifeq ($(WAVES), 1)
|
||||
COMPILE_ARGS += --trace-fst
|
||||
endif
|
||||
endif
|
||||
|
||||
iverilog_dump.v:
|
||||
echo 'module iverilog_dump();' > $@
|
||||
echo 'initial begin' >> $@
|
||||
echo ' $$dumpfile("$(TOPLEVEL).fst");' >> $@
|
||||
echo ' $$dumpvars(0, $(TOPLEVEL));' >> $@
|
||||
echo 'end' >> $@
|
||||
echo 'endmodule' >> $@
|
||||
|
||||
clean::
|
||||
@rm -rf sim_build_*
|
||||
@rm -rf iverilog_dump.v
|
||||
@rm -rf dump.fst $(TOPLEVEL).fst
|
||||
|
||||
include $(shell cocotb-config --makefiles)/Makefile.sim
|
||||
|
378
example/ADM_PCIE_9V3/fpga_axi_x8/tb/fpga_core/test_fpga_core.py
Normal file
378
example/ADM_PCIE_9V3/fpga_axi_x8/tb/fpga_core/test_fpga_core.py
Normal file
@ -0,0 +1,378 @@
|
||||
"""
|
||||
|
||||
Copyright (c) 2020 Alex Forencich
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
"""
|
||||
|
||||
import logging
|
||||
import os
|
||||
|
||||
import cocotb_test.simulator
|
||||
|
||||
import cocotb
|
||||
from cocotb.log import SimLog
|
||||
from cocotb.triggers import RisingEdge, FallingEdge, Timer
|
||||
|
||||
from cocotbext.pcie.core import RootComplex
|
||||
from cocotbext.pcie.xilinx.us import UltraScalePlusPcieDevice
|
||||
from cocotbext.axi.utils import hexdump_str
|
||||
|
||||
|
||||
class TB(object):
|
||||
def __init__(self, dut):
|
||||
self.dut = dut
|
||||
|
||||
self.log = SimLog("cocotb.tb")
|
||||
self.log.setLevel(logging.DEBUG)
|
||||
|
||||
# PCIe
|
||||
self.rc = RootComplex()
|
||||
|
||||
self.dev = UltraScalePlusPcieDevice(
|
||||
# configuration options
|
||||
pcie_generation=3,
|
||||
pcie_link_width=8,
|
||||
user_clk_frequency=250e6,
|
||||
alignment="dword",
|
||||
cq_cc_straddle=False,
|
||||
rq_rc_straddle=False,
|
||||
rc_4tlp_straddle=False,
|
||||
enable_pf1=False,
|
||||
enable_client_tag=True,
|
||||
enable_extended_tag=True,
|
||||
enable_parity=False,
|
||||
enable_rx_msg_interface=False,
|
||||
enable_sriov=False,
|
||||
enable_extended_configuration=False,
|
||||
|
||||
enable_pf0_msi=True,
|
||||
enable_pf1_msi=False,
|
||||
|
||||
# signals
|
||||
# Clock and Reset Interface
|
||||
user_clk=dut.clk,
|
||||
user_reset=dut.rst,
|
||||
# user_lnk_up
|
||||
# sys_clk
|
||||
# sys_clk_gt
|
||||
# sys_reset
|
||||
# phy_rdy_out
|
||||
|
||||
# Requester reQuest Interface
|
||||
rq_entity=dut,
|
||||
rq_name="m_axis_rq",
|
||||
# pcie_rq_seq_num0=dut.s_axis_rq_seq_num_0,
|
||||
# pcie_rq_seq_num_vld0=dut.s_axis_rq_seq_num_valid_0,
|
||||
# pcie_rq_seq_num1=dut.s_axis_rq_seq_num_1,
|
||||
# pcie_rq_seq_num_vld1=dut.s_axis_rq_seq_num_valid_1,
|
||||
# pcie_rq_tag0
|
||||
# pcie_rq_tag1
|
||||
# pcie_rq_tag_av
|
||||
# pcie_rq_tag_vld0
|
||||
# pcie_rq_tag_vld1
|
||||
|
||||
# Requester Completion Interface
|
||||
rc_entity=dut,
|
||||
rc_name="s_axis_rc",
|
||||
|
||||
# Completer reQuest Interface
|
||||
cq_entity=dut,
|
||||
cq_name="s_axis_cq",
|
||||
# pcie_cq_np_req
|
||||
# pcie_cq_np_req_count
|
||||
|
||||
# Completer Completion Interface
|
||||
cc_entity=dut,
|
||||
cc_name="m_axis_cc",
|
||||
|
||||
# Transmit Flow Control Interface
|
||||
# pcie_tfc_nph_av=dut.pcie_tfc_nph_av,
|
||||
# pcie_tfc_npd_av=dut.pcie_tfc_npd_av,
|
||||
|
||||
# Configuration Management Interface
|
||||
cfg_mgmt_addr=dut.cfg_mgmt_addr,
|
||||
cfg_mgmt_function_number=dut.cfg_mgmt_function_number,
|
||||
cfg_mgmt_write=dut.cfg_mgmt_write,
|
||||
cfg_mgmt_write_data=dut.cfg_mgmt_write_data,
|
||||
cfg_mgmt_byte_enable=dut.cfg_mgmt_byte_enable,
|
||||
cfg_mgmt_read=dut.cfg_mgmt_read,
|
||||
cfg_mgmt_read_data=dut.cfg_mgmt_read_data,
|
||||
cfg_mgmt_read_write_done=dut.cfg_mgmt_read_write_done,
|
||||
# cfg_mgmt_debug_access
|
||||
|
||||
# Configuration Status Interface
|
||||
# cfg_phy_link_down
|
||||
# cfg_phy_link_status
|
||||
# cfg_negotiated_width
|
||||
# cfg_current_speed
|
||||
cfg_max_payload=dut.cfg_max_payload,
|
||||
cfg_max_read_req=dut.cfg_max_read_req,
|
||||
# cfg_function_status
|
||||
# cfg_vf_status
|
||||
# cfg_function_power_state
|
||||
# cfg_vf_power_state
|
||||
# cfg_link_power_state
|
||||
# cfg_err_cor_out
|
||||
# cfg_err_nonfatal_out
|
||||
# cfg_err_fatal_out
|
||||
# cfg_local_error_out
|
||||
# cfg_local_error_valid
|
||||
# cfg_rx_pm_state
|
||||
# cfg_tx_pm_state
|
||||
# cfg_ltssm_state
|
||||
# cfg_rcb_status
|
||||
# cfg_obff_enable
|
||||
# cfg_pl_status_change
|
||||
# cfg_tph_requester_enable
|
||||
# cfg_tph_st_mode
|
||||
# cfg_vf_tph_requester_enable
|
||||
# cfg_vf_tph_st_mode
|
||||
|
||||
# Configuration Received Message Interface
|
||||
# cfg_msg_received
|
||||
# cfg_msg_received_data
|
||||
# cfg_msg_received_type
|
||||
|
||||
# Configuration Transmit Message Interface
|
||||
# cfg_msg_transmit
|
||||
# cfg_msg_transmit_type
|
||||
# cfg_msg_transmit_data
|
||||
# cfg_msg_transmit_done
|
||||
|
||||
# Configuration Flow Control Interface
|
||||
# cfg_fc_ph=dut.cfg_fc_ph,
|
||||
# cfg_fc_pd=dut.cfg_fc_pd,
|
||||
# cfg_fc_nph=dut.cfg_fc_nph,
|
||||
# cfg_fc_npd=dut.cfg_fc_npd,
|
||||
# cfg_fc_cplh=dut.cfg_fc_cplh,
|
||||
# cfg_fc_cpld=dut.cfg_fc_cpld,
|
||||
# cfg_fc_sel=dut.cfg_fc_sel,
|
||||
|
||||
# Configuration Control Interface
|
||||
# cfg_hot_reset_in
|
||||
# cfg_hot_reset_out
|
||||
# cfg_config_space_enable
|
||||
# cfg_dsn
|
||||
# cfg_bus_number
|
||||
# cfg_ds_port_number
|
||||
# cfg_ds_bus_number
|
||||
# cfg_ds_device_number
|
||||
# cfg_ds_function_number
|
||||
# cfg_power_state_change_ack
|
||||
# cfg_power_state_change_interrupt
|
||||
cfg_err_cor_in=dut.status_error_cor,
|
||||
cfg_err_uncor_in=dut.status_error_uncor,
|
||||
# cfg_flr_in_process
|
||||
# cfg_flr_done
|
||||
# cfg_vf_flr_in_process
|
||||
# cfg_vf_flr_func_num
|
||||
# cfg_vf_flr_done
|
||||
# cfg_pm_aspm_l1_entry_reject
|
||||
# cfg_pm_aspm_tx_l0s_entry_disable
|
||||
# cfg_req_pm_transition_l23_ready
|
||||
# cfg_link_training_enable
|
||||
|
||||
# Configuration Interrupt Controller Interface
|
||||
# cfg_interrupt_int
|
||||
# cfg_interrupt_sent
|
||||
# cfg_interrupt_pending
|
||||
cfg_interrupt_msi_enable=dut.cfg_interrupt_msi_enable,
|
||||
cfg_interrupt_msi_mmenable=dut.cfg_interrupt_msi_mmenable,
|
||||
cfg_interrupt_msi_mask_update=dut.cfg_interrupt_msi_mask_update,
|
||||
cfg_interrupt_msi_data=dut.cfg_interrupt_msi_data,
|
||||
# cfg_interrupt_msi_select=dut.cfg_interrupt_msi_select,
|
||||
cfg_interrupt_msi_int=dut.cfg_interrupt_msi_int,
|
||||
cfg_interrupt_msi_pending_status=dut.cfg_interrupt_msi_pending_status,
|
||||
cfg_interrupt_msi_pending_status_data_enable=dut.cfg_interrupt_msi_pending_status_data_enable,
|
||||
# cfg_interrupt_msi_pending_status_function_num=dut.cfg_interrupt_msi_pending_status_function_num,
|
||||
cfg_interrupt_msi_sent=dut.cfg_interrupt_msi_sent,
|
||||
cfg_interrupt_msi_fail=dut.cfg_interrupt_msi_fail,
|
||||
# cfg_interrupt_msix_enable
|
||||
# cfg_interrupt_msix_mask
|
||||
# cfg_interrupt_msix_vf_enable
|
||||
# cfg_interrupt_msix_vf_mask
|
||||
# cfg_interrupt_msix_address
|
||||
# cfg_interrupt_msix_data
|
||||
# cfg_interrupt_msix_int
|
||||
# cfg_interrupt_msix_vec_pending
|
||||
# cfg_interrupt_msix_vec_pending_status
|
||||
cfg_interrupt_msi_attr=dut.cfg_interrupt_msi_attr,
|
||||
cfg_interrupt_msi_tph_present=dut.cfg_interrupt_msi_tph_present,
|
||||
cfg_interrupt_msi_tph_type=dut.cfg_interrupt_msi_tph_type,
|
||||
# cfg_interrupt_msi_tph_st_tag=dut.cfg_interrupt_msi_tph_st_tag,
|
||||
# cfg_interrupt_msi_function_number=dut.cfg_interrupt_msi_function_number,
|
||||
|
||||
# Configuration Extend Interface
|
||||
# cfg_ext_read_received
|
||||
# cfg_ext_write_received
|
||||
# cfg_ext_register_number
|
||||
# cfg_ext_function_number
|
||||
# cfg_ext_write_data
|
||||
# cfg_ext_write_byte_enable
|
||||
# cfg_ext_read_data
|
||||
# cfg_ext_read_data_valid
|
||||
)
|
||||
|
||||
# self.dev.log.setLevel(logging.DEBUG)
|
||||
|
||||
self.rc.make_port().connect(self.dev)
|
||||
|
||||
self.dev.functions[0].msi_multiple_message_capable = 5
|
||||
|
||||
self.dev.functions[0].configure_bar(0, 2**22)
|
||||
self.dev.functions[0].configure_bar(1, 2**22)
|
||||
|
||||
async def init(self):
|
||||
|
||||
await FallingEdge(self.dut.rst)
|
||||
await Timer(100, 'ns')
|
||||
|
||||
await self.rc.enumerate(enable_bus_mastering=True, configure_msi=True)
|
||||
|
||||
|
||||
@cocotb.test()
|
||||
async def run_test(dut):
|
||||
|
||||
tb = TB(dut)
|
||||
|
||||
await tb.init()
|
||||
|
||||
mem_base, mem_data = tb.rc.alloc_region(16*1024*1024)
|
||||
|
||||
dev_pf0_bar0 = tb.rc.tree[0][0].bar_addr[0]
|
||||
dev_pf0_bar1 = tb.rc.tree[0][0].bar_addr[1]
|
||||
|
||||
tb.log.info("Test memory write to BAR 1")
|
||||
|
||||
await tb.rc.mem_write(dev_pf0_bar1, b'\x11\x22\x33\x44')
|
||||
|
||||
await Timer(100, 'ns')
|
||||
|
||||
tb.log.info("Test memory read from BAR 1")
|
||||
|
||||
val = await tb.rc.mem_read(dev_pf0_bar1, 4, 1000)
|
||||
tb.log.info("Read data: %s", val)
|
||||
assert val == b'\x11\x22\x33\x44'
|
||||
|
||||
tb.log.info("Test DMA")
|
||||
|
||||
# write packet data
|
||||
mem_data[0:1024] = bytearray([x % 256 for x in range(1024)])
|
||||
|
||||
# enable DMA
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100000, 1)
|
||||
|
||||
# write pcie read descriptor
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100100, (mem_base+0x0000) & 0xffffffff)
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100104, (mem_base+0x0000 >> 32) & 0xffffffff)
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100108, (0x100) & 0xffffffff)
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x10010C, (0x100 >> 32) & 0xffffffff)
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100110, 0x400)
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100114, 0xAA)
|
||||
|
||||
await Timer(2000, 'ns')
|
||||
|
||||
# read status
|
||||
val = await tb.rc.mem_read_dword(dev_pf0_bar0+0x100118)
|
||||
tb.log.info("Status: 0x%x", val)
|
||||
assert val == 0xAA
|
||||
|
||||
# write pcie write descriptor
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100200, (mem_base+0x1000) & 0xffffffff)
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100204, (mem_base+0x1000 >> 32) & 0xffffffff)
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100208, (0x100) & 0xffffffff)
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x10020C, (0x100 >> 32) & 0xffffffff)
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100210, 0x400)
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100214, 0x55)
|
||||
|
||||
await Timer(2000, 'ns')
|
||||
|
||||
# read status
|
||||
val = await tb.rc.mem_read_dword(dev_pf0_bar0+0x100218)
|
||||
tb.log.info("Status: 0x%x", val)
|
||||
assert val == 0x55
|
||||
|
||||
tb.log.info("%s", hexdump_str(mem_data, 0x1000, 64))
|
||||
|
||||
assert mem_data[0:1024] == mem_data[0x1000:0x1000+1024]
|
||||
|
||||
await RisingEdge(dut.clk)
|
||||
await RisingEdge(dut.clk)
|
||||
|
||||
|
||||
# cocotb-test
|
||||
|
||||
tests_dir = os.path.dirname(__file__)
|
||||
rtl_dir = os.path.abspath(os.path.join(tests_dir, '..', '..', 'rtl'))
|
||||
lib_dir = os.path.abspath(os.path.join(rtl_dir, '..', 'lib'))
|
||||
pcie_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'pcie', 'rtl'))
|
||||
|
||||
|
||||
def test_fpga_core(request):
|
||||
dut = "fpga_core"
|
||||
module = os.path.splitext(os.path.basename(__file__))[0]
|
||||
toplevel = dut
|
||||
|
||||
verilog_sources = [
|
||||
os.path.join(rtl_dir, f"{dut}.v"),
|
||||
os.path.join(rtl_dir, "axi_ram.v"),
|
||||
os.path.join(rtl_dir, "axis_register.v"),
|
||||
os.path.join(pcie_rtl_dir, "axis_arb_mux.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_us_axil_master.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_us_axi_dma.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_us_axi_dma_rd.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_us_axi_dma_wr.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_tag_manager.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_us_axi_master.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_us_axi_master_rd.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_us_axi_master_wr.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_us_axis_cq_demux.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_us_cfg.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_us_msi.v"),
|
||||
os.path.join(pcie_rtl_dir, "arbiter.v"),
|
||||
os.path.join(pcie_rtl_dir, "priority_encoder.v"),
|
||||
os.path.join(pcie_rtl_dir, "pulse_merge.v"),
|
||||
]
|
||||
|
||||
parameters = {}
|
||||
|
||||
parameters['AXIS_PCIE_DATA_WIDTH'] = 256
|
||||
parameters['AXIS_PCIE_KEEP_WIDTH'] = parameters['AXIS_PCIE_DATA_WIDTH'] // 32
|
||||
parameters['AXIS_PCIE_RQ_USER_WIDTH'] = 62 if parameters['AXIS_PCIE_DATA_WIDTH'] < 512 else 137
|
||||
parameters['AXIS_PCIE_RC_USER_WIDTH'] = 75 if parameters['AXIS_PCIE_DATA_WIDTH'] < 512 else 161
|
||||
parameters['AXIS_PCIE_CQ_USER_WIDTH'] = 88 if parameters['AXIS_PCIE_DATA_WIDTH'] < 512 else 183
|
||||
parameters['AXIS_PCIE_CC_USER_WIDTH'] = 33 if parameters['AXIS_PCIE_DATA_WIDTH'] < 512 else 81
|
||||
parameters['RQ_SEQ_NUM_WIDTH'] = 6
|
||||
|
||||
extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()}
|
||||
|
||||
sim_build = os.path.join(tests_dir,
|
||||
"sim_build_"+request.node.name.replace('[', '-').replace(']', ''))
|
||||
|
||||
cocotb_test.simulator.run(
|
||||
python_search=[tests_dir],
|
||||
verilog_sources=verilog_sources,
|
||||
toplevel=toplevel,
|
||||
module=module,
|
||||
parameters=parameters,
|
||||
sim_build=sim_build,
|
||||
extra_env=extra_env,
|
||||
)
|
@ -1 +0,0 @@
|
||||
../lib/pcie/tb/pcie.py
|
@ -1 +0,0 @@
|
||||
../lib/pcie/tb/pcie_us.py
|
@ -1 +0,0 @@
|
||||
../lib/pcie/tb/pcie_usp.py
|
@ -1,512 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
"""
|
||||
|
||||
Copyright (c) 2018 Alex Forencich
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
"""
|
||||
|
||||
from myhdl import *
|
||||
import os
|
||||
import struct
|
||||
|
||||
import pcie
|
||||
import pcie_usp
|
||||
|
||||
module = 'fpga_core'
|
||||
testbench = 'test_%s' % module
|
||||
|
||||
srcs = []
|
||||
|
||||
srcs.append("../rtl/%s.v" % module)
|
||||
srcs.append("../rtl/axi_ram.v")
|
||||
srcs.append("../rtl/axis_register.v")
|
||||
srcs.append("../lib/pcie/rtl/axis_arb_mux.v")
|
||||
srcs.append("../lib/pcie/rtl/pcie_us_axil_master.v")
|
||||
srcs.append("../lib/pcie/rtl/pcie_us_axi_dma.v")
|
||||
srcs.append("../lib/pcie/rtl/pcie_us_axi_dma_rd.v")
|
||||
srcs.append("../lib/pcie/rtl/pcie_us_axi_dma_wr.v")
|
||||
srcs.append("../lib/pcie/rtl/pcie_tag_manager.v")
|
||||
srcs.append("../lib/pcie/rtl/pcie_us_axi_master.v")
|
||||
srcs.append("../lib/pcie/rtl/pcie_us_axi_master_rd.v")
|
||||
srcs.append("../lib/pcie/rtl/pcie_us_axi_master_wr.v")
|
||||
srcs.append("../lib/pcie/rtl/pcie_us_axis_cq_demux.v")
|
||||
srcs.append("../lib/pcie/rtl/pcie_us_cfg.v")
|
||||
srcs.append("../lib/pcie/rtl/pcie_us_msi.v")
|
||||
srcs.append("../lib/pcie/rtl/arbiter.v")
|
||||
srcs.append("../lib/pcie/rtl/priority_encoder.v")
|
||||
srcs.append("../lib/pcie/rtl/pulse_merge.v")
|
||||
srcs.append("%s.v" % testbench)
|
||||
|
||||
src = ' '.join(srcs)
|
||||
|
||||
build_cmd = "iverilog -o %s.vvp %s" % (testbench, src)
|
||||
|
||||
def bench():
|
||||
|
||||
# Parameters
|
||||
AXIS_PCIE_DATA_WIDTH = 256
|
||||
AXIS_PCIE_KEEP_WIDTH = (AXIS_PCIE_DATA_WIDTH/32)
|
||||
AXIS_PCIE_RC_USER_WIDTH = 75
|
||||
AXIS_PCIE_RQ_USER_WIDTH = 62
|
||||
AXIS_PCIE_CQ_USER_WIDTH = 88
|
||||
AXIS_PCIE_CC_USER_WIDTH = 33
|
||||
|
||||
# Inputs
|
||||
clk = Signal(bool(0))
|
||||
rst = Signal(bool(0))
|
||||
current_test = Signal(intbv(0)[8:])
|
||||
|
||||
m_axis_rq_tready = Signal(bool(0))
|
||||
s_axis_rc_tdata = Signal(intbv(0)[AXIS_PCIE_DATA_WIDTH:])
|
||||
s_axis_rc_tkeep = Signal(intbv(0)[AXIS_PCIE_KEEP_WIDTH:])
|
||||
s_axis_rc_tlast = Signal(bool(0))
|
||||
s_axis_rc_tuser = Signal(intbv(0)[AXIS_PCIE_RC_USER_WIDTH:])
|
||||
s_axis_rc_tvalid = Signal(bool(0))
|
||||
s_axis_cq_tdata = Signal(intbv(0)[AXIS_PCIE_DATA_WIDTH:])
|
||||
s_axis_cq_tkeep = Signal(intbv(0)[AXIS_PCIE_KEEP_WIDTH:])
|
||||
s_axis_cq_tlast = Signal(bool(0))
|
||||
s_axis_cq_tuser = Signal(intbv(0)[AXIS_PCIE_CQ_USER_WIDTH:])
|
||||
s_axis_cq_tvalid = Signal(bool(0))
|
||||
m_axis_cc_tready = Signal(bool(0))
|
||||
cfg_max_payload = Signal(intbv(0)[2:])
|
||||
cfg_max_read_req = Signal(intbv(0)[3:])
|
||||
cfg_mgmt_read_data = Signal(intbv(0)[32:])
|
||||
cfg_mgmt_read_write_done = Signal(bool(0))
|
||||
cfg_interrupt_msi_enable = Signal(intbv(0)[4:])
|
||||
cfg_interrupt_msi_mmenable = Signal(intbv(0)[12:])
|
||||
cfg_interrupt_msi_mask_update = Signal(bool(0))
|
||||
cfg_interrupt_msi_data = Signal(intbv(0)[32:])
|
||||
cfg_interrupt_msi_sent = Signal(bool(0))
|
||||
cfg_interrupt_msi_fail = Signal(bool(0))
|
||||
|
||||
# Outputs
|
||||
user_led_g = Signal(intbv(0)[2:])
|
||||
user_led_r = Signal(bool(0))
|
||||
front_led = Signal(intbv(0)[2:])
|
||||
m_axis_rq_tdata = Signal(intbv(0)[AXIS_PCIE_DATA_WIDTH:])
|
||||
m_axis_rq_tkeep = Signal(intbv(0)[AXIS_PCIE_KEEP_WIDTH:])
|
||||
m_axis_rq_tlast = Signal(bool(0))
|
||||
m_axis_rq_tuser = Signal(intbv(0)[AXIS_PCIE_RQ_USER_WIDTH:])
|
||||
m_axis_rq_tvalid = Signal(bool(0))
|
||||
s_axis_rc_tready = Signal(bool(0))
|
||||
s_axis_cq_tready = Signal(bool(0))
|
||||
m_axis_cc_tdata = Signal(intbv(0)[AXIS_PCIE_DATA_WIDTH:])
|
||||
m_axis_cc_tkeep = Signal(intbv(0)[AXIS_PCIE_KEEP_WIDTH:])
|
||||
m_axis_cc_tlast = Signal(bool(0))
|
||||
m_axis_cc_tuser = Signal(intbv(0)[AXIS_PCIE_CC_USER_WIDTH:])
|
||||
m_axis_cc_tvalid = Signal(bool(0))
|
||||
status_error_cor = Signal(bool(0))
|
||||
status_error_uncor = Signal(bool(0))
|
||||
cfg_mgmt_addr = Signal(intbv(0)[10:])
|
||||
cfg_mgmt_function_number = Signal(intbv(0)[8:])
|
||||
cfg_mgmt_write = Signal(bool(0))
|
||||
cfg_mgmt_write_data = Signal(intbv(0)[32:])
|
||||
cfg_mgmt_byte_enable = Signal(intbv(0)[4:])
|
||||
cfg_mgmt_read = Signal(bool(0))
|
||||
cfg_interrupt_msi_int = Signal(intbv(0)[32:])
|
||||
cfg_interrupt_msi_pending_status = Signal(intbv(0)[32:])
|
||||
cfg_interrupt_msi_select = Signal(intbv(0)[2:])
|
||||
cfg_interrupt_msi_pending_status_function_num = Signal(intbv(0)[2:])
|
||||
cfg_interrupt_msi_pending_status_data_enable = Signal(bool(0))
|
||||
cfg_interrupt_msi_attr = Signal(intbv(0)[3:])
|
||||
cfg_interrupt_msi_tph_present = Signal(bool(0))
|
||||
cfg_interrupt_msi_tph_type = Signal(intbv(0)[2:])
|
||||
cfg_interrupt_msi_tph_st_tag = Signal(intbv(0)[8:])
|
||||
cfg_interrupt_msi_function_number = Signal(intbv(0)[8:])
|
||||
|
||||
# Clock and Reset Interface
|
||||
user_clk=Signal(bool(0))
|
||||
user_reset=Signal(bool(0))
|
||||
sys_clk=Signal(bool(0))
|
||||
sys_reset=Signal(bool(0))
|
||||
|
||||
# PCIe devices
|
||||
rc = pcie.RootComplex()
|
||||
|
||||
mem_base, mem_data = rc.alloc_region(16*1024*1024)
|
||||
|
||||
dev = pcie_usp.UltrascalePlusPCIe()
|
||||
|
||||
dev.pcie_generation = 3
|
||||
dev.pcie_link_width = 8
|
||||
dev.user_clk_frequency = 250e6
|
||||
|
||||
dev.functions[0].msi_multiple_message_capable = 5
|
||||
|
||||
dev.functions[0].configure_bar(0, 4*1024*1024)
|
||||
dev.functions[0].configure_bar(1, 4*1024*1024)
|
||||
|
||||
rc.make_port().connect(dev)
|
||||
|
||||
pcie_logic = dev.create_logic(
|
||||
# Completer reQuest Interface
|
||||
m_axis_cq_tdata=s_axis_cq_tdata,
|
||||
m_axis_cq_tuser=s_axis_cq_tuser,
|
||||
m_axis_cq_tlast=s_axis_cq_tlast,
|
||||
m_axis_cq_tkeep=s_axis_cq_tkeep,
|
||||
m_axis_cq_tvalid=s_axis_cq_tvalid,
|
||||
m_axis_cq_tready=s_axis_cq_tready,
|
||||
#pcie_cq_np_req=pcie_cq_np_req,
|
||||
pcie_cq_np_req=Signal(intbv(1)[2:]),
|
||||
#pcie_cq_np_req_count=pcie_cq_np_req_count,
|
||||
|
||||
# Completer Completion Interface
|
||||
s_axis_cc_tdata=m_axis_cc_tdata,
|
||||
s_axis_cc_tuser=m_axis_cc_tuser,
|
||||
s_axis_cc_tlast=m_axis_cc_tlast,
|
||||
s_axis_cc_tkeep=m_axis_cc_tkeep,
|
||||
s_axis_cc_tvalid=m_axis_cc_tvalid,
|
||||
s_axis_cc_tready=m_axis_cc_tready,
|
||||
|
||||
# Requester reQuest Interface
|
||||
s_axis_rq_tdata=m_axis_rq_tdata,
|
||||
s_axis_rq_tuser=m_axis_rq_tuser,
|
||||
s_axis_rq_tlast=m_axis_rq_tlast,
|
||||
s_axis_rq_tkeep=m_axis_rq_tkeep,
|
||||
s_axis_rq_tvalid=m_axis_rq_tvalid,
|
||||
s_axis_rq_tready=m_axis_rq_tready,
|
||||
#pcie_rq_seq_num0=pcie_rq_seq_num0,
|
||||
#pcie_rq_seq_num_vld0=pcie_rq_seq_num_vld0,
|
||||
#pcie_rq_seq_num1=pcie_rq_seq_num1,
|
||||
#pcie_rq_seq_num_vld1=pcie_rq_seq_num_vld1,
|
||||
#pcie_rq_tag0=pcie_rq_tag0,
|
||||
#pcie_rq_tag1=pcie_rq_tag1,
|
||||
#pcie_rq_tag_av=pcie_rq_tag_av,
|
||||
#pcie_rq_tag_vld0=pcie_rq_tag_vld0,
|
||||
#pcie_rq_tag_vld1=pcie_rq_tag_vld1,
|
||||
|
||||
# Requester Completion Interface
|
||||
m_axis_rc_tdata=s_axis_rc_tdata,
|
||||
m_axis_rc_tuser=s_axis_rc_tuser,
|
||||
m_axis_rc_tlast=s_axis_rc_tlast,
|
||||
m_axis_rc_tkeep=s_axis_rc_tkeep,
|
||||
m_axis_rc_tvalid=s_axis_rc_tvalid,
|
||||
m_axis_rc_tready=s_axis_rc_tready,
|
||||
|
||||
# Transmit Flow Control Interface
|
||||
#pcie_tfc_nph_av=pcie_tfc_nph_av,
|
||||
#pcie_tfc_npd_av=pcie_tfc_npd_av,
|
||||
|
||||
# Configuration Management Interface
|
||||
cfg_mgmt_addr=cfg_mgmt_addr,
|
||||
cfg_mgmt_function_number=cfg_mgmt_function_number,
|
||||
cfg_mgmt_write=cfg_mgmt_write,
|
||||
cfg_mgmt_write_data=cfg_mgmt_write_data,
|
||||
cfg_mgmt_byte_enable=cfg_mgmt_byte_enable,
|
||||
cfg_mgmt_read=cfg_mgmt_read,
|
||||
cfg_mgmt_read_data=cfg_mgmt_read_data,
|
||||
cfg_mgmt_read_write_done=cfg_mgmt_read_write_done,
|
||||
#cfg_mgmt_debug_access=cfg_mgmt_debug_access,
|
||||
|
||||
# Configuration Status Interface
|
||||
#cfg_phy_link_down=cfg_phy_link_down,
|
||||
#cfg_phy_link_status=cfg_phy_link_status,
|
||||
#cfg_negotiated_width=cfg_negotiated_width,
|
||||
#cfg_current_speed=cfg_current_speed,
|
||||
cfg_max_payload=cfg_max_payload,
|
||||
cfg_max_read_req=cfg_max_read_req,
|
||||
#cfg_function_status=cfg_function_status,
|
||||
#cfg_vf_status=cfg_vf_status,
|
||||
#cfg_function_power_state=cfg_function_power_state,
|
||||
#cfg_vf_power_state=cfg_vf_power_state,
|
||||
#cfg_link_power_state=cfg_link_power_state,
|
||||
#cfg_err_cor_out=cfg_err_cor_out,
|
||||
#cfg_err_nonfatal_out=cfg_err_nonfatal_out,
|
||||
#cfg_err_fatal_out=cfg_err_fatal_out,
|
||||
#cfg_local_err_out=cfg_local_err_out,
|
||||
#cfg_local_err_valid=cfg_local_err_valid,
|
||||
#cfg_rx_pm_state=cfg_rx_pm_state,
|
||||
#cfg_tx_pm_state=cfg_tx_pm_state,
|
||||
#cfg_ltssm_state=cfg_ltssm_state,
|
||||
#cfg_rcb_status=cfg_rcb_status,
|
||||
#cfg_obff_enable=cfg_obff_enable,
|
||||
#cfg_pl_status_change=cfg_pl_status_change,
|
||||
#cfg_tph_requester_enable=cfg_tph_requester_enable,
|
||||
#cfg_tph_st_mode=cfg_tph_st_mode,
|
||||
#cfg_vf_tph_requester_enable=cfg_vf_tph_requester_enable,
|
||||
#cfg_vf_tph_st_mode=cfg_vf_tph_st_mode,
|
||||
|
||||
# Configuration Received Message Interface
|
||||
#cfg_msg_received=cfg_msg_received,
|
||||
#cfg_msg_received_data=cfg_msg_received_data,
|
||||
#cfg_msg_received_type=cfg_msg_received_type,
|
||||
|
||||
# Configuration Transmit Message Interface
|
||||
#cfg_msg_transmit=cfg_msg_transmit,
|
||||
#cfg_msg_transmit_type=cfg_msg_transmit_type,
|
||||
#cfg_msg_transmit_data=cfg_msg_transmit_data,
|
||||
#cfg_msg_transmit_done=cfg_msg_transmit_done,
|
||||
|
||||
# Configuration Flow Control Interface
|
||||
#cfg_fc_ph=cfg_fc_ph,
|
||||
#cfg_fc_pd=cfg_fc_pd,
|
||||
#cfg_fc_nph=cfg_fc_nph,
|
||||
#cfg_fc_npd=cfg_fc_npd,
|
||||
#cfg_fc_cplh=cfg_fc_cplh,
|
||||
#cfg_fc_cpld=cfg_fc_cpld,
|
||||
#cfg_fc_sel=cfg_fc_sel,
|
||||
|
||||
# Configuration Control Interface
|
||||
#cfg_hot_reset_in=cfg_hot_reset_in,
|
||||
#cfg_hot_reset_out=cfg_hot_reset_out,
|
||||
#cfg_config_space_enable=cfg_config_space_enable,
|
||||
#cfg_dsn=cfg_dsn,
|
||||
#cfg_ds_port_number=cfg_ds_port_number,
|
||||
#cfg_ds_bus_number=cfg_ds_bus_number,
|
||||
#cfg_ds_device_number=cfg_ds_device_number,
|
||||
#cfg_ds_function_number=cfg_ds_function_number,
|
||||
#cfg_power_state_change_ack=cfg_power_state_change_ack,
|
||||
#cfg_power_state_change_interrupt=cfg_power_state_change_interrupt,
|
||||
cfg_err_cor_in=status_error_cor,
|
||||
cfg_err_uncor_in=status_error_uncor,
|
||||
#cfg_flr_done=cfg_flr_done,
|
||||
#cfg_vf_flr_done=cfg_vf_flr_done,
|
||||
#cfg_flr_in_process=cfg_flr_in_process,
|
||||
#cfg_vf_flr_in_process=cfg_vf_flr_in_process,
|
||||
#cfg_req_pm_transition_l23_ready=cfg_req_pm_transition_l23_ready,
|
||||
#cfg_link_training_enable=cfg_link_training_enable,
|
||||
|
||||
# Configuration Interrupt Controller Interface
|
||||
#cfg_interrupt_int=cfg_interrupt_int,
|
||||
#cfg_interrupt_sent=cfg_interrupt_sent,
|
||||
#cfg_interrupt_pending=cfg_interrupt_pending,
|
||||
cfg_interrupt_msi_enable=cfg_interrupt_msi_enable,
|
||||
cfg_interrupt_msi_mmenable=cfg_interrupt_msi_mmenable,
|
||||
cfg_interrupt_msi_mask_update=cfg_interrupt_msi_mask_update,
|
||||
cfg_interrupt_msi_data=cfg_interrupt_msi_data,
|
||||
cfg_interrupt_msi_select=cfg_interrupt_msi_select,
|
||||
cfg_interrupt_msi_int=cfg_interrupt_msi_int,
|
||||
cfg_interrupt_msi_pending_status=cfg_interrupt_msi_pending_status,
|
||||
cfg_interrupt_msi_pending_status_data_enable=cfg_interrupt_msi_pending_status_data_enable,
|
||||
cfg_interrupt_msi_pending_status_function_num=cfg_interrupt_msi_pending_status_function_num,
|
||||
cfg_interrupt_msi_sent=cfg_interrupt_msi_sent,
|
||||
cfg_interrupt_msi_fail=cfg_interrupt_msi_fail,
|
||||
#cfg_interrupt_msix_enable=cfg_interrupt_msix_enable,
|
||||
#cfg_interrupt_msix_mask=cfg_interrupt_msix_mask,
|
||||
#cfg_interrupt_msix_vf_enable=cfg_interrupt_msix_vf_enable,
|
||||
#cfg_interrupt_msix_vf_mask=cfg_interrupt_msix_vf_mask,
|
||||
#cfg_interrupt_msix_address=cfg_interrupt_msix_address,
|
||||
#cfg_interrupt_msix_data=cfg_interrupt_msix_data,
|
||||
#cfg_interrupt_msix_int=cfg_interrupt_msix_int,
|
||||
#cfg_interrupt_msix_vec_pending=cfg_interrupt_msix_vec_pending,
|
||||
#cfg_interrupt_msix_vec_pending_status=cfg_interrupt_msix_vec_pending_status,
|
||||
cfg_interrupt_msi_attr=cfg_interrupt_msi_attr,
|
||||
cfg_interrupt_msi_tph_present=cfg_interrupt_msi_tph_present,
|
||||
cfg_interrupt_msi_tph_type=cfg_interrupt_msi_tph_type,
|
||||
cfg_interrupt_msi_tph_st_tag=cfg_interrupt_msi_tph_st_tag,
|
||||
cfg_interrupt_msi_function_number=cfg_interrupt_msi_function_number,
|
||||
|
||||
# Configuration Extend Interface
|
||||
#cfg_ext_read_received=cfg_ext_read_received,
|
||||
#cfg_ext_write_received=cfg_ext_write_received,
|
||||
#cfg_ext_register_number=cfg_ext_register_number,
|
||||
#cfg_ext_function_number=cfg_ext_function_number,
|
||||
#cfg_ext_write_data=cfg_ext_write_data,
|
||||
#cfg_ext_write_byte_enable=cfg_ext_write_byte_enable,
|
||||
#cfg_ext_read_data=cfg_ext_read_data,
|
||||
#cfg_ext_read_data_valid=cfg_ext_read_data_valid,
|
||||
|
||||
# Clock and Reset Interface
|
||||
user_clk=user_clk,
|
||||
user_reset=user_reset,
|
||||
#user_lnk_up=user_lnk_up,
|
||||
sys_clk=sys_clk,
|
||||
sys_clk_gt=sys_clk,
|
||||
sys_reset=sys_reset,
|
||||
#phy_rdy_out=phy_rdy_out
|
||||
)
|
||||
|
||||
# DUT
|
||||
if os.system(build_cmd):
|
||||
raise Exception("Error running build command")
|
||||
|
||||
dut = Cosimulation(
|
||||
"vvp -m myhdl %s.vvp -lxt2" % testbench,
|
||||
clk=user_clk,
|
||||
rst=user_reset,
|
||||
current_test=current_test,
|
||||
user_led_g=user_led_g,
|
||||
user_led_r=user_led_r,
|
||||
front_led=front_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_function_number=cfg_mgmt_function_number,
|
||||
cfg_mgmt_write=cfg_mgmt_write,
|
||||
cfg_mgmt_write_data=cfg_mgmt_write_data,
|
||||
cfg_mgmt_byte_enable=cfg_mgmt_byte_enable,
|
||||
cfg_mgmt_read=cfg_mgmt_read,
|
||||
cfg_mgmt_read_data=cfg_mgmt_read_data,
|
||||
cfg_mgmt_read_write_done=cfg_mgmt_read_write_done,
|
||||
cfg_interrupt_msi_enable=cfg_interrupt_msi_enable,
|
||||
cfg_interrupt_msi_int=cfg_interrupt_msi_int,
|
||||
cfg_interrupt_msi_sent=cfg_interrupt_msi_sent,
|
||||
cfg_interrupt_msi_fail=cfg_interrupt_msi_fail,
|
||||
cfg_interrupt_msi_mmenable=cfg_interrupt_msi_mmenable,
|
||||
cfg_interrupt_msi_pending_status=cfg_interrupt_msi_pending_status,
|
||||
cfg_interrupt_msi_mask_update=cfg_interrupt_msi_mask_update,
|
||||
cfg_interrupt_msi_select=cfg_interrupt_msi_select,
|
||||
cfg_interrupt_msi_data=cfg_interrupt_msi_data,
|
||||
cfg_interrupt_msi_pending_status_function_num=cfg_interrupt_msi_pending_status_function_num,
|
||||
cfg_interrupt_msi_pending_status_data_enable=cfg_interrupt_msi_pending_status_data_enable,
|
||||
cfg_interrupt_msi_attr=cfg_interrupt_msi_attr,
|
||||
cfg_interrupt_msi_tph_present=cfg_interrupt_msi_tph_present,
|
||||
cfg_interrupt_msi_tph_type=cfg_interrupt_msi_tph_type,
|
||||
cfg_interrupt_msi_tph_st_tag=cfg_interrupt_msi_tph_st_tag,
|
||||
cfg_interrupt_msi_function_number=cfg_interrupt_msi_function_number,
|
||||
status_error_cor=status_error_cor,
|
||||
status_error_uncor=status_error_uncor
|
||||
)
|
||||
|
||||
@always(delay(5))
|
||||
def clkgen():
|
||||
clk.next = not clk
|
||||
|
||||
@always_comb
|
||||
def clk_logic():
|
||||
sys_clk.next = clk
|
||||
sys_reset.next = not rst
|
||||
|
||||
@instance
|
||||
def check():
|
||||
yield delay(100)
|
||||
yield clk.posedge
|
||||
rst.next = 1
|
||||
yield clk.posedge
|
||||
rst.next = 0
|
||||
yield clk.posedge
|
||||
yield delay(100)
|
||||
yield clk.posedge
|
||||
|
||||
# testbench stimulus
|
||||
|
||||
current_tag = 1
|
||||
|
||||
yield clk.posedge
|
||||
print("test 1: enumeration")
|
||||
current_test.next = 1
|
||||
|
||||
yield rc.enumerate(enable_bus_mastering=True, configure_msi=True)
|
||||
|
||||
dev_pf0_bar0 = dev.functions[0].bar[0] & 0xfffffffc
|
||||
dev_pf0_bar1 = dev.functions[0].bar[1] & 0xfffffffc
|
||||
|
||||
yield delay(100)
|
||||
|
||||
yield clk.posedge
|
||||
print("test 2: memory write to bar 1")
|
||||
current_test.next = 2
|
||||
|
||||
yield rc.mem_write(dev_pf0_bar1, b'\x11\x22\x33\x44')
|
||||
|
||||
yield delay(100)
|
||||
|
||||
yield clk.posedge
|
||||
print("test 3: memory read from bar 1")
|
||||
current_test.next = 3
|
||||
|
||||
val = yield from rc.mem_read(dev_pf0_bar1, 4, 1000)
|
||||
print(val)
|
||||
assert val == b'\x11\x22\x33\x44'
|
||||
|
||||
yield delay(100)
|
||||
|
||||
yield clk.posedge
|
||||
print("test 4: test DMA")
|
||||
current_test.next = 4
|
||||
|
||||
# write packet data
|
||||
mem_data[0:1024] = bytearray([x%256 for x in range(1024)])
|
||||
|
||||
# enable DMA
|
||||
yield rc.mem_write(dev_pf0_bar0+0x100000, struct.pack('<L', 1))
|
||||
|
||||
# write pcie read descriptor
|
||||
yield rc.mem_write(dev_pf0_bar0+0x100100, struct.pack('<L', (mem_base+0x0000) & 0xffffffff))
|
||||
yield rc.mem_write(dev_pf0_bar0+0x100104, struct.pack('<L', (mem_base+0x0000 >> 32) & 0xffffffff))
|
||||
yield rc.mem_write(dev_pf0_bar0+0x100108, struct.pack('<L', (0x100) & 0xffffffff))
|
||||
yield rc.mem_write(dev_pf0_bar0+0x10010C, struct.pack('<L', (0x100 >> 32) & 0xffffffff))
|
||||
yield rc.mem_write(dev_pf0_bar0+0x100110, struct.pack('<L', 0x400))
|
||||
yield rc.mem_write(dev_pf0_bar0+0x100114, struct.pack('<L', 0xAA))
|
||||
|
||||
yield delay(2000)
|
||||
|
||||
# read status
|
||||
val = yield from rc.mem_read(dev_pf0_bar0+0x100118, 4)
|
||||
print(val)
|
||||
|
||||
# write pcie write descriptor
|
||||
yield rc.mem_write(dev_pf0_bar0+0x100200, struct.pack('<L', (mem_base+0x1000) & 0xffffffff))
|
||||
yield rc.mem_write(dev_pf0_bar0+0x100204, struct.pack('<L', (mem_base+0x1000 >> 32) & 0xffffffff))
|
||||
yield rc.mem_write(dev_pf0_bar0+0x100208, struct.pack('<L', (0x100) & 0xffffffff))
|
||||
yield rc.mem_write(dev_pf0_bar0+0x10020C, struct.pack('<L', (0x100 >> 32) & 0xffffffff))
|
||||
yield rc.mem_write(dev_pf0_bar0+0x100210, struct.pack('<L', 0x400))
|
||||
yield rc.mem_write(dev_pf0_bar0+0x100214, struct.pack('<L', 0x55))
|
||||
|
||||
yield delay(2000)
|
||||
|
||||
# read status
|
||||
val = yield from rc.mem_read(dev_pf0_bar0+0x100218, 4)
|
||||
print(val)
|
||||
|
||||
data = mem_data[0x1000:(0x1000)+64]
|
||||
for i in range(0, len(data), 16):
|
||||
print(" ".join(("{:02x}".format(c) for c in bytearray(data[i:i+16]))))
|
||||
|
||||
assert mem_data[0:1024] == mem_data[0x1000:0x1000+1024]
|
||||
|
||||
yield delay(100)
|
||||
|
||||
raise StopSimulation
|
||||
|
||||
return instances()
|
||||
|
||||
def test_bench():
|
||||
sim = Simulation(bench())
|
||||
sim.run()
|
||||
|
||||
if __name__ == '__main__':
|
||||
print("Running test...")
|
||||
test_bench()
|
@ -1,243 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2018 Alex Forencich
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
// Language: Verilog 2001
|
||||
|
||||
`timescale 1ns / 1ps
|
||||
|
||||
/*
|
||||
* Testbench for fpga_core
|
||||
*/
|
||||
module test_fpga_core;
|
||||
|
||||
// Parameters
|
||||
parameter AXIS_PCIE_DATA_WIDTH = 256;
|
||||
parameter AXIS_PCIE_KEEP_WIDTH = (AXIS_PCIE_DATA_WIDTH/32);
|
||||
parameter AXIS_PCIE_RC_USER_WIDTH = 75;
|
||||
parameter AXIS_PCIE_RQ_USER_WIDTH = 62;
|
||||
parameter AXIS_PCIE_CQ_USER_WIDTH = 88;
|
||||
parameter AXIS_PCIE_CC_USER_WIDTH = 33;
|
||||
|
||||
// Inputs
|
||||
reg clk = 0;
|
||||
reg rst = 0;
|
||||
reg [7:0] current_test = 0;
|
||||
|
||||
reg m_axis_rq_tready = 0;
|
||||
reg [AXIS_PCIE_DATA_WIDTH-1:0] s_axis_rc_tdata = 0;
|
||||
reg [AXIS_PCIE_KEEP_WIDTH-1:0] s_axis_rc_tkeep = 0;
|
||||
reg s_axis_rc_tlast = 0;
|
||||
reg [AXIS_PCIE_RC_USER_WIDTH-1:0] s_axis_rc_tuser = 0;
|
||||
reg s_axis_rc_tvalid = 0;
|
||||
reg [AXIS_PCIE_DATA_WIDTH-1:0] s_axis_cq_tdata = 0;
|
||||
reg [AXIS_PCIE_KEEP_WIDTH-1:0] s_axis_cq_tkeep = 0;
|
||||
reg s_axis_cq_tlast = 0;
|
||||
reg [AXIS_PCIE_CQ_USER_WIDTH-1:0] s_axis_cq_tuser = 0;
|
||||
reg s_axis_cq_tvalid = 0;
|
||||
reg m_axis_cc_tready = 0;
|
||||
reg [2:0] cfg_max_payload = 0;
|
||||
reg [2:0] cfg_max_read_req = 0;
|
||||
reg [31:0] cfg_mgmt_read_data = 0;
|
||||
reg cfg_mgmt_read_write_done = 0;
|
||||
reg [3:0] cfg_interrupt_msi_enable = 0;
|
||||
reg [11:0] cfg_interrupt_msi_mmenable = 0;
|
||||
reg cfg_interrupt_msi_mask_update = 0;
|
||||
reg [31:0] cfg_interrupt_msi_data = 0;
|
||||
reg cfg_interrupt_msi_sent = 0;
|
||||
reg cfg_interrupt_msi_fail = 0;
|
||||
|
||||
// Outputs
|
||||
wire [1:0] user_led_g;
|
||||
wire user_led_r;
|
||||
wire [1:0] front_led;
|
||||
wire [AXIS_PCIE_DATA_WIDTH-1:0] m_axis_rq_tdata;
|
||||
wire [AXIS_PCIE_KEEP_WIDTH-1:0] m_axis_rq_tkeep;
|
||||
wire m_axis_rq_tlast;
|
||||
wire [AXIS_PCIE_RQ_USER_WIDTH-1:0] m_axis_rq_tuser;
|
||||
wire m_axis_rq_tvalid;
|
||||
wire s_axis_rc_tready;
|
||||
wire s_axis_cq_tready;
|
||||
wire [AXIS_PCIE_DATA_WIDTH-1:0] m_axis_cc_tdata;
|
||||
wire [AXIS_PCIE_KEEP_WIDTH-1:0] m_axis_cc_tkeep;
|
||||
wire m_axis_cc_tlast;
|
||||
wire [AXIS_PCIE_CC_USER_WIDTH-1:0] m_axis_cc_tuser;
|
||||
wire m_axis_cc_tvalid;
|
||||
wire [9:0] cfg_mgmt_addr;
|
||||
wire [7:0] cfg_mgmt_function_number;
|
||||
wire cfg_mgmt_write;
|
||||
wire [31:0] cfg_mgmt_write_data;
|
||||
wire [3:0] cfg_mgmt_byte_enable;
|
||||
wire cfg_mgmt_read;
|
||||
wire [3:0] cfg_interrupt_msi_select;
|
||||
wire [31:0] cfg_interrupt_msi_int;
|
||||
wire [31:0] cfg_interrupt_msi_pending_status;
|
||||
wire cfg_interrupt_msi_pending_status_data_enable;
|
||||
wire [3:0] cfg_interrupt_msi_pending_status_function_num;
|
||||
wire [2:0] cfg_interrupt_msi_attr;
|
||||
wire cfg_interrupt_msi_tph_present;
|
||||
wire [1:0] cfg_interrupt_msi_tph_type;
|
||||
wire [8:0] cfg_interrupt_msi_tph_st_tag;
|
||||
wire [3:0] cfg_interrupt_msi_function_number;
|
||||
wire status_error_cor;
|
||||
wire status_error_uncor;
|
||||
|
||||
initial begin
|
||||
// myhdl integration
|
||||
$from_myhdl(
|
||||
clk,
|
||||
rst,
|
||||
current_test,
|
||||
m_axis_rq_tready,
|
||||
s_axis_rc_tdata,
|
||||
s_axis_rc_tkeep,
|
||||
s_axis_rc_tlast,
|
||||
s_axis_rc_tuser,
|
||||
s_axis_rc_tvalid,
|
||||
s_axis_cq_tdata,
|
||||
s_axis_cq_tkeep,
|
||||
s_axis_cq_tlast,
|
||||
s_axis_cq_tuser,
|
||||
s_axis_cq_tvalid,
|
||||
m_axis_cc_tready,
|
||||
cfg_max_payload,
|
||||
cfg_max_read_req,
|
||||
cfg_mgmt_read_data,
|
||||
cfg_mgmt_read_write_done,
|
||||
cfg_interrupt_msi_enable,
|
||||
cfg_interrupt_msi_mmenable,
|
||||
cfg_interrupt_msi_mask_update,
|
||||
cfg_interrupt_msi_data,
|
||||
cfg_interrupt_msi_sent,
|
||||
cfg_interrupt_msi_fail
|
||||
);
|
||||
$to_myhdl(
|
||||
user_led_g,
|
||||
user_led_r,
|
||||
front_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_function_number,
|
||||
cfg_mgmt_write,
|
||||
cfg_mgmt_write_data,
|
||||
cfg_mgmt_byte_enable,
|
||||
cfg_mgmt_read,
|
||||
cfg_interrupt_msi_select,
|
||||
cfg_interrupt_msi_int,
|
||||
cfg_interrupt_msi_pending_status,
|
||||
cfg_interrupt_msi_pending_status_data_enable,
|
||||
cfg_interrupt_msi_pending_status_function_num,
|
||||
cfg_interrupt_msi_attr,
|
||||
cfg_interrupt_msi_tph_present,
|
||||
cfg_interrupt_msi_tph_type,
|
||||
cfg_interrupt_msi_tph_st_tag,
|
||||
cfg_interrupt_msi_function_number,
|
||||
status_error_cor,
|
||||
status_error_uncor
|
||||
);
|
||||
|
||||
// dump file
|
||||
$dumpfile("test_fpga_core.lxt");
|
||||
$dumpvars(0, test_fpga_core);
|
||||
end
|
||||
|
||||
fpga_core #(
|
||||
.AXIS_PCIE_DATA_WIDTH(AXIS_PCIE_DATA_WIDTH),
|
||||
.AXIS_PCIE_KEEP_WIDTH(AXIS_PCIE_KEEP_WIDTH),
|
||||
.AXIS_PCIE_RC_USER_WIDTH(AXIS_PCIE_RC_USER_WIDTH),
|
||||
.AXIS_PCIE_RQ_USER_WIDTH(AXIS_PCIE_RQ_USER_WIDTH),
|
||||
.AXIS_PCIE_CQ_USER_WIDTH(AXIS_PCIE_CQ_USER_WIDTH),
|
||||
.AXIS_PCIE_CC_USER_WIDTH(AXIS_PCIE_CC_USER_WIDTH)
|
||||
)
|
||||
UUT (
|
||||
.clk(clk),
|
||||
.rst(rst),
|
||||
.user_led_g(user_led_g),
|
||||
.user_led_r(user_led_r),
|
||||
.front_led(front_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_function_number(cfg_mgmt_function_number),
|
||||
.cfg_mgmt_write(cfg_mgmt_write),
|
||||
.cfg_mgmt_write_data(cfg_mgmt_write_data),
|
||||
.cfg_mgmt_byte_enable(cfg_mgmt_byte_enable),
|
||||
.cfg_mgmt_read(cfg_mgmt_read),
|
||||
.cfg_mgmt_read_data(cfg_mgmt_read_data),
|
||||
.cfg_mgmt_read_write_done(cfg_mgmt_read_write_done),
|
||||
.cfg_interrupt_msi_enable(cfg_interrupt_msi_enable),
|
||||
.cfg_interrupt_msi_mmenable(cfg_interrupt_msi_mmenable),
|
||||
.cfg_interrupt_msi_mask_update(cfg_interrupt_msi_mask_update),
|
||||
.cfg_interrupt_msi_data(cfg_interrupt_msi_data),
|
||||
.cfg_interrupt_msi_select(cfg_interrupt_msi_select),
|
||||
.cfg_interrupt_msi_int(cfg_interrupt_msi_int),
|
||||
.cfg_interrupt_msi_pending_status(cfg_interrupt_msi_pending_status),
|
||||
.cfg_interrupt_msi_pending_status_data_enable(cfg_interrupt_msi_pending_status_data_enable),
|
||||
.cfg_interrupt_msi_pending_status_function_num(cfg_interrupt_msi_pending_status_function_num),
|
||||
.cfg_interrupt_msi_sent(cfg_interrupt_msi_sent),
|
||||
.cfg_interrupt_msi_fail(cfg_interrupt_msi_fail),
|
||||
.cfg_interrupt_msi_attr(cfg_interrupt_msi_attr),
|
||||
.cfg_interrupt_msi_tph_present(cfg_interrupt_msi_tph_present),
|
||||
.cfg_interrupt_msi_tph_type(cfg_interrupt_msi_tph_type),
|
||||
.cfg_interrupt_msi_tph_st_tag(cfg_interrupt_msi_tph_st_tag),
|
||||
.cfg_interrupt_msi_function_number(cfg_interrupt_msi_function_number),
|
||||
.status_error_cor(status_error_cor),
|
||||
.status_error_uncor(status_error_uncor)
|
||||
);
|
||||
|
||||
endmodule
|
@ -1 +0,0 @@
|
||||
../lib/pcie/tb/axis_ep.py
|
107
example/AU200/fpga_axi/tb/fpga_core/Makefile
Normal file
107
example/AU200/fpga_axi/tb/fpga_core/Makefile
Normal file
@ -0,0 +1,107 @@
|
||||
# Copyright (c) 2020 Alex Forencich
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in
|
||||
# all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
# THE SOFTWARE.
|
||||
|
||||
TOPLEVEL_LANG = verilog
|
||||
|
||||
SIM ?= icarus
|
||||
WAVES ?= 0
|
||||
|
||||
COCOTB_HDL_TIMEUNIT = 1ns
|
||||
COCOTB_HDL_TIMEPRECISION = 1ps
|
||||
|
||||
DUT = fpga_core
|
||||
TOPLEVEL = $(DUT)
|
||||
MODULE = test_$(DUT)
|
||||
VERILOG_SOURCES += ../../rtl/$(DUT).v
|
||||
VERILOG_SOURCES += ../../rtl/axi_ram.v
|
||||
VERILOG_SOURCES += ../../rtl/axis_register.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/axis_arb_mux.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_axil_master.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_axi_dma.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_axi_dma_rd.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_axi_dma_wr.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_tag_manager.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_axi_master.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_axi_master_rd.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_axi_master_wr.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_axis_cq_demux.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_cfg.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_msi.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/arbiter.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/priority_encoder.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pulse_merge.v
|
||||
|
||||
# module parameters
|
||||
export PARAM_AXIS_PCIE_DATA_WIDTH ?= 512
|
||||
export PARAM_AXIS_PCIE_KEEP_WIDTH ?= $(shell expr $(PARAM_AXIS_PCIE_DATA_WIDTH) / 32 )
|
||||
export PARAM_AXIS_PCIE_RQ_USER_WIDTH ?= $(if $(filter-out 512,$(PARAM_AXIS_PCIE_DATA_WIDTH)),62,137)
|
||||
export PARAM_AXIS_PCIE_RC_USER_WIDTH ?= $(if $(filter-out 512,$(PARAM_AXIS_PCIE_DATA_WIDTH)),75,161)
|
||||
export PARAM_AXIS_PCIE_CQ_USER_WIDTH ?= $(if $(filter-out 512,$(PARAM_AXIS_PCIE_DATA_WIDTH)),88,183)
|
||||
export PARAM_AXIS_PCIE_CC_USER_WIDTH ?= $(if $(filter-out 512,$(PARAM_AXIS_PCIE_DATA_WIDTH)),33,81)
|
||||
export PARAM_RQ_SEQ_NUM_WIDTH ?= 6
|
||||
|
||||
SIM_BUILD ?= sim_build_$(MODULE)
|
||||
|
||||
ifeq ($(SIM), icarus)
|
||||
PLUSARGS += -fst
|
||||
|
||||
COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_DATA_WIDTH=$(PARAM_AXIS_PCIE_DATA_WIDTH)
|
||||
COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_KEEP_WIDTH=$(PARAM_AXIS_PCIE_KEEP_WIDTH)
|
||||
COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_RQ_USER_WIDTH=$(PARAM_AXIS_PCIE_RQ_USER_WIDTH)
|
||||
COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_RC_USER_WIDTH=$(PARAM_AXIS_PCIE_RC_USER_WIDTH)
|
||||
COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_CQ_USER_WIDTH=$(PARAM_AXIS_PCIE_CQ_USER_WIDTH)
|
||||
COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_CC_USER_WIDTH=$(PARAM_AXIS_PCIE_CC_USER_WIDTH)
|
||||
COMPILE_ARGS += -P $(TOPLEVEL).RQ_SEQ_NUM_WIDTH=$(PARAM_RQ_SEQ_NUM_WIDTH)
|
||||
|
||||
ifeq ($(WAVES), 1)
|
||||
VERILOG_SOURCES += iverilog_dump.v
|
||||
COMPILE_ARGS += -s iverilog_dump
|
||||
endif
|
||||
else ifeq ($(SIM), verilator)
|
||||
COMPILE_ARGS += -Wno-SELRANGE -Wno-WIDTH
|
||||
|
||||
COMPILE_ARGS += -GAXIS_PCIE_DATA_WIDTH=$(PARAM_AXIS_PCIE_DATA_WIDTH)
|
||||
COMPILE_ARGS += -GAXIS_PCIE_KEEP_WIDTH=$(PARAM_AXIS_PCIE_KEEP_WIDTH)
|
||||
COMPILE_ARGS += -GAXIS_PCIE_RQ_USER_WIDTH=$(PARAM_AXIS_PCIE_RQ_USER_WIDTH)
|
||||
COMPILE_ARGS += -GAXIS_PCIE_RC_USER_WIDTH=$(PARAM_AXIS_PCIE_RC_USER_WIDTH)
|
||||
COMPILE_ARGS += -GAXIS_PCIE_CQ_USER_WIDTH=$(PARAM_AXIS_PCIE_CQ_USER_WIDTH)
|
||||
COMPILE_ARGS += -GAXIS_PCIE_CC_USER_WIDTH=$(PARAM_AXIS_PCIE_CC_USER_WIDTH)
|
||||
COMPILE_ARGS += -GRQ_SEQ_NUM_WIDTH=$(PARAM_RQ_SEQ_NUM_WIDTH)
|
||||
|
||||
ifeq ($(WAVES), 1)
|
||||
COMPILE_ARGS += --trace-fst
|
||||
endif
|
||||
endif
|
||||
|
||||
iverilog_dump.v:
|
||||
echo 'module iverilog_dump();' > $@
|
||||
echo 'initial begin' >> $@
|
||||
echo ' $$dumpfile("$(TOPLEVEL).fst");' >> $@
|
||||
echo ' $$dumpvars(0, $(TOPLEVEL));' >> $@
|
||||
echo 'end' >> $@
|
||||
echo 'endmodule' >> $@
|
||||
|
||||
clean::
|
||||
@rm -rf sim_build_*
|
||||
@rm -rf iverilog_dump.v
|
||||
@rm -rf dump.fst $(TOPLEVEL).fst
|
||||
|
||||
include $(shell cocotb-config --makefiles)/Makefile.sim
|
||||
|
380
example/AU200/fpga_axi/tb/fpga_core/test_fpga_core.py
Normal file
380
example/AU200/fpga_axi/tb/fpga_core/test_fpga_core.py
Normal file
@ -0,0 +1,380 @@
|
||||
"""
|
||||
|
||||
Copyright (c) 2020 Alex Forencich
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
"""
|
||||
|
||||
import logging
|
||||
import os
|
||||
|
||||
import cocotb_test.simulator
|
||||
|
||||
import cocotb
|
||||
from cocotb.log import SimLog
|
||||
from cocotb.triggers import RisingEdge, FallingEdge, Timer
|
||||
|
||||
from cocotbext.pcie.core import RootComplex
|
||||
from cocotbext.pcie.xilinx.us import UltraScalePlusPcieDevice
|
||||
from cocotbext.axi.utils import hexdump_str
|
||||
|
||||
|
||||
class TB(object):
|
||||
def __init__(self, dut):
|
||||
self.dut = dut
|
||||
|
||||
self.log = SimLog("cocotb.tb")
|
||||
self.log.setLevel(logging.DEBUG)
|
||||
|
||||
# PCIe
|
||||
self.rc = RootComplex()
|
||||
|
||||
self.dev = UltraScalePlusPcieDevice(
|
||||
# configuration options
|
||||
pcie_generation=3,
|
||||
pcie_link_width=16,
|
||||
user_clk_frequency=250e6,
|
||||
alignment="dword",
|
||||
cq_cc_straddle=False,
|
||||
rq_rc_straddle=False,
|
||||
rc_4tlp_straddle=False,
|
||||
enable_pf1=False,
|
||||
enable_client_tag=True,
|
||||
enable_extended_tag=True,
|
||||
enable_parity=False,
|
||||
enable_rx_msg_interface=False,
|
||||
enable_sriov=False,
|
||||
enable_extended_configuration=False,
|
||||
|
||||
enable_pf0_msi=True,
|
||||
enable_pf1_msi=False,
|
||||
|
||||
# signals
|
||||
# Clock and Reset Interface
|
||||
user_clk=dut.clk,
|
||||
user_reset=dut.rst,
|
||||
# user_lnk_up
|
||||
# sys_clk
|
||||
# sys_clk_gt
|
||||
# sys_reset
|
||||
# phy_rdy_out
|
||||
|
||||
# Requester reQuest Interface
|
||||
rq_entity=dut,
|
||||
rq_name="m_axis_rq",
|
||||
# pcie_rq_seq_num0=dut.s_axis_rq_seq_num_0,
|
||||
# pcie_rq_seq_num_vld0=dut.s_axis_rq_seq_num_valid_0,
|
||||
# pcie_rq_seq_num1=dut.s_axis_rq_seq_num_1,
|
||||
# pcie_rq_seq_num_vld1=dut.s_axis_rq_seq_num_valid_1,
|
||||
# pcie_rq_tag0
|
||||
# pcie_rq_tag1
|
||||
# pcie_rq_tag_av
|
||||
# pcie_rq_tag_vld0
|
||||
# pcie_rq_tag_vld1
|
||||
|
||||
# Requester Completion Interface
|
||||
rc_entity=dut,
|
||||
rc_name="s_axis_rc",
|
||||
|
||||
# Completer reQuest Interface
|
||||
cq_entity=dut,
|
||||
cq_name="s_axis_cq",
|
||||
# pcie_cq_np_req
|
||||
# pcie_cq_np_req_count
|
||||
|
||||
# Completer Completion Interface
|
||||
cc_entity=dut,
|
||||
cc_name="m_axis_cc",
|
||||
|
||||
# Transmit Flow Control Interface
|
||||
# pcie_tfc_nph_av=dut.pcie_tfc_nph_av,
|
||||
# pcie_tfc_npd_av=dut.pcie_tfc_npd_av,
|
||||
|
||||
# Configuration Management Interface
|
||||
cfg_mgmt_addr=dut.cfg_mgmt_addr,
|
||||
cfg_mgmt_function_number=dut.cfg_mgmt_function_number,
|
||||
cfg_mgmt_write=dut.cfg_mgmt_write,
|
||||
cfg_mgmt_write_data=dut.cfg_mgmt_write_data,
|
||||
cfg_mgmt_byte_enable=dut.cfg_mgmt_byte_enable,
|
||||
cfg_mgmt_read=dut.cfg_mgmt_read,
|
||||
cfg_mgmt_read_data=dut.cfg_mgmt_read_data,
|
||||
cfg_mgmt_read_write_done=dut.cfg_mgmt_read_write_done,
|
||||
# cfg_mgmt_debug_access
|
||||
|
||||
# Configuration Status Interface
|
||||
# cfg_phy_link_down
|
||||
# cfg_phy_link_status
|
||||
# cfg_negotiated_width
|
||||
# cfg_current_speed
|
||||
cfg_max_payload=dut.cfg_max_payload,
|
||||
cfg_max_read_req=dut.cfg_max_read_req,
|
||||
# cfg_function_status
|
||||
# cfg_vf_status
|
||||
# cfg_function_power_state
|
||||
# cfg_vf_power_state
|
||||
# cfg_link_power_state
|
||||
# cfg_err_cor_out
|
||||
# cfg_err_nonfatal_out
|
||||
# cfg_err_fatal_out
|
||||
# cfg_local_error_out
|
||||
# cfg_local_error_valid
|
||||
# cfg_rx_pm_state
|
||||
# cfg_tx_pm_state
|
||||
# cfg_ltssm_state
|
||||
# cfg_rcb_status
|
||||
# cfg_obff_enable
|
||||
# cfg_pl_status_change
|
||||
# cfg_tph_requester_enable
|
||||
# cfg_tph_st_mode
|
||||
# cfg_vf_tph_requester_enable
|
||||
# cfg_vf_tph_st_mode
|
||||
|
||||
# Configuration Received Message Interface
|
||||
# cfg_msg_received
|
||||
# cfg_msg_received_data
|
||||
# cfg_msg_received_type
|
||||
|
||||
# Configuration Transmit Message Interface
|
||||
# cfg_msg_transmit
|
||||
# cfg_msg_transmit_type
|
||||
# cfg_msg_transmit_data
|
||||
# cfg_msg_transmit_done
|
||||
|
||||
# Configuration Flow Control Interface
|
||||
# cfg_fc_ph=dut.cfg_fc_ph,
|
||||
# cfg_fc_pd=dut.cfg_fc_pd,
|
||||
# cfg_fc_nph=dut.cfg_fc_nph,
|
||||
# cfg_fc_npd=dut.cfg_fc_npd,
|
||||
# cfg_fc_cplh=dut.cfg_fc_cplh,
|
||||
# cfg_fc_cpld=dut.cfg_fc_cpld,
|
||||
# cfg_fc_sel=dut.cfg_fc_sel,
|
||||
|
||||
# Configuration Control Interface
|
||||
# cfg_hot_reset_in
|
||||
# cfg_hot_reset_out
|
||||
# cfg_config_space_enable
|
||||
# cfg_dsn
|
||||
# cfg_bus_number
|
||||
# cfg_ds_port_number
|
||||
# cfg_ds_bus_number
|
||||
# cfg_ds_device_number
|
||||
# cfg_ds_function_number
|
||||
# cfg_power_state_change_ack
|
||||
# cfg_power_state_change_interrupt
|
||||
cfg_err_cor_in=dut.status_error_cor,
|
||||
cfg_err_uncor_in=dut.status_error_uncor,
|
||||
# cfg_flr_in_process
|
||||
# cfg_flr_done
|
||||
# cfg_vf_flr_in_process
|
||||
# cfg_vf_flr_func_num
|
||||
# cfg_vf_flr_done
|
||||
# cfg_pm_aspm_l1_entry_reject
|
||||
# cfg_pm_aspm_tx_l0s_entry_disable
|
||||
# cfg_req_pm_transition_l23_ready
|
||||
# cfg_link_training_enable
|
||||
|
||||
# Configuration Interrupt Controller Interface
|
||||
# cfg_interrupt_int
|
||||
# cfg_interrupt_sent
|
||||
# cfg_interrupt_pending
|
||||
cfg_interrupt_msi_enable=dut.cfg_interrupt_msi_enable,
|
||||
cfg_interrupt_msi_mmenable=dut.cfg_interrupt_msi_mmenable,
|
||||
cfg_interrupt_msi_mask_update=dut.cfg_interrupt_msi_mask_update,
|
||||
cfg_interrupt_msi_data=dut.cfg_interrupt_msi_data,
|
||||
# cfg_interrupt_msi_select=dut.cfg_interrupt_msi_select,
|
||||
cfg_interrupt_msi_int=dut.cfg_interrupt_msi_int,
|
||||
cfg_interrupt_msi_pending_status=dut.cfg_interrupt_msi_pending_status,
|
||||
cfg_interrupt_msi_pending_status_data_enable=dut.cfg_interrupt_msi_pending_status_data_enable,
|
||||
# cfg_interrupt_msi_pending_status_function_num=dut.cfg_interrupt_msi_pending_status_function_num,
|
||||
cfg_interrupt_msi_sent=dut.cfg_interrupt_msi_sent,
|
||||
cfg_interrupt_msi_fail=dut.cfg_interrupt_msi_fail,
|
||||
# cfg_interrupt_msix_enable
|
||||
# cfg_interrupt_msix_mask
|
||||
# cfg_interrupt_msix_vf_enable
|
||||
# cfg_interrupt_msix_vf_mask
|
||||
# cfg_interrupt_msix_address
|
||||
# cfg_interrupt_msix_data
|
||||
# cfg_interrupt_msix_int
|
||||
# cfg_interrupt_msix_vec_pending
|
||||
# cfg_interrupt_msix_vec_pending_status
|
||||
cfg_interrupt_msi_attr=dut.cfg_interrupt_msi_attr,
|
||||
cfg_interrupt_msi_tph_present=dut.cfg_interrupt_msi_tph_present,
|
||||
cfg_interrupt_msi_tph_type=dut.cfg_interrupt_msi_tph_type,
|
||||
# cfg_interrupt_msi_tph_st_tag=dut.cfg_interrupt_msi_tph_st_tag,
|
||||
# cfg_interrupt_msi_function_number=dut.cfg_interrupt_msi_function_number,
|
||||
|
||||
# Configuration Extend Interface
|
||||
# cfg_ext_read_received
|
||||
# cfg_ext_write_received
|
||||
# cfg_ext_register_number
|
||||
# cfg_ext_function_number
|
||||
# cfg_ext_write_data
|
||||
# cfg_ext_write_byte_enable
|
||||
# cfg_ext_read_data
|
||||
# cfg_ext_read_data_valid
|
||||
)
|
||||
|
||||
# self.dev.log.setLevel(logging.DEBUG)
|
||||
|
||||
self.rc.make_port().connect(self.dev)
|
||||
|
||||
self.dev.functions[0].msi_multiple_message_capable = 5
|
||||
|
||||
self.dev.functions[0].configure_bar(0, 2**22)
|
||||
self.dev.functions[0].configure_bar(1, 2**22)
|
||||
|
||||
dut.sw.setimmediatevalue(0)
|
||||
|
||||
async def init(self):
|
||||
|
||||
await FallingEdge(self.dut.rst)
|
||||
await Timer(100, 'ns')
|
||||
|
||||
await self.rc.enumerate(enable_bus_mastering=True, configure_msi=True)
|
||||
|
||||
|
||||
@cocotb.test()
|
||||
async def run_test(dut):
|
||||
|
||||
tb = TB(dut)
|
||||
|
||||
await tb.init()
|
||||
|
||||
mem_base, mem_data = tb.rc.alloc_region(16*1024*1024)
|
||||
|
||||
dev_pf0_bar0 = tb.rc.tree[0][0].bar_addr[0]
|
||||
dev_pf0_bar1 = tb.rc.tree[0][0].bar_addr[1]
|
||||
|
||||
tb.log.info("Test memory write to BAR 1")
|
||||
|
||||
await tb.rc.mem_write(dev_pf0_bar1, b'\x11\x22\x33\x44')
|
||||
|
||||
await Timer(100, 'ns')
|
||||
|
||||
tb.log.info("Test memory read from BAR 1")
|
||||
|
||||
val = await tb.rc.mem_read(dev_pf0_bar1, 4, 1000)
|
||||
tb.log.info("Read data: %s", val)
|
||||
assert val == b'\x11\x22\x33\x44'
|
||||
|
||||
tb.log.info("Test DMA")
|
||||
|
||||
# write packet data
|
||||
mem_data[0:1024] = bytearray([x % 256 for x in range(1024)])
|
||||
|
||||
# enable DMA
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100000, 1)
|
||||
|
||||
# write pcie read descriptor
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100100, (mem_base+0x0000) & 0xffffffff)
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100104, (mem_base+0x0000 >> 32) & 0xffffffff)
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100108, (0x100) & 0xffffffff)
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x10010C, (0x100 >> 32) & 0xffffffff)
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100110, 0x400)
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100114, 0xAA)
|
||||
|
||||
await Timer(2000, 'ns')
|
||||
|
||||
# read status
|
||||
val = await tb.rc.mem_read_dword(dev_pf0_bar0+0x100118)
|
||||
tb.log.info("Status: 0x%x", val)
|
||||
assert val == 0xAA
|
||||
|
||||
# write pcie write descriptor
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100200, (mem_base+0x1000) & 0xffffffff)
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100204, (mem_base+0x1000 >> 32) & 0xffffffff)
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100208, (0x100) & 0xffffffff)
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x10020C, (0x100 >> 32) & 0xffffffff)
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100210, 0x400)
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100214, 0x55)
|
||||
|
||||
await Timer(2000, 'ns')
|
||||
|
||||
# read status
|
||||
val = await tb.rc.mem_read_dword(dev_pf0_bar0+0x100218)
|
||||
tb.log.info("Status: 0x%x", val)
|
||||
assert val == 0x55
|
||||
|
||||
tb.log.info("%s", hexdump_str(mem_data, 0x1000, 64))
|
||||
|
||||
assert mem_data[0:1024] == mem_data[0x1000:0x1000+1024]
|
||||
|
||||
await RisingEdge(dut.clk)
|
||||
await RisingEdge(dut.clk)
|
||||
|
||||
|
||||
# cocotb-test
|
||||
|
||||
tests_dir = os.path.dirname(__file__)
|
||||
rtl_dir = os.path.abspath(os.path.join(tests_dir, '..', '..', 'rtl'))
|
||||
lib_dir = os.path.abspath(os.path.join(rtl_dir, '..', 'lib'))
|
||||
pcie_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'pcie', 'rtl'))
|
||||
|
||||
|
||||
def test_fpga_core(request):
|
||||
dut = "fpga_core"
|
||||
module = os.path.splitext(os.path.basename(__file__))[0]
|
||||
toplevel = dut
|
||||
|
||||
verilog_sources = [
|
||||
os.path.join(rtl_dir, f"{dut}.v"),
|
||||
os.path.join(rtl_dir, "axi_ram.v"),
|
||||
os.path.join(rtl_dir, "axis_register.v"),
|
||||
os.path.join(pcie_rtl_dir, "axis_arb_mux.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_us_axil_master.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_us_axi_dma.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_us_axi_dma_rd.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_us_axi_dma_wr.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_tag_manager.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_us_axi_master.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_us_axi_master_rd.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_us_axi_master_wr.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_us_axis_cq_demux.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_us_cfg.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_us_msi.v"),
|
||||
os.path.join(pcie_rtl_dir, "arbiter.v"),
|
||||
os.path.join(pcie_rtl_dir, "priority_encoder.v"),
|
||||
os.path.join(pcie_rtl_dir, "pulse_merge.v"),
|
||||
]
|
||||
|
||||
parameters = {}
|
||||
|
||||
parameters['AXIS_PCIE_DATA_WIDTH'] = 512
|
||||
parameters['AXIS_PCIE_KEEP_WIDTH'] = parameters['AXIS_PCIE_DATA_WIDTH'] // 32
|
||||
parameters['AXIS_PCIE_RQ_USER_WIDTH'] = 62 if parameters['AXIS_PCIE_DATA_WIDTH'] < 512 else 137
|
||||
parameters['AXIS_PCIE_RC_USER_WIDTH'] = 75 if parameters['AXIS_PCIE_DATA_WIDTH'] < 512 else 161
|
||||
parameters['AXIS_PCIE_CQ_USER_WIDTH'] = 88 if parameters['AXIS_PCIE_DATA_WIDTH'] < 512 else 183
|
||||
parameters['AXIS_PCIE_CC_USER_WIDTH'] = 33 if parameters['AXIS_PCIE_DATA_WIDTH'] < 512 else 81
|
||||
parameters['RQ_SEQ_NUM_WIDTH'] = 6
|
||||
|
||||
extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()}
|
||||
|
||||
sim_build = os.path.join(tests_dir,
|
||||
"sim_build_"+request.node.name.replace('[', '-').replace(']', ''))
|
||||
|
||||
cocotb_test.simulator.run(
|
||||
python_search=[tests_dir],
|
||||
verilog_sources=verilog_sources,
|
||||
toplevel=toplevel,
|
||||
module=module,
|
||||
parameters=parameters,
|
||||
sim_build=sim_build,
|
||||
extra_env=extra_env,
|
||||
)
|
@ -1 +0,0 @@
|
||||
../lib/pcie/tb/pcie.py
|
@ -1 +0,0 @@
|
||||
../lib/pcie/tb/pcie_us.py
|
@ -1 +0,0 @@
|
||||
../lib/pcie/tb/pcie_usp.py
|
@ -1,520 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
"""
|
||||
|
||||
Copyright (c) 2018 Alex Forencich
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
"""
|
||||
|
||||
from myhdl import *
|
||||
import os
|
||||
import struct
|
||||
|
||||
import pcie
|
||||
import pcie_usp
|
||||
|
||||
module = 'fpga_core'
|
||||
testbench = 'test_%s' % module
|
||||
|
||||
srcs = []
|
||||
|
||||
srcs.append("../rtl/%s.v" % module)
|
||||
srcs.append("../rtl/axi_ram.v")
|
||||
srcs.append("../rtl/axis_register.v")
|
||||
srcs.append("../lib/pcie/rtl/axis_arb_mux.v")
|
||||
srcs.append("../lib/pcie/rtl/pcie_us_axil_master.v")
|
||||
srcs.append("../lib/pcie/rtl/pcie_us_axi_dma.v")
|
||||
srcs.append("../lib/pcie/rtl/pcie_us_axi_dma_rd.v")
|
||||
srcs.append("../lib/pcie/rtl/pcie_us_axi_dma_wr.v")
|
||||
srcs.append("../lib/pcie/rtl/pcie_tag_manager.v")
|
||||
srcs.append("../lib/pcie/rtl/pcie_us_axi_master.v")
|
||||
srcs.append("../lib/pcie/rtl/pcie_us_axi_master_rd.v")
|
||||
srcs.append("../lib/pcie/rtl/pcie_us_axi_master_wr.v")
|
||||
srcs.append("../lib/pcie/rtl/pcie_us_axis_cq_demux.v")
|
||||
srcs.append("../lib/pcie/rtl/pcie_us_cfg.v")
|
||||
srcs.append("../lib/pcie/rtl/pcie_us_msi.v")
|
||||
srcs.append("../lib/pcie/rtl/arbiter.v")
|
||||
srcs.append("../lib/pcie/rtl/priority_encoder.v")
|
||||
srcs.append("../lib/pcie/rtl/pulse_merge.v")
|
||||
srcs.append("%s.v" % testbench)
|
||||
|
||||
src = ' '.join(srcs)
|
||||
|
||||
build_cmd = "iverilog -o %s.vvp %s" % (testbench, src)
|
||||
|
||||
def bench():
|
||||
|
||||
# Parameters
|
||||
AXIS_PCIE_DATA_WIDTH = 512
|
||||
AXIS_PCIE_KEEP_WIDTH = (AXIS_PCIE_DATA_WIDTH/32)
|
||||
AXIS_PCIE_RC_USER_WIDTH = 161
|
||||
AXIS_PCIE_RQ_USER_WIDTH = 137
|
||||
AXIS_PCIE_CQ_USER_WIDTH = 183
|
||||
AXIS_PCIE_CC_USER_WIDTH = 81
|
||||
|
||||
# Inputs
|
||||
clk = Signal(bool(0))
|
||||
rst = Signal(bool(0))
|
||||
current_test = Signal(intbv(0)[8:])
|
||||
|
||||
btnu = Signal(bool(0))
|
||||
btnl = Signal(bool(0))
|
||||
btnd = Signal(bool(0))
|
||||
btnr = Signal(bool(0))
|
||||
btnc = Signal(bool(0))
|
||||
sw = Signal(intbv(0)[4:])
|
||||
m_axis_rq_tready = Signal(bool(0))
|
||||
s_axis_rc_tdata = Signal(intbv(0)[AXIS_PCIE_DATA_WIDTH:])
|
||||
s_axis_rc_tkeep = Signal(intbv(0)[AXIS_PCIE_KEEP_WIDTH:])
|
||||
s_axis_rc_tlast = Signal(bool(0))
|
||||
s_axis_rc_tuser = Signal(intbv(0)[AXIS_PCIE_RC_USER_WIDTH:])
|
||||
s_axis_rc_tvalid = Signal(bool(0))
|
||||
s_axis_cq_tdata = Signal(intbv(0)[AXIS_PCIE_DATA_WIDTH:])
|
||||
s_axis_cq_tkeep = Signal(intbv(0)[AXIS_PCIE_KEEP_WIDTH:])
|
||||
s_axis_cq_tlast = Signal(bool(0))
|
||||
s_axis_cq_tuser = Signal(intbv(0)[AXIS_PCIE_CQ_USER_WIDTH:])
|
||||
s_axis_cq_tvalid = Signal(bool(0))
|
||||
m_axis_cc_tready = Signal(bool(0))
|
||||
cfg_max_payload = Signal(intbv(0)[2:])
|
||||
cfg_max_read_req = Signal(intbv(0)[3:])
|
||||
cfg_mgmt_read_data = Signal(intbv(0)[32:])
|
||||
cfg_mgmt_read_write_done = Signal(bool(0))
|
||||
cfg_interrupt_msi_enable = Signal(intbv(0)[4:])
|
||||
cfg_interrupt_msi_mmenable = Signal(intbv(0)[12:])
|
||||
cfg_interrupt_msi_mask_update = Signal(bool(0))
|
||||
cfg_interrupt_msi_data = Signal(intbv(0)[32:])
|
||||
cfg_interrupt_msi_sent = Signal(bool(0))
|
||||
cfg_interrupt_msi_fail = Signal(bool(0))
|
||||
|
||||
# Outputs
|
||||
led = Signal(intbv(0)[8:])
|
||||
m_axis_rq_tdata = Signal(intbv(0)[AXIS_PCIE_DATA_WIDTH:])
|
||||
m_axis_rq_tkeep = Signal(intbv(0)[AXIS_PCIE_KEEP_WIDTH:])
|
||||
m_axis_rq_tlast = Signal(bool(0))
|
||||
m_axis_rq_tuser = Signal(intbv(0)[AXIS_PCIE_RQ_USER_WIDTH:])
|
||||
m_axis_rq_tvalid = Signal(bool(0))
|
||||
s_axis_rc_tready = Signal(bool(0))
|
||||
s_axis_cq_tready = Signal(bool(0))
|
||||
m_axis_cc_tdata = Signal(intbv(0)[AXIS_PCIE_DATA_WIDTH:])
|
||||
m_axis_cc_tkeep = Signal(intbv(0)[AXIS_PCIE_KEEP_WIDTH:])
|
||||
m_axis_cc_tlast = Signal(bool(0))
|
||||
m_axis_cc_tuser = Signal(intbv(0)[AXIS_PCIE_CC_USER_WIDTH:])
|
||||
m_axis_cc_tvalid = Signal(bool(0))
|
||||
status_error_cor = Signal(bool(0))
|
||||
status_error_uncor = Signal(bool(0))
|
||||
cfg_mgmt_addr = Signal(intbv(0)[10:])
|
||||
cfg_mgmt_function_number = Signal(intbv(0)[8:])
|
||||
cfg_mgmt_write = Signal(bool(0))
|
||||
cfg_mgmt_write_data = Signal(intbv(0)[32:])
|
||||
cfg_mgmt_byte_enable = Signal(intbv(0)[4:])
|
||||
cfg_mgmt_read = Signal(bool(0))
|
||||
cfg_interrupt_msi_int = Signal(intbv(0)[32:])
|
||||
cfg_interrupt_msi_pending_status = Signal(intbv(0)[32:])
|
||||
cfg_interrupt_msi_select = Signal(intbv(0)[2:])
|
||||
cfg_interrupt_msi_pending_status_function_num = Signal(intbv(0)[2:])
|
||||
cfg_interrupt_msi_pending_status_data_enable = Signal(bool(0))
|
||||
cfg_interrupt_msi_attr = Signal(intbv(0)[3:])
|
||||
cfg_interrupt_msi_tph_present = Signal(bool(0))
|
||||
cfg_interrupt_msi_tph_type = Signal(intbv(0)[2:])
|
||||
cfg_interrupt_msi_tph_st_tag = Signal(intbv(0)[8:])
|
||||
cfg_interrupt_msi_function_number = Signal(intbv(0)[8:])
|
||||
|
||||
# Clock and Reset Interface
|
||||
user_clk=Signal(bool(0))
|
||||
user_reset=Signal(bool(0))
|
||||
sys_clk=Signal(bool(0))
|
||||
sys_reset=Signal(bool(0))
|
||||
|
||||
# PCIe devices
|
||||
rc = pcie.RootComplex()
|
||||
|
||||
mem_base, mem_data = rc.alloc_region(16*1024*1024)
|
||||
|
||||
dev = pcie_usp.UltrascalePlusPCIe()
|
||||
|
||||
dev.pcie_generation = 3
|
||||
dev.pcie_link_width = 16
|
||||
dev.user_clk_frequency = 250e6
|
||||
|
||||
dev.functions[0].msi_multiple_message_capable = 5
|
||||
|
||||
dev.functions[0].configure_bar(0, 4*1024*1024)
|
||||
dev.functions[0].configure_bar(1, 4*1024*1024)
|
||||
|
||||
rc.make_port().connect(dev)
|
||||
|
||||
pcie_logic = dev.create_logic(
|
||||
# Completer reQuest Interface
|
||||
m_axis_cq_tdata=s_axis_cq_tdata,
|
||||
m_axis_cq_tuser=s_axis_cq_tuser,
|
||||
m_axis_cq_tlast=s_axis_cq_tlast,
|
||||
m_axis_cq_tkeep=s_axis_cq_tkeep,
|
||||
m_axis_cq_tvalid=s_axis_cq_tvalid,
|
||||
m_axis_cq_tready=s_axis_cq_tready,
|
||||
#pcie_cq_np_req=pcie_cq_np_req,
|
||||
pcie_cq_np_req=Signal(intbv(1)[2:]),
|
||||
#pcie_cq_np_req_count=pcie_cq_np_req_count,
|
||||
|
||||
# Completer Completion Interface
|
||||
s_axis_cc_tdata=m_axis_cc_tdata,
|
||||
s_axis_cc_tuser=m_axis_cc_tuser,
|
||||
s_axis_cc_tlast=m_axis_cc_tlast,
|
||||
s_axis_cc_tkeep=m_axis_cc_tkeep,
|
||||
s_axis_cc_tvalid=m_axis_cc_tvalid,
|
||||
s_axis_cc_tready=m_axis_cc_tready,
|
||||
|
||||
# Requester reQuest Interface
|
||||
s_axis_rq_tdata=m_axis_rq_tdata,
|
||||
s_axis_rq_tuser=m_axis_rq_tuser,
|
||||
s_axis_rq_tlast=m_axis_rq_tlast,
|
||||
s_axis_rq_tkeep=m_axis_rq_tkeep,
|
||||
s_axis_rq_tvalid=m_axis_rq_tvalid,
|
||||
s_axis_rq_tready=m_axis_rq_tready,
|
||||
#pcie_rq_seq_num0=pcie_rq_seq_num0,
|
||||
#pcie_rq_seq_num_vld0=pcie_rq_seq_num_vld0,
|
||||
#pcie_rq_seq_num1=pcie_rq_seq_num1,
|
||||
#pcie_rq_seq_num_vld1=pcie_rq_seq_num_vld1,
|
||||
#pcie_rq_tag0=pcie_rq_tag0,
|
||||
#pcie_rq_tag1=pcie_rq_tag1,
|
||||
#pcie_rq_tag_av=pcie_rq_tag_av,
|
||||
#pcie_rq_tag_vld0=pcie_rq_tag_vld0,
|
||||
#pcie_rq_tag_vld1=pcie_rq_tag_vld1,
|
||||
|
||||
# Requester Completion Interface
|
||||
m_axis_rc_tdata=s_axis_rc_tdata,
|
||||
m_axis_rc_tuser=s_axis_rc_tuser,
|
||||
m_axis_rc_tlast=s_axis_rc_tlast,
|
||||
m_axis_rc_tkeep=s_axis_rc_tkeep,
|
||||
m_axis_rc_tvalid=s_axis_rc_tvalid,
|
||||
m_axis_rc_tready=s_axis_rc_tready,
|
||||
|
||||
# Transmit Flow Control Interface
|
||||
#pcie_tfc_nph_av=pcie_tfc_nph_av,
|
||||
#pcie_tfc_npd_av=pcie_tfc_npd_av,
|
||||
|
||||
# Configuration Management Interface
|
||||
cfg_mgmt_addr=cfg_mgmt_addr,
|
||||
cfg_mgmt_function_number=cfg_mgmt_function_number,
|
||||
cfg_mgmt_write=cfg_mgmt_write,
|
||||
cfg_mgmt_write_data=cfg_mgmt_write_data,
|
||||
cfg_mgmt_byte_enable=cfg_mgmt_byte_enable,
|
||||
cfg_mgmt_read=cfg_mgmt_read,
|
||||
cfg_mgmt_read_data=cfg_mgmt_read_data,
|
||||
cfg_mgmt_read_write_done=cfg_mgmt_read_write_done,
|
||||
#cfg_mgmt_debug_access=cfg_mgmt_debug_access,
|
||||
|
||||
# Configuration Status Interface
|
||||
#cfg_phy_link_down=cfg_phy_link_down,
|
||||
#cfg_phy_link_status=cfg_phy_link_status,
|
||||
#cfg_negotiated_width=cfg_negotiated_width,
|
||||
#cfg_current_speed=cfg_current_speed,
|
||||
cfg_max_payload=cfg_max_payload,
|
||||
cfg_max_read_req=cfg_max_read_req,
|
||||
#cfg_function_status=cfg_function_status,
|
||||
#cfg_vf_status=cfg_vf_status,
|
||||
#cfg_function_power_state=cfg_function_power_state,
|
||||
#cfg_vf_power_state=cfg_vf_power_state,
|
||||
#cfg_link_power_state=cfg_link_power_state,
|
||||
#cfg_err_cor_out=cfg_err_cor_out,
|
||||
#cfg_err_nonfatal_out=cfg_err_nonfatal_out,
|
||||
#cfg_err_fatal_out=cfg_err_fatal_out,
|
||||
#cfg_local_err_out=cfg_local_err_out,
|
||||
#cfg_local_err_valid=cfg_local_err_valid,
|
||||
#cfg_rx_pm_state=cfg_rx_pm_state,
|
||||
#cfg_tx_pm_state=cfg_tx_pm_state,
|
||||
#cfg_ltssm_state=cfg_ltssm_state,
|
||||
#cfg_rcb_status=cfg_rcb_status,
|
||||
#cfg_obff_enable=cfg_obff_enable,
|
||||
#cfg_pl_status_change=cfg_pl_status_change,
|
||||
#cfg_tph_requester_enable=cfg_tph_requester_enable,
|
||||
#cfg_tph_st_mode=cfg_tph_st_mode,
|
||||
#cfg_vf_tph_requester_enable=cfg_vf_tph_requester_enable,
|
||||
#cfg_vf_tph_st_mode=cfg_vf_tph_st_mode,
|
||||
|
||||
# Configuration Received Message Interface
|
||||
#cfg_msg_received=cfg_msg_received,
|
||||
#cfg_msg_received_data=cfg_msg_received_data,
|
||||
#cfg_msg_received_type=cfg_msg_received_type,
|
||||
|
||||
# Configuration Transmit Message Interface
|
||||
#cfg_msg_transmit=cfg_msg_transmit,
|
||||
#cfg_msg_transmit_type=cfg_msg_transmit_type,
|
||||
#cfg_msg_transmit_data=cfg_msg_transmit_data,
|
||||
#cfg_msg_transmit_done=cfg_msg_transmit_done,
|
||||
|
||||
# Configuration Flow Control Interface
|
||||
#cfg_fc_ph=cfg_fc_ph,
|
||||
#cfg_fc_pd=cfg_fc_pd,
|
||||
#cfg_fc_nph=cfg_fc_nph,
|
||||
#cfg_fc_npd=cfg_fc_npd,
|
||||
#cfg_fc_cplh=cfg_fc_cplh,
|
||||
#cfg_fc_cpld=cfg_fc_cpld,
|
||||
#cfg_fc_sel=cfg_fc_sel,
|
||||
|
||||
# Configuration Control Interface
|
||||
#cfg_hot_reset_in=cfg_hot_reset_in,
|
||||
#cfg_hot_reset_out=cfg_hot_reset_out,
|
||||
#cfg_config_space_enable=cfg_config_space_enable,
|
||||
#cfg_dsn=cfg_dsn,
|
||||
#cfg_ds_port_number=cfg_ds_port_number,
|
||||
#cfg_ds_bus_number=cfg_ds_bus_number,
|
||||
#cfg_ds_device_number=cfg_ds_device_number,
|
||||
#cfg_ds_function_number=cfg_ds_function_number,
|
||||
#cfg_power_state_change_ack=cfg_power_state_change_ack,
|
||||
#cfg_power_state_change_interrupt=cfg_power_state_change_interrupt,
|
||||
cfg_err_cor_in=status_error_cor,
|
||||
cfg_err_uncor_in=status_error_uncor,
|
||||
#cfg_flr_done=cfg_flr_done,
|
||||
#cfg_vf_flr_done=cfg_vf_flr_done,
|
||||
#cfg_flr_in_process=cfg_flr_in_process,
|
||||
#cfg_vf_flr_in_process=cfg_vf_flr_in_process,
|
||||
#cfg_req_pm_transition_l23_ready=cfg_req_pm_transition_l23_ready,
|
||||
#cfg_link_training_enable=cfg_link_training_enable,
|
||||
|
||||
# Configuration Interrupt Controller Interface
|
||||
#cfg_interrupt_int=cfg_interrupt_int,
|
||||
#cfg_interrupt_sent=cfg_interrupt_sent,
|
||||
#cfg_interrupt_pending=cfg_interrupt_pending,
|
||||
cfg_interrupt_msi_enable=cfg_interrupt_msi_enable,
|
||||
cfg_interrupt_msi_mmenable=cfg_interrupt_msi_mmenable,
|
||||
cfg_interrupt_msi_mask_update=cfg_interrupt_msi_mask_update,
|
||||
cfg_interrupt_msi_data=cfg_interrupt_msi_data,
|
||||
cfg_interrupt_msi_select=cfg_interrupt_msi_select,
|
||||
cfg_interrupt_msi_int=cfg_interrupt_msi_int,
|
||||
cfg_interrupt_msi_pending_status=cfg_interrupt_msi_pending_status,
|
||||
cfg_interrupt_msi_pending_status_data_enable=cfg_interrupt_msi_pending_status_data_enable,
|
||||
cfg_interrupt_msi_pending_status_function_num=cfg_interrupt_msi_pending_status_function_num,
|
||||
cfg_interrupt_msi_sent=cfg_interrupt_msi_sent,
|
||||
cfg_interrupt_msi_fail=cfg_interrupt_msi_fail,
|
||||
#cfg_interrupt_msix_enable=cfg_interrupt_msix_enable,
|
||||
#cfg_interrupt_msix_mask=cfg_interrupt_msix_mask,
|
||||
#cfg_interrupt_msix_vf_enable=cfg_interrupt_msix_vf_enable,
|
||||
#cfg_interrupt_msix_vf_mask=cfg_interrupt_msix_vf_mask,
|
||||
#cfg_interrupt_msix_address=cfg_interrupt_msix_address,
|
||||
#cfg_interrupt_msix_data=cfg_interrupt_msix_data,
|
||||
#cfg_interrupt_msix_int=cfg_interrupt_msix_int,
|
||||
#cfg_interrupt_msix_vec_pending=cfg_interrupt_msix_vec_pending,
|
||||
#cfg_interrupt_msix_vec_pending_status=cfg_interrupt_msix_vec_pending_status,
|
||||
cfg_interrupt_msi_attr=cfg_interrupt_msi_attr,
|
||||
cfg_interrupt_msi_tph_present=cfg_interrupt_msi_tph_present,
|
||||
cfg_interrupt_msi_tph_type=cfg_interrupt_msi_tph_type,
|
||||
cfg_interrupt_msi_tph_st_tag=cfg_interrupt_msi_tph_st_tag,
|
||||
cfg_interrupt_msi_function_number=cfg_interrupt_msi_function_number,
|
||||
|
||||
# Configuration Extend Interface
|
||||
#cfg_ext_read_received=cfg_ext_read_received,
|
||||
#cfg_ext_write_received=cfg_ext_write_received,
|
||||
#cfg_ext_register_number=cfg_ext_register_number,
|
||||
#cfg_ext_function_number=cfg_ext_function_number,
|
||||
#cfg_ext_write_data=cfg_ext_write_data,
|
||||
#cfg_ext_write_byte_enable=cfg_ext_write_byte_enable,
|
||||
#cfg_ext_read_data=cfg_ext_read_data,
|
||||
#cfg_ext_read_data_valid=cfg_ext_read_data_valid,
|
||||
|
||||
# Clock and Reset Interface
|
||||
user_clk=user_clk,
|
||||
user_reset=user_reset,
|
||||
#user_lnk_up=user_lnk_up,
|
||||
sys_clk=sys_clk,
|
||||
sys_clk_gt=sys_clk,
|
||||
sys_reset=sys_reset,
|
||||
#phy_rdy_out=phy_rdy_out
|
||||
)
|
||||
|
||||
# DUT
|
||||
if os.system(build_cmd):
|
||||
raise Exception("Error running build command")
|
||||
|
||||
dut = Cosimulation(
|
||||
"vvp -m myhdl %s.vvp -lxt2" % testbench,
|
||||
clk=user_clk,
|
||||
rst=user_reset,
|
||||
current_test=current_test,
|
||||
btnu=btnu,
|
||||
btnl=btnl,
|
||||
btnd=btnd,
|
||||
btnr=btnr,
|
||||
btnc=btnc,
|
||||
sw=sw,
|
||||
led=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_function_number=cfg_mgmt_function_number,
|
||||
cfg_mgmt_write=cfg_mgmt_write,
|
||||
cfg_mgmt_write_data=cfg_mgmt_write_data,
|
||||
cfg_mgmt_byte_enable=cfg_mgmt_byte_enable,
|
||||
cfg_mgmt_read=cfg_mgmt_read,
|
||||
cfg_mgmt_read_data=cfg_mgmt_read_data,
|
||||
cfg_mgmt_read_write_done=cfg_mgmt_read_write_done,
|
||||
cfg_interrupt_msi_enable=cfg_interrupt_msi_enable,
|
||||
cfg_interrupt_msi_int=cfg_interrupt_msi_int,
|
||||
cfg_interrupt_msi_sent=cfg_interrupt_msi_sent,
|
||||
cfg_interrupt_msi_fail=cfg_interrupt_msi_fail,
|
||||
cfg_interrupt_msi_mmenable=cfg_interrupt_msi_mmenable,
|
||||
cfg_interrupt_msi_pending_status=cfg_interrupt_msi_pending_status,
|
||||
cfg_interrupt_msi_mask_update=cfg_interrupt_msi_mask_update,
|
||||
cfg_interrupt_msi_select=cfg_interrupt_msi_select,
|
||||
cfg_interrupt_msi_data=cfg_interrupt_msi_data,
|
||||
cfg_interrupt_msi_pending_status_function_num=cfg_interrupt_msi_pending_status_function_num,
|
||||
cfg_interrupt_msi_pending_status_data_enable=cfg_interrupt_msi_pending_status_data_enable,
|
||||
cfg_interrupt_msi_attr=cfg_interrupt_msi_attr,
|
||||
cfg_interrupt_msi_tph_present=cfg_interrupt_msi_tph_present,
|
||||
cfg_interrupt_msi_tph_type=cfg_interrupt_msi_tph_type,
|
||||
cfg_interrupt_msi_tph_st_tag=cfg_interrupt_msi_tph_st_tag,
|
||||
cfg_interrupt_msi_function_number=cfg_interrupt_msi_function_number,
|
||||
status_error_cor=status_error_cor,
|
||||
status_error_uncor=status_error_uncor
|
||||
)
|
||||
|
||||
@always(delay(5))
|
||||
def clkgen():
|
||||
clk.next = not clk
|
||||
|
||||
@always_comb
|
||||
def clk_logic():
|
||||
sys_clk.next = clk
|
||||
sys_reset.next = not rst
|
||||
|
||||
@instance
|
||||
def check():
|
||||
yield delay(100)
|
||||
yield clk.posedge
|
||||
rst.next = 1
|
||||
yield clk.posedge
|
||||
rst.next = 0
|
||||
yield clk.posedge
|
||||
yield delay(100)
|
||||
yield clk.posedge
|
||||
|
||||
# testbench stimulus
|
||||
|
||||
current_tag = 1
|
||||
|
||||
yield clk.posedge
|
||||
print("test 1: enumeration")
|
||||
current_test.next = 1
|
||||
|
||||
yield rc.enumerate(enable_bus_mastering=True, configure_msi=True)
|
||||
|
||||
dev_pf0_bar0 = dev.functions[0].bar[0] & 0xfffffffc
|
||||
dev_pf0_bar1 = dev.functions[0].bar[1] & 0xfffffffc
|
||||
|
||||
yield delay(100)
|
||||
|
||||
yield clk.posedge
|
||||
print("test 2: memory write to bar 1")
|
||||
current_test.next = 2
|
||||
|
||||
yield rc.mem_write(dev_pf0_bar1, b'\x11\x22\x33\x44')
|
||||
|
||||
yield delay(100)
|
||||
|
||||
yield clk.posedge
|
||||
print("test 3: memory read from bar 1")
|
||||
current_test.next = 3
|
||||
|
||||
val = yield from rc.mem_read(dev_pf0_bar1, 4, 1000)
|
||||
print(val)
|
||||
assert val == b'\x11\x22\x33\x44'
|
||||
|
||||
yield delay(100)
|
||||
|
||||
yield clk.posedge
|
||||
print("test 4: test DMA")
|
||||
current_test.next = 4
|
||||
|
||||
# write packet data
|
||||
mem_data[0:1024] = bytearray([x%256 for x in range(1024)])
|
||||
|
||||
# enable DMA
|
||||
yield rc.mem_write(dev_pf0_bar0+0x100000, struct.pack('<L', 1))
|
||||
|
||||
# write pcie read descriptor
|
||||
yield rc.mem_write(dev_pf0_bar0+0x100100, struct.pack('<L', (mem_base+0x0000) & 0xffffffff))
|
||||
yield rc.mem_write(dev_pf0_bar0+0x100104, struct.pack('<L', (mem_base+0x0000 >> 32) & 0xffffffff))
|
||||
yield rc.mem_write(dev_pf0_bar0+0x100108, struct.pack('<L', (0x100) & 0xffffffff))
|
||||
yield rc.mem_write(dev_pf0_bar0+0x10010C, struct.pack('<L', (0x100 >> 32) & 0xffffffff))
|
||||
yield rc.mem_write(dev_pf0_bar0+0x100110, struct.pack('<L', 0x400))
|
||||
yield rc.mem_write(dev_pf0_bar0+0x100114, struct.pack('<L', 0xAA))
|
||||
|
||||
yield delay(2000)
|
||||
|
||||
# read status
|
||||
val = yield from rc.mem_read(dev_pf0_bar0+0x100118, 4)
|
||||
print(val)
|
||||
|
||||
# write pcie write descriptor
|
||||
yield rc.mem_write(dev_pf0_bar0+0x100200, struct.pack('<L', (mem_base+0x1000) & 0xffffffff))
|
||||
yield rc.mem_write(dev_pf0_bar0+0x100204, struct.pack('<L', (mem_base+0x1000 >> 32) & 0xffffffff))
|
||||
yield rc.mem_write(dev_pf0_bar0+0x100208, struct.pack('<L', (0x100) & 0xffffffff))
|
||||
yield rc.mem_write(dev_pf0_bar0+0x10020C, struct.pack('<L', (0x100 >> 32) & 0xffffffff))
|
||||
yield rc.mem_write(dev_pf0_bar0+0x100210, struct.pack('<L', 0x400))
|
||||
yield rc.mem_write(dev_pf0_bar0+0x100214, struct.pack('<L', 0x55))
|
||||
|
||||
yield delay(2000)
|
||||
|
||||
# read status
|
||||
val = yield from rc.mem_read(dev_pf0_bar0+0x100218, 4)
|
||||
print(val)
|
||||
|
||||
data = mem_data[0x1000:(0x1000)+64]
|
||||
for i in range(0, len(data), 16):
|
||||
print(" ".join(("{:02x}".format(c) for c in bytearray(data[i:i+16]))))
|
||||
|
||||
assert mem_data[0:1024] == mem_data[0x1000:0x1000+1024]
|
||||
|
||||
yield delay(100)
|
||||
|
||||
raise StopSimulation
|
||||
|
||||
return instances()
|
||||
|
||||
def test_bench():
|
||||
sim = Simulation(bench())
|
||||
sim.run()
|
||||
|
||||
if __name__ == '__main__':
|
||||
print("Running test...")
|
||||
test_bench()
|
@ -1,243 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2018 Alex Forencich
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
// Language: Verilog 2001
|
||||
|
||||
`timescale 1ns / 1ps
|
||||
|
||||
/*
|
||||
* Testbench for fpga_core
|
||||
*/
|
||||
module test_fpga_core;
|
||||
|
||||
// Parameters
|
||||
parameter AXIS_PCIE_DATA_WIDTH = 512;
|
||||
parameter AXIS_PCIE_KEEP_WIDTH = (AXIS_PCIE_DATA_WIDTH/32);
|
||||
parameter AXIS_PCIE_RC_USER_WIDTH = 161;
|
||||
parameter AXIS_PCIE_RQ_USER_WIDTH = 137;
|
||||
parameter AXIS_PCIE_CQ_USER_WIDTH = 183;
|
||||
parameter AXIS_PCIE_CC_USER_WIDTH = 81;
|
||||
|
||||
// Inputs
|
||||
reg clk = 0;
|
||||
reg rst = 0;
|
||||
reg [7:0] current_test = 0;
|
||||
|
||||
reg [3:0] sw = 0;
|
||||
reg m_axis_rq_tready = 0;
|
||||
reg [AXIS_PCIE_DATA_WIDTH-1:0] s_axis_rc_tdata = 0;
|
||||
reg [AXIS_PCIE_KEEP_WIDTH-1:0] s_axis_rc_tkeep = 0;
|
||||
reg s_axis_rc_tlast = 0;
|
||||
reg [AXIS_PCIE_RC_USER_WIDTH-1:0] s_axis_rc_tuser = 0;
|
||||
reg s_axis_rc_tvalid = 0;
|
||||
reg [AXIS_PCIE_DATA_WIDTH-1:0] s_axis_cq_tdata = 0;
|
||||
reg [AXIS_PCIE_KEEP_WIDTH-1:0] s_axis_cq_tkeep = 0;
|
||||
reg s_axis_cq_tlast = 0;
|
||||
reg [AXIS_PCIE_CQ_USER_WIDTH-1:0] s_axis_cq_tuser = 0;
|
||||
reg s_axis_cq_tvalid = 0;
|
||||
reg m_axis_cc_tready = 0;
|
||||
reg [2:0] cfg_max_payload = 0;
|
||||
reg [2:0] cfg_max_read_req = 0;
|
||||
reg [31:0] cfg_mgmt_read_data = 0;
|
||||
reg cfg_mgmt_read_write_done = 0;
|
||||
reg [3:0] cfg_interrupt_msi_enable = 0;
|
||||
reg [11:0] cfg_interrupt_msi_mmenable = 0;
|
||||
reg cfg_interrupt_msi_mask_update = 0;
|
||||
reg [31:0] cfg_interrupt_msi_data = 0;
|
||||
reg cfg_interrupt_msi_sent = 0;
|
||||
reg cfg_interrupt_msi_fail = 0;
|
||||
|
||||
// Outputs
|
||||
wire [2:0] led;
|
||||
wire [1:0] user_led_g;
|
||||
wire user_led_r;
|
||||
wire [1:0] front_led;
|
||||
wire [AXIS_PCIE_DATA_WIDTH-1:0] m_axis_rq_tdata;
|
||||
wire [AXIS_PCIE_KEEP_WIDTH-1:0] m_axis_rq_tkeep;
|
||||
wire m_axis_rq_tlast;
|
||||
wire [AXIS_PCIE_RQ_USER_WIDTH-1:0] m_axis_rq_tuser;
|
||||
wire m_axis_rq_tvalid;
|
||||
wire s_axis_rc_tready;
|
||||
wire s_axis_cq_tready;
|
||||
wire [AXIS_PCIE_DATA_WIDTH-1:0] m_axis_cc_tdata;
|
||||
wire [AXIS_PCIE_KEEP_WIDTH-1:0] m_axis_cc_tkeep;
|
||||
wire m_axis_cc_tlast;
|
||||
wire [AXIS_PCIE_CC_USER_WIDTH-1:0] m_axis_cc_tuser;
|
||||
wire m_axis_cc_tvalid;
|
||||
wire [9:0] cfg_mgmt_addr;
|
||||
wire [7:0] cfg_mgmt_function_number;
|
||||
wire cfg_mgmt_write;
|
||||
wire [31:0] cfg_mgmt_write_data;
|
||||
wire [3:0] cfg_mgmt_byte_enable;
|
||||
wire cfg_mgmt_read;
|
||||
wire [3:0] cfg_interrupt_msi_select;
|
||||
wire [31:0] cfg_interrupt_msi_int;
|
||||
wire [31:0] cfg_interrupt_msi_pending_status;
|
||||
wire cfg_interrupt_msi_pending_status_data_enable;
|
||||
wire [3:0] cfg_interrupt_msi_pending_status_function_num;
|
||||
wire [2:0] cfg_interrupt_msi_attr;
|
||||
wire cfg_interrupt_msi_tph_present;
|
||||
wire [1:0] cfg_interrupt_msi_tph_type;
|
||||
wire [8:0] cfg_interrupt_msi_tph_st_tag;
|
||||
wire [3:0] cfg_interrupt_msi_function_number;
|
||||
wire status_error_cor;
|
||||
wire status_error_uncor;
|
||||
|
||||
initial begin
|
||||
// myhdl integration
|
||||
$from_myhdl(
|
||||
clk,
|
||||
rst,
|
||||
current_test,
|
||||
sw,
|
||||
m_axis_rq_tready,
|
||||
s_axis_rc_tdata,
|
||||
s_axis_rc_tkeep,
|
||||
s_axis_rc_tlast,
|
||||
s_axis_rc_tuser,
|
||||
s_axis_rc_tvalid,
|
||||
s_axis_cq_tdata,
|
||||
s_axis_cq_tkeep,
|
||||
s_axis_cq_tlast,
|
||||
s_axis_cq_tuser,
|
||||
s_axis_cq_tvalid,
|
||||
m_axis_cc_tready,
|
||||
cfg_max_payload,
|
||||
cfg_max_read_req,
|
||||
cfg_mgmt_read_data,
|
||||
cfg_mgmt_read_write_done,
|
||||
cfg_interrupt_msi_enable,
|
||||
cfg_interrupt_msi_mmenable,
|
||||
cfg_interrupt_msi_mask_update,
|
||||
cfg_interrupt_msi_data,
|
||||
cfg_interrupt_msi_sent,
|
||||
cfg_interrupt_msi_fail
|
||||
);
|
||||
$to_myhdl(
|
||||
led,
|
||||
m_axis_rq_tdata,
|
||||
m_axis_rq_tkeep,
|
||||
m_axis_rq_tlast,
|
||||
m_axis_rq_tuser,
|
||||
m_axis_rq_tvalid,
|
||||
s_axis_rc_tready,
|
||||
s_axis_cq_tready,
|
||||
m_axis_cc_tdata,
|
||||
m_axis_cc_tkeep,
|
||||
m_axis_cc_tlast,
|
||||
m_axis_cc_tuser,
|
||||
m_axis_cc_tvalid,
|
||||
cfg_mgmt_addr,
|
||||
cfg_mgmt_function_number,
|
||||
cfg_mgmt_write,
|
||||
cfg_mgmt_write_data,
|
||||
cfg_mgmt_byte_enable,
|
||||
cfg_mgmt_read,
|
||||
cfg_interrupt_msi_select,
|
||||
cfg_interrupt_msi_int,
|
||||
cfg_interrupt_msi_pending_status,
|
||||
cfg_interrupt_msi_pending_status_data_enable,
|
||||
cfg_interrupt_msi_pending_status_function_num,
|
||||
cfg_interrupt_msi_attr,
|
||||
cfg_interrupt_msi_tph_present,
|
||||
cfg_interrupt_msi_tph_type,
|
||||
cfg_interrupt_msi_tph_st_tag,
|
||||
cfg_interrupt_msi_function_number,
|
||||
status_error_cor,
|
||||
status_error_uncor
|
||||
);
|
||||
|
||||
// dump file
|
||||
$dumpfile("test_fpga_core.lxt");
|
||||
$dumpvars(0, test_fpga_core);
|
||||
end
|
||||
|
||||
fpga_core #(
|
||||
.AXIS_PCIE_DATA_WIDTH(AXIS_PCIE_DATA_WIDTH),
|
||||
.AXIS_PCIE_KEEP_WIDTH(AXIS_PCIE_KEEP_WIDTH),
|
||||
.AXIS_PCIE_RC_USER_WIDTH(AXIS_PCIE_RC_USER_WIDTH),
|
||||
.AXIS_PCIE_RQ_USER_WIDTH(AXIS_PCIE_RQ_USER_WIDTH),
|
||||
.AXIS_PCIE_CQ_USER_WIDTH(AXIS_PCIE_CQ_USER_WIDTH),
|
||||
.AXIS_PCIE_CC_USER_WIDTH(AXIS_PCIE_CC_USER_WIDTH)
|
||||
)
|
||||
UUT (
|
||||
.clk(clk),
|
||||
.rst(rst),
|
||||
.sw(sw),
|
||||
.led(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_function_number(cfg_mgmt_function_number),
|
||||
.cfg_mgmt_write(cfg_mgmt_write),
|
||||
.cfg_mgmt_write_data(cfg_mgmt_write_data),
|
||||
.cfg_mgmt_byte_enable(cfg_mgmt_byte_enable),
|
||||
.cfg_mgmt_read(cfg_mgmt_read),
|
||||
.cfg_mgmt_read_data(cfg_mgmt_read_data),
|
||||
.cfg_mgmt_read_write_done(cfg_mgmt_read_write_done),
|
||||
.cfg_interrupt_msi_enable(cfg_interrupt_msi_enable),
|
||||
.cfg_interrupt_msi_mmenable(cfg_interrupt_msi_mmenable),
|
||||
.cfg_interrupt_msi_mask_update(cfg_interrupt_msi_mask_update),
|
||||
.cfg_interrupt_msi_data(cfg_interrupt_msi_data),
|
||||
.cfg_interrupt_msi_select(cfg_interrupt_msi_select),
|
||||
.cfg_interrupt_msi_int(cfg_interrupt_msi_int),
|
||||
.cfg_interrupt_msi_pending_status(cfg_interrupt_msi_pending_status),
|
||||
.cfg_interrupt_msi_pending_status_data_enable(cfg_interrupt_msi_pending_status_data_enable),
|
||||
.cfg_interrupt_msi_pending_status_function_num(cfg_interrupt_msi_pending_status_function_num),
|
||||
.cfg_interrupt_msi_sent(cfg_interrupt_msi_sent),
|
||||
.cfg_interrupt_msi_fail(cfg_interrupt_msi_fail),
|
||||
.cfg_interrupt_msi_attr(cfg_interrupt_msi_attr),
|
||||
.cfg_interrupt_msi_tph_present(cfg_interrupt_msi_tph_present),
|
||||
.cfg_interrupt_msi_tph_type(cfg_interrupt_msi_tph_type),
|
||||
.cfg_interrupt_msi_tph_st_tag(cfg_interrupt_msi_tph_st_tag),
|
||||
.cfg_interrupt_msi_function_number(cfg_interrupt_msi_function_number),
|
||||
.status_error_cor(status_error_cor),
|
||||
.status_error_uncor(status_error_uncor)
|
||||
);
|
||||
|
||||
endmodule
|
@ -1 +0,0 @@
|
||||
../lib/pcie/tb/axis_ep.py
|
107
example/AU250/fpga_axi/tb/fpga_core/Makefile
Normal file
107
example/AU250/fpga_axi/tb/fpga_core/Makefile
Normal file
@ -0,0 +1,107 @@
|
||||
# Copyright (c) 2020 Alex Forencich
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in
|
||||
# all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
# THE SOFTWARE.
|
||||
|
||||
TOPLEVEL_LANG = verilog
|
||||
|
||||
SIM ?= icarus
|
||||
WAVES ?= 0
|
||||
|
||||
COCOTB_HDL_TIMEUNIT = 1ns
|
||||
COCOTB_HDL_TIMEPRECISION = 1ps
|
||||
|
||||
DUT = fpga_core
|
||||
TOPLEVEL = $(DUT)
|
||||
MODULE = test_$(DUT)
|
||||
VERILOG_SOURCES += ../../rtl/$(DUT).v
|
||||
VERILOG_SOURCES += ../../rtl/axi_ram.v
|
||||
VERILOG_SOURCES += ../../rtl/axis_register.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/axis_arb_mux.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_axil_master.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_axi_dma.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_axi_dma_rd.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_axi_dma_wr.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_tag_manager.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_axi_master.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_axi_master_rd.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_axi_master_wr.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_axis_cq_demux.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_cfg.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_msi.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/arbiter.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/priority_encoder.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pulse_merge.v
|
||||
|
||||
# module parameters
|
||||
export PARAM_AXIS_PCIE_DATA_WIDTH ?= 512
|
||||
export PARAM_AXIS_PCIE_KEEP_WIDTH ?= $(shell expr $(PARAM_AXIS_PCIE_DATA_WIDTH) / 32 )
|
||||
export PARAM_AXIS_PCIE_RQ_USER_WIDTH ?= $(if $(filter-out 512,$(PARAM_AXIS_PCIE_DATA_WIDTH)),62,137)
|
||||
export PARAM_AXIS_PCIE_RC_USER_WIDTH ?= $(if $(filter-out 512,$(PARAM_AXIS_PCIE_DATA_WIDTH)),75,161)
|
||||
export PARAM_AXIS_PCIE_CQ_USER_WIDTH ?= $(if $(filter-out 512,$(PARAM_AXIS_PCIE_DATA_WIDTH)),88,183)
|
||||
export PARAM_AXIS_PCIE_CC_USER_WIDTH ?= $(if $(filter-out 512,$(PARAM_AXIS_PCIE_DATA_WIDTH)),33,81)
|
||||
export PARAM_RQ_SEQ_NUM_WIDTH ?= 6
|
||||
|
||||
SIM_BUILD ?= sim_build_$(MODULE)
|
||||
|
||||
ifeq ($(SIM), icarus)
|
||||
PLUSARGS += -fst
|
||||
|
||||
COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_DATA_WIDTH=$(PARAM_AXIS_PCIE_DATA_WIDTH)
|
||||
COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_KEEP_WIDTH=$(PARAM_AXIS_PCIE_KEEP_WIDTH)
|
||||
COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_RQ_USER_WIDTH=$(PARAM_AXIS_PCIE_RQ_USER_WIDTH)
|
||||
COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_RC_USER_WIDTH=$(PARAM_AXIS_PCIE_RC_USER_WIDTH)
|
||||
COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_CQ_USER_WIDTH=$(PARAM_AXIS_PCIE_CQ_USER_WIDTH)
|
||||
COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_CC_USER_WIDTH=$(PARAM_AXIS_PCIE_CC_USER_WIDTH)
|
||||
COMPILE_ARGS += -P $(TOPLEVEL).RQ_SEQ_NUM_WIDTH=$(PARAM_RQ_SEQ_NUM_WIDTH)
|
||||
|
||||
ifeq ($(WAVES), 1)
|
||||
VERILOG_SOURCES += iverilog_dump.v
|
||||
COMPILE_ARGS += -s iverilog_dump
|
||||
endif
|
||||
else ifeq ($(SIM), verilator)
|
||||
COMPILE_ARGS += -Wno-SELRANGE -Wno-WIDTH
|
||||
|
||||
COMPILE_ARGS += -GAXIS_PCIE_DATA_WIDTH=$(PARAM_AXIS_PCIE_DATA_WIDTH)
|
||||
COMPILE_ARGS += -GAXIS_PCIE_KEEP_WIDTH=$(PARAM_AXIS_PCIE_KEEP_WIDTH)
|
||||
COMPILE_ARGS += -GAXIS_PCIE_RQ_USER_WIDTH=$(PARAM_AXIS_PCIE_RQ_USER_WIDTH)
|
||||
COMPILE_ARGS += -GAXIS_PCIE_RC_USER_WIDTH=$(PARAM_AXIS_PCIE_RC_USER_WIDTH)
|
||||
COMPILE_ARGS += -GAXIS_PCIE_CQ_USER_WIDTH=$(PARAM_AXIS_PCIE_CQ_USER_WIDTH)
|
||||
COMPILE_ARGS += -GAXIS_PCIE_CC_USER_WIDTH=$(PARAM_AXIS_PCIE_CC_USER_WIDTH)
|
||||
COMPILE_ARGS += -GRQ_SEQ_NUM_WIDTH=$(PARAM_RQ_SEQ_NUM_WIDTH)
|
||||
|
||||
ifeq ($(WAVES), 1)
|
||||
COMPILE_ARGS += --trace-fst
|
||||
endif
|
||||
endif
|
||||
|
||||
iverilog_dump.v:
|
||||
echo 'module iverilog_dump();' > $@
|
||||
echo 'initial begin' >> $@
|
||||
echo ' $$dumpfile("$(TOPLEVEL).fst");' >> $@
|
||||
echo ' $$dumpvars(0, $(TOPLEVEL));' >> $@
|
||||
echo 'end' >> $@
|
||||
echo 'endmodule' >> $@
|
||||
|
||||
clean::
|
||||
@rm -rf sim_build_*
|
||||
@rm -rf iverilog_dump.v
|
||||
@rm -rf dump.fst $(TOPLEVEL).fst
|
||||
|
||||
include $(shell cocotb-config --makefiles)/Makefile.sim
|
||||
|
380
example/AU250/fpga_axi/tb/fpga_core/test_fpga_core.py
Normal file
380
example/AU250/fpga_axi/tb/fpga_core/test_fpga_core.py
Normal file
@ -0,0 +1,380 @@
|
||||
"""
|
||||
|
||||
Copyright (c) 2020 Alex Forencich
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
"""
|
||||
|
||||
import logging
|
||||
import os
|
||||
|
||||
import cocotb_test.simulator
|
||||
|
||||
import cocotb
|
||||
from cocotb.log import SimLog
|
||||
from cocotb.triggers import RisingEdge, FallingEdge, Timer
|
||||
|
||||
from cocotbext.pcie.core import RootComplex
|
||||
from cocotbext.pcie.xilinx.us import UltraScalePlusPcieDevice
|
||||
from cocotbext.axi.utils import hexdump_str
|
||||
|
||||
|
||||
class TB(object):
|
||||
def __init__(self, dut):
|
||||
self.dut = dut
|
||||
|
||||
self.log = SimLog("cocotb.tb")
|
||||
self.log.setLevel(logging.DEBUG)
|
||||
|
||||
# PCIe
|
||||
self.rc = RootComplex()
|
||||
|
||||
self.dev = UltraScalePlusPcieDevice(
|
||||
# configuration options
|
||||
pcie_generation=3,
|
||||
pcie_link_width=16,
|
||||
user_clk_frequency=250e6,
|
||||
alignment="dword",
|
||||
cq_cc_straddle=False,
|
||||
rq_rc_straddle=False,
|
||||
rc_4tlp_straddle=False,
|
||||
enable_pf1=False,
|
||||
enable_client_tag=True,
|
||||
enable_extended_tag=True,
|
||||
enable_parity=False,
|
||||
enable_rx_msg_interface=False,
|
||||
enable_sriov=False,
|
||||
enable_extended_configuration=False,
|
||||
|
||||
enable_pf0_msi=True,
|
||||
enable_pf1_msi=False,
|
||||
|
||||
# signals
|
||||
# Clock and Reset Interface
|
||||
user_clk=dut.clk,
|
||||
user_reset=dut.rst,
|
||||
# user_lnk_up
|
||||
# sys_clk
|
||||
# sys_clk_gt
|
||||
# sys_reset
|
||||
# phy_rdy_out
|
||||
|
||||
# Requester reQuest Interface
|
||||
rq_entity=dut,
|
||||
rq_name="m_axis_rq",
|
||||
# pcie_rq_seq_num0=dut.s_axis_rq_seq_num_0,
|
||||
# pcie_rq_seq_num_vld0=dut.s_axis_rq_seq_num_valid_0,
|
||||
# pcie_rq_seq_num1=dut.s_axis_rq_seq_num_1,
|
||||
# pcie_rq_seq_num_vld1=dut.s_axis_rq_seq_num_valid_1,
|
||||
# pcie_rq_tag0
|
||||
# pcie_rq_tag1
|
||||
# pcie_rq_tag_av
|
||||
# pcie_rq_tag_vld0
|
||||
# pcie_rq_tag_vld1
|
||||
|
||||
# Requester Completion Interface
|
||||
rc_entity=dut,
|
||||
rc_name="s_axis_rc",
|
||||
|
||||
# Completer reQuest Interface
|
||||
cq_entity=dut,
|
||||
cq_name="s_axis_cq",
|
||||
# pcie_cq_np_req
|
||||
# pcie_cq_np_req_count
|
||||
|
||||
# Completer Completion Interface
|
||||
cc_entity=dut,
|
||||
cc_name="m_axis_cc",
|
||||
|
||||
# Transmit Flow Control Interface
|
||||
# pcie_tfc_nph_av=dut.pcie_tfc_nph_av,
|
||||
# pcie_tfc_npd_av=dut.pcie_tfc_npd_av,
|
||||
|
||||
# Configuration Management Interface
|
||||
cfg_mgmt_addr=dut.cfg_mgmt_addr,
|
||||
cfg_mgmt_function_number=dut.cfg_mgmt_function_number,
|
||||
cfg_mgmt_write=dut.cfg_mgmt_write,
|
||||
cfg_mgmt_write_data=dut.cfg_mgmt_write_data,
|
||||
cfg_mgmt_byte_enable=dut.cfg_mgmt_byte_enable,
|
||||
cfg_mgmt_read=dut.cfg_mgmt_read,
|
||||
cfg_mgmt_read_data=dut.cfg_mgmt_read_data,
|
||||
cfg_mgmt_read_write_done=dut.cfg_mgmt_read_write_done,
|
||||
# cfg_mgmt_debug_access
|
||||
|
||||
# Configuration Status Interface
|
||||
# cfg_phy_link_down
|
||||
# cfg_phy_link_status
|
||||
# cfg_negotiated_width
|
||||
# cfg_current_speed
|
||||
cfg_max_payload=dut.cfg_max_payload,
|
||||
cfg_max_read_req=dut.cfg_max_read_req,
|
||||
# cfg_function_status
|
||||
# cfg_vf_status
|
||||
# cfg_function_power_state
|
||||
# cfg_vf_power_state
|
||||
# cfg_link_power_state
|
||||
# cfg_err_cor_out
|
||||
# cfg_err_nonfatal_out
|
||||
# cfg_err_fatal_out
|
||||
# cfg_local_error_out
|
||||
# cfg_local_error_valid
|
||||
# cfg_rx_pm_state
|
||||
# cfg_tx_pm_state
|
||||
# cfg_ltssm_state
|
||||
# cfg_rcb_status
|
||||
# cfg_obff_enable
|
||||
# cfg_pl_status_change
|
||||
# cfg_tph_requester_enable
|
||||
# cfg_tph_st_mode
|
||||
# cfg_vf_tph_requester_enable
|
||||
# cfg_vf_tph_st_mode
|
||||
|
||||
# Configuration Received Message Interface
|
||||
# cfg_msg_received
|
||||
# cfg_msg_received_data
|
||||
# cfg_msg_received_type
|
||||
|
||||
# Configuration Transmit Message Interface
|
||||
# cfg_msg_transmit
|
||||
# cfg_msg_transmit_type
|
||||
# cfg_msg_transmit_data
|
||||
# cfg_msg_transmit_done
|
||||
|
||||
# Configuration Flow Control Interface
|
||||
# cfg_fc_ph=dut.cfg_fc_ph,
|
||||
# cfg_fc_pd=dut.cfg_fc_pd,
|
||||
# cfg_fc_nph=dut.cfg_fc_nph,
|
||||
# cfg_fc_npd=dut.cfg_fc_npd,
|
||||
# cfg_fc_cplh=dut.cfg_fc_cplh,
|
||||
# cfg_fc_cpld=dut.cfg_fc_cpld,
|
||||
# cfg_fc_sel=dut.cfg_fc_sel,
|
||||
|
||||
# Configuration Control Interface
|
||||
# cfg_hot_reset_in
|
||||
# cfg_hot_reset_out
|
||||
# cfg_config_space_enable
|
||||
# cfg_dsn
|
||||
# cfg_bus_number
|
||||
# cfg_ds_port_number
|
||||
# cfg_ds_bus_number
|
||||
# cfg_ds_device_number
|
||||
# cfg_ds_function_number
|
||||
# cfg_power_state_change_ack
|
||||
# cfg_power_state_change_interrupt
|
||||
cfg_err_cor_in=dut.status_error_cor,
|
||||
cfg_err_uncor_in=dut.status_error_uncor,
|
||||
# cfg_flr_in_process
|
||||
# cfg_flr_done
|
||||
# cfg_vf_flr_in_process
|
||||
# cfg_vf_flr_func_num
|
||||
# cfg_vf_flr_done
|
||||
# cfg_pm_aspm_l1_entry_reject
|
||||
# cfg_pm_aspm_tx_l0s_entry_disable
|
||||
# cfg_req_pm_transition_l23_ready
|
||||
# cfg_link_training_enable
|
||||
|
||||
# Configuration Interrupt Controller Interface
|
||||
# cfg_interrupt_int
|
||||
# cfg_interrupt_sent
|
||||
# cfg_interrupt_pending
|
||||
cfg_interrupt_msi_enable=dut.cfg_interrupt_msi_enable,
|
||||
cfg_interrupt_msi_mmenable=dut.cfg_interrupt_msi_mmenable,
|
||||
cfg_interrupt_msi_mask_update=dut.cfg_interrupt_msi_mask_update,
|
||||
cfg_interrupt_msi_data=dut.cfg_interrupt_msi_data,
|
||||
# cfg_interrupt_msi_select=dut.cfg_interrupt_msi_select,
|
||||
cfg_interrupt_msi_int=dut.cfg_interrupt_msi_int,
|
||||
cfg_interrupt_msi_pending_status=dut.cfg_interrupt_msi_pending_status,
|
||||
cfg_interrupt_msi_pending_status_data_enable=dut.cfg_interrupt_msi_pending_status_data_enable,
|
||||
# cfg_interrupt_msi_pending_status_function_num=dut.cfg_interrupt_msi_pending_status_function_num,
|
||||
cfg_interrupt_msi_sent=dut.cfg_interrupt_msi_sent,
|
||||
cfg_interrupt_msi_fail=dut.cfg_interrupt_msi_fail,
|
||||
# cfg_interrupt_msix_enable
|
||||
# cfg_interrupt_msix_mask
|
||||
# cfg_interrupt_msix_vf_enable
|
||||
# cfg_interrupt_msix_vf_mask
|
||||
# cfg_interrupt_msix_address
|
||||
# cfg_interrupt_msix_data
|
||||
# cfg_interrupt_msix_int
|
||||
# cfg_interrupt_msix_vec_pending
|
||||
# cfg_interrupt_msix_vec_pending_status
|
||||
cfg_interrupt_msi_attr=dut.cfg_interrupt_msi_attr,
|
||||
cfg_interrupt_msi_tph_present=dut.cfg_interrupt_msi_tph_present,
|
||||
cfg_interrupt_msi_tph_type=dut.cfg_interrupt_msi_tph_type,
|
||||
# cfg_interrupt_msi_tph_st_tag=dut.cfg_interrupt_msi_tph_st_tag,
|
||||
# cfg_interrupt_msi_function_number=dut.cfg_interrupt_msi_function_number,
|
||||
|
||||
# Configuration Extend Interface
|
||||
# cfg_ext_read_received
|
||||
# cfg_ext_write_received
|
||||
# cfg_ext_register_number
|
||||
# cfg_ext_function_number
|
||||
# cfg_ext_write_data
|
||||
# cfg_ext_write_byte_enable
|
||||
# cfg_ext_read_data
|
||||
# cfg_ext_read_data_valid
|
||||
)
|
||||
|
||||
# self.dev.log.setLevel(logging.DEBUG)
|
||||
|
||||
self.rc.make_port().connect(self.dev)
|
||||
|
||||
self.dev.functions[0].msi_multiple_message_capable = 5
|
||||
|
||||
self.dev.functions[0].configure_bar(0, 2**22)
|
||||
self.dev.functions[0].configure_bar(1, 2**22)
|
||||
|
||||
dut.sw.setimmediatevalue(0)
|
||||
|
||||
async def init(self):
|
||||
|
||||
await FallingEdge(self.dut.rst)
|
||||
await Timer(100, 'ns')
|
||||
|
||||
await self.rc.enumerate(enable_bus_mastering=True, configure_msi=True)
|
||||
|
||||
|
||||
@cocotb.test()
|
||||
async def run_test(dut):
|
||||
|
||||
tb = TB(dut)
|
||||
|
||||
await tb.init()
|
||||
|
||||
mem_base, mem_data = tb.rc.alloc_region(16*1024*1024)
|
||||
|
||||
dev_pf0_bar0 = tb.rc.tree[0][0].bar_addr[0]
|
||||
dev_pf0_bar1 = tb.rc.tree[0][0].bar_addr[1]
|
||||
|
||||
tb.log.info("Test memory write to BAR 1")
|
||||
|
||||
await tb.rc.mem_write(dev_pf0_bar1, b'\x11\x22\x33\x44')
|
||||
|
||||
await Timer(100, 'ns')
|
||||
|
||||
tb.log.info("Test memory read from BAR 1")
|
||||
|
||||
val = await tb.rc.mem_read(dev_pf0_bar1, 4, 1000)
|
||||
tb.log.info("Read data: %s", val)
|
||||
assert val == b'\x11\x22\x33\x44'
|
||||
|
||||
tb.log.info("Test DMA")
|
||||
|
||||
# write packet data
|
||||
mem_data[0:1024] = bytearray([x % 256 for x in range(1024)])
|
||||
|
||||
# enable DMA
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100000, 1)
|
||||
|
||||
# write pcie read descriptor
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100100, (mem_base+0x0000) & 0xffffffff)
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100104, (mem_base+0x0000 >> 32) & 0xffffffff)
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100108, (0x100) & 0xffffffff)
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x10010C, (0x100 >> 32) & 0xffffffff)
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100110, 0x400)
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100114, 0xAA)
|
||||
|
||||
await Timer(2000, 'ns')
|
||||
|
||||
# read status
|
||||
val = await tb.rc.mem_read_dword(dev_pf0_bar0+0x100118)
|
||||
tb.log.info("Status: 0x%x", val)
|
||||
assert val == 0xAA
|
||||
|
||||
# write pcie write descriptor
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100200, (mem_base+0x1000) & 0xffffffff)
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100204, (mem_base+0x1000 >> 32) & 0xffffffff)
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100208, (0x100) & 0xffffffff)
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x10020C, (0x100 >> 32) & 0xffffffff)
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100210, 0x400)
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100214, 0x55)
|
||||
|
||||
await Timer(2000, 'ns')
|
||||
|
||||
# read status
|
||||
val = await tb.rc.mem_read_dword(dev_pf0_bar0+0x100218)
|
||||
tb.log.info("Status: 0x%x", val)
|
||||
assert val == 0x55
|
||||
|
||||
tb.log.info("%s", hexdump_str(mem_data, 0x1000, 64))
|
||||
|
||||
assert mem_data[0:1024] == mem_data[0x1000:0x1000+1024]
|
||||
|
||||
await RisingEdge(dut.clk)
|
||||
await RisingEdge(dut.clk)
|
||||
|
||||
|
||||
# cocotb-test
|
||||
|
||||
tests_dir = os.path.dirname(__file__)
|
||||
rtl_dir = os.path.abspath(os.path.join(tests_dir, '..', '..', 'rtl'))
|
||||
lib_dir = os.path.abspath(os.path.join(rtl_dir, '..', 'lib'))
|
||||
pcie_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'pcie', 'rtl'))
|
||||
|
||||
|
||||
def test_fpga_core(request):
|
||||
dut = "fpga_core"
|
||||
module = os.path.splitext(os.path.basename(__file__))[0]
|
||||
toplevel = dut
|
||||
|
||||
verilog_sources = [
|
||||
os.path.join(rtl_dir, f"{dut}.v"),
|
||||
os.path.join(rtl_dir, "axi_ram.v"),
|
||||
os.path.join(rtl_dir, "axis_register.v"),
|
||||
os.path.join(pcie_rtl_dir, "axis_arb_mux.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_us_axil_master.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_us_axi_dma.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_us_axi_dma_rd.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_us_axi_dma_wr.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_tag_manager.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_us_axi_master.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_us_axi_master_rd.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_us_axi_master_wr.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_us_axis_cq_demux.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_us_cfg.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_us_msi.v"),
|
||||
os.path.join(pcie_rtl_dir, "arbiter.v"),
|
||||
os.path.join(pcie_rtl_dir, "priority_encoder.v"),
|
||||
os.path.join(pcie_rtl_dir, "pulse_merge.v"),
|
||||
]
|
||||
|
||||
parameters = {}
|
||||
|
||||
parameters['AXIS_PCIE_DATA_WIDTH'] = 512
|
||||
parameters['AXIS_PCIE_KEEP_WIDTH'] = parameters['AXIS_PCIE_DATA_WIDTH'] // 32
|
||||
parameters['AXIS_PCIE_RQ_USER_WIDTH'] = 62 if parameters['AXIS_PCIE_DATA_WIDTH'] < 512 else 137
|
||||
parameters['AXIS_PCIE_RC_USER_WIDTH'] = 75 if parameters['AXIS_PCIE_DATA_WIDTH'] < 512 else 161
|
||||
parameters['AXIS_PCIE_CQ_USER_WIDTH'] = 88 if parameters['AXIS_PCIE_DATA_WIDTH'] < 512 else 183
|
||||
parameters['AXIS_PCIE_CC_USER_WIDTH'] = 33 if parameters['AXIS_PCIE_DATA_WIDTH'] < 512 else 81
|
||||
parameters['RQ_SEQ_NUM_WIDTH'] = 6
|
||||
|
||||
extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()}
|
||||
|
||||
sim_build = os.path.join(tests_dir,
|
||||
"sim_build_"+request.node.name.replace('[', '-').replace(']', ''))
|
||||
|
||||
cocotb_test.simulator.run(
|
||||
python_search=[tests_dir],
|
||||
verilog_sources=verilog_sources,
|
||||
toplevel=toplevel,
|
||||
module=module,
|
||||
parameters=parameters,
|
||||
sim_build=sim_build,
|
||||
extra_env=extra_env,
|
||||
)
|
@ -1 +0,0 @@
|
||||
../lib/pcie/tb/pcie.py
|
@ -1 +0,0 @@
|
||||
../lib/pcie/tb/pcie_us.py
|
@ -1 +0,0 @@
|
||||
../lib/pcie/tb/pcie_usp.py
|
@ -1,520 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
"""
|
||||
|
||||
Copyright (c) 2018 Alex Forencich
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
"""
|
||||
|
||||
from myhdl import *
|
||||
import os
|
||||
import struct
|
||||
|
||||
import pcie
|
||||
import pcie_usp
|
||||
|
||||
module = 'fpga_core'
|
||||
testbench = 'test_%s' % module
|
||||
|
||||
srcs = []
|
||||
|
||||
srcs.append("../rtl/%s.v" % module)
|
||||
srcs.append("../rtl/axi_ram.v")
|
||||
srcs.append("../rtl/axis_register.v")
|
||||
srcs.append("../lib/pcie/rtl/axis_arb_mux.v")
|
||||
srcs.append("../lib/pcie/rtl/pcie_us_axil_master.v")
|
||||
srcs.append("../lib/pcie/rtl/pcie_us_axi_dma.v")
|
||||
srcs.append("../lib/pcie/rtl/pcie_us_axi_dma_rd.v")
|
||||
srcs.append("../lib/pcie/rtl/pcie_us_axi_dma_wr.v")
|
||||
srcs.append("../lib/pcie/rtl/pcie_tag_manager.v")
|
||||
srcs.append("../lib/pcie/rtl/pcie_us_axi_master.v")
|
||||
srcs.append("../lib/pcie/rtl/pcie_us_axi_master_rd.v")
|
||||
srcs.append("../lib/pcie/rtl/pcie_us_axi_master_wr.v")
|
||||
srcs.append("../lib/pcie/rtl/pcie_us_axis_cq_demux.v")
|
||||
srcs.append("../lib/pcie/rtl/pcie_us_cfg.v")
|
||||
srcs.append("../lib/pcie/rtl/pcie_us_msi.v")
|
||||
srcs.append("../lib/pcie/rtl/arbiter.v")
|
||||
srcs.append("../lib/pcie/rtl/priority_encoder.v")
|
||||
srcs.append("../lib/pcie/rtl/pulse_merge.v")
|
||||
srcs.append("%s.v" % testbench)
|
||||
|
||||
src = ' '.join(srcs)
|
||||
|
||||
build_cmd = "iverilog -o %s.vvp %s" % (testbench, src)
|
||||
|
||||
def bench():
|
||||
|
||||
# Parameters
|
||||
AXIS_PCIE_DATA_WIDTH = 512
|
||||
AXIS_PCIE_KEEP_WIDTH = (AXIS_PCIE_DATA_WIDTH/32)
|
||||
AXIS_PCIE_RC_USER_WIDTH = 161
|
||||
AXIS_PCIE_RQ_USER_WIDTH = 137
|
||||
AXIS_PCIE_CQ_USER_WIDTH = 183
|
||||
AXIS_PCIE_CC_USER_WIDTH = 81
|
||||
|
||||
# Inputs
|
||||
clk = Signal(bool(0))
|
||||
rst = Signal(bool(0))
|
||||
current_test = Signal(intbv(0)[8:])
|
||||
|
||||
btnu = Signal(bool(0))
|
||||
btnl = Signal(bool(0))
|
||||
btnd = Signal(bool(0))
|
||||
btnr = Signal(bool(0))
|
||||
btnc = Signal(bool(0))
|
||||
sw = Signal(intbv(0)[4:])
|
||||
m_axis_rq_tready = Signal(bool(0))
|
||||
s_axis_rc_tdata = Signal(intbv(0)[AXIS_PCIE_DATA_WIDTH:])
|
||||
s_axis_rc_tkeep = Signal(intbv(0)[AXIS_PCIE_KEEP_WIDTH:])
|
||||
s_axis_rc_tlast = Signal(bool(0))
|
||||
s_axis_rc_tuser = Signal(intbv(0)[AXIS_PCIE_RC_USER_WIDTH:])
|
||||
s_axis_rc_tvalid = Signal(bool(0))
|
||||
s_axis_cq_tdata = Signal(intbv(0)[AXIS_PCIE_DATA_WIDTH:])
|
||||
s_axis_cq_tkeep = Signal(intbv(0)[AXIS_PCIE_KEEP_WIDTH:])
|
||||
s_axis_cq_tlast = Signal(bool(0))
|
||||
s_axis_cq_tuser = Signal(intbv(0)[AXIS_PCIE_CQ_USER_WIDTH:])
|
||||
s_axis_cq_tvalid = Signal(bool(0))
|
||||
m_axis_cc_tready = Signal(bool(0))
|
||||
cfg_max_payload = Signal(intbv(0)[2:])
|
||||
cfg_max_read_req = Signal(intbv(0)[3:])
|
||||
cfg_mgmt_read_data = Signal(intbv(0)[32:])
|
||||
cfg_mgmt_read_write_done = Signal(bool(0))
|
||||
cfg_interrupt_msi_enable = Signal(intbv(0)[4:])
|
||||
cfg_interrupt_msi_mmenable = Signal(intbv(0)[12:])
|
||||
cfg_interrupt_msi_mask_update = Signal(bool(0))
|
||||
cfg_interrupt_msi_data = Signal(intbv(0)[32:])
|
||||
cfg_interrupt_msi_sent = Signal(bool(0))
|
||||
cfg_interrupt_msi_fail = Signal(bool(0))
|
||||
|
||||
# Outputs
|
||||
led = Signal(intbv(0)[8:])
|
||||
m_axis_rq_tdata = Signal(intbv(0)[AXIS_PCIE_DATA_WIDTH:])
|
||||
m_axis_rq_tkeep = Signal(intbv(0)[AXIS_PCIE_KEEP_WIDTH:])
|
||||
m_axis_rq_tlast = Signal(bool(0))
|
||||
m_axis_rq_tuser = Signal(intbv(0)[AXIS_PCIE_RQ_USER_WIDTH:])
|
||||
m_axis_rq_tvalid = Signal(bool(0))
|
||||
s_axis_rc_tready = Signal(bool(0))
|
||||
s_axis_cq_tready = Signal(bool(0))
|
||||
m_axis_cc_tdata = Signal(intbv(0)[AXIS_PCIE_DATA_WIDTH:])
|
||||
m_axis_cc_tkeep = Signal(intbv(0)[AXIS_PCIE_KEEP_WIDTH:])
|
||||
m_axis_cc_tlast = Signal(bool(0))
|
||||
m_axis_cc_tuser = Signal(intbv(0)[AXIS_PCIE_CC_USER_WIDTH:])
|
||||
m_axis_cc_tvalid = Signal(bool(0))
|
||||
status_error_cor = Signal(bool(0))
|
||||
status_error_uncor = Signal(bool(0))
|
||||
cfg_mgmt_addr = Signal(intbv(0)[10:])
|
||||
cfg_mgmt_function_number = Signal(intbv(0)[8:])
|
||||
cfg_mgmt_write = Signal(bool(0))
|
||||
cfg_mgmt_write_data = Signal(intbv(0)[32:])
|
||||
cfg_mgmt_byte_enable = Signal(intbv(0)[4:])
|
||||
cfg_mgmt_read = Signal(bool(0))
|
||||
cfg_interrupt_msi_int = Signal(intbv(0)[32:])
|
||||
cfg_interrupt_msi_pending_status = Signal(intbv(0)[32:])
|
||||
cfg_interrupt_msi_select = Signal(intbv(0)[2:])
|
||||
cfg_interrupt_msi_pending_status_function_num = Signal(intbv(0)[2:])
|
||||
cfg_interrupt_msi_pending_status_data_enable = Signal(bool(0))
|
||||
cfg_interrupt_msi_attr = Signal(intbv(0)[3:])
|
||||
cfg_interrupt_msi_tph_present = Signal(bool(0))
|
||||
cfg_interrupt_msi_tph_type = Signal(intbv(0)[2:])
|
||||
cfg_interrupt_msi_tph_st_tag = Signal(intbv(0)[8:])
|
||||
cfg_interrupt_msi_function_number = Signal(intbv(0)[8:])
|
||||
|
||||
# Clock and Reset Interface
|
||||
user_clk=Signal(bool(0))
|
||||
user_reset=Signal(bool(0))
|
||||
sys_clk=Signal(bool(0))
|
||||
sys_reset=Signal(bool(0))
|
||||
|
||||
# PCIe devices
|
||||
rc = pcie.RootComplex()
|
||||
|
||||
mem_base, mem_data = rc.alloc_region(16*1024*1024)
|
||||
|
||||
dev = pcie_usp.UltrascalePlusPCIe()
|
||||
|
||||
dev.pcie_generation = 3
|
||||
dev.pcie_link_width = 16
|
||||
dev.user_clk_frequency = 250e6
|
||||
|
||||
dev.functions[0].msi_multiple_message_capable = 5
|
||||
|
||||
dev.functions[0].configure_bar(0, 4*1024*1024)
|
||||
dev.functions[0].configure_bar(1, 4*1024*1024)
|
||||
|
||||
rc.make_port().connect(dev)
|
||||
|
||||
pcie_logic = dev.create_logic(
|
||||
# Completer reQuest Interface
|
||||
m_axis_cq_tdata=s_axis_cq_tdata,
|
||||
m_axis_cq_tuser=s_axis_cq_tuser,
|
||||
m_axis_cq_tlast=s_axis_cq_tlast,
|
||||
m_axis_cq_tkeep=s_axis_cq_tkeep,
|
||||
m_axis_cq_tvalid=s_axis_cq_tvalid,
|
||||
m_axis_cq_tready=s_axis_cq_tready,
|
||||
#pcie_cq_np_req=pcie_cq_np_req,
|
||||
pcie_cq_np_req=Signal(intbv(1)[2:]),
|
||||
#pcie_cq_np_req_count=pcie_cq_np_req_count,
|
||||
|
||||
# Completer Completion Interface
|
||||
s_axis_cc_tdata=m_axis_cc_tdata,
|
||||
s_axis_cc_tuser=m_axis_cc_tuser,
|
||||
s_axis_cc_tlast=m_axis_cc_tlast,
|
||||
s_axis_cc_tkeep=m_axis_cc_tkeep,
|
||||
s_axis_cc_tvalid=m_axis_cc_tvalid,
|
||||
s_axis_cc_tready=m_axis_cc_tready,
|
||||
|
||||
# Requester reQuest Interface
|
||||
s_axis_rq_tdata=m_axis_rq_tdata,
|
||||
s_axis_rq_tuser=m_axis_rq_tuser,
|
||||
s_axis_rq_tlast=m_axis_rq_tlast,
|
||||
s_axis_rq_tkeep=m_axis_rq_tkeep,
|
||||
s_axis_rq_tvalid=m_axis_rq_tvalid,
|
||||
s_axis_rq_tready=m_axis_rq_tready,
|
||||
#pcie_rq_seq_num0=pcie_rq_seq_num0,
|
||||
#pcie_rq_seq_num_vld0=pcie_rq_seq_num_vld0,
|
||||
#pcie_rq_seq_num1=pcie_rq_seq_num1,
|
||||
#pcie_rq_seq_num_vld1=pcie_rq_seq_num_vld1,
|
||||
#pcie_rq_tag0=pcie_rq_tag0,
|
||||
#pcie_rq_tag1=pcie_rq_tag1,
|
||||
#pcie_rq_tag_av=pcie_rq_tag_av,
|
||||
#pcie_rq_tag_vld0=pcie_rq_tag_vld0,
|
||||
#pcie_rq_tag_vld1=pcie_rq_tag_vld1,
|
||||
|
||||
# Requester Completion Interface
|
||||
m_axis_rc_tdata=s_axis_rc_tdata,
|
||||
m_axis_rc_tuser=s_axis_rc_tuser,
|
||||
m_axis_rc_tlast=s_axis_rc_tlast,
|
||||
m_axis_rc_tkeep=s_axis_rc_tkeep,
|
||||
m_axis_rc_tvalid=s_axis_rc_tvalid,
|
||||
m_axis_rc_tready=s_axis_rc_tready,
|
||||
|
||||
# Transmit Flow Control Interface
|
||||
#pcie_tfc_nph_av=pcie_tfc_nph_av,
|
||||
#pcie_tfc_npd_av=pcie_tfc_npd_av,
|
||||
|
||||
# Configuration Management Interface
|
||||
cfg_mgmt_addr=cfg_mgmt_addr,
|
||||
cfg_mgmt_function_number=cfg_mgmt_function_number,
|
||||
cfg_mgmt_write=cfg_mgmt_write,
|
||||
cfg_mgmt_write_data=cfg_mgmt_write_data,
|
||||
cfg_mgmt_byte_enable=cfg_mgmt_byte_enable,
|
||||
cfg_mgmt_read=cfg_mgmt_read,
|
||||
cfg_mgmt_read_data=cfg_mgmt_read_data,
|
||||
cfg_mgmt_read_write_done=cfg_mgmt_read_write_done,
|
||||
#cfg_mgmt_debug_access=cfg_mgmt_debug_access,
|
||||
|
||||
# Configuration Status Interface
|
||||
#cfg_phy_link_down=cfg_phy_link_down,
|
||||
#cfg_phy_link_status=cfg_phy_link_status,
|
||||
#cfg_negotiated_width=cfg_negotiated_width,
|
||||
#cfg_current_speed=cfg_current_speed,
|
||||
cfg_max_payload=cfg_max_payload,
|
||||
cfg_max_read_req=cfg_max_read_req,
|
||||
#cfg_function_status=cfg_function_status,
|
||||
#cfg_vf_status=cfg_vf_status,
|
||||
#cfg_function_power_state=cfg_function_power_state,
|
||||
#cfg_vf_power_state=cfg_vf_power_state,
|
||||
#cfg_link_power_state=cfg_link_power_state,
|
||||
#cfg_err_cor_out=cfg_err_cor_out,
|
||||
#cfg_err_nonfatal_out=cfg_err_nonfatal_out,
|
||||
#cfg_err_fatal_out=cfg_err_fatal_out,
|
||||
#cfg_local_err_out=cfg_local_err_out,
|
||||
#cfg_local_err_valid=cfg_local_err_valid,
|
||||
#cfg_rx_pm_state=cfg_rx_pm_state,
|
||||
#cfg_tx_pm_state=cfg_tx_pm_state,
|
||||
#cfg_ltssm_state=cfg_ltssm_state,
|
||||
#cfg_rcb_status=cfg_rcb_status,
|
||||
#cfg_obff_enable=cfg_obff_enable,
|
||||
#cfg_pl_status_change=cfg_pl_status_change,
|
||||
#cfg_tph_requester_enable=cfg_tph_requester_enable,
|
||||
#cfg_tph_st_mode=cfg_tph_st_mode,
|
||||
#cfg_vf_tph_requester_enable=cfg_vf_tph_requester_enable,
|
||||
#cfg_vf_tph_st_mode=cfg_vf_tph_st_mode,
|
||||
|
||||
# Configuration Received Message Interface
|
||||
#cfg_msg_received=cfg_msg_received,
|
||||
#cfg_msg_received_data=cfg_msg_received_data,
|
||||
#cfg_msg_received_type=cfg_msg_received_type,
|
||||
|
||||
# Configuration Transmit Message Interface
|
||||
#cfg_msg_transmit=cfg_msg_transmit,
|
||||
#cfg_msg_transmit_type=cfg_msg_transmit_type,
|
||||
#cfg_msg_transmit_data=cfg_msg_transmit_data,
|
||||
#cfg_msg_transmit_done=cfg_msg_transmit_done,
|
||||
|
||||
# Configuration Flow Control Interface
|
||||
#cfg_fc_ph=cfg_fc_ph,
|
||||
#cfg_fc_pd=cfg_fc_pd,
|
||||
#cfg_fc_nph=cfg_fc_nph,
|
||||
#cfg_fc_npd=cfg_fc_npd,
|
||||
#cfg_fc_cplh=cfg_fc_cplh,
|
||||
#cfg_fc_cpld=cfg_fc_cpld,
|
||||
#cfg_fc_sel=cfg_fc_sel,
|
||||
|
||||
# Configuration Control Interface
|
||||
#cfg_hot_reset_in=cfg_hot_reset_in,
|
||||
#cfg_hot_reset_out=cfg_hot_reset_out,
|
||||
#cfg_config_space_enable=cfg_config_space_enable,
|
||||
#cfg_dsn=cfg_dsn,
|
||||
#cfg_ds_port_number=cfg_ds_port_number,
|
||||
#cfg_ds_bus_number=cfg_ds_bus_number,
|
||||
#cfg_ds_device_number=cfg_ds_device_number,
|
||||
#cfg_ds_function_number=cfg_ds_function_number,
|
||||
#cfg_power_state_change_ack=cfg_power_state_change_ack,
|
||||
#cfg_power_state_change_interrupt=cfg_power_state_change_interrupt,
|
||||
cfg_err_cor_in=status_error_cor,
|
||||
cfg_err_uncor_in=status_error_uncor,
|
||||
#cfg_flr_done=cfg_flr_done,
|
||||
#cfg_vf_flr_done=cfg_vf_flr_done,
|
||||
#cfg_flr_in_process=cfg_flr_in_process,
|
||||
#cfg_vf_flr_in_process=cfg_vf_flr_in_process,
|
||||
#cfg_req_pm_transition_l23_ready=cfg_req_pm_transition_l23_ready,
|
||||
#cfg_link_training_enable=cfg_link_training_enable,
|
||||
|
||||
# Configuration Interrupt Controller Interface
|
||||
#cfg_interrupt_int=cfg_interrupt_int,
|
||||
#cfg_interrupt_sent=cfg_interrupt_sent,
|
||||
#cfg_interrupt_pending=cfg_interrupt_pending,
|
||||
cfg_interrupt_msi_enable=cfg_interrupt_msi_enable,
|
||||
cfg_interrupt_msi_mmenable=cfg_interrupt_msi_mmenable,
|
||||
cfg_interrupt_msi_mask_update=cfg_interrupt_msi_mask_update,
|
||||
cfg_interrupt_msi_data=cfg_interrupt_msi_data,
|
||||
cfg_interrupt_msi_select=cfg_interrupt_msi_select,
|
||||
cfg_interrupt_msi_int=cfg_interrupt_msi_int,
|
||||
cfg_interrupt_msi_pending_status=cfg_interrupt_msi_pending_status,
|
||||
cfg_interrupt_msi_pending_status_data_enable=cfg_interrupt_msi_pending_status_data_enable,
|
||||
cfg_interrupt_msi_pending_status_function_num=cfg_interrupt_msi_pending_status_function_num,
|
||||
cfg_interrupt_msi_sent=cfg_interrupt_msi_sent,
|
||||
cfg_interrupt_msi_fail=cfg_interrupt_msi_fail,
|
||||
#cfg_interrupt_msix_enable=cfg_interrupt_msix_enable,
|
||||
#cfg_interrupt_msix_mask=cfg_interrupt_msix_mask,
|
||||
#cfg_interrupt_msix_vf_enable=cfg_interrupt_msix_vf_enable,
|
||||
#cfg_interrupt_msix_vf_mask=cfg_interrupt_msix_vf_mask,
|
||||
#cfg_interrupt_msix_address=cfg_interrupt_msix_address,
|
||||
#cfg_interrupt_msix_data=cfg_interrupt_msix_data,
|
||||
#cfg_interrupt_msix_int=cfg_interrupt_msix_int,
|
||||
#cfg_interrupt_msix_vec_pending=cfg_interrupt_msix_vec_pending,
|
||||
#cfg_interrupt_msix_vec_pending_status=cfg_interrupt_msix_vec_pending_status,
|
||||
cfg_interrupt_msi_attr=cfg_interrupt_msi_attr,
|
||||
cfg_interrupt_msi_tph_present=cfg_interrupt_msi_tph_present,
|
||||
cfg_interrupt_msi_tph_type=cfg_interrupt_msi_tph_type,
|
||||
cfg_interrupt_msi_tph_st_tag=cfg_interrupt_msi_tph_st_tag,
|
||||
cfg_interrupt_msi_function_number=cfg_interrupt_msi_function_number,
|
||||
|
||||
# Configuration Extend Interface
|
||||
#cfg_ext_read_received=cfg_ext_read_received,
|
||||
#cfg_ext_write_received=cfg_ext_write_received,
|
||||
#cfg_ext_register_number=cfg_ext_register_number,
|
||||
#cfg_ext_function_number=cfg_ext_function_number,
|
||||
#cfg_ext_write_data=cfg_ext_write_data,
|
||||
#cfg_ext_write_byte_enable=cfg_ext_write_byte_enable,
|
||||
#cfg_ext_read_data=cfg_ext_read_data,
|
||||
#cfg_ext_read_data_valid=cfg_ext_read_data_valid,
|
||||
|
||||
# Clock and Reset Interface
|
||||
user_clk=user_clk,
|
||||
user_reset=user_reset,
|
||||
#user_lnk_up=user_lnk_up,
|
||||
sys_clk=sys_clk,
|
||||
sys_clk_gt=sys_clk,
|
||||
sys_reset=sys_reset,
|
||||
#phy_rdy_out=phy_rdy_out
|
||||
)
|
||||
|
||||
# DUT
|
||||
if os.system(build_cmd):
|
||||
raise Exception("Error running build command")
|
||||
|
||||
dut = Cosimulation(
|
||||
"vvp -m myhdl %s.vvp -lxt2" % testbench,
|
||||
clk=user_clk,
|
||||
rst=user_reset,
|
||||
current_test=current_test,
|
||||
btnu=btnu,
|
||||
btnl=btnl,
|
||||
btnd=btnd,
|
||||
btnr=btnr,
|
||||
btnc=btnc,
|
||||
sw=sw,
|
||||
led=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_function_number=cfg_mgmt_function_number,
|
||||
cfg_mgmt_write=cfg_mgmt_write,
|
||||
cfg_mgmt_write_data=cfg_mgmt_write_data,
|
||||
cfg_mgmt_byte_enable=cfg_mgmt_byte_enable,
|
||||
cfg_mgmt_read=cfg_mgmt_read,
|
||||
cfg_mgmt_read_data=cfg_mgmt_read_data,
|
||||
cfg_mgmt_read_write_done=cfg_mgmt_read_write_done,
|
||||
cfg_interrupt_msi_enable=cfg_interrupt_msi_enable,
|
||||
cfg_interrupt_msi_int=cfg_interrupt_msi_int,
|
||||
cfg_interrupt_msi_sent=cfg_interrupt_msi_sent,
|
||||
cfg_interrupt_msi_fail=cfg_interrupt_msi_fail,
|
||||
cfg_interrupt_msi_mmenable=cfg_interrupt_msi_mmenable,
|
||||
cfg_interrupt_msi_pending_status=cfg_interrupt_msi_pending_status,
|
||||
cfg_interrupt_msi_mask_update=cfg_interrupt_msi_mask_update,
|
||||
cfg_interrupt_msi_select=cfg_interrupt_msi_select,
|
||||
cfg_interrupt_msi_data=cfg_interrupt_msi_data,
|
||||
cfg_interrupt_msi_pending_status_function_num=cfg_interrupt_msi_pending_status_function_num,
|
||||
cfg_interrupt_msi_pending_status_data_enable=cfg_interrupt_msi_pending_status_data_enable,
|
||||
cfg_interrupt_msi_attr=cfg_interrupt_msi_attr,
|
||||
cfg_interrupt_msi_tph_present=cfg_interrupt_msi_tph_present,
|
||||
cfg_interrupt_msi_tph_type=cfg_interrupt_msi_tph_type,
|
||||
cfg_interrupt_msi_tph_st_tag=cfg_interrupt_msi_tph_st_tag,
|
||||
cfg_interrupt_msi_function_number=cfg_interrupt_msi_function_number,
|
||||
status_error_cor=status_error_cor,
|
||||
status_error_uncor=status_error_uncor
|
||||
)
|
||||
|
||||
@always(delay(5))
|
||||
def clkgen():
|
||||
clk.next = not clk
|
||||
|
||||
@always_comb
|
||||
def clk_logic():
|
||||
sys_clk.next = clk
|
||||
sys_reset.next = not rst
|
||||
|
||||
@instance
|
||||
def check():
|
||||
yield delay(100)
|
||||
yield clk.posedge
|
||||
rst.next = 1
|
||||
yield clk.posedge
|
||||
rst.next = 0
|
||||
yield clk.posedge
|
||||
yield delay(100)
|
||||
yield clk.posedge
|
||||
|
||||
# testbench stimulus
|
||||
|
||||
current_tag = 1
|
||||
|
||||
yield clk.posedge
|
||||
print("test 1: enumeration")
|
||||
current_test.next = 1
|
||||
|
||||
yield rc.enumerate(enable_bus_mastering=True, configure_msi=True)
|
||||
|
||||
dev_pf0_bar0 = dev.functions[0].bar[0] & 0xfffffffc
|
||||
dev_pf0_bar1 = dev.functions[0].bar[1] & 0xfffffffc
|
||||
|
||||
yield delay(100)
|
||||
|
||||
yield clk.posedge
|
||||
print("test 2: memory write to bar 1")
|
||||
current_test.next = 2
|
||||
|
||||
yield rc.mem_write(dev_pf0_bar1, b'\x11\x22\x33\x44')
|
||||
|
||||
yield delay(100)
|
||||
|
||||
yield clk.posedge
|
||||
print("test 3: memory read from bar 1")
|
||||
current_test.next = 3
|
||||
|
||||
val = yield from rc.mem_read(dev_pf0_bar1, 4, 1000)
|
||||
print(val)
|
||||
assert val == b'\x11\x22\x33\x44'
|
||||
|
||||
yield delay(100)
|
||||
|
||||
yield clk.posedge
|
||||
print("test 4: test DMA")
|
||||
current_test.next = 4
|
||||
|
||||
# write packet data
|
||||
mem_data[0:1024] = bytearray([x%256 for x in range(1024)])
|
||||
|
||||
# enable DMA
|
||||
yield rc.mem_write(dev_pf0_bar0+0x100000, struct.pack('<L', 1))
|
||||
|
||||
# write pcie read descriptor
|
||||
yield rc.mem_write(dev_pf0_bar0+0x100100, struct.pack('<L', (mem_base+0x0000) & 0xffffffff))
|
||||
yield rc.mem_write(dev_pf0_bar0+0x100104, struct.pack('<L', (mem_base+0x0000 >> 32) & 0xffffffff))
|
||||
yield rc.mem_write(dev_pf0_bar0+0x100108, struct.pack('<L', (0x100) & 0xffffffff))
|
||||
yield rc.mem_write(dev_pf0_bar0+0x10010C, struct.pack('<L', (0x100 >> 32) & 0xffffffff))
|
||||
yield rc.mem_write(dev_pf0_bar0+0x100110, struct.pack('<L', 0x400))
|
||||
yield rc.mem_write(dev_pf0_bar0+0x100114, struct.pack('<L', 0xAA))
|
||||
|
||||
yield delay(2000)
|
||||
|
||||
# read status
|
||||
val = yield from rc.mem_read(dev_pf0_bar0+0x100118, 4)
|
||||
print(val)
|
||||
|
||||
# write pcie write descriptor
|
||||
yield rc.mem_write(dev_pf0_bar0+0x100200, struct.pack('<L', (mem_base+0x1000) & 0xffffffff))
|
||||
yield rc.mem_write(dev_pf0_bar0+0x100204, struct.pack('<L', (mem_base+0x1000 >> 32) & 0xffffffff))
|
||||
yield rc.mem_write(dev_pf0_bar0+0x100208, struct.pack('<L', (0x100) & 0xffffffff))
|
||||
yield rc.mem_write(dev_pf0_bar0+0x10020C, struct.pack('<L', (0x100 >> 32) & 0xffffffff))
|
||||
yield rc.mem_write(dev_pf0_bar0+0x100210, struct.pack('<L', 0x400))
|
||||
yield rc.mem_write(dev_pf0_bar0+0x100214, struct.pack('<L', 0x55))
|
||||
|
||||
yield delay(2000)
|
||||
|
||||
# read status
|
||||
val = yield from rc.mem_read(dev_pf0_bar0+0x100218, 4)
|
||||
print(val)
|
||||
|
||||
data = mem_data[0x1000:(0x1000)+64]
|
||||
for i in range(0, len(data), 16):
|
||||
print(" ".join(("{:02x}".format(c) for c in bytearray(data[i:i+16]))))
|
||||
|
||||
assert mem_data[0:1024] == mem_data[0x1000:0x1000+1024]
|
||||
|
||||
yield delay(100)
|
||||
|
||||
raise StopSimulation
|
||||
|
||||
return instances()
|
||||
|
||||
def test_bench():
|
||||
sim = Simulation(bench())
|
||||
sim.run()
|
||||
|
||||
if __name__ == '__main__':
|
||||
print("Running test...")
|
||||
test_bench()
|
@ -1,243 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2018 Alex Forencich
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
// Language: Verilog 2001
|
||||
|
||||
`timescale 1ns / 1ps
|
||||
|
||||
/*
|
||||
* Testbench for fpga_core
|
||||
*/
|
||||
module test_fpga_core;
|
||||
|
||||
// Parameters
|
||||
parameter AXIS_PCIE_DATA_WIDTH = 512;
|
||||
parameter AXIS_PCIE_KEEP_WIDTH = (AXIS_PCIE_DATA_WIDTH/32);
|
||||
parameter AXIS_PCIE_RC_USER_WIDTH = 161;
|
||||
parameter AXIS_PCIE_RQ_USER_WIDTH = 137;
|
||||
parameter AXIS_PCIE_CQ_USER_WIDTH = 183;
|
||||
parameter AXIS_PCIE_CC_USER_WIDTH = 81;
|
||||
|
||||
// Inputs
|
||||
reg clk = 0;
|
||||
reg rst = 0;
|
||||
reg [7:0] current_test = 0;
|
||||
|
||||
reg [3:0] sw = 0;
|
||||
reg m_axis_rq_tready = 0;
|
||||
reg [AXIS_PCIE_DATA_WIDTH-1:0] s_axis_rc_tdata = 0;
|
||||
reg [AXIS_PCIE_KEEP_WIDTH-1:0] s_axis_rc_tkeep = 0;
|
||||
reg s_axis_rc_tlast = 0;
|
||||
reg [AXIS_PCIE_RC_USER_WIDTH-1:0] s_axis_rc_tuser = 0;
|
||||
reg s_axis_rc_tvalid = 0;
|
||||
reg [AXIS_PCIE_DATA_WIDTH-1:0] s_axis_cq_tdata = 0;
|
||||
reg [AXIS_PCIE_KEEP_WIDTH-1:0] s_axis_cq_tkeep = 0;
|
||||
reg s_axis_cq_tlast = 0;
|
||||
reg [AXIS_PCIE_CQ_USER_WIDTH-1:0] s_axis_cq_tuser = 0;
|
||||
reg s_axis_cq_tvalid = 0;
|
||||
reg m_axis_cc_tready = 0;
|
||||
reg [2:0] cfg_max_payload = 0;
|
||||
reg [2:0] cfg_max_read_req = 0;
|
||||
reg [31:0] cfg_mgmt_read_data = 0;
|
||||
reg cfg_mgmt_read_write_done = 0;
|
||||
reg [3:0] cfg_interrupt_msi_enable = 0;
|
||||
reg [11:0] cfg_interrupt_msi_mmenable = 0;
|
||||
reg cfg_interrupt_msi_mask_update = 0;
|
||||
reg [31:0] cfg_interrupt_msi_data = 0;
|
||||
reg cfg_interrupt_msi_sent = 0;
|
||||
reg cfg_interrupt_msi_fail = 0;
|
||||
|
||||
// Outputs
|
||||
wire [2:0] led;
|
||||
wire [1:0] user_led_g;
|
||||
wire user_led_r;
|
||||
wire [1:0] front_led;
|
||||
wire [AXIS_PCIE_DATA_WIDTH-1:0] m_axis_rq_tdata;
|
||||
wire [AXIS_PCIE_KEEP_WIDTH-1:0] m_axis_rq_tkeep;
|
||||
wire m_axis_rq_tlast;
|
||||
wire [AXIS_PCIE_RQ_USER_WIDTH-1:0] m_axis_rq_tuser;
|
||||
wire m_axis_rq_tvalid;
|
||||
wire s_axis_rc_tready;
|
||||
wire s_axis_cq_tready;
|
||||
wire [AXIS_PCIE_DATA_WIDTH-1:0] m_axis_cc_tdata;
|
||||
wire [AXIS_PCIE_KEEP_WIDTH-1:0] m_axis_cc_tkeep;
|
||||
wire m_axis_cc_tlast;
|
||||
wire [AXIS_PCIE_CC_USER_WIDTH-1:0] m_axis_cc_tuser;
|
||||
wire m_axis_cc_tvalid;
|
||||
wire [9:0] cfg_mgmt_addr;
|
||||
wire [7:0] cfg_mgmt_function_number;
|
||||
wire cfg_mgmt_write;
|
||||
wire [31:0] cfg_mgmt_write_data;
|
||||
wire [3:0] cfg_mgmt_byte_enable;
|
||||
wire cfg_mgmt_read;
|
||||
wire [3:0] cfg_interrupt_msi_select;
|
||||
wire [31:0] cfg_interrupt_msi_int;
|
||||
wire [31:0] cfg_interrupt_msi_pending_status;
|
||||
wire cfg_interrupt_msi_pending_status_data_enable;
|
||||
wire [3:0] cfg_interrupt_msi_pending_status_function_num;
|
||||
wire [2:0] cfg_interrupt_msi_attr;
|
||||
wire cfg_interrupt_msi_tph_present;
|
||||
wire [1:0] cfg_interrupt_msi_tph_type;
|
||||
wire [8:0] cfg_interrupt_msi_tph_st_tag;
|
||||
wire [3:0] cfg_interrupt_msi_function_number;
|
||||
wire status_error_cor;
|
||||
wire status_error_uncor;
|
||||
|
||||
initial begin
|
||||
// myhdl integration
|
||||
$from_myhdl(
|
||||
clk,
|
||||
rst,
|
||||
current_test,
|
||||
sw,
|
||||
m_axis_rq_tready,
|
||||
s_axis_rc_tdata,
|
||||
s_axis_rc_tkeep,
|
||||
s_axis_rc_tlast,
|
||||
s_axis_rc_tuser,
|
||||
s_axis_rc_tvalid,
|
||||
s_axis_cq_tdata,
|
||||
s_axis_cq_tkeep,
|
||||
s_axis_cq_tlast,
|
||||
s_axis_cq_tuser,
|
||||
s_axis_cq_tvalid,
|
||||
m_axis_cc_tready,
|
||||
cfg_max_payload,
|
||||
cfg_max_read_req,
|
||||
cfg_mgmt_read_data,
|
||||
cfg_mgmt_read_write_done,
|
||||
cfg_interrupt_msi_enable,
|
||||
cfg_interrupt_msi_mmenable,
|
||||
cfg_interrupt_msi_mask_update,
|
||||
cfg_interrupt_msi_data,
|
||||
cfg_interrupt_msi_sent,
|
||||
cfg_interrupt_msi_fail
|
||||
);
|
||||
$to_myhdl(
|
||||
led,
|
||||
m_axis_rq_tdata,
|
||||
m_axis_rq_tkeep,
|
||||
m_axis_rq_tlast,
|
||||
m_axis_rq_tuser,
|
||||
m_axis_rq_tvalid,
|
||||
s_axis_rc_tready,
|
||||
s_axis_cq_tready,
|
||||
m_axis_cc_tdata,
|
||||
m_axis_cc_tkeep,
|
||||
m_axis_cc_tlast,
|
||||
m_axis_cc_tuser,
|
||||
m_axis_cc_tvalid,
|
||||
cfg_mgmt_addr,
|
||||
cfg_mgmt_function_number,
|
||||
cfg_mgmt_write,
|
||||
cfg_mgmt_write_data,
|
||||
cfg_mgmt_byte_enable,
|
||||
cfg_mgmt_read,
|
||||
cfg_interrupt_msi_select,
|
||||
cfg_interrupt_msi_int,
|
||||
cfg_interrupt_msi_pending_status,
|
||||
cfg_interrupt_msi_pending_status_data_enable,
|
||||
cfg_interrupt_msi_pending_status_function_num,
|
||||
cfg_interrupt_msi_attr,
|
||||
cfg_interrupt_msi_tph_present,
|
||||
cfg_interrupt_msi_tph_type,
|
||||
cfg_interrupt_msi_tph_st_tag,
|
||||
cfg_interrupt_msi_function_number,
|
||||
status_error_cor,
|
||||
status_error_uncor
|
||||
);
|
||||
|
||||
// dump file
|
||||
$dumpfile("test_fpga_core.lxt");
|
||||
$dumpvars(0, test_fpga_core);
|
||||
end
|
||||
|
||||
fpga_core #(
|
||||
.AXIS_PCIE_DATA_WIDTH(AXIS_PCIE_DATA_WIDTH),
|
||||
.AXIS_PCIE_KEEP_WIDTH(AXIS_PCIE_KEEP_WIDTH),
|
||||
.AXIS_PCIE_RC_USER_WIDTH(AXIS_PCIE_RC_USER_WIDTH),
|
||||
.AXIS_PCIE_RQ_USER_WIDTH(AXIS_PCIE_RQ_USER_WIDTH),
|
||||
.AXIS_PCIE_CQ_USER_WIDTH(AXIS_PCIE_CQ_USER_WIDTH),
|
||||
.AXIS_PCIE_CC_USER_WIDTH(AXIS_PCIE_CC_USER_WIDTH)
|
||||
)
|
||||
UUT (
|
||||
.clk(clk),
|
||||
.rst(rst),
|
||||
.sw(sw),
|
||||
.led(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_function_number(cfg_mgmt_function_number),
|
||||
.cfg_mgmt_write(cfg_mgmt_write),
|
||||
.cfg_mgmt_write_data(cfg_mgmt_write_data),
|
||||
.cfg_mgmt_byte_enable(cfg_mgmt_byte_enable),
|
||||
.cfg_mgmt_read(cfg_mgmt_read),
|
||||
.cfg_mgmt_read_data(cfg_mgmt_read_data),
|
||||
.cfg_mgmt_read_write_done(cfg_mgmt_read_write_done),
|
||||
.cfg_interrupt_msi_enable(cfg_interrupt_msi_enable),
|
||||
.cfg_interrupt_msi_mmenable(cfg_interrupt_msi_mmenable),
|
||||
.cfg_interrupt_msi_mask_update(cfg_interrupt_msi_mask_update),
|
||||
.cfg_interrupt_msi_data(cfg_interrupt_msi_data),
|
||||
.cfg_interrupt_msi_select(cfg_interrupt_msi_select),
|
||||
.cfg_interrupt_msi_int(cfg_interrupt_msi_int),
|
||||
.cfg_interrupt_msi_pending_status(cfg_interrupt_msi_pending_status),
|
||||
.cfg_interrupt_msi_pending_status_data_enable(cfg_interrupt_msi_pending_status_data_enable),
|
||||
.cfg_interrupt_msi_pending_status_function_num(cfg_interrupt_msi_pending_status_function_num),
|
||||
.cfg_interrupt_msi_sent(cfg_interrupt_msi_sent),
|
||||
.cfg_interrupt_msi_fail(cfg_interrupt_msi_fail),
|
||||
.cfg_interrupt_msi_attr(cfg_interrupt_msi_attr),
|
||||
.cfg_interrupt_msi_tph_present(cfg_interrupt_msi_tph_present),
|
||||
.cfg_interrupt_msi_tph_type(cfg_interrupt_msi_tph_type),
|
||||
.cfg_interrupt_msi_tph_st_tag(cfg_interrupt_msi_tph_st_tag),
|
||||
.cfg_interrupt_msi_function_number(cfg_interrupt_msi_function_number),
|
||||
.status_error_cor(status_error_cor),
|
||||
.status_error_uncor(status_error_uncor)
|
||||
);
|
||||
|
||||
endmodule
|
@ -1 +0,0 @@
|
||||
../lib/pcie/tb/axis_ep.py
|
107
example/AU280/fpga_axi/tb/fpga_core/Makefile
Normal file
107
example/AU280/fpga_axi/tb/fpga_core/Makefile
Normal file
@ -0,0 +1,107 @@
|
||||
# Copyright (c) 2020 Alex Forencich
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in
|
||||
# all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
# THE SOFTWARE.
|
||||
|
||||
TOPLEVEL_LANG = verilog
|
||||
|
||||
SIM ?= icarus
|
||||
WAVES ?= 0
|
||||
|
||||
COCOTB_HDL_TIMEUNIT = 1ns
|
||||
COCOTB_HDL_TIMEPRECISION = 1ps
|
||||
|
||||
DUT = fpga_core
|
||||
TOPLEVEL = $(DUT)
|
||||
MODULE = test_$(DUT)
|
||||
VERILOG_SOURCES += ../../rtl/$(DUT).v
|
||||
VERILOG_SOURCES += ../../rtl/axi_ram.v
|
||||
VERILOG_SOURCES += ../../rtl/axis_register.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/axis_arb_mux.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_axil_master.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_axi_dma.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_axi_dma_rd.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_axi_dma_wr.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_tag_manager.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_axi_master.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_axi_master_rd.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_axi_master_wr.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_axis_cq_demux.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_cfg.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_msi.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/arbiter.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/priority_encoder.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pulse_merge.v
|
||||
|
||||
# module parameters
|
||||
export PARAM_AXIS_PCIE_DATA_WIDTH ?= 512
|
||||
export PARAM_AXIS_PCIE_KEEP_WIDTH ?= $(shell expr $(PARAM_AXIS_PCIE_DATA_WIDTH) / 32 )
|
||||
export PARAM_AXIS_PCIE_RQ_USER_WIDTH ?= $(if $(filter-out 512,$(PARAM_AXIS_PCIE_DATA_WIDTH)),62,137)
|
||||
export PARAM_AXIS_PCIE_RC_USER_WIDTH ?= $(if $(filter-out 512,$(PARAM_AXIS_PCIE_DATA_WIDTH)),75,161)
|
||||
export PARAM_AXIS_PCIE_CQ_USER_WIDTH ?= $(if $(filter-out 512,$(PARAM_AXIS_PCIE_DATA_WIDTH)),88,183)
|
||||
export PARAM_AXIS_PCIE_CC_USER_WIDTH ?= $(if $(filter-out 512,$(PARAM_AXIS_PCIE_DATA_WIDTH)),33,81)
|
||||
export PARAM_RQ_SEQ_NUM_WIDTH ?= 6
|
||||
|
||||
SIM_BUILD ?= sim_build_$(MODULE)
|
||||
|
||||
ifeq ($(SIM), icarus)
|
||||
PLUSARGS += -fst
|
||||
|
||||
COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_DATA_WIDTH=$(PARAM_AXIS_PCIE_DATA_WIDTH)
|
||||
COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_KEEP_WIDTH=$(PARAM_AXIS_PCIE_KEEP_WIDTH)
|
||||
COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_RQ_USER_WIDTH=$(PARAM_AXIS_PCIE_RQ_USER_WIDTH)
|
||||
COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_RC_USER_WIDTH=$(PARAM_AXIS_PCIE_RC_USER_WIDTH)
|
||||
COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_CQ_USER_WIDTH=$(PARAM_AXIS_PCIE_CQ_USER_WIDTH)
|
||||
COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_CC_USER_WIDTH=$(PARAM_AXIS_PCIE_CC_USER_WIDTH)
|
||||
COMPILE_ARGS += -P $(TOPLEVEL).RQ_SEQ_NUM_WIDTH=$(PARAM_RQ_SEQ_NUM_WIDTH)
|
||||
|
||||
ifeq ($(WAVES), 1)
|
||||
VERILOG_SOURCES += iverilog_dump.v
|
||||
COMPILE_ARGS += -s iverilog_dump
|
||||
endif
|
||||
else ifeq ($(SIM), verilator)
|
||||
COMPILE_ARGS += -Wno-SELRANGE -Wno-WIDTH
|
||||
|
||||
COMPILE_ARGS += -GAXIS_PCIE_DATA_WIDTH=$(PARAM_AXIS_PCIE_DATA_WIDTH)
|
||||
COMPILE_ARGS += -GAXIS_PCIE_KEEP_WIDTH=$(PARAM_AXIS_PCIE_KEEP_WIDTH)
|
||||
COMPILE_ARGS += -GAXIS_PCIE_RQ_USER_WIDTH=$(PARAM_AXIS_PCIE_RQ_USER_WIDTH)
|
||||
COMPILE_ARGS += -GAXIS_PCIE_RC_USER_WIDTH=$(PARAM_AXIS_PCIE_RC_USER_WIDTH)
|
||||
COMPILE_ARGS += -GAXIS_PCIE_CQ_USER_WIDTH=$(PARAM_AXIS_PCIE_CQ_USER_WIDTH)
|
||||
COMPILE_ARGS += -GAXIS_PCIE_CC_USER_WIDTH=$(PARAM_AXIS_PCIE_CC_USER_WIDTH)
|
||||
COMPILE_ARGS += -GRQ_SEQ_NUM_WIDTH=$(PARAM_RQ_SEQ_NUM_WIDTH)
|
||||
|
||||
ifeq ($(WAVES), 1)
|
||||
COMPILE_ARGS += --trace-fst
|
||||
endif
|
||||
endif
|
||||
|
||||
iverilog_dump.v:
|
||||
echo 'module iverilog_dump();' > $@
|
||||
echo 'initial begin' >> $@
|
||||
echo ' $$dumpfile("$(TOPLEVEL).fst");' >> $@
|
||||
echo ' $$dumpvars(0, $(TOPLEVEL));' >> $@
|
||||
echo 'end' >> $@
|
||||
echo 'endmodule' >> $@
|
||||
|
||||
clean::
|
||||
@rm -rf sim_build_*
|
||||
@rm -rf iverilog_dump.v
|
||||
@rm -rf dump.fst $(TOPLEVEL).fst
|
||||
|
||||
include $(shell cocotb-config --makefiles)/Makefile.sim
|
||||
|
378
example/AU280/fpga_axi/tb/fpga_core/test_fpga_core.py
Normal file
378
example/AU280/fpga_axi/tb/fpga_core/test_fpga_core.py
Normal file
@ -0,0 +1,378 @@
|
||||
"""
|
||||
|
||||
Copyright (c) 2020 Alex Forencich
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
"""
|
||||
|
||||
import logging
|
||||
import os
|
||||
|
||||
import cocotb_test.simulator
|
||||
|
||||
import cocotb
|
||||
from cocotb.log import SimLog
|
||||
from cocotb.triggers import RisingEdge, FallingEdge, Timer
|
||||
|
||||
from cocotbext.pcie.core import RootComplex
|
||||
from cocotbext.pcie.xilinx.us import UltraScalePlusPcieDevice
|
||||
from cocotbext.axi.utils import hexdump_str
|
||||
|
||||
|
||||
class TB(object):
|
||||
def __init__(self, dut):
|
||||
self.dut = dut
|
||||
|
||||
self.log = SimLog("cocotb.tb")
|
||||
self.log.setLevel(logging.DEBUG)
|
||||
|
||||
# PCIe
|
||||
self.rc = RootComplex()
|
||||
|
||||
self.dev = UltraScalePlusPcieDevice(
|
||||
# configuration options
|
||||
pcie_generation=3,
|
||||
pcie_link_width=16,
|
||||
user_clk_frequency=250e6,
|
||||
alignment="dword",
|
||||
cq_cc_straddle=False,
|
||||
rq_rc_straddle=False,
|
||||
rc_4tlp_straddle=False,
|
||||
enable_pf1=False,
|
||||
enable_client_tag=True,
|
||||
enable_extended_tag=True,
|
||||
enable_parity=False,
|
||||
enable_rx_msg_interface=False,
|
||||
enable_sriov=False,
|
||||
enable_extended_configuration=False,
|
||||
|
||||
enable_pf0_msi=True,
|
||||
enable_pf1_msi=False,
|
||||
|
||||
# signals
|
||||
# Clock and Reset Interface
|
||||
user_clk=dut.clk,
|
||||
user_reset=dut.rst,
|
||||
# user_lnk_up
|
||||
# sys_clk
|
||||
# sys_clk_gt
|
||||
# sys_reset
|
||||
# phy_rdy_out
|
||||
|
||||
# Requester reQuest Interface
|
||||
rq_entity=dut,
|
||||
rq_name="m_axis_rq",
|
||||
# pcie_rq_seq_num0=dut.s_axis_rq_seq_num_0,
|
||||
# pcie_rq_seq_num_vld0=dut.s_axis_rq_seq_num_valid_0,
|
||||
# pcie_rq_seq_num1=dut.s_axis_rq_seq_num_1,
|
||||
# pcie_rq_seq_num_vld1=dut.s_axis_rq_seq_num_valid_1,
|
||||
# pcie_rq_tag0
|
||||
# pcie_rq_tag1
|
||||
# pcie_rq_tag_av
|
||||
# pcie_rq_tag_vld0
|
||||
# pcie_rq_tag_vld1
|
||||
|
||||
# Requester Completion Interface
|
||||
rc_entity=dut,
|
||||
rc_name="s_axis_rc",
|
||||
|
||||
# Completer reQuest Interface
|
||||
cq_entity=dut,
|
||||
cq_name="s_axis_cq",
|
||||
# pcie_cq_np_req
|
||||
# pcie_cq_np_req_count
|
||||
|
||||
# Completer Completion Interface
|
||||
cc_entity=dut,
|
||||
cc_name="m_axis_cc",
|
||||
|
||||
# Transmit Flow Control Interface
|
||||
# pcie_tfc_nph_av=dut.pcie_tfc_nph_av,
|
||||
# pcie_tfc_npd_av=dut.pcie_tfc_npd_av,
|
||||
|
||||
# Configuration Management Interface
|
||||
cfg_mgmt_addr=dut.cfg_mgmt_addr,
|
||||
cfg_mgmt_function_number=dut.cfg_mgmt_function_number,
|
||||
cfg_mgmt_write=dut.cfg_mgmt_write,
|
||||
cfg_mgmt_write_data=dut.cfg_mgmt_write_data,
|
||||
cfg_mgmt_byte_enable=dut.cfg_mgmt_byte_enable,
|
||||
cfg_mgmt_read=dut.cfg_mgmt_read,
|
||||
cfg_mgmt_read_data=dut.cfg_mgmt_read_data,
|
||||
cfg_mgmt_read_write_done=dut.cfg_mgmt_read_write_done,
|
||||
# cfg_mgmt_debug_access
|
||||
|
||||
# Configuration Status Interface
|
||||
# cfg_phy_link_down
|
||||
# cfg_phy_link_status
|
||||
# cfg_negotiated_width
|
||||
# cfg_current_speed
|
||||
cfg_max_payload=dut.cfg_max_payload,
|
||||
cfg_max_read_req=dut.cfg_max_read_req,
|
||||
# cfg_function_status
|
||||
# cfg_vf_status
|
||||
# cfg_function_power_state
|
||||
# cfg_vf_power_state
|
||||
# cfg_link_power_state
|
||||
# cfg_err_cor_out
|
||||
# cfg_err_nonfatal_out
|
||||
# cfg_err_fatal_out
|
||||
# cfg_local_error_out
|
||||
# cfg_local_error_valid
|
||||
# cfg_rx_pm_state
|
||||
# cfg_tx_pm_state
|
||||
# cfg_ltssm_state
|
||||
# cfg_rcb_status
|
||||
# cfg_obff_enable
|
||||
# cfg_pl_status_change
|
||||
# cfg_tph_requester_enable
|
||||
# cfg_tph_st_mode
|
||||
# cfg_vf_tph_requester_enable
|
||||
# cfg_vf_tph_st_mode
|
||||
|
||||
# Configuration Received Message Interface
|
||||
# cfg_msg_received
|
||||
# cfg_msg_received_data
|
||||
# cfg_msg_received_type
|
||||
|
||||
# Configuration Transmit Message Interface
|
||||
# cfg_msg_transmit
|
||||
# cfg_msg_transmit_type
|
||||
# cfg_msg_transmit_data
|
||||
# cfg_msg_transmit_done
|
||||
|
||||
# Configuration Flow Control Interface
|
||||
# cfg_fc_ph=dut.cfg_fc_ph,
|
||||
# cfg_fc_pd=dut.cfg_fc_pd,
|
||||
# cfg_fc_nph=dut.cfg_fc_nph,
|
||||
# cfg_fc_npd=dut.cfg_fc_npd,
|
||||
# cfg_fc_cplh=dut.cfg_fc_cplh,
|
||||
# cfg_fc_cpld=dut.cfg_fc_cpld,
|
||||
# cfg_fc_sel=dut.cfg_fc_sel,
|
||||
|
||||
# Configuration Control Interface
|
||||
# cfg_hot_reset_in
|
||||
# cfg_hot_reset_out
|
||||
# cfg_config_space_enable
|
||||
# cfg_dsn
|
||||
# cfg_bus_number
|
||||
# cfg_ds_port_number
|
||||
# cfg_ds_bus_number
|
||||
# cfg_ds_device_number
|
||||
# cfg_ds_function_number
|
||||
# cfg_power_state_change_ack
|
||||
# cfg_power_state_change_interrupt
|
||||
cfg_err_cor_in=dut.status_error_cor,
|
||||
cfg_err_uncor_in=dut.status_error_uncor,
|
||||
# cfg_flr_in_process
|
||||
# cfg_flr_done
|
||||
# cfg_vf_flr_in_process
|
||||
# cfg_vf_flr_func_num
|
||||
# cfg_vf_flr_done
|
||||
# cfg_pm_aspm_l1_entry_reject
|
||||
# cfg_pm_aspm_tx_l0s_entry_disable
|
||||
# cfg_req_pm_transition_l23_ready
|
||||
# cfg_link_training_enable
|
||||
|
||||
# Configuration Interrupt Controller Interface
|
||||
# cfg_interrupt_int
|
||||
# cfg_interrupt_sent
|
||||
# cfg_interrupt_pending
|
||||
cfg_interrupt_msi_enable=dut.cfg_interrupt_msi_enable,
|
||||
cfg_interrupt_msi_mmenable=dut.cfg_interrupt_msi_mmenable,
|
||||
cfg_interrupt_msi_mask_update=dut.cfg_interrupt_msi_mask_update,
|
||||
cfg_interrupt_msi_data=dut.cfg_interrupt_msi_data,
|
||||
# cfg_interrupt_msi_select=dut.cfg_interrupt_msi_select,
|
||||
cfg_interrupt_msi_int=dut.cfg_interrupt_msi_int,
|
||||
cfg_interrupt_msi_pending_status=dut.cfg_interrupt_msi_pending_status,
|
||||
cfg_interrupt_msi_pending_status_data_enable=dut.cfg_interrupt_msi_pending_status_data_enable,
|
||||
# cfg_interrupt_msi_pending_status_function_num=dut.cfg_interrupt_msi_pending_status_function_num,
|
||||
cfg_interrupt_msi_sent=dut.cfg_interrupt_msi_sent,
|
||||
cfg_interrupt_msi_fail=dut.cfg_interrupt_msi_fail,
|
||||
# cfg_interrupt_msix_enable
|
||||
# cfg_interrupt_msix_mask
|
||||
# cfg_interrupt_msix_vf_enable
|
||||
# cfg_interrupt_msix_vf_mask
|
||||
# cfg_interrupt_msix_address
|
||||
# cfg_interrupt_msix_data
|
||||
# cfg_interrupt_msix_int
|
||||
# cfg_interrupt_msix_vec_pending
|
||||
# cfg_interrupt_msix_vec_pending_status
|
||||
cfg_interrupt_msi_attr=dut.cfg_interrupt_msi_attr,
|
||||
cfg_interrupt_msi_tph_present=dut.cfg_interrupt_msi_tph_present,
|
||||
cfg_interrupt_msi_tph_type=dut.cfg_interrupt_msi_tph_type,
|
||||
# cfg_interrupt_msi_tph_st_tag=dut.cfg_interrupt_msi_tph_st_tag,
|
||||
# cfg_interrupt_msi_function_number=dut.cfg_interrupt_msi_function_number,
|
||||
|
||||
# Configuration Extend Interface
|
||||
# cfg_ext_read_received
|
||||
# cfg_ext_write_received
|
||||
# cfg_ext_register_number
|
||||
# cfg_ext_function_number
|
||||
# cfg_ext_write_data
|
||||
# cfg_ext_write_byte_enable
|
||||
# cfg_ext_read_data
|
||||
# cfg_ext_read_data_valid
|
||||
)
|
||||
|
||||
# self.dev.log.setLevel(logging.DEBUG)
|
||||
|
||||
self.rc.make_port().connect(self.dev)
|
||||
|
||||
self.dev.functions[0].msi_multiple_message_capable = 5
|
||||
|
||||
self.dev.functions[0].configure_bar(0, 2**22)
|
||||
self.dev.functions[0].configure_bar(1, 2**22)
|
||||
|
||||
async def init(self):
|
||||
|
||||
await FallingEdge(self.dut.rst)
|
||||
await Timer(100, 'ns')
|
||||
|
||||
await self.rc.enumerate(enable_bus_mastering=True, configure_msi=True)
|
||||
|
||||
|
||||
@cocotb.test()
|
||||
async def run_test(dut):
|
||||
|
||||
tb = TB(dut)
|
||||
|
||||
await tb.init()
|
||||
|
||||
mem_base, mem_data = tb.rc.alloc_region(16*1024*1024)
|
||||
|
||||
dev_pf0_bar0 = tb.rc.tree[0][0].bar_addr[0]
|
||||
dev_pf0_bar1 = tb.rc.tree[0][0].bar_addr[1]
|
||||
|
||||
tb.log.info("Test memory write to BAR 1")
|
||||
|
||||
await tb.rc.mem_write(dev_pf0_bar1, b'\x11\x22\x33\x44')
|
||||
|
||||
await Timer(100, 'ns')
|
||||
|
||||
tb.log.info("Test memory read from BAR 1")
|
||||
|
||||
val = await tb.rc.mem_read(dev_pf0_bar1, 4, 1000)
|
||||
tb.log.info("Read data: %s", val)
|
||||
assert val == b'\x11\x22\x33\x44'
|
||||
|
||||
tb.log.info("Test DMA")
|
||||
|
||||
# write packet data
|
||||
mem_data[0:1024] = bytearray([x % 256 for x in range(1024)])
|
||||
|
||||
# enable DMA
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100000, 1)
|
||||
|
||||
# write pcie read descriptor
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100100, (mem_base+0x0000) & 0xffffffff)
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100104, (mem_base+0x0000 >> 32) & 0xffffffff)
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100108, (0x100) & 0xffffffff)
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x10010C, (0x100 >> 32) & 0xffffffff)
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100110, 0x400)
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100114, 0xAA)
|
||||
|
||||
await Timer(2000, 'ns')
|
||||
|
||||
# read status
|
||||
val = await tb.rc.mem_read_dword(dev_pf0_bar0+0x100118)
|
||||
tb.log.info("Status: 0x%x", val)
|
||||
assert val == 0xAA
|
||||
|
||||
# write pcie write descriptor
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100200, (mem_base+0x1000) & 0xffffffff)
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100204, (mem_base+0x1000 >> 32) & 0xffffffff)
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100208, (0x100) & 0xffffffff)
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x10020C, (0x100 >> 32) & 0xffffffff)
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100210, 0x400)
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100214, 0x55)
|
||||
|
||||
await Timer(2000, 'ns')
|
||||
|
||||
# read status
|
||||
val = await tb.rc.mem_read_dword(dev_pf0_bar0+0x100218)
|
||||
tb.log.info("Status: 0x%x", val)
|
||||
assert val == 0x55
|
||||
|
||||
tb.log.info("%s", hexdump_str(mem_data, 0x1000, 64))
|
||||
|
||||
assert mem_data[0:1024] == mem_data[0x1000:0x1000+1024]
|
||||
|
||||
await RisingEdge(dut.clk)
|
||||
await RisingEdge(dut.clk)
|
||||
|
||||
|
||||
# cocotb-test
|
||||
|
||||
tests_dir = os.path.dirname(__file__)
|
||||
rtl_dir = os.path.abspath(os.path.join(tests_dir, '..', '..', 'rtl'))
|
||||
lib_dir = os.path.abspath(os.path.join(rtl_dir, '..', 'lib'))
|
||||
pcie_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'pcie', 'rtl'))
|
||||
|
||||
|
||||
def test_fpga_core(request):
|
||||
dut = "fpga_core"
|
||||
module = os.path.splitext(os.path.basename(__file__))[0]
|
||||
toplevel = dut
|
||||
|
||||
verilog_sources = [
|
||||
os.path.join(rtl_dir, f"{dut}.v"),
|
||||
os.path.join(rtl_dir, "axi_ram.v"),
|
||||
os.path.join(rtl_dir, "axis_register.v"),
|
||||
os.path.join(pcie_rtl_dir, "axis_arb_mux.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_us_axil_master.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_us_axi_dma.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_us_axi_dma_rd.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_us_axi_dma_wr.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_tag_manager.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_us_axi_master.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_us_axi_master_rd.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_us_axi_master_wr.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_us_axis_cq_demux.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_us_cfg.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_us_msi.v"),
|
||||
os.path.join(pcie_rtl_dir, "arbiter.v"),
|
||||
os.path.join(pcie_rtl_dir, "priority_encoder.v"),
|
||||
os.path.join(pcie_rtl_dir, "pulse_merge.v"),
|
||||
]
|
||||
|
||||
parameters = {}
|
||||
|
||||
parameters['AXIS_PCIE_DATA_WIDTH'] = 512
|
||||
parameters['AXIS_PCIE_KEEP_WIDTH'] = parameters['AXIS_PCIE_DATA_WIDTH'] // 32
|
||||
parameters['AXIS_PCIE_RQ_USER_WIDTH'] = 62 if parameters['AXIS_PCIE_DATA_WIDTH'] < 512 else 137
|
||||
parameters['AXIS_PCIE_RC_USER_WIDTH'] = 75 if parameters['AXIS_PCIE_DATA_WIDTH'] < 512 else 161
|
||||
parameters['AXIS_PCIE_CQ_USER_WIDTH'] = 88 if parameters['AXIS_PCIE_DATA_WIDTH'] < 512 else 183
|
||||
parameters['AXIS_PCIE_CC_USER_WIDTH'] = 33 if parameters['AXIS_PCIE_DATA_WIDTH'] < 512 else 81
|
||||
parameters['RQ_SEQ_NUM_WIDTH'] = 6
|
||||
|
||||
extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()}
|
||||
|
||||
sim_build = os.path.join(tests_dir,
|
||||
"sim_build_"+request.node.name.replace('[', '-').replace(']', ''))
|
||||
|
||||
cocotb_test.simulator.run(
|
||||
python_search=[tests_dir],
|
||||
verilog_sources=verilog_sources,
|
||||
toplevel=toplevel,
|
||||
module=module,
|
||||
parameters=parameters,
|
||||
sim_build=sim_build,
|
||||
extra_env=extra_env,
|
||||
)
|
@ -1 +0,0 @@
|
||||
../lib/pcie/tb/pcie.py
|
@ -1 +0,0 @@
|
||||
../lib/pcie/tb/pcie_us.py
|
@ -1 +0,0 @@
|
||||
../lib/pcie/tb/pcie_usp.py
|
@ -1,506 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
"""
|
||||
|
||||
Copyright (c) 2018 Alex Forencich
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
"""
|
||||
|
||||
from myhdl import *
|
||||
import os
|
||||
import struct
|
||||
|
||||
import pcie
|
||||
import pcie_usp
|
||||
|
||||
module = 'fpga_core'
|
||||
testbench = 'test_%s' % module
|
||||
|
||||
srcs = []
|
||||
|
||||
srcs.append("../rtl/%s.v" % module)
|
||||
srcs.append("../rtl/axi_ram.v")
|
||||
srcs.append("../rtl/axis_register.v")
|
||||
srcs.append("../lib/pcie/rtl/axis_arb_mux.v")
|
||||
srcs.append("../lib/pcie/rtl/pcie_us_axil_master.v")
|
||||
srcs.append("../lib/pcie/rtl/pcie_us_axi_dma.v")
|
||||
srcs.append("../lib/pcie/rtl/pcie_us_axi_dma_rd.v")
|
||||
srcs.append("../lib/pcie/rtl/pcie_us_axi_dma_wr.v")
|
||||
srcs.append("../lib/pcie/rtl/pcie_tag_manager.v")
|
||||
srcs.append("../lib/pcie/rtl/pcie_us_axi_master.v")
|
||||
srcs.append("../lib/pcie/rtl/pcie_us_axi_master_rd.v")
|
||||
srcs.append("../lib/pcie/rtl/pcie_us_axi_master_wr.v")
|
||||
srcs.append("../lib/pcie/rtl/pcie_us_axis_cq_demux.v")
|
||||
srcs.append("../lib/pcie/rtl/pcie_us_cfg.v")
|
||||
srcs.append("../lib/pcie/rtl/pcie_us_msi.v")
|
||||
srcs.append("../lib/pcie/rtl/arbiter.v")
|
||||
srcs.append("../lib/pcie/rtl/priority_encoder.v")
|
||||
srcs.append("../lib/pcie/rtl/pulse_merge.v")
|
||||
srcs.append("%s.v" % testbench)
|
||||
|
||||
src = ' '.join(srcs)
|
||||
|
||||
build_cmd = "iverilog -o %s.vvp %s" % (testbench, src)
|
||||
|
||||
def bench():
|
||||
|
||||
# Parameters
|
||||
AXIS_PCIE_DATA_WIDTH = 512
|
||||
AXIS_PCIE_KEEP_WIDTH = (AXIS_PCIE_DATA_WIDTH/32)
|
||||
AXIS_PCIE_RC_USER_WIDTH = 161
|
||||
AXIS_PCIE_RQ_USER_WIDTH = 137
|
||||
AXIS_PCIE_CQ_USER_WIDTH = 183
|
||||
AXIS_PCIE_CC_USER_WIDTH = 81
|
||||
|
||||
# Inputs
|
||||
clk = Signal(bool(0))
|
||||
rst = Signal(bool(0))
|
||||
current_test = Signal(intbv(0)[8:])
|
||||
|
||||
m_axis_rq_tready = Signal(bool(0))
|
||||
s_axis_rc_tdata = Signal(intbv(0)[AXIS_PCIE_DATA_WIDTH:])
|
||||
s_axis_rc_tkeep = Signal(intbv(0)[AXIS_PCIE_KEEP_WIDTH:])
|
||||
s_axis_rc_tlast = Signal(bool(0))
|
||||
s_axis_rc_tuser = Signal(intbv(0)[AXIS_PCIE_RC_USER_WIDTH:])
|
||||
s_axis_rc_tvalid = Signal(bool(0))
|
||||
s_axis_cq_tdata = Signal(intbv(0)[AXIS_PCIE_DATA_WIDTH:])
|
||||
s_axis_cq_tkeep = Signal(intbv(0)[AXIS_PCIE_KEEP_WIDTH:])
|
||||
s_axis_cq_tlast = Signal(bool(0))
|
||||
s_axis_cq_tuser = Signal(intbv(0)[AXIS_PCIE_CQ_USER_WIDTH:])
|
||||
s_axis_cq_tvalid = Signal(bool(0))
|
||||
m_axis_cc_tready = Signal(bool(0))
|
||||
cfg_max_payload = Signal(intbv(0)[2:])
|
||||
cfg_max_read_req = Signal(intbv(0)[3:])
|
||||
cfg_mgmt_read_data = Signal(intbv(0)[32:])
|
||||
cfg_mgmt_read_write_done = Signal(bool(0))
|
||||
cfg_interrupt_msi_enable = Signal(intbv(0)[4:])
|
||||
cfg_interrupt_msi_mmenable = Signal(intbv(0)[12:])
|
||||
cfg_interrupt_msi_mask_update = Signal(bool(0))
|
||||
cfg_interrupt_msi_data = Signal(intbv(0)[32:])
|
||||
cfg_interrupt_msi_sent = Signal(bool(0))
|
||||
cfg_interrupt_msi_fail = Signal(bool(0))
|
||||
|
||||
# Outputs
|
||||
m_axis_rq_tdata = Signal(intbv(0)[AXIS_PCIE_DATA_WIDTH:])
|
||||
m_axis_rq_tkeep = Signal(intbv(0)[AXIS_PCIE_KEEP_WIDTH:])
|
||||
m_axis_rq_tlast = Signal(bool(0))
|
||||
m_axis_rq_tuser = Signal(intbv(0)[AXIS_PCIE_RQ_USER_WIDTH:])
|
||||
m_axis_rq_tvalid = Signal(bool(0))
|
||||
s_axis_rc_tready = Signal(bool(0))
|
||||
s_axis_cq_tready = Signal(bool(0))
|
||||
m_axis_cc_tdata = Signal(intbv(0)[AXIS_PCIE_DATA_WIDTH:])
|
||||
m_axis_cc_tkeep = Signal(intbv(0)[AXIS_PCIE_KEEP_WIDTH:])
|
||||
m_axis_cc_tlast = Signal(bool(0))
|
||||
m_axis_cc_tuser = Signal(intbv(0)[AXIS_PCIE_CC_USER_WIDTH:])
|
||||
m_axis_cc_tvalid = Signal(bool(0))
|
||||
status_error_cor = Signal(bool(0))
|
||||
status_error_uncor = Signal(bool(0))
|
||||
cfg_mgmt_addr = Signal(intbv(0)[10:])
|
||||
cfg_mgmt_function_number = Signal(intbv(0)[8:])
|
||||
cfg_mgmt_write = Signal(bool(0))
|
||||
cfg_mgmt_write_data = Signal(intbv(0)[32:])
|
||||
cfg_mgmt_byte_enable = Signal(intbv(0)[4:])
|
||||
cfg_mgmt_read = Signal(bool(0))
|
||||
cfg_interrupt_msi_int = Signal(intbv(0)[32:])
|
||||
cfg_interrupt_msi_pending_status = Signal(intbv(0)[32:])
|
||||
cfg_interrupt_msi_select = Signal(intbv(0)[2:])
|
||||
cfg_interrupt_msi_pending_status_function_num = Signal(intbv(0)[2:])
|
||||
cfg_interrupt_msi_pending_status_data_enable = Signal(bool(0))
|
||||
cfg_interrupt_msi_attr = Signal(intbv(0)[3:])
|
||||
cfg_interrupt_msi_tph_present = Signal(bool(0))
|
||||
cfg_interrupt_msi_tph_type = Signal(intbv(0)[2:])
|
||||
cfg_interrupt_msi_tph_st_tag = Signal(intbv(0)[8:])
|
||||
cfg_interrupt_msi_function_number = Signal(intbv(0)[8:])
|
||||
|
||||
# Clock and Reset Interface
|
||||
user_clk=Signal(bool(0))
|
||||
user_reset=Signal(bool(0))
|
||||
sys_clk=Signal(bool(0))
|
||||
sys_reset=Signal(bool(0))
|
||||
|
||||
# PCIe devices
|
||||
rc = pcie.RootComplex()
|
||||
|
||||
mem_base, mem_data = rc.alloc_region(16*1024*1024)
|
||||
|
||||
dev = pcie_usp.UltrascalePlusPCIe()
|
||||
|
||||
dev.pcie_generation = 3
|
||||
dev.pcie_link_width = 16
|
||||
dev.user_clk_frequency = 250e6
|
||||
|
||||
dev.functions[0].msi_multiple_message_capable = 5
|
||||
|
||||
dev.functions[0].configure_bar(0, 4*1024*1024)
|
||||
dev.functions[0].configure_bar(1, 4*1024*1024)
|
||||
|
||||
rc.make_port().connect(dev)
|
||||
|
||||
pcie_logic = dev.create_logic(
|
||||
# Completer reQuest Interface
|
||||
m_axis_cq_tdata=s_axis_cq_tdata,
|
||||
m_axis_cq_tuser=s_axis_cq_tuser,
|
||||
m_axis_cq_tlast=s_axis_cq_tlast,
|
||||
m_axis_cq_tkeep=s_axis_cq_tkeep,
|
||||
m_axis_cq_tvalid=s_axis_cq_tvalid,
|
||||
m_axis_cq_tready=s_axis_cq_tready,
|
||||
#pcie_cq_np_req=pcie_cq_np_req,
|
||||
pcie_cq_np_req=Signal(intbv(1)[2:]),
|
||||
#pcie_cq_np_req_count=pcie_cq_np_req_count,
|
||||
|
||||
# Completer Completion Interface
|
||||
s_axis_cc_tdata=m_axis_cc_tdata,
|
||||
s_axis_cc_tuser=m_axis_cc_tuser,
|
||||
s_axis_cc_tlast=m_axis_cc_tlast,
|
||||
s_axis_cc_tkeep=m_axis_cc_tkeep,
|
||||
s_axis_cc_tvalid=m_axis_cc_tvalid,
|
||||
s_axis_cc_tready=m_axis_cc_tready,
|
||||
|
||||
# Requester reQuest Interface
|
||||
s_axis_rq_tdata=m_axis_rq_tdata,
|
||||
s_axis_rq_tuser=m_axis_rq_tuser,
|
||||
s_axis_rq_tlast=m_axis_rq_tlast,
|
||||
s_axis_rq_tkeep=m_axis_rq_tkeep,
|
||||
s_axis_rq_tvalid=m_axis_rq_tvalid,
|
||||
s_axis_rq_tready=m_axis_rq_tready,
|
||||
#pcie_rq_seq_num0=pcie_rq_seq_num0,
|
||||
#pcie_rq_seq_num_vld0=pcie_rq_seq_num_vld0,
|
||||
#pcie_rq_seq_num1=pcie_rq_seq_num1,
|
||||
#pcie_rq_seq_num_vld1=pcie_rq_seq_num_vld1,
|
||||
#pcie_rq_tag0=pcie_rq_tag0,
|
||||
#pcie_rq_tag1=pcie_rq_tag1,
|
||||
#pcie_rq_tag_av=pcie_rq_tag_av,
|
||||
#pcie_rq_tag_vld0=pcie_rq_tag_vld0,
|
||||
#pcie_rq_tag_vld1=pcie_rq_tag_vld1,
|
||||
|
||||
# Requester Completion Interface
|
||||
m_axis_rc_tdata=s_axis_rc_tdata,
|
||||
m_axis_rc_tuser=s_axis_rc_tuser,
|
||||
m_axis_rc_tlast=s_axis_rc_tlast,
|
||||
m_axis_rc_tkeep=s_axis_rc_tkeep,
|
||||
m_axis_rc_tvalid=s_axis_rc_tvalid,
|
||||
m_axis_rc_tready=s_axis_rc_tready,
|
||||
|
||||
# Transmit Flow Control Interface
|
||||
#pcie_tfc_nph_av=pcie_tfc_nph_av,
|
||||
#pcie_tfc_npd_av=pcie_tfc_npd_av,
|
||||
|
||||
# Configuration Management Interface
|
||||
cfg_mgmt_addr=cfg_mgmt_addr,
|
||||
cfg_mgmt_function_number=cfg_mgmt_function_number,
|
||||
cfg_mgmt_write=cfg_mgmt_write,
|
||||
cfg_mgmt_write_data=cfg_mgmt_write_data,
|
||||
cfg_mgmt_byte_enable=cfg_mgmt_byte_enable,
|
||||
cfg_mgmt_read=cfg_mgmt_read,
|
||||
cfg_mgmt_read_data=cfg_mgmt_read_data,
|
||||
cfg_mgmt_read_write_done=cfg_mgmt_read_write_done,
|
||||
#cfg_mgmt_debug_access=cfg_mgmt_debug_access,
|
||||
|
||||
# Configuration Status Interface
|
||||
#cfg_phy_link_down=cfg_phy_link_down,
|
||||
#cfg_phy_link_status=cfg_phy_link_status,
|
||||
#cfg_negotiated_width=cfg_negotiated_width,
|
||||
#cfg_current_speed=cfg_current_speed,
|
||||
cfg_max_payload=cfg_max_payload,
|
||||
cfg_max_read_req=cfg_max_read_req,
|
||||
#cfg_function_status=cfg_function_status,
|
||||
#cfg_vf_status=cfg_vf_status,
|
||||
#cfg_function_power_state=cfg_function_power_state,
|
||||
#cfg_vf_power_state=cfg_vf_power_state,
|
||||
#cfg_link_power_state=cfg_link_power_state,
|
||||
#cfg_err_cor_out=cfg_err_cor_out,
|
||||
#cfg_err_nonfatal_out=cfg_err_nonfatal_out,
|
||||
#cfg_err_fatal_out=cfg_err_fatal_out,
|
||||
#cfg_local_err_out=cfg_local_err_out,
|
||||
#cfg_local_err_valid=cfg_local_err_valid,
|
||||
#cfg_rx_pm_state=cfg_rx_pm_state,
|
||||
#cfg_tx_pm_state=cfg_tx_pm_state,
|
||||
#cfg_ltssm_state=cfg_ltssm_state,
|
||||
#cfg_rcb_status=cfg_rcb_status,
|
||||
#cfg_obff_enable=cfg_obff_enable,
|
||||
#cfg_pl_status_change=cfg_pl_status_change,
|
||||
#cfg_tph_requester_enable=cfg_tph_requester_enable,
|
||||
#cfg_tph_st_mode=cfg_tph_st_mode,
|
||||
#cfg_vf_tph_requester_enable=cfg_vf_tph_requester_enable,
|
||||
#cfg_vf_tph_st_mode=cfg_vf_tph_st_mode,
|
||||
|
||||
# Configuration Received Message Interface
|
||||
#cfg_msg_received=cfg_msg_received,
|
||||
#cfg_msg_received_data=cfg_msg_received_data,
|
||||
#cfg_msg_received_type=cfg_msg_received_type,
|
||||
|
||||
# Configuration Transmit Message Interface
|
||||
#cfg_msg_transmit=cfg_msg_transmit,
|
||||
#cfg_msg_transmit_type=cfg_msg_transmit_type,
|
||||
#cfg_msg_transmit_data=cfg_msg_transmit_data,
|
||||
#cfg_msg_transmit_done=cfg_msg_transmit_done,
|
||||
|
||||
# Configuration Flow Control Interface
|
||||
#cfg_fc_ph=cfg_fc_ph,
|
||||
#cfg_fc_pd=cfg_fc_pd,
|
||||
#cfg_fc_nph=cfg_fc_nph,
|
||||
#cfg_fc_npd=cfg_fc_npd,
|
||||
#cfg_fc_cplh=cfg_fc_cplh,
|
||||
#cfg_fc_cpld=cfg_fc_cpld,
|
||||
#cfg_fc_sel=cfg_fc_sel,
|
||||
|
||||
# Configuration Control Interface
|
||||
#cfg_hot_reset_in=cfg_hot_reset_in,
|
||||
#cfg_hot_reset_out=cfg_hot_reset_out,
|
||||
#cfg_config_space_enable=cfg_config_space_enable,
|
||||
#cfg_dsn=cfg_dsn,
|
||||
#cfg_ds_port_number=cfg_ds_port_number,
|
||||
#cfg_ds_bus_number=cfg_ds_bus_number,
|
||||
#cfg_ds_device_number=cfg_ds_device_number,
|
||||
#cfg_ds_function_number=cfg_ds_function_number,
|
||||
#cfg_power_state_change_ack=cfg_power_state_change_ack,
|
||||
#cfg_power_state_change_interrupt=cfg_power_state_change_interrupt,
|
||||
cfg_err_cor_in=status_error_cor,
|
||||
cfg_err_uncor_in=status_error_uncor,
|
||||
#cfg_flr_done=cfg_flr_done,
|
||||
#cfg_vf_flr_done=cfg_vf_flr_done,
|
||||
#cfg_flr_in_process=cfg_flr_in_process,
|
||||
#cfg_vf_flr_in_process=cfg_vf_flr_in_process,
|
||||
#cfg_req_pm_transition_l23_ready=cfg_req_pm_transition_l23_ready,
|
||||
#cfg_link_training_enable=cfg_link_training_enable,
|
||||
|
||||
# Configuration Interrupt Controller Interface
|
||||
#cfg_interrupt_int=cfg_interrupt_int,
|
||||
#cfg_interrupt_sent=cfg_interrupt_sent,
|
||||
#cfg_interrupt_pending=cfg_interrupt_pending,
|
||||
cfg_interrupt_msi_enable=cfg_interrupt_msi_enable,
|
||||
cfg_interrupt_msi_mmenable=cfg_interrupt_msi_mmenable,
|
||||
cfg_interrupt_msi_mask_update=cfg_interrupt_msi_mask_update,
|
||||
cfg_interrupt_msi_data=cfg_interrupt_msi_data,
|
||||
cfg_interrupt_msi_select=cfg_interrupt_msi_select,
|
||||
cfg_interrupt_msi_int=cfg_interrupt_msi_int,
|
||||
cfg_interrupt_msi_pending_status=cfg_interrupt_msi_pending_status,
|
||||
cfg_interrupt_msi_pending_status_data_enable=cfg_interrupt_msi_pending_status_data_enable,
|
||||
cfg_interrupt_msi_pending_status_function_num=cfg_interrupt_msi_pending_status_function_num,
|
||||
cfg_interrupt_msi_sent=cfg_interrupt_msi_sent,
|
||||
cfg_interrupt_msi_fail=cfg_interrupt_msi_fail,
|
||||
#cfg_interrupt_msix_enable=cfg_interrupt_msix_enable,
|
||||
#cfg_interrupt_msix_mask=cfg_interrupt_msix_mask,
|
||||
#cfg_interrupt_msix_vf_enable=cfg_interrupt_msix_vf_enable,
|
||||
#cfg_interrupt_msix_vf_mask=cfg_interrupt_msix_vf_mask,
|
||||
#cfg_interrupt_msix_address=cfg_interrupt_msix_address,
|
||||
#cfg_interrupt_msix_data=cfg_interrupt_msix_data,
|
||||
#cfg_interrupt_msix_int=cfg_interrupt_msix_int,
|
||||
#cfg_interrupt_msix_vec_pending=cfg_interrupt_msix_vec_pending,
|
||||
#cfg_interrupt_msix_vec_pending_status=cfg_interrupt_msix_vec_pending_status,
|
||||
cfg_interrupt_msi_attr=cfg_interrupt_msi_attr,
|
||||
cfg_interrupt_msi_tph_present=cfg_interrupt_msi_tph_present,
|
||||
cfg_interrupt_msi_tph_type=cfg_interrupt_msi_tph_type,
|
||||
cfg_interrupt_msi_tph_st_tag=cfg_interrupt_msi_tph_st_tag,
|
||||
cfg_interrupt_msi_function_number=cfg_interrupt_msi_function_number,
|
||||
|
||||
# Configuration Extend Interface
|
||||
#cfg_ext_read_received=cfg_ext_read_received,
|
||||
#cfg_ext_write_received=cfg_ext_write_received,
|
||||
#cfg_ext_register_number=cfg_ext_register_number,
|
||||
#cfg_ext_function_number=cfg_ext_function_number,
|
||||
#cfg_ext_write_data=cfg_ext_write_data,
|
||||
#cfg_ext_write_byte_enable=cfg_ext_write_byte_enable,
|
||||
#cfg_ext_read_data=cfg_ext_read_data,
|
||||
#cfg_ext_read_data_valid=cfg_ext_read_data_valid,
|
||||
|
||||
# Clock and Reset Interface
|
||||
user_clk=user_clk,
|
||||
user_reset=user_reset,
|
||||
#user_lnk_up=user_lnk_up,
|
||||
sys_clk=sys_clk,
|
||||
sys_clk_gt=sys_clk,
|
||||
sys_reset=sys_reset,
|
||||
#phy_rdy_out=phy_rdy_out
|
||||
)
|
||||
|
||||
# DUT
|
||||
if os.system(build_cmd):
|
||||
raise Exception("Error running build command")
|
||||
|
||||
dut = Cosimulation(
|
||||
"vvp -m myhdl %s.vvp -lxt2" % testbench,
|
||||
clk=user_clk,
|
||||
rst=user_reset,
|
||||
current_test=current_test,
|
||||
m_axis_rq_tdata=m_axis_rq_tdata,
|
||||
m_axis_rq_tkeep=m_axis_rq_tkeep,
|
||||
m_axis_rq_tlast=m_axis_rq_tlast,
|
||||
m_axis_rq_tready=m_axis_rq_tready,
|
||||
m_axis_rq_tuser=m_axis_rq_tuser,
|
||||
m_axis_rq_tvalid=m_axis_rq_tvalid,
|
||||
s_axis_rc_tdata=s_axis_rc_tdata,
|
||||
s_axis_rc_tkeep=s_axis_rc_tkeep,
|
||||
s_axis_rc_tlast=s_axis_rc_tlast,
|
||||
s_axis_rc_tready=s_axis_rc_tready,
|
||||
s_axis_rc_tuser=s_axis_rc_tuser,
|
||||
s_axis_rc_tvalid=s_axis_rc_tvalid,
|
||||
s_axis_cq_tdata=s_axis_cq_tdata,
|
||||
s_axis_cq_tkeep=s_axis_cq_tkeep,
|
||||
s_axis_cq_tlast=s_axis_cq_tlast,
|
||||
s_axis_cq_tready=s_axis_cq_tready,
|
||||
s_axis_cq_tuser=s_axis_cq_tuser,
|
||||
s_axis_cq_tvalid=s_axis_cq_tvalid,
|
||||
m_axis_cc_tdata=m_axis_cc_tdata,
|
||||
m_axis_cc_tkeep=m_axis_cc_tkeep,
|
||||
m_axis_cc_tlast=m_axis_cc_tlast,
|
||||
m_axis_cc_tready=m_axis_cc_tready,
|
||||
m_axis_cc_tuser=m_axis_cc_tuser,
|
||||
m_axis_cc_tvalid=m_axis_cc_tvalid,
|
||||
cfg_max_payload=cfg_max_payload,
|
||||
cfg_max_read_req=cfg_max_read_req,
|
||||
cfg_mgmt_addr=cfg_mgmt_addr,
|
||||
cfg_mgmt_function_number=cfg_mgmt_function_number,
|
||||
cfg_mgmt_write=cfg_mgmt_write,
|
||||
cfg_mgmt_write_data=cfg_mgmt_write_data,
|
||||
cfg_mgmt_byte_enable=cfg_mgmt_byte_enable,
|
||||
cfg_mgmt_read=cfg_mgmt_read,
|
||||
cfg_mgmt_read_data=cfg_mgmt_read_data,
|
||||
cfg_mgmt_read_write_done=cfg_mgmt_read_write_done,
|
||||
cfg_interrupt_msi_enable=cfg_interrupt_msi_enable,
|
||||
cfg_interrupt_msi_int=cfg_interrupt_msi_int,
|
||||
cfg_interrupt_msi_sent=cfg_interrupt_msi_sent,
|
||||
cfg_interrupt_msi_fail=cfg_interrupt_msi_fail,
|
||||
cfg_interrupt_msi_mmenable=cfg_interrupt_msi_mmenable,
|
||||
cfg_interrupt_msi_pending_status=cfg_interrupt_msi_pending_status,
|
||||
cfg_interrupt_msi_mask_update=cfg_interrupt_msi_mask_update,
|
||||
cfg_interrupt_msi_select=cfg_interrupt_msi_select,
|
||||
cfg_interrupt_msi_data=cfg_interrupt_msi_data,
|
||||
cfg_interrupt_msi_pending_status_function_num=cfg_interrupt_msi_pending_status_function_num,
|
||||
cfg_interrupt_msi_pending_status_data_enable=cfg_interrupt_msi_pending_status_data_enable,
|
||||
cfg_interrupt_msi_attr=cfg_interrupt_msi_attr,
|
||||
cfg_interrupt_msi_tph_present=cfg_interrupt_msi_tph_present,
|
||||
cfg_interrupt_msi_tph_type=cfg_interrupt_msi_tph_type,
|
||||
cfg_interrupt_msi_tph_st_tag=cfg_interrupt_msi_tph_st_tag,
|
||||
cfg_interrupt_msi_function_number=cfg_interrupt_msi_function_number,
|
||||
status_error_cor=status_error_cor,
|
||||
status_error_uncor=status_error_uncor
|
||||
)
|
||||
|
||||
@always(delay(5))
|
||||
def clkgen():
|
||||
clk.next = not clk
|
||||
|
||||
@always_comb
|
||||
def clk_logic():
|
||||
sys_clk.next = clk
|
||||
sys_reset.next = not rst
|
||||
|
||||
@instance
|
||||
def check():
|
||||
yield delay(100)
|
||||
yield clk.posedge
|
||||
rst.next = 1
|
||||
yield clk.posedge
|
||||
rst.next = 0
|
||||
yield clk.posedge
|
||||
yield delay(100)
|
||||
yield clk.posedge
|
||||
|
||||
# testbench stimulus
|
||||
|
||||
current_tag = 1
|
||||
|
||||
yield clk.posedge
|
||||
print("test 1: enumeration")
|
||||
current_test.next = 1
|
||||
|
||||
yield rc.enumerate(enable_bus_mastering=True, configure_msi=True)
|
||||
|
||||
dev_pf0_bar0 = dev.functions[0].bar[0] & 0xfffffffc
|
||||
dev_pf0_bar1 = dev.functions[0].bar[1] & 0xfffffffc
|
||||
|
||||
yield delay(100)
|
||||
|
||||
yield clk.posedge
|
||||
print("test 2: memory write to bar 1")
|
||||
current_test.next = 2
|
||||
|
||||
yield rc.mem_write(dev_pf0_bar1, b'\x11\x22\x33\x44')
|
||||
|
||||
yield delay(100)
|
||||
|
||||
yield clk.posedge
|
||||
print("test 3: memory read from bar 1")
|
||||
current_test.next = 3
|
||||
|
||||
val = yield from rc.mem_read(dev_pf0_bar1, 4, 1000)
|
||||
print(val)
|
||||
assert val == b'\x11\x22\x33\x44'
|
||||
|
||||
yield delay(100)
|
||||
|
||||
yield clk.posedge
|
||||
print("test 4: test DMA")
|
||||
current_test.next = 4
|
||||
|
||||
# write packet data
|
||||
mem_data[0:1024] = bytearray([x%256 for x in range(1024)])
|
||||
|
||||
# enable DMA
|
||||
yield rc.mem_write(dev_pf0_bar0+0x100000, struct.pack('<L', 1))
|
||||
|
||||
# write pcie read descriptor
|
||||
yield rc.mem_write(dev_pf0_bar0+0x100100, struct.pack('<L', (mem_base+0x0000) & 0xffffffff))
|
||||
yield rc.mem_write(dev_pf0_bar0+0x100104, struct.pack('<L', (mem_base+0x0000 >> 32) & 0xffffffff))
|
||||
yield rc.mem_write(dev_pf0_bar0+0x100108, struct.pack('<L', (0x100) & 0xffffffff))
|
||||
yield rc.mem_write(dev_pf0_bar0+0x10010C, struct.pack('<L', (0x100 >> 32) & 0xffffffff))
|
||||
yield rc.mem_write(dev_pf0_bar0+0x100110, struct.pack('<L', 0x400))
|
||||
yield rc.mem_write(dev_pf0_bar0+0x100114, struct.pack('<L', 0xAA))
|
||||
|
||||
yield delay(2000)
|
||||
|
||||
# read status
|
||||
val = yield from rc.mem_read(dev_pf0_bar0+0x100118, 4)
|
||||
print(val)
|
||||
|
||||
# write pcie write descriptor
|
||||
yield rc.mem_write(dev_pf0_bar0+0x100200, struct.pack('<L', (mem_base+0x1000) & 0xffffffff))
|
||||
yield rc.mem_write(dev_pf0_bar0+0x100204, struct.pack('<L', (mem_base+0x1000 >> 32) & 0xffffffff))
|
||||
yield rc.mem_write(dev_pf0_bar0+0x100208, struct.pack('<L', (0x100) & 0xffffffff))
|
||||
yield rc.mem_write(dev_pf0_bar0+0x10020C, struct.pack('<L', (0x100 >> 32) & 0xffffffff))
|
||||
yield rc.mem_write(dev_pf0_bar0+0x100210, struct.pack('<L', 0x400))
|
||||
yield rc.mem_write(dev_pf0_bar0+0x100214, struct.pack('<L', 0x55))
|
||||
|
||||
yield delay(2000)
|
||||
|
||||
# read status
|
||||
val = yield from rc.mem_read(dev_pf0_bar0+0x100218, 4)
|
||||
print(val)
|
||||
|
||||
data = mem_data[0x1000:(0x1000)+64]
|
||||
for i in range(0, len(data), 16):
|
||||
print(" ".join(("{:02x}".format(c) for c in bytearray(data[i:i+16]))))
|
||||
|
||||
assert mem_data[0:1024] == mem_data[0x1000:0x1000+1024]
|
||||
|
||||
yield delay(100)
|
||||
|
||||
raise StopSimulation
|
||||
|
||||
return instances()
|
||||
|
||||
def test_bench():
|
||||
sim = Simulation(bench())
|
||||
sim.run()
|
||||
|
||||
if __name__ == '__main__':
|
||||
print("Running test...")
|
||||
test_bench()
|
@ -1,234 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2018 Alex Forencich
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
// Language: Verilog 2001
|
||||
|
||||
`timescale 1ns / 1ps
|
||||
|
||||
/*
|
||||
* Testbench for fpga_core
|
||||
*/
|
||||
module test_fpga_core;
|
||||
|
||||
// Parameters
|
||||
parameter AXIS_PCIE_DATA_WIDTH = 512;
|
||||
parameter AXIS_PCIE_KEEP_WIDTH = (AXIS_PCIE_DATA_WIDTH/32);
|
||||
parameter AXIS_PCIE_RC_USER_WIDTH = 161;
|
||||
parameter AXIS_PCIE_RQ_USER_WIDTH = 137;
|
||||
parameter AXIS_PCIE_CQ_USER_WIDTH = 183;
|
||||
parameter AXIS_PCIE_CC_USER_WIDTH = 81;
|
||||
|
||||
// Inputs
|
||||
reg clk = 0;
|
||||
reg rst = 0;
|
||||
reg [7:0] current_test = 0;
|
||||
|
||||
reg m_axis_rq_tready = 0;
|
||||
reg [AXIS_PCIE_DATA_WIDTH-1:0] s_axis_rc_tdata = 0;
|
||||
reg [AXIS_PCIE_KEEP_WIDTH-1:0] s_axis_rc_tkeep = 0;
|
||||
reg s_axis_rc_tlast = 0;
|
||||
reg [AXIS_PCIE_RC_USER_WIDTH-1:0] s_axis_rc_tuser = 0;
|
||||
reg s_axis_rc_tvalid = 0;
|
||||
reg [AXIS_PCIE_DATA_WIDTH-1:0] s_axis_cq_tdata = 0;
|
||||
reg [AXIS_PCIE_KEEP_WIDTH-1:0] s_axis_cq_tkeep = 0;
|
||||
reg s_axis_cq_tlast = 0;
|
||||
reg [AXIS_PCIE_CQ_USER_WIDTH-1:0] s_axis_cq_tuser = 0;
|
||||
reg s_axis_cq_tvalid = 0;
|
||||
reg m_axis_cc_tready = 0;
|
||||
reg [2:0] cfg_max_payload = 0;
|
||||
reg [2:0] cfg_max_read_req = 0;
|
||||
reg [31:0] cfg_mgmt_read_data = 0;
|
||||
reg cfg_mgmt_read_write_done = 0;
|
||||
reg [3:0] cfg_interrupt_msi_enable = 0;
|
||||
reg [11:0] cfg_interrupt_msi_mmenable = 0;
|
||||
reg cfg_interrupt_msi_mask_update = 0;
|
||||
reg [31:0] cfg_interrupt_msi_data = 0;
|
||||
reg cfg_interrupt_msi_sent = 0;
|
||||
reg cfg_interrupt_msi_fail = 0;
|
||||
|
||||
// Outputs
|
||||
wire [AXIS_PCIE_DATA_WIDTH-1:0] m_axis_rq_tdata;
|
||||
wire [AXIS_PCIE_KEEP_WIDTH-1:0] m_axis_rq_tkeep;
|
||||
wire m_axis_rq_tlast;
|
||||
wire [AXIS_PCIE_RQ_USER_WIDTH-1:0] m_axis_rq_tuser;
|
||||
wire m_axis_rq_tvalid;
|
||||
wire s_axis_rc_tready;
|
||||
wire s_axis_cq_tready;
|
||||
wire [AXIS_PCIE_DATA_WIDTH-1:0] m_axis_cc_tdata;
|
||||
wire [AXIS_PCIE_KEEP_WIDTH-1:0] m_axis_cc_tkeep;
|
||||
wire m_axis_cc_tlast;
|
||||
wire [AXIS_PCIE_CC_USER_WIDTH-1:0] m_axis_cc_tuser;
|
||||
wire m_axis_cc_tvalid;
|
||||
wire [9:0] cfg_mgmt_addr;
|
||||
wire [7:0] cfg_mgmt_function_number;
|
||||
wire cfg_mgmt_write;
|
||||
wire [31:0] cfg_mgmt_write_data;
|
||||
wire [3:0] cfg_mgmt_byte_enable;
|
||||
wire cfg_mgmt_read;
|
||||
wire [3:0] cfg_interrupt_msi_select;
|
||||
wire [31:0] cfg_interrupt_msi_int;
|
||||
wire [31:0] cfg_interrupt_msi_pending_status;
|
||||
wire cfg_interrupt_msi_pending_status_data_enable;
|
||||
wire [3:0] cfg_interrupt_msi_pending_status_function_num;
|
||||
wire [2:0] cfg_interrupt_msi_attr;
|
||||
wire cfg_interrupt_msi_tph_present;
|
||||
wire [1:0] cfg_interrupt_msi_tph_type;
|
||||
wire [8:0] cfg_interrupt_msi_tph_st_tag;
|
||||
wire [3:0] cfg_interrupt_msi_function_number;
|
||||
wire status_error_cor;
|
||||
wire status_error_uncor;
|
||||
|
||||
initial begin
|
||||
// myhdl integration
|
||||
$from_myhdl(
|
||||
clk,
|
||||
rst,
|
||||
current_test,
|
||||
m_axis_rq_tready,
|
||||
s_axis_rc_tdata,
|
||||
s_axis_rc_tkeep,
|
||||
s_axis_rc_tlast,
|
||||
s_axis_rc_tuser,
|
||||
s_axis_rc_tvalid,
|
||||
s_axis_cq_tdata,
|
||||
s_axis_cq_tkeep,
|
||||
s_axis_cq_tlast,
|
||||
s_axis_cq_tuser,
|
||||
s_axis_cq_tvalid,
|
||||
m_axis_cc_tready,
|
||||
cfg_max_payload,
|
||||
cfg_max_read_req,
|
||||
cfg_mgmt_read_data,
|
||||
cfg_mgmt_read_write_done,
|
||||
cfg_interrupt_msi_enable,
|
||||
cfg_interrupt_msi_mmenable,
|
||||
cfg_interrupt_msi_mask_update,
|
||||
cfg_interrupt_msi_data,
|
||||
cfg_interrupt_msi_sent,
|
||||
cfg_interrupt_msi_fail
|
||||
);
|
||||
$to_myhdl(
|
||||
m_axis_rq_tdata,
|
||||
m_axis_rq_tkeep,
|
||||
m_axis_rq_tlast,
|
||||
m_axis_rq_tuser,
|
||||
m_axis_rq_tvalid,
|
||||
s_axis_rc_tready,
|
||||
s_axis_cq_tready,
|
||||
m_axis_cc_tdata,
|
||||
m_axis_cc_tkeep,
|
||||
m_axis_cc_tlast,
|
||||
m_axis_cc_tuser,
|
||||
m_axis_cc_tvalid,
|
||||
cfg_mgmt_addr,
|
||||
cfg_mgmt_function_number,
|
||||
cfg_mgmt_write,
|
||||
cfg_mgmt_write_data,
|
||||
cfg_mgmt_byte_enable,
|
||||
cfg_mgmt_read,
|
||||
cfg_interrupt_msi_select,
|
||||
cfg_interrupt_msi_int,
|
||||
cfg_interrupt_msi_pending_status,
|
||||
cfg_interrupt_msi_pending_status_data_enable,
|
||||
cfg_interrupt_msi_pending_status_function_num,
|
||||
cfg_interrupt_msi_attr,
|
||||
cfg_interrupt_msi_tph_present,
|
||||
cfg_interrupt_msi_tph_type,
|
||||
cfg_interrupt_msi_tph_st_tag,
|
||||
cfg_interrupt_msi_function_number,
|
||||
status_error_cor,
|
||||
status_error_uncor
|
||||
);
|
||||
|
||||
// dump file
|
||||
$dumpfile("test_fpga_core.lxt");
|
||||
$dumpvars(0, test_fpga_core);
|
||||
end
|
||||
|
||||
fpga_core #(
|
||||
.AXIS_PCIE_DATA_WIDTH(AXIS_PCIE_DATA_WIDTH),
|
||||
.AXIS_PCIE_KEEP_WIDTH(AXIS_PCIE_KEEP_WIDTH),
|
||||
.AXIS_PCIE_RC_USER_WIDTH(AXIS_PCIE_RC_USER_WIDTH),
|
||||
.AXIS_PCIE_RQ_USER_WIDTH(AXIS_PCIE_RQ_USER_WIDTH),
|
||||
.AXIS_PCIE_CQ_USER_WIDTH(AXIS_PCIE_CQ_USER_WIDTH),
|
||||
.AXIS_PCIE_CC_USER_WIDTH(AXIS_PCIE_CC_USER_WIDTH)
|
||||
)
|
||||
UUT (
|
||||
.clk(clk),
|
||||
.rst(rst),
|
||||
.m_axis_rq_tdata(m_axis_rq_tdata),
|
||||
.m_axis_rq_tkeep(m_axis_rq_tkeep),
|
||||
.m_axis_rq_tlast(m_axis_rq_tlast),
|
||||
.m_axis_rq_tready(m_axis_rq_tready),
|
||||
.m_axis_rq_tuser(m_axis_rq_tuser),
|
||||
.m_axis_rq_tvalid(m_axis_rq_tvalid),
|
||||
.s_axis_rc_tdata(s_axis_rc_tdata),
|
||||
.s_axis_rc_tkeep(s_axis_rc_tkeep),
|
||||
.s_axis_rc_tlast(s_axis_rc_tlast),
|
||||
.s_axis_rc_tready(s_axis_rc_tready),
|
||||
.s_axis_rc_tuser(s_axis_rc_tuser),
|
||||
.s_axis_rc_tvalid(s_axis_rc_tvalid),
|
||||
.s_axis_cq_tdata(s_axis_cq_tdata),
|
||||
.s_axis_cq_tkeep(s_axis_cq_tkeep),
|
||||
.s_axis_cq_tlast(s_axis_cq_tlast),
|
||||
.s_axis_cq_tready(s_axis_cq_tready),
|
||||
.s_axis_cq_tuser(s_axis_cq_tuser),
|
||||
.s_axis_cq_tvalid(s_axis_cq_tvalid),
|
||||
.m_axis_cc_tdata(m_axis_cc_tdata),
|
||||
.m_axis_cc_tkeep(m_axis_cc_tkeep),
|
||||
.m_axis_cc_tlast(m_axis_cc_tlast),
|
||||
.m_axis_cc_tready(m_axis_cc_tready),
|
||||
.m_axis_cc_tuser(m_axis_cc_tuser),
|
||||
.m_axis_cc_tvalid(m_axis_cc_tvalid),
|
||||
.cfg_max_payload(cfg_max_payload),
|
||||
.cfg_max_read_req(cfg_max_read_req),
|
||||
.cfg_mgmt_addr(cfg_mgmt_addr),
|
||||
.cfg_mgmt_function_number(cfg_mgmt_function_number),
|
||||
.cfg_mgmt_write(cfg_mgmt_write),
|
||||
.cfg_mgmt_write_data(cfg_mgmt_write_data),
|
||||
.cfg_mgmt_byte_enable(cfg_mgmt_byte_enable),
|
||||
.cfg_mgmt_read(cfg_mgmt_read),
|
||||
.cfg_mgmt_read_data(cfg_mgmt_read_data),
|
||||
.cfg_mgmt_read_write_done(cfg_mgmt_read_write_done),
|
||||
.cfg_interrupt_msi_enable(cfg_interrupt_msi_enable),
|
||||
.cfg_interrupt_msi_mmenable(cfg_interrupt_msi_mmenable),
|
||||
.cfg_interrupt_msi_mask_update(cfg_interrupt_msi_mask_update),
|
||||
.cfg_interrupt_msi_data(cfg_interrupt_msi_data),
|
||||
.cfg_interrupt_msi_select(cfg_interrupt_msi_select),
|
||||
.cfg_interrupt_msi_int(cfg_interrupt_msi_int),
|
||||
.cfg_interrupt_msi_pending_status(cfg_interrupt_msi_pending_status),
|
||||
.cfg_interrupt_msi_pending_status_data_enable(cfg_interrupt_msi_pending_status_data_enable),
|
||||
.cfg_interrupt_msi_pending_status_function_num(cfg_interrupt_msi_pending_status_function_num),
|
||||
.cfg_interrupt_msi_sent(cfg_interrupt_msi_sent),
|
||||
.cfg_interrupt_msi_fail(cfg_interrupt_msi_fail),
|
||||
.cfg_interrupt_msi_attr(cfg_interrupt_msi_attr),
|
||||
.cfg_interrupt_msi_tph_present(cfg_interrupt_msi_tph_present),
|
||||
.cfg_interrupt_msi_tph_type(cfg_interrupt_msi_tph_type),
|
||||
.cfg_interrupt_msi_tph_st_tag(cfg_interrupt_msi_tph_st_tag),
|
||||
.cfg_interrupt_msi_function_number(cfg_interrupt_msi_function_number),
|
||||
.status_error_cor(status_error_cor),
|
||||
.status_error_uncor(status_error_uncor)
|
||||
);
|
||||
|
||||
endmodule
|
@ -1 +0,0 @@
|
||||
../lib/pcie/tb/axis_ep.py
|
107
example/AU50/fpga_axi/tb/fpga_core/Makefile
Normal file
107
example/AU50/fpga_axi/tb/fpga_core/Makefile
Normal file
@ -0,0 +1,107 @@
|
||||
# Copyright (c) 2020 Alex Forencich
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in
|
||||
# all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
# THE SOFTWARE.
|
||||
|
||||
TOPLEVEL_LANG = verilog
|
||||
|
||||
SIM ?= icarus
|
||||
WAVES ?= 0
|
||||
|
||||
COCOTB_HDL_TIMEUNIT = 1ns
|
||||
COCOTB_HDL_TIMEPRECISION = 1ps
|
||||
|
||||
DUT = fpga_core
|
||||
TOPLEVEL = $(DUT)
|
||||
MODULE = test_$(DUT)
|
||||
VERILOG_SOURCES += ../../rtl/$(DUT).v
|
||||
VERILOG_SOURCES += ../../rtl/axi_ram.v
|
||||
VERILOG_SOURCES += ../../rtl/axis_register.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/axis_arb_mux.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_axil_master.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_axi_dma.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_axi_dma_rd.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_axi_dma_wr.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_tag_manager.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_axi_master.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_axi_master_rd.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_axi_master_wr.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_axis_cq_demux.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_cfg.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_msi.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/arbiter.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/priority_encoder.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pulse_merge.v
|
||||
|
||||
# module parameters
|
||||
export PARAM_AXIS_PCIE_DATA_WIDTH ?= 512
|
||||
export PARAM_AXIS_PCIE_KEEP_WIDTH ?= $(shell expr $(PARAM_AXIS_PCIE_DATA_WIDTH) / 32 )
|
||||
export PARAM_AXIS_PCIE_RQ_USER_WIDTH ?= $(if $(filter-out 512,$(PARAM_AXIS_PCIE_DATA_WIDTH)),62,137)
|
||||
export PARAM_AXIS_PCIE_RC_USER_WIDTH ?= $(if $(filter-out 512,$(PARAM_AXIS_PCIE_DATA_WIDTH)),75,161)
|
||||
export PARAM_AXIS_PCIE_CQ_USER_WIDTH ?= $(if $(filter-out 512,$(PARAM_AXIS_PCIE_DATA_WIDTH)),88,183)
|
||||
export PARAM_AXIS_PCIE_CC_USER_WIDTH ?= $(if $(filter-out 512,$(PARAM_AXIS_PCIE_DATA_WIDTH)),33,81)
|
||||
export PARAM_RQ_SEQ_NUM_WIDTH ?= 6
|
||||
|
||||
SIM_BUILD ?= sim_build_$(MODULE)
|
||||
|
||||
ifeq ($(SIM), icarus)
|
||||
PLUSARGS += -fst
|
||||
|
||||
COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_DATA_WIDTH=$(PARAM_AXIS_PCIE_DATA_WIDTH)
|
||||
COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_KEEP_WIDTH=$(PARAM_AXIS_PCIE_KEEP_WIDTH)
|
||||
COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_RQ_USER_WIDTH=$(PARAM_AXIS_PCIE_RQ_USER_WIDTH)
|
||||
COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_RC_USER_WIDTH=$(PARAM_AXIS_PCIE_RC_USER_WIDTH)
|
||||
COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_CQ_USER_WIDTH=$(PARAM_AXIS_PCIE_CQ_USER_WIDTH)
|
||||
COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_CC_USER_WIDTH=$(PARAM_AXIS_PCIE_CC_USER_WIDTH)
|
||||
COMPILE_ARGS += -P $(TOPLEVEL).RQ_SEQ_NUM_WIDTH=$(PARAM_RQ_SEQ_NUM_WIDTH)
|
||||
|
||||
ifeq ($(WAVES), 1)
|
||||
VERILOG_SOURCES += iverilog_dump.v
|
||||
COMPILE_ARGS += -s iverilog_dump
|
||||
endif
|
||||
else ifeq ($(SIM), verilator)
|
||||
COMPILE_ARGS += -Wno-SELRANGE -Wno-WIDTH
|
||||
|
||||
COMPILE_ARGS += -GAXIS_PCIE_DATA_WIDTH=$(PARAM_AXIS_PCIE_DATA_WIDTH)
|
||||
COMPILE_ARGS += -GAXIS_PCIE_KEEP_WIDTH=$(PARAM_AXIS_PCIE_KEEP_WIDTH)
|
||||
COMPILE_ARGS += -GAXIS_PCIE_RQ_USER_WIDTH=$(PARAM_AXIS_PCIE_RQ_USER_WIDTH)
|
||||
COMPILE_ARGS += -GAXIS_PCIE_RC_USER_WIDTH=$(PARAM_AXIS_PCIE_RC_USER_WIDTH)
|
||||
COMPILE_ARGS += -GAXIS_PCIE_CQ_USER_WIDTH=$(PARAM_AXIS_PCIE_CQ_USER_WIDTH)
|
||||
COMPILE_ARGS += -GAXIS_PCIE_CC_USER_WIDTH=$(PARAM_AXIS_PCIE_CC_USER_WIDTH)
|
||||
COMPILE_ARGS += -GRQ_SEQ_NUM_WIDTH=$(PARAM_RQ_SEQ_NUM_WIDTH)
|
||||
|
||||
ifeq ($(WAVES), 1)
|
||||
COMPILE_ARGS += --trace-fst
|
||||
endif
|
||||
endif
|
||||
|
||||
iverilog_dump.v:
|
||||
echo 'module iverilog_dump();' > $@
|
||||
echo 'initial begin' >> $@
|
||||
echo ' $$dumpfile("$(TOPLEVEL).fst");' >> $@
|
||||
echo ' $$dumpvars(0, $(TOPLEVEL));' >> $@
|
||||
echo 'end' >> $@
|
||||
echo 'endmodule' >> $@
|
||||
|
||||
clean::
|
||||
@rm -rf sim_build_*
|
||||
@rm -rf iverilog_dump.v
|
||||
@rm -rf dump.fst $(TOPLEVEL).fst
|
||||
|
||||
include $(shell cocotb-config --makefiles)/Makefile.sim
|
||||
|
378
example/AU50/fpga_axi/tb/fpga_core/test_fpga_core.py
Normal file
378
example/AU50/fpga_axi/tb/fpga_core/test_fpga_core.py
Normal file
@ -0,0 +1,378 @@
|
||||
"""
|
||||
|
||||
Copyright (c) 2020 Alex Forencich
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
"""
|
||||
|
||||
import logging
|
||||
import os
|
||||
|
||||
import cocotb_test.simulator
|
||||
|
||||
import cocotb
|
||||
from cocotb.log import SimLog
|
||||
from cocotb.triggers import RisingEdge, FallingEdge, Timer
|
||||
|
||||
from cocotbext.pcie.core import RootComplex
|
||||
from cocotbext.pcie.xilinx.us import UltraScalePlusPcieDevice
|
||||
from cocotbext.axi.utils import hexdump_str
|
||||
|
||||
|
||||
class TB(object):
|
||||
def __init__(self, dut):
|
||||
self.dut = dut
|
||||
|
||||
self.log = SimLog("cocotb.tb")
|
||||
self.log.setLevel(logging.DEBUG)
|
||||
|
||||
# PCIe
|
||||
self.rc = RootComplex()
|
||||
|
||||
self.dev = UltraScalePlusPcieDevice(
|
||||
# configuration options
|
||||
pcie_generation=3,
|
||||
pcie_link_width=16,
|
||||
user_clk_frequency=250e6,
|
||||
alignment="dword",
|
||||
cq_cc_straddle=False,
|
||||
rq_rc_straddle=False,
|
||||
rc_4tlp_straddle=False,
|
||||
enable_pf1=False,
|
||||
enable_client_tag=True,
|
||||
enable_extended_tag=True,
|
||||
enable_parity=False,
|
||||
enable_rx_msg_interface=False,
|
||||
enable_sriov=False,
|
||||
enable_extended_configuration=False,
|
||||
|
||||
enable_pf0_msi=True,
|
||||
enable_pf1_msi=False,
|
||||
|
||||
# signals
|
||||
# Clock and Reset Interface
|
||||
user_clk=dut.clk,
|
||||
user_reset=dut.rst,
|
||||
# user_lnk_up
|
||||
# sys_clk
|
||||
# sys_clk_gt
|
||||
# sys_reset
|
||||
# phy_rdy_out
|
||||
|
||||
# Requester reQuest Interface
|
||||
rq_entity=dut,
|
||||
rq_name="m_axis_rq",
|
||||
# pcie_rq_seq_num0=dut.s_axis_rq_seq_num_0,
|
||||
# pcie_rq_seq_num_vld0=dut.s_axis_rq_seq_num_valid_0,
|
||||
# pcie_rq_seq_num1=dut.s_axis_rq_seq_num_1,
|
||||
# pcie_rq_seq_num_vld1=dut.s_axis_rq_seq_num_valid_1,
|
||||
# pcie_rq_tag0
|
||||
# pcie_rq_tag1
|
||||
# pcie_rq_tag_av
|
||||
# pcie_rq_tag_vld0
|
||||
# pcie_rq_tag_vld1
|
||||
|
||||
# Requester Completion Interface
|
||||
rc_entity=dut,
|
||||
rc_name="s_axis_rc",
|
||||
|
||||
# Completer reQuest Interface
|
||||
cq_entity=dut,
|
||||
cq_name="s_axis_cq",
|
||||
# pcie_cq_np_req
|
||||
# pcie_cq_np_req_count
|
||||
|
||||
# Completer Completion Interface
|
||||
cc_entity=dut,
|
||||
cc_name="m_axis_cc",
|
||||
|
||||
# Transmit Flow Control Interface
|
||||
# pcie_tfc_nph_av=dut.pcie_tfc_nph_av,
|
||||
# pcie_tfc_npd_av=dut.pcie_tfc_npd_av,
|
||||
|
||||
# Configuration Management Interface
|
||||
cfg_mgmt_addr=dut.cfg_mgmt_addr,
|
||||
cfg_mgmt_function_number=dut.cfg_mgmt_function_number,
|
||||
cfg_mgmt_write=dut.cfg_mgmt_write,
|
||||
cfg_mgmt_write_data=dut.cfg_mgmt_write_data,
|
||||
cfg_mgmt_byte_enable=dut.cfg_mgmt_byte_enable,
|
||||
cfg_mgmt_read=dut.cfg_mgmt_read,
|
||||
cfg_mgmt_read_data=dut.cfg_mgmt_read_data,
|
||||
cfg_mgmt_read_write_done=dut.cfg_mgmt_read_write_done,
|
||||
# cfg_mgmt_debug_access
|
||||
|
||||
# Configuration Status Interface
|
||||
# cfg_phy_link_down
|
||||
# cfg_phy_link_status
|
||||
# cfg_negotiated_width
|
||||
# cfg_current_speed
|
||||
cfg_max_payload=dut.cfg_max_payload,
|
||||
cfg_max_read_req=dut.cfg_max_read_req,
|
||||
# cfg_function_status
|
||||
# cfg_vf_status
|
||||
# cfg_function_power_state
|
||||
# cfg_vf_power_state
|
||||
# cfg_link_power_state
|
||||
# cfg_err_cor_out
|
||||
# cfg_err_nonfatal_out
|
||||
# cfg_err_fatal_out
|
||||
# cfg_local_error_out
|
||||
# cfg_local_error_valid
|
||||
# cfg_rx_pm_state
|
||||
# cfg_tx_pm_state
|
||||
# cfg_ltssm_state
|
||||
# cfg_rcb_status
|
||||
# cfg_obff_enable
|
||||
# cfg_pl_status_change
|
||||
# cfg_tph_requester_enable
|
||||
# cfg_tph_st_mode
|
||||
# cfg_vf_tph_requester_enable
|
||||
# cfg_vf_tph_st_mode
|
||||
|
||||
# Configuration Received Message Interface
|
||||
# cfg_msg_received
|
||||
# cfg_msg_received_data
|
||||
# cfg_msg_received_type
|
||||
|
||||
# Configuration Transmit Message Interface
|
||||
# cfg_msg_transmit
|
||||
# cfg_msg_transmit_type
|
||||
# cfg_msg_transmit_data
|
||||
# cfg_msg_transmit_done
|
||||
|
||||
# Configuration Flow Control Interface
|
||||
# cfg_fc_ph=dut.cfg_fc_ph,
|
||||
# cfg_fc_pd=dut.cfg_fc_pd,
|
||||
# cfg_fc_nph=dut.cfg_fc_nph,
|
||||
# cfg_fc_npd=dut.cfg_fc_npd,
|
||||
# cfg_fc_cplh=dut.cfg_fc_cplh,
|
||||
# cfg_fc_cpld=dut.cfg_fc_cpld,
|
||||
# cfg_fc_sel=dut.cfg_fc_sel,
|
||||
|
||||
# Configuration Control Interface
|
||||
# cfg_hot_reset_in
|
||||
# cfg_hot_reset_out
|
||||
# cfg_config_space_enable
|
||||
# cfg_dsn
|
||||
# cfg_bus_number
|
||||
# cfg_ds_port_number
|
||||
# cfg_ds_bus_number
|
||||
# cfg_ds_device_number
|
||||
# cfg_ds_function_number
|
||||
# cfg_power_state_change_ack
|
||||
# cfg_power_state_change_interrupt
|
||||
cfg_err_cor_in=dut.status_error_cor,
|
||||
cfg_err_uncor_in=dut.status_error_uncor,
|
||||
# cfg_flr_in_process
|
||||
# cfg_flr_done
|
||||
# cfg_vf_flr_in_process
|
||||
# cfg_vf_flr_func_num
|
||||
# cfg_vf_flr_done
|
||||
# cfg_pm_aspm_l1_entry_reject
|
||||
# cfg_pm_aspm_tx_l0s_entry_disable
|
||||
# cfg_req_pm_transition_l23_ready
|
||||
# cfg_link_training_enable
|
||||
|
||||
# Configuration Interrupt Controller Interface
|
||||
# cfg_interrupt_int
|
||||
# cfg_interrupt_sent
|
||||
# cfg_interrupt_pending
|
||||
cfg_interrupt_msi_enable=dut.cfg_interrupt_msi_enable,
|
||||
cfg_interrupt_msi_mmenable=dut.cfg_interrupt_msi_mmenable,
|
||||
cfg_interrupt_msi_mask_update=dut.cfg_interrupt_msi_mask_update,
|
||||
cfg_interrupt_msi_data=dut.cfg_interrupt_msi_data,
|
||||
# cfg_interrupt_msi_select=dut.cfg_interrupt_msi_select,
|
||||
cfg_interrupt_msi_int=dut.cfg_interrupt_msi_int,
|
||||
cfg_interrupt_msi_pending_status=dut.cfg_interrupt_msi_pending_status,
|
||||
cfg_interrupt_msi_pending_status_data_enable=dut.cfg_interrupt_msi_pending_status_data_enable,
|
||||
# cfg_interrupt_msi_pending_status_function_num=dut.cfg_interrupt_msi_pending_status_function_num,
|
||||
cfg_interrupt_msi_sent=dut.cfg_interrupt_msi_sent,
|
||||
cfg_interrupt_msi_fail=dut.cfg_interrupt_msi_fail,
|
||||
# cfg_interrupt_msix_enable
|
||||
# cfg_interrupt_msix_mask
|
||||
# cfg_interrupt_msix_vf_enable
|
||||
# cfg_interrupt_msix_vf_mask
|
||||
# cfg_interrupt_msix_address
|
||||
# cfg_interrupt_msix_data
|
||||
# cfg_interrupt_msix_int
|
||||
# cfg_interrupt_msix_vec_pending
|
||||
# cfg_interrupt_msix_vec_pending_status
|
||||
cfg_interrupt_msi_attr=dut.cfg_interrupt_msi_attr,
|
||||
cfg_interrupt_msi_tph_present=dut.cfg_interrupt_msi_tph_present,
|
||||
cfg_interrupt_msi_tph_type=dut.cfg_interrupt_msi_tph_type,
|
||||
# cfg_interrupt_msi_tph_st_tag=dut.cfg_interrupt_msi_tph_st_tag,
|
||||
# cfg_interrupt_msi_function_number=dut.cfg_interrupt_msi_function_number,
|
||||
|
||||
# Configuration Extend Interface
|
||||
# cfg_ext_read_received
|
||||
# cfg_ext_write_received
|
||||
# cfg_ext_register_number
|
||||
# cfg_ext_function_number
|
||||
# cfg_ext_write_data
|
||||
# cfg_ext_write_byte_enable
|
||||
# cfg_ext_read_data
|
||||
# cfg_ext_read_data_valid
|
||||
)
|
||||
|
||||
# self.dev.log.setLevel(logging.DEBUG)
|
||||
|
||||
self.rc.make_port().connect(self.dev)
|
||||
|
||||
self.dev.functions[0].msi_multiple_message_capable = 5
|
||||
|
||||
self.dev.functions[0].configure_bar(0, 2**22)
|
||||
self.dev.functions[0].configure_bar(1, 2**22)
|
||||
|
||||
async def init(self):
|
||||
|
||||
await FallingEdge(self.dut.rst)
|
||||
await Timer(100, 'ns')
|
||||
|
||||
await self.rc.enumerate(enable_bus_mastering=True, configure_msi=True)
|
||||
|
||||
|
||||
@cocotb.test()
|
||||
async def run_test(dut):
|
||||
|
||||
tb = TB(dut)
|
||||
|
||||
await tb.init()
|
||||
|
||||
mem_base, mem_data = tb.rc.alloc_region(16*1024*1024)
|
||||
|
||||
dev_pf0_bar0 = tb.rc.tree[0][0].bar_addr[0]
|
||||
dev_pf0_bar1 = tb.rc.tree[0][0].bar_addr[1]
|
||||
|
||||
tb.log.info("Test memory write to BAR 1")
|
||||
|
||||
await tb.rc.mem_write(dev_pf0_bar1, b'\x11\x22\x33\x44')
|
||||
|
||||
await Timer(100, 'ns')
|
||||
|
||||
tb.log.info("Test memory read from BAR 1")
|
||||
|
||||
val = await tb.rc.mem_read(dev_pf0_bar1, 4, 1000)
|
||||
tb.log.info("Read data: %s", val)
|
||||
assert val == b'\x11\x22\x33\x44'
|
||||
|
||||
tb.log.info("Test DMA")
|
||||
|
||||
# write packet data
|
||||
mem_data[0:1024] = bytearray([x % 256 for x in range(1024)])
|
||||
|
||||
# enable DMA
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100000, 1)
|
||||
|
||||
# write pcie read descriptor
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100100, (mem_base+0x0000) & 0xffffffff)
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100104, (mem_base+0x0000 >> 32) & 0xffffffff)
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100108, (0x100) & 0xffffffff)
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x10010C, (0x100 >> 32) & 0xffffffff)
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100110, 0x400)
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100114, 0xAA)
|
||||
|
||||
await Timer(2000, 'ns')
|
||||
|
||||
# read status
|
||||
val = await tb.rc.mem_read_dword(dev_pf0_bar0+0x100118)
|
||||
tb.log.info("Status: 0x%x", val)
|
||||
assert val == 0xAA
|
||||
|
||||
# write pcie write descriptor
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100200, (mem_base+0x1000) & 0xffffffff)
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100204, (mem_base+0x1000 >> 32) & 0xffffffff)
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100208, (0x100) & 0xffffffff)
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x10020C, (0x100 >> 32) & 0xffffffff)
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100210, 0x400)
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100214, 0x55)
|
||||
|
||||
await Timer(2000, 'ns')
|
||||
|
||||
# read status
|
||||
val = await tb.rc.mem_read_dword(dev_pf0_bar0+0x100218)
|
||||
tb.log.info("Status: 0x%x", val)
|
||||
assert val == 0x55
|
||||
|
||||
tb.log.info("%s", hexdump_str(mem_data, 0x1000, 64))
|
||||
|
||||
assert mem_data[0:1024] == mem_data[0x1000:0x1000+1024]
|
||||
|
||||
await RisingEdge(dut.clk)
|
||||
await RisingEdge(dut.clk)
|
||||
|
||||
|
||||
# cocotb-test
|
||||
|
||||
tests_dir = os.path.dirname(__file__)
|
||||
rtl_dir = os.path.abspath(os.path.join(tests_dir, '..', '..', 'rtl'))
|
||||
lib_dir = os.path.abspath(os.path.join(rtl_dir, '..', 'lib'))
|
||||
pcie_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'pcie', 'rtl'))
|
||||
|
||||
|
||||
def test_fpga_core(request):
|
||||
dut = "fpga_core"
|
||||
module = os.path.splitext(os.path.basename(__file__))[0]
|
||||
toplevel = dut
|
||||
|
||||
verilog_sources = [
|
||||
os.path.join(rtl_dir, f"{dut}.v"),
|
||||
os.path.join(rtl_dir, "axi_ram.v"),
|
||||
os.path.join(rtl_dir, "axis_register.v"),
|
||||
os.path.join(pcie_rtl_dir, "axis_arb_mux.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_us_axil_master.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_us_axi_dma.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_us_axi_dma_rd.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_us_axi_dma_wr.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_tag_manager.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_us_axi_master.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_us_axi_master_rd.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_us_axi_master_wr.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_us_axis_cq_demux.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_us_cfg.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_us_msi.v"),
|
||||
os.path.join(pcie_rtl_dir, "arbiter.v"),
|
||||
os.path.join(pcie_rtl_dir, "priority_encoder.v"),
|
||||
os.path.join(pcie_rtl_dir, "pulse_merge.v"),
|
||||
]
|
||||
|
||||
parameters = {}
|
||||
|
||||
parameters['AXIS_PCIE_DATA_WIDTH'] = 512
|
||||
parameters['AXIS_PCIE_KEEP_WIDTH'] = parameters['AXIS_PCIE_DATA_WIDTH'] // 32
|
||||
parameters['AXIS_PCIE_RQ_USER_WIDTH'] = 62 if parameters['AXIS_PCIE_DATA_WIDTH'] < 512 else 137
|
||||
parameters['AXIS_PCIE_RC_USER_WIDTH'] = 75 if parameters['AXIS_PCIE_DATA_WIDTH'] < 512 else 161
|
||||
parameters['AXIS_PCIE_CQ_USER_WIDTH'] = 88 if parameters['AXIS_PCIE_DATA_WIDTH'] < 512 else 183
|
||||
parameters['AXIS_PCIE_CC_USER_WIDTH'] = 33 if parameters['AXIS_PCIE_DATA_WIDTH'] < 512 else 81
|
||||
parameters['RQ_SEQ_NUM_WIDTH'] = 6
|
||||
|
||||
extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()}
|
||||
|
||||
sim_build = os.path.join(tests_dir,
|
||||
"sim_build_"+request.node.name.replace('[', '-').replace(']', ''))
|
||||
|
||||
cocotb_test.simulator.run(
|
||||
python_search=[tests_dir],
|
||||
verilog_sources=verilog_sources,
|
||||
toplevel=toplevel,
|
||||
module=module,
|
||||
parameters=parameters,
|
||||
sim_build=sim_build,
|
||||
extra_env=extra_env,
|
||||
)
|
@ -1 +0,0 @@
|
||||
../lib/pcie/tb/pcie.py
|
@ -1 +0,0 @@
|
||||
../lib/pcie/tb/pcie_us.py
|
@ -1 +0,0 @@
|
||||
../lib/pcie/tb/pcie_usp.py
|
@ -1,506 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
"""
|
||||
|
||||
Copyright (c) 2018 Alex Forencich
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
"""
|
||||
|
||||
from myhdl import *
|
||||
import os
|
||||
import struct
|
||||
|
||||
import pcie
|
||||
import pcie_usp
|
||||
|
||||
module = 'fpga_core'
|
||||
testbench = 'test_%s' % module
|
||||
|
||||
srcs = []
|
||||
|
||||
srcs.append("../rtl/%s.v" % module)
|
||||
srcs.append("../rtl/axi_ram.v")
|
||||
srcs.append("../rtl/axis_register.v")
|
||||
srcs.append("../lib/pcie/rtl/axis_arb_mux.v")
|
||||
srcs.append("../lib/pcie/rtl/pcie_us_axil_master.v")
|
||||
srcs.append("../lib/pcie/rtl/pcie_us_axi_dma.v")
|
||||
srcs.append("../lib/pcie/rtl/pcie_us_axi_dma_rd.v")
|
||||
srcs.append("../lib/pcie/rtl/pcie_us_axi_dma_wr.v")
|
||||
srcs.append("../lib/pcie/rtl/pcie_tag_manager.v")
|
||||
srcs.append("../lib/pcie/rtl/pcie_us_axi_master.v")
|
||||
srcs.append("../lib/pcie/rtl/pcie_us_axi_master_rd.v")
|
||||
srcs.append("../lib/pcie/rtl/pcie_us_axi_master_wr.v")
|
||||
srcs.append("../lib/pcie/rtl/pcie_us_axis_cq_demux.v")
|
||||
srcs.append("../lib/pcie/rtl/pcie_us_cfg.v")
|
||||
srcs.append("../lib/pcie/rtl/pcie_us_msi.v")
|
||||
srcs.append("../lib/pcie/rtl/arbiter.v")
|
||||
srcs.append("../lib/pcie/rtl/priority_encoder.v")
|
||||
srcs.append("../lib/pcie/rtl/pulse_merge.v")
|
||||
srcs.append("%s.v" % testbench)
|
||||
|
||||
src = ' '.join(srcs)
|
||||
|
||||
build_cmd = "iverilog -o %s.vvp %s" % (testbench, src)
|
||||
|
||||
def bench():
|
||||
|
||||
# Parameters
|
||||
AXIS_PCIE_DATA_WIDTH = 512
|
||||
AXIS_PCIE_KEEP_WIDTH = (AXIS_PCIE_DATA_WIDTH/32)
|
||||
AXIS_PCIE_RC_USER_WIDTH = 161
|
||||
AXIS_PCIE_RQ_USER_WIDTH = 137
|
||||
AXIS_PCIE_CQ_USER_WIDTH = 183
|
||||
AXIS_PCIE_CC_USER_WIDTH = 81
|
||||
|
||||
# Inputs
|
||||
clk = Signal(bool(0))
|
||||
rst = Signal(bool(0))
|
||||
current_test = Signal(intbv(0)[8:])
|
||||
|
||||
m_axis_rq_tready = Signal(bool(0))
|
||||
s_axis_rc_tdata = Signal(intbv(0)[AXIS_PCIE_DATA_WIDTH:])
|
||||
s_axis_rc_tkeep = Signal(intbv(0)[AXIS_PCIE_KEEP_WIDTH:])
|
||||
s_axis_rc_tlast = Signal(bool(0))
|
||||
s_axis_rc_tuser = Signal(intbv(0)[AXIS_PCIE_RC_USER_WIDTH:])
|
||||
s_axis_rc_tvalid = Signal(bool(0))
|
||||
s_axis_cq_tdata = Signal(intbv(0)[AXIS_PCIE_DATA_WIDTH:])
|
||||
s_axis_cq_tkeep = Signal(intbv(0)[AXIS_PCIE_KEEP_WIDTH:])
|
||||
s_axis_cq_tlast = Signal(bool(0))
|
||||
s_axis_cq_tuser = Signal(intbv(0)[AXIS_PCIE_CQ_USER_WIDTH:])
|
||||
s_axis_cq_tvalid = Signal(bool(0))
|
||||
m_axis_cc_tready = Signal(bool(0))
|
||||
cfg_max_payload = Signal(intbv(0)[2:])
|
||||
cfg_max_read_req = Signal(intbv(0)[3:])
|
||||
cfg_mgmt_read_data = Signal(intbv(0)[32:])
|
||||
cfg_mgmt_read_write_done = Signal(bool(0))
|
||||
cfg_interrupt_msi_enable = Signal(intbv(0)[4:])
|
||||
cfg_interrupt_msi_mmenable = Signal(intbv(0)[12:])
|
||||
cfg_interrupt_msi_mask_update = Signal(bool(0))
|
||||
cfg_interrupt_msi_data = Signal(intbv(0)[32:])
|
||||
cfg_interrupt_msi_sent = Signal(bool(0))
|
||||
cfg_interrupt_msi_fail = Signal(bool(0))
|
||||
|
||||
# Outputs
|
||||
m_axis_rq_tdata = Signal(intbv(0)[AXIS_PCIE_DATA_WIDTH:])
|
||||
m_axis_rq_tkeep = Signal(intbv(0)[AXIS_PCIE_KEEP_WIDTH:])
|
||||
m_axis_rq_tlast = Signal(bool(0))
|
||||
m_axis_rq_tuser = Signal(intbv(0)[AXIS_PCIE_RQ_USER_WIDTH:])
|
||||
m_axis_rq_tvalid = Signal(bool(0))
|
||||
s_axis_rc_tready = Signal(bool(0))
|
||||
s_axis_cq_tready = Signal(bool(0))
|
||||
m_axis_cc_tdata = Signal(intbv(0)[AXIS_PCIE_DATA_WIDTH:])
|
||||
m_axis_cc_tkeep = Signal(intbv(0)[AXIS_PCIE_KEEP_WIDTH:])
|
||||
m_axis_cc_tlast = Signal(bool(0))
|
||||
m_axis_cc_tuser = Signal(intbv(0)[AXIS_PCIE_CC_USER_WIDTH:])
|
||||
m_axis_cc_tvalid = Signal(bool(0))
|
||||
status_error_cor = Signal(bool(0))
|
||||
status_error_uncor = Signal(bool(0))
|
||||
cfg_mgmt_addr = Signal(intbv(0)[10:])
|
||||
cfg_mgmt_function_number = Signal(intbv(0)[8:])
|
||||
cfg_mgmt_write = Signal(bool(0))
|
||||
cfg_mgmt_write_data = Signal(intbv(0)[32:])
|
||||
cfg_mgmt_byte_enable = Signal(intbv(0)[4:])
|
||||
cfg_mgmt_read = Signal(bool(0))
|
||||
cfg_interrupt_msi_int = Signal(intbv(0)[32:])
|
||||
cfg_interrupt_msi_pending_status = Signal(intbv(0)[32:])
|
||||
cfg_interrupt_msi_select = Signal(intbv(0)[2:])
|
||||
cfg_interrupt_msi_pending_status_function_num = Signal(intbv(0)[2:])
|
||||
cfg_interrupt_msi_pending_status_data_enable = Signal(bool(0))
|
||||
cfg_interrupt_msi_attr = Signal(intbv(0)[3:])
|
||||
cfg_interrupt_msi_tph_present = Signal(bool(0))
|
||||
cfg_interrupt_msi_tph_type = Signal(intbv(0)[2:])
|
||||
cfg_interrupt_msi_tph_st_tag = Signal(intbv(0)[8:])
|
||||
cfg_interrupt_msi_function_number = Signal(intbv(0)[8:])
|
||||
|
||||
# Clock and Reset Interface
|
||||
user_clk=Signal(bool(0))
|
||||
user_reset=Signal(bool(0))
|
||||
sys_clk=Signal(bool(0))
|
||||
sys_reset=Signal(bool(0))
|
||||
|
||||
# PCIe devices
|
||||
rc = pcie.RootComplex()
|
||||
|
||||
mem_base, mem_data = rc.alloc_region(16*1024*1024)
|
||||
|
||||
dev = pcie_usp.UltrascalePlusPCIe()
|
||||
|
||||
dev.pcie_generation = 3
|
||||
dev.pcie_link_width = 16
|
||||
dev.user_clk_frequency = 250e6
|
||||
|
||||
dev.functions[0].msi_multiple_message_capable = 5
|
||||
|
||||
dev.functions[0].configure_bar(0, 4*1024*1024)
|
||||
dev.functions[0].configure_bar(1, 4*1024*1024)
|
||||
|
||||
rc.make_port().connect(dev)
|
||||
|
||||
pcie_logic = dev.create_logic(
|
||||
# Completer reQuest Interface
|
||||
m_axis_cq_tdata=s_axis_cq_tdata,
|
||||
m_axis_cq_tuser=s_axis_cq_tuser,
|
||||
m_axis_cq_tlast=s_axis_cq_tlast,
|
||||
m_axis_cq_tkeep=s_axis_cq_tkeep,
|
||||
m_axis_cq_tvalid=s_axis_cq_tvalid,
|
||||
m_axis_cq_tready=s_axis_cq_tready,
|
||||
#pcie_cq_np_req=pcie_cq_np_req,
|
||||
pcie_cq_np_req=Signal(intbv(1)[2:]),
|
||||
#pcie_cq_np_req_count=pcie_cq_np_req_count,
|
||||
|
||||
# Completer Completion Interface
|
||||
s_axis_cc_tdata=m_axis_cc_tdata,
|
||||
s_axis_cc_tuser=m_axis_cc_tuser,
|
||||
s_axis_cc_tlast=m_axis_cc_tlast,
|
||||
s_axis_cc_tkeep=m_axis_cc_tkeep,
|
||||
s_axis_cc_tvalid=m_axis_cc_tvalid,
|
||||
s_axis_cc_tready=m_axis_cc_tready,
|
||||
|
||||
# Requester reQuest Interface
|
||||
s_axis_rq_tdata=m_axis_rq_tdata,
|
||||
s_axis_rq_tuser=m_axis_rq_tuser,
|
||||
s_axis_rq_tlast=m_axis_rq_tlast,
|
||||
s_axis_rq_tkeep=m_axis_rq_tkeep,
|
||||
s_axis_rq_tvalid=m_axis_rq_tvalid,
|
||||
s_axis_rq_tready=m_axis_rq_tready,
|
||||
#pcie_rq_seq_num0=pcie_rq_seq_num0,
|
||||
#pcie_rq_seq_num_vld0=pcie_rq_seq_num_vld0,
|
||||
#pcie_rq_seq_num1=pcie_rq_seq_num1,
|
||||
#pcie_rq_seq_num_vld1=pcie_rq_seq_num_vld1,
|
||||
#pcie_rq_tag0=pcie_rq_tag0,
|
||||
#pcie_rq_tag1=pcie_rq_tag1,
|
||||
#pcie_rq_tag_av=pcie_rq_tag_av,
|
||||
#pcie_rq_tag_vld0=pcie_rq_tag_vld0,
|
||||
#pcie_rq_tag_vld1=pcie_rq_tag_vld1,
|
||||
|
||||
# Requester Completion Interface
|
||||
m_axis_rc_tdata=s_axis_rc_tdata,
|
||||
m_axis_rc_tuser=s_axis_rc_tuser,
|
||||
m_axis_rc_tlast=s_axis_rc_tlast,
|
||||
m_axis_rc_tkeep=s_axis_rc_tkeep,
|
||||
m_axis_rc_tvalid=s_axis_rc_tvalid,
|
||||
m_axis_rc_tready=s_axis_rc_tready,
|
||||
|
||||
# Transmit Flow Control Interface
|
||||
#pcie_tfc_nph_av=pcie_tfc_nph_av,
|
||||
#pcie_tfc_npd_av=pcie_tfc_npd_av,
|
||||
|
||||
# Configuration Management Interface
|
||||
cfg_mgmt_addr=cfg_mgmt_addr,
|
||||
cfg_mgmt_function_number=cfg_mgmt_function_number,
|
||||
cfg_mgmt_write=cfg_mgmt_write,
|
||||
cfg_mgmt_write_data=cfg_mgmt_write_data,
|
||||
cfg_mgmt_byte_enable=cfg_mgmt_byte_enable,
|
||||
cfg_mgmt_read=cfg_mgmt_read,
|
||||
cfg_mgmt_read_data=cfg_mgmt_read_data,
|
||||
cfg_mgmt_read_write_done=cfg_mgmt_read_write_done,
|
||||
#cfg_mgmt_debug_access=cfg_mgmt_debug_access,
|
||||
|
||||
# Configuration Status Interface
|
||||
#cfg_phy_link_down=cfg_phy_link_down,
|
||||
#cfg_phy_link_status=cfg_phy_link_status,
|
||||
#cfg_negotiated_width=cfg_negotiated_width,
|
||||
#cfg_current_speed=cfg_current_speed,
|
||||
cfg_max_payload=cfg_max_payload,
|
||||
cfg_max_read_req=cfg_max_read_req,
|
||||
#cfg_function_status=cfg_function_status,
|
||||
#cfg_vf_status=cfg_vf_status,
|
||||
#cfg_function_power_state=cfg_function_power_state,
|
||||
#cfg_vf_power_state=cfg_vf_power_state,
|
||||
#cfg_link_power_state=cfg_link_power_state,
|
||||
#cfg_err_cor_out=cfg_err_cor_out,
|
||||
#cfg_err_nonfatal_out=cfg_err_nonfatal_out,
|
||||
#cfg_err_fatal_out=cfg_err_fatal_out,
|
||||
#cfg_local_err_out=cfg_local_err_out,
|
||||
#cfg_local_err_valid=cfg_local_err_valid,
|
||||
#cfg_rx_pm_state=cfg_rx_pm_state,
|
||||
#cfg_tx_pm_state=cfg_tx_pm_state,
|
||||
#cfg_ltssm_state=cfg_ltssm_state,
|
||||
#cfg_rcb_status=cfg_rcb_status,
|
||||
#cfg_obff_enable=cfg_obff_enable,
|
||||
#cfg_pl_status_change=cfg_pl_status_change,
|
||||
#cfg_tph_requester_enable=cfg_tph_requester_enable,
|
||||
#cfg_tph_st_mode=cfg_tph_st_mode,
|
||||
#cfg_vf_tph_requester_enable=cfg_vf_tph_requester_enable,
|
||||
#cfg_vf_tph_st_mode=cfg_vf_tph_st_mode,
|
||||
|
||||
# Configuration Received Message Interface
|
||||
#cfg_msg_received=cfg_msg_received,
|
||||
#cfg_msg_received_data=cfg_msg_received_data,
|
||||
#cfg_msg_received_type=cfg_msg_received_type,
|
||||
|
||||
# Configuration Transmit Message Interface
|
||||
#cfg_msg_transmit=cfg_msg_transmit,
|
||||
#cfg_msg_transmit_type=cfg_msg_transmit_type,
|
||||
#cfg_msg_transmit_data=cfg_msg_transmit_data,
|
||||
#cfg_msg_transmit_done=cfg_msg_transmit_done,
|
||||
|
||||
# Configuration Flow Control Interface
|
||||
#cfg_fc_ph=cfg_fc_ph,
|
||||
#cfg_fc_pd=cfg_fc_pd,
|
||||
#cfg_fc_nph=cfg_fc_nph,
|
||||
#cfg_fc_npd=cfg_fc_npd,
|
||||
#cfg_fc_cplh=cfg_fc_cplh,
|
||||
#cfg_fc_cpld=cfg_fc_cpld,
|
||||
#cfg_fc_sel=cfg_fc_sel,
|
||||
|
||||
# Configuration Control Interface
|
||||
#cfg_hot_reset_in=cfg_hot_reset_in,
|
||||
#cfg_hot_reset_out=cfg_hot_reset_out,
|
||||
#cfg_config_space_enable=cfg_config_space_enable,
|
||||
#cfg_dsn=cfg_dsn,
|
||||
#cfg_ds_port_number=cfg_ds_port_number,
|
||||
#cfg_ds_bus_number=cfg_ds_bus_number,
|
||||
#cfg_ds_device_number=cfg_ds_device_number,
|
||||
#cfg_ds_function_number=cfg_ds_function_number,
|
||||
#cfg_power_state_change_ack=cfg_power_state_change_ack,
|
||||
#cfg_power_state_change_interrupt=cfg_power_state_change_interrupt,
|
||||
cfg_err_cor_in=status_error_cor,
|
||||
cfg_err_uncor_in=status_error_uncor,
|
||||
#cfg_flr_done=cfg_flr_done,
|
||||
#cfg_vf_flr_done=cfg_vf_flr_done,
|
||||
#cfg_flr_in_process=cfg_flr_in_process,
|
||||
#cfg_vf_flr_in_process=cfg_vf_flr_in_process,
|
||||
#cfg_req_pm_transition_l23_ready=cfg_req_pm_transition_l23_ready,
|
||||
#cfg_link_training_enable=cfg_link_training_enable,
|
||||
|
||||
# Configuration Interrupt Controller Interface
|
||||
#cfg_interrupt_int=cfg_interrupt_int,
|
||||
#cfg_interrupt_sent=cfg_interrupt_sent,
|
||||
#cfg_interrupt_pending=cfg_interrupt_pending,
|
||||
cfg_interrupt_msi_enable=cfg_interrupt_msi_enable,
|
||||
cfg_interrupt_msi_mmenable=cfg_interrupt_msi_mmenable,
|
||||
cfg_interrupt_msi_mask_update=cfg_interrupt_msi_mask_update,
|
||||
cfg_interrupt_msi_data=cfg_interrupt_msi_data,
|
||||
cfg_interrupt_msi_select=cfg_interrupt_msi_select,
|
||||
cfg_interrupt_msi_int=cfg_interrupt_msi_int,
|
||||
cfg_interrupt_msi_pending_status=cfg_interrupt_msi_pending_status,
|
||||
cfg_interrupt_msi_pending_status_data_enable=cfg_interrupt_msi_pending_status_data_enable,
|
||||
cfg_interrupt_msi_pending_status_function_num=cfg_interrupt_msi_pending_status_function_num,
|
||||
cfg_interrupt_msi_sent=cfg_interrupt_msi_sent,
|
||||
cfg_interrupt_msi_fail=cfg_interrupt_msi_fail,
|
||||
#cfg_interrupt_msix_enable=cfg_interrupt_msix_enable,
|
||||
#cfg_interrupt_msix_mask=cfg_interrupt_msix_mask,
|
||||
#cfg_interrupt_msix_vf_enable=cfg_interrupt_msix_vf_enable,
|
||||
#cfg_interrupt_msix_vf_mask=cfg_interrupt_msix_vf_mask,
|
||||
#cfg_interrupt_msix_address=cfg_interrupt_msix_address,
|
||||
#cfg_interrupt_msix_data=cfg_interrupt_msix_data,
|
||||
#cfg_interrupt_msix_int=cfg_interrupt_msix_int,
|
||||
#cfg_interrupt_msix_vec_pending=cfg_interrupt_msix_vec_pending,
|
||||
#cfg_interrupt_msix_vec_pending_status=cfg_interrupt_msix_vec_pending_status,
|
||||
cfg_interrupt_msi_attr=cfg_interrupt_msi_attr,
|
||||
cfg_interrupt_msi_tph_present=cfg_interrupt_msi_tph_present,
|
||||
cfg_interrupt_msi_tph_type=cfg_interrupt_msi_tph_type,
|
||||
cfg_interrupt_msi_tph_st_tag=cfg_interrupt_msi_tph_st_tag,
|
||||
cfg_interrupt_msi_function_number=cfg_interrupt_msi_function_number,
|
||||
|
||||
# Configuration Extend Interface
|
||||
#cfg_ext_read_received=cfg_ext_read_received,
|
||||
#cfg_ext_write_received=cfg_ext_write_received,
|
||||
#cfg_ext_register_number=cfg_ext_register_number,
|
||||
#cfg_ext_function_number=cfg_ext_function_number,
|
||||
#cfg_ext_write_data=cfg_ext_write_data,
|
||||
#cfg_ext_write_byte_enable=cfg_ext_write_byte_enable,
|
||||
#cfg_ext_read_data=cfg_ext_read_data,
|
||||
#cfg_ext_read_data_valid=cfg_ext_read_data_valid,
|
||||
|
||||
# Clock and Reset Interface
|
||||
user_clk=user_clk,
|
||||
user_reset=user_reset,
|
||||
#user_lnk_up=user_lnk_up,
|
||||
sys_clk=sys_clk,
|
||||
sys_clk_gt=sys_clk,
|
||||
sys_reset=sys_reset,
|
||||
#phy_rdy_out=phy_rdy_out
|
||||
)
|
||||
|
||||
# DUT
|
||||
if os.system(build_cmd):
|
||||
raise Exception("Error running build command")
|
||||
|
||||
dut = Cosimulation(
|
||||
"vvp -m myhdl %s.vvp -lxt2" % testbench,
|
||||
clk=user_clk,
|
||||
rst=user_reset,
|
||||
current_test=current_test,
|
||||
m_axis_rq_tdata=m_axis_rq_tdata,
|
||||
m_axis_rq_tkeep=m_axis_rq_tkeep,
|
||||
m_axis_rq_tlast=m_axis_rq_tlast,
|
||||
m_axis_rq_tready=m_axis_rq_tready,
|
||||
m_axis_rq_tuser=m_axis_rq_tuser,
|
||||
m_axis_rq_tvalid=m_axis_rq_tvalid,
|
||||
s_axis_rc_tdata=s_axis_rc_tdata,
|
||||
s_axis_rc_tkeep=s_axis_rc_tkeep,
|
||||
s_axis_rc_tlast=s_axis_rc_tlast,
|
||||
s_axis_rc_tready=s_axis_rc_tready,
|
||||
s_axis_rc_tuser=s_axis_rc_tuser,
|
||||
s_axis_rc_tvalid=s_axis_rc_tvalid,
|
||||
s_axis_cq_tdata=s_axis_cq_tdata,
|
||||
s_axis_cq_tkeep=s_axis_cq_tkeep,
|
||||
s_axis_cq_tlast=s_axis_cq_tlast,
|
||||
s_axis_cq_tready=s_axis_cq_tready,
|
||||
s_axis_cq_tuser=s_axis_cq_tuser,
|
||||
s_axis_cq_tvalid=s_axis_cq_tvalid,
|
||||
m_axis_cc_tdata=m_axis_cc_tdata,
|
||||
m_axis_cc_tkeep=m_axis_cc_tkeep,
|
||||
m_axis_cc_tlast=m_axis_cc_tlast,
|
||||
m_axis_cc_tready=m_axis_cc_tready,
|
||||
m_axis_cc_tuser=m_axis_cc_tuser,
|
||||
m_axis_cc_tvalid=m_axis_cc_tvalid,
|
||||
cfg_max_payload=cfg_max_payload,
|
||||
cfg_max_read_req=cfg_max_read_req,
|
||||
cfg_mgmt_addr=cfg_mgmt_addr,
|
||||
cfg_mgmt_function_number=cfg_mgmt_function_number,
|
||||
cfg_mgmt_write=cfg_mgmt_write,
|
||||
cfg_mgmt_write_data=cfg_mgmt_write_data,
|
||||
cfg_mgmt_byte_enable=cfg_mgmt_byte_enable,
|
||||
cfg_mgmt_read=cfg_mgmt_read,
|
||||
cfg_mgmt_read_data=cfg_mgmt_read_data,
|
||||
cfg_mgmt_read_write_done=cfg_mgmt_read_write_done,
|
||||
cfg_interrupt_msi_enable=cfg_interrupt_msi_enable,
|
||||
cfg_interrupt_msi_int=cfg_interrupt_msi_int,
|
||||
cfg_interrupt_msi_sent=cfg_interrupt_msi_sent,
|
||||
cfg_interrupt_msi_fail=cfg_interrupt_msi_fail,
|
||||
cfg_interrupt_msi_mmenable=cfg_interrupt_msi_mmenable,
|
||||
cfg_interrupt_msi_pending_status=cfg_interrupt_msi_pending_status,
|
||||
cfg_interrupt_msi_mask_update=cfg_interrupt_msi_mask_update,
|
||||
cfg_interrupt_msi_select=cfg_interrupt_msi_select,
|
||||
cfg_interrupt_msi_data=cfg_interrupt_msi_data,
|
||||
cfg_interrupt_msi_pending_status_function_num=cfg_interrupt_msi_pending_status_function_num,
|
||||
cfg_interrupt_msi_pending_status_data_enable=cfg_interrupt_msi_pending_status_data_enable,
|
||||
cfg_interrupt_msi_attr=cfg_interrupt_msi_attr,
|
||||
cfg_interrupt_msi_tph_present=cfg_interrupt_msi_tph_present,
|
||||
cfg_interrupt_msi_tph_type=cfg_interrupt_msi_tph_type,
|
||||
cfg_interrupt_msi_tph_st_tag=cfg_interrupt_msi_tph_st_tag,
|
||||
cfg_interrupt_msi_function_number=cfg_interrupt_msi_function_number,
|
||||
status_error_cor=status_error_cor,
|
||||
status_error_uncor=status_error_uncor
|
||||
)
|
||||
|
||||
@always(delay(5))
|
||||
def clkgen():
|
||||
clk.next = not clk
|
||||
|
||||
@always_comb
|
||||
def clk_logic():
|
||||
sys_clk.next = clk
|
||||
sys_reset.next = not rst
|
||||
|
||||
@instance
|
||||
def check():
|
||||
yield delay(100)
|
||||
yield clk.posedge
|
||||
rst.next = 1
|
||||
yield clk.posedge
|
||||
rst.next = 0
|
||||
yield clk.posedge
|
||||
yield delay(100)
|
||||
yield clk.posedge
|
||||
|
||||
# testbench stimulus
|
||||
|
||||
current_tag = 1
|
||||
|
||||
yield clk.posedge
|
||||
print("test 1: enumeration")
|
||||
current_test.next = 1
|
||||
|
||||
yield rc.enumerate(enable_bus_mastering=True, configure_msi=True)
|
||||
|
||||
dev_pf0_bar0 = dev.functions[0].bar[0] & 0xfffffffc
|
||||
dev_pf0_bar1 = dev.functions[0].bar[1] & 0xfffffffc
|
||||
|
||||
yield delay(100)
|
||||
|
||||
yield clk.posedge
|
||||
print("test 2: memory write to bar 1")
|
||||
current_test.next = 2
|
||||
|
||||
yield rc.mem_write(dev_pf0_bar1, b'\x11\x22\x33\x44')
|
||||
|
||||
yield delay(100)
|
||||
|
||||
yield clk.posedge
|
||||
print("test 3: memory read from bar 1")
|
||||
current_test.next = 3
|
||||
|
||||
val = yield from rc.mem_read(dev_pf0_bar1, 4, 1000)
|
||||
print(val)
|
||||
assert val == b'\x11\x22\x33\x44'
|
||||
|
||||
yield delay(100)
|
||||
|
||||
yield clk.posedge
|
||||
print("test 4: test DMA")
|
||||
current_test.next = 4
|
||||
|
||||
# write packet data
|
||||
mem_data[0:1024] = bytearray([x%256 for x in range(1024)])
|
||||
|
||||
# enable DMA
|
||||
yield rc.mem_write(dev_pf0_bar0+0x100000, struct.pack('<L', 1))
|
||||
|
||||
# write pcie read descriptor
|
||||
yield rc.mem_write(dev_pf0_bar0+0x100100, struct.pack('<L', (mem_base+0x0000) & 0xffffffff))
|
||||
yield rc.mem_write(dev_pf0_bar0+0x100104, struct.pack('<L', (mem_base+0x0000 >> 32) & 0xffffffff))
|
||||
yield rc.mem_write(dev_pf0_bar0+0x100108, struct.pack('<L', (0x100) & 0xffffffff))
|
||||
yield rc.mem_write(dev_pf0_bar0+0x10010C, struct.pack('<L', (0x100 >> 32) & 0xffffffff))
|
||||
yield rc.mem_write(dev_pf0_bar0+0x100110, struct.pack('<L', 0x400))
|
||||
yield rc.mem_write(dev_pf0_bar0+0x100114, struct.pack('<L', 0xAA))
|
||||
|
||||
yield delay(2000)
|
||||
|
||||
# read status
|
||||
val = yield from rc.mem_read(dev_pf0_bar0+0x100118, 4)
|
||||
print(val)
|
||||
|
||||
# write pcie write descriptor
|
||||
yield rc.mem_write(dev_pf0_bar0+0x100200, struct.pack('<L', (mem_base+0x1000) & 0xffffffff))
|
||||
yield rc.mem_write(dev_pf0_bar0+0x100204, struct.pack('<L', (mem_base+0x1000 >> 32) & 0xffffffff))
|
||||
yield rc.mem_write(dev_pf0_bar0+0x100208, struct.pack('<L', (0x100) & 0xffffffff))
|
||||
yield rc.mem_write(dev_pf0_bar0+0x10020C, struct.pack('<L', (0x100 >> 32) & 0xffffffff))
|
||||
yield rc.mem_write(dev_pf0_bar0+0x100210, struct.pack('<L', 0x400))
|
||||
yield rc.mem_write(dev_pf0_bar0+0x100214, struct.pack('<L', 0x55))
|
||||
|
||||
yield delay(2000)
|
||||
|
||||
# read status
|
||||
val = yield from rc.mem_read(dev_pf0_bar0+0x100218, 4)
|
||||
print(val)
|
||||
|
||||
data = mem_data[0x1000:(0x1000)+64]
|
||||
for i in range(0, len(data), 16):
|
||||
print(" ".join(("{:02x}".format(c) for c in bytearray(data[i:i+16]))))
|
||||
|
||||
assert mem_data[0:1024] == mem_data[0x1000:0x1000+1024]
|
||||
|
||||
yield delay(100)
|
||||
|
||||
raise StopSimulation
|
||||
|
||||
return instances()
|
||||
|
||||
def test_bench():
|
||||
sim = Simulation(bench())
|
||||
sim.run()
|
||||
|
||||
if __name__ == '__main__':
|
||||
print("Running test...")
|
||||
test_bench()
|
@ -1,234 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2018 Alex Forencich
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
// Language: Verilog 2001
|
||||
|
||||
`timescale 1ns / 1ps
|
||||
|
||||
/*
|
||||
* Testbench for fpga_core
|
||||
*/
|
||||
module test_fpga_core;
|
||||
|
||||
// Parameters
|
||||
parameter AXIS_PCIE_DATA_WIDTH = 512;
|
||||
parameter AXIS_PCIE_KEEP_WIDTH = (AXIS_PCIE_DATA_WIDTH/32);
|
||||
parameter AXIS_PCIE_RC_USER_WIDTH = 161;
|
||||
parameter AXIS_PCIE_RQ_USER_WIDTH = 137;
|
||||
parameter AXIS_PCIE_CQ_USER_WIDTH = 183;
|
||||
parameter AXIS_PCIE_CC_USER_WIDTH = 81;
|
||||
|
||||
// Inputs
|
||||
reg clk = 0;
|
||||
reg rst = 0;
|
||||
reg [7:0] current_test = 0;
|
||||
|
||||
reg m_axis_rq_tready = 0;
|
||||
reg [AXIS_PCIE_DATA_WIDTH-1:0] s_axis_rc_tdata = 0;
|
||||
reg [AXIS_PCIE_KEEP_WIDTH-1:0] s_axis_rc_tkeep = 0;
|
||||
reg s_axis_rc_tlast = 0;
|
||||
reg [AXIS_PCIE_RC_USER_WIDTH-1:0] s_axis_rc_tuser = 0;
|
||||
reg s_axis_rc_tvalid = 0;
|
||||
reg [AXIS_PCIE_DATA_WIDTH-1:0] s_axis_cq_tdata = 0;
|
||||
reg [AXIS_PCIE_KEEP_WIDTH-1:0] s_axis_cq_tkeep = 0;
|
||||
reg s_axis_cq_tlast = 0;
|
||||
reg [AXIS_PCIE_CQ_USER_WIDTH-1:0] s_axis_cq_tuser = 0;
|
||||
reg s_axis_cq_tvalid = 0;
|
||||
reg m_axis_cc_tready = 0;
|
||||
reg [2:0] cfg_max_payload = 0;
|
||||
reg [2:0] cfg_max_read_req = 0;
|
||||
reg [31:0] cfg_mgmt_read_data = 0;
|
||||
reg cfg_mgmt_read_write_done = 0;
|
||||
reg [3:0] cfg_interrupt_msi_enable = 0;
|
||||
reg [11:0] cfg_interrupt_msi_mmenable = 0;
|
||||
reg cfg_interrupt_msi_mask_update = 0;
|
||||
reg [31:0] cfg_interrupt_msi_data = 0;
|
||||
reg cfg_interrupt_msi_sent = 0;
|
||||
reg cfg_interrupt_msi_fail = 0;
|
||||
|
||||
// Outputs
|
||||
wire [AXIS_PCIE_DATA_WIDTH-1:0] m_axis_rq_tdata;
|
||||
wire [AXIS_PCIE_KEEP_WIDTH-1:0] m_axis_rq_tkeep;
|
||||
wire m_axis_rq_tlast;
|
||||
wire [AXIS_PCIE_RQ_USER_WIDTH-1:0] m_axis_rq_tuser;
|
||||
wire m_axis_rq_tvalid;
|
||||
wire s_axis_rc_tready;
|
||||
wire s_axis_cq_tready;
|
||||
wire [AXIS_PCIE_DATA_WIDTH-1:0] m_axis_cc_tdata;
|
||||
wire [AXIS_PCIE_KEEP_WIDTH-1:0] m_axis_cc_tkeep;
|
||||
wire m_axis_cc_tlast;
|
||||
wire [AXIS_PCIE_CC_USER_WIDTH-1:0] m_axis_cc_tuser;
|
||||
wire m_axis_cc_tvalid;
|
||||
wire [9:0] cfg_mgmt_addr;
|
||||
wire [7:0] cfg_mgmt_function_number;
|
||||
wire cfg_mgmt_write;
|
||||
wire [31:0] cfg_mgmt_write_data;
|
||||
wire [3:0] cfg_mgmt_byte_enable;
|
||||
wire cfg_mgmt_read;
|
||||
wire [3:0] cfg_interrupt_msi_select;
|
||||
wire [31:0] cfg_interrupt_msi_int;
|
||||
wire [31:0] cfg_interrupt_msi_pending_status;
|
||||
wire cfg_interrupt_msi_pending_status_data_enable;
|
||||
wire [3:0] cfg_interrupt_msi_pending_status_function_num;
|
||||
wire [2:0] cfg_interrupt_msi_attr;
|
||||
wire cfg_interrupt_msi_tph_present;
|
||||
wire [1:0] cfg_interrupt_msi_tph_type;
|
||||
wire [8:0] cfg_interrupt_msi_tph_st_tag;
|
||||
wire [3:0] cfg_interrupt_msi_function_number;
|
||||
wire status_error_cor;
|
||||
wire status_error_uncor;
|
||||
|
||||
initial begin
|
||||
// myhdl integration
|
||||
$from_myhdl(
|
||||
clk,
|
||||
rst,
|
||||
current_test,
|
||||
m_axis_rq_tready,
|
||||
s_axis_rc_tdata,
|
||||
s_axis_rc_tkeep,
|
||||
s_axis_rc_tlast,
|
||||
s_axis_rc_tuser,
|
||||
s_axis_rc_tvalid,
|
||||
s_axis_cq_tdata,
|
||||
s_axis_cq_tkeep,
|
||||
s_axis_cq_tlast,
|
||||
s_axis_cq_tuser,
|
||||
s_axis_cq_tvalid,
|
||||
m_axis_cc_tready,
|
||||
cfg_max_payload,
|
||||
cfg_max_read_req,
|
||||
cfg_mgmt_read_data,
|
||||
cfg_mgmt_read_write_done,
|
||||
cfg_interrupt_msi_enable,
|
||||
cfg_interrupt_msi_mmenable,
|
||||
cfg_interrupt_msi_mask_update,
|
||||
cfg_interrupt_msi_data,
|
||||
cfg_interrupt_msi_sent,
|
||||
cfg_interrupt_msi_fail
|
||||
);
|
||||
$to_myhdl(
|
||||
m_axis_rq_tdata,
|
||||
m_axis_rq_tkeep,
|
||||
m_axis_rq_tlast,
|
||||
m_axis_rq_tuser,
|
||||
m_axis_rq_tvalid,
|
||||
s_axis_rc_tready,
|
||||
s_axis_cq_tready,
|
||||
m_axis_cc_tdata,
|
||||
m_axis_cc_tkeep,
|
||||
m_axis_cc_tlast,
|
||||
m_axis_cc_tuser,
|
||||
m_axis_cc_tvalid,
|
||||
cfg_mgmt_addr,
|
||||
cfg_mgmt_function_number,
|
||||
cfg_mgmt_write,
|
||||
cfg_mgmt_write_data,
|
||||
cfg_mgmt_byte_enable,
|
||||
cfg_mgmt_read,
|
||||
cfg_interrupt_msi_select,
|
||||
cfg_interrupt_msi_int,
|
||||
cfg_interrupt_msi_pending_status,
|
||||
cfg_interrupt_msi_pending_status_data_enable,
|
||||
cfg_interrupt_msi_pending_status_function_num,
|
||||
cfg_interrupt_msi_attr,
|
||||
cfg_interrupt_msi_tph_present,
|
||||
cfg_interrupt_msi_tph_type,
|
||||
cfg_interrupt_msi_tph_st_tag,
|
||||
cfg_interrupt_msi_function_number,
|
||||
status_error_cor,
|
||||
status_error_uncor
|
||||
);
|
||||
|
||||
// dump file
|
||||
$dumpfile("test_fpga_core.lxt");
|
||||
$dumpvars(0, test_fpga_core);
|
||||
end
|
||||
|
||||
fpga_core #(
|
||||
.AXIS_PCIE_DATA_WIDTH(AXIS_PCIE_DATA_WIDTH),
|
||||
.AXIS_PCIE_KEEP_WIDTH(AXIS_PCIE_KEEP_WIDTH),
|
||||
.AXIS_PCIE_RC_USER_WIDTH(AXIS_PCIE_RC_USER_WIDTH),
|
||||
.AXIS_PCIE_RQ_USER_WIDTH(AXIS_PCIE_RQ_USER_WIDTH),
|
||||
.AXIS_PCIE_CQ_USER_WIDTH(AXIS_PCIE_CQ_USER_WIDTH),
|
||||
.AXIS_PCIE_CC_USER_WIDTH(AXIS_PCIE_CC_USER_WIDTH)
|
||||
)
|
||||
UUT (
|
||||
.clk(clk),
|
||||
.rst(rst),
|
||||
.m_axis_rq_tdata(m_axis_rq_tdata),
|
||||
.m_axis_rq_tkeep(m_axis_rq_tkeep),
|
||||
.m_axis_rq_tlast(m_axis_rq_tlast),
|
||||
.m_axis_rq_tready(m_axis_rq_tready),
|
||||
.m_axis_rq_tuser(m_axis_rq_tuser),
|
||||
.m_axis_rq_tvalid(m_axis_rq_tvalid),
|
||||
.s_axis_rc_tdata(s_axis_rc_tdata),
|
||||
.s_axis_rc_tkeep(s_axis_rc_tkeep),
|
||||
.s_axis_rc_tlast(s_axis_rc_tlast),
|
||||
.s_axis_rc_tready(s_axis_rc_tready),
|
||||
.s_axis_rc_tuser(s_axis_rc_tuser),
|
||||
.s_axis_rc_tvalid(s_axis_rc_tvalid),
|
||||
.s_axis_cq_tdata(s_axis_cq_tdata),
|
||||
.s_axis_cq_tkeep(s_axis_cq_tkeep),
|
||||
.s_axis_cq_tlast(s_axis_cq_tlast),
|
||||
.s_axis_cq_tready(s_axis_cq_tready),
|
||||
.s_axis_cq_tuser(s_axis_cq_tuser),
|
||||
.s_axis_cq_tvalid(s_axis_cq_tvalid),
|
||||
.m_axis_cc_tdata(m_axis_cc_tdata),
|
||||
.m_axis_cc_tkeep(m_axis_cc_tkeep),
|
||||
.m_axis_cc_tlast(m_axis_cc_tlast),
|
||||
.m_axis_cc_tready(m_axis_cc_tready),
|
||||
.m_axis_cc_tuser(m_axis_cc_tuser),
|
||||
.m_axis_cc_tvalid(m_axis_cc_tvalid),
|
||||
.cfg_max_payload(cfg_max_payload),
|
||||
.cfg_max_read_req(cfg_max_read_req),
|
||||
.cfg_mgmt_addr(cfg_mgmt_addr),
|
||||
.cfg_mgmt_function_number(cfg_mgmt_function_number),
|
||||
.cfg_mgmt_write(cfg_mgmt_write),
|
||||
.cfg_mgmt_write_data(cfg_mgmt_write_data),
|
||||
.cfg_mgmt_byte_enable(cfg_mgmt_byte_enable),
|
||||
.cfg_mgmt_read(cfg_mgmt_read),
|
||||
.cfg_mgmt_read_data(cfg_mgmt_read_data),
|
||||
.cfg_mgmt_read_write_done(cfg_mgmt_read_write_done),
|
||||
.cfg_interrupt_msi_enable(cfg_interrupt_msi_enable),
|
||||
.cfg_interrupt_msi_mmenable(cfg_interrupt_msi_mmenable),
|
||||
.cfg_interrupt_msi_mask_update(cfg_interrupt_msi_mask_update),
|
||||
.cfg_interrupt_msi_data(cfg_interrupt_msi_data),
|
||||
.cfg_interrupt_msi_select(cfg_interrupt_msi_select),
|
||||
.cfg_interrupt_msi_int(cfg_interrupt_msi_int),
|
||||
.cfg_interrupt_msi_pending_status(cfg_interrupt_msi_pending_status),
|
||||
.cfg_interrupt_msi_pending_status_data_enable(cfg_interrupt_msi_pending_status_data_enable),
|
||||
.cfg_interrupt_msi_pending_status_function_num(cfg_interrupt_msi_pending_status_function_num),
|
||||
.cfg_interrupt_msi_sent(cfg_interrupt_msi_sent),
|
||||
.cfg_interrupt_msi_fail(cfg_interrupt_msi_fail),
|
||||
.cfg_interrupt_msi_attr(cfg_interrupt_msi_attr),
|
||||
.cfg_interrupt_msi_tph_present(cfg_interrupt_msi_tph_present),
|
||||
.cfg_interrupt_msi_tph_type(cfg_interrupt_msi_tph_type),
|
||||
.cfg_interrupt_msi_tph_st_tag(cfg_interrupt_msi_tph_st_tag),
|
||||
.cfg_interrupt_msi_function_number(cfg_interrupt_msi_function_number),
|
||||
.status_error_cor(status_error_cor),
|
||||
.status_error_uncor(status_error_uncor)
|
||||
);
|
||||
|
||||
endmodule
|
@ -1 +0,0 @@
|
||||
../lib/pcie/tb/axis_ep.py
|
107
example/ExaNIC_X10/fpga_axi/tb/fpga_core/Makefile
Normal file
107
example/ExaNIC_X10/fpga_axi/tb/fpga_core/Makefile
Normal file
@ -0,0 +1,107 @@
|
||||
# Copyright (c) 2020 Alex Forencich
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in
|
||||
# all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
# THE SOFTWARE.
|
||||
|
||||
TOPLEVEL_LANG = verilog
|
||||
|
||||
SIM ?= icarus
|
||||
WAVES ?= 0
|
||||
|
||||
COCOTB_HDL_TIMEUNIT = 1ns
|
||||
COCOTB_HDL_TIMEPRECISION = 1ps
|
||||
|
||||
DUT = fpga_core
|
||||
TOPLEVEL = $(DUT)
|
||||
MODULE = test_$(DUT)
|
||||
VERILOG_SOURCES += ../../rtl/$(DUT).v
|
||||
VERILOG_SOURCES += ../../rtl/axi_ram.v
|
||||
VERILOG_SOURCES += ../../rtl/axis_register.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/axis_arb_mux.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_axil_master.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_axi_dma.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_axi_dma_rd.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_axi_dma_wr.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_tag_manager.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_axi_master.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_axi_master_rd.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_axi_master_wr.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_axis_cq_demux.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_cfg.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_msi.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/arbiter.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/priority_encoder.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pulse_merge.v
|
||||
|
||||
# module parameters
|
||||
export PARAM_AXIS_PCIE_DATA_WIDTH ?= 256
|
||||
export PARAM_AXIS_PCIE_KEEP_WIDTH ?= $(shell expr $(PARAM_AXIS_PCIE_DATA_WIDTH) / 32 )
|
||||
export PARAM_AXIS_PCIE_RQ_USER_WIDTH ?= 60
|
||||
export PARAM_AXIS_PCIE_RC_USER_WIDTH ?= 75
|
||||
export PARAM_AXIS_PCIE_CQ_USER_WIDTH ?= 85
|
||||
export PARAM_AXIS_PCIE_CC_USER_WIDTH ?= 33
|
||||
export PARAM_RQ_SEQ_NUM_WIDTH ?= 4
|
||||
|
||||
SIM_BUILD ?= sim_build_$(MODULE)
|
||||
|
||||
ifeq ($(SIM), icarus)
|
||||
PLUSARGS += -fst
|
||||
|
||||
COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_DATA_WIDTH=$(PARAM_AXIS_PCIE_DATA_WIDTH)
|
||||
COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_KEEP_WIDTH=$(PARAM_AXIS_PCIE_KEEP_WIDTH)
|
||||
COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_RQ_USER_WIDTH=$(PARAM_AXIS_PCIE_RQ_USER_WIDTH)
|
||||
COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_RC_USER_WIDTH=$(PARAM_AXIS_PCIE_RC_USER_WIDTH)
|
||||
COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_CQ_USER_WIDTH=$(PARAM_AXIS_PCIE_CQ_USER_WIDTH)
|
||||
COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_CC_USER_WIDTH=$(PARAM_AXIS_PCIE_CC_USER_WIDTH)
|
||||
COMPILE_ARGS += -P $(TOPLEVEL).RQ_SEQ_NUM_WIDTH=$(PARAM_RQ_SEQ_NUM_WIDTH)
|
||||
|
||||
ifeq ($(WAVES), 1)
|
||||
VERILOG_SOURCES += iverilog_dump.v
|
||||
COMPILE_ARGS += -s iverilog_dump
|
||||
endif
|
||||
else ifeq ($(SIM), verilator)
|
||||
COMPILE_ARGS += -Wno-SELRANGE -Wno-WIDTH
|
||||
|
||||
COMPILE_ARGS += -GAXIS_PCIE_DATA_WIDTH=$(PARAM_AXIS_PCIE_DATA_WIDTH)
|
||||
COMPILE_ARGS += -GAXIS_PCIE_KEEP_WIDTH=$(PARAM_AXIS_PCIE_KEEP_WIDTH)
|
||||
COMPILE_ARGS += -GAXIS_PCIE_RQ_USER_WIDTH=$(PARAM_AXIS_PCIE_RQ_USER_WIDTH)
|
||||
COMPILE_ARGS += -GAXIS_PCIE_RC_USER_WIDTH=$(PARAM_AXIS_PCIE_RC_USER_WIDTH)
|
||||
COMPILE_ARGS += -GAXIS_PCIE_CQ_USER_WIDTH=$(PARAM_AXIS_PCIE_CQ_USER_WIDTH)
|
||||
COMPILE_ARGS += -GAXIS_PCIE_CC_USER_WIDTH=$(PARAM_AXIS_PCIE_CC_USER_WIDTH)
|
||||
COMPILE_ARGS += -GRQ_SEQ_NUM_WIDTH=$(PARAM_RQ_SEQ_NUM_WIDTH)
|
||||
|
||||
ifeq ($(WAVES), 1)
|
||||
COMPILE_ARGS += --trace-fst
|
||||
endif
|
||||
endif
|
||||
|
||||
iverilog_dump.v:
|
||||
echo 'module iverilog_dump();' > $@
|
||||
echo 'initial begin' >> $@
|
||||
echo ' $$dumpfile("$(TOPLEVEL).fst");' >> $@
|
||||
echo ' $$dumpvars(0, $(TOPLEVEL));' >> $@
|
||||
echo 'end' >> $@
|
||||
echo 'endmodule' >> $@
|
||||
|
||||
clean::
|
||||
@rm -rf sim_build_*
|
||||
@rm -rf iverilog_dump.v
|
||||
@rm -rf dump.fst $(TOPLEVEL).fst
|
||||
|
||||
include $(shell cocotb-config --makefiles)/Makefile.sim
|
||||
|
376
example/ExaNIC_X10/fpga_axi/tb/fpga_core/test_fpga_core.py
Normal file
376
example/ExaNIC_X10/fpga_axi/tb/fpga_core/test_fpga_core.py
Normal file
@ -0,0 +1,376 @@
|
||||
"""
|
||||
|
||||
Copyright (c) 2020 Alex Forencich
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
"""
|
||||
|
||||
import logging
|
||||
import os
|
||||
|
||||
import cocotb_test.simulator
|
||||
|
||||
import cocotb
|
||||
from cocotb.log import SimLog
|
||||
from cocotb.triggers import RisingEdge, FallingEdge, Timer
|
||||
|
||||
from cocotbext.pcie.core import RootComplex
|
||||
from cocotbext.pcie.xilinx.us import UltraScalePcieDevice
|
||||
from cocotbext.axi.utils import hexdump_str
|
||||
|
||||
|
||||
class TB(object):
|
||||
def __init__(self, dut):
|
||||
self.dut = dut
|
||||
|
||||
self.log = SimLog("cocotb.tb")
|
||||
self.log.setLevel(logging.DEBUG)
|
||||
|
||||
# PCIe
|
||||
self.rc = RootComplex()
|
||||
|
||||
self.dev = UltraScalePcieDevice(
|
||||
# configuration options
|
||||
pcie_generation=3,
|
||||
pcie_link_width=8,
|
||||
user_clk_frequency=250e6,
|
||||
alignment="dword",
|
||||
straddle=False,
|
||||
enable_pf1=False,
|
||||
enable_client_tag=True,
|
||||
enable_extended_tag=True,
|
||||
enable_parity=False,
|
||||
enable_rx_msg_interface=False,
|
||||
enable_sriov=False,
|
||||
enable_extended_configuration=False,
|
||||
|
||||
enable_pf0_msi=True,
|
||||
enable_pf1_msi=False,
|
||||
|
||||
# signals
|
||||
# Clock and Reset Interface
|
||||
user_clk=dut.clk,
|
||||
user_reset=dut.rst,
|
||||
# user_lnk_up
|
||||
# sys_clk
|
||||
# sys_clk_gt
|
||||
# sys_reset
|
||||
# phy_rdy_out
|
||||
|
||||
# Requester reQuest Interface
|
||||
rq_entity=dut,
|
||||
rq_name="m_axis_rq",
|
||||
# pcie_rq_seq_num0=dut.s_axis_rq_seq_num_0,
|
||||
# pcie_rq_seq_num_vld0=dut.s_axis_rq_seq_num_valid_0,
|
||||
# pcie_rq_seq_num1=dut.s_axis_rq_seq_num_1,
|
||||
# pcie_rq_seq_num_vld1=dut.s_axis_rq_seq_num_valid_1,
|
||||
# pcie_rq_tag0
|
||||
# pcie_rq_tag1
|
||||
# pcie_rq_tag_av
|
||||
# pcie_rq_tag_vld0
|
||||
# pcie_rq_tag_vld1
|
||||
|
||||
# Requester Completion Interface
|
||||
rc_entity=dut,
|
||||
rc_name="s_axis_rc",
|
||||
|
||||
# Completer reQuest Interface
|
||||
cq_entity=dut,
|
||||
cq_name="s_axis_cq",
|
||||
# pcie_cq_np_req
|
||||
# pcie_cq_np_req_count
|
||||
|
||||
# Completer Completion Interface
|
||||
cc_entity=dut,
|
||||
cc_name="m_axis_cc",
|
||||
|
||||
# Transmit Flow Control Interface
|
||||
# pcie_tfc_nph_av=dut.pcie_tfc_nph_av,
|
||||
# pcie_tfc_npd_av=dut.pcie_tfc_npd_av,
|
||||
|
||||
# Configuration Management Interface
|
||||
cfg_mgmt_addr=dut.cfg_mgmt_addr,
|
||||
cfg_mgmt_write=dut.cfg_mgmt_write,
|
||||
cfg_mgmt_write_data=dut.cfg_mgmt_write_data,
|
||||
cfg_mgmt_byte_enable=dut.cfg_mgmt_byte_enable,
|
||||
cfg_mgmt_read=dut.cfg_mgmt_read,
|
||||
cfg_mgmt_read_data=dut.cfg_mgmt_read_data,
|
||||
cfg_mgmt_read_write_done=dut.cfg_mgmt_read_write_done,
|
||||
# cfg_mgmt_debug_access
|
||||
|
||||
# Configuration Status Interface
|
||||
# cfg_phy_link_down
|
||||
# cfg_phy_link_status
|
||||
# cfg_negotiated_width
|
||||
# cfg_current_speed
|
||||
cfg_max_payload=dut.cfg_max_payload,
|
||||
cfg_max_read_req=dut.cfg_max_read_req,
|
||||
# cfg_function_status
|
||||
# cfg_vf_status
|
||||
# cfg_function_power_state
|
||||
# cfg_vf_power_state
|
||||
# cfg_link_power_state
|
||||
# cfg_err_cor_out
|
||||
# cfg_err_nonfatal_out
|
||||
# cfg_err_fatal_out
|
||||
# cfg_local_error_out
|
||||
# cfg_local_error_valid
|
||||
# cfg_rx_pm_state
|
||||
# cfg_tx_pm_state
|
||||
# cfg_ltssm_state
|
||||
# cfg_rcb_status
|
||||
# cfg_obff_enable
|
||||
# cfg_pl_status_change
|
||||
# cfg_tph_requester_enable
|
||||
# cfg_tph_st_mode
|
||||
# cfg_vf_tph_requester_enable
|
||||
# cfg_vf_tph_st_mode
|
||||
|
||||
# Configuration Received Message Interface
|
||||
# cfg_msg_received
|
||||
# cfg_msg_received_data
|
||||
# cfg_msg_received_type
|
||||
|
||||
# Configuration Transmit Message Interface
|
||||
# cfg_msg_transmit
|
||||
# cfg_msg_transmit_type
|
||||
# cfg_msg_transmit_data
|
||||
# cfg_msg_transmit_done
|
||||
|
||||
# Configuration Flow Control Interface
|
||||
# cfg_fc_ph=dut.cfg_fc_ph,
|
||||
# cfg_fc_pd=dut.cfg_fc_pd,
|
||||
# cfg_fc_nph=dut.cfg_fc_nph,
|
||||
# cfg_fc_npd=dut.cfg_fc_npd,
|
||||
# cfg_fc_cplh=dut.cfg_fc_cplh,
|
||||
# cfg_fc_cpld=dut.cfg_fc_cpld,
|
||||
# cfg_fc_sel=dut.cfg_fc_sel,
|
||||
|
||||
# Configuration Control Interface
|
||||
# cfg_hot_reset_in
|
||||
# cfg_hot_reset_out
|
||||
# cfg_config_space_enable
|
||||
# cfg_dsn
|
||||
# cfg_bus_number
|
||||
# cfg_ds_port_number
|
||||
# cfg_ds_bus_number
|
||||
# cfg_ds_device_number
|
||||
# cfg_ds_function_number
|
||||
# cfg_power_state_change_ack
|
||||
# cfg_power_state_change_interrupt
|
||||
cfg_err_cor_in=dut.status_error_cor,
|
||||
cfg_err_uncor_in=dut.status_error_uncor,
|
||||
# cfg_flr_in_process
|
||||
# cfg_flr_done
|
||||
# cfg_vf_flr_in_process
|
||||
# cfg_vf_flr_func_num
|
||||
# cfg_vf_flr_done
|
||||
# cfg_pm_aspm_l1_entry_reject
|
||||
# cfg_pm_aspm_tx_l0s_entry_disable
|
||||
# cfg_req_pm_transition_l23_ready
|
||||
# cfg_link_training_enable
|
||||
|
||||
# Configuration Interrupt Controller Interface
|
||||
# cfg_interrupt_int
|
||||
# cfg_interrupt_sent
|
||||
# cfg_interrupt_pending
|
||||
cfg_interrupt_msi_enable=dut.cfg_interrupt_msi_enable,
|
||||
cfg_interrupt_msi_vf_enable=dut.cfg_interrupt_msi_vf_enable,
|
||||
cfg_interrupt_msi_mmenable=dut.cfg_interrupt_msi_mmenable,
|
||||
cfg_interrupt_msi_mask_update=dut.cfg_interrupt_msi_mask_update,
|
||||
cfg_interrupt_msi_data=dut.cfg_interrupt_msi_data,
|
||||
cfg_interrupt_msi_select=dut.cfg_interrupt_msi_select,
|
||||
cfg_interrupt_msi_int=dut.cfg_interrupt_msi_int,
|
||||
cfg_interrupt_msi_pending_status=dut.cfg_interrupt_msi_pending_status,
|
||||
cfg_interrupt_msi_pending_status_data_enable=dut.cfg_interrupt_msi_pending_status_data_enable,
|
||||
cfg_interrupt_msi_pending_status_function_num=dut.cfg_interrupt_msi_pending_status_function_num,
|
||||
cfg_interrupt_msi_sent=dut.cfg_interrupt_msi_sent,
|
||||
cfg_interrupt_msi_fail=dut.cfg_interrupt_msi_fail,
|
||||
# cfg_interrupt_msix_enable
|
||||
# cfg_interrupt_msix_mask
|
||||
# cfg_interrupt_msix_vf_enable
|
||||
# cfg_interrupt_msix_vf_mask
|
||||
# cfg_interrupt_msix_address
|
||||
# cfg_interrupt_msix_data
|
||||
# cfg_interrupt_msix_int
|
||||
# cfg_interrupt_msix_vec_pending
|
||||
# cfg_interrupt_msix_vec_pending_status
|
||||
cfg_interrupt_msi_attr=dut.cfg_interrupt_msi_attr,
|
||||
cfg_interrupt_msi_tph_present=dut.cfg_interrupt_msi_tph_present,
|
||||
cfg_interrupt_msi_tph_type=dut.cfg_interrupt_msi_tph_type,
|
||||
# cfg_interrupt_msi_tph_st_tag=dut.cfg_interrupt_msi_tph_st_tag,
|
||||
# cfg_interrupt_msi_function_number=dut.cfg_interrupt_msi_function_number,
|
||||
|
||||
# Configuration Extend Interface
|
||||
# cfg_ext_read_received
|
||||
# cfg_ext_write_received
|
||||
# cfg_ext_register_number
|
||||
# cfg_ext_function_number
|
||||
# cfg_ext_write_data
|
||||
# cfg_ext_write_byte_enable
|
||||
# cfg_ext_read_data
|
||||
# cfg_ext_read_data_valid
|
||||
)
|
||||
|
||||
# self.dev.log.setLevel(logging.DEBUG)
|
||||
|
||||
self.rc.make_port().connect(self.dev)
|
||||
|
||||
self.dev.functions[0].msi_multiple_message_capable = 5
|
||||
|
||||
self.dev.functions[0].configure_bar(0, 2**22)
|
||||
self.dev.functions[0].configure_bar(1, 2**22)
|
||||
|
||||
async def init(self):
|
||||
|
||||
await FallingEdge(self.dut.rst)
|
||||
await Timer(100, 'ns')
|
||||
|
||||
await self.rc.enumerate(enable_bus_mastering=True, configure_msi=True)
|
||||
|
||||
|
||||
@cocotb.test()
|
||||
async def run_test(dut):
|
||||
|
||||
tb = TB(dut)
|
||||
|
||||
await tb.init()
|
||||
|
||||
mem_base, mem_data = tb.rc.alloc_region(16*1024*1024)
|
||||
|
||||
dev_pf0_bar0 = tb.rc.tree[0][0].bar_addr[0]
|
||||
dev_pf0_bar1 = tb.rc.tree[0][0].bar_addr[1]
|
||||
|
||||
tb.log.info("Test memory write to BAR 1")
|
||||
|
||||
await tb.rc.mem_write(dev_pf0_bar1, b'\x11\x22\x33\x44')
|
||||
|
||||
await Timer(100, 'ns')
|
||||
|
||||
tb.log.info("Test memory read from BAR 1")
|
||||
|
||||
val = await tb.rc.mem_read(dev_pf0_bar1, 4, 1000)
|
||||
tb.log.info("Read data: %s", val)
|
||||
assert val == b'\x11\x22\x33\x44'
|
||||
|
||||
tb.log.info("Test DMA")
|
||||
|
||||
# write packet data
|
||||
mem_data[0:1024] = bytearray([x % 256 for x in range(1024)])
|
||||
|
||||
# enable DMA
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100000, 1)
|
||||
|
||||
# write pcie read descriptor
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100100, (mem_base+0x0000) & 0xffffffff)
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100104, (mem_base+0x0000 >> 32) & 0xffffffff)
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100108, (0x100) & 0xffffffff)
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x10010C, (0x100 >> 32) & 0xffffffff)
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100110, 0x400)
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100114, 0xAA)
|
||||
|
||||
await Timer(2000, 'ns')
|
||||
|
||||
# read status
|
||||
val = await tb.rc.mem_read_dword(dev_pf0_bar0+0x100118)
|
||||
tb.log.info("Status: 0x%x", val)
|
||||
assert val == 0xAA
|
||||
|
||||
# write pcie write descriptor
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100200, (mem_base+0x1000) & 0xffffffff)
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100204, (mem_base+0x1000 >> 32) & 0xffffffff)
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100208, (0x100) & 0xffffffff)
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x10020C, (0x100 >> 32) & 0xffffffff)
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100210, 0x400)
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100214, 0x55)
|
||||
|
||||
await Timer(2000, 'ns')
|
||||
|
||||
# read status
|
||||
val = await tb.rc.mem_read_dword(dev_pf0_bar0+0x100218)
|
||||
tb.log.info("Status: 0x%x", val)
|
||||
assert val == 0x55
|
||||
|
||||
tb.log.info("%s", hexdump_str(mem_data, 0x1000, 64))
|
||||
|
||||
assert mem_data[0:1024] == mem_data[0x1000:0x1000+1024]
|
||||
|
||||
await RisingEdge(dut.clk)
|
||||
await RisingEdge(dut.clk)
|
||||
|
||||
|
||||
# cocotb-test
|
||||
|
||||
tests_dir = os.path.dirname(__file__)
|
||||
rtl_dir = os.path.abspath(os.path.join(tests_dir, '..', '..', 'rtl'))
|
||||
lib_dir = os.path.abspath(os.path.join(rtl_dir, '..', 'lib'))
|
||||
pcie_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'pcie', 'rtl'))
|
||||
|
||||
|
||||
def test_fpga_core(request):
|
||||
dut = "fpga_core"
|
||||
module = os.path.splitext(os.path.basename(__file__))[0]
|
||||
toplevel = dut
|
||||
|
||||
verilog_sources = [
|
||||
os.path.join(rtl_dir, f"{dut}.v"),
|
||||
os.path.join(rtl_dir, "axi_ram.v"),
|
||||
os.path.join(rtl_dir, "axis_register.v"),
|
||||
os.path.join(pcie_rtl_dir, "axis_arb_mux.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_us_axil_master.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_us_axi_dma.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_us_axi_dma_rd.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_us_axi_dma_wr.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_tag_manager.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_us_axi_master.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_us_axi_master_rd.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_us_axi_master_wr.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_us_axis_cq_demux.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_us_cfg.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_us_msi.v"),
|
||||
os.path.join(pcie_rtl_dir, "arbiter.v"),
|
||||
os.path.join(pcie_rtl_dir, "priority_encoder.v"),
|
||||
os.path.join(pcie_rtl_dir, "pulse_merge.v"),
|
||||
]
|
||||
|
||||
parameters = {}
|
||||
|
||||
parameters['AXIS_PCIE_DATA_WIDTH'] = 256
|
||||
parameters['AXIS_PCIE_KEEP_WIDTH'] = parameters['AXIS_PCIE_DATA_WIDTH'] // 32
|
||||
parameters['AXIS_PCIE_RQ_USER_WIDTH'] = 60
|
||||
parameters['AXIS_PCIE_RC_USER_WIDTH'] = 75
|
||||
parameters['AXIS_PCIE_CQ_USER_WIDTH'] = 85
|
||||
parameters['AXIS_PCIE_CC_USER_WIDTH'] = 33
|
||||
parameters['RQ_SEQ_NUM_WIDTH'] = 4
|
||||
|
||||
extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()}
|
||||
|
||||
sim_build = os.path.join(tests_dir,
|
||||
"sim_build_"+request.node.name.replace('[', '-').replace(']', ''))
|
||||
|
||||
cocotb_test.simulator.run(
|
||||
python_search=[tests_dir],
|
||||
verilog_sources=verilog_sources,
|
||||
toplevel=toplevel,
|
||||
module=module,
|
||||
parameters=parameters,
|
||||
sim_build=sim_build,
|
||||
extra_env=extra_env,
|
||||
)
|
@ -1 +0,0 @@
|
||||
../lib/pcie/tb/pcie.py
|
@ -1 +0,0 @@
|
||||
../lib/pcie/tb/pcie_us.py
|
@ -1,512 +0,0 @@
|
||||
#!/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
|
||||
AXIS_PCIE_DATA_WIDTH = 256
|
||||
AXIS_PCIE_KEEP_WIDTH = (AXIS_PCIE_DATA_WIDTH/32)
|
||||
AXIS_PCIE_RC_USER_WIDTH = 75
|
||||
AXIS_PCIE_RQ_USER_WIDTH = 60
|
||||
AXIS_PCIE_CQ_USER_WIDTH = 85
|
||||
AXIS_PCIE_CC_USER_WIDTH = 33
|
||||
|
||||
# Inputs
|
||||
clk = Signal(bool(0))
|
||||
rst = Signal(bool(0))
|
||||
current_test = Signal(intbv(0)[8:])
|
||||
|
||||
m_axis_rq_tready = Signal(bool(0))
|
||||
s_axis_rc_tdata = Signal(intbv(0)[AXIS_PCIE_DATA_WIDTH:])
|
||||
s_axis_rc_tkeep = Signal(intbv(0)[AXIS_PCIE_KEEP_WIDTH:])
|
||||
s_axis_rc_tlast = Signal(bool(0))
|
||||
s_axis_rc_tuser = Signal(intbv(0)[AXIS_PCIE_RC_USER_WIDTH:])
|
||||
s_axis_rc_tvalid = Signal(bool(0))
|
||||
s_axis_cq_tdata = Signal(intbv(0)[AXIS_PCIE_DATA_WIDTH:])
|
||||
s_axis_cq_tkeep = Signal(intbv(0)[AXIS_PCIE_KEEP_WIDTH:])
|
||||
s_axis_cq_tlast = Signal(bool(0))
|
||||
s_axis_cq_tuser = Signal(intbv(0)[AXIS_PCIE_CQ_USER_WIDTH:])
|
||||
s_axis_cq_tvalid = Signal(bool(0))
|
||||
m_axis_cc_tready = Signal(bool(0))
|
||||
cfg_max_payload = Signal(intbv(0)[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)[AXIS_PCIE_DATA_WIDTH:])
|
||||
m_axis_rq_tkeep = Signal(intbv(0)[AXIS_PCIE_KEEP_WIDTH:])
|
||||
m_axis_rq_tlast = Signal(bool(0))
|
||||
m_axis_rq_tuser = Signal(intbv(0)[AXIS_PCIE_RQ_USER_WIDTH:])
|
||||
m_axis_rq_tvalid = Signal(bool(0))
|
||||
s_axis_rc_tready = Signal(bool(0))
|
||||
s_axis_cq_tready = Signal(bool(0))
|
||||
m_axis_cc_tdata = Signal(intbv(0)[AXIS_PCIE_DATA_WIDTH:])
|
||||
m_axis_cc_tkeep = Signal(intbv(0)[AXIS_PCIE_KEEP_WIDTH:])
|
||||
m_axis_cc_tlast = Signal(bool(0))
|
||||
m_axis_cc_tuser = Signal(intbv(0)[AXIS_PCIE_CC_USER_WIDTH:])
|
||||
m_axis_cc_tvalid = Signal(bool(0))
|
||||
status_error_cor = Signal(bool(0))
|
||||
status_error_uncor = Signal(bool(0))
|
||||
cfg_mgmt_addr = Signal(intbv(0)[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_clk_frequency = 250e6
|
||||
|
||||
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()
|
@ -1,243 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2018 Alex Forencich
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
// Language: Verilog 2001
|
||||
|
||||
`timescale 1ns / 1ps
|
||||
|
||||
/*
|
||||
* Testbench for fpga_core
|
||||
*/
|
||||
module test_fpga_core;
|
||||
|
||||
// Parameters
|
||||
parameter AXIS_PCIE_DATA_WIDTH = 256;
|
||||
parameter AXIS_PCIE_KEEP_WIDTH = (AXIS_PCIE_DATA_WIDTH/32);
|
||||
parameter AXIS_PCIE_RC_USER_WIDTH = 75;
|
||||
parameter AXIS_PCIE_RQ_USER_WIDTH = 60;
|
||||
parameter AXIS_PCIE_CQ_USER_WIDTH = 85;
|
||||
parameter AXIS_PCIE_CC_USER_WIDTH = 33;
|
||||
|
||||
// Inputs
|
||||
reg clk = 0;
|
||||
reg rst = 0;
|
||||
reg [7:0] current_test = 0;
|
||||
|
||||
reg m_axis_rq_tready = 0;
|
||||
reg [AXIS_PCIE_DATA_WIDTH-1:0] s_axis_rc_tdata = 0;
|
||||
reg [AXIS_PCIE_KEEP_WIDTH-1:0] s_axis_rc_tkeep = 0;
|
||||
reg s_axis_rc_tlast = 0;
|
||||
reg [AXIS_PCIE_RC_USER_WIDTH-1:0] s_axis_rc_tuser = 0;
|
||||
reg s_axis_rc_tvalid = 0;
|
||||
reg [AXIS_PCIE_DATA_WIDTH-1:0] s_axis_cq_tdata = 0;
|
||||
reg [AXIS_PCIE_KEEP_WIDTH-1:0] s_axis_cq_tkeep = 0;
|
||||
reg s_axis_cq_tlast = 0;
|
||||
reg [AXIS_PCIE_CQ_USER_WIDTH-1:0] s_axis_cq_tuser = 0;
|
||||
reg s_axis_cq_tvalid = 0;
|
||||
reg m_axis_cc_tready = 0;
|
||||
reg [2:0] cfg_max_payload = 0;
|
||||
reg [2:0] cfg_max_read_req = 0;
|
||||
reg [31:0] cfg_mgmt_read_data = 0;
|
||||
reg cfg_mgmt_read_write_done = 0;
|
||||
reg [3:0] cfg_interrupt_msi_enable = 0;
|
||||
reg [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 [AXIS_PCIE_DATA_WIDTH-1:0] m_axis_rq_tdata;
|
||||
wire [AXIS_PCIE_KEEP_WIDTH-1:0] m_axis_rq_tkeep;
|
||||
wire m_axis_rq_tlast;
|
||||
wire [AXIS_PCIE_RQ_USER_WIDTH-1:0] m_axis_rq_tuser;
|
||||
wire m_axis_rq_tvalid;
|
||||
wire s_axis_rc_tready;
|
||||
wire s_axis_cq_tready;
|
||||
wire [AXIS_PCIE_DATA_WIDTH-1:0] m_axis_cc_tdata;
|
||||
wire [AXIS_PCIE_KEEP_WIDTH-1:0] m_axis_cc_tkeep;
|
||||
wire m_axis_cc_tlast;
|
||||
wire [AXIS_PCIE_CC_USER_WIDTH-1:0] m_axis_cc_tuser;
|
||||
wire m_axis_cc_tvalid;
|
||||
wire [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 #(
|
||||
.AXIS_PCIE_DATA_WIDTH(AXIS_PCIE_DATA_WIDTH),
|
||||
.AXIS_PCIE_KEEP_WIDTH(AXIS_PCIE_KEEP_WIDTH),
|
||||
.AXIS_PCIE_RC_USER_WIDTH(AXIS_PCIE_RC_USER_WIDTH),
|
||||
.AXIS_PCIE_RQ_USER_WIDTH(AXIS_PCIE_RQ_USER_WIDTH),
|
||||
.AXIS_PCIE_CQ_USER_WIDTH(AXIS_PCIE_CQ_USER_WIDTH),
|
||||
.AXIS_PCIE_CC_USER_WIDTH(AXIS_PCIE_CC_USER_WIDTH)
|
||||
)
|
||||
UUT (
|
||||
.clk(clk),
|
||||
.rst(rst),
|
||||
.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
|
@ -1 +0,0 @@
|
||||
../lib/pcie/tb/axis_ep.py
|
107
example/ExaNIC_X25/fpga_axi/tb/fpga_core/Makefile
Normal file
107
example/ExaNIC_X25/fpga_axi/tb/fpga_core/Makefile
Normal file
@ -0,0 +1,107 @@
|
||||
# Copyright (c) 2020 Alex Forencich
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in
|
||||
# all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
# THE SOFTWARE.
|
||||
|
||||
TOPLEVEL_LANG = verilog
|
||||
|
||||
SIM ?= icarus
|
||||
WAVES ?= 0
|
||||
|
||||
COCOTB_HDL_TIMEUNIT = 1ns
|
||||
COCOTB_HDL_TIMEPRECISION = 1ps
|
||||
|
||||
DUT = fpga_core
|
||||
TOPLEVEL = $(DUT)
|
||||
MODULE = test_$(DUT)
|
||||
VERILOG_SOURCES += ../../rtl/$(DUT).v
|
||||
VERILOG_SOURCES += ../../rtl/axi_ram.v
|
||||
VERILOG_SOURCES += ../../rtl/axis_register.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/axis_arb_mux.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_axil_master.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_axi_dma.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_axi_dma_rd.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_axi_dma_wr.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_tag_manager.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_axi_master.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_axi_master_rd.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_axi_master_wr.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_axis_cq_demux.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_cfg.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_msi.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/arbiter.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/priority_encoder.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pulse_merge.v
|
||||
|
||||
# module parameters
|
||||
export PARAM_AXIS_PCIE_DATA_WIDTH ?= 256
|
||||
export PARAM_AXIS_PCIE_KEEP_WIDTH ?= $(shell expr $(PARAM_AXIS_PCIE_DATA_WIDTH) / 32 )
|
||||
export PARAM_AXIS_PCIE_RQ_USER_WIDTH ?= $(if $(filter-out 512,$(PARAM_AXIS_PCIE_DATA_WIDTH)),62,137)
|
||||
export PARAM_AXIS_PCIE_RC_USER_WIDTH ?= $(if $(filter-out 512,$(PARAM_AXIS_PCIE_DATA_WIDTH)),75,161)
|
||||
export PARAM_AXIS_PCIE_CQ_USER_WIDTH ?= $(if $(filter-out 512,$(PARAM_AXIS_PCIE_DATA_WIDTH)),88,183)
|
||||
export PARAM_AXIS_PCIE_CC_USER_WIDTH ?= $(if $(filter-out 512,$(PARAM_AXIS_PCIE_DATA_WIDTH)),33,81)
|
||||
export PARAM_RQ_SEQ_NUM_WIDTH ?= 6
|
||||
|
||||
SIM_BUILD ?= sim_build_$(MODULE)
|
||||
|
||||
ifeq ($(SIM), icarus)
|
||||
PLUSARGS += -fst
|
||||
|
||||
COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_DATA_WIDTH=$(PARAM_AXIS_PCIE_DATA_WIDTH)
|
||||
COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_KEEP_WIDTH=$(PARAM_AXIS_PCIE_KEEP_WIDTH)
|
||||
COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_RQ_USER_WIDTH=$(PARAM_AXIS_PCIE_RQ_USER_WIDTH)
|
||||
COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_RC_USER_WIDTH=$(PARAM_AXIS_PCIE_RC_USER_WIDTH)
|
||||
COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_CQ_USER_WIDTH=$(PARAM_AXIS_PCIE_CQ_USER_WIDTH)
|
||||
COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_CC_USER_WIDTH=$(PARAM_AXIS_PCIE_CC_USER_WIDTH)
|
||||
COMPILE_ARGS += -P $(TOPLEVEL).RQ_SEQ_NUM_WIDTH=$(PARAM_RQ_SEQ_NUM_WIDTH)
|
||||
|
||||
ifeq ($(WAVES), 1)
|
||||
VERILOG_SOURCES += iverilog_dump.v
|
||||
COMPILE_ARGS += -s iverilog_dump
|
||||
endif
|
||||
else ifeq ($(SIM), verilator)
|
||||
COMPILE_ARGS += -Wno-SELRANGE -Wno-WIDTH
|
||||
|
||||
COMPILE_ARGS += -GAXIS_PCIE_DATA_WIDTH=$(PARAM_AXIS_PCIE_DATA_WIDTH)
|
||||
COMPILE_ARGS += -GAXIS_PCIE_KEEP_WIDTH=$(PARAM_AXIS_PCIE_KEEP_WIDTH)
|
||||
COMPILE_ARGS += -GAXIS_PCIE_RQ_USER_WIDTH=$(PARAM_AXIS_PCIE_RQ_USER_WIDTH)
|
||||
COMPILE_ARGS += -GAXIS_PCIE_RC_USER_WIDTH=$(PARAM_AXIS_PCIE_RC_USER_WIDTH)
|
||||
COMPILE_ARGS += -GAXIS_PCIE_CQ_USER_WIDTH=$(PARAM_AXIS_PCIE_CQ_USER_WIDTH)
|
||||
COMPILE_ARGS += -GAXIS_PCIE_CC_USER_WIDTH=$(PARAM_AXIS_PCIE_CC_USER_WIDTH)
|
||||
COMPILE_ARGS += -GRQ_SEQ_NUM_WIDTH=$(PARAM_RQ_SEQ_NUM_WIDTH)
|
||||
|
||||
ifeq ($(WAVES), 1)
|
||||
COMPILE_ARGS += --trace-fst
|
||||
endif
|
||||
endif
|
||||
|
||||
iverilog_dump.v:
|
||||
echo 'module iverilog_dump();' > $@
|
||||
echo 'initial begin' >> $@
|
||||
echo ' $$dumpfile("$(TOPLEVEL).fst");' >> $@
|
||||
echo ' $$dumpvars(0, $(TOPLEVEL));' >> $@
|
||||
echo 'end' >> $@
|
||||
echo 'endmodule' >> $@
|
||||
|
||||
clean::
|
||||
@rm -rf sim_build_*
|
||||
@rm -rf iverilog_dump.v
|
||||
@rm -rf dump.fst $(TOPLEVEL).fst
|
||||
|
||||
include $(shell cocotb-config --makefiles)/Makefile.sim
|
||||
|
378
example/ExaNIC_X25/fpga_axi/tb/fpga_core/test_fpga_core.py
Normal file
378
example/ExaNIC_X25/fpga_axi/tb/fpga_core/test_fpga_core.py
Normal file
@ -0,0 +1,378 @@
|
||||
"""
|
||||
|
||||
Copyright (c) 2020 Alex Forencich
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
"""
|
||||
|
||||
import logging
|
||||
import os
|
||||
|
||||
import cocotb_test.simulator
|
||||
|
||||
import cocotb
|
||||
from cocotb.log import SimLog
|
||||
from cocotb.triggers import RisingEdge, FallingEdge, Timer
|
||||
|
||||
from cocotbext.pcie.core import RootComplex
|
||||
from cocotbext.pcie.xilinx.us import UltraScalePlusPcieDevice
|
||||
from cocotbext.axi.utils import hexdump_str
|
||||
|
||||
|
||||
class TB(object):
|
||||
def __init__(self, dut):
|
||||
self.dut = dut
|
||||
|
||||
self.log = SimLog("cocotb.tb")
|
||||
self.log.setLevel(logging.DEBUG)
|
||||
|
||||
# PCIe
|
||||
self.rc = RootComplex()
|
||||
|
||||
self.dev = UltraScalePlusPcieDevice(
|
||||
# configuration options
|
||||
pcie_generation=3,
|
||||
pcie_link_width=8,
|
||||
user_clk_frequency=250e6,
|
||||
alignment="dword",
|
||||
cq_cc_straddle=False,
|
||||
rq_rc_straddle=False,
|
||||
rc_4tlp_straddle=False,
|
||||
enable_pf1=False,
|
||||
enable_client_tag=True,
|
||||
enable_extended_tag=True,
|
||||
enable_parity=False,
|
||||
enable_rx_msg_interface=False,
|
||||
enable_sriov=False,
|
||||
enable_extended_configuration=False,
|
||||
|
||||
enable_pf0_msi=True,
|
||||
enable_pf1_msi=False,
|
||||
|
||||
# signals
|
||||
# Clock and Reset Interface
|
||||
user_clk=dut.clk,
|
||||
user_reset=dut.rst,
|
||||
# user_lnk_up
|
||||
# sys_clk
|
||||
# sys_clk_gt
|
||||
# sys_reset
|
||||
# phy_rdy_out
|
||||
|
||||
# Requester reQuest Interface
|
||||
rq_entity=dut,
|
||||
rq_name="m_axis_rq",
|
||||
# pcie_rq_seq_num0=dut.s_axis_rq_seq_num_0,
|
||||
# pcie_rq_seq_num_vld0=dut.s_axis_rq_seq_num_valid_0,
|
||||
# pcie_rq_seq_num1=dut.s_axis_rq_seq_num_1,
|
||||
# pcie_rq_seq_num_vld1=dut.s_axis_rq_seq_num_valid_1,
|
||||
# pcie_rq_tag0
|
||||
# pcie_rq_tag1
|
||||
# pcie_rq_tag_av
|
||||
# pcie_rq_tag_vld0
|
||||
# pcie_rq_tag_vld1
|
||||
|
||||
# Requester Completion Interface
|
||||
rc_entity=dut,
|
||||
rc_name="s_axis_rc",
|
||||
|
||||
# Completer reQuest Interface
|
||||
cq_entity=dut,
|
||||
cq_name="s_axis_cq",
|
||||
# pcie_cq_np_req
|
||||
# pcie_cq_np_req_count
|
||||
|
||||
# Completer Completion Interface
|
||||
cc_entity=dut,
|
||||
cc_name="m_axis_cc",
|
||||
|
||||
# Transmit Flow Control Interface
|
||||
# pcie_tfc_nph_av=dut.pcie_tfc_nph_av,
|
||||
# pcie_tfc_npd_av=dut.pcie_tfc_npd_av,
|
||||
|
||||
# Configuration Management Interface
|
||||
cfg_mgmt_addr=dut.cfg_mgmt_addr,
|
||||
cfg_mgmt_function_number=dut.cfg_mgmt_function_number,
|
||||
cfg_mgmt_write=dut.cfg_mgmt_write,
|
||||
cfg_mgmt_write_data=dut.cfg_mgmt_write_data,
|
||||
cfg_mgmt_byte_enable=dut.cfg_mgmt_byte_enable,
|
||||
cfg_mgmt_read=dut.cfg_mgmt_read,
|
||||
cfg_mgmt_read_data=dut.cfg_mgmt_read_data,
|
||||
cfg_mgmt_read_write_done=dut.cfg_mgmt_read_write_done,
|
||||
# cfg_mgmt_debug_access
|
||||
|
||||
# Configuration Status Interface
|
||||
# cfg_phy_link_down
|
||||
# cfg_phy_link_status
|
||||
# cfg_negotiated_width
|
||||
# cfg_current_speed
|
||||
cfg_max_payload=dut.cfg_max_payload,
|
||||
cfg_max_read_req=dut.cfg_max_read_req,
|
||||
# cfg_function_status
|
||||
# cfg_vf_status
|
||||
# cfg_function_power_state
|
||||
# cfg_vf_power_state
|
||||
# cfg_link_power_state
|
||||
# cfg_err_cor_out
|
||||
# cfg_err_nonfatal_out
|
||||
# cfg_err_fatal_out
|
||||
# cfg_local_error_out
|
||||
# cfg_local_error_valid
|
||||
# cfg_rx_pm_state
|
||||
# cfg_tx_pm_state
|
||||
# cfg_ltssm_state
|
||||
# cfg_rcb_status
|
||||
# cfg_obff_enable
|
||||
# cfg_pl_status_change
|
||||
# cfg_tph_requester_enable
|
||||
# cfg_tph_st_mode
|
||||
# cfg_vf_tph_requester_enable
|
||||
# cfg_vf_tph_st_mode
|
||||
|
||||
# Configuration Received Message Interface
|
||||
# cfg_msg_received
|
||||
# cfg_msg_received_data
|
||||
# cfg_msg_received_type
|
||||
|
||||
# Configuration Transmit Message Interface
|
||||
# cfg_msg_transmit
|
||||
# cfg_msg_transmit_type
|
||||
# cfg_msg_transmit_data
|
||||
# cfg_msg_transmit_done
|
||||
|
||||
# Configuration Flow Control Interface
|
||||
# cfg_fc_ph=dut.cfg_fc_ph,
|
||||
# cfg_fc_pd=dut.cfg_fc_pd,
|
||||
# cfg_fc_nph=dut.cfg_fc_nph,
|
||||
# cfg_fc_npd=dut.cfg_fc_npd,
|
||||
# cfg_fc_cplh=dut.cfg_fc_cplh,
|
||||
# cfg_fc_cpld=dut.cfg_fc_cpld,
|
||||
# cfg_fc_sel=dut.cfg_fc_sel,
|
||||
|
||||
# Configuration Control Interface
|
||||
# cfg_hot_reset_in
|
||||
# cfg_hot_reset_out
|
||||
# cfg_config_space_enable
|
||||
# cfg_dsn
|
||||
# cfg_bus_number
|
||||
# cfg_ds_port_number
|
||||
# cfg_ds_bus_number
|
||||
# cfg_ds_device_number
|
||||
# cfg_ds_function_number
|
||||
# cfg_power_state_change_ack
|
||||
# cfg_power_state_change_interrupt
|
||||
cfg_err_cor_in=dut.status_error_cor,
|
||||
cfg_err_uncor_in=dut.status_error_uncor,
|
||||
# cfg_flr_in_process
|
||||
# cfg_flr_done
|
||||
# cfg_vf_flr_in_process
|
||||
# cfg_vf_flr_func_num
|
||||
# cfg_vf_flr_done
|
||||
# cfg_pm_aspm_l1_entry_reject
|
||||
# cfg_pm_aspm_tx_l0s_entry_disable
|
||||
# cfg_req_pm_transition_l23_ready
|
||||
# cfg_link_training_enable
|
||||
|
||||
# Configuration Interrupt Controller Interface
|
||||
# cfg_interrupt_int
|
||||
# cfg_interrupt_sent
|
||||
# cfg_interrupt_pending
|
||||
cfg_interrupt_msi_enable=dut.cfg_interrupt_msi_enable,
|
||||
cfg_interrupt_msi_mmenable=dut.cfg_interrupt_msi_mmenable,
|
||||
cfg_interrupt_msi_mask_update=dut.cfg_interrupt_msi_mask_update,
|
||||
cfg_interrupt_msi_data=dut.cfg_interrupt_msi_data,
|
||||
# cfg_interrupt_msi_select=dut.cfg_interrupt_msi_select,
|
||||
cfg_interrupt_msi_int=dut.cfg_interrupt_msi_int,
|
||||
cfg_interrupt_msi_pending_status=dut.cfg_interrupt_msi_pending_status,
|
||||
cfg_interrupt_msi_pending_status_data_enable=dut.cfg_interrupt_msi_pending_status_data_enable,
|
||||
# cfg_interrupt_msi_pending_status_function_num=dut.cfg_interrupt_msi_pending_status_function_num,
|
||||
cfg_interrupt_msi_sent=dut.cfg_interrupt_msi_sent,
|
||||
cfg_interrupt_msi_fail=dut.cfg_interrupt_msi_fail,
|
||||
# cfg_interrupt_msix_enable
|
||||
# cfg_interrupt_msix_mask
|
||||
# cfg_interrupt_msix_vf_enable
|
||||
# cfg_interrupt_msix_vf_mask
|
||||
# cfg_interrupt_msix_address
|
||||
# cfg_interrupt_msix_data
|
||||
# cfg_interrupt_msix_int
|
||||
# cfg_interrupt_msix_vec_pending
|
||||
# cfg_interrupt_msix_vec_pending_status
|
||||
cfg_interrupt_msi_attr=dut.cfg_interrupt_msi_attr,
|
||||
cfg_interrupt_msi_tph_present=dut.cfg_interrupt_msi_tph_present,
|
||||
cfg_interrupt_msi_tph_type=dut.cfg_interrupt_msi_tph_type,
|
||||
# cfg_interrupt_msi_tph_st_tag=dut.cfg_interrupt_msi_tph_st_tag,
|
||||
# cfg_interrupt_msi_function_number=dut.cfg_interrupt_msi_function_number,
|
||||
|
||||
# Configuration Extend Interface
|
||||
# cfg_ext_read_received
|
||||
# cfg_ext_write_received
|
||||
# cfg_ext_register_number
|
||||
# cfg_ext_function_number
|
||||
# cfg_ext_write_data
|
||||
# cfg_ext_write_byte_enable
|
||||
# cfg_ext_read_data
|
||||
# cfg_ext_read_data_valid
|
||||
)
|
||||
|
||||
# self.dev.log.setLevel(logging.DEBUG)
|
||||
|
||||
self.rc.make_port().connect(self.dev)
|
||||
|
||||
self.dev.functions[0].msi_multiple_message_capable = 5
|
||||
|
||||
self.dev.functions[0].configure_bar(0, 2**22)
|
||||
self.dev.functions[0].configure_bar(1, 2**22)
|
||||
|
||||
async def init(self):
|
||||
|
||||
await FallingEdge(self.dut.rst)
|
||||
await Timer(100, 'ns')
|
||||
|
||||
await self.rc.enumerate(enable_bus_mastering=True, configure_msi=True)
|
||||
|
||||
|
||||
@cocotb.test()
|
||||
async def run_test(dut):
|
||||
|
||||
tb = TB(dut)
|
||||
|
||||
await tb.init()
|
||||
|
||||
mem_base, mem_data = tb.rc.alloc_region(16*1024*1024)
|
||||
|
||||
dev_pf0_bar0 = tb.rc.tree[0][0].bar_addr[0]
|
||||
dev_pf0_bar1 = tb.rc.tree[0][0].bar_addr[1]
|
||||
|
||||
tb.log.info("Test memory write to BAR 1")
|
||||
|
||||
await tb.rc.mem_write(dev_pf0_bar1, b'\x11\x22\x33\x44')
|
||||
|
||||
await Timer(100, 'ns')
|
||||
|
||||
tb.log.info("Test memory read from BAR 1")
|
||||
|
||||
val = await tb.rc.mem_read(dev_pf0_bar1, 4, 1000)
|
||||
tb.log.info("Read data: %s", val)
|
||||
assert val == b'\x11\x22\x33\x44'
|
||||
|
||||
tb.log.info("Test DMA")
|
||||
|
||||
# write packet data
|
||||
mem_data[0:1024] = bytearray([x % 256 for x in range(1024)])
|
||||
|
||||
# enable DMA
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100000, 1)
|
||||
|
||||
# write pcie read descriptor
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100100, (mem_base+0x0000) & 0xffffffff)
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100104, (mem_base+0x0000 >> 32) & 0xffffffff)
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100108, (0x100) & 0xffffffff)
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x10010C, (0x100 >> 32) & 0xffffffff)
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100110, 0x400)
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100114, 0xAA)
|
||||
|
||||
await Timer(2000, 'ns')
|
||||
|
||||
# read status
|
||||
val = await tb.rc.mem_read_dword(dev_pf0_bar0+0x100118)
|
||||
tb.log.info("Status: 0x%x", val)
|
||||
assert val == 0xAA
|
||||
|
||||
# write pcie write descriptor
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100200, (mem_base+0x1000) & 0xffffffff)
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100204, (mem_base+0x1000 >> 32) & 0xffffffff)
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100208, (0x100) & 0xffffffff)
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x10020C, (0x100 >> 32) & 0xffffffff)
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100210, 0x400)
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100214, 0x55)
|
||||
|
||||
await Timer(2000, 'ns')
|
||||
|
||||
# read status
|
||||
val = await tb.rc.mem_read_dword(dev_pf0_bar0+0x100218)
|
||||
tb.log.info("Status: 0x%x", val)
|
||||
assert val == 0x55
|
||||
|
||||
tb.log.info("%s", hexdump_str(mem_data, 0x1000, 64))
|
||||
|
||||
assert mem_data[0:1024] == mem_data[0x1000:0x1000+1024]
|
||||
|
||||
await RisingEdge(dut.clk)
|
||||
await RisingEdge(dut.clk)
|
||||
|
||||
|
||||
# cocotb-test
|
||||
|
||||
tests_dir = os.path.dirname(__file__)
|
||||
rtl_dir = os.path.abspath(os.path.join(tests_dir, '..', '..', 'rtl'))
|
||||
lib_dir = os.path.abspath(os.path.join(rtl_dir, '..', 'lib'))
|
||||
pcie_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'pcie', 'rtl'))
|
||||
|
||||
|
||||
def test_fpga_core(request):
|
||||
dut = "fpga_core"
|
||||
module = os.path.splitext(os.path.basename(__file__))[0]
|
||||
toplevel = dut
|
||||
|
||||
verilog_sources = [
|
||||
os.path.join(rtl_dir, f"{dut}.v"),
|
||||
os.path.join(rtl_dir, "axi_ram.v"),
|
||||
os.path.join(rtl_dir, "axis_register.v"),
|
||||
os.path.join(pcie_rtl_dir, "axis_arb_mux.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_us_axil_master.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_us_axi_dma.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_us_axi_dma_rd.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_us_axi_dma_wr.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_tag_manager.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_us_axi_master.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_us_axi_master_rd.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_us_axi_master_wr.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_us_axis_cq_demux.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_us_cfg.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_us_msi.v"),
|
||||
os.path.join(pcie_rtl_dir, "arbiter.v"),
|
||||
os.path.join(pcie_rtl_dir, "priority_encoder.v"),
|
||||
os.path.join(pcie_rtl_dir, "pulse_merge.v"),
|
||||
]
|
||||
|
||||
parameters = {}
|
||||
|
||||
parameters['AXIS_PCIE_DATA_WIDTH'] = 256
|
||||
parameters['AXIS_PCIE_KEEP_WIDTH'] = parameters['AXIS_PCIE_DATA_WIDTH'] // 32
|
||||
parameters['AXIS_PCIE_RQ_USER_WIDTH'] = 62 if parameters['AXIS_PCIE_DATA_WIDTH'] < 512 else 137
|
||||
parameters['AXIS_PCIE_RC_USER_WIDTH'] = 75 if parameters['AXIS_PCIE_DATA_WIDTH'] < 512 else 161
|
||||
parameters['AXIS_PCIE_CQ_USER_WIDTH'] = 88 if parameters['AXIS_PCIE_DATA_WIDTH'] < 512 else 183
|
||||
parameters['AXIS_PCIE_CC_USER_WIDTH'] = 33 if parameters['AXIS_PCIE_DATA_WIDTH'] < 512 else 81
|
||||
parameters['RQ_SEQ_NUM_WIDTH'] = 6
|
||||
|
||||
extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()}
|
||||
|
||||
sim_build = os.path.join(tests_dir,
|
||||
"sim_build_"+request.node.name.replace('[', '-').replace(']', ''))
|
||||
|
||||
cocotb_test.simulator.run(
|
||||
python_search=[tests_dir],
|
||||
verilog_sources=verilog_sources,
|
||||
toplevel=toplevel,
|
||||
module=module,
|
||||
parameters=parameters,
|
||||
sim_build=sim_build,
|
||||
extra_env=extra_env,
|
||||
)
|
@ -1 +0,0 @@
|
||||
../lib/pcie/tb/pcie.py
|
@ -1 +0,0 @@
|
||||
../lib/pcie/tb/pcie_us.py
|
@ -1 +0,0 @@
|
||||
../lib/pcie/tb/pcie_usp.py
|
@ -1,512 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
"""
|
||||
|
||||
Copyright (c) 2018 Alex Forencich
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
"""
|
||||
|
||||
from myhdl import *
|
||||
import os
|
||||
import struct
|
||||
|
||||
import pcie
|
||||
import pcie_usp
|
||||
|
||||
module = 'fpga_core'
|
||||
testbench = 'test_%s' % module
|
||||
|
||||
srcs = []
|
||||
|
||||
srcs.append("../rtl/%s.v" % module)
|
||||
srcs.append("../rtl/axi_ram.v")
|
||||
srcs.append("../rtl/axis_register.v")
|
||||
srcs.append("../lib/pcie/rtl/axis_arb_mux.v")
|
||||
srcs.append("../lib/pcie/rtl/pcie_us_axil_master.v")
|
||||
srcs.append("../lib/pcie/rtl/pcie_us_axi_dma.v")
|
||||
srcs.append("../lib/pcie/rtl/pcie_us_axi_dma_rd.v")
|
||||
srcs.append("../lib/pcie/rtl/pcie_us_axi_dma_wr.v")
|
||||
srcs.append("../lib/pcie/rtl/pcie_tag_manager.v")
|
||||
srcs.append("../lib/pcie/rtl/pcie_us_axi_master.v")
|
||||
srcs.append("../lib/pcie/rtl/pcie_us_axi_master_rd.v")
|
||||
srcs.append("../lib/pcie/rtl/pcie_us_axi_master_wr.v")
|
||||
srcs.append("../lib/pcie/rtl/pcie_us_axis_cq_demux.v")
|
||||
srcs.append("../lib/pcie/rtl/pcie_us_cfg.v")
|
||||
srcs.append("../lib/pcie/rtl/pcie_us_msi.v")
|
||||
srcs.append("../lib/pcie/rtl/arbiter.v")
|
||||
srcs.append("../lib/pcie/rtl/priority_encoder.v")
|
||||
srcs.append("../lib/pcie/rtl/pulse_merge.v")
|
||||
srcs.append("%s.v" % testbench)
|
||||
|
||||
src = ' '.join(srcs)
|
||||
|
||||
build_cmd = "iverilog -o %s.vvp %s" % (testbench, src)
|
||||
|
||||
def bench():
|
||||
|
||||
# Parameters
|
||||
AXIS_PCIE_DATA_WIDTH = 256
|
||||
AXIS_PCIE_KEEP_WIDTH = (AXIS_PCIE_DATA_WIDTH/32)
|
||||
AXIS_PCIE_RC_USER_WIDTH = 75
|
||||
AXIS_PCIE_RQ_USER_WIDTH = 62
|
||||
AXIS_PCIE_CQ_USER_WIDTH = 88
|
||||
AXIS_PCIE_CC_USER_WIDTH = 33
|
||||
|
||||
# Inputs
|
||||
clk = Signal(bool(0))
|
||||
rst = Signal(bool(0))
|
||||
current_test = Signal(intbv(0)[8:])
|
||||
|
||||
m_axis_rq_tready = Signal(bool(0))
|
||||
s_axis_rc_tdata = Signal(intbv(0)[AXIS_PCIE_DATA_WIDTH:])
|
||||
s_axis_rc_tkeep = Signal(intbv(0)[AXIS_PCIE_KEEP_WIDTH:])
|
||||
s_axis_rc_tlast = Signal(bool(0))
|
||||
s_axis_rc_tuser = Signal(intbv(0)[AXIS_PCIE_RC_USER_WIDTH:])
|
||||
s_axis_rc_tvalid = Signal(bool(0))
|
||||
s_axis_cq_tdata = Signal(intbv(0)[AXIS_PCIE_DATA_WIDTH:])
|
||||
s_axis_cq_tkeep = Signal(intbv(0)[AXIS_PCIE_KEEP_WIDTH:])
|
||||
s_axis_cq_tlast = Signal(bool(0))
|
||||
s_axis_cq_tuser = Signal(intbv(0)[AXIS_PCIE_CQ_USER_WIDTH:])
|
||||
s_axis_cq_tvalid = Signal(bool(0))
|
||||
m_axis_cc_tready = Signal(bool(0))
|
||||
cfg_max_payload = Signal(intbv(0)[2:])
|
||||
cfg_max_read_req = Signal(intbv(0)[3:])
|
||||
cfg_mgmt_read_data = Signal(intbv(0)[32:])
|
||||
cfg_mgmt_read_write_done = Signal(bool(0))
|
||||
cfg_interrupt_msi_enable = Signal(intbv(0)[4:])
|
||||
cfg_interrupt_msi_mmenable = Signal(intbv(0)[12:])
|
||||
cfg_interrupt_msi_mask_update = Signal(bool(0))
|
||||
cfg_interrupt_msi_data = Signal(intbv(0)[32:])
|
||||
cfg_interrupt_msi_sent = Signal(bool(0))
|
||||
cfg_interrupt_msi_fail = Signal(bool(0))
|
||||
|
||||
# Outputs
|
||||
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)[AXIS_PCIE_DATA_WIDTH:])
|
||||
m_axis_rq_tkeep = Signal(intbv(0)[AXIS_PCIE_KEEP_WIDTH:])
|
||||
m_axis_rq_tlast = Signal(bool(0))
|
||||
m_axis_rq_tuser = Signal(intbv(0)[AXIS_PCIE_RQ_USER_WIDTH:])
|
||||
m_axis_rq_tvalid = Signal(bool(0))
|
||||
s_axis_rc_tready = Signal(bool(0))
|
||||
s_axis_cq_tready = Signal(bool(0))
|
||||
m_axis_cc_tdata = Signal(intbv(0)[AXIS_PCIE_DATA_WIDTH:])
|
||||
m_axis_cc_tkeep = Signal(intbv(0)[AXIS_PCIE_KEEP_WIDTH:])
|
||||
m_axis_cc_tlast = Signal(bool(0))
|
||||
m_axis_cc_tuser = Signal(intbv(0)[AXIS_PCIE_CC_USER_WIDTH:])
|
||||
m_axis_cc_tvalid = Signal(bool(0))
|
||||
status_error_cor = Signal(bool(0))
|
||||
status_error_uncor = Signal(bool(0))
|
||||
cfg_mgmt_addr = Signal(intbv(0)[10:])
|
||||
cfg_mgmt_function_number = Signal(intbv(0)[8:])
|
||||
cfg_mgmt_write = Signal(bool(0))
|
||||
cfg_mgmt_write_data = Signal(intbv(0)[32:])
|
||||
cfg_mgmt_byte_enable = Signal(intbv(0)[4:])
|
||||
cfg_mgmt_read = Signal(bool(0))
|
||||
cfg_interrupt_msi_int = Signal(intbv(0)[32:])
|
||||
cfg_interrupt_msi_pending_status = Signal(intbv(0)[32:])
|
||||
cfg_interrupt_msi_select = Signal(intbv(0)[2:])
|
||||
cfg_interrupt_msi_pending_status_function_num = Signal(intbv(0)[2:])
|
||||
cfg_interrupt_msi_pending_status_data_enable = Signal(bool(0))
|
||||
cfg_interrupt_msi_attr = Signal(intbv(0)[3:])
|
||||
cfg_interrupt_msi_tph_present = Signal(bool(0))
|
||||
cfg_interrupt_msi_tph_type = Signal(intbv(0)[2:])
|
||||
cfg_interrupt_msi_tph_st_tag = Signal(intbv(0)[8:])
|
||||
cfg_interrupt_msi_function_number = Signal(intbv(0)[8:])
|
||||
|
||||
# Clock and Reset Interface
|
||||
user_clk=Signal(bool(0))
|
||||
user_reset=Signal(bool(0))
|
||||
sys_clk=Signal(bool(0))
|
||||
sys_reset=Signal(bool(0))
|
||||
|
||||
# PCIe devices
|
||||
rc = pcie.RootComplex()
|
||||
|
||||
mem_base, mem_data = rc.alloc_region(16*1024*1024)
|
||||
|
||||
dev = pcie_usp.UltrascalePlusPCIe()
|
||||
|
||||
dev.pcie_generation = 3
|
||||
dev.pcie_link_width = 8
|
||||
dev.user_clk_frequency = 250e6
|
||||
|
||||
dev.functions[0].msi_multiple_message_capable = 5
|
||||
|
||||
dev.functions[0].configure_bar(0, 4*1024*1024)
|
||||
dev.functions[0].configure_bar(1, 4*1024*1024)
|
||||
|
||||
rc.make_port().connect(dev)
|
||||
|
||||
pcie_logic = dev.create_logic(
|
||||
# Completer reQuest Interface
|
||||
m_axis_cq_tdata=s_axis_cq_tdata,
|
||||
m_axis_cq_tuser=s_axis_cq_tuser,
|
||||
m_axis_cq_tlast=s_axis_cq_tlast,
|
||||
m_axis_cq_tkeep=s_axis_cq_tkeep,
|
||||
m_axis_cq_tvalid=s_axis_cq_tvalid,
|
||||
m_axis_cq_tready=s_axis_cq_tready,
|
||||
#pcie_cq_np_req=pcie_cq_np_req,
|
||||
pcie_cq_np_req=Signal(intbv(1)[2:]),
|
||||
#pcie_cq_np_req_count=pcie_cq_np_req_count,
|
||||
|
||||
# Completer Completion Interface
|
||||
s_axis_cc_tdata=m_axis_cc_tdata,
|
||||
s_axis_cc_tuser=m_axis_cc_tuser,
|
||||
s_axis_cc_tlast=m_axis_cc_tlast,
|
||||
s_axis_cc_tkeep=m_axis_cc_tkeep,
|
||||
s_axis_cc_tvalid=m_axis_cc_tvalid,
|
||||
s_axis_cc_tready=m_axis_cc_tready,
|
||||
|
||||
# Requester reQuest Interface
|
||||
s_axis_rq_tdata=m_axis_rq_tdata,
|
||||
s_axis_rq_tuser=m_axis_rq_tuser,
|
||||
s_axis_rq_tlast=m_axis_rq_tlast,
|
||||
s_axis_rq_tkeep=m_axis_rq_tkeep,
|
||||
s_axis_rq_tvalid=m_axis_rq_tvalid,
|
||||
s_axis_rq_tready=m_axis_rq_tready,
|
||||
#pcie_rq_seq_num0=pcie_rq_seq_num0,
|
||||
#pcie_rq_seq_num_vld0=pcie_rq_seq_num_vld0,
|
||||
#pcie_rq_seq_num1=pcie_rq_seq_num1,
|
||||
#pcie_rq_seq_num_vld1=pcie_rq_seq_num_vld1,
|
||||
#pcie_rq_tag0=pcie_rq_tag0,
|
||||
#pcie_rq_tag1=pcie_rq_tag1,
|
||||
#pcie_rq_tag_av=pcie_rq_tag_av,
|
||||
#pcie_rq_tag_vld0=pcie_rq_tag_vld0,
|
||||
#pcie_rq_tag_vld1=pcie_rq_tag_vld1,
|
||||
|
||||
# Requester Completion Interface
|
||||
m_axis_rc_tdata=s_axis_rc_tdata,
|
||||
m_axis_rc_tuser=s_axis_rc_tuser,
|
||||
m_axis_rc_tlast=s_axis_rc_tlast,
|
||||
m_axis_rc_tkeep=s_axis_rc_tkeep,
|
||||
m_axis_rc_tvalid=s_axis_rc_tvalid,
|
||||
m_axis_rc_tready=s_axis_rc_tready,
|
||||
|
||||
# Transmit Flow Control Interface
|
||||
#pcie_tfc_nph_av=pcie_tfc_nph_av,
|
||||
#pcie_tfc_npd_av=pcie_tfc_npd_av,
|
||||
|
||||
# Configuration Management Interface
|
||||
cfg_mgmt_addr=cfg_mgmt_addr,
|
||||
cfg_mgmt_function_number=cfg_mgmt_function_number,
|
||||
cfg_mgmt_write=cfg_mgmt_write,
|
||||
cfg_mgmt_write_data=cfg_mgmt_write_data,
|
||||
cfg_mgmt_byte_enable=cfg_mgmt_byte_enable,
|
||||
cfg_mgmt_read=cfg_mgmt_read,
|
||||
cfg_mgmt_read_data=cfg_mgmt_read_data,
|
||||
cfg_mgmt_read_write_done=cfg_mgmt_read_write_done,
|
||||
#cfg_mgmt_debug_access=cfg_mgmt_debug_access,
|
||||
|
||||
# Configuration Status Interface
|
||||
#cfg_phy_link_down=cfg_phy_link_down,
|
||||
#cfg_phy_link_status=cfg_phy_link_status,
|
||||
#cfg_negotiated_width=cfg_negotiated_width,
|
||||
#cfg_current_speed=cfg_current_speed,
|
||||
cfg_max_payload=cfg_max_payload,
|
||||
cfg_max_read_req=cfg_max_read_req,
|
||||
#cfg_function_status=cfg_function_status,
|
||||
#cfg_vf_status=cfg_vf_status,
|
||||
#cfg_function_power_state=cfg_function_power_state,
|
||||
#cfg_vf_power_state=cfg_vf_power_state,
|
||||
#cfg_link_power_state=cfg_link_power_state,
|
||||
#cfg_err_cor_out=cfg_err_cor_out,
|
||||
#cfg_err_nonfatal_out=cfg_err_nonfatal_out,
|
||||
#cfg_err_fatal_out=cfg_err_fatal_out,
|
||||
#cfg_local_err_out=cfg_local_err_out,
|
||||
#cfg_local_err_valid=cfg_local_err_valid,
|
||||
#cfg_rx_pm_state=cfg_rx_pm_state,
|
||||
#cfg_tx_pm_state=cfg_tx_pm_state,
|
||||
#cfg_ltssm_state=cfg_ltssm_state,
|
||||
#cfg_rcb_status=cfg_rcb_status,
|
||||
#cfg_obff_enable=cfg_obff_enable,
|
||||
#cfg_pl_status_change=cfg_pl_status_change,
|
||||
#cfg_tph_requester_enable=cfg_tph_requester_enable,
|
||||
#cfg_tph_st_mode=cfg_tph_st_mode,
|
||||
#cfg_vf_tph_requester_enable=cfg_vf_tph_requester_enable,
|
||||
#cfg_vf_tph_st_mode=cfg_vf_tph_st_mode,
|
||||
|
||||
# Configuration Received Message Interface
|
||||
#cfg_msg_received=cfg_msg_received,
|
||||
#cfg_msg_received_data=cfg_msg_received_data,
|
||||
#cfg_msg_received_type=cfg_msg_received_type,
|
||||
|
||||
# Configuration Transmit Message Interface
|
||||
#cfg_msg_transmit=cfg_msg_transmit,
|
||||
#cfg_msg_transmit_type=cfg_msg_transmit_type,
|
||||
#cfg_msg_transmit_data=cfg_msg_transmit_data,
|
||||
#cfg_msg_transmit_done=cfg_msg_transmit_done,
|
||||
|
||||
# Configuration Flow Control Interface
|
||||
#cfg_fc_ph=cfg_fc_ph,
|
||||
#cfg_fc_pd=cfg_fc_pd,
|
||||
#cfg_fc_nph=cfg_fc_nph,
|
||||
#cfg_fc_npd=cfg_fc_npd,
|
||||
#cfg_fc_cplh=cfg_fc_cplh,
|
||||
#cfg_fc_cpld=cfg_fc_cpld,
|
||||
#cfg_fc_sel=cfg_fc_sel,
|
||||
|
||||
# Configuration Control Interface
|
||||
#cfg_hot_reset_in=cfg_hot_reset_in,
|
||||
#cfg_hot_reset_out=cfg_hot_reset_out,
|
||||
#cfg_config_space_enable=cfg_config_space_enable,
|
||||
#cfg_dsn=cfg_dsn,
|
||||
#cfg_ds_port_number=cfg_ds_port_number,
|
||||
#cfg_ds_bus_number=cfg_ds_bus_number,
|
||||
#cfg_ds_device_number=cfg_ds_device_number,
|
||||
#cfg_ds_function_number=cfg_ds_function_number,
|
||||
#cfg_power_state_change_ack=cfg_power_state_change_ack,
|
||||
#cfg_power_state_change_interrupt=cfg_power_state_change_interrupt,
|
||||
cfg_err_cor_in=status_error_cor,
|
||||
cfg_err_uncor_in=status_error_uncor,
|
||||
#cfg_flr_done=cfg_flr_done,
|
||||
#cfg_vf_flr_done=cfg_vf_flr_done,
|
||||
#cfg_flr_in_process=cfg_flr_in_process,
|
||||
#cfg_vf_flr_in_process=cfg_vf_flr_in_process,
|
||||
#cfg_req_pm_transition_l23_ready=cfg_req_pm_transition_l23_ready,
|
||||
#cfg_link_training_enable=cfg_link_training_enable,
|
||||
|
||||
# Configuration Interrupt Controller Interface
|
||||
#cfg_interrupt_int=cfg_interrupt_int,
|
||||
#cfg_interrupt_sent=cfg_interrupt_sent,
|
||||
#cfg_interrupt_pending=cfg_interrupt_pending,
|
||||
cfg_interrupt_msi_enable=cfg_interrupt_msi_enable,
|
||||
cfg_interrupt_msi_mmenable=cfg_interrupt_msi_mmenable,
|
||||
cfg_interrupt_msi_mask_update=cfg_interrupt_msi_mask_update,
|
||||
cfg_interrupt_msi_data=cfg_interrupt_msi_data,
|
||||
cfg_interrupt_msi_select=cfg_interrupt_msi_select,
|
||||
cfg_interrupt_msi_int=cfg_interrupt_msi_int,
|
||||
cfg_interrupt_msi_pending_status=cfg_interrupt_msi_pending_status,
|
||||
cfg_interrupt_msi_pending_status_data_enable=cfg_interrupt_msi_pending_status_data_enable,
|
||||
cfg_interrupt_msi_pending_status_function_num=cfg_interrupt_msi_pending_status_function_num,
|
||||
cfg_interrupt_msi_sent=cfg_interrupt_msi_sent,
|
||||
cfg_interrupt_msi_fail=cfg_interrupt_msi_fail,
|
||||
#cfg_interrupt_msix_enable=cfg_interrupt_msix_enable,
|
||||
#cfg_interrupt_msix_mask=cfg_interrupt_msix_mask,
|
||||
#cfg_interrupt_msix_vf_enable=cfg_interrupt_msix_vf_enable,
|
||||
#cfg_interrupt_msix_vf_mask=cfg_interrupt_msix_vf_mask,
|
||||
#cfg_interrupt_msix_address=cfg_interrupt_msix_address,
|
||||
#cfg_interrupt_msix_data=cfg_interrupt_msix_data,
|
||||
#cfg_interrupt_msix_int=cfg_interrupt_msix_int,
|
||||
#cfg_interrupt_msix_vec_pending=cfg_interrupt_msix_vec_pending,
|
||||
#cfg_interrupt_msix_vec_pending_status=cfg_interrupt_msix_vec_pending_status,
|
||||
cfg_interrupt_msi_attr=cfg_interrupt_msi_attr,
|
||||
cfg_interrupt_msi_tph_present=cfg_interrupt_msi_tph_present,
|
||||
cfg_interrupt_msi_tph_type=cfg_interrupt_msi_tph_type,
|
||||
cfg_interrupt_msi_tph_st_tag=cfg_interrupt_msi_tph_st_tag,
|
||||
cfg_interrupt_msi_function_number=cfg_interrupt_msi_function_number,
|
||||
|
||||
# Configuration Extend Interface
|
||||
#cfg_ext_read_received=cfg_ext_read_received,
|
||||
#cfg_ext_write_received=cfg_ext_write_received,
|
||||
#cfg_ext_register_number=cfg_ext_register_number,
|
||||
#cfg_ext_function_number=cfg_ext_function_number,
|
||||
#cfg_ext_write_data=cfg_ext_write_data,
|
||||
#cfg_ext_write_byte_enable=cfg_ext_write_byte_enable,
|
||||
#cfg_ext_read_data=cfg_ext_read_data,
|
||||
#cfg_ext_read_data_valid=cfg_ext_read_data_valid,
|
||||
|
||||
# Clock and Reset Interface
|
||||
user_clk=user_clk,
|
||||
user_reset=user_reset,
|
||||
#user_lnk_up=user_lnk_up,
|
||||
sys_clk=sys_clk,
|
||||
sys_clk_gt=sys_clk,
|
||||
sys_reset=sys_reset,
|
||||
#phy_rdy_out=phy_rdy_out
|
||||
)
|
||||
|
||||
# DUT
|
||||
if os.system(build_cmd):
|
||||
raise Exception("Error running build command")
|
||||
|
||||
dut = Cosimulation(
|
||||
"vvp -m myhdl %s.vvp -lxt2" % testbench,
|
||||
clk=user_clk,
|
||||
rst=user_reset,
|
||||
current_test=current_test,
|
||||
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_function_number=cfg_mgmt_function_number,
|
||||
cfg_mgmt_write=cfg_mgmt_write,
|
||||
cfg_mgmt_write_data=cfg_mgmt_write_data,
|
||||
cfg_mgmt_byte_enable=cfg_mgmt_byte_enable,
|
||||
cfg_mgmt_read=cfg_mgmt_read,
|
||||
cfg_mgmt_read_data=cfg_mgmt_read_data,
|
||||
cfg_mgmt_read_write_done=cfg_mgmt_read_write_done,
|
||||
cfg_interrupt_msi_enable=cfg_interrupt_msi_enable,
|
||||
cfg_interrupt_msi_int=cfg_interrupt_msi_int,
|
||||
cfg_interrupt_msi_sent=cfg_interrupt_msi_sent,
|
||||
cfg_interrupt_msi_fail=cfg_interrupt_msi_fail,
|
||||
cfg_interrupt_msi_mmenable=cfg_interrupt_msi_mmenable,
|
||||
cfg_interrupt_msi_pending_status=cfg_interrupt_msi_pending_status,
|
||||
cfg_interrupt_msi_mask_update=cfg_interrupt_msi_mask_update,
|
||||
cfg_interrupt_msi_select=cfg_interrupt_msi_select,
|
||||
cfg_interrupt_msi_data=cfg_interrupt_msi_data,
|
||||
cfg_interrupt_msi_pending_status_function_num=cfg_interrupt_msi_pending_status_function_num,
|
||||
cfg_interrupt_msi_pending_status_data_enable=cfg_interrupt_msi_pending_status_data_enable,
|
||||
cfg_interrupt_msi_attr=cfg_interrupt_msi_attr,
|
||||
cfg_interrupt_msi_tph_present=cfg_interrupt_msi_tph_present,
|
||||
cfg_interrupt_msi_tph_type=cfg_interrupt_msi_tph_type,
|
||||
cfg_interrupt_msi_tph_st_tag=cfg_interrupt_msi_tph_st_tag,
|
||||
cfg_interrupt_msi_function_number=cfg_interrupt_msi_function_number,
|
||||
status_error_cor=status_error_cor,
|
||||
status_error_uncor=status_error_uncor
|
||||
)
|
||||
|
||||
@always(delay(5))
|
||||
def clkgen():
|
||||
clk.next = not clk
|
||||
|
||||
@always_comb
|
||||
def clk_logic():
|
||||
sys_clk.next = clk
|
||||
sys_reset.next = not rst
|
||||
|
||||
@instance
|
||||
def check():
|
||||
yield delay(100)
|
||||
yield clk.posedge
|
||||
rst.next = 1
|
||||
yield clk.posedge
|
||||
rst.next = 0
|
||||
yield clk.posedge
|
||||
yield delay(100)
|
||||
yield clk.posedge
|
||||
|
||||
# testbench stimulus
|
||||
|
||||
current_tag = 1
|
||||
|
||||
yield clk.posedge
|
||||
print("test 1: enumeration")
|
||||
current_test.next = 1
|
||||
|
||||
yield rc.enumerate(enable_bus_mastering=True, configure_msi=True)
|
||||
|
||||
dev_pf0_bar0 = dev.functions[0].bar[0] & 0xfffffffc
|
||||
dev_pf0_bar1 = dev.functions[0].bar[1] & 0xfffffffc
|
||||
|
||||
yield delay(100)
|
||||
|
||||
yield clk.posedge
|
||||
print("test 2: memory write to bar 1")
|
||||
current_test.next = 2
|
||||
|
||||
yield rc.mem_write(dev_pf0_bar1, b'\x11\x22\x33\x44')
|
||||
|
||||
yield delay(100)
|
||||
|
||||
yield clk.posedge
|
||||
print("test 3: memory read from bar 1")
|
||||
current_test.next = 3
|
||||
|
||||
val = yield from rc.mem_read(dev_pf0_bar1, 4, 1000)
|
||||
print(val)
|
||||
assert val == b'\x11\x22\x33\x44'
|
||||
|
||||
yield delay(100)
|
||||
|
||||
yield clk.posedge
|
||||
print("test 4: test DMA")
|
||||
current_test.next = 4
|
||||
|
||||
# write packet data
|
||||
mem_data[0:1024] = bytearray([x%256 for x in range(1024)])
|
||||
|
||||
# enable DMA
|
||||
yield rc.mem_write(dev_pf0_bar0+0x100000, struct.pack('<L', 1))
|
||||
|
||||
# write pcie read descriptor
|
||||
yield rc.mem_write(dev_pf0_bar0+0x100100, struct.pack('<L', (mem_base+0x0000) & 0xffffffff))
|
||||
yield rc.mem_write(dev_pf0_bar0+0x100104, struct.pack('<L', (mem_base+0x0000 >> 32) & 0xffffffff))
|
||||
yield rc.mem_write(dev_pf0_bar0+0x100108, struct.pack('<L', (0x100) & 0xffffffff))
|
||||
yield rc.mem_write(dev_pf0_bar0+0x10010C, struct.pack('<L', (0x100 >> 32) & 0xffffffff))
|
||||
yield rc.mem_write(dev_pf0_bar0+0x100110, struct.pack('<L', 0x400))
|
||||
yield rc.mem_write(dev_pf0_bar0+0x100114, struct.pack('<L', 0xAA))
|
||||
|
||||
yield delay(2000)
|
||||
|
||||
# read status
|
||||
val = yield from rc.mem_read(dev_pf0_bar0+0x100118, 4)
|
||||
print(val)
|
||||
|
||||
# write pcie write descriptor
|
||||
yield rc.mem_write(dev_pf0_bar0+0x100200, struct.pack('<L', (mem_base+0x1000) & 0xffffffff))
|
||||
yield rc.mem_write(dev_pf0_bar0+0x100204, struct.pack('<L', (mem_base+0x1000 >> 32) & 0xffffffff))
|
||||
yield rc.mem_write(dev_pf0_bar0+0x100208, struct.pack('<L', (0x100) & 0xffffffff))
|
||||
yield rc.mem_write(dev_pf0_bar0+0x10020C, struct.pack('<L', (0x100 >> 32) & 0xffffffff))
|
||||
yield rc.mem_write(dev_pf0_bar0+0x100210, struct.pack('<L', 0x400))
|
||||
yield rc.mem_write(dev_pf0_bar0+0x100214, struct.pack('<L', 0x55))
|
||||
|
||||
yield delay(2000)
|
||||
|
||||
# read status
|
||||
val = yield from rc.mem_read(dev_pf0_bar0+0x100218, 4)
|
||||
print(val)
|
||||
|
||||
data = mem_data[0x1000:(0x1000)+64]
|
||||
for i in range(0, len(data), 16):
|
||||
print(" ".join(("{:02x}".format(c) for c in bytearray(data[i:i+16]))))
|
||||
|
||||
assert mem_data[0:1024] == mem_data[0x1000:0x1000+1024]
|
||||
|
||||
yield delay(100)
|
||||
|
||||
raise StopSimulation
|
||||
|
||||
return instances()
|
||||
|
||||
def test_bench():
|
||||
sim = Simulation(bench())
|
||||
sim.run()
|
||||
|
||||
if __name__ == '__main__':
|
||||
print("Running test...")
|
||||
test_bench()
|
@ -1,243 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2018 Alex Forencich
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
// Language: Verilog 2001
|
||||
|
||||
`timescale 1ns / 1ps
|
||||
|
||||
/*
|
||||
* Testbench for fpga_core
|
||||
*/
|
||||
module test_fpga_core;
|
||||
|
||||
// Parameters
|
||||
parameter AXIS_PCIE_DATA_WIDTH = 256;
|
||||
parameter AXIS_PCIE_KEEP_WIDTH = (AXIS_PCIE_DATA_WIDTH/32);
|
||||
parameter AXIS_PCIE_RC_USER_WIDTH = 75;
|
||||
parameter AXIS_PCIE_RQ_USER_WIDTH = 62;
|
||||
parameter AXIS_PCIE_CQ_USER_WIDTH = 88;
|
||||
parameter AXIS_PCIE_CC_USER_WIDTH = 33;
|
||||
|
||||
// Inputs
|
||||
reg clk = 0;
|
||||
reg rst = 0;
|
||||
reg [7:0] current_test = 0;
|
||||
|
||||
reg m_axis_rq_tready = 0;
|
||||
reg [AXIS_PCIE_DATA_WIDTH-1:0] s_axis_rc_tdata = 0;
|
||||
reg [AXIS_PCIE_KEEP_WIDTH-1:0] s_axis_rc_tkeep = 0;
|
||||
reg s_axis_rc_tlast = 0;
|
||||
reg [AXIS_PCIE_RC_USER_WIDTH-1:0] s_axis_rc_tuser = 0;
|
||||
reg s_axis_rc_tvalid = 0;
|
||||
reg [AXIS_PCIE_DATA_WIDTH-1:0] s_axis_cq_tdata = 0;
|
||||
reg [AXIS_PCIE_KEEP_WIDTH-1:0] s_axis_cq_tkeep = 0;
|
||||
reg s_axis_cq_tlast = 0;
|
||||
reg [AXIS_PCIE_CQ_USER_WIDTH-1:0] s_axis_cq_tuser = 0;
|
||||
reg s_axis_cq_tvalid = 0;
|
||||
reg m_axis_cc_tready = 0;
|
||||
reg [2:0] cfg_max_payload = 0;
|
||||
reg [2:0] cfg_max_read_req = 0;
|
||||
reg [31:0] cfg_mgmt_read_data = 0;
|
||||
reg cfg_mgmt_read_write_done = 0;
|
||||
reg [3:0] cfg_interrupt_msi_enable = 0;
|
||||
reg [11:0] cfg_interrupt_msi_mmenable = 0;
|
||||
reg cfg_interrupt_msi_mask_update = 0;
|
||||
reg [31:0] cfg_interrupt_msi_data = 0;
|
||||
reg cfg_interrupt_msi_sent = 0;
|
||||
reg cfg_interrupt_msi_fail = 0;
|
||||
|
||||
// Outputs
|
||||
wire [1:0] sfp_1_led;
|
||||
wire [1:0] sfp_2_led;
|
||||
wire [1:0] sma_led;
|
||||
wire [AXIS_PCIE_DATA_WIDTH-1:0] m_axis_rq_tdata;
|
||||
wire [AXIS_PCIE_KEEP_WIDTH-1:0] m_axis_rq_tkeep;
|
||||
wire m_axis_rq_tlast;
|
||||
wire [AXIS_PCIE_RQ_USER_WIDTH-1:0] m_axis_rq_tuser;
|
||||
wire m_axis_rq_tvalid;
|
||||
wire s_axis_rc_tready;
|
||||
wire s_axis_cq_tready;
|
||||
wire [AXIS_PCIE_DATA_WIDTH-1:0] m_axis_cc_tdata;
|
||||
wire [AXIS_PCIE_KEEP_WIDTH-1:0] m_axis_cc_tkeep;
|
||||
wire m_axis_cc_tlast;
|
||||
wire [AXIS_PCIE_CC_USER_WIDTH-1:0] m_axis_cc_tuser;
|
||||
wire m_axis_cc_tvalid;
|
||||
wire [9:0] cfg_mgmt_addr;
|
||||
wire [7:0] cfg_mgmt_function_number;
|
||||
wire cfg_mgmt_write;
|
||||
wire [31:0] cfg_mgmt_write_data;
|
||||
wire [3:0] cfg_mgmt_byte_enable;
|
||||
wire cfg_mgmt_read;
|
||||
wire [3:0] cfg_interrupt_msi_select;
|
||||
wire [31:0] cfg_interrupt_msi_int;
|
||||
wire [31:0] cfg_interrupt_msi_pending_status;
|
||||
wire cfg_interrupt_msi_pending_status_data_enable;
|
||||
wire [3:0] cfg_interrupt_msi_pending_status_function_num;
|
||||
wire [2:0] cfg_interrupt_msi_attr;
|
||||
wire cfg_interrupt_msi_tph_present;
|
||||
wire [1:0] cfg_interrupt_msi_tph_type;
|
||||
wire [8:0] cfg_interrupt_msi_tph_st_tag;
|
||||
wire [3:0] cfg_interrupt_msi_function_number;
|
||||
wire status_error_cor;
|
||||
wire status_error_uncor;
|
||||
|
||||
initial begin
|
||||
// myhdl integration
|
||||
$from_myhdl(
|
||||
clk,
|
||||
rst,
|
||||
current_test,
|
||||
m_axis_rq_tready,
|
||||
s_axis_rc_tdata,
|
||||
s_axis_rc_tkeep,
|
||||
s_axis_rc_tlast,
|
||||
s_axis_rc_tuser,
|
||||
s_axis_rc_tvalid,
|
||||
s_axis_cq_tdata,
|
||||
s_axis_cq_tkeep,
|
||||
s_axis_cq_tlast,
|
||||
s_axis_cq_tuser,
|
||||
s_axis_cq_tvalid,
|
||||
m_axis_cc_tready,
|
||||
cfg_max_payload,
|
||||
cfg_max_read_req,
|
||||
cfg_mgmt_read_data,
|
||||
cfg_mgmt_read_write_done,
|
||||
cfg_interrupt_msi_enable,
|
||||
cfg_interrupt_msi_mmenable,
|
||||
cfg_interrupt_msi_mask_update,
|
||||
cfg_interrupt_msi_data,
|
||||
cfg_interrupt_msi_sent,
|
||||
cfg_interrupt_msi_fail
|
||||
);
|
||||
$to_myhdl(
|
||||
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_function_number,
|
||||
cfg_mgmt_write,
|
||||
cfg_mgmt_write_data,
|
||||
cfg_mgmt_byte_enable,
|
||||
cfg_mgmt_read,
|
||||
cfg_interrupt_msi_select,
|
||||
cfg_interrupt_msi_int,
|
||||
cfg_interrupt_msi_pending_status,
|
||||
cfg_interrupt_msi_pending_status_data_enable,
|
||||
cfg_interrupt_msi_pending_status_function_num,
|
||||
cfg_interrupt_msi_attr,
|
||||
cfg_interrupt_msi_tph_present,
|
||||
cfg_interrupt_msi_tph_type,
|
||||
cfg_interrupt_msi_tph_st_tag,
|
||||
cfg_interrupt_msi_function_number,
|
||||
status_error_cor,
|
||||
status_error_uncor
|
||||
);
|
||||
|
||||
// dump file
|
||||
$dumpfile("test_fpga_core.lxt");
|
||||
$dumpvars(0, test_fpga_core);
|
||||
end
|
||||
|
||||
fpga_core #(
|
||||
.AXIS_PCIE_DATA_WIDTH(AXIS_PCIE_DATA_WIDTH),
|
||||
.AXIS_PCIE_KEEP_WIDTH(AXIS_PCIE_KEEP_WIDTH),
|
||||
.AXIS_PCIE_RC_USER_WIDTH(AXIS_PCIE_RC_USER_WIDTH),
|
||||
.AXIS_PCIE_RQ_USER_WIDTH(AXIS_PCIE_RQ_USER_WIDTH),
|
||||
.AXIS_PCIE_CQ_USER_WIDTH(AXIS_PCIE_CQ_USER_WIDTH),
|
||||
.AXIS_PCIE_CC_USER_WIDTH(AXIS_PCIE_CC_USER_WIDTH)
|
||||
)
|
||||
UUT (
|
||||
.clk(clk),
|
||||
.rst(rst),
|
||||
.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_function_number(cfg_mgmt_function_number),
|
||||
.cfg_mgmt_write(cfg_mgmt_write),
|
||||
.cfg_mgmt_write_data(cfg_mgmt_write_data),
|
||||
.cfg_mgmt_byte_enable(cfg_mgmt_byte_enable),
|
||||
.cfg_mgmt_read(cfg_mgmt_read),
|
||||
.cfg_mgmt_read_data(cfg_mgmt_read_data),
|
||||
.cfg_mgmt_read_write_done(cfg_mgmt_read_write_done),
|
||||
.cfg_interrupt_msi_enable(cfg_interrupt_msi_enable),
|
||||
.cfg_interrupt_msi_mmenable(cfg_interrupt_msi_mmenable),
|
||||
.cfg_interrupt_msi_mask_update(cfg_interrupt_msi_mask_update),
|
||||
.cfg_interrupt_msi_data(cfg_interrupt_msi_data),
|
||||
.cfg_interrupt_msi_select(cfg_interrupt_msi_select),
|
||||
.cfg_interrupt_msi_int(cfg_interrupt_msi_int),
|
||||
.cfg_interrupt_msi_pending_status(cfg_interrupt_msi_pending_status),
|
||||
.cfg_interrupt_msi_pending_status_data_enable(cfg_interrupt_msi_pending_status_data_enable),
|
||||
.cfg_interrupt_msi_pending_status_function_num(cfg_interrupt_msi_pending_status_function_num),
|
||||
.cfg_interrupt_msi_sent(cfg_interrupt_msi_sent),
|
||||
.cfg_interrupt_msi_fail(cfg_interrupt_msi_fail),
|
||||
.cfg_interrupt_msi_attr(cfg_interrupt_msi_attr),
|
||||
.cfg_interrupt_msi_tph_present(cfg_interrupt_msi_tph_present),
|
||||
.cfg_interrupt_msi_tph_type(cfg_interrupt_msi_tph_type),
|
||||
.cfg_interrupt_msi_tph_st_tag(cfg_interrupt_msi_tph_st_tag),
|
||||
.cfg_interrupt_msi_function_number(cfg_interrupt_msi_function_number),
|
||||
.status_error_cor(status_error_cor),
|
||||
.status_error_uncor(status_error_uncor)
|
||||
);
|
||||
|
||||
endmodule
|
@ -1 +0,0 @@
|
||||
../lib/pcie/tb/axis_ep.py
|
107
example/VCU108/fpga_axi/tb/fpga_core/Makefile
Normal file
107
example/VCU108/fpga_axi/tb/fpga_core/Makefile
Normal file
@ -0,0 +1,107 @@
|
||||
# Copyright (c) 2020 Alex Forencich
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in
|
||||
# all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
# THE SOFTWARE.
|
||||
|
||||
TOPLEVEL_LANG = verilog
|
||||
|
||||
SIM ?= icarus
|
||||
WAVES ?= 0
|
||||
|
||||
COCOTB_HDL_TIMEUNIT = 1ns
|
||||
COCOTB_HDL_TIMEPRECISION = 1ps
|
||||
|
||||
DUT = fpga_core
|
||||
TOPLEVEL = $(DUT)
|
||||
MODULE = test_$(DUT)
|
||||
VERILOG_SOURCES += ../../rtl/$(DUT).v
|
||||
VERILOG_SOURCES += ../../rtl/axi_ram.v
|
||||
VERILOG_SOURCES += ../../rtl/axis_register.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/axis_arb_mux.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_axil_master.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_axi_dma.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_axi_dma_rd.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_axi_dma_wr.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_tag_manager.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_axi_master.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_axi_master_rd.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_axi_master_wr.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_axis_cq_demux.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_cfg.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_msi.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/arbiter.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/priority_encoder.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pulse_merge.v
|
||||
|
||||
# module parameters
|
||||
export PARAM_AXIS_PCIE_DATA_WIDTH ?= 256
|
||||
export PARAM_AXIS_PCIE_KEEP_WIDTH ?= $(shell expr $(PARAM_AXIS_PCIE_DATA_WIDTH) / 32 )
|
||||
export PARAM_AXIS_PCIE_RQ_USER_WIDTH ?= 60
|
||||
export PARAM_AXIS_PCIE_RC_USER_WIDTH ?= 75
|
||||
export PARAM_AXIS_PCIE_CQ_USER_WIDTH ?= 85
|
||||
export PARAM_AXIS_PCIE_CC_USER_WIDTH ?= 33
|
||||
export PARAM_RQ_SEQ_NUM_WIDTH ?= 4
|
||||
|
||||
SIM_BUILD ?= sim_build_$(MODULE)
|
||||
|
||||
ifeq ($(SIM), icarus)
|
||||
PLUSARGS += -fst
|
||||
|
||||
COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_DATA_WIDTH=$(PARAM_AXIS_PCIE_DATA_WIDTH)
|
||||
COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_KEEP_WIDTH=$(PARAM_AXIS_PCIE_KEEP_WIDTH)
|
||||
COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_RQ_USER_WIDTH=$(PARAM_AXIS_PCIE_RQ_USER_WIDTH)
|
||||
COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_RC_USER_WIDTH=$(PARAM_AXIS_PCIE_RC_USER_WIDTH)
|
||||
COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_CQ_USER_WIDTH=$(PARAM_AXIS_PCIE_CQ_USER_WIDTH)
|
||||
COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_CC_USER_WIDTH=$(PARAM_AXIS_PCIE_CC_USER_WIDTH)
|
||||
COMPILE_ARGS += -P $(TOPLEVEL).RQ_SEQ_NUM_WIDTH=$(PARAM_RQ_SEQ_NUM_WIDTH)
|
||||
|
||||
ifeq ($(WAVES), 1)
|
||||
VERILOG_SOURCES += iverilog_dump.v
|
||||
COMPILE_ARGS += -s iverilog_dump
|
||||
endif
|
||||
else ifeq ($(SIM), verilator)
|
||||
COMPILE_ARGS += -Wno-SELRANGE -Wno-WIDTH
|
||||
|
||||
COMPILE_ARGS += -GAXIS_PCIE_DATA_WIDTH=$(PARAM_AXIS_PCIE_DATA_WIDTH)
|
||||
COMPILE_ARGS += -GAXIS_PCIE_KEEP_WIDTH=$(PARAM_AXIS_PCIE_KEEP_WIDTH)
|
||||
COMPILE_ARGS += -GAXIS_PCIE_RQ_USER_WIDTH=$(PARAM_AXIS_PCIE_RQ_USER_WIDTH)
|
||||
COMPILE_ARGS += -GAXIS_PCIE_RC_USER_WIDTH=$(PARAM_AXIS_PCIE_RC_USER_WIDTH)
|
||||
COMPILE_ARGS += -GAXIS_PCIE_CQ_USER_WIDTH=$(PARAM_AXIS_PCIE_CQ_USER_WIDTH)
|
||||
COMPILE_ARGS += -GAXIS_PCIE_CC_USER_WIDTH=$(PARAM_AXIS_PCIE_CC_USER_WIDTH)
|
||||
COMPILE_ARGS += -GRQ_SEQ_NUM_WIDTH=$(PARAM_RQ_SEQ_NUM_WIDTH)
|
||||
|
||||
ifeq ($(WAVES), 1)
|
||||
COMPILE_ARGS += --trace-fst
|
||||
endif
|
||||
endif
|
||||
|
||||
iverilog_dump.v:
|
||||
echo 'module iverilog_dump();' > $@
|
||||
echo 'initial begin' >> $@
|
||||
echo ' $$dumpfile("$(TOPLEVEL).fst");' >> $@
|
||||
echo ' $$dumpvars(0, $(TOPLEVEL));' >> $@
|
||||
echo 'end' >> $@
|
||||
echo 'endmodule' >> $@
|
||||
|
||||
clean::
|
||||
@rm -rf sim_build_*
|
||||
@rm -rf iverilog_dump.v
|
||||
@rm -rf dump.fst $(TOPLEVEL).fst
|
||||
|
||||
include $(shell cocotb-config --makefiles)/Makefile.sim
|
||||
|
383
example/VCU108/fpga_axi/tb/fpga_core/test_fpga_core.py
Normal file
383
example/VCU108/fpga_axi/tb/fpga_core/test_fpga_core.py
Normal file
@ -0,0 +1,383 @@
|
||||
"""
|
||||
|
||||
Copyright (c) 2020 Alex Forencich
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
"""
|
||||
|
||||
import logging
|
||||
import os
|
||||
|
||||
import cocotb_test.simulator
|
||||
|
||||
import cocotb
|
||||
from cocotb.log import SimLog
|
||||
from cocotb.triggers import RisingEdge, FallingEdge, Timer
|
||||
|
||||
from cocotbext.pcie.core import RootComplex
|
||||
from cocotbext.pcie.xilinx.us import UltraScalePcieDevice
|
||||
from cocotbext.axi.utils import hexdump_str
|
||||
|
||||
|
||||
class TB(object):
|
||||
def __init__(self, dut):
|
||||
self.dut = dut
|
||||
|
||||
self.log = SimLog("cocotb.tb")
|
||||
self.log.setLevel(logging.DEBUG)
|
||||
|
||||
# PCIe
|
||||
self.rc = RootComplex()
|
||||
|
||||
self.dev = UltraScalePcieDevice(
|
||||
# configuration options
|
||||
pcie_generation=3,
|
||||
pcie_link_width=8,
|
||||
user_clk_frequency=250e6,
|
||||
alignment="dword",
|
||||
straddle=False,
|
||||
enable_pf1=False,
|
||||
enable_client_tag=True,
|
||||
enable_extended_tag=True,
|
||||
enable_parity=False,
|
||||
enable_rx_msg_interface=False,
|
||||
enable_sriov=False,
|
||||
enable_extended_configuration=False,
|
||||
|
||||
enable_pf0_msi=True,
|
||||
enable_pf1_msi=False,
|
||||
|
||||
# signals
|
||||
# Clock and Reset Interface
|
||||
user_clk=dut.clk,
|
||||
user_reset=dut.rst,
|
||||
# user_lnk_up
|
||||
# sys_clk
|
||||
# sys_clk_gt
|
||||
# sys_reset
|
||||
# phy_rdy_out
|
||||
|
||||
# Requester reQuest Interface
|
||||
rq_entity=dut,
|
||||
rq_name="m_axis_rq",
|
||||
# pcie_rq_seq_num0=dut.s_axis_rq_seq_num_0,
|
||||
# pcie_rq_seq_num_vld0=dut.s_axis_rq_seq_num_valid_0,
|
||||
# pcie_rq_seq_num1=dut.s_axis_rq_seq_num_1,
|
||||
# pcie_rq_seq_num_vld1=dut.s_axis_rq_seq_num_valid_1,
|
||||
# pcie_rq_tag0
|
||||
# pcie_rq_tag1
|
||||
# pcie_rq_tag_av
|
||||
# pcie_rq_tag_vld0
|
||||
# pcie_rq_tag_vld1
|
||||
|
||||
# Requester Completion Interface
|
||||
rc_entity=dut,
|
||||
rc_name="s_axis_rc",
|
||||
|
||||
# Completer reQuest Interface
|
||||
cq_entity=dut,
|
||||
cq_name="s_axis_cq",
|
||||
# pcie_cq_np_req
|
||||
# pcie_cq_np_req_count
|
||||
|
||||
# Completer Completion Interface
|
||||
cc_entity=dut,
|
||||
cc_name="m_axis_cc",
|
||||
|
||||
# Transmit Flow Control Interface
|
||||
# pcie_tfc_nph_av=dut.pcie_tfc_nph_av,
|
||||
# pcie_tfc_npd_av=dut.pcie_tfc_npd_av,
|
||||
|
||||
# Configuration Management Interface
|
||||
cfg_mgmt_addr=dut.cfg_mgmt_addr,
|
||||
cfg_mgmt_write=dut.cfg_mgmt_write,
|
||||
cfg_mgmt_write_data=dut.cfg_mgmt_write_data,
|
||||
cfg_mgmt_byte_enable=dut.cfg_mgmt_byte_enable,
|
||||
cfg_mgmt_read=dut.cfg_mgmt_read,
|
||||
cfg_mgmt_read_data=dut.cfg_mgmt_read_data,
|
||||
cfg_mgmt_read_write_done=dut.cfg_mgmt_read_write_done,
|
||||
# cfg_mgmt_debug_access
|
||||
|
||||
# Configuration Status Interface
|
||||
# cfg_phy_link_down
|
||||
# cfg_phy_link_status
|
||||
# cfg_negotiated_width
|
||||
# cfg_current_speed
|
||||
cfg_max_payload=dut.cfg_max_payload,
|
||||
cfg_max_read_req=dut.cfg_max_read_req,
|
||||
# cfg_function_status
|
||||
# cfg_vf_status
|
||||
# cfg_function_power_state
|
||||
# cfg_vf_power_state
|
||||
# cfg_link_power_state
|
||||
# cfg_err_cor_out
|
||||
# cfg_err_nonfatal_out
|
||||
# cfg_err_fatal_out
|
||||
# cfg_local_error_out
|
||||
# cfg_local_error_valid
|
||||
# cfg_rx_pm_state
|
||||
# cfg_tx_pm_state
|
||||
# cfg_ltssm_state
|
||||
# cfg_rcb_status
|
||||
# cfg_obff_enable
|
||||
# cfg_pl_status_change
|
||||
# cfg_tph_requester_enable
|
||||
# cfg_tph_st_mode
|
||||
# cfg_vf_tph_requester_enable
|
||||
# cfg_vf_tph_st_mode
|
||||
|
||||
# Configuration Received Message Interface
|
||||
# cfg_msg_received
|
||||
# cfg_msg_received_data
|
||||
# cfg_msg_received_type
|
||||
|
||||
# Configuration Transmit Message Interface
|
||||
# cfg_msg_transmit
|
||||
# cfg_msg_transmit_type
|
||||
# cfg_msg_transmit_data
|
||||
# cfg_msg_transmit_done
|
||||
|
||||
# Configuration Flow Control Interface
|
||||
# cfg_fc_ph=dut.cfg_fc_ph,
|
||||
# cfg_fc_pd=dut.cfg_fc_pd,
|
||||
# cfg_fc_nph=dut.cfg_fc_nph,
|
||||
# cfg_fc_npd=dut.cfg_fc_npd,
|
||||
# cfg_fc_cplh=dut.cfg_fc_cplh,
|
||||
# cfg_fc_cpld=dut.cfg_fc_cpld,
|
||||
# cfg_fc_sel=dut.cfg_fc_sel,
|
||||
|
||||
# Configuration Control Interface
|
||||
# cfg_hot_reset_in
|
||||
# cfg_hot_reset_out
|
||||
# cfg_config_space_enable
|
||||
# cfg_dsn
|
||||
# cfg_bus_number
|
||||
# cfg_ds_port_number
|
||||
# cfg_ds_bus_number
|
||||
# cfg_ds_device_number
|
||||
# cfg_ds_function_number
|
||||
# cfg_power_state_change_ack
|
||||
# cfg_power_state_change_interrupt
|
||||
cfg_err_cor_in=dut.status_error_cor,
|
||||
cfg_err_uncor_in=dut.status_error_uncor,
|
||||
# cfg_flr_in_process
|
||||
# cfg_flr_done
|
||||
# cfg_vf_flr_in_process
|
||||
# cfg_vf_flr_func_num
|
||||
# cfg_vf_flr_done
|
||||
# cfg_pm_aspm_l1_entry_reject
|
||||
# cfg_pm_aspm_tx_l0s_entry_disable
|
||||
# cfg_req_pm_transition_l23_ready
|
||||
# cfg_link_training_enable
|
||||
|
||||
# Configuration Interrupt Controller Interface
|
||||
# cfg_interrupt_int
|
||||
# cfg_interrupt_sent
|
||||
# cfg_interrupt_pending
|
||||
cfg_interrupt_msi_enable=dut.cfg_interrupt_msi_enable,
|
||||
cfg_interrupt_msi_vf_enable=dut.cfg_interrupt_msi_vf_enable,
|
||||
cfg_interrupt_msi_mmenable=dut.cfg_interrupt_msi_mmenable,
|
||||
cfg_interrupt_msi_mask_update=dut.cfg_interrupt_msi_mask_update,
|
||||
cfg_interrupt_msi_data=dut.cfg_interrupt_msi_data,
|
||||
cfg_interrupt_msi_select=dut.cfg_interrupt_msi_select,
|
||||
cfg_interrupt_msi_int=dut.cfg_interrupt_msi_int,
|
||||
cfg_interrupt_msi_pending_status=dut.cfg_interrupt_msi_pending_status,
|
||||
cfg_interrupt_msi_pending_status_data_enable=dut.cfg_interrupt_msi_pending_status_data_enable,
|
||||
cfg_interrupt_msi_pending_status_function_num=dut.cfg_interrupt_msi_pending_status_function_num,
|
||||
cfg_interrupt_msi_sent=dut.cfg_interrupt_msi_sent,
|
||||
cfg_interrupt_msi_fail=dut.cfg_interrupt_msi_fail,
|
||||
# cfg_interrupt_msix_enable
|
||||
# cfg_interrupt_msix_mask
|
||||
# cfg_interrupt_msix_vf_enable
|
||||
# cfg_interrupt_msix_vf_mask
|
||||
# cfg_interrupt_msix_address
|
||||
# cfg_interrupt_msix_data
|
||||
# cfg_interrupt_msix_int
|
||||
# cfg_interrupt_msix_vec_pending
|
||||
# cfg_interrupt_msix_vec_pending_status
|
||||
cfg_interrupt_msi_attr=dut.cfg_interrupt_msi_attr,
|
||||
cfg_interrupt_msi_tph_present=dut.cfg_interrupt_msi_tph_present,
|
||||
cfg_interrupt_msi_tph_type=dut.cfg_interrupt_msi_tph_type,
|
||||
# cfg_interrupt_msi_tph_st_tag=dut.cfg_interrupt_msi_tph_st_tag,
|
||||
# cfg_interrupt_msi_function_number=dut.cfg_interrupt_msi_function_number,
|
||||
|
||||
# Configuration Extend Interface
|
||||
# cfg_ext_read_received
|
||||
# cfg_ext_write_received
|
||||
# cfg_ext_register_number
|
||||
# cfg_ext_function_number
|
||||
# cfg_ext_write_data
|
||||
# cfg_ext_write_byte_enable
|
||||
# cfg_ext_read_data
|
||||
# cfg_ext_read_data_valid
|
||||
)
|
||||
|
||||
# self.dev.log.setLevel(logging.DEBUG)
|
||||
|
||||
self.rc.make_port().connect(self.dev)
|
||||
|
||||
self.dev.functions[0].msi_multiple_message_capable = 5
|
||||
|
||||
self.dev.functions[0].configure_bar(0, 2**22)
|
||||
self.dev.functions[0].configure_bar(1, 2**22)
|
||||
|
||||
dut.btnu.setimmediatevalue(0)
|
||||
dut.btnl.setimmediatevalue(0)
|
||||
dut.btnd.setimmediatevalue(0)
|
||||
dut.btnr.setimmediatevalue(0)
|
||||
dut.btnc.setimmediatevalue(0)
|
||||
dut.sw.setimmediatevalue(0)
|
||||
|
||||
async def init(self):
|
||||
|
||||
await FallingEdge(self.dut.rst)
|
||||
await Timer(100, 'ns')
|
||||
|
||||
await self.rc.enumerate(enable_bus_mastering=True, configure_msi=True)
|
||||
|
||||
|
||||
@cocotb.test()
|
||||
async def run_test(dut):
|
||||
|
||||
tb = TB(dut)
|
||||
|
||||
await tb.init()
|
||||
|
||||
mem_base, mem_data = tb.rc.alloc_region(16*1024*1024)
|
||||
|
||||
dev_pf0_bar0 = tb.rc.tree[0][0].bar_addr[0]
|
||||
dev_pf0_bar1 = tb.rc.tree[0][0].bar_addr[1]
|
||||
|
||||
tb.log.info("Test memory write to BAR 1")
|
||||
|
||||
await tb.rc.mem_write(dev_pf0_bar1, b'\x11\x22\x33\x44')
|
||||
|
||||
await Timer(100, 'ns')
|
||||
|
||||
tb.log.info("Test memory read from BAR 1")
|
||||
|
||||
val = await tb.rc.mem_read(dev_pf0_bar1, 4, 1000)
|
||||
tb.log.info("Read data: %s", val)
|
||||
assert val == b'\x11\x22\x33\x44'
|
||||
|
||||
tb.log.info("Test DMA")
|
||||
|
||||
# write packet data
|
||||
mem_data[0:1024] = bytearray([x % 256 for x in range(1024)])
|
||||
|
||||
# enable DMA
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100000, 1)
|
||||
|
||||
# write pcie read descriptor
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100100, (mem_base+0x0000) & 0xffffffff)
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100104, (mem_base+0x0000 >> 32) & 0xffffffff)
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100108, (0x100) & 0xffffffff)
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x10010C, (0x100 >> 32) & 0xffffffff)
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100110, 0x400)
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100114, 0xAA)
|
||||
|
||||
await Timer(2000, 'ns')
|
||||
|
||||
# read status
|
||||
val = await tb.rc.mem_read_dword(dev_pf0_bar0+0x100118)
|
||||
tb.log.info("Status: 0x%x", val)
|
||||
assert val == 0xAA
|
||||
|
||||
# write pcie write descriptor
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100200, (mem_base+0x1000) & 0xffffffff)
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100204, (mem_base+0x1000 >> 32) & 0xffffffff)
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100208, (0x100) & 0xffffffff)
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x10020C, (0x100 >> 32) & 0xffffffff)
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100210, 0x400)
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100214, 0x55)
|
||||
|
||||
await Timer(2000, 'ns')
|
||||
|
||||
# read status
|
||||
val = await tb.rc.mem_read_dword(dev_pf0_bar0+0x100218)
|
||||
tb.log.info("Status: 0x%x", val)
|
||||
assert val == 0x55
|
||||
|
||||
tb.log.info("%s", hexdump_str(mem_data, 0x1000, 64))
|
||||
|
||||
assert mem_data[0:1024] == mem_data[0x1000:0x1000+1024]
|
||||
|
||||
await RisingEdge(dut.clk)
|
||||
await RisingEdge(dut.clk)
|
||||
|
||||
|
||||
# cocotb-test
|
||||
|
||||
tests_dir = os.path.dirname(__file__)
|
||||
rtl_dir = os.path.abspath(os.path.join(tests_dir, '..', '..', 'rtl'))
|
||||
lib_dir = os.path.abspath(os.path.join(rtl_dir, '..', 'lib'))
|
||||
pcie_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'pcie', 'rtl'))
|
||||
|
||||
|
||||
def test_fpga_core(request):
|
||||
dut = "fpga_core"
|
||||
module = os.path.splitext(os.path.basename(__file__))[0]
|
||||
toplevel = dut
|
||||
|
||||
verilog_sources = [
|
||||
os.path.join(rtl_dir, f"{dut}.v"),
|
||||
os.path.join(rtl_dir, "axi_ram.v"),
|
||||
os.path.join(rtl_dir, "axis_register.v"),
|
||||
os.path.join(pcie_rtl_dir, "axis_arb_mux.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_us_axil_master.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_us_axi_dma.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_us_axi_dma_rd.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_us_axi_dma_wr.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_tag_manager.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_us_axi_master.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_us_axi_master_rd.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_us_axi_master_wr.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_us_axis_cq_demux.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_us_cfg.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_us_msi.v"),
|
||||
os.path.join(pcie_rtl_dir, "arbiter.v"),
|
||||
os.path.join(pcie_rtl_dir, "priority_encoder.v"),
|
||||
os.path.join(pcie_rtl_dir, "pulse_merge.v"),
|
||||
]
|
||||
|
||||
parameters = {}
|
||||
|
||||
parameters['AXIS_PCIE_DATA_WIDTH'] = 256
|
||||
parameters['AXIS_PCIE_KEEP_WIDTH'] = parameters['AXIS_PCIE_DATA_WIDTH'] // 32
|
||||
parameters['AXIS_PCIE_RQ_USER_WIDTH'] = 60
|
||||
parameters['AXIS_PCIE_RC_USER_WIDTH'] = 75
|
||||
parameters['AXIS_PCIE_CQ_USER_WIDTH'] = 85
|
||||
parameters['AXIS_PCIE_CC_USER_WIDTH'] = 33
|
||||
parameters['RQ_SEQ_NUM_WIDTH'] = 4
|
||||
|
||||
extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()}
|
||||
|
||||
sim_build = os.path.join(tests_dir,
|
||||
"sim_build_"+request.node.name.replace('[', '-').replace(']', ''))
|
||||
|
||||
cocotb_test.simulator.run(
|
||||
python_search=[tests_dir],
|
||||
verilog_sources=verilog_sources,
|
||||
toplevel=toplevel,
|
||||
module=module,
|
||||
parameters=parameters,
|
||||
sim_build=sim_build,
|
||||
extra_env=extra_env,
|
||||
)
|
@ -1 +0,0 @@
|
||||
../lib/pcie/tb/pcie.py
|
@ -1 +0,0 @@
|
||||
../lib/pcie/tb/pcie_us.py
|
@ -1,515 +0,0 @@
|
||||
#!/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:])
|
||||
|
||||
btnu = Signal(bool(0))
|
||||
btnl = Signal(bool(0))
|
||||
btnd = Signal(bool(0))
|
||||
btnr = Signal(bool(0))
|
||||
btnc = Signal(bool(0))
|
||||
sw = Signal(intbv(0)[4:])
|
||||
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
|
||||
led = Signal(intbv(0)[8:])
|
||||
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_clk_frequency = 250e6
|
||||
|
||||
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,
|
||||
btnu=btnu,
|
||||
btnl=btnl,
|
||||
btnd=btnd,
|
||||
btnr=btnr,
|
||||
btnc=btnc,
|
||||
sw=sw,
|
||||
led=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()
|
@ -1,242 +0,0 @@
|
||||
/*
|
||||
|
||||
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 btnu = 0;
|
||||
reg btnl = 0;
|
||||
reg btnd = 0;
|
||||
reg btnr = 0;
|
||||
reg btnc = 0;
|
||||
reg [3:0] sw = 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 [7:0] 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,
|
||||
btnu,
|
||||
btnl,
|
||||
btnd,
|
||||
btnr,
|
||||
btnc,
|
||||
sw,
|
||||
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(
|
||||
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),
|
||||
.btnu(btnu),
|
||||
.btnl(btnl),
|
||||
.btnd(btnd),
|
||||
.btnr(btnr),
|
||||
.btnc(btnc),
|
||||
.sw(sw),
|
||||
.led(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
|
@ -1 +0,0 @@
|
||||
../lib/pcie/tb/axis_ep.py
|
107
example/VCU118/fpga_axi_x8/tb/fpga_core/Makefile
Normal file
107
example/VCU118/fpga_axi_x8/tb/fpga_core/Makefile
Normal file
@ -0,0 +1,107 @@
|
||||
# Copyright (c) 2020 Alex Forencich
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in
|
||||
# all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
# THE SOFTWARE.
|
||||
|
||||
TOPLEVEL_LANG = verilog
|
||||
|
||||
SIM ?= icarus
|
||||
WAVES ?= 0
|
||||
|
||||
COCOTB_HDL_TIMEUNIT = 1ns
|
||||
COCOTB_HDL_TIMEPRECISION = 1ps
|
||||
|
||||
DUT = fpga_core
|
||||
TOPLEVEL = $(DUT)
|
||||
MODULE = test_$(DUT)
|
||||
VERILOG_SOURCES += ../../rtl/$(DUT).v
|
||||
VERILOG_SOURCES += ../../rtl/axi_ram.v
|
||||
VERILOG_SOURCES += ../../rtl/axis_register.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/axis_arb_mux.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_axil_master.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_axi_dma.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_axi_dma_rd.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_axi_dma_wr.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_tag_manager.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_axi_master.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_axi_master_rd.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_axi_master_wr.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_axis_cq_demux.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_cfg.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_msi.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/arbiter.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/priority_encoder.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pulse_merge.v
|
||||
|
||||
# module parameters
|
||||
export PARAM_AXIS_PCIE_DATA_WIDTH ?= 256
|
||||
export PARAM_AXIS_PCIE_KEEP_WIDTH ?= $(shell expr $(PARAM_AXIS_PCIE_DATA_WIDTH) / 32 )
|
||||
export PARAM_AXIS_PCIE_RQ_USER_WIDTH ?= $(if $(filter-out 512,$(PARAM_AXIS_PCIE_DATA_WIDTH)),62,137)
|
||||
export PARAM_AXIS_PCIE_RC_USER_WIDTH ?= $(if $(filter-out 512,$(PARAM_AXIS_PCIE_DATA_WIDTH)),75,161)
|
||||
export PARAM_AXIS_PCIE_CQ_USER_WIDTH ?= $(if $(filter-out 512,$(PARAM_AXIS_PCIE_DATA_WIDTH)),88,183)
|
||||
export PARAM_AXIS_PCIE_CC_USER_WIDTH ?= $(if $(filter-out 512,$(PARAM_AXIS_PCIE_DATA_WIDTH)),33,81)
|
||||
export PARAM_RQ_SEQ_NUM_WIDTH ?= 6
|
||||
|
||||
SIM_BUILD ?= sim_build_$(MODULE)
|
||||
|
||||
ifeq ($(SIM), icarus)
|
||||
PLUSARGS += -fst
|
||||
|
||||
COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_DATA_WIDTH=$(PARAM_AXIS_PCIE_DATA_WIDTH)
|
||||
COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_KEEP_WIDTH=$(PARAM_AXIS_PCIE_KEEP_WIDTH)
|
||||
COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_RQ_USER_WIDTH=$(PARAM_AXIS_PCIE_RQ_USER_WIDTH)
|
||||
COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_RC_USER_WIDTH=$(PARAM_AXIS_PCIE_RC_USER_WIDTH)
|
||||
COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_CQ_USER_WIDTH=$(PARAM_AXIS_PCIE_CQ_USER_WIDTH)
|
||||
COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_CC_USER_WIDTH=$(PARAM_AXIS_PCIE_CC_USER_WIDTH)
|
||||
COMPILE_ARGS += -P $(TOPLEVEL).RQ_SEQ_NUM_WIDTH=$(PARAM_RQ_SEQ_NUM_WIDTH)
|
||||
|
||||
ifeq ($(WAVES), 1)
|
||||
VERILOG_SOURCES += iverilog_dump.v
|
||||
COMPILE_ARGS += -s iverilog_dump
|
||||
endif
|
||||
else ifeq ($(SIM), verilator)
|
||||
COMPILE_ARGS += -Wno-SELRANGE -Wno-WIDTH
|
||||
|
||||
COMPILE_ARGS += -GAXIS_PCIE_DATA_WIDTH=$(PARAM_AXIS_PCIE_DATA_WIDTH)
|
||||
COMPILE_ARGS += -GAXIS_PCIE_KEEP_WIDTH=$(PARAM_AXIS_PCIE_KEEP_WIDTH)
|
||||
COMPILE_ARGS += -GAXIS_PCIE_RQ_USER_WIDTH=$(PARAM_AXIS_PCIE_RQ_USER_WIDTH)
|
||||
COMPILE_ARGS += -GAXIS_PCIE_RC_USER_WIDTH=$(PARAM_AXIS_PCIE_RC_USER_WIDTH)
|
||||
COMPILE_ARGS += -GAXIS_PCIE_CQ_USER_WIDTH=$(PARAM_AXIS_PCIE_CQ_USER_WIDTH)
|
||||
COMPILE_ARGS += -GAXIS_PCIE_CC_USER_WIDTH=$(PARAM_AXIS_PCIE_CC_USER_WIDTH)
|
||||
COMPILE_ARGS += -GRQ_SEQ_NUM_WIDTH=$(PARAM_RQ_SEQ_NUM_WIDTH)
|
||||
|
||||
ifeq ($(WAVES), 1)
|
||||
COMPILE_ARGS += --trace-fst
|
||||
endif
|
||||
endif
|
||||
|
||||
iverilog_dump.v:
|
||||
echo 'module iverilog_dump();' > $@
|
||||
echo 'initial begin' >> $@
|
||||
echo ' $$dumpfile("$(TOPLEVEL).fst");' >> $@
|
||||
echo ' $$dumpvars(0, $(TOPLEVEL));' >> $@
|
||||
echo 'end' >> $@
|
||||
echo 'endmodule' >> $@
|
||||
|
||||
clean::
|
||||
@rm -rf sim_build_*
|
||||
@rm -rf iverilog_dump.v
|
||||
@rm -rf dump.fst $(TOPLEVEL).fst
|
||||
|
||||
include $(shell cocotb-config --makefiles)/Makefile.sim
|
||||
|
385
example/VCU118/fpga_axi_x8/tb/fpga_core/test_fpga_core.py
Normal file
385
example/VCU118/fpga_axi_x8/tb/fpga_core/test_fpga_core.py
Normal file
@ -0,0 +1,385 @@
|
||||
"""
|
||||
|
||||
Copyright (c) 2020 Alex Forencich
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
"""
|
||||
|
||||
import logging
|
||||
import os
|
||||
|
||||
import cocotb_test.simulator
|
||||
|
||||
import cocotb
|
||||
from cocotb.log import SimLog
|
||||
from cocotb.triggers import RisingEdge, FallingEdge, Timer
|
||||
|
||||
from cocotbext.pcie.core import RootComplex
|
||||
from cocotbext.pcie.xilinx.us import UltraScalePlusPcieDevice
|
||||
from cocotbext.axi.utils import hexdump_str
|
||||
|
||||
|
||||
class TB(object):
|
||||
def __init__(self, dut):
|
||||
self.dut = dut
|
||||
|
||||
self.log = SimLog("cocotb.tb")
|
||||
self.log.setLevel(logging.DEBUG)
|
||||
|
||||
# PCIe
|
||||
self.rc = RootComplex()
|
||||
|
||||
self.dev = UltraScalePlusPcieDevice(
|
||||
# configuration options
|
||||
pcie_generation=3,
|
||||
pcie_link_width=8,
|
||||
user_clk_frequency=250e6,
|
||||
alignment="dword",
|
||||
cq_cc_straddle=False,
|
||||
rq_rc_straddle=False,
|
||||
rc_4tlp_straddle=False,
|
||||
enable_pf1=False,
|
||||
enable_client_tag=True,
|
||||
enable_extended_tag=True,
|
||||
enable_parity=False,
|
||||
enable_rx_msg_interface=False,
|
||||
enable_sriov=False,
|
||||
enable_extended_configuration=False,
|
||||
|
||||
enable_pf0_msi=True,
|
||||
enable_pf1_msi=False,
|
||||
|
||||
# signals
|
||||
# Clock and Reset Interface
|
||||
user_clk=dut.clk,
|
||||
user_reset=dut.rst,
|
||||
# user_lnk_up
|
||||
# sys_clk
|
||||
# sys_clk_gt
|
||||
# sys_reset
|
||||
# phy_rdy_out
|
||||
|
||||
# Requester reQuest Interface
|
||||
rq_entity=dut,
|
||||
rq_name="m_axis_rq",
|
||||
# pcie_rq_seq_num0=dut.s_axis_rq_seq_num_0,
|
||||
# pcie_rq_seq_num_vld0=dut.s_axis_rq_seq_num_valid_0,
|
||||
# pcie_rq_seq_num1=dut.s_axis_rq_seq_num_1,
|
||||
# pcie_rq_seq_num_vld1=dut.s_axis_rq_seq_num_valid_1,
|
||||
# pcie_rq_tag0
|
||||
# pcie_rq_tag1
|
||||
# pcie_rq_tag_av
|
||||
# pcie_rq_tag_vld0
|
||||
# pcie_rq_tag_vld1
|
||||
|
||||
# Requester Completion Interface
|
||||
rc_entity=dut,
|
||||
rc_name="s_axis_rc",
|
||||
|
||||
# Completer reQuest Interface
|
||||
cq_entity=dut,
|
||||
cq_name="s_axis_cq",
|
||||
# pcie_cq_np_req
|
||||
# pcie_cq_np_req_count
|
||||
|
||||
# Completer Completion Interface
|
||||
cc_entity=dut,
|
||||
cc_name="m_axis_cc",
|
||||
|
||||
# Transmit Flow Control Interface
|
||||
# pcie_tfc_nph_av=dut.pcie_tfc_nph_av,
|
||||
# pcie_tfc_npd_av=dut.pcie_tfc_npd_av,
|
||||
|
||||
# Configuration Management Interface
|
||||
cfg_mgmt_addr=dut.cfg_mgmt_addr,
|
||||
cfg_mgmt_function_number=dut.cfg_mgmt_function_number,
|
||||
cfg_mgmt_write=dut.cfg_mgmt_write,
|
||||
cfg_mgmt_write_data=dut.cfg_mgmt_write_data,
|
||||
cfg_mgmt_byte_enable=dut.cfg_mgmt_byte_enable,
|
||||
cfg_mgmt_read=dut.cfg_mgmt_read,
|
||||
cfg_mgmt_read_data=dut.cfg_mgmt_read_data,
|
||||
cfg_mgmt_read_write_done=dut.cfg_mgmt_read_write_done,
|
||||
# cfg_mgmt_debug_access
|
||||
|
||||
# Configuration Status Interface
|
||||
# cfg_phy_link_down
|
||||
# cfg_phy_link_status
|
||||
# cfg_negotiated_width
|
||||
# cfg_current_speed
|
||||
cfg_max_payload=dut.cfg_max_payload,
|
||||
cfg_max_read_req=dut.cfg_max_read_req,
|
||||
# cfg_function_status
|
||||
# cfg_vf_status
|
||||
# cfg_function_power_state
|
||||
# cfg_vf_power_state
|
||||
# cfg_link_power_state
|
||||
# cfg_err_cor_out
|
||||
# cfg_err_nonfatal_out
|
||||
# cfg_err_fatal_out
|
||||
# cfg_local_error_out
|
||||
# cfg_local_error_valid
|
||||
# cfg_rx_pm_state
|
||||
# cfg_tx_pm_state
|
||||
# cfg_ltssm_state
|
||||
# cfg_rcb_status
|
||||
# cfg_obff_enable
|
||||
# cfg_pl_status_change
|
||||
# cfg_tph_requester_enable
|
||||
# cfg_tph_st_mode
|
||||
# cfg_vf_tph_requester_enable
|
||||
# cfg_vf_tph_st_mode
|
||||
|
||||
# Configuration Received Message Interface
|
||||
# cfg_msg_received
|
||||
# cfg_msg_received_data
|
||||
# cfg_msg_received_type
|
||||
|
||||
# Configuration Transmit Message Interface
|
||||
# cfg_msg_transmit
|
||||
# cfg_msg_transmit_type
|
||||
# cfg_msg_transmit_data
|
||||
# cfg_msg_transmit_done
|
||||
|
||||
# Configuration Flow Control Interface
|
||||
# cfg_fc_ph=dut.cfg_fc_ph,
|
||||
# cfg_fc_pd=dut.cfg_fc_pd,
|
||||
# cfg_fc_nph=dut.cfg_fc_nph,
|
||||
# cfg_fc_npd=dut.cfg_fc_npd,
|
||||
# cfg_fc_cplh=dut.cfg_fc_cplh,
|
||||
# cfg_fc_cpld=dut.cfg_fc_cpld,
|
||||
# cfg_fc_sel=dut.cfg_fc_sel,
|
||||
|
||||
# Configuration Control Interface
|
||||
# cfg_hot_reset_in
|
||||
# cfg_hot_reset_out
|
||||
# cfg_config_space_enable
|
||||
# cfg_dsn
|
||||
# cfg_bus_number
|
||||
# cfg_ds_port_number
|
||||
# cfg_ds_bus_number
|
||||
# cfg_ds_device_number
|
||||
# cfg_ds_function_number
|
||||
# cfg_power_state_change_ack
|
||||
# cfg_power_state_change_interrupt
|
||||
cfg_err_cor_in=dut.status_error_cor,
|
||||
cfg_err_uncor_in=dut.status_error_uncor,
|
||||
# cfg_flr_in_process
|
||||
# cfg_flr_done
|
||||
# cfg_vf_flr_in_process
|
||||
# cfg_vf_flr_func_num
|
||||
# cfg_vf_flr_done
|
||||
# cfg_pm_aspm_l1_entry_reject
|
||||
# cfg_pm_aspm_tx_l0s_entry_disable
|
||||
# cfg_req_pm_transition_l23_ready
|
||||
# cfg_link_training_enable
|
||||
|
||||
# Configuration Interrupt Controller Interface
|
||||
# cfg_interrupt_int
|
||||
# cfg_interrupt_sent
|
||||
# cfg_interrupt_pending
|
||||
cfg_interrupt_msi_enable=dut.cfg_interrupt_msi_enable,
|
||||
cfg_interrupt_msi_mmenable=dut.cfg_interrupt_msi_mmenable,
|
||||
cfg_interrupt_msi_mask_update=dut.cfg_interrupt_msi_mask_update,
|
||||
cfg_interrupt_msi_data=dut.cfg_interrupt_msi_data,
|
||||
# cfg_interrupt_msi_select=dut.cfg_interrupt_msi_select,
|
||||
cfg_interrupt_msi_int=dut.cfg_interrupt_msi_int,
|
||||
cfg_interrupt_msi_pending_status=dut.cfg_interrupt_msi_pending_status,
|
||||
cfg_interrupt_msi_pending_status_data_enable=dut.cfg_interrupt_msi_pending_status_data_enable,
|
||||
# cfg_interrupt_msi_pending_status_function_num=dut.cfg_interrupt_msi_pending_status_function_num,
|
||||
cfg_interrupt_msi_sent=dut.cfg_interrupt_msi_sent,
|
||||
cfg_interrupt_msi_fail=dut.cfg_interrupt_msi_fail,
|
||||
# cfg_interrupt_msix_enable
|
||||
# cfg_interrupt_msix_mask
|
||||
# cfg_interrupt_msix_vf_enable
|
||||
# cfg_interrupt_msix_vf_mask
|
||||
# cfg_interrupt_msix_address
|
||||
# cfg_interrupt_msix_data
|
||||
# cfg_interrupt_msix_int
|
||||
# cfg_interrupt_msix_vec_pending
|
||||
# cfg_interrupt_msix_vec_pending_status
|
||||
cfg_interrupt_msi_attr=dut.cfg_interrupt_msi_attr,
|
||||
cfg_interrupt_msi_tph_present=dut.cfg_interrupt_msi_tph_present,
|
||||
cfg_interrupt_msi_tph_type=dut.cfg_interrupt_msi_tph_type,
|
||||
# cfg_interrupt_msi_tph_st_tag=dut.cfg_interrupt_msi_tph_st_tag,
|
||||
# cfg_interrupt_msi_function_number=dut.cfg_interrupt_msi_function_number,
|
||||
|
||||
# Configuration Extend Interface
|
||||
# cfg_ext_read_received
|
||||
# cfg_ext_write_received
|
||||
# cfg_ext_register_number
|
||||
# cfg_ext_function_number
|
||||
# cfg_ext_write_data
|
||||
# cfg_ext_write_byte_enable
|
||||
# cfg_ext_read_data
|
||||
# cfg_ext_read_data_valid
|
||||
)
|
||||
|
||||
# self.dev.log.setLevel(logging.DEBUG)
|
||||
|
||||
self.rc.make_port().connect(self.dev)
|
||||
|
||||
self.dev.functions[0].msi_multiple_message_capable = 5
|
||||
|
||||
self.dev.functions[0].configure_bar(0, 2**22)
|
||||
self.dev.functions[0].configure_bar(1, 2**22)
|
||||
|
||||
dut.btnu.setimmediatevalue(0)
|
||||
dut.btnl.setimmediatevalue(0)
|
||||
dut.btnd.setimmediatevalue(0)
|
||||
dut.btnr.setimmediatevalue(0)
|
||||
dut.btnc.setimmediatevalue(0)
|
||||
dut.sw.setimmediatevalue(0)
|
||||
|
||||
async def init(self):
|
||||
|
||||
await FallingEdge(self.dut.rst)
|
||||
await Timer(100, 'ns')
|
||||
|
||||
await self.rc.enumerate(enable_bus_mastering=True, configure_msi=True)
|
||||
|
||||
|
||||
@cocotb.test()
|
||||
async def run_test(dut):
|
||||
|
||||
tb = TB(dut)
|
||||
|
||||
await tb.init()
|
||||
|
||||
mem_base, mem_data = tb.rc.alloc_region(16*1024*1024)
|
||||
|
||||
dev_pf0_bar0 = tb.rc.tree[0][0].bar_addr[0]
|
||||
dev_pf0_bar1 = tb.rc.tree[0][0].bar_addr[1]
|
||||
|
||||
tb.log.info("Test memory write to BAR 1")
|
||||
|
||||
await tb.rc.mem_write(dev_pf0_bar1, b'\x11\x22\x33\x44')
|
||||
|
||||
await Timer(100, 'ns')
|
||||
|
||||
tb.log.info("Test memory read from BAR 1")
|
||||
|
||||
val = await tb.rc.mem_read(dev_pf0_bar1, 4, 1000)
|
||||
tb.log.info("Read data: %s", val)
|
||||
assert val == b'\x11\x22\x33\x44'
|
||||
|
||||
tb.log.info("Test DMA")
|
||||
|
||||
# write packet data
|
||||
mem_data[0:1024] = bytearray([x % 256 for x in range(1024)])
|
||||
|
||||
# enable DMA
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100000, 1)
|
||||
|
||||
# write pcie read descriptor
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100100, (mem_base+0x0000) & 0xffffffff)
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100104, (mem_base+0x0000 >> 32) & 0xffffffff)
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100108, (0x100) & 0xffffffff)
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x10010C, (0x100 >> 32) & 0xffffffff)
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100110, 0x400)
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100114, 0xAA)
|
||||
|
||||
await Timer(2000, 'ns')
|
||||
|
||||
# read status
|
||||
val = await tb.rc.mem_read_dword(dev_pf0_bar0+0x100118)
|
||||
tb.log.info("Status: 0x%x", val)
|
||||
assert val == 0xAA
|
||||
|
||||
# write pcie write descriptor
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100200, (mem_base+0x1000) & 0xffffffff)
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100204, (mem_base+0x1000 >> 32) & 0xffffffff)
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100208, (0x100) & 0xffffffff)
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x10020C, (0x100 >> 32) & 0xffffffff)
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100210, 0x400)
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100214, 0x55)
|
||||
|
||||
await Timer(2000, 'ns')
|
||||
|
||||
# read status
|
||||
val = await tb.rc.mem_read_dword(dev_pf0_bar0+0x100218)
|
||||
tb.log.info("Status: 0x%x", val)
|
||||
assert val == 0x55
|
||||
|
||||
tb.log.info("%s", hexdump_str(mem_data, 0x1000, 64))
|
||||
|
||||
assert mem_data[0:1024] == mem_data[0x1000:0x1000+1024]
|
||||
|
||||
await RisingEdge(dut.clk)
|
||||
await RisingEdge(dut.clk)
|
||||
|
||||
|
||||
# cocotb-test
|
||||
|
||||
tests_dir = os.path.dirname(__file__)
|
||||
rtl_dir = os.path.abspath(os.path.join(tests_dir, '..', '..', 'rtl'))
|
||||
lib_dir = os.path.abspath(os.path.join(rtl_dir, '..', 'lib'))
|
||||
pcie_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'pcie', 'rtl'))
|
||||
|
||||
|
||||
def test_fpga_core(request):
|
||||
dut = "fpga_core"
|
||||
module = os.path.splitext(os.path.basename(__file__))[0]
|
||||
toplevel = dut
|
||||
|
||||
verilog_sources = [
|
||||
os.path.join(rtl_dir, f"{dut}.v"),
|
||||
os.path.join(rtl_dir, "axi_ram.v"),
|
||||
os.path.join(rtl_dir, "axis_register.v"),
|
||||
os.path.join(pcie_rtl_dir, "axis_arb_mux.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_us_axil_master.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_us_axi_dma.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_us_axi_dma_rd.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_us_axi_dma_wr.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_tag_manager.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_us_axi_master.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_us_axi_master_rd.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_us_axi_master_wr.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_us_axis_cq_demux.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_us_cfg.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_us_msi.v"),
|
||||
os.path.join(pcie_rtl_dir, "arbiter.v"),
|
||||
os.path.join(pcie_rtl_dir, "priority_encoder.v"),
|
||||
os.path.join(pcie_rtl_dir, "pulse_merge.v"),
|
||||
]
|
||||
|
||||
parameters = {}
|
||||
|
||||
parameters['AXIS_PCIE_DATA_WIDTH'] = 256
|
||||
parameters['AXIS_PCIE_KEEP_WIDTH'] = parameters['AXIS_PCIE_DATA_WIDTH'] // 32
|
||||
parameters['AXIS_PCIE_RQ_USER_WIDTH'] = 62 if parameters['AXIS_PCIE_DATA_WIDTH'] < 512 else 137
|
||||
parameters['AXIS_PCIE_RC_USER_WIDTH'] = 75 if parameters['AXIS_PCIE_DATA_WIDTH'] < 512 else 161
|
||||
parameters['AXIS_PCIE_CQ_USER_WIDTH'] = 88 if parameters['AXIS_PCIE_DATA_WIDTH'] < 512 else 183
|
||||
parameters['AXIS_PCIE_CC_USER_WIDTH'] = 33 if parameters['AXIS_PCIE_DATA_WIDTH'] < 512 else 81
|
||||
parameters['RQ_SEQ_NUM_WIDTH'] = 6
|
||||
|
||||
extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()}
|
||||
|
||||
sim_build = os.path.join(tests_dir,
|
||||
"sim_build_"+request.node.name.replace('[', '-').replace(']', ''))
|
||||
|
||||
cocotb_test.simulator.run(
|
||||
python_search=[tests_dir],
|
||||
verilog_sources=verilog_sources,
|
||||
toplevel=toplevel,
|
||||
module=module,
|
||||
parameters=parameters,
|
||||
sim_build=sim_build,
|
||||
extra_env=extra_env,
|
||||
)
|
@ -1 +0,0 @@
|
||||
../lib/pcie/tb/pcie.py
|
@ -1 +0,0 @@
|
||||
../lib/pcie/tb/pcie_us.py
|
@ -1 +0,0 @@
|
||||
../lib/pcie/tb/pcie_usp.py
|
@ -1,520 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
"""
|
||||
|
||||
Copyright (c) 2018 Alex Forencich
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
"""
|
||||
|
||||
from myhdl import *
|
||||
import os
|
||||
import struct
|
||||
|
||||
import pcie
|
||||
import pcie_usp
|
||||
|
||||
module = 'fpga_core'
|
||||
testbench = 'test_%s' % module
|
||||
|
||||
srcs = []
|
||||
|
||||
srcs.append("../rtl/%s.v" % module)
|
||||
srcs.append("../rtl/axi_ram.v")
|
||||
srcs.append("../rtl/axis_register.v")
|
||||
srcs.append("../lib/pcie/rtl/axis_arb_mux.v")
|
||||
srcs.append("../lib/pcie/rtl/pcie_us_axil_master.v")
|
||||
srcs.append("../lib/pcie/rtl/pcie_us_axi_dma.v")
|
||||
srcs.append("../lib/pcie/rtl/pcie_us_axi_dma_rd.v")
|
||||
srcs.append("../lib/pcie/rtl/pcie_us_axi_dma_wr.v")
|
||||
srcs.append("../lib/pcie/rtl/pcie_tag_manager.v")
|
||||
srcs.append("../lib/pcie/rtl/pcie_us_axi_master.v")
|
||||
srcs.append("../lib/pcie/rtl/pcie_us_axi_master_rd.v")
|
||||
srcs.append("../lib/pcie/rtl/pcie_us_axi_master_wr.v")
|
||||
srcs.append("../lib/pcie/rtl/pcie_us_axis_cq_demux.v")
|
||||
srcs.append("../lib/pcie/rtl/pcie_us_cfg.v")
|
||||
srcs.append("../lib/pcie/rtl/pcie_us_msi.v")
|
||||
srcs.append("../lib/pcie/rtl/arbiter.v")
|
||||
srcs.append("../lib/pcie/rtl/priority_encoder.v")
|
||||
srcs.append("../lib/pcie/rtl/pulse_merge.v")
|
||||
srcs.append("%s.v" % testbench)
|
||||
|
||||
src = ' '.join(srcs)
|
||||
|
||||
build_cmd = "iverilog -o %s.vvp %s" % (testbench, src)
|
||||
|
||||
def bench():
|
||||
|
||||
# Parameters
|
||||
AXIS_PCIE_DATA_WIDTH = 256
|
||||
AXIS_PCIE_KEEP_WIDTH = (AXIS_PCIE_DATA_WIDTH/32)
|
||||
AXIS_PCIE_RC_USER_WIDTH = 75
|
||||
AXIS_PCIE_RQ_USER_WIDTH = 62
|
||||
AXIS_PCIE_CQ_USER_WIDTH = 88
|
||||
AXIS_PCIE_CC_USER_WIDTH = 33
|
||||
|
||||
# Inputs
|
||||
clk = Signal(bool(0))
|
||||
rst = Signal(bool(0))
|
||||
current_test = Signal(intbv(0)[8:])
|
||||
|
||||
btnu = Signal(bool(0))
|
||||
btnl = Signal(bool(0))
|
||||
btnd = Signal(bool(0))
|
||||
btnr = Signal(bool(0))
|
||||
btnc = Signal(bool(0))
|
||||
sw = Signal(intbv(0)[4:])
|
||||
m_axis_rq_tready = Signal(bool(0))
|
||||
s_axis_rc_tdata = Signal(intbv(0)[AXIS_PCIE_DATA_WIDTH:])
|
||||
s_axis_rc_tkeep = Signal(intbv(0)[AXIS_PCIE_KEEP_WIDTH:])
|
||||
s_axis_rc_tlast = Signal(bool(0))
|
||||
s_axis_rc_tuser = Signal(intbv(0)[AXIS_PCIE_RC_USER_WIDTH:])
|
||||
s_axis_rc_tvalid = Signal(bool(0))
|
||||
s_axis_cq_tdata = Signal(intbv(0)[AXIS_PCIE_DATA_WIDTH:])
|
||||
s_axis_cq_tkeep = Signal(intbv(0)[AXIS_PCIE_KEEP_WIDTH:])
|
||||
s_axis_cq_tlast = Signal(bool(0))
|
||||
s_axis_cq_tuser = Signal(intbv(0)[AXIS_PCIE_CQ_USER_WIDTH:])
|
||||
s_axis_cq_tvalid = Signal(bool(0))
|
||||
m_axis_cc_tready = Signal(bool(0))
|
||||
cfg_max_payload = Signal(intbv(0)[2:])
|
||||
cfg_max_read_req = Signal(intbv(0)[3:])
|
||||
cfg_mgmt_read_data = Signal(intbv(0)[32:])
|
||||
cfg_mgmt_read_write_done = Signal(bool(0))
|
||||
cfg_interrupt_msi_enable = Signal(intbv(0)[4:])
|
||||
cfg_interrupt_msi_mmenable = Signal(intbv(0)[12:])
|
||||
cfg_interrupt_msi_mask_update = Signal(bool(0))
|
||||
cfg_interrupt_msi_data = Signal(intbv(0)[32:])
|
||||
cfg_interrupt_msi_sent = Signal(bool(0))
|
||||
cfg_interrupt_msi_fail = Signal(bool(0))
|
||||
|
||||
# Outputs
|
||||
led = Signal(intbv(0)[8:])
|
||||
m_axis_rq_tdata = Signal(intbv(0)[AXIS_PCIE_DATA_WIDTH:])
|
||||
m_axis_rq_tkeep = Signal(intbv(0)[AXIS_PCIE_KEEP_WIDTH:])
|
||||
m_axis_rq_tlast = Signal(bool(0))
|
||||
m_axis_rq_tuser = Signal(intbv(0)[AXIS_PCIE_RQ_USER_WIDTH:])
|
||||
m_axis_rq_tvalid = Signal(bool(0))
|
||||
s_axis_rc_tready = Signal(bool(0))
|
||||
s_axis_cq_tready = Signal(bool(0))
|
||||
m_axis_cc_tdata = Signal(intbv(0)[AXIS_PCIE_DATA_WIDTH:])
|
||||
m_axis_cc_tkeep = Signal(intbv(0)[AXIS_PCIE_KEEP_WIDTH:])
|
||||
m_axis_cc_tlast = Signal(bool(0))
|
||||
m_axis_cc_tuser = Signal(intbv(0)[AXIS_PCIE_CC_USER_WIDTH:])
|
||||
m_axis_cc_tvalid = Signal(bool(0))
|
||||
status_error_cor = Signal(bool(0))
|
||||
status_error_uncor = Signal(bool(0))
|
||||
cfg_mgmt_addr = Signal(intbv(0)[10:])
|
||||
cfg_mgmt_function_number = Signal(intbv(0)[8:])
|
||||
cfg_mgmt_write = Signal(bool(0))
|
||||
cfg_mgmt_write_data = Signal(intbv(0)[32:])
|
||||
cfg_mgmt_byte_enable = Signal(intbv(0)[4:])
|
||||
cfg_mgmt_read = Signal(bool(0))
|
||||
cfg_interrupt_msi_int = Signal(intbv(0)[32:])
|
||||
cfg_interrupt_msi_pending_status = Signal(intbv(0)[32:])
|
||||
cfg_interrupt_msi_select = Signal(intbv(0)[2:])
|
||||
cfg_interrupt_msi_pending_status_function_num = Signal(intbv(0)[2:])
|
||||
cfg_interrupt_msi_pending_status_data_enable = Signal(bool(0))
|
||||
cfg_interrupt_msi_attr = Signal(intbv(0)[3:])
|
||||
cfg_interrupt_msi_tph_present = Signal(bool(0))
|
||||
cfg_interrupt_msi_tph_type = Signal(intbv(0)[2:])
|
||||
cfg_interrupt_msi_tph_st_tag = Signal(intbv(0)[8:])
|
||||
cfg_interrupt_msi_function_number = Signal(intbv(0)[8:])
|
||||
|
||||
# Clock and Reset Interface
|
||||
user_clk=Signal(bool(0))
|
||||
user_reset=Signal(bool(0))
|
||||
sys_clk=Signal(bool(0))
|
||||
sys_reset=Signal(bool(0))
|
||||
|
||||
# PCIe devices
|
||||
rc = pcie.RootComplex()
|
||||
|
||||
mem_base, mem_data = rc.alloc_region(16*1024*1024)
|
||||
|
||||
dev = pcie_usp.UltrascalePlusPCIe()
|
||||
|
||||
dev.pcie_generation = 3
|
||||
dev.pcie_link_width = 8
|
||||
dev.user_clk_frequency = 250e6
|
||||
|
||||
dev.functions[0].msi_multiple_message_capable = 5
|
||||
|
||||
dev.functions[0].configure_bar(0, 4*1024*1024)
|
||||
dev.functions[0].configure_bar(1, 4*1024*1024)
|
||||
|
||||
rc.make_port().connect(dev)
|
||||
|
||||
pcie_logic = dev.create_logic(
|
||||
# Completer reQuest Interface
|
||||
m_axis_cq_tdata=s_axis_cq_tdata,
|
||||
m_axis_cq_tuser=s_axis_cq_tuser,
|
||||
m_axis_cq_tlast=s_axis_cq_tlast,
|
||||
m_axis_cq_tkeep=s_axis_cq_tkeep,
|
||||
m_axis_cq_tvalid=s_axis_cq_tvalid,
|
||||
m_axis_cq_tready=s_axis_cq_tready,
|
||||
#pcie_cq_np_req=pcie_cq_np_req,
|
||||
pcie_cq_np_req=Signal(intbv(1)[2:]),
|
||||
#pcie_cq_np_req_count=pcie_cq_np_req_count,
|
||||
|
||||
# Completer Completion Interface
|
||||
s_axis_cc_tdata=m_axis_cc_tdata,
|
||||
s_axis_cc_tuser=m_axis_cc_tuser,
|
||||
s_axis_cc_tlast=m_axis_cc_tlast,
|
||||
s_axis_cc_tkeep=m_axis_cc_tkeep,
|
||||
s_axis_cc_tvalid=m_axis_cc_tvalid,
|
||||
s_axis_cc_tready=m_axis_cc_tready,
|
||||
|
||||
# Requester reQuest Interface
|
||||
s_axis_rq_tdata=m_axis_rq_tdata,
|
||||
s_axis_rq_tuser=m_axis_rq_tuser,
|
||||
s_axis_rq_tlast=m_axis_rq_tlast,
|
||||
s_axis_rq_tkeep=m_axis_rq_tkeep,
|
||||
s_axis_rq_tvalid=m_axis_rq_tvalid,
|
||||
s_axis_rq_tready=m_axis_rq_tready,
|
||||
#pcie_rq_seq_num0=pcie_rq_seq_num0,
|
||||
#pcie_rq_seq_num_vld0=pcie_rq_seq_num_vld0,
|
||||
#pcie_rq_seq_num1=pcie_rq_seq_num1,
|
||||
#pcie_rq_seq_num_vld1=pcie_rq_seq_num_vld1,
|
||||
#pcie_rq_tag0=pcie_rq_tag0,
|
||||
#pcie_rq_tag1=pcie_rq_tag1,
|
||||
#pcie_rq_tag_av=pcie_rq_tag_av,
|
||||
#pcie_rq_tag_vld0=pcie_rq_tag_vld0,
|
||||
#pcie_rq_tag_vld1=pcie_rq_tag_vld1,
|
||||
|
||||
# Requester Completion Interface
|
||||
m_axis_rc_tdata=s_axis_rc_tdata,
|
||||
m_axis_rc_tuser=s_axis_rc_tuser,
|
||||
m_axis_rc_tlast=s_axis_rc_tlast,
|
||||
m_axis_rc_tkeep=s_axis_rc_tkeep,
|
||||
m_axis_rc_tvalid=s_axis_rc_tvalid,
|
||||
m_axis_rc_tready=s_axis_rc_tready,
|
||||
|
||||
# Transmit Flow Control Interface
|
||||
#pcie_tfc_nph_av=pcie_tfc_nph_av,
|
||||
#pcie_tfc_npd_av=pcie_tfc_npd_av,
|
||||
|
||||
# Configuration Management Interface
|
||||
cfg_mgmt_addr=cfg_mgmt_addr,
|
||||
cfg_mgmt_function_number=cfg_mgmt_function_number,
|
||||
cfg_mgmt_write=cfg_mgmt_write,
|
||||
cfg_mgmt_write_data=cfg_mgmt_write_data,
|
||||
cfg_mgmt_byte_enable=cfg_mgmt_byte_enable,
|
||||
cfg_mgmt_read=cfg_mgmt_read,
|
||||
cfg_mgmt_read_data=cfg_mgmt_read_data,
|
||||
cfg_mgmt_read_write_done=cfg_mgmt_read_write_done,
|
||||
#cfg_mgmt_debug_access=cfg_mgmt_debug_access,
|
||||
|
||||
# Configuration Status Interface
|
||||
#cfg_phy_link_down=cfg_phy_link_down,
|
||||
#cfg_phy_link_status=cfg_phy_link_status,
|
||||
#cfg_negotiated_width=cfg_negotiated_width,
|
||||
#cfg_current_speed=cfg_current_speed,
|
||||
cfg_max_payload=cfg_max_payload,
|
||||
cfg_max_read_req=cfg_max_read_req,
|
||||
#cfg_function_status=cfg_function_status,
|
||||
#cfg_vf_status=cfg_vf_status,
|
||||
#cfg_function_power_state=cfg_function_power_state,
|
||||
#cfg_vf_power_state=cfg_vf_power_state,
|
||||
#cfg_link_power_state=cfg_link_power_state,
|
||||
#cfg_err_cor_out=cfg_err_cor_out,
|
||||
#cfg_err_nonfatal_out=cfg_err_nonfatal_out,
|
||||
#cfg_err_fatal_out=cfg_err_fatal_out,
|
||||
#cfg_local_err_out=cfg_local_err_out,
|
||||
#cfg_local_err_valid=cfg_local_err_valid,
|
||||
#cfg_rx_pm_state=cfg_rx_pm_state,
|
||||
#cfg_tx_pm_state=cfg_tx_pm_state,
|
||||
#cfg_ltssm_state=cfg_ltssm_state,
|
||||
#cfg_rcb_status=cfg_rcb_status,
|
||||
#cfg_obff_enable=cfg_obff_enable,
|
||||
#cfg_pl_status_change=cfg_pl_status_change,
|
||||
#cfg_tph_requester_enable=cfg_tph_requester_enable,
|
||||
#cfg_tph_st_mode=cfg_tph_st_mode,
|
||||
#cfg_vf_tph_requester_enable=cfg_vf_tph_requester_enable,
|
||||
#cfg_vf_tph_st_mode=cfg_vf_tph_st_mode,
|
||||
|
||||
# Configuration Received Message Interface
|
||||
#cfg_msg_received=cfg_msg_received,
|
||||
#cfg_msg_received_data=cfg_msg_received_data,
|
||||
#cfg_msg_received_type=cfg_msg_received_type,
|
||||
|
||||
# Configuration Transmit Message Interface
|
||||
#cfg_msg_transmit=cfg_msg_transmit,
|
||||
#cfg_msg_transmit_type=cfg_msg_transmit_type,
|
||||
#cfg_msg_transmit_data=cfg_msg_transmit_data,
|
||||
#cfg_msg_transmit_done=cfg_msg_transmit_done,
|
||||
|
||||
# Configuration Flow Control Interface
|
||||
#cfg_fc_ph=cfg_fc_ph,
|
||||
#cfg_fc_pd=cfg_fc_pd,
|
||||
#cfg_fc_nph=cfg_fc_nph,
|
||||
#cfg_fc_npd=cfg_fc_npd,
|
||||
#cfg_fc_cplh=cfg_fc_cplh,
|
||||
#cfg_fc_cpld=cfg_fc_cpld,
|
||||
#cfg_fc_sel=cfg_fc_sel,
|
||||
|
||||
# Configuration Control Interface
|
||||
#cfg_hot_reset_in=cfg_hot_reset_in,
|
||||
#cfg_hot_reset_out=cfg_hot_reset_out,
|
||||
#cfg_config_space_enable=cfg_config_space_enable,
|
||||
#cfg_dsn=cfg_dsn,
|
||||
#cfg_ds_port_number=cfg_ds_port_number,
|
||||
#cfg_ds_bus_number=cfg_ds_bus_number,
|
||||
#cfg_ds_device_number=cfg_ds_device_number,
|
||||
#cfg_ds_function_number=cfg_ds_function_number,
|
||||
#cfg_power_state_change_ack=cfg_power_state_change_ack,
|
||||
#cfg_power_state_change_interrupt=cfg_power_state_change_interrupt,
|
||||
cfg_err_cor_in=status_error_cor,
|
||||
cfg_err_uncor_in=status_error_uncor,
|
||||
#cfg_flr_done=cfg_flr_done,
|
||||
#cfg_vf_flr_done=cfg_vf_flr_done,
|
||||
#cfg_flr_in_process=cfg_flr_in_process,
|
||||
#cfg_vf_flr_in_process=cfg_vf_flr_in_process,
|
||||
#cfg_req_pm_transition_l23_ready=cfg_req_pm_transition_l23_ready,
|
||||
#cfg_link_training_enable=cfg_link_training_enable,
|
||||
|
||||
# Configuration Interrupt Controller Interface
|
||||
#cfg_interrupt_int=cfg_interrupt_int,
|
||||
#cfg_interrupt_sent=cfg_interrupt_sent,
|
||||
#cfg_interrupt_pending=cfg_interrupt_pending,
|
||||
cfg_interrupt_msi_enable=cfg_interrupt_msi_enable,
|
||||
cfg_interrupt_msi_mmenable=cfg_interrupt_msi_mmenable,
|
||||
cfg_interrupt_msi_mask_update=cfg_interrupt_msi_mask_update,
|
||||
cfg_interrupt_msi_data=cfg_interrupt_msi_data,
|
||||
cfg_interrupt_msi_select=cfg_interrupt_msi_select,
|
||||
cfg_interrupt_msi_int=cfg_interrupt_msi_int,
|
||||
cfg_interrupt_msi_pending_status=cfg_interrupt_msi_pending_status,
|
||||
cfg_interrupt_msi_pending_status_data_enable=cfg_interrupt_msi_pending_status_data_enable,
|
||||
cfg_interrupt_msi_pending_status_function_num=cfg_interrupt_msi_pending_status_function_num,
|
||||
cfg_interrupt_msi_sent=cfg_interrupt_msi_sent,
|
||||
cfg_interrupt_msi_fail=cfg_interrupt_msi_fail,
|
||||
#cfg_interrupt_msix_enable=cfg_interrupt_msix_enable,
|
||||
#cfg_interrupt_msix_mask=cfg_interrupt_msix_mask,
|
||||
#cfg_interrupt_msix_vf_enable=cfg_interrupt_msix_vf_enable,
|
||||
#cfg_interrupt_msix_vf_mask=cfg_interrupt_msix_vf_mask,
|
||||
#cfg_interrupt_msix_address=cfg_interrupt_msix_address,
|
||||
#cfg_interrupt_msix_data=cfg_interrupt_msix_data,
|
||||
#cfg_interrupt_msix_int=cfg_interrupt_msix_int,
|
||||
#cfg_interrupt_msix_vec_pending=cfg_interrupt_msix_vec_pending,
|
||||
#cfg_interrupt_msix_vec_pending_status=cfg_interrupt_msix_vec_pending_status,
|
||||
cfg_interrupt_msi_attr=cfg_interrupt_msi_attr,
|
||||
cfg_interrupt_msi_tph_present=cfg_interrupt_msi_tph_present,
|
||||
cfg_interrupt_msi_tph_type=cfg_interrupt_msi_tph_type,
|
||||
cfg_interrupt_msi_tph_st_tag=cfg_interrupt_msi_tph_st_tag,
|
||||
cfg_interrupt_msi_function_number=cfg_interrupt_msi_function_number,
|
||||
|
||||
# Configuration Extend Interface
|
||||
#cfg_ext_read_received=cfg_ext_read_received,
|
||||
#cfg_ext_write_received=cfg_ext_write_received,
|
||||
#cfg_ext_register_number=cfg_ext_register_number,
|
||||
#cfg_ext_function_number=cfg_ext_function_number,
|
||||
#cfg_ext_write_data=cfg_ext_write_data,
|
||||
#cfg_ext_write_byte_enable=cfg_ext_write_byte_enable,
|
||||
#cfg_ext_read_data=cfg_ext_read_data,
|
||||
#cfg_ext_read_data_valid=cfg_ext_read_data_valid,
|
||||
|
||||
# Clock and Reset Interface
|
||||
user_clk=user_clk,
|
||||
user_reset=user_reset,
|
||||
#user_lnk_up=user_lnk_up,
|
||||
sys_clk=sys_clk,
|
||||
sys_clk_gt=sys_clk,
|
||||
sys_reset=sys_reset,
|
||||
#phy_rdy_out=phy_rdy_out
|
||||
)
|
||||
|
||||
# DUT
|
||||
if os.system(build_cmd):
|
||||
raise Exception("Error running build command")
|
||||
|
||||
dut = Cosimulation(
|
||||
"vvp -m myhdl %s.vvp -lxt2" % testbench,
|
||||
clk=user_clk,
|
||||
rst=user_reset,
|
||||
current_test=current_test,
|
||||
btnu=btnu,
|
||||
btnl=btnl,
|
||||
btnd=btnd,
|
||||
btnr=btnr,
|
||||
btnc=btnc,
|
||||
sw=sw,
|
||||
led=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_function_number=cfg_mgmt_function_number,
|
||||
cfg_mgmt_write=cfg_mgmt_write,
|
||||
cfg_mgmt_write_data=cfg_mgmt_write_data,
|
||||
cfg_mgmt_byte_enable=cfg_mgmt_byte_enable,
|
||||
cfg_mgmt_read=cfg_mgmt_read,
|
||||
cfg_mgmt_read_data=cfg_mgmt_read_data,
|
||||
cfg_mgmt_read_write_done=cfg_mgmt_read_write_done,
|
||||
cfg_interrupt_msi_enable=cfg_interrupt_msi_enable,
|
||||
cfg_interrupt_msi_int=cfg_interrupt_msi_int,
|
||||
cfg_interrupt_msi_sent=cfg_interrupt_msi_sent,
|
||||
cfg_interrupt_msi_fail=cfg_interrupt_msi_fail,
|
||||
cfg_interrupt_msi_mmenable=cfg_interrupt_msi_mmenable,
|
||||
cfg_interrupt_msi_pending_status=cfg_interrupt_msi_pending_status,
|
||||
cfg_interrupt_msi_mask_update=cfg_interrupt_msi_mask_update,
|
||||
cfg_interrupt_msi_select=cfg_interrupt_msi_select,
|
||||
cfg_interrupt_msi_data=cfg_interrupt_msi_data,
|
||||
cfg_interrupt_msi_pending_status_function_num=cfg_interrupt_msi_pending_status_function_num,
|
||||
cfg_interrupt_msi_pending_status_data_enable=cfg_interrupt_msi_pending_status_data_enable,
|
||||
cfg_interrupt_msi_attr=cfg_interrupt_msi_attr,
|
||||
cfg_interrupt_msi_tph_present=cfg_interrupt_msi_tph_present,
|
||||
cfg_interrupt_msi_tph_type=cfg_interrupt_msi_tph_type,
|
||||
cfg_interrupt_msi_tph_st_tag=cfg_interrupt_msi_tph_st_tag,
|
||||
cfg_interrupt_msi_function_number=cfg_interrupt_msi_function_number,
|
||||
status_error_cor=status_error_cor,
|
||||
status_error_uncor=status_error_uncor
|
||||
)
|
||||
|
||||
@always(delay(5))
|
||||
def clkgen():
|
||||
clk.next = not clk
|
||||
|
||||
@always_comb
|
||||
def clk_logic():
|
||||
sys_clk.next = clk
|
||||
sys_reset.next = not rst
|
||||
|
||||
@instance
|
||||
def check():
|
||||
yield delay(100)
|
||||
yield clk.posedge
|
||||
rst.next = 1
|
||||
yield clk.posedge
|
||||
rst.next = 0
|
||||
yield clk.posedge
|
||||
yield delay(100)
|
||||
yield clk.posedge
|
||||
|
||||
# testbench stimulus
|
||||
|
||||
current_tag = 1
|
||||
|
||||
yield clk.posedge
|
||||
print("test 1: enumeration")
|
||||
current_test.next = 1
|
||||
|
||||
yield rc.enumerate(enable_bus_mastering=True, configure_msi=True)
|
||||
|
||||
dev_pf0_bar0 = dev.functions[0].bar[0] & 0xfffffffc
|
||||
dev_pf0_bar1 = dev.functions[0].bar[1] & 0xfffffffc
|
||||
|
||||
yield delay(100)
|
||||
|
||||
yield clk.posedge
|
||||
print("test 2: memory write to bar 1")
|
||||
current_test.next = 2
|
||||
|
||||
yield rc.mem_write(dev_pf0_bar1, b'\x11\x22\x33\x44')
|
||||
|
||||
yield delay(100)
|
||||
|
||||
yield clk.posedge
|
||||
print("test 3: memory read from bar 1")
|
||||
current_test.next = 3
|
||||
|
||||
val = yield from rc.mem_read(dev_pf0_bar1, 4, 1000)
|
||||
print(val)
|
||||
assert val == b'\x11\x22\x33\x44'
|
||||
|
||||
yield delay(100)
|
||||
|
||||
yield clk.posedge
|
||||
print("test 4: test DMA")
|
||||
current_test.next = 4
|
||||
|
||||
# write packet data
|
||||
mem_data[0:1024] = bytearray([x%256 for x in range(1024)])
|
||||
|
||||
# enable DMA
|
||||
yield rc.mem_write(dev_pf0_bar0+0x100000, struct.pack('<L', 1))
|
||||
|
||||
# write pcie read descriptor
|
||||
yield rc.mem_write(dev_pf0_bar0+0x100100, struct.pack('<L', (mem_base+0x0000) & 0xffffffff))
|
||||
yield rc.mem_write(dev_pf0_bar0+0x100104, struct.pack('<L', (mem_base+0x0000 >> 32) & 0xffffffff))
|
||||
yield rc.mem_write(dev_pf0_bar0+0x100108, struct.pack('<L', (0x100) & 0xffffffff))
|
||||
yield rc.mem_write(dev_pf0_bar0+0x10010C, struct.pack('<L', (0x100 >> 32) & 0xffffffff))
|
||||
yield rc.mem_write(dev_pf0_bar0+0x100110, struct.pack('<L', 0x400))
|
||||
yield rc.mem_write(dev_pf0_bar0+0x100114, struct.pack('<L', 0xAA))
|
||||
|
||||
yield delay(2000)
|
||||
|
||||
# read status
|
||||
val = yield from rc.mem_read(dev_pf0_bar0+0x100118, 4)
|
||||
print(val)
|
||||
|
||||
# write pcie write descriptor
|
||||
yield rc.mem_write(dev_pf0_bar0+0x100200, struct.pack('<L', (mem_base+0x1000) & 0xffffffff))
|
||||
yield rc.mem_write(dev_pf0_bar0+0x100204, struct.pack('<L', (mem_base+0x1000 >> 32) & 0xffffffff))
|
||||
yield rc.mem_write(dev_pf0_bar0+0x100208, struct.pack('<L', (0x100) & 0xffffffff))
|
||||
yield rc.mem_write(dev_pf0_bar0+0x10020C, struct.pack('<L', (0x100 >> 32) & 0xffffffff))
|
||||
yield rc.mem_write(dev_pf0_bar0+0x100210, struct.pack('<L', 0x400))
|
||||
yield rc.mem_write(dev_pf0_bar0+0x100214, struct.pack('<L', 0x55))
|
||||
|
||||
yield delay(2000)
|
||||
|
||||
# read status
|
||||
val = yield from rc.mem_read(dev_pf0_bar0+0x100218, 4)
|
||||
print(val)
|
||||
|
||||
data = mem_data[0x1000:(0x1000)+64]
|
||||
for i in range(0, len(data), 16):
|
||||
print(" ".join(("{:02x}".format(c) for c in bytearray(data[i:i+16]))))
|
||||
|
||||
assert mem_data[0:1024] == mem_data[0x1000:0x1000+1024]
|
||||
|
||||
yield delay(100)
|
||||
|
||||
raise StopSimulation
|
||||
|
||||
return instances()
|
||||
|
||||
def test_bench():
|
||||
sim = Simulation(bench())
|
||||
sim.run()
|
||||
|
||||
if __name__ == '__main__':
|
||||
print("Running test...")
|
||||
test_bench()
|
@ -1,258 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2018 Alex Forencich
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
// Language: Verilog 2001
|
||||
|
||||
`timescale 1ns / 1ps
|
||||
|
||||
/*
|
||||
* Testbench for fpga_core
|
||||
*/
|
||||
module test_fpga_core;
|
||||
|
||||
// Parameters
|
||||
parameter AXIS_PCIE_DATA_WIDTH = 256;
|
||||
parameter AXIS_PCIE_KEEP_WIDTH = (AXIS_PCIE_DATA_WIDTH/32);
|
||||
parameter AXIS_PCIE_RC_USER_WIDTH = 75;
|
||||
parameter AXIS_PCIE_RQ_USER_WIDTH = 62;
|
||||
parameter AXIS_PCIE_CQ_USER_WIDTH = 88;
|
||||
parameter AXIS_PCIE_CC_USER_WIDTH = 33;
|
||||
|
||||
// Inputs
|
||||
reg clk = 0;
|
||||
reg rst = 0;
|
||||
reg [7:0] current_test = 0;
|
||||
|
||||
reg btnu = 0;
|
||||
reg btnl = 0;
|
||||
reg btnd = 0;
|
||||
reg btnr = 0;
|
||||
reg btnc = 0;
|
||||
reg [3:0] sw = 0;
|
||||
reg m_axis_rq_tready = 0;
|
||||
reg [AXIS_PCIE_DATA_WIDTH-1:0] s_axis_rc_tdata = 0;
|
||||
reg [AXIS_PCIE_KEEP_WIDTH-1:0] s_axis_rc_tkeep = 0;
|
||||
reg s_axis_rc_tlast = 0;
|
||||
reg [AXIS_PCIE_RC_USER_WIDTH-1:0] s_axis_rc_tuser = 0;
|
||||
reg s_axis_rc_tvalid = 0;
|
||||
reg [AXIS_PCIE_DATA_WIDTH-1:0] s_axis_cq_tdata = 0;
|
||||
reg [AXIS_PCIE_KEEP_WIDTH-1:0] s_axis_cq_tkeep = 0;
|
||||
reg s_axis_cq_tlast = 0;
|
||||
reg [AXIS_PCIE_CQ_USER_WIDTH-1:0] s_axis_cq_tuser = 0;
|
||||
reg s_axis_cq_tvalid = 0;
|
||||
reg m_axis_cc_tready = 0;
|
||||
reg [2:0] cfg_max_payload = 0;
|
||||
reg [2:0] cfg_max_read_req = 0;
|
||||
reg [31:0] cfg_mgmt_read_data = 0;
|
||||
reg cfg_mgmt_read_write_done = 0;
|
||||
reg [3:0] cfg_interrupt_msi_enable = 0;
|
||||
reg [11:0] cfg_interrupt_msi_mmenable = 0;
|
||||
reg cfg_interrupt_msi_mask_update = 0;
|
||||
reg [31:0] cfg_interrupt_msi_data = 0;
|
||||
reg cfg_interrupt_msi_sent = 0;
|
||||
reg cfg_interrupt_msi_fail = 0;
|
||||
|
||||
// Outputs
|
||||
wire [7:0] led;
|
||||
wire [1:0] user_led_g;
|
||||
wire user_led_r;
|
||||
wire [1:0] front_led;
|
||||
wire [AXIS_PCIE_DATA_WIDTH-1:0] m_axis_rq_tdata;
|
||||
wire [AXIS_PCIE_KEEP_WIDTH-1:0] m_axis_rq_tkeep;
|
||||
wire m_axis_rq_tlast;
|
||||
wire [AXIS_PCIE_RQ_USER_WIDTH-1:0] m_axis_rq_tuser;
|
||||
wire m_axis_rq_tvalid;
|
||||
wire s_axis_rc_tready;
|
||||
wire s_axis_cq_tready;
|
||||
wire [AXIS_PCIE_DATA_WIDTH-1:0] m_axis_cc_tdata;
|
||||
wire [AXIS_PCIE_KEEP_WIDTH-1:0] m_axis_cc_tkeep;
|
||||
wire m_axis_cc_tlast;
|
||||
wire [AXIS_PCIE_CC_USER_WIDTH-1:0] m_axis_cc_tuser;
|
||||
wire m_axis_cc_tvalid;
|
||||
wire [9:0] cfg_mgmt_addr;
|
||||
wire [7:0] cfg_mgmt_function_number;
|
||||
wire cfg_mgmt_write;
|
||||
wire [31:0] cfg_mgmt_write_data;
|
||||
wire [3:0] cfg_mgmt_byte_enable;
|
||||
wire cfg_mgmt_read;
|
||||
wire [3:0] cfg_interrupt_msi_select;
|
||||
wire [31:0] cfg_interrupt_msi_int;
|
||||
wire [31:0] cfg_interrupt_msi_pending_status;
|
||||
wire cfg_interrupt_msi_pending_status_data_enable;
|
||||
wire [3:0] cfg_interrupt_msi_pending_status_function_num;
|
||||
wire [2:0] cfg_interrupt_msi_attr;
|
||||
wire cfg_interrupt_msi_tph_present;
|
||||
wire [1:0] cfg_interrupt_msi_tph_type;
|
||||
wire [8:0] cfg_interrupt_msi_tph_st_tag;
|
||||
wire [3:0] cfg_interrupt_msi_function_number;
|
||||
wire status_error_cor;
|
||||
wire status_error_uncor;
|
||||
|
||||
initial begin
|
||||
// myhdl integration
|
||||
$from_myhdl(
|
||||
clk,
|
||||
rst,
|
||||
current_test,
|
||||
btnu,
|
||||
btnl,
|
||||
btnd,
|
||||
btnr,
|
||||
btnc,
|
||||
sw,
|
||||
m_axis_rq_tready,
|
||||
s_axis_rc_tdata,
|
||||
s_axis_rc_tkeep,
|
||||
s_axis_rc_tlast,
|
||||
s_axis_rc_tuser,
|
||||
s_axis_rc_tvalid,
|
||||
s_axis_cq_tdata,
|
||||
s_axis_cq_tkeep,
|
||||
s_axis_cq_tlast,
|
||||
s_axis_cq_tuser,
|
||||
s_axis_cq_tvalid,
|
||||
m_axis_cc_tready,
|
||||
cfg_max_payload,
|
||||
cfg_max_read_req,
|
||||
cfg_mgmt_read_data,
|
||||
cfg_mgmt_read_write_done,
|
||||
cfg_interrupt_msi_enable,
|
||||
cfg_interrupt_msi_mmenable,
|
||||
cfg_interrupt_msi_mask_update,
|
||||
cfg_interrupt_msi_data,
|
||||
cfg_interrupt_msi_sent,
|
||||
cfg_interrupt_msi_fail
|
||||
);
|
||||
$to_myhdl(
|
||||
led,
|
||||
m_axis_rq_tdata,
|
||||
m_axis_rq_tkeep,
|
||||
m_axis_rq_tlast,
|
||||
m_axis_rq_tuser,
|
||||
m_axis_rq_tvalid,
|
||||
s_axis_rc_tready,
|
||||
s_axis_cq_tready,
|
||||
m_axis_cc_tdata,
|
||||
m_axis_cc_tkeep,
|
||||
m_axis_cc_tlast,
|
||||
m_axis_cc_tuser,
|
||||
m_axis_cc_tvalid,
|
||||
cfg_mgmt_addr,
|
||||
cfg_mgmt_function_number,
|
||||
cfg_mgmt_write,
|
||||
cfg_mgmt_write_data,
|
||||
cfg_mgmt_byte_enable,
|
||||
cfg_mgmt_read,
|
||||
cfg_interrupt_msi_select,
|
||||
cfg_interrupt_msi_int,
|
||||
cfg_interrupt_msi_pending_status,
|
||||
cfg_interrupt_msi_pending_status_data_enable,
|
||||
cfg_interrupt_msi_pending_status_function_num,
|
||||
cfg_interrupt_msi_attr,
|
||||
cfg_interrupt_msi_tph_present,
|
||||
cfg_interrupt_msi_tph_type,
|
||||
cfg_interrupt_msi_tph_st_tag,
|
||||
cfg_interrupt_msi_function_number,
|
||||
status_error_cor,
|
||||
status_error_uncor
|
||||
);
|
||||
|
||||
// dump file
|
||||
$dumpfile("test_fpga_core.lxt");
|
||||
$dumpvars(0, test_fpga_core);
|
||||
end
|
||||
|
||||
fpga_core #(
|
||||
.AXIS_PCIE_DATA_WIDTH(AXIS_PCIE_DATA_WIDTH),
|
||||
.AXIS_PCIE_KEEP_WIDTH(AXIS_PCIE_KEEP_WIDTH),
|
||||
.AXIS_PCIE_RC_USER_WIDTH(AXIS_PCIE_RC_USER_WIDTH),
|
||||
.AXIS_PCIE_RQ_USER_WIDTH(AXIS_PCIE_RQ_USER_WIDTH),
|
||||
.AXIS_PCIE_CQ_USER_WIDTH(AXIS_PCIE_CQ_USER_WIDTH),
|
||||
.AXIS_PCIE_CC_USER_WIDTH(AXIS_PCIE_CC_USER_WIDTH)
|
||||
)
|
||||
UUT (
|
||||
.clk(clk),
|
||||
.rst(rst),
|
||||
.btnu(btnu),
|
||||
.btnl(btnl),
|
||||
.btnd(btnd),
|
||||
.btnr(btnr),
|
||||
.btnc(btnc),
|
||||
.sw(sw),
|
||||
.led(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_function_number(cfg_mgmt_function_number),
|
||||
.cfg_mgmt_write(cfg_mgmt_write),
|
||||
.cfg_mgmt_write_data(cfg_mgmt_write_data),
|
||||
.cfg_mgmt_byte_enable(cfg_mgmt_byte_enable),
|
||||
.cfg_mgmt_read(cfg_mgmt_read),
|
||||
.cfg_mgmt_read_data(cfg_mgmt_read_data),
|
||||
.cfg_mgmt_read_write_done(cfg_mgmt_read_write_done),
|
||||
.cfg_interrupt_msi_enable(cfg_interrupt_msi_enable),
|
||||
.cfg_interrupt_msi_mmenable(cfg_interrupt_msi_mmenable),
|
||||
.cfg_interrupt_msi_mask_update(cfg_interrupt_msi_mask_update),
|
||||
.cfg_interrupt_msi_data(cfg_interrupt_msi_data),
|
||||
.cfg_interrupt_msi_select(cfg_interrupt_msi_select),
|
||||
.cfg_interrupt_msi_int(cfg_interrupt_msi_int),
|
||||
.cfg_interrupt_msi_pending_status(cfg_interrupt_msi_pending_status),
|
||||
.cfg_interrupt_msi_pending_status_data_enable(cfg_interrupt_msi_pending_status_data_enable),
|
||||
.cfg_interrupt_msi_pending_status_function_num(cfg_interrupt_msi_pending_status_function_num),
|
||||
.cfg_interrupt_msi_sent(cfg_interrupt_msi_sent),
|
||||
.cfg_interrupt_msi_fail(cfg_interrupt_msi_fail),
|
||||
.cfg_interrupt_msi_attr(cfg_interrupt_msi_attr),
|
||||
.cfg_interrupt_msi_tph_present(cfg_interrupt_msi_tph_present),
|
||||
.cfg_interrupt_msi_tph_type(cfg_interrupt_msi_tph_type),
|
||||
.cfg_interrupt_msi_tph_st_tag(cfg_interrupt_msi_tph_st_tag),
|
||||
.cfg_interrupt_msi_function_number(cfg_interrupt_msi_function_number),
|
||||
.status_error_cor(status_error_cor),
|
||||
.status_error_uncor(status_error_uncor)
|
||||
);
|
||||
|
||||
endmodule
|
@ -1 +0,0 @@
|
||||
../lib/pcie/tb/axis_ep.py
|
107
example/VCU1525/fpga_axi/tb/fpga_core/Makefile
Normal file
107
example/VCU1525/fpga_axi/tb/fpga_core/Makefile
Normal file
@ -0,0 +1,107 @@
|
||||
# Copyright (c) 2020 Alex Forencich
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in
|
||||
# all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
# THE SOFTWARE.
|
||||
|
||||
TOPLEVEL_LANG = verilog
|
||||
|
||||
SIM ?= icarus
|
||||
WAVES ?= 0
|
||||
|
||||
COCOTB_HDL_TIMEUNIT = 1ns
|
||||
COCOTB_HDL_TIMEPRECISION = 1ps
|
||||
|
||||
DUT = fpga_core
|
||||
TOPLEVEL = $(DUT)
|
||||
MODULE = test_$(DUT)
|
||||
VERILOG_SOURCES += ../../rtl/$(DUT).v
|
||||
VERILOG_SOURCES += ../../rtl/axi_ram.v
|
||||
VERILOG_SOURCES += ../../rtl/axis_register.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/axis_arb_mux.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_axil_master.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_axi_dma.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_axi_dma_rd.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_axi_dma_wr.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_tag_manager.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_axi_master.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_axi_master_rd.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_axi_master_wr.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_axis_cq_demux.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_cfg.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_msi.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/arbiter.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/priority_encoder.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pulse_merge.v
|
||||
|
||||
# module parameters
|
||||
export PARAM_AXIS_PCIE_DATA_WIDTH ?= 512
|
||||
export PARAM_AXIS_PCIE_KEEP_WIDTH ?= $(shell expr $(PARAM_AXIS_PCIE_DATA_WIDTH) / 32 )
|
||||
export PARAM_AXIS_PCIE_RQ_USER_WIDTH ?= $(if $(filter-out 512,$(PARAM_AXIS_PCIE_DATA_WIDTH)),62,137)
|
||||
export PARAM_AXIS_PCIE_RC_USER_WIDTH ?= $(if $(filter-out 512,$(PARAM_AXIS_PCIE_DATA_WIDTH)),75,161)
|
||||
export PARAM_AXIS_PCIE_CQ_USER_WIDTH ?= $(if $(filter-out 512,$(PARAM_AXIS_PCIE_DATA_WIDTH)),88,183)
|
||||
export PARAM_AXIS_PCIE_CC_USER_WIDTH ?= $(if $(filter-out 512,$(PARAM_AXIS_PCIE_DATA_WIDTH)),33,81)
|
||||
export PARAM_RQ_SEQ_NUM_WIDTH ?= 6
|
||||
|
||||
SIM_BUILD ?= sim_build_$(MODULE)
|
||||
|
||||
ifeq ($(SIM), icarus)
|
||||
PLUSARGS += -fst
|
||||
|
||||
COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_DATA_WIDTH=$(PARAM_AXIS_PCIE_DATA_WIDTH)
|
||||
COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_KEEP_WIDTH=$(PARAM_AXIS_PCIE_KEEP_WIDTH)
|
||||
COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_RQ_USER_WIDTH=$(PARAM_AXIS_PCIE_RQ_USER_WIDTH)
|
||||
COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_RC_USER_WIDTH=$(PARAM_AXIS_PCIE_RC_USER_WIDTH)
|
||||
COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_CQ_USER_WIDTH=$(PARAM_AXIS_PCIE_CQ_USER_WIDTH)
|
||||
COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_CC_USER_WIDTH=$(PARAM_AXIS_PCIE_CC_USER_WIDTH)
|
||||
COMPILE_ARGS += -P $(TOPLEVEL).RQ_SEQ_NUM_WIDTH=$(PARAM_RQ_SEQ_NUM_WIDTH)
|
||||
|
||||
ifeq ($(WAVES), 1)
|
||||
VERILOG_SOURCES += iverilog_dump.v
|
||||
COMPILE_ARGS += -s iverilog_dump
|
||||
endif
|
||||
else ifeq ($(SIM), verilator)
|
||||
COMPILE_ARGS += -Wno-SELRANGE -Wno-WIDTH
|
||||
|
||||
COMPILE_ARGS += -GAXIS_PCIE_DATA_WIDTH=$(PARAM_AXIS_PCIE_DATA_WIDTH)
|
||||
COMPILE_ARGS += -GAXIS_PCIE_KEEP_WIDTH=$(PARAM_AXIS_PCIE_KEEP_WIDTH)
|
||||
COMPILE_ARGS += -GAXIS_PCIE_RQ_USER_WIDTH=$(PARAM_AXIS_PCIE_RQ_USER_WIDTH)
|
||||
COMPILE_ARGS += -GAXIS_PCIE_RC_USER_WIDTH=$(PARAM_AXIS_PCIE_RC_USER_WIDTH)
|
||||
COMPILE_ARGS += -GAXIS_PCIE_CQ_USER_WIDTH=$(PARAM_AXIS_PCIE_CQ_USER_WIDTH)
|
||||
COMPILE_ARGS += -GAXIS_PCIE_CC_USER_WIDTH=$(PARAM_AXIS_PCIE_CC_USER_WIDTH)
|
||||
COMPILE_ARGS += -GRQ_SEQ_NUM_WIDTH=$(PARAM_RQ_SEQ_NUM_WIDTH)
|
||||
|
||||
ifeq ($(WAVES), 1)
|
||||
COMPILE_ARGS += --trace-fst
|
||||
endif
|
||||
endif
|
||||
|
||||
iverilog_dump.v:
|
||||
echo 'module iverilog_dump();' > $@
|
||||
echo 'initial begin' >> $@
|
||||
echo ' $$dumpfile("$(TOPLEVEL).fst");' >> $@
|
||||
echo ' $$dumpvars(0, $(TOPLEVEL));' >> $@
|
||||
echo 'end' >> $@
|
||||
echo 'endmodule' >> $@
|
||||
|
||||
clean::
|
||||
@rm -rf sim_build_*
|
||||
@rm -rf iverilog_dump.v
|
||||
@rm -rf dump.fst $(TOPLEVEL).fst
|
||||
|
||||
include $(shell cocotb-config --makefiles)/Makefile.sim
|
||||
|
380
example/VCU1525/fpga_axi/tb/fpga_core/test_fpga_core.py
Normal file
380
example/VCU1525/fpga_axi/tb/fpga_core/test_fpga_core.py
Normal file
@ -0,0 +1,380 @@
|
||||
"""
|
||||
|
||||
Copyright (c) 2020 Alex Forencich
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
"""
|
||||
|
||||
import logging
|
||||
import os
|
||||
|
||||
import cocotb_test.simulator
|
||||
|
||||
import cocotb
|
||||
from cocotb.log import SimLog
|
||||
from cocotb.triggers import RisingEdge, FallingEdge, Timer
|
||||
|
||||
from cocotbext.pcie.core import RootComplex
|
||||
from cocotbext.pcie.xilinx.us import UltraScalePlusPcieDevice
|
||||
from cocotbext.axi.utils import hexdump_str
|
||||
|
||||
|
||||
class TB(object):
|
||||
def __init__(self, dut):
|
||||
self.dut = dut
|
||||
|
||||
self.log = SimLog("cocotb.tb")
|
||||
self.log.setLevel(logging.DEBUG)
|
||||
|
||||
# PCIe
|
||||
self.rc = RootComplex()
|
||||
|
||||
self.dev = UltraScalePlusPcieDevice(
|
||||
# configuration options
|
||||
pcie_generation=3,
|
||||
pcie_link_width=16,
|
||||
user_clk_frequency=250e6,
|
||||
alignment="dword",
|
||||
cq_cc_straddle=False,
|
||||
rq_rc_straddle=False,
|
||||
rc_4tlp_straddle=False,
|
||||
enable_pf1=False,
|
||||
enable_client_tag=True,
|
||||
enable_extended_tag=True,
|
||||
enable_parity=False,
|
||||
enable_rx_msg_interface=False,
|
||||
enable_sriov=False,
|
||||
enable_extended_configuration=False,
|
||||
|
||||
enable_pf0_msi=True,
|
||||
enable_pf1_msi=False,
|
||||
|
||||
# signals
|
||||
# Clock and Reset Interface
|
||||
user_clk=dut.clk,
|
||||
user_reset=dut.rst,
|
||||
# user_lnk_up
|
||||
# sys_clk
|
||||
# sys_clk_gt
|
||||
# sys_reset
|
||||
# phy_rdy_out
|
||||
|
||||
# Requester reQuest Interface
|
||||
rq_entity=dut,
|
||||
rq_name="m_axis_rq",
|
||||
# pcie_rq_seq_num0=dut.s_axis_rq_seq_num_0,
|
||||
# pcie_rq_seq_num_vld0=dut.s_axis_rq_seq_num_valid_0,
|
||||
# pcie_rq_seq_num1=dut.s_axis_rq_seq_num_1,
|
||||
# pcie_rq_seq_num_vld1=dut.s_axis_rq_seq_num_valid_1,
|
||||
# pcie_rq_tag0
|
||||
# pcie_rq_tag1
|
||||
# pcie_rq_tag_av
|
||||
# pcie_rq_tag_vld0
|
||||
# pcie_rq_tag_vld1
|
||||
|
||||
# Requester Completion Interface
|
||||
rc_entity=dut,
|
||||
rc_name="s_axis_rc",
|
||||
|
||||
# Completer reQuest Interface
|
||||
cq_entity=dut,
|
||||
cq_name="s_axis_cq",
|
||||
# pcie_cq_np_req
|
||||
# pcie_cq_np_req_count
|
||||
|
||||
# Completer Completion Interface
|
||||
cc_entity=dut,
|
||||
cc_name="m_axis_cc",
|
||||
|
||||
# Transmit Flow Control Interface
|
||||
# pcie_tfc_nph_av=dut.pcie_tfc_nph_av,
|
||||
# pcie_tfc_npd_av=dut.pcie_tfc_npd_av,
|
||||
|
||||
# Configuration Management Interface
|
||||
cfg_mgmt_addr=dut.cfg_mgmt_addr,
|
||||
cfg_mgmt_function_number=dut.cfg_mgmt_function_number,
|
||||
cfg_mgmt_write=dut.cfg_mgmt_write,
|
||||
cfg_mgmt_write_data=dut.cfg_mgmt_write_data,
|
||||
cfg_mgmt_byte_enable=dut.cfg_mgmt_byte_enable,
|
||||
cfg_mgmt_read=dut.cfg_mgmt_read,
|
||||
cfg_mgmt_read_data=dut.cfg_mgmt_read_data,
|
||||
cfg_mgmt_read_write_done=dut.cfg_mgmt_read_write_done,
|
||||
# cfg_mgmt_debug_access
|
||||
|
||||
# Configuration Status Interface
|
||||
# cfg_phy_link_down
|
||||
# cfg_phy_link_status
|
||||
# cfg_negotiated_width
|
||||
# cfg_current_speed
|
||||
cfg_max_payload=dut.cfg_max_payload,
|
||||
cfg_max_read_req=dut.cfg_max_read_req,
|
||||
# cfg_function_status
|
||||
# cfg_vf_status
|
||||
# cfg_function_power_state
|
||||
# cfg_vf_power_state
|
||||
# cfg_link_power_state
|
||||
# cfg_err_cor_out
|
||||
# cfg_err_nonfatal_out
|
||||
# cfg_err_fatal_out
|
||||
# cfg_local_error_out
|
||||
# cfg_local_error_valid
|
||||
# cfg_rx_pm_state
|
||||
# cfg_tx_pm_state
|
||||
# cfg_ltssm_state
|
||||
# cfg_rcb_status
|
||||
# cfg_obff_enable
|
||||
# cfg_pl_status_change
|
||||
# cfg_tph_requester_enable
|
||||
# cfg_tph_st_mode
|
||||
# cfg_vf_tph_requester_enable
|
||||
# cfg_vf_tph_st_mode
|
||||
|
||||
# Configuration Received Message Interface
|
||||
# cfg_msg_received
|
||||
# cfg_msg_received_data
|
||||
# cfg_msg_received_type
|
||||
|
||||
# Configuration Transmit Message Interface
|
||||
# cfg_msg_transmit
|
||||
# cfg_msg_transmit_type
|
||||
# cfg_msg_transmit_data
|
||||
# cfg_msg_transmit_done
|
||||
|
||||
# Configuration Flow Control Interface
|
||||
# cfg_fc_ph=dut.cfg_fc_ph,
|
||||
# cfg_fc_pd=dut.cfg_fc_pd,
|
||||
# cfg_fc_nph=dut.cfg_fc_nph,
|
||||
# cfg_fc_npd=dut.cfg_fc_npd,
|
||||
# cfg_fc_cplh=dut.cfg_fc_cplh,
|
||||
# cfg_fc_cpld=dut.cfg_fc_cpld,
|
||||
# cfg_fc_sel=dut.cfg_fc_sel,
|
||||
|
||||
# Configuration Control Interface
|
||||
# cfg_hot_reset_in
|
||||
# cfg_hot_reset_out
|
||||
# cfg_config_space_enable
|
||||
# cfg_dsn
|
||||
# cfg_bus_number
|
||||
# cfg_ds_port_number
|
||||
# cfg_ds_bus_number
|
||||
# cfg_ds_device_number
|
||||
# cfg_ds_function_number
|
||||
# cfg_power_state_change_ack
|
||||
# cfg_power_state_change_interrupt
|
||||
cfg_err_cor_in=dut.status_error_cor,
|
||||
cfg_err_uncor_in=dut.status_error_uncor,
|
||||
# cfg_flr_in_process
|
||||
# cfg_flr_done
|
||||
# cfg_vf_flr_in_process
|
||||
# cfg_vf_flr_func_num
|
||||
# cfg_vf_flr_done
|
||||
# cfg_pm_aspm_l1_entry_reject
|
||||
# cfg_pm_aspm_tx_l0s_entry_disable
|
||||
# cfg_req_pm_transition_l23_ready
|
||||
# cfg_link_training_enable
|
||||
|
||||
# Configuration Interrupt Controller Interface
|
||||
# cfg_interrupt_int
|
||||
# cfg_interrupt_sent
|
||||
# cfg_interrupt_pending
|
||||
cfg_interrupt_msi_enable=dut.cfg_interrupt_msi_enable,
|
||||
cfg_interrupt_msi_mmenable=dut.cfg_interrupt_msi_mmenable,
|
||||
cfg_interrupt_msi_mask_update=dut.cfg_interrupt_msi_mask_update,
|
||||
cfg_interrupt_msi_data=dut.cfg_interrupt_msi_data,
|
||||
# cfg_interrupt_msi_select=dut.cfg_interrupt_msi_select,
|
||||
cfg_interrupt_msi_int=dut.cfg_interrupt_msi_int,
|
||||
cfg_interrupt_msi_pending_status=dut.cfg_interrupt_msi_pending_status,
|
||||
cfg_interrupt_msi_pending_status_data_enable=dut.cfg_interrupt_msi_pending_status_data_enable,
|
||||
# cfg_interrupt_msi_pending_status_function_num=dut.cfg_interrupt_msi_pending_status_function_num,
|
||||
cfg_interrupt_msi_sent=dut.cfg_interrupt_msi_sent,
|
||||
cfg_interrupt_msi_fail=dut.cfg_interrupt_msi_fail,
|
||||
# cfg_interrupt_msix_enable
|
||||
# cfg_interrupt_msix_mask
|
||||
# cfg_interrupt_msix_vf_enable
|
||||
# cfg_interrupt_msix_vf_mask
|
||||
# cfg_interrupt_msix_address
|
||||
# cfg_interrupt_msix_data
|
||||
# cfg_interrupt_msix_int
|
||||
# cfg_interrupt_msix_vec_pending
|
||||
# cfg_interrupt_msix_vec_pending_status
|
||||
cfg_interrupt_msi_attr=dut.cfg_interrupt_msi_attr,
|
||||
cfg_interrupt_msi_tph_present=dut.cfg_interrupt_msi_tph_present,
|
||||
cfg_interrupt_msi_tph_type=dut.cfg_interrupt_msi_tph_type,
|
||||
# cfg_interrupt_msi_tph_st_tag=dut.cfg_interrupt_msi_tph_st_tag,
|
||||
# cfg_interrupt_msi_function_number=dut.cfg_interrupt_msi_function_number,
|
||||
|
||||
# Configuration Extend Interface
|
||||
# cfg_ext_read_received
|
||||
# cfg_ext_write_received
|
||||
# cfg_ext_register_number
|
||||
# cfg_ext_function_number
|
||||
# cfg_ext_write_data
|
||||
# cfg_ext_write_byte_enable
|
||||
# cfg_ext_read_data
|
||||
# cfg_ext_read_data_valid
|
||||
)
|
||||
|
||||
# self.dev.log.setLevel(logging.DEBUG)
|
||||
|
||||
self.rc.make_port().connect(self.dev)
|
||||
|
||||
self.dev.functions[0].msi_multiple_message_capable = 5
|
||||
|
||||
self.dev.functions[0].configure_bar(0, 2**22)
|
||||
self.dev.functions[0].configure_bar(1, 2**22)
|
||||
|
||||
dut.sw.setimmediatevalue(0)
|
||||
|
||||
async def init(self):
|
||||
|
||||
await FallingEdge(self.dut.rst)
|
||||
await Timer(100, 'ns')
|
||||
|
||||
await self.rc.enumerate(enable_bus_mastering=True, configure_msi=True)
|
||||
|
||||
|
||||
@cocotb.test()
|
||||
async def run_test(dut):
|
||||
|
||||
tb = TB(dut)
|
||||
|
||||
await tb.init()
|
||||
|
||||
mem_base, mem_data = tb.rc.alloc_region(16*1024*1024)
|
||||
|
||||
dev_pf0_bar0 = tb.rc.tree[0][0].bar_addr[0]
|
||||
dev_pf0_bar1 = tb.rc.tree[0][0].bar_addr[1]
|
||||
|
||||
tb.log.info("Test memory write to BAR 1")
|
||||
|
||||
await tb.rc.mem_write(dev_pf0_bar1, b'\x11\x22\x33\x44')
|
||||
|
||||
await Timer(100, 'ns')
|
||||
|
||||
tb.log.info("Test memory read from BAR 1")
|
||||
|
||||
val = await tb.rc.mem_read(dev_pf0_bar1, 4, 1000)
|
||||
tb.log.info("Read data: %s", val)
|
||||
assert val == b'\x11\x22\x33\x44'
|
||||
|
||||
tb.log.info("Test DMA")
|
||||
|
||||
# write packet data
|
||||
mem_data[0:1024] = bytearray([x % 256 for x in range(1024)])
|
||||
|
||||
# enable DMA
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100000, 1)
|
||||
|
||||
# write pcie read descriptor
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100100, (mem_base+0x0000) & 0xffffffff)
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100104, (mem_base+0x0000 >> 32) & 0xffffffff)
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100108, (0x100) & 0xffffffff)
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x10010C, (0x100 >> 32) & 0xffffffff)
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100110, 0x400)
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100114, 0xAA)
|
||||
|
||||
await Timer(2000, 'ns')
|
||||
|
||||
# read status
|
||||
val = await tb.rc.mem_read_dword(dev_pf0_bar0+0x100118)
|
||||
tb.log.info("Status: 0x%x", val)
|
||||
assert val == 0xAA
|
||||
|
||||
# write pcie write descriptor
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100200, (mem_base+0x1000) & 0xffffffff)
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100204, (mem_base+0x1000 >> 32) & 0xffffffff)
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100208, (0x100) & 0xffffffff)
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x10020C, (0x100 >> 32) & 0xffffffff)
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100210, 0x400)
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100214, 0x55)
|
||||
|
||||
await Timer(2000, 'ns')
|
||||
|
||||
# read status
|
||||
val = await tb.rc.mem_read_dword(dev_pf0_bar0+0x100218)
|
||||
tb.log.info("Status: 0x%x", val)
|
||||
assert val == 0x55
|
||||
|
||||
tb.log.info("%s", hexdump_str(mem_data, 0x1000, 64))
|
||||
|
||||
assert mem_data[0:1024] == mem_data[0x1000:0x1000+1024]
|
||||
|
||||
await RisingEdge(dut.clk)
|
||||
await RisingEdge(dut.clk)
|
||||
|
||||
|
||||
# cocotb-test
|
||||
|
||||
tests_dir = os.path.dirname(__file__)
|
||||
rtl_dir = os.path.abspath(os.path.join(tests_dir, '..', '..', 'rtl'))
|
||||
lib_dir = os.path.abspath(os.path.join(rtl_dir, '..', 'lib'))
|
||||
pcie_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'pcie', 'rtl'))
|
||||
|
||||
|
||||
def test_fpga_core(request):
|
||||
dut = "fpga_core"
|
||||
module = os.path.splitext(os.path.basename(__file__))[0]
|
||||
toplevel = dut
|
||||
|
||||
verilog_sources = [
|
||||
os.path.join(rtl_dir, f"{dut}.v"),
|
||||
os.path.join(rtl_dir, "axi_ram.v"),
|
||||
os.path.join(rtl_dir, "axis_register.v"),
|
||||
os.path.join(pcie_rtl_dir, "axis_arb_mux.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_us_axil_master.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_us_axi_dma.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_us_axi_dma_rd.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_us_axi_dma_wr.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_tag_manager.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_us_axi_master.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_us_axi_master_rd.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_us_axi_master_wr.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_us_axis_cq_demux.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_us_cfg.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_us_msi.v"),
|
||||
os.path.join(pcie_rtl_dir, "arbiter.v"),
|
||||
os.path.join(pcie_rtl_dir, "priority_encoder.v"),
|
||||
os.path.join(pcie_rtl_dir, "pulse_merge.v"),
|
||||
]
|
||||
|
||||
parameters = {}
|
||||
|
||||
parameters['AXIS_PCIE_DATA_WIDTH'] = 512
|
||||
parameters['AXIS_PCIE_KEEP_WIDTH'] = parameters['AXIS_PCIE_DATA_WIDTH'] // 32
|
||||
parameters['AXIS_PCIE_RQ_USER_WIDTH'] = 62 if parameters['AXIS_PCIE_DATA_WIDTH'] < 512 else 137
|
||||
parameters['AXIS_PCIE_RC_USER_WIDTH'] = 75 if parameters['AXIS_PCIE_DATA_WIDTH'] < 512 else 161
|
||||
parameters['AXIS_PCIE_CQ_USER_WIDTH'] = 88 if parameters['AXIS_PCIE_DATA_WIDTH'] < 512 else 183
|
||||
parameters['AXIS_PCIE_CC_USER_WIDTH'] = 33 if parameters['AXIS_PCIE_DATA_WIDTH'] < 512 else 81
|
||||
parameters['RQ_SEQ_NUM_WIDTH'] = 6
|
||||
|
||||
extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()}
|
||||
|
||||
sim_build = os.path.join(tests_dir,
|
||||
"sim_build_"+request.node.name.replace('[', '-').replace(']', ''))
|
||||
|
||||
cocotb_test.simulator.run(
|
||||
python_search=[tests_dir],
|
||||
verilog_sources=verilog_sources,
|
||||
toplevel=toplevel,
|
||||
module=module,
|
||||
parameters=parameters,
|
||||
sim_build=sim_build,
|
||||
extra_env=extra_env,
|
||||
)
|
@ -1 +0,0 @@
|
||||
../lib/pcie/tb/pcie.py
|
@ -1 +0,0 @@
|
||||
../lib/pcie/tb/pcie_us.py
|
@ -1 +0,0 @@
|
||||
../lib/pcie/tb/pcie_usp.py
|
@ -1,520 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
"""
|
||||
|
||||
Copyright (c) 2018 Alex Forencich
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
"""
|
||||
|
||||
from myhdl import *
|
||||
import os
|
||||
import struct
|
||||
|
||||
import pcie
|
||||
import pcie_usp
|
||||
|
||||
module = 'fpga_core'
|
||||
testbench = 'test_%s' % module
|
||||
|
||||
srcs = []
|
||||
|
||||
srcs.append("../rtl/%s.v" % module)
|
||||
srcs.append("../rtl/axi_ram.v")
|
||||
srcs.append("../rtl/axis_register.v")
|
||||
srcs.append("../lib/pcie/rtl/axis_arb_mux.v")
|
||||
srcs.append("../lib/pcie/rtl/pcie_us_axil_master.v")
|
||||
srcs.append("../lib/pcie/rtl/pcie_us_axi_dma.v")
|
||||
srcs.append("../lib/pcie/rtl/pcie_us_axi_dma_rd.v")
|
||||
srcs.append("../lib/pcie/rtl/pcie_us_axi_dma_wr.v")
|
||||
srcs.append("../lib/pcie/rtl/pcie_tag_manager.v")
|
||||
srcs.append("../lib/pcie/rtl/pcie_us_axi_master.v")
|
||||
srcs.append("../lib/pcie/rtl/pcie_us_axi_master_rd.v")
|
||||
srcs.append("../lib/pcie/rtl/pcie_us_axi_master_wr.v")
|
||||
srcs.append("../lib/pcie/rtl/pcie_us_axis_cq_demux.v")
|
||||
srcs.append("../lib/pcie/rtl/pcie_us_cfg.v")
|
||||
srcs.append("../lib/pcie/rtl/pcie_us_msi.v")
|
||||
srcs.append("../lib/pcie/rtl/arbiter.v")
|
||||
srcs.append("../lib/pcie/rtl/priority_encoder.v")
|
||||
srcs.append("../lib/pcie/rtl/pulse_merge.v")
|
||||
srcs.append("%s.v" % testbench)
|
||||
|
||||
src = ' '.join(srcs)
|
||||
|
||||
build_cmd = "iverilog -o %s.vvp %s" % (testbench, src)
|
||||
|
||||
def bench():
|
||||
|
||||
# Parameters
|
||||
AXIS_PCIE_DATA_WIDTH = 512
|
||||
AXIS_PCIE_KEEP_WIDTH = (AXIS_PCIE_DATA_WIDTH/32)
|
||||
AXIS_PCIE_RC_USER_WIDTH = 161
|
||||
AXIS_PCIE_RQ_USER_WIDTH = 137
|
||||
AXIS_PCIE_CQ_USER_WIDTH = 183
|
||||
AXIS_PCIE_CC_USER_WIDTH = 81
|
||||
|
||||
# Inputs
|
||||
clk = Signal(bool(0))
|
||||
rst = Signal(bool(0))
|
||||
current_test = Signal(intbv(0)[8:])
|
||||
|
||||
btnu = Signal(bool(0))
|
||||
btnl = Signal(bool(0))
|
||||
btnd = Signal(bool(0))
|
||||
btnr = Signal(bool(0))
|
||||
btnc = Signal(bool(0))
|
||||
sw = Signal(intbv(0)[4:])
|
||||
m_axis_rq_tready = Signal(bool(0))
|
||||
s_axis_rc_tdata = Signal(intbv(0)[AXIS_PCIE_DATA_WIDTH:])
|
||||
s_axis_rc_tkeep = Signal(intbv(0)[AXIS_PCIE_KEEP_WIDTH:])
|
||||
s_axis_rc_tlast = Signal(bool(0))
|
||||
s_axis_rc_tuser = Signal(intbv(0)[AXIS_PCIE_RC_USER_WIDTH:])
|
||||
s_axis_rc_tvalid = Signal(bool(0))
|
||||
s_axis_cq_tdata = Signal(intbv(0)[AXIS_PCIE_DATA_WIDTH:])
|
||||
s_axis_cq_tkeep = Signal(intbv(0)[AXIS_PCIE_KEEP_WIDTH:])
|
||||
s_axis_cq_tlast = Signal(bool(0))
|
||||
s_axis_cq_tuser = Signal(intbv(0)[AXIS_PCIE_CQ_USER_WIDTH:])
|
||||
s_axis_cq_tvalid = Signal(bool(0))
|
||||
m_axis_cc_tready = Signal(bool(0))
|
||||
cfg_max_payload = Signal(intbv(0)[2:])
|
||||
cfg_max_read_req = Signal(intbv(0)[3:])
|
||||
cfg_mgmt_read_data = Signal(intbv(0)[32:])
|
||||
cfg_mgmt_read_write_done = Signal(bool(0))
|
||||
cfg_interrupt_msi_enable = Signal(intbv(0)[4:])
|
||||
cfg_interrupt_msi_mmenable = Signal(intbv(0)[12:])
|
||||
cfg_interrupt_msi_mask_update = Signal(bool(0))
|
||||
cfg_interrupt_msi_data = Signal(intbv(0)[32:])
|
||||
cfg_interrupt_msi_sent = Signal(bool(0))
|
||||
cfg_interrupt_msi_fail = Signal(bool(0))
|
||||
|
||||
# Outputs
|
||||
led = Signal(intbv(0)[8:])
|
||||
m_axis_rq_tdata = Signal(intbv(0)[AXIS_PCIE_DATA_WIDTH:])
|
||||
m_axis_rq_tkeep = Signal(intbv(0)[AXIS_PCIE_KEEP_WIDTH:])
|
||||
m_axis_rq_tlast = Signal(bool(0))
|
||||
m_axis_rq_tuser = Signal(intbv(0)[AXIS_PCIE_RQ_USER_WIDTH:])
|
||||
m_axis_rq_tvalid = Signal(bool(0))
|
||||
s_axis_rc_tready = Signal(bool(0))
|
||||
s_axis_cq_tready = Signal(bool(0))
|
||||
m_axis_cc_tdata = Signal(intbv(0)[AXIS_PCIE_DATA_WIDTH:])
|
||||
m_axis_cc_tkeep = Signal(intbv(0)[AXIS_PCIE_KEEP_WIDTH:])
|
||||
m_axis_cc_tlast = Signal(bool(0))
|
||||
m_axis_cc_tuser = Signal(intbv(0)[AXIS_PCIE_CC_USER_WIDTH:])
|
||||
m_axis_cc_tvalid = Signal(bool(0))
|
||||
status_error_cor = Signal(bool(0))
|
||||
status_error_uncor = Signal(bool(0))
|
||||
cfg_mgmt_addr = Signal(intbv(0)[10:])
|
||||
cfg_mgmt_function_number = Signal(intbv(0)[8:])
|
||||
cfg_mgmt_write = Signal(bool(0))
|
||||
cfg_mgmt_write_data = Signal(intbv(0)[32:])
|
||||
cfg_mgmt_byte_enable = Signal(intbv(0)[4:])
|
||||
cfg_mgmt_read = Signal(bool(0))
|
||||
cfg_interrupt_msi_int = Signal(intbv(0)[32:])
|
||||
cfg_interrupt_msi_pending_status = Signal(intbv(0)[32:])
|
||||
cfg_interrupt_msi_select = Signal(intbv(0)[2:])
|
||||
cfg_interrupt_msi_pending_status_function_num = Signal(intbv(0)[2:])
|
||||
cfg_interrupt_msi_pending_status_data_enable = Signal(bool(0))
|
||||
cfg_interrupt_msi_attr = Signal(intbv(0)[3:])
|
||||
cfg_interrupt_msi_tph_present = Signal(bool(0))
|
||||
cfg_interrupt_msi_tph_type = Signal(intbv(0)[2:])
|
||||
cfg_interrupt_msi_tph_st_tag = Signal(intbv(0)[8:])
|
||||
cfg_interrupt_msi_function_number = Signal(intbv(0)[8:])
|
||||
|
||||
# Clock and Reset Interface
|
||||
user_clk=Signal(bool(0))
|
||||
user_reset=Signal(bool(0))
|
||||
sys_clk=Signal(bool(0))
|
||||
sys_reset=Signal(bool(0))
|
||||
|
||||
# PCIe devices
|
||||
rc = pcie.RootComplex()
|
||||
|
||||
mem_base, mem_data = rc.alloc_region(16*1024*1024)
|
||||
|
||||
dev = pcie_usp.UltrascalePlusPCIe()
|
||||
|
||||
dev.pcie_generation = 3
|
||||
dev.pcie_link_width = 16
|
||||
dev.user_clk_frequency = 250e6
|
||||
|
||||
dev.functions[0].msi_multiple_message_capable = 5
|
||||
|
||||
dev.functions[0].configure_bar(0, 4*1024*1024)
|
||||
dev.functions[0].configure_bar(1, 4*1024*1024)
|
||||
|
||||
rc.make_port().connect(dev)
|
||||
|
||||
pcie_logic = dev.create_logic(
|
||||
# Completer reQuest Interface
|
||||
m_axis_cq_tdata=s_axis_cq_tdata,
|
||||
m_axis_cq_tuser=s_axis_cq_tuser,
|
||||
m_axis_cq_tlast=s_axis_cq_tlast,
|
||||
m_axis_cq_tkeep=s_axis_cq_tkeep,
|
||||
m_axis_cq_tvalid=s_axis_cq_tvalid,
|
||||
m_axis_cq_tready=s_axis_cq_tready,
|
||||
#pcie_cq_np_req=pcie_cq_np_req,
|
||||
pcie_cq_np_req=Signal(intbv(1)[2:]),
|
||||
#pcie_cq_np_req_count=pcie_cq_np_req_count,
|
||||
|
||||
# Completer Completion Interface
|
||||
s_axis_cc_tdata=m_axis_cc_tdata,
|
||||
s_axis_cc_tuser=m_axis_cc_tuser,
|
||||
s_axis_cc_tlast=m_axis_cc_tlast,
|
||||
s_axis_cc_tkeep=m_axis_cc_tkeep,
|
||||
s_axis_cc_tvalid=m_axis_cc_tvalid,
|
||||
s_axis_cc_tready=m_axis_cc_tready,
|
||||
|
||||
# Requester reQuest Interface
|
||||
s_axis_rq_tdata=m_axis_rq_tdata,
|
||||
s_axis_rq_tuser=m_axis_rq_tuser,
|
||||
s_axis_rq_tlast=m_axis_rq_tlast,
|
||||
s_axis_rq_tkeep=m_axis_rq_tkeep,
|
||||
s_axis_rq_tvalid=m_axis_rq_tvalid,
|
||||
s_axis_rq_tready=m_axis_rq_tready,
|
||||
#pcie_rq_seq_num0=pcie_rq_seq_num0,
|
||||
#pcie_rq_seq_num_vld0=pcie_rq_seq_num_vld0,
|
||||
#pcie_rq_seq_num1=pcie_rq_seq_num1,
|
||||
#pcie_rq_seq_num_vld1=pcie_rq_seq_num_vld1,
|
||||
#pcie_rq_tag0=pcie_rq_tag0,
|
||||
#pcie_rq_tag1=pcie_rq_tag1,
|
||||
#pcie_rq_tag_av=pcie_rq_tag_av,
|
||||
#pcie_rq_tag_vld0=pcie_rq_tag_vld0,
|
||||
#pcie_rq_tag_vld1=pcie_rq_tag_vld1,
|
||||
|
||||
# Requester Completion Interface
|
||||
m_axis_rc_tdata=s_axis_rc_tdata,
|
||||
m_axis_rc_tuser=s_axis_rc_tuser,
|
||||
m_axis_rc_tlast=s_axis_rc_tlast,
|
||||
m_axis_rc_tkeep=s_axis_rc_tkeep,
|
||||
m_axis_rc_tvalid=s_axis_rc_tvalid,
|
||||
m_axis_rc_tready=s_axis_rc_tready,
|
||||
|
||||
# Transmit Flow Control Interface
|
||||
#pcie_tfc_nph_av=pcie_tfc_nph_av,
|
||||
#pcie_tfc_npd_av=pcie_tfc_npd_av,
|
||||
|
||||
# Configuration Management Interface
|
||||
cfg_mgmt_addr=cfg_mgmt_addr,
|
||||
cfg_mgmt_function_number=cfg_mgmt_function_number,
|
||||
cfg_mgmt_write=cfg_mgmt_write,
|
||||
cfg_mgmt_write_data=cfg_mgmt_write_data,
|
||||
cfg_mgmt_byte_enable=cfg_mgmt_byte_enable,
|
||||
cfg_mgmt_read=cfg_mgmt_read,
|
||||
cfg_mgmt_read_data=cfg_mgmt_read_data,
|
||||
cfg_mgmt_read_write_done=cfg_mgmt_read_write_done,
|
||||
#cfg_mgmt_debug_access=cfg_mgmt_debug_access,
|
||||
|
||||
# Configuration Status Interface
|
||||
#cfg_phy_link_down=cfg_phy_link_down,
|
||||
#cfg_phy_link_status=cfg_phy_link_status,
|
||||
#cfg_negotiated_width=cfg_negotiated_width,
|
||||
#cfg_current_speed=cfg_current_speed,
|
||||
cfg_max_payload=cfg_max_payload,
|
||||
cfg_max_read_req=cfg_max_read_req,
|
||||
#cfg_function_status=cfg_function_status,
|
||||
#cfg_vf_status=cfg_vf_status,
|
||||
#cfg_function_power_state=cfg_function_power_state,
|
||||
#cfg_vf_power_state=cfg_vf_power_state,
|
||||
#cfg_link_power_state=cfg_link_power_state,
|
||||
#cfg_err_cor_out=cfg_err_cor_out,
|
||||
#cfg_err_nonfatal_out=cfg_err_nonfatal_out,
|
||||
#cfg_err_fatal_out=cfg_err_fatal_out,
|
||||
#cfg_local_err_out=cfg_local_err_out,
|
||||
#cfg_local_err_valid=cfg_local_err_valid,
|
||||
#cfg_rx_pm_state=cfg_rx_pm_state,
|
||||
#cfg_tx_pm_state=cfg_tx_pm_state,
|
||||
#cfg_ltssm_state=cfg_ltssm_state,
|
||||
#cfg_rcb_status=cfg_rcb_status,
|
||||
#cfg_obff_enable=cfg_obff_enable,
|
||||
#cfg_pl_status_change=cfg_pl_status_change,
|
||||
#cfg_tph_requester_enable=cfg_tph_requester_enable,
|
||||
#cfg_tph_st_mode=cfg_tph_st_mode,
|
||||
#cfg_vf_tph_requester_enable=cfg_vf_tph_requester_enable,
|
||||
#cfg_vf_tph_st_mode=cfg_vf_tph_st_mode,
|
||||
|
||||
# Configuration Received Message Interface
|
||||
#cfg_msg_received=cfg_msg_received,
|
||||
#cfg_msg_received_data=cfg_msg_received_data,
|
||||
#cfg_msg_received_type=cfg_msg_received_type,
|
||||
|
||||
# Configuration Transmit Message Interface
|
||||
#cfg_msg_transmit=cfg_msg_transmit,
|
||||
#cfg_msg_transmit_type=cfg_msg_transmit_type,
|
||||
#cfg_msg_transmit_data=cfg_msg_transmit_data,
|
||||
#cfg_msg_transmit_done=cfg_msg_transmit_done,
|
||||
|
||||
# Configuration Flow Control Interface
|
||||
#cfg_fc_ph=cfg_fc_ph,
|
||||
#cfg_fc_pd=cfg_fc_pd,
|
||||
#cfg_fc_nph=cfg_fc_nph,
|
||||
#cfg_fc_npd=cfg_fc_npd,
|
||||
#cfg_fc_cplh=cfg_fc_cplh,
|
||||
#cfg_fc_cpld=cfg_fc_cpld,
|
||||
#cfg_fc_sel=cfg_fc_sel,
|
||||
|
||||
# Configuration Control Interface
|
||||
#cfg_hot_reset_in=cfg_hot_reset_in,
|
||||
#cfg_hot_reset_out=cfg_hot_reset_out,
|
||||
#cfg_config_space_enable=cfg_config_space_enable,
|
||||
#cfg_dsn=cfg_dsn,
|
||||
#cfg_ds_port_number=cfg_ds_port_number,
|
||||
#cfg_ds_bus_number=cfg_ds_bus_number,
|
||||
#cfg_ds_device_number=cfg_ds_device_number,
|
||||
#cfg_ds_function_number=cfg_ds_function_number,
|
||||
#cfg_power_state_change_ack=cfg_power_state_change_ack,
|
||||
#cfg_power_state_change_interrupt=cfg_power_state_change_interrupt,
|
||||
cfg_err_cor_in=status_error_cor,
|
||||
cfg_err_uncor_in=status_error_uncor,
|
||||
#cfg_flr_done=cfg_flr_done,
|
||||
#cfg_vf_flr_done=cfg_vf_flr_done,
|
||||
#cfg_flr_in_process=cfg_flr_in_process,
|
||||
#cfg_vf_flr_in_process=cfg_vf_flr_in_process,
|
||||
#cfg_req_pm_transition_l23_ready=cfg_req_pm_transition_l23_ready,
|
||||
#cfg_link_training_enable=cfg_link_training_enable,
|
||||
|
||||
# Configuration Interrupt Controller Interface
|
||||
#cfg_interrupt_int=cfg_interrupt_int,
|
||||
#cfg_interrupt_sent=cfg_interrupt_sent,
|
||||
#cfg_interrupt_pending=cfg_interrupt_pending,
|
||||
cfg_interrupt_msi_enable=cfg_interrupt_msi_enable,
|
||||
cfg_interrupt_msi_mmenable=cfg_interrupt_msi_mmenable,
|
||||
cfg_interrupt_msi_mask_update=cfg_interrupt_msi_mask_update,
|
||||
cfg_interrupt_msi_data=cfg_interrupt_msi_data,
|
||||
cfg_interrupt_msi_select=cfg_interrupt_msi_select,
|
||||
cfg_interrupt_msi_int=cfg_interrupt_msi_int,
|
||||
cfg_interrupt_msi_pending_status=cfg_interrupt_msi_pending_status,
|
||||
cfg_interrupt_msi_pending_status_data_enable=cfg_interrupt_msi_pending_status_data_enable,
|
||||
cfg_interrupt_msi_pending_status_function_num=cfg_interrupt_msi_pending_status_function_num,
|
||||
cfg_interrupt_msi_sent=cfg_interrupt_msi_sent,
|
||||
cfg_interrupt_msi_fail=cfg_interrupt_msi_fail,
|
||||
#cfg_interrupt_msix_enable=cfg_interrupt_msix_enable,
|
||||
#cfg_interrupt_msix_mask=cfg_interrupt_msix_mask,
|
||||
#cfg_interrupt_msix_vf_enable=cfg_interrupt_msix_vf_enable,
|
||||
#cfg_interrupt_msix_vf_mask=cfg_interrupt_msix_vf_mask,
|
||||
#cfg_interrupt_msix_address=cfg_interrupt_msix_address,
|
||||
#cfg_interrupt_msix_data=cfg_interrupt_msix_data,
|
||||
#cfg_interrupt_msix_int=cfg_interrupt_msix_int,
|
||||
#cfg_interrupt_msix_vec_pending=cfg_interrupt_msix_vec_pending,
|
||||
#cfg_interrupt_msix_vec_pending_status=cfg_interrupt_msix_vec_pending_status,
|
||||
cfg_interrupt_msi_attr=cfg_interrupt_msi_attr,
|
||||
cfg_interrupt_msi_tph_present=cfg_interrupt_msi_tph_present,
|
||||
cfg_interrupt_msi_tph_type=cfg_interrupt_msi_tph_type,
|
||||
cfg_interrupt_msi_tph_st_tag=cfg_interrupt_msi_tph_st_tag,
|
||||
cfg_interrupt_msi_function_number=cfg_interrupt_msi_function_number,
|
||||
|
||||
# Configuration Extend Interface
|
||||
#cfg_ext_read_received=cfg_ext_read_received,
|
||||
#cfg_ext_write_received=cfg_ext_write_received,
|
||||
#cfg_ext_register_number=cfg_ext_register_number,
|
||||
#cfg_ext_function_number=cfg_ext_function_number,
|
||||
#cfg_ext_write_data=cfg_ext_write_data,
|
||||
#cfg_ext_write_byte_enable=cfg_ext_write_byte_enable,
|
||||
#cfg_ext_read_data=cfg_ext_read_data,
|
||||
#cfg_ext_read_data_valid=cfg_ext_read_data_valid,
|
||||
|
||||
# Clock and Reset Interface
|
||||
user_clk=user_clk,
|
||||
user_reset=user_reset,
|
||||
#user_lnk_up=user_lnk_up,
|
||||
sys_clk=sys_clk,
|
||||
sys_clk_gt=sys_clk,
|
||||
sys_reset=sys_reset,
|
||||
#phy_rdy_out=phy_rdy_out
|
||||
)
|
||||
|
||||
# DUT
|
||||
if os.system(build_cmd):
|
||||
raise Exception("Error running build command")
|
||||
|
||||
dut = Cosimulation(
|
||||
"vvp -m myhdl %s.vvp -lxt2" % testbench,
|
||||
clk=user_clk,
|
||||
rst=user_reset,
|
||||
current_test=current_test,
|
||||
btnu=btnu,
|
||||
btnl=btnl,
|
||||
btnd=btnd,
|
||||
btnr=btnr,
|
||||
btnc=btnc,
|
||||
sw=sw,
|
||||
led=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_function_number=cfg_mgmt_function_number,
|
||||
cfg_mgmt_write=cfg_mgmt_write,
|
||||
cfg_mgmt_write_data=cfg_mgmt_write_data,
|
||||
cfg_mgmt_byte_enable=cfg_mgmt_byte_enable,
|
||||
cfg_mgmt_read=cfg_mgmt_read,
|
||||
cfg_mgmt_read_data=cfg_mgmt_read_data,
|
||||
cfg_mgmt_read_write_done=cfg_mgmt_read_write_done,
|
||||
cfg_interrupt_msi_enable=cfg_interrupt_msi_enable,
|
||||
cfg_interrupt_msi_int=cfg_interrupt_msi_int,
|
||||
cfg_interrupt_msi_sent=cfg_interrupt_msi_sent,
|
||||
cfg_interrupt_msi_fail=cfg_interrupt_msi_fail,
|
||||
cfg_interrupt_msi_mmenable=cfg_interrupt_msi_mmenable,
|
||||
cfg_interrupt_msi_pending_status=cfg_interrupt_msi_pending_status,
|
||||
cfg_interrupt_msi_mask_update=cfg_interrupt_msi_mask_update,
|
||||
cfg_interrupt_msi_select=cfg_interrupt_msi_select,
|
||||
cfg_interrupt_msi_data=cfg_interrupt_msi_data,
|
||||
cfg_interrupt_msi_pending_status_function_num=cfg_interrupt_msi_pending_status_function_num,
|
||||
cfg_interrupt_msi_pending_status_data_enable=cfg_interrupt_msi_pending_status_data_enable,
|
||||
cfg_interrupt_msi_attr=cfg_interrupt_msi_attr,
|
||||
cfg_interrupt_msi_tph_present=cfg_interrupt_msi_tph_present,
|
||||
cfg_interrupt_msi_tph_type=cfg_interrupt_msi_tph_type,
|
||||
cfg_interrupt_msi_tph_st_tag=cfg_interrupt_msi_tph_st_tag,
|
||||
cfg_interrupt_msi_function_number=cfg_interrupt_msi_function_number,
|
||||
status_error_cor=status_error_cor,
|
||||
status_error_uncor=status_error_uncor
|
||||
)
|
||||
|
||||
@always(delay(5))
|
||||
def clkgen():
|
||||
clk.next = not clk
|
||||
|
||||
@always_comb
|
||||
def clk_logic():
|
||||
sys_clk.next = clk
|
||||
sys_reset.next = not rst
|
||||
|
||||
@instance
|
||||
def check():
|
||||
yield delay(100)
|
||||
yield clk.posedge
|
||||
rst.next = 1
|
||||
yield clk.posedge
|
||||
rst.next = 0
|
||||
yield clk.posedge
|
||||
yield delay(100)
|
||||
yield clk.posedge
|
||||
|
||||
# testbench stimulus
|
||||
|
||||
current_tag = 1
|
||||
|
||||
yield clk.posedge
|
||||
print("test 1: enumeration")
|
||||
current_test.next = 1
|
||||
|
||||
yield rc.enumerate(enable_bus_mastering=True, configure_msi=True)
|
||||
|
||||
dev_pf0_bar0 = dev.functions[0].bar[0] & 0xfffffffc
|
||||
dev_pf0_bar1 = dev.functions[0].bar[1] & 0xfffffffc
|
||||
|
||||
yield delay(100)
|
||||
|
||||
yield clk.posedge
|
||||
print("test 2: memory write to bar 1")
|
||||
current_test.next = 2
|
||||
|
||||
yield rc.mem_write(dev_pf0_bar1, b'\x11\x22\x33\x44')
|
||||
|
||||
yield delay(100)
|
||||
|
||||
yield clk.posedge
|
||||
print("test 3: memory read from bar 1")
|
||||
current_test.next = 3
|
||||
|
||||
val = yield from rc.mem_read(dev_pf0_bar1, 4, 1000)
|
||||
print(val)
|
||||
assert val == b'\x11\x22\x33\x44'
|
||||
|
||||
yield delay(100)
|
||||
|
||||
yield clk.posedge
|
||||
print("test 4: test DMA")
|
||||
current_test.next = 4
|
||||
|
||||
# write packet data
|
||||
mem_data[0:1024] = bytearray([x%256 for x in range(1024)])
|
||||
|
||||
# enable DMA
|
||||
yield rc.mem_write(dev_pf0_bar0+0x100000, struct.pack('<L', 1))
|
||||
|
||||
# write pcie read descriptor
|
||||
yield rc.mem_write(dev_pf0_bar0+0x100100, struct.pack('<L', (mem_base+0x0000) & 0xffffffff))
|
||||
yield rc.mem_write(dev_pf0_bar0+0x100104, struct.pack('<L', (mem_base+0x0000 >> 32) & 0xffffffff))
|
||||
yield rc.mem_write(dev_pf0_bar0+0x100108, struct.pack('<L', (0x100) & 0xffffffff))
|
||||
yield rc.mem_write(dev_pf0_bar0+0x10010C, struct.pack('<L', (0x100 >> 32) & 0xffffffff))
|
||||
yield rc.mem_write(dev_pf0_bar0+0x100110, struct.pack('<L', 0x400))
|
||||
yield rc.mem_write(dev_pf0_bar0+0x100114, struct.pack('<L', 0xAA))
|
||||
|
||||
yield delay(2000)
|
||||
|
||||
# read status
|
||||
val = yield from rc.mem_read(dev_pf0_bar0+0x100118, 4)
|
||||
print(val)
|
||||
|
||||
# write pcie write descriptor
|
||||
yield rc.mem_write(dev_pf0_bar0+0x100200, struct.pack('<L', (mem_base+0x1000) & 0xffffffff))
|
||||
yield rc.mem_write(dev_pf0_bar0+0x100204, struct.pack('<L', (mem_base+0x1000 >> 32) & 0xffffffff))
|
||||
yield rc.mem_write(dev_pf0_bar0+0x100208, struct.pack('<L', (0x100) & 0xffffffff))
|
||||
yield rc.mem_write(dev_pf0_bar0+0x10020C, struct.pack('<L', (0x100 >> 32) & 0xffffffff))
|
||||
yield rc.mem_write(dev_pf0_bar0+0x100210, struct.pack('<L', 0x400))
|
||||
yield rc.mem_write(dev_pf0_bar0+0x100214, struct.pack('<L', 0x55))
|
||||
|
||||
yield delay(2000)
|
||||
|
||||
# read status
|
||||
val = yield from rc.mem_read(dev_pf0_bar0+0x100218, 4)
|
||||
print(val)
|
||||
|
||||
data = mem_data[0x1000:(0x1000)+64]
|
||||
for i in range(0, len(data), 16):
|
||||
print(" ".join(("{:02x}".format(c) for c in bytearray(data[i:i+16]))))
|
||||
|
||||
assert mem_data[0:1024] == mem_data[0x1000:0x1000+1024]
|
||||
|
||||
yield delay(100)
|
||||
|
||||
raise StopSimulation
|
||||
|
||||
return instances()
|
||||
|
||||
def test_bench():
|
||||
sim = Simulation(bench())
|
||||
sim.run()
|
||||
|
||||
if __name__ == '__main__':
|
||||
print("Running test...")
|
||||
test_bench()
|
@ -1,243 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2018 Alex Forencich
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
// Language: Verilog 2001
|
||||
|
||||
`timescale 1ns / 1ps
|
||||
|
||||
/*
|
||||
* Testbench for fpga_core
|
||||
*/
|
||||
module test_fpga_core;
|
||||
|
||||
// Parameters
|
||||
parameter AXIS_PCIE_DATA_WIDTH = 512;
|
||||
parameter AXIS_PCIE_KEEP_WIDTH = (AXIS_PCIE_DATA_WIDTH/32);
|
||||
parameter AXIS_PCIE_RC_USER_WIDTH = 161;
|
||||
parameter AXIS_PCIE_RQ_USER_WIDTH = 137;
|
||||
parameter AXIS_PCIE_CQ_USER_WIDTH = 183;
|
||||
parameter AXIS_PCIE_CC_USER_WIDTH = 81;
|
||||
|
||||
// Inputs
|
||||
reg clk = 0;
|
||||
reg rst = 0;
|
||||
reg [7:0] current_test = 0;
|
||||
|
||||
reg [3:0] sw = 0;
|
||||
reg m_axis_rq_tready = 0;
|
||||
reg [AXIS_PCIE_DATA_WIDTH-1:0] s_axis_rc_tdata = 0;
|
||||
reg [AXIS_PCIE_KEEP_WIDTH-1:0] s_axis_rc_tkeep = 0;
|
||||
reg s_axis_rc_tlast = 0;
|
||||
reg [AXIS_PCIE_RC_USER_WIDTH-1:0] s_axis_rc_tuser = 0;
|
||||
reg s_axis_rc_tvalid = 0;
|
||||
reg [AXIS_PCIE_DATA_WIDTH-1:0] s_axis_cq_tdata = 0;
|
||||
reg [AXIS_PCIE_KEEP_WIDTH-1:0] s_axis_cq_tkeep = 0;
|
||||
reg s_axis_cq_tlast = 0;
|
||||
reg [AXIS_PCIE_CQ_USER_WIDTH-1:0] s_axis_cq_tuser = 0;
|
||||
reg s_axis_cq_tvalid = 0;
|
||||
reg m_axis_cc_tready = 0;
|
||||
reg [2:0] cfg_max_payload = 0;
|
||||
reg [2:0] cfg_max_read_req = 0;
|
||||
reg [31:0] cfg_mgmt_read_data = 0;
|
||||
reg cfg_mgmt_read_write_done = 0;
|
||||
reg [3:0] cfg_interrupt_msi_enable = 0;
|
||||
reg [11:0] cfg_interrupt_msi_mmenable = 0;
|
||||
reg cfg_interrupt_msi_mask_update = 0;
|
||||
reg [31:0] cfg_interrupt_msi_data = 0;
|
||||
reg cfg_interrupt_msi_sent = 0;
|
||||
reg cfg_interrupt_msi_fail = 0;
|
||||
|
||||
// Outputs
|
||||
wire [2:0] led;
|
||||
wire [1:0] user_led_g;
|
||||
wire user_led_r;
|
||||
wire [1:0] front_led;
|
||||
wire [AXIS_PCIE_DATA_WIDTH-1:0] m_axis_rq_tdata;
|
||||
wire [AXIS_PCIE_KEEP_WIDTH-1:0] m_axis_rq_tkeep;
|
||||
wire m_axis_rq_tlast;
|
||||
wire [AXIS_PCIE_RQ_USER_WIDTH-1:0] m_axis_rq_tuser;
|
||||
wire m_axis_rq_tvalid;
|
||||
wire s_axis_rc_tready;
|
||||
wire s_axis_cq_tready;
|
||||
wire [AXIS_PCIE_DATA_WIDTH-1:0] m_axis_cc_tdata;
|
||||
wire [AXIS_PCIE_KEEP_WIDTH-1:0] m_axis_cc_tkeep;
|
||||
wire m_axis_cc_tlast;
|
||||
wire [AXIS_PCIE_CC_USER_WIDTH-1:0] m_axis_cc_tuser;
|
||||
wire m_axis_cc_tvalid;
|
||||
wire [9:0] cfg_mgmt_addr;
|
||||
wire [7:0] cfg_mgmt_function_number;
|
||||
wire cfg_mgmt_write;
|
||||
wire [31:0] cfg_mgmt_write_data;
|
||||
wire [3:0] cfg_mgmt_byte_enable;
|
||||
wire cfg_mgmt_read;
|
||||
wire [3:0] cfg_interrupt_msi_select;
|
||||
wire [31:0] cfg_interrupt_msi_int;
|
||||
wire [31:0] cfg_interrupt_msi_pending_status;
|
||||
wire cfg_interrupt_msi_pending_status_data_enable;
|
||||
wire [3:0] cfg_interrupt_msi_pending_status_function_num;
|
||||
wire [2:0] cfg_interrupt_msi_attr;
|
||||
wire cfg_interrupt_msi_tph_present;
|
||||
wire [1:0] cfg_interrupt_msi_tph_type;
|
||||
wire [8:0] cfg_interrupt_msi_tph_st_tag;
|
||||
wire [3:0] cfg_interrupt_msi_function_number;
|
||||
wire status_error_cor;
|
||||
wire status_error_uncor;
|
||||
|
||||
initial begin
|
||||
// myhdl integration
|
||||
$from_myhdl(
|
||||
clk,
|
||||
rst,
|
||||
current_test,
|
||||
sw,
|
||||
m_axis_rq_tready,
|
||||
s_axis_rc_tdata,
|
||||
s_axis_rc_tkeep,
|
||||
s_axis_rc_tlast,
|
||||
s_axis_rc_tuser,
|
||||
s_axis_rc_tvalid,
|
||||
s_axis_cq_tdata,
|
||||
s_axis_cq_tkeep,
|
||||
s_axis_cq_tlast,
|
||||
s_axis_cq_tuser,
|
||||
s_axis_cq_tvalid,
|
||||
m_axis_cc_tready,
|
||||
cfg_max_payload,
|
||||
cfg_max_read_req,
|
||||
cfg_mgmt_read_data,
|
||||
cfg_mgmt_read_write_done,
|
||||
cfg_interrupt_msi_enable,
|
||||
cfg_interrupt_msi_mmenable,
|
||||
cfg_interrupt_msi_mask_update,
|
||||
cfg_interrupt_msi_data,
|
||||
cfg_interrupt_msi_sent,
|
||||
cfg_interrupt_msi_fail
|
||||
);
|
||||
$to_myhdl(
|
||||
led,
|
||||
m_axis_rq_tdata,
|
||||
m_axis_rq_tkeep,
|
||||
m_axis_rq_tlast,
|
||||
m_axis_rq_tuser,
|
||||
m_axis_rq_tvalid,
|
||||
s_axis_rc_tready,
|
||||
s_axis_cq_tready,
|
||||
m_axis_cc_tdata,
|
||||
m_axis_cc_tkeep,
|
||||
m_axis_cc_tlast,
|
||||
m_axis_cc_tuser,
|
||||
m_axis_cc_tvalid,
|
||||
cfg_mgmt_addr,
|
||||
cfg_mgmt_function_number,
|
||||
cfg_mgmt_write,
|
||||
cfg_mgmt_write_data,
|
||||
cfg_mgmt_byte_enable,
|
||||
cfg_mgmt_read,
|
||||
cfg_interrupt_msi_select,
|
||||
cfg_interrupt_msi_int,
|
||||
cfg_interrupt_msi_pending_status,
|
||||
cfg_interrupt_msi_pending_status_data_enable,
|
||||
cfg_interrupt_msi_pending_status_function_num,
|
||||
cfg_interrupt_msi_attr,
|
||||
cfg_interrupt_msi_tph_present,
|
||||
cfg_interrupt_msi_tph_type,
|
||||
cfg_interrupt_msi_tph_st_tag,
|
||||
cfg_interrupt_msi_function_number,
|
||||
status_error_cor,
|
||||
status_error_uncor
|
||||
);
|
||||
|
||||
// dump file
|
||||
$dumpfile("test_fpga_core.lxt");
|
||||
$dumpvars(0, test_fpga_core);
|
||||
end
|
||||
|
||||
fpga_core #(
|
||||
.AXIS_PCIE_DATA_WIDTH(AXIS_PCIE_DATA_WIDTH),
|
||||
.AXIS_PCIE_KEEP_WIDTH(AXIS_PCIE_KEEP_WIDTH),
|
||||
.AXIS_PCIE_RC_USER_WIDTH(AXIS_PCIE_RC_USER_WIDTH),
|
||||
.AXIS_PCIE_RQ_USER_WIDTH(AXIS_PCIE_RQ_USER_WIDTH),
|
||||
.AXIS_PCIE_CQ_USER_WIDTH(AXIS_PCIE_CQ_USER_WIDTH),
|
||||
.AXIS_PCIE_CC_USER_WIDTH(AXIS_PCIE_CC_USER_WIDTH)
|
||||
)
|
||||
UUT (
|
||||
.clk(clk),
|
||||
.rst(rst),
|
||||
.sw(sw),
|
||||
.led(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_function_number(cfg_mgmt_function_number),
|
||||
.cfg_mgmt_write(cfg_mgmt_write),
|
||||
.cfg_mgmt_write_data(cfg_mgmt_write_data),
|
||||
.cfg_mgmt_byte_enable(cfg_mgmt_byte_enable),
|
||||
.cfg_mgmt_read(cfg_mgmt_read),
|
||||
.cfg_mgmt_read_data(cfg_mgmt_read_data),
|
||||
.cfg_mgmt_read_write_done(cfg_mgmt_read_write_done),
|
||||
.cfg_interrupt_msi_enable(cfg_interrupt_msi_enable),
|
||||
.cfg_interrupt_msi_mmenable(cfg_interrupt_msi_mmenable),
|
||||
.cfg_interrupt_msi_mask_update(cfg_interrupt_msi_mask_update),
|
||||
.cfg_interrupt_msi_data(cfg_interrupt_msi_data),
|
||||
.cfg_interrupt_msi_select(cfg_interrupt_msi_select),
|
||||
.cfg_interrupt_msi_int(cfg_interrupt_msi_int),
|
||||
.cfg_interrupt_msi_pending_status(cfg_interrupt_msi_pending_status),
|
||||
.cfg_interrupt_msi_pending_status_data_enable(cfg_interrupt_msi_pending_status_data_enable),
|
||||
.cfg_interrupt_msi_pending_status_function_num(cfg_interrupt_msi_pending_status_function_num),
|
||||
.cfg_interrupt_msi_sent(cfg_interrupt_msi_sent),
|
||||
.cfg_interrupt_msi_fail(cfg_interrupt_msi_fail),
|
||||
.cfg_interrupt_msi_attr(cfg_interrupt_msi_attr),
|
||||
.cfg_interrupt_msi_tph_present(cfg_interrupt_msi_tph_present),
|
||||
.cfg_interrupt_msi_tph_type(cfg_interrupt_msi_tph_type),
|
||||
.cfg_interrupt_msi_tph_st_tag(cfg_interrupt_msi_tph_st_tag),
|
||||
.cfg_interrupt_msi_function_number(cfg_interrupt_msi_function_number),
|
||||
.status_error_cor(status_error_cor),
|
||||
.status_error_uncor(status_error_uncor)
|
||||
);
|
||||
|
||||
endmodule
|
@ -1 +0,0 @@
|
||||
../lib/pcie/tb/axis_ep.py
|
107
example/ZCU106/fpga_axi/tb/fpga_core/Makefile
Normal file
107
example/ZCU106/fpga_axi/tb/fpga_core/Makefile
Normal file
@ -0,0 +1,107 @@
|
||||
# Copyright (c) 2020 Alex Forencich
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in
|
||||
# all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
# THE SOFTWARE.
|
||||
|
||||
TOPLEVEL_LANG = verilog
|
||||
|
||||
SIM ?= icarus
|
||||
WAVES ?= 0
|
||||
|
||||
COCOTB_HDL_TIMEUNIT = 1ns
|
||||
COCOTB_HDL_TIMEPRECISION = 1ps
|
||||
|
||||
DUT = fpga_core
|
||||
TOPLEVEL = $(DUT)
|
||||
MODULE = test_$(DUT)
|
||||
VERILOG_SOURCES += ../../rtl/$(DUT).v
|
||||
VERILOG_SOURCES += ../../rtl/axi_ram.v
|
||||
VERILOG_SOURCES += ../../rtl/axis_register.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/axis_arb_mux.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_axil_master.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_axi_dma.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_axi_dma_rd.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_axi_dma_wr.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_tag_manager.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_axi_master.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_axi_master_rd.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_axi_master_wr.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_axis_cq_demux.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_cfg.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_msi.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/arbiter.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/priority_encoder.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pulse_merge.v
|
||||
|
||||
# module parameters
|
||||
export PARAM_AXIS_PCIE_DATA_WIDTH ?= 128
|
||||
export PARAM_AXIS_PCIE_KEEP_WIDTH ?= $(shell expr $(PARAM_AXIS_PCIE_DATA_WIDTH) / 32 )
|
||||
export PARAM_AXIS_PCIE_RQ_USER_WIDTH ?= $(if $(filter-out 512,$(PARAM_AXIS_PCIE_DATA_WIDTH)),62,137)
|
||||
export PARAM_AXIS_PCIE_RC_USER_WIDTH ?= $(if $(filter-out 512,$(PARAM_AXIS_PCIE_DATA_WIDTH)),75,161)
|
||||
export PARAM_AXIS_PCIE_CQ_USER_WIDTH ?= $(if $(filter-out 512,$(PARAM_AXIS_PCIE_DATA_WIDTH)),88,183)
|
||||
export PARAM_AXIS_PCIE_CC_USER_WIDTH ?= $(if $(filter-out 512,$(PARAM_AXIS_PCIE_DATA_WIDTH)),33,81)
|
||||
export PARAM_RQ_SEQ_NUM_WIDTH ?= 6
|
||||
|
||||
SIM_BUILD ?= sim_build_$(MODULE)
|
||||
|
||||
ifeq ($(SIM), icarus)
|
||||
PLUSARGS += -fst
|
||||
|
||||
COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_DATA_WIDTH=$(PARAM_AXIS_PCIE_DATA_WIDTH)
|
||||
COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_KEEP_WIDTH=$(PARAM_AXIS_PCIE_KEEP_WIDTH)
|
||||
COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_RQ_USER_WIDTH=$(PARAM_AXIS_PCIE_RQ_USER_WIDTH)
|
||||
COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_RC_USER_WIDTH=$(PARAM_AXIS_PCIE_RC_USER_WIDTH)
|
||||
COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_CQ_USER_WIDTH=$(PARAM_AXIS_PCIE_CQ_USER_WIDTH)
|
||||
COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_CC_USER_WIDTH=$(PARAM_AXIS_PCIE_CC_USER_WIDTH)
|
||||
COMPILE_ARGS += -P $(TOPLEVEL).RQ_SEQ_NUM_WIDTH=$(PARAM_RQ_SEQ_NUM_WIDTH)
|
||||
|
||||
ifeq ($(WAVES), 1)
|
||||
VERILOG_SOURCES += iverilog_dump.v
|
||||
COMPILE_ARGS += -s iverilog_dump
|
||||
endif
|
||||
else ifeq ($(SIM), verilator)
|
||||
COMPILE_ARGS += -Wno-SELRANGE -Wno-WIDTH
|
||||
|
||||
COMPILE_ARGS += -GAXIS_PCIE_DATA_WIDTH=$(PARAM_AXIS_PCIE_DATA_WIDTH)
|
||||
COMPILE_ARGS += -GAXIS_PCIE_KEEP_WIDTH=$(PARAM_AXIS_PCIE_KEEP_WIDTH)
|
||||
COMPILE_ARGS += -GAXIS_PCIE_RQ_USER_WIDTH=$(PARAM_AXIS_PCIE_RQ_USER_WIDTH)
|
||||
COMPILE_ARGS += -GAXIS_PCIE_RC_USER_WIDTH=$(PARAM_AXIS_PCIE_RC_USER_WIDTH)
|
||||
COMPILE_ARGS += -GAXIS_PCIE_CQ_USER_WIDTH=$(PARAM_AXIS_PCIE_CQ_USER_WIDTH)
|
||||
COMPILE_ARGS += -GAXIS_PCIE_CC_USER_WIDTH=$(PARAM_AXIS_PCIE_CC_USER_WIDTH)
|
||||
COMPILE_ARGS += -GRQ_SEQ_NUM_WIDTH=$(PARAM_RQ_SEQ_NUM_WIDTH)
|
||||
|
||||
ifeq ($(WAVES), 1)
|
||||
COMPILE_ARGS += --trace-fst
|
||||
endif
|
||||
endif
|
||||
|
||||
iverilog_dump.v:
|
||||
echo 'module iverilog_dump();' > $@
|
||||
echo 'initial begin' >> $@
|
||||
echo ' $$dumpfile("$(TOPLEVEL).fst");' >> $@
|
||||
echo ' $$dumpvars(0, $(TOPLEVEL));' >> $@
|
||||
echo 'end' >> $@
|
||||
echo 'endmodule' >> $@
|
||||
|
||||
clean::
|
||||
@rm -rf sim_build_*
|
||||
@rm -rf iverilog_dump.v
|
||||
@rm -rf dump.fst $(TOPLEVEL).fst
|
||||
|
||||
include $(shell cocotb-config --makefiles)/Makefile.sim
|
||||
|
385
example/ZCU106/fpga_axi/tb/fpga_core/test_fpga_core.py
Normal file
385
example/ZCU106/fpga_axi/tb/fpga_core/test_fpga_core.py
Normal file
@ -0,0 +1,385 @@
|
||||
"""
|
||||
|
||||
Copyright (c) 2020 Alex Forencich
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
"""
|
||||
|
||||
import logging
|
||||
import os
|
||||
|
||||
import cocotb_test.simulator
|
||||
|
||||
import cocotb
|
||||
from cocotb.log import SimLog
|
||||
from cocotb.triggers import RisingEdge, FallingEdge, Timer
|
||||
|
||||
from cocotbext.pcie.core import RootComplex
|
||||
from cocotbext.pcie.xilinx.us import UltraScalePlusPcieDevice
|
||||
from cocotbext.axi.utils import hexdump_str
|
||||
|
||||
|
||||
class TB(object):
|
||||
def __init__(self, dut):
|
||||
self.dut = dut
|
||||
|
||||
self.log = SimLog("cocotb.tb")
|
||||
self.log.setLevel(logging.DEBUG)
|
||||
|
||||
# PCIe
|
||||
self.rc = RootComplex()
|
||||
|
||||
self.dev = UltraScalePlusPcieDevice(
|
||||
# configuration options
|
||||
pcie_generation=3,
|
||||
pcie_link_width=4,
|
||||
user_clk_frequency=250e6,
|
||||
alignment="dword",
|
||||
cq_cc_straddle=False,
|
||||
rq_rc_straddle=False,
|
||||
rc_4tlp_straddle=False,
|
||||
enable_pf1=False,
|
||||
enable_client_tag=True,
|
||||
enable_extended_tag=True,
|
||||
enable_parity=False,
|
||||
enable_rx_msg_interface=False,
|
||||
enable_sriov=False,
|
||||
enable_extended_configuration=False,
|
||||
|
||||
enable_pf0_msi=True,
|
||||
enable_pf1_msi=False,
|
||||
|
||||
# signals
|
||||
# Clock and Reset Interface
|
||||
user_clk=dut.clk,
|
||||
user_reset=dut.rst,
|
||||
# user_lnk_up
|
||||
# sys_clk
|
||||
# sys_clk_gt
|
||||
# sys_reset
|
||||
# phy_rdy_out
|
||||
|
||||
# Requester reQuest Interface
|
||||
rq_entity=dut,
|
||||
rq_name="m_axis_rq",
|
||||
# pcie_rq_seq_num0=dut.s_axis_rq_seq_num_0,
|
||||
# pcie_rq_seq_num_vld0=dut.s_axis_rq_seq_num_valid_0,
|
||||
# pcie_rq_seq_num1=dut.s_axis_rq_seq_num_1,
|
||||
# pcie_rq_seq_num_vld1=dut.s_axis_rq_seq_num_valid_1,
|
||||
# pcie_rq_tag0
|
||||
# pcie_rq_tag1
|
||||
# pcie_rq_tag_av
|
||||
# pcie_rq_tag_vld0
|
||||
# pcie_rq_tag_vld1
|
||||
|
||||
# Requester Completion Interface
|
||||
rc_entity=dut,
|
||||
rc_name="s_axis_rc",
|
||||
|
||||
# Completer reQuest Interface
|
||||
cq_entity=dut,
|
||||
cq_name="s_axis_cq",
|
||||
# pcie_cq_np_req
|
||||
# pcie_cq_np_req_count
|
||||
|
||||
# Completer Completion Interface
|
||||
cc_entity=dut,
|
||||
cc_name="m_axis_cc",
|
||||
|
||||
# Transmit Flow Control Interface
|
||||
# pcie_tfc_nph_av=dut.pcie_tfc_nph_av,
|
||||
# pcie_tfc_npd_av=dut.pcie_tfc_npd_av,
|
||||
|
||||
# Configuration Management Interface
|
||||
cfg_mgmt_addr=dut.cfg_mgmt_addr,
|
||||
cfg_mgmt_function_number=dut.cfg_mgmt_function_number,
|
||||
cfg_mgmt_write=dut.cfg_mgmt_write,
|
||||
cfg_mgmt_write_data=dut.cfg_mgmt_write_data,
|
||||
cfg_mgmt_byte_enable=dut.cfg_mgmt_byte_enable,
|
||||
cfg_mgmt_read=dut.cfg_mgmt_read,
|
||||
cfg_mgmt_read_data=dut.cfg_mgmt_read_data,
|
||||
cfg_mgmt_read_write_done=dut.cfg_mgmt_read_write_done,
|
||||
# cfg_mgmt_debug_access
|
||||
|
||||
# Configuration Status Interface
|
||||
# cfg_phy_link_down
|
||||
# cfg_phy_link_status
|
||||
# cfg_negotiated_width
|
||||
# cfg_current_speed
|
||||
cfg_max_payload=dut.cfg_max_payload,
|
||||
cfg_max_read_req=dut.cfg_max_read_req,
|
||||
# cfg_function_status
|
||||
# cfg_vf_status
|
||||
# cfg_function_power_state
|
||||
# cfg_vf_power_state
|
||||
# cfg_link_power_state
|
||||
# cfg_err_cor_out
|
||||
# cfg_err_nonfatal_out
|
||||
# cfg_err_fatal_out
|
||||
# cfg_local_error_out
|
||||
# cfg_local_error_valid
|
||||
# cfg_rx_pm_state
|
||||
# cfg_tx_pm_state
|
||||
# cfg_ltssm_state
|
||||
# cfg_rcb_status
|
||||
# cfg_obff_enable
|
||||
# cfg_pl_status_change
|
||||
# cfg_tph_requester_enable
|
||||
# cfg_tph_st_mode
|
||||
# cfg_vf_tph_requester_enable
|
||||
# cfg_vf_tph_st_mode
|
||||
|
||||
# Configuration Received Message Interface
|
||||
# cfg_msg_received
|
||||
# cfg_msg_received_data
|
||||
# cfg_msg_received_type
|
||||
|
||||
# Configuration Transmit Message Interface
|
||||
# cfg_msg_transmit
|
||||
# cfg_msg_transmit_type
|
||||
# cfg_msg_transmit_data
|
||||
# cfg_msg_transmit_done
|
||||
|
||||
# Configuration Flow Control Interface
|
||||
# cfg_fc_ph=dut.cfg_fc_ph,
|
||||
# cfg_fc_pd=dut.cfg_fc_pd,
|
||||
# cfg_fc_nph=dut.cfg_fc_nph,
|
||||
# cfg_fc_npd=dut.cfg_fc_npd,
|
||||
# cfg_fc_cplh=dut.cfg_fc_cplh,
|
||||
# cfg_fc_cpld=dut.cfg_fc_cpld,
|
||||
# cfg_fc_sel=dut.cfg_fc_sel,
|
||||
|
||||
# Configuration Control Interface
|
||||
# cfg_hot_reset_in
|
||||
# cfg_hot_reset_out
|
||||
# cfg_config_space_enable
|
||||
# cfg_dsn
|
||||
# cfg_bus_number
|
||||
# cfg_ds_port_number
|
||||
# cfg_ds_bus_number
|
||||
# cfg_ds_device_number
|
||||
# cfg_ds_function_number
|
||||
# cfg_power_state_change_ack
|
||||
# cfg_power_state_change_interrupt
|
||||
cfg_err_cor_in=dut.status_error_cor,
|
||||
cfg_err_uncor_in=dut.status_error_uncor,
|
||||
# cfg_flr_in_process
|
||||
# cfg_flr_done
|
||||
# cfg_vf_flr_in_process
|
||||
# cfg_vf_flr_func_num
|
||||
# cfg_vf_flr_done
|
||||
# cfg_pm_aspm_l1_entry_reject
|
||||
# cfg_pm_aspm_tx_l0s_entry_disable
|
||||
# cfg_req_pm_transition_l23_ready
|
||||
# cfg_link_training_enable
|
||||
|
||||
# Configuration Interrupt Controller Interface
|
||||
# cfg_interrupt_int
|
||||
# cfg_interrupt_sent
|
||||
# cfg_interrupt_pending
|
||||
cfg_interrupt_msi_enable=dut.cfg_interrupt_msi_enable,
|
||||
cfg_interrupt_msi_mmenable=dut.cfg_interrupt_msi_mmenable,
|
||||
cfg_interrupt_msi_mask_update=dut.cfg_interrupt_msi_mask_update,
|
||||
cfg_interrupt_msi_data=dut.cfg_interrupt_msi_data,
|
||||
# cfg_interrupt_msi_select=dut.cfg_interrupt_msi_select,
|
||||
cfg_interrupt_msi_int=dut.cfg_interrupt_msi_int,
|
||||
cfg_interrupt_msi_pending_status=dut.cfg_interrupt_msi_pending_status,
|
||||
cfg_interrupt_msi_pending_status_data_enable=dut.cfg_interrupt_msi_pending_status_data_enable,
|
||||
# cfg_interrupt_msi_pending_status_function_num=dut.cfg_interrupt_msi_pending_status_function_num,
|
||||
cfg_interrupt_msi_sent=dut.cfg_interrupt_msi_sent,
|
||||
cfg_interrupt_msi_fail=dut.cfg_interrupt_msi_fail,
|
||||
# cfg_interrupt_msix_enable
|
||||
# cfg_interrupt_msix_mask
|
||||
# cfg_interrupt_msix_vf_enable
|
||||
# cfg_interrupt_msix_vf_mask
|
||||
# cfg_interrupt_msix_address
|
||||
# cfg_interrupt_msix_data
|
||||
# cfg_interrupt_msix_int
|
||||
# cfg_interrupt_msix_vec_pending
|
||||
# cfg_interrupt_msix_vec_pending_status
|
||||
cfg_interrupt_msi_attr=dut.cfg_interrupt_msi_attr,
|
||||
cfg_interrupt_msi_tph_present=dut.cfg_interrupt_msi_tph_present,
|
||||
cfg_interrupt_msi_tph_type=dut.cfg_interrupt_msi_tph_type,
|
||||
# cfg_interrupt_msi_tph_st_tag=dut.cfg_interrupt_msi_tph_st_tag,
|
||||
# cfg_interrupt_msi_function_number=dut.cfg_interrupt_msi_function_number,
|
||||
|
||||
# Configuration Extend Interface
|
||||
# cfg_ext_read_received
|
||||
# cfg_ext_write_received
|
||||
# cfg_ext_register_number
|
||||
# cfg_ext_function_number
|
||||
# cfg_ext_write_data
|
||||
# cfg_ext_write_byte_enable
|
||||
# cfg_ext_read_data
|
||||
# cfg_ext_read_data_valid
|
||||
)
|
||||
|
||||
# self.dev.log.setLevel(logging.DEBUG)
|
||||
|
||||
self.rc.make_port().connect(self.dev)
|
||||
|
||||
self.dev.functions[0].msi_multiple_message_capable = 5
|
||||
|
||||
self.dev.functions[0].configure_bar(0, 2**22)
|
||||
self.dev.functions[0].configure_bar(1, 2**22)
|
||||
|
||||
dut.btnu.setimmediatevalue(0)
|
||||
dut.btnl.setimmediatevalue(0)
|
||||
dut.btnd.setimmediatevalue(0)
|
||||
dut.btnr.setimmediatevalue(0)
|
||||
dut.btnc.setimmediatevalue(0)
|
||||
dut.sw.setimmediatevalue(0)
|
||||
|
||||
async def init(self):
|
||||
|
||||
await FallingEdge(self.dut.rst)
|
||||
await Timer(100, 'ns')
|
||||
|
||||
await self.rc.enumerate(enable_bus_mastering=True, configure_msi=True)
|
||||
|
||||
|
||||
@cocotb.test()
|
||||
async def run_test(dut):
|
||||
|
||||
tb = TB(dut)
|
||||
|
||||
await tb.init()
|
||||
|
||||
mem_base, mem_data = tb.rc.alloc_region(16*1024*1024)
|
||||
|
||||
dev_pf0_bar0 = tb.rc.tree[0][0].bar_addr[0]
|
||||
dev_pf0_bar1 = tb.rc.tree[0][0].bar_addr[1]
|
||||
|
||||
tb.log.info("Test memory write to BAR 1")
|
||||
|
||||
await tb.rc.mem_write(dev_pf0_bar1, b'\x11\x22\x33\x44')
|
||||
|
||||
await Timer(100, 'ns')
|
||||
|
||||
tb.log.info("Test memory read from BAR 1")
|
||||
|
||||
val = await tb.rc.mem_read(dev_pf0_bar1, 4, 1000)
|
||||
tb.log.info("Read data: %s", val)
|
||||
assert val == b'\x11\x22\x33\x44'
|
||||
|
||||
tb.log.info("Test DMA")
|
||||
|
||||
# write packet data
|
||||
mem_data[0:1024] = bytearray([x % 256 for x in range(1024)])
|
||||
|
||||
# enable DMA
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100000, 1)
|
||||
|
||||
# write pcie read descriptor
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100100, (mem_base+0x0000) & 0xffffffff)
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100104, (mem_base+0x0000 >> 32) & 0xffffffff)
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100108, (0x100) & 0xffffffff)
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x10010C, (0x100 >> 32) & 0xffffffff)
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100110, 0x400)
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100114, 0xAA)
|
||||
|
||||
await Timer(2000, 'ns')
|
||||
|
||||
# read status
|
||||
val = await tb.rc.mem_read_dword(dev_pf0_bar0+0x100118)
|
||||
tb.log.info("Status: 0x%x", val)
|
||||
assert val == 0xAA
|
||||
|
||||
# write pcie write descriptor
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100200, (mem_base+0x1000) & 0xffffffff)
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100204, (mem_base+0x1000 >> 32) & 0xffffffff)
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100208, (0x100) & 0xffffffff)
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x10020C, (0x100 >> 32) & 0xffffffff)
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100210, 0x400)
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100214, 0x55)
|
||||
|
||||
await Timer(2000, 'ns')
|
||||
|
||||
# read status
|
||||
val = await tb.rc.mem_read_dword(dev_pf0_bar0+0x100218)
|
||||
tb.log.info("Status: 0x%x", val)
|
||||
assert val == 0x55
|
||||
|
||||
tb.log.info("%s", hexdump_str(mem_data, 0x1000, 64))
|
||||
|
||||
assert mem_data[0:1024] == mem_data[0x1000:0x1000+1024]
|
||||
|
||||
await RisingEdge(dut.clk)
|
||||
await RisingEdge(dut.clk)
|
||||
|
||||
|
||||
# cocotb-test
|
||||
|
||||
tests_dir = os.path.dirname(__file__)
|
||||
rtl_dir = os.path.abspath(os.path.join(tests_dir, '..', '..', 'rtl'))
|
||||
lib_dir = os.path.abspath(os.path.join(rtl_dir, '..', 'lib'))
|
||||
pcie_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'pcie', 'rtl'))
|
||||
|
||||
|
||||
def test_fpga_core(request):
|
||||
dut = "fpga_core"
|
||||
module = os.path.splitext(os.path.basename(__file__))[0]
|
||||
toplevel = dut
|
||||
|
||||
verilog_sources = [
|
||||
os.path.join(rtl_dir, f"{dut}.v"),
|
||||
os.path.join(rtl_dir, "axi_ram.v"),
|
||||
os.path.join(rtl_dir, "axis_register.v"),
|
||||
os.path.join(pcie_rtl_dir, "axis_arb_mux.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_us_axil_master.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_us_axi_dma.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_us_axi_dma_rd.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_us_axi_dma_wr.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_tag_manager.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_us_axi_master.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_us_axi_master_rd.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_us_axi_master_wr.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_us_axis_cq_demux.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_us_cfg.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_us_msi.v"),
|
||||
os.path.join(pcie_rtl_dir, "arbiter.v"),
|
||||
os.path.join(pcie_rtl_dir, "priority_encoder.v"),
|
||||
os.path.join(pcie_rtl_dir, "pulse_merge.v"),
|
||||
]
|
||||
|
||||
parameters = {}
|
||||
|
||||
parameters['AXIS_PCIE_DATA_WIDTH'] = 128
|
||||
parameters['AXIS_PCIE_KEEP_WIDTH'] = parameters['AXIS_PCIE_DATA_WIDTH'] // 32
|
||||
parameters['AXIS_PCIE_RQ_USER_WIDTH'] = 62 if parameters['AXIS_PCIE_DATA_WIDTH'] < 512 else 137
|
||||
parameters['AXIS_PCIE_RC_USER_WIDTH'] = 75 if parameters['AXIS_PCIE_DATA_WIDTH'] < 512 else 161
|
||||
parameters['AXIS_PCIE_CQ_USER_WIDTH'] = 88 if parameters['AXIS_PCIE_DATA_WIDTH'] < 512 else 183
|
||||
parameters['AXIS_PCIE_CC_USER_WIDTH'] = 33 if parameters['AXIS_PCIE_DATA_WIDTH'] < 512 else 81
|
||||
parameters['RQ_SEQ_NUM_WIDTH'] = 6
|
||||
|
||||
extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()}
|
||||
|
||||
sim_build = os.path.join(tests_dir,
|
||||
"sim_build_"+request.node.name.replace('[', '-').replace(']', ''))
|
||||
|
||||
cocotb_test.simulator.run(
|
||||
python_search=[tests_dir],
|
||||
verilog_sources=verilog_sources,
|
||||
toplevel=toplevel,
|
||||
module=module,
|
||||
parameters=parameters,
|
||||
sim_build=sim_build,
|
||||
extra_env=extra_env,
|
||||
)
|
@ -1 +0,0 @@
|
||||
../lib/pcie/tb/pcie.py
|
@ -1 +0,0 @@
|
||||
../lib/pcie/tb/pcie_us.py
|
@ -1 +0,0 @@
|
||||
../lib/pcie/tb/pcie_usp.py
|
@ -1,520 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
"""
|
||||
|
||||
Copyright (c) 2020 Alex Forencich
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
"""
|
||||
|
||||
from myhdl import *
|
||||
import os
|
||||
import struct
|
||||
|
||||
import pcie
|
||||
import pcie_usp
|
||||
|
||||
module = 'fpga_core'
|
||||
testbench = 'test_%s' % module
|
||||
|
||||
srcs = []
|
||||
|
||||
srcs.append("../rtl/%s.v" % module)
|
||||
srcs.append("../rtl/axi_ram.v")
|
||||
srcs.append("../rtl/axis_register.v")
|
||||
srcs.append("../lib/pcie/rtl/axis_arb_mux.v")
|
||||
srcs.append("../lib/pcie/rtl/pcie_us_axil_master.v")
|
||||
srcs.append("../lib/pcie/rtl/pcie_us_axi_dma.v")
|
||||
srcs.append("../lib/pcie/rtl/pcie_us_axi_dma_rd.v")
|
||||
srcs.append("../lib/pcie/rtl/pcie_us_axi_dma_wr.v")
|
||||
srcs.append("../lib/pcie/rtl/pcie_tag_manager.v")
|
||||
srcs.append("../lib/pcie/rtl/pcie_us_axi_master.v")
|
||||
srcs.append("../lib/pcie/rtl/pcie_us_axi_master_rd.v")
|
||||
srcs.append("../lib/pcie/rtl/pcie_us_axi_master_wr.v")
|
||||
srcs.append("../lib/pcie/rtl/pcie_us_axis_cq_demux.v")
|
||||
srcs.append("../lib/pcie/rtl/pcie_us_cfg.v")
|
||||
srcs.append("../lib/pcie/rtl/pcie_us_msi.v")
|
||||
srcs.append("../lib/pcie/rtl/arbiter.v")
|
||||
srcs.append("../lib/pcie/rtl/priority_encoder.v")
|
||||
srcs.append("../lib/pcie/rtl/pulse_merge.v")
|
||||
srcs.append("%s.v" % testbench)
|
||||
|
||||
src = ' '.join(srcs)
|
||||
|
||||
build_cmd = "iverilog -o %s.vvp %s" % (testbench, src)
|
||||
|
||||
def bench():
|
||||
|
||||
# Parameters
|
||||
AXIS_PCIE_DATA_WIDTH = 128
|
||||
AXIS_PCIE_KEEP_WIDTH = (AXIS_PCIE_DATA_WIDTH/32)
|
||||
AXIS_PCIE_RC_USER_WIDTH = 75
|
||||
AXIS_PCIE_RQ_USER_WIDTH = 62
|
||||
AXIS_PCIE_CQ_USER_WIDTH = 88
|
||||
AXIS_PCIE_CC_USER_WIDTH = 33
|
||||
|
||||
# Inputs
|
||||
clk = Signal(bool(0))
|
||||
rst = Signal(bool(0))
|
||||
current_test = Signal(intbv(0)[8:])
|
||||
|
||||
btnu = Signal(bool(0))
|
||||
btnl = Signal(bool(0))
|
||||
btnd = Signal(bool(0))
|
||||
btnr = Signal(bool(0))
|
||||
btnc = Signal(bool(0))
|
||||
sw = Signal(intbv(0)[8:])
|
||||
m_axis_rq_tready = Signal(bool(0))
|
||||
s_axis_rc_tdata = Signal(intbv(0)[AXIS_PCIE_DATA_WIDTH:])
|
||||
s_axis_rc_tkeep = Signal(intbv(0)[AXIS_PCIE_KEEP_WIDTH:])
|
||||
s_axis_rc_tlast = Signal(bool(0))
|
||||
s_axis_rc_tuser = Signal(intbv(0)[AXIS_PCIE_RC_USER_WIDTH:])
|
||||
s_axis_rc_tvalid = Signal(bool(0))
|
||||
s_axis_cq_tdata = Signal(intbv(0)[AXIS_PCIE_DATA_WIDTH:])
|
||||
s_axis_cq_tkeep = Signal(intbv(0)[AXIS_PCIE_KEEP_WIDTH:])
|
||||
s_axis_cq_tlast = Signal(bool(0))
|
||||
s_axis_cq_tuser = Signal(intbv(0)[AXIS_PCIE_CQ_USER_WIDTH:])
|
||||
s_axis_cq_tvalid = Signal(bool(0))
|
||||
m_axis_cc_tready = Signal(bool(0))
|
||||
cfg_max_payload = Signal(intbv(0)[2:])
|
||||
cfg_max_read_req = Signal(intbv(0)[3:])
|
||||
cfg_mgmt_read_data = Signal(intbv(0)[32:])
|
||||
cfg_mgmt_read_write_done = Signal(bool(0))
|
||||
cfg_interrupt_msi_enable = Signal(intbv(0)[4:])
|
||||
cfg_interrupt_msi_mmenable = Signal(intbv(0)[12:])
|
||||
cfg_interrupt_msi_mask_update = Signal(bool(0))
|
||||
cfg_interrupt_msi_data = Signal(intbv(0)[32:])
|
||||
cfg_interrupt_msi_sent = Signal(bool(0))
|
||||
cfg_interrupt_msi_fail = Signal(bool(0))
|
||||
|
||||
# Outputs
|
||||
led = Signal(intbv(0)[8:])
|
||||
m_axis_rq_tdata = Signal(intbv(0)[AXIS_PCIE_DATA_WIDTH:])
|
||||
m_axis_rq_tkeep = Signal(intbv(0)[AXIS_PCIE_KEEP_WIDTH:])
|
||||
m_axis_rq_tlast = Signal(bool(0))
|
||||
m_axis_rq_tuser = Signal(intbv(0)[AXIS_PCIE_RQ_USER_WIDTH:])
|
||||
m_axis_rq_tvalid = Signal(bool(0))
|
||||
s_axis_rc_tready = Signal(bool(0))
|
||||
s_axis_cq_tready = Signal(bool(0))
|
||||
m_axis_cc_tdata = Signal(intbv(0)[AXIS_PCIE_DATA_WIDTH:])
|
||||
m_axis_cc_tkeep = Signal(intbv(0)[AXIS_PCIE_KEEP_WIDTH:])
|
||||
m_axis_cc_tlast = Signal(bool(0))
|
||||
m_axis_cc_tuser = Signal(intbv(0)[AXIS_PCIE_CC_USER_WIDTH:])
|
||||
m_axis_cc_tvalid = Signal(bool(0))
|
||||
status_error_cor = Signal(bool(0))
|
||||
status_error_uncor = Signal(bool(0))
|
||||
cfg_mgmt_addr = Signal(intbv(0)[10:])
|
||||
cfg_mgmt_function_number = Signal(intbv(0)[8:])
|
||||
cfg_mgmt_write = Signal(bool(0))
|
||||
cfg_mgmt_write_data = Signal(intbv(0)[32:])
|
||||
cfg_mgmt_byte_enable = Signal(intbv(0)[4:])
|
||||
cfg_mgmt_read = Signal(bool(0))
|
||||
cfg_interrupt_msi_int = Signal(intbv(0)[32:])
|
||||
cfg_interrupt_msi_pending_status = Signal(intbv(0)[32:])
|
||||
cfg_interrupt_msi_select = Signal(intbv(0)[2:])
|
||||
cfg_interrupt_msi_pending_status_function_num = Signal(intbv(0)[2:])
|
||||
cfg_interrupt_msi_pending_status_data_enable = Signal(bool(0))
|
||||
cfg_interrupt_msi_attr = Signal(intbv(0)[3:])
|
||||
cfg_interrupt_msi_tph_present = Signal(bool(0))
|
||||
cfg_interrupt_msi_tph_type = Signal(intbv(0)[2:])
|
||||
cfg_interrupt_msi_tph_st_tag = Signal(intbv(0)[8:])
|
||||
cfg_interrupt_msi_function_number = Signal(intbv(0)[8:])
|
||||
|
||||
# Clock and Reset Interface
|
||||
user_clk=Signal(bool(0))
|
||||
user_reset=Signal(bool(0))
|
||||
sys_clk=Signal(bool(0))
|
||||
sys_reset=Signal(bool(0))
|
||||
|
||||
# PCIe devices
|
||||
rc = pcie.RootComplex()
|
||||
|
||||
mem_base, mem_data = rc.alloc_region(16*1024*1024)
|
||||
|
||||
dev = pcie_usp.UltrascalePlusPCIe()
|
||||
|
||||
dev.pcie_generation = 3
|
||||
dev.pcie_link_width = 4
|
||||
dev.user_clk_frequency = 250e6
|
||||
|
||||
dev.functions[0].msi_multiple_message_capable = 5
|
||||
|
||||
dev.functions[0].configure_bar(0, 4*1024*1024)
|
||||
dev.functions[0].configure_bar(1, 4*1024*1024)
|
||||
|
||||
rc.make_port().connect(dev)
|
||||
|
||||
pcie_logic = dev.create_logic(
|
||||
# Completer reQuest Interface
|
||||
m_axis_cq_tdata=s_axis_cq_tdata,
|
||||
m_axis_cq_tuser=s_axis_cq_tuser,
|
||||
m_axis_cq_tlast=s_axis_cq_tlast,
|
||||
m_axis_cq_tkeep=s_axis_cq_tkeep,
|
||||
m_axis_cq_tvalid=s_axis_cq_tvalid,
|
||||
m_axis_cq_tready=s_axis_cq_tready,
|
||||
#pcie_cq_np_req=pcie_cq_np_req,
|
||||
pcie_cq_np_req=Signal(intbv(1)[2:]),
|
||||
#pcie_cq_np_req_count=pcie_cq_np_req_count,
|
||||
|
||||
# Completer Completion Interface
|
||||
s_axis_cc_tdata=m_axis_cc_tdata,
|
||||
s_axis_cc_tuser=m_axis_cc_tuser,
|
||||
s_axis_cc_tlast=m_axis_cc_tlast,
|
||||
s_axis_cc_tkeep=m_axis_cc_tkeep,
|
||||
s_axis_cc_tvalid=m_axis_cc_tvalid,
|
||||
s_axis_cc_tready=m_axis_cc_tready,
|
||||
|
||||
# Requester reQuest Interface
|
||||
s_axis_rq_tdata=m_axis_rq_tdata,
|
||||
s_axis_rq_tuser=m_axis_rq_tuser,
|
||||
s_axis_rq_tlast=m_axis_rq_tlast,
|
||||
s_axis_rq_tkeep=m_axis_rq_tkeep,
|
||||
s_axis_rq_tvalid=m_axis_rq_tvalid,
|
||||
s_axis_rq_tready=m_axis_rq_tready,
|
||||
#pcie_rq_seq_num0=pcie_rq_seq_num0,
|
||||
#pcie_rq_seq_num_vld0=pcie_rq_seq_num_vld0,
|
||||
#pcie_rq_seq_num1=pcie_rq_seq_num1,
|
||||
#pcie_rq_seq_num_vld1=pcie_rq_seq_num_vld1,
|
||||
#pcie_rq_tag0=pcie_rq_tag0,
|
||||
#pcie_rq_tag1=pcie_rq_tag1,
|
||||
#pcie_rq_tag_av=pcie_rq_tag_av,
|
||||
#pcie_rq_tag_vld0=pcie_rq_tag_vld0,
|
||||
#pcie_rq_tag_vld1=pcie_rq_tag_vld1,
|
||||
|
||||
# Requester Completion Interface
|
||||
m_axis_rc_tdata=s_axis_rc_tdata,
|
||||
m_axis_rc_tuser=s_axis_rc_tuser,
|
||||
m_axis_rc_tlast=s_axis_rc_tlast,
|
||||
m_axis_rc_tkeep=s_axis_rc_tkeep,
|
||||
m_axis_rc_tvalid=s_axis_rc_tvalid,
|
||||
m_axis_rc_tready=s_axis_rc_tready,
|
||||
|
||||
# Transmit Flow Control Interface
|
||||
#pcie_tfc_nph_av=pcie_tfc_nph_av,
|
||||
#pcie_tfc_npd_av=pcie_tfc_npd_av,
|
||||
|
||||
# Configuration Management Interface
|
||||
cfg_mgmt_addr=cfg_mgmt_addr,
|
||||
cfg_mgmt_function_number=cfg_mgmt_function_number,
|
||||
cfg_mgmt_write=cfg_mgmt_write,
|
||||
cfg_mgmt_write_data=cfg_mgmt_write_data,
|
||||
cfg_mgmt_byte_enable=cfg_mgmt_byte_enable,
|
||||
cfg_mgmt_read=cfg_mgmt_read,
|
||||
cfg_mgmt_read_data=cfg_mgmt_read_data,
|
||||
cfg_mgmt_read_write_done=cfg_mgmt_read_write_done,
|
||||
#cfg_mgmt_debug_access=cfg_mgmt_debug_access,
|
||||
|
||||
# Configuration Status Interface
|
||||
#cfg_phy_link_down=cfg_phy_link_down,
|
||||
#cfg_phy_link_status=cfg_phy_link_status,
|
||||
#cfg_negotiated_width=cfg_negotiated_width,
|
||||
#cfg_current_speed=cfg_current_speed,
|
||||
cfg_max_payload=cfg_max_payload,
|
||||
cfg_max_read_req=cfg_max_read_req,
|
||||
#cfg_function_status=cfg_function_status,
|
||||
#cfg_vf_status=cfg_vf_status,
|
||||
#cfg_function_power_state=cfg_function_power_state,
|
||||
#cfg_vf_power_state=cfg_vf_power_state,
|
||||
#cfg_link_power_state=cfg_link_power_state,
|
||||
#cfg_err_cor_out=cfg_err_cor_out,
|
||||
#cfg_err_nonfatal_out=cfg_err_nonfatal_out,
|
||||
#cfg_err_fatal_out=cfg_err_fatal_out,
|
||||
#cfg_local_err_out=cfg_local_err_out,
|
||||
#cfg_local_err_valid=cfg_local_err_valid,
|
||||
#cfg_rx_pm_state=cfg_rx_pm_state,
|
||||
#cfg_tx_pm_state=cfg_tx_pm_state,
|
||||
#cfg_ltssm_state=cfg_ltssm_state,
|
||||
#cfg_rcb_status=cfg_rcb_status,
|
||||
#cfg_obff_enable=cfg_obff_enable,
|
||||
#cfg_pl_status_change=cfg_pl_status_change,
|
||||
#cfg_tph_requester_enable=cfg_tph_requester_enable,
|
||||
#cfg_tph_st_mode=cfg_tph_st_mode,
|
||||
#cfg_vf_tph_requester_enable=cfg_vf_tph_requester_enable,
|
||||
#cfg_vf_tph_st_mode=cfg_vf_tph_st_mode,
|
||||
|
||||
# Configuration Received Message Interface
|
||||
#cfg_msg_received=cfg_msg_received,
|
||||
#cfg_msg_received_data=cfg_msg_received_data,
|
||||
#cfg_msg_received_type=cfg_msg_received_type,
|
||||
|
||||
# Configuration Transmit Message Interface
|
||||
#cfg_msg_transmit=cfg_msg_transmit,
|
||||
#cfg_msg_transmit_type=cfg_msg_transmit_type,
|
||||
#cfg_msg_transmit_data=cfg_msg_transmit_data,
|
||||
#cfg_msg_transmit_done=cfg_msg_transmit_done,
|
||||
|
||||
# Configuration Flow Control Interface
|
||||
#cfg_fc_ph=cfg_fc_ph,
|
||||
#cfg_fc_pd=cfg_fc_pd,
|
||||
#cfg_fc_nph=cfg_fc_nph,
|
||||
#cfg_fc_npd=cfg_fc_npd,
|
||||
#cfg_fc_cplh=cfg_fc_cplh,
|
||||
#cfg_fc_cpld=cfg_fc_cpld,
|
||||
#cfg_fc_sel=cfg_fc_sel,
|
||||
|
||||
# Configuration Control Interface
|
||||
#cfg_hot_reset_in=cfg_hot_reset_in,
|
||||
#cfg_hot_reset_out=cfg_hot_reset_out,
|
||||
#cfg_config_space_enable=cfg_config_space_enable,
|
||||
#cfg_dsn=cfg_dsn,
|
||||
#cfg_ds_port_number=cfg_ds_port_number,
|
||||
#cfg_ds_bus_number=cfg_ds_bus_number,
|
||||
#cfg_ds_device_number=cfg_ds_device_number,
|
||||
#cfg_ds_function_number=cfg_ds_function_number,
|
||||
#cfg_power_state_change_ack=cfg_power_state_change_ack,
|
||||
#cfg_power_state_change_interrupt=cfg_power_state_change_interrupt,
|
||||
cfg_err_cor_in=status_error_cor,
|
||||
cfg_err_uncor_in=status_error_uncor,
|
||||
#cfg_flr_done=cfg_flr_done,
|
||||
#cfg_vf_flr_done=cfg_vf_flr_done,
|
||||
#cfg_flr_in_process=cfg_flr_in_process,
|
||||
#cfg_vf_flr_in_process=cfg_vf_flr_in_process,
|
||||
#cfg_req_pm_transition_l23_ready=cfg_req_pm_transition_l23_ready,
|
||||
#cfg_link_training_enable=cfg_link_training_enable,
|
||||
|
||||
# Configuration Interrupt Controller Interface
|
||||
#cfg_interrupt_int=cfg_interrupt_int,
|
||||
#cfg_interrupt_sent=cfg_interrupt_sent,
|
||||
#cfg_interrupt_pending=cfg_interrupt_pending,
|
||||
cfg_interrupt_msi_enable=cfg_interrupt_msi_enable,
|
||||
cfg_interrupt_msi_mmenable=cfg_interrupt_msi_mmenable,
|
||||
cfg_interrupt_msi_mask_update=cfg_interrupt_msi_mask_update,
|
||||
cfg_interrupt_msi_data=cfg_interrupt_msi_data,
|
||||
cfg_interrupt_msi_select=cfg_interrupt_msi_select,
|
||||
cfg_interrupt_msi_int=cfg_interrupt_msi_int,
|
||||
cfg_interrupt_msi_pending_status=cfg_interrupt_msi_pending_status,
|
||||
cfg_interrupt_msi_pending_status_data_enable=cfg_interrupt_msi_pending_status_data_enable,
|
||||
cfg_interrupt_msi_pending_status_function_num=cfg_interrupt_msi_pending_status_function_num,
|
||||
cfg_interrupt_msi_sent=cfg_interrupt_msi_sent,
|
||||
cfg_interrupt_msi_fail=cfg_interrupt_msi_fail,
|
||||
#cfg_interrupt_msix_enable=cfg_interrupt_msix_enable,
|
||||
#cfg_interrupt_msix_mask=cfg_interrupt_msix_mask,
|
||||
#cfg_interrupt_msix_vf_enable=cfg_interrupt_msix_vf_enable,
|
||||
#cfg_interrupt_msix_vf_mask=cfg_interrupt_msix_vf_mask,
|
||||
#cfg_interrupt_msix_address=cfg_interrupt_msix_address,
|
||||
#cfg_interrupt_msix_data=cfg_interrupt_msix_data,
|
||||
#cfg_interrupt_msix_int=cfg_interrupt_msix_int,
|
||||
#cfg_interrupt_msix_vec_pending=cfg_interrupt_msix_vec_pending,
|
||||
#cfg_interrupt_msix_vec_pending_status=cfg_interrupt_msix_vec_pending_status,
|
||||
cfg_interrupt_msi_attr=cfg_interrupt_msi_attr,
|
||||
cfg_interrupt_msi_tph_present=cfg_interrupt_msi_tph_present,
|
||||
cfg_interrupt_msi_tph_type=cfg_interrupt_msi_tph_type,
|
||||
cfg_interrupt_msi_tph_st_tag=cfg_interrupt_msi_tph_st_tag,
|
||||
cfg_interrupt_msi_function_number=cfg_interrupt_msi_function_number,
|
||||
|
||||
# Configuration Extend Interface
|
||||
#cfg_ext_read_received=cfg_ext_read_received,
|
||||
#cfg_ext_write_received=cfg_ext_write_received,
|
||||
#cfg_ext_register_number=cfg_ext_register_number,
|
||||
#cfg_ext_function_number=cfg_ext_function_number,
|
||||
#cfg_ext_write_data=cfg_ext_write_data,
|
||||
#cfg_ext_write_byte_enable=cfg_ext_write_byte_enable,
|
||||
#cfg_ext_read_data=cfg_ext_read_data,
|
||||
#cfg_ext_read_data_valid=cfg_ext_read_data_valid,
|
||||
|
||||
# Clock and Reset Interface
|
||||
user_clk=user_clk,
|
||||
user_reset=user_reset,
|
||||
#user_lnk_up=user_lnk_up,
|
||||
sys_clk=sys_clk,
|
||||
sys_clk_gt=sys_clk,
|
||||
sys_reset=sys_reset,
|
||||
#phy_rdy_out=phy_rdy_out
|
||||
)
|
||||
|
||||
# DUT
|
||||
if os.system(build_cmd):
|
||||
raise Exception("Error running build command")
|
||||
|
||||
dut = Cosimulation(
|
||||
"vvp -m myhdl %s.vvp -lxt2" % testbench,
|
||||
clk=user_clk,
|
||||
rst=user_reset,
|
||||
current_test=current_test,
|
||||
btnu=btnu,
|
||||
btnl=btnl,
|
||||
btnd=btnd,
|
||||
btnr=btnr,
|
||||
btnc=btnc,
|
||||
sw=sw,
|
||||
led=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_function_number=cfg_mgmt_function_number,
|
||||
cfg_mgmt_write=cfg_mgmt_write,
|
||||
cfg_mgmt_write_data=cfg_mgmt_write_data,
|
||||
cfg_mgmt_byte_enable=cfg_mgmt_byte_enable,
|
||||
cfg_mgmt_read=cfg_mgmt_read,
|
||||
cfg_mgmt_read_data=cfg_mgmt_read_data,
|
||||
cfg_mgmt_read_write_done=cfg_mgmt_read_write_done,
|
||||
cfg_interrupt_msi_enable=cfg_interrupt_msi_enable,
|
||||
cfg_interrupt_msi_int=cfg_interrupt_msi_int,
|
||||
cfg_interrupt_msi_sent=cfg_interrupt_msi_sent,
|
||||
cfg_interrupt_msi_fail=cfg_interrupt_msi_fail,
|
||||
cfg_interrupt_msi_mmenable=cfg_interrupt_msi_mmenable,
|
||||
cfg_interrupt_msi_pending_status=cfg_interrupt_msi_pending_status,
|
||||
cfg_interrupt_msi_mask_update=cfg_interrupt_msi_mask_update,
|
||||
cfg_interrupt_msi_select=cfg_interrupt_msi_select,
|
||||
cfg_interrupt_msi_data=cfg_interrupt_msi_data,
|
||||
cfg_interrupt_msi_pending_status_function_num=cfg_interrupt_msi_pending_status_function_num,
|
||||
cfg_interrupt_msi_pending_status_data_enable=cfg_interrupt_msi_pending_status_data_enable,
|
||||
cfg_interrupt_msi_attr=cfg_interrupt_msi_attr,
|
||||
cfg_interrupt_msi_tph_present=cfg_interrupt_msi_tph_present,
|
||||
cfg_interrupt_msi_tph_type=cfg_interrupt_msi_tph_type,
|
||||
cfg_interrupt_msi_tph_st_tag=cfg_interrupt_msi_tph_st_tag,
|
||||
cfg_interrupt_msi_function_number=cfg_interrupt_msi_function_number,
|
||||
status_error_cor=status_error_cor,
|
||||
status_error_uncor=status_error_uncor
|
||||
)
|
||||
|
||||
@always(delay(5))
|
||||
def clkgen():
|
||||
clk.next = not clk
|
||||
|
||||
@always_comb
|
||||
def clk_logic():
|
||||
sys_clk.next = clk
|
||||
sys_reset.next = not rst
|
||||
|
||||
@instance
|
||||
def check():
|
||||
yield delay(100)
|
||||
yield clk.posedge
|
||||
rst.next = 1
|
||||
yield clk.posedge
|
||||
rst.next = 0
|
||||
yield clk.posedge
|
||||
yield delay(100)
|
||||
yield clk.posedge
|
||||
|
||||
# testbench stimulus
|
||||
|
||||
current_tag = 1
|
||||
|
||||
yield clk.posedge
|
||||
print("test 1: enumeration")
|
||||
current_test.next = 1
|
||||
|
||||
yield rc.enumerate(enable_bus_mastering=True, configure_msi=True)
|
||||
|
||||
dev_pf0_bar0 = dev.functions[0].bar[0] & 0xfffffffc
|
||||
dev_pf0_bar1 = dev.functions[0].bar[1] & 0xfffffffc
|
||||
|
||||
yield delay(100)
|
||||
|
||||
yield clk.posedge
|
||||
print("test 2: memory write to bar 1")
|
||||
current_test.next = 2
|
||||
|
||||
yield rc.mem_write(dev_pf0_bar1, b'\x11\x22\x33\x44')
|
||||
|
||||
yield delay(100)
|
||||
|
||||
yield clk.posedge
|
||||
print("test 3: memory read from bar 1")
|
||||
current_test.next = 3
|
||||
|
||||
val = yield from rc.mem_read(dev_pf0_bar1, 4, 1000)
|
||||
print(val)
|
||||
assert val == b'\x11\x22\x33\x44'
|
||||
|
||||
yield delay(100)
|
||||
|
||||
yield clk.posedge
|
||||
print("test 4: test DMA")
|
||||
current_test.next = 4
|
||||
|
||||
# write packet data
|
||||
mem_data[0:1024] = bytearray([x%256 for x in range(1024)])
|
||||
|
||||
# enable DMA
|
||||
yield rc.mem_write(dev_pf0_bar0+0x100000, struct.pack('<L', 1))
|
||||
|
||||
# write pcie read descriptor
|
||||
yield rc.mem_write(dev_pf0_bar0+0x100100, struct.pack('<L', (mem_base+0x0000) & 0xffffffff))
|
||||
yield rc.mem_write(dev_pf0_bar0+0x100104, struct.pack('<L', (mem_base+0x0000 >> 32) & 0xffffffff))
|
||||
yield rc.mem_write(dev_pf0_bar0+0x100108, struct.pack('<L', (0x100) & 0xffffffff))
|
||||
yield rc.mem_write(dev_pf0_bar0+0x10010C, struct.pack('<L', (0x100 >> 32) & 0xffffffff))
|
||||
yield rc.mem_write(dev_pf0_bar0+0x100110, struct.pack('<L', 0x400))
|
||||
yield rc.mem_write(dev_pf0_bar0+0x100114, struct.pack('<L', 0xAA))
|
||||
|
||||
yield delay(2000)
|
||||
|
||||
# read status
|
||||
val = yield from rc.mem_read(dev_pf0_bar0+0x100118, 4)
|
||||
print(val)
|
||||
|
||||
# write pcie write descriptor
|
||||
yield rc.mem_write(dev_pf0_bar0+0x100200, struct.pack('<L', (mem_base+0x1000) & 0xffffffff))
|
||||
yield rc.mem_write(dev_pf0_bar0+0x100204, struct.pack('<L', (mem_base+0x1000 >> 32) & 0xffffffff))
|
||||
yield rc.mem_write(dev_pf0_bar0+0x100208, struct.pack('<L', (0x100) & 0xffffffff))
|
||||
yield rc.mem_write(dev_pf0_bar0+0x10020C, struct.pack('<L', (0x100 >> 32) & 0xffffffff))
|
||||
yield rc.mem_write(dev_pf0_bar0+0x100210, struct.pack('<L', 0x400))
|
||||
yield rc.mem_write(dev_pf0_bar0+0x100214, struct.pack('<L', 0x55))
|
||||
|
||||
yield delay(2000)
|
||||
|
||||
# read status
|
||||
val = yield from rc.mem_read(dev_pf0_bar0+0x100218, 4)
|
||||
print(val)
|
||||
|
||||
data = mem_data[0x1000:(0x1000)+64]
|
||||
for i in range(0, len(data), 16):
|
||||
print(" ".join(("{:02x}".format(c) for c in bytearray(data[i:i+16]))))
|
||||
|
||||
assert mem_data[0:1024] == mem_data[0x1000:0x1000+1024]
|
||||
|
||||
yield delay(100)
|
||||
|
||||
raise StopSimulation
|
||||
|
||||
return instances()
|
||||
|
||||
def test_bench():
|
||||
sim = Simulation(bench())
|
||||
sim.run()
|
||||
|
||||
if __name__ == '__main__':
|
||||
print("Running test...")
|
||||
test_bench()
|
@ -1,258 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2020 Alex Forencich
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
// Language: Verilog 2001
|
||||
|
||||
`timescale 1ns / 1ps
|
||||
|
||||
/*
|
||||
* Testbench for fpga_core
|
||||
*/
|
||||
module test_fpga_core;
|
||||
|
||||
// Parameters
|
||||
parameter AXIS_PCIE_DATA_WIDTH = 128;
|
||||
parameter AXIS_PCIE_KEEP_WIDTH = (AXIS_PCIE_DATA_WIDTH/32);
|
||||
parameter AXIS_PCIE_RC_USER_WIDTH = 75;
|
||||
parameter AXIS_PCIE_RQ_USER_WIDTH = 62;
|
||||
parameter AXIS_PCIE_CQ_USER_WIDTH = 88;
|
||||
parameter AXIS_PCIE_CC_USER_WIDTH = 33;
|
||||
|
||||
// Inputs
|
||||
reg clk = 0;
|
||||
reg rst = 0;
|
||||
reg [7:0] current_test = 0;
|
||||
|
||||
reg btnu = 0;
|
||||
reg btnl = 0;
|
||||
reg btnd = 0;
|
||||
reg btnr = 0;
|
||||
reg btnc = 0;
|
||||
reg [7:0] sw = 0;
|
||||
reg m_axis_rq_tready = 0;
|
||||
reg [AXIS_PCIE_DATA_WIDTH-1:0] s_axis_rc_tdata = 0;
|
||||
reg [AXIS_PCIE_KEEP_WIDTH-1:0] s_axis_rc_tkeep = 0;
|
||||
reg s_axis_rc_tlast = 0;
|
||||
reg [AXIS_PCIE_RC_USER_WIDTH-1:0] s_axis_rc_tuser = 0;
|
||||
reg s_axis_rc_tvalid = 0;
|
||||
reg [AXIS_PCIE_DATA_WIDTH-1:0] s_axis_cq_tdata = 0;
|
||||
reg [AXIS_PCIE_KEEP_WIDTH-1:0] s_axis_cq_tkeep = 0;
|
||||
reg s_axis_cq_tlast = 0;
|
||||
reg [AXIS_PCIE_CQ_USER_WIDTH-1:0] s_axis_cq_tuser = 0;
|
||||
reg s_axis_cq_tvalid = 0;
|
||||
reg m_axis_cc_tready = 0;
|
||||
reg [2:0] cfg_max_payload = 0;
|
||||
reg [2:0] cfg_max_read_req = 0;
|
||||
reg [31:0] cfg_mgmt_read_data = 0;
|
||||
reg cfg_mgmt_read_write_done = 0;
|
||||
reg [3:0] cfg_interrupt_msi_enable = 0;
|
||||
reg [11:0] cfg_interrupt_msi_mmenable = 0;
|
||||
reg cfg_interrupt_msi_mask_update = 0;
|
||||
reg [31:0] cfg_interrupt_msi_data = 0;
|
||||
reg cfg_interrupt_msi_sent = 0;
|
||||
reg cfg_interrupt_msi_fail = 0;
|
||||
|
||||
// Outputs
|
||||
wire [7:0] led;
|
||||
wire [1:0] user_led_g;
|
||||
wire user_led_r;
|
||||
wire [1:0] front_led;
|
||||
wire [AXIS_PCIE_DATA_WIDTH-1:0] m_axis_rq_tdata;
|
||||
wire [AXIS_PCIE_KEEP_WIDTH-1:0] m_axis_rq_tkeep;
|
||||
wire m_axis_rq_tlast;
|
||||
wire [AXIS_PCIE_RQ_USER_WIDTH-1:0] m_axis_rq_tuser;
|
||||
wire m_axis_rq_tvalid;
|
||||
wire s_axis_rc_tready;
|
||||
wire s_axis_cq_tready;
|
||||
wire [AXIS_PCIE_DATA_WIDTH-1:0] m_axis_cc_tdata;
|
||||
wire [AXIS_PCIE_KEEP_WIDTH-1:0] m_axis_cc_tkeep;
|
||||
wire m_axis_cc_tlast;
|
||||
wire [AXIS_PCIE_CC_USER_WIDTH-1:0] m_axis_cc_tuser;
|
||||
wire m_axis_cc_tvalid;
|
||||
wire [9:0] cfg_mgmt_addr;
|
||||
wire [7:0] cfg_mgmt_function_number;
|
||||
wire cfg_mgmt_write;
|
||||
wire [31:0] cfg_mgmt_write_data;
|
||||
wire [3:0] cfg_mgmt_byte_enable;
|
||||
wire cfg_mgmt_read;
|
||||
wire [3:0] cfg_interrupt_msi_select;
|
||||
wire [31:0] cfg_interrupt_msi_int;
|
||||
wire [31:0] cfg_interrupt_msi_pending_status;
|
||||
wire cfg_interrupt_msi_pending_status_data_enable;
|
||||
wire [3:0] cfg_interrupt_msi_pending_status_function_num;
|
||||
wire [2:0] cfg_interrupt_msi_attr;
|
||||
wire cfg_interrupt_msi_tph_present;
|
||||
wire [1:0] cfg_interrupt_msi_tph_type;
|
||||
wire [8:0] cfg_interrupt_msi_tph_st_tag;
|
||||
wire [3:0] cfg_interrupt_msi_function_number;
|
||||
wire status_error_cor;
|
||||
wire status_error_uncor;
|
||||
|
||||
initial begin
|
||||
// myhdl integration
|
||||
$from_myhdl(
|
||||
clk,
|
||||
rst,
|
||||
current_test,
|
||||
btnu,
|
||||
btnl,
|
||||
btnd,
|
||||
btnr,
|
||||
btnc,
|
||||
sw,
|
||||
m_axis_rq_tready,
|
||||
s_axis_rc_tdata,
|
||||
s_axis_rc_tkeep,
|
||||
s_axis_rc_tlast,
|
||||
s_axis_rc_tuser,
|
||||
s_axis_rc_tvalid,
|
||||
s_axis_cq_tdata,
|
||||
s_axis_cq_tkeep,
|
||||
s_axis_cq_tlast,
|
||||
s_axis_cq_tuser,
|
||||
s_axis_cq_tvalid,
|
||||
m_axis_cc_tready,
|
||||
cfg_max_payload,
|
||||
cfg_max_read_req,
|
||||
cfg_mgmt_read_data,
|
||||
cfg_mgmt_read_write_done,
|
||||
cfg_interrupt_msi_enable,
|
||||
cfg_interrupt_msi_mmenable,
|
||||
cfg_interrupt_msi_mask_update,
|
||||
cfg_interrupt_msi_data,
|
||||
cfg_interrupt_msi_sent,
|
||||
cfg_interrupt_msi_fail
|
||||
);
|
||||
$to_myhdl(
|
||||
led,
|
||||
m_axis_rq_tdata,
|
||||
m_axis_rq_tkeep,
|
||||
m_axis_rq_tlast,
|
||||
m_axis_rq_tuser,
|
||||
m_axis_rq_tvalid,
|
||||
s_axis_rc_tready,
|
||||
s_axis_cq_tready,
|
||||
m_axis_cc_tdata,
|
||||
m_axis_cc_tkeep,
|
||||
m_axis_cc_tlast,
|
||||
m_axis_cc_tuser,
|
||||
m_axis_cc_tvalid,
|
||||
cfg_mgmt_addr,
|
||||
cfg_mgmt_function_number,
|
||||
cfg_mgmt_write,
|
||||
cfg_mgmt_write_data,
|
||||
cfg_mgmt_byte_enable,
|
||||
cfg_mgmt_read,
|
||||
cfg_interrupt_msi_select,
|
||||
cfg_interrupt_msi_int,
|
||||
cfg_interrupt_msi_pending_status,
|
||||
cfg_interrupt_msi_pending_status_data_enable,
|
||||
cfg_interrupt_msi_pending_status_function_num,
|
||||
cfg_interrupt_msi_attr,
|
||||
cfg_interrupt_msi_tph_present,
|
||||
cfg_interrupt_msi_tph_type,
|
||||
cfg_interrupt_msi_tph_st_tag,
|
||||
cfg_interrupt_msi_function_number,
|
||||
status_error_cor,
|
||||
status_error_uncor
|
||||
);
|
||||
|
||||
// dump file
|
||||
$dumpfile("test_fpga_core.lxt");
|
||||
$dumpvars(0, test_fpga_core);
|
||||
end
|
||||
|
||||
fpga_core #(
|
||||
.AXIS_PCIE_DATA_WIDTH(AXIS_PCIE_DATA_WIDTH),
|
||||
.AXIS_PCIE_KEEP_WIDTH(AXIS_PCIE_KEEP_WIDTH),
|
||||
.AXIS_PCIE_RC_USER_WIDTH(AXIS_PCIE_RC_USER_WIDTH),
|
||||
.AXIS_PCIE_RQ_USER_WIDTH(AXIS_PCIE_RQ_USER_WIDTH),
|
||||
.AXIS_PCIE_CQ_USER_WIDTH(AXIS_PCIE_CQ_USER_WIDTH),
|
||||
.AXIS_PCIE_CC_USER_WIDTH(AXIS_PCIE_CC_USER_WIDTH)
|
||||
)
|
||||
UUT (
|
||||
.clk(clk),
|
||||
.rst(rst),
|
||||
.btnu(btnu),
|
||||
.btnl(btnl),
|
||||
.btnd(btnd),
|
||||
.btnr(btnr),
|
||||
.btnc(btnc),
|
||||
.sw(sw),
|
||||
.led(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_function_number(cfg_mgmt_function_number),
|
||||
.cfg_mgmt_write(cfg_mgmt_write),
|
||||
.cfg_mgmt_write_data(cfg_mgmt_write_data),
|
||||
.cfg_mgmt_byte_enable(cfg_mgmt_byte_enable),
|
||||
.cfg_mgmt_read(cfg_mgmt_read),
|
||||
.cfg_mgmt_read_data(cfg_mgmt_read_data),
|
||||
.cfg_mgmt_read_write_done(cfg_mgmt_read_write_done),
|
||||
.cfg_interrupt_msi_enable(cfg_interrupt_msi_enable),
|
||||
.cfg_interrupt_msi_mmenable(cfg_interrupt_msi_mmenable),
|
||||
.cfg_interrupt_msi_mask_update(cfg_interrupt_msi_mask_update),
|
||||
.cfg_interrupt_msi_data(cfg_interrupt_msi_data),
|
||||
.cfg_interrupt_msi_select(cfg_interrupt_msi_select),
|
||||
.cfg_interrupt_msi_int(cfg_interrupt_msi_int),
|
||||
.cfg_interrupt_msi_pending_status(cfg_interrupt_msi_pending_status),
|
||||
.cfg_interrupt_msi_pending_status_data_enable(cfg_interrupt_msi_pending_status_data_enable),
|
||||
.cfg_interrupt_msi_pending_status_function_num(cfg_interrupt_msi_pending_status_function_num),
|
||||
.cfg_interrupt_msi_sent(cfg_interrupt_msi_sent),
|
||||
.cfg_interrupt_msi_fail(cfg_interrupt_msi_fail),
|
||||
.cfg_interrupt_msi_attr(cfg_interrupt_msi_attr),
|
||||
.cfg_interrupt_msi_tph_present(cfg_interrupt_msi_tph_present),
|
||||
.cfg_interrupt_msi_tph_type(cfg_interrupt_msi_tph_type),
|
||||
.cfg_interrupt_msi_tph_st_tag(cfg_interrupt_msi_tph_st_tag),
|
||||
.cfg_interrupt_msi_function_number(cfg_interrupt_msi_function_number),
|
||||
.status_error_cor(status_error_cor),
|
||||
.status_error_uncor(status_error_uncor)
|
||||
);
|
||||
|
||||
endmodule
|
@ -1 +0,0 @@
|
||||
../lib/pcie/tb/axis_ep.py
|
107
example/fb2CG/fpga_axi/tb/fpga_core/Makefile
Normal file
107
example/fb2CG/fpga_axi/tb/fpga_core/Makefile
Normal file
@ -0,0 +1,107 @@
|
||||
# Copyright (c) 2020 Alex Forencich
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in
|
||||
# all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
# THE SOFTWARE.
|
||||
|
||||
TOPLEVEL_LANG = verilog
|
||||
|
||||
SIM ?= icarus
|
||||
WAVES ?= 0
|
||||
|
||||
COCOTB_HDL_TIMEUNIT = 1ns
|
||||
COCOTB_HDL_TIMEPRECISION = 1ps
|
||||
|
||||
DUT = fpga_core
|
||||
TOPLEVEL = $(DUT)
|
||||
MODULE = test_$(DUT)
|
||||
VERILOG_SOURCES += ../../rtl/$(DUT).v
|
||||
VERILOG_SOURCES += ../../rtl/axi_ram.v
|
||||
VERILOG_SOURCES += ../../rtl/axis_register.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/axis_arb_mux.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_axil_master.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_axi_dma.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_axi_dma_rd.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_axi_dma_wr.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_tag_manager.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_axi_master.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_axi_master_rd.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_axi_master_wr.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_axis_cq_demux.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_cfg.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pcie_us_msi.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/arbiter.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/priority_encoder.v
|
||||
VERILOG_SOURCES += ../../lib/pcie/rtl/pulse_merge.v
|
||||
|
||||
# module parameters
|
||||
export PARAM_AXIS_PCIE_DATA_WIDTH ?= 512
|
||||
export PARAM_AXIS_PCIE_KEEP_WIDTH ?= $(shell expr $(PARAM_AXIS_PCIE_DATA_WIDTH) / 32 )
|
||||
export PARAM_AXIS_PCIE_RQ_USER_WIDTH ?= $(if $(filter-out 512,$(PARAM_AXIS_PCIE_DATA_WIDTH)),62,137)
|
||||
export PARAM_AXIS_PCIE_RC_USER_WIDTH ?= $(if $(filter-out 512,$(PARAM_AXIS_PCIE_DATA_WIDTH)),75,161)
|
||||
export PARAM_AXIS_PCIE_CQ_USER_WIDTH ?= $(if $(filter-out 512,$(PARAM_AXIS_PCIE_DATA_WIDTH)),88,183)
|
||||
export PARAM_AXIS_PCIE_CC_USER_WIDTH ?= $(if $(filter-out 512,$(PARAM_AXIS_PCIE_DATA_WIDTH)),33,81)
|
||||
export PARAM_RQ_SEQ_NUM_WIDTH ?= 6
|
||||
|
||||
SIM_BUILD ?= sim_build_$(MODULE)
|
||||
|
||||
ifeq ($(SIM), icarus)
|
||||
PLUSARGS += -fst
|
||||
|
||||
COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_DATA_WIDTH=$(PARAM_AXIS_PCIE_DATA_WIDTH)
|
||||
COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_KEEP_WIDTH=$(PARAM_AXIS_PCIE_KEEP_WIDTH)
|
||||
COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_RQ_USER_WIDTH=$(PARAM_AXIS_PCIE_RQ_USER_WIDTH)
|
||||
COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_RC_USER_WIDTH=$(PARAM_AXIS_PCIE_RC_USER_WIDTH)
|
||||
COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_CQ_USER_WIDTH=$(PARAM_AXIS_PCIE_CQ_USER_WIDTH)
|
||||
COMPILE_ARGS += -P $(TOPLEVEL).AXIS_PCIE_CC_USER_WIDTH=$(PARAM_AXIS_PCIE_CC_USER_WIDTH)
|
||||
COMPILE_ARGS += -P $(TOPLEVEL).RQ_SEQ_NUM_WIDTH=$(PARAM_RQ_SEQ_NUM_WIDTH)
|
||||
|
||||
ifeq ($(WAVES), 1)
|
||||
VERILOG_SOURCES += iverilog_dump.v
|
||||
COMPILE_ARGS += -s iverilog_dump
|
||||
endif
|
||||
else ifeq ($(SIM), verilator)
|
||||
COMPILE_ARGS += -Wno-SELRANGE -Wno-WIDTH
|
||||
|
||||
COMPILE_ARGS += -GAXIS_PCIE_DATA_WIDTH=$(PARAM_AXIS_PCIE_DATA_WIDTH)
|
||||
COMPILE_ARGS += -GAXIS_PCIE_KEEP_WIDTH=$(PARAM_AXIS_PCIE_KEEP_WIDTH)
|
||||
COMPILE_ARGS += -GAXIS_PCIE_RQ_USER_WIDTH=$(PARAM_AXIS_PCIE_RQ_USER_WIDTH)
|
||||
COMPILE_ARGS += -GAXIS_PCIE_RC_USER_WIDTH=$(PARAM_AXIS_PCIE_RC_USER_WIDTH)
|
||||
COMPILE_ARGS += -GAXIS_PCIE_CQ_USER_WIDTH=$(PARAM_AXIS_PCIE_CQ_USER_WIDTH)
|
||||
COMPILE_ARGS += -GAXIS_PCIE_CC_USER_WIDTH=$(PARAM_AXIS_PCIE_CC_USER_WIDTH)
|
||||
COMPILE_ARGS += -GRQ_SEQ_NUM_WIDTH=$(PARAM_RQ_SEQ_NUM_WIDTH)
|
||||
|
||||
ifeq ($(WAVES), 1)
|
||||
COMPILE_ARGS += --trace-fst
|
||||
endif
|
||||
endif
|
||||
|
||||
iverilog_dump.v:
|
||||
echo 'module iverilog_dump();' > $@
|
||||
echo 'initial begin' >> $@
|
||||
echo ' $$dumpfile("$(TOPLEVEL).fst");' >> $@
|
||||
echo ' $$dumpvars(0, $(TOPLEVEL));' >> $@
|
||||
echo 'end' >> $@
|
||||
echo 'endmodule' >> $@
|
||||
|
||||
clean::
|
||||
@rm -rf sim_build_*
|
||||
@rm -rf iverilog_dump.v
|
||||
@rm -rf dump.fst $(TOPLEVEL).fst
|
||||
|
||||
include $(shell cocotb-config --makefiles)/Makefile.sim
|
||||
|
378
example/fb2CG/fpga_axi/tb/fpga_core/test_fpga_core.py
Normal file
378
example/fb2CG/fpga_axi/tb/fpga_core/test_fpga_core.py
Normal file
@ -0,0 +1,378 @@
|
||||
"""
|
||||
|
||||
Copyright (c) 2020 Alex Forencich
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
"""
|
||||
|
||||
import logging
|
||||
import os
|
||||
|
||||
import cocotb_test.simulator
|
||||
|
||||
import cocotb
|
||||
from cocotb.log import SimLog
|
||||
from cocotb.triggers import RisingEdge, FallingEdge, Timer
|
||||
|
||||
from cocotbext.pcie.core import RootComplex
|
||||
from cocotbext.pcie.xilinx.us import UltraScalePlusPcieDevice
|
||||
from cocotbext.axi.utils import hexdump_str
|
||||
|
||||
|
||||
class TB(object):
|
||||
def __init__(self, dut):
|
||||
self.dut = dut
|
||||
|
||||
self.log = SimLog("cocotb.tb")
|
||||
self.log.setLevel(logging.DEBUG)
|
||||
|
||||
# PCIe
|
||||
self.rc = RootComplex()
|
||||
|
||||
self.dev = UltraScalePlusPcieDevice(
|
||||
# configuration options
|
||||
pcie_generation=3,
|
||||
pcie_link_width=16,
|
||||
user_clk_frequency=250e6,
|
||||
alignment="dword",
|
||||
cq_cc_straddle=False,
|
||||
rq_rc_straddle=False,
|
||||
rc_4tlp_straddle=False,
|
||||
enable_pf1=False,
|
||||
enable_client_tag=True,
|
||||
enable_extended_tag=True,
|
||||
enable_parity=False,
|
||||
enable_rx_msg_interface=False,
|
||||
enable_sriov=False,
|
||||
enable_extended_configuration=False,
|
||||
|
||||
enable_pf0_msi=True,
|
||||
enable_pf1_msi=False,
|
||||
|
||||
# signals
|
||||
# Clock and Reset Interface
|
||||
user_clk=dut.clk,
|
||||
user_reset=dut.rst,
|
||||
# user_lnk_up
|
||||
# sys_clk
|
||||
# sys_clk_gt
|
||||
# sys_reset
|
||||
# phy_rdy_out
|
||||
|
||||
# Requester reQuest Interface
|
||||
rq_entity=dut,
|
||||
rq_name="m_axis_rq",
|
||||
# pcie_rq_seq_num0=dut.s_axis_rq_seq_num_0,
|
||||
# pcie_rq_seq_num_vld0=dut.s_axis_rq_seq_num_valid_0,
|
||||
# pcie_rq_seq_num1=dut.s_axis_rq_seq_num_1,
|
||||
# pcie_rq_seq_num_vld1=dut.s_axis_rq_seq_num_valid_1,
|
||||
# pcie_rq_tag0
|
||||
# pcie_rq_tag1
|
||||
# pcie_rq_tag_av
|
||||
# pcie_rq_tag_vld0
|
||||
# pcie_rq_tag_vld1
|
||||
|
||||
# Requester Completion Interface
|
||||
rc_entity=dut,
|
||||
rc_name="s_axis_rc",
|
||||
|
||||
# Completer reQuest Interface
|
||||
cq_entity=dut,
|
||||
cq_name="s_axis_cq",
|
||||
# pcie_cq_np_req
|
||||
# pcie_cq_np_req_count
|
||||
|
||||
# Completer Completion Interface
|
||||
cc_entity=dut,
|
||||
cc_name="m_axis_cc",
|
||||
|
||||
# Transmit Flow Control Interface
|
||||
# pcie_tfc_nph_av=dut.pcie_tfc_nph_av,
|
||||
# pcie_tfc_npd_av=dut.pcie_tfc_npd_av,
|
||||
|
||||
# Configuration Management Interface
|
||||
cfg_mgmt_addr=dut.cfg_mgmt_addr,
|
||||
cfg_mgmt_function_number=dut.cfg_mgmt_function_number,
|
||||
cfg_mgmt_write=dut.cfg_mgmt_write,
|
||||
cfg_mgmt_write_data=dut.cfg_mgmt_write_data,
|
||||
cfg_mgmt_byte_enable=dut.cfg_mgmt_byte_enable,
|
||||
cfg_mgmt_read=dut.cfg_mgmt_read,
|
||||
cfg_mgmt_read_data=dut.cfg_mgmt_read_data,
|
||||
cfg_mgmt_read_write_done=dut.cfg_mgmt_read_write_done,
|
||||
# cfg_mgmt_debug_access
|
||||
|
||||
# Configuration Status Interface
|
||||
# cfg_phy_link_down
|
||||
# cfg_phy_link_status
|
||||
# cfg_negotiated_width
|
||||
# cfg_current_speed
|
||||
cfg_max_payload=dut.cfg_max_payload,
|
||||
cfg_max_read_req=dut.cfg_max_read_req,
|
||||
# cfg_function_status
|
||||
# cfg_vf_status
|
||||
# cfg_function_power_state
|
||||
# cfg_vf_power_state
|
||||
# cfg_link_power_state
|
||||
# cfg_err_cor_out
|
||||
# cfg_err_nonfatal_out
|
||||
# cfg_err_fatal_out
|
||||
# cfg_local_error_out
|
||||
# cfg_local_error_valid
|
||||
# cfg_rx_pm_state
|
||||
# cfg_tx_pm_state
|
||||
# cfg_ltssm_state
|
||||
# cfg_rcb_status
|
||||
# cfg_obff_enable
|
||||
# cfg_pl_status_change
|
||||
# cfg_tph_requester_enable
|
||||
# cfg_tph_st_mode
|
||||
# cfg_vf_tph_requester_enable
|
||||
# cfg_vf_tph_st_mode
|
||||
|
||||
# Configuration Received Message Interface
|
||||
# cfg_msg_received
|
||||
# cfg_msg_received_data
|
||||
# cfg_msg_received_type
|
||||
|
||||
# Configuration Transmit Message Interface
|
||||
# cfg_msg_transmit
|
||||
# cfg_msg_transmit_type
|
||||
# cfg_msg_transmit_data
|
||||
# cfg_msg_transmit_done
|
||||
|
||||
# Configuration Flow Control Interface
|
||||
# cfg_fc_ph=dut.cfg_fc_ph,
|
||||
# cfg_fc_pd=dut.cfg_fc_pd,
|
||||
# cfg_fc_nph=dut.cfg_fc_nph,
|
||||
# cfg_fc_npd=dut.cfg_fc_npd,
|
||||
# cfg_fc_cplh=dut.cfg_fc_cplh,
|
||||
# cfg_fc_cpld=dut.cfg_fc_cpld,
|
||||
# cfg_fc_sel=dut.cfg_fc_sel,
|
||||
|
||||
# Configuration Control Interface
|
||||
# cfg_hot_reset_in
|
||||
# cfg_hot_reset_out
|
||||
# cfg_config_space_enable
|
||||
# cfg_dsn
|
||||
# cfg_bus_number
|
||||
# cfg_ds_port_number
|
||||
# cfg_ds_bus_number
|
||||
# cfg_ds_device_number
|
||||
# cfg_ds_function_number
|
||||
# cfg_power_state_change_ack
|
||||
# cfg_power_state_change_interrupt
|
||||
cfg_err_cor_in=dut.status_error_cor,
|
||||
cfg_err_uncor_in=dut.status_error_uncor,
|
||||
# cfg_flr_in_process
|
||||
# cfg_flr_done
|
||||
# cfg_vf_flr_in_process
|
||||
# cfg_vf_flr_func_num
|
||||
# cfg_vf_flr_done
|
||||
# cfg_pm_aspm_l1_entry_reject
|
||||
# cfg_pm_aspm_tx_l0s_entry_disable
|
||||
# cfg_req_pm_transition_l23_ready
|
||||
# cfg_link_training_enable
|
||||
|
||||
# Configuration Interrupt Controller Interface
|
||||
# cfg_interrupt_int
|
||||
# cfg_interrupt_sent
|
||||
# cfg_interrupt_pending
|
||||
cfg_interrupt_msi_enable=dut.cfg_interrupt_msi_enable,
|
||||
cfg_interrupt_msi_mmenable=dut.cfg_interrupt_msi_mmenable,
|
||||
cfg_interrupt_msi_mask_update=dut.cfg_interrupt_msi_mask_update,
|
||||
cfg_interrupt_msi_data=dut.cfg_interrupt_msi_data,
|
||||
# cfg_interrupt_msi_select=dut.cfg_interrupt_msi_select,
|
||||
cfg_interrupt_msi_int=dut.cfg_interrupt_msi_int,
|
||||
cfg_interrupt_msi_pending_status=dut.cfg_interrupt_msi_pending_status,
|
||||
cfg_interrupt_msi_pending_status_data_enable=dut.cfg_interrupt_msi_pending_status_data_enable,
|
||||
# cfg_interrupt_msi_pending_status_function_num=dut.cfg_interrupt_msi_pending_status_function_num,
|
||||
cfg_interrupt_msi_sent=dut.cfg_interrupt_msi_sent,
|
||||
cfg_interrupt_msi_fail=dut.cfg_interrupt_msi_fail,
|
||||
# cfg_interrupt_msix_enable
|
||||
# cfg_interrupt_msix_mask
|
||||
# cfg_interrupt_msix_vf_enable
|
||||
# cfg_interrupt_msix_vf_mask
|
||||
# cfg_interrupt_msix_address
|
||||
# cfg_interrupt_msix_data
|
||||
# cfg_interrupt_msix_int
|
||||
# cfg_interrupt_msix_vec_pending
|
||||
# cfg_interrupt_msix_vec_pending_status
|
||||
cfg_interrupt_msi_attr=dut.cfg_interrupt_msi_attr,
|
||||
cfg_interrupt_msi_tph_present=dut.cfg_interrupt_msi_tph_present,
|
||||
cfg_interrupt_msi_tph_type=dut.cfg_interrupt_msi_tph_type,
|
||||
# cfg_interrupt_msi_tph_st_tag=dut.cfg_interrupt_msi_tph_st_tag,
|
||||
# cfg_interrupt_msi_function_number=dut.cfg_interrupt_msi_function_number,
|
||||
|
||||
# Configuration Extend Interface
|
||||
# cfg_ext_read_received
|
||||
# cfg_ext_write_received
|
||||
# cfg_ext_register_number
|
||||
# cfg_ext_function_number
|
||||
# cfg_ext_write_data
|
||||
# cfg_ext_write_byte_enable
|
||||
# cfg_ext_read_data
|
||||
# cfg_ext_read_data_valid
|
||||
)
|
||||
|
||||
# self.dev.log.setLevel(logging.DEBUG)
|
||||
|
||||
self.rc.make_port().connect(self.dev)
|
||||
|
||||
self.dev.functions[0].msi_multiple_message_capable = 5
|
||||
|
||||
self.dev.functions[0].configure_bar(0, 2**22)
|
||||
self.dev.functions[0].configure_bar(1, 2**22)
|
||||
|
||||
async def init(self):
|
||||
|
||||
await FallingEdge(self.dut.rst)
|
||||
await Timer(100, 'ns')
|
||||
|
||||
await self.rc.enumerate(enable_bus_mastering=True, configure_msi=True)
|
||||
|
||||
|
||||
@cocotb.test()
|
||||
async def run_test(dut):
|
||||
|
||||
tb = TB(dut)
|
||||
|
||||
await tb.init()
|
||||
|
||||
mem_base, mem_data = tb.rc.alloc_region(16*1024*1024)
|
||||
|
||||
dev_pf0_bar0 = tb.rc.tree[0][0].bar_addr[0]
|
||||
dev_pf0_bar1 = tb.rc.tree[0][0].bar_addr[1]
|
||||
|
||||
tb.log.info("Test memory write to BAR 1")
|
||||
|
||||
await tb.rc.mem_write(dev_pf0_bar1, b'\x11\x22\x33\x44')
|
||||
|
||||
await Timer(100, 'ns')
|
||||
|
||||
tb.log.info("Test memory read from BAR 1")
|
||||
|
||||
val = await tb.rc.mem_read(dev_pf0_bar1, 4, 1000)
|
||||
tb.log.info("Read data: %s", val)
|
||||
assert val == b'\x11\x22\x33\x44'
|
||||
|
||||
tb.log.info("Test DMA")
|
||||
|
||||
# write packet data
|
||||
mem_data[0:1024] = bytearray([x % 256 for x in range(1024)])
|
||||
|
||||
# enable DMA
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100000, 1)
|
||||
|
||||
# write pcie read descriptor
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100100, (mem_base+0x0000) & 0xffffffff)
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100104, (mem_base+0x0000 >> 32) & 0xffffffff)
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100108, (0x100) & 0xffffffff)
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x10010C, (0x100 >> 32) & 0xffffffff)
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100110, 0x400)
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100114, 0xAA)
|
||||
|
||||
await Timer(2000, 'ns')
|
||||
|
||||
# read status
|
||||
val = await tb.rc.mem_read_dword(dev_pf0_bar0+0x100118)
|
||||
tb.log.info("Status: 0x%x", val)
|
||||
assert val == 0xAA
|
||||
|
||||
# write pcie write descriptor
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100200, (mem_base+0x1000) & 0xffffffff)
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100204, (mem_base+0x1000 >> 32) & 0xffffffff)
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100208, (0x100) & 0xffffffff)
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x10020C, (0x100 >> 32) & 0xffffffff)
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100210, 0x400)
|
||||
await tb.rc.mem_write_dword(dev_pf0_bar0+0x100214, 0x55)
|
||||
|
||||
await Timer(2000, 'ns')
|
||||
|
||||
# read status
|
||||
val = await tb.rc.mem_read_dword(dev_pf0_bar0+0x100218)
|
||||
tb.log.info("Status: 0x%x", val)
|
||||
assert val == 0x55
|
||||
|
||||
tb.log.info("%s", hexdump_str(mem_data, 0x1000, 64))
|
||||
|
||||
assert mem_data[0:1024] == mem_data[0x1000:0x1000+1024]
|
||||
|
||||
await RisingEdge(dut.clk)
|
||||
await RisingEdge(dut.clk)
|
||||
|
||||
|
||||
# cocotb-test
|
||||
|
||||
tests_dir = os.path.dirname(__file__)
|
||||
rtl_dir = os.path.abspath(os.path.join(tests_dir, '..', '..', 'rtl'))
|
||||
lib_dir = os.path.abspath(os.path.join(rtl_dir, '..', 'lib'))
|
||||
pcie_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'pcie', 'rtl'))
|
||||
|
||||
|
||||
def test_fpga_core(request):
|
||||
dut = "fpga_core"
|
||||
module = os.path.splitext(os.path.basename(__file__))[0]
|
||||
toplevel = dut
|
||||
|
||||
verilog_sources = [
|
||||
os.path.join(rtl_dir, f"{dut}.v"),
|
||||
os.path.join(rtl_dir, "axi_ram.v"),
|
||||
os.path.join(rtl_dir, "axis_register.v"),
|
||||
os.path.join(pcie_rtl_dir, "axis_arb_mux.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_us_axil_master.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_us_axi_dma.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_us_axi_dma_rd.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_us_axi_dma_wr.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_tag_manager.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_us_axi_master.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_us_axi_master_rd.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_us_axi_master_wr.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_us_axis_cq_demux.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_us_cfg.v"),
|
||||
os.path.join(pcie_rtl_dir, "pcie_us_msi.v"),
|
||||
os.path.join(pcie_rtl_dir, "arbiter.v"),
|
||||
os.path.join(pcie_rtl_dir, "priority_encoder.v"),
|
||||
os.path.join(pcie_rtl_dir, "pulse_merge.v"),
|
||||
]
|
||||
|
||||
parameters = {}
|
||||
|
||||
parameters['AXIS_PCIE_DATA_WIDTH'] = 512
|
||||
parameters['AXIS_PCIE_KEEP_WIDTH'] = parameters['AXIS_PCIE_DATA_WIDTH'] // 32
|
||||
parameters['AXIS_PCIE_RQ_USER_WIDTH'] = 62 if parameters['AXIS_PCIE_DATA_WIDTH'] < 512 else 137
|
||||
parameters['AXIS_PCIE_RC_USER_WIDTH'] = 75 if parameters['AXIS_PCIE_DATA_WIDTH'] < 512 else 161
|
||||
parameters['AXIS_PCIE_CQ_USER_WIDTH'] = 88 if parameters['AXIS_PCIE_DATA_WIDTH'] < 512 else 183
|
||||
parameters['AXIS_PCIE_CC_USER_WIDTH'] = 33 if parameters['AXIS_PCIE_DATA_WIDTH'] < 512 else 81
|
||||
parameters['RQ_SEQ_NUM_WIDTH'] = 6
|
||||
|
||||
extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()}
|
||||
|
||||
sim_build = os.path.join(tests_dir,
|
||||
"sim_build_"+request.node.name.replace('[', '-').replace(']', ''))
|
||||
|
||||
cocotb_test.simulator.run(
|
||||
python_search=[tests_dir],
|
||||
verilog_sources=verilog_sources,
|
||||
toplevel=toplevel,
|
||||
module=module,
|
||||
parameters=parameters,
|
||||
sim_build=sim_build,
|
||||
extra_env=extra_env,
|
||||
)
|
@ -1 +0,0 @@
|
||||
../lib/pcie/tb/pcie.py
|
@ -1 +0,0 @@
|
||||
../lib/pcie/tb/pcie_us.py
|
@ -1 +0,0 @@
|
||||
../lib/pcie/tb/pcie_usp.py
|
@ -1,514 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
"""
|
||||
|
||||
Copyright (c) 2018 Alex Forencich
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
"""
|
||||
|
||||
from myhdl import *
|
||||
import os
|
||||
import struct
|
||||
|
||||
import pcie
|
||||
import pcie_usp
|
||||
|
||||
module = 'fpga_core'
|
||||
testbench = 'test_%s' % module
|
||||
|
||||
srcs = []
|
||||
|
||||
srcs.append("../rtl/%s.v" % module)
|
||||
srcs.append("../rtl/axi_ram.v")
|
||||
srcs.append("../rtl/axis_register.v")
|
||||
srcs.append("../lib/pcie/rtl/axis_arb_mux.v")
|
||||
srcs.append("../lib/pcie/rtl/pcie_us_axil_master.v")
|
||||
srcs.append("../lib/pcie/rtl/pcie_us_axi_dma.v")
|
||||
srcs.append("../lib/pcie/rtl/pcie_us_axi_dma_rd.v")
|
||||
srcs.append("../lib/pcie/rtl/pcie_us_axi_dma_wr.v")
|
||||
srcs.append("../lib/pcie/rtl/pcie_tag_manager.v")
|
||||
srcs.append("../lib/pcie/rtl/pcie_us_axi_master.v")
|
||||
srcs.append("../lib/pcie/rtl/pcie_us_axi_master_rd.v")
|
||||
srcs.append("../lib/pcie/rtl/pcie_us_axi_master_wr.v")
|
||||
srcs.append("../lib/pcie/rtl/pcie_us_axis_cq_demux.v")
|
||||
srcs.append("../lib/pcie/rtl/pcie_us_cfg.v")
|
||||
srcs.append("../lib/pcie/rtl/pcie_us_msi.v")
|
||||
srcs.append("../lib/pcie/rtl/arbiter.v")
|
||||
srcs.append("../lib/pcie/rtl/priority_encoder.v")
|
||||
srcs.append("../lib/pcie/rtl/pulse_merge.v")
|
||||
srcs.append("%s.v" % testbench)
|
||||
|
||||
src = ' '.join(srcs)
|
||||
|
||||
build_cmd = "iverilog -o %s.vvp %s" % (testbench, src)
|
||||
|
||||
def bench():
|
||||
|
||||
# Parameters
|
||||
AXIS_PCIE_DATA_WIDTH = 512
|
||||
AXIS_PCIE_KEEP_WIDTH = (AXIS_PCIE_DATA_WIDTH/32)
|
||||
AXIS_PCIE_RC_USER_WIDTH = 161
|
||||
AXIS_PCIE_RQ_USER_WIDTH = 137
|
||||
AXIS_PCIE_CQ_USER_WIDTH = 183
|
||||
AXIS_PCIE_CC_USER_WIDTH = 81
|
||||
|
||||
# Inputs
|
||||
clk = Signal(bool(0))
|
||||
rst = Signal(bool(0))
|
||||
current_test = Signal(intbv(0)[8:])
|
||||
|
||||
m_axis_rq_tready = Signal(bool(0))
|
||||
s_axis_rc_tdata = Signal(intbv(0)[AXIS_PCIE_DATA_WIDTH:])
|
||||
s_axis_rc_tkeep = Signal(intbv(0)[AXIS_PCIE_KEEP_WIDTH:])
|
||||
s_axis_rc_tlast = Signal(bool(0))
|
||||
s_axis_rc_tuser = Signal(intbv(0)[AXIS_PCIE_RC_USER_WIDTH:])
|
||||
s_axis_rc_tvalid = Signal(bool(0))
|
||||
s_axis_cq_tdata = Signal(intbv(0)[AXIS_PCIE_DATA_WIDTH:])
|
||||
s_axis_cq_tkeep = Signal(intbv(0)[AXIS_PCIE_KEEP_WIDTH:])
|
||||
s_axis_cq_tlast = Signal(bool(0))
|
||||
s_axis_cq_tuser = Signal(intbv(0)[AXIS_PCIE_CQ_USER_WIDTH:])
|
||||
s_axis_cq_tvalid = Signal(bool(0))
|
||||
m_axis_cc_tready = Signal(bool(0))
|
||||
cfg_max_payload = Signal(intbv(0)[2:])
|
||||
cfg_max_read_req = Signal(intbv(0)[3:])
|
||||
cfg_mgmt_read_data = Signal(intbv(0)[32:])
|
||||
cfg_mgmt_read_write_done = Signal(bool(0))
|
||||
cfg_interrupt_msi_enable = Signal(intbv(0)[4:])
|
||||
cfg_interrupt_msi_mmenable = Signal(intbv(0)[12:])
|
||||
cfg_interrupt_msi_mask_update = Signal(bool(0))
|
||||
cfg_interrupt_msi_data = Signal(intbv(0)[32:])
|
||||
cfg_interrupt_msi_sent = Signal(bool(0))
|
||||
cfg_interrupt_msi_fail = Signal(bool(0))
|
||||
|
||||
# Outputs
|
||||
led_red = Signal(intbv(0)[8:])
|
||||
led_green = Signal(intbv(0)[8:])
|
||||
led_bmc = Signal(intbv(0)[2:])
|
||||
led_exp = Signal(intbv(0)[2:])
|
||||
m_axis_rq_tdata = Signal(intbv(0)[AXIS_PCIE_DATA_WIDTH:])
|
||||
m_axis_rq_tkeep = Signal(intbv(0)[AXIS_PCIE_KEEP_WIDTH:])
|
||||
m_axis_rq_tlast = Signal(bool(0))
|
||||
m_axis_rq_tuser = Signal(intbv(0)[AXIS_PCIE_RQ_USER_WIDTH:])
|
||||
m_axis_rq_tvalid = Signal(bool(0))
|
||||
s_axis_rc_tready = Signal(bool(0))
|
||||
s_axis_cq_tready = Signal(bool(0))
|
||||
m_axis_cc_tdata = Signal(intbv(0)[AXIS_PCIE_DATA_WIDTH:])
|
||||
m_axis_cc_tkeep = Signal(intbv(0)[AXIS_PCIE_KEEP_WIDTH:])
|
||||
m_axis_cc_tlast = Signal(bool(0))
|
||||
m_axis_cc_tuser = Signal(intbv(0)[AXIS_PCIE_CC_USER_WIDTH:])
|
||||
m_axis_cc_tvalid = Signal(bool(0))
|
||||
status_error_cor = Signal(bool(0))
|
||||
status_error_uncor = Signal(bool(0))
|
||||
cfg_mgmt_addr = Signal(intbv(0)[10:])
|
||||
cfg_mgmt_function_number = Signal(intbv(0)[8:])
|
||||
cfg_mgmt_write = Signal(bool(0))
|
||||
cfg_mgmt_write_data = Signal(intbv(0)[32:])
|
||||
cfg_mgmt_byte_enable = Signal(intbv(0)[4:])
|
||||
cfg_mgmt_read = Signal(bool(0))
|
||||
cfg_interrupt_msi_int = Signal(intbv(0)[32:])
|
||||
cfg_interrupt_msi_pending_status = Signal(intbv(0)[32:])
|
||||
cfg_interrupt_msi_select = Signal(intbv(0)[2:])
|
||||
cfg_interrupt_msi_pending_status_function_num = Signal(intbv(0)[2:])
|
||||
cfg_interrupt_msi_pending_status_data_enable = Signal(bool(0))
|
||||
cfg_interrupt_msi_attr = Signal(intbv(0)[3:])
|
||||
cfg_interrupt_msi_tph_present = Signal(bool(0))
|
||||
cfg_interrupt_msi_tph_type = Signal(intbv(0)[2:])
|
||||
cfg_interrupt_msi_tph_st_tag = Signal(intbv(0)[8:])
|
||||
cfg_interrupt_msi_function_number = Signal(intbv(0)[8:])
|
||||
|
||||
# Clock and Reset Interface
|
||||
user_clk=Signal(bool(0))
|
||||
user_reset=Signal(bool(0))
|
||||
sys_clk=Signal(bool(0))
|
||||
sys_reset=Signal(bool(0))
|
||||
|
||||
# PCIe devices
|
||||
rc = pcie.RootComplex()
|
||||
|
||||
mem_base, mem_data = rc.alloc_region(16*1024*1024)
|
||||
|
||||
dev = pcie_usp.UltrascalePlusPCIe()
|
||||
|
||||
dev.pcie_generation = 3
|
||||
dev.pcie_link_width = 16
|
||||
dev.user_clk_frequency = 250e6
|
||||
|
||||
dev.functions[0].msi_multiple_message_capable = 5
|
||||
|
||||
dev.functions[0].configure_bar(0, 4*1024*1024)
|
||||
dev.functions[0].configure_bar(1, 4*1024*1024)
|
||||
|
||||
rc.make_port().connect(dev)
|
||||
|
||||
pcie_logic = dev.create_logic(
|
||||
# Completer reQuest Interface
|
||||
m_axis_cq_tdata=s_axis_cq_tdata,
|
||||
m_axis_cq_tuser=s_axis_cq_tuser,
|
||||
m_axis_cq_tlast=s_axis_cq_tlast,
|
||||
m_axis_cq_tkeep=s_axis_cq_tkeep,
|
||||
m_axis_cq_tvalid=s_axis_cq_tvalid,
|
||||
m_axis_cq_tready=s_axis_cq_tready,
|
||||
#pcie_cq_np_req=pcie_cq_np_req,
|
||||
pcie_cq_np_req=Signal(intbv(1)[2:]),
|
||||
#pcie_cq_np_req_count=pcie_cq_np_req_count,
|
||||
|
||||
# Completer Completion Interface
|
||||
s_axis_cc_tdata=m_axis_cc_tdata,
|
||||
s_axis_cc_tuser=m_axis_cc_tuser,
|
||||
s_axis_cc_tlast=m_axis_cc_tlast,
|
||||
s_axis_cc_tkeep=m_axis_cc_tkeep,
|
||||
s_axis_cc_tvalid=m_axis_cc_tvalid,
|
||||
s_axis_cc_tready=m_axis_cc_tready,
|
||||
|
||||
# Requester reQuest Interface
|
||||
s_axis_rq_tdata=m_axis_rq_tdata,
|
||||
s_axis_rq_tuser=m_axis_rq_tuser,
|
||||
s_axis_rq_tlast=m_axis_rq_tlast,
|
||||
s_axis_rq_tkeep=m_axis_rq_tkeep,
|
||||
s_axis_rq_tvalid=m_axis_rq_tvalid,
|
||||
s_axis_rq_tready=m_axis_rq_tready,
|
||||
#pcie_rq_seq_num0=pcie_rq_seq_num0,
|
||||
#pcie_rq_seq_num_vld0=pcie_rq_seq_num_vld0,
|
||||
#pcie_rq_seq_num1=pcie_rq_seq_num1,
|
||||
#pcie_rq_seq_num_vld1=pcie_rq_seq_num_vld1,
|
||||
#pcie_rq_tag0=pcie_rq_tag0,
|
||||
#pcie_rq_tag1=pcie_rq_tag1,
|
||||
#pcie_rq_tag_av=pcie_rq_tag_av,
|
||||
#pcie_rq_tag_vld0=pcie_rq_tag_vld0,
|
||||
#pcie_rq_tag_vld1=pcie_rq_tag_vld1,
|
||||
|
||||
# Requester Completion Interface
|
||||
m_axis_rc_tdata=s_axis_rc_tdata,
|
||||
m_axis_rc_tuser=s_axis_rc_tuser,
|
||||
m_axis_rc_tlast=s_axis_rc_tlast,
|
||||
m_axis_rc_tkeep=s_axis_rc_tkeep,
|
||||
m_axis_rc_tvalid=s_axis_rc_tvalid,
|
||||
m_axis_rc_tready=s_axis_rc_tready,
|
||||
|
||||
# Transmit Flow Control Interface
|
||||
#pcie_tfc_nph_av=pcie_tfc_nph_av,
|
||||
#pcie_tfc_npd_av=pcie_tfc_npd_av,
|
||||
|
||||
# Configuration Management Interface
|
||||
cfg_mgmt_addr=cfg_mgmt_addr,
|
||||
cfg_mgmt_function_number=cfg_mgmt_function_number,
|
||||
cfg_mgmt_write=cfg_mgmt_write,
|
||||
cfg_mgmt_write_data=cfg_mgmt_write_data,
|
||||
cfg_mgmt_byte_enable=cfg_mgmt_byte_enable,
|
||||
cfg_mgmt_read=cfg_mgmt_read,
|
||||
cfg_mgmt_read_data=cfg_mgmt_read_data,
|
||||
cfg_mgmt_read_write_done=cfg_mgmt_read_write_done,
|
||||
#cfg_mgmt_debug_access=cfg_mgmt_debug_access,
|
||||
|
||||
# Configuration Status Interface
|
||||
#cfg_phy_link_down=cfg_phy_link_down,
|
||||
#cfg_phy_link_status=cfg_phy_link_status,
|
||||
#cfg_negotiated_width=cfg_negotiated_width,
|
||||
#cfg_current_speed=cfg_current_speed,
|
||||
cfg_max_payload=cfg_max_payload,
|
||||
cfg_max_read_req=cfg_max_read_req,
|
||||
#cfg_function_status=cfg_function_status,
|
||||
#cfg_vf_status=cfg_vf_status,
|
||||
#cfg_function_power_state=cfg_function_power_state,
|
||||
#cfg_vf_power_state=cfg_vf_power_state,
|
||||
#cfg_link_power_state=cfg_link_power_state,
|
||||
#cfg_err_cor_out=cfg_err_cor_out,
|
||||
#cfg_err_nonfatal_out=cfg_err_nonfatal_out,
|
||||
#cfg_err_fatal_out=cfg_err_fatal_out,
|
||||
#cfg_local_err_out=cfg_local_err_out,
|
||||
#cfg_local_err_valid=cfg_local_err_valid,
|
||||
#cfg_rx_pm_state=cfg_rx_pm_state,
|
||||
#cfg_tx_pm_state=cfg_tx_pm_state,
|
||||
#cfg_ltssm_state=cfg_ltssm_state,
|
||||
#cfg_rcb_status=cfg_rcb_status,
|
||||
#cfg_obff_enable=cfg_obff_enable,
|
||||
#cfg_pl_status_change=cfg_pl_status_change,
|
||||
#cfg_tph_requester_enable=cfg_tph_requester_enable,
|
||||
#cfg_tph_st_mode=cfg_tph_st_mode,
|
||||
#cfg_vf_tph_requester_enable=cfg_vf_tph_requester_enable,
|
||||
#cfg_vf_tph_st_mode=cfg_vf_tph_st_mode,
|
||||
|
||||
# Configuration Received Message Interface
|
||||
#cfg_msg_received=cfg_msg_received,
|
||||
#cfg_msg_received_data=cfg_msg_received_data,
|
||||
#cfg_msg_received_type=cfg_msg_received_type,
|
||||
|
||||
# Configuration Transmit Message Interface
|
||||
#cfg_msg_transmit=cfg_msg_transmit,
|
||||
#cfg_msg_transmit_type=cfg_msg_transmit_type,
|
||||
#cfg_msg_transmit_data=cfg_msg_transmit_data,
|
||||
#cfg_msg_transmit_done=cfg_msg_transmit_done,
|
||||
|
||||
# Configuration Flow Control Interface
|
||||
#cfg_fc_ph=cfg_fc_ph,
|
||||
#cfg_fc_pd=cfg_fc_pd,
|
||||
#cfg_fc_nph=cfg_fc_nph,
|
||||
#cfg_fc_npd=cfg_fc_npd,
|
||||
#cfg_fc_cplh=cfg_fc_cplh,
|
||||
#cfg_fc_cpld=cfg_fc_cpld,
|
||||
#cfg_fc_sel=cfg_fc_sel,
|
||||
|
||||
# Configuration Control Interface
|
||||
#cfg_hot_reset_in=cfg_hot_reset_in,
|
||||
#cfg_hot_reset_out=cfg_hot_reset_out,
|
||||
#cfg_config_space_enable=cfg_config_space_enable,
|
||||
#cfg_dsn=cfg_dsn,
|
||||
#cfg_ds_port_number=cfg_ds_port_number,
|
||||
#cfg_ds_bus_number=cfg_ds_bus_number,
|
||||
#cfg_ds_device_number=cfg_ds_device_number,
|
||||
#cfg_ds_function_number=cfg_ds_function_number,
|
||||
#cfg_power_state_change_ack=cfg_power_state_change_ack,
|
||||
#cfg_power_state_change_interrupt=cfg_power_state_change_interrupt,
|
||||
cfg_err_cor_in=status_error_cor,
|
||||
cfg_err_uncor_in=status_error_uncor,
|
||||
#cfg_flr_done=cfg_flr_done,
|
||||
#cfg_vf_flr_done=cfg_vf_flr_done,
|
||||
#cfg_flr_in_process=cfg_flr_in_process,
|
||||
#cfg_vf_flr_in_process=cfg_vf_flr_in_process,
|
||||
#cfg_req_pm_transition_l23_ready=cfg_req_pm_transition_l23_ready,
|
||||
#cfg_link_training_enable=cfg_link_training_enable,
|
||||
|
||||
# Configuration Interrupt Controller Interface
|
||||
#cfg_interrupt_int=cfg_interrupt_int,
|
||||
#cfg_interrupt_sent=cfg_interrupt_sent,
|
||||
#cfg_interrupt_pending=cfg_interrupt_pending,
|
||||
cfg_interrupt_msi_enable=cfg_interrupt_msi_enable,
|
||||
cfg_interrupt_msi_mmenable=cfg_interrupt_msi_mmenable,
|
||||
cfg_interrupt_msi_mask_update=cfg_interrupt_msi_mask_update,
|
||||
cfg_interrupt_msi_data=cfg_interrupt_msi_data,
|
||||
cfg_interrupt_msi_select=cfg_interrupt_msi_select,
|
||||
cfg_interrupt_msi_int=cfg_interrupt_msi_int,
|
||||
cfg_interrupt_msi_pending_status=cfg_interrupt_msi_pending_status,
|
||||
cfg_interrupt_msi_pending_status_data_enable=cfg_interrupt_msi_pending_status_data_enable,
|
||||
cfg_interrupt_msi_pending_status_function_num=cfg_interrupt_msi_pending_status_function_num,
|
||||
cfg_interrupt_msi_sent=cfg_interrupt_msi_sent,
|
||||
cfg_interrupt_msi_fail=cfg_interrupt_msi_fail,
|
||||
#cfg_interrupt_msix_enable=cfg_interrupt_msix_enable,
|
||||
#cfg_interrupt_msix_mask=cfg_interrupt_msix_mask,
|
||||
#cfg_interrupt_msix_vf_enable=cfg_interrupt_msix_vf_enable,
|
||||
#cfg_interrupt_msix_vf_mask=cfg_interrupt_msix_vf_mask,
|
||||
#cfg_interrupt_msix_address=cfg_interrupt_msix_address,
|
||||
#cfg_interrupt_msix_data=cfg_interrupt_msix_data,
|
||||
#cfg_interrupt_msix_int=cfg_interrupt_msix_int,
|
||||
#cfg_interrupt_msix_vec_pending=cfg_interrupt_msix_vec_pending,
|
||||
#cfg_interrupt_msix_vec_pending_status=cfg_interrupt_msix_vec_pending_status,
|
||||
cfg_interrupt_msi_attr=cfg_interrupt_msi_attr,
|
||||
cfg_interrupt_msi_tph_present=cfg_interrupt_msi_tph_present,
|
||||
cfg_interrupt_msi_tph_type=cfg_interrupt_msi_tph_type,
|
||||
cfg_interrupt_msi_tph_st_tag=cfg_interrupt_msi_tph_st_tag,
|
||||
cfg_interrupt_msi_function_number=cfg_interrupt_msi_function_number,
|
||||
|
||||
# Configuration Extend Interface
|
||||
#cfg_ext_read_received=cfg_ext_read_received,
|
||||
#cfg_ext_write_received=cfg_ext_write_received,
|
||||
#cfg_ext_register_number=cfg_ext_register_number,
|
||||
#cfg_ext_function_number=cfg_ext_function_number,
|
||||
#cfg_ext_write_data=cfg_ext_write_data,
|
||||
#cfg_ext_write_byte_enable=cfg_ext_write_byte_enable,
|
||||
#cfg_ext_read_data=cfg_ext_read_data,
|
||||
#cfg_ext_read_data_valid=cfg_ext_read_data_valid,
|
||||
|
||||
# Clock and Reset Interface
|
||||
user_clk=user_clk,
|
||||
user_reset=user_reset,
|
||||
#user_lnk_up=user_lnk_up,
|
||||
sys_clk=sys_clk,
|
||||
sys_clk_gt=sys_clk,
|
||||
sys_reset=sys_reset,
|
||||
#phy_rdy_out=phy_rdy_out
|
||||
)
|
||||
|
||||
# DUT
|
||||
if os.system(build_cmd):
|
||||
raise Exception("Error running build command")
|
||||
|
||||
dut = Cosimulation(
|
||||
"vvp -m myhdl %s.vvp -lxt2" % testbench,
|
||||
clk=user_clk,
|
||||
rst=user_reset,
|
||||
current_test=current_test,
|
||||
led_red=led_red,
|
||||
led_green=led_green,
|
||||
led_bmc=led_bmc,
|
||||
led_exp=led_exp,
|
||||
m_axis_rq_tdata=m_axis_rq_tdata,
|
||||
m_axis_rq_tkeep=m_axis_rq_tkeep,
|
||||
m_axis_rq_tlast=m_axis_rq_tlast,
|
||||
m_axis_rq_tready=m_axis_rq_tready,
|
||||
m_axis_rq_tuser=m_axis_rq_tuser,
|
||||
m_axis_rq_tvalid=m_axis_rq_tvalid,
|
||||
s_axis_rc_tdata=s_axis_rc_tdata,
|
||||
s_axis_rc_tkeep=s_axis_rc_tkeep,
|
||||
s_axis_rc_tlast=s_axis_rc_tlast,
|
||||
s_axis_rc_tready=s_axis_rc_tready,
|
||||
s_axis_rc_tuser=s_axis_rc_tuser,
|
||||
s_axis_rc_tvalid=s_axis_rc_tvalid,
|
||||
s_axis_cq_tdata=s_axis_cq_tdata,
|
||||
s_axis_cq_tkeep=s_axis_cq_tkeep,
|
||||
s_axis_cq_tlast=s_axis_cq_tlast,
|
||||
s_axis_cq_tready=s_axis_cq_tready,
|
||||
s_axis_cq_tuser=s_axis_cq_tuser,
|
||||
s_axis_cq_tvalid=s_axis_cq_tvalid,
|
||||
m_axis_cc_tdata=m_axis_cc_tdata,
|
||||
m_axis_cc_tkeep=m_axis_cc_tkeep,
|
||||
m_axis_cc_tlast=m_axis_cc_tlast,
|
||||
m_axis_cc_tready=m_axis_cc_tready,
|
||||
m_axis_cc_tuser=m_axis_cc_tuser,
|
||||
m_axis_cc_tvalid=m_axis_cc_tvalid,
|
||||
cfg_max_payload=cfg_max_payload,
|
||||
cfg_max_read_req=cfg_max_read_req,
|
||||
cfg_mgmt_addr=cfg_mgmt_addr,
|
||||
cfg_mgmt_function_number=cfg_mgmt_function_number,
|
||||
cfg_mgmt_write=cfg_mgmt_write,
|
||||
cfg_mgmt_write_data=cfg_mgmt_write_data,
|
||||
cfg_mgmt_byte_enable=cfg_mgmt_byte_enable,
|
||||
cfg_mgmt_read=cfg_mgmt_read,
|
||||
cfg_mgmt_read_data=cfg_mgmt_read_data,
|
||||
cfg_mgmt_read_write_done=cfg_mgmt_read_write_done,
|
||||
cfg_interrupt_msi_enable=cfg_interrupt_msi_enable,
|
||||
cfg_interrupt_msi_int=cfg_interrupt_msi_int,
|
||||
cfg_interrupt_msi_sent=cfg_interrupt_msi_sent,
|
||||
cfg_interrupt_msi_fail=cfg_interrupt_msi_fail,
|
||||
cfg_interrupt_msi_mmenable=cfg_interrupt_msi_mmenable,
|
||||
cfg_interrupt_msi_pending_status=cfg_interrupt_msi_pending_status,
|
||||
cfg_interrupt_msi_mask_update=cfg_interrupt_msi_mask_update,
|
||||
cfg_interrupt_msi_select=cfg_interrupt_msi_select,
|
||||
cfg_interrupt_msi_data=cfg_interrupt_msi_data,
|
||||
cfg_interrupt_msi_pending_status_function_num=cfg_interrupt_msi_pending_status_function_num,
|
||||
cfg_interrupt_msi_pending_status_data_enable=cfg_interrupt_msi_pending_status_data_enable,
|
||||
cfg_interrupt_msi_attr=cfg_interrupt_msi_attr,
|
||||
cfg_interrupt_msi_tph_present=cfg_interrupt_msi_tph_present,
|
||||
cfg_interrupt_msi_tph_type=cfg_interrupt_msi_tph_type,
|
||||
cfg_interrupt_msi_tph_st_tag=cfg_interrupt_msi_tph_st_tag,
|
||||
cfg_interrupt_msi_function_number=cfg_interrupt_msi_function_number,
|
||||
status_error_cor=status_error_cor,
|
||||
status_error_uncor=status_error_uncor
|
||||
)
|
||||
|
||||
@always(delay(5))
|
||||
def clkgen():
|
||||
clk.next = not clk
|
||||
|
||||
@always_comb
|
||||
def clk_logic():
|
||||
sys_clk.next = clk
|
||||
sys_reset.next = not rst
|
||||
|
||||
@instance
|
||||
def check():
|
||||
yield delay(100)
|
||||
yield clk.posedge
|
||||
rst.next = 1
|
||||
yield clk.posedge
|
||||
rst.next = 0
|
||||
yield clk.posedge
|
||||
yield delay(100)
|
||||
yield clk.posedge
|
||||
|
||||
# testbench stimulus
|
||||
|
||||
current_tag = 1
|
||||
|
||||
yield clk.posedge
|
||||
print("test 1: enumeration")
|
||||
current_test.next = 1
|
||||
|
||||
yield rc.enumerate(enable_bus_mastering=True, configure_msi=True)
|
||||
|
||||
dev_pf0_bar0 = dev.functions[0].bar[0] & 0xfffffffc
|
||||
dev_pf0_bar1 = dev.functions[0].bar[1] & 0xfffffffc
|
||||
|
||||
yield delay(100)
|
||||
|
||||
yield clk.posedge
|
||||
print("test 2: memory write to bar 1")
|
||||
current_test.next = 2
|
||||
|
||||
yield rc.mem_write(dev_pf0_bar1, b'\x11\x22\x33\x44')
|
||||
|
||||
yield delay(100)
|
||||
|
||||
yield clk.posedge
|
||||
print("test 3: memory read from bar 1")
|
||||
current_test.next = 3
|
||||
|
||||
val = yield from rc.mem_read(dev_pf0_bar1, 4, 1000)
|
||||
print(val)
|
||||
assert val == b'\x11\x22\x33\x44'
|
||||
|
||||
yield delay(100)
|
||||
|
||||
yield clk.posedge
|
||||
print("test 4: test DMA")
|
||||
current_test.next = 4
|
||||
|
||||
# write packet data
|
||||
mem_data[0:1024] = bytearray([x%256 for x in range(1024)])
|
||||
|
||||
# enable DMA
|
||||
yield rc.mem_write(dev_pf0_bar0+0x100000, struct.pack('<L', 1))
|
||||
|
||||
# write pcie read descriptor
|
||||
yield rc.mem_write(dev_pf0_bar0+0x100100, struct.pack('<L', (mem_base+0x0000) & 0xffffffff))
|
||||
yield rc.mem_write(dev_pf0_bar0+0x100104, struct.pack('<L', (mem_base+0x0000 >> 32) & 0xffffffff))
|
||||
yield rc.mem_write(dev_pf0_bar0+0x100108, struct.pack('<L', (0x100) & 0xffffffff))
|
||||
yield rc.mem_write(dev_pf0_bar0+0x10010C, struct.pack('<L', (0x100 >> 32) & 0xffffffff))
|
||||
yield rc.mem_write(dev_pf0_bar0+0x100110, struct.pack('<L', 0x400))
|
||||
yield rc.mem_write(dev_pf0_bar0+0x100114, struct.pack('<L', 0xAA))
|
||||
|
||||
yield delay(2000)
|
||||
|
||||
# read status
|
||||
val = yield from rc.mem_read(dev_pf0_bar0+0x100118, 4)
|
||||
print(val)
|
||||
|
||||
# write pcie write descriptor
|
||||
yield rc.mem_write(dev_pf0_bar0+0x100200, struct.pack('<L', (mem_base+0x1000) & 0xffffffff))
|
||||
yield rc.mem_write(dev_pf0_bar0+0x100204, struct.pack('<L', (mem_base+0x1000 >> 32) & 0xffffffff))
|
||||
yield rc.mem_write(dev_pf0_bar0+0x100208, struct.pack('<L', (0x100) & 0xffffffff))
|
||||
yield rc.mem_write(dev_pf0_bar0+0x10020C, struct.pack('<L', (0x100 >> 32) & 0xffffffff))
|
||||
yield rc.mem_write(dev_pf0_bar0+0x100210, struct.pack('<L', 0x400))
|
||||
yield rc.mem_write(dev_pf0_bar0+0x100214, struct.pack('<L', 0x55))
|
||||
|
||||
yield delay(2000)
|
||||
|
||||
# read status
|
||||
val = yield from rc.mem_read(dev_pf0_bar0+0x100218, 4)
|
||||
print(val)
|
||||
|
||||
data = mem_data[0x1000:(0x1000)+64]
|
||||
for i in range(0, len(data), 16):
|
||||
print(" ".join(("{:02x}".format(c) for c in bytearray(data[i:i+16]))))
|
||||
|
||||
assert mem_data[0:1024] == mem_data[0x1000:0x1000+1024]
|
||||
|
||||
yield delay(100)
|
||||
|
||||
raise StopSimulation
|
||||
|
||||
return instances()
|
||||
|
||||
def test_bench():
|
||||
sim = Simulation(bench())
|
||||
sim.run()
|
||||
|
||||
if __name__ == '__main__':
|
||||
print("Running test...")
|
||||
test_bench()
|
@ -1,246 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2018 Alex Forencich
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
// Language: Verilog 2001
|
||||
|
||||
`timescale 1ns / 1ps
|
||||
|
||||
/*
|
||||
* Testbench for fpga_core
|
||||
*/
|
||||
module test_fpga_core;
|
||||
|
||||
// Parameters
|
||||
parameter AXIS_PCIE_DATA_WIDTH = 512;
|
||||
parameter AXIS_PCIE_KEEP_WIDTH = (AXIS_PCIE_DATA_WIDTH/32);
|
||||
parameter AXIS_PCIE_RC_USER_WIDTH = 161;
|
||||
parameter AXIS_PCIE_RQ_USER_WIDTH = 137;
|
||||
parameter AXIS_PCIE_CQ_USER_WIDTH = 183;
|
||||
parameter AXIS_PCIE_CC_USER_WIDTH = 81;
|
||||
|
||||
// Inputs
|
||||
reg clk = 0;
|
||||
reg rst = 0;
|
||||
reg [7:0] current_test = 0;
|
||||
|
||||
reg m_axis_rq_tready = 0;
|
||||
reg [AXIS_PCIE_DATA_WIDTH-1:0] s_axis_rc_tdata = 0;
|
||||
reg [AXIS_PCIE_KEEP_WIDTH-1:0] s_axis_rc_tkeep = 0;
|
||||
reg s_axis_rc_tlast = 0;
|
||||
reg [AXIS_PCIE_RC_USER_WIDTH-1:0] s_axis_rc_tuser = 0;
|
||||
reg s_axis_rc_tvalid = 0;
|
||||
reg [AXIS_PCIE_DATA_WIDTH-1:0] s_axis_cq_tdata = 0;
|
||||
reg [AXIS_PCIE_KEEP_WIDTH-1:0] s_axis_cq_tkeep = 0;
|
||||
reg s_axis_cq_tlast = 0;
|
||||
reg [AXIS_PCIE_CQ_USER_WIDTH-1:0] s_axis_cq_tuser = 0;
|
||||
reg s_axis_cq_tvalid = 0;
|
||||
reg m_axis_cc_tready = 0;
|
||||
reg [2:0] cfg_max_payload = 0;
|
||||
reg [2:0] cfg_max_read_req = 0;
|
||||
reg [31:0] cfg_mgmt_read_data = 0;
|
||||
reg cfg_mgmt_read_write_done = 0;
|
||||
reg [3:0] cfg_interrupt_msi_enable = 0;
|
||||
reg [11:0] cfg_interrupt_msi_mmenable = 0;
|
||||
reg cfg_interrupt_msi_mask_update = 0;
|
||||
reg [31:0] cfg_interrupt_msi_data = 0;
|
||||
reg cfg_interrupt_msi_sent = 0;
|
||||
reg cfg_interrupt_msi_fail = 0;
|
||||
|
||||
// Outputs
|
||||
wire [7:0] led_red;
|
||||
wire [7:0] led_green;
|
||||
wire [1:0] led_bmc;
|
||||
wire [1:0] led_exp;
|
||||
wire [AXIS_PCIE_DATA_WIDTH-1:0] m_axis_rq_tdata;
|
||||
wire [AXIS_PCIE_KEEP_WIDTH-1:0] m_axis_rq_tkeep;
|
||||
wire m_axis_rq_tlast;
|
||||
wire [AXIS_PCIE_RQ_USER_WIDTH-1:0] m_axis_rq_tuser;
|
||||
wire m_axis_rq_tvalid;
|
||||
wire s_axis_rc_tready;
|
||||
wire s_axis_cq_tready;
|
||||
wire [AXIS_PCIE_DATA_WIDTH-1:0] m_axis_cc_tdata;
|
||||
wire [AXIS_PCIE_KEEP_WIDTH-1:0] m_axis_cc_tkeep;
|
||||
wire m_axis_cc_tlast;
|
||||
wire [AXIS_PCIE_CC_USER_WIDTH-1:0] m_axis_cc_tuser;
|
||||
wire m_axis_cc_tvalid;
|
||||
wire [9:0] cfg_mgmt_addr;
|
||||
wire [7:0] cfg_mgmt_function_number;
|
||||
wire cfg_mgmt_write;
|
||||
wire [31:0] cfg_mgmt_write_data;
|
||||
wire [3:0] cfg_mgmt_byte_enable;
|
||||
wire cfg_mgmt_read;
|
||||
wire [3:0] cfg_interrupt_msi_select;
|
||||
wire [31:0] cfg_interrupt_msi_int;
|
||||
wire [31:0] cfg_interrupt_msi_pending_status;
|
||||
wire cfg_interrupt_msi_pending_status_data_enable;
|
||||
wire [3:0] cfg_interrupt_msi_pending_status_function_num;
|
||||
wire [2:0] cfg_interrupt_msi_attr;
|
||||
wire cfg_interrupt_msi_tph_present;
|
||||
wire [1:0] cfg_interrupt_msi_tph_type;
|
||||
wire [8:0] cfg_interrupt_msi_tph_st_tag;
|
||||
wire [3:0] cfg_interrupt_msi_function_number;
|
||||
wire status_error_cor;
|
||||
wire status_error_uncor;
|
||||
|
||||
initial begin
|
||||
// myhdl integration
|
||||
$from_myhdl(
|
||||
clk,
|
||||
rst,
|
||||
current_test,
|
||||
m_axis_rq_tready,
|
||||
s_axis_rc_tdata,
|
||||
s_axis_rc_tkeep,
|
||||
s_axis_rc_tlast,
|
||||
s_axis_rc_tuser,
|
||||
s_axis_rc_tvalid,
|
||||
s_axis_cq_tdata,
|
||||
s_axis_cq_tkeep,
|
||||
s_axis_cq_tlast,
|
||||
s_axis_cq_tuser,
|
||||
s_axis_cq_tvalid,
|
||||
m_axis_cc_tready,
|
||||
cfg_max_payload,
|
||||
cfg_max_read_req,
|
||||
cfg_mgmt_read_data,
|
||||
cfg_mgmt_read_write_done,
|
||||
cfg_interrupt_msi_enable,
|
||||
cfg_interrupt_msi_mmenable,
|
||||
cfg_interrupt_msi_mask_update,
|
||||
cfg_interrupt_msi_data,
|
||||
cfg_interrupt_msi_sent,
|
||||
cfg_interrupt_msi_fail
|
||||
);
|
||||
$to_myhdl(
|
||||
led_red,
|
||||
led_green,
|
||||
led_bmc,
|
||||
led_exp,
|
||||
m_axis_rq_tdata,
|
||||
m_axis_rq_tkeep,
|
||||
m_axis_rq_tlast,
|
||||
m_axis_rq_tuser,
|
||||
m_axis_rq_tvalid,
|
||||
s_axis_rc_tready,
|
||||
s_axis_cq_tready,
|
||||
m_axis_cc_tdata,
|
||||
m_axis_cc_tkeep,
|
||||
m_axis_cc_tlast,
|
||||
m_axis_cc_tuser,
|
||||
m_axis_cc_tvalid,
|
||||
cfg_mgmt_addr,
|
||||
cfg_mgmt_function_number,
|
||||
cfg_mgmt_write,
|
||||
cfg_mgmt_write_data,
|
||||
cfg_mgmt_byte_enable,
|
||||
cfg_mgmt_read,
|
||||
cfg_interrupt_msi_select,
|
||||
cfg_interrupt_msi_int,
|
||||
cfg_interrupt_msi_pending_status,
|
||||
cfg_interrupt_msi_pending_status_data_enable,
|
||||
cfg_interrupt_msi_pending_status_function_num,
|
||||
cfg_interrupt_msi_attr,
|
||||
cfg_interrupt_msi_tph_present,
|
||||
cfg_interrupt_msi_tph_type,
|
||||
cfg_interrupt_msi_tph_st_tag,
|
||||
cfg_interrupt_msi_function_number,
|
||||
status_error_cor,
|
||||
status_error_uncor
|
||||
);
|
||||
|
||||
// dump file
|
||||
$dumpfile("test_fpga_core.lxt");
|
||||
$dumpvars(0, test_fpga_core);
|
||||
end
|
||||
|
||||
fpga_core #(
|
||||
.AXIS_PCIE_DATA_WIDTH(AXIS_PCIE_DATA_WIDTH),
|
||||
.AXIS_PCIE_KEEP_WIDTH(AXIS_PCIE_KEEP_WIDTH),
|
||||
.AXIS_PCIE_RC_USER_WIDTH(AXIS_PCIE_RC_USER_WIDTH),
|
||||
.AXIS_PCIE_RQ_USER_WIDTH(AXIS_PCIE_RQ_USER_WIDTH),
|
||||
.AXIS_PCIE_CQ_USER_WIDTH(AXIS_PCIE_CQ_USER_WIDTH),
|
||||
.AXIS_PCIE_CC_USER_WIDTH(AXIS_PCIE_CC_USER_WIDTH)
|
||||
)
|
||||
UUT (
|
||||
.clk(clk),
|
||||
.rst(rst),
|
||||
.led_red(led_red),
|
||||
.led_green(led_green),
|
||||
.led_bmc(led_bmc),
|
||||
.led_exp(led_exp),
|
||||
.m_axis_rq_tdata(m_axis_rq_tdata),
|
||||
.m_axis_rq_tkeep(m_axis_rq_tkeep),
|
||||
.m_axis_rq_tlast(m_axis_rq_tlast),
|
||||
.m_axis_rq_tready(m_axis_rq_tready),
|
||||
.m_axis_rq_tuser(m_axis_rq_tuser),
|
||||
.m_axis_rq_tvalid(m_axis_rq_tvalid),
|
||||
.s_axis_rc_tdata(s_axis_rc_tdata),
|
||||
.s_axis_rc_tkeep(s_axis_rc_tkeep),
|
||||
.s_axis_rc_tlast(s_axis_rc_tlast),
|
||||
.s_axis_rc_tready(s_axis_rc_tready),
|
||||
.s_axis_rc_tuser(s_axis_rc_tuser),
|
||||
.s_axis_rc_tvalid(s_axis_rc_tvalid),
|
||||
.s_axis_cq_tdata(s_axis_cq_tdata),
|
||||
.s_axis_cq_tkeep(s_axis_cq_tkeep),
|
||||
.s_axis_cq_tlast(s_axis_cq_tlast),
|
||||
.s_axis_cq_tready(s_axis_cq_tready),
|
||||
.s_axis_cq_tuser(s_axis_cq_tuser),
|
||||
.s_axis_cq_tvalid(s_axis_cq_tvalid),
|
||||
.m_axis_cc_tdata(m_axis_cc_tdata),
|
||||
.m_axis_cc_tkeep(m_axis_cc_tkeep),
|
||||
.m_axis_cc_tlast(m_axis_cc_tlast),
|
||||
.m_axis_cc_tready(m_axis_cc_tready),
|
||||
.m_axis_cc_tuser(m_axis_cc_tuser),
|
||||
.m_axis_cc_tvalid(m_axis_cc_tvalid),
|
||||
.cfg_max_payload(cfg_max_payload),
|
||||
.cfg_max_read_req(cfg_max_read_req),
|
||||
.cfg_mgmt_addr(cfg_mgmt_addr),
|
||||
.cfg_mgmt_function_number(cfg_mgmt_function_number),
|
||||
.cfg_mgmt_write(cfg_mgmt_write),
|
||||
.cfg_mgmt_write_data(cfg_mgmt_write_data),
|
||||
.cfg_mgmt_byte_enable(cfg_mgmt_byte_enable),
|
||||
.cfg_mgmt_read(cfg_mgmt_read),
|
||||
.cfg_mgmt_read_data(cfg_mgmt_read_data),
|
||||
.cfg_mgmt_read_write_done(cfg_mgmt_read_write_done),
|
||||
.cfg_interrupt_msi_enable(cfg_interrupt_msi_enable),
|
||||
.cfg_interrupt_msi_mmenable(cfg_interrupt_msi_mmenable),
|
||||
.cfg_interrupt_msi_mask_update(cfg_interrupt_msi_mask_update),
|
||||
.cfg_interrupt_msi_data(cfg_interrupt_msi_data),
|
||||
.cfg_interrupt_msi_select(cfg_interrupt_msi_select),
|
||||
.cfg_interrupt_msi_int(cfg_interrupt_msi_int),
|
||||
.cfg_interrupt_msi_pending_status(cfg_interrupt_msi_pending_status),
|
||||
.cfg_interrupt_msi_pending_status_data_enable(cfg_interrupt_msi_pending_status_data_enable),
|
||||
.cfg_interrupt_msi_pending_status_function_num(cfg_interrupt_msi_pending_status_function_num),
|
||||
.cfg_interrupt_msi_sent(cfg_interrupt_msi_sent),
|
||||
.cfg_interrupt_msi_fail(cfg_interrupt_msi_fail),
|
||||
.cfg_interrupt_msi_attr(cfg_interrupt_msi_attr),
|
||||
.cfg_interrupt_msi_tph_present(cfg_interrupt_msi_tph_present),
|
||||
.cfg_interrupt_msi_tph_type(cfg_interrupt_msi_tph_type),
|
||||
.cfg_interrupt_msi_tph_st_tag(cfg_interrupt_msi_tph_st_tag),
|
||||
.cfg_interrupt_msi_function_number(cfg_interrupt_msi_function_number),
|
||||
.status_error_cor(status_error_cor),
|
||||
.status_error_uncor(status_error_uncor)
|
||||
);
|
||||
|
||||
endmodule
|
Loading…
x
Reference in New Issue
Block a user