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

FPGA基础 -- 无毛刺时钟切换(glitch-free clock switching)

“工程可落地”的无毛刺时钟切换(glitch-free clock switching)讲解与可用代码,分别覆盖ASIC通用做法FPGA厂商原语做法,并配上时序/CDC约束与验证要点

一、问题本质与设计目标

clk_outclk0 切到 clk1(或反向)时,如果简单用 assign clk_out = sel ? clk1 : clk0;,一旦 sel 在任意时刻翻转、恰逢两路时钟处于不同电平/相位,就会产生:

  • runt pulse(短脉冲):违反下游触发器的最小高/低脉宽约束;
  • 毛刺与双沿:造成“多计数/少计数”、状态机跳变等隐患;
  • CDC风险sel 通常与两路时钟都异步,若直接驱动组合 MUX,会让毛刺概率放大。

设计目标:切换时实现“break-before-make”(先关后开),只在低电平窗口改变门控,使 clk_out 要么连续、要么短暂停(保持低电平)再平滑接入新时钟,但绝不产生短脉冲


二、ASIC/通用RTL方案(And-Or 门控 + 低电平更新 + 互斥握手)

核心思路:

  1. 将两路时钟分别门控gclk0 = clk0 & en0gclk1 = clk1 & en1
  2. 输出 clk_out = gclk0 | gclk1
  3. en0/en1 互斥,并且只在相应时钟的低电平边界更新(常用 negedge clk 或 ICG 低电平锁存),从而保证开/关都发生在“安全窗口”。

典型可综合参考实现(ASIC/标准单元库/不走FPGA LUT 时钟网络的前提):

// ===============================================================
// Glitch-free 2:1 Clock Switch (ASIC/通用RTL参考)
// - 先关后开(break-before-make)
// - 在各自时钟的 negedge 更新 en,保证改变发生在低电平窗口
// - 对 sel 进行双级同步(各自域)
// ===============================================================
module clk_switch_gf (input  wire rst_n,     // 异步复位,低有效input  wire clk0,      // 时钟0(可与clk1异步/不同频)input  wire clk1,      // 时钟1input  wire sel_async, // 1->选择clk1,0->选择clk0(异步控制)output wire clk_out
);// 1) 将 sel 分别同步到两个时钟域,降低亚稳态风险reg sel0_d1, sel0_d2;reg sel1_d1, sel1_d2;always @(posedge clk0 or negedge rst_n) beginif (!rst_n) {sel0_d1, sel0_d2} <= 2'b00;else        {sel0_d1, sel0_d2} <= {sel_async, sel0_d1};endalways @(posedge clk1 or negedge rst_n) beginif (!rst_n) {sel1_d1, sel1_d2} <= 2'b00;else        {sel1_d1, sel1_d2} <= {sel_async, sel1_d1};endwire sel0 = sel0_d2; // 在clk0域观察到的选择(0=>clk0)wire sel1 = sel1_d2; // 在clk1域观察到的选择(1=>clk1)// 2) 互斥门控en,在各自时钟的negedge更新(低电平窗口)//    break-before-make:新使能只有在另一边彻底关闭后才能拉起reg en0, en1;// 默认上电选择clk0(可按需调整)always @(negedge clk0 or negedge rst_n) beginif (!rst_n) en0 <= 1'b1;                       // 上电默认clk0else        en0 <= (~sel0) & (~en1);           // 只有当选择clk0 且 en1已关 才能开endalways @(negedge clk1 or negedge rst_n) beginif (!rst_n) en1 <= 1'b0;                       // 上电默认clk1关闭else        en1 <= ( sel1) & (~en0);           // 只有当选择clk1 且 en0已关 才能开end// 3) 时钟门控与汇合(ASIC请用ICG/CLKGATE原语替换 & 与 |)wire gclk0 = clk0 & en0;wire gclk1 = clk1 & en1;assign clk_out = gclk0 | gclk1;endmodule

关键点说明

  • 互斥保证en0 <= ~sel0 & ~en1en1 <= sel1 & ~en0 形成“你关我才开”的互锁。理论上可用形式验证/断言证明 !(en0 & en1) 永真。
  • 低电平更新:在 negedge clk 改变 enX,意味着 enX 的翻转发生在 clkX 低电平期间,不会截断高电平造成短脉冲。
  • 允许短暂停顿:切换窗口内可能出现 en0=en1=0(输出保持低电平若干 ns/周期),这不是毛刺,是安全空档
  • ICG/库原语:ASIC务必以**集成时钟门控单元(ICG)**替代 &|,从而满足架构/版图上的时钟树规则与占空比/脉宽保障。
  • 边界场景:若被关闭的时钟卡死在高电平导致 negedge 不来,上述算法会一直保持输出低电平(安全降级)。若要求“输入卡死也要强制切走”,需在ICG/库里使用带“停摆忽略”能力的专用门控/切换单元,或引入看门狗辅助。

