相关阅读
Verilog基础专栏https://blog.csdn.net/weixin_45791458/category_12263729.html?spm=1001.2014.3001.5482
目录
1、连续赋值延时
1.1、赋值内嵌延时
1.2、线网声明延时
1.3、门延迟
2、过程赋值延时
2.1、过程语句前置时序控制
2.2、过程赋值语句内嵌时序控制
连续赋值延迟用于指定=右侧表达式的操作数发生值的变化到左值被更新之间的时间间隔,它们模拟了惯性延迟模型(Inertial Delay Model,IDM),即他们会把短于门级原语(Primitive)或连续赋值语句(Continuous assignment)的传播延迟(Propagation Delay)的脉冲过滤掉,只能传送稳定时间大于等于传播延迟的信号。连续赋值延时可以分为三种:赋值内嵌延迟、线网声明延迟和门延迟。
惯性延迟是指如果右侧操作数在前一个更改有时间传播到左侧之前发生更改,则会采取以下步骤:
通俗来讲就是如果在赋值号右侧的改变因为延迟尚未赋给左侧,此时出现了新的赋值号右侧的改变,如果导致新的计算结果和原来计划的一样,则原定赋值照常进行,否则原赋值将被取消。如果新的计算结果和当前左值一样,则不会发生任何事件,否则会重新根据值计算延迟并在延迟后赋值。
赋值内嵌延时指的是直接在连续赋值语句中说明延迟值,下图是连续赋值语句语法的BNF范式形式,有关BNF范式的内容,可以在Verilog基础专栏的以往文章中找到。
其中可选的[delay3]就描述了赋值内嵌延时,他可以是简单的#加上一个延迟值,也可以是#后()包围的最多三个mintypmax_expression,这三个表达式分别表示上升延迟,下降延迟和关断延迟。
上升延迟是指赋值号右值发生变化后,左值从当前的0,x,z变为即将赋予的1所需的时间
下降延迟是指赋值号右值发生变化后,左值从当前的1,x,z变为即将赋予的0所需的时间。
关断延迟是指赋值号右值发生变化后,左值从当前的0,1,x变为即将赋予的z所需的时间。
另外,如果信号值从0,1,z变为即将赋予的x,延迟值为这三者中最低小的值。
当只有一个表达式时,其表示上升延迟,同时下降延迟和关断延迟也与其相同。
当只有两个表达式时,其表示上升延迟和下降延迟,同时关断延迟也与两者中最小值相同。
值得说明的是mintypmax_expression本身可以由一个或三个表达式构成,当其由一个表达式构成时,代表延迟的最小值、典型值和最大值都指定为这个表达式,当其由三个表达式构成时,代表延迟的最小值、典型值和最大值分别指定为这三个表达式。
显然,上面所说的都是针对标量赋值给标量的情况,那对于矢量赋值,该如何确定是使用上升延迟、下降延迟还是关断延迟呢?
Verilog官方文档对这个的描述十分模糊,我在其他资料中找到了有关于此的描述,如下所示。
线网声明延迟来源于net声明的过程,如下图所示。
其中的[delay3]可选项与上一小节的相同,这里的延迟对所有对此net的连续赋值和以此net为输出的门级原语(primitive)生效。注意到语法定义中有[list_of_net_decl_assignment]可选项,这代表可以在net声明时进行连续赋值,如下图所示。
当net声明中存在连续赋值时,延迟会变成连续赋值的一部分(被解释为赋值内嵌延迟),而不是线网声明延迟。因此会失去上面说明的特性。
线网声明延迟的其他细节与赋值内嵌延迟一致。
门延迟指的是在使用门级原语(primitive)时指定的延时,因为门级原语的输入输出就像是使用了连续赋值语句,所以把它归为此类,下图为门级原语的语法。
可以看到其中有些器件拥有[delay3]可选项,有些器件只有[delay2]可选项,因为有些器件不会出现输出为z的情况,如下图所示的n_input_gatetype和n_output_gatetype的真值表。
门延迟其他的细节与赋值内嵌延迟相同,注意线网声明延迟可以与赋值内嵌延迟或门延迟叠加。
过程赋值延迟顾名思义,是存在于过程语句中的延迟,分为过程语句前置时序控制和过程赋值语句内嵌时序控制两种。过程语句指的是在initial块或always块内的语句,有关于这两个块的相关细节,可以在Verilog基础专栏的以往文章中找到。
过程语句前置时序控制的语法如下图所示。
可以看到在一个statement_or_null前可以有procedural_timing_control_statment,形式为delay_control或event_control,其中delay_control可以是#加简单的延时值,也可以是mintypmax_expression。当控制流遇到procedural_timing_control_statment时,会暂定执行后面的语句,直到相应的延迟时间后或相应的事件发生(一般只有在begin-end块内,procedural_timing_control_statment才能阻塞整个块的执行,因为begin-end保证了上一条语句执行完成后才开始执行下一条语句)。
过程赋值语句内嵌时序控制,是在过程赋值语句内部的,只针对过程赋值语句的特定延时,它们模拟了传输延迟模型(Transport Delay Model, TDM),即它们能传送所有宽度的脉冲,也就是说它们可以传输毛刺(Glitch)。
两种过程赋值语句的语法如下图所示,分别是阻塞赋值和非阻塞赋值。
其中可选的[delay_or_event_control]便是过程赋值语句内嵌时序控制,可以看到它相比于过程语句前置时序控制,增加了repeat语句描述的event_control。
对于阻塞赋值来说,当控制流传到赋值语句时,立刻计算赋值号=右侧的expression,并等待[delay_or_event_control]发生后进行赋值,赋值完成后此语句才结束,这就代表着后面的语句也会受到[delay_or_event_control]的阻塞(如果语句在begin-end块中)。
对于非阻塞赋值来说,当控制流传到赋值语句时,立刻计算赋值号<=右侧的expression,此时控制流可以继续执行下面的语句,就好像是计算完<=右侧的expression后赋值语句就结束了一样,但其实依然需要[delay_or_event_control]发生后进行赋值,只是非阻塞赋值的内嵌时序控制不会阻塞后面的语句。
图源自《IEEE Standard for Verilog® Hardware Description Language 2005》