我发现的所有#0
相关代码示例都与程序代码(begin
- end
中的IE代码)有关。连续分配和原始实例化怎么样? IEEE 1364& IEEE 1800(分别是Verilog和SystemVerilog)只给出了我能找到的一行描述(在部分名称下引用所有版本的IEEE 1364" 分层事件队列") :
显式零延迟(
#0
)要求暂停进程并将其添加为当前时间的非活动事件,以便在当前时间的下一个模拟周期中恢复进程。
我阅读了文档,并与早在IEEE Std 1364-1995之前与Verilog合作的一些工程师进行了交谈。总之,非活动区域是使触发器与Verilog的不确定处理顺序同步的失败解决方案。后来,Verilog创建了非阻塞分配(<=
)并解决了与不确定顺序的同步问题。非活动区域留在调度程序中,不会破坏遗留代码和一些不起眼的角落情况。现代指南说避免使用#0
因为它会产生竞争条件并可能妨碍模拟性能。性能影响是对小型设计的关注。我使用混合RTL到晶体管级模块运行巨大的设计。因此,即使是小的性能提升,也不需要调试胭脂竞赛条件就可以节省时间。
我已经在大规模设计中运行测试用例删除/添加#0
到Verilog原语。有些模拟器有其他人没有的显着变化。在LRM之后很难分辨谁做得更好或者有更聪明的优化器。
添加per-compile脚本以删除#0
的硬编码形式,这很容易。挑战在于参数化延迟。我是否真的需要创建生成块以避免非活动区域?感觉它会带来更多的问题而不是解决:
generate
if ( RISE > 0 || FALL > 0)
tranif1 #(RISE,FALL) ipassgate ( D, S, G );
else
tranif1 ipassgate ( D, S, G );
if ( RISE > 0 || FALL > 0 || DECAY > 0)
cmos #(RISE,FALL,DECAY) i1 ( out, in, NG, PG );
else
cmos i1 ( out, in, NG, PG );
if (DELAY > 0)
assign #(DELAY) io = drive ? data : 'z;
else
assign io = drive ? data : 'z;
endgenerate
Verilog原语和连续分配从一开始就与Verilog一起使用。我认为参数化延迟比无效区域长。我还没有找到有关这些条件的推荐或解释的任何文档。我的Verilog / SystemVerilog大师的本地网络都不确定它应该在哪个区域运行。是否有一个我们都忽略的细节或者它是语言中的灰色区域?如果是灰色区域,我该如何确定植入方式?
接受的答案应包括对任何版本的IEEE1364或IEEE1800的引用。或者至少是一种做概念验证测试的方法。
答案 0 :(得分:4)
这很简单。部分 28.16 1800-2012 LRM的门和净延迟以及1364-2005 LRM的 7.14门和净延迟部分都说
对于门和网络,默认延迟在没有延迟时应为零 给出了规范。 这意味着
gateName instanceName (pins);
相当于写作
gateName #0 instanceName (pins);
我不确定您引用的文字来自哪里,但是1800-2012 LRM的 4.4.2.3非活动事件区部分说
如果在活动区域集中执行事件,则显式为#0 延迟控制要求暂停进程并执行事件 预定进入当前时隙的非活动区域 该过程可以在下一个非活动迭代中恢复。
关键文本是delay control
,这是一个程序结构。因此#0作为非活动事件仅适用于程序语句。
程序#0
的问题在于它们会移动竞争条件,但它们并没有消除它们。有时您必须添加多个序列#0以远离竞赛条件,但您并不总是知道多少,因为另一段代码也添加了#0。只需看看UVM代码;它充斥着凌乱的#0,因为他们没有花时间正确编码。