日常记录(29)断言property
断言测试代码
module taa ();
reg clk1, clk2, clk3;
reg a,b,c,d,e,f,g,h;
initial begin
fork
begin
clk1=0;
forever #2 clk1=~clk1;
end
begin
clk2=0;
forever #3 clk2=~clk2;
end
begin
clk3=0;
forever #5 clk3=~clk3;
end
join
end
property p1;
@(posedge clk1) disable iff(a) $rose(b) |-> c[=2] ##1 d[=2] ##1 !d;
endproperty
a1: assert property(p1);
property p2;
@(posedge clk1) disable iff(a) $rose(b) |=> c[=2] ##1 d[=2] ##1 !d;
endproperty
a2: assert property(p2);
let p3=(d && b && c);
property p4;
@(posedge clk1) disable iff(a) p3 |-> e[=2] ##1 f[=2] ##1 !g;
endproperty
a4: assert property(p4);
property p5;
@(posedge clk1) disable iff(a) p3 |-> not(e[=2] ##1 f[=2] ##1 !g);
endproperty
a5: assert property(p5);
property p6;
@(posedge clk1)
disable iff(a)
$rose(b) |-> (c[=2] ##1 d[=2] ##1 !d) and ((e ##1 f) or (g ##1 h));
endproperty
a6: assert property(p6);
property p7;
@(posedge clk1)
disable iff(a)
$rose(b) |-> (c[=2] ##1 d[=2] ##1 !d) intersect ((e ##1 f) or (g ##1 h));
endproperty
a7: assert property(p7);
property p9(x,y);
x |-> ##1 x && y;
endproperty
property p8;
@(posedge clk1)
a ##1 (b||c)[->1] |->
if(d) (##1 e |-> f)
else p9(g ,h);
endproperty
a8: assert property(p8);
// property p10(p);
// p and (1'b1 |=> p10(p));
// endproperty
// a10: assert property(p10(h));
property p10;
@(posedge clk1) a ##1 @(posedge clk2) b ;
endproperty
a10: assert property(p10);
property p11;
@(posedge clk1) a |=> @(posedge clk2) b ;
endproperty
a11: assert property(p11);
property p12;
@(posedge clk1) a |-> @(posedge clk2) b ##1 @(posedge clk3) c; //illegal but can pass
//@(posedge clk1) a |-> @(posedge clk1) b ##1 @(posedge clk2) c;
endproperty
a12: assert property(p12);
//a13: assume property @(clk1) b dist{0:=40, 1:=60};
//property proto
// @(posedge clk1) b |-> b[*1:$] ##0 c;
//endproperty
a15: assume property(p1);
a14: cover property(p1);
initial begin
forever #1 {a,b,c,d,e,f,g,h}=$urandom;
end
initial begin
#10 assign a=1;
#20 assign a=0;
#10000 $finish;
end
endmodule
断言说明
p1: $rose(b) |-> c[=2] ##1 d[=2] ##1 !d
a为0表示生效,在b的上升沿出现后,同样的时钟周期开始计算,出现两个c以后,等1时钟周期,出现两个d以后,等一个时钟周期d为0.
property p1;
@(posedge clk1) disable iff(a) $rose(b) |-> c[=2] ##1 d[=2] ##1 !d;
endproperty
a1: assert property(p1);
p2: |=>
p2, |=>表示下一周期开始计算。
property p2;
@(posedge clk1) disable iff(a) $rose(b) |=> c[=2] ##1 d[=2] ##1 !d;
endproperty
a2: assert property(p2);
p4: let p3=(d && b && c)
let p3=(d && b && c);
property p4;
@(posedge clk1) disable iff(a) p3 |-> e[=2] ##1 f[=2] ##1 !g;
endproperty
a4: assert property(p4);
p5: not和!g
property p5;
@(posedge clk1) disable iff(a) p3 |-> not(e[=2] ##1 f[=2] ##1 !g);
endproperty
a5: assert property(p5);
p6 p7: and、or、intersect
property p6;
@(posedge clk1)
disable iff(a)
$rose(b) |-> (c[=2] ##1 d[=2] ##1 !d) and ((e ##1 f) or (g ##1 h));
endproperty
a6: assert property(p6);
property p7;
@(posedge clk1)
disable iff(a)
$rose(b) |-> (c[=2] ##1 d[=2] ##1 !d) intersect ((e ##1 f) or (g ##1 h));
endproperty
a7: assert property(p7);
p8,if、else、->、||、&&
property p9(x,y);
x |-> ##1 x && y;
endproperty
property p8;
@(posedge clk1)
a ##1 (b||c)[->1] |->
if(d) (##1 e |-> f)
else p9(g ,h);
endproperty
a8: assert property(p8);
p10,p11,p12的跨时钟、a为1,
p10 @(posedge clk1) a ##1 @(posedge clk2) b,在clk1位上升沿判断a为1后,经过不到1个时间单位,clk2上升沿后判断b为1,成立
property p10;
@(posedge clk1) a ##1 @(posedge clk2) b ;
endproperty
a10: assert property(p10);
下降为失败,向上的箭头为成功。
p11和p10不同
|=>起始点不在 @(posedge clk1) a处。
property p11;
@(posedge clk1) a |=> @(posedge clk2) b ;
endproperty
a11: assert property(p11);
p12
p12的,,,在clk1位上升沿判断a为1后,经过不到1个时间单位,clk2上升沿后判断b为1,经过不到(或者等于)1个时间单位,clk3上升沿后判断c为1,成立。
和理论的时钟偏移,然后过渡到下一个时钟单位,经过一个周期的结果输出,有出入
property p12;
@(posedge clk1) a |-> @(posedge clk2) b ##1 @(posedge clk3) c; //illegal but can pass
//@(posedge clk1) a |-> @(posedge clk1) b ##1 @(posedge clk2) c;
endproperty
a12: assert property(p12);
apb断言检查中赋值
在下一次传输开始前,上一次的PADDR和PWRITE信号应该保持不变。
$rose(penable)表示出现了一个apb的读写传输,这时候将paddr存储在addr1中。
[=1]表示非连续重复一次,enable拉低,传输结束点,该传输结束点的上一个周期的地址值,存储在addr2中。
past缺省值为1,即上一个周期的值。
property paddr_stable_next_trans;
logic [31:0] addr1,addr2;//记录前后两次传输的地址
@(posedge clk)
$first_match( ($rose(penable),addr1==paddr) ##1 ((psel && !penable)[=1],addr2 = $past(paddr)) )
|-> addr1 == addr2;
// ($rose(penable),addr1==paddr)是上一次事务传输正在传输的阶段,将这个地址记录
//((psel && !penable)[=1],addr2 = $past(paddr))是下一次传输准备阶段,
//注意:此时记录的是上一拍传输的地址,这就使得paddr信号保持不变
endproperty
assert property(paddr_stable_next_trans) else `uvm_error("ASSERT","....");
property pwrite_stable_next_trans;
logic pwrite1,pwrite2;
@(posedge clk)
$first_match( ($rose(penable),pwrite1==pwrite) ##1 ((psel && !penable)[=1],pwrite2 = $past(pwrite)) )
|-> pwrite1 == pwrite2;
endproperty
assert property(pwrite_stable_next_trans) else `uvm_error("ASSERT","....");
断言*的含义
=是表示非连续重复次数,*是表示连续重复次数。
表示连续的意思:
@ (posedge clk) a [*3] ———— 断定“@ (posedge clk) a”在连续3个时钟周期内都成立。
@ (posedge clk) a [*1:3] ———— 断定“@ (posedge clk) a”在连续1~3个时钟周期内都成立。
断言开启和关闭
https://www.cnblogs.com/csjt/p/15890518.html
$assertoff暂时关闭所有断言的执行,如果该函数执行时断言正在执行,正在执行的断言不会被终止;
$asserton重新启动断言执行;
$assertkill将会终止设计中所有的断言,包括已经执行的断言,当遇到下一个断言需要开始执行时,需要使用$asserton启动;
Le vent se lève! . . . il faut tenter de vivre!
Le vent se lève! . . . il faut tenter de vivre!