2. Agilex时序模型与约束基础

Agilex器件采用Intel 10nm SuperFin工艺,其时钟网络在结构上延续了HyperFlex架构的核心思想,但在时钟资源分布、PLL能力和SDC约束语义上都有明显变化。理解Agilex的时序模型,不能只停留在"写SDC约束"的层面,而要先弄清楚时钟信号从哪来、经过哪些资源、最终到达寄存器的路径上存在哪些可建模的延迟与不确定性。本节围绕时钟网络、PLL、全局/区域时钟资源以及SDC约束语法展开,目标是让读者能够为Agilex设计写出结构清晰、语义正确的时钟约束。

一、Agilex时钟网络的分层结构

Agilex的时钟资源可以按覆盖范围分为三个层次:全局时钟(GCLK)、区域时钟(RCLK)和局部/外围时钟。全局时钟网络贯穿整个芯片,能够驱动任意位置的逻辑单元,适合作为系统主时钟、复位同步时钟和跨象限数据通路的参考时钟。区域时钟网络只覆盖芯片的一个象限或一个I/O列,扇出较小、插入延迟更低,适合驱动局部高扇出逻辑或I/O接口的采样时钟。局部时钟则通常由PLL的补偿输出或时钟分频器直接产生,用于特定模块内部的时序收敛。

在约束层面,这三类时钟的差异主要体现在SDC中create_clock与create_generated_clock的源点选择上。全局时钟一般从专用时钟输入引脚或PLL输出定义,区域时钟则常从PLL的某个输出或时钟控制块的输出定义。如果约束时把区域时钟错误地定义在全局网络上,STA会按全局延迟模型计算,导致建立/保持余量被高估或低估。

Agilex 时钟网络分层与 SDC 约束源点 专用时钟输入引脚 CLK_IN / REFCLK I/O PLL 分数分频 / 扩频 Fabric PLL 多输出 / 级联 时钟控制块 CCB 时钟选择 / 分频 / 门控 动态切换与旁路 输出至 GCLK / RCLK 全局时钟网络 GCLK 覆盖全芯片 · 高扇出 · 低偏斜 区域时钟网络 RCLK 象限覆盖 · 低插入延迟 局部 / 外围时钟 模块内 · 补偿输出 · 分频 SDC 约束源点选择 create_clock -name sys_clk -period 2.5 [get_ports clk_in] create_generated_clock -name pll_out -source [get_pins pll|refclk] [get_pins pll|outclk0] create_generated_clock -name rclk_div -divide_by 2 -source [get_pins ccb|clkout] [get_pins ccb|div_out]

二、PLL建模与输出时钟定义

Agilex的PLL分为I/O PLL和Fabric PLL两类。I/O PLL主要服务于高速接口,支持分数分频和扩频时钟;Fabric PLL位于内核逻辑区域,通常有多个输出,可级联到时钟控制块。在SDC中,PLL本身不需要单独约束,但PLL的输入参考时钟必须用create_clock定义,PLL的每个输出则用create_generated_clock定义,并正确指定-source为参考时钟的源点。

一个常见的错误是只定义PLL输入时钟,而忽略输出时钟的生成关系。这样STA会把PLL输出当作独立时钟处理,导致跨时钟域路径被误判为异步路径,或者建立/保持检查完全丢失。正确的做法是:先定义参考时钟,再为每个PLL输出定义生成时钟,并注明分频/倍频关系。例如参考时钟为100MHz、PLL输出为250MHz时,应写为-multiply_by 5 -divide_by 2,而不是简单写一个周期值。

对于扩频时钟,Agilex支持在PLL中启用SSC(Spread Spectrum Clocking)。此时SDC中应使用set_clock_uncertainty为扩频时钟增加额外的抖动余量,通常按扩频深度和调制频率估算。例如扩频深度为-0.5%、调制频率30kHz时,周期抖动可按0.005 × 周期估算,再叠加PLL本身的周期抖动。

三、时钟组与时钟特性建模

时钟组(clock group)是SDC中用于声明时钟之间异步关系的关键约束。Agilex设计中,如果两个时钟来自不同的PLL或不同的输入引脚,且它们之间没有固定的相位关系,就应该用set_clock_groups -asynchronous声明为异步组。这样STA会跳过这两个时钟域之间的建立/保持检查,避免大量虚假违例。

