【问题标题】:Assert statement in VerilogVerilog 中的断言语句
【发布时间】:2012-12-16 19:34:58
【问题描述】:

我是 Verilog 的新手,请耐心等待。

我想知道 Verilog 中是否有断言语句。在我的测试平台中,我希望能够断言模块的输出等于某些值。

例如,

mymodule m(in, out);
assert(out == 1'b1);

谷歌搜索给了我一个few links,但它们要么太复杂,要么似乎不是我想要的。

【问题讨论】:

    标签: assert verilog


    【解决方案1】:

    有一个名为OVL 的断言开源库。然而,它相当沉重。我从那里得到的一个技巧是创建一个模块来进行断言。

    module assert(input clk, input test);
        always @(posedge clk)
        begin
            if (test !== 1)
            begin
                $display("ASSERTION FAILED in %m");
                $finish;
            end
        end
    endmodule
    

    现在,任何时候你想检查一个信号,你所要做的就是在你的模块中实例化一个断言,就像这样:

    module my_cool_module(input clk, ...);
    
         ...
    
         assert a0(.clk(clk), .test(some_signal && some_other_signal));
    
         ...
    
    endmodule
    

    当断言失败时,你会收到这样的消息:

    ASSERTION FAILED in my_cool_module.a0
    

    display 语句中的 %m 将显示违规断言的整个层次结构,当您在较大的项目中有很多这样的断言时,这很方便。

    你可能想知道我为什么要检查时钟的边缘。这很微妙,但很重要。如果上面表达式中的 some_signal 和 some_other_signal 被分配到不同的 always 块中,则表达式可能会在短时间内为 false,具体取决于 Verilog 模拟器调度块的顺序(即使逻辑完全有效)。这会给你一个假阴性。

    上面要注意的另一件事是我使用 !==,如果测试值为 X 或 Z,这将导致断言失败。如果它使用正常的 !=,它可能会在某些情况下默默地给出误报案例。

    【讨论】:

    • 我看不出这如何与从特定时间开始的断言一起工作。
    【解决方案2】:

    将以上内容与宏一起为我工作:

    `define assert(signal, value) \
            if (signal !== value) begin \
                $display("ASSERTION FAILED in %m: signal != value"); \
                $finish; \
            end
    

    然后在我的测试模块中:

    initial begin // assertions
        #32 `assert(q, 16'hF0CB)
    end
    

    以测试失败案例为例:

    ASSERTION FAILED in test_shift_register: q != 16'hF0CB
    

    【讨论】:

      【解决方案3】:

      你可以这样写

      if(!(out==1'b1)) $finish;
      

      【讨论】:

        【解决方案4】:

        如果您的模拟器支持 SystemVerilog 语法,则有一个 assert 关键字可以满足您的需求。

        【讨论】:

          【解决方案5】:

          Verilog 不支持断言。一些工具支持 PSL,它将断言放在 cmets 中,但这是非标准的。您应该考虑使用来自测试台的分层引用,否则您必须将每个断言放在一个会变得混乱的进程中。

          模仿类 C 断言的最简单方法可能是“定义”,因为这将使它们成为全局的。

          `define assert(condition) if(condition) begin $finish(1); end
          

          为了在非程序环境中检查信号,例如您的示例,您需要一个不同的宏来构建条件信号,然后触发该信号的测试事件。

          `define assert_always(condition) generate if(1) begin wire test = condition; always @(test) `assert(condition) end endgenerate
          

          上面的生成将为变量 test 创建一个新范围,因此多个实例应该可以工作。

          程序中更好的方法可能是在单独的文件中创建任务,然后将其包含在任何模块声明中。

          task assert(input condition);
          if(!condition)
            $finish(2);
          endtask
          

          对于非过程上下文,您需要创建一个包含进程和该模块实例的模块。这将需要每个实例的唯一名称,除非您将它放在生成块中。

          【讨论】:

          • 我真的很喜欢这种方法。最好是这样的(可能):`define assert(condition, message) if(condition) begin $diplay(message); $完成(1);结束
          猜你喜欢
          • 2014-09-13
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-11-16
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多