由浅入深地讲解 Verilog 中的锁存器(Latch)**,包括:
锁存器是一种电平敏感的时序逻辑单元,用于在特定控制信号(如 enable
或 clk
为高电平)时锁存输入数据,否则保持原状态。
本质上,它在控制信号有效时“透明”地传输数据”,无效时“记住上次的值”。
+-----------+
D ------>| |
| Latch |----> Q
EN ----->| (Enable) |
+-----------+
类型 | 控制信号敏感方式 | 特点 |
---|---|---|
透明锁存器(Transparent Latch) | 电平敏感(高电平或低电平) | 开启时透传,关闭时保持 |
边沿触发器(Flip-Flop) | 上升/下降沿敏感 | 只在边沿更新值(由两个锁存器组合) |
注意:触发器(如 D Flip-Flop)是由两个互补使能的锁存器串联形成的结构(主从结构),是锁存器的扩展版本。
锁存器一般是在 always
块中使用电平敏感的敏感列表并缺少完整的 else 分支时自动生成。
module latch_example (
input wire en,
input wire d,
output reg q
);
always @(en or d) begin
if (en)
q = d;
// 没有 else,q 会自动保持原值,综合器推断 latch
end
endmodule
❗ 这是经典 latch 写法:
if
条件成立赋新值,条件不成立时,q 保持原值,导致 latch 自动生成。
如下代码也会综合出 latch,因为 q
只有在某个条件下才赋值:
always @(a or b or sel) begin
if (sel)
q = a; // 没有对 sel==0 情况赋值 => latch!
end
为避免这种情况,建议始终覆盖所有逻辑分支,如:
always @(a or b or sel) begin
if (sel)
q = a;
else
q = b; // 所有分支覆盖 => 组合逻辑
end
特性 | 锁存器(Latch) | 触发器(Flip-Flop) |
---|---|---|
敏感性 | 电平敏感 | 边沿敏感 |
控制方式 | Enable 信号 | Clock 上升/下降沿 |
透明性 | 是(在 EN 有效时) | 否 |
建模方法 | 电平触发 always | 边沿触发 always_ff |
延迟控制 | 容易受组合逻辑影响 | 较稳定,边沿采样 |
用途 | 短暂锁存/流水线优化 | 寄存器、状态保持 |
错误用法 | 问题原因 |
---|---|
没有覆盖所有 if/else 分支 |
导致 latch 被综合 |
在组合逻辑路径中插入 latch | 不易分析,逻辑难以收敛 |
Latch 控制信号由组合逻辑生成 | 产生不定延迟与冒险 |
在主流 FPGA 项目中,推荐只使用触发器,不主动写 latch,原因包括:
编译后,在 Messages -> Synthesized Design -> Latches Inferred 会列出 latch;
可通过约束文件添加:
set_property HD.CLK_SRC {NONE} [get_cells -hierarchical -filter {CELLTYPE == latch}]
来阻止 latch 合成;
always_ff @(posedge clk)
(SystemVerilog)always @(*)
且 全分支赋值知识点 | 说明 |
---|---|
锁存器本质 | 电平敏感,控制信号有效时透明,反之保持 |
建模方式 | 条件赋值但未赋全分支时会被综合出 latch |
与触发器区别 | 触发器是边沿敏感,锁存器是电平敏感 |
风险 | 容易引起时序问题、冒险、毛刺 |
建议 | 组合逻辑必须全分支赋值,时序逻辑建议统一用触发器 |