Testing 使用System Verilog进行串行测试和断言
我有一个verilog模块的串行输出,我想使用系统verilog来测试它 如果串行输入'SI'值为8'h9A,则称为'SO'的输出将输出类似于8'hC6的内容 是否有一种简单的方法来编码/解码串行IO,而不必明确描述每个信号 例如: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
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),并将变量传递给序列(exseq_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