三、FPGA实现的工程做法(强烈建议优先用厂商原语)

在FPGA中禁止用 LUT/组合逻辑直接门控时钟或在Fabric里“与/或”,应使用专用全局时钟资源。各家芯片都提供了可无毛刺切换的全局时钟 MUX/门控原语:

1) Xilinx(7-Series/UltraScale/UltraScale+)

推荐BUFGCTRLBUFGMUX_CTRL / BUFGCE
最稳妥的做法是用 CE 互斥实现“先关后开”,把选择握手逻辑产生的 en0/en1 直接接到 BUFG 的使能脚:

// 同步/互斥逻辑与你在ASIC方案一致(建议仍做双级同步+negedge更新)
// 这里展示用 BUFGCTRL 做无毛刺切换的骨架:wire en0, en1;  // 互斥门控(同上文逻辑生成)BUFGCTRL #(.INIT_OUT(1'b0)  // 上电输出默认值
) u_bufgctrl (.I0     (clk0),.I1     (clk1),.S0     (1'b1),  // 置1:忽略S,完全由CE控制.S1     (1'b1),.CE0    (en0),   // 只使能一路.CE1    (en1),.IGNORE0(1'b0),.IGNORE1(1'b0),.O      (clk_out)
);

要点:

  • S0=S1=1,让 CE0/CE1 完全决定输出;做到“break-before-make”即可无毛刺切换,不要求两路同频同相
  • 若输入时钟可能卡死,UltraScale 家族还可利用 BUFGCTRL 的更高级用法(IGNORE 等)实现“卡死时强制切走”,具体参照器件文档。
  • 如果只是在一条时钟上启停,用 BUFGCE 就够;两路切换仍建议 BUFGCTRL

2) Intel(Altera)

使用 Clock Control Block(老名 ALTCLKCTRL),选择 glitch-free switchover 选项。原则同上:

  • 让工具把你的门控/切换逻辑映射到全局时钟控制块
  • 互斥 CE + 先关后开;
  • 具体端口名/参数在不同代器件略有差异(Cyclone/Arria/Agilex),用 IP 向导生成后把CE互斥逻辑接上即可。

3) Lattice(ECP5、CrossLink-NX、MachXO等)

使用器件提供的 全局时钟控制/多路选择原语(例如 CLKMUX2ECLK 相关原语、DCCA/CLKDIVF 等)。同样遵循:

  • 不要用 LUT 对时钟 &|
  • 使用官方时钟MUX/门控资源,并用互斥 CE 驱动;
  • 具体原语名与接法以器件 TRM 为准。

四、时序与CDC约束(必须做)

  1. Clock Groupsclk0clk1 大多无关/异步,在 STA 里:

    • set_clock_groups -asynchronous -group {clk0} -group {clk1}
      或在 Vivado 用 set_clock_groups -exclusive(取决于你的语义:确实不会同时到下游)。
  2. 派生/生成时钟:把 clk_out 定义为生成时钟,并指明它与激活源之间的关系(静态检查要知道这个树)。

  3. 选择信号路径sel_async -> sel_sync 的路径设为CDC/false_path,例如

    • set_false_path -from [get_ports sel_async] -to [get_pins sel0_d1/D sel1_d1/D]
      或用工具自带 CDC 例外标注。
  4. 最小脉宽约束(ASIC尤甚):对 clk_out 设置 set_min_pulse_width -high/-low,匹配目标工艺/库要求。

  5. 保持互斥:为 en0 & en1 添加综合/形式约束或 SVA 断言,禁止同时为1;并考虑 dont_touch 保护关键互锁逻辑,避免综合优化破坏。


五、功能验证建议(强烈推荐)

  • 随机切换:在仿真里对 sel_async 做随机抖动与突发翻转(远高于两路时钟频率),观察 clk_out 波形:

    • 不出现小于阈值的高/低脉宽(可写断言主动检查)。
  • 频比/相位覆盖:覆盖常见组合:同频同相/同频反相/不等频/一快一慢。

  • 停摆场景:将被关闭的时钟“卡高/卡低”,确认 clk_out 行为(安全降级或利用原语强制切走)。

  • SVA断言样例(思路示意):

    • assert never (en0 && en1);
    • assert clk_out 的任一高脉宽 ≥ T_min_high,低脉宽 ≥ T_min_low(基于周期测量模块或专用checker)。

六、常见坑与规避

  • 在Fabric里用门电路直接改时钟:在FPGA是大忌,务必用全局时钟原语。
  • 只做组合MUXassign clk_out = sel?clk1:clk0; 必出毛刺。
  • 同步缺失sel 不双级同步,容易把亚稳态直接“扩散”到门控。
  • 非互斥CE:两路 CE 可能瞬间同时为1(或先开后关),会叠加出“怪脉冲”。
  • negedge更新被禁止:若公司规范不允许 negedge 触发器,可改为低电平透明锁存的 ICG 方案,或者在FPGA用带“glitchless”承诺的原语,仍保证“低电平窗口更新”。

