example/KR260: Add support for 10GBASE-R on KR260

Signed-off-by: Alex Forencich <alex@alexforencich.com>
This commit is contained in:
Alex Forencich
2025-02-22 23:01:52 -08:00
parent db8b1fc27e
commit 4a439783f1
10 changed files with 633 additions and 144 deletions

View File

@@ -20,6 +20,7 @@ MODULE = $(COCOTB_TEST_MODULES)
TOPLEVEL = $(COCOTB_TOPLEVEL)
VERILOG_SOURCES += ../../rtl/$(DUT).sv
VERILOG_SOURCES += ../../lib/taxi/rtl/eth/taxi_eth_mac_1g_fifo.f
VERILOG_SOURCES += ../../lib/taxi/rtl/eth/us/taxi_eth_mac_25g_us.f
VERILOG_SOURCES += ../../lib/taxi/rtl/eth/taxi_eth_mac_1g_rgmii_fifo.f
VERILOG_SOURCES += ../../lib/taxi/rtl/sync/taxi_sync_reset.sv
VERILOG_SOURCES += ../../lib/taxi/rtl/sync/taxi_sync_signal.sv
@@ -35,6 +36,7 @@ export PARAM_SIM := "1'b1"
export PARAM_VENDOR := "\"XILINX\""
export PARAM_FAMILY := "\"zynquplus\""
export PARAM_USE_CLK90 := "1'b1"
export PARAM_SFP_RATE := "1'b1"
ifeq ($(SIM), icarus)
PLUSARGS += -fst

View File

@@ -0,0 +1 @@
../../lib/taxi/tb/eth/baser.py

View File

