Verifying Power Intent & Early Data Checks
Chapter 14 — Verifying Power Intent & Early Data Checks
A multivoltage chip carries two parallel descriptions of itself. One is the logical design — the RTL and the gates that implement function. The other is the power intent: the declaration of which supplies exist, how the design is partitioned into power domains, when each domain is on or off, and what protective logic must guard the boundaries between them. These two descriptions must agree. When they do not, the silicon does not merely run slowly or burn extra power — it fails outright, and often fails in ways that only appear after a domain is powered down in the field, months after tapeout. This chapter is about catching that disagreement as early and as cheaply as possible. We will look at what a static low-power rule check actually inspects, how early data checks validate the intent against the library and netlist before any heavy implementation begins, how successive refinement lets you verify a partial intent, and how power-aware equivalence confirms that the implemented netlist still honors the intent you signed off on.
Why Power-Intent Bugs Are Silicon-Killers
A functional bug usually announces itself in simulation. A power-intent bug frequently does not, because the offending condition only arises in a power state that ordinary functional vectors never exercise. Consider the canonical failure: a signal crosses from a domain that can be switched off into a
domain that stays on, but no isolation cell was inserted on that crossing. While both domains are powered, the path behaves perfectly. The moment the source domain collapses, its outputs float to an indeterminate voltage. That floating value propagates into the always-on logic, can turn on both transistors of a downstream gate, and creates a crowbar current path that either corrupts state or, over time, damages the device.

The same catastrophe class includes a level shifter omitted between two different voltage rails (a logichigh from a low rail may not reliably register as high on a high rail), a retention register that loses state because its retention supply was never connected, a power switch whose enable is driven by logic inside the very domain it is switching off, and an isolation enable that arrives from a domain that is itself off when isolation is needed. Each of these is invisible to a designer reading RTL, because RTL has no notion of supplies. Each is a single missing or mis-specified line of power intent. And each can kill a part. The economic argument follows directly. The cost of catching one of these bugs scales with how late you catch it. A static check at the RTL handoff costs minutes. The same bug found in gate-level poweraware simulation costs days of debug. Found in silicon, it costs a respin — months and a great deal of money. The discipline of this chapter is to push the discovery as far left as the available information allows.
Static Power-Intent Checks: The Low-Power Rule Check
A static low-power rule check is the power-domain analog of a lint or design-rule check. It loads the power intent (an IEEE 1801 / UPF description), the logical design, and the technology and cell libraries, then reasons about the structure of the power architecture without simulating any vectors. Because it is static, it is exhaustive over the conditions it models — it does not depend on stimulus reaching a corner case. The checks fall into a handful of conceptual families:
| Check family | What it inspects | Representative failure caught |
|---|---|---|
| Domain | Every instance maps to exactly one power | An instance left unassigned, |
| consistency | domain; domain boundaries are well-formed | defaulting to the wrong supply |
| Supply | Every supply net is driven, reachable, and | A floating or unbound supply; |
| consistency | connected to the cells that need it | retention supply never hooked up |
| Strategy | Each domain crossing that needs protection has coverage | An unprotected off-to-on crossing an isolation / level-shift / retention strategy |
| Strategy | Inserted strategy matches the crossing direction, | Isolation clamp value that conflicts |
| correctness | polarity, and clamp value | with downstream expectation |
| Control | Isolation enables, switch enables, and retention | Isolation enable sourced from the |
| reachability | saves come from a supply that is live when | domain being shut off |
needed
| Element | Protection cells sit on the correct side of the | Level shifter powered from the wrong |
|---|---|---|
| placement | boundary and on the correct supply | rail |
The most valuable of these is the unprotected crossing check. The tool walks every net that leaves one power domain and enters another, computes the relative voltage and on/off relationship of the two domains across all defined power states, and asks whether the present protection is sufficient. An offto-on crossing demands isolation. A crossing between different voltages demands a level shifter. A crossing that is both demands an enable-style level shifter or an isolation-plus-shift pair. If the required strategy is absent, the tool flags it — long before a single gate is placed. Equally important is control-signal reachability. Isolation only works if its enable is asserted before the source domain powers down and stays asserted until power returns. If the enable is generated inside the domain that is being switched off, the enable itself disappears at exactly the wrong moment. A static check traces the driver of each control signal back to its supply and confirms that supply remains live throughout the relevant power state. A typical invocation of the static checker looks like this:
# Load the logical design, then the power intent on top of it
read_design -netlist ./rtl/top.v
load_power_intent -upf ./pi/top.upf
# Run the full battery of structural low-power rule checks
check_power_intent \
-domains \
-supplies \
-strategies \
-control_reach \
-severity_min warning
# Emit a human-readable, bucketed report
report_power_intent -output ./reports/pi_check.rpt -group_by severity
The -group_by severity switch matters: the output is bucketed, not a flat list, which is the subject of the next section.
The Check Manager: Buckets, Severities, and Waivers
A real design produces hundreds of check results on the first run, and most of them are not bugs — they are artifacts of an incomplete intent, intentional design choices, or known-and-accepted conditions. A check manager exists to make that volume tractable. It runs the battery of checks once, then sorts every result into severity buckets so that engineering attention flows to the right place. The conventional buckets are three:
| Severity | Meaning | Default disposition |
|---|---|---|
| Error | A condition that will produce wrong or dangerous | Must fix or formally waive before sign-off |
silicon if shipped
Warning A condition that is probably wrong but may be Must be reviewed and consciously
| legitimate | dispositioned | |
|---|---|---|
| Info | A note about a structure that is unusual but not unsafe | Read once, usually accepted |
The point of bucketing is triage. Errors block sign-off. Warnings demand a decision — fix or accept — and that decision must be recorded. Info messages exist so that nothing is hidden, but they do not gate progress. Two further mechanisms keep the process honest. Tolerating a result tells the manager that a particular condition is expected during the current phase — for example, an unprotected crossing that will be protected by a strategy not yet written. A tolerated result is suppressed for now but reappears if it survives into a later phase where it should have been resolved. Waiving a result is a permanent, documented decision that a flagged condition is acceptable: the engineer attaches a justification, and the waiver is tracked so that an auditor can later ask why every waived check was waived. The
cardinal rule is that a waiver is a sentence of explanation attached to a signature, never a silent suppression.
# Tolerate crossings that a later refinement phase will protect
set_check_status -tolerate \
-check_type unprotected_crossing \
-reason "isolation strategy added in phase 2"
# Permanently waive a reviewed, intentional condition
waive_check_result \
-id PI-ISO-0047 \
-reason "test-mode net, isolation handled by DFT clamp" \
-owner "pd_team" -date 2026-06-13
# Re-run and confirm only genuine errors remain
report_power_intent -buckets {error} -fail_if_nonempty
The final line encodes the gate: the run fails if any unwaived error survives. That single boolean is what a project actually signs off against.
Successive Refinement: Verifying an Incomplete Intent
Power intent is not written all at once. It arrives in layers. At RTL handoff an architect may declare the domains and the high-level power states but leave the precise isolation cells, clamp values, and supply-net names to be filled in during implementation. Successive refinement is the methodology that lets each contributor add detail on top of what came before without rewriting it, and it has a direct consequence for verification: you must be able to check a partial intent and have the checker understand that some incompleteness is expected, not erroneous.