七、一个更“厂味”的Xilinx落地骨架(推荐在FPGA中用)

把上文“互斥CE + 双域同步”的思想直接喂给 BUFGCTRL,实现最标准的无毛刺切换:

module xilinx_bufgctrl_switch (input  wire rst_n,input  wire clk0,input  wire clk1,input  wire sel_async, // 1->clk1, 0->clk0output wire clk_out
);// 双域同步(同上)reg sel0_d1, sel0_d2, sel1_d1, sel1_d2;always @(posedge clk0 or negedge rst_n) beginif (!rst_n) {sel0_d1, sel0_d2} <= 2'b00;else        {sel0_d1, sel0_d2} <= {sel_async, sel0_d1};endalways @(posedge clk1 or negedge rst_n) beginif (!rst_n) {sel1_d1, sel1_d2} <= 2'b00;else        {sel1_d1, sel1_d2} <= {sel_async, sel1_d1};endwire sel0 = sel0_d2;wire sel1 = sel1_d2;// 在各自域低电平窗口更新互斥CE(与ASIC方案一致)reg en0, en1;always @(negedge clk0 or negedge rst_n) beginif (!rst_n) en0 <= 1'b1;else        en0 <= (~sel0) & (~en1);endalways @(negedge clk1 or negedge rst_n) beginif (!rst_n) en1 <= 1'b0;else        en1 <= ( sel1) & (~en0);end// 用BUFGCTRL做最终无毛刺切换(CE互斥,S固定=1)BUFGCTRL #(.INIT_OUT(1'b0)) u_bufgctrl (.I0(clk0), .I1(clk1),.S0(1'b1), .S1(1'b1),.CE0(en0), .CE1(en1),.IGNORE0(1'b0), .IGNORE1(1'b0),.O(clk_out));
endmodule

这套在 7-Series/UltraScale(+) 都是“顺着工具”的推荐用法;Intel/Lattice 用各自的 Clock Control Block 同理迁移。


八、结语(选型建议)

  • FPGA项目优先用官方时钟控制原语(BUFGCTRL/ALTCLKCTRL/CLKMUX2…),在其外围用互斥CE + 低相位更新 + 双域同步的模板即可。
  • ASIC项目:用ICG + 低电平锁存的门控结构替代 &/|,维持同样的状态机互斥与更新时机;在STA里做好生成时钟最小脉宽时钟组隔离约束。
  • 若有“输入卡死也要切”的强需求,选用带忽略/强制切换能力的专用单元(不同工艺/FPGA原语的具体脚位名称不同),或增加看门狗配合强制降级策略。
http://www.dtcms.com/a/494749.html

相关文章:

  • Vhost架构解析:vhost-net与vhost-user详解
  • 西安建设商城类网站html静态网站源码
  • 一个基于双向时序卷积网络(BiTCN)的时间序列预测MATLAB程序
  • 【超详细】C#自定义工具类-StringHelper
  • 网站关闭与域名备案怎么设置网页版浏览器
  • 11G显存DPO强化学习微调实战
  • 在 Ubuntu 上安装 MinIO 并使用 Python 封装类操作对象存储
  • 基于DDGS实现图片搜索,文本搜索,新闻搜索
  • 点胶喷嘴技术支持东莞网站建设昆明软件定制
  • 怎样做钓鱼网站网站编辑教程
  • AI驱动软件测试全流程自动化:从理论到实践的深度探索
  • 开源接口管理工具PostIn,从安装到入门零基础指南
  • 构建未来的智能体:Coze 的能力、部署与应用场景
  • DBCO-Sulfo-NHS ester酯,1400191-52-7在生物正交连接体系中的作用机制与功能开发
  • 【cursor】通用开发环境配置指南(AI辅助开发最佳实践)
  • 【数据结构】双向链表“0”基础知识讲解 + 实战演练
  • 药品经营许可证识别技术:通过深度学习算法实现资质文件的自动化识别与核验
  • 网站的建设思想企业app定制
  • YOLOv3 目标检测算法核心技术
  • MySQL 主从复制故障排查及解决方案
  • 告别单打独斗:多智能体协作如何解决复杂问题?
  • Netty连接断开检测:Epoll与NIO的对比及实战解决方案
  • 神经网络之反向传播
  • el-table-column show-overflow-tooltip 只能显示纯文本,无法渲染 <p> 标签
  • (定时任务)接上篇:定时任务的分布式执行与分布式锁使用场景
  • 广州网站制作哪家专业凡科互动游戏可以作弊码
  • caching_sha2_password认证插件说明
  • 13.继承(一)
  • vue3:el-progress的圆形无线滚动,心跳、呼吸效果,加载中的效果
  • 高速光耦:电子系统的卓越赋能者