cocotb is a coroutine based cosimulation library for writing VHDL and Verilog testbenches in Python.
- Read the documentation
- Get involved:
- Raise a bug / request an enhancement (Requires a GitHub account)
- Join the Gitter chat room
Note: The current master branch of the cocotb repository is expected to be released as cocotb 2.0, which contains API-breaking changes from previous 1.x releases. Please use the stable/1.8 branch if you're building cocotb from source, or just install it from PyPi.
Installation
The current stable version of cocotb requires:
- Python 3.6+
- GNU Make 3+
- An HDL simulator (such as Icarus Verilog, Verilator, GHDL or other simulator)
After installing these dependencies, the latest stable version of cocotb can be installed with pip.
For more details on installation, including prerequisites, see the documentation.
For details on how to install the development version of cocotb, see the preliminary documentation of the future release.
Usage
As a first trivial introduction to cocotb, the following example "tests" a flip-flop.
First, we need a hardware design which we can test. For this example, create a file dff.sv with SystemVerilog code for a simple D flip-flop. You could also use any other language a cocotb-supported simulator understands, e.g. VHDL.
// dff.sv `timescale 1us/1ns module dff ( output logic q, input logic clk, d ); always @(posedge clk) begin q <= d; end endmodule
An example of a simple randomized cocotb testbench:
# test_dff.py import random import cocotb from cocotb.clock import Clock from cocotb.triggers import RisingEdge from cocotb.types import LogicArray @cocotb.test() async def dff_simple_test(dut): """Test that d propagates to q""" # Assert initial output is unknown assert LogicArray(dut.q.value) == LogicArray("X") # Set initial input value to prevent it from floating dut.d.value = 0 clock = Clock(dut.clk, 10, units="us") # Create a 10us period clock on port clk # Start the clock. Start it low to avoid issues on the first RisingEdge cocotb.start_soon(clock.start(start_high=False)) # Synchronize with the clock. This will regisiter the initial `d` value await RisingEdge(dut.clk) expected_val = 0 # Matches initial input value for i in range(10): val = random.randint(0, 1) dut.d.value = val # Assign the random value val to the input port d await RisingEdge(dut.clk) assert dut.q.value == expected_val, f"output q was incorrect on the {i}th cycle" expected_val = val # Save random value for next RisingEdge # Check the final input on the next clock await RisingEdge(dut.clk) assert dut.q.value == expected_val, "output q was incorrect on the last cycle"
A simple Makefile:
# Makefile TOPLEVEL_LANG = verilog VERILOG_SOURCES = $(shell pwd)/dff.sv TOPLEVEL = dff MODULE = test_dff include $(shell cocotb-config --makefiles)/Makefile.sim
In order to run the test with Icarus Verilog, execute:
For more information please see the cocotb documentation and our wiki.
Tutorials, examples and related projects
- the tutorial section in the official documentation
- cocotb-bus for pre-packaged testbenching tools and reusable bus interfaces.
- cocotb-based USB 1.1 test suite for FPGA IP, with testbenches for a variety of open source USB cores
cocotb-coverage, an extension for Functional Coverage and Constrained Randomizationuvm-python, an almost 1:1 port of UVM 1.2 to Pythonpyuvm, The UVM IEEE 1800.2 specification built upon cocotb and implemented from scratch in Python.- our wiki on extension modules
- the list of GitHub projects depending on cocotb