mirror of
https://github.com/fpganinja/taxi.git
synced 2026-04-08 13:08:42 -07:00
cndm: Initial commit of corundum-micro
Signed-off-by: Alex Forencich <alex@alexforencich.com>
This commit is contained in:
276
src/cndm/tb/cndm.py
Normal file
276
src/cndm/tb/cndm.py
Normal file
@@ -0,0 +1,276 @@
|
||||
# SPDX-License-Identifier: CERN-OHL-S-2.0
|
||||
"""
|
||||
|
||||
Copyright (c) 2025 FPGA Ninja, LLC
|
||||
|
||||
Authors:
|
||||
- Alex Forencich
|
||||
|
||||
"""
|
||||
|
||||
import logging
|
||||
import struct
|
||||
from collections import deque
|
||||
|
||||
from cocotb.queue import Queue
|
||||
|
||||
class Port:
|
||||
def __init__(self, driver, index, hw_regs):
|
||||
self.driver = driver
|
||||
self.log = driver.log
|
||||
self.index = index
|
||||
self.hw_regs = hw_regs
|
||||
|
||||
self.rxq_log_size = (256).bit_length()-1
|
||||
self.rxq_size = 2**self.rxq_log_size
|
||||
self.rxq_mask = self.rxq_size-1
|
||||
self.rxq = None
|
||||
self.rxq_prod = 0
|
||||
self.rxq_cons = 0
|
||||
|
||||
self.rx_info = [None] * self.rxq_size
|
||||
|
||||
self.rxcq_log_size = (256).bit_length()-1
|
||||
self.rxcq_size = 2**self.rxcq_log_size
|
||||
self.rxcq_mask = self.rxcq_size-1
|
||||
self.rxcq = None
|
||||
self.rxcq_prod = 0
|
||||
self.rxcq_cons = 0
|
||||
|
||||
self.txq_log_size = (256).bit_length()-1
|
||||
self.txq_size = 2**self.txq_log_size
|
||||
self.txq_mask = self.txq_size-1
|
||||
self.txq = None
|
||||
self.txq_prod = 0
|
||||
self.txq_cons = 0
|
||||
|
||||
self.tx_info = [None] * self.txq_size
|
||||
|
||||
self.txcq_log_size = (256).bit_length()-1
|
||||
self.txcq_size = 2**self.txcq_log_size
|
||||
self.txcq_mask = self.txcq_size-1
|
||||
self.txcq = None
|
||||
self.txcq_prod = 0
|
||||
self.txcq_cons = 0
|
||||
|
||||
self.rx_queue = Queue()
|
||||
|
||||
async def init(self):
|
||||
|
||||
self.rxq = self.driver.pool.alloc_region(self.rxq_size*16)
|
||||
addr = self.rxq.get_absolute_address(0)
|
||||
await self.hw_regs.write_dword(0x0200, 0x00000000)
|
||||
await self.hw_regs.write_dword(0x0204, 0x00000000)
|
||||
await self.hw_regs.write_dword(0x0208, addr & 0xffffffff)
|
||||
await self.hw_regs.write_dword(0x020c, addr >> 32)
|
||||
await self.hw_regs.write_dword(0x0200, 0x00000001 | (self.rxq_log_size << 16))
|
||||
|
||||
self.rxcq = self.driver.pool.alloc_region(self.rxcq_size*16)
|
||||
addr = self.rxcq.get_absolute_address(0)
|
||||
await self.hw_regs.write_dword(0x0400, 0x00000000)
|
||||
await self.hw_regs.write_dword(0x0408, addr & 0xffffffff)
|
||||
await self.hw_regs.write_dword(0x040c, addr >> 32)
|
||||
await self.hw_regs.write_dword(0x0400, 0x00000001 | (self.rxcq_log_size << 16))
|
||||
|
||||
self.txq = self.driver.pool.alloc_region(self.txq_size*16)
|
||||
addr = self.txq.get_absolute_address(0)
|
||||
await self.hw_regs.write_dword(0x0100, 0x00000000)
|
||||
await self.hw_regs.write_dword(0x0104, 0x00000000)
|
||||
await self.hw_regs.write_dword(0x0108, addr & 0xffffffff)
|
||||
await self.hw_regs.write_dword(0x010c, addr >> 32)
|
||||
await self.hw_regs.write_dword(0x0100, 0x00000001 | (self.txq_log_size << 16))
|
||||
|
||||
self.txcq = self.driver.pool.alloc_region(self.txcq_size*16)
|
||||
addr = self.txcq.get_absolute_address(0)
|
||||
await self.hw_regs.write_dword(0x0300, 0x00000000)
|
||||
await self.hw_regs.write_dword(0x0308, addr & 0xffffffff)
|
||||
await self.hw_regs.write_dword(0x030c, addr >> 32)
|
||||
await self.hw_regs.write_dword(0x0300, 0x00000001 | (self.txcq_log_size << 16))
|
||||
|
||||
# wait for writes to complete
|
||||
await self.hw_regs.read_dword(0)
|
||||
|
||||
await self.refill_rx_buffers()
|
||||
|
||||
async def start_xmit(self, data):
|
||||
headroom = 10
|
||||
tx_buf = self.driver.alloc_pkt()
|
||||
await tx_buf.write(headroom, data)
|
||||
index = self.txq_prod & self.txq_mask
|
||||
ptr = tx_buf.get_absolute_address(0)
|
||||
struct.pack_into('<xxxxLQ', self.txq.mem, 16*index, len(data), ptr+headroom)
|
||||
self.tx_info[index] = tx_buf
|
||||
self.txq_prod += 1
|
||||
await self.hw_regs.write_dword(0x0104, self.txq_prod & 0xffff)
|
||||
|
||||
async def recv(self):
|
||||
return await self.rx_queue.get()
|
||||
|
||||
async def recv_nowait(self):
|
||||
return self.rx_queue.get_nowait()
|
||||
|
||||
def free_tx_desc(self, index):
|
||||
pkt = self.tx_info[index]
|
||||
self.driver.free_pkt(pkt)
|
||||
self.tx_info[index] = None
|
||||
|
||||
def free_tx_buf(self):
|
||||
while self.txq_cons != self.txq_prod:
|
||||
index = self.txq_cons & self.txq_mask
|
||||
self.free_tx_desc(index)
|
||||
self.txq_cons += 1
|
||||
|
||||
async def process_tx_cq(self):
|
||||
|
||||
cq_cons_ptr = self.txcq_cons
|
||||
cons_ptr = self.txq_cons
|
||||
|
||||
while True:
|
||||
cq_index = cq_cons_ptr & self.txcq_mask
|
||||
index = cons_ptr & self.txq_mask
|
||||
|
||||
cpl_data = struct.unpack_from("<LLLL", self.txcq.mem, cq_index*16)
|
||||
|
||||
self.log.info("TX CQ index %d data %s", cq_index, cpl_data)
|
||||
|
||||
if bool(cpl_data[-1] & 0x80000000) == bool(cq_cons_ptr & self.txcq_size):
|
||||
self.log.info("CQ empty")
|
||||
break
|
||||
|
||||
pkt = self.tx_info[index]
|
||||
|
||||
self.free_tx_desc(index)
|
||||
|
||||
cq_cons_ptr += 1
|
||||
cons_ptr += 1
|
||||
|
||||
self.txcq_cons = cq_cons_ptr
|
||||
self.txq_cons = cons_ptr
|
||||
|
||||
def free_rx_desc(self, index):
|
||||
pkt = self.rx_info[index]
|
||||
self.driver.free_pkt(pkt)
|
||||
self.rx_info[index] = None
|
||||
|
||||
def free_rx_buf(self):
|
||||
while self.rxq_cons != self.rxq_prod:
|
||||
index = self.rxq_cons & self.rxq_mask
|
||||
self.free_rx_desc(index)
|
||||
self.rxq_cons += 1
|
||||
|
||||
def prepare_rx_desc(self, index):
|
||||
pkt = self.driver.alloc_pkt()
|
||||
self.rx_info[index] = pkt
|
||||
|
||||
length = pkt.size
|
||||
ptr = pkt.get_absolute_address(0)
|
||||
|
||||
struct.pack_into('<xxxxLQ', self.rxq.mem, 16*index, length, ptr)
|
||||
|
||||
async def refill_rx_buffers(self):
|
||||
missing = self.rxq_size - (self.rxq_prod - self.rxq_cons)
|
||||
|
||||
if missing < 8:
|
||||
return
|
||||
|
||||
for k in range(missing):
|
||||
self.prepare_rx_desc(self.rxq_prod & self.rxq_mask)
|
||||
self.rxq_prod += 1
|
||||
|
||||
await self.hw_regs.write_dword(0x0204, self.rxq_prod & 0xffff)
|
||||
|
||||
async def process_rx_cq(self):
|
||||
|
||||
cq_cons_ptr = self.rxcq_cons
|
||||
cons_ptr = self.rxq_cons
|
||||
|
||||
while True:
|
||||
cq_index = cq_cons_ptr & self.rxcq_mask
|
||||
index = cons_ptr & self.rxq_mask
|
||||
|
||||
cpl_data = struct.unpack_from("<LLLL", self.rxcq.mem, cq_index*16)
|
||||
|
||||
self.log.info("RX CQ index %d data %s", cq_index, cpl_data)
|
||||
|
||||
if bool(cpl_data[-1] & 0x80000000) == bool(cq_cons_ptr & self.rxcq_size):
|
||||
self.log.info("CQ empty")
|
||||
break
|
||||
|
||||
pkt = self.rx_info[index]
|
||||
length = cpl_data[1]
|
||||
|
||||
data = pkt[:length]
|
||||
|
||||
self.log.info("Packet: %s", data)
|
||||
|
||||
self.rx_queue.put_nowait(data)
|
||||
|
||||
self.free_rx_desc(index)
|
||||
|
||||
cq_cons_ptr += 1
|
||||
cons_ptr += 1
|
||||
|
||||
self.rxcq_cons = cq_cons_ptr
|
||||
self.rxq_cons = cons_ptr
|
||||
|
||||
await self.refill_rx_buffers()
|
||||
|
||||
async def interrupt_handler(self):
|
||||
self.log.info("Interrupt")
|
||||
await self.process_rx_cq()
|
||||
await self.process_tx_cq()
|
||||
|
||||
|
||||
class Driver:
|
||||
def __init__(self):
|
||||
self.log = logging.getLogger("cocotb.cndm")
|
||||
|
||||
self.dev = None
|
||||
self.pool = None
|
||||
self.hw_regs = None
|
||||
|
||||
self.ports = []
|
||||
|
||||
self.free_packets = deque()
|
||||
self.allocated_packets = []
|
||||
|
||||
async def init_pcie_dev(self, dev):
|
||||
self.dev = dev
|
||||
self.pool = dev.rc.mem_pool
|
||||
|
||||
await dev.enable_device()
|
||||
await dev.set_master()
|
||||
await dev.alloc_irq_vectors(32, 32)
|
||||
|
||||
self.hw_regs = dev.bar_window[0]
|
||||
|
||||
await self.init_common()
|
||||
|
||||
async def init_common(self):
|
||||
self.port_count = await self.hw_regs.read_dword(0x0100)
|
||||
self.port_offset = await self.hw_regs.read_dword(0x0104)
|
||||
self.port_stride = await self.hw_regs.read_dword(0x0108)
|
||||
|
||||
self.log.info("Port count: %d", self.port_count)
|
||||
self.log.info("Port offset: 0x%x", self.port_offset)
|
||||
self.log.info("Port stride: 0x%x", self.port_stride)
|
||||
|
||||
for k in range(self.port_count):
|
||||
port = Port(self, k, self.hw_regs.create_window(self.port_offset + self.port_stride*k))
|
||||
await port.init()
|
||||
self.dev.request_irq(k, port.interrupt_handler)
|
||||
|
||||
self.ports.append(port)
|
||||
|
||||
def alloc_pkt(self):
|
||||
if self.free_packets:
|
||||
return self.free_packets.popleft()
|
||||
|
||||
pkt = self.pool.alloc_region(4096)
|
||||
self.allocated_packets.append(pkt)
|
||||
return pkt
|
||||
|
||||
def free_pkt(self, pkt):
|
||||
assert pkt is not None
|
||||
assert pkt in self.allocated_packets
|
||||
self.free_packets.append(pkt)
|
||||
59
src/cndm/tb/cndm_micro_pcie_us/Makefile
Normal file
59
src/cndm/tb/cndm_micro_pcie_us/Makefile
Normal file
@@ -0,0 +1,59 @@
|
||||
# SPDX-License-Identifier: CERN-OHL-S-2.0
|
||||
#
|
||||
# Copyright (c) 2020-2025 FPGA Ninja, LLC
|
||||
#
|
||||
# Authors:
|
||||
# - Alex Forencich
|
||||
|
||||
TOPLEVEL_LANG = verilog
|
||||
|
||||
SIM ?= verilator
|
||||
WAVES ?= 0
|
||||
|
||||
COCOTB_HDL_TIMEUNIT = 1ns
|
||||
COCOTB_HDL_TIMEPRECISION = 1ps
|
||||
|
||||
RTL_DIR = ../../rtl
|
||||
LIB_DIR = ../../lib
|
||||
TAXI_SRC_DIR = $(LIB_DIR)/taxi/src
|
||||
|
||||
DUT = cndm_micro_pcie_us
|
||||
COCOTB_TEST_MODULES = test_$(DUT)
|
||||
COCOTB_TOPLEVEL = test_$(DUT)
|
||||
MODULE = $(COCOTB_TEST_MODULES)
|
||||
TOPLEVEL = $(COCOTB_TOPLEVEL)
|
||||
VERILOG_SOURCES += $(COCOTB_TOPLEVEL).sv
|
||||
VERILOG_SOURCES += $(RTL_DIR)/$(DUT).f
|
||||
VERILOG_SOURCES += $(TAXI_SRC_DIR)/axis/rtl/taxi_axis_async_fifo.f
|
||||
VERILOG_SOURCES += $(TAXI_SRC_DIR)/sync/rtl/taxi_sync_reset.sv
|
||||
VERILOG_SOURCES += $(TAXI_SRC_DIR)/sync/rtl/taxi_sync_signal.sv
|
||||
|
||||
# handle file list files
|
||||
process_f_file = $(call process_f_files,$(addprefix $(dir $1),$(shell cat $1)))
|
||||
process_f_files = $(foreach f,$1,$(if $(filter %.f,$f),$(call process_f_file,$f),$f))
|
||||
uniq_base = $(if $1,$(call uniq_base,$(foreach f,$1,$(if $(filter-out $(notdir $(lastword $1)),$(notdir $f)),$f,))) $(lastword $1))
|
||||
VERILOG_SOURCES := $(call uniq_base,$(call process_f_files,$(VERILOG_SOURCES)))
|
||||
|
||||
# module parameters
|
||||
export PARAM_SIM := "1'b1"
|
||||
export PARAM_VENDOR := "\"XILINX\""
|
||||
export PARAM_FAMILY := "\"virtexuplus\""
|
||||
export PARAM_PORTS := 2
|
||||
export PARAM_MAC_DATA_W := 32
|
||||
export PARAM_AXIS_PCIE_DATA_W := 256
|
||||
export PARAM_BAR0_APERTURE := 24
|
||||
|
||||
ifeq ($(SIM), icarus)
|
||||
PLUSARGS += -fst
|
||||
|
||||
COMPILE_ARGS += $(foreach v,$(filter PARAM_%,$(.VARIABLES)),-P $(COCOTB_TOPLEVEL).$(subst PARAM_,,$(v))=$($(v)))
|
||||
else ifeq ($(SIM), verilator)
|
||||
COMPILE_ARGS += $(foreach v,$(filter PARAM_%,$(.VARIABLES)),-G$(subst PARAM_,,$(v))=$($(v)))
|
||||
|
||||
ifeq ($(WAVES), 1)
|
||||
COMPILE_ARGS += --trace-fst
|
||||
VERILATOR_TRACE = 1
|
||||
endif
|
||||
endif
|
||||
|
||||
include $(shell cocotb-config --makefiles)/Makefile.sim
|
||||
1
src/cndm/tb/cndm_micro_pcie_us/cndm.py
Symbolic link
1
src/cndm/tb/cndm_micro_pcie_us/cndm.py
Symbolic link
@@ -0,0 +1 @@
|
||||
../cndm.py
|
||||
520
src/cndm/tb/cndm_micro_pcie_us/test_cndm_micro_pcie_us.py
Normal file
520
src/cndm/tb/cndm_micro_pcie_us/test_cndm_micro_pcie_us.py
Normal file
@@ -0,0 +1,520 @@
|
||||
#!/usr/bin/env python
|
||||
# SPDX-License-Identifier: CERN-OHL-S-2.0
|
||||
"""
|
||||
|
||||
Copyright (c) 2020-2025 FPGA Ninja, LLC
|
||||
|
||||
Authors:
|
||||
- Alex Forencich
|
||||
|
||||
"""
|
||||
|
||||
import logging
|
||||
import os
|
||||
import sys
|
||||
|
||||
import pytest
|
||||
import cocotb_test.simulator
|
||||
|
||||
import cocotb
|
||||
from cocotb.clock import Clock
|
||||
from cocotb.triggers import RisingEdge, FallingEdge, Timer
|
||||
|
||||
from cocotbext.axi import AxiStreamBus
|
||||
from cocotbext.eth import EthMac
|
||||
from cocotbext.pcie.core import RootComplex
|
||||
from cocotbext.pcie.xilinx.us import UltraScalePlusPcieDevice
|
||||
|
||||
try:
|
||||
import cndm
|
||||
except ImportError:
|
||||
# attempt import from current directory
|
||||
sys.path.insert(0, os.path.join(os.path.dirname(__file__)))
|
||||
try:
|
||||
import cndm
|
||||
finally:
|
||||
del sys.path[0]
|
||||
|
||||
|
||||
class TB:
|
||||
def __init__(self, dut):
|
||||
self.dut = dut
|
||||
|
||||
self.log = logging.getLogger("cocotb.tb")
|
||||
self.log.setLevel(logging.DEBUG)
|
||||
|
||||
# PCIe
|
||||
self.rc = RootComplex()
|
||||
|
||||
self.rc.max_payload_size = 0x1 # 256 bytes
|
||||
self.rc.max_read_request_size = 0x2 # 512 bytes
|
||||
|
||||
self.dev = UltraScalePlusPcieDevice(
|
||||
# configuration options
|
||||
pcie_generation=3,
|
||||
pcie_link_width=8,
|
||||
user_clk_frequency=250e6,
|
||||
alignment="dword",
|
||||
cq_straddle=False,
|
||||
cc_straddle=False,
|
||||
rq_straddle=False,
|
||||
rc_straddle=False,
|
||||
rc_4tlp_straddle=False,
|
||||
pf_count=1,
|
||||
max_payload_size=1024,
|
||||
enable_client_tag=True,
|
||||
enable_extended_tag=True,
|
||||
enable_parity=False,
|
||||
enable_rx_msg_interface=False,
|
||||
enable_sriov=False,
|
||||
enable_extended_configuration=False,
|
||||
|
||||
pf0_msi_enable=True,
|
||||
pf0_msi_count=32,
|
||||
pf1_msi_enable=False,
|
||||
pf1_msi_count=1,
|
||||
pf2_msi_enable=False,
|
||||
pf2_msi_count=1,
|
||||
pf3_msi_enable=False,
|
||||
pf3_msi_count=1,
|
||||
pf0_msix_enable=False,
|
||||
pf0_msix_table_size=31,
|
||||
pf0_msix_table_bir=4,
|
||||
pf0_msix_table_offset=0x00000000,
|
||||
pf0_msix_pba_bir=4,
|
||||
pf0_msix_pba_offset=0x00008000,
|
||||
pf1_msix_enable=False,
|
||||
pf1_msix_table_size=0,
|
||||
pf1_msix_table_bir=0,
|
||||
pf1_msix_table_offset=0x00000000,
|
||||
pf1_msix_pba_bir=0,
|
||||
pf1_msix_pba_offset=0x00000000,
|
||||
pf2_msix_enable=False,
|
||||
pf2_msix_table_size=0,
|
||||
pf2_msix_table_bir=0,
|
||||
pf2_msix_table_offset=0x00000000,
|
||||
pf2_msix_pba_bir=0,
|
||||
pf2_msix_pba_offset=0x00000000,
|
||||
pf3_msix_enable=False,
|
||||
pf3_msix_table_size=0,
|
||||
pf3_msix_table_bir=0,
|
||||
pf3_msix_table_offset=0x00000000,
|
||||
pf3_msix_pba_bir=0,
|
||||
pf3_msix_pba_offset=0x00000000,
|
||||
|
||||
# signals
|
||||
# Clock and Reset Interface
|
||||
user_clk=dut.pcie_clk,
|
||||
user_reset=dut.pcie_rst,
|
||||
# user_lnk_up
|
||||
# sys_clk
|
||||
# sys_clk_gt
|
||||
# sys_reset
|
||||
# phy_rdy_out
|
||||
|
||||
# Requester reQuest Interface
|
||||
rq_bus=AxiStreamBus.from_entity(dut.m_axis_pcie_rq),
|
||||
pcie_rq_seq_num0=dut.pcie_rq_seq_num0,
|
||||
pcie_rq_seq_num_vld0=dut.pcie_rq_seq_num_vld0,
|
||||
pcie_rq_seq_num1=dut.pcie_rq_seq_num1,
|
||||
pcie_rq_seq_num_vld1=dut.pcie_rq_seq_num_vld1,
|
||||
# pcie_rq_tag0
|
||||
# pcie_rq_tag1
|
||||
# pcie_rq_tag_av
|
||||
# pcie_rq_tag_vld0
|
||||
# pcie_rq_tag_vld1
|
||||
|
||||
# Requester Completion Interface
|
||||
rc_bus=AxiStreamBus.from_entity(dut.s_axis_pcie_rc),
|
||||
|
||||
# Completer reQuest Interface
|
||||
cq_bus=AxiStreamBus.from_entity(dut.s_axis_pcie_cq),
|
||||
# pcie_cq_np_req
|
||||
# pcie_cq_np_req_count
|
||||
|
||||
# Completer Completion Interface
|
||||
cc_bus=AxiStreamBus.from_entity(dut.m_axis_pcie_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=dut.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=dut.cfg_interrupt_msix_enable,
|
||||
# cfg_interrupt_msix_mask=dut.cfg_interrupt_msix_mask,
|
||||
# cfg_interrupt_msix_vf_enable=dut.cfg_interrupt_msix_vf_enable,
|
||||
# cfg_interrupt_msix_vf_mask=dut.cfg_interrupt_msix_vf_mask,
|
||||
# cfg_interrupt_msix_address=dut.cfg_interrupt_msix_address,
|
||||
# cfg_interrupt_msix_data=dut.cfg_interrupt_msix_data,
|
||||
# cfg_interrupt_msix_int=dut.cfg_interrupt_msix_int,
|
||||
# cfg_interrupt_msix_vec_pending=dut.cfg_interrupt_msix_vec_pending,
|
||||
# cfg_interrupt_msix_vec_pending_status=dut.cfg_interrupt_msix_vec_pending_status,
|
||||
# cfg_interrupt_msix_sent=dut.cfg_interrupt_msix_sent,
|
||||
# cfg_interrupt_msix_fail=dut.cfg_interrupt_msix_fail,
|
||||
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].configure_bar(0, 2**int(dut.uut.axil_ctrl_bar.ADDR_W))
|
||||
|
||||
# Ethernet
|
||||
self.port_mac = []
|
||||
|
||||
eth_clock_period = 3.2
|
||||
eth_speed = 10e9
|
||||
|
||||
for k in range(len(dut.mac_axis_tx)):
|
||||
cocotb.start_soon(Clock(dut.mac_tx_clk[k], eth_clock_period, units="ns").start())
|
||||
cocotb.start_soon(Clock(dut.mac_rx_clk[k], eth_clock_period, units="ns").start())
|
||||
|
||||
dut.mac_tx_rst[k].setimmediatevalue(0)
|
||||
dut.mac_rx_rst[k].setimmediatevalue(0)
|
||||
|
||||
mac = EthMac(
|
||||
tx_clk=dut.mac_tx_clk[k],
|
||||
tx_rst=dut.mac_tx_rst[k],
|
||||
tx_bus=AxiStreamBus.from_entity(dut.mac_axis_tx[k]),
|
||||
rx_clk=dut.mac_rx_clk[k],
|
||||
rx_rst=dut.mac_rx_rst[k],
|
||||
rx_bus=AxiStreamBus.from_entity(dut.mac_axis_rx[k]),
|
||||
ifg=12, speed=eth_speed
|
||||
)
|
||||
self.port_mac.append(mac)
|
||||
|
||||
# cocotb.start_soon(Clock(dut.sfp_mgt_refclk_p, 6.4, units="ns").start())
|
||||
|
||||
# self.sfp_sources = []
|
||||
# self.sfp_sinks = []
|
||||
|
||||
# for ch in dut.uut.sfp_mac_inst.ch:
|
||||
# gt_inst = ch.ch_inst.gt.gt_inst
|
||||
|
||||
# if ch.ch_inst.DATA_W.value == 64:
|
||||
# if ch.ch_inst.CFG_LOW_LATENCY.value:
|
||||
# clk = 2.482
|
||||
# gbx_cfg = (66, [64, 65])
|
||||
# else:
|
||||
# clk = 2.56
|
||||
# gbx_cfg = None
|
||||
# else:
|
||||
# if ch.ch_inst.CFG_LOW_LATENCY.value:
|
||||
# clk = 3.102
|
||||
# gbx_cfg = (66, [64, 65])
|
||||
# else:
|
||||
# clk = 3.2
|
||||
# gbx_cfg = None
|
||||
|
||||
# cocotb.start_soon(Clock(gt_inst.tx_clk, clk, units="ns").start())
|
||||
# cocotb.start_soon(Clock(gt_inst.rx_clk, clk, units="ns").start())
|
||||
|
||||
# self.sfp_sources.append(BaseRSerdesSource(
|
||||
# data=gt_inst.serdes_rx_data,
|
||||
# data_valid=gt_inst.serdes_rx_data_valid,
|
||||
# hdr=gt_inst.serdes_rx_hdr,
|
||||
# hdr_valid=gt_inst.serdes_rx_hdr_valid,
|
||||
# clock=gt_inst.rx_clk,
|
||||
# slip=gt_inst.serdes_rx_bitslip,
|
||||
# reverse=True,
|
||||
# gbx_cfg=gbx_cfg
|
||||
# ))
|
||||
# self.sfp_sinks.append(BaseRSerdesSink(
|
||||
# data=gt_inst.serdes_tx_data,
|
||||
# data_valid=gt_inst.serdes_tx_data_valid,
|
||||
# hdr=gt_inst.serdes_tx_hdr,
|
||||
# hdr_valid=gt_inst.serdes_tx_hdr_valid,
|
||||
# gbx_sync=gt_inst.serdes_tx_gbx_sync,
|
||||
# clock=gt_inst.tx_clk,
|
||||
# reverse=True,
|
||||
# gbx_cfg=gbx_cfg
|
||||
# ))
|
||||
#
|
||||
self.loopback_enable = False
|
||||
cocotb.start_soon(self._run_loopback())
|
||||
|
||||
async def init(self):
|
||||
|
||||
for mac in self.port_mac:
|
||||
mac.rx.reset.setimmediatevalue(0)
|
||||
mac.tx.reset.setimmediatevalue(0)
|
||||
|
||||
await FallingEdge(self.dut.pcie_rst)
|
||||
await Timer(100, 'ns')
|
||||
|
||||
for k in range(10):
|
||||
await RisingEdge(self.dut.pcie_clk)
|
||||
|
||||
for mac in self.port_mac:
|
||||
mac.rx.reset.value = 1
|
||||
mac.tx.reset.value = 1
|
||||
|
||||
for k in range(10):
|
||||
await RisingEdge(self.dut.pcie_clk)
|
||||
|
||||
for mac in self.port_mac:
|
||||
mac.rx.reset.value = 0
|
||||
mac.tx.reset.value = 0
|
||||
|
||||
for k in range(10):
|
||||
await RisingEdge(self.dut.pcie_clk)
|
||||
|
||||
await self.rc.enumerate()
|
||||
|
||||
async def _run_loopback(self):
|
||||
while True:
|
||||
await RisingEdge(self.dut.pcie_clk)
|
||||
|
||||
if self.loopback_enable:
|
||||
for mac in self.port_mac:
|
||||
while not mac.tx.empty():
|
||||
await mac.rx.send(await mac.tx.recv())
|
||||
|
||||
@cocotb.test()
|
||||
async def run_test(dut):
|
||||
|
||||
tb = TB(dut)
|
||||
|
||||
await tb.init()
|
||||
|
||||
tb.log.info("Init driver model")
|
||||
driver = cndm.Driver()
|
||||
await driver.init_pcie_dev(tb.rc.find_device(tb.dev.functions[0].pcie_id))
|
||||
|
||||
tb.log.info("Init complete")
|
||||
|
||||
tb.log.info("Send and receive single packet on each port")
|
||||
|
||||
for k in range(len(driver.ports)):
|
||||
data = f"Corundum rocks on port {k}!".encode('ascii')
|
||||
|
||||
await driver.ports[k].start_xmit(data)
|
||||
|
||||
pkt = await tb.port_mac[k].tx.recv()
|
||||
tb.log.info("Got TX packet: %s", pkt)
|
||||
|
||||
assert bytes(pkt) == data
|
||||
|
||||
await tb.port_mac[k].rx.send(pkt)
|
||||
|
||||
pkt = await driver.ports[k].recv()
|
||||
tb.log.info("Got RX packet: %s", pkt)
|
||||
|
||||
assert bytes(pkt) == data
|
||||
|
||||
tb.log.info("Multiple small packets")
|
||||
|
||||
count = 64
|
||||
pkts = [bytearray([(x+k) % 256 for x in range(60)]) for k in range(count)]
|
||||
|
||||
tb.loopback_enable = True
|
||||
|
||||
for p in pkts:
|
||||
await driver.ports[0].start_xmit(p)
|
||||
|
||||
for k in range(count):
|
||||
pkt = await driver.ports[0].recv()
|
||||
|
||||
tb.log.info("Got RX packet: %s", pkt)
|
||||
|
||||
assert bytes(pkt) == pkts[k]
|
||||
|
||||
tb.loopback_enable = False
|
||||
|
||||
tb.log.info("Multiple large packets")
|
||||
|
||||
count = 64
|
||||
pkts = [bytearray([(x+k) % 256 for x in range(1514)]) for k in range(count)]
|
||||
|
||||
tb.loopback_enable = True
|
||||
|
||||
for p in pkts:
|
||||
await driver.ports[0].start_xmit(p)
|
||||
|
||||
for k in range(count):
|
||||
pkt = await driver.ports[0].recv()
|
||||
|
||||
tb.log.info("Got RX packet: %s", pkt)
|
||||
|
||||
assert bytes(pkt) == pkts[k]
|
||||
|
||||
tb.loopback_enable = False
|
||||
|
||||
await RisingEdge(dut.pcie_clk)
|
||||
await RisingEdge(dut.pcie_clk)
|
||||
|
||||
|
||||
# cocotb-test
|
||||
|
||||
tests_dir = os.path.abspath(os.path.dirname(__file__))
|
||||
rtl_dir = os.path.abspath(os.path.join(tests_dir, '..', '..', 'rtl'))
|
||||
lib_dir = os.path.abspath(os.path.join(tests_dir, '..', '..', 'lib'))
|
||||
taxi_src_dir = os.path.abspath(os.path.join(lib_dir, 'taxi', 'src'))
|
||||
|
||||
|
||||
def process_f_files(files):
|
||||
lst = {}
|
||||
for f in files:
|
||||
if f[-2:].lower() == '.f':
|
||||
with open(f, 'r') as fp:
|
||||
l = fp.read().split()
|
||||
for f in process_f_files([os.path.join(os.path.dirname(f), x) for x in l]):
|
||||
lst[os.path.basename(f)] = f
|
||||
else:
|
||||
lst[os.path.basename(f)] = f
|
||||
return list(lst.values())
|
||||
|
||||
|
||||
@pytest.mark.parametrize("mac_data_w", [32, 64])
|
||||
def test_cndm_micro_pcie_us(request, mac_data_w):
|
||||
dut = "cndm_micro_pcie_us"
|
||||
module = os.path.splitext(os.path.basename(__file__))[0]
|
||||
toplevel = module
|
||||
|
||||
verilog_sources = [
|
||||
os.path.join(tests_dir, f"{toplevel}.sv"),
|
||||
os.path.join(rtl_dir, f"{dut}.f"),
|
||||
os.path.join(taxi_src_dir, "axis", "rtl", "taxi_axis_async_fifo.f"),
|
||||
os.path.join(taxi_src_dir, "sync", "rtl", "taxi_sync_reset.sv"),
|
||||
os.path.join(taxi_src_dir, "sync", "rtl", "taxi_sync_signal.sv"),
|
||||
]
|
||||
|
||||
verilog_sources = process_f_files(verilog_sources)
|
||||
|
||||
parameters = {}
|
||||
|
||||
parameters['SIM'] = "1'b1"
|
||||
parameters['VENDOR'] = "\"XILINX\""
|
||||
parameters['FAMILY'] = "\"virtexuplus\""
|
||||
parameters['PORTS'] = 2
|
||||
parameters['MAC_DATA_W'] = mac_data_w
|
||||
parameters['AXIS_PCIE_DATA_W'] = 256
|
||||
parameters['BAR0_APERTURE'] = 24
|
||||
|
||||
extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()}
|
||||
|
||||
sim_build = os.path.join(tests_dir, "sim_build",
|
||||
request.node.name.replace('[', '-').replace(']', ''))
|
||||
|
||||
cocotb_test.simulator.run(
|
||||
simulator="verilator",
|
||||
python_search=[tests_dir],
|
||||
verilog_sources=verilog_sources,
|
||||
toplevel=toplevel,
|
||||
module=module,
|
||||
parameters=parameters,
|
||||
sim_build=sim_build,
|
||||
extra_env=extra_env,
|
||||
)
|
||||
228
src/cndm/tb/cndm_micro_pcie_us/test_cndm_micro_pcie_us.sv
Normal file
228
src/cndm/tb/cndm_micro_pcie_us/test_cndm_micro_pcie_us.sv
Normal file
@@ -0,0 +1,228 @@
|
||||
// SPDX-License-Identifier: CERN-OHL-S-2.0
|
||||
/*
|
||||
|
||||
Copyright (c) 2025 FPGA Ninja, LLC
|
||||
|
||||
Authors:
|
||||
- Alex Forencich
|
||||
|
||||
*/
|
||||
|
||||
`resetall
|
||||
`timescale 1ns / 1ps
|
||||
`default_nettype none
|
||||
|
||||
/*
|
||||
* FPGA core logic testbench
|
||||
*/
|
||||
module test_cndm_micro_pcie_us #
|
||||
(
|
||||
/* verilator lint_off WIDTHTRUNC */
|
||||
parameter logic SIM = 1'b0,
|
||||
parameter string VENDOR = "XILINX",
|
||||
parameter string FAMILY = "virtexuplus",
|
||||
parameter PORTS = 2,
|
||||
parameter MAC_DATA_W = 32,
|
||||
parameter AXIS_PCIE_DATA_W = 256,
|
||||
parameter AXIS_PCIE_RC_USER_W = AXIS_PCIE_DATA_W < 512 ? 75 : 161,
|
||||
parameter AXIS_PCIE_RQ_USER_W = AXIS_PCIE_DATA_W < 512 ? 62 : 137,
|
||||
parameter AXIS_PCIE_CQ_USER_W = AXIS_PCIE_DATA_W < 512 ? 85 : 183,
|
||||
parameter AXIS_PCIE_CC_USER_W = AXIS_PCIE_DATA_W < 512 ? 33 : 81,
|
||||
parameter BAR0_APERTURE = 24
|
||||
/* verilator lint_on WIDTHTRUNC */
|
||||
)
|
||||
();
|
||||
|
||||
localparam AXIS_PCIE_KEEP_W = (AXIS_PCIE_DATA_W/32);
|
||||
localparam RQ_SEQ_NUM_W = AXIS_PCIE_RQ_USER_W == 60 ? 4 : 6;
|
||||
|
||||
logic sfp_mgt_refclk_p;
|
||||
logic sfp_mgt_refclk_n;
|
||||
logic sfp_mgt_refclk_out;
|
||||
|
||||
logic [1:0] sfp_npres;
|
||||
logic [1:0] sfp_tx_fault;
|
||||
logic [1:0] sfp_los;
|
||||
|
||||
logic pcie_clk;
|
||||
logic pcie_rst;
|
||||
|
||||
taxi_axis_if #(
|
||||
.DATA_W(AXIS_PCIE_DATA_W),
|
||||
.KEEP_EN(1),
|
||||
.KEEP_W(AXIS_PCIE_KEEP_W),
|
||||
.USER_EN(1),
|
||||
.USER_W(AXIS_PCIE_CQ_USER_W)
|
||||
) s_axis_pcie_cq();
|
||||
|
||||
taxi_axis_if #(
|
||||
.DATA_W(AXIS_PCIE_DATA_W),
|
||||
.KEEP_EN(1),
|
||||
.KEEP_W(AXIS_PCIE_KEEP_W),
|
||||
.USER_EN(1),
|
||||
.USER_W(AXIS_PCIE_CC_USER_W)
|
||||
) m_axis_pcie_cc();
|
||||
|
||||
taxi_axis_if #(
|
||||
.DATA_W(AXIS_PCIE_DATA_W),
|
||||
.KEEP_EN(1),
|
||||
.KEEP_W(AXIS_PCIE_KEEP_W),
|
||||
.USER_EN(1),
|
||||
.USER_W(AXIS_PCIE_RQ_USER_W)
|
||||
) m_axis_pcie_rq();
|
||||
|
||||
taxi_axis_if #(
|
||||
.DATA_W(AXIS_PCIE_DATA_W),
|
||||
.KEEP_EN(1),
|
||||
.KEEP_W(AXIS_PCIE_KEEP_W),
|
||||
.USER_EN(1),
|
||||
.USER_W(AXIS_PCIE_RC_USER_W)
|
||||
) s_axis_pcie_rc();
|
||||
|
||||
logic [RQ_SEQ_NUM_W-1:0] pcie_rq_seq_num0;
|
||||
logic pcie_rq_seq_num_vld0;
|
||||
logic [RQ_SEQ_NUM_W-1:0] pcie_rq_seq_num1;
|
||||
logic pcie_rq_seq_num_vld1;
|
||||
|
||||
logic [2:0] cfg_max_payload;
|
||||
logic [2:0] cfg_max_read_req;
|
||||
logic [3:0] cfg_rcb_status;
|
||||
|
||||
logic [9:0] cfg_mgmt_addr;
|
||||
logic [7:0] cfg_mgmt_function_number;
|
||||
logic cfg_mgmt_write;
|
||||
logic [31:0] cfg_mgmt_write_data;
|
||||
logic [3:0] cfg_mgmt_byte_enable;
|
||||
logic cfg_mgmt_read;
|
||||
logic [31:0] cfg_mgmt_read_data;
|
||||
logic cfg_mgmt_read_write_done;
|
||||
|
||||
logic [7:0] cfg_fc_ph;
|
||||
logic [11:0] cfg_fc_pd;
|
||||
logic [7:0] cfg_fc_nph;
|
||||
logic [11:0] cfg_fc_npd;
|
||||
logic [7:0] cfg_fc_cplh;
|
||||
logic [11:0] cfg_fc_cpld;
|
||||
logic [2:0] cfg_fc_sel;
|
||||
|
||||
logic [3:0] cfg_interrupt_msi_enable;
|
||||
logic [11:0] cfg_interrupt_msi_mmenable;
|
||||
logic cfg_interrupt_msi_mask_update;
|
||||
logic [31:0] cfg_interrupt_msi_data;
|
||||
logic [1:0] cfg_interrupt_msi_select;
|
||||
logic [31:0] cfg_interrupt_msi_int;
|
||||
logic [31:0] cfg_interrupt_msi_pending_status;
|
||||
logic cfg_interrupt_msi_pending_status_data_enable;
|
||||
logic [1:0] cfg_interrupt_msi_pending_status_function_num;
|
||||
logic cfg_interrupt_msi_sent;
|
||||
logic cfg_interrupt_msi_fail;
|
||||
logic [2:0] cfg_interrupt_msi_attr;
|
||||
logic cfg_interrupt_msi_tph_present;
|
||||
logic [1:0] cfg_interrupt_msi_tph_type;
|
||||
logic [7:0] cfg_interrupt_msi_tph_st_tag;
|
||||
logic [7:0] cfg_interrupt_msi_function_number;
|
||||
|
||||
logic mac_tx_clk[PORTS];
|
||||
logic mac_tx_rst[PORTS];
|
||||
|
||||
taxi_axis_if #(
|
||||
.DATA_W(MAC_DATA_W),
|
||||
.ID_W(8),
|
||||
.USER_EN(1),
|
||||
.USER_W(1)
|
||||
) mac_axis_tx[PORTS]();
|
||||
|
||||
logic mac_rx_clk[PORTS];
|
||||
logic mac_rx_rst[PORTS];
|
||||
|
||||
taxi_axis_if #(
|
||||
.DATA_W(96),
|
||||
.KEEP_W(1),
|
||||
.ID_W(8)
|
||||
) mac_axis_tx_cpl[PORTS]();
|
||||
|
||||
taxi_axis_if #(
|
||||
.DATA_W(MAC_DATA_W),
|
||||
.ID_W(8),
|
||||
.USER_EN(1),
|
||||
.USER_W(1)
|
||||
) mac_axis_rx[PORTS]();
|
||||
|
||||
cndm_micro_pcie_us #(
|
||||
.SIM(SIM),
|
||||
.VENDOR(VENDOR),
|
||||
.FAMILY(FAMILY),
|
||||
.PORTS(PORTS),
|
||||
.RQ_SEQ_NUM_W(RQ_SEQ_NUM_W),
|
||||
.BAR0_APERTURE(BAR0_APERTURE)
|
||||
)
|
||||
uut (
|
||||
/*
|
||||
* PCIe
|
||||
*/
|
||||
.pcie_clk(pcie_clk),
|
||||
.pcie_rst(pcie_rst),
|
||||
.s_axis_pcie_cq(s_axis_pcie_cq),
|
||||
.m_axis_pcie_cc(m_axis_pcie_cc),
|
||||
.m_axis_pcie_rq(m_axis_pcie_rq),
|
||||
.s_axis_pcie_rc(s_axis_pcie_rc),
|
||||
|
||||
.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),
|
||||
|
||||
.cfg_max_payload(cfg_max_payload),
|
||||
.cfg_max_read_req(cfg_max_read_req),
|
||||
.cfg_rcb_status(cfg_rcb_status),
|
||||
|
||||
.cfg_mgmt_addr(cfg_mgmt_addr),
|
||||
.cfg_mgmt_function_number(cfg_mgmt_function_number),
|
||||
.cfg_mgmt_write(cfg_mgmt_write),
|
||||
.cfg_mgmt_write_data(cfg_mgmt_write_data),
|
||||
.cfg_mgmt_byte_enable(cfg_mgmt_byte_enable),
|
||||
.cfg_mgmt_read(cfg_mgmt_read),
|
||||
.cfg_mgmt_read_data(cfg_mgmt_read_data),
|
||||
.cfg_mgmt_read_write_done(cfg_mgmt_read_write_done),
|
||||
|
||||
.cfg_fc_ph(cfg_fc_ph),
|
||||
.cfg_fc_pd(cfg_fc_pd),
|
||||
.cfg_fc_nph(cfg_fc_nph),
|
||||
.cfg_fc_npd(cfg_fc_npd),
|
||||
.cfg_fc_cplh(cfg_fc_cplh),
|
||||
.cfg_fc_cpld(cfg_fc_cpld),
|
||||
.cfg_fc_sel(cfg_fc_sel),
|
||||
|
||||
.cfg_interrupt_msi_enable(cfg_interrupt_msi_enable),
|
||||
.cfg_interrupt_msi_mmenable(cfg_interrupt_msi_mmenable),
|
||||
.cfg_interrupt_msi_mask_update(cfg_interrupt_msi_mask_update),
|
||||
.cfg_interrupt_msi_data(cfg_interrupt_msi_data),
|
||||
.cfg_interrupt_msi_select(cfg_interrupt_msi_select),
|
||||
.cfg_interrupt_msi_int(cfg_interrupt_msi_int),
|
||||
.cfg_interrupt_msi_pending_status(cfg_interrupt_msi_pending_status),
|
||||
.cfg_interrupt_msi_pending_status_data_enable(cfg_interrupt_msi_pending_status_data_enable),
|
||||
.cfg_interrupt_msi_pending_status_function_num(cfg_interrupt_msi_pending_status_function_num),
|
||||
.cfg_interrupt_msi_sent(cfg_interrupt_msi_sent),
|
||||
.cfg_interrupt_msi_fail(cfg_interrupt_msi_fail),
|
||||
.cfg_interrupt_msi_attr(cfg_interrupt_msi_attr),
|
||||
.cfg_interrupt_msi_tph_present(cfg_interrupt_msi_tph_present),
|
||||
.cfg_interrupt_msi_tph_type(cfg_interrupt_msi_tph_type),
|
||||
.cfg_interrupt_msi_tph_st_tag(cfg_interrupt_msi_tph_st_tag),
|
||||
.cfg_interrupt_msi_function_number(cfg_interrupt_msi_function_number),
|
||||
|
||||
/*
|
||||
* Ethernet: SFP+
|
||||
*/
|
||||
.mac_tx_clk(mac_tx_clk),
|
||||
.mac_tx_rst(mac_tx_rst),
|
||||
.mac_axis_tx(mac_axis_tx),
|
||||
.mac_axis_tx_cpl(mac_axis_tx_cpl),
|
||||
|
||||
.mac_rx_clk(mac_rx_clk),
|
||||
.mac_rx_rst(mac_rx_rst),
|
||||
.mac_axis_rx(mac_axis_rx)
|
||||
);
|
||||
|
||||
endmodule
|
||||
|
||||
`resetall
|
||||
Reference in New Issue
Block a user