Skip to content
DenseChip
Learn
PracticeCode labInterview

DenseChip

Navigate

Menu

LearnPracticeCode labInterview

Tools

All toolsSV editorCode repoResume
DenseChip

Practice, courses, and chip-design tools in one focused workspace.

LearnPracticeCode labInterviewToolsLearning paths

© 2026 DenseChip

AboutRoadmapCareersInternshipsFAQContactPrivacyTerms
Skip to lesson

Course contents

  • How to Use This Course
  • Reading Paths
  • Glossary
  • Metrics Reference
  • Formal Cheat Sheet
  • Formal Foundations19
  • Properties and SVA16
  • Property Development and Constraints19
  • Proof Engines and Convergence23
  • Formal Applications20
    • Connectivity Checking
    • Register (CSR) Verification
    • Deadlock, Livelock and Starvation Checks
    • Reset Determinism and X
      • Two-State Formal and the X Problem
      • Reset Determinism Proofs
      • X-Aware Analysis in Concept
    • Data, Handshake and Pipeline Property Sets
    • Other Applications, Honestly Scoped
  • Equivalence Checking14
  • Formal Coverage and Signoff15
  • Methodology and Debug13
  • Interview Prep15
  • Capstone: A Chip-Block Verification Lab24
Loading lesson

←Reset Determinism and X
  1. Topics
  2. Formal Verification
  3. Formal Applications
  4. Reset Determinism and X
  5. Two-State Formal and the X Problem
