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

FPGA时序约束中set_clock_groups的实战设计指南

FPGA小白FPGA小白
技术分享
4小时前
0
0
8

Quick Start

  • 打开Vivado 2024.2(或更新版本),创建一个空工程,器件选择Xilinx Artix-7 XC7A35T-1CSG324C(示例)。
  • 编写一个包含两个异步时钟域(clk_a 50MHz, clk_b 75MHz)的简单设计,两个域之间只有一个寄存器级跨时钟域(CDC)同步器。
  • 在约束文件(.xdc)中,先定义两个主时钟:create_clock -period 20.000 -name clk_a [get_ports clk_a]create_clock -period 13.333 -name clk_b [get_ports clk_b]
  • 添加 set_clock_groups -asynchronous -group [get_clocks clk_a] -group [get_clocks clk_b]
  • 运行综合(Synthesis),打开综合后的时序报告(Report Timing Summary),确认没有跨时钟域的路径被分析(即报告只显示同域路径)。
  • 运行实现(Implementation),检查实现后的时序报告,确认无跨时钟域违例(WNS、TNS均为正)。
  • 可选:在仿真中注入跨时钟域数据,观察同步器输出稳定无亚稳态传播。

前置条件与环境

项目推荐值说明替代方案
器件/板卡Xilinx Artix-7 XC7A35T-1CSG324C入门级FPGA,支持多时钟域任何Xilinx 7系列或UltraScale+;Intel Cyclone V也可(需对应工具)
EDA版本Vivado 2024.2支持set_clock_groups完整语法Vivado 2019.1+;Intel Quartus Prime 18.0+(对应derive_pll_clocks)
仿真器Vivado Simulator 或 ModelSim用于功能验证和CDC行为检查VCS、Questa、Xsim
时钟/复位两个独立时钟源(板级晶振或PLL)clk_a 50MHz, clk_b 75MHz(示例)任意频率差>10%的异步时钟
接口依赖无外部接口要求仅内部寄存器CDC可扩展至AXI跨时钟域
约束文件一个.xdc文件包含主时钟定义和set_clock_groups可拆分为多个.xdc,但需注意优先级

目标与验收标准

  • 功能点:设计包含两个异步时钟域之间的单比特CDC同步器(两级寄存器)。
  • 性能指标:综合/实现后,时序报告中不应出现跨时钟域路径(即所有跨域路径被正确忽略)。
  • 资源/Fmax:不额外增加LUT/FF;Fmax由每个域内最差路径决定,不受跨域影响。
  • 验收方式:在Vivado中运行report_timing_summary,检查“Inter-Clock Paths”部分应显示“0 paths analyzed”。
  • 运行report_clock_interaction,确认clk_a和clk_b之间无交互(Interaction = None)。
  • 仿真中,跨时钟域数据经过同步器后无毛刺或亚稳态传播。

实施步骤

1. 工程结构与RTL设计

  • 创建顶层模块top,例化两个子模块:clk_a_domainclk_b_domain
  • clk_a_domain中生成一个单比特信号data_a(例如计数器溢出),通过两级寄存器同步到clk_b_domain
  • 同步器代码:always @(posedge clk_b) begin sync1 <= data_a; sync2 <= sync1; end
module top (
    input wire clk_a,
    input wire clk_b,
    input wire rst_n,
    output wire data_out
);

    reg [7:0] counter_a;
    reg data_a;
    reg sync1, sync2;

    // clk_a domain: generate data_a
    always @(posedge clk_a or negedge rst_n) begin
        if (!rst_n) begin
            counter_a &lt;= 8'd0;
            data_a &lt;= 1'b0;
        end else begin
            counter_a &lt;= counter_a + 1'b1;
            if (counter_a == 8'd255)
                data_a &lt;= 1'b1;
            else
                data_a &lt;= 1'b0;
        end
    end

    // CDC: synchronize data_a to clk_b domain
    always @(posedge clk_b or negedge rst_n) begin
        if (!rst_n) begin
            sync1 &lt;= 1'b0;
            sync2 &lt;= 1'b0;
        end else begin
            sync1 &lt;= data_a;
            sync2 &lt;= sync1;
        end
    end

    assign data_out = sync2;

endmodule

逐行说明

  • 第1行:声明顶层模块top,包含时钟、复位和输出端口。
  • 第2行:输入端口clk_a,50MHz时钟。
  • 第3行:输入端口clk_b,75MHz时钟。
  • 第4行:输入端口rst_n,低电平有效复位。
  • 第5行:输出端口data_out,同步后的数据。
  • 第7行:寄存器counter_a,8位计数器,用于产生脉冲。
  • 第8行:寄存器data_a,在clk_a域中生成的单比特信号。
  • 第9行:寄存器sync1sync2,构成两级同步器。
  • 第12行:clk_a域的逻辑块,敏感列表为clk_a上升沿或rst_n下降沿。
  • 第13-14行:复位时清零计数器和data_a。
  • 第15-20行:非复位时,计数器递增;当计数到255时,data_a置1,否则置0。
  • 第23行:CDC同步逻辑块,敏感列表为clk_b上升沿或rst_n下降沿。
  • 第24-25行:复位时清零同步器寄存器。
  • 第26-28行:非复位时,将data_a传递到sync1,再将sync1传递到sync2。
  • 第31行:将sync2赋值给输出data_out。

2. 约束文件编写

  • 创建一个.xdc文件(例如top.xdc),添加以下内容。
create_clock -period 20.000 -name clk_a [get_ports clk_a]
create_clock -period 13.333 -name clk_b [get_ports clk_b]
set_clock_groups -asynchronous -group [get_clocks clk_a] -group [get_clocks clk_b]

逐行说明

  • 第1行:定义主时钟clk_a,周期20ns(50MHz),绑定到端口clk_a。
  • 第2行:定义主时钟clk_b,周期13.333ns(75MHz),绑定到端口clk_b。
  • 第3行:将clk_a和clk_b设为异步时钟组,指示工具不分析它们之间的跨时钟域路径。

3. 综合与实现

  • 在Vivado中运行综合(Synthesis)。
  • 综合完成后,打开Report Timing Summary,在“Inter-Clock Paths”部分应看到“0 paths analyzed”。
  • 运行实现(Implementation),再次检查时序报告,确认WNS(最差负slack)和TNS(总负slack)均为正数。
  • 运行report_clock_interaction,确认clk_a和clk_b之间的交互状态为“None”。

4. 仿真验证(可选)

  • 编写testbench,驱动clk_a和clk_b,并观察data_out。
  • 注入跨时钟域数据后,检查同步器输出是否稳定,无毛刺或亚稳态传播。

验证结果

  • 综合后时序报告显示“Inter-Clock Paths: 0 paths analyzed”,符合预期。
  • 实现后WNS和TNS均为正,无跨时钟域违例。
  • report_clock_interaction显示clk_a和clk_b之间无交互。
  • 仿真中,data_out在clk_b域中稳定输出,无亚稳态现象。

排障指南

  • 问题1:时序报告中仍显示跨时钟域路径。
    原因:set_clock_groups未正确应用或时钟定义有误。
    解决:检查.xdc文件中时钟名称是否与create_clock定义一致;确认set_clock_groups语法正确,且未被其他约束覆盖。
  • 问题2:实现后WNS为负。
    原因:域内路径本身时序紧张,或跨域路径未被完全忽略。
    解决:先检查同域路径是否满足时序;若跨域路径仍被分析,尝试使用set_false_path作为补充。
  • 问题3:仿真中出现亚稳态。
    原因:同步器寄存器数量不足或复位不同步。
    解决:使用两级同步器(必要时三级);确保复位信号同步到目标时钟域。

扩展应用

  • 多时钟域设计:可将set_clock_groups扩展至三个或更多异步时钟组,例如-group [get_clocks clk_a] -group [get_clocks clk_b] -group [get_clocks clk_c]
  • 结合PLL:若时钟由PLL生成,使用derive_pll_clocks后,再应用set_clock_groups
  • 复杂CDC:对于多比特或握手协议,需结合set_max_delayset_bus_skew约束。

参考

  • Xilinx UG903: Vivado Design Suite User Guide: Using Constraints
  • Xilinx UG949: Vivado Design Suite User Guide: Methodology
  • IEEE Std 1364-2001 Verilog HDL

附录:完整约束文件示例

# top.xdc
create_clock -period 20.000 -name clk_a [get_ports clk_a]
create_clock -period 13.333 -name clk_b [get_ports clk_b]
set_clock_groups -asynchronous -group [get_clocks clk_a] -group [get_clocks clk_b]

逐行说明

  • 第1行:定义clk_a主时钟,周期20ns。
  • 第2行:定义clk_b主时钟,周期13.333ns。
  • 第3行:设置异步时钟组,忽略clk_a和clk_b之间的路径。
标签:
本文原创,作者:FPGA小白,其版权均为FPGA线上课程平台|最全栈的FPGA学习平台|FPGA工程师认证培训所有。
如需转载,请注明出处:https://z.shaonianxue.cn/44350.html
FPGA小白

FPGA小白

初级工程师
成电国芯®的讲师哦,专业FPGA已有10年。
47722.46W7.34W34.40W
分享:
成电国芯FPGA赛事课即将上线
FPGA图像处理中双线性插值的优化实现指南(2026年版)
FPGA图像处理中双线性插值的优化实现指南(2026年版)上一篇
Verilog中generate语句的2026年高效用法与仿真技巧下一篇
Verilog中generate语句的2026年高效用法与仿真技巧
相关文章
总数:1.20K
FPGA实习项目实战:2026年用Zynq实现智能小车控制

FPGA实习项目实战:2026年用Zynq实现智能小车控制

QuickStart准备硬件:Zynq-7020开发板(如Zedb…
技术分享
14天前
0
0
51
0
2026年Q2国产FPGA在工业相机中的实时图像处理应用:上手指南与实施手册

2026年Q2国产FPGA在工业相机中的实时图像处理应用:上手指南与实施手册

QuickStart准备硬件:选用国产FPGA开发板(如安路SF1系列…
技术分享
14天前
0
0
42
0
FPGA竞赛:2026年Q2备赛选题聚焦端侧AI推理与多传感器融合

FPGA竞赛:2026年Q2备赛选题聚焦端侧AI推理与多传感器融合

QuickStart步骤一:下载并安装Vivado2024.2(或…
技术分享
12天前
0
0
32
0
评论表单游客 您好,欢迎参与讨论。
加载中…
评论列表
总数:0
FPGA线上课程平台|最全栈的FPGA学习平台|FPGA工程师认证培训
没有相关内容