TCJJ

导航

SV_14_Assertions

摘要:断言验证是指使用断言语言来指定设计中的预期行为,以及相对于验证中的设计来评估断言的工具。

  • ABV:基于断言的验证运行设计工程师在设计过程中获取验证信息,还支持内部状态、数据路径和错误先决条件覆盖分析;
  • 一个 简单例子就是FIFO的判断空满;
  • HDL可以编写断言,但其形式是很复杂的;

1. 断言的两种形式 

  • Immediate Assertions:基于事件语义,与always块相似;
  • Concurrent Assertions:基于时钟语义,与带时钟的always块相似。

1.1 Immediate Assertions

  • 立即断言是对过程语句宏表达式的测试;
  • 如果表达式的结果为x、z、0,则断言解释为false,断言失败;否则断言成功。
1 assertion_label : assert (expression)
2  pass block code;
3 else
4 fail block code;

1.1.1 一些打印的信息:

  • $fatal:运行致命错误;
  • $error:运行错误;
  • $warning:运行警告,可以被一些特殊工具覆盖掉;
  • $info:打印一些失败信息,无特定的严重程度;

也可以使用$display()函数

 1 //+++++++++++++++++++++++++++++++++++++++++++++++++
 2 // DUT With Immediate assertions
 3 //+++++++++++++++++++++++++++++++++++++++++++++++++
 4 module assert_immediate();
 5
 6 reg clk, grant, request;
 7 time current_time;
 8
 9 initial begin
10 clk = 0;
11 grant = 0;
12 request = 0;
13 #4 request = 1;
14 #4 grant = 1;
15 #4 request = 0;
16 #4 $finish;
17 end
18
19 always #1 clk = ~clk;
20 //=================================================
21 // Assertion used in always block
22 //=================================================
23 always @ (posedge clk)
24 begin
25 if (grant == 1) begin
26 CHECK_REQ_WHEN_GNT : assert (grant && request) begin
27 $display ("Seems to be working as expected");
28 end else begin
29 current_time = $time;
30 #1 $error("assert failed at time %0t", current_time);
31 end
32 end
33 end
34
35 endmodule
36
37 //compile result
38
39 Info: "assert_immediate.sv", 21:
40 assert_immediate.CHECK_REQ_WHEN_GNT: at time 9
41  Seems to be working as expected
42 Info: "assert_immediate.sv", 21:
43 assert_immediate.CHECK_REQ_WHEN_GNT: at time 11
44  Seems to be working as expected
45 "assert_immediate.sv", 21:
46  assert_immediate.CHECK_REQ_WHEN_GNT:
47  started at 13s failed at 13s
48 Offending '(grant && request)'
49 Error: "assert_immediate.sv", 21:
50 assert_immediate.CHECK_REQ_WHEN_GNT: at time 14
51 assert failed at time 13
52 "assert_immediate.sv", 21:
53  assert_immediate.CHECK_REQ_WHEN_GNT:
54  started at 15s failed at 15s
55 Offending '(grant && request)'
View Code

2. Concurrent assertions

  • 并发断言描述跨时间的行为;
  • 并发断言仅在时钟tick时才计算;
  • 评估中使用的值为采样值,避免了模拟器对事件的影响;
  • 关键字propert将并发断言与立即断言分开;

2.1 并发断言有以下几层

  • Boolean:布尔代数层
  • Sequences:序列层
  • Property:属性层
  • Property directive:属性指令层

一个例子:

测试波形:

 测试代码:

 1 //+++++++++++++++++++++++++++++++++++++++++++++++++
 2 // DUT With assertions
 3 //+++++++++++++++++++++++++++++++++++++++++++++++++
 4 module concurrent_assertion(
 5 input wire clk,req,reset,
 6 output reg gnt);
 7 //=================================================
 8 // Sequence Layer
 9 //=================================================
10 sequence req_gnt_seq;
11 // (~req & gnt) and (~req & ~gnt) is Boolean Layer
12 (~req & gnt) ##1 (~req & ~gnt);
13 endsequence
14 //=================================================
15 // Property Specification Layer
16 //=================================================
17 property req_gnt_prop;
18 @ (posedge clk)
19 disable iff (reset)
20 req |-> req_gnt_seq;
21 endproperty
22 //=================================================
23 // Assertion Directive Layer
24 //=================================================
25 req_gnt_assert : assert property (req_gnt_prop)
26 else
27 $display("@%0dns Assertion Failed", $time);
28 //=================================================
29 // Actual DUT RTL
30 //=================================================
31 always @ (posedge clk)
32 gnt <= req;
33
34 endmodule
35
36 //+++++++++++++++++++++++++++++++++++++++++++++++
37 // Testbench Code
38 //+++++++++++++++++++++++++++++++++++++++++++++++
39 module concurrent_assertion_tb();
40
41 reg clk = 0;
42 reg reset, req = 0;
43 wire gnt;
44
45 always #3 clk ++;
46
47 initial begin
48 reset <= 1;
49 #20 reset <= 0;
50 // Make the assertion pass
51 #100 @ (posedge clk) req <= 1;
52 @ (posedge clk) req <= 0;
53 // Make the assertion fail
54 #100 @ (posedge clk) req <= 1;
55 repeat (5) @ (posedge clk);
56 req <= 0;
57 #10 $finish;
58 end
59
60 concurrent_assertion dut (clk,req,reset,gnt);
61
62 endmodule
63 //compile result
64
65  @129ns Assertion Failed
66  @237ns Assertion Failed
67  @243ns Assertion Failed
68  @249ns Assertion Failed
69  @255ns Assertion Failed
70 @261ns Assertion Failed
View Code

  在并发断言的所有层中:

  • 基本的构建块是布尔层,它的值为0或1;
  • 序列层基本是建立在布尔层上,序列定义任何并发断言的最基本构造;
  • 属性层建立在序列层之上(并不总是如此)。
  • 要使属性成为模拟的一部分,需要在属性执行层中的assert语句中使用该属性。

2.2 Boolean layer

  • 布尔层是并发断言的最底层,对变量进行布尔表达式检查;
  • 布尔表达式允许包含函数调用;
  1. 出现在表达式中的函数不能包含 output 或 ref 参数 (允许使用 const ref 参数 );
  2. 函数应该是automatic的(或者不保留状态信息),并且没有副作用;

布尔层的使用限制

不能使用的数据类型:

  • shortreal, real,realtime
  • string
  • event
  • handle
  • class
  • associative arrays
  • dynamic arrays

不能使用的操作符:

  • assignment(赋值),increment(自增),decrement(自减)
1 module assertion_boolean();
2
3 wire ce, en;
4 wire [7:0] addr;
5
6 // This code will not compile
7 (en && ce && addr < 100);
8
9 endmodule

2.3 Sequences

  • 序列层使用布尔层来构造有效地时间序列;
  • 最简单的序列行为是线性序列;
  1. 线性序列是一个有限的SV布尔表达式列表,它按线性顺序递增;
  2. 在第一个时钟周期的第一个布尔表达式为真,第二个时钟周期的第二个布尔表达式为真,直到最后一个 时钟周期的布尔表达式为真,才会匹配成功。
  • 序列可以声明的位置:
  1. module
  2. interface
  3. program
  4. clocking block
  5. package
  • 序列之间可以互相调用;
  • 一些构造序列的操作符:
  1. ##
  2. [* ]
  3. [= ]
  4. [-> ]
  5. throughout
  6. within left
  7. intersect
  8. and
  9. or

