GF-Cocotb -- Python Testbench Generation

SkillDev tools

Python-based testbench generation using Cocotb. Alternative to SystemVerilog testbenches for Python-native hardware engineers. Example: "create a cocotb test for the FIFO", "write Python testbench"

Available today. Use it from your connected AI after setup.

Connect ahel once, and every AI you use reads what you have installed.

Then ask your AI: use the GF-Cocotb -- Python Testbench Generation skill

What this skill tells your AI

The instructions your AI receives, as published by codejunkie99/gateflow-plugin in skills/gf-cocotb/SKILL.md and read by ahel’s review.

Generate Cocotb testbenches as an alternative to SystemVerilog TBs.

Tool Detection

python3 -c "import cocotb" 2>/dev/null

If not found, return GATEFLOW-RESULT ERROR with: pip install cocotb

Test Template

import cocotb
from cocotb.clock import Clock
from cocotb.triggers import RisingEdge

@cocotb.test()
async def test_reset(dut):
    clock = Clock(dut.clk, 10, units="ns")
    cocotb.start_soon(clock.start())
    dut.rst_n.value = 0
    for _ in range(3):
        await RisingEdge(dut.clk)
    dut.rst_n.value = 1
    await RisingEdge(dut.clk)
    assert dut.count.value == 0

When to Use

CocotbSV Testbench
Python (lower barrier)SystemVerilog
Complex stimulus (Python libs)Protocol + coverage
Slower (co-simulation)Faster (native)

Makefile Template

SIM ?= icarus
TOPLEVEL_LANG ?= verilog
VERILOG_SOURCES += $(PWD)/rtl/$(DUT).sv
TOPLEVEL = $(DUT)
MODULE = test_$(DUT)
COCOTB_HDL_TIMEUNIT = 1ns
COCOTB_HDL_TIMEPRECISION = 1ps

ifeq ($(SIM),verilator)
    EXTRA_ARGS += --trace --trace-structs
endif

SIM_BUILD = sim_build/$(SIM)
include $(shell cocotb-config --makefiles)/Makefile.sim

Test Templates

FIFO Test

import cocotb
from cocotb.clock import Clock
from cocotb.triggers import RisingEdge, ClockCycles
import random

async def reset_fifo(dut):
    dut.rst.value = 1
    dut.wr_en.value = 0
    dut.rd_en.value = 0
    await ClockCycles(dut.clk, 5)
    dut.rst.value = 0
    await RisingEdge(dut.clk)

@cocotb.test()
async def test_fifo_write_read(dut):
    clock = Clock(dut.clk, 10, units="ns")
    cocotb.start_soon(clock.start())
    await reset_fifo(dut)

    assert dut.empty.value == 1
    written = []
    for i in range(16):
        data = random.randint(0, 255)
        written.append(data)
        dut.din.value = data
        dut.wr_en.value = 1
        await RisingEdge(dut.clk)
    dut.wr_en.value = 0
    await RisingEdge(dut.clk)
    assert dut.full.value == 1

    read = []
    for i in range(16):
        dut.rd_en.value = 1
        await RisingEdge(dut.clk)
        read.append(int(dut.dout.value))
    dut.rd_en.value = 0
    assert read == written

Valid/Ready Handshake Test

@cocotb.test()
async def test_handshake(dut):
    clock = Clock(dut.clk, 10, units="ns")
    cocotb.start_soon(clock.start())
    # ... reset ...

    async def driver():
        for data in range(20):
            dut.s_data.value = data
            dut.s_valid.value = 1
            while True:
                await RisingEdge(dut.clk)
                if dut.s_ready.value == 1:
                    break
        dut.s_valid.value = 0

    async def backpressure():
        while True:
            dut.m_ready.value = random.randint(0, 1)
            await ClockCycles(dut.clk, random.randint(1, 4))

    cocotb.start_soon(driver())
    cocotb.start_soon(backpressure())
    await ClockCycles(dut.clk, 200)

FSM Test

from enum import IntEnum

class State(IntEnum):
    IDLE = 0
    ACTIVE = 1
    DONE = 2

@cocotb.test()
async def test_fsm(dut):
    clock = Clock(dut.clk, 10, units="ns")
    cocotb.start_soon(clock.start())
    # reset...
    assert int(dut.state.value) == State.IDLE
    dut.start.value = 1
    await RisingEdge(dut.clk)
    dut.start.value = 0
    await RisingEdge(dut.clk)
    assert int(dut.state.value) == State.ACTIVE

Python Runner (pytest)

import os
from pathlib import Path
from cocotb_tools.runner import get_runner

def test_module():
    sim = os.getenv("SIM", "icarus")
    runner = get_runner(sim)
    runner.build(
        sources=[Path("rtl/my_module.sv")],
        hdl_toplevel="my_module",
    )
    runner.test(
        hdl_toplevel="my_module",
        test_module="test_my_module",
    )

cocotbext Protocol Libraries

PackageProtocolInstall
cocotbext-axiAXI4, AXI-Lite, AXI-Streampip install cocotbext-axi
cocotbext-wishboneWishbone B4pip install cocotbext-wishbone
cocotbext-spiSPIpip install cocotbext-spi
cocotbext-uartUARTpip install cocotbext-uart
cocotbext-ethEthernetpip install cocotbext-eth
cocotbext-pciePCIepip install cocotbext-pcie

AXI-Lite Example

from cocotbext.axi import AxiLiteBus, AxiLiteMaster

axil = AxiLiteMaster(AxiLiteBus.from_prefix(dut, "s_axi"), dut.clk, dut.rst)
await axil.write(0x0000, b'\x42\x00\x00\x00')
data = await axil.read(0x0000, 4)

Decision Matrix: Cocotb vs SV TB

FactorUse CocotbUse SV/UVM
Team knows PythonYes-
FPGA projectYes-
Large ASIC with UVM infra-Yes
Need open-source CIYes-
Standard protocols (AXI, SPI)Yes (cocotbext)-
Deep constrained random-Yes
Rapid iterationYes-

GATEFLOW-RESULT Integration

---GATEFLOW-RESULT---
STATUS: PASS | FAIL | ERROR
ERRORS: <count>
WARNINGS: <count>
FILES: <test files>
DETAILS: <summary>
---END-GATEFLOW-RESULT---

Signals

GitHub stars
112
Forks
14
Last commit
May 2026
Advanced
Catalog kind
skill
Gateway key
gf-cocotb
Source
github.com/codejunkie99/gateflow-plugin