FPGA 输入输出延迟 IDELAY/ODELAY:抽头、参考时钟与源同步对齐
做低速接口时,FPGA 的 IO 脚「进来就能用」;一旦上到几百 Mbps 的源同步接口,PCB 上几根走线长短差出几个皮秒,采样窗口就偏了。Xilinx 7 系列在 IO 管脚旁放了一格可以 32 级精细调节的延迟线——IDELAYE2/ODELAYE2,配上 IDELAYCTRL 连续校准。本文讲清 FPGA 输入输出延迟 IDELAY/ODELAY 的机制、分辨率口径和对齐方法。时钟网络基础见 FPGA 时钟区域与 BUFG,管脚电平与 bank 供电见 FPGA IO Bank 与 VCCO 和 LVCMOS 电平标准。
本文要回答的问题
- 走线等长不是在 PCB 上做了吗,为什么 FPGA 内部还要可调延迟?
- 一个 tap(抽头)到底延迟多少皮秒?它和 IDELAYCTRL 的参考时钟是什么关系?
- IDELAYE2 的 fixed、variable、var_loadable 几种模式行为差在哪?
CE、INC、LOAD怎么动? - 为什么用了延迟原语就必须例化 IDELAYCTRL,忘了会怎样?
- 源同步接口里数据和随路时钟一起进 FPGA,靠什么把采样沿挪到数据眼中央?
- IO 延迟、普通布线延迟、MMCM 相移三者各管哪一段,什么坑最常见?
下面这张流程卡先给一条工程主线:从管脚旁的延迟抽头出发,经参考时钟校准、抽头计数、采相对齐,到运行期的动态维护,后文逐节展开。
读这张卡要注意它既是硬件位置顺序,也是调试顺序:先确认延迟线在通路里的位置,再确认标尺(参考时钟)准不准,然后才谈调几个抽头。很多调不通的案例卡在第 2 步——抽头在动,但每个抽头代表多少皮秒从一开始就配错了。
一、为什么 IO 需要皮秒级的可调延迟
先看没有可调延迟时会发生什么。数字接口的可靠采样依赖一个朴素条件:时钟采样沿到来时,数据必须已经稳定,并保持足够时间,即满足建立时间与保持时间。片内同步设计里,这个条件由时序分析和时钟树平衡保证;而信号一旦走出芯片,三件事情就脱离了时序工具的掌控。
第一是 PCB 走线偏斜(skew)。 8 位数据总线加一根随路时钟,即使布线工程师努力等长,过孔、绕线、BGA 扇出仍会让各根线的传播时间相差几十到几百皮秒。对 25 MHz 的接口这无所谓(一个比特周期 40 ns),对 500 Mbps 的 DDR 接口,单位间隔只有 2 ns,几十皮秒的偏斜就开始实质吃掉时序裕量。
第二是源同步系统的固有相位关系。 源同步接口(并行 ADC/DAC、CMOS 图像传感器、DDR 显存的前身)不传单独的恢复时钟,而是发送端把时钟和数据一起发出来,时钟边沿刻意落在数据跳变沿附近——具体落在眼图的哪个位置,取决于发送端设计和走线长度。FPGA 收到后必须自己把这个沿「挪」到数据眼中央。
第三是工艺、电压、温度漂移。 一根固定缓冲器的延迟随 PVT 变化,可以差出相当可观的比例。要在量产和温变下都保持窗口,延迟线必须被连续校准,而不是出厂一个固定值。
普通布线延迟解决不了这件事:布线延迟是布局布线的副产品,粒度粗、不可在运行期按管脚独立微调,时序工具也不会为了对齐外部数据眼去逐根走线调几百皮秒。于是 FPGA 厂商在每个 IO 块里塞进了专用的、可逐级数字选择的延迟单元。这就是 FPGA 输入输出延迟 IDELAY/ODELAY 的定位:它是管脚旁的一小段「延迟游标」,粒度细到一个抽头几十皮秒,且可以静态配置或运行期动态拨动。
二、延迟原语在 IO 通路里的位置
7 系列器件中,输入延迟原语是 IDELAYE2,输出延迟原语是 ODELAYE2,二者结构对称:都是 32 级(抽头值 0–31)的延迟链,既可以作用在通用 IO 通路上,也可以与 ISERDESE2/OSERDESE2 串并转换器级联,服务高速源同步接口。IDELAYE2 位于输入缓冲器 IBUF 之后、ILOGIC/ISERDESE2 之前;ODELAYE2 在输出通路上位于 OLOGIC/OSERDESE2 与输出缓冲器之间。延迟链的「标尺」由同 bank 组内的 IDELAYCTRL 提供。
读这张图抓住红色节点:真正被调节的只有 IDELAYE2 那一小段,它夹在缓冲器和采样逻辑之间,不改变信号的逻辑内容,只挪动它到达采样点的时间。紫色 IDELAYCTRL 不传递数据,它给同组所有延迟链提供校准基准——没有它,抽头仍可计数,但每级的实际延迟会随电压温度漂移。
输出方向同理:OSERDESE2 并转串之后的数据经 ODELAYE2 延迟再出脚,用来补偿输出时钟与数据间的偏斜(output delay 还可配成作用于输出时钟路径)。一条双向通路可以同时例化输入、输出两个延迟原语,互不影响。
三、四种工作模式与抽头动作
IDELAYE2 的行为由 IDELAY_TYPE 参数决定,共有四种配置口径;输出原语的模式集合类似。它们的差别只在一件事:抽头值在什么时候、由谁、以什么方式改变。
| 模式 | 抽头初值 | 运行期能否改 | 改变方式 | 典型用途 |
|---|---|---|---|---|
FIXED | 配置时 IDELAY_VALUE 写死 | 否 | 重新下载位流 | 板级偏斜已知且固定的一次性补偿 |
VARIABLE | 0(或配置值) | 能 | CE+INC 逐抽头增减 | 上电训练一次,之后不动 |
VAR_LOADABLE | 任意 | 能 | LD 直接装入 5 位抽头值,也可增减 | 需要跳到任意抽头的眼图扫描、动态校准 |
DATAIN(输入数据路径选择口径) | —— | —— | 选择延迟对象来自 IO 脚还是内部路径 | 内部反馈、零延迟 hold 修正等特殊接线 |
控制脚的动作要成对理解:CE 是计数使能,在时钟 C 沿有效;INC 为高表示加一抽头、为低表示减一抽头,所以 VARIABLE 模式下「往眼中央挪」就是一串带方向的单步脉冲。LOAD(VAR_LOADABLE 下配合 REGRST 与 5 位 CNTVALUEIN)则是把目标抽头值一次装入,不必从 0 一步步拨,新值在 C 时钟沿之后经若干拍生效,CNTVALUEOUT 回读当前实际抽头,LDPIPEEN 决定装入值是否先经一级流水线寄存。所有动态脚都由用户时钟 C 驱动,RST 把抽头复位到配置初值。
一段最小的可变延迟例化骨架如下,真实工程直接用原语模板或 SelectIO Wizard 生成,参数按器件用户指南填。
IDELAYE2 #(
.IDELAY_TYPE("VAR_LOADABLE"),
.DELAY_SRC("IDATAIN"),
.IDELAY_VALUE(0),
.HIGH_PERFORMANCE_MODE("TRUE"),
.SIGNAL_PATTERN("DATA")
) u_idelay (
.IDATAIN(d_from_pad),
.DATAOUT(d_delayed),
.C(clk_cal),
.CE(1'b0),
.INC(1'b0),
.LD(tap_ld),
.REGRST(1'b0),
.LDPIPEEN(1'b0),
.CNTVALUEIN(tap_value),
.CNTVALUEOUT(tap_current),
.CINVCTRLSEL(1'b1)
);需要强调两个上限语义:抽头值是环形计数还是到顶停住、增减一拍生效还是两拍生效,不同模式/不同原语版本的细节以 7 Series Libraries Guide 的真值表为准;HIGH_PERFORMANCE_MODE 打开会牺牲一点功耗换更小的 duty cycle 失真,高速时钟/选通信号建议开。
四、IDELAYCTRL:参考时钟决定每个抽头的皮秒数
延迟链由一串延时单元构成,单元延时受工艺和温压影响。IDELAYCTRL 的工作就是用一个干净的参考时钟连续测量、补偿这条链,使「一个抽头」在全温范围内维持约等于参考时钟周期某个固定分数的延迟。因此 tap 分辨率不是独立常量,而是 REFCLK 频率的函数,7 系列口径的近似关系如下表(约数,仅用于建立量级直觉,具体器件与速度等级以数据手册的 delay per tap 参数为准)。
| REFCLK 频率 | 参考周期 | 每抽头延迟(约) |
|---|---|---|
| 200 MHz | 5.00 ns | 约 52 ps/tap |
| 300 MHz | 3.33 ns | 约 78 ps/tap |
读这张表的正确姿势:频率越高,每个抽头越「粗」——反直觉但符合结构,校准基准周期变短,分给每一级的时间份额变大;想要更细的分辨率就选较低的合法参考频率。REFCLK 必须落在器件支持的频率区间内并由全局/区域时钟缓冲驱动,频率和抖动都有要求,常用 MMCM/PLL 专门生成一路(时钟资源的分工见 FPGA 时钟区域与 BUFG)。
使用规则有四条,每条都对应一类真实故障:
- 一个 bank 组一个 IDELAYCTRL。 7 系列中若干 IO bank 共享一个 IDELAYCTRL 实例(按器件的 bank 组划分),组内任何一个 bank 用了 IDELAY/ODELAY,就必须例化它;一个组内不要重复例化。
- 先 RDY 后用延迟。 上电后 IDELAYCTRL 需要一段校准时间,
RDY拉高才表示抽头标尺稳定。用户逻辑应在复位/训练流程里等RDY,期间不要装入抽头或开始接收数据。 - REFCLK 必须连续稳定。 参考时钟停振或频率不对,
RDY会拉低,延迟线失去校准——表现为温漂变大、抽头对应的皮秒数整体错误。 - 忘了例化的后果不是报错而是漂移。 工具在某些配置下能推断或直接 DRC 报错拦下;但即便位流生成成功,未校准的抽头值随温压漂移,接口会表现为「冷机能跑、热了花屏」这类最难定位的症状。
读图注意绿色主干与红色回环:正常路径是上电、等就绪、初装、训练、运行;一旦运行中 RDY 掉下去(参考时钟抖动、供电跌落),就要走红色回环重来。把 RDY 接进用户逻辑而不是悬空,是产品设计和 demo 的分水岭。
五、源同步采相对齐:随路时钟与抽头怎么配合
有了游标之后,源同步接收的完整套路是:随路时钟进专用时钟缓冲驱动采样时钟树,数据进 IDELAYE2 再进串并转换器,二者在 ISERDESE2 的采样点上完成相位对齐。
随路时钟在 7 系列里通常走 BUFIO(只覆盖一个 IO 列、专供 ISERDESE 时钟脚,偏斜极小)和 BUFR(区域时钟,可带分频,驱动用户逻辑)的组合;BUFIO 用于高速串行采样本身,BUFR 分频后的并行时钟用于把解出的数据交给内部逻辑。数据眼的左右边界这样找:固定随路时钟相位,从抽头 0 开始逐抽头增加延迟,同时让发送端发训练图样,统计每个抽头下的误码;能正确接收的抽头区间就是「眼」,最后把抽头定在区间中点。这一过程称为入眼训练(eye training)或写入均衡式校准,产品里上电训练一次,裕量紧张的接口还要周期性复测。
读这张波形抓住一个动作:随路时钟的采样沿(图中时钟上升沿)原本压在原始数据的跳变附近,偏左时建立时间不足;把数据整体延迟若干抽头后,跳变沿右移,采样沿落进两个跳变沿中间的数据稳定区——这就是「居中」的全部含义。注意被延迟的对象既可以是数据,也可以在需要时延迟随路时钟本身,取决于接口方向和窗口形状,两种做法的相位效果相反,训练前先固定一种口径。
数据对正之后还有一道「字界」问题:串并转换器不知道一串比特从哪里算一个字节,需要靠训练图样做 bitslip(比特滑移)对齐并行字边界。这属于 ISERDESE2/OSERDESE2 串并转换的主题,本文只点出它在抽头对齐之后进行:先保证每个比特采得对,再保证字节切得齐。高速 DDR 接口的完整接收链(IDELAYE2 + BUFIO/BUFR + ISERDESE2 + bitslip)会在后续串并转换专题中展开。
六、IO 延迟、布线延迟与 MMCM 相移的分工
工程上最常见的混淆是「挪相位」有三套机制,各管一段,不能互相替代。
| 维度 | IDELAY/ODELAY | 普通布线延迟 | MMCM/PLL 相移 |
|---|---|---|---|
| 作用位置 | 管脚缓冲器旁,逐管脚独立 | 信号路径上的连线与 LUT,全局分布 | 时钟发生器输出,作用于整条时钟树 |
| 调节粒度 | 约 50–80 ps 一抽头,32 级 | 不可刻意控制,工具决定 | 时钟周期的分数,动态相移分辨率更粗 |
| 作用范围 | 单个 IO 信号 | 单个内部信号 | 该时钟域的全部负载 |
| 运行期可调 | 可(variable/loadable) | 否 | 可(动态相移端口) |
| 校准 | IDELAYCTRL 连续校准 | 静态时序分析覆盖 | MMCM 内部锁定 |
| 解决的问题 | 板级走线偏斜、源同步入眼 | 内部逻辑路径时序 | 时钟域相位、大粒度时钟对齐 |
一句话分工:板级、逐脚、皮秒游标找 IO 延迟;整片时钟域的相位搬动找 MMCM;内部数据路径的时序收敛交给布局布线,不要想着拿抽头去修内部时序违例。 三者也协作:典型源同步接收里 MMCM 先生成相位合适、频率合规的 IDELAYCTRL 参考时钟和区域时钟,IO 延迟负责每根数据线的精细游标。与 Intel/Altera 器件做泛化对比时,其 IO 延迟单元(IO_DELAY 口径)同样是分级延迟链加校准模块、同样绑定 bank 与专用校准时钟,概念可迁移,但抽头数、分辨率公式、原语名与复位口径完全不同,跨平台代码不要直接照搬。
七、常见坑清单
- REFCLK 频率接错。 约束里写 200 MHz、实际 MMCM 配成别的频率,工具未必报错,但每个抽头的皮秒数整体偏离,训练出的抽头值换一块板或换温度就失效。先量频率再训练。
- 同 bank 多电压与原语可用性。 延迟原语支持哪些电平标准、哪些 bank 类型有约束,与 FPGA IO Bank 与 VCCO 的供电规划绑在一起;电平标准本身的选择见 LVCMOS 电平标准,管脚规划阶段就要核,不要等上板。
- 忘记等 RDY。 复位释放后立刻装入抽头并开始采样,校准未完成期间的行为没有保证。复位序列里显式等待
RDY。 - 把 RDY 悬空。 运行中参考时钟出问题无从知晓,接口花屏却没有任何状态可查。
- 抽头调到边界值当锁定点。 训练出的可靠区间若贴着 0 或 31,说明延迟预算已经不够(走线偏斜过大或分辨率不合适),正确做法是回板级查等长或换参考时钟口径,而不是量产时赌温度。
- 动态校准与业务接收抢同一条链路。 入眼训练期间数据无效,动态重调必须安排在空闲期或配合接收端的失锁/重训练协议,不能在正常流量中直接拨抽头。
- 输出方向只调了数据没调时钟。 ODELAY 的补偿对象要按发送端偏斜结构成对规划,单补一路会把对端的窗口推歪。
这一篇在知识体系里的位置
本文属于 FPGA IO 与高速接口支线的「管脚时序」环节。时钟侧的上游基础是 FPGA 时钟区域与 BUFG:全局时钟、区域时钟与 BUFIO/BUFR 的资源划分都在那里;电平与管脚侧是 FPGA IO Bank 与 VCCO 和 LVCMOS 电平标准。下游一篇是 ISERDESE2/OSERDESE2 串并转换(抽头对齐之后的 bitslip 与字界对齐),再往后是 DDR 读写均衡这类完整接口训练专题;时序收敛方法与约束写法则归入 XDC 管脚与时序约束 与 时序报告入门。
总结
FPGA 输入输出延迟 IDELAY/ODELAY 是放在每个 IO 管脚旁的 32 级可调延迟链:IDELAYE2 管输入、ODELAYE2 管输出,FIXED/VARIABLE/VAR_LOADABLE 决定抽头是写死、逐拍增减还是直接装入;抽头的皮秒标尺由同 bank 组唯一的 IDELAYCTRL 用连续运行的 REFCLK 校准,200 MHz 约 52 ps、300 MHz 约 78 ps 只是约数、以数据手册为准,例化后必须等 RDY 再用。源同步接收靠 BUFIO/BUFR 驱动随路时钟、逐抽头扫出数据眼并锁定在中央,字界对齐再交给后续串并转换环节。记住分工边界:逐脚板级偏斜找 IO 延迟,整域相位找 MMCM,内部时序找布局布线,三套机制各管一段。