10.【Verilog】Verilog 同步与异步
2026/5/1 7:12:31 网站建设 项目流程

第一步:分析与整理Verilog 同步与异步

1. 背景

  • 上一个文章(建立/保持时间)指出:当触发器输入数据与时钟不相关时,容易导致时序 violation。
  • 本章目的:解决模块间因异步问题导致的时序违例。
  • 定义范围:只关注从异步时钟的时序结果分析解决问题,不深究异步电路结构或产生原因。

2. 同步时钟的定义与分类

定义:频率相同或频率比为整数倍,且相位相同或相位差固定的两个时钟为同步时钟。或者简化为:时钟同源且频率比为整数倍。

2.1 同源同频同相位

  • 完全同步,数据传递只需满足正常的建立/保持时间,无需特殊同步设计。

2.2 同源同频不同相位

  • 相位差固定(因时钟路径不同导致的偏移),仍可认为是同步的。
  • 只要控制数据延迟在合理范围内,就能满足时序。版图级可修复固定相位差。

2.3 同源不同频但存在整数倍分频比

  • 一个时钟是另一个时钟的分频,相位差固定。

  • 慢时钟域 → 快时钟域:快时钟总能采到慢时钟的信号(只要满足建立/保持时间)。快时钟域采到的信号会持续多个周期(频率比)。

    • 若要求只持续一个周期,需进行上升沿检测
    • 上升沿检测 Verilog 代码
      reg [1:0] sig2_r; always @(posedge clk2 or negedge rstn) begin if (!rstn) sig2_r <= 2'b0; else sig2_r <= {sig2_r[0], sig1}; end assign sig2 = sig2_r[0] && !sig2_r[1];
    • 仿真波形显示 sig2 为单周期脉冲。
  • 快时钟域 → 慢时钟域

    • 慢时钟域能安全采集到快时钟信号的前提是:快时钟信号宽度足够。若快时钟域信号过窄(例如单周期脉冲),慢时钟域可能漏掉。
    • 解决方案:在快时钟域将窄脉冲展宽
      • 频率比小时,用延迟链展宽。
      • 频率比大时,用计数器展宽。
    • 示例:频率比为2,用延迟2拍展宽
      reg [1:0] sig11_r; always @(posedge clk1 or negedge rstn) begin if (!rstn) sig11_r <= 2'b0; else sig11_r <= {sig11_r[0], sig11}; end reg sig22_r; always @(posedge clk2 or negedge rstn) begin if (!rstn) sig22_r <= 1'b0; else sig22_r <= |sig11_r; end assign sig22 = sig22_r;
    • 波形显示快时钟域脉冲展宽后,慢时钟域可以采到。

结论:同源且频率比为整数倍时,可视为同步,一般无需特殊同步处理。

3. 异步时钟的定义与分类

以下三种情况可视为异步:

3.1 不同源

  • 两个不同的时钟源(如晶振A和晶振B)产生的时钟。即使频率相同,相位关系也不固定,每次上电可能不同。是最常见的异步情况。

3.2 同源但频率比不是整数倍

  • 例如同源的7MHz和3MHz,相位差会变化,时序难以控制,按异步处理。

3.3 同源频率比为整数倍但不满足时序要求

  • 前文提到,快→慢时钟域若快信号太窄,慢时钟域无法安全采样,也可视为异步问题。慢时钟域时序宽松,快时钟域严格,但快信号过窄会导致漏采、timing violation。

本章只介绍分类,异步问题的解决方法将在后续章节介绍。


第二步:费曼教学法 – 通俗讲解同步与异步

作为验证工程师。今天我们要讨论的是数字电路设计中一个核心概念:同步与异步。它决定了两个模块之间是否可以“无脑”通信,还是需要“协调员”。我用“火车站列车时刻表”来比喻,帮你彻底搞懂。

一、同步与异步:火车站的比喻

想象有两个火车站:

  • 同步火车站:所有列车(时钟)都来自同一个调度中心(同源),时间表(频率和相位)完全对齐或者是整数倍关系。比如每隔10分钟发一趟快车,每隔20分钟发一趟慢车,慢车发车时刻总是与快车中的某一趟重合。乘客(数据)从快车换乘慢车很轻松,因为车次时间有规律。
  • 异步火车站:列车来自不同的调度中心(不同源),或者时间表不是整数倍关系(比如一趟每隔7分钟,另一趟每隔3分钟)。两边的时刻表无法对齐,乘客换乘时可能错过车,或者被夹在门中间(亚稳态)。

数字设计中,同步时钟域之间可以直接传输数据,只要计算好建立/保持时间。异步时钟域之间必须使用同步化处理(如双寄存器握手、FIFO等),否则会出时序违例。

二、同步时钟的三种情况(原文分类详解)

情况1:同频同相 – 完美同步

  • 两个时钟一模一样。数据直接传,没有任何问题。
  • 工作中:同一时钟树下的各个触发器。

情况2:同频不同相 – 有固定相位差

  • 例如时钟A比时钟B晚1ns到达(由于布线上路径长)。这1ns是固定的,后端可以调整。
  • 只要保证数据从A域传递到B域时,路径延迟加上相位差满足建立/保持时间,就没问题。
  • 注意:如果相位差太大导致setup违例,需要在后端修复(插入延迟、调整时钟树)。

情况3:同源整倍数分频 – 需要处理脉冲宽度

  • 典型场景:一个100MHz时钟,分频得到50MHz时钟(下降沿或上升沿计数产生)。两者同源,相位固定。
  • 慢→快:50MHz域的信号到100MHz域,100MHz时钟总能采到(因为慢信号宽度≥10ns,快时钟周期10ns)。若不希望快域信号持续两个周期,可用上升沿检测电路(代码见前),将长脉冲转为一个周期脉冲。
  • 快→慢:100MHz的单周期脉冲(10ns)到50MHz域,50MHz时钟每20ns采样一次,很可能漏掉。解决方法:在快域将脉冲展宽,例如用寄存器延迟两拍(20ns),确保慢时钟能采到。展宽后用组合逻辑(如|)合并成电平信号。

