tests: add axis loopback test
This commit is contained in:
23
axi/tb/axis_cocotb_loopback_test/Makefile
Normal file
23
axi/tb/axis_cocotb_loopback_test/Makefile
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
TOPLEVEL_LANG = verilog
|
||||||
|
SIM ?= verilator
|
||||||
|
|
||||||
|
PWD := $(shell pwd)
|
||||||
|
RTL_DIR ?= $(PWD)/../../rtl
|
||||||
|
TB_DIR ?= $(PWD)
|
||||||
|
|
||||||
|
TOPLEVEL = tb_axis_loopback
|
||||||
|
MODULE = test_axis_loopback
|
||||||
|
|
||||||
|
VERILOG_SOURCES += $(RTL_DIR)/axis_if.sv
|
||||||
|
VERILOG_SOURCES += $(RTL_DIR)/axis_flat_to_if.sv
|
||||||
|
VERILOG_SOURCES += $(RTL_DIR)/axis_if_to_flat.sv
|
||||||
|
VERILOG_SOURCES += $(RTL_DIR)/axis_desc_flat_to_if.sv
|
||||||
|
VERILOG_SOURCES += $(RTL_DIR)/axis_desc_if_to_flat.sv
|
||||||
|
VERILOG_SOURCES += $(TB_DIR)/axis_loopback.sv
|
||||||
|
VERILOG_SOURCES += $(TB_DIR)/tb_axis_loopback.sv
|
||||||
|
|
||||||
|
COMPILE_ARGS += -I$(RTL_DIR)
|
||||||
|
EXTRA_ARGS += --trace
|
||||||
|
EXTRA_ARGS += --trace-structs
|
||||||
|
|
||||||
|
include $(shell cocotb-config --makefiles)/Makefile.sim
|
||||||
126
axi/tb/axis_cocotb_loopback_test/test_axis_loopback.py
Normal file
126
axi/tb/axis_cocotb_loopback_test/test_axis_loopback.py
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
import random
|
||||||
|
|
||||||
|
import cocotb
|
||||||
|
from cocotb.clock import Clock
|
||||||
|
from cocotb.triggers import RisingEdge, Timer, with_timeout
|
||||||
|
|
||||||
|
|
||||||
|
CLK_PERIOD_NS = 10
|
||||||
|
|
||||||
|
|
||||||
|
async def reset_dut(dut):
|
||||||
|
dut.rst.value = 1
|
||||||
|
|
||||||
|
dut.s_axis_tdata.value = 0
|
||||||
|
dut.s_axis_tkeep.value = 0
|
||||||
|
dut.s_axis_tstrb.value = 0
|
||||||
|
dut.s_axis_tlast.value = 0
|
||||||
|
dut.s_axis_tid.value = 0
|
||||||
|
dut.s_axis_tdest.value = 0
|
||||||
|
dut.s_axis_tuser.value = 0
|
||||||
|
dut.s_axis_tvalid.value = 0
|
||||||
|
dut.m_axis_tready.value = 0
|
||||||
|
|
||||||
|
for _ in range(5):
|
||||||
|
await RisingEdge(dut.clk)
|
||||||
|
|
||||||
|
dut.rst.value = 0
|
||||||
|
|
||||||
|
for _ in range(2):
|
||||||
|
await RisingEdge(dut.clk)
|
||||||
|
|
||||||
|
|
||||||
|
async def send_axis_beat(dut, beat):
|
||||||
|
dut.s_axis_tdata.value = beat["data"]
|
||||||
|
dut.s_axis_tkeep.value = beat["keep"]
|
||||||
|
dut.s_axis_tstrb.value = beat["strb"]
|
||||||
|
dut.s_axis_tlast.value = beat["last"]
|
||||||
|
dut.s_axis_tid.value = beat["id"]
|
||||||
|
dut.s_axis_tdest.value = beat["dest"]
|
||||||
|
dut.s_axis_tuser.value = beat["user"]
|
||||||
|
dut.s_axis_tvalid.value = 1
|
||||||
|
|
||||||
|
while True:
|
||||||
|
await RisingEdge(dut.clk)
|
||||||
|
if int(dut.s_axis_tready.value):
|
||||||
|
break
|
||||||
|
|
||||||
|
dut.s_axis_tvalid.value = 0
|
||||||
|
|
||||||
|
|
||||||
|
async def recv_axis_beats(dut, count, ready_pattern=None):
|
||||||
|
beats = []
|
||||||
|
cycle = 0
|
||||||
|
|
||||||
|
while len(beats) < count:
|
||||||
|
ready = 1
|
||||||
|
if ready_pattern is not None:
|
||||||
|
ready = ready_pattern[cycle % len(ready_pattern)]
|
||||||
|
dut.m_axis_tready.value = ready
|
||||||
|
|
||||||
|
await RisingEdge(dut.clk)
|
||||||
|
|
||||||
|
if ready and int(dut.m_axis_tvalid.value):
|
||||||
|
beats.append({
|
||||||
|
"data": int(dut.m_axis_tdata.value),
|
||||||
|
"keep": int(dut.m_axis_tkeep.value),
|
||||||
|
"strb": int(dut.m_axis_tstrb.value),
|
||||||
|
"last": int(dut.m_axis_tlast.value),
|
||||||
|
"id": int(dut.m_axis_tid.value),
|
||||||
|
"dest": int(dut.m_axis_tdest.value),
|
||||||
|
"user": int(dut.m_axis_tuser.value),
|
||||||
|
})
|
||||||
|
|
||||||
|
cycle += 1
|
||||||
|
|
||||||
|
dut.m_axis_tready.value = 0
|
||||||
|
return beats
|
||||||
|
|
||||||
|
|
||||||
|
@cocotb.test()
|
||||||
|
async def test_axis_loopback_basic(dut):
|
||||||
|
cocotb.start_soon(Clock(dut.clk, CLK_PERIOD_NS, units="ns").start())
|
||||||
|
await reset_dut(dut)
|
||||||
|
|
||||||
|
tx = [
|
||||||
|
{"data": 0x1122334455667788, "keep": 0xFF, "strb": 0xFF,
|
||||||
|
"last": 0, "id": 1, "dest": 2, "user": 3},
|
||||||
|
{"data": 0xAABBCCDDEEFF0011, "keep": 0xFF, "strb": 0xFF,
|
||||||
|
"last": 1, "id": 1, "dest": 2, "user": 4},
|
||||||
|
]
|
||||||
|
|
||||||
|
rx_task = cocotb.start_soon(recv_axis_beats(dut, len(tx)))
|
||||||
|
|
||||||
|
for beat in tx:
|
||||||
|
await send_axis_beat(dut, beat)
|
||||||
|
|
||||||
|
rx = await with_timeout(rx_task, 1, "us")
|
||||||
|
assert rx == tx
|
||||||
|
|
||||||
|
|
||||||
|
@cocotb.test()
|
||||||
|
async def test_axis_loopback_with_backpressure(dut):
|
||||||
|
cocotb.start_soon(Clock(dut.clk, CLK_PERIOD_NS, units="ns").start())
|
||||||
|
await reset_dut(dut)
|
||||||
|
|
||||||
|
random.seed(1)
|
||||||
|
tx = []
|
||||||
|
for i in range(16):
|
||||||
|
tx.append({
|
||||||
|
"data": random.getrandbits(64),
|
||||||
|
"keep": 0xFF,
|
||||||
|
"strb": 0xFF,
|
||||||
|
"last": int(i == 15),
|
||||||
|
"id": i & 0xFF,
|
||||||
|
"dest": (i + 1) & 0xFF,
|
||||||
|
"user": (i + 2) & 0xFF,
|
||||||
|
})
|
||||||
|
|
||||||
|
rx_task = cocotb.start_soon(recv_axis_beats(
|
||||||
|
dut, len(tx), ready_pattern=[1, 0, 1, 1, 0]))
|
||||||
|
|
||||||
|
for beat in tx:
|
||||||
|
await send_axis_beat(dut, beat)
|
||||||
|
|
||||||
|
rx = await with_timeout(rx_task, 5, "us")
|
||||||
|
assert rx == tx
|
||||||
Reference in New Issue
Block a user