SVA中的序列表达式操作符
1 intersect
intersect两侧的表达式都是sequence,不能是property,使用intersect时需要确保其两侧的sequence必须同时开始,且当两个sequence最终同时匹配时才认为两个序列的intersect匹配,即两个sequence匹配的长度必须相同,intersect操作符和and操作符很相似,但是and没有要求两个序列最终匹配时同时匹配。intersect使用示意图如下:
`timescale 1 ns / 1 ps
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 【仿真结果】
2 within
within右侧sequence的起止点必须位于左侧sequence的起止点之内,当然within左右两侧sequence的起止点可以一样,整个“sequence_1 within sequence_2”匹配成功的结束点与右侧sequence的结束点一致。within使用示意图如下:
`timescale 1 ns / 1 ps
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 【仿真结果】 3 throughout
在SVA中有时需要某些信号在一个序列的检查过程中一直保持一个状态,此时就可以使用throughout操作符,当这些信号的状态发生不期望的变化时,序列的检查即认为失败。throughout使用示意图如下:
`timescale 1 ns / 1 ps
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 【仿真结果】
这里需要注意,在SVA中还存在着另一种操作符“disable iff”其功能与throughout非常类似,但是在使用时还需要注意两者的差异。
【示例】
`timescale 1 ns / 1 ps
module top_tb;
logic clk,rst;
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;rst = 1'b0;
#2 rst = 1'b1;
#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;rst = 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
property pr;
disable iff(!rst)
@(posedge clk) $rose(sig0) |-> ##1 (sig1 throughout s);
endproperty // pr
a : assert property(p) $display("@%0t | p : PASSED!",$time);
else $display("@%0t | p : FAILED!",$time);
a0 : assert property(pr) $display("@%0t | pr : PASSED!",$time);
else $display("@%0t | pr : FAILED!",$time);
endmodule // top_tb 【仿真结果】示例中,通过属性p可以看到,p中throughout两侧序列和相关信号的采样都是基于采样事件的,throughout的作用范围限于其两侧序列和信号的被检查时间。Pr中的disable iff作用时间与当前属性的时间相同,并且当其中条件满足时后续的检查将会被终止并产生空成功(vacuous success),如图中24ns处所示。而且disable iff中的信号不像throughout两侧的表达式是基于采样事件的,disable iff信号可以异步于采样事件存在。由此可见,disable iff和throughout区别可总结如下:
| disable iff | throughout |
| 作用时间等同于当前property | 作用时间为其两侧序列和信号被检查的时间 |
| 可以异步于当前采样事件 | 与当前采样事件同步 |
| 如果iff后的条件发生,将终止当前序列表达式的检查,产生空成功 | 如果其两侧的序列或者信号不匹配,那么当前序列会失败 |
4 first_match
在对一些指定时序窗口同时发生的多个序列进行检查时,使用first_match可以检查这些同时发出的序列进程中第一个完成匹配的序列,然后丢弃对于其他未完成序列进程的检查。
【示例】
`timescale 1 ns / 1 ps
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 【仿真结果】 5 ended
详见“SVA中被抛弃的ended”
6 matched
在一些场景,可能会碰到这样的情况:在一个属性中不同序列基于不同的采样事件,那么如何在基于不同采样事件的序列之间进行交互呢?在SVA中使用matched可以用来检测其中一个子序列的结束点,从而实现基于不同采样事件的序列之间的同步交互。与ended结构类似,使用matched的序列必须要有自己的采样事件,不同的是matched序列使用的采样事件可以与调用其的属性使用的采样事件不同。
【示例】
`timescale 1 ns / 1 ps
module top_tb;
logic clk1,clk2;
logic sig1,sig2;
initial begin
clk1 = 1'b0;clk2 = 1'b0;
fork
forever #1 clk1 = ~clk1;
forever #2 clk2 = ~clk2;
join
end
initial begin
sig1 = 1'b0;sig2 = 1'b0;
#2 sig1 = 1'b1;
#2 sig1 = 1'b0;
#2 sig2 = 1'b1;
#4 sig2 = 1'b0;
#2 sig1 = 1'b1;
#2 sig1 = 1'b0;
#2 sig2 = 1'b1;
#4 $stop;
end
sequence s1;
@(posedge clk1) $rose(sig1);
endsequence // s1
sequence s2;
@(posedge clk2) $rose(sig2);
endsequence // s2
property p;
@(posedge clk2) s1.matched |-> ##1 s2;
endproperty // p
a : assert property(p) $display("@%0t | p : PASSED!",$time);
else $display("@%0t | p : FAILED!",$time);
endmodule // top_tb 【仿真结果】 【示例】
`timescale 1 ns / 1 ps
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 【仿真结果】 示例中,序列s在7ns处匹配成功,s.matched结果将会保存着。$rose(sig0)在6ns时基于clk2匹配成功,即属性p1中“|=>”先行算子$rose(sig0)匹配,但是后续算子在属性p1中并没有明确指定采样事件,所以此处属性的匹配将在基于clk2的先行算子匹配后的一个采样周期
匹配成功。在属性p2中,后续算子指定了采样事件为clk1,此时前后算子基于不同的采样事件,在基于clk2采样事件的先行算子满足要求之后,在距离其最近的基于clk1采样事件的时刻检查s.matched是否匹配,而示例中s.matched在7ns时满足要求,所以此时整个属性匹配成功。这里需要注意,SVA会自动同步不同信号或者子序列使用的时钟域,并且当序列中使用了多个时钟信号时,只允许在其中使用“##1”进行延迟,关于多时钟在SVA中的应用可参考“SVA中的multi-clock”一文。
科大讯飞公司氛围 468人发布
