SVA的动态控制
SVA中提供了一些系统函数,可以在RTL设计代码或者仿真环境中用于控制断言的执行,常用的断言控制函数有:$assertoff,$asserton,$assertkill,这些函数可以指定参数,如果不指定参数那么这些函数的作用域将默认为整个设计。这些函数的使用个数如下:
$assert_task[(level[,list_of_modules_or_assertions])];
其中
assert_task可以是assertionon、assertoff、assertkill中的任何一个;
Level用于指定层以下哪几层设计受到函数的影响,如果level为0,函数将影响指定层以下所有的设计;
list_of_modules_or_assertions指定该函数作用于哪些模块或者断言(不能指向序列,但是可以指向属性);
这几个函数的具体意义如下:
$assertoff暂时关闭所有断言的执行,如果该函数执行时断言正在执行,正在执行的断言不会被终止;
$asserton重新启动断言执行;
$assertkill将会终止设计中所有的断言,包括已经执行的断言。当遇到下一个断言需要开始执行时,该断言不会启动,除非使用$asserton启动;
`timescale 1 ns / 1 ps
module top_tb;
logic clk;
logic sig0,sig1,sig2;
initial begin
clk = 1'b0;
forever #1 clk = ~clk;
end
// p1 stimulus
initial begin
sig0 = 1'b0;sig1 = 1'b0;sig2 = 1'b1;
#2 sig0 = 1'b1;
#2 sig0 = 1'b0;sig1 = 1'b1;
#2 sig1 = 1'b0;
$assertoff;
#2 sig2 = 1'b0;
#2 sig2 = 1'b1;
#4 sig0 = 1'b1; // new
#2 sig0 = 1'b0;sig1 = 1'b1;
#2 sig1 = 1'b0;
#2 sig2 = 1'b0;
#2 sig2 = 1'b1;
$asserton;
#4 sig0 = 1'b1; // new
#2 sig0 = 1'b0;sig1 = 1'b1;
#2 sig1 = 1'b0;
#2 sig2 = 1'b0;
#2 sig2 = 1'b1;
#6 $stop;
end
// instanced dut
test u_dut0(clk,sig0,sig1,sig2,2'b00);
test u_dut1(clk,sig0,sig1,sig2,2'b01);
test u_dut2(clk,sig0,sig1,sig2,2'b10);
// sequence
sequence s;
$rose(sig1) ##2 $fell(sig2);
endsequence // s
// property
property p;
@(posedge clk) $rose(sig0) |-> ##1 s;
endproperty // p
a : assert property(p) $display("@%0t | p : PASSED!",$time);
else $display("@%0t | p : FAILED!",$time);
endmodule // top_tb
module test(clk,sig0,sig1,sig2,num);
input clk,sig0,sig1,sig2,num;
logic [1:0] num;
sequence s;
$rose(sig1) ##2 $fell(sig2);
endsequence // s
// property
property p;
@(posedge clk) $rose(sig0) |-> ##1 s;
endproperty // p
a : assert property(p) $display("@%0t DUT%h | p : PASSED!",$time,num);
else $display("@%0t DUT%h | p : FAILED!",$time,num);
endmodule // test 【仿真结果】 示例中,第一次断言在3ns处触发开始,虽然$assertoff发生6ns处,在该断言检查的过程中,但是第一次断言的执行并没有受到$assertoff影响。但是15ns处第二次断言触发,但是在第一次断言执行的过程中已经执行了$assertoff,所以第二次断言被关闭,不会执行;22ns时$asserton执行,重新启动断言检查,所以之后的27ns开始的第三次断言被有效触发执行。因为$assertoff和$asserton中都没有指定任何参数,所以他们的作用域是当前函数调用执行域及其以下所有层次。
【示例】
`timescale 1 ns / 1 ps
module top_tb;
logic clk;
logic sig0,sig1,sig2;
initial begin
clk = 1'b0;
forever #1 clk = ~clk;
end
// p1 stimulus
initial begin
sig0 = 1'b0;sig1 = 1'b0;sig2 = 1'b1;
#2 sig0 = 1'b1;
#2 sig0 = 1'b0;sig1 = 1'b1;
#2 sig1 = 1'b0;
$assertkill;
#2 sig2 = 1'b0;
#2 sig2 = 1'b1;
#4 sig0 = 1'b1; // new
#2 sig0 = 1'b0;sig1 = 1'b1;
#2 sig1 = 1'b0;
#2 sig2 = 1'b0;
#2 sig2 = 1'b1;
$asserton;
#4 sig0 = 1'b1; // new
#2 sig0 = 1'b0;sig1 = 1'b1;
#2 sig1 = 1'b0;
#2 sig2 = 1'b0;
#2 sig2 = 1'b1;
#6 $stop;
end
// instanced dut
test u_dut0(clk,sig0,sig1,sig2,2'b00);
test u_dut1(clk,sig0,sig1,sig2,2'b01);
test u_dut2(clk,sig0,sig1,sig2,2'b10);
// sequence
sequence s;
$rose(sig1) ##2 $fell(sig2);
endsequence // s
// property
property p;
@(posedge clk) $rose(sig0) |-> ##1 s;
endproperty // p
a : assert property(p) $display("@%0t | p : PASSED!",$time);
else $display("@%0t | p : FAILED!",$time);
endmodule // top_tb
module test(clk,sig0,sig1,sig2,num);
input clk,sig0,sig1,sig2,num;
logic [1:0] num;
sequence s;
$rose(sig1) ##2 $fell(sig2);
endsequence // s
// property
property p;
@(posedge clk) $rose(sig0) |-> ##1 s;
endproperty // p
a : assert property(p) $display("@%0t DUT%h | p : PASSED!",$time,num);
else $display("@%0t DUT%h | p : FAILED!",$time,num);
endmodule // test 【仿真结果】 该示例中,6ns时$assertkill执行,虽然这时候3ns开始的断言还在执行中,但是会立即被终止其执行,即当前正在执行的断言会被$assertkill终止,而不管其是否正在执行。如果后续的断言还要继续执行,那么需要使用$asserton重新开启断言检查。
【示例】
`timescale 1 ns / 1 ps
module top_tb;
logic clk;
logic sig0,sig1,sig2;
initial begin
clk = 1'b0;
forever #1 clk = ~clk;
end
// p1 stimulus
initial begin
sig0 = 1'b0;sig1 = 1'b0;sig2 = 1'b1;
#2 sig0 = 1'b1;
#2 sig0 = 1'b0;sig1 = 1'b1;
#2 sig1 = 1'b0;
$assertoff(1,test);
#2 sig2 = 1'b0;
#2 sig2 = 1'b1;
#4 sig0 = 1'b1; // new
#2 sig0 = 1'b0;sig1 = 1'b1;
#2 sig1 = 1'b0;
#2 sig2 = 1'b0;
#2 sig2 = 1'b1;
$asserton;
#4 sig0 = 1'b1; // new
#2 sig0 = 1'b0;sig1 = 1'b1;
#2 sig1 = 1'b0;
#2 sig2 = 1'b0;
#2 sig2 = 1'b1;
#6 $stop;
end
// instanced dut
test u_dut0(clk,sig0,sig1,sig2,2'b00);
test u_dut1(clk,sig0,sig1,sig2,2'b01);
test u_dut2(clk,sig0,sig1,sig2,2'b10);
// sequence
sequence s;
$rose(sig1) ##2 $fell(sig2);
endsequence // s
// property
property p;
@(posedge clk) $rose(sig0) |-> ##1 s;
endproperty // p
a : assert property(p) $display("@%0t | p : PASSED!",$time);
else $display("@%0t | p : FAILED!",$time);
endmodule // top_tb
module test(clk,sig0,sig1,sig2,num);
input clk,sig0,sig1,sig2,num;
logic [1:0] num;
sequence s;
$rose(sig1) ##2 $fell(sig2);
endsequence // s
// property
property p;
@(posedge clk) $rose(sig0) |-> ##1 s;
endproperty // p
a : assert property(p) $display("@%0t DUT%h | p : PASSED!",$time,num);
else $display("@%0t DUT%h | p : FAILED!",$time,num);
endmodule // test 【仿真结果】 示例中,$assertoff(1,test)表示所有例化自test的实例中的断言从6ns开始关闭,此时如果有断言正在执行将不会受到$assertoff(1,test)的影响,之后新的例化自test的实例中的断言将不再执行,直到后续$asserton重新开启断言检查。
【示例】
`timescale 1 ns / 1 ps
module top_tb;
logic clk;
logic sig0,sig1,sig2;
initial begin
clk = 1'b0;
forever #1 clk = ~clk;
end
// p1 stimulus
initial begin
sig0 = 1'b0;sig1 = 1'b0;sig2 = 1'b1;
#2 sig0 = 1'b1;
#2 sig0 = 1'b0;sig1 = 1'b1;
#2 sig1 = 1'b0;
$assertoff(0,u_dut0);
$assertoff(1,u_dut1);
$assertoff(1,top_tb);
#2 sig2 = 1'b0;
#2 sig2 = 1'b1;
#4 sig0 = 1'b1; // new
#2 sig0 = 1'b0;sig1 = 1'b1;
#2 sig1 = 1'b0;
#2 sig2 = 1'b0;
#2 sig2 = 1'b1;
$asserton(0,u_dut0);
#4 sig0 = 1'b1; // new
#2 sig0 = 1'b0;sig1 = 1'b1;
#2 sig1 = 1'b0;
#2 sig2 = 1'b0;
#2 sig2 = 1'b1;
#6 $stop;
end
// instanced dut
test u_dut0(clk,sig0,sig1,sig2,2'b00);
test u_dut1(clk,sig0,sig1,sig2,2'b01);
test u_dut2(clk,sig0,sig1,sig2,2'b10);
// sequence
sequence s;
$rose(sig1) ##2 $fell(sig2);
endsequence // s
// property
property p;
@(posedge clk) $rose(sig0) |-> ##1 s;
endproperty // p
a : assert property(p) $display("@%0t | p : PASSED!",$time);
else $display("@%0t | p : FAILED!",$time);
endmodule // top_tb
module test(clk,sig0,sig1,sig2,num);
input clk,sig0,sig1,sig2,num;
logic [1:0] num;
sequence s;
$rose(sig1) ##2 $fell(sig2);
endsequence // s
// property
property p;
@(posedge clk) $rose(sig0) |-> ##1 s;
endproperty // p
a : assert property(p) $display("@%0t DUT%h | p : PASSED!",$time,num);
else $display("@%0t DUT%h | p : FAILED!",$time,num);
endmodule // test 【仿真结果】 示例中,$assertoff(0,u_dut0);/$assertoff(1,u_dut1);/$assertoff(1,top_tb);分别将:u_dut0及其以下所有层次断言关闭;u_dut1模块内的所有断言关闭;top_tb模块内的所有断言关闭,但是不包含其下所有层次。因为u_dut2未受到影响,所以其断言检查一直有效;$asserton(0,u_dut0)重新开启了u_dut0的断言检查,所以开启后仅u_dut0的断言重新使能,而之前关闭的u_dut1和top_tb断言检查并未重新启动。所以在具体设计时,一定要分清楚需要关闭的断言的层次要求,以免关闭需要的检查。

