property rule(x, y);
##1 x |-> y;
endproperty
一般对于sequence或者property,默认情况下,在使用同一个时钟来对数据做采样,但是也不排除多个时钟的采样情况;
@(posedge clk0) sig0 ##1 @(posedge clk1) sig1
如果一个sequence或者property需要声明多个时钟来做数据采样,可以使用##1
结合第二个时钟沿采样;
只能使用##1
来表示与第一个时钟(clk0)沿紧密相连的下一个时钟(clk1)沿;
seqauence
操作符号例如and、or、intersect等无法被使用在多时钟sequence
;
以下的多时钟sequence
声明均是非法的;
@(posedge clk0) sig0 ##0 @(posedge clk1) sig1
@(posedge clk0) sig0 ##2 @(posedge clk1) sig1
@(posedge clk0) sig0 intersect @(posedge clk1) sig1
property
中的and、or、not则可以用在多时钟的property
声明中,因为它们仅代表逻辑运算,并不参与sequence
之间的时序关系;
可以在sequence中独立指定时钟:
sequence s2; @(posedge clk) a ##2b; endsequence
property p2; not s2; endproperty
assert property(p2);
可以在property中独立指定时钟:
property p3; @(posedge clk) not (a ##2 b); endproperty
assert property(p3);
在过程块中,可以继承过程块的时钟:
always @(posedge clk) assert property(not (a ##2 b));
在时钟块,也可以继承时钟块的时钟:
clocking master_clk @(posedge clk);
property p3; not (a ##2 b); endproperty
endclocking
assert property(master_clk.p3);
断言的时钟由一下条件的优先级逐级判定:
对于多时钟的断言,必须显式声明时钟,无法继承或者使用默认时钟;
如果是多时钟断言,也无法嵌套入由时钟驱动的过程块语句;
always @(clk) assert property(mult_clock_prop); // illegal
initial @(clk) assert property(mult_clock_prop); // illegal
多时钟断言,也无法嵌套入时钟块;
bind
方法可以满足在设计外部定义断言,而将其绑定到设计内部或者接口上面;bind design_block_or_instance_name block_with_assertions
bind
可以将包含断言的模块与设计模块或者实例进行绑定,既可以满足对设计内部信号的可视性,又能够满足断言模块的独立性;interface range(input clk, enable, input int minval, expr);
property crange_en;
@(posedge clk) enable |-> (minval <= expr); // 小于等于
endproperty
range_chk: assert property(crange_en);
endinterface
bind cr_unit range r1(c_clk, c_en, v_low, (in1&&in2));
// cr_unit是模块名
// range是接口
// r1是interface的实例,括号中的参数(信号)都来自于design,也就是model的端口信号或者内部信号
bind
方法一样都需要例化;
tb.层次1.层次2.信号名
;interface
的例化实在tb中;bind
的例化最终实在模块内部,也就是dut内部;assert
、assume
和cover
都是非组合的方式,即它们本身并不会阻塞后续的语句,但是expect是一种阻塞的property
使用方式;expect
的语法同assert
一致,不过他会等待property
执行通过,才会执行后续的语句;wait
语句的地方,就可以使用expect
语句;initial begin
#200ms;
expect(@(posedge clk) 1 ##1 b ##1 c)
else $error("expect failed");
ABC: ...
end
a ##1 b ##1 c
,这种写法相当于一个sequence;a |=> b |=> c
,这种写法与上面的功能一样,但是相当于多个sequence;integer data;
...
task automatic wait_for(integer value, output bit success);
expect(@(posedge clk) ##[1:10] data == value) success = 1;
else success = 0;
endtask
initial begin
bit ok;
wait_for(23, ok); // wait for value 23
end