示例回顾:快域脉冲展宽代码中,sig11_r存了快域信号的两拍历史,sig22_r在慢时钟沿判断是否有任一拍为高,从而输出高电平。

关键公式:展宽长度 = 慢时钟周期 / 快时钟周期 + 1。频率比为2时,展宽2拍足够。

三、异步时钟的三种情况(需警惕)

类型1:不同源 – 最常见

  • 比如芯片内部,一个来自PLL的100MHz,另一个来自外部晶振直接输入的24MHz。两者没有相位关系。
  • 直接传输数据会导致亚稳态,必须使用异步FIFO握手协议双寄存器同步器(仅限单bit信号)。

类型2:同源但频率比不是整数倍

  • 例如用同一个PLL产生125MHz和33.33MHz(3.75倍,不是整数)。它们的相位关系随时间漂移,无法保证稳定。
  • 按异步处理。

类型3:同源整数倍但快域信号太窄导致慢域漏采

  • 仍可视为异步问题。因为漏采会导致数据丢失,即使逻辑上频率是整数倍。解决方案同上:在快域展宽。
  • 注意:这类问题常被忽视——设计者认为“整数倍就是同步”,但实际上单周期脉冲在慢域可能丢失。

四、工作中如何应用?

4.1 判断是否为同步时钟

  • 问自己:两个时钟是否源于同一个PLL或同一个外部晶振?分频系数是否为整数?相位差是否可以通过后端约束固定?
  • 若答案为“是”,可视为同步,直接传输数据需计算好组合逻辑延迟,并注意脉冲展宽问题。
  • 若答案为“否”,必须采用异步处理。

4.2 同步时钟域间的设计要点

  • 慢→快:通常直接打拍接收,若需要只持续一个周期,加边沿检测。
  • 快→慢:必须保证快域信号宽度 > 慢时钟周期 + 快时钟周期(通常安全裕量)。若宽度不够,在快域展宽。
  • 边沿检测代码(通用模板):
    reg sig_dly1, sig_dly2; always @(posedge clk_fast) {sig_dly2, sig_dly1} <= {sig_dly1, sig_slow}; wire posedge_detected = sig_dly1 & ~sig_dly2;

4.3 异步时钟域的处理(简要提及)

  • 单bit信号:使用两级寄存器同步器(reg [1:0] sync; always @(posedge clk2) sync <= {sync[0], sig1};)。输出为sync[1]。这能降低亚稳态概率,但不能避免所有问题,且信号可能会延迟一两个周期。
  • 多bit信号:使用异步FIFO,或握手协议(请求/应答)。
  • 时序要求:对同步器所在的路径,通常需要设置set_false_pathset_clock_groups -asynchronous,避免STA工具误报违例。

4.4 验证工程师的职责

  • 识别异步接口:阅读设计文档,找出所有跨时钟域(CDC)路径。
  • 检查是否有正确的同步处理:比如在RTL中看到单bit信号直接从一个时钟域赋值到另一个时钟域且没有两级寄存器,要报bug。
  • 仿真中观察亚稳态:虽然仿真器难以真正模拟亚稳态,但可以通过故意让时钟沿靠近来触发x传播,验证同步器是否能恢复。
  • 使用CDC工具:专业工具(如SpyGlass、Questasim CDC)会自动检查CDC路径并报告问题。

4.5 常见错误及避免

错误后果正确做法
认为整数倍分频就完全同步,忽略快→慢窄脉冲慢域漏采数据,功能错误展宽快域脉冲或使用握手机制
慢→快信号直接采,不处理持续多周期问题逻辑误判(例如认为脉冲只持续一周期)加边沿检测转换为单周期
异步信号未用两级同步器直接采亚稳态传播,触发器输出x导致功能错使用两级寄存器同步
多bit异步总线用各自同步器(未用FIFO)各bit同步后可能不同步,产生错误数据使用异步FIFO或握手
在异步路径上添加时序约束(误设false path)STA可能遗漏真正的时序问题正确设置set_clock_groups -asynchronous

五、学习建议

  1. 仿真实验:修改原文中的快→慢例子,改变快域脉冲宽度,观察慢时钟域何时漏采。尝试用展宽电路修复,测量所需的最小展宽拍数。
  2. 动手写同步器:写一个两级同步器模块,输入异步信号,输出同步后的信号。在testbench中用不同的时钟源激励,观察输出延迟和可能的x
  3. 分析真实芯片的CDC:找到一款MCU或FPGA的参考设计,查看其跨时钟域处理方式,理解为什么有的地方用握手,有的地方用FIFO。
  4. 学习CDC工具:如果条件允许,跑一下SpyGlass CDC规则检查,理解常见违规类型(如“signal from different clock without synchronizer”)。

六、总结

同步与异步,核心就是问:“这两个时钟有关系吗?”

  • 有关系(同步):就像火车时刻表对得齐,可以直接换乘,但要小心快车去慢车会“错过车”(窄脉冲漏采)。
  • 没关系(异步):就像两个独立运营的地铁,必须通过“换乘大厅”(同步器、FIFO、握手)才能互通,否则就会撞车或掉入轨道。

作为验证工程师,你不需要设计这些同步电路,但必须识别出哪些接口是异步的,并确认设计者已经做了正确的同步处理。如果发现“裸奔”的跨时钟域赋值,立刻报bug。这是保证芯片可靠性的底线。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询