假设我们有一个协议,它说明了以下内容。一旦主机设置req
为fill
,从机将通过以下方式发出 4 次传输信号rsp
:
整个事务的 SVA 序列将是(假设从设备可以在idle
周期之间插入trans
周期):
req == fill ##1 (trans [->1]) [*4];
现在,假设允许 master 流水线请求。这意味着下一个fill
可以在 4trans
个周期完成之前开始:
上面的 SVA 序列无济于事,因为第二次fill
它将错误地匹配 4trans
个周期,使最后一个trans
“浮动”。只有在匹配前一个循环之后,它才需要开始匹配trans
循环fill
。
该序列需要在单个评估中不可用的全局信息。基本上它需要知道它的另一个实例正在运行。我能想到的唯一方法是使用一些 RTL 支持代码:
int num_trans_seen;
bit trans_ongoing;
bit trans_done;
bit trans_queued;
always @(posedge clk or negedge rst_n)
if (!rst_n) begin
num_trans_seen;
trans_ongoing <= 0;
trans_done <= 0;
trans_queued <= 0;
end
else begin
if (trans_ongoing)
if (num_trans_seen == 3 && req == trans) begin
trans_done <= 1;
if (req == fill || trans_queued)
trans_queued <= 0;
else
trans_ongoing <= 0;
num_trans_seen == 0;
end
else
if (trans_queued) begin
trans_queued <= 0;
trans_ongoing <= 1;
end
if (trans_done)
trans_done <= 0;
end
trans_ongoing
上面的代码应该在事务正在进行时提高该位,并在发送最后一个 atrans_done
时在时钟周期中脉冲。(我说应该是因为我没有测试它,但这不是重点。让我们假设它有效。)trans
fill
有了这样的东西,可以将序列重写为:
req == fill ##0 (trans_ongoing ##0 trans_done [->1]) [*0:1]
##1 (trans [->1]) [*4];
这应该可行,但我对我需要支持代码这一事实并不特别兴奋。其中有很多冗余,因为我基本上重新描述了事务是什么以及流水线如何工作的大部分内容。它也不那么容易重复使用。Asequence
可以放在一个包中并导入到其他地方。支持代码只能放置在某些模块中并重复使用,但它是一个与存储序列的包不同的逻辑实体。
这里的问题是:有什么方法可以编写序列的流水线版本,同时避免需要支持代码?