一.断言简介
1.断言的概念
断言(SVA)主要用于验证设计的行为,断言的主要有两个功能:
- 在特定条件或事件序列的故障上生成警告或错误
- 收集功能覆盖率的数据
断言一般出现在那些位置:interface, module,clocking,program
2.断言的类型
(1)立即断言
立即断言执行时如同过程语句,它在程序执行到这个程序块使立即执行。
断言比if语句更加紧凑,且断言里面的逻辑跟if语句是相反的。设计者应该期望括号内的表达式为真,否则输出一个错误。
//使用if语句检查一个信号
bus.cb.request<=1;
repeat(2) @bus.cb;
if(bus.cb.grant!=2'b01)
$display("Error,grant!=1");
//简单的立即断言
bus.cb.request<=1;
repeat(2) @bus.cb;
al:assert (bus.cb==2'b01);
//定制断言行为
bus.cb.request<=1;
repeat(2) @bus.cb;
al:assert (bus.cb==2'b01)
else $error("Grant not asserted");
(2)并发断言
并发断言可以认为时一个连续运行的模块,他为整个仿真过程检查信号的值,需要在断言内指定一个采样时钟。
例中是一个检查仲裁器request信号的断言,request信号除了在复位期间,其他任何时候都不能是X或Z。
//检查X/Z的并发断言
interface arb_if(input bit clk);
logic[1:0] grant,request;
logic rst;
property request_2state;
@(posedge clk) disable iff(rst);
$isunknown(request)==0; //确保没有z或者x值存在
endproperty
assert_request_2state:assert property(requset_2state);
endinterface
3.断言的符号
概念网上有很多,只做简单介绍,详细可参考:
assertion断言入门
二.APB断言实战
1.apb时序
APB协议这里不做详解,参考文章:
APB详解
2.断言代码
interface apb_if(input pclk,
input presetn);
logic[31:0] paddr;
logic[31:0] prdata;
logic[31:0] pwdata;
logic[15:0] psel;
logic penable;
logic pwrite;
logic pready;
// psel,presetn is valid
property signal_valid(signal);
@(posedge pclk)
!$isunknown(signal);
endproperty:signal_valid
CHK_PSEL:assert property(signal_valid(psel));
CHK_PRESETN:assert property(signal_valid(presetn));
COVER_PSEL:assert property(signal_valid(presetn));
//onehot
property psel_onehot0;
@(posedge pclk)
$onehot(psel);
endproperty:psel_onehot0
PSEL_ONLY_ONE:assert property(psel_onehot0);
//penable,pwrite,pready is valid
property control_signal_valid(signal);
@(posedge pclk)
$onehot(psel) |-> !$isunknown(signal);
endproperty:control_signal_valid
CHK_PENABLE:assert property(control_signal_valid(penable));
CHK_PWRITE:assert property(control_signal_valid(pwrite));
CHK_PREADY:assert property(control_signal_valid(pready));
//psel --> penable
property psel_penable;
@(posedge pclk)
$rose($onehot(psel)) |=> $rose(penable);
endproperty:psel_penable
CHK_PSEL_PENBALE:assert property(psel_penable);
//penable --> penable
property penable_penable;
@(posedge pclk)
$rose(penable) |=> $fell(penable);
endperty:penable_penable
CHK_PENABLE_PENABLE:assert property(penable_penable);
//pwdata is valid
property pwdata_valid
@(posedge pclk)
($onehot(psel) && pwrite) |-> !$isunknown(pwdata);
endproperty:pwdata_valid
CHK_PWDATA:assert property(pwdata_valid);
//prdata is valid
property prdata_valid
@(posedge pclk)
$rose($onehot(penable) && !pwrite && pready) |-> !$isunknown(prdata) ##1 $fell(penable);
endproperty:prdata_valid
CHK_PRDATD:assert property(prdata_valid);
//stable
property psel_assert_signal_stable(signal);
@(posedge pclk)
(!$stable(psel) && $onehot(psel)) |=> $stable(signal)[*1:$] ##1 $fell(penable);
endproperty:psel_assert_signal_stable;
PSEL_STABLE:assert property(psel_assert_signal_stable(psel));
PWRITE_STABLE:assert property(psel_assert_signal_stable(pwrite));
PADDR_STABLE:assert property(psel_assert_signal_stable(paddr));
PWDATA_SIGNAL:assert property(psel_assert_signal_stable(pwdata&&pwrite));
endinterface:apb_if
TB中增加断言控制
initial begin
fork
forever begin
wait(rst==0);
$assertoff();
wait(rst==1);
$asserton();
end
join_none
end