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)'
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例子代码:

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