FPGA线上课程平台|最全栈的FPGA学习平台|FPGA工程师认证培训
登录
首页-技术文章/快讯-技术分享-正文

FPGA时序收敛指南:set_clock_groups在多时钟域设计中的实施与验证(2026版)

二牛学FPGA二牛学FPGA
技术分享
15小时前
0
0
9

Quick Start

打开Vivado 2026.1(或对应版本),创建一个空工程,目标器件选择Xilinx Artix-7 XC7A35T(或手头板卡)。添加两个异步时钟源:一个100 MHz系统时钟(clk_100),一个50 MHz外设时钟(clk_50)。编写一个简单的双域同步器模块,用于将单比特信号从clk_100域传递到clk_50域。在XDC约束文件中添加以下命令:set_clock_groups -asynchronous -group [get_clocks clk_100] -group [get_clocks clk_50]。运行综合(Synthesis),确认无CRITICAL WARNING。运行实现(Implementation),查看时序报告:跨时钟域路径应被标记为“False Path”,WNS(最差负时序裕量)应为正数。生成比特流并下载到板卡,用逻辑分析仪(ILA)观察同步器输出,应无亚稳态导致的毛刺。

前置条件与环境

项目推荐值说明替代方案
器件/板卡Xilinx Artix-7 XC7A35T典型中低端FPGA,多时钟域场景常见Intel Cyclone V、Lattice ECP5
EDA版本Vivado 2026.1支持最新set_clock_groups语法与CDC分析Vivado 2023.x、Quartus Prime 24.x
仿真器Vivado Simulator(xsim)内置于Vivado,无需额外安装ModelSim、Questa、Verilator
时钟/复位100 MHz系统时钟,50 MHz外设时钟,异步复位(低有效)两个时钟互不同源,典型异步场景任意频率组合,只要明确异步关系
接口依赖无外部接口,仅内部逻辑本例聚焦内部CDC,不涉及IO若涉及IO,需额外IO约束
约束文件XDC格式Vivado原生约束格式SDC(Quartus/其他工具)

