AVL-AXI-STREAM Receiver
The receiver side of the AVL-AXI-STREAM agent does not follow the standard AVL / UVM structure of sequence, sequencer and driver.
As the receiver is responsive the overhead of interacting between a monitor, sequence and driver is overly complicated and not required.
Instead the receiver is implemented as a single driver that implements the legal protocol for the bus via 3 user defined tasks:
RecDriver.resetAction to be taken on bus reset. By default all completion signals are set to 0.Driver.quiesceAction to be taken between transactions. By default all completion signals are set to 0.RecDriver.driveAction of driving.
In AXI-STEAM the receiver is only responsible for driving tready (if present), and as such the rdriver is very simple.
Rate Control
The receiver driver is responsible for rate control. By setting the rate_limit variable in the RecDriver class, using a lambda function that returns a value between 0.0 and 1.0 the user can control the rate of driving the tready signal, if supported.
avl.Factory.set_variable("*.agent.rdrv.rate_limit", lambda: 0.1)
Example
# Copyright 2024 Apheleia
#
# Description:
# Apheleia attributes example
import avl
import avl_axi_stream
import cocotb
class example_env(avl.Env):
def __init__(self, name, parent):
super().__init__(name, parent)
self.hdl = avl.Factory.get_variable(f"{self.get_full_name()}.hdl", None)
self.clk = avl.Factory.get_variable(f"{self.get_full_name()}.clk", None)
self.rst_n = avl.Factory.get_variable(f"{self.get_full_name()}.rst_n", None)
self.agent = avl_axi_stream.Agent("agent", self)
async def run_phase(self):
self.raise_objection()
await cocotb.start(self.timeout(1, units="ms"))
await cocotb.start(self.clock(self.clk, 100))
await self.async_reset(self.rst_n, duration=100, units="ns", active_high=False)
self.drop_objection()
@cocotb.test
async def test(dut):
"""
Example Simple interface
- tready
- No tstrb
- No tkeep
- tlast
- No tid
- No tdest
- No tuser
- No twakeup
- 100 packets in the transmit sequence with a rate limit of 0.1
- random data
:param dut: The DUT instance
:return: None
"""
avl.Factory.set_variable("*.clk", dut.clk)
avl.Factory.set_variable("*.rst_n", dut.rst_n)
avl.Factory.set_variable("*.hdl", dut.axi_stream_if)
avl.Factory.set_variable("*.agent.cfg.has_transmitter", True)
avl.Factory.set_variable("*.agent.cfg.has_receiver", True)
avl.Factory.set_variable("*.agent.cfg.has_monitor", True)
avl.Factory.set_variable("*.agent.cfg.has_coverage", True)
avl.Factory.set_variable("*.agent.cfg.has_trace", True)
avl.Factory.set_variable("*.agent.tsqr.tseq.n_items", 100)
avl.Factory.set_variable("*.agent.tsqr.tseq.packet_length", lambda: 32)
avl.Factory.set_variable("*.agent.tdrv.rate_limit", lambda: 0.1)
avl.Factory.set_variable("*.agent.rdrv.rate_limit", lambda: 0.5)
avl.Factory.set_override_by_type(avl_axi_stream.TransSequence, avl_axi_stream.PacketSequence)
e = example_env("env", None)
await e.start()