On this page

    Part 5 of 10, lesson 12 of 20Part 5 of 10/Formal Applications/Lesson 12 of 20All levels

    Two-State Formal and the X Problem

    Why asserting the absence of X proves nothing in a two-state model, and which questions to ask instead.

    Why it matters

    The reassuring proof is one line: assert that no signal is unknown, watch it pass, ship. It proves nothing, because in a two-state model there is no unknown for the check to find: the predicate is constant false, so its negation is constant true, and it is just as true of a design with an unreset register as of one without. The unreset register that motivated the check is still unreset. This lesson shows what the flow here does with that assertion, then asks the questions the tool can answer.

    The core idea

    A two-state formal model has no X or Z. An unreset register holds an arbitrary but fixed zero or one, chosen by the solver to try to break the proof. A missing reset therefore shows up as a counterexample from an arbitrary value, never as an unknown. Asserting the absence of X in that model is asserting a property of the modelling, not of the design. The table below is the whole boundary in one place:

    Question

    Two-state formal

    Needs what instead

    is any signal X after reset

    cannot say: no X in the model

    X-aware analysis plus X simulation

    does reset determine the control state

    proves it: two-copy harness

    this topic's next lesson

    does an unreset register affect outputs

    shows it as differing copies

    reset-determinism counterexample

    is the reset value correct

    proves it: check after the reset edge

    register proofs

    Worked example: the assertion that cannot discriminate

    The textbook assertion is below. It is a concept block, not a run, because this flow cannot run it usefully. The native front end does not treat the unknown test as constant false: it treats it as a free value, so the assertion is refuted at step 1 on a correctly reset register and on an unreset one alike (this was run on both). The other front end rejects the unknown test outright. Either way the assertion cannot tell the two designs apart, which is the practical form of 'proves nothing'. In a strict two-state semantics it would be constant true, and cannot tell them apart either:

    design.sv
    // not-run: the unknown-absence assertion cannot be run usefully in this flow (refuted on every design, or rejected)
    // x_no_unknown: assert (!$isunknown(status));   // two-state: constant true; this flow: refuted on a reset register too

    What the flow can answer are two honest questions about the same register, each as a runnable check. The module below holds the register twice, a copy A and a copy B driven by the same inputs, with free and different initial values. The question 'is the register zero after reset' is r_after_reset; the question 'does the reset make the two copies agree, whatever they held before' is d_copies. With a reset clause on both, both pass:

    xdemo.sv
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    // formal: prove 4 expect pass slang top xdemo
    module xdemo #(parameter RESET = 1) (
      input  wire clk,
      input  wire rst,
      input  wire set,
      output reg  status,
      output reg  status_b
    );
      // copy A and copy B of the same register, driven by the same inputs
      always @(posedge clk) begin
        if (RESET != 0 && rst) begin status <= 1'b0; status_b <= 1'b0; end
        else if (set)          begin status <= 1'b1; status_b <= 1'b1; end
      end
    
      reg init = 1'b1;
      always @(posedge clk) init <= 1'b0;
      always @(*) if (init) assume (rst);
      always @(posedge clk) if (!init && $past(rst)) begin
        r_after_reset: assert (status == 1'b0);       // the reset value
        d_copies:      assert (status == status_b);   // the copies agree: reset determinism
      end
    endmodule

    Remove the reset clause and the same two questions fail. This is the unreset register the unknown check was meant to catch, and it is caught as a counterexample from an arbitrary value: copy A starts at 1 and copy B at 0, nothing resets them, and the checks that judge the cycle after reset fail. The register is reported at step 2, one step after the state it judges, which follows the reporting rule of the course:

    Step

    rst

    copy A

    copy B

    Outcome

    0

    1

    1 (arbitrary)

    0 (arbitrary)

    reset cycle, not checked; no reset clause, so the values survive

    1

    0

    1

    0

    state after the reset edge: not zero, copies differ

    2

    -

    -

    -

    counterexample: r_after_reset and d_copies reported

    xdemo.sv
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    // formal: bmc 6 expect fail slang top xdemo define RESET=0
    module xdemo #(parameter RESET = 1) (
      input  wire clk,
      input  wire rst,
      input  wire set,
      output reg  status,
      output reg  status_b
    );
      // copy A and copy B of the same register, driven by the same inputs
      always @(posedge clk) begin
        if (RESET != 0 && rst) begin status <= 1'b0; status_b <= 1'b0; end
        else if (set)          begin status <= 1'b1; status_b <= 1'b1; end
      end
    
      reg init = 1'b1;
      always @(posedge clk) init <= 1'b0;
      always @(*) if (init) assume (rst);
      always @(posedge clk) if (!init && $past(rst)) begin
        r_after_reset: assert (status == 1'b0);       // the reset value
        d_copies:      assert (status == status_b);   // the copies agree: reset determinism
      end
    endmodule

    Root cause: a missing reset clause, found by the right question. Fix the RTL by adding the reset clause; the proof above is the same module with the clause in place.

    What the review looks for

    • No unknown-absence assertion anywhere in the proof set: the review rejects it as modelling theatre.

    • Every control register has a reset-determinism or reset-value argument tracing to a proof in this topic or the register topic.

    • Unreset storage is listed explicitly with its justification: memory arrays, data paths, and what reads them first.

    Verify and debug

    Suspect every proof that passes suspiciously fast on a new design: mutate the reset logic to confirm the proof can fail, as the second run above does. A determinism failure names the register whose copies differ; add the reset clause, do not constrain the initial value, unless the initial value is itself specified and reviewed.

    The unknown-absence assertion in the signoff set: the symptom is a clean report with unreset registers in the netlist, found by anyone who reads the predicate list. The cause is trusting a two-state predicate about a four-state concern. The fix is deleting the assertion and replacing it with the determinism proofs of the next lesson plus the X analysis of the last.

    Expect: how do you prove there is no X? Answer that you cannot in two-state formal, and say what you do instead: reset determinism for control, explicit X analysis for propagation, and X simulation for the rest. Anyone who accepts the unknown-absence assertion has failed the interview.

    Check yourself A colleague adds initial values to every register so the proof starts cleanly. What do you say?

    That the proof now starts from a state the silicon may never see, and a missing reset clause hides behind the initial value. Reset every control register explicitly; initial values are not a reset strategy.

    Related topics

    • Next: Reset Determinism Proofs

    • RTL: X-Propagation Discipline

    Previous

    94 / 183

    Next: Reset Determinism Proofs

    Up next

    Up nextReset Determinism Proofs

    Sign in to save progress

    Practice this lessonPrevious lessonReport an error

    See also

    • X-Aware Analysis in Concept