关于锁存器问题的讨论
很多同学提问到锁存器的相关问题,说明大家对这方面知识还不是很了解,今天我们就来探讨一下。
上图是两个没有else的代码,其等效于下图的代码。
也就是说,当if条件里面没有写else时,默认是表示“保持不变”的意思。
接下来,我们来讨论一下,硬件中是如何实现“保持不变”的。
左边是时序时序逻辑的代码,右边是该代码所对应的硬件电路。特别注意图中红色的那个线,那个就是保持不变的“反馈”。由图中可以看出,当时钟上升沿的时候,当选择器的结果赋值给信号b;非上升沿的时候,b一直保持不变,因此红色线在此期间也是保持不变的。当a为0的时候,选择器选择当前b的结果,然后在下一个时钟上升沿赋给信号b。
由引可见,实现“保持不变”的关键在于D寄存器。
众所周知,组合逻辑代码是没有D寄存器的,那么它又是如何实现保持不变呢?这个就会用到锁存器了。
上图是组合逻辑代码,及其对应电路。为了让信号b保持不变,就要用到一个叫“锁存器”的器件。当a为1时,b就会等于1;当a为0时,b会保持不变。
关于锁存器的危害,可以参考MDY的“大串讲”视频,总之我们知道锁存器是不好东西的,尽量不要有锁存器,也就是说组合逻辑里,要让“if else”条件补全。
常见问题
问1:是不是所有的代码,if else都需要补全呢?
答:如前面所讨论的,对于时序逻辑可以由D寄存器实现“保持不变”,所以时序逻辑是不需要补全的,只有组合逻辑才需要。
问2:是不是只要组合逻辑的if else补充了,就不会生成锁存器了?
答:不一定。这里的关键在于“保持不变”,千万不要从“代码层次”来理解,而应该从“功能的层次”来理解,要找准到底有没有“保持不变”。例如,下面的代码,虽然else写上去了,但写不写else都是让b保持不变。所以这仍然会综合出锁存器。
问3:是不是组合逻辑不写else,就一定会生成锁存器?
答:不一定。这里仍然要从是否包括“保持不变”这个功能来分析。如下面代码,假设a是1比特信号,其值只有0和1。那么已经涵盖了所有情况,再不会有其他情况,所以不会出现保持不变的情形,这个时候也不会生成锁存器。
问4:case不写default,是否会生成锁存器?
答:case不写default,相当于if 条件不写else,其情况分析跟前面3个问题一样,关键在于有没有“保持不变”的功能。
问5:功能上,我一定要实现“组合逻辑的保持不变”功能,该如何做?
答:通常来说,所谓“组合逻辑的保持不变”,是指“该段代码”是组合逻辑写的,但需要与前一个时钟的值保持不变,如下代码,这种需求是很正常的。
解决方法,仍然是靠D触发器来实现“保持不变”的功能。只不过是把一个时序逻辑的ALWAYS写法,换成组合逻辑+时钟逻辑的写法而已,代码如下。
问6:问题5的扩展,我就是要实现组合逻辑的保持,并且小于一个时钟周期的。
答:不正常需求,FPGA不会这么设计的。