Step 4 of 9 — Claude for VLSI Series

RTL Design Engineer Guide

Your complete playbook for using Claude in RTL design work — from first-pass module generation to deep code review, FSM design, FIFO implementation, and AXI4 interfaces.

FSM Design FIFO AXI4 Code Review Linting Parameterization Reset Strategy 15+ Prompts
SPEC Ask Claude to outline design SKELETON Ports, params, signal decls LOGIC Fill always blocks, FSM, datapath REVIEW Lint, reset, CDC, synthesis TESTBENCH Auto-generate sim + assertions TAPEOUT ✓ Ship it

01 What Claude Does Best for RTL Engineers

TaskClaude QualityNotes
FSM design from state diagram / specExcellentOne-hot, binary, gray encoding; full case/parallel case
Synchronous FIFO (single-clock)ExcellentPointer arithmetic, full/empty flags, byte-enable variants
Parameterized module templatesExcellentWIDTH, DEPTH, STAGES parameters with proper localparam
AXI4 / AXI4-Lite slave interfacesExcellentSpec-compliant handshake, burst mode, BRESP
RTL code review & lintExcellentLatches, reset, blocking/non-blocking, CDC flags
Testbench generation (basic)GoodDirected tests; needs DV guide for coverage-driven TB
Async FIFO (dual-clock)GoodGray code pointers — always verify metastability margins
Synthesis optimization hintsGoodRetiming suggestions, false path candidates, don't-touch
Custom cell primitives (stdcell-level)FairRequires pdk documentation in context

02 FSM Design Prompts

Claude excels at FSMs. The key: describe states, transitions, and outputs in plain English — Claude handles encoding, reset, and full_case automatically.

1
Mealy FSM from State Description
Converts plain-English state description to synthesizable one-hot FSM
Act as a senior RTL engineer. Write a synthesizable SystemVerilog Mealy FSM.

States: IDLE, ARBIT, GRANT, WAIT, DONE
Transitions:
- IDLE → ARBIT when req is asserted
- ARBIT → GRANT when gnt_in is received
- GRANT → WAIT after 1 cycle
- WAIT → DONE when ack is received, else stay in WAIT
- DONE → IDLE unconditionally next cycle
- Any state → IDLE if rst_n is deasserted

Outputs:
- grant_out: assert only in GRANT state
- busy: assert in ARBIT, GRANT, WAIT states

