---
title: 'AssertMiner: Module-Level Assertions'
url: https://www.emergentmind.com/topics/assertminer
type: topic
---

# AssertMiner: Module-Level Assertions

AssertMiner is a module-level assertion generation framework for Register-Transfer Level (RTL) designs that combines static structural analysis based on Abstract Syntax Trees (ASTs) with Large Language Model (LLM)-guided inference to synthesize SystemVerilog Assertions (SVAs). Unlike previous approaches that focus primarily on top-level assertions derived from design specifications, AssertMiner targets micro-architectural modules, where design errors are most frequent and difficult to localize. By systematically extracting and leveraging internal module context (module call graphs, I/O tables, and dataflow graphs), AssertMiner prompts LLMs with concise and semantically rich summaries to generate both specifications and deep module-level assertions, thereby increasing the coverage and efficacy of assertion-based verification (ABV) [2511.10007].

## 1. Motivation and Conceptual Framework

Assertion-based verification in RTL design often relies on debugging functional anomalies using top-level assertions. However, errors at the module or submodule level tend to manifest late and lack precise localization. For example, a bug injected in a SHA3 "padder" submodule triggers only delayed or nonspecific alarms when guarded solely by top-level checks, extending debugging time and complicating root cause analysis. AssertMiner addresses this by generating deep, module-local assertions that fire earlier and pinpoint the faulty signal directly.

AssertMiner's central methodological distinction is the decoupling of module specification inference from potentially flawed RTL implementations. By constructing a static, language-agnostic structural representation of the design using ASTs, the framework provides LLMs with focused, implementation-independent prompts. These prompts facilitate the generation of precise, high-utility assertions that are resilient to both spec omissions and RTL-level bugs.

## 2. Static Structural Extraction

AssertMiner's initial phase conducts a comprehensive, design-wide static analysis to construct three foundational representations:

- **Module Call Graph ($G_{call}$):**  
  The directed graph $G_{call} = (V, E)$ has nodes $V = \{m_1, \ldots, m_n\}$ representing modules, with edges $(m_i \to m_j) \in E$ indicating that module $m_i$ instantiates $m_j$.

- **I/O Table per Module:**  
  For every module $m$, AssertMiner extracts $IO(m) = \{(p, dir, conn)\}$, where $p$ is a port, $dir$ designates direction (input or output), and $conn$ is the corresponding signal at the parent level.

- **Dataflow Graph ($G_{data}$):**  
  For each module, $G_{data} = (N, D)$ consists of signal identifiers $N$ and directed edges $D$ capturing intra-module assignments and dependencies (e.g., $s_1 \to s_2$ if $s_1$ influences $s_2$).

A recursive AST traversal algorithm records module declarations, port connectivity, instantiations, and data dependencies, and prunes internal-only signals to yield minimal "signal chains" connecting module inputs to outputs. The key steps are illustrated in the following pseudocode excerpt:

```python
function build_structures(AST_root):
  for each module_node in AST_root:
    V.add(module_node.name)
    IO[module_node.name] = parse_ports(module_node.ports)
    for each inst in module_node.instantations:
      E.add((module_node.name, inst.module_name))
      resolve_connections(IO, module_node.name, inst)
    for each stmt in module_node.statements:
      if stmt is assignment or always:
         for (src in stmt.rhs_signals):
            D.add((src, stmt.lhs_signal))
  for each module m:
    signal_chains[m] = backward_trace(IO[m].outputs, D)
    prune_internal(signal_chains[m], IO[m])
```

## 3. LLM-Guided Module Specification and Assertion Mining

With per-module structural artifacts established, AssertMiner employs a two-stage LLM prompting pipeline:

1. **Module-Level Specification Extraction:**  
   Each module $m$ is described via a concise prompt incorporating:
   - the module and parent name (from $G_{call}$),
   - I/O table $IO(m)$,
   - representative simplified signal chains, and
   - the top-level natural-language specification.

   Example prompt:
   ```
   You are given the following module structural summary:
   • Module: padder
   • Inputs: [clk, reset, data_in]
   • Outputs: [data_out, valid]
   • Signal chains: clk→pad_state→data_out; data_in→pad_logic→data_out
   The top-level design is a SHA3 hash function.
   Please infer a concise module-level functional specification for padder, in one or two sentences.
   ```

   Few-shot in-context examples strengthen generalization and mitigate LLM hallucinations or misattribution of RTL errors.

