逻辑综合中多路径时序例外(Multi-cycle Path)的正确配置方法
逻辑综合阶段写 Multi-cycle Path(MCP),最容易踩的坑不是语法,而是只写了 -setup 没写 -hold,导致 hold 检查沿被工具默认挪到 (N-1) 捕获沿,综合器为了修这个被推后的 hold 狂插 buffer,面积 timing 双输。下面这套以 Design Compiler(DC)为主视角,Genus 同理,把 MCP 在综合阶段的配置讲透。
一、先判断这条路径"该不该"是 MCP
不是所有"我俩隔 N 个周期才采一次"都能砍——DC/Genus 认 MCP 的前提是数据发起寄存器和捕获寄存器的使能逻辑能对齐 N 周期节奏,工具才敢放宽 setup 检查。典型候选:
• 流水线里插的"使能链"控制的间歇采样(如 en 每 8 周期才高一次)
• 慢时钟域采快时钟域、且接收侧用 N 分频使能做采样(非 CDC 握手那种)
• 配置寄存器类总线,valid 信号保证 N 周期内稳定
⚠ 纯 CDC 异步(无使能链、无分频对齐)别用 MCP,上 set_clock_groups -asynchronous 或 set_false_path,MCP 救不了亚稳态。
二、同频 MCP:setup/hold 必须成对
DC 里 set_multicycle_path N -setup 不跟 -hold 时,默认行为是:
• setup 检查挪到第 N 个捕获沿
• hold 检查也跟着挪到第 (N-1) 个捕获沿(而不是第 0 个发起沿)
对你的 N-cycle 路径来说,hold 原本应该在发起沿同周期查,现在被推到前一个捕获沿,比想要的严一倍,综合器白插 buffer。
# 错误:只写 setup
set_multicycle_path 3 -setup -from [get_pins u_dat/ff_d0_reg/CK] \
-to [get_pins u_dat/ff_d3_reg/D]
# 正确:同频 3-cycle 标准配对
set_multicycle_path 3 -setup -from [get_pins u_dat/ff_d0_reg/CK] \
-to [get_pins u_dat/ff_d3_reg/D]
set_multicycle_path 2 -hold -from [get_pins u_dat/ff_d0_reg/CK] \
-to [get_pins u_dat/ff_d3_reg/D]
规律一句:同频 MCP,setup = N,hold = N-1,成对写。report_constraint -all_violators 跑完看 hold 那栏,如果 3-cycle 路径 hold 还爆,先回来看是不是漏了 -hold。
三、跨频 MCP:-start / -end 按方向带
跨时钟 MCP 不加 -start/-end,工具默认两个时钟都按捕获时钟算周期,方向反了就白设。
场景 多周期针对谁 setup hold
快→慢(N 针对快) 发起时钟(快) -setup -start -hold -start
慢→快(N 针对慢) 捕获时钟(慢) -setup -end -hold -end
# 例:CLK_FAST=500MHz(2ns),CLK_SLOW=125MHz(8ns),慢采快 N=4(针对慢钟4周期=快钟16周期)
# 但这里"4-cycle"按慢钟表述更直观,DC 里 -end 锚捕获侧
set_multicycle_path 4 -setup -end -from [get_clocks CLK_FAST] -to [get_clocks CLK_SLOW]
set_multicycle_path 3 -hold -end -from [get_clocks CLK_FAST] -to [get_clocks CLK_SLOW]
Genus 里语法一致,但跨时钟 MCP 在 Genus 综合后要再跑一次 check_timing,它比 DC 更敏感于 capture 侧时钟树还没长出来的阶段——综合期报"Uncertainty derived from clock tree"是正常的,sign-off 阶段 PT 里再核一次就行。
四、同点多模式 / 多周期:-add 别忘了
一个端点同时挂多个时钟(功能模式 + DFT / 扫描模式),MCP 必须 -add,否则后写的覆盖先写的:
set_multicycle_path 2 -setup -from [get_clocks FUNC_CLK] -to [get_clocks FUNC_CLK] -add
set_multicycle_path 2 -hold -from [get_clocks FUNC_CLK] -to [get_clocks FUNC_CLK] -add
# DFT 模式另起一组,不-add 就冲掉上面
set_multicycle_path 1 -setup -from [get_clocks TEST_CLK] -to [get_clocks TEST_CLK] -add
五、综合→STA→PR 三段约束一致性
综合阶段写的 MCP,DC 的 .sdc 要原样喂给 PT 和 ICC2/Innovus,别在 PT 里重写一套——常见事故是:
• 综合里 set_multicycle_path 3 -setup(漏 hold)→ DC 插了一堆 buffer 修 hold
• PT 里某人补了 -hold 2 → 突然 WNS +0.8 ns,但综合网表里那些 buffer 已经白插了,面积回不来
稳妥做法是:SDC 归 SDC,综合/STA/PR 三段共用同一份,模式切换用 if {${MODE}=="func"} ... 包起来,别各写各的。
六、验:综合阶段就能抓的漏
DC 里 check_timing 重点扫三类:
• "Multicycle path without hold" —— 只写了 setup 的,必须回补
• "Unconstrained paths through multicycle endpoints" —— MCP 的 to 端点还有别的路径没约束,容易被漏
• "No common clock" on MCP —— 跨时钟 MCP 却没给 -start/-end,工具可能按错方向算
check_timing -verbose > check_timing.rpt
report_timing -setup -max_paths 20 -through [get_pins u_dat/ff_d3_reg/D] > mc_path_setup.rpt
report_timing -hold -max_paths 20 -through [get_pins u_dat/ff_d3_reg/D] > mc_path_hold.rpt
两段 report 里 slack 同正、setup/hold 检查沿间隔符合 N 周期,MCP 才算锁住。
综合里 MCP 的真谛:同频必配对 setup/hold、跨频按快慢方向带 -start/-end、多模式 -add、SDC 三段共用一份。漏任何一条,不是 timing 假收敛就是面积白烧,PT 里查出来的时候已经晚了。





