Skip to content
João Carvalho edited this page Dec 5, 2023 · 11 revisions

The following page collects examples, snippets, best practises and so on - please add your own!

See also the tutorials in the official documentation at https://cocotb.readthedocs.io/ and the https://cocotb.readthedocs.io/en/latest/examples.html section.

import cocotb

Setting Bits of a Vector

from cocotb.binary import BinaryValue

my_vector = BinaryValue(n_bits=4)
my_vector[0] <= 1

Extracting Bits from a Vector

from cocotb.binary import BinaryValue

my_vector = BinaryValue(value=0xC0DE)
my_bit_0 = my_vector[0]

Serializing

TBD

Deserializing

TBD

Reversing a Vector

TBD

Resizing a Vector

TBD

Sign-extending a Vector

TBD

Not Driving a Signal; Tri-stating a Signal

from cocotb.binary import BinaryValue

my_signal = BinaryValue('z')

Working with a Bidirectional Signal

TBD

Accessing a signal inside a VHDL generate loop

Use my_loop_label[X].my_signal where X is the loop index.

Using a Matlab/Simulink Reference Model

You can use the Matlab Engine for Python to essentially call Matlab from a cocotb test. Sometimes you might have models already written in Matlab, or someone insisting that Matlab is the golden truth ;)
Works both way, can be used for data generation too. You only need to convert the python data types to what the engine wants to see.
There might be more efficient ways to do this than what is shown below but this shows the idea.

Matlab Engine Doc - Need to install first.

For Example:

# Start engine
import matlab.engine
eng = matlab.engine.start_matlab()
eng.addpath('c:\cocotb\examples\adder\model', nargout=0)  # make sure myModel.m file is in the current path or add it to the path

# Run test, collect input/output values in numpy array
# ...

# Call Matlab Model with Matlab friendly datatype
testPassed = eng.myModel(matlab.double(din.tolist()), matlab.double(dout.tolist()), settings)

if testPassed:
    dut._log.info("MATLAB MODEL MATCH!")
else:
    dut._log.info("MATLAB MODEL DOES NOT MATCH!")`

Stimulus from Oscilloscope Capture

TBD

Checking whether a coroutine is still active

# my coroutine
async def my_coroutine():
    do_something()
    return something

# my test
async def my_test(dut):
    (...)
    my_task = await cocotb.start(my_coroutine())

    # wait for coroutine to finish
    while not my_task.done():
        await RisingEdge(dut.clk)

    # get return value
    corou_return = my_task.result()

See more: coroutines-and-tasks, cocotb.task.Task.

Monitoring an asynchronous bus

The BusMonitor class expects a clocked synchronous interface but sometimes you'll have simple asynchronous interfaces that you want to monitor. In this case you can use the fact that you can specify a list of signals to a trigger to watch all the signals of a bus.

For example, imagine a Bus defined with n signals, in this case I'll use 8 vectors:

class ControlBus(Bus):
    '''Models a bunch of common signals.'''
    _signals = ['ctrl0',
                'ctrl1',
                'ctrl2',
                'ctrl3',
                'ctrl4',
                'ctrl5',
                'ctrl6',
                'ctrl7' ]
   
    def __init__(self, entity, name):
        Bus.__init__(self, entity, name, self._signals)

then the monitor would look like:

class ControlMonitor(Monitor):
    def __init__(self, name, bus, callback=None, event=None):
        self.name = name
        self.bus  = bus
        Monitor.__init__(self, callback, event)

    @cocotb.coroutine
    async def _monitor_recv(self):
        while True:
            trig = await First(*[Edge(hdl) for name,hdl in self.bus._signals.items()])
            self.log.info("trigger was %s"%trig)