首页
搜索 搜索
当前位置:快讯 > 正文

【聚看点】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
  • 代码每次修改之后都要进行重新编译