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
    • Writing Properties That Can Fail and Say Something
    • Assumptions as a Contract
      • Assumption Taxonomy and Ownership
      • Assume Versus Assert by Side
      • The Assumption Review
      • Turning Assumptions into Assertions
    • Abstraction and Complexity
    • Assume-Guarantee and Black Boxes
    • Reusable Property Sets
  • Proof Engines and Convergence23
  • Formal Applications20
  • Equivalence Checking14
  • Formal Coverage and Signoff15
  • Methodology and Debug13
  • Interview Prep15
  • Capstone: A Chip-Block Verification Lab24
Loading lesson

←Assumptions as a Contract
  1. Topics
  2. Formal Verification
  3. Property Development and Constraints
  4. Assumptions as a Contract
  5. Turning Assumptions into Assertions
On this page

    Part 3 of 10, lesson 8 of 19Part 3 of 10/Property Development and Constraints/Lesson 8 of 19All levels

    Turning Assumptions into Assertions

    Convert block A's assumption into an assertion on block B, and find the bug that A's unit proof could not.

    Why it matters

    A's unit proof passes under "data stays stable until grant". Integration fails. The neighbour B had never been asked to keep that rule. Job of this lesson: the assume-to-assert conversion: the same rule, the same text, assumed in A and asserted on the signals B drives.

    The core idea

    The rule module has one body and two roles. Placed on A's inputs it is an assumption; placed on B's outputs it is an assertion that must be proved. The conversion is that one change, made at the integration level, and the assertion is the discharge. A miter that compares two implementations is a different tool: it does not convert assumptions.

    Rule X above two boxes: A proved under X, and B proved to guarantee X.
    Rule X is used twice: assumed in the proof of A and asserted in the proof of B. Together they give the proof of A and B connected.

    Worked example

    B is a requester: it raises req with a word and holds both until granted. Its fault (BUG=1) takes a new word while waiting. The rule module, asserted on B's outputs, proves for the good B and fails for the faulty one at step 3 (depth 3 passes). A's own unit proof passes either way, because it assumes the rule. The system of A and B shows the consequence at step 4.

    a_blk.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
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    // formal: prove 6 expect pass slang top unitB define BUG=0
    `define FORMAL
    module a_blk (input wire clk, input wire rst, input wire req, input wire [3:0] data, input wire gnt,
                  output reg ov, output reg [3:0] out, output wire dbg_pend, output wire [3:0] dbg_held);
      reg pend; reg [3:0] held;
      assign dbg_pend = pend; assign dbg_held = held;
      always @(posedge clk) begin
        if (rst) begin pend <= 1'b0; ov <= 1'b0; end
        else begin
          ov <= req && gnt;
          if (req && !gnt) pend <= 1'b1; else if (gnt) pend <= 1'b0;
          if (req && !pend) held <= data;
          out <= pend ? held : data;
        end
      end
    endmodule
    module hold_rule #(parameter ASSUME = 0) (input wire clk, input wire rst, input wire req, input wire [3:0] data, input wire gnt);
      reg init = 1'b1; reg pv = 1'b0, pg = 1'b0, prst = 1'b1; reg [3:0] pd = 4'd0;
      always @(posedge clk) begin init <= 1'b0; pv <= req; pg <= gnt; prst <= rst; pd <= data; end
      wire waiting = !init && !rst && !prst && pv && !pg;
      generate if (ASSUME == 2) begin : g_n
      end else if (ASSUME) begin : g_a
        always @(*) if (waiting) begin r_req: assume (req); r_dat: assume (data == pd); end
      end else begin : g_s
        always @(*) if (waiting) begin r_req: assert (req); r_dat: assert (data == pd); end
      end endgenerate
    endmodule
    module a_spec (input wire clk, input wire rst, input wire req, input wire [3:0] data, input wire gnt, input wire ov, input wire [3:0] out);
      reg init = 1'b1; reg pgo = 1'b0, prst = 1'b1; reg [3:0] pd = 4'd0;
      always @(posedge clk) begin init <= 1'b0; pgo <= req && gnt; prst <= rst; pd <= data; end
      always @(*) if (!init && !prst && pgo) a_answer: assert (ov && out == pd);
      always @(*) if (!init) c_wait_then_grant: cover (!prst && ov && out == pd && out != 4'd0);
    endmodule
    module unitA #(parameter ASSUME = 1, parameter BUG = 0) (input wire clk, input wire rst, input wire req, input wire [3:0] data, input wire gnt);
      wire ov; wire [3:0] out; wire dp; wire [3:0] dh;
      reg init0 = 1'b1; always @(posedge clk) init0 <= 1'b0; always @(*) if (init0) assume (rst);
      a_blk u_a (.clk(clk), .rst(rst), .req(req), .data(data), .gnt(gnt), .ov(ov), .out(out), .dbg_pend(dp), .dbg_held(dh));
      reg qv = 1'b0, qg = 1'b0; always @(posedge clk) begin qv <= req; qg <= gnt; end
      always @(*) if (!init0 && ASSUME == 1) h_hist: assert (!dp || rst || (qv && !qg));
      always @(*) if (!init0 && ASSUME == 1) h_pend: assert (!dp || rst || dh == data);
      hold_rule #(.ASSUME(ASSUME)) u_r (.clk(clk), .rst(rst), .req(req), .data(data), .gnt(gnt));
      a_spec u_s (.clk(clk), .rst(rst), .req(req), .data(data), .gnt(gnt), .ov(ov), .out(out));
    endmodule
    module b_req #(parameter BUG = 0) (input wire clk, input wire rst, input wire want, input wire [3:0] nd, input wire gnt,
                                       output wire req, output wire [3:0] data);
      reg busy; reg [3:0] d;
      assign req = busy; assign data = d;
      always @(posedge clk) begin
        if (rst) busy <= 1'b0;
        else begin
          if (!busy && want) begin busy <= 1'b1; d <= nd; end
          else if (busy && gnt) busy <= 1'b0;
          else if (busy && BUG == 1 && want) d <= nd;
        end
      end
    endmodule
    module unitB #(parameter BUG = 0) (input wire clk, input wire rst, input wire want, input wire [3:0] nd, input wire gnt);
      wire req; wire [3:0] data;
      reg init0 = 1'b1; always @(posedge clk) init0 <= 1'b0; always @(*) if (init0) assume (rst);
      b_req #(.BUG(BUG)) u_b (.clk(clk), .rst(rst), .want(want), .nd(nd), .gnt(gnt), .req(req), .data(data));
      hold_rule #(.ASSUME(0)) u_r (.clk(clk), .rst(rst), .req(req), .data(data), .gnt(gnt));
    endmodule
    module sysAB #(parameter BUG = 0) (input wire clk, input wire rst, input wire want, input wire [3:0] nd, input wire gnt);
      wire req; wire [3:0] data; wire ov; wire [3:0] out; wire dp; wire [3:0] dh;
      reg init0 = 1'b1; always @(posedge clk) init0 <= 1'b0; always @(*) if (init0) assume (rst);
      b_req #(.BUG(BUG)) u_b (.clk(clk), .rst(rst), .want(want), .nd(nd), .gnt(gnt), .req(req), .data(data));
      a_blk u_a (.clk(clk), .rst(rst), .req(req), .data(data), .gnt(gnt), .ov(ov), .out(out), .dbg_pend(dp), .dbg_held(dh));
      always @(*) if (!init0 && BUG == 0) begin h_pend_req: assert (!dp || req); h_pend_held: assert (!dp || dh == data); end
      a_spec u_s (.clk(clk), .rst(rst), .req(req), .data(data), .gnt(gnt), .ov(ov), .out(out));
    endmodule
    a_blk.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
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    // formal: bmc 4 expect fail slang top unitB define BUG=1
    `define FORMAL
    module a_blk (input wire clk, input wire rst, input wire req, input wire [3:0] data, input wire gnt,
                  output reg ov, output reg [3:0] out, output wire dbg_pend, output wire [3:0] dbg_held);
      reg pend; reg [3:0] held;
      assign dbg_pend = pend; assign dbg_held = held;
      always @(posedge clk) begin
        if (rst) begin pend <= 1'b0; ov <= 1'b0; end
        else begin
          ov <= req && gnt;
          if (req && !gnt) pend <= 1'b1; else if (gnt) pend <= 1'b0;
          if (req && !pend) held <= data;
          out <= pend ? held : data;
        end
      end
    endmodule
    module hold_rule #(parameter ASSUME = 0) (input wire clk, input wire rst, input wire req, input wire [3:0] data, input wire gnt);
      reg init = 1'b1; reg pv = 1'b0, pg = 1'b0, prst = 1'b1; reg [3:0] pd = 4'd0;
      always @(posedge clk) begin init <= 1'b0; pv <= req; pg <= gnt; prst <= rst; pd <= data; end
      wire waiting = !init && !rst && !prst && pv && !pg;
      generate if (ASSUME == 2) begin : g_n
      end else if (ASSUME) begin : g_a
        always @(*) if (waiting) begin r_req: assume (req); r_dat: assume (data == pd); end
      end else begin : g_s
        always @(*) if (waiting) begin r_req: assert (req); r_dat: assert (data == pd); end
      end endgenerate
    endmodule
    module a_spec (input wire clk, input wire rst, input wire req, input wire [3:0] data, input wire gnt, input wire ov, input wire [3:0] out);
      reg init = 1'b1; reg pgo = 1'b0, prst = 1'b1; reg [3:0] pd = 4'd0;
      always @(posedge clk) begin init <= 1'b0; pgo <= req && gnt; prst <= rst; pd <= data; end
      always @(*) if (!init && !prst && pgo) a_answer: assert (ov && out == pd);
      always @(*) if (!init) c_wait_then_grant: cover (!prst && ov && out == pd && out != 4'd0);
    endmodule
    module unitA #(parameter ASSUME = 1, parameter BUG = 0) (input wire clk, input wire rst, input wire req, input wire [3:0] data, input wire gnt);
      wire ov; wire [3:0] out; wire dp; wire [3:0] dh;
      reg init0 = 1'b1; always @(posedge clk) init0 <= 1'b0; always @(*) if (init0) assume (rst);
      a_blk u_a (.clk(clk), .rst(rst), .req(req), .data(data), .gnt(gnt), .ov(ov), .out(out), .dbg_pend(dp), .dbg_held(dh));
      reg qv = 1'b0, qg = 1'b0; always @(posedge clk) begin qv <= req; qg <= gnt; end
      always @(*) if (!init0 && ASSUME == 1) h_hist: assert (!dp || rst || (qv && !qg));
      always @(*) if (!init0 && ASSUME == 1) h_pend: assert (!dp || rst || dh == data);
      hold_rule #(.ASSUME(ASSUME)) u_r (.clk(clk), .rst(rst), .req(req), .data(data), .gnt(gnt));
      a_spec u_s (.clk(clk), .rst(rst), .req(req), .data(data), .gnt(gnt), .ov(ov), .out(out));
    endmodule
    module b_req #(parameter BUG = 0) (input wire clk, input wire rst, input wire want, input wire [3:0] nd, input wire gnt,
                                       output wire req, output wire [3:0] data);
      reg busy; reg [3:0] d;
      assign req = busy; assign data = d;
      always @(posedge clk) begin
        if (rst) busy <= 1'b0;
        else begin
          if (!busy && want) begin busy <= 1'b1; d <= nd; end
          else if (busy && gnt) busy <= 1'b0;
          else if (busy && BUG == 1 && want) d <= nd;
        end
      end
    endmodule
    module unitB #(parameter BUG = 0) (input wire clk, input wire rst, input wire want, input wire [3:0] nd, input wire gnt);
      wire req; wire [3:0] data;
      reg init0 = 1'b1; always @(posedge clk) init0 <= 1'b0; always @(*) if (init0) assume (rst);
      b_req #(.BUG(BUG)) u_b (.clk(clk), .rst(rst), .want(want), .nd(nd), .gnt(gnt), .req(req), .data(data));
      hold_rule #(.ASSUME(0)) u_r (.clk(clk), .rst(rst), .req(req), .data(data), .gnt(gnt));
    endmodule
    module sysAB #(parameter BUG = 0) (input wire clk, input wire rst, input wire want, input wire [3:0] nd, input wire gnt);
      wire req; wire [3:0] data; wire ov; wire [3:0] out; wire dp; wire [3:0] dh;
      reg init0 = 1'b1; always @(posedge clk) init0 <= 1'b0; always @(*) if (init0) assume (rst);
      b_req #(.BUG(BUG)) u_b (.clk(clk), .rst(rst), .want(want), .nd(nd), .gnt(gnt), .req(req), .data(data));
      a_blk u_a (.clk(clk), .rst(rst), .req(req), .data(data), .gnt(gnt), .ov(ov), .out(out), .dbg_pend(dp), .dbg_held(dh));
      always @(*) if (!init0 && BUG == 0) begin h_pend_req: assert (!dp || req); h_pend_held: assert (!dp || dh == data); end
      a_spec u_s (.clk(clk), .rst(rst), .req(req), .data(data), .gnt(gnt), .ov(ov), .out(out));
    endmodule
    a_blk.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
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    // formal: prove 6 expect pass slang top unitA define ASSUME=1 define BUG=0
    `define FORMAL
    module a_blk (input wire clk, input wire rst, input wire req, input wire [3:0] data, input wire gnt,
                  output reg ov, output reg [3:0] out, output wire dbg_pend, output wire [3:0] dbg_held);
      reg pend; reg [3:0] held;
      assign dbg_pend = pend; assign dbg_held = held;
      always @(posedge clk) begin
        if (rst) begin pend <= 1'b0; ov <= 1'b0; end
        else begin
          ov <= req && gnt;
          if (req && !gnt) pend <= 1'b1; else if (gnt) pend <= 1'b0;
          if (req && !pend) held <= data;
          out <= pend ? held : data;
        end
      end
    endmodule
    module hold_rule #(parameter ASSUME = 0) (input wire clk, input wire rst, input wire req, input wire [3:0] data, input wire gnt);
      reg init = 1'b1; reg pv = 1'b0, pg = 1'b0, prst = 1'b1; reg [3:0] pd = 4'd0;
      always @(posedge clk) begin init <= 1'b0; pv <= req; pg <= gnt; prst <= rst; pd <= data; end
      wire waiting = !init && !rst && !prst && pv && !pg;
      generate if (ASSUME == 2) begin : g_n
      end else if (ASSUME) begin : g_a
        always @(*) if (waiting) begin r_req: assume (req); r_dat: assume (data == pd); end
      end else begin : g_s
        always @(*) if (waiting) begin r_req: assert (req); r_dat: assert (data == pd); end
      end endgenerate
    endmodule
    module a_spec (input wire clk, input wire rst, input wire req, input wire [3:0] data, input wire gnt, input wire ov, input wire [3:0] out);
      reg init = 1'b1; reg pgo = 1'b0, prst = 1'b1; reg [3:0] pd = 4'd0;
      always @(posedge clk) begin init <= 1'b0; pgo <= req && gnt; prst <= rst; pd <= data; end
      always @(*) if (!init && !prst && pgo) a_answer: assert (ov && out == pd);
      always @(*) if (!init) c_wait_then_grant: cover (!prst && ov && out == pd && out != 4'd0);
    endmodule
    module unitA #(parameter ASSUME = 1, parameter BUG = 0) (input wire clk, input wire rst, input wire req, input wire [3:0] data, input wire gnt);
      wire ov; wire [3:0] out; wire dp; wire [3:0] dh;
      reg init0 = 1'b1; always @(posedge clk) init0 <= 1'b0; always @(*) if (init0) assume (rst);
      a_blk u_a (.clk(clk), .rst(rst), .req(req), .data(data), .gnt(gnt), .ov(ov), .out(out), .dbg_pend(dp), .dbg_held(dh));
      reg qv = 1'b0, qg = 1'b0; always @(posedge clk) begin qv <= req; qg <= gnt; end
      always @(*) if (!init0 && ASSUME == 1) h_hist: assert (!dp || rst || (qv && !qg));
      always @(*) if (!init0 && ASSUME == 1) h_pend: assert (!dp || rst || dh == data);
      hold_rule #(.ASSUME(ASSUME)) u_r (.clk(clk), .rst(rst), .req(req), .data(data), .gnt(gnt));
      a_spec u_s (.clk(clk), .rst(rst), .req(req), .data(data), .gnt(gnt), .ov(ov), .out(out));
    endmodule
    module b_req #(parameter BUG = 0) (input wire clk, input wire rst, input wire want, input wire [3:0] nd, input wire gnt,
                                       output wire req, output wire [3:0] data);
      reg busy; reg [3:0] d;
      assign req = busy; assign data = d;
      always @(posedge clk) begin
        if (rst) busy <= 1'b0;
        else begin
          if (!busy && want) begin busy <= 1'b1; d <= nd; end
          else if (busy && gnt) busy <= 1'b0;
          else if (busy && BUG == 1 && want) d <= nd;
        end
      end
    endmodule
    module unitB #(parameter BUG = 0) (input wire clk, input wire rst, input wire want, input wire [3:0] nd, input wire gnt);
      wire req; wire [3:0] data;
      reg init0 = 1'b1; always @(posedge clk) init0 <= 1'b0; always @(*) if (init0) assume (rst);
      b_req #(.BUG(BUG)) u_b (.clk(clk), .rst(rst), .want(want), .nd(nd), .gnt(gnt), .req(req), .data(data));
      hold_rule #(.ASSUME(0)) u_r (.clk(clk), .rst(rst), .req(req), .data(data), .gnt(gnt));
    endmodule
    module sysAB #(parameter BUG = 0) (input wire clk, input wire rst, input wire want, input wire [3:0] nd, input wire gnt);
      wire req; wire [3:0] data; wire ov; wire [3:0] out; wire dp; wire [3:0] dh;
      reg init0 = 1'b1; always @(posedge clk) init0 <= 1'b0; always @(*) if (init0) assume (rst);
      b_req #(.BUG(BUG)) u_b (.clk(clk), .rst(rst), .want(want), .nd(nd), .gnt(gnt), .req(req), .data(data));
      a_blk u_a (.clk(clk), .rst(rst), .req(req), .data(data), .gnt(gnt), .ov(ov), .out(out), .dbg_pend(dp), .dbg_held(dh));
      always @(*) if (!init0 && BUG == 0) begin h_pend_req: assert (!dp || req); h_pend_held: assert (!dp || dh == data); end
      a_spec u_s (.clk(clk), .rst(rst), .req(req), .data(data), .gnt(gnt), .ov(ov), .out(out));
    endmodule
    a_blk.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
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    // formal: prove 6 expect pass slang top sysAB define BUG=0
    `define FORMAL
    module a_blk (input wire clk, input wire rst, input wire req, input wire [3:0] data, input wire gnt,
                  output reg ov, output reg [3:0] out, output wire dbg_pend, output wire [3:0] dbg_held);
      reg pend; reg [3:0] held;
      assign dbg_pend = pend; assign dbg_held = held;
      always @(posedge clk) begin
        if (rst) begin pend <= 1'b0; ov <= 1'b0; end
        else begin
          ov <= req && gnt;
          if (req && !gnt) pend <= 1'b1; else if (gnt) pend <= 1'b0;
          if (req && !pend) held <= data;
          out <= pend ? held : data;
        end
      end
    endmodule
    module hold_rule #(parameter ASSUME = 0) (input wire clk, input wire rst, input wire req, input wire [3:0] data, input wire gnt);
      reg init = 1'b1; reg pv = 1'b0, pg = 1'b0, prst = 1'b1; reg [3:0] pd = 4'd0;
      always @(posedge clk) begin init <= 1'b0; pv <= req; pg <= gnt; prst <= rst; pd <= data; end
      wire waiting = !init && !rst && !prst && pv && !pg;
      generate if (ASSUME == 2) begin : g_n
      end else if (ASSUME) begin : g_a
        always @(*) if (waiting) begin r_req: assume (req); r_dat: assume (data == pd); end
      end else begin : g_s
        always @(*) if (waiting) begin r_req: assert (req); r_dat: assert (data == pd); end
      end endgenerate
    endmodule
    module a_spec (input wire clk, input wire rst, input wire req, input wire [3:0] data, input wire gnt, input wire ov, input wire [3:0] out);
      reg init = 1'b1; reg pgo = 1'b0, prst = 1'b1; reg [3:0] pd = 4'd0;
      always @(posedge clk) begin init <= 1'b0; pgo <= req && gnt; prst <= rst; pd <= data; end
      always @(*) if (!init && !prst && pgo) a_answer: assert (ov && out == pd);
      always @(*) if (!init) c_wait_then_grant: cover (!prst && ov && out == pd && out != 4'd0);
    endmodule
    module unitA #(parameter ASSUME = 1, parameter BUG = 0) (input wire clk, input wire rst, input wire req, input wire [3:0] data, input wire gnt);
      wire ov; wire [3:0] out; wire dp; wire [3:0] dh;
      reg init0 = 1'b1; always @(posedge clk) init0 <= 1'b0; always @(*) if (init0) assume (rst);
      a_blk u_a (.clk(clk), .rst(rst), .req(req), .data(data), .gnt(gnt), .ov(ov), .out(out), .dbg_pend(dp), .dbg_held(dh));
      reg qv = 1'b0, qg = 1'b0; always @(posedge clk) begin qv <= req; qg <= gnt; end
      always @(*) if (!init0 && ASSUME == 1) h_hist: assert (!dp || rst || (qv && !qg));
      always @(*) if (!init0 && ASSUME == 1) h_pend: assert (!dp || rst || dh == data);
      hold_rule #(.ASSUME(ASSUME)) u_r (.clk(clk), .rst(rst), .req(req), .data(data), .gnt(gnt));
      a_spec u_s (.clk(clk), .rst(rst), .req(req), .data(data), .gnt(gnt), .ov(ov), .out(out));
    endmodule
    module b_req #(parameter BUG = 0) (input wire clk, input wire rst, input wire want, input wire [3:0] nd, input wire gnt,
                                       output wire req, output wire [3:0] data);
      reg busy; reg [3:0] d;
      assign req = busy; assign data = d;
      always @(posedge clk) begin
        if (rst) busy <= 1'b0;
        else begin
          if (!busy && want) begin busy <= 1'b1; d <= nd; end
          else if (busy && gnt) busy <= 1'b0;
          else if (busy && BUG == 1 && want) d <= nd;
        end
      end
    endmodule
    module unitB #(parameter BUG = 0) (input wire clk, input wire rst, input wire want, input wire [3:0] nd, input wire gnt);
      wire req; wire [3:0] data;
      reg init0 = 1'b1; always @(posedge clk) init0 <= 1'b0; always @(*) if (init0) assume (rst);
      b_req #(.BUG(BUG)) u_b (.clk(clk), .rst(rst), .want(want), .nd(nd), .gnt(gnt), .req(req), .data(data));
      hold_rule #(.ASSUME(0)) u_r (.clk(clk), .rst(rst), .req(req), .data(data), .gnt(gnt));
    endmodule
    module sysAB #(parameter BUG = 0) (input wire clk, input wire rst, input wire want, input wire [3:0] nd, input wire gnt);
      wire req; wire [3:0] data; wire ov; wire [3:0] out; wire dp; wire [3:0] dh;
      reg init0 = 1'b1; always @(posedge clk) init0 <= 1'b0; always @(*) if (init0) assume (rst);
      b_req #(.BUG(BUG)) u_b (.clk(clk), .rst(rst), .want(want), .nd(nd), .gnt(gnt), .req(req), .data(data));
      a_blk u_a (.clk(clk), .rst(rst), .req(req), .data(data), .gnt(gnt), .ov(ov), .out(out), .dbg_pend(dp), .dbg_held(dh));
      always @(*) if (!init0 && BUG == 0) begin h_pend_req: assert (!dp || req); h_pend_held: assert (!dp || dh == data); end
      a_spec u_s (.clk(clk), .rst(rst), .req(req), .data(data), .gnt(gnt), .ov(ov), .out(out));
    endmodule
    a_blk.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
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    // formal: bmc 5 expect fail slang top sysAB define BUG=1
    `define FORMAL
    module a_blk (input wire clk, input wire rst, input wire req, input wire [3:0] data, input wire gnt,
                  output reg ov, output reg [3:0] out, output wire dbg_pend, output wire [3:0] dbg_held);
      reg pend; reg [3:0] held;
      assign dbg_pend = pend; assign dbg_held = held;
      always @(posedge clk) begin
        if (rst) begin pend <= 1'b0; ov <= 1'b0; end
        else begin
          ov <= req && gnt;
          if (req && !gnt) pend <= 1'b1; else if (gnt) pend <= 1'b0;
          if (req && !pend) held <= data;
          out <= pend ? held : data;
        end
      end
    endmodule
    module hold_rule #(parameter ASSUME = 0) (input wire clk, input wire rst, input wire req, input wire [3:0] data, input wire gnt);
      reg init = 1'b1; reg pv = 1'b0, pg = 1'b0, prst = 1'b1; reg [3:0] pd = 4'd0;
      always @(posedge clk) begin init <= 1'b0; pv <= req; pg <= gnt; prst <= rst; pd <= data; end
      wire waiting = !init && !rst && !prst && pv && !pg;
      generate if (ASSUME == 2) begin : g_n
      end else if (ASSUME) begin : g_a
        always @(*) if (waiting) begin r_req: assume (req); r_dat: assume (data == pd); end
      end else begin : g_s
        always @(*) if (waiting) begin r_req: assert (req); r_dat: assert (data == pd); end
      end endgenerate
    endmodule
    module a_spec (input wire clk, input wire rst, input wire req, input wire [3:0] data, input wire gnt, input wire ov, input wire [3:0] out);
      reg init = 1'b1; reg pgo = 1'b0, prst = 1'b1; reg [3:0] pd = 4'd0;
      always @(posedge clk) begin init <= 1'b0; pgo <= req && gnt; prst <= rst; pd <= data; end
      always @(*) if (!init && !prst && pgo) a_answer: assert (ov && out == pd);
      always @(*) if (!init) c_wait_then_grant: cover (!prst && ov && out == pd && out != 4'd0);
    endmodule
    module unitA #(parameter ASSUME = 1, parameter BUG = 0) (input wire clk, input wire rst, input wire req, input wire [3:0] data, input wire gnt);
      wire ov; wire [3:0] out; wire dp; wire [3:0] dh;
      reg init0 = 1'b1; always @(posedge clk) init0 <= 1'b0; always @(*) if (init0) assume (rst);
      a_blk u_a (.clk(clk), .rst(rst), .req(req), .data(data), .gnt(gnt), .ov(ov), .out(out), .dbg_pend(dp), .dbg_held(dh));
      reg qv = 1'b0, qg = 1'b0; always @(posedge clk) begin qv <= req; qg <= gnt; end
      always @(*) if (!init0 && ASSUME == 1) h_hist: assert (!dp || rst || (qv && !qg));
      always @(*) if (!init0 && ASSUME == 1) h_pend: assert (!dp || rst || dh == data);
      hold_rule #(.ASSUME(ASSUME)) u_r (.clk(clk), .rst(rst), .req(req), .data(data), .gnt(gnt));
      a_spec u_s (.clk(clk), .rst(rst), .req(req), .data(data), .gnt(gnt), .ov(ov), .out(out));
    endmodule
    module b_req #(parameter BUG = 0) (input wire clk, input wire rst, input wire want, input wire [3:0] nd, input wire gnt,
                                       output wire req, output wire [3:0] data);
      reg busy; reg [3:0] d;
      assign req = busy; assign data = d;
      always @(posedge clk) begin
        if (rst) busy <= 1'b0;
        else begin
          if (!busy && want) begin busy <= 1'b1; d <= nd; end
          else if (busy && gnt) busy <= 1'b0;
          else if (busy && BUG == 1 && want) d <= nd;
        end
      end
    endmodule
    module unitB #(parameter BUG = 0) (input wire clk, input wire rst, input wire want, input wire [3:0] nd, input wire gnt);
      wire req; wire [3:0] data;
      reg init0 = 1'b1; always @(posedge clk) init0 <= 1'b0; always @(*) if (init0) assume (rst);
      b_req #(.BUG(BUG)) u_b (.clk(clk), .rst(rst), .want(want), .nd(nd), .gnt(gnt), .req(req), .data(data));
      hold_rule #(.ASSUME(0)) u_r (.clk(clk), .rst(rst), .req(req), .data(data), .gnt(gnt));
    endmodule
    module sysAB #(parameter BUG = 0) (input wire clk, input wire rst, input wire want, input wire [3:0] nd, input wire gnt);
      wire req; wire [3:0] data; wire ov; wire [3:0] out; wire dp; wire [3:0] dh;
      reg init0 = 1'b1; always @(posedge clk) init0 <= 1'b0; always @(*) if (init0) assume (rst);
      b_req #(.BUG(BUG)) u_b (.clk(clk), .rst(rst), .want(want), .nd(nd), .gnt(gnt), .req(req), .data(data));
      a_blk u_a (.clk(clk), .rst(rst), .req(req), .data(data), .gnt(gnt), .ov(ov), .out(out), .dbg_pend(dp), .dbg_held(dh));
      always @(*) if (!init0 && BUG == 0) begin h_pend_req: assert (!dp || req); h_pend_held: assert (!dp || dh == data); end
      a_spec u_s (.clk(clk), .rst(rst), .req(req), .data(data), .gnt(gnt), .ov(ov), .out(out));
    endmodule

    Step

    B drives (req, data) and A sees gnt

    What breaks

    2

    1, 1; gnt 0

    B waits with word 1

    3

    1, 0; gnt 1

    B swapped in word 0 while waiting (the rule fails at this step in B's own proof); the grant arrives

    4

    -

    A answers with the held word 1; a_answer fails: the grant cycle carried 0

    The system proof for the good B passes with two helper assertions about A's internal state; they are asserted only when B is good, because they are not invariants of the faulty requester. The rule is now discharged: A is proved under X, B proves X, and the two together prove the specification.

    What a reviewer looks for

    • Each assumption in a unit proof has a named assertion on the neighbour, in a table, with its proof result.

    • The rule text is shared between the assume and the assert, so the two cannot drift.

    • A neighbour fault is planted and shown to fail the assertion while the unit proof of the consumer still passes.

    Verify and debug

    When integration fails and the unit proofs pass, list the assumptions of the failing block and look for the assertion that should discharge each. A row without an assertion, or with one that passes only because it is assumed, is the gap.

    The assume that hides a real bug. Symptom: a block proves clean and silicon fails. Cause: the failing input was assumed away instead of asserted on the neighbour. Fix: assert at the block boundary when the neighbour is verified, and keep assumes for documented interface rules. Found by: a neighbour fault that the unit proof of the consumer does not see.

    "The unit proof is clean; why does integration fail?" Because every assumption of the unit is somebody else's duty. Show the rule module used twice, the neighbour fault failing its assertion at step 3 and the system failing at step 4.

    Check yourself The faulty B fails its own assertion at step 3 but the system fails at step 4. Why the extra step?

    The system property is A's answer, which appears one cycle after the grant that uses B's changed word. B's assertion sees the changed word the cycle it appears.

    Related topics

    • Assume-Guarantee Contracts

    • Formal Signoff Criteria

    • Previous: The Assumption Review

    • Next topic: Abstraction and Complexity

    Previous

    48 / 183

    Next: Abstraction and Complexity

    Up next

    Up nextAbstraction and Complexity

    Sign in to save progress

    Practice this lessonPrevious lessonReport an error

    See also

    • Assumption Taxonomy and Ownership
    • Assume Versus Assert by Side