rules_cocotb
Bazel rules that run cocotb Python testbenches against Verilog/SystemVerilog and VHDL modules using open-source HDL simulators (Verilator, Icarus Verilog, GHDL).
Overview
A cocotb_test is a Bazel test target that pairs:
- a Verilog or VHDL
*_librarytarget (fromrules_verilogorrules_vhdl) as the module under test, - one or more Python
cocotbtest sources, and - a
cocotb_toolchainthat picks the simulator.
The two top-level rules are documented under Rules; the per-simulator integrations live under Simulators.
End-to-end example
The walkthrough below builds a tiny 8-bit adder, drives it from a Python cocotb testbench, and runs the test with Verilator.
MODULE.bazel
bazel_dep(name = "rules_verilog", version = "1.1.1")
bazel_dep(name = "rules_cocotb", version = "{version}")
rules_cocotb registers a default toolchain
(//cocotb/toolchain:toolchain) wired to Verilator (default), Icarus
Verilog, and GHDL. No further register_toolchains call is required to
use the bundled simulators.
adder.sv
module adder (
input [7:0] x,
input [7:0] y,
input carry_in,
output carry_output_bit,
output [7:0] sum
);
logic [8:0] result;
assign result = x + y + carry_in;
assign sum = result[7:0];
assign carry_output_bit = result[8];
endmodule
adder_test.py
import cocotb
from cocotb.handle import HierarchyObject
from cocotb.triggers import Timer
@cocotb.test()
async def test_adder(dut: HierarchyObject) -> None:
"""Drive a handful of vectors through the 8-bit adder."""
vectors = [
# (x, y, carry_in, expected_sum, expected_carry_out)
(0x00, 0x00, 0, 0x00, 0),
(0xFF, 0x01, 0, 0x00, 1),
(0x55, 0xAA, 1, 0x00, 1),
]
for x, y, cin, exp_sum, exp_cout in vectors:
dut.x.value = x
dut.y.value = y
dut.carry_in.value = cin
await Timer(1, units="ns")
sum_val = int(dut.sum.value)
cout_val = int(dut.carry_output_bit.value)
assert sum_val == exp_sum and cout_val == exp_cout, (
f"adder mismatch for x={x:#04x} y={y:#04x} cin={cin}"
)
BUILD.bazel
load("@rules_verilog//verilog:defs.bzl", "verilog_library")
load("@rules_cocotb//cocotb:cocotb_test.bzl", "cocotb_test")
verilog_library(
name = "adder",
srcs = ["adder.sv"],
)
cocotb_test(
name = "adder_test",
srcs = ["adder_test.py"],
module = ":adder",
sim = "verilator",
)
Run it
$ bazel test //path/to:adder_test
//path/to:adder_test PASSED
To rerun under Icarus instead, change sim = "verilator" to
sim = "icarus". To swap to a VHDL toplevel, replace verilog_library
with vhdl_library from rules_vhdl and pick sim = "ghdl".
Going further
- The
cocotb_testreference covers the full attribute set (params,sim_opts,env, etc.). - The
cocotb_toolchainreference shows how to define a custom toolchain — for selecting a different default simulator, narrowing the set of simulators, or wiring in a bring-your-own-installcocotb_*_sim. - The Simulators section lists every built-in simulator integration and per-simulator status.