目录

  1. 引言
  2. Latch 形成的原因
  3. 避免 Latch 的方法
  4. 参考资料

引言

在 Verilog 设计中,Latch(锁存器)通常是非预期的行为,尤其是在同步时序设计中。Latch 可能会导致不稳定的时序和难以预测的电路行为,因此需要尽量避免。本文将详细介绍 Latch 生成的原因,并提供一些避免 Latch 的有效方法。


Latch 形成的原因

Latch 主要是在 组合逻辑 中生成的,主要原因包括:

  • if-else 语句中没有为所有情况赋值
  • case 语句中缺少 default
  • 在组合逻辑 always @(*) 代码块中,没有覆盖所有情况

如果信号在某些情况下未被赋值,综合工具会推断出 Latch 来保存之前的值,从而导致意外的寄存行为。


避免 Latch 的方法

3.1 使用完整的 if-else 语句

如果 if-else 语句没有覆盖所有可能情况,可能会导致 Latch。

❌ 错误示例:可能导致 Latch

always @(*) begin
    if (enable) 
        data_out = data_in;  // 当 enable == 0 时,data_out 保持不变,导致 Latch
end

✅ 正确示例:完整赋值,避免 Latch

always @(*) begin
    if (enable) 
        data_out = data_in;
    else
        data_out = 0;  // 确保 data_out 始终有确定的值
end


3.2 在 case 语句中包含 default

如果 case 语句没有覆盖所有可能情况,可能会导致 Latch。

❌ 错误示例:可能导致 Latch

always @(*) begin
    case (sel)
        2'b00: out = a;
        2'b01: out = b;
        2'b10: out = c;  // sel == 2'b11 时,没有赋值,可能会生成 Latch
    endcase
end

✅ 正确示例:添加 default 避免 Latch

always @(*) begin
    case (sel)
        2'b00: out = a;
        2'b01: out = b;
        2'b10: out = c;
        default: out = 0;  // 确保所有情况都有明确赋值
    endcase
end


3.3 在组合逻辑中初始化所有变量

如果组合逻辑 always @(*) 块中的信号没有默认赋值,可能会导致 Latch。

❌ 错误示例:可能导致 Latch

always @(*) begin
    if (enable)
        out = a;  // 当 enable == 0 时,out 保持原值
end

✅ 正确示例:初始化变量

always @(*) begin
    out = 0;  // 先初始化,确保所有情况都有定义
    if (enable)
        out = a;
end


3.4 使用 always_ff (SystemVerilog)

在 SystemVerilog 中,可以使用 always_ff 避免综合 Latch。

always_ff @(posedge clk) begin
    if (reset)
        data_out <= 0;
    else
        data_out <= data_in;
end

always_ff 语句确保代码严格符合时序逻辑设计,避免非预期的 Latch 生成。


参考资料

  1. IEEE 1364-2005 Verilog Standard
  2. ASIC World – Verilog Coding Guidelines
  3. SystemVerilog IEEE 1800 Standard