目录
摘要:断言验证是指使用断言语言来指定设计中的预期行为,以及相对于验证中的设计来评估断言的工具。
- 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)'
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
在并发断言的所有层中:
- 基本的构建块是布尔层,它的值为0或1;
- 序列层基本是建立在布尔层上,序列定义任何并发断言的最基本构造;
- 属性层建立在序列层之上(并不总是如此)。
- 要使属性成为模拟的一部分,需要在属性执行层中的assert语句中使用该属性。
2.2 Boolean layer
- 布尔层是并发断言的最底层,对变量进行布尔表达式检查;
- 布尔表达式允许包含函数调用;
- 出现在表达式中的函数不能包含 output 或 ref 参数 (允许使用 const ref 参数 );
- 函数应该是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
- 序列层使用布尔层来构造有效地时间序列;
- 最简单的序列行为是线性序列;
- 线性序列是一个有限的SV布尔表达式列表,它按线性顺序递增;
- 在第一个时钟周期的第一个布尔表达式为真,第二个时钟周期的第二个布尔表达式为真,直到最后一个 时钟周期的布尔表达式为真,才会匹配成功。
- 序列可以声明的位置:
- module
- interface
- program
- clocking block
- package
- 序列之间可以互相调用;
- 一些构造序列的操作符:
- ##
- [* ]
- [= ]
- [-> ]
- throughout
- within left
- intersect
- and
- 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
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
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'
2.3.4 Binary operators
- 二元操作符接受两个操作数或两个序列,并生成一个新序列;
- 几个常用的二元操作符:
- and:两个序列同时 开始,不一定同时结束,匹配长度取最大的;
- intersect:两个序列同时开始,同时结束;
- 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
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))'
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))'
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)
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
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
2.4 Properties
- 属性层构建在序列层之上,它使用零个或多个序列来检查设计假设;
- 为了 使用行为验证 ,必须 shiyassert、assume、cover语句;
- 属性本身不会产生任何结果,在序列的情况下,才有断言的真假。
属性可以在下列模块中声明:
- module
- interface
- program
- clocking block
- package
- a compilation unit
属性可以有以下几种形式:
- 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'
- negation
- disjunction
- if...else
- implication
- 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.
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
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.
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.
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
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.
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.
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
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.
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.
4. Assert,Assume,Cover
- property本身不能用于检查,需要与assert、assume、cover一起使用。
- assert:指定该 属性是否正确;
- assume:指定属性作为验证环境的假定,对于正式的验证工具显得更有用;
- cover:为了覆盖率而监视属性,可以咋模拟结束后查看覆盖率报告。
- 可以使用的地方:
- initial or always block
- module
- interface
- 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
5. Binding
- 在验证工程师 添加断言的时候往往不希望对RTL设计进行改动,可以用Binding的方法进行验证;
- 可以将断言内容写在单独的一个文件内,并使用bind将断言端口与testbench代码的RTL端口进行连接;
- bind可以使用的地方:
- module
- interface
- compilation unit scope
- 两种形式的bind
- multi instance:对一个模块的多个实例进行绑定;
- 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
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
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
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
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.
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
7. Clock resolution
- 并发断言需要时钟的参与,有多种方式可以解决时钟的产生问题;
- 带有时钟的序列实例:在序列声明本身指定时钟;
- 带有时钟的属性实例:在属性声明本身指定时钟;
- 从程序块中引用时钟:触发器解析时钟;
- 时钟块:专门定义一个时钟;
- 默认时钟:与上面类似。
- 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