目标与验收标准

  • 功能点:单比特信号从clk_100域正确同步到clk_50域,无数据丢失或错误。
  • 性能指标:WNS ≥ 0 ns,无时序违规路径。
  • 资源:同步器占用约2-3个寄存器,无额外LUT。
  • Fmax:两个时钟域各自满足目标频率(100 MHz和50 MHz)。
  • 验收方式

    实施步骤

    1. 工程结构与RTL设计

    创建Vivado工程,添加以下RTL文件。核心模块是一个双域同步器,用于演示set_clock_groups的效果。

    // sync_2ff.v
    module sync_2ff (
     input wire clk_dst, // 目标时钟域时钟
     input wire rst_n,   // 异步复位,低有效
     input wire data_in, // 源时钟域数据
     output wire data_out // 同步后数据
    );
    
    reg sync_reg1, sync_reg2;
    
    always @(posedge clk_dst or negedge rst_n) begin
     if (!rst_n) begin
       sync_reg1 <= 1'b0;
       sync_reg2 <= 1'b0;
     end else begin
       sync_reg1 <= data_in;
       sync_reg2 <= sync_reg1;
     end
    end
    
    assign data_out = sync_reg2;
    
    endmodule

    逐行说明

    • 第1-6行:模块声明。clk_dst是目标时钟域时钟;rst_n是异步复位(低有效);data_in来自源时钟域;data_out是同步后输出。
    • 第8行:定义两个寄存器sync_reg1和sync_reg2,构成双级同步器。
    • 第10-16行:always块在clk_dst上升沿触发,rst_n低电平时复位两个寄存器为0。否则,sync_reg1捕获data_in,sync_reg2捕获sync_reg1。这是标准双级同步器结构,用于消除亚稳态。
    • 第18行:将sync_reg2赋值给输出data_out。同步器延迟2个目标时钟周期。

    2. 顶层模块与时钟生成

    顶层模块实例化同步器,并生成两个异步时钟(通过PLL或MMCM)。本例使用Vivado IP Catalog中的Clocking Wizard生成100 MHz和50 MHz时钟。

    // top.v
    module top (
     input wire clk_100, // 板级100 MHz时钟
     input wire rst_n,   // 板级复位
     output wire sync_out // 同步后输出
    );
    
    // 实例化PLL生成50 MHz时钟
    wire clk_50;
    clk_wiz_0 u_clk_wiz (
     .clk_in1(clk_100),
     .clk_out1(clk_50),
     .resetn(rst_n),
     .locked()
    );
    
    // 源时钟域:直接使用clk_100产生一个翻转信号
    reg toggle;
    always @(posedge clk_100 or negedge rst_n) begin
     if (!rst_n)
       toggle <= 1'b0;
     else
       toggle <= ~toggle;
    end
    
    // 实例化同步器
    sync_2ff u_sync (
     .clk_dst(clk_50),
     .rst_n(rst_n),
     .data_in(toggle),
     .data_out(sync_out)
    );
    
    endmodule

    逐行说明

    • 第1-6行:顶层模块声明,clk_100是板级输入时钟,rst_n是异步复位,sync_out是输出。
    • 第9-15行:实例化PLL IP(clk_wiz_0),输入clk_100,输出clk_50(50 MHz)。locked信号未使用,可忽略。
    • 第18-24行:在clk_100域中生成一个翻转信号toggle,用于模拟源时钟域数据变化。
    • 第27-32行:实例化同步器,将toggle同步到clk_50域,输出sync_out。

    3. 约束文件(XDC)

    约束文件是set_clock_groups的核心。首先定义时钟,然后设置异步时钟组。

    # constraints.xdc
    # 定义主时钟
    create_clock -name clk_100 -period 10.000 [get_ports clk_100]
    
    # 定义PLL输出时钟(由工具自动推导,但手动指定更清晰)
    create_clock -name clk_50 -period 20.000 [get_pins u_clk_wiz/clk_out1]
    
    # 设置异步时钟组
    set_clock_groups -asynchronous -group [get_clocks clk_100] -group [get_clocks clk_50]
    
    # 可选:设置输入输出延迟(本例无IO,省略)

    逐行说明

    • 第2行create_clock -name clk_100 -period 10.000 [get_ports clk_100]:定义100 MHz主时钟,周期10 ns,绑定到顶层端口clk_100。
    • 第5行create_clock -name clk_50 -period 20.000 [get_pins u_clk_wiz/clk_out1]:定义50 MHz时钟,周期20 ns,绑定到PLL输出引脚。注意:Vivado通常自动推导PLL输出时钟,但手动定义可避免歧义。
    • 第8行set_clock_groups -asynchronous -group [get_clocks clk_100] -group [get_clocks clk_50]:将clk_100和clk_50声明为异步时钟组。这告诉工具:两个时钟域之间的所有路径都是false path,无需时序分析。这是最关键的约束。

    4. 综合与实现

    在Vivado中运行Synthesis,观察Tcl Console无CRITICAL WARNING关于跨时钟域路径。运行Implementation,完成后打开“Report Timing Summary”。在“Paths”选项卡中,过滤“Inter-clock paths”,应显示0条违规路径。若仍有跨时钟域路径被分析,检查XDC中时钟名称是否匹配(如get_clocks拼写错误)。

    常见坑与排查

    • 坑1:时钟名称不匹配。现象:set_clock_groups报WARNING“找不到时钟”。检查:在Tcl Console运行report_clocks,确认时钟名称与get_clocks中一致。
    • 坑2:PLL输出时钟未被自动推导。现象:set_clock_groups仅作用于主时钟,PLL输出路径仍被分析。解决:手动添加create_clock约束PLL输出引脚。

    原理与设计说明

    set_clock_groups的本质是告诉时序分析工具:指定时钟组之间的所有路径都是false path(虚假路径),不需要进行时序计算。为什么需要这个?在多时钟域设计中,源时钟域寄存器到目标时钟域寄存器的路径,由于时钟相位关系不确定,无法保证建立/保持时间满足。工具若强行分析,会报告大量违规(WNS为负),但这些违规是“假”的——因为设计者已经通过同步器(如双级触发器)处理了亚稳态。set_clock_groups的作用就是屏蔽这些路径,让工具专注于真正的时序关键路径。

    关键矛盾:工具默认假设所有时钟相关(即使不同源),并分析所有跨时钟域路径。这会导致:

    • 大量时序违规淹没真正需要关注的路径。
    • 工具在布局布线时可能为跨时钟域路径优化,浪费资源。

    set_clock_groups通过-asynchronous选项声明时钟间无固定相位关系,工具直接跳过这些路径。注意:-asynchronous-logically_exclusive-physically_exclusive不同。后者用于时钟多路复用或物理互斥场景,而异步是跨时钟域最常用选项。

    边界条件

    • set_clock_groups只影响时序分析,不影响仿真或功能。仿真中跨时钟域路径仍会传播信号(可能产生亚稳态,但仿真模型通常不会模拟)。
    • 如果两个时钟域之间有同步器以外的组合逻辑路径(如直接连接),set_clock_groups仍会将其标记为false path,这可能导致功能错误。因此,必须确保所有跨时钟域路径都经过同步器。

    验证与结果

    指标测量条件结果(示例)
    WNS(最差负时序裕量)实现后,clk_100域内部路径+0.125 ns(满足)
    跨时钟域路径违规数实现后,过滤Inter-clock paths0条
    同步器延迟仿真,从toggle变化到sync_out变化2个clk_50周期(40 ns)
    资源占用实现后报告2个寄存器(sync_reg1, sync_reg2)
    Fmax(clk_100域)实现后报告≥ 125 MHz(裕量充足)

    测量条件:Vivado 2026.1,Artix-7 XC7A35T,速度等级-1。以上结果基于典型配置,实际值以工程为准。

    故障排查(Troubleshooting)

    • 现象:实现后时序报告仍有跨时钟域违规路径。原因:set_clock_groups未生效或时钟名称错误。检查点:在Tcl Console运行report_clock_interaction,查看时钟组关系。修复建议:确认XDC中时钟名称与report_clocks输出一致;检查XDC是否被包含在工程中(Set as Target Constraint)。
    • 现象:综合时出现CRITICAL WARNING“Clock has no target”或“Unconstrained clock”。原因:PLL输出时钟未被定义。检查点:查看综合日志,搜索“unconstrained”。修复建议:手动添加create_clock约束PLL输出引脚。
    • 现象:仿真中同步器输出出现不定态(X)。原因:复位未正确连接或同步器初始值未定义。检查点:检查rst_n是否连接到同步器;检查仿真波形中复位时序。修复建议:确保复位信号在仿真开始时有效;或给寄存器赋初值(initial块,仅仿真用)。
    • 现象:上板后同步器输出数据错误(如丢失脉冲)。原因:源时钟域数据变化太快,目标时钟域采样不足(违背奈奎斯特)。检查点:测量源时钟域数据最小脉宽,确保大于目标时钟周期。修复建议:在源时钟域对数据做展宽(至少保持2个目标时钟周期),或使用握手协议。
    • 现象:set_clock_groups报语法错误。原因:XDC中使用了不支持的选项或拼写错误。检查点:查看Vivado文档(UG903)中set_clock_groups语法。修复建议:确保使用-asynchronous(不是-async),且每个-group后跟[get_clocks ...]
    • 现象:实现后资源报告中同步器使用了LUT而非寄存器。原因:综合工具可能优化了寄存器为LUT(如移位寄存器推断)。检查点:查看综合后的网表,确认同步器结构。修复建议:在RTL中使用(* keep = "true" *)属性防止优化。
    • 现象:跨时钟域路径被标记为“False Path”,但WNS仍为负。原因:其他路径(如同一个时钟域内部)存在违规。检查点:在时序报告中过滤“Intra-clock paths”。修复建议:优化内部逻辑(如流水线、降低频率)。
    • 现象:使用多个set_clock_groups命令时,后一个覆盖前一个。原因:Vivado中最后一个set_clock_groups生效,之前被覆盖。检查点:查看Tcl Console中命令执行顺序。修复建议:将所有时钟放在一个set_clock_groups命令中,用多个-group

    扩展与下一步

    • 参数化同步器级数:将双级同步器改为参数化模块,支持2-5级,以应对不同亚稳态MTBF要求。
    • 多比特CDC:对于多比特信号(如总线),使用握手协议或异步FIFO,而非简单同步器。set_clock_groups同样适用。
    • 跨平台约束:若使用Intel Quartus,对应命令是set_clock_groups(相同语法)或derive_clock_uncertainty。Lattice Radiant使用set_false_path逐条设置。
    • 加入断言与覆盖:在仿真中添加SVA断言,检查同步器输出是否在预期延迟内变化;使用功能覆盖点确保所有CDC路径被测试。
    • 形式验证:使用工具(如JasperGold)形式化验证CDC结构是否正确(如无组合逻辑路径)。

    参考与信息来源

    • Xilinx UG903: Vivado Design Suite User Guide: Using Constraints (v2026.1)
    • Xilinx UG949: Vivado Design Suite User Guide: Methodology (v2026.1)
    • Clifford E. Cummings, “Clock Domain Crossing (CDC) Design & Verification Techniques”, SNUG 2008
    • Intel Quartus Prime Pro Edition User Guide: Timing Analyzer (v24.x)

    技术附录

    术语表

    • CDC (Clock Domain Crossing):时钟域交叉,信号从一个时钟域传递到另一个时钟域。
    • False Path:虚假路径,时序分析中忽略的路径。
    • WNS (Worst Negative Slack):最差负时序裕量,负值表示时序违规。
    • MTBF (Mean Time Between Failures):平均故障间隔时间,衡量亚稳态可靠性。

    检查清单

    • [ ] 所有跨时钟域路径都经过同步器(双级或更多)。
    • [ ] XDC中定义了所有时钟(包括PLL输出)。
    • [ ] set_clock_groups命令包含所有异步时钟组。
    • [ ] 实现后时序报告无跨时钟域违规。
    • [ ] 仿真验证了同步器功能正确。

    关键约束速查

    # 定义主时钟
    create_clock -name clk_a -period 10.000 [get_ports clk_a]
    
    # 定义衍生时钟(PLL输出)
    create_clock -name clk_b -period 20.000 [get_pins pll_instance/clk_out]
    标签:
    本文原创,作者:二牛学FPGA,其版权均为FPGA线上课程平台|最全栈的FPGA学习平台|FPGA工程师认证培训所有。
    如需转载,请注明出处:https://z.shaonianxue.cn/41016.html
    二牛学FPGA

    二牛学FPGA

    初级工程师
    这家伙真懒,几个字都不愿写!
    95819.43W3.99W3.67W
    分享:
    成电国芯FPGA赛事课即将上线
    VHDL入门实践:2026年GHDL与ModelSim仿真工具对比与操作指南
    VHDL入门实践:2026年GHDL与ModelSim仿真工具对比与操作指南上一篇
    FPGA时序收敛实践:set_clock_groups在多时钟域设计中的用法指南下一篇
    FPGA时序收敛实践:set_clock_groups在多时钟域设计中的用法指南
    相关文章
    总数:991
    Chiplet系统级验证中的FPGA原型验证实施指南

    Chiplet系统级验证中的FPGA原型验证实施指南

    随着Chiplet(芯粒)技术成为高性能计算与异构集成的主流方案,其系统…
    技术分享
    15天前
    0
    0
    33
    0
    FPGA与GPU协同调度上手指南:面向数据中心异构加速任务

    FPGA与GPU协同调度上手指南:面向数据中心异构加速任务

    随着数据中心工作负载日益复杂,单一加速器架构难以兼顾性能、能效与灵活性。…
    技术分享
    23天前
    0
    0
    53
    0
    Vivado 2026.1时序收敛:基于机器学习的自动路径分组方法

    Vivado 2026.1时序收敛:基于机器学习的自动路径分组方法

    QuickStart打开Vivado2026.1,新建或打开一个已…
    技术分享
    7小时前
    0
    0
    3
    0
    评论表单游客 您好,欢迎参与讨论。
    加载中…
    评论列表
    总数:0
    FPGA线上课程平台|最全栈的FPGA学习平台|FPGA工程师认证培训
    没有相关内容