避免latch verilog FPGA 基础练习2
发现问题,用技术解决问题。兴趣是自己的源动力 !
前言
本文由如何避免latch的问题场景,来更详细的描述verilog中的组合逻辑电路和时序逻辑电路等等理论知识。由latch这个问题入手来阐述更多理论知识,有助于更好的理解和记忆。
一、latch是什么?
Latch其实就是锁存器,是一种在异步电路系统中,对输入信号电平敏感的单元,用来存储信息。锁存器在数据未锁存时,输出端的信号随输入信号变化,就像信号通过一个缓冲器,一旦锁存信号有效,则数据被锁存,输入信号不起作用。因此,锁存器也被称为透明锁存器,指的是不锁存时输出对于输入是透明的。
简单理解latch的核心就是一句话:一旦锁存信号有效,则数据被锁存,输入信号不起作用。
二、latch出现的场景和危害
2.1 场景
Latch的问题是因为只有组合逻辑才会产生这种问题,产生Latch是我们在同步电路中尽量避免的,但并不表示Latch没有用的或者说是错误的,Latch在异步电路中是非常有用的,只是我们设计的是同步电路,要尽量避免。
上面这句话说只有组合逻辑才产生latch,又接着说latch在同步电路中要避免,如果不理解组合逻辑、时序逻辑、异步电路和同步电路,理解起来会有点绕。2.3、2.4节会对这句话解惑。
2.2 危害
在同步电路中Latch会产生不好的效果
- 如对毛刺敏感;不能异步复位,上电后处于不定态;还会让静态时序分析变得十分复杂;
理解:从latch本身的特性出发:一旦锁存信号有效,则数据被锁存,输入信号不起作用。理解了这句话,就可以明白为什么latch会产生这么多不良效果了
- 在FPGA的资源中,大部分器件没有锁存器这个东西,所以需要用使用寄存器来组成锁存器所以会占用更多逻辑资源;在ASIC设计中,锁存器也会带来额外的延时和DFT,并不利于提高系统的工作频 率
简单理解就是:锁存器可能会有多个寄存器组成,浪费资源。
2.3 组合逻辑和时序逻辑
这里先给出组合逻辑和时序逻辑的概念的简单理解:
- 组合逻辑:数字电路满足任意时刻的输出仅仅取决于该时刻的输入,那么该数字电路为组合逻辑电路。简单理解就是输入进来立刻输出*
注意:这里的数字电路不是仅仅理解为一个电路与门,如下图。可能是一个复杂的组合逻辑。
两种组合逻辑代码如下:
always @(*)
temp <= A + B;
assign temp <= A + B;
- 时序逻辑:如果数字电路任意时刻的输出不仅取决于当前时刻的输入,而且还取决于数字电路原来的状态,那么该数字电路为时序逻辑电路。简单理解就是输出的值要依赖某个状态,这个状态就是时钟的上升沿或者下降沿*
下面是时序逻辑代码示例
always @(posedge clk or posedge reset) begin
if (reset) begin
Q <= 4'b0000;
end else begin
Q <= Q + 1;
end
end
2.4 同步(时序)逻辑电路 和 异步(时序)逻辑电路
- 同步时序电路:狭隘的定义就是数字电路(简单或者复杂的与或门组合)被同一个时钟信号驱动。
注意理解:时序逻辑电路中肯定有组合逻辑的成分存在,但组合逻辑电路中却不可能有时序逻辑的成分存在。
这里可以返回到2.1节去理解,latch只有在组合逻辑中存在。因为时序电路中存在组合逻辑(这里不要只从verilog代码层面去考虑,要从verilog代码映射的电路图来考虑,如上图),所以需要在同步电路中去避免latch的产生。
- 异步时序电路:简单理解就是一个时序电路(异步也是时序电路),多个有差异的时钟来决定输入和输出。
这里总结一下第二节的内容:组合逻辑、时序逻辑、同步时序和异步时序,理解的关键就是抓住输入和输出这两个关键词。即:输入和输出不依赖其他信号就是组合逻辑,依赖时钟就是时序逻辑。时序逻辑中又分同步和异步,输入输出只依赖一个时钟就是同步,依赖多个时钟就是异步。
理解以上概念了,再回头看latch发生的场景,就豁然开朗了。
三、如何避免latch
- 情况一:组合逻辑中if语句没有else
module latch_one
(
input wire in1 , //输入信号in1
input wire in2 , //输入信号in2
input wire in3 , //输入信号in3
output reg [7:0] out //输出信号out
);
//out:根据3个输入信号选择输出对应的8bit out信号
always@(*)
if({in1, in2, in3} == 3'b000)
out = 8'b0000_0001;
else if({in1, in2, in3} == 3'b001)
out = 8'b0000_0010;
else if({in1, in2, in3} == 3'b010)
out = 8'b0000_0100;
else if({in1, in2, in3} == 3'b011)
out = 8'b0000_1000;
else if({in1, in2, in3} == 3'b100)
out = 8'b0001_0000;
else if({in1, in2, in3} == 3'b101)
out = 8'b0010_0000;
else if({in1, in2, in3} == 3'b110)
out = 8'b0100_0000;
else if({in1, in2, in3} == 3'b111)
out = 8'b1000_0000;
// else 把最后一个if的else注释掉,就会产生latch
// out = 8'b0000_0001;
endmodule
- 情况二:组合逻辑中case的条件不能够完全列举且不写default
module latch_two
(
input wire in1 , //输入信号in1
input wire in2 , //输入信号in2
input wire in3 , //输入信号in2
output reg [7:0] out //输出信号out
);
//out:根据3个输入信号选择输出对应的8bit out信号
always@(*)
case({in1, in2, in3})
3'b000 : out = 8'b0000_0001;
3'b001 : out = 8'b0000_0010;
3'b010 : out = 8'b0000_0100;
3'b011 : out = 8'b0000_1000;
3'b100 : out = 8'b0001_0000;
3'b101 : out = 8'b0010_0000;
3'b110 : out = 8'b0100_0000;
//把最后一种情况和default都注释掉,使case的条件不能够完全列举
//3'b111 : out = 8'b1000_0000;
//default: out = 8'b0000_0001;
endcase
endmodule
endmodule
- 情况三:组合逻辑中输出变量赋值给自己
module latch_three
(
input wire in1 , //输入信号in1
input wire in2 , //输入信号in2
input wire in3 , //输入信号in3
output reg [7:0] out //输出信号out
);
//out:根据3个输入信号选择输出对应的8bit out信号
always@(*)
if({in1, in2, in3} == 3'b000)
out = 8'b0000_0001;
else if({in1, in2, in3} == 3'b001)
out = 8'b0000_0010;
elseif({in1, in2, in3} == 3'b010)
out = 8'b0000_0100;
elseif({in1, in2, in3} == 3'b011)
out = 8'b0000_1000;
elseif({in1, in2, in3} == 3'b100)
out = 8'b0001_0000;
elseif({in1, in2, in3} == 3'b101)
out = 8'b0010_0000;
elseif({in1, in2, in3} == 3'b110)
out = 8'b0100_0000;
elseif({in1, in2, in3} == 3'b111)
out = 8'b1000_0000;
else
out = out;//输出变量赋值给自己
总结
核心思想:在抛出latch这个问题的情况下,去理解一些基础的理论概念,大致理解就行。知道在编写代码的时候,如何去避免latch。
- 欢迎一起交流学习,如有错误之处,还请各位指正。
参考资料文章来源:https://www.toymoban.com/news/detail-758269.html
[1] FPGA之组合逻辑与时序逻辑、同步逻辑与异步逻辑的概念文章来源地址https://www.toymoban.com/news/detail-758269.html
到了这里,关于避免latch verilog FPGA 基础练习2的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!