【聚看点】08-避免Latch的产生
2023-05-23 21:11:27
博客园
(资料图片仅供参考)
1.Latch简介
Latch就是锁存器,是一种在异步电路系统中,对输入信号电平敏感的单元,用来存储信息锁存器在数据未锁存时,输出端的信号随输入信号变化,就像信号通过一个缓冲器,一旦锁存信号有效,数据就会被锁存,输入信号不起作用,因此,锁存器也被称为透明锁存器,指的是不锁存时输出对于输入是透明的
2. 异步电路与同步电路
异步电路:异步电路主要是组合逻辑,用于产生FIFO或者RAM的读写控制信号脉冲,但是它同时也用在时序电路中,此时它没有统一的时钟,状态变化的时刻是不稳定的,通常输入信号只在电路处于稳定状态时才发生变化同步电路:同步电路是由时序电路(寄存器和各种触发器)和组合逻辑电路构成的电路,其所有操作都是在严格的时钟控制下完成的,这些时序电路共享一个时钟CLK,而所有的状态变化都是在时钟上升沿(或者下降沿)完成的异步电路中广泛使用的是Latch,在异步电路中可以使用Latch替代寄存器,但是在同步电路中,Latch对于电路会出现不好的结果
- 对于毛刺敏感
- 不能异步复位,上电之后处于不定态
- 占用更多的逻辑资源
- 额外延迟
- 复杂的静态时序分析
3.几种产生Latch的情况及避免
- 组合逻辑中if-else语句,缺少else语句
- 组合逻辑中case条件分支语句条件未完全列举,且缺少default语句(在使用case语句的时候要么完全列举所有情况,要么加default)
- 组合逻辑中输出变量赋值给了自己
4.验证Latch
使用之前写过的3-8译码器进行验证Latch.qpf结尾的文件就是之前创建的quartus项目文件,双击可以打开quartus项目
4.1 正确的代码
module decoder( input wire in_1, input wire in_2, input wire in_3, output reg [7:0] out); always@(*) begin if({in_1,in_2,in_3} == 3"b000) out <= 8"b0000_0001; else if ({in_1,in_2,in_3} == 3"b001) out <= 8"b0000_0010; else if ({in_1,in_2,in_3} == 3"b010) out <= 8"b0000_0100; else if ({in_1,in_2,in_3} == 3"b011) out <= 8"b0000_1000; else if ({in_1,in_2,in_3} == 3"b100) out <= 8"b0001_0000; else if ({in_1,in_2,in_3} == 3"b101) out <= 8"b0010_0000; else if ({in_1,in_2,in_3} == 3"b110) out <= 8"b0100_0000; else if ({in_1,in_2,in_3} == 3"b111) out <= 8"b1000_0000; else out <= 8"b0000_0001; endendmodule
4.2 if-else 产生latch
module decoder( input wire in_1, input wire in_2, input wire in_3, output reg [7:0] out); always@(*) begin if({in_1,in_2,in_3} == 3"b000) out <= 8"b0000_0001; else if ({in_1,in_2,in_3} == 3"b001) out <= 8"b0000_0010; else if ({in_1,in_2,in_3} == 3"b010) out <= 8"b0000_0100; else if ({in_1,in_2,in_3} == 3"b011) out <= 8"b0000_1000; else if ({in_1,in_2,in_3} == 3"b100) out <= 8"b0001_0000; else if ({in_1,in_2,in_3} == 3"b101) out <= 8"b0010_0000; else if ({in_1,in_2,in_3} == 3"b110) out <= 8"b0100_0000; else if ({in_1,in_2,in_3} == 3"b111) out <= 8"b1000_0000; // else // out <= 8"b0000_0001; endendmodule
4.3 case语句产生latch情况
```plaintextmodule decoder( input wire in_1, input wire in_2, input wire in_3, output reg [8:0] out); // 使用case语句 // 使用if-else语句 always@(*) begin case({in_1,in_2,in_3}) 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; // 3"b111 : out = 8"b1000_0000; // default : out = 8"b0000_0001; endcase endendmodule
正常代码综合
错误代码综合
4.4 将变量赋值给自己
module decoder( input wire in_1, input wire in_2, input wire in_3, output reg [8:0] out); // 使用case语句 // 使用if-else语句 always@(*) begin case({in_1,in_2,in_3}) 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; 3"b111 : out = 8"b1000_0000; default : out = out; // 将输出变量赋值给自己,也会产生latch endcase endendmodule
- 代码每次修改之后都要进行重新编译