3

我有一个 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

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

4

2 回答 2

5

尝试一个序列并参考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关键字,并允许您传递常量(例如,)并仍然允许您传递网络引用。有关更多信息,请参阅IEEE Std 1800-2012第 16.8.2 节(序列声明中的局部变量形式参数)。expected8'h9A8'hC6

这是一个简单的测试平台来证明这个断言。我正在开车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
于 2013-06-11T17:30:26.743 回答
3

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

希望它能给你一个想法。

于 2013-06-11T15:13:12.333 回答