Assertion断言入门(四)——断言覆盖率

以APB总线协议的断言检查和断言覆盖率为例,学习断言的基本使用和断言覆盖率覆盖。需要用到关键词cover来收集断言覆盖。

APB总线协议时序图如下:(首图为读操作时序和后图为写操作时序)

PS:关于APB协议的详细的描述可见AMBA总线协议中APB协议总结一文:APB总线协议
在这里插入图片描述
在这里插入图片描述

断言检查一

  • 在PSEL为高时,PADDR总线不可以为x值;
property p_addr_no_x;
    @(posedge clk) psel |-> !$isunknow(paddr); 
endproperty
assert property(p_addr_no_x) else `uvm_error("ASSERT","PADDR is unknow when PSEL is high");

断言检查二

  • 在PSEL拉高的下一个周期,PENABLE也应该为高。
property penable_rise;
    @(posedge clk) $rose(psel) |=> $rose(penable);
endproperty
assert property(penable_rise) else `uvm_error("ASSERT","PENABLE not rose after 1 cylce PSEL rose");

断言检查三

  • 在PENABLE拉高的下一个周期,PENABLE应该拉低;
property penable_fell;
    @(posedge clk) $rose(penable) |=> $fell(penable);
endproperty
assert property(penable_fell) else `uvm_error("ASSERT","PENABLE not fell after 1 cylce PENABLE rose");

断言检查四

  • 在PSEL和PWRITE同时保持为高的阶段,PWDATA需要保持。
property pwdata_stable;
    @(posedge clk) (psel && !penable) ##1 (psel && penable) |-> $stable(pwdata);
endproperty
assert property(pwadata_stable) else `uvm_error("ASSERT","PENABLE not stable after 1 cylce PENABLE ....");

断言检查五

  • 在下一次传输开始前,上一次的PADDR和PWRITE信号应该保持不变。
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","....");    

断言检查六

  • 读操作时,在PENABLE拉高的同一周期,PRADTA也应该发生变化。
property prdata_change;
    @(posedge clk) $rose(penable) && !pwrite |-> !$stable(prdata);
endproperty
assert property(prdata_change) else `uvm_error("ASSERT","....");

断言覆盖率一

  • 在写操时,分别发生连续写和非连续写;
property cov_nonburst;//非连续写
   @(posedge clk) $rose(penable) |-> pwrite throughout 
  	 ( ##1 (!penable)[*2] ##1 penable[=1]);
endproperty
cover property(cov_nonburst) else `uvm_error("ASSERT","....");
property cov_burst;//连续写
   @(posedge clk) $rose(penable) |-> pwrite throughout ( ##2 penable);
endproperty
cover property(cov_burst) else `uvm_error("ASSERT","....");    

断言覆盖率二

  • 对同一个地址先做写做操作,再不间隔做读操作;
property cov_write_read;
    logic [31:0] addr;//因为是对同一个地址,要记录地址
    @(posedge clk) ($rose(penable) && pwrite,addr= paddr) |->
    	(##2 ($rose(penable)&& !pwrite && addr==paddr));
endproperty
cover property(cov_write_read) else `uvm_error("ASSERT","....");

断言覆盖率三

  • 对同一个地址做连续两次写操作再从中读数据。
property cov_twice_write;
    logic [31:0] addr;//因为是对同一个地址,要记录地址
    @(posedge clk) 
    ($rose(penable) && pwrite, addr=paddr) |-> (
    	##2 ($rose(penable) && pwrite && addr==paddr) 
     	##2 ($rose(penable) && !pwrite && addr==paddr) 
    );
endproperty
cover property(cov_twice_write) else `uvm_error("ASSERT","....");   

断言覆盖率四

  • 在读操作时,分别发生连续读和非连续读;
property cov_read_nonburst;//非连续读
    @(posedge clk) 
    $rose(penable) |-> !pwrite throughout (##1 (!penable)[*2] ##1 penable [=1]); 
endproperty
cover property(cov_read_nonburst) else `uvm_error("ASSERT","...."); 
property cov_read_burst;//连续读
    @(posedge clk) 
    $rose(penable) |-> !pwrite throughout (##2 penable); 
endproperty
cover property(cov_read_burst) else `uvm_error("ASSERT","....");   

断言覆盖率五

  • 发生对同一个地址的读操作,再不间隔做写操作,再不间隔做读操作。
property cov_twice_write_read;
    logic [31:0] addr;//因为是对同一个地址,要记录地址
    @(posedge clk) 
   ($rose(penable) && !pwrite, addr=paddr) |->  (
  	 	##2 ($rose(penable) && pwrite && addr==paddr)
     	##2 ($rose(penable) && !pwrite && addr==paddr)
    );
endproperty
cover property(cov_twice_write_read) else `uvm_error("ASSERT","...."); 

注意:

  • 在仿真时,要添加额外的仿真选项: -assertdebug -assertcover。assertdebug是为了调试断言,assertcover是为了收集断言覆盖。
  • 这些property都可以在TB中的interface内定义;

最后再加上一个对整个assertion控制:

//在外部定义
initial begin
   fork
       forever begin
           wait(rst_n==0);
           $assertoff();
           wait(rst_n==1);
           $asserton();
       end
   join_none
end
  • 23
    点赞
  • 180
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小小verifier

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值