【问题标题】:Serial Testbenching and assertions with System-Verilog使用 System-Verilog 进行串行测试和断言
【发布时间】:2013-06-11 06:37:29
【问题描述】:

我有一个 Verilog 模块的串行输出,我想使用 system-verilog 进行测试。

如果正确的串行输入 'SI' 的值为 8'h9A,则名为“SO”的输出将输出类似 8'hC6 的内容。

有没有一种简单的方法可以对串行 IO 进行编码/解码,而无需明确描述每个信号?

例如:

assert property @(posedge clk) $rose(EN) |-> ##[1:3] SI ##1 !SI[*2] ##1 SI[*2] ##1 !SI ##1 SI ##1 !SI
                                             ##[1:3] SO[*2] ##1 !SO[*3] ##1 SO[*2] ##1 !SO;

它看起来像一团乱麻,几乎不可读。我很想写

8'h9A ##[1:3] 8'hC6

但显然这不起作用。任何建议或示例都将受到欢迎。提前致谢。

【问题讨论】:

    标签: testing verilog system-verilog verification system-verilog-assertions


    【解决方案1】:

    尝试一个序列并参考IEEE Std 1800-2012 16.10 节(局部变量):

    sequence seq_serial(logic signal, local logic [7:0] expected);
        byte idx = 7;
        (signal == expected[idx], idx--)[*8];
    endsequence : seq_serial
    
    asrt_si0x9A_so0xC6 : assert property ( @(posedge clk)
        $rose(EN) |-> ##[1:3] seq_serial(SI, 8'h9A) ##[1:3] seq_serial(SO, 8'hC6) );
    

    这相当于提供的断言并且更具可读性。

    请注意local 关键字,它将expected 视为变量而不是引用,并允许您传递常量(例如8'h9A8'hC6)并仍然允许您传递网络引用。有关更多信息,请参阅IEEE Std 1800-2012 第 16.8.2 节(序列声明中的局部变量形式参数)。

    这里有一个简单的测试平台来证明这个断言。我正在开车SO,因为我没有真正的 DUT,我想演示通过和失败的场景。

    bit EN, clk;
    logic SI,SO;
    logic [7:0] si_var, so_var;
    initial forever #10ns clk++; // clock generator
    default clocking cb @(posedge clk); output #1ns EN,SI,SO; endclocking : cb
    initial begin : test_vector
        si_var = 8'h9A;
        so_var = 8'hC6;
        ##1 cb.EN <= 1;
        ##($urandom_range(2,0)); // rand delay
        foreach(si_var[i]) ##1 cb.SI <= si_var[i];
        ##($urandom_range(2,0)); // rand delay
        foreach(so_var[i]) ##1 cb.SO <= so_var[i];
        ##1 cb.EN <= 0;
    
        /* Now make the assertion fail */
        so_var = 8'hC7; // make fail
        ##3 cb.EN <= 1;
        ##($urandom_range(2,0)); // rand delay
        foreach(si_var[i]) ##1 cb.SI <= si_var[i];
        ##($urandom_range(2,0)); // rand delay
        foreach(so_var[i]) ##1 cb.SO <= so_var[i];
        ##1 cb.EN <= 0;
    
        #10ns; // little delay before finish
        $finish(2);
    end : test_vector
    

    【讨论】:

    • 正是我想要的。绝妙的答案。非常感谢。
    • 有一点,每次我尝试使用 local 数据类型时,T 都会出错。
    • 也许您的供应商尚未将local 实现为序列帖子。 IEEE Std 1800-2005 没有明确说明任何内容,但在 -2009 和 -2012 中有示例。两种解决方法(在我的模拟器上工作):1)删除local,将值分配给变量(例如si_var和so_var)并将变量传递给序列(例如seq_serial3(SI, si_var) ##[1:3] seq_serial3(SO, so_var))。 2) 删除local,在byte idx=7; 下方添加logic [7:0] sampled = expected;,并将expected[idx]sampled[idx] 交换。
    • 是的.. 没有local 也能完美运行。我知道每个供应商实施的指导方针都略有不同。我很高兴它有效。
    【解决方案2】:

    您通常不使用断言来描述对数据项的检查,而是使用控制信号。在这种情况下,您需要将整个输入流收集到一个 16 位向量中,收集整个输出流并检查您在 SO 线上得到的内容是否与您应该得到的相符(对 SI 上的内容进行一些转换行)。

    我的 SystemVerilog 生锈了,但我将给你一个简单的例子来说明我的意思。请注意,它不可编译。

    // collect input
    always @(posedge clk) begin
      if en == 1 begin
        collect_input();
      end
    end
    
    logic[7:0] si;
    
    task collect_input();
      for i from 0 to 7 begin
        si[i] = SI;  // take care of endianness here, might be si[7-i];
      end
    endtask
    
    
    // collect output
    ...
    
    logic[7:0] so;
    
    ...
    
    collect_output();
      for ...
    
      // after collecting so, check that it's correct
      if so != transform(si) begin
        $error("wrong output data");
      end
    endtask
    

    希望它能给你一个想法。

    【讨论】:

    • 您甚至可以在断言中使用这个概念。 SVA 的秘诀在于,您可以编写普通代码将要检查的内容转换为方便的形式,然后触发断言进行检查。为此,我会使用更灵活的东西。
    猜你喜欢
    • 2019-09-23
    • 1970-01-01
    • 1970-01-01
    • 2017-03-13
    • 2018-10-21
    • 1970-01-01
    • 1970-01-01
    • 2014-09-13
    • 1970-01-01
    相关资源
    最近更新 更多