Requirements:
- One-hot encoding
- Synchronous active-low reset
- Non-blocking assignments (<=) throughout
- Include `full_case parallel_case pragmas
- 2-space indentation
- Add the state as an enum typedef
2
FSM Review — Find All Issues
Deep review of an existing FSM for synthesis and logic bugs
Review this FSM for all issues. Check in this order:

1. LATCH INFERENCE — any state or output without a default assignment?
2. RESET COMPLETENESS — every register reset in the reset clause?
3. FULL CASE — are all possible state values covered?
4. ENCODING — is the declared encoding consistent with usage?
5. OUTPUT GLITCHES — any combinational outputs that could glitch?
6. CDC RISK — any signals crossing from/to this FSM to a different clock domain?

Report each issue as:
[SEVERITY: CRITICAL/WARN/INFO] Line XX — category — description — fix

[PASTE FSM RTL HERE]

03 FIFO Design Prompts

3
Synchronous FIFO — Full Implementation
Complete parameterized sync FIFO with full/empty/almost-full flags
Act as a senior RTL engineer. Write a complete synchronous FIFO in SystemVerilog.

Parameters:
- DATA_WIDTH = 32 (default)
- DEPTH = 512 (default, must be power of 2)
- ALMOST_FULL_THRESH = 8

Ports:
- clk, rst_n
- wr_en, wr_data[DATA_WIDTH-1:0]
- rd_en, rd_data[DATA_WIDTH-1:0]
- full, almost_full, empty, almost_empty
- count[$clog2(DEPTH):0]  // occupancy counter

Requirements:
- Use $clog2(DEPTH)+1 wide pointers for full/empty disambiguation
- Non-blocking assignments only
- Simultaneous read+write when not empty/full must work correctly
- Use an always_ff block for registers, always_comb for combinational
- Add 2 SVA assertions: no write when full, no read when empty
- Synthesizable — no initial blocks
4
Async FIFO — Dual-Clock with Gray Code Pointers
CDC-safe async FIFO using Gray-coded pointer synchronization
Act as a senior RTL engineer with deep CDC expertise.
Write a dual-clock asynchronous FIFO in SystemVerilog.

Parameters: DATA_WIDTH=32, DEPTH=16 (power of 2)

Write clock domain (wr_clk): wr_en, wr_data, full
Read clock domain  (rd_clk): rd_en, rd_data, empty

Requirements:
- Gray-coded write/read pointers
- 2-FF synchronizer for pointer crossing (wr→rd and rd→wr)
- Binary pointers for memory addressing, Gray for CDC
- Separate resets for each domain (wr_rst_n, rd_rst_n)
- Memory array inferred as synchronous RAM
- Non-blocking assignments everywhere
- Comment each clock domain boundary clearly

Also explain: why Gray code is necessary here and what happens
if we used binary pointers instead.

04 AXI4 Interface Prompts

5
AXI4-Lite Slave — Register Map
Complete AXI4-Lite slave with configurable register map
Write a synthesizable AXI4-Lite slave in SystemVerilog.

Register map (base address 0x0):
- 0x00: CTRL_REG  [31:0] — R/W, reset=0
- 0x04: STATUS_REG[31:0] — RO, driven by hardware inputs
- 0x08: IRQ_REG   [31:0] — R/W1C (write 1 to clear)
- 0x0C: VERSION   [31:0] — RO, constant = 32'h0100_0001

AXI4-Lite parameters: DATA_WIDTH=32, ADDR_WIDTH=8

Requirements:
- AWVALID/AWREADY, WVALID/WREADY, BVALID/BREADY handshake
- ARVALID/ARREADY, RVALID/RREADY handshake
- BRESP and RRESP = 2'b00 (OKAY) for valid, 2'b10 (SLVERR) for bad addr
- Non-blocking assignments, synchronous active-low reset
- Separate always_ff for write address, write data, read logic
- IRQ_REG must OR-reduce input irq_src[31:0] on write 0 side
6
AXI4 Full — Burst Write Slave
AXI4 full-spec burst write with INCR support
Write an AXI4 burst write slave in SystemVerilog. Support INCR burst type only.

Parameters: ID_WIDTH=4, DATA_WIDTH=64, ADDR_WIDTH=32, MAX_BURST=256

State machine required for write path:
- IDLE → AW_RECV (when AWVALID) → W_RECV (stream write data) → B_RESP

Beat counting:
- Use AWLEN to count beats (AWLEN+1 beats per burst)
- Strobe (WSTRB) must gate each byte lane of write data
- Assert BVALID only after WLAST received

Error handling:
- Assert BRESP=SLVERR if AWADDR is out of range
- Assert BRESP=SLVERR if AWBURST != 2'b01 (non-INCR)

After writing the RTL, list the 3 most common AXI4 protocol
violations you see in real designs and how to detect them.

05 Code Review & Lint Prompts

7
Full RTL Code Review
Comprehensive review covering synthesis, lint, and functional issues
Act as a senior RTL design engineer doing a pre-tape-out code review.
Review the following SystemVerilog module and check ALL of these:

SYNTHESIS ISSUES:
□ Latch inference (incomplete if/case without defaults)
□ Combinational loops
□ Inferred vs. explicit RAM primitives
□ Multi-driven nets

CODING STYLE:
□ Blocking assignments in clocked blocks (must use <=)
□ Non-blocking assignments in combinational blocks (use =)
□ Missing default in case statements
□ Magic numbers (use parameters/localparams)

FUNCTIONAL RISKS:
□ Reset completeness — every FF must reset
□ Unused signals / undriven inputs
□ Integer overflow in counter arithmetic
□ Off-by-one in FIFO pointers or address decode

CDC RISKS:
□ Signals crossing clock domains without synchronizers
□ Multi-bit signals crossing domains without encoding

Format each issue: [SEVERITY] Line:XX — Category — Issue — Fix
SEVERITY: CRITICAL | WARNING | INFO

[PASTE MODULE HERE]
8
Debug Simulation Mismatch
Root cause analysis for RTL behavior that doesn't match expectation
I have a simulation mismatch. Help me debug.

SYMPTOM: [describe exactly what signal is wrong, at what time, value seen vs expected]
Example: "At T=150ns, out_data shows 0xDEAD but I expect 0xBEEF.
         This happens only when wr_en and rd_en are both asserted simultaneously."

TESTBENCH STIMULUS:
[paste relevant waveform or test sequence]

RTL MODULE:
[paste the relevant module or portion]

Think step by step:
1. Identify the exact signal path from input to the failing output
2. Find the cycle where the signal first diverges from expected
3. State the most likely root cause (priority encoder, missing case, wrong reset)
4. Propose a minimum-diff fix (change only what's needed)

06 Parameterization & Reuse Prompts

9
Parameterize an Existing Module
Convert hardcoded widths/depths to proper parameters with generate
Refactor this RTL module to be fully parameterized. Rules:
- Replace all hardcoded bit-widths with parameters
- Use $clog2() for address width derived from depth
- Add localparam for any derived constants
- Add parameter validation using an initial block assertion:
  initial begin
    assert(DATA_WIDTH > 0 && DATA_WIDTH <= 128)
      else $fatal("DATA_WIDTH out of range");
  end
- Keep the interface identical — only add parameters, don't change port names
- Ensure the module still synthesizes with default parameter values

[PASTE MODULE HERE]
10
Generate Testbench + Assertions
Auto-generate a directed testbench with SVA checkers
Write a SystemVerilog testbench for the module below.

Requirements:
- Clock gen: 10ns period (100MHz)
- Active-low synchronous reset for first 5 cycles
- Test cases to include:
  1. Basic functional test (normal operation)
  2. Back-to-back operations (no idle cycles between)
  3. Reset in the middle of operation
  4. Boundary values (min/max inputs)
- SVA assertions bound to the DUT:
  - At least 1 assertion per major interface signal
  - Include $past() for checking registered behavior
- Use $display with timestamps for debug
- Add a PASS/FAIL summary at end of sim ($finish)

[PASTE MODULE UNDER TEST HERE]

07 Advanced RTL Prompts

11
Pipeline Stage Insertion
Add pipeline registers to a combinational path to hit timing
My critical path has 47ns of combinational logic and my target clock is 1GHz (1ns).
I need to insert pipeline stages to meet timing.

Given this combinational datapath:
[PASTE COMBINATIONAL ALWAYS BLOCK OR ASSIGN STATEMENTS]

Instructions:
1. Identify the natural cut points (after each major operation)
2. Insert N pipeline register stages (I'll tell you N, default=2)
3. Add pipeline valid/enable signals so partial stalls work correctly
4. Maintain the same input/output interface — add only _pipe_q suffix registers
5. Show the retimed latency table: original 0-cycle vs N-cycle pipeline
12
Reset Strategy Audit
Check and fix async vs sync reset usage across a module
Audit the reset strategy in this RTL module.

My project standard: synchronous active-low reset (posedge clk, no negedge rst_n).

Check and fix:
1. Any asynchronous reset (negedge rst_n in sensitivity list) — convert to sync
2. Any signal missing reset (not assigned in the if(!rst_n) branch)
3. Any reset value that looks wrong (non-zero reset for a counter etc.)
4. Any multi-cycle reset concern (reset de-assertion synchronization)

For each issue, show: original line → corrected line

[PASTE MODULE HERE]
13
Round-Robin Arbiter
Fair arbitration logic for N requestors
Write a parameterized round-robin arbiter in SystemVerilog.

Parameters: N_REQ = 4 (number of requestors)

Interface:
- clk, rst_n
- req[N_REQ-1:0]    // request vector (any bit can be set)
- grant[N_REQ-1:0]  // one-hot grant output
- grant_valid        // pulse when grant is issued

Behavior:
- At most one grant per cycle
- Round-robin priority: after granting requestor I, next grant
  considers I+1 first, wrapping around
- If no request is active, grant_valid is low
- Grant is registered (no combinational output on grant)

Add a fairness assertion: no single requestor can be starved
for more than N_REQ cycles when it is continuously requesting.
14
Explain a Complex RTL Module
Understand inherited or third-party RTL quickly
Explain this RTL module to me as if I'm a senior engineer seeing it for the first time.

Structure your explanation as:
1. PURPOSE — what does this module do in one sentence?
2. INTERFACE — explain each port (direction, purpose, any protocol)
3. KEY LOGIC BLOCKS — explain each always/assign block in plain English
4. STATE MACHINE (if any) — list states and what each one does
5. TIMING — any multi-cycle paths, pipeline stages, or timing-sensitive logic?
6. POTENTIAL ISSUES — anything that looks risky or non-standard?

[PASTE MODULE HERE]
15
Synthesis Pragma Optimizer
Add correct synthesis attributes and pragmas for DC/Vivado
Add synthesis pragmas/attributes to this RTL module for Synopsys DC.

Add the following where appropriate:
- /* synthesis full_case */ on case statements with all cases covered
- /* synthesis parallel_case */ where priority encoder is not intended
- (* dont_touch = "true" *) on signals that must not be optimized away
- (* max_fanout = "32" *) on high-fanout control signals
- syn_keep / keep attributes on debug signals
- Identify any nets that should be set_dont_touch in SDC instead

After the annotated RTL, provide the companion SDC commands
(set_false_path, set_multicycle_path) for any paths you identified.

[PASTE MODULE HERE]

08 Recommended RTL Design Workflow with Claude

1

Spec → Outline

Paste your spec or describe in plain English. Ask Claude to output a design outline: ports, parameters, key internal signals, and state machine structure. Validate this before writing any code.

2

Generate Skeleton

Ask for the module skeleton: port list, parameter declarations, typedef enums for FSM states, and internal signal declarations. No logic yet — just the framework.

3

Fill Logic Block by Block

Add the FSM next-state logic first, then registered outputs, then combinational logic. Ask Claude to fill one always block at a time — check each before continuing.

4

Code Review Pass

Use Prompt #7 above to run a comprehensive review. Fix any CRITICAL issues immediately. Document WARN items for the DV team.

5

Generate Testbench

Use Prompt #10 to auto-generate a directed testbench. Run simulation. Paste any failures back into Claude with the waveform description for debug (Prompt #8).

6

Synthesis Check

Run through DC/Vivado. Paste synthesis warnings back to Claude — ask it to explain each warning and suggest RTL fixes.

Always Verify Generated RTL

Claude's RTL is typically ~90% correct on first pass for standard patterns. Always run lint (SpyGlass/Verilator) and simulation on every generated module. For async FIFOs and CDC structures, also run formal CDC analysis — Claude cannot simulate metastability.

FAQ RTL Engineer Questions

Can Claude write synthesizable Verilog RTL? +

Yes. Claude generates synthesizable Verilog and SystemVerilog — FSMs, FIFOs, AXI interfaces, parameterized modules, and more. Always use non-blocking assignments in clocked blocks and verify outputs through your lint/simulation flow. Claude achieves ~90% correct RTL on the first pass for standard design patterns.

How do I use Claude to review RTL code? +

Paste your RTL module and ask Claude to check for: latch inference, reset completeness, non-blocking assignment violations, clock domain crossing risks, and synthesis pragma usage. Specify your tool (Synopsys DC, Vivado) for tool-specific advice.

Can Claude debug simulation mismatches? +

Yes. Share the failing waveform description or assertion message, the relevant RTL, and the expected behavior. Ask Claude to trace through the logic step-by-step using chain-of-thought prompting.

How do I get Claude to follow my team's RTL coding style? +

Create a Project with a system prompt defining your style: non-blocking assignments, naming conventions (_q suffix for registers, _d for next-state), indentation, parameter placement, port ordering. Include one example module in your style — Claude will match it precisely.

What RTL tasks is Claude NOT good at? +

Claude struggles with: analog/mixed-signal design, technology-specific primitives without documentation, precise timing constraints that depend on place-and-route results, and very long (>2000 line) RTL modules where it may miss cross-module interactions. Always simulate and lint every generated RTL.