Clifford E. Cummings 论文详解(四)Correct Methods For Adding Delays To Verilog Behavioral Models

摘要

设计工程师经常构建带有行为延迟的 Verilog 模型。大多数硬件描述语言允许各种各样的延迟编码风格,但很少有允许的编码风格真正模拟实际的硬件延迟。一些最常见的延迟建模风格对真实硬件的表现非常糟糕。本文检查了常用的延迟建模样式,并指出哪些样式的行为像真实的硬件,哪些不。

1.0 前言

用于组合逻辑建模的最常见的行为 Verilog 编码风格之一是将延迟放置在 always 块中的阻塞赋值的左侧。这种编码风格是有缺陷的,因为它可以很容易地产生错误的输出值,或者可以在比模型规范允许的更短的时间内将输入传播到输出。

本文详细介绍了使用具有延迟的连续赋值的延迟建模风格,以及使用阻塞和非阻塞赋值的过程赋值,赋值操作符两边都有延迟。

为了帮助理解延迟建模,下一节还简要介绍了固有延迟和传输延迟,以及 Verilog 命令行开关,这些开关通常用于模拟既不是完全固有延迟模型也不是完全传输延迟模型的模型。

2.0 固有和传输延迟建模

固有延迟模型只有在输入信号保持不变(稳定)的时间等于或大于模型的传播延迟后,才会将信号传播到输出端。如果两个输入更改之间的时间短于过程赋值延迟、连续赋值延迟或门延迟,则先前计划但未实现的输出事件将被新计划的输出事件替换。

传输延迟模型在任何输入信号改变后将所有信号传播到输出。在传输延迟模型中,计划的输出值会排队执行。

拒绝和错误延迟模型传播所有大于错误设置的信号,传播介于拒绝和错误设置之间的信号的未知值,并且不传播低于拒绝设置的信号。

对于大多数 Verilog 仿真器,拒绝和错误设置指定为传播延迟的百分比,以 10% 为倍数。

使用拒绝/错误开关的纯固有延迟示例。添加 Verilog 命令行选项:

+pulse_r/100 +pulse_e/100
拒绝所有小于 100% 传播延迟的脉冲。

使用拒绝/错误开关的纯传输延迟示例。添加 Verilog 命令行选项:

+pulse_r/0 +pulse_e/0
通过所有大于 0% 传播延迟的脉冲。

使用拒绝/错误开关的半现实延迟示例。添加 Verilog 命令行选项:

+pulse_r/30 +pulse_e/70
拒绝小于 30% 的脉冲,传播 30-70% 之间的未知脉冲,并通过所有大于 70% 传播延迟的脉冲。

3.0 阻塞赋值延时模型

在阻塞赋值(如图 1 所示)的左侧(LHS)或右侧(RHS)添加延迟以建模组合逻辑,这在新的甚至有经验的 Verilog 用户中非常常见,但是这种做法是有缺陷的。
在这里插入图片描述
对于图 2 中所示的 adder_t1 示例,输出应在输入改变后 12ns 更新。如果 a 输入在 15 时刻发生变化,如图 3 所示,那么如果 a、b 和 ci 输入在接下来的 9ns 内都发生变化,则输出将使用 a、b 和 ci 的最新值进行更新。这种建模风格只允许 ci 输入在 3ns 后将一个值传播到求和和进位输出,而不是所需的 12ns 传播延迟。
在这里插入图片描述在这里插入图片描述
将延迟添加到任何阻塞赋值序列的左侧(LHS)来建模组合逻辑也是有缺陷的。

图 4 中显示的 adder_t7a 示例将延迟放在第一个阻塞赋值上,而不将延迟放在第二个赋值上。这将具有与 adder_t1 示例相同的有缺陷的行为。

adder_t7b 示例也在图 4 中显示,它将延迟放在第二个阻塞赋值上,而不将延迟放在第一个阻塞赋值上。该模型将在第一次输入变化时对输入进行采样,并将输出分配到临时位置,直到完成指定的阻塞延迟。然后将使用不再有效的旧临时输出值写入输出。在 12ns 延迟期内的其他输入变化将不会被计算,这意味着旧的错误值将保留在输出上,直到更多的输入变化发生。

