Claude Code-driven RTL design pipeline — zero Python dependencies, Claude Code main session is the driver.
VeriFlow-CC treats Claude Code as the pipeline brain: the main Claude Code session controls stage transitions, calls a sub-agent for RTL generation, and handles errors and rollbacks.
Differences from the full VeriFlow-Agent:
- No LangGraph / LangChain / Streamlit
- No
pip installrequired - Claude Code itself is the interaction and decision layer
- State persisted to JSON, recoverable after session restart
User types /vf-rtl <project_dir>
↓
Main Claude (skill prompt injected)
│
├→ Step 0: init + clarification → eda_env.sh, clarifications.md
├→ Stage 1: spec_golden (vf-spec-golden merged agent)
│ → spec.json + golden_model.py
├→ Stage 2: codegen (vf-coder AI assembly per module, parallel)
│ → rtl/*.v
├→ Stage 3: verify_fix (inline sim + error recovery, 3-retry budget)
│ → logs/sim.log, expected_trace_*.md, VCD analysis
└→ Stage 4: lint_synth (vf-linter + vf-synthesizer, parallel)
→ logs/lint.log + synth_report.txt
4 stages: spec_golden → codegen → verify_fix → lint_synth. Sub-agents handle specialist work (RTL coding, lint, synthesis). Main session handles orchestration and error recovery.
git clone https://github.com/bjwanneng/veriflow-cc.git
cd veriflow-cc
python install.pyInstalls to ~/.claude/:
skills/vf-rtl/SKILL.md— Pipeline orchestration skillskills/vf-rtl/state.py— State managementskills/vf-rtl/vcd2table.py— VCD waveform analysisskills/vf-rtl/coding_style.md— Verilog coding style rulesskills/vf-rtl/cocotb_runner.py— Cocotb simulation runnerskills/vf-rtl/iverilog_runner.py— Pure-Verilog simulation runnerskills/vf-rtl/timing_contract_checker.py— Timing contract validatoragents/vf-coder.md— RTL code generation sub-agentagents/vf-spec-golden.md— Spec + golden model generation sub-agentagents/vf-tb-gen.md— Testbench generation sub-agentagents/vf-linter.md— Lint sub-agentagents/vf-synthesizer.md— Synthesis sub-agent
Uninstall: python install.py --uninstall
my_alu/
├── requirement.md # Functional requirements (required)
├── constraints.md # Design constraints (optional)
├── design_intent.md # Preliminary design ideas (optional)
└── context/ # Reference materials (optional)
└── reference.md
Input files:
| File | Required | Description |
|---|---|---|
requirement.md |
Yes | Functional requirements: what the design does |
constraints.md |
No | Timing, area, power, IO constraints |
design_intent.md |
No | Architecture preferences, IP reuse, design decisions |
context/*.md |
No | Reference materials, IP docs, datasheets |
If optional files are missing, the pipeline asks targeted clarification questions during Step 0.
/vf-rtl /path/to/my_alu
Strict sequential execution, no skipping:
spec_golden → codegen → verify_fix → lint_synth
1 2 3 4
| Stage | Type | Input | Output |
|---|---|---|---|
| spec_golden | LLM (vf-spec-golden) | requirement.md, constraints.md, design_intent.md, context/ | spec.json + golden_model.py |
| codegen | vf-coder sub-agent (AI assembly per module, parallel) | spec.json, golden_model.py, coding_style.md | rtl/*.v |
| verify_fix | EDA (iverilog+vvp or cocotb) + error recovery | rtl/.v, tb/.v, golden_model.py | logs/sim.log, VCD waveform analysis, expected_trace_*.md |
| lint_synth | EDA (iverilog + yosys, parallel) | rtl/*.v | logs/lint.log + synth_report.txt |
Stage 1 produces golden_model.py which serves as both reference model and test vector generator:
- Algorithm implementation with cycle-accurate trace output
- Test vectors validated against spec.json timing contracts
- Used by vcd2table.py for waveform diff during error recovery
The vf-coder sub-agent includes 5 inline Verilog-2005 mini-patterns:
- FSM (three-block: state-reg + next-state + outputs)
- Hash round (single-cycle registered)
- Pipeline register (2-stage with valid passthrough)
- Handshake (hold_until_ack)
- Barrel shifter (variable-distance rotation, Verilog-2005 legal)
These give the LLM concrete register-transfer skeletons to adapt, eliminating the need for external reference implementations.
vf-coder.md includes 7 common pitfalls (P1–P7) from SM3 retrospective:
- Combinational latches from incomplete
always @* validpulse cleared one cycle too early- Missing
defaultin FSMcase - Counter rollover via implicit overflow
validanddataupdated in different cycles- Using
_nextvalue as if it were a register - Reset polarity mix-up
Mandatory 7-point pre-write self-check ensures every module is verified before writing.
Before proceeding past Stage 1, a readiness check validates spec.json and golden_model.py for completeness.
EDA tool paths (iverilog, vvp, yosys) are discovered once in Step 0 and saved to .veriflow/eda_env.sh. Every subsequent EDA command sources this file, avoiding the "PATH doesn't persist between Bash calls" issue. eda_env.sh also exports PYTHONPATH pointing at the installed skill directory, so helper scripts can import state.py without per-call PYTHONPATH prefixes.
All EDA outputs are saved to log files for post-run analysis:
logs/lint.log— iverilog syntax check outputlogs/sim.log— integration simulation outputlogs/sim.raw.log— raw simulation output (iverilog_runner --save-raw-log)logs/wave_diff.txt— VCD vs golden model comparisonlogs/wave_table.txt— VCD waveform cycle tablelogs/expected_trace_golden.md— per-cycle register traces from golden_model.py (Stage 3 error recovery)logs/timing_diagnostic.json— bug classification + fix suggestionslogs/prev_failure_summary.md— concise failure summary injected to next vf-coder retryworkspace/synth/synth_report.txt— yosys synthesis report
The simulation hook uses strict 3-layer verification on logs/sim.log:
- File must exist and be non-empty
- No lines matching
[FAIL]orFAILED:prefix - Must contain an explicit
ALL TESTS PASSEDsummary line
This prevents false-positive "all green" when sim.log contains both passing and failing tests, or is empty.
Stage 3 (verify_fix) uses cocotb (Python co-simulation) as the primary simulation path when available:
- cocotb's
await RisingEdge(dut.clk)fires via VPI callback AFTER the NBA region, eliminating all Verilog TB-DUT race conditions - Per-cycle internal register comparison against golden model trace
- Cycle-level timing contract assertions (registered output stability, pipeline delay)
- Falls back to Verilog
$display-based testbenches when cocotb is unavailable
When simulation fails:
timing_diagnostic.pyclassifies the bug (A=computation, B=timing offset, D=initialization)- A concise
prev_failure_summary.mdis built with cycle, signal, expected, actual, and fix suggestion - This summary is injected into the next vf-coder retry via
PREV_FAILUREfield - The retry addresses the exact divergence before any other rewriting
spec.json port definitions are locked after Stage 1. Port semantic fields enforce consistent interpretation across all stages:
reset_polarity:"active_high"only (reset ports must declare this)handshake:"hold_until_ack"|"single_cycle"|"pulse"(valid ports must declare this)ack_port: name of the associated ack input (required forhold_until_ack)
spec.json includes machine-verifiable timing contracts for every inter-module connection:
producer_cycle,visible_cycle,consumer_cycle— exact cycle relationshipssame_cycle_visible,pipeline_delay_cycles— registered vs combinational semanticssample_phase— posedge or negedge sampling, preventing TB/DUT races
- Structured Root Cause Analysis: Before modifying any file, must complete a 5-point analysis (error location → signal trace → root cause hypothesis → minimal fix plan → impact scope) written to
stage_journal.md - Golden model comparison: Run golden model with failing test inputs and compare intermediate values with RTL output
- Per-cycle trace diff:
logs/expected_trace_golden.md(from golden_model.py) vs VCD-derived actual values — the fastest way to localise the wrong NBA assignment - Failure feedback injection:
prev_failure_summary.mdis passed to next vf-coder retry targeting the exact divergence - 3-retry budget: Stops after 3 failed fix attempts and asks user for help
- File control: No new
.vfiles during error recovery; debug artifacts cleaned up after each attempt - Testbench rule: TB infrastructure bugs may be fixed; assertions must not be weakened
my_project/
├── requirement.md # Functional requirements (required)
├── constraints.md # Timing, area, power, IO constraints (optional)
├── design_intent.md # Architecture preferences, IP reuse (optional)
├── context/ # Reference materials (optional)
├── .veriflow/
│ ├── pipeline_state.json # Pipeline state (resumable)
│ └── eda_env.sh # EDA tool paths + PYTHONPATH (auto-generated)
├── logs/
│ ├── lint.log # iverilog lint output
│ ├── sim.log # Integration simulation output
│ ├── sim.raw.log # Raw simulation log
│ ├── wave_diff.txt # VCD vs golden model comparison
│ ├── wave_table.txt # VCD waveform cycle table
│ ├── expected_trace_golden.md # Per-cycle register traces from golden_model.py
│ ├── timing_diagnostic.json # Bug classification + fix suggestions
│ └── prev_failure_summary.md # Concise failure summary for retry
└── workspace/
├── docs/
│ ├── spec.json # Interface spec (ports, constraints, timing contracts)
│ └── golden_model.py # Reference model with cycle-accurate trace
├── rtl/ # Generated Verilog files
├── tb/ # Testbenches (one per module + integration)
├── sim/ # Compiled simulation (.vvp files)
└── synth/
└── synth_report.txt # Yosys synthesis report
veriflow-cc/
├── src/
│ ├── claude_skills/
│ │ └── vf-rtl/
│ │ ├── SKILL.md # Pipeline orchestration skill
│ │ ├── state.py # State machine (JSON persistence)
│ │ ├── init.py # Project init (discovers EDA, writes eda_env.sh)
│ │ ├── vcd2table.py # VCD waveform to cycle table converter
│ │ ├── iverilog_runner.py # Pure-Verilog simulation runner
│ │ ├── cocotb_runner.py # Cocotb simulation runner
│ │ ├── timing_diagnostic.py # Bug classification + fix suggestions
│ │ ├── timing_contract_checker.py
│ │ ├── error_recovery.md # Stage 3 error recovery procedure
│ │ ├── design_rules.md # Design rules for all stages
│ │ ├── coding_style.md # Verilog-2005 coding rules
│ │ └── templates/ # Template files for sub-agents
│ │ ├── spec_template.json
│ │ ├── golden_model_template.py
│ │ ├── cocotb_template.py
│ │ └── tb_integration_template.v
│ └── claude_agents/
│ ├── vf-spec-golden.md # Spec + golden model generation (Stage 1)
│ ├── vf-coder.md # RTL code generation (Stage 2)
│ ├── vf-tb-gen.md # Testbench generation
│ ├── vf-linter.md # Lint sub-agent (Stage 4)
│ └── vf-synthesizer.md # Synthesis sub-agent (Stage 4)
├── install.py # Python installer (symlinks to ~/.claude/)
├── tests/ # Test suite (pytest + unittest)
├── CLAUDE.md # Claude Code project instructions
└── README.md # This file
- Python 3.10+ (for state.py, no pip packages)
- Claude Code (logged in)
iverilog/vvp(optional, for lint/sim stages)yosys(optional, for synth stage)
No pip install required.
Run all tests:
python -m pytest tests/ -qOr with unittest:
python -m unittest discover tests -vpython install.py --uninstallEnsure the agent's tools field uses comma-separated capitalized names:
# WRONG — causes silent tool permission failure
tools:
- read
- write
# CORRECT
tools: Read, Write, Glob, Grep, BashSee GitHub Issue #12392 for details.
iverilog needs its internal drivers (ivlpp, ivl) which live in lib/ivl/. The pipeline auto-discovers and saves these paths. Verify with:
source .veriflow/eda_env.sh && iverilog -VThe sim hook uses strict 3-layer verification: (1) sim.log must be non-empty, (2) no [FAIL] or FAILED: lines, (3) must contain ALL TESTS PASSED. If your testbench prints [FAIL] in passing messages (e.g., "checking FAIL case"), use a different format to avoid triggering Layer 2.
Add WeChat for more details and discussion: