sv断言(未完待续)

什么是断言?

断言:断言是一种声明,即某个属性必须为真。

设计规范:请求req信号被断言后,确认ack信号必须在1到3个时钟后到达。

断言用于:

  • 文档设计意图(例如:每个请求信号req都有一个确认信号ack)
  • 在仿真时间内验证设计是否符合规范
  • 验证设计假设(例如:状态值为独热码)
  • 定位发生故障的位置是在设计而不是在输出
  • 为形式验证提供语义
  • 描述功能覆盖点
  • 等....要求澄清规范中的歧义

无断言的验证

在出现像SVA这样的特殊断言语言之前,验证检查必须用编程语句进行编码

嵌入式验证检查与综合

必须对Synthesis隐藏用VeriIog编写的检查代码

  • Synthesis无法区分硬件模型和嵌入的检查器代码

    问题:

    1.你知道有多少设计工程师会在if.else-RTL状态中添加这么多额外的代码?

    2.此检查代码对综合是隐藏的,但它在仿真中始终处于活动状态(不容易为复位或低功率模式关闭)

    SystemVerilog断言更容易,而且在综合中忽略SVA

    被综合忽略,并且可以在仿真过程中关闭断言

SystemVerilog有两种类型的断言

立即断言:立即断言测试当前时间的条件

​ 如果 state 不是独热码,则生成fatal 错误。

​ 注:立即断言实际与if…else语句相同,但带有断言控件。

并发断言:分布在多个时钟周期上的一系列事件events。

​ 并发断言作为后台进程与RTL代码并行运行

​ 注:并发断言有一组广泛的运算符来描述复杂的设计条件

断言严重性系统任务

  • 断言消息可以划分为严重级别

​ 注:如果未指定严重性级别,则断言消息默认为错误级别

​ 用户提供的消息被附加到特定于工具的消息中,该消息包含源文件位置和模拟时间。

​ 该消息是可选的;如果未指定,则仍将打印特定于工具的消息

​ UVM测试台中的断言应使用UVM消息函数,如UVM_report_warning和UVM_report_error,以便UVM重新跟踪消息(应该是使用uvm_info,如果要捕获设计中的错误 assert(而不是if else),用uvm_warning 或者 uvm_error 产生消息 )

断言通过/失败操作

  • 断言可以有通过和失败的“操作”

​ 注: 用户定义的通过/失败语句可以执行任何操作(提示:使用%m显示包含消息的语句的层次结构路径)

  • pass和fail语句可以是任何过程性语句

​ 多个语句必须以begin-end分组

  • 通过的行为是可选的

    • 如果保持“关闭”,则在断言通过时不采取任何操作
  • fail的行为也是可选的

    • 如果保持关闭状态,则会打印一条默认的工具生成消息,其中包含错误消息的严重级别

      通过时不执行任何操作,失败时显示默认消息。

用断言检测故障

信号在一个时钟周期内可能发生多次变化(潜在的故障),原因有很多

  • 组合解码,时钟域交叉,异步复位等

​ eg:时钟周期内的这个小故障将影响我的设计功能——我需要检测它。❌

​ 时钟周期内的这个故障永远不会存储在我的寄存器中——我可以忽略它。🐕

注:lmmediate断言是可以随时评估值的编程语句。并发断言基于周期,并且仅在时钟边缘评估值

立即和并发断言优点和缺点

立即断言

  • 优点:
    • 易于编写-简单的语法
    • 接近正在检查的代码
    • 可以检查时钟周期之间的异步值
    • 代码的自文档化
  • 缺点:
    • 无法使用binding
    • 复位或低功率时难以禁用
    • 必须遵循良好的RTL规范以防止出现竞争条件(就像任何编程语句一样)

并发断言

  • 优点:

    • 后台任务定义它,它就会运行
    • 基于周期, 周期之间没有故障
    • 可以使用binding
    • 适用于模拟和形式验证
  • 缺点:

    • 更难定义(和调试)
    • 可能与正在检查的代码相距甚远
    • 无法检测到故障

    并发断言是基于周期的

    序列(sequence)定义:序列是分布在一个或多个时钟周期上的一系列真/假表达式。

    • sequence可以在module、interface、program、clocking块和package中声明。

    • sequence也可以提供形式参数,用来提高复用性

    • 表示“周期延迟”

      • 指定在计算序列中的下一个表达式之前等待的时钟周期数

        • 第一个表达式立即求值

        • 后续表达式将在以后的时钟周期进行求值

    注:1.@(posedge clock)不是延迟,它指定了此属性的周期

    1. req必须在一个时钟周期后grant

    2. 必须在一到三个时钟周期之后request和grant

    3. 也可以有条件的关闭。

      sequence的注意事项:

      • sequence用来提供下列的场景描述:第一个时钟周期,第一个表达式成立的,接下来在若干时钟周期后,第二个表达式也成立,一次类推,在接下来的若干时钟周期,后续的表达式也成立。
      • sequence可以在module、interface、program、clocking块和package中声明。
      • sequence也可以提供形式参数,用来提高复用性。

    并发断言的理解

    并发断言在每个时钟周期启动一个新线程

10ns。请求为真,因此线程继续,30ns读取成功

新的评估线程在时间20、30和40开始。请求为false,因此这些线程中的每一个都会在这些时间失败

设计正在发挥作用。那为什么得到3个断言失败?

这个gotcha的修复方法被称为蕴含运算符。

利用蕴含运算符的条件序列

一个序列可以使用蕴含运算符进行条件化

  • 如果条件为true,则对序列进行求值

  • 如果条件为false,则不计算序列(不在乎)

  • 蕴含(implication)是目前讨论到的允许定义前提条件的一项技术。例如,要对一个指定的序列进行检验,必须某个前提条件为真。

|-> 重叠蕴含:序列求值立即开始

|=>非重叠蕴含:序列评估在下一个时钟开始

|=>|-> ##1 相同。

蕴含相关的术语

蕴含(implication)操作符用来表示,如果property中左边的先行算子(antecedent)成立,那么property右边的后续算子(consequent)才会被计算。如果先行算子不成功,那么整个属性就默认得被认为成功,这叫做“空成功”(vacuous success)。蕴含结构只能用在属性定义中,不能在序列中使用

其他特性

timing Windows:

  • property p;
        @(posedge clk) req |-> ##[1:3] ack;
    endproperty
    a: assert property(p);
    
  • 注:表示req为高的上升沿后,ack需要在1-3个周期内置高。

  • 如果##[1:3] 被替换为 ##[1:] 则表示最大仿真时间

repetition 重复操作:

  • property p;
        @(posedge clk) req |-> ##1 ack ##1 ack ##1 ack;
    endproperty
    a: assert property(p);
    
  • 表示req为高的上升沿后,ack需要保持三个周期的高。当然也可以用下面的方法:(|-> ##1 当然 也能替换为 |=>)

  • property p;
        @(posedge clk)  |-> ##1 ack[3:3];
    endproperty
    a: assert property(p);
    

go to repetition 跟随重复

  • property p;
        @(posedge clk) mem_en |-> ##1 req[->3] ##1 ack;
    endproperty
    a: assert property(p);
    
    • 其中 ##1 req[->3] 表示在rmem_en为高的上升沿之后,经过一个时钟周期,req在接下来的有三个上升沿为高,而且不需要连续。但必须要保证 :在##1 ack 发生之前的上升沿 req是刚好完成最后一次匹配。

Nonconsecutive repetition 非连续重复

  • 跟上述类似,改为:req[*3],就是非连续重复,区别是,不要求req最后一次匹配发生在ack之前。也就是req完成三次匹配之后,可以等若干周期后发生。

throughout

  • vs 蕴含。蕴含允许定义前提条件的一项技术,eg:对某一个序列进行检验,必须某个前提条件为真。

  • 遇到这种情形:要求在检验序列整个过程中,某个条件是否必须一直为真。而蕴含只能在时钟沿检验前提条件一次,然后就检验后续算子部分。不能检测先行算子是否一直保持为真。

  • 因此,引入throughout运算符:保证某些条件在整个序列验证过程中一直为真。

  • (experssion)  throughout (sequence definition)
    
  • 	property p31;
     
            @(posedge clk) $rose(rdy) |->(rdy) throughout (##1 ( mem_en && req ) ##1 ( ack[->3] ) ##1 ( !req && !mem_en ) );
     
      endproperty
     
    a31: assert property(p31);
    
  • 在rdy 上升沿开始检验,在信号mem_en 和 req 上升沿和下降沿之间,ack 应该是连续或者间断地出现3次高电平。在此过程中 start 一致保持为高电平。

within

  • within 关键字通常是与时序属性一起使用。指定一个时间窗口,在这个时间窗口某个条件必须发生。

  • property p;
        @(posedge clk) req |-> ##[5:5] (req within 5 ns);
    endproperty
    
    
    • 表示在5 个时间周期内,req必须为高电平。

    • 此外 req within 5 ns是个嵌套序列。

    • property p;
          @(posedge clk) req |-> (ack within 3) throughout 3;
      endproperty
      
      
      • 表示 req为高电平后,ack必须在接下来三个周期保持为高电平。此例属于连续性要求。

    within常用于一下场景:

    1. 时序关系:在一个序列中描述的事件必须在另一个序列中定义的时间窗口内发生。

    2. 超时条件:描述一个事件必须在一定时间内发生,否则会触发超时条件。

    3. 连续性要求:描述一个事件必须在另一个事件发生后的一定时间内连续发生。

      • eg:

      • property req_ack_property;
            @(posedge clk) req |-> ##1 ack ##1 (ack within 3) |-> ##1 begin
                uvm_error("Timeout", $sformatf("Timeout: ack signal did not meet timing requirements"));
                // $error("Timeout: ack signal did not meet timing requirements");
            end
        endproperty
        
        assert property (req_ack_property);
        

值变化函数(Value Change Functions)

  • 在数字电路设计和验证中,这些函数通常用于检测信号值的变化,并执行相应的操作或逻辑

  • 这些函数可以帮助验证工程师监视信号的变化,捕获特定的事件,并对设计进行详细的分析和调试。

    • cycle_definition是可选的,很少需要(请参阅下面的注释);lt指定用于对表达式进行采样的时钟(例如:$rose(ack,@posedge master_clk)
  • $past
    • $past(n,expression) // 表示n个时钟周期前的值

    • 提供信号在之前周期的值。

    • 一般用于时序性质。以便在当前时钟周期中访问之前时钟周期的信号值。

      时序性质 注:

      1. 在硬件设计和验证中,时序性质(temporal properties)通常用于描述信号之间的时序关系和事件发生的顺序。
      2. 时序性质是一种形式化的描述,用于规范和验证设计中的时序行为。
      3. 时序性质可以帮助验证工程师确保设计在特定的时钟周期内按照预期的方式运行,并满足特定的时序要求。
      4. 包含内容:
        • 事件发生的顺序:描述事件之间的发生顺序,例如在信号 A 发生后,信号 B 必须在下一个时钟周期内发生。
        • 时钟周期关系:描述信号在不同时钟周期内的行为,例如在时钟的第三个周期内,某个信号必须保持为高电平。
        • 时序约束:描述信号之间的时间关系,例如在一个特定时间窗口内,某个事件必须发生。
      5. 时序性质通常用于形式化验证中。例如在使用属性规约语言(Property Specification Language,PSL)或 SystemVerilog Assertions (SVA) 中描述设计的行为。
      6. 通过定义和验证时序性质,验证工程师可以确保设计在不同的时钟周期内满足特定的时序要求,从而提高设计的正确性和可靠性。
posted @ 2024-02-26 18:57  LeslieQ  阅读(2)  评论(0编辑  收藏  举报