这些加法器不模拟任何已知的硬件。

建模指南:不要在阻塞赋值的 LHS 上放置延迟来建模组合逻辑。这是一种糟糕的编码风格。

测试平台指南:在测试平台阻塞赋值的 LHS 上放置延迟是合理的,因为延迟只是用于时空顺序输入激励事件。
在这里插入图片描述

3.1 RHS 阻塞延时

将延迟添加到阻塞的右侧(RHS)以建模组合逻辑也是有缺陷的。

对于图 5 中所示的 adder_t6 示例,输出应该在输入更改后 12ns 更新。如果 a 输入在时间 15 改变,RHS 输入值将被采样,输出将用采样值更新,而在接下来的 12ns 内所有其他 a, b 和 ci 输入的变化将不被计算。这意味着旧的错误值将保留在输出中,直到出现更多的输入更改。
在这里插入图片描述
当在赋值语句的 RHS 上放置延迟时,多个阻塞赋值也存在同样的问题。图 6 中显示的 adder_t11a 和 adder_t11b 示例演示了与 adder_t6 示例相同的有缺陷的行为。

在阻塞赋值的 RHS 上具有延迟的加法器示例中,没有一个表现得像任何已知的硬件。

建模指南:不要在阻塞赋值的 RHS 上放置延迟来建模组合逻辑。这是一种糟糕的编码风格。

测试平台指南:不要在测试平台中阻塞赋值的 RHS 上放置延迟。

总体指南:在任何阻塞赋值的 RHS 上放置延迟既令人困惑又是一种糟糕的编码风格。应该避免这种 Verilog 编码实践。
在这里插入图片描述

4.0 非阻塞赋值延时模型

在这里插入图片描述
将延迟添加到非阻塞赋值(如图 7 所示)的左侧(LHS)以建模组合逻辑是有缺陷的。

图 8 所示的 adder_t2 示例(非阻塞赋值)中存在与图 2 所示的 adder_t1 示例(阻塞赋值)中存在的问题相同。如果 a 输入在 15 时刻发生变化,那么如果 a、b 和 ci 输入在接下来的 9ns 内都发生变化,则输出将更新为 a、b 和 ci 的最新值。这种建模风格允许 ci 输入仅在 3ns 而不是所需的 12ns 传播延迟后将值传播到求和和进位输出。
在这里插入图片描述
同样可以证明,将延迟添加到任何非阻塞赋值序列的左侧(LHS)来建模组合逻辑也是有缺陷的。

用 LHS 非阻塞赋值建模的加法器不模拟任何已知的硬件。

建模指南:不要在非阻塞赋值的 LHS 上放置延迟来建模组合逻辑。这是一种糟糕的编码风格。

测试平台指南:非阻塞赋值比阻塞赋值的仿真效率低;因此,一般来说,不鼓励在建模或测试平台生成的非阻塞赋值的 LHS 上放置延迟。

4.1 RHS 非阻塞延时

将延迟添加到非阻塞赋值的右侧(RHS)(如图 9 所示)将准确地为具有传输延迟的组合逻辑建模。

在图 9 所示的 adder_t3 示例中,如果 a 输入在时间 15 发生变化,如图 10 所示,那么将计算所有输入,新的输出值将排队等待 12 秒后被分配。在输出排队(为将来的赋值安排)但尚未赋值之后,将立即设置 always 块,以便在下一个输入事件上触发。这意味着所有输入事件将在 12ns 延迟后将新值排队放置在输出上。这种编码风格为具有传输延迟的组合逻辑建模。
在这里插入图片描述
推荐应用:使用这种编码风格来模拟行为延迟线逻辑。

建模指南:只有在尝试为传输输出传播行为建模时,才在非阻塞赋值的 RHS上 放置延迟。这种编码风格将准确地模拟纯传输延迟的延迟线和组合逻辑;然而,这种编码风格通常会导致仿真速度变慢。

测试平台指南:这种编码风格通常用于测试平台,当激励必须在未来的时钟边缘或在设定的延迟之后进行调度时,而不妨碍在同一 always 块中赋值后续激励事件。
在这里插入图片描述

4.2 多个 RHS 非阻塞延迟

