always触发的具体时机
本文主要探究always触发的具体时机。
问题背景
首先查看下面代码,是一段同步时序下使用KEY控制LED的简单代码:
1 | module flip_flop( |
这部分代码中,使用到了异步复位,rst_n出现下降沿,在always语句块中判断rst_n电平,如果是低电平则进行复位。
一个猜想就产生了:进入always语句块时的时刻,是触发信号已经稳定下来的时刻,而不是跳变过程中的中间态。
此时观察敏感信号clk,根据猜想推测:在clk的上升沿时触发,clk稳定下来为高电平的时刻开始执行always语句块中的内容。如果key信号和clk完全同步变化,则led_out的输出永远为高电平,否则为低电平。
设计实验
根据猜想设计如下代码:
1 | module always_test( |
对应tb文件:
1 | module tb_always_test( |
显然,如果猜想正确,a电平输出将保持高电平。
仿真验证
运行仿真,a信号果然是高电平,证明猜想正确。
拓展
野火FPGA曾说:计算赋值号右手边的信号时,所有的变量值均是触发沿到来前的值,更新的赋值号左手边的信号作为触发沿后的值,并且保持到下一个触发沿到来时候,等待更新。
这句话的前半句如果仔细考虑,会感觉有点反因果:先计算,后触发计算。
真实情况是当clk信号触发下降沿时,此时clk信号已经是高电平,其他寄存器并未发生变化。而后执行被clk信号触发而驱动的语句块,第一步进行右边信号的计算,但此时参与计算的寄存器的值均未被更新;第二步左边信号开始更新赋值,此时寄存器的值被更新。
考虑到从clk拉到高电平稳定到第一个步骤时间极短,画图时这一误差并未画出,视觉显示为重叠在一起,故而看作是下降沿之前的值;同理第二个步骤,看作为下降沿之后的值。