Every quasi-static signal carries the same proof obligation: stable before use. Whoever claims the signal is static must show what enforces the stability and what would catch it if the enforcement broke. An obligation nobody writes down is an obligation nobody meets.
For each quasi-static signal, name the stability window (reset, a named mode, a stopped clock), the enforcer (gated write, mode machine, stopped clock), and the observer (the assertion or check that fires if the signal moves inside the window). A row missing any of the three is incomplete.
Item | Example entry |
|---|---|
Signal | filter_coeff[15:0], live copy. |
Stability window | RUN mode: from mode-enter plus settle time until mode-exit. |
Enforcer | Write enable gated by run_state == IDLE; live copy updates only on the synced load pulse. |
Observer | Assertion p_coeff_stable (below) plus a simulation check that scrambles the shadow copy mid-run. |
The stability property is a one-line assertion: while the consumer is active, the value must not change. It costs almost nothing and catches exactly the failure that matters, a write path that fires when it should not.
// snippet
// the live configuration must hold still whenever the datapath uses it
property p_cfg_stable;
@(posedge clk_d) use_enable |-> $stable(cfg_live);
endproperty
a_cfg_stable : assert property (p_cfg_stable);The matching simulation check scrambles the writable (shadow) copy while use_enable is high and confirms the live copy and the outputs do not move. Together the assertion and the test cover both directions: the live value never changes in use, and writes outside the window cannot leak through.
The reviewer reads the obligation table, not the intent comment. “Static configuration” in a comment proves nothing; a named window with an enforcer and an observer proves the claim was taken seriously. Signals without all three get synchronisers, not trust.
The assertion states the wrong property: the obligation is stability during use, not stability always. Gate it with the use condition (use_enable), so the legal update window passes and only a change during use fires.