Declarative Project Model
project.yml and ip.yml describe the design. Autodiscovery finds the sources, the dependency resolver orders them, and lock files pin the result. The same description builds on four vendor backends with no vendor TCL.
A command-line workflow for FPGA development, from project setup through verification and hardware deployment.
This is how IP gets developed with RouteRTL, from spec to hardware validation. Each stage is one rr command over a declarative project description. A human runs it from a terminal; an agent runs it unattended. The table shows both, side by side.
| Stage | The human | The shared surface | The agents |
|---|---|---|---|
| 01Spec | HumanWrites the design brief; reviews each requirement in a guided walkthrough and signs off before anything downstream exists. | requirements.yml — every requirement testable, tagged, citable | AgentsFills requirements from the brief, then walks the human through each one — rationale, edge cases, what a test would assert, and the strongest objection it can construct. |
| 02Describe | HumanDeclares board, top entity, and lint profile in one YAML file. No source lists, no compile order — discovery is the tool's job. | autodiscovery + dependency resolver own the build graph | AgentsQueries the schema before writing any key — never guesses a field name; a variant target overrides in its own file, never the shared root. |
| 03Author | HumanWrites HDL in any editor. Dropping a file into src/ is the entire integration step. | the resolved graph, inspectable at any moment | AgentsWrites HDL the same way, then verifies its place in the graph instead of assuming it — sources and dependencies are queryable facts. |
| 04Lint | HumanReads one report, tuned by the profile the project declares — not whatever a vendor tool felt like warning about. | profile-driven, identical verdict for every caller | AgentsGates itself: lints after every edit and iterates until clean, before a human ever sees the diff. |
| 05Verify | HumanScaffolds cocotb tests anchored to requirement tags; reads results knowing exactly which requirement each test defends. | @requires(REQ-N) ties every test back to the spec | AgentsAttacks the DUT adversarially — a green bar that found no bugs is a yellow flag. Defects get filed, never worked around. |
| 06Build | HumanSubmits synthesis, implementation, bitstream — then does something better with the next 40 minutes. | memory-aware admission, one arbiter for every caller | AgentsSubmit-then-poll: builds run contained and parallel-safe, and two agents can never collide on the same build slot. |
| 07Bring-up | HumanPrograms and verifies the board from the same terminal — and can confirm the silicon actually runs the bitstream just built. | rr hw bit-sha — the bitstream identity check | AgentsFully hands-off: takes a board lease, switches the power outlet itself, programs, verifies — no human asked to flip a switch. |
| 08Validate | HumanReads a validation run scored against a declared hardware contract — expected outcomes, not vibes. | runtimes/hw.yml — the bench, declared | AgentsExecutes the contract on real silicon, records pass / fail / unexercised per requirement, and promotes runs that earn it. |
| ↩Loop | HumanFiles findings and re-scopes. A hardware surprise becomes a ticket, not tribal memory. | the loop closes on the same artifacts it started from | AgentsFeeds findings back into requirements and tests autonomously — the next pass through the loop starts stronger than the last. |
Why the middle column matters: agents don't get a separate flow. Every stage an agent drives autonomously is the same command a human types — which is why adopting RouteRTL for your team and adopting it for your agents is the same decision, made once.
One CLI, rr, drives the whole flow: sources, lint, simulation, synthesis, bitstream, programming, and embedded Linux.
The project is a few declarative files, not scripts. A checkout builds the same on any machine, in CI, and across Vivado, Quartus, Radiant, and Libero.
Verification is part of the flow: requirements, simulation, formal proofs, and on-chip capture close into one loop.
project.yml and ip.yml describe the design. Autodiscovery finds the sources, the dependency resolver orders them, and lock files pin the result. The same description builds on four vendor backends with no vendor TCL.
Dependency Management (Cargo for FPGAs): IP resolves from a growing registry with license detection, ip.lock pins every dependency, and provenance and BOM reports record exactly what went into each artifact.
Each requirement stays linked to the tests, assertions, and formal properties that prove it. Coverage maps show which tests actually reached each requirement, and contract gates reject missing or vacuous evidence before it reaches CI.
Explore verification contractsThe smart linter enforces design rules for clocking, memory inference, and arithmetic before the tools run. When a vendor tool fails anyway, rr diagnose maps the log to known causes and fixes.
A SLURM-style queue arbitrates builds and simulations, leases give each user exclusive use of a shared board, and the embedded analyzer (REA) captures live signals from the running silicon.
The full loop runs through one CLI: requirement, lint, simulation, formal, synthesis, bitstream, programming, board evidence, and back to the requirement. Every step leaves an artifact an engineer can review, identical locally, in CI, and under pre-commit gates.
Every stage must give the next stage evidence that can be checked. Two cases get special attention: a test that passes without ever reaching the logic it claims to cover, and a formal proof that only holds because the signal it checks was never connected. In both cases RouteRTL reports a failure instead of a pass.
A feature starts as a written requirement. Everything downstream stays tied to it, so there is always something concrete to prove against.
The requirement becomes runnable tests that drive the design with hard-coded expectations. This is the first check of real behaviour against the requirement.
Coverage maps each requirement to the tests that actually reached it. A suite that passes without exercising the target logic does not count as covered.
Formal properties cover the corners simulation cannot reach. An anti-vacuity gate throws out any proof that only holds because nothing was connected behind it.
On the board, the embedded analyzer captures live signals from the running silicon. Hardware is checked against the same requirement, not assumed to match the simulation.
What the board reveals feeds the next requirement. The whole cycle runs as a budgeted loop session that closes on evidence, not on a green bar.
recorded: the coverage gate in use
Eight minutes on a real FIFO from the registry: the contract is scaffolded from the FIFO's own HDL (reset polarity observed in the source), four requirements are declared, and an agent (claude) implements them from the contract alone. The suite passes at two of four; the coverage map fails with exit 1 until the agent closes the gap.
The same FPGA work with and without a managed project flow.
IP is copied between projects by hand, with no record of version or origin.
Versioned modules, resolved and pinned, via rr pkg add
Source lists and compile order are maintained by hand in per-project scripts.
A topological sort derives the same compile order on every machine.
A separate Makefile flow per simulator: Modelsim, Vivado, GHDL.
One command for every simulator: rr sim run
The local environment and CI are set up separately and drift apart.
The same Docker-backed, pre-commit gated execution everywhere.
Add a UART module to the sensor hub and wire it to the main AXI bus.
Resolving dependencies, scaffolding tests…
UART IP added; testbench boilerplate scaffolded. Wiring next.
Graphical EDA tools, complex Makefiles, and undocumented TCL paths are hard to manage directly. RouteRTL provides a declarative, deterministic CLI contract built for headless execution and peer review.
Every command has a stable, scriptable interface. rr sim run and rr linting behave the same regardless of which vendor toolchain sits underneath.
From project.yml to CSR memory maps, the configuration layer stays machine-readable by design.
rr testgen and rr sim scaffold bootstrap testbenches, reducing boilerplate and keeping verification work focused.
rr exposes its tooling as a Model Context Protocol server. One command wires Claude Code, Cursor, Continue, or Zed into the rr surface — agents get direct access to rr_pkg_search, rr_doctor, rr_sim_*, rr_lint_*, rr_board_*, the rules engine, and the rest via .mcp.json.
Procedure-grade skills ship with the SDK — ip-registry-maintenance, fpga-avmm-hang-diagnose, vivado-batch-mode, zynq7-sd-boot-bringup, and more. Claude discovers them automatically when rr is installed; the right one fires for the right problem.
ip.lock pins what goes into a build; rr provenance proves what came out of it is current for the right part and target. The same records verify installed IP and export as a bill of materials.
Is the bitstream current, built from these sources, for this part and target? A non-zero exit gates the flow before a silently-wrong artifact ships.
rr provenanceEvery installed IP file is checked against the SHA-256 recorded in ip.lock — catching tampering, accidental edits, and corrupted downloads.
rr pkg verifyEvery IP with its version, commit, resolved license, tool inventory, and target device — exportable as CycloneDX or SPDX for compliance tooling.
rr bom --export cyclonedx -o sbom.cdx.jsonAn agent can repeat the flow; an engineer reviews the artifacts. Use rr hardware doctor for the connectivity preflight; board validation is captured by hardware contract runs.
what's in the box
78 seconds: rr init, lint, testgen, cocotb sim, yosys synth, nextpnr place-and-route, icepack bitstream. Target: iCE40 UP5K (iCEBreaker), open toolchain.