【发布时间】:2016-08-29 16:18:37
【问题描述】:
假设我们有一个协议,其中包含以下内容。一旦主机将req 设置为fill,从机将通过rsp 发出4 次传输信号:
整个事务的 SVA 序列将是(假设从站可以在 trans 周期之间插入 idle 周期):
req == fill ##1 (trans [->1]) [*4];
现在,假设允许主节点处理请求。这意味着下一个fill 可以在 4 个trans 循环完成之前开始:
上面的 SVA 序列无济于事,因为第二个 fill 将错误地匹配 4 个 trans 循环,而最后一个 trans “浮动”。只有在前一个 fill 的循环匹配后,它才需要开始匹配 trans 循环。
序列需要在单个评估中不可用的全局信息。基本上它需要知道它的另一个实例正在运行。我能想到的唯一方法是使用一些 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 位,并在发送fill 的最后一个trans 时在时钟周期内脉冲trans_done。 (我说应该是因为我没有测试它,但这不是重点。让我们假设它有效。)
有了这样的东西,可以将序列重写为:
req == fill ##0 (trans_ongoing ##0 trans_done [->1]) [*0:1]
##1 (trans [->1]) [*4];
这应该可行,但我对我需要支持代码这一事实并不感到特别兴奋。其中有很多冗余,因为我基本上重新描述了事务是什么以及流水线如何工作的大部分内容。它也不那么容易重复使用。 sequence 可以放在一个包中并导入到其他地方。支持代码只能放在某个模块中并重复使用,但它是一个不同于存储序列的包的逻辑实体。
这里的问题是:有什么方法可以编写序列的流水线版本,同时避免需要支持代码?
【问题讨论】:
-
rsp的idle和trans的区别容易解码吗?
-
我的理解是,如果另一个“填充”在“填充”和 4 个“反式”周期之间到达,那么后面的“填充”将被简单地忽略(在图像中,第二个“填充”将被忽略)。请评论我的理解。
-
@KaranShah 不,第二次填充有 4 个“反式”循环在正在进行的循环完成后开始。
-
@Greg 是的,它们是枚举类型。在一个时钟中您看到 IDLE,在另一个时钟中您看到 TRANS。弄清楚发生了 TRANS 是很容易的部分。将 TRANS 循环映射到适当的 FILL 是困难的部分。
标签: system-verilog system-verilog-assertions