Building a BFM

Bus Functional Models (BFMs) abstract signal-level details into transaction-level calls. In Cocotb, a Driver is simply a Python class that toggles signals.

Simple Driver Example

Let's create a reusable driver for a simple Valid/Ready interface.

import cocotb
from cocotb.triggers import RisingEdge
class StreamDriver:
    def __init__(self, bus, clock):
        self.bus = bus
        self.clock = clock
    async def send(self, data):
        """Send one transaction"""
        self.bus.valid.value = 1
        self.bus.data.value = data
        while True:
            await RisingEdge(self.clock)
            if self.bus.ready.value == 1:
                break
        self.bus.valid.value = 0

Using the Driver

@cocotb.test()
async def test_stream(dut):
    # Instantiate the BFM
    driver = StreamDriver(dut, dut.clk)
    # Use it!
    await driver.send(0xAA)
    await driver.send(0xBB)