| name | localv-exploiting-information-locality |
| description | Multi-agent framework for generating large-scale Verilog/RTL code from long hardware specifications by decomposing long-document-to-long-code into short-document, short-code tasks via information locality. Triggers: 'generate Verilog from spec', 'RTL generation from documentation', 'hardware code from specification document', 'decompose HDL generation', 'multi-module Verilog generation', 'IP-level code generation'. |
LocalV: Exploiting Information Locality for Scalable RTL Code Generation
This skill enables Claude to generate large-scale Register-Transfer Level (RTL) Verilog code from lengthy hardware specification documents by applying the LocalV decomposition strategy. Instead of attempting monolithic long-document-to-long-code generation (which degrades in both syntactic and semantic correctness), this approach partitions specifications hierarchically, generates code per-submodule with only locally relevant context, merges fragments with interface consistency checks, and debugs errors using AST-guided fault localization. The core insight is information locality: in modular hardware design, the information needed to implement a code unit is concentrated in a small subset of the specification.
When to Use
- When the user asks to generate Verilog or SystemVerilog from a multi-page hardware specification document (e.g., an IP datasheet, interface spec, or architecture description)
- When generating RTL code that spans multiple submodules (e.g., an SoC component with controllers, datapaths, FSMs, and register banks)
- When a specification document exceeds ~2,000 words and the target code exceeds ~500 lines, making single-shot generation unreliable
- When the user provides a hardware spec and asks for synthesizable HDL with correct port interfaces across module boundaries
- When debugging generated Verilog against a testbench and needing to localize failures to specific submodules rather than rewriting everything
- When translating any long structured technical document into modular code where sections map naturally to implementation units (applies beyond hardware to any domain with strong document-to-code locality)
Key Technique
Information Locality. Hardware IP specifications are hierarchically organized: top-level architecture sections describe module decomposition, while subsections detail individual submodules (ALU, register file, DMA controller, etc.). The code implementing each submodule depends predominantly on its corresponding documentation section, not the entire document. LocalV quantifies this with an entropy metric — hardware specs exhibit normalized entropy ~0.73 vs. ~0.82 for general software, confirming tighter locality. This means we can safely narrow context per code fragment without losing critical information.
Decompose, Generate, Merge, Debug. LocalV operates as a five-agent pipeline: (1) a Planner that reads the full spec once to produce a pseudo-code skeleton with placeholders for each submodule, (2) a Retriever that builds dual-level indices (semantic summaries + lexical signal/parameter extraction) over the spec and fetches only relevant sections per task, (3) an RTL Agent that generates each code fragment using only its local context window, (4) a Merger that integrates fragments while resolving port widths, signal names, and connectivity using retrieved interface documentation, and (5) a Debugger that uses AST dependency tracing to map simulation failures back to specific code regions and their corresponding spec sections for targeted fixes.
Why this beats monolithic generation. Single-shot LLM generation of 1,000+ line Verilog from a 10,000-word spec suffers from attention dilution (critical constraints buried in irrelevant text), output degradation (error rate climbs with length), and opaque debugging (no way to isolate which spec requirement caused which failure). LocalV's decomposition achieved 45.0% functional pass rate vs. 21.6% for the prior best agent system on IP-level benchmarks — a 23.4-point improvement.
Step-by-Step Workflow
-
Index the specification document. Parse the hardware spec into paragraphs segmented by section headers. For each paragraph, create two indices: (a) a semantic summary of functional intent (e.g., "DMA channel arbitration logic"), and (b) a lexical index extracting signal names, module identifiers, macros, parameters, and bit widths. Store these as a queryable map from section IDs to content.
-
Analyze module hierarchy. Read the top-level architecture section to identify the module decomposition: list all submodules, their parent-child relationships, and interface boundaries. Produce a module tree (e.g., top → {controller, datapath, register_bank}).
-
Plan the code skeleton. Generate a pseudo-code skeleton for the top-level module containing structural placeholders for each submodule. Each placeholder defines: the submodule name, its expected port interface (direction, width, name), and a natural-language description of its function. This skeleton becomes the task list.
-
Retrieve local context per submodule. For each placeholder in the skeleton, query both semantic and lexical indices to fetch only the specification sections relevant to that submodule. Include interface sections shared with adjacent modules. Discard all unrelated spec content — this is the locality exploitation step.
-
Generate code fragments independently. For each submodule, pass only its retrieved spec sections plus the port interface contract from the skeleton to the code generator. Generate synthesizable Verilog for that fragment alone. This keeps each generation task within a short-context, short-output regime where LLM accuracy is highest.
-
Merge fragments with interface validation. Combine all generated fragments into the top-level module. For each inter-module connection, verify: (a) port names match across instantiation and declaration, (b) signal widths are consistent, (c) clock and reset conventions are uniform. Retrieve interface documentation to resolve any mismatches. Use an LLM pass to refine integration rather than naive concatenation.
-
Run simulation and collect errors. Execute the merged code against the provided testbench. Capture compilation errors, simulation waveforms, and assertion failures with specific signal names and timestamps.
-
Localize faults via AST tracing. Parse the generated Verilog into an AST. For each failing signal, trace its driver chain and dependency graph through the AST to identify the specific code region (submodule and line range) responsible. Map that code region back to its source spec section via the index.
-
Provide the Debugger only with: the faulty code region, the AST-traced dependency information, the error details, and the locally relevant spec sections. Generate line-number-specific edit actions. Apply edits and re-simulate.
Concrete Examples
Example 1: Generating an AES Encryption IP from Specification
User: "Here's a 15-page AES-128 IP specification. Generate synthesizable Verilog for the full module including key expansion, SubBytes, ShiftRows, MixColumns, and the top-level controller."
Approach:
- Index the spec: identify sections for key expansion algorithm, S-box lookup table, round transformations, controller FSM, and AXI-Lite register interface.
- Build module tree:
aes_top → {aes_controller, key_expansion, aes_round → {sub_bytes, shift_rows, mix_columns}, axi_lite_regs}.
- Create skeleton with port contracts — e.g.,
aes_round takes input [127:0] state_in, input [127:0] round_key, outputs output [127:0] state_out.
- For
key_expansion, retrieve only sections 3.2 (key schedule algorithm) and 2.1 (interface signals). Ignore sections on round transformations.
- Generate each submodule independently:
sub_bytes gets only the S-box table and substitution spec.
- Merge into
aes_top, verifying that round_key width matches between key_expansion output and aes_round input.
Output structure:
// aes_top.v — generated via LocalV decomposition
module aes_top (
input clk,
input rst_n,
input [31:0] s_axi_awaddr,
// ... AXI-Lite ports from spec section 2.1
output [127:0] ciphertext,
output done
);
// Submodule instantiations with verified interfaces
key_expansion u_key_exp (.clk(clk), .key_in(key), .round(round_cnt), .round_key(rkey));
aes_round u_round (.state_in(state), .round_key(rkey), .state_out(state_next));
aes_controller u_ctrl (.clk(clk), .rst_n(rst_n), .start(start), .round(round_cnt), .done(done));
endmodule
Example 2: Debugging a Generated SD Card Controller
User: "The generated SD controller fails simulation — the CRC check always reports errors. Here's the testbench log."
Approach:
- Parse the generated Verilog into an AST.
- From the error log, identify the failing signal:
crc_valid remains low after data transfer.
- Trace
crc_valid through the AST: it is driven by crc_check module, which depends on data_shift_reg and crc_poly.
- Retrieve only spec sections covering CRC-7/CRC-16 polynomial definitions and the data framing protocol.
- Identify the bug: the CRC polynomial is initialized with CRC-7 (
7'h09) but the data phase requires CRC-16 (16'h1021). The generator used the wrong polynomial because both were in nearby spec sections.
- Generate targeted edit: change line 247 from
.poly(7'h09) to .poly(16'h1021) and adjust the register width from [6:0] to [15:0].
Example 3: Applying LocalV to Non-Hardware Domain (Long API Spec to Client Library)
User: "Here's a 200-page REST API specification. Generate a typed Python client with methods for each endpoint group."
Approach:
- Index the spec by endpoint groups (Authentication, Users, Orders, Payments, Webhooks).
- Plan skeleton: one class per group, shared base client with auth/retry logic.
- For each endpoint group, retrieve only its section: path, method, request schema, response schema, error codes.
- Generate each class independently with only its local spec context.
- Merge into a single client package, validating shared types (e.g.,
UserId referenced in both Users and Orders) are consistent.
- Run type checker as the "simulation" step; trace type errors back to specific endpoint methods and their spec sections.
Best Practices
- Do: Always build the module hierarchy and skeleton before generating any code. The skeleton defines port contracts that prevent interface mismatches during merging.
- Do: Use dual-level indexing (semantic + lexical) for retrieval. Semantic summaries catch functional intent; lexical indices catch specific signal names and parameters that semantic search misses.
- Do: Keep each generation task's context under 4,000 tokens of spec content. Beyond this, accuracy degrades. If a submodule's relevant spec is longer, further decompose it.
- Do: Verify interface consistency at merge time by checking every port connection against both the skeleton contract and the original spec. Width mismatches and naming inconsistencies are the most common merge failures.
- Avoid: Feeding the entire specification to a single generation call. Even with large context windows, attention dilution causes the model to hallucinate signals, miss constraints, or produce syntactically valid but functionally wrong code.
- Avoid: Debugging by regenerating entire modules. Use AST tracing to isolate the fault to the smallest possible code region and its corresponding spec section — then fix only that region.
Error Handling
Compilation errors after merge. These typically arise from undeclared signals at module boundaries. Trace the undeclared signal to its expected source submodule. Check whether the generating step omitted it (re-generate that fragment with explicit port list from skeleton) or the merger failed to wire it (re-run merge with the interface spec section).
Simulation timeout or hang. Usually caused by FSM deadlock — a state with no valid transition. Parse the AST to extract the FSM state graph. Compare against the spec's state transition table. Identify missing transitions and add them.
Inconsistent signal widths. When two submodules connect signals of different widths, retrieve the spec section defining the signal and use it as ground truth. Adjust the incorrect module's port declaration.
Retrieval returning irrelevant sections. If the lexical index returns too many matches (common signal names like clk, data), tighten retrieval by combining lexical queries with semantic filtering — require both signal name match and functional context relevance.
Iteration budget exhausted with remaining failures. Report the failing test cases, the AST-traced fault locations, and the relevant spec sections. This gives the user a precise debugging map rather than a vague "it doesn't work."
Limitations
- Tightly coupled designs. When submodules have extensive cross-dependencies (e.g., a pipelined processor where forwarding logic touches every stage), information locality is weaker and decomposition yields less benefit. The entropy metric can predict this — normalized entropy above 0.85 suggests the spec is too interconnected for clean partitioning.
- Incomplete or ambiguous specifications. LocalV assumes spec sections contain sufficient detail to implement their corresponding submodules. If the spec leaves behavior underspecified, the generated code will reflect those gaps.
- Non-modular specs. If the specification is written as a flat narrative without section structure, the hierarchical indexing step cannot produce meaningful partitions. Preprocessing to add structure (or asking the user to identify module boundaries) is required.
- Verification coverage. The approach depends on testbenches to validate correctness. Without adequate testbenches, functional bugs go undetected regardless of generation quality.
- Synthesis constraints. Generated code may be functionally correct but suboptimal for area/timing/power. LocalV does not incorporate physical design constraints into generation.
Reference
Paper: Lyu et al., "LocalV: Exploiting Information Locality for IP-level Verilog Generation," arXiv:2602.00704, 2026. https://arxiv.org/abs/2602.00704
Key insight to look for: Section 3's entropy-based quantification of information locality, Algorithm 1's AST-guided debugging loop, and Table 3's ablation showing that removing hierarchical indexing alone drops functional pass rate by 10 points — confirming that targeted context retrieval is the most impactful component.