2.3.1 ## operator

  • ##后跟一个数字或者一个范围;
  • req ##1 gnt :表示gnt在 req一个时钟后发生;
  • req ##0 gnt:表示gnt 与 req 在同一边缘上,通常用于合并两个序列;
  • req  ##[0:3] gnt:表示  gnt 在 req的0-3个时钟后有效;
  • 可以用变量代替常量表示延迟。
  1 //+++++++++++++++++++++++++++++++++++++++++++++++++
  2 //   DUT With assertions
  3 //+++++++++++++++++++++++++++++++++++++++++++++++++
  4 module hash_sequence();
  5 
  6 logic clk = 0;
  7 always #1 clk ++;
  8 
  9 logic [2:0] req,gnt;
 10 logic reset;
 11 //=================================================
 12 // Shows basic usage of ## delay operator
 13 //=================================================
 14 sequence req_gnt_1clock_seq;
 15   req[0] ##1 gnt[0];
 16 endsequence
 17 //=================================================
 18 // Shows range usage of ## delay operator
 19 //=================================================
 20 sequence req_gnt_3to5clock_seq;
 21   req[1] ##[3:5] gnt[1];
 22 endsequence
 23 //=================================================
 24 // Shows zero delay usage of ## delay operator
 25 //=================================================
 26 sequence req_gnt_0clock_seq;
 27   req[2] ##0 gnt[2];
 28 endsequence
 29 //=================================================
 30 // Shows sequence called within sequence 
 31 //=================================================
 32 sequence master_seq;
 33   req_gnt_1clock_seq ##1 req_gnt_3to5clock_seq ##1 req_gnt_0clock_seq;
 34 endsequence
 35 //=================================================
 36 //  Declare property for each of sequence
 37 //  We may use more then one seuqnce in a property
 38 //=================================================
 39 property req_gnt_1clock_prop;
 40   @ (posedge clk)
 41   disable iff (reset)
 42      req[0] |-> req_gnt_1clock_seq;
 43 endproperty
 44 
 45 property req_gnt_3to5clock_prop;
 46   @ (posedge clk)
 47   disable iff (reset)
 48      req[1] |-> req_gnt_3to5clock_seq;
 49 endproperty
 50 
 51 property req_gnt_0clock_prop;
 52   @ (posedge clk)
 53   disable iff (reset)
 54      req[2] |-> req_gnt_0clock_seq;
 55 endproperty
 56 
 57 property master_prop;
 58   @ (posedge clk)
 59   disable iff (reset)
 60      req[0] |-> master_seq;
 61 endproperty
 62   
 63 //=================================================
 64 // Assertion Directive Layer
 65 //=================================================
 66 req_gnt_1clock_assert    : assert property (req_gnt_1clock_prop);
 67 req_gnt_3to5clock_assert : assert property (req_gnt_3to5clock_prop);
 68 req_gnt_0clock_assert    : assert property (req_gnt_0clock_prop);
 69 master_assert            : assert property (master_prop);
 70 
 71 //=================================================
 72 // Drive the input vectors to test assetion
 73 //=================================================
 74 initial begin
 75   // Init all the values
 76   reset  <= 0;
 77   for (int i = 0; i < 3; i++) begin
 78     req[i] <= 0;
 79     gnt[i] <= 0;
 80   end
 81   @ (posedge clk);
 82   req[0] <= 1;
 83   @ (posedge clk);
 84   gnt[0] <= 1;
 85   req[0] <= 0;
 86   @ (posedge clk);
 87   gnt[0] <= 0;
 88   req[1] <= 1;
 89   @ (posedge clk);
 90   req[1] <= 0;
 91   repeat(3) @ (posedge clk);
 92   gnt[1] <= 1;
 93   @ (posedge clk);
 94   gnt[1] <= 0;
 95   req[2] <= 1;
 96   gnt[2] <= 1;
 97   @ (posedge clk);
 98   req[2] <= 0;
 99   gnt[2] <= 0;
100   // Cause assertion to fail
101   @ (posedge clk);
102   req[0] <= 1;
103   repeat(2) @ (posedge clk);
104   gnt[0] <= 1;
105   req[0] <= 0;
106   #30 $finish;
107 end
108 
109 endmodule
110 
111 //compile  result
112  Error: Assertion error.
113  Time: 23 ns Started: 21 ns  Scope: 
114  hash_sequence.req_gnt_1clock_assert File: hash_sequence.sv Line: 63
115  Error: Assertion error.
116  Time: 23 ns Started: 21 ns  Scope: 
117  hash_sequence.master_assert File: hash_sequence.sv Line: 66
118  Error: Assertion error.
119  Time: 27 ns Started: 23 ns  Scope: 
120  hash_sequence.master_assert File: hash_sequence.sv Line: 66
View Code

2.3.2 Repetition operators