但要注意,异步声明不等于"不需要做跨时钟域处理"。如果两个异步时钟域之间确实有数据传递,仍然需要同步器(如双触发器、握手电路或异步FIFO),并且要用set_false_path或set_max_delay -datapath_only对同步器路径做约束。Agilex的HyperFlex架构中,跨时钟域路径如果经过Hyper-Register,还需要考虑旁路模式下的延迟差异。

时钟特性建模还包括:时钟延迟(set_clock_latency)、时钟不确定性(set_clock_uncertainty)、时钟转换时间(set_clock_transition)以及时钟门控检查(set_clock_gating_check)。在Agilex中,全局时钟网络的插入延迟通常由工具自动估算,但区域时钟和局部时钟的延迟需要根据实际布局手动补充。对于I/O接口,还需要用set_input_delay和set_output_delay描述外部器件的时序要求,并确保参考时钟与数据之间的相位关系正确。

实践提示:在Agilex中,建议先用derive_pll_clocks自动推导PLL输出时钟,再用derive_clock_uncertainty自动添加抖动余量,最后手动补充时钟组和跨时钟域约束。自动推导后务必用report_clocks检查每个时钟的源点、周期和生成关系是否正确。

四、SDC约束的编写顺序与检查

一个可维护的Agilex SDC文件通常按以下顺序组织:先定义基础时钟(输入引脚、PLL参考),再定义生成时钟(PLL输出、分频器输出),然后设置时钟组和异步关系,接着补充输入/输出延迟和跨时钟域约束,最后添加时钟不确定性和转换时间。这个顺序不是强制的,但遵循它可以避免"先约束后定义"导致的源点找不到问题。

编写完成后,用report_clocks检查时钟列表,用report_clock_networks查看时钟网络拓扑,用check_timing确认没有未约束的时钟或未约束的路径。如果check_timing报告"no clock"或"unconstrained path",说明约束覆盖不完整,需要回到时钟定义阶段补充。

# Agilex 时钟约束示例片段
create_clock -name ref_clk -period 10.0 [get_ports clk_in]
create_generated_clock -name pll_core_clk \
  -source [get_pins pll_inst|refclk] \
  -multiply_by 5 -divide_by 2 \
  [get_pins pll_inst|outclk0]
create_generated_clock -name pll_io_clk \
  -source [get_pins pll_inst|refclk] \
  -divide_by 4 \
  [get_pins pll_inst|outclk1]
set_clock_groups -asynchronous \
  -group {ref_clk pll_core_clk} \
  -group {pll_io_clk}
set_clock_uncertainty -setup 0.15 [get_clocks pll_core_clk]
set_clock_uncertainty -hold 0.05 [get_clocks pll_core_clk]

这段约束中,ref_clk是100MHz输入,pll_core_clk是250MHz生成时钟,pll_io_clk是25MHz生成时钟。两个PLL输出被声明为异步组,因为它们服务于不同的接口域。建立不确定性0.15ns和保持不确定性0.05ns是示例值,实际应根据PLL抖动和扩频配置调整。

五、常见约束错误与排查方向

Agilex时序约束中最常见的三类错误是:生成时钟源点写错、时钟组声明过宽、以及输入/输出延迟参考时钟不匹配。生成时钟源点写错会导致STA无法建立正确的时钟树关系,表现为report_clocks中生成时钟的源点显示为"none"或指向错误引脚。时钟组声明过宽会把本应做时序检查的同步时钟也排除掉,造成漏检。输入/输出延迟参考时钟不匹配则会让I/O路径的建立/保持检查基于错误的时钟边沿,导致接口时序误判。

排查时,先用report_clocks -verbose确认每个时钟的源点、周期和生成关系,再用report_clock_groups检查异步组是否覆盖了正确的时钟对,最后用report_timing -from [get_clocks ...] -to [get_clocks ...]抽查关键跨时钟域路径是否被正确约束。对于I/O接口,用report_timing -from [get_ports ...] -to [get_ports ...]确认输入/输出延迟是否生效。

掌握Agilex的时钟网络分层、PLL输出建模、时钟组语义和SDC编写顺序,是后续时序收敛工作的基础。约束写对了,STA报告才有参考价值;约束写错了,后续所有优化都可能建立在错误的前提上。