The practical pattern is to run the same checker at each refinement boundary but with the bar set appropriately for the available detail. Early on, a missing isolation cell is informational — the strategy may not be written yet — but a missing isolation strategy on an off-to-on crossing is still an error,
because that is a constraint-layer decision that should already exist. As detail arrives, conditions that were tolerated get retired, and the checker's bar tightens until, at sign-off, nothing is tolerated and every result is either clean or waived.
# Phase 1: constraint intent only — check architecture, allow missing cells
load_power_intent -upf ./pi/constraints.upf
check_power_intent -domains -strategies -allow_incomplete_implementation
# Phase 2: implementation intent layered on top — now demand full strategies
load_power_intent -upf ./pi/implementation.upf -refine
check_power_intent -domains -strategies -control_reach -strict
The -refine flag signals that the new file adds to rather than replaces the loaded intent, and - strict removes the early-phase leniency. Running the same tool with a graduated bar is what makes refinement safe: nothing slips through a gap between phases because every phase re-checks the accumulated whole.
Power-Aware Equivalence: Did Implementation Keep the Promise?
Static checks verify that the intent is self-consistent. They do not, by themselves, prove that the implemented netlist still obeys that intent after synthesis, placement, optimization, and ECOs have rewritten it. Implementation tools insert and move isolation cells, level shifters, switches, and retention registers. A buffer added during timing closure might be placed in the wrong domain. An optimization might delete an isolation cell it wrongly judged redundant. Power-aware equivalence closes that gap. Conceptually, equivalence checking compares two views and proves they are functionally identical under all power states. In a power-aware flow the comparison must account for supplies: an isolation cell is not a redundant buffer to be optimized away — it changes behavior precisely when its source domain is off. The checker therefore models each power state and confirms that, in every state, the implemented netlist produces the same outputs the intent demands, including the clamped values that isolation cells assert when their domain is down. The two comparisons worth running are RTL-plus-intent versus gate-level netlist (did synthesis preserve both function and power behavior?) and netlist-before versus netlist-after an ECO or insertion step (did this transformation disturb the power structure?). A discrepancy that points at a protection cell — a missing isolation clamp, a level shifter that moved across a boundary — is exactly the silicon-killer this whole chapter exists to prevent, now caught at the netlist rather than in the fab.
# Power-aware equivalence: golden intent vs. implemented netlist
read_golden -netlist ./rtl/top.v -upf ./pi/top.upf
read_revised -netlist ./impl/top.gate.v -upf ./pi/top.upf
verify_equivalence \
-power_aware \
-across_power_states \
-report ./reports/pi_equiv.rpt
A Catalog of Common Power-Intent Error Classes
The errors that static checks and equivalence catch cluster into a recognizable set. Knowing the root cause of each shortens debug enormously, because the report tells you what is wrong and this table tells you why.
| Error class | Typical root cause | Consequence if shipped |
|---|---|---|
| Unprotected off-to-on | Missing isolation strategy on a boundary | Floating input, crowbar current, |
| crossing | net | corrupt state |
| Missing level shifter | Voltage difference between domains not declared or not honored | Unreliable logic-level recognition, marginal failures |
| Isolation enable not live | Enable sourced from the domain being switched off | Isolation never asserts; equivalent to no isolation |
| Retention not | Retention supply net unbound or save/ | State lost across power-down; |
| connected | restore not specified | functional reset on wake |
| Switch enable self- | Power-switch enable driven from inside | Domain cannot be powered back up |
| gating | its own domain | cleanly |
| Floating / unbound | Supply net declared but never driven or | Cells with no valid power reference; |
| supply | connected | undefined behavior |
| Wrong clamp value | Isolation clamp polarity conflicts with downstream logic | Glitch or wrong constant during power-down window |
| Cell on wrong rail | Protection cell powered by the wrong supply | Cell itself collapses when it is needed most |
| Domain misassignment | Instance left unmapped or mapped to default domain | Logic powered by the wrong rail across states |
A Conceptual Verification Flow
Stripped to its essentials, the loop is short and is the same at every refinement phase. The discipline is in running it relentlessly, never in its complexity.

