• Property使用


    1. 介绍

    • 结合sequence(序列)对时序和逻辑的描述,property(属性)可以用来描述合计的确切行为;
    • property可以在验证中用来做assumption,checker或者coverage;
      • 当使用assert关键词时,可以用作checker来检查设计是否遵循property的描述;
      • 当使用assum关键词时,可以作为环境的假设条件,对于仿真环境和形式验证均起到对激励进行假设的作用;
      • 当使用cover关键词时,可以将property是否真正通过作为断言覆盖率来衡量;
    • property可以在module、interface、clocking块或者package中声明;
    • property也可以同sequence一样具备形式参数;
      property rule(x, y);
      	##1 x |-> y;
      endproperty
      
      • 1
      • 2
      • 3

    2. 时钟声明

    • 一般对于sequence或者property,默认情况下,在使用同一个时钟来对数据做采样,但是也不排除多个时钟的采样情况;

      	@(posedge clk0) sig0 ##1 @(posedge clk1) sig1
      
      • 1
    • 如果一个sequence或者property需要声明多个时钟来做数据采样,可以使用##1结合第二个时钟沿采样;

    • 只能使用##1来表示与第一个时钟(clk0)沿紧密相连的下一个时钟(clk1)沿;

    • seqauence操作符号例如and、or、intersect等无法被使用在多时钟sequence

    • 以下的多时钟sequence声明均是非法的;

      	@(posedge clk0) sig0 ##0 @(posedge clk1) sig1
      	@(posedge clk0) sig0 ##2 @(posedge clk1) sig1
      	@(posedge clk0) sig0 intersect @(posedge clk1) sig1
      
      • 1
      • 2
      • 3
    • property中的and、or、not则可以用在多时钟的property声明中,因为它们仅代表逻辑运算,并不参与sequence之间的时序关系;

    • 可以在sequence中独立指定时钟:

      sequence s2;	@(posedge clk) a ##2b;	endsequence
      property p2;	not s2;	endproperty
      assert property(p2);
      
      • 1
      • 2
      • 3
    • 可以在property中独立指定时钟:

      property p3;	@(posedge clk) not (a ##2 b);	endproperty
      assert property(p3);
      
      • 1
      • 2
    • 在过程块中,可以继承过程块的时钟:

      always @(posedge clk) assert property(not (a ##2 b));
      
      • 1
    • 在时钟块,也可以继承时钟块的时钟:

      clocking master_clk @(posedge clk);
      	property p3;	not (a ##2 b);	endproperty
      endclocking
      assert property(master_clk.p3);
      
      • 1
      • 2
      • 3
      • 4
    • 断言的时钟由一下条件的优先级逐级判定:

      • 显示声明断言时钟
      • 继承断言所嵌入环境的时钟
      • 继承默认的时钟
    • 对于多时钟的断言,必须显式声明时钟,无法继承或者使用默认时钟;

    • 如果是多时钟断言,也无法嵌套入由时钟驱动的过程块语句;

      always @(clk) assert property(mult_clock_prop);  // illegal
      initial @(clk) assert property(mult_clock_prop);  // illegal
      
      • 1
      • 2
    • 多时钟断言,也无法嵌套入时钟块;

    3. 绑定

    • 断言可以嵌入到设计中,也可以在设计外部定义,断言不可综合;
    • 嵌入到设计中,可以存在无法综合的问题,需要同时考虑添加编译定向(compiler directive);
    • 在设计外部定义,不用担心综合问题;
    • bind方法可以满足在设计外部定义断言,而将其绑定到设计内部或者接口上面;
    • 使用方法:bind design_block_or_instance_name block_with_assertions
    • bind可以将包含断言的模块与设计模块或者实例进行绑定,既可以满足对设计内部信号的可视性,又能够满足断言模块的独立性;
    • 使用绑定的优势在于,无法修改原有设计代码,也无需添加检测信号,既可以实现断言的添加;
      interface range(input clk, enable, input int minval, expr);
      	property crange_en;
      		@(posedge clk) enable |-> (minval <= expr);  // 小于等于
      	endproperty
      	range_chk: assert property(crange_en);
      endinterface
      
      bind cr_unit range r1(c_clk, c_en, v_low, (in1&&in2));
      // cr_unit是模块名
      // range是接口
      // r1是interface的实例,括号中的参数(信号)都来自于design,也就是model的端口信号或者内部信号
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
    • 在tb中例化interface,与dut做连接,这和bind方法一样都需要例化;
      • 不同的是,在例化dut的时候要把端口连上,如果想看到dut内部信号就得tb.层次1.层次2.信号名
      • 在用bind绑定模块和interface的时候,默认能够看到interface里面边界以及内部信号,这里的内部信号不包含内部层次以下的信号;
      • interface的例化实在tb中;
      • bind的例化最终实在模块内部,也就是dut内部;

    4. expect语句

    • 之前的assertassumecover都是非组合的方式,即它们本身并不会阻塞后续的语句,但是expect是一种阻塞的property使用方式;
    • expect的语法同assert一致,不过他会等待property执行通过,才会执行后续的语句;
    • 简单来看,可以使用wait语句的地方,就可以使用expect语句;
      initial begin
      	#200ms;
      	expect(@(posedge clk) 1 ##1 b ##1 c)
      		else $error("expect failed");
      	ABC: ... 
      end
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
    • 仿真在200ms开始,如果在连续的3个周期,可以一次看到a = 1, b = 1, c = 1,那么expect语句就会通过,否则会出现运行错误;
    • 当我们期望一些特定时序的时候,作为阻塞条件,我们则可以使用property的这种方式,来将其嵌入到过程语句块中;
    • a ##1 b ##1 c,这种写法相当于一个sequence;
    • a |=> b |=> c,这种写法与上面的功能一样,但是相当于多个sequence;
    • 和assert语句的调用方式类似,它也可以使用在function和task中,同时在可以引用静态变量或者动态变量;
      integer data;
      ...
      task automatic wait_for(integer value, output bit success);
      	expect(@(posedge clk) ##[1:10] data == value) success = 1;
      		else success = 0;
      endtask
      
      initial begin
      	bit ok;
      	wait_for(23, ok);  // wait for value 23
      end
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
  • 相关阅读:
    锐捷端口安全实验配置
    外卖系统的运转:背后的技术和管理细节
    redis 缓存设计
    Android 13.0 添加自定义服务,并生成jar给第三方app调用
    学生HTML网页作业:基于HTML+CSS+JavaScript画家企业8页
    MongoDB3.x创建用户与用户角色
    联盛德W801系列9-wifi和4G模块(air724ug)并存使用MQTT总结
    Vue页面结构
    图形数据库的实战应用:如何在 Neo4j 中有效管理复杂关系
    v-charts
  • 原文地址:https://blog.csdn.net/Bunny9__/article/details/126454068