向模型组合逻辑的多个顺序非阻塞赋值的右侧(RHS)添加延迟是有缺陷的,除非所有 RHS 输入标识符都列在敏感度列表中,包括只在 always 块中赋值和使用的中间临时值,如图 11 所示。

对于图 11 中所示的 adder_t9c 和 adder_t9d 示例,非阻塞赋值是并行执行的,并且在 tmp 更新之后,因为 tmp 位于敏感度列表中,always 块将再次被触发,计算 RHS 方程并使用正确的值更新 LHS 方程(在第二次遍历 always 块时)。

建模指南:一般来说,不要在非阻塞分配的 RHS 上放置延迟来建模组合逻辑。这种编码风格可能会令人困惑,并且仿真效率不高。在非阻塞赋值的 RHS 上放置延迟以在时序逻辑上模拟时钟到输出行为是一种常见且有时很有用的做法。
在这里插入图片描述

5.0 连续赋值延迟模型

在这里插入图片描述
将延迟添加到连续赋值(如图 12 所示)中,可以准确地为具有固有延迟的组合逻辑建模,这是一种推荐的编码风格。

对于图 13 中所示的 adder_t4 示例,输出直到最后一次输入变化后 12ns 才会发生变化(所有输入稳定后 12ns)。任何间隔小于 12ns 的输入序列更改都将导致任何未来计划的输出事件(具有相应赋值时间的输出值)被新的输出事件替换。

图 14 显示了在图 13 中所示的 adder_t4 代码上运行仿真的输出波形。第一个 a 输入更改发生在时间 15,这将导致在时间 27 调度一个输出事件,但是 b 输入的更改和 a 输入的另外两个更改分别发生在时间 17、19 和 21,将导致三个新的输出事件被调度。只有最后一个输出事件实际完成,并且在时间 33 赋值输出。

连续赋值不会“排队”输出赋值,它们只会跟踪下一个输出值及其发生的时间;因此,连续赋值是具有固有延迟的组合逻辑的模型。
在这里插入图片描述

5.1 多个连续赋值

类似地,可以通过向连续赋值添加延迟来建模逻辑功能,其输出用于驱动其他具有延迟的连续赋值的输入,如图 15 所示,也可以精确地建模具有固有延迟的组合逻辑。
在这里插入图片描述

5.2 混合无延迟 always 块和连续赋值

在没有延迟的 always 块中建模逻辑功能,然后将 always 块中间值传递给具有延迟的连续赋值,如图 16 所示,将准确地为具有固有延迟的组合逻辑建模。
在这里插入图片描述
对于图 16 所示的 adder_t5 示例,tmp 变量在所有输入事件之后更新。直到 tmp 变量最后一次更改后 12ns,连续赋值输出才会更改。always 块输入更改的任何序列都将导致 tmp 更改,这将导致在连续赋值输出上调度一个新的输出事件。在 tmp 保持 12ns 不变之前,不会更新连续赋值输出。这种编码方式对具有固有延迟的组合逻辑进行建模。

建模指南:使用带有延迟的连续赋值来建模简单的组合逻辑。这种编码方式可以精确地仿真具有固有延迟的组合逻辑。

建模指南:使用没有延迟的 always 块来建模复杂的组合逻辑,这些逻辑更容易使用 Verilog 行为结构(如“case-case -casex”、“if-else”等)来呈现。无延迟 always 块的输出可以驱动到连续赋值中,从而将行为延迟应用于模型。这种编码方式可以精确地仿真具有固有延迟的复杂组合逻辑。

测试平台指南:连续赋值可以在测试平台上的任何地方使用,以将激励值驱动到实例化模型的输入端口和双向端口上。

6.0 总结

在 always 块中的语句中添加的任何延迟都不能准确地模拟实际硬件的行为,因此不应该这样做。唯一的例外是小心地将延迟添加到非阻塞赋值的右侧,这将准确地模拟传输延迟,通常以仿真器性能为代价。

将延迟添加到任何连续赋值序列中,或者在 always 块中建模没有延迟的复杂逻辑,并通过具有延迟的连续赋值驱动 always 块输出,都可以准确地建模固有延迟,并且是建模组合逻辑的推荐编码风格。

参考资料

https://www.researchgate.net/profile/Clifford-Cummings

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值