Verilog 在递归属性中使用队列

Verilog 在递归属性中使用队列,verilog,system-verilog,verification,assertions,system-verilog-assertions,Verilog,System Verilog,Verification,Assertions,System Verilog Assertions,我有一些来自1位串行端口的数据,这些数据是可变长度字节的倍数,例如: byte expected_1 [$] = {8'hBA, 8'hDD, 8'hC0, 8'hDE}; byte expected_2 [$] = {8'h01, 8'h23, 8'h45, 8'h67, 8'h89, 8'hAB, 8'hCD, 8'hEF}; 在每个正时钟边缘,发送一位。我需要测试成百上千个序列(将来可能是上千个),所以我想用系统verilog中的断言自动化这个过程。新的2012标准允许将队列传递给属

我有一些来自1位串行端口的数据,这些数据是可变长度字节的倍数,例如:

byte expected_1 [$] = {8'hBA, 8'hDD, 8'hC0, 8'hDE};
byte expected_2 [$] = {8'h01, 8'h23, 8'h45, 8'h67, 8'h89, 8'hAB, 8'hCD, 8'hEF};  
在每个正时钟边缘,发送一位。我需要测试成百上千个序列(将来可能是上千个),所以我想用系统verilog中的断言自动化这个过程。新的2012标准允许将队列传递给属性,但是可以通过递归属性发送队列吗?我收到了一些关于分层参考的错误

这就是我目前所拥有的(在@Greg的帮助下):

在我的测试台中调用断言应该很容易:

A1 : `ez_assert(expected_1);
错误消息如下所示:

1) passing hierarchical ref to be used in another hierarchical ref is not supported 
2) Illegal SVA property in RHS of'##' expression 
3) Local variable queue_size referenced in expression before getting initialized

我对断言长可变长度序列的其他想法持开放态度。

尝试与
seq\u serial
相同的策略:

sequence seq_queue_pattern(bit en, logic data, byte expt_queue [$]);
    int qidx = 0;
    ( !en throughout (seq_serial(data,expt_queue[qidx]), qidx++)[*] )
    ##1 (qidx==expt_queue.size);
endsequence : seq_queue_pattern

asrt_expected_1 : assert property ( $fell(en) |-> seq_queue_pattern(en,data,expected_1));
asrt_expected_2 : assert property ( $fell(en) |-> seq_queue_pattern(en,data,expected_2));
如果en高或
seq_serial
链与预期不匹配,则此断言将失败。不要认为亲子关系位置很重要:

  • en
    在最终
    seq_serial
    完成后不在乎一个时钟:
    • (!en-through(seq_-serial(data,expt_-queue[qidx]),qidx++[*]))#1(qidx==expt_-queue.size)
  • en
    在最终
    seq_serial
    完成或失败后必须低一个时钟,之后不必在意
    • !en贯穿((序列(数据,导出队列[qidx]),qidx++)[*]##1
      (qidx==expt_queue.size))
  • en
    必须在最终
    seq_serial
    完成后低一个时钟,之后无需在意
    • !en贯穿((序列(数据,导出队列[qidx]),qidx++)[*]##1
      (qidx==expt_queue.size))##1(qidx==expt_queue.size)
序列和属性中的队列是新的,可能还没有得到所有模拟器的完全支持。要解决此限制,请使用参数化宏为每个预期队列流创建序列:

`define asrt_qpat(en,monitor, expt_queue) \
    sequence seq_queue_pattern__``expt_queue (bit en, logic data); \
        int qidx = 0; \
        (!en throughout (seq_serial(data,expt_queue[qidx]), qidx++)[*]) \
        ##1 (qidx==expt_queue.size); \
    endsequence : seq_queue_pattern__``expt_queue \
    \
    asrt_``expt_queue : assert property( @(posedge clk) \
        $fell(en) |=> seq_queue_pattern__``expt_queue (en,monitor) ) \
    else $error("Bad Sequence @ time: %t. Info: %m", $time);

`asrt_qpat(en,data[0],expected_1)
`asrt_qpat(en,data[1],expected_2)

如果将这些错误信息添加到问题的末尾,则更容易理解。在进入真正的问题之前,需要清除小错误。分配给整个队列需要在花括号前加一个引号(例如,
q[$]='{…};
)。多行宏需要在每行末尾(最后一行除外)使用反斜杠(“\”)。您的模拟器是否确实支持向属性传递队列?我需要更正自己的完整队列分配的单引号。队列显然是例外,因为第7.10节“队列”中有明确的示例,但这是允许的(10.10.3)。结构字面值(5.10)、数组字面值(5.10)、未打包数组(7.4)、动态数组(7.5)和关联数组(7.8)使用
{
进行完整赋值。我已经启动并运行了它,但使用了不同的路径。我最后不得不使用fork join并给出预期的字节数。(关于无限范围的内容)如果有机会,我会尝试一下你的方法。谢谢你的回答。我很想看看你的方法。fork-join有什么帮助?fork-join最终没有帮助。你的代码几乎可以工作,但偏移量是1字节(断言检查延迟了1字节)你是说晚了一点吗?如果是这样的话,请将
|=>
更改为
|->
。抱歉,断言在正确的时间开始,但在1字节后失败。可能是
(seq_ser(..),qidx++)[*]#1(qidx==expt_queue.size)
消息说在失败时qidx=0。我从未见过
[*]
本身..这是如何工作的?
`define asrt_qpat(en,monitor, expt_queue) \
    sequence seq_queue_pattern__``expt_queue (bit en, logic data); \
        int qidx = 0; \
        (!en throughout (seq_serial(data,expt_queue[qidx]), qidx++)[*]) \
        ##1 (qidx==expt_queue.size); \
    endsequence : seq_queue_pattern__``expt_queue \
    \
    asrt_``expt_queue : assert property( @(posedge clk) \
        $fell(en) |=> seq_queue_pattern__``expt_queue (en,monitor) ) \
    else $error("Bad Sequence @ time: %t. Info: %m", $time);

`asrt_qpat(en,data[0],expected_1)
`asrt_qpat(en,data[1],expected_2)