构造一些比较复杂的序列时,常用的交叠操作符有时已经不能满足要求。
1.intersect
- 通常来说使用方法是(sequence)intersect(sequence),两端不能是property,需要确认两端的sequence都同时开始;
- 两个sequence长度也相同;
module top_tb;
logic clk;
logic sig0,sig1,sig2,sig3,sig4;
initial begin
clk = 1'b0;
forever #1 clk = ~clk;
end
initial begin
sig0 = 1'b0;sig1 = 1'b0;sig2 = 1'b0;
sig3 = 1'b0;sig4 = 1'b0;
#4 sig0 = 1'b1;
#2 sig0 = 1'b0;sig1 = 1'b1;sig3 = 1'b1;
#2 sig3 = 1'b0;sig1 = 1'b0;sig2 = 1'b1;
#2 sig3 = 1'b0;
#2 sig2 = 1'b1;sig4 = 1'b1;
#2 sig2 = 1'b0;sig4 = 1'b0;
#2 $stop;
end
sequence s1;
sig1 ##[1:5] sig2;
endsequence // s1
sequence s2;
sig3 ##[2:4] sig4;
endsequence // s2
property p;
@(posedge clk) $rose(sig0) |-> ##1 (s1 intersect s2);
endproperty // p
property p1;
@(posedge clk) $rose(sig0) |-> ##1 s1;
endproperty // p1
property p2;
@(posedge clk) $rose(sig0) |-> ##1 s2;
endproperty // p2
a : assert property(p) $display("@%0t | p : PASSED!",$time);
else $display("@%0t | p : FAILED!",$time);
a1 : assert property(p1) $display("@%0t | p1 : PASSED!",$time);
else $display("@%0t | p1 : FAILED!",$time);
a2 : assert property(p2) $display("@%0t | p2 : PASSED!",$time);
else $display("@%0t | p2 : FAILED!",$time);
endmodule // top_tb
- 有两个序列sequence1和sequence2,s1是在7ns处sig1高电平,然后等带一个时钟周期,9ns处sig2高电平。
- 在7ns处sig3高电平,然后等待3个时钟周期13ns处sig4高电平,断言成功;
- 然后在两个都成功的13ns处aintersect成功;
2.within
相较于intersect是两个sequence是同时开始,within是(sequence)intersect(sequence)右侧的起止点必须在左侧的起止点之内,当然也可以一样。
module top_tb;
logic clk;
logic sig0,sig1,sig2,sig3,sig4;
initial begin
clk = 1'b0;
forever #1 clk = ~clk;
end
initial begin
sig0 = 1'b0;sig1 = 1'b0;sig2 = 1'b0;
sig3 = 1'b0;sig4 = 1'b0;
#4 sig0 = 1'b1;
#2 sig0 = 1'b0;sig1 = 1'b1;
#2 sig1 = 1'b0;
#2 sig3 = 1'b1;
#2 sig3 = 1'b0;
#4 sig4 = 1'b1;
#2 sig4 = 1'b0;sig2 = 1'b1;
#2 sig2 = 1'b0;
#2 $stop;
end
sequence s1;
sig1 ##[1:6] sig2;
endsequence // s1
sequence s2;
sig3 ##[3:4] sig4;
endsequence // s2
property p;
@(posedge clk) $rose(sig0) |-> ##1 (s2 within s1);
endproperty // p
property p1;
@(posedge clk) $rose(sig0) |-> ##1 s1;
endproperty // p1
property p2;
@(posedge clk) $rose(sig0) |-> ##3 s2;
endproperty // p2
a : assert property(p) $display("@%0t | p : PASSED!",$time);
else $display("@%0t | p : FAILED!",$time);
a1 : assert property(p1) $display("@%0t | p1 : PASSED!",$time);
else $display("@%0t | p1 : FAILED!",$time);
a2 : assert property(p2) $display("@%0t | p2 : PASSED!",$time);
else $display("@%0t | p2 : FAILED!",$time);
endmodule // top_tb
- 这里的有右侧s是s1,然后以最后一个起止点s1的作为within的终点,也就是取决于最长的那个
3.throughout
如果期望某些信号在一个序列检查中一直保持一个状态,可以使用throughout;
module top_tb;
logic clk;
logic sig0,sig1,sig2,sig3;
initial begin
clk = 1'b0;
forever #1 clk = ~clk;
end
initial begin
sig0 = 1'b0;sig1 = 1'b0;sig2 = 1'b0;sig3 = 1'b0;
#2 sig0 = 1'b1;
#2 sig0 = 1'b0;sig1 = 1'b1;sig2 = 1'b1;
#2 sig2 = 1'b0;
#6 sig3 = 1'b1;
#2 sig3 = 1'b0;sig1 = 1'b0;
#4 sig0 = 1'b1;
#2 sig0 = 1'b0;sig1 = 1'b1;sig2 = 1'b1;
#2 sig2 = 1'b0;
#2 sig1 = 1'b0;
#2 sig1 = 1'b1;
#2 sig3 = 1'b1;
#2 sig3 = 1'b0;sig1 = 1'b0;
#2 $stop;
end
sequence s;
sig2 ##[1:6] sig3;
endsequence // s
property p;
@(posedge clk) $rose(sig0) |-> ##1 (sig1 throughout s);
endproperty // p
a : assert property(p) $display("@%0t | p : PASSED!",$time);
else $display("@%0t | p : FAILED!",$time);
endmodule // top_tb
- 在1ns处sig0为低,在3ns处为高,$rose为真,然后隔一个时钟周期5ns处开始看sig1与s的关系
- s在sig2在5ns处为高,第四个周期,就是13ns处sig3为高,s成立,然后throughout成立;
disable iff | throughout |
---|---|
作用时间等同于当前property | 作用时间为其两侧序列和信号被检查的时间 |
可以异步于当前采样事件 | 与当前采样事件同步 |
如果iff后的条件发生,将终止当前序列表达式的检查,产生空成功 | 如果其两侧的序列或者信号不匹配,那么当前序列会失败 |
4.first_match
如果需要对同时发生的多个序列进行断言时,使用first_match可以检查同时发生的序列进程中第一个完成的是谁,然后会丢弃对剩余的序列的检查;
module top_tb;
logic clk;
logic sig0,sig1,sig2,sig3;
initial begin
clk = 1'b0;
forever #1 clk = ~clk;
end
initial begin
sig0 = 1'b0;sig1 = 1'b0;sig2 = 1'b0;sig3 = 1'b0;
#2 sig0 = 1'b1;sig1 = 1'b1;
#2 sig0 = 1'b0;sig1 = 1'b0;sig2 = 1'b1;
#6 sig2 = 1'b0;
#2 sig3 = 1'b1;
#2 sig3 = 1'b0;
#2 $stop;
end
property p1;
@(posedge clk) $rose(sig0) |-> sig1 ##1 sig2[*1:4] ##2 sig3;
endproperty // p1
property p2;
@(posedge clk) $rose(sig0) |-> sig1 ##1 first_match(sig2[*1:4]) ##2 sig3;
endproperty // p2
a1 : assert property(p1) $display("@%0t | p1 : PASSED!",$time);
else $display("@%0t | p1 : FAILED!",$time);
a2 : assert property(p2) $display("@%0t | p2 : PASSED!",$time);
else $display("@%0t | p2 : FAILED!",$time);
endmodule // top_tb
- 对应sig2[*1:4]会同时开启4个并行的进程,分别检查sig2连续匹配1次、2次、3次和4次为高的情况,四个进程只要有一个匹配成功即认为sig2[*1:4]匹配成功一次
- sig2[*1:4]第三次匹配成功后的两个采样周期sig3也匹配,所以sig2[*1:4]第四次检查被舍弃
5.matched
如果想要让property中不同sequence之间进行交互,我们可以使用matched来检测其中一个子序列的结束点,然后实现不同采样sequence之间的同步交互。同时matched的sequence必须有自己的采样事件,不同的是matched序列使用的采样事件可以与调用其的属性使用的采样事件不同。
module top_tb;
logic clk1,clk2;
logic sig0,sig1,sig2;
initial begin
clk1 = 1'b0;clk2 = 1'b0;
fork
forever #1 clk1 = ~clk1;
forever #2 clk2 = ~clk2;
join
end
initial begin
sig0 = 1'b0;sig1 = 1'b0;sig2 = 1'b1;
#4 sig1 = 1'b1;
#1 sig0 = 1'b1;
#1 sig2 = 1'b0;sig1 = 1'b0;
#8 $stop;
end
sequence s;
@(posedge clk1) $rose(sig1) ##1 $fell(sig2);
endsequence // s
property p1;
@(posedge clk2) $rose(sig0) |=> s.matched;
endproperty // p1
property p2;
@(posedge clk2) $rose(sig0) |=> @(posedge clk1) s.matched;
endproperty // p2
a1 : assert property(p1) $display("@%0t | p1 : PASSED!",$time);
else $display("@%0t | p1 : FAILED!",$time);
a2 : assert property(p2) $display("@%0t | p2 : PASSED!",$time);
else $display("@%0t | p2 : FAILED!",$time);
endmodule // top_tb
- p1是在6ns$rose成功,然后等一个周期10ns处match;
- p2是在6ns$rose成功,然后以clk1的上升沿7ns处match
- 在s中$rose在5ns成立,然后再一个时钟周期后7ns开始match,而且结果会暂存起来;
- $rose(sig0)在6ns时基于clk2匹配成功,然后7ns处与match;
- 匹配成功。在属性p2中,后续算子指定了采样事件为clk1,此时前后算子基于不同的采样事件,在基于clk2采样事件的先行算子满足要求之后,在距离其最近的基于clk1采样事件的时刻检查s.matched是否匹配,而示例中s.matched在7ns时满足要求,所以此时整个属性匹配成功。