测试的序列需要重复时,有以下三种方式可供选择:(最小值可以小于0,最大值为$)

  • a[*n ]b:连续跟随重复操作符,重复之间以及两个匹配之间只有一个时钟的延迟;

 

 

  

 

  • [-> ]:不连续跟随重复操作符,重复之间可以有多个时钟的延迟,两个匹配之间只有一个时钟的延迟;

  • [= ]:不连续不跟随重复操作符,重复之间以及两个匹配之间可以有多个时钟的延迟;

  •  empty sequence:空序列是一个不匹配任何正整数时钟ticks的序列;
    • (empty ##0 seq ) 没有匹配结果;
    • (seq ##0 empty ) 没有匹配结果;
    • (empty ##n seq ) 其中n>0,相当于 (##(n-1)seq);
    • (seq ##n empty ) 其中n>0,相当于(seq  ##(n-1));

consective repetition例子波形图:

 consective repetition例子代码:

View Code

 Goto repetition例子波形图:

  Goto repetition例子代码:

 1 //+++++++++++++++++++++++++++++++++++++++++++++++++
 2 //   DUT With assertions
 3 //+++++++++++++++++++++++++++++++++++++++++++++++++
 4 module goto_assertion();
 5 
 6 logic clk = 0;
 7 always #1 clk ++;
 8 
 9 logic req,busy,gnt;
10 //=================================================
11 // Sequence Layer
12 //=================================================
13 sequence boring_way_seq;
14   req ##1 ((!busy[*0:$] ##1 busy) [*3]) ##1 gnt;
15 endsequence
16 
17 sequence cool_way_seq;
18   req ##1 (busy [->3]) ##1 gnt;
19 endsequence
20 
21 //=================================================
22 // Property Specification Layer
23 //=================================================
24 property boring_way_prop;
25   @ (posedge clk) 
26       req |=> boring_way_seq;
27 endproperty
28 
29 property cool_way_prop;
30   @ (posedge clk) 
31       req |=> cool_way_seq;
32 endproperty
33 //=================================================
34 // Assertion Directive Layer
35 //=================================================
36 boring_way_assert : assert property (boring_way_prop);
37 cool_way_assert   : assert property (cool_way_prop);
38 
39 //=================================================
40 // Generate input vectors
41 //=================================================
42 initial begin
43   // Pass sequence
44   gen_seq(3,0); 
45   repeat (20) @ (posedge clk);
46   // Fail sequence (gnt is not asserted properly)
47   gen_seq(3,1); 
48   // Terminate the sim
49   #30 $finish;
50 end
51 //=================================================
52 /// Task to generate input sequence
53 //=================================================
54 task  gen_seq (int busy_delay,int gnt_delay);
55   req <= 0; busy <= 0;gnt <= 0;
56   @ (posedge clk);
57   req <= 1;
58   @ (posedge clk);
59   req  <= 0;
60   repeat (busy_delay) begin
61    @ (posedge clk);
62     busy <= 1;
63    @ (posedge clk);
64     busy <= 0;
65   end
66   repeat (gnt_delay) @ (posedge clk);
67   gnt <= 1;
68   @ (posedge clk);
69   gnt <= 0;
70 endtask
71 
72 endmodule
73 
74 //compile result
75     
76  "goto_assertion.sv", 33: boring_way_assert: 
77    started at 61s failed at 75s
78          Offending 'gnt'
79  "goto_assertion.sv", 34: cool_way_assert: 
80    started at 61s failed at 75s
81          Offending 'gnt
View Code

  NonConsective repetition例子波形图:

NonConsective repetition例子代码:

 1 //+++++++++++++++++++++++++++++++++++++++++++++++++
 2 //   DUT With assertions
 3 //+++++++++++++++++++++++++++++++++++++++++++++++++
 4 module noncon_assertion();
 5 
 6 logic clk = 0;
 7 always #1 clk ++;
 8 
 9 logic req,busy,gnt;
10 //=================================================
11 // Sequence Layer
12 //=================================================
13 sequence boring_way_seq;
14   req ##1 ((!busy[*0:$] ##1 busy) [*3]) ##1 !busy[*0:$] ##1 gnt;
15 endsequence
16 
17 sequence cool_way_seq;
18   req ##1 (busy [=3]) ##1 gnt;
19 endsequence
20 
21 //=================================================
22 // Property Specification Layer
23 //=================================================
24 property boring_way_prop;
25   @ (posedge clk) 
26       req |-> boring_way_seq;
27 endproperty
28 
29 property cool_way_prop;
30   @ (posedge clk) 
31       req |-> cool_way_seq;
32 endproperty
33 //=================================================
34 // Assertion Directive Layer
35 //=================================================
36 boring_way_assert : assert property (boring_way_prop);
37 cool_way_assert   : assert property (cool_way_prop);
38 
39 //=================================================
40 // Generate input vectors
41 //=================================================
42 initial begin
43   // Pass sequence
44   gen_seq(3,0); 
45   repeat (20) @ (posedge clk);
46   // This was fail in goto, but not here
47   gen_seq(3,1); 
48   repeat (20) @ (posedge clk);
49   gen_seq(3,5); 
50   // Lets fail one 
51   repeat (20) @ (posedge clk);
52   gen_seq(5,5); 
53   // Terminate the sim
54   #30 $finish;
55 end
56 //=================================================
57 /// Task to generate input sequence
58 //=================================================
59 task  gen_seq (int busy_delay,int gnt_delay);
60   req <= 0; busy <= 0;gnt <= 0;
61   @ (posedge clk);
62   req <= 1;
63   @ (posedge clk);
64   req  <= 0;
65   repeat (busy_delay) begin
66    @ (posedge clk);
67     busy <= 1;
68    @ (posedge clk);
69     busy <= 0;
70   end
71   repeat (gnt_delay) @ (posedge clk);
72   gnt <= 1;
73   @ (posedge clk);
74   gnt <= 0;
75 endtask
76 
77 endmodule
78 
79 //compile result
80     
81  "noncon_assertion.sv", 33: boring_way_assert: 
82    started at 189s failed at 205s
83          Offending 'gnt'
84  "noncon_assertion.sv", 34: cool_way_assert: 
85    started at 189s failed at 205s
86          Offending 'gnt'
View Code

2.3.4 Binary operators

  • 二元操作符接受两个操作数或两个序列,并生成一个新序列;
  • 几个常用的二元操作符:
  1. and:两个序列同时 开始,不一定同时结束,匹配长度取最大的;
  2. intersect:两个序列同时开始,同时结束;
  3. or :两个序列有一个匹配即可,匹配 长度取最小的;
 1 //+++++++++++++++++++++++++++++++++++++++++++++++++
 2 //   DUT With assertions
 3 //+++++++++++++++++++++++++++++++++++++++++++++++++
 4 module binary_assertion();
 5 
 6 logic clk = 0;
 7 always #1 clk ++;
 8 
 9 logic req,gnt,busy;
10 //=================================================
11 // Sequence Specification Layer
12 //=================================================
13 sequence s1;
14  $past(!req,1) ##1 ($rose(gnt) and $past(!gnt,1));
15 endsequence
16 
17 sequence s2;
18  $past(!req,1) ##1 $rose(gnt) ##1 $fell(gnt);
19 endsequence 
20 
21 sequence s3;
22   req ##1 gnt ##1 busy ##1 (!req and !gnt and !busy);
23 endsequence
24 
25 sequence s4;
26   req ##[1:3] gnt;
27 endsequence
28 //=================================================
29 // Property Specification Layer
30 //=================================================
31 property and_prop;
32   @ (posedge clk) 
33     req |-> s1 and s2;
34 endproperty
35 
36 property intersect_prop;
37   @ (posedge clk) 
38     req |-> s1 intersect s3;
39 endproperty
40 
41 property or_prop;
42   @ (posedge clk) 
43     req |-> s1 or s4;
44 endproperty
45 //=================================================
46 // Assertion Directive Layer
47 //=================================================
48 and_assert       : assert property (and_prop);
49 intersect_assert : assert property (intersect_prop);
50 or_assert        : assert property (or_prop);
51 //=================================================
52 // Generate input vectors
53 //=================================================
54 initial begin
55   req <= 0;gnt <= 0;busy<=0;
56   repeat(10) @ (posedge clk);
57   req <= 1;
58   @( posedge clk);
59   gnt <= 1;
60   req <= 0;
61   @( posedge clk);
62   busy <= 1;
63   // Make the assertion fail now
64   // OR will not fail
65   req <= 0;gnt <= 0; busy <= 0;
66   repeat(10) @ (posedge clk);
67   req <= 1;
68   repeat (2) @( posedge clk);
69   req <= 0;
70   gnt <= 1;
71   @( posedge clk);
72   @( posedge clk);
73   req <= 0;gnt <= 0; busy <= 0;
74   // Terminate the sim
75   #30 $finish;
76 end
77 
78 endmodule
79 
80 //compil result
81     
82  Error: Assertion error.
83  Time: 23 ns Started: 21 ns  
84   intersect_assert File: binary_assertion.sv Line: 46
85  Error: Assertion error.
86  Time: 47 ns Started: 47 ns  
87  and_assert File: binary_assertion.sv Line: 45
88  Error: Assertion error.
89  Time: 47 ns Started: 45 ns  
90  and_assert File: binary_assertion.sv Line: 45
91  Error: Assertion error.
92  Time: 47 ns Started: 47 ns  
93  intersect_assert File: binary_assertion.sv Line: 46
94  Error: Assertion error.
95  Time: 47 ns Started: 45 ns  
96  intersect_assert File: binary_assertion.sv Line: 46
View Code

2.3.5 Match operators

  • 匹配操作符接受两个操作数或两个序列,并生成一个新序列;

first_match

只取第一次匹配成功的序列;

throughout

在匹配throughout后面的一个序列时,throughout前的序列一直有效;

within

在匹配长度上within前的序列包含于within后的序列;

 1 //+++++++++++++++++++++++++++++++++++++++++++++++++
 2 //   DUT With assertions
 3 //+++++++++++++++++++++++++++++++++++++++++++++++++
 4 module match_assertion();
 5 
 6 logic clk = 0;
 7 always #1 clk ++;
 8 
 9 logic burst_enable, master_busy, slave_busy;
10 //=================================================
11 // Property Specification Layer
12 //=================================================
13 property first_match_prop;
14   @ (posedge clk) 
15     $rose(burst_enable) |=> 
16       first_match(burst_enable ##[0:4] !master_busy);
17 endproperty
18        
19 property throughout_prop;
20   @ (posedge clk) 
21     $rose(burst_enable) |-> 
22       (burst_enable) throughout 
23           ( ##2 (!slave_busy && !master_busy) [*6]);
24 endproperty
25 
26 property within_prop;
27   @ (posedge clk) 
28     $rose(burst_enable) |=> 
29        (!slave_busy[*6]) within 
30            (($fell(master_busy)) ##1 !master_busy[*7]);
31 endproperty
32 //=================================================
33 // Assertion Directive Layer
34 //=================================================
35 within_assert     : assert property (within_prop);
36 throughout_assert : assert property (throughout_prop);
37 first_match_assert: assert property (first_match_prop);
38 //=================================================
39 // Generate input vectors
40 //=================================================
41 initial begin
42   burst_enable <= 0; master_busy <= 1; slave_busy <= 1;
43   @ (posedge clk); 
44   burst_enable <= 1;
45   @ (posedge clk); 
46   master_busy <= 0;
47   @ (posedge clk); 
48   slave_busy <= 0;
49   repeat(6) @ (posedge clk);
50   slave_busy <= 1;
51   @ (posedge clk); 
52   burst_enable <= 0;
53   master_busy <= 1;
54   // Fail both the assertion
55   repeat(20) @ (posedge clk);
56   burst_enable <= 0; master_busy <= 1; slave_busy <= 1;
57   @ (posedge clk); 
58   burst_enable <= 1;
59   @ (posedge clk); 
60   master_busy <= 0;
61   @ (posedge clk); 
62   slave_busy <= 0;
63   repeat(5) @ (posedge clk);
64   slave_busy <= 1;
65   @ (posedge clk); 
66   burst_enable <= 0;
67   master_busy <= 1;
68   // Terminate the sim
69   repeat(20) @ (posedge clk);
70   $finish;
71 end
72 
73 endmodule
74 
75 //compile result
76  "match_assertion.sv", 26: within_assert: started at 63s failed at 77s
77          Offending '(!slave_busy)'
78  "match_assertion.sv", 27: throughout_assert: started at 63s failed at 77s
79          Offending '((!slave_busy) && (!master_busy))'
View Code

2.3.6 System tasks

  • $sampled:返回与上次时钟事件相关的表达式的采样值(有些多余);
  • $rose:信号跳变为1,返回true;
  • $fell:信号跳变为0,返回true;
  • $stable:两次时钟事件的信号值不变,返回true;
  • $past:返回前一个时钟周期的表达式的采样值。
  • $onehot:信号只拉高一次则为真;
  • $onehot0:信号只拉低一次为真;
  • $isunknown:匹配到x或者z为真;
 1 module system_assertion();
 2 
 3 logic clk = 0;
 4 always #1 clk ++;
 5 
 6 logic req,gnt;
 7 //-------------------------------------------------
 8 // Property Specification Layer
 9 //-------------------------------------------------
10 property system_prop;
11   @ (posedge clk) 
12       ($rose(req) && $past(!req,1)) |=> 
13          ($rose(gnt) && $past(!gnt,1));
14 endproperty
15 //-------------------------------------------------
16 // Assertion Directive Layer
17 //-------------------------------------------------
18 system_assert : assert property (system_prop);
19 //-------------------------------------------------
20 // Generate input vectors
21 //-------------------------------------------------
22 initial begin
23   req <= 0;gnt <= 0;
24   repeat(10) @ (posedge clk);
25   req <= 1;
26   @( posedge clk);
27   gnt <= 1;
28   req <= 0;
29   @( posedge clk);
30   // Make the assertion fail now
31   req <= 0;gnt <= 0;
32   repeat(10) @ (posedge clk);
33   req <= 1;
34   @( posedge clk);
35   req <= 0;
36   gnt <= 0;
37   // Terminate the sim
38   #30 $finish;
39 end
40 
41 endmodule
42 
43 //compile result
44     
45  "system_assertion.sv", 18: 
46  system_assertion.system_assert: started at 45s failed at 47s
47          Offending '($rose(gnt) && $past((!gnt), 1))'
View Code

2.3.7 Sequence arguments

  • 序列可以用参数声明,当一个序列被实例化时,实际的参数可以传递给该序列;
  • 通过将形式参数替换为实际参数,序列用实际参数展开; 
  • 使用带参数的序列有一大优点是,它可以重用
 1 //+++++++++++++++++++++++++++++++++++++++++++++++++
 2 //   DUT With assertions
 3 //+++++++++++++++++++++++++++++++++++++++++++++++++
 4 module propargs_assertion();
 5 logic clk = 0;
 6 logic req,gnt;
 7 logic a,b;
 8 //=================================================
 9 // Sequence Layer with args (NO TYPE)
10 //=================================================
11 sequence notype_seq (X, Y);
12   (~X & Y) ##1 (~X & ~Y);
13 endsequence
14 //=================================================
15 // Sequence Layer with args (NO TYPE)
16 //=================================================
17 sequence withtype_seq (logic X, logic Y);
18   (~X & Y) ##1 (~X & ~Y);
19 endsequence
20 //=================================================
21 // Property Specification Layer
22 //=================================================
23 property req_gnt_notype_prop(M,N);
24   @ (posedge clk) 
25       req |=> notype_seq(M,N);
26 endproperty
27 
28 property a_b_type_prop(logic M, logic N;
29   @ (posedge clk) 
30       a |=> withtype_seq(M,N);
31 endproperty
32 //=================================================
33 // Assertion Directive Layer
34 //=================================================
35 req_gnt_notype_assert : assert property (req_gnt_notype_prop(req,gnt));
36 a_b_type_assert       : assert property (a_b_type_prop(a,b));
37 //=================================================
38 // Actual DUT RTL
39 //=================================================
40 always @ (posedge clk)
41   gnt <= req;
42 
43 always @ (posedge clk)
44   b <= a;
45 
46 //+++++++++++++++++++++++++++++++++++++++++++++++++
47 //  Assertion testing code
48 //+++++++++++++++++++++++++++++++++++++++++++++++++
49 always #3 clk ++;
50 
51 initial begin
52   // Make the assertion pass
53   #100 @ (posedge clk) req  <= 1;
54   @ (posedge clk) req <= 0;
55   // Make the assertion fail
56   #100 @ (posedge clk) req  <= 1;
57   repeat (2) @ (posedge clk);
58   req <= 0;
59 
60   // Make the assertion pass
61   #100 @ (posedge clk) a  <= 1;
62   @ (posedge clk) a <= 0;
63   // Make the assertion fail
64   #100 @ (posedge clk) a  <= 1;
65   repeat (2) @ (posedge clk);
66   a <= 0;
67   #10 $finish;
68 end
69 
70 endmodule
71 
72 //compile result
73    (~X & Y) ##1 (~X & ~Y);
74        |
75  ERROR (args_assertion.sv,46): (time 225 NS) 
76  Assertion args_assertion.req_gnt_type_assert 
77  has failed (2 cycles, starting 219 NS)
78    (~X & Y) ##1 (~X & ~Y);
79        |
80  ERROR (args_assertion.sv,45): (time 225 NS)
81   Assertion args_assertion.req_gnt_notype_assert 
82  has failed (2 cycles, starting 219 NS)
83    (~X & Y) ##1 (~X & ~Y);
84        |
85  ERROR (args_assertion.sv,48): (time 447 NS) 
86  Assertion args_assertion.a_b_type_assert 
87  has failed (2 cycles, starting 441 NS)
88    (~X & Y) ##1 (~X & ~Y);
89        |
90  ERROR (args_assertion.sv,47): (time 447 NS) 
91  Assertion args_assertion.a_b_notype_assert 
92  has failed (2 cycles, starting 441 NS)
View Code

2.3.8 Local Variables

可以在序列或者属性中包含局部变量。可以为这些局部变量赋值,并在之后采样;

 1 //+++++++++++++++++++++++++++++++++++++++++++++++++
 2 //   DUT With assertions
 3 //+++++++++++++++++++++++++++++++++++++++++++++++++
 4 module localvar_assertion();
 5 
 6 logic clk = 0;
 7 always #1 clk ++;
 8 
 9 logic [7:0] portin, portout;
10 logic       in_en, out_en;
11 //=================================================
12 // Sequence Layer
13 //=================================================
14 sequence local_var_seq;
15    logic [7:0] lport;
16    (in_en, lport = portin) ##[1:5] 
17       (out_en and lport == portout);
18 endsequence
19 //=================================================
20 // Property Specification Layer
21 //=================================================
22 property local_var_prop;
23   @ (posedge clk) 
24       in_en |-> local_var_seq;
25 endproperty
26 //=================================================
27 // Assertion Directive Layer
28 //=================================================
29 local_var_assert : assert property (local_var_prop);
30 //=================================================
31 // Simple DUT logic 
32 //=================================================
33 always @ (posedge clk)
34 begin
35   portout <= (portin < 4) ? portin : portin + 1;
36   out_en  <= in_en;
37 end
38 //=================================================
39 // Generate input vectors
40 //=================================================
41 initial begin
42   in_en <= 0; out_en <= 0;
43   portin <= 0; portout <= 0;
44   repeat (20) @ (posedge clk);
45   for (int i =0 ; i < 8; i ++) begin
46     @ (posedge clk);
47     in_en <= 1;
48     portin <= i;
49     @ (posedge clk);
50     in_en <= 0;
51     portin <= 0;
52   end
53   #30 $finish;
54 end
55 
56 endmodule
57 
58 //compile result
59  Assertion error.
60  Time: 69 ns Started: 59 ns  
61  localvar_assertion.local_var_assert Line: 26
62  Assertion error.
63  Time: 73 ns Started: 63 ns  
64  localvar_assertion.local_var_assert Line: 26
65  Assertion error.
66  Time: 77 ns Started: 67 ns  
67  localvar_assertion.local_var_assert Line: 26
68  Assertion error.
69  Time: 81 ns Started: 71 ns  
70  localvar_assertion.local_var_assert Line: 26
View Code

2.3.9 Calling subroutine 

  • 任务、方法,空函数、系统任务等子例程都可以在成功匹配序列的最后被调用;
  • 序列和后面的子例程用()括起来;
 1 //+++++++++++++++++++++++++++++++++++++++++++++++++
 2 //   DUT With assertions
 3 //+++++++++++++++++++++++++++++++++++++++++++++++++
 4 module subroutine_assertion();
 5 
 6 logic clk = 0;
 7 always #1 clk ++;
 8 
 9 logic [7:0] portin, portout;
10 logic       in_en, out_en;
11 //=================================================
12 // Sequence Layer
13 //=================================================
14 sequence local_var_seq;
15    logic [7:0] lport;
16    (in_en, lport = portin) ##[1:5] 
17       (out_en and lport == portout, 
18         $display ("@%0dns Input port %0d and Output port %0d match", 
19          $time, lport,portout));
20 endsequence
21 //=================================================
22 // Property Specification Layer
23 //=================================================
24 property local_var_prop;
25   @ (posedge clk) 
26       in_en |-> local_var_seq;
27 endproperty
28 //=================================================
29 // Assertion Directive Layer
30 //=================================================
31 local_var_assert : assert property (local_var_prop);
32 //=================================================
33 // Simple DUT logic 
34 //=================================================
35 always @ (posedge clk)
36 begin
37   portout <= (portin < 4) ? portin : portin + 1;
38   out_en  <= in_en;
39 end
40 //=================================================
41 // Generate input vectors
42 //=================================================
43 initial begin
44   in_en <= 0; out_en <= 0;
45   portin <= 0; portout <= 0;
46   repeat (20) @ (posedge clk);
47   for (int i =0 ; i < 8; i ++) begin
48     @ (posedge clk);
49     in_en <= 1;
50     portin <= i;
51     @ (posedge clk);
52     in_en <= 0;
53     portin <= 0;
54   end
55   #30 $finish;
56 end
57 
58 endmodule
59 
60 //compile result
61     
62  @45ns Input port 0 and Output port 0 match
63  @49ns Input port 1 and Output port 1 match
64  @53ns Input port 2 and Output port 2 match
65  @57ns Input port 3 and Output port 3 match
66  Assertion error.
67  Time: 69 ns Started: 59 ns  localvar_assertion.local_var_assert Line: 28
68  Assertion error.
69  Time: 73 ns Started: 63 ns  localvar_assertion.local_var_assert Line: 28
70  Assertion error.
71  Time: 77 ns Started: 67 ns  localvar_assertion.local_var_assert Line: 28
72  Assertion error.
73  Time: 81 ns Started: 71 ns  localvar_assertion.local_var_assert Line: 28
View Code

2.4 Properties

  • 属性层构建在序列层之上,它使用零个或多个序列来检查设计假设;
  • 为了 使用行为验证 ,必须 shiyassert、assume、cover语句;
  • 属性本身不会产生任何结果,在序列的情况下,才有断言的真假。

属性可以在下列模块中声明:

  1. module
  2. interface
  3. program
  4. clocking block
  5. package
  6. a compilation unit

属性可以有以下几种形式:

  1. sequence  
     1 //+++++++++++++++++++++++++++++++++++++++++++++++++
     2 //   DUT With assertions
     3 //+++++++++++++++++++++++++++++++++++++++++++++++++
     4 module propseq_assertion();
     5 
     6 logic req,gnt,clk;
     7 //=================================================
     8 //  Clock generator
     9 //=================================================
    10 initial begin
    11  clk = 0; 
    12  forever #1 clk ++;
    13 end
    14 //=================================================
    15 // Simple DUT behaviour
    16 //=================================================
    17 always @ (posedge clk)
    18   gnt <= req;
    19 //=================================================
    20 // Test Vector generation
    21 //=================================================
    22 initial begin
    23   req <= 0;
    24   #3 req <= 1;
    25   #5 req <= 0;
    26   #1 $finish;
    27 end
    28 //=================================================
    29 // A sequence property
    30 //=================================================
    31 property propseq_prop;
    32   @ (posedge clk)
    33     req ##1 gnt;
    34 endproperty
    35 //=================================================
    36 // Assertion Directive Layer
    37 //=================================================
    38 propseq_assert : assert property (propseq_prop);
    39 
    40 endmodule
    41 
    42 //compile result
    43     
    44  "propseq_assertion.sv", 38:
    45   propseq_assertion.propseq_assert: started at 1s failed at 1s
    46          Offending 'req'
    47  "propseq_assertion.sv", 38: 
    48  propseq_assertion.propseq_assert: started at 3s failed at 3s
    49          Offending 'req'
    View Code
  2. negation
  3. disjunction
  4. if...else
  5. implication
  6. another named property

2.4.1 Another named property  

  • 一个属性可以调用另一个属性;
 1 //+++++++++++++++++++++++++++++++++++++++++++++++++
 2 //   DUT With assertions
 3 //+++++++++++++++++++++++++++++++++++++++++++++++++
 4 module nameproperty_assertion();
 5 
 6 logic req,gnt,clk;
 7 //=================================================
 8 //  Clock generator
 9 //=================================================
10 initial begin
11  clk = 0; 
12  forever #1 clk ++;
13 end
14 //=================================================
15 // Simple DUT behaviour
16 //=================================================
17 always @ (posedge clk)
18   gnt <= req;
19 //=================================================
20 // Test Vector generation
21 //=================================================
22 initial begin
23   req <= 0;
24   #3 req <= 1;
25   #5 req <= 0;
26   #1 $finish;
27 end
28 //=================================================
29 // One property called inside another property
30 //=================================================
31 property vanila_prop;
32    req ##1 gnt;
33 endproperty
34 
35 property nameproperty_prop;
36   @ (posedge clk)
37     vanila_prop;
38 endproperty
39 //=================================================
40 // Assertion Directive Layer
41 //=================================================
42 nameproperty_assert : assert property (nameproperty_prop);
43 
44 endmodule
45 
46 //compile result
47     
48  "nameproperty_assertion.sv", 42: 
49  nameproperty_assertion.nameproperty_assert: started at 1s failed at 1s
50          Offending 'req'
51  "nameproperty_assertion.sv", 42: 
52  nameproperty_assertion.nameproperty_assert: started at 3s failed at 3s
53          Offending 'req'
54  $finish called from file "nameproperty_assertion.sv", line 26.
View Code

2.4.2 Negation

  • 用(not)操作符实现对属性的否定操作
 1 //+++++++++++++++++++++++++++++++++++++++++++++++++
 2 //   DUT With assertions
 3 //+++++++++++++++++++++++++++++++++++++++++++++++++
 4 module negation_assertion();
 5 
 6 logic req,gnt,clk;
 7 //=================================================
 8 //  Clock generator
 9 //=================================================
10 initial begin
11  clk = 0; 
12  forever #1 clk ++;
13 end
14 //=================================================
15 // Simple DUT behaviour
16 //=================================================
17 always @ (posedge clk)
18   gnt <= req;
19 //=================================================
20 // Test Vector generation
21 //=================================================
22 initial begin
23   req <= 0;
24   #3 req <= 1;
25   #5 req <= 0;
26   #1 $finish;
27 end
28 //=================================================
29 // A negation property
30 //=================================================
31 property negation_prop;
32   @ (posedge clk)
33     not (req ##1 gnt);
34 endproperty
35 //=================================================
36 // Assertion Directive Layer
37 //=================================================
38 negation_assert : assert property (negation_prop);
39 
40 endmodule
41  "negation_assertion.sv", 38: 
42  negation_assertion.negation_assert: started at 5s failed at 7s
View Code

2.4.3 Disjunction

  • 用或(or)来实现对属性的disjunction,至少有一个属性为真,则结果为真。
 1 //+++++++++++++++++++++++++++++++++++++++++++++++++
 2 //   DUT With assertions
 3 //+++++++++++++++++++++++++++++++++++++++++++++++++
 4 module disjunction_assertion();
 5 
 6 logic req,gnt,clk;
 7 //=================================================
 8 //  Clock generator
 9 //=================================================
10 initial begin
11  clk = 0; 
12  forever #1 clk ++;
13 end
14 //=================================================
15 // Simple DUT behaviour
16 //=================================================
17 logic gnt2;
18 initial begin
19   gnt2 <= 0; gnt <= 0;
20 end
21 always @ (posedge clk)
22 begin
23   gnt2 <= req;
24   gnt  <= gnt2;
25 end
26 //=================================================
27 // Test Vector generation
28 //=================================================
29 initial begin
30   req <= 0;
31   #3 req <= 1;
32   #5 req <= 0;
33   #1 $finish;
34 end
35 //=================================================
36 // A disjunction property
37 //=================================================
38 property delay1;
39     req ##1 gnt;
40 endproperty
41 property delay2;
42     req ##2 gnt;
43 endproperty
44 // See the OR operator
45 property disjunction_prop;
46   @ (posedge clk)
47     delay1 or delay2;
48 endproperty
49 //=================================================
50 // Assertion Directive Layer
51 //=================================================
52 disjunction_assert : assert property (disjunction_prop);
53 
54 endmodule
55 
56 //compile result
57  "disjunction_assertion.sv", 52: 
58  disjunction_assertion.disjunction_assert: started at 1s failed at 1s
59          Offending 'req'
60  "disjunction_assertion.sv", 52: 
61  disjunction_assertion.disjunction_assert: started at 3s failed at 3s
62          Offending 'req'
63  $finish called from file "disjunction_assertion.sv", line 33.
View Code

2.4.4 conjunction

  • 用(and)实现对属性的conjunction,所有属性为真,结果才为真。
 1 //+++++++++++++++++++++++++++++++++++++++++++++++++
 2 //   DUT With assertions
 3 //+++++++++++++++++++++++++++++++++++++++++++++++++
 4 module conjunction_assertion();
 5 
 6 logic req,gnt,clk;
 7 //=================================================
 8 //  Clock generator
 9 //=================================================
10 initial begin
11  clk = 0; 
12  forever #1 clk ++;
13 end
14 //=================================================
15 // Simple DUT behaviour
16 //=================================================
17 logic gnt2;
18 initial begin
19   gnt2 <= 0; gnt <= 0;
20 end
21 always @ (posedge clk)
22 begin
23   gnt2 <= req;
24   gnt  <= gnt2;
25 end
26 //=================================================
27 // Test Vector generation
28 //=================================================
29 initial begin
30   req <= 0;
31   #3 req <= 1;
32   #5 req <= 0;
33   #1 $finish;
34 end
35 //=================================================
36 // A conjunction property
37 //=================================================
38 property delay1;
39     req ##1 gnt;
40 endproperty
41 property delay2;
42     req ##2 gnt;
43 endproperty
44 // See the AND operator
45 property conjunction_prop;
46   @ (posedge clk)
47     delay1 and delay2;
48 endproperty
49 //=================================================
50 // Assertion Directive Layer
51 //=================================================
52 conjunction_assert : assert property (conjunction_prop);
53 
54 endmodule
55 
56 //compile result
57     
58  "conjunction_assertion.sv", 52: 
59  conjunction_assertion.conjunction_assert: started at 1s failed at 1s
60          Offending 'req'
61  "conjunction_assertion.sv", 52: 
62  conjunction_assertion.conjunction_assert: started at 3s failed at 3s
63          Offending 'req'
64  "conjunction_assertion.sv", 52: 
65  conjunction_assertion.conjunction_assert: started at 5s failed at 7s
66          Offending 'gnt'
67  $finish called from file "conjunction_assertion.sv", line 33.
View Code

2.4.5 if...else

1 //形式1
2 if (expression_or_dist) property_expr1
3 //形式2
4 if (expression_or_dist) property_expr1
5  else property_expr2
 1 //+++++++++++++++++++++++++++++++++++++++++++++++++
 2 //   DUT With assertions
 3 //+++++++++++++++++++++++++++++++++++++++++++++++++
 4 module ifelse_assertion();
 5 
 6 logic req,gnt,clk,check;
 7 //=================================================
 8 //  Clock generator
 9 //=================================================
10 initial begin
11  clk = 0; 
12  forever #1 clk ++;
13 end
14 //=================================================
15 // Simple DUT behaviour
16 //=================================================
17 logic gnt2;
18 initial begin
19   gnt2 <= 0; gnt <= 0;
20 end
21 always @ (posedge clk)
22 begin
23   gnt2 <= req;
24   gnt  <= gnt2;
25 end
26 //=================================================
27 // Test Vector generation
28 //=================================================
29 initial begin
30   req <= 0;check <= 0;
31   #3 req <= 1;
32   #10 req <= 0;check <= 1;
33   #3 req <= 1;
34   #5 req <= 0;
35   #1 $finish;
36 end
37 //=================================================
38 // A ifelse property
39 //=================================================
40 property delay1;
41     req ##1 gnt;
42 endproperty
43 property delay2;
44     req ##2 gnt;
45 endproperty
46 // See the OR operator
47 property ifelse_prop;
48   @ (posedge clk)
49     if (check)
50        delay1
51     else
52        delay2;
53 endproperty
54 //=================================================
55 // Assertion Directive Layer
56 //=================================================
57 ifelse_assert : assert property (ifelse_prop);
58 
59 endmodule
60 //compile result
61     
62  "ifelse_assertion.sv", 57: ifelse_assertion.ifelse_assert: 
63  started at 1s failed at 1s
64          Offending 'req'
65  "ifelse_assertion.sv", 57: ifelse_assertion.ifelse_assert: 
66  started at 3s failed at 3s
67          Offending 'req'
68  "ifelse_assertion.sv", 57: ifelse_assertion.ifelse_assert: 
69  started at 15s failed at 15s
70          Offending 'req'
71  "ifelse_assertion.sv", 57: ifelse_assertion.ifelse_assert:
72   started at 17s failed at 19s
73          Offending 'gnt'
74  $finish called from file "ifelse_assertion.sv", line 35.
75  
View Code

2.4.6 Implication

  • 类似于if...else属性操作,用于检查前面的序列是否发生,从而检查接下来的行为。
  • 如果sequence_expr匹配成功,而property_expr匹配失败,则结果为真,是一种伪真;
  • sequence_expr的结束点是property_expr的起点;
1 sequence_expr |-> property_expr
  • |->:重叠隐含操作符;
  • 前面匹配和后面匹配在同一个时钟内;
1 sequence_expr |=> property_expr
  • |->:非重叠隐含操作符;
  • 前面匹配和后面匹配相差一个时钟;
 1 //+++++++++++++++++++++++++++++++++++++++++++++++++
 2 //   DUT With assertions
 3 //+++++++++++++++++++++++++++++++++++++++++++++++++
 4 module implication_assertion();
 5 
 6 logic clk = 0;
 7 always #1 clk ++;
 8 
 9 logic req,busy,gnt;
10 //=================================================
11 // Sequence Layer
12 //=================================================
13 sequence implication_seq;
14   req ##1 (busy [->3]) ##1 gnt;
15 endsequence
16 
17 //=================================================
18 // Property Specification Layer
19 //=================================================
20 property overlap_prop;
21   @ (posedge clk) 
22       req |-> implication_seq;
23 endproperty
24 
25 property nonoverlap_prop;
26   @ (posedge clk) 
27       req |=> implication_seq;
28 endproperty
29 //=================================================
30 // Assertion Directive Layer
31 //=================================================
32 overlap_assert    : assert property (overlap_prop);
33 nonoverlap_assert : assert property (nonoverlap_prop);
34 
35 //=================================================
36 // Generate input vectors
37 //=================================================
38 initial begin
39   // Pass sequence
40   gen_seq(3,0); 
41   repeat (20) @ (posedge clk);
42   // Fail sequence (gnt is not asserted properly)
43   gen_seq(3,1); 
44   // Terminate the sim
45   #30 $finish;
46 end
47 //=================================================
48 /// Task to generate input sequence
49 //=================================================
50 task  gen_seq (int busy_delay,int gnt_delay);
51   req <= 0; busy <= 0;gnt <= 0;
52   @ (posedge clk);
53   req <= 1;
54   @ (posedge clk);
55   req  <= 0;
56   repeat (busy_delay) begin
57    @ (posedge clk);
58     busy <= 1;
59    @ (posedge clk);
60     busy <= 0;
61   end
62   repeat (gnt_delay) @ (posedge clk);
63   gnt <= 1;
64   @ (posedge clk);
65   gnt <= 0;
66 endtask
67 
68 endmodule
69 
70 //compile result
71  "implication_assertion.sv", 33: 
72  implication_assertion.nonoverlap_assert: started at 3s failed at 5s
73          Offending 'req'
74  "implication_assertion.sv", 33: 
75  implication_assertion.nonoverlap_assert: started at 61s failed at 63s
76          Offending 'req'
77  "implication_assertion.sv", 32: 
78  implication_assertion.overlap_assert: started at 61s failed at 75s
79          Offending 'gnt'
80  $finish called from file "implication_assertion.sv", line 45.
View Code

2.4.7 disable iff

  • 如果后面的表达式是激活的,则禁用该属性,用于重置检查;
 1 //+++++++++++++++++++++++++++++++++++++++++++++++++
 2 //   DUT With assertions
 3 //+++++++++++++++++++++++++++++++++++++++++++++++++
 4 module disableiff_assertion(
 5   input wire clk,req,reset, 
 6   output reg gnt);
 7 //=================================================
 8 // Sequence Layer
 9 //=================================================
10 sequence req_gnt_seq;
11   // (~req & gnt) and (~req & ~gnt) is Boolean Layer
12   (~req & gnt) ##1 (~req & ~gnt);
13 endsequence
14 //=================================================
15 // Property Specification Layer
16 //=================================================
17 property req_gnt_prop;
18   @ (posedge clk) // At every posedge clk
19     disable iff (reset) // disable if reset is asserted
20       req |=> req_gnt_seq;
21 endproperty
22 //=================================================
23 // Assertion Directive Layer
24 //=================================================
25 req_gnt_assert : assert property (req_gnt_prop);
26 //=================================================
27 // Actual DUT RTL
28 //=================================================
29 always @ (posedge clk)
30   gnt <= req;
31 
32 endmodule
33 
34 //+++++++++++++++++++++++++++++++++++++++++++++++
35 //   Testbench Code
36 //+++++++++++++++++++++++++++++++++++++++++++++++
37 module disableiff_assertion_tb();
38 
39 reg clk = 0;
40 reg reset, req = 0;
41 wire gnt;
42 
43 always #3 clk ++;
44 
45 initial begin
46   reset <= 1;
47   #20 reset <= 0;
48   // Make the assertion pass
49   #100 @ (posedge clk) req  <= 1;
50   @ (posedge clk) req <= 0;
51   // Make the assertion fail
52   #100 @ (posedge clk) req  <= 1;
53   repeat (5) @ (posedge clk);
54   req <= 0;
55   #10 $finish;
56 end
57 
58 disableiff_assertion dut (clk,req,reset,gnt);
59 
60 endmodule
61 
62 //compile result
63     
64  "disableiff_assertion.sv", 25: disableiff_assertion_tb.dut.req_gnt_assert:
65   started at 237s failed at 243s
66          Offending '((~req) & gnt)'
67  "disableiff_assertion.sv", 25: disableiff_assertion_tb.dut.req_gnt_assert:
68   started at 243s failed at 249s
69          Offending '((~req) & gnt)'
70  "disableiff_assertion.sv", 25: disableiff_assertion_tb.dut.req_gnt_assert:
71   started at 249s failed at 255s
72          Offending '((~req) & gnt)'
73  "disableiff_assertion.sv", 25: disableiff_assertion_tb.dut.req_gnt_assert:
74   started at 255s failed at 261s
75          Offending '((~req) & gnt)'
76  $finish called from file "disableiff_assertion.sv", line 55.
View Code

2.4.8 Recursive property 

  • 当属性调用自身时,被称为递归属性;
  • 否定运算符not不可用于递归属性;
  • disable iff不能用于递归属性;
 1 //+++++++++++++++++++++++++++++++++++++++++++++++++
 2 //   DUT With assertions
 3 //+++++++++++++++++++++++++++++++++++++++++++++++++
 4 module recursive_assertion();
 5 logic clk = 0;
 6 logic req;
 7 //=================================================
 8 // Property Specification Layer
 9 //=================================================
10 property recursive_prop(M);
11       M and (1'b1 |=> recursive_prop(M));
12 endproperty
13 //=================================================
14 // Assertion Directive Layer
15 //=================================================
16 recursive_assert : assert property (recursive_prop(req));
17 //+++++++++++++++++++++++++++++++++++++++++++++++++
18 //  Assertion testing code
19 //+++++++++++++++++++++++++++++++++++++++++++++++++
20 always #1 clk ++;
21 
22 initial begin
23   // Make the assertion pass
24   #100 @ (posedge clk) req  <= 1;
25   repeat (20) @ (posedge clk);
26   req <= 0;
27   #10 $finish;
28 end
29 
30 endmodule
View Code

3. Multi clock support

  • 检查来自多个时钟域的信号或变量;
  • 在序列和属性中都支持多时钟声明;

3.1 Multi clock sequence

  • 多时钟序列是使用单延迟连接操作符##1连接单时钟子序列来建立的;
  • 该操作不重叠,并在 两个序列的时钟之间进行同步;
  • ##1解释为第一个序列的结束点到最近的第二个序列点开始的时间;
 1 //+++++++++++++++++++++++++++++++++++++++++++++++++
 2 //   DUT With assertions
 3 //+++++++++++++++++++++++++++++++++++++++++++++++++
 4 module multi_clock_seq_assertion();
 5 logic clk1 = 0;
 6 logic clk2 = 0;
 7 logic req;
 8 logic gnt;
 9 //=================================================
10 // Sequence Specification Layer
11 //=================================================
12 sequence multi_clock_seq;
13    @(posedge clk1) req ##1 @(posedge clk2) gnt;
14 endsequence
15 //=================================================
16 // Property Specification Layer
17 //=================================================
18 property multi_clock_prop;
19   @ (posedge clk1)
20       req |-> multi_clock_seq;
21 endproperty
22 //=================================================
23 // Assertion Directive Layer
24 //=================================================
25 multi_clock_assert : assert property (multi_clock_prop);
26 //=================================================
27 // Here gnt is driven with respect to CLK2
28 //=================================================
29 initial begin
30   #20 gnt <= 1;
31   #120 gnt <= 0;
32 end
33 //+++++++++++++++++++++++++++++++++++++++++++++++++
34 //  Assertion testing code
35 //+++++++++++++++++++++++++++++++++++++++++++++++++
36 initial begin
37   // Make the assertion pass
38   req  <= 0; gnt <= 0;
39   #100 @ (posedge clk1) req  <= 1;
40   repeat (20) @ (posedge clk1);
41   req <= 0;
42   #10 $finish;
43 end
44 
45 always #1   clk1 ++;
46 always #6.1 clk2 ++;
47 
48 endmodule
49 
50 //compile result
51     
52  "multi_clock_seq_assertion.sv", 25: 
53  multi_clock_seq_assertion.multi_clock_assert: started at 139s failed at 150s
54          Offending 'gnt'
55  "multi_clock_seq_assertion.sv", 25: 
56  multi_clock_seq_assertion.multi_clock_assert: started at 141s failed at 150s
57          Offending 'gnt'
58  $finish called from file "multi_clock_seq_assertion.sv", line 42.
View Code

3.2 Multi clock property

  • 多时钟序列本身就是一种多时钟属性。
 1 //+++++++++++++++++++++++++++++++++++++++++++++++++
 2 //   DUT With assertions
 3 //+++++++++++++++++++++++++++++++++++++++++++++++++
 4 module multi_clock_prop_assertion();
 5 logic clk1 = 0;
 6 logic clk2 = 0;
 7 logic req;
 8 logic gnt;
 9 //=================================================
10 // Property Specification Layer
11 //=================================================
12 property multi_clock_prop;
13   @(posedge clk1) req |-> ##1 @(posedge clk2) gnt;
14 endproperty
15 //=================================================
16 // Assertion Directive Layer
17 //=================================================
18 multi_clock_assert : assert property (multi_clock_prop);
19 //=================================================
20 // Here gnt is driven with respect to CLK2
21 //=================================================
22 initial begin
23   #20 gnt <= 1;
24   #120 gnt <= 0;
25 end
26 //+++++++++++++++++++++++++++++++++++++++++++++++++
27 //  Assertion testing code
28 //+++++++++++++++++++++++++++++++++++++++++++++++++
29 initial begin
30   // Make the assertion pass
31   req  <= 0; gnt <= 0;
32   #100 @ (posedge clk1) req  <= 1;
33   repeat (20) @ (posedge clk1);
34   req <= 0;
35   #10 $finish;
36 end
37 
38 always #1   clk1 ++;
39 always #6.1 clk2 ++;
40 
41 endmodule
42 
43 //compile result
44     
45  "multi_clock_prop_assertion.sv", 18: 
46  multi_clock_prop_assertion.multi_clock_assert: started at 139s failed at 150s
47          Offending 'gnt'
48  "multi_clock_prop_assertion.sv", 18: 
49  multi_clock_prop_assertion.multi_clock_assert: started at 141s failed at 150s
50          Offending 'gnt'
51  $finish called from file "multi_clock_prop_assertion.sv", line 35.
View Code

4. Assert,Assume,Cover

  • property本身不能用于检查,需要与assert、assume、cover一起使用。
  1. assert:指定该 属性是否正确;
  2. assume:指定属性作为验证环境的假定,对于正式的验证工具显得更有用;
  3. cover:为了覆盖率而监视属性,可以咋模拟结束后查看覆盖率报告。
  • 可以使用的地方:
  1. initial or always block
  2. module
  3. interface
  4. program
 1 //+++++++++++++++++++++++++++++++++++++++++++++++++
 2 //   DUT With assertions
 3 //+++++++++++++++++++++++++++++++++++++++++++++++++
 4 module assert_assume_cover_assertion();
 5 logic clk = 0;
 6 logic req,gnt;
 7 logic ce,wr;
 8 logic [7:0] addr, data;
 9 //=================================================
10 // Property Specification Layer
11 //=================================================
12 property req_gnt_prop;
13   @ (posedge clk)
14       req |=> gnt;
15 endproperty
16 //=================================================
17 // Check if address falls in range for a write 
18 // operation
19 //=================================================
20 property addr_hit_prop(int min, int max);
21   @ (posedge clk)
22    (ce & wr) |-> (addr >= min && addr <= max);
23 endproperty
24 //=================================================
25 // Simple DUT with assert
26 //=================================================
27 always @ (posedge clk)
28 begin
29    gnt <= req;
30    //==============================================
31    // Assert inside a always block
32    //==============================================
33    req_gnt_assert : assert property (req_gnt_prop);
34 end
35 //=================================================
36 // This is how you use "assume"
37 //=================================================
38 req_gnt_assume  : assume property (req_gnt_prop);
39 //=================================================
40 // This is how you use "assert"
41 //=================================================
42 req_gnt_assert2 : assert property (req_gnt_prop);
43 //=================================================
44 // This is how you use "cover"
45 //=================================================
46 req_gnt_cover   : cover property (req_gnt_prop);
47 addr_hit_cover  : cover property (addr_hit_prop(1,5));
48 //+++++++++++++++++++++++++++++++++++++++++++++++++
49 //  Assertion testing code
50 //+++++++++++++++++++++++++++++++++++++++++++++++++
51 always #1 clk ++;
52 
53 initial begin
54   ce <= 0; wr <= 0; addr <= 0; req <= 0; gnt <= 0;
55   data <= 0;
56   // Make the assertion pass
57   @ (posedge clk) req  <= 1;
58   @ (posedge gnt);
59   for (int i = 0; i < 10; i ++) begin
60     @ (posedge clk);
61     ce <= 1;
62     wr <= 1;
63     addr <= i;
64     data <= $random;
65     @ (posedge clk);
66     ce <= 0;
67     wr <= 0;
68     addr <= 0;
69   end
70   @ (posedge clk);
71   req <= 0;
72   // Check 
73   #10 $finish;
74 end
75 
76 endmodule
77 
78 //compile result
79 $finish called from file "assert_assume_cover_assertion.sv", line 73.
80  $finish at simulation time                   55
81  "assert_assume_cover_assertion.sv", 46: 
82  assert_assume_cover_assertion.req_gnt_cover, 27 attempts, 22 match
83  "assert_assume_cover_assertion.sv", 47: 
84  assert_assume_cover_assertion.addr_hit_cover, 27 attempts, 5 match
View Code

5. Binding

  • 在验证工程师 添加断言的时候往往不希望对RTL设计进行改动,可以用Binding的方法进行验证;
  • 可以将断言内容写在单独的一个文件内,并使用bind将断言端口与testbench代码的RTL端口进行连接;
  • bind可以使用的地方:
  1. module
  2. interface
  3. compilation unit scope
  • 两种形式的bind
  1. multi instance:对一个模块的多个实例进行绑定;
  2. single instance:对一个模块的单个实例进行绑定;

一个 完整的实例:

 1 //+++++++++++++++++++++++++++++++++++++++++++++++++
 2 //   DUT With assertions
 3 //+++++++++++++++++++++++++++++++++++++++++++++++++
 4 module bind_assertion(
 5   input wire clk,req,reset, 
 6   output reg gnt);
 7 //=================================================
 8 // Actual DUT RTL
 9 //=================================================
10 always @ (posedge clk)
11   gnt <= req;
12 
13 endmodule
DUT File
 1 //+++++++++++++++++++++++++++++++++++++++++++++++++
 2 //   Assertion Verification IP
 3 //+++++++++++++++++++++++++++++++++++++++++++++++++
 4 module assertion_ip(input wire clk_ip, req_ip,reset_ip,gnt_ip);
 5 //=================================================
 6 // Sequence Layer
 7 //=================================================
 8 sequence req_gnt_seq;
 9   (~req_ip & gnt_ip) ##1 (~req_ip & ~gnt_ip);
10 endsequence
11 //=================================================
12 // Property Specification Layer
13 //=================================================
14 property req_gnt_prop;
15   @ (posedge clk_ip) 
16     disable iff (reset_ip)
17       req_ip |=> req_gnt_seq;
18 endproperty
19 //=================================================
20 // Assertion Directive Layer
21 //=================================================
22 req_gnt_assert : assert property (req_gnt_prop)
23                  else
24                  $display("@%0dns Assertion Failed", $time);
25 
26 endmodule
Assertion File
 1 //+++++++++++++++++++++++++++++++++++++++++++++++++
 2 //  Binding File 
 3 //+++++++++++++++++++++++++++++++++++++++++++++++++
 4 module binding_module();
 5 //=================================================
 6 // Bind by Module name : This will bind all instance
 7 // of DUT
 8 //=================================================
 9 // Here RTL : stands for design under test
10 //      VIP : Assertion file
11 //   RTL Module Name  VIP module Name   Instance Name
12 bind bind_assertion   assertion_ip      U_assert_ip (
13 // .vip port (RTL port)
14  .clk_ip   (clk),
15  .req_ip   (req),
16  .reset_ip (reset),
17  .gnt_ip   (gnt)
18 );
19 //=================================================
20 // Bind by instance name : This will bind only instance
21 //  names in list
22 //=================================================
23 // Here RTL : stands for design under test
24 //      VIP : Assertion file
25 //     RTL Module Name Instance Path               VIP module Name Instance Name
26 //bind bind_assertion :$root.bind_assertion_tb.dut assertion_ip    U_assert_ip (
27 // .vip port (RTL port)
28 // .clk_ip   (clk),
29 // .req_ip   (req),
30 // .reset_ip (reset),
31 // .gnt_ip   (gnt)
32 //);
33 //=================================================
34 
35 endmodule
Binding File
 1 //+++++++++++++++++++++++++++++++++++++++++++++++
 2 //   Testbench Code
 3 //+++++++++++++++++++++++++++++++++++++++++++++++
 4 `include "assertion_ip.sv"
 5 `include "bind_assertion.sv"
 6 `include "binding_module.sv"
 7 
 8 module bind_assertion_tb();
 9 
10 reg clk = 0;
11 reg reset, req = 0;
12 wire gnt;
13 
14 always #3 clk ++;
15 
16 initial begin
17   reset <= 1;
18   #20 reset <= 0;
19   // Make the assertion pass
20   #100 @ (posedge clk) req  <= 1;
21   @ (posedge clk) req <= 0;
22   // Make the assertion fail
23   #100 @ (posedge clk) req  <= 1;
24   repeat (5) @ (posedge clk);
25   req <= 0;
26   #10 $finish;
27 end
28 
29 bind_assertion dut (clk,req,reset,gnt);
30 
31 endmodule
Testbench File
 1     
 2  "assertion_ip.sv", 22: bind_assertion_tb.dut.U_assert_ip.req_gnt_assert:
 3   started at 237s failed at 243s
 4          Offending '((~req_ip) & gnt_ip)'
 5  @243ns Assertion Failed
 6  "assertion_ip.sv", 22: bind_assertion_tb.dut.U_assert_ip.req_gnt_assert: 
 7   started at 243s failed at 249s
 8          Offending '((~req_ip) & gnt_ip)'
 9  @249ns Assertion Failed
10  "assertion_ip.sv", 22: bind_assertion_tb.dut.U_assert_ip.req_gnt_assert: 
11   started at 249s failed at 255s
12          Offending '((~req_ip) & gnt_ip)'
13  @255ns Assertion Failed
14  "assertion_ip.sv", 22: bind_assertion_tb.dut.U_assert_ip.req_gnt_assert: 
15   started at 255s failed at 261s
16          Offending '((~req_ip) & gnt_ip)'
17  @261ns Assertion Failed
18  $finish called from file "bind_assertion_tb.sv", line 26.
Simulation : Binding

6. Expect

  • 语法上 与assert相同,但expect是在过程块中使用的,他会等待一个属性的值为true或者false;
 1 module expect_assertion;
 2 
 3 logic clk = 0;
 4 always #1 clk ++;
 5 
 6 logic a, b,c;
 7 
 8 default clocking myclk @ (posedge clk);
 9 
10 endclocking
11 
12 initial begin 
13   a <= 0;
14   b <= 0;
15   c <= 0;
16   ##1;
17   a <= 1;
18   ##1;
19   a <= 0;
20   b <= 1;
21   ##1;
22   b <= 0;
23   c <= 0;
24   ##1;
25   c <= 0;
26   ##20000 $finish;
27 end
28 
29 initial begin
30   ##1;
31   // Wait for the sequence if pass, terminate sim
32   expect ( @ (posedge clk) a ##1 b ##1 c ##1 !c)
33      $finish;
34    else
35      $error ("Something is wrong");
36 end
37   
38 endmodule
39 
40 //compile result
41     
42  Something is wrong
43  Simulation complete via $finish(1) at time 40007 NS + 0
View Code

7. Clock resolution

  • 并发断言需要时钟的参与,有多种方式可以解决时钟的产生问题;
  1. 带有时钟的序列实例:在序列声明本身指定时钟;
  2. 带有时钟的属性实例:在属性声明本身指定时钟;
  3. 从程序块中引用时钟:触发器解析时钟;
  4. 时钟块:专门定义一个时钟;
  5. 默认时钟:与上面类似。
  • 3:Contextually inferred clock from a procedural block. : In this procedural block trigger resolve to clock.
  • 4:Clocking block : A clocking block can be used for resolving the clock.
 1 //+++++++++++++++++++++++++++++++++++++++++++++++++
 2 //   DUT With assertions
 3 //+++++++++++++++++++++++++++++++++++++++++++++++++
 4 module clock_resolve_assertion();
 5 logic clk = 0;
 6 logic req,gnt;
 7 //=================================================
 8 // Clock inside a sequence 
 9 //=================================================
10 sequence req_gnt_seq;
11   @ (posedge clk)
12       req ##1 gnt;
13 endsequence
14 //=================================================
15 // Clock inside a property
16 //=================================================
17 property req_gnt_prop;
18   @ (posedge clk)
19       req |=> gnt;
20 endproperty
21 //=================================================
22 // Clock infered from a always block
23 //=================================================
24 always @ (posedge clk)
25 begin
26    gnt <= req;
27    //==============================================
28    // Here clock is infered to be posedge clk
29    //==============================================
30    req_gnt_assert : assert property (req  |=> gnt);
31 end
32 //=================================================
33 // Default clocking
34 //=================================================
35 default clocking aclk @ (posedge clk);
36   input req;
37   input gnt;
38 endclocking
39 
40 property req_gnt_default_prop;
41    req |-> ##1 gnt;
42 endproperty
43 //=================================================
44 // clocking clocking
45 //=================================================
46 clocking reqclk @ (posedge clk);
47   input req;
48   input gnt;
49 endclocking
50 
51 property req_gnt_clocking_prop;
52    reqclk.req |-> ##1 reqclk.gnt;
53 endproperty
54 //+++++++++++++++++++++++++++++++++++++++++++++++++
55 // Now call all the assertion in one go
56 //+++++++++++++++++++++++++++++++++++++++++++++++++
57 a1  : assert property (req_gnt_prop);
58 a2  : assert property (req_gnt_default_prop);
59 a3  : assert property (req_gnt_clocking_prop);
60 //+++++++++++++++++++++++++++++++++++++++++++++++++
61 //  Assertion testing code
62 //+++++++++++++++++++++++++++++++++++++++++++++++++
63 always #1 clk ++;
64 
65 initial begin
66   $monitor("Req %b Gnt %b",req,gnt);
67   req <= 0; gnt <= 0;
68   // Make the assertion pass
69   ##1 req  <= 1;
70   ##20;
71   req <= 0;
72   #10 $finish;
73 end
74 
75 endmodule
76 
77 //compile result
78  Req 0 Gnt 0
79  Req 1 Gnt 0
80  Req 1 Gnt 1
81  Req 0 Gnt 1
82  Req 0 Gnt 0
View Code

posted on 2021-03-04 10:59  TCJJ  阅读(326)  评论(0)    收藏  举报

1