NELIX Silicon Lab Docs Launch Silicon Lab Launch Silicon Lab

Testbenches and cocotb

What a testbench is, how a cocotb test is built, and the pattern every test in this lab follows.

Student 2 min read · Updated 2026-10-05

On this page cocotbThe shape of a testLine by lineWhy the falling edgeSigned valuesA good assert messageWhat the lab allows in a test

A testbench is code that drives a design's inputs and checks its outputs. It is not part of the chip. It exists to find mistakes before the design becomes hardware.

cocotb#

In this lab a testbench is a Python file, run by cocotb. Your design runs inside the Icarus Verilog simulator; cocotb lets Python set its inputs, wait for clock edges and read its outputs.

Python is a good fit: working out the expected answer is ordinary programming.

The shape of a test#

This is the test from the Blank starter, complete.

python
import cocotb
from cocotb.clock import Clock
from cocotb.triggers import FallingEdge


@cocotb.test()
async def test_top(dut):
    """q follows d one clock later, and reset clears it."""
    cocotb.start_soon(Clock(dut.clk, 10, unit="ns").start())
    dut.d.value = 0xFF
    dut.rst_n.value = 0
    await FallingEdge(dut.clk)
    await FallingEdge(dut.clk)
    assert int(dut.q.value) == 0, f"q expected 0 in reset, got {int(dut.q.value)}"
    dut.rst_n.value = 1

    for value in (0x01, 0x80, 0x5A, 0x00, 0xFF):
        dut.d.value = value
        await FallingEdge(dut.clk)
        assert int(dut.q.value) == value, f"q expected {value}, got {int(dut.q.value)}"

Line by line#

LineWhat it does
@cocotb.test()Marks the function as a test
async def test_top(dut)dut is your design. dut.q is its port q
Clock(dut.clk, 10, unit="ns")A 10 ns clock on clk
dut.d.value = 0xFFDrive an input
await FallingEdge(dut.clk)Wait for the clock to fall
int(dut.q.value)Read an output as a number
assert ..., "message"A check. If it is false the test fails and prints the message

Why the falling edge#

The design changes its outputs on the rising edge. If the test drove inputs and read outputs at that same instant, it would race the design. Driving and reading on the falling edge puts the test half a period away from the action.

Signed values#

int(dut.acc.value) reads the bits as an unsigned number. For a signed output use dut.acc.value.to_signed().

A good assert message#

Write the message for the person who will see it fail: the inputs, what was expected, what was seen.

python
assert got == want, f"subtract {a}, {b}: expected {want}, saw {got}"

What the lab allows in a test#

A test may import cocotb, cocotb.clock, cocotb.triggers and random, and nothing else. It may not open files, start processes or use the network.

Related

Something unclear or missing? Send feedbackSign in and use Feedback to tell us.