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

Testing 使用System Verilog进行串行测试和断言,testing,verilog,system-verilog,verification,system-verilog-assertions,Testing,Verilog,System Verilog,Verification,System Verilog Assertions,我有一个verilog模块的串行输出,我想使用系统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

我有一个verilog模块的串行输出,我想使用系统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

但很明显,这是行不通的。任何建议或例子都是非常受欢迎的。提前谢谢

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

希望它能给你一个想法。

尝试一个序列,并参考第16.10节(局部变量):

这相当于所提供的断言,更具可读性

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

这里有一个简单的测试台来证明这个断言。我之所以驾驶
,是因为我没有真正的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
位EN,clk;
逻辑SI,SO;
逻辑[7:0]si_var,so_var;
永久首字母#10ns clk++//时钟发生器
默认时钟cb@(posedge时钟);输出#1ns EN,SI,SO;结束计时:cb
初始开始:测试向量
si_var=8'h9A;
so_var=8'hC6;

##1 cb.EN您甚至可以在断言中使用此概念。SVA的秘密在于,您可以编写普通代码,将要检查的内容转换为方便的形式,然后触发断言进行检查。为此,我会使用更灵活的方法,这正是我想要的。回答得很好。非常感谢。但有一件事,我没有在每次尝试使用
local
数据类型时都出错。也许您的供应商还没有将
local
作为sequence post实现。IEEE标准1800-2005没有明确说明什么,但在-2009年和-2012年有一些例子。两个解决方法(麻烦在我的模拟器上工作):1)删除
local
,将值分配给变量(ex si_var&so_var),并将变量传递给序列(ex
seq_serial3(si,si_var)#[1:3]seq_serial3(so,so_var)
)。2) 将
本地
放在
字节idx=7下面添加<代码>逻辑[7:0]采样=预期,并将
预期的[idx]
采样的[idx]
进行交换。是的。。它在没有
local
的情况下工作得很好。我知道每个供应商执行的准则都有点不同。我很高兴它能起作用。
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