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.
| Task | Claude Quality | Notes |
|---|---|---|
| FSM design from state diagram / spec | Excellent | One-hot, binary, gray encoding; full case/parallel case |
| Synchronous FIFO (single-clock) | Excellent | Pointer arithmetic, full/empty flags, byte-enable variants |
| Parameterized module templates | Excellent | WIDTH, DEPTH, STAGES parameters with proper localparam |
| AXI4 / AXI4-Lite slave interfaces | Excellent | Spec-compliant handshake, burst mode, BRESP |
| RTL code review & lint | Excellent | Latches, reset, blocking/non-blocking, CDC flags |
| Testbench generation (basic) | Good | Directed tests; needs DV guide for coverage-driven TB |
| Async FIFO (dual-clock) | Good | Gray code pointers — always verify metastability margins |
| Synthesis optimization hints | Good | Retiming suggestions, false path candidates, don't-touch |
| Custom cell primitives (stdcell-level) | Fair | Requires pdk documentation in context |
Claude excels at FSMs. The key: describe states, transitions, and outputs in plain English — Claude handles encoding, reset, and full_case automatically.
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
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]
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
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.
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
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.
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]
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)
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]
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]
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
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]
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.
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]
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]
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.
Ask for the module skeleton: port list, parameter declarations, typedef enums for FSM states, and internal signal declarations. No logic yet — just the framework.
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.
Use Prompt #7 above to run a comprehensive review. Fix any CRITICAL issues immediately. Document WARN items for the DV team.
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).
Run through DC/Vivado. Paste synthesis warnings back to Claude — ask it to explain each warning and suggest RTL fixes.
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.
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.
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.
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.
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.
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.