当前位置: 首页 > ops >正文

FPGA基础 -- Verilog 锁存器简介

由浅入深地讲解 Verilog 中的锁存器(Latch)**,包括:

  1. 什么是锁存器(定义与作用)
  2. 锁存器的分类(透明锁存器 vs 边沿触发器)
  3. Verilog 中锁存器的建模方式
  4. 锁存器与触发器的区别
  5. 锁存器的时序特性与设计陷阱
  6. 实际应用与避免锁存器的最佳实践
  7. 综合工具识别锁存器的方式与调试技巧

一、什么是锁存器(Latch)?

锁存器是一种电平敏感的时序逻辑单元,用于在特定控制信号(如 enableclk 为高电平)时锁存输入数据,否则保持原状态。

🔧 本质上,它在控制信号有效时“透明”地传输数据”,无效时“记住上次的值”

锁存器的简要逻辑图:

         +-----------+
D ------>|           ||  Latch    |----> Q
EN ----->| (Enable)  |+-----------+

二、锁存器的分类

类型控制信号敏感方式特点
透明锁存器(Transparent Latch)电平敏感(高电平或低电平)开启时透传,关闭时保持
边沿触发器(Flip-Flop)上升/下降沿敏感只在边沿更新值(由两个锁存器组合)

注意:触发器(如 D Flip-Flop)是由两个互补使能的锁存器串联形成的结构(主从结构),是锁存器的扩展版本。


三、Verilog 中锁存器的建模方式

锁存器一般是always 块中使用电平敏感的敏感列表并缺少完整的 else 分支时自动生成。

1. 透明锁存器建模示例

module latch_example (input  wire en,input  wire d,output reg  q
);always @(en or d) beginif (en)q = d;// 没有 else,q 会自动保持原值,综合器推断 latch
endendmodule

❗ 这是经典 latch 写法if 条件成立赋新值,条件不成立时,q 保持原值,导致 latch 自动生成。


2. 如果不小心写出 latch?

如下代码也会综合出 latch,因为 q 只有在某个条件下才赋值:

always @(a or b or sel) beginif (sel)q = a; // 没有对 sel==0 情况赋值 => latch!
end

为避免这种情况,建议始终覆盖所有逻辑分支,如:

always @(a or b or sel) beginif (sel)q = a;elseq = b;  // 所有分支覆盖 => 组合逻辑
end

四、锁存器与触发器的区别

特性锁存器(Latch)触发器(Flip-Flop)
敏感性电平敏感边沿敏感
控制方式Enable 信号Clock 上升/下降沿
透明性是(在 EN 有效时)
建模方法电平触发 always边沿触发 always_ff
延迟控制容易受组合逻辑影响较稳定,边沿采样
用途短暂锁存/流水线优化寄存器、状态保持

五、锁存器的时序特性与设计陷阱

时序特性:

  • 透明期内输入变化会直接影响输出,很容易引入毛刺或竞争;
  • 在综合中,如果 Latch 与组合逻辑交织使用,可能会出现 逻辑冒险(hazard)
  • Hold time 要求更严格,不易进行 STA(静态时序分析);

常见设计陷阱:

错误用法问题原因
没有覆盖所有 if/else 分支导致 latch 被综合
在组合逻辑路径中插入 latch不易分析,逻辑难以收敛
Latch 控制信号由组合逻辑生成产生不定延迟与冒险

六、实际应用场景与如何规避 latch?

✅ 可控使用的场景(明确要用 latch):

  • 异步数据采样或保持
  • 功耗优化(某些低速模块)
  • 状态保持器(FSM 中稀有)

❌ 一般应规避 latch:

在主流 FPGA 项目中,推荐只使用触发器,不主动写 latch,原因包括:

  • 综合工具难以时序约束 latch;
  • ILA 等调试工具难以观测 latch 的状态;
  • latch 可能引入冒险、毛刺、竞争,造成 bug;

七、Vivado/Quartus/Lattice 中 latch 检查方式

✅ Vivado 示例:

  1. 编译后,在 Messages -> Synthesized Design -> Latches Inferred 会列出 latch;

  2. 可通过约束文件添加:

    set_property HD.CLK_SRC {NONE} [get_cells -hierarchical -filter {CELLTYPE == latch}]
    

    来阻止 latch 合成;

✅ 建议工具策略:

  • 使用 always_ff @(posedge clk)(SystemVerilog)
  • 在组合逻辑使用 always @(*)全分支赋值

总结

知识点说明
锁存器本质电平敏感,控制信号有效时透明,反之保持
建模方式条件赋值但未赋全分支时会被综合出 latch
与触发器区别触发器是边沿敏感,锁存器是电平敏感
风险容易引起时序问题、冒险、毛刺
建议组合逻辑必须全分支赋值,时序逻辑建议统一用触发器
http://www.xdnf.cn/news/14498.html

相关文章:

  • Python 区块链与Web3开发指南
  • 实战指南:用DataHub管理Hive元数据
  • 断言(Assertion)中常用的正则表达式
  • 最大公约数
  • 详细讲解Redis为什么被设计成单线程
  • 前端开发面试题总结-vue2框架篇(四)
  • Controller Area Network (CAN) 通信机制简介
  • 解决Matplotlib三维图无法旋转的问题
  • springboot入门之路(一)
  • Spring MVC 处理静态资源请求 - ResourceHandler
  • [Jenkins在线安装]
  • 为什么会出现 make 工程管理器?它到底能做什么?
  • Arduino入门教程:10、屏幕显示
  • python大学校园旧物捐赠系统
  • Linux操作系统之进程(六):进程的控制(上)
  • 分治算法之归并排序
  • Day04_C语言基础数据结构重点复习笔记20250618
  • 反转链表二--LeetCode
  • Neo4j 入门到精通(Cypher语言详解)
  • 前端部署更新后,如何优雅地通知用户刷新页面?
  • OpenCV——图像形态学
  • Arrays.asList() 的不可变陷阱:问题、原理与解决方案
  • 秋招是开发算法一起准备,还是只准备一个
  • 技能系统详解(1)——技能
  • mysql 学习
  • 45-Oracle 索引的新建与重建
  • 6-16阿里前端面试记录
  • RAG 架构地基工程-Retrieval 模块的系统设计分享
  • 学习STC51单片机41(芯片为STC89C52RCRC)智能小车8(测速显示到OLED显示屏)
  • git最常用命令