Latch 是什么
latch 即锁存器,是一种对电平敏感的存储单元电路,和寄存器一样都是基本存储单元,但是寄存器是边沿触发的存储器,锁存器是电平触发的存储器。
组合逻辑电路和时序逻辑电路
在数字电路中将逻辑电路分成两大类,一类叫组合逻辑电路,另一类叫做时序逻辑电路。
- 组合逻辑电路:组合逻辑电路是一种输出状态只与当前输入直接相关的电路,它的输出仅仅取决于当前的输入状态,而不受到过去的输入状态或时钟信号的影响。
- 时序逻辑电路:时序逻辑电路是一种输出状态不仅与当前输入相关,且还与过去状态相关的电路,它的输出不仅取决于当前的输入状态,还要考虑过去状态。
注意
在FPGA中通常将没有时钟的电路归为组合逻辑电路,有时钟的电路归为时序逻辑电路。
Latch 的危害
Latch具有以下危害:
- Latch是电平触发的,因此有Latch的电路抗干扰能力差
- Latch不能异步复位
- Latch上电后处于不定态,会让静态时序分析变得十分复杂
- 大部分FPGA器件没有 Latch这个东西,需要用使用寄存器来组成锁存器,会占用更多逻辑资源等问题
产生 Latch 的原因
在组合逻辑电路中如果变量的赋值操作没有覆盖到分支语句(如 if else 、case endcase、? : 等)的每一个分支就会产生Latch,常见的有以下情况:
- if 语句没有 else
- case 语句没有 defaul
- 变量自己给自己赋值
注意:
只有在组合逻辑电路中才会产生Latch(这里的组合逻辑是以有无时钟来区分的)
if 语句没有 else
示例代码如下:
module latch_one (
input wire in1,
input wire in2,
output reg[3:0] out
);
always @(*) begin
if({in1, in2} == 2'd0)
out = 4'b0001;
else if({in1, in2} == 2'd1)
out = 4'b0010;
else if({in1, in2} == 2'd2)
out = 4'b0100;
// else
// out = 4'b1000;
end
endmodule
上面代码中out变量的赋值没有覆盖到if语句的每一个分支(没有else部分),通过vivado进行语法分析后发现其原理图如下,可以看到生成了latch。
case 语句没有 defaul
示例代码如下:
module latch_tow (
input wire in1,
input wire in2,
output reg[3:0] out
);
always @(*) begin
case({in1, in2})
2'd0: out = 4'd0001;
2'd1: out = 4'd0010;
2'd2: out = 4'd0100;
// default:out = 4'd1000;
endcase
end
endmodule
上面代码中out变量的赋值没有覆盖到case语句的每一个分支(没有default部分),通过vivado进行语法分析后发现其原理图如下,可以看到生成了latch。
变量自己给自己赋值
示例代码如下:
module latch_three(
input in1,
input in2,
output wire[3:0] out
// output reg[3:0] out
);
//在条件运算符中自己对自己赋值
assign out = (in1 != in2) ? in1 : out;
在case语句中自己对自己赋值
//always @(*) begin
// case({in1, in2})
// 2'd0: out = 4'd0001;
// 2'd1: out = 4'd0010;
// 2'd2: out = 4'd0100;
default:out = 4'd1000;
default: out = out;
// endcase
//end
在if语句中自己对自己赋值
//always @(*) begin
// if({in1, in2} == 2'd0)
// out = 4'b0001;
// else if({in1, in2} == 2'd1)
// out = 4'b0010;
// else if({in1, in2} == 2'd2)
// out = 4'b0100;
// else
// out = 4'b1000;
else
out = out;
//end
endmodule
面代码中out变量在条件运算符中存在自己对自己赋值的情况,通过vivado进行语法分析后发现其原理图如下,可以看到生成了latch。
注意:
在if语句中自己对自己赋值和在case语句中自己对自己赋值也会产生Latch