Home Articles

使用System-Verilog进行串行测试和断言

Asked
Viewed 1818 times
3

我有一个verilog模块的串行输出,我想使用system-verilog来测试testbench .

输出被称为'SO'将输出类似8'hC6的东西,给出正确的串行输入'SI',其值为8'h9A .

是否有一种简单的方法来编码/解码串行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

但显然这不起作用 . 任何建议或例子都非常受欢迎 . 提前致谢 .

2 Answers

  • 4

    您通常不使用断言来描述对数据项的检查,而是使用控制信号 . 在这种情况下你需要的是将你的整个输入流收集到一个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
    

    希望它能给你一个想法 .

  • 3

    尝试一个序列并参考IEEE Std 1800-2012 section 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 section 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
    

Related