- 1. Load the logical design, the power intent, and the technology and cell libraries together, so the
checker can cross-reference all three.
- 2. Run the static low-power rule checks across domains, supplies, strategies, and control reachability.
- 3. Triage the results into error, warning, and info buckets; record a disposition for every warning.
- 4. Fix genuine bugs in the intent or design; tolerate what a later phase will resolve; waive reviewed
and justified conditions.
- 5. Re-check until the error bucket is empty and every remaining flag is consciously dispositioned.
- 6. Once the intent is clean, confirm with power-aware equivalence that the implemented netlist still
matches the signed-off intent. The flow is iterative by nature: a fix to one strategy can expose a newly reachable crossing, so the loop runs many times across a project. What never changes is the exit condition — no unwaived errors, and a recorded reason behind every waiver.
Interview Q&A
simulation for finding isolation bugs? Because they are exhaustive over the conditions they model rather than dependent on stimulus. A simulation only catches a missing isolation cell if a test vector actually drives the source domain into its off state while the crossing is active — a corner that ordinary functional vectors rarely hit. The static checker reasons structurally about every domain crossing across every declared power state, so it cannot miss a crossing simply because no test exercised it. Simulation remains valuable for dynamic, sequenced behavior, but for the structural question "is every crossing protected?" the static check is both faster and more complete.
distinction matter? Tolerating is temporary and phase-scoped: it suppresses a result that is expected
to be resolved by a later refinement, and the result automatically reappears if it survives into a phase where it should have been fixed. Waiving is permanent and accountable: it is a documented engineering decision that a flagged condition is acceptable, carrying a justification, an owner, and a date. The distinction matters because it prevents two failure modes — a tolerated bug being forgotten (it comes back), and a waived bug being unaccountable (it carries a recorded reason an auditor can challenge). Conflating the two lets real bugs hide behind suppression.
same condition can be informational early and an error late. With a constraint-layer-only intent, a missing isolation cell is expected, because the implementation strategy has not been written — so it is info or tolerated. But a missing isolation strategy on an off-to-on crossing is an error even at that early stage, because declaring required protection is a constraint-layer responsibility. As implementation detail is layered in, the checker's bar tightens: tolerated conditions are retired and leniency flags are removed, until at sign-off nothing is tolerated and every result is clean or formally waived.
Because it is not functionally redundant — it changes behavior precisely in the state a power-unaware tool ignores. While both domains are on, an isolation cell may pass its input through and look like a buffer, which is why a power-unaware optimizer might delete it. But when the source domain powers down, the cell asserts a defined clamp value instead of passing a floating input. Power-aware equivalence models each power state explicitly and compares behavior in the off state too, so it recognizes that removing the cell changes the design's response when the domain collapses — exactly the silicon-killing case the check exists to protect.
Key Takeaways
- Power-intent bugs are silicon-killers because they hide in power states that functional vectors rarely exercise; a single missing isolation or wrong supply can crowbar a device. Catch them as far left as the available information allows.
- Static low-power rule checks are exhaustive over structure: they verify domain and supply consistency, strategy coverage and correctness, control-signal reachability, and protection-cell placement — all without stimulus.
- A check manager buckets results into error, warning, and info, and supports tolerate (temporary, phase-scoped) and waive (permanent, justified) so attention flows to genuine bugs and every disposition is recorded.
- Successive refinement lets you verify a partial intent and tighten the bar as detail arrives; re- checking the accumulated whole at each phase prevents bugs from slipping through gaps between phases.
- Power-aware equivalence proves the implemented netlist still honors the signed-off intent across all power states, catching protection cells that implementation deleted, moved, or mis-rolled.
- The verification loop is short and relentless: load → check → triage → fix or waive → re-check, exiting only when no unwaived error remains, then confirming with equivalence.
ChipBuddy
← Home
Comments
Leave a Reply