From e7dddc0dfd59cb47924c3d016528e5a7aefe7650 Mon Sep 17 00:00:00 2001 From: Alex Forencich Date: Fri, 15 Oct 2021 01:08:14 -0700 Subject: [PATCH] Add cocotb testbenches for AXI stream BASE-R TX and RX modules --- tb/axis_baser_rx_64/Makefile | 85 +++++++ tb/axis_baser_rx_64/baser.py | 1 + tb/axis_baser_rx_64/test_axis_baser_rx_64.py | 165 +++++++++++++ tb/axis_baser_tx_64/Makefile | 100 ++++++++ tb/axis_baser_tx_64/baser.py | 1 + tb/axis_baser_tx_64/test_axis_baser_tx_64.py | 245 +++++++++++++++++++ 6 files changed, 597 insertions(+) create mode 100644 tb/axis_baser_rx_64/Makefile create mode 120000 tb/axis_baser_rx_64/baser.py create mode 100644 tb/axis_baser_rx_64/test_axis_baser_rx_64.py create mode 100644 tb/axis_baser_tx_64/Makefile create mode 120000 tb/axis_baser_tx_64/baser.py create mode 100644 tb/axis_baser_tx_64/test_axis_baser_tx_64.py diff --git a/tb/axis_baser_rx_64/Makefile b/tb/axis_baser_rx_64/Makefile new file mode 100644 index 000000000..0bd40bd36 --- /dev/null +++ b/tb/axis_baser_rx_64/Makefile @@ -0,0 +1,85 @@ +# Copyright (c) 2021 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 = axis_baser_rx_64 +TOPLEVEL = $(DUT) +MODULE = test_$(DUT) +VERILOG_SOURCES += ../../rtl/$(DUT).v +VERILOG_SOURCES += ../../rtl/lfsr.v + +# module parameters +export PARAM_DATA_WIDTH ?= 64 +export PARAM_KEEP_WIDTH ?= $(shell expr $(PARAM_DATA_WIDTH) / 8 ) +export PARAM_HDR_WIDTH ?= 2 +export PARAM_PTP_TS_ENABLE ?= 0 +export PARAM_PTP_TS_WIDTH ?= 96 +#export PARAM_USER_WIDTH ?= (parameters['PTP_TS_WIDTH'] if parameters['PTP_TS_ENABLE'] else 0) + 1 +export PARAM_USER_WIDTH ?= 1 + +ifeq ($(SIM), icarus) + PLUSARGS += -fst + + COMPILE_ARGS += -P $(TOPLEVEL).DATA_WIDTH=$(PARAM_DATA_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).KEEP_WIDTH=$(PARAM_KEEP_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).HDR_WIDTH=$(PARAM_HDR_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).PTP_TS_ENABLE=$(PARAM_PTP_TS_ENABLE) + COMPILE_ARGS += -P $(TOPLEVEL).PTP_TS_WIDTH=$(PARAM_PTP_TS_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).USER_WIDTH=$(PARAM_USER_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 += -GDATA_WIDTH=$(PARAM_DATA_WIDTH) + COMPILE_ARGS += -GKEEP_WIDTH=$(PARAM_KEEP_WIDTH) + COMPILE_ARGS += -GHDR_WIDTH=$(PARAM_HDR_WIDTH) + COMPILE_ARGS += -GPTP_TS_ENABLE=$(PARAM_PTP_TS_ENABLE) + COMPILE_ARGS += -GPTP_TS_WIDTH=$(PARAM_PTP_TS_WIDTH) + COMPILE_ARGS += -GUSER_WIDTH=$(PARAM_USER_WIDTH) + + ifeq ($(WAVES), 1) + COMPILE_ARGS += --trace-fst + endif +endif + +include $(shell cocotb-config --makefiles)/Makefile.sim + +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 iverilog_dump.v + @rm -rf dump.fst $(TOPLEVEL).fst diff --git a/tb/axis_baser_rx_64/baser.py b/tb/axis_baser_rx_64/baser.py new file mode 120000 index 000000000..33a23687c --- /dev/null +++ b/tb/axis_baser_rx_64/baser.py @@ -0,0 +1 @@ +../baser.py \ No newline at end of file diff --git a/tb/axis_baser_rx_64/test_axis_baser_rx_64.py b/tb/axis_baser_rx_64/test_axis_baser_rx_64.py new file mode 100644 index 000000000..0fb3c249c --- /dev/null +++ b/tb/axis_baser_rx_64/test_axis_baser_rx_64.py @@ -0,0 +1,165 @@ +#!/usr/bin/env python +""" + +Copyright (c) 2021 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 itertools +import logging +import os +import sys + +import cocotb_test.simulator + +import cocotb +from cocotb.clock import Clock +from cocotb.triggers import RisingEdge +from cocotb.regression import TestFactory + +from cocotbext.eth import XgmiiFrame +from cocotbext.axi import AxiStreamBus, AxiStreamSink + +try: + from baser import BaseRSerdesSource +except ImportError: + # attempt import from current directory + sys.path.insert(0, os.path.join(os.path.dirname(__file__))) + try: + from baser import BaseRSerdesSource + 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) + + cocotb.fork(Clock(dut.clk, 6.4, units="ns").start()) + + self.source = BaseRSerdesSource(dut.encoded_rx_data, dut.encoded_rx_hdr, dut.clk, scramble=False) + self.sink = AxiStreamSink(AxiStreamBus.from_prefix(dut, "m_axis"), dut.clk, dut.rst) + + dut.ptp_ts.setimmediatevalue(0) + + async def reset(self): + self.dut.rst.setimmediatevalue(0) + await RisingEdge(self.dut.clk) + await RisingEdge(self.dut.clk) + self.dut.rst <= 1 + await RisingEdge(self.dut.clk) + await RisingEdge(self.dut.clk) + self.dut.rst <= 0 + await RisingEdge(self.dut.clk) + await RisingEdge(self.dut.clk) + + +async def run_test(dut, payload_lengths=None, payload_data=None, ifg=12): + + tb = TB(dut) + + tb.source.ifg = ifg + + await tb.reset() + + test_frames = [payload_data(x) for x in payload_lengths()] + + for test_data in test_frames: + test_frame = XgmiiFrame.from_payload(test_data) + await tb.source.send(test_frame) + + for test_data in test_frames: + rx_frame = await tb.sink.recv() + + assert rx_frame.tdata == test_data + assert rx_frame.tuser == 0 + + assert tb.sink.empty() + + await RisingEdge(dut.clk) + await RisingEdge(dut.clk) + + +def size_list(): + return list(range(60, 128)) + [512, 1514, 9214] + [60]*10 + + +def incrementing_payload(length): + return bytearray(itertools.islice(itertools.cycle(range(256)), length)) + + +def cycle_en(): + return itertools.cycle([0, 0, 0, 1]) + + +if cocotb.SIM_NAME: + + factory = TestFactory(run_test) + factory.add_option("payload_lengths", [size_list]) + factory.add_option("payload_data", [incrementing_payload]) + factory.add_option("ifg", [12, 0]) + factory.generate_tests() + + +# 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(rtl_dir, '..', 'lib')) +axis_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'axis', 'rtl')) + + +def test_axis_baser_rx_64(request): + dut = "axis_baser_rx_64" + 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, "lfsr.v"), + ] + + parameters = {} + + parameters['DATA_WIDTH'] = 64 + parameters['KEEP_WIDTH'] = parameters['DATA_WIDTH'] // 8 + parameters['HDR_WIDTH'] = 2 + parameters['PTP_TS_ENABLE'] = 0 + parameters['PTP_TS_WIDTH'] = 96 + parameters['USER_WIDTH'] = (parameters['PTP_TS_WIDTH'] if parameters['PTP_TS_ENABLE'] else 0) + 1 + + 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, + ) diff --git a/tb/axis_baser_tx_64/Makefile b/tb/axis_baser_tx_64/Makefile new file mode 100644 index 000000000..437cd4cf6 --- /dev/null +++ b/tb/axis_baser_tx_64/Makefile @@ -0,0 +1,100 @@ +# Copyright (c) 2021 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 = axis_baser_tx_64 +TOPLEVEL = $(DUT) +MODULE = test_$(DUT) +VERILOG_SOURCES += ../../rtl/$(DUT).v +VERILOG_SOURCES += ../../rtl/lfsr.v + +# module parameters +export PARAM_DATA_WIDTH ?= 64 +export PARAM_KEEP_WIDTH ?= $(shell expr $(PARAM_DATA_WIDTH) / 8 ) +export PARAM_HDR_WIDTH ?= 2 +export PARAM_ENABLE_PADDING ?= 1 +export PARAM_ENABLE_DIC ?= 1 +export PARAM_MIN_FRAME_LENGTH ?= 64 +export PARAM_PTP_TS_ENABLE ?= 0 +export PARAM_PTP_TS_WIDTH ?= 96 +export PARAM_PTP_TAG_ENABLE ?= $(PARAM_PTP_TS_ENABLE) +export PARAM_PTP_TAG_WIDTH ?= 16 +#export PARAM_USER_WIDTH ?= (parameters['PTP_TAG_WIDTH'] if parameters['PTP_TAG_ENABLE'] else 0) + 1 +export PARAM_USER_WIDTH ?= 1 + +ifeq ($(SIM), icarus) + PLUSARGS += -fst + + COMPILE_ARGS += -P $(TOPLEVEL).DATA_WIDTH=$(PARAM_DATA_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).KEEP_WIDTH=$(PARAM_KEEP_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).HDR_WIDTH=$(PARAM_HDR_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).ENABLE_PADDING=$(PARAM_ENABLE_PADDING) + COMPILE_ARGS += -P $(TOPLEVEL).ENABLE_DIC=$(PARAM_ENABLE_DIC) + COMPILE_ARGS += -P $(TOPLEVEL).MIN_FRAME_LENGTH=$(PARAM_MIN_FRAME_LENGTH) + COMPILE_ARGS += -P $(TOPLEVEL).PTP_TS_ENABLE=$(PARAM_PTP_TS_ENABLE) + COMPILE_ARGS += -P $(TOPLEVEL).PTP_TS_WIDTH=$(PARAM_PTP_TS_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).PTP_TAG_ENABLE=$(PARAM_PTP_TAG_ENABLE) + COMPILE_ARGS += -P $(TOPLEVEL).PTP_TAG_WIDTH=$(PARAM_PTP_TAG_WIDTH) + COMPILE_ARGS += -P $(TOPLEVEL).USER_WIDTH=$(PARAM_USER_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 += -GDATA_WIDTH=$(PARAM_DATA_WIDTH) + COMPILE_ARGS += -GKEEP_WIDTH=$(PARAM_KEEP_WIDTH) + COMPILE_ARGS += -GHDR_WIDTH=$(PARAM_HDR_WIDTH) + COMPILE_ARGS += -GENABLE_PADDING=$(PARAM_ENABLE_PADDING) + COMPILE_ARGS += -GENABLE_DIC=$(PARAM_ENABLE_DIC) + COMPILE_ARGS += -GMIN_FRAME_LENGTH=$(PARAM_MIN_FRAME_LENGTH) + COMPILE_ARGS += -GPTP_TS_ENABLE=$(PARAM_PTP_TS_ENABLE) + COMPILE_ARGS += -GPTP_TS_WIDTH=$(PARAM_PTP_TS_WIDTH) + COMPILE_ARGS += -GPTP_TAG_ENABLE=$(PARAM_PTP_TAG_ENABLE) + COMPILE_ARGS += -GPTP_TAG_WIDTH=$(PARAM_PTP_TAG_WIDTH) + COMPILE_ARGS += -GUSER_WIDTH=$(PARAM_USER_WIDTH) + + ifeq ($(WAVES), 1) + COMPILE_ARGS += --trace-fst + endif +endif + +include $(shell cocotb-config --makefiles)/Makefile.sim + +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 iverilog_dump.v + @rm -rf dump.fst $(TOPLEVEL).fst diff --git a/tb/axis_baser_tx_64/baser.py b/tb/axis_baser_tx_64/baser.py new file mode 120000 index 000000000..33a23687c --- /dev/null +++ b/tb/axis_baser_tx_64/baser.py @@ -0,0 +1 @@ +../baser.py \ No newline at end of file diff --git a/tb/axis_baser_tx_64/test_axis_baser_tx_64.py b/tb/axis_baser_tx_64/test_axis_baser_tx_64.py new file mode 100644 index 000000000..3329f0940 --- /dev/null +++ b/tb/axis_baser_tx_64/test_axis_baser_tx_64.py @@ -0,0 +1,245 @@ +#!/usr/bin/env python +""" + +Copyright (c) 2021 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 itertools +import logging +import os +import sys + +import cocotb_test.simulator +import pytest + +import cocotb +from cocotb.clock import Clock +from cocotb.triggers import RisingEdge +from cocotb.regression import TestFactory + +from cocotbext.axi import AxiStreamBus, AxiStreamSource + +try: + from baser import BaseRSerdesSink +except ImportError: + # attempt import from current directory + sys.path.insert(0, os.path.join(os.path.dirname(__file__))) + try: + from baser import BaseRSerdesSink + 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) + + cocotb.fork(Clock(dut.clk, 6.4, units="ns").start()) + + self.source = AxiStreamSource(AxiStreamBus.from_prefix(dut, "s_axis"), dut.clk, dut.rst) + self.sink = BaseRSerdesSink(dut.encoded_tx_data, dut.encoded_tx_hdr, dut.clk, scramble=False) + + dut.ifg_delay.setimmediatevalue(0) + dut.ptp_ts.setimmediatevalue(0) + + async def reset(self): + self.dut.rst.setimmediatevalue(0) + await RisingEdge(self.dut.clk) + await RisingEdge(self.dut.clk) + self.dut.rst <= 1 + await RisingEdge(self.dut.clk) + await RisingEdge(self.dut.clk) + self.dut.rst <= 0 + await RisingEdge(self.dut.clk) + await RisingEdge(self.dut.clk) + + +async def run_test(dut, payload_lengths=None, payload_data=None, ifg=12): + + tb = TB(dut) + + tb.dut.ifg_delay <= ifg + + await tb.reset() + + test_frames = [payload_data(x) for x in payload_lengths()] + + for test_data in test_frames: + await tb.source.send(test_data) + + for test_data in test_frames: + rx_frame = await tb.sink.recv() + + assert rx_frame.get_payload() == test_data + assert rx_frame.check_fcs() + + assert tb.sink.empty() + + await RisingEdge(dut.clk) + await RisingEdge(dut.clk) + + +async def run_test_alignment(dut, payload_data=None, ifg=12): + + enable_dic = int(os.getenv("PARAM_ENABLE_DIC")) + + tb = TB(dut) + + byte_width = tb.source.width // 8 + + tb.dut.ifg_delay <= ifg + + for length in range(60, 92): + + await tb.reset() + + test_frames = [payload_data(length) for k in range(10)] + start_lane = [] + + for test_data in test_frames: + await tb.source.send(test_data) + + for test_data in test_frames: + rx_frame = await tb.sink.recv() + + assert rx_frame.get_payload() == test_data + assert rx_frame.check_fcs() + assert rx_frame.ctrl is None + + start_lane.append(rx_frame.start_lane) + + tb.log.info("length: %d", length) + tb.log.info("start_lane: %s", start_lane) + + start_lane_ref = [] + + # compute expected starting lanes + lane = 0 + deficit_idle_count = 0 + + for test_data in test_frames: + if ifg == 0: + lane = 0 + + start_lane_ref.append(lane) + lane = (lane + len(test_data)+4+ifg) % byte_width + + if enable_dic: + offset = lane % 4 + if deficit_idle_count+offset >= 4: + offset += 4 + lane = (lane - offset) % byte_width + deficit_idle_count = (deficit_idle_count + offset) % 4 + else: + offset = lane % 4 + if offset > 0: + offset += 4 + lane = (lane - offset) % byte_width + + tb.log.info("start_lane_ref: %s", start_lane_ref) + + assert start_lane_ref == start_lane + + await RisingEdge(dut.clk) + + assert tb.sink.empty() + + await RisingEdge(dut.clk) + await RisingEdge(dut.clk) + + +def size_list(): + return list(range(60, 128)) + [512, 1514, 9214] + [60]*10 + + +def incrementing_payload(length): + return bytearray(itertools.islice(itertools.cycle(range(256)), length)) + + +def cycle_en(): + return itertools.cycle([0, 0, 0, 1]) + + +if cocotb.SIM_NAME: + + factory = TestFactory(run_test) + factory.add_option("payload_lengths", [size_list]) + factory.add_option("payload_data", [incrementing_payload]) + factory.add_option("ifg", [12]) + factory.generate_tests() + + factory = TestFactory(run_test_alignment) + factory.add_option("payload_data", [incrementing_payload]) + factory.add_option("ifg", [12]) + factory.generate_tests() + + +# 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(rtl_dir, '..', 'lib')) +axis_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'axis', 'rtl')) + + +@pytest.mark.parametrize("enable_dic", [1, 0]) +def test_axis_baser_tx_64(request, enable_dic): + dut = "axis_baser_tx_64" + 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, "lfsr.v"), + ] + + parameters = {} + + parameters['DATA_WIDTH'] = 64 + parameters['KEEP_WIDTH'] = parameters['DATA_WIDTH'] // 8 + parameters['HDR_WIDTH'] = 2 + parameters['ENABLE_PADDING'] = 1 + parameters['ENABLE_DIC'] = enable_dic + parameters['MIN_FRAME_LENGTH'] = 64 + parameters['PTP_TS_ENABLE'] = 0 + parameters['PTP_TS_WIDTH'] = 96 + parameters['PTP_TAG_ENABLE'] = parameters['PTP_TS_ENABLE'] + parameters['PTP_TAG_WIDTH'] = 16 + parameters['USER_WIDTH'] = (parameters['PTP_TAG_WIDTH'] if parameters['PTP_TAG_ENABLE'] else 0) + 1 + + 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, + )