2. **Feature Decomposition and Assertion Generation:**  
   The LLM further decomposes inferred module specifications into atomic verification features—concise, testable predicates. For each feature, the model generates a concrete SystemVerilog assertion using a unified template:
   ```
   assert property (@(posedge <CLK>)
      (<AP1> && <AP2> …) |-> (<AP3> && <AP4> …) );
   ```
   Atomic propositions like `padder.pad_state == 0` or `padder.data_out == {data_in, padding}` instantiate the placeholders, standardized across assertion outputs.

## 4. Integration with Assertion Suites

Module-level assertions produced by AssertMiner are designed to complement top-level suites created by methods such as AssertLLM and Spec2Assertion. The practical workflow is:

1. Run Spec2Assertion for top-level assertions.
2. Run AssertMiner for module-local assertions.
3. Aggregate both sets for input into formal property verification tools.

This unified strategy achieves broad functional coverage (via top-level properties) and efficient, localized bug identification (via deep module checks). Experimental measurements report increases in branch and statement coverage metrics (e.g., BFC up to 4.33% improvement for AssertLLM + AssertMiner, SFC up to 5.13% for Spec2Assertion + AssertMiner), with only a modest number of additional assertions introduced [2511.10007].

## 5. Empirical Evaluation and Results

AssertMiner was evaluated on benchmarks derived from IWLS-2005, using designs such as I²C (1282 LOC), ECG (1635 LOC), Pairing (2145 LOC), and SHA3 (618 LOC). Key evaluation criteria include:

| Metric Symbol | Definition                                   | Usage                                         |
|---------------|----------------------------------------------|-----------------------------------------------|
| N             | Number of generated assertions               | Overall yield                                 |
| S             | Number syntax-correct                        | Filtering syntactic errors                     |
| P             | Number passing FPV (valid)                   | Assertion effectiveness                       |
| NVR           | Non-Violation Rate $=\frac{P}{S}\times100\%$ | Assertion precision                           |
| BFC           | Branch Functional Coverage                   | Coverage via JasperGold FPV                   |
| SFC           | Statement Functional Coverage                | Coverage via JasperGold FPV                   |
| TFC           | Toggle Functional Coverage                   | Coverage via JasperGold FPV                   |

Notably, AssertMiner demonstrated P/N ratios from 46% to 83% and SFC/BFC above 80% across all tested designs (e.g., SHA3: 24 assertions, 20 valid, SFC=82.93%, BFC=80%). Integration with AssertLLM or Spec2Assertion consistently led to higher functional coverage and error-detection rates than standalone use or even manually crafted assertions (mutation-testing gains of 5%–19%).

## 6. Illustrative Examples

AssertMiner-generated specifications and assertions exemplify deep local semantic capture. For the SHA3 padder submodule:

- **Inferred Specification:**  
  "The padder module initializes on reset, then appends a single ‘1’ bit followed by the minimum number of ‘0’ bits to reach the required block length, asserting valid_out for one cycle."

- **Generated Assertion (SystemVerilog fragment):**
  ```systemverilog
  assert property (@(posedge clk) disable iff (reset)
    (reset == 1) |-> (padder.pad_state == IDLE)
  );
  assert property (@(posedge clk)
    (padder.valid_in && padder.pad_state != END)
       |-> ##[1] (padder.data_out == {padder.data_in, 1'b1, {padder.pad_count{1'b0}})
  );
  ```

For an I²C controller:
- **Inferred Specification:**  
  "On start condition, the controller must drive SCL low within one cycle and pull SDA low to transmit the address bit."
- **Generated Assertion:**  
  ```systemverilog
  assert property (@(posedge clk) disable iff (reset)
    (i2c.start && i2c.bus_busy == 0)
      |-> ##1 (i2c.SCL == 0 && i2c.SDA == address_bit)
  );
  ```

## 7. Limitations and Future Research Directions

AssertMiner's reliance on AST-based extraction is robust to language variations, but scaling challenges emerge for designs with deep or wide hierarchies. Traversal overhead and the complexity of resulting signal-chain summaries can become prohibitive. Inaccuracies in the AST—stemming from nonstandard preprocessing or vendor-specific constructs—could mislead the LLM, providing erroneous prompt contexts.

Potential avenues for future work include:
- Implementation of hierarchical pruning algorithms to focus the LLM on high-value subgraphs.
- Augmenting static analysis with simulation-based traces to provide dynamic context.
- Automated ranking of mined assertions based on novelty or predicted error-detection impact to improve reviewer efficiency [2511.10007].

AssertMiner advances the practical automation of module-focused assertion-based verification, closing the specification-to-assertion gap at the micro-architectural level and enabling streamlined, early, and precise RTL bug discovery.

Source: https://www.emergentmind.com/topics/assertminer