释义
在进行FPGA设计的过程中,经常会在编译程序时发现有一些warning提示生成了一些latch.
Latch,中文译成锁存器,是一种对脉冲电平敏感的存储单元电路,它们可以在特定输入脉冲电平作用下改变状态。锁存,就是把信号暂存以维持某种电平状态。锁存器的最主要作用是缓存,其次完成高速的控制其与慢速的外设的不同步问题,再其次是解决驱动的问题,最后是解决一个 I/O 口既能输出也能输入的问题。在FPGA程序设计过程中,出现latch绝大多数情况是因为if和case语句的不完全描述,导致程序在综合过程中出现了latch的功能行为。
坏处
1)功能仿真结果和后仿不符;
2)出现无法测试的逻辑;
3)逻辑工作不稳定,特别是latch部分对毛刺异常敏感;
4)某些及其特殊的情况下,如果出现正反馈,可能会导致灾难性的后果。(出现正反馈导致高频振荡,最后导致芯片过热炸掉)
好处
latch有弊就一定有利。在FPGA的LE中,总存在一个latch和一个D触发器,在支持DDR的IOE(IOB)中也存在着一个latch来实现DDIO。不过在我们平时的设计中,对latch还是要尽可能的敬而远之。
如何避免
1)在组合逻辑进程中,if语句一定要有else!并且所有的信号都要在if的所有分支中被赋值。
always @( * ) begin
if ( sig_a == 1'b1 ) sig_b = sig_c;
end
这个是绝对会产生latch的。
正确的应该是
always @( * ) begin
if ( sig_a == 1'b1 ) sig_b = sig_c;
else sig_b = sig_d;
end
另外需要注意,下面也会产生latch。也就是说在组合逻辑进程中不能出现自己赋值给自己或者间接出现自己赋值给自己的情况。
always @( * ) begin
if ( rst == 1'b1 ) counter = 32'h00000000;
else counter = counter + 1;
end
但如果是时序逻辑进程,则不存在该问题。
2)case语句的default一定不能少!
原因和if语句相同,这里不再多说了。
需要提醒的是,在时序逻辑进程中,default语句也一定要加上,这是一个很好的习惯。
3)组合逻辑进程敏感变量不能少也不能多。
这个问题倒不是太大,verilog2001语法中可以直接用* 搞定了。