FPGA开发中如何避免Latch的产生?

作者:FPGA入门到精通

在FPGA开发中,避免Latch的产生是一项重要的设计原则,这也是FPGA初学者容易出现的一个错误。

本文将详细探讨Latch的概念、产生原因、潜在危害以及如何避免Latch的产生。

一、Latch是什么?

Latch就是锁存器,是一种对输入信号电平敏感的存储单元电路,可以在特定输入信号作用下改变状态,并在没有新的输入信号时保持当前状态。

Latch与锁存器的区别,锁存器是时钟边沿触发的存储器,输出状态只在时钟边沿变化,与时钟信号同步工作,因此在抑制噪声和异步信号方面更加稳定。

二、Latch的危害有哪些?

Latch在组合逻辑中会产生严重的危害,所以FPGA设计规范中都要求避免Latch的产生,以确保设计的可靠性和稳定性。

这些危害主要有:

1、毛刺(Glitch)问题

Latch可能导致输出信号产生瞬态的、不稳定的值,这些毛刺可能会传播到电路的其他部分,引起不可预测的行为。

2、时序分析困难

Latch的存在使得时序分析变得更加复杂,因为它们的行为不依赖于时钟信号,这使得确定准确的时序约束变得困难。

3、设计可维护性差

Latch的存在使得设计难以理解和维护,因为它们的非同步特性可能导致难以追踪的问题。

三、Latch的产生的几种情况

Latch在FPGA设计中的产生通常与代码逻辑有关系,在组合逻辑中容易出现,下面给出产生Latch的几种情况以及解决办法。

1、不完整的条件语句

在Verilog或VHDL中,如果 if 语句没有完全覆盖所有可能的条件,或者case语句没有使用 default 分支,就可能导致Latch的产生。

(1)不完整的if语句(没有else)

产生Latch的代码:

reg q;
always @(*) begin
   if (en) q = data_in; // 如果en为0,q没有被赋值,产生Latch
end

避免Latch的代码:

reg q;
always @(*) begin
   if (en) q = data_in;
   else    q = 0;       // 明确为q赋值,避免Latch
end

(2)不完整的case语句(没有Default)


产生Latch的代码:

reg q;
always @(*) begin
   case (sel)
       2'b00: q = data0;
       2'b01: q = data1;
   endcase // 没有default分支,sel为2'b10或2'b11时产生Latch
end

避免Latch的代码:

reg q;
always @(*) begin
   case (sel)
       2'b00: q = data0;
       2'b01: q = data1;
       default: q = 0; // 添加default分支,避免Latch
   endcase

2、信号自我赋值

在组合逻辑中,如果一个信号的赋值依赖于其自身的当前值,这也可能导致Latch行为。

产生Latch的代码:

reg [1:0] q;
always @(*) begin
   case (sel)
       2'b00: q = q; // q赋值给自身,产生Latch
       2'b01: q = 2'd1;
       default: q = 1'b0;
   endcase
end

避免Latch的代码:

reg [1:0] q;
always @(*) begin
   case (sel)
       2'b00: q = 2'd2;
       2'b01: q = 2'd1;
       default: q = 1'b0;
   endcase
end

四、总结

Latch的危害很严重,我们在写代码的过程中需要极力避免的。

其实处理起来也很简单,那就是在写组合逻辑代码(如assign语句或always(*)语句块)时,一定要把if语句和case语句写全,要包含else和default,且不能出现信号直接赋值自己的情况。

最新文章

最新文章