wave2tb-generator
Generate a cycle-based SystemVerilog testbench from a captured VCD waveform and DUT RTL.
Why This Project Matters
- Small design team using Chisel can keep their verification written in svsim.
- Outsourced backend/PD teams usually need plain, static SV testbenches for GLS handoff.
- This tool bridges both worlds by converting captured VCD behavior into deterministic, standalone SV TB code (no Chisel runtime dependency).
- It reduces manual TB rewrite effort and lowers handoff risk between frontend and backend flows.
Workflow
- Parse DUT ports from RTL in Python (
tree-sitter-verilog). - Read VCD waveform and auto-match one DUT scope.
- Build a JSON IR containing per-cycle input stimulus and expected outputs.
- Emit a standalone SystemVerilog testbench that:
- drives the same per-cycle stimulus (only emits changed input assignments),
- steps the DUT clock,
- checks expected outputs every cycle.
Install
uv sync
After uv sync, run CLI commands with uv run (recommended), for example:
uv run wave2tb --help
If you prefer not to use uv run each time, activate the venv first:
source .venv/bin/activate
wave2tb --help
CLI
Generate testbench in one step from VCD + RTL:
uv run wave2tb vcd-to-tb \
--vcd test/out/reference.vcd \
--rtl test/data/sample_dut.sv \
--top-module sample_dut \
--clock clk \
--tb-out test/out/generated_tb.sv \
--ir-out test/out/generated.ir.json
Generate IR and testbench (legacy two-output command):
uv run wave2tb from-vcd \
--vcd test/out/reference.vcd \
--rtl test/data/sample_dut.sv \
--top-module sample_dut \
--clock clk \
--ir-out test/out/generated.ir.json \
--tb-out test/out/generated_tb.sv
Generate testbench from an existing IR:
uv run wave2tb ir-to-tb \
--ir test/out/generated.ir.json \
--tb-out test/out/generated_tb.sv
Optional external equivalence verification:
uv run wave2tb vcd-to-tb \
--vcd test/out/reference.vcd \
--rtl test/data/sample_dut.sv \
--top-module sample_dut \
--clock clk \
--tb-out test/out/generated_tb.sv \
--verify-with-verilator
End-to-End Test
Run:
bash test/run_e2e.sh
Note: the optional --verify-with-verilator flow and test/run_e2e.sh require external Verilator.
Generated Output Examples
generated.ir.json (delta IR)
generated.ir.json uses encoding: "delta" and is the intermediate format consumed by the toolchain. Core rules:
- Top-level metadata includes
schema_version,encoding,top_module,scope,timescale,clock_name, andclock_edge. - The
portsarray stores the DUT port list; each item hasdirection,name, andwidth. - The
cyclesarray is time-ordered; each entry hasindex,time,inputs, andoutputs. inputs/outputsonly store signals that changed relative to the previous cycle; an empty object means no changes in that direction for this cycle.- When loading IR, the tool performs carry-forward expansion to reconstruct full per-cycle vectors before TB generation.
generated_tb.sv (generated SystemVerilog TB)
Below is the key excerpt copied from the real test artifact test/out/generated_tb.sv: the statements inside initial begin ... end.
clk = CLK_IDLE;
rst_n = '0;
clear = '0;
en = '0;
din = '0;
mode = '0;
// cycle 0, source_time=5 (1ps)
step_to_edge();
`CHECK_EQ(accum, 6'b000000, 0, "accum");
`CHECK_EQ(dout, 4'b0000, 0, "dout");
`CHECK_EQ(valid, 1'b0, 0, "valid");
`CHECK_EQ(parity, 1'b0, 0, "parity");
step_to_idle();
// cycle 1, source_time=15 (1ps)
rst_n = 1'b1;
en = 1'b1;
din = 4'b0011;
step_to_edge();
`CHECK_EQ(accum, 6'b000011, 1, "accum");
`CHECK_EQ(dout, 4'b0011, 1, "dout");
`CHECK_EQ(valid, 1'b1, 1, "valid");
`CHECK_EQ(parity, 1'b1, 1, "parity");
step_to_idle();
$display("PASS: %0d cycles checked for sample_dut from scope reference_wave_tb.u_dut", NUM_CYCLES);
$finish;
Metadata
Release files for wave2tb-generator 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| wave2tb_generator-0.1.0.tar.gz | 17.7 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| wave2tb_generator-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 36.1 kB
Release files / wave2tb_generator-0.1.0.tar.gz
| Download URL | wave2tb_generator-0.1.0.tar.gz |
|---|---|
| Size | 17.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
f563ea156924d653e510aef2ba60ded15c19746330803b4aa1b9648088ceb60f
|
|
BLAKE2b-256 checksum How to use checksums |
e6d261848f2ccee7c6d43aa0818d9b73017152b230ef24ad4b67ee5b1ee71665
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.9.25 {"installer":{"name":"uv","version":"0.9.25","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Arch Linux","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Release files / wave2tb_generator-0.1.0-py3-none-any.whl
| Download URL | wave2tb_generator-0.1.0-py3-none-any.whl |
|---|---|
| Size | 18.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
0e23a6c49b3908aafafc385ea454bc9b56d78128f3ef7e738fd25bcdf9492d8d
|
|
BLAKE2b-256 checksum How to use checksums |
dacd717b069aeb18517aa2a85f146d0fae09ba5796f72433c48e38ef995139f0
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.9.25 {"installer":{"name":"uv","version":"0.9.25","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Arch Linux","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|