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

AboutContactPrivacyTerms
Skip to lesson

Course contents

  • RTL Foundations36
  • Combinational Design25
  • Sequential Design27
  • FSM & Control27
  • Timing & Clocking39
  • Reset & CDC34
  • Memory & Buses57
  • Advanced RTL28
    • Parameterization and Generate Hub
    • Top-Level Integration Hub
    • Synthesis Intent Hub
    • Style and Static Checks Hub
    • Assertions in RTL Hub
      • Immediate vs concurrent assertions
      • assert, cover, and assume roles
      • Common RTL property templates
      • SVA Cheat Sheet and Bug Hunt
    • Formal Verification Basics Hub
    • Reusable SystemVerilog for RTL
  • Senior & Interview76
  • Glossary and Notation
Loading lesson

‹Assertions in RTL Hub
  1. Topics
  2. RTL Design
  3. Advanced RTL
  4. Assertions in RTL Hub
  5. assert, cover, and assume roles

Part 8 · Advanced · Advanced

assert, cover, and assume roles

Assert flags violations, cover records exercised scenarios, and assume constrains the environment.

On this page

    Why this matters

    An assume that states design behaviour instead of environment behaviour removes the failing trace, and the bug survives review. An implication whose trigger never fires passes without checking anything.

    After this lesson you can: assign assert, cover and assume to the right questions, and cover the exact antecedent of an implication.

    Three jobs

    Each construct answers a different question about the same interface.

    • assert checks design obligations and flags violations.

    • cover tracks whether important scenarios are reachable/exercised.

    • assume constrains environment behavior, mainly in formal contexts.

    • Avoid over-constraining assumptions that exclude real bug traces.

    design.sv
    1
    2
    3
    4
    5
    6
    7
    8
    // snippet
    cover property (@(posedge clk) disable iff (!rst_n)
      req); // exact antecedent exercise/reachability
    cover property (@(posedge clk) disable iff (!rst_n)
      req ##1 grant);
    
    assume property (@(posedge clk) disable iff (!rst_n)
      !(req && cancel));

    The first cover names the exact antecedent req; the second asks for the stricter one-cycle answer sequence. The assume states one environment rule: cancel never rides with a request.

    One trace, three readings

    All three constructs read the same signals. The trace below has two requests, answered after two cycles and after one, and one cancel on an idle cycle.

    Each slot is one clock cycle, numbered from 0; read each construct against the slots it names.

    • Assert req |-> ##[1:3] grant: the request in slot 1 is answered in slot 3 (two cycles) and the one in slot 5 in slot 6 (one cycle). Both are inside the window, so nothing is reported.

    • Cover req: hits in slots 1 and 5, so the assertion was exercised, not passed vacuously.

    • Cover req ##1 grant: misses for the slot 1 request (no grant in slot 2) and hits in slot 6. One hit is enough to mark the scenario covered.

    • Assume !(req && cancel): cancel is high only in slot 4, where req is low, so the stimulus kept its promise. In formal, the tool would never even try a trace with both high.

    On success

    On failure

    assert

    Nothing reported

    Violation flagged

    cover

    Scenario marked exercised

    Coverage hole remains

    assume

    Environment kept legal

    Stimulus broke its promise

    Strong promises hide bugs

    An assume removes traces instead of checking them. When it states design behavior rather than environment behavior, it removes the failing trace and the bug survives review.

    design.sv
    1
    2
    3
    4
    5
    6
    7
    // snippet
    // Good: a rule about the environment (inputs only).
    assume property (@(posedge clk) disable iff (!rst_n)
      !(req && cancel));
    // Bad: a rule about the design under test. It assumes the grant the proof should check.
    assume property (@(posedge clk) disable iff (!rst_n)
      req |-> ##1 grant);

    Keep assumes to input rules such as the cancel rule above. Grant timing stays an assert, where a violation is evidence.

    Common mistakes

    Common pitfall

    An implication holds vacuously on traces where its antecedent never triggers. Zero exact-antecedent hits in simulation mean non-exercise in that run. A bounded formal cover miss means no witness within the searched depth; proven unreachability needs a complete reachability result under the assumptions. Neither a bounded miss nor an unrelated sequence cover invalidates a separately established property proof.

    Interview

    Likely question: “What is the difference between assert, cover, and assume?”

    • Assert states a design obligation; a violation is a bug.

    • Cover records simulation exercise or searches formal reachability for the named sequence.

    • Assume promises environment behavior, and is reviewed as strictly as RTL.

    Check yourself The req ##1 grant cover misses while the response assertion passes. Is the assertion vacuous?

    Not necessarily: requests answered at age 2 or 3 exercise the implication but miss this cover. Inspect the exact req cover and distinguish simulation, bounded search and unbounded proof results.

    Check yourself An assume states that every request is granted in one cycle. Why is it dangerous?

    It keeps only traces where the design is already correct. A slower-but-legal answer disappears from the proof, and so does the bug report.

    Testbench

    Three responders answer the same stimulus with one-, two-, and three-cycle latency. Cover counters record each latency, one monitor per responder checks the window, and the cancel input exercises the environment rule.

    grant_resp.sv
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    // A responder with latency D: grant is high exactly D cycles after a req
    // pulse, as sampled on the clock.
    module grant_resp #(parameter [2:0] D = 2) (
      input  logic clk, rst_n, req,
      output logic grant
    );
      logic [2:0] cnt;
      always_ff @(posedge clk or negedge rst_n) begin
        if (!rst_n) cnt <= 3'd0;
        else if (req) cnt <= D;
        else if (cnt != 3'd0) cnt <= cnt - 3'd1;
      end
      assign grant = (cnt == 3'd1);
    endmodule
    
    // Plain-RTL form of: req |-> ##[1:3] grant.
    // Each pending bit records one request age; overlapping windows are preserved.
    module grant_window_mon (
      input  logic clk, rst_n, req, grant,
      output logic violation
    );
      logic [2:0] pending;
      always_ff @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin pending <= 3'd0; violation <= 1'b0; end
        else begin
          violation <= pending[2] && (grant !== 1'b1);
          if (grant === 1'b1) pending <= {2'b00, req};
          else               pending <= {pending[1:0], req};
        end
      end
    endmodule
    
    • Result: 180 matched sampled grants in each age bin, with all pending requests drained. Changing all responders to D=2 would produce 540 age-2 hits and fail the bin checks.

    • Expected checks: zero window violations and zero cycles with req and cancel together.

    Remember

    • Assert states a design obligation. Cover shows a scenario is exercised or reachable. Assume constrains the environment.

    • An implication is vacuous where its antecedent never triggers; cover the antecedent to see it.

    • Keep assumes to input rules, such as cancel never riding with a request.

    Rule of thumb: grant timing is an assert, where a violation is evidence; an assume would hide it.

    How this was checked

    Testbench run with Icarus Verilog 13.0 (2026-10-16): prints PASS: 180 matched sampled grants in each age bin, with all pending requests drained. Changing all responders to D=2 would give 540 age-2 hits and fail the bin checks. The checks are simulation checks, not a formal proof.

    Keep going

    • Code lab: SVA cover wrapper

    • Interview: run a mock interview on this topic

    Related topics

    • Immediate vs concurrent assertions

    • Common RTL property templates

    Previous

    260 / 350

    Next: Common RTL property templates

    Up next

    Up nextCommon RTL property templates

    Sign in to save progress

    Practice this lessonReport an error

    See also

    • SVA Cheat Sheet and Bug Hunt
    clkreqgrantcancel
    One trace read by the assert, the two covers and the assume