Getting Started with rustdv
You have some RTL — maybe an open-source core you just downloaded — and you want to verify it with a testbench written in Rust. This document takes you from nothing to a running regression, step by step. It assumes you have never used rustdv before; it does not assume you know Rust well (the book Rust for RTL Verification teaches that part).
Start by cloning the repository, in Step 1. It brings the framework, the TinyALU design and its worked testbench, starter templates, the book's runnable figures, the regression suite, and the skills that let Claude write a testbench for you. Every step here uses it.
There is one choice to make and it comes later: whether you write the testbench yourself or have Claude write it. Both are covered at the end, and they mix well.
Step 0: Install the tools (once per machine)
- Rust — one command, from rustup.rs:
The repository pins its compiler in|rust-toolchain.toml, so inside a clonerustupfetches the right one on its own. - Icarus Verilog — the four-state reference simulator:
The run scripts compile with# or the prebuilt oss-cad-suite: github.com/YosysHQ/oss-cad-suite-build |-g2012, so you need a build with SystemVerilog-2012 support. Any current Icarus has it; the oss-cad-suite build is the one this project is tested against. - Verilator — optional, and the fast two-state backend:
lz4 is not optional if you want waveforms. Verilator's FST writer linksliblz4, soRUSTDV_VERILATOR_MODE=debugfails to build without it. Every other Verilator mode runs fine. - Optional but recommended: VS Code + rust-analyzer (use model 1) or Claude Code / Cowork (use model 2), and GTKWave for waveforms.
Platform note: rustdv's simulator backend is VPI-based and is developed and tested on Linux and macOS with Icarus and Verilator. Windows users should work inside WSL, and commercial simulators are not supported today.
STATUS.mdin the repository records what has actually been run, and where.
Step 1: Clone rustdv and prove your setup works
Before touching your own core, run the known-good example. This isolates "my tools are broken" from "my testbench is wrong" — the most valuable distinction in verification.
&&
If all three pass, everything you need works. If one fails, fix it now — nothing later will work until it does.
Step 2: Set up your project
Keep your project outside the rustdv clone, next to it:
hobby/
├── rustdv/ ← the clone from step 1
└── my-core/ ← yours
├── hdl/ ← the RTL you downloaded
├── my_core_tb/ ← the Rust testbench crate (step 3)
└── sim/
├── timescale.v
└── run.sh
Ready-made starting files live in the repository at
.claude/skills/new-rustdv-testbench/templates/ — a Cargo.toml,
lib.rs, run.sh, and timescale.v. Copy them and rename the
placeholders.
Your testbench points at the clone. Two lines in my_core_tb/Cargo.toml, and
the paths are relative to that file:
[]
= { = "../../rustdv/rustdv" } # → the clone's rustdv/ workspace dir
[]
= { = "../../rustdv/rustdv/rustdv-vpi-stubs" }
The second one only matters for cargo test; Step 3 explains it.
Step 3: The five files of a first testbench
A rustdv testbench is a Rust library that the simulator loads — there is no Verilog testbench at all. The minimum is one crate with:
Cargo.toml— two settings matter and both are required:crate-type = ["cdylib", "rlib"], plus therustdv-vpi-stubsdev-dependency socargo testlinks. The template has them.src/lib.rs— starts from the template:use rustdv::prelude::*;, onerustdv::vpi_bootstrap!();, and one#[rustdv::test]function that starts a clock and touches a signal. Get this passing before writing any real verification code.sim/timescale.v— three lines; must be compiled first or Icarus defaults to 1-second precision and your nanosecond clock goes wrong.sim/run.sh— builds the crate, renames the.soto.vpi, compiles your RTL, runsvvp. Adapt the template's three variables: crate name, top module name, RTL file list.- Your RTL, unmodified, in
hdl/.
Run sim/run.sh. When you see your smoke test pass, you have a live
Rust-to-simulator connection, and everything from here on is ordinary
(book-shaped) testbench work: BFM → driver and monitors → scoreboard →
sequences. The complete worked example is rustdv/tinyalu_tb/ in this
repo, and the book's Interlude chapter walks through every file of it.
Two tips for the growth phase:
- Want waveforms? Add a
dump.vnext to your RTL and pass-s dumpas a second top module to iverilog:module dump; initial begin $dumpfile("waves.vcd"); $dumpvars(0, my_top); end endmodule - A test hangs? The run prints a seed (
RUSTDV_RANDOM_SEED=...); re-run with the same seed and read the log from the top — a panic earlier in the log is the cause of a hang later in it, nine times out of ten.
Use model 1: writing the Rust yourself
Open my_core_tb/ in your IDE with rust-analyzer. The compiler is your
co-pilot here more than in any language you've used: most testbench wiring
mistakes (wrong transaction type on a port, missing connection, sharing a
value two tasks both mutate) are compile errors, and rust-analyzer shows
them as you type, before any simulation.
Work in this order, and don't skip step 1:
- Transactions + a predictor function, with
#[test]unit tests — verified in milliseconds withcargo test, no simulator. - The BFM (reset + one operation), exercised by a directed test.
- Monitors and a scoreboard; then sequences and random tests.
The SKILL.md files under .claude/skills/ are written for AI agents but
read perfectly well as human checklists — especially write-a-bfm (timing
conventions) and debug-a-regression.
Use model 2: letting Claude write it
This repository ships skills that teach Claude rustdv's setup steps, idioms, and debugging playbook. To use them:
-
Put the rustdv clone and your project in one folder (the
hobby/layout above) and open that folder in Claude Code or Cowork. -
Claude discovers
.claude/skills/automatically when working in the repo. If your project lives outside it, copy the.claude/directory to your project root — the skills travel well. -
Ask for what you want, and name the constraint that matters:
Build a rustdv testbench for the SPI core in
my-core/hdl/, using the skills in this repo andrustdv/tinyalu_tbas the reference. Start with a smoke test that proves the clock and reset work, show me the run output, and only then grow the BFM and scoreboard. -
Hold Claude to the same standard you'd hold yourself: every stage ends with a running regression (
REGRESSION: PASSis the only acceptable "done"), and a scoreboard isn't finished until a deliberately broken DUT makes it fail. Thedebug-a-regressionskill shows the mutation test; ask Claude to run it.
The two models mix well: let Claude scaffold the project and the BFM's timing loops, then write the interesting parts — the predictor, the sequences, the checks — yourself. That's where the verification thinking lives, and it's the part worth learning by hand.
Where to go next
- The book (
book-pdf/): chapters 1–14 teach the Rust; the Interlude walks the complete TinyALU testbench end to end. rustdv/tinyalu_tb/: the living reference — every pattern in the skills appears there in context.- The repository
README.md: the same testbench walked component by component, with the UVM-concept map. STATUS.md: the implementation history and the deviations log — what has been run, on what, and what is still missing.