@@ -11,7 +11,9 @@ Authors:
import logging
import os
import sys
import pytest
import cocotb_test.simulator
import cocotb
@@ -20,6 +22,17 @@ from cocotb.clock import Clock
from cocotb.triggers import RisingEdge, Timer, Combine
from cocotbext.eth import GmiiFrame, GmiiSource, GmiiSink, RgmiiPhy
from cocotbext.eth import XgmiiFrame
try:
from baser import BaseRSerdesSource, BaseRSerdesSink
except ImportError:
# attempt import from current directory
sys.path.insert(0, os.path.join(os.path.dirname(__file__)))
try:
from baser import BaseRSerdesSource, BaseRSerdesSink
finally:
del sys.path[0]
class TB:
@@ -29,18 +42,29 @@ class TB:
self.log = SimLog("cocotb.tb")
self.log.setLevel(logging.DEBUG)
cocotb.start_soon(Clock(dut.sfp_gmii_clk, 8, units="ns").start())
self.baset_phy2 = RgmiiPhy(dut.phy2_rgmii_txd, dut.phy2_rgmii_tx_ctl, dut.phy2_rgmii_tx_clk,
dut.phy2_rgmii_rxd, dut.phy2_rgmii_rx_ctl, dut.phy2_rgmii_rx_clk, speed=speed)
self.baset_phy3 = RgmiiPhy(dut.phy3_rgmii_txd, dut.phy3_rgmii_tx_ctl, dut.phy3_rgmii_tx_clk,
dut.phy3_rgmii_rxd, dut.phy3_rgmii_rx_ctl, dut.phy3_rgmii_rx_clk, speed=speed)
self.sfp_source = GmiiSource(dut.sfp_gmii_rxd, dut.sfp_gmii_rx_er, dut.sfp_gmii_rx_dv,
dut.sfp_gmii_clk, dut.sfp_gmii_rst, dut.sfp_gmii_clk_en)
self.sfp_sink = GmiiSink(dut.sfp_gmii_txd, dut.sfp_gmii_tx_er, dut.sfp_gmii_tx_en,
dut.sfp_gmii_clk, dut.sfp_gmii_rst, dut.sfp_gmii_clk_en)
if dut.SFP_RATE.value == 0:
cocotb.start_soon(Clock(dut.sfp_gmii_clk, 8, units="ns").start())
self.sfp_source = GmiiSource(dut.sfp_gmii_rxd, dut.sfp_gmii_rx_er, dut.sfp_gmii_rx_dv,
dut.sfp_gmii_clk, dut.sfp_gmii_rst, dut.sfp_gmii_clk_en)
self.sfp_sink = GmiiSink(dut.sfp_gmii_txd, dut.sfp_gmii_tx_er, dut.sfp_gmii_tx_en,
dut.sfp_gmii_clk, dut.sfp_gmii_rst, dut.sfp_gmii_clk_en)
else:
cocotb.start_soon(Clock(dut.sfp_mgt_refclk_p, 6.4, units="ns").start())
ch = dut.sfp_mac.sfp_mac_inst.ch[0]
cocotb.start_soon(Clock(ch.ch_inst.tx_clk, 6.4, units="ns").start())
cocotb.start_soon(Clock(ch.ch_inst.rx_clk, 6.4, units="ns").start())
self.sfp_source = BaseRSerdesSource(ch.ch_inst.serdes_rx_data, ch.ch_inst.serdes_rx_hdr, ch.ch_inst.rx_clk, slip=ch.ch_inst.serdes_rx_bitslip, reverse=True)
self.sfp_sink = BaseRSerdesSink(ch.ch_inst.serdes_tx_data, ch.ch_inst.serdes_tx_hdr, ch.ch_inst.tx_clk, reverse=True)
cocotb.start_soon(self._run_clk())
@@ -61,6 +85,9 @@ class TB:
self.dut.rst.value = 0
self.dut.sfp_gmii_rst.value = 0
for k in range(10):
await RisingEdge(self.dut.clk)
async def _run_clk(self):
t = Timer(2, 'ns')
while True:
@@ -116,6 +143,46 @@ async def mac_test(tb, source, sink):
tb.log.info("MAC test done")
async def mac_test_25g(tb, source, sink):
tb.log.info("Test MAC")
tb.log.info("Multiple small packets")
count = 64
pkts = [bytearray([(x+k) % 256 for x in range(60)]) for k in range(count)]
for p in pkts:
await source.send(XgmiiFrame.from_payload(p))
for k in range(count):
rx_frame = await sink.recv()
tb.log.info("RX frame: %s", rx_frame)
assert rx_frame.get_payload() == pkts[k]
assert rx_frame.check_fcs()
tb.log.info("Multiple large packets")
count = 32
pkts = [bytearray([(x+k) % 256 for x in range(1514)]) for k in range(count)]
for p in pkts:
await source.send(XgmiiFrame.from_payload(p))
for k in range(count):
rx_frame = await sink.recv()
tb.log.info("RX frame: %s", rx_frame)
assert rx_frame.get_payload() == pkts[k]
assert rx_frame.check_fcs()
tb.log.info("MAC test done")
@cocotb.test()
async def run_test(dut):
@@ -123,19 +190,24 @@ async def run_test(dut):
await tb.init()
tests = []
tb.log.info("Start BASE-T MAC loopback test on PHY2")
phy2_test_cr = cocotb.start_soon(mac_test(tb, tb.baset_phy2.rx, tb.baset_phy2.tx))
tests.append(cocotb.start_soon(mac_test(tb, tb.baset_phy2.rx, tb.baset_phy2.tx)))
tb.log.info("Start BASE-T MAC loopback test on PHY3")
phy3_test_cr = cocotb.start_soon(mac_test(tb, tb.baset_phy3.rx, tb.baset_phy3.tx))
tests.append(cocotb.start_soon(mac_test(tb, tb.baset_phy3.rx, tb.baset_phy3.tx)))
tb.log.info("Start SFP MAC loopback test")
if dut.SFP_RATE.value == 0:
tb.log.info("Start 1G SFP MAC loopback test")
tests.append(cocotb.start_soon(mac_test(tb, tb.sfp_source, tb.sfp_sink)))
else:
tb.log.info("Start 10G SFP MAC loopback test")
tests.append(cocotb.start_soon(mac_test_25g(tb, tb.sfp_source, tb.sfp_sink)))
sfp_test_cr = cocotb.start_soon(mac_test(tb, tb.sfp_source, tb.sfp_sink))
await Combine(phy2_test_cr, phy3_test_cr, sfp_test_cr)
await Combine(*tests)
await RisingEdge(dut.clk)
await RisingEdge(dut.clk)
@@ -161,7 +233,8 @@ def process_f_files(files):
return list(lst.values())
def test_fpga_core(request):
@pytest.mark.parametrize("sfp_rate", [0, 1])
def test_fpga_core(request, sfp_rate):
dut = "fpga_core"
module = os.path.splitext(os.path.basename(__file__))[0]
toplevel = dut
@@ -169,6 +242,7 @@ def test_fpga_core(request):
verilog_sources = [
os.path.join(rtl_dir, f"{dut}.sv"),
os.path.join(lib_dir, "taxi", "rtl", "eth", "taxi_eth_mac_1g_fifo.f"),
os.path.join(lib_dir, "taxi", "rtl", "eth", "us", "taxi_eth_mac_25g_us.f"),
os.path.join(lib_dir, "taxi", "rtl", "eth", "taxi_eth_mac_1g_rgmii_fifo.f"),
os.path.join(lib_dir, "taxi", "rtl", "sync", "taxi_sync_reset.sv"),
os.path.join(lib_dir, "taxi", "rtl", "sync", "taxi_sync_signal.sv"),
@@ -182,6 +256,7 @@ def test_fpga_core(request):
parameters['VENDOR'] = "\"XILINX\""
parameters['FAMILY'] = "\"zynquplus\""
parameters['USE_CLK90'] = "1'b1"
parameters['SFP_RATE'] = f"1'b{sfp_rate}"
extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()}