FPGA 专家 13:高阶时序收敛——物理约束、多角点、hold 治理
本文是
fpga/专家层第 16 篇。常规手段见进阶 时序收敛方法、时序收敛实战案例,例外纪律见时序例外场景,签核见专家层《FPGA 时序签核》。
一、收敛决策树

二、建立 vs 保持
| 建立(setup) | 保持(hold) | |
|---|---|---|
| 检查 | 下一个沿前数据稳定 | 当前沿后数据保持窗口 |
| 危险角 | 慢角(高温低压) | 快角(低温高压) |
| 降频 | 可救 | 无效甚至更糟 |
| 根因 | 逻辑级数多/布线长 | 路径过短+时钟偏斜/漏约束 |
| 手段 | 打拍/retiming/物理靠近 | 平衡时钟树/插延迟级/正确 CDC 约束 |
三、高阶工具箱
- Pblock/LOC:通信密集模块锁相邻区域,缩短物理布线(不过度锁定);
- 时钟树:全局/区域缓冲、MMCM 就近,治时钟偏斜;
- phys_opt_design:物理 retiming/复制/重布线;
- 多角点:slow max 建立 + fast min 保持同时零违例;
- uncertainty:set_clock_uncertainty 留抖动/PLL 裕量;
- 例外纪律:跨域用 set_clock_groups(结构有同步器前提)、个别用精确 false path/multicycle,逐条注释;
- 增量收敛:锁存已收敛布局布线,只迭代未收敛模块。
四、签核红线
- WNS/TNS、WHS/THS 全部 ≥0(所有角);
- check_timing 无 unconstrained 路径;
- 无大片粗暴 false path;
- 跨时钟域 report_cdc 零未解释项;
- 温压边界留裕量(uncertainty 合理)。
五、签核前的约束审计:先保证你在解正确的问题
时序收敛的第一原则是:任何红色数字在确认约束正确性之前都不值得处理。一个典型项目的时间报告里,真正需要改 RTL 的违例可能只占少数,其余是漏约束、错约束和伪路径。约束审计第一步:时钟完整性。用 check_timing/check_clocks 确认每个时钟都被 create_clock/create_generated_clock 正确定义:主时钟在输入端口或 GT/PLL 输出脚上,generated clock 表达分频/倍频关系,且只有一个源头(重复定义会互相覆盖);检查是否有 unconstrained internal pins(通常意味着某个 MMCM 输出漏了 generated clock)。时钟交互矩阵(report_clock_interaction)应逐格检查:同步关系用默认时序、真异步用 set_clock_groups -asynchronous、可安全放宽的同源分频用 multicycle,任何“未知/未约束”的交互格都要解释。
第二步:路径分类。把路径分成必须收敛的真同步路径、CDC 路径(靠同步器/FIFO 保证,见 intermediate/42)、静态配置路径(复位、上电常量)、测试路径。CDC 路径必须配合 report_cdc 或等价审计确认接收端确有两级同步/握手,才可以进异步时钟组——set_clock_groups 的语义是“我用结构保证了安全”,不是“这格别查了”。第三步:IO 与虚时钟:所有进出 FPGA 的同步接口要有 input/output delay 并挂在对应时钟(常用 virtual clock),否则工具对内向外向路径不做真实检查;板级延迟、器件 tco/tSU 要进约束。第四步:例外复核:每条 false_path/multicycle 必须精确(-from/-to/-through 到具体时钟或引脚,禁止全时钟宽泛声明)、必须有注释说明对应的结构保证,并在评审中逐条过目。经验上,一个干净收敛的设计,例外表很短且每条都能在 RTL 里指出对应电路;反之满屏 false_path 的项目几乎一定在掩盖真问题。做完这一步,报告里剩下的违例才是工程问题。
六、建立违例的物理观:报告怎么读、瓶颈长在哪
高阶收敛与入门的差别在于看报告的方式:不是按违例数量从大到小机械打拍,而是理解每条关键路径在硅片上的物理形态。打开一条违例路径报告,先看路径分类与端点:起点是普通 FF、RAM/ROM 输出、DSP 输出还是 carry 链,终点同理;源时钟和目的时钟是否同域(跨域违例回到第五节处理)。再看延迟构成:logic delay(单元延迟,反映逻辑级数)与 route delay(布线延迟,反映物理距离/拥塞)的比例。route 占比很高(如超过 55%~65%)时,问题是物理的——源/目的被布得太远、跨时钟区域、经过拥塞区,打拍帮助有限,应靠布局(Pblock/相对约束)或把通信结构改成本地化;logic 占比高时,是组合级数太多(大 mux、宽加法比较、case 嵌套),打拍、retiming、预译码才对路。再看时钟偏斜(clock skew):大正偏斜会吃掉建立裕量、负偏斜则可能制造保持违例,偏斜大通常是时钟树负载不均或门控造成的。
还要看统计形态而不是单条路径:如果几十条违例都从同一组 FF 出发,那是高扇出控制网问题,复制寄存器/加使能;违例集中在两个层次化模块之间,说明模块边界布局远或接口逻辑宽;违例路径终点集中在某个 RAM/DSP,可能是端口到内部寄存器的固有偏斜,需要调整流水。利用 GUI 里的 Device 视图看路径实际走线:跨 SLR(SSI 器件的 super logic region)路径经过超长互连,延迟可数倍于本地路径,这类路径必须从架构上减少或打拍(见多 die 设计专题 专家 42 的系统观点)。物理观收敛的核心动作是:让通信密集的结构在硅片上也相邻。层次化设计、物理约束分区(logicLock/Pblock 风格)、数据流沿一个方向布局,都是为这一点服务。养成“先在芯片上看路径、再决定改 RTL 还是改布局”的习惯,收敛工作就从试错变成诊断。
七、物理优化工具箱:Pblock、相对约束与高扇出治理
当结构级手段(打拍、retiming)和策略调整都做完后,物理约束是最后的精细手段,但必须克制使用——约束的本质是剥夺工具的布局自由度,过度约束会让整片变差。Pblock 的正确用法是圈定通信簇而不是钉死单个模块:把边界清晰、内部互连密集、对外接口少的子系统(如一组处理流水线+其本地 BRAM/DSP)框到相邻时钟区域,工具仍可在框内自由放置;Pblock 应包含余量资源(约 70%~80% 利用率上限)并允许呼吸。不要把大量 FF 用 LOC 钉到具体坐标,那会让布线器无法处理拥塞,常见后果是被钉区域周边全线恶化。判定要不要 Pblock 的依据是第六节的物理证据:多次实现中关键路径稳定地因为跨区长线违例,才值得固化布局;偶发违例优先用策略种子解决。
**高扇出网(high-fanout net)**是最常见的可物理治理问题:复位、使能、状态机状态、就绪/有效标志等信号扇出几千个负载时,单条网络延迟和偏斜都会变大。手段按温和程度排序:综合属性 max_fanout 让工具自动复制;把“全局使能”改成流水的局部使能(架构最优);显式复制寄存器并手工划分负载区域;确实全局且无延迟敏感的信号才用 BUFG 走全局时钟网(滥用全局缓冲会占用宝贵时钟资源且不适合数据信号)。时钟结构治理:检查时钟是否全部走 BUFG/BUFGCE/BUFH 等专用资源,有没有“分频时钟”用逻辑与出来当钟(应改时钟使能);门控单元靠近负载放置以平衡偏斜;MMCM/PLL 靠近使用它的时钟区域。DSP/BRAM 注册级启用:这些硬核内置输入输出寄存器,把流水打在硬核内部时序几乎免费,宽算术/存储流水应充分使用。跨 SLR/长线:在 SSI 器件中规划“时钟和数据流不过线或集中过线”,必要时把接口寄存器放在目的 SLR 侧。每用一个物理手段都要 A/B 对比报告——确认关键路径改善且没有制造新的违例簇,再固化进约束。
八、保持时间违例的系统治理:为什么快角会咬人
保持时间问题在 FPGA 上通常由工具自动加延迟修复,但当 WHS 反复为负时,背后几乎总是结构问题而非“延迟不够”。先复习机理:保持检查要求源寄存器在沿后发出的新数据不能在同一沿到达太早冲掉旧值,决定量是数据最短期望到达时间与捕获沿(含偏斜)之差。快工艺角(低温、高压)下逻辑和布线都更快,最小延迟变小,hold 最容易失败;降低时钟频率完全不改变同沿关系,所以降频救不了 hold,甚至因为工具在慢角放松布局而让快角更差。根因一:时钟偏斜主导。如果捕获 FF 的时钟比发射 FF 晚到(大正偏斜),数据即使走正常逻辑也可能“赶在旧沿的保持窗口结束前”到达。治理是平衡时钟树:确认两个 FF 在同一全局/区域时钟网络上、中间没有手工布线的时钟、门控没有制造局部延迟差;大模块用一个时钟源,局部插时钟使能而不是分频时钟。
根因二:同沿极简路径。相邻 FF 之间只有一根线或一个 LUT(控制信号直传、复位同步链旁边的数据路径),最小延迟接近零;工具会在布线中加延迟单元/LUT 修复,但如果这样的路径有几万条(典型于自动生成的总线或复位分发),修复资源会推高拥塞甚至失败。结构性解法是让这类相邻寄存器路径天然带一个逻辑级或在设计规范中禁止“裸连线跨大距离”的同沿传输。根因三:伪 CDC 路径当真路径检查或反之。漏约束的异步路径在快角产生大量 hold 违例(因为工具试图让无关时钟沿满足保持),正确做法是审计时钟域并补 set_clock_groups(第五节);反过来,对真实同频相移路径乱加 false path 则会掩盖真故障。根因四:源同步/IO 接口,器件内部 hold 修复与引脚时序共同作用,需要正确的延迟约束(见 专家 03)。治理流程:先确认快角报告的路径分类(内部还是 IO、是否跨域),再治时钟结构,再让工具物理修复,最后在多个实现种子上验证 WHS 稳定为正。hold 修复会增加布线延迟、间接影响 setup,因此 setup/hold 必须一起看、所有角一起签。
九、多角点与不确定性:让报告代表真实工况
“常温 25℃ 收敛”不构成签核,因为硅的延迟随工艺、电压、温度(PVT)漂移,器件模型因此提供多个分析角。FPGA 工具默认做多角分析:慢角(低压、慢速码片、按手册的高温或低温——注意部分器件高温和低温都可能出现在慢模型,具体看库文档)检查最大延迟/建立;快角(高压、低温、快码片)检查最小延迟/保持。签核要求是报告中的每个角、每个时钟域、每条受约束路径 WNS/TNS 和 WHS/THS 都不为负,且留有余量。“只收 setup 再说”的策略危险:为修 setup 而插入的逻辑/布局变化会改变快角,hold 可能在最后一轮全部冒出来;正确节奏是每轮迭代后两个角都看。时钟不确定性 set_clock_uncertainty 代表工具无法精确知道的抖动和偏差:MMCM/PLL 输出有相位抖动,同步时钟之间有相位误差,板级时钟有周期抖动;工具通常从时钟资源自动推导一部分,但设计者常要为系统裕量追加不确定性(如数百 ps),相当于主动提高时序标准。不确定性不是越大越好:过大等于无意义降频,应按时钟树数据手册和系统抖动预算推导。
多配置/多速率签核也要纳入:同一个比特流支持多个时钟频率或动态重配时钟时,要对各频率组合分别分析(或用 create_clock 的多场景/多模式机制);部分可重配置设计中,静态逻辑在所有 RM 配置下都必须收敛(专题 03)。签核报告规范建议冻结:timing summary 首页(WNS/TNS/WHS/THS、脉冲宽度、时钟偏斜)、check_timing 无告警、clock interaction 表、CDC 报告、利用率/拥塞、几个最差端点所属模块;报告和比特流、RTL hash 绑定归档。这样现场出时序相关问题(高温下偶发错误)时能对照当时签核条件。还要建立对“工艺漂移+老化”的常识:FPGA 厂商的时序模型已含量产分布,只要按模型签核即可,但温度边界和电压拉偏是系统责任——如果板上电源在负载阶跃下跌落超过器件数据手册,任何时序签核都会失效,这把问题连到了 PI 设计(专家 23)。
十、收敛流程化:从随机种子到可重复的签核方法论
高阶团队把时序当作可管理的工程过程,而不是“跑 implementation 看运气”。迭代节奏:先在快速综合/少量布局估计阶段抓大结构问题(时钟域、明显级数、资源冲突),不要等到全布线;中期按模块/层次做 OOC 时序预算(每个层次内部和跨层次端口都有周期数约定),系统集成时违例只应来自预算之外;后期冻结结构,只做物理微调与策略选择。预算法:为接口级联分配周期预算(每段流水允许的逻辑/布线延迟),设计评审按预算检查,而不是把无约束的 RTL 扔给工具;跨 SLR、跨时钟区、硬核周边路径要单独预算(这些地方布线延迟显著高)。策略与种子:综合策略(默认/性能/面积)、实现策略(explore/aggressive)、placement/post-route phys_opt 开关和多种子并行是最后的统计优化——多跑几个实现选最好结果是正当工程手段,但不能替代结构优化;把种子当唯一手段会得到“这台机器这次收敛”的脆弱结果,任何小改动都可能重来。
增量/锁存流程:对大设计,先收敛并锁存稳定基础(时钟、硬核、关键框架),后续迭代用增量实现或分区,把工具的自由度集中在变更区域,缩短迭代时间并保护已有时序。报告驱动的质量门:CI/夜间构建除了综合通过,应自动抓取 WNS/TNS/WHS/THS、unconstrained 数、CDC 未知项、拥塞等级,任何一项劣化超阈值就失败(FPGA CI 实践见 专家 46);RTL lint 与时钟域检查前置(intermediate/46)。知识沉淀:维护团队级“违例模式—修复手段”库(高扇出复制、某硬核周边必加流水、某封装的 Pblock 经验),新项目在架构评审就应用。签核会上要回答五个问题:约束是否完整正确、所有角是否为正且有余量、CDC 是否全部有结构对应、物理布局是否可重复(换种子/小改动不崩)、报告是否与发布物绑定归档。时序收敛本质上是一个“用周期预算管理复杂度”的系统工程;把它流程化,团队就不再依赖个别英雄在流片/发版前夜救火。
十一、SSI/SLR 器件的时序治理:多 die 设计专题
基于堆叠硅互连(SSI)的大器件由多个 super logic region(SLR,各自是一个 die)通过超长的中介层互连组成,它解决了容量问题,也制造了 FPGA 时序里最硬的一类约束:SLR crossings 的延迟和拥塞远高于普通布线。原则一,架构先行:在层次划分时就按 SLR 组织逻辑——每个大功能块归属一个 SLR,跨 SLR 只走预先设计的窄接口(AXI 通道、FIFO、寄存器边界),绝不让数据流和控制网在 SLR 之间自由扩散;用 Pblock 把大模块约束到指定 SLR,边界接口寄存器放在对方一侧(目的 SLR 侧寄存),使跨线变成单周期的寄存器到寄存器路径。原则二,时钟规划:尽量让时钟域局限在 SLR 内;必须跨 SLR 的时钟通过专用时钟驱动能力并评估偏斜,跨 SLR 的数据接口两侧寄存器用同一时钟。原则三,硬核归属:收发器、DDR 控制器、PCIe 块固定在某个 SLR,使用它们的逻辑应就近放置,跨 die 喂高速数据是常见灾难;先看器件 floorplan 里硬核位置再分区。
签核时要看 SLR crossing 专用报告(跨线数量、最差跨线路径、每个 crossing 的寄存器化情况),理想状态下跨线全部是“目的侧寄存的单拍路径”且数量与架构预算一致;大量未寄存跨线说明功能分区失败。拥塞报告要按 SLR 分别检查,某个 SLR 满了即使总量有余量也无法布线——容量规划按 SLR 分别记账(这也是多 FPGA 分区思想的单片版本,见 02 多 FPGA 原型系统 ASIC 分区/TDM)。经验法则:单片 SLR 能放下的设计不要为“余量更大”选 SSI 器件,跨 die 的收敛成本和构建时间是真实代价;一旦使用,floorplan 工作要在项目早期而不是时序救火阶段进行。
十二、接口与硬核周边:DDR、收发器、PCIe 的时序预算
最差时序路径常常不在随机用户逻辑,而在硬核周边和 IO 接口,这些地方有固化的延迟结构,通用打拍未必有效,必须按接口特性专门预算。DDR 控制器侧:MIG 的用户接口有固定频率和时序关系,用户逻辑到接口的 FIFO/命令 FIFO 应使用 IP 提供的边界约束和示例连接,跨到用户时钟域在异步 FIFO 处完成(专家 06);不要把复杂逻辑塞进 PHY 附近的时钟域。收发器:复位/配置类信号是慢路径,用户数据在收发器内部时钟域,跨到用户逻辑全部走 IP 内置 FIFO;收发器的发送/接收用户时钟(如 156.25MHz)应在同区域驱动相关流水线,长距离引到另一角会制造偏斜问题。PCIe/以太网:AXI-Stream 用户接口侧的时序模型由 IP 约束保证,用户管线入口加寄存器级,不要在 valid/ready 上做跨模块组合依赖。
外部 IO:源同步接口(LVDS、RGMII、MIPI 之类)用 IO 原语和 IDELAY/IDDR 结构实现,时序约束包括输入/输出延迟和数据手册参数,收敛点在 IO 寄存器(专家 03);系统同步接口用虚拟时钟加 board delay。通用建议是为每个外部/硬核接口建立一页“时序预算表”:时钟频率、IP 边界保证了什么、用户侧必须在几拍内完成、允许的逻辑级数、跨域点在哪。接口先按预算设计,集成时违例就很少;反之,把 IP 当普通模块随意连线,接口区会成为项目末期的时序黑洞。
十三、签核清单与时序文化
一份可交付的时序签核包应包含:timing summary 全角截图/导出(WNS/TNS/WHS/TPWS、脉冲宽度、偏斜、所有时钟);check_timing 零告警;clock interaction 表逐格解释;CDC 审计(工具报告所有跨域点与对应同步结构,零未解释项);IO 延迟约束与板级依据;Pblock/物理约束清单(每条有报告依据);时序例外清单(每条精确、有注释、有评审记录);利用率/拥塞与 SLR crossing(如适用);最差路径分模块统计;构建可复现信息(工具版本、种子、RTL hash)。签核标准不是“绿了就行”:关键路径留合理正余量(如 ≥0.3~0.5ns,按团队标准),所有工作模式和速率档都过,温压角全覆盖,多次构建结果稳定(换种子不翻红)。
“时序文化”比单次签核更重要:架构评审看周期预算而不是事后验收;RTL 代码评审把流水线、复位风格、时钟使能、接口寄存器化纳入检查;lint 和时钟域扫描进 CI;每次合入跑快速时序趋势检查,劣化早发现;时序问题由设计者负责到底,不甩给“后端”。FPGA 没有独立后端团队,写 RTL 的人就是做物理收敛的人,这种责任一体性决定了:高质量 FPGA 工程师写每一行时序逻辑时,脑子里都有它在芯片上的长度、扇出和时钟域——高阶时序技术到最后不是约束技巧,而是这种物理直觉的系统化。
十四、实战案例:一个跨 SLR 设计的收敛过程
综合一个典型案例说明方法论的落地顺序。某视频处理平台移植到更大容量 SSI 器件后,顶层 WNS 约 -1.2ns,违例路径上百条,团队最初的反应是“加打拍、换 explore 种子”,改善有限且每轮迭代 8 小时。第一步做约束审计:发现一个 MMCM 输出时钟漏了 generated clock,产生一批假违例,补约束后剩余 60 条真实违例。第二步读物理报告:在 Device 视图发现关键路径的源/目的 FF 分别落在 SLR0 和 SLR2,route delay 占 70%,根因是数据流水线按功能模块分区时,一个状态反馈环跨了三片 SLR。架构调整:把反馈环涉及的仲裁器和状态寄存器收拢到中间 SLR 的一个 Pblock,跨 SLR 接口全部插入目的侧寄存器,数据流改为单向穿越(SLR0→1→2),消除反向长路径;这一步 WNS 变为 -0.3ns。第三步治高扇出:全局 start 信号扇出 1.2 万,加 max_fanout 复制和局部使能后再收 0.2ns。第四步 phys_opt 开启 aggressive hold/setup 联合优化和多种子,WHS 从 -0.05 修复为正、WNS 收敛到 +0.15ns。最后在慢角(高温低压)和快角(低温高压)双角复核,跨 SLR crossing 报告里所有跨线都是寄存路径,固化 Pblock 和约束进版本库。
复盘要点:真正有效的动作依次是约束正确性、物理结构、架构反馈环、扇出、策略——盲目打拍和刷种子排在最后;每一步都有报告证据而非直觉;收敛后约束和 floorplan 成为资产,后续版本迭代时间从两天缩到半天。这正体现了第十节的流程化思想:把“救火”变成可重复的诊断顺序,时序收敛才不再依赖个人英雄主义,而成为团队可复制的工程能力,这也是本篇希望传递给一线工程师的最终价值。
常见坑对照
| 坑 | 后果 | 正确做法 |
|---|---|---|
| hold 违例降频 | 快角更糟/无效 | 时钟平衡+插延迟+查 CDC |
| 只过常温角 | 极端温度挂 | 慢角快角都零违例 |
| 大片 false path | 掩盖真问题 | 精确路径+逐条注释 |
| Pblock 乱锁 | 工具无处腾挪 | 结构/策略用尽再用 |
| 时钟走普通布线 | 偏斜大 | BUFG/区域时钟专用资源 |
| 跨域漏约束 | 假同步检查/怪违例 | clock_groups + CDC 报告 |
相关与延伸
一句话总结
高阶时序收敛是从'改 RTL'进入'管物理和角点':先用 check_timing/CDC 排除漏约束和假违例,再结构级打拍/retiming/高扇出复制,然后策略级 explore+phys_opt_design,最后才用 Pblock/LOC 把通信密集模块物理锁定到相邻区域缩短布线、并平衡时钟树治偏斜。关键认知两条:①建立违例在慢角(高温低压)、降频可救;保持违例在快角(低温高压)、降频无效甚至更糟——根因多是时钟偏斜、过短同沿路径或漏约束的跨域路径,靠平衡时钟树、插延迟级和正确 set_clock_groups 治理;②签核必须多角点同时零违例(WNS/TNS 慢角建立、WHS/THS 快角保持),否则常温过了极端温度挂。时序例外侧应清晰:跨域用 clock_groups(前提是已有同步器/FIFO 结构)、个别路径用精确 false path/multicycle 并逐条注释,例外是声明结构保证而非消红数字的橡皮。