RTL Review Lab

An LLM reviews Verilog work products against a 9-rule checklist; every number comes from planted defects with known ground truth. Code: github.com/pavanyadava007/rtl-review-lab

Browse the held-out files

Pick a file: the yellow line is where the defect was planted. Green findings match the planted defect, red ones are false positives. LLM run shown: . The first file is a spec constant the LLM caught and lint cannot see.

Results

Measured 2026-09-29 on one NVIDIA L4 (Qwen3-Coder 30B and Qwen2.5-Coder 7B through Ollama, temperature 0.3). Regenerate everything with make report; raw per-review output is in results/raw.jsonl.

What the numbers say

Scoring checks the rule and the location, not the wording of the explanation. A manual read of the 9 hits on review-only rules in one held-out walkthrough run (seed 0): 8 explain the defect correctly, 1 names the right register and rule but gives a wrong reason. A reviewer still has to read the finding.

Three things I got wrong first and fixed before the final runs: the model's answer to the same prompt changed between Ollama's cached and uncached evaluation, so every LLM number is averaged over three seeds; the mutant generator once named a planted signal unused_bits, and Verilator's default --unused-regexp is *unused*, so lint was told to ignore it (renamed, affected files re-run); and a random testbench retriggered timers too often to expose some spec defects, so validation now uses three stimulus settings.

Held-out test modules (11 modules, planted defects and clean files)

Reviewerseedsrecallprecisionfalse findings per clean fileclean files with 0 findings
lint (Verilator + Yosys)10.560.950.001.00
qwen2.5-coder:7b, walkthrough, prompt v230.65 ± 0.040.43 ± 0.042.00 ± 0.340.55 ± 0.07
hybrid: lint + qwen2.5-coder:7b, walkthrough, prompt v2 (review-only rules)30.64 ± 0.040.65 ± 0.030.79 ± 0.300.67 ± 0.04
qwen3-coder:30b, checklist, prompt v230.48 ± 0.020.34 ± 0.040.09 ± 0.130.97 ± 0.04
hybrid: lint + qwen3-coder:30b, checklist, prompt v2 (review-only rules)30.80 ± 0.010.70 ± 0.030.06 ± 0.090.97 ± 0.04
qwen3-coder:30b, checklist+lint, prompt v230.77 ± 0.010.68 ± 0.030.001.00
hybrid: lint + qwen3-coder:30b, checklist+lint, prompt v2 (review-only rules)30.77 ± 0.010.78 ± 0.030.001.00
qwen3-coder:30b, spectable, prompt v210.650.840.001.00
hybrid: lint + qwen3-coder:30b, spectable, prompt v2 (review-only rules)10.680.900.001.00
qwen3-coder:30b, verify, prompt v230.66 ± 0.010.95 ± 0.030.001.00
hybrid: lint + qwen3-coder:30b, verify, prompt v2 (review-only rules)30.69 ± 0.010.96 ± 0.010.001.00
qwen3-coder:30b, walkthrough, prompt v230.70 ± 0.010.93 ± 0.010.001.00
hybrid: lint + qwen3-coder:30b, walkthrough, prompt v2 (review-only rules)30.70 ± 0.010.95 ± 0.010.001.00
post hoc: lint + walkthrough (R02, R04) + spectable (R07, R08)10.770.920.001.00

Recall per rule (held-out; * = rule lint tools cannot see)

Rulenlint (Verilator + Yosys)qwen2.5-coder:7b, walkthrough, prompt v2hybrid: lint + qwen2.5-coder:7b, walkthrough, prompt v2 (review-only rules)qwen3-coder:30b, checklist, prompt v2qwen3-coder:30b, checklist+lint, prompt v2qwen3-coder:30b, spectable, prompt v2qwen3-coder:30b, verify, prompt v2qwen3-coder:30b, walkthrough, prompt v2hybrid: lint + qwen3-coder:30b, walkthrough, prompt v2 (review-only rules)post hoc: lint + walkthrough (R02, R04) + spectable (R07, R08)
R01 Non-blocking assignments in clocked blocks101.000.971.001.001.001.001.001.001.001.00
R02 Complete reset *100.000.100.100.930.900.200.570.600.600.70
R03 No latches11.001.001.001.001.001.001.001.001.001.00
R04 Complete sensitivity list *10.000.000.000.000.000.000.000.000.000.00
R05 Matching widths101.001.001.000.001.000.800.831.001.001.00
R06 No unused signals111.001.001.000.301.001.001.001.001.001.00
R07 Constants match the specification *90.000.300.300.330.220.440.180.220.220.44
R08 Boundary conditions match the specification *30.000.330.330.330.220.330.000.000.000.33
R09 Safe FSM default *20.000.330.000.000.000.000.000.000.000.00

Dev modules (prompt iteration, 6 modules, 1 seed)

Reviewerseedsrecallprecisionfalse findings per clean fileclean files with 0 findings
lint (Verilator + Yosys)10.610.810.001.00
qwen3-coder:30b, checklist, prompt v110.610.192.000.33
hybrid: lint + qwen3-coder:30b, checklist, prompt v1 (review-only rules)10.900.570.500.67
qwen3-coder:30b, checklist, prompt v210.580.231.830.33
hybrid: lint + qwen3-coder:30b, checklist, prompt v2 (review-only rules)10.840.600.500.67
qwen3-coder:30b, checklist+lint, prompt v110.840.371.500.33
hybrid: lint + qwen3-coder:30b, checklist+lint, prompt v1 (review-only rules)10.840.580.830.33
qwen3-coder:30b, checklist+lint, prompt v210.840.463.170.50
hybrid: lint + qwen3-coder:30b, checklist+lint, prompt v2 (review-only rules)10.840.572.670.50
qwen3-coder:30b, spectable, prompt v210.710.700.001.00
hybrid: lint + qwen3-coder:30b, spectable, prompt v2 (review-only rules)10.740.720.001.00
qwen3-coder:30b, walkthrough, prompt v110.870.670.170.83
hybrid: lint + qwen3-coder:30b, walkthrough, prompt v1 (review-only rules)10.870.780.001.00
qwen3-coder:30b, walkthrough, prompt v210.810.750.001.00
hybrid: lint + qwen3-coder:30b, walkthrough, prompt v2 (review-only rules)10.810.820.001.00
post hoc: lint + walkthrough (R02, R04) + spectable (R07, R08)10.840.730.001.00

Review time (NVIDIA L4, Ollama, all runs)

Reviewerreviewsmedian seconds per filemean
qwen2.5-coder:7b, walkthrough2049.711.5
qwen3-coder:30b, checklist2782.43.3
qwen3-coder:30b, checklist+lint2782.33.3
qwen3-coder:30b, spectable10531.634.4
qwen3-coder:30b, verify20410.812.4
qwen3-coder:30b, walkthrough2786.57.8