任何信号在FPGA器件内部通过连线和逻辑单元时,都有一定的延时,正是我们通常所说的走线延时和门延时。延时的大小与连线的长短和逻辑单元的数目有关,同时还受器件本身的制造工艺、工作电压、温度等条件的影响。信号的高低电平转换也需要一定的上升或下降时间。由于存在这些因素的影响,多个信号的电平值发生变化时,在信号变化的瞬间,组合逻辑的输出并非同时,而是有先有后,因此往往会出现一些不正确的信号,例如一些很小的脉冲尖峰信号,我们称之为“毛刺”。如果一个组合逻辑电路中有毛刺出现,就说明该电路存在“冒险”。
下面我们可以列举一个简单例子来看看毛刺现象是如何产生和消除的。如图1所示,每个门延时的时间是2ns,而不同的走线延时略有不同。
图1组合逻辑路径的延时标记
在这个实例模型中,我们不难计算出输入信号a、b、c、d、e从输入到输出信号y所经过的延时。通过计算,可以得到a、b、c信号到达输出y的延时是12ns,d到达输出y的延时是9ns,而e到达输出y的延时是7ns。从这些传输延时中,我们可以推断出,在第一个输入信号到达输出端y之前,输出y将保持原来的结果;而在最后一个输入信号到达输出端之后,输出y将获得我们期望的新的结果。从本实例来看,7ns之前输出y保持原结果,12ns之后输出y获得新的结果。那么这里就存在一个问题,在7ns和12ns之间的这5ns时间内,输入y将会是什么状态呢?
如图2所示,这里列举一种出现毛刺的情况。假设在0ns以前,输入信号a、b、c、d、e取值均为0,此时输出y=1;在0ns时,b、c、d由0变化为1,输出y=1。在理想情况下,输出y应该一直保持1不变。但从我们的延时模型来看,实际上在9ns到12ns期间,输出y有短暂的低脉冲出现,这不是电路应该的状态,它也就是这个组合逻辑的毛刺。
图2逻辑延时波形
既然我们的多个输入信号的变化前后取值都保持高电平,那么这个低脉冲的毛刺其实不是我们希望看到的,也很可能在后续电路中这个毛刺导致后续的采集出现错误,甚至使得一些功能被误触发。
好了,言归正传,要消除这个毛刺,通常有两个办法,一个办法是硬办法,如果在y信号上并联一个电容,便可轻松的将这类脉冲宽度很小的干扰滤除。但是,我们现在是在FPGA器件内部,还真没有这样的条件和可能性这么处理,那么只能放弃这种方案。另一种办法其实也就是引入时序逻辑,用寄存器多输出信号打一拍,这其实也是时序逻辑明显优于组合逻辑的特性。
如图3所示,在原有组合逻辑的基础上,我们添加了一个寄存器用于锁存最终的输出信号y。
图3寄存器锁存组合逻辑输出
如图4所示,在引入了寄存器后,新的最终的输出yreg不再随意的改变,而是在每个时钟clk的上升沿锁存当前的输出值。
图4寄存器锁存波形
引入时序逻辑后,并不是说完全就不会产生错误的数据采集或锁存。在时序逻辑中,我们只要遵循一定的规则就可以避免很多问题,如保证时钟clk有效沿前后的数据建立时间和保持时间内待采集的数据是稳定的。