cocotb

2.0.1 · active · verified Thu Apr 16

cocotb is a coroutine-based cosimulation library that enables writing Verilog and VHDL testbenches in Python. It provides a robust framework for verifying hardware designs by interacting directly with commercial and open-source HDL simulators. The current version is 2.0.1, with major releases typically aligning with significant architectural changes, moving towards more Pythonic async/await patterns.

Common errors

Warnings

Install

Imports

Quickstart

This Python code defines a basic `cocotb` test for a D flip-flop (DFF) with clock and data inputs (`clk`, `i`) and a data output (`q`). To run this, you need a corresponding Verilog/VHDL DFF design file (e.g., `dff.v` or `dff.vhdl`) and a `Makefile` to integrate with an HDL simulator (like Icarus Verilog or GHDL). The `Makefile` typically specifies `TOPLEVEL`, `TOPLEVEL_LANG`, and `SIM` variables, and orchestrates the simulation. For simpler execution, `pytest-cocotb` can also be used.

import cocotb
from cocotb.triggers import Timer, RisingEdge
from cocotb.clock import Clock
import os

@cocotb.test()
async def my_first_test(dut):
    """Attempt to verify D flip-flop functionality"""
    cocotb.log.info("Starting my_first_test")

    # Access signals on the DUT (Design Under Test)
    # These signal names (clk, i, q) correspond to ports in an HDL design
    clk = dut.clk
    i = dut.i
    q = dut.q

    # Set initial values
    i.value = 0
    await Timer(1, units="ns")

    # Create a clock
    clock = Clock(clk, 10, units="ns")  # 10 ns period, 100MHz
    cocotb.start_soon(clock.start())

    # Assert reset if available (common in DFF designs)
    if hasattr(dut, 'reset_n'): # Check if 'reset_n' signal exists on DUT
        dut.reset_n.value = 0
        await RisingEdge(clk)
        await RisingEdge(clk) # Ensure reset holds for a bit
        dut.reset_n.value = 1
        await RisingEdge(clk)
    else:
        await RisingEdge(clk) # Just advance clock if no reset

    # Test case 1: input 0, expect output 0 (after clock edge)
    i.value = 0
    await RisingEdge(clk)
    cocotb.log.info(f"Input: {i.value}, Output: {q.value}")
    assert q.value == 0, f"Expected q=0, got {q.value}"

    # Test case 2: input 1, expect output 0 (output lags input by one clock cycle)
    i.value = 1
    await RisingEdge(clk)
    cocotb.log.info(f"Input: {i.value}, Output: {q.value}")
    assert q.value == 0, f"Expected q=0, got {q.value}" 

    # Test case 3: input 1, expect output 1 (on the next clock edge)
    await RisingEdge(clk)
    cocotb.log.info(f"Input: {i.value}, Output: {q.value}")
    assert q.value == 1, f"Expected q=1, got {q.value}"

    cocotb.log.info("Test finished")

view raw JSON →