先说个我自己的经历。去年做一块基于FPGA的LVDS采集板,平时Debug时用50Mbps低速模式跑得稳如老狗,结果切到700Mbps高速档位后,板子开始随机冒误码,偶尔整帧丢数据。刚开始我怀疑是后端接的RK3566那边MIPI转LVDS配置有问题,翻了一整天驱动,最后才发现问题出在前端LVDS接收链路上——ISERDESE2的采样点根本没有落在眼图中心,BITSLIP也在错误的位置上找字边界。这件事让我彻底明白一个道理:LVDS高速传输不是把ISERDESE2和OSERDESE2例化上就完事,真正决定成败的是IDELAY2的延迟校准和BITSLIP的位滑动对齐。这篇就专门写这个——如何用一套自动校准机制,让ISERDESE2和OSERDESE2在LVDS链路上跑得稳、跑得准,顺便把IDELAY2和BITSLIP的配合逻辑讲透。
1. LVDS接收为什么这么难调:ISERDESE2和OSERDESE2只是起点
很多做过LVDS接口的工程师都有这种体验:设计参考原理图时看着挺简单,FPGA引脚上拉个100欧匹配电阻,差分对直连进去,代码里例化一个ISERDESE2做解串,完事。但真正跑起来才发现,时序问题全藏在细节里。
1.1 眼图窗口是怎么被一步步"吃"掉的
LVDS链路上,发送端OSERDESE2把并行的8位数据转成串行比特流,经过PCB走线到接收端ISERDESE2。理想情况下,每个比特的窗口宽度就是1/数据率。比如700Mbps,单bit宽度大约是1.43ns。但实际链路上会有几个损耗源:
PCB走线长度差,差分对内正负线长度不匹配,会产生相位偏移。LVDS通常要求对内等长控制在5mil以内,但实际板厂签核时经常差个几十mil。别小看这几十mil,FR4板材上信号传播速度大约是6mil/ps,30mil的差异就是5ps的偏移,高速时能明显吃掉眼高。
器件批次差异,发送端驱动器的上升沿速率不一致,不同批次的LVDS Driver特性差异会导致相同的PCB设计呈现不同的时延。
温度与电压漂移,这个最讨厌。板子刚上电和跑半小时后,FPGA内部逻辑延迟、IOB延迟、IDELAY2的tap单位延迟都会随温度电压变化。校准如果只做一次,运行一段时间后可能就偏出眼图中心了。
这些误差累积下来,接收端ISERDESE2的采样时钟沿很可能就没有落在数据的稳定区域,而是在数据跳变沿附近徘徊。这时候误码的随机性就体现出来了,时好时坏,很难复现。
1.2 为什么需要IDELAY2和BITSLIP两个维度来校准
这是我当时最大的认知误区,以为采样点不对就调延迟,延迟调完就万事大吉。实际上LVDS接收对齐要解决两个完全不同层面的问题:
第一个层面是bit级的相位对齐。ISERDESE2在高速时钟沿采样串行数据,我们要确保采样时刻落在每个bit的眼图中心。这个由IDELAY2来调整,它可以对输入信号插入可编程的延迟,精度通常是一个tap约78ps(7系列)。调整IDELAY2,相当于在时间轴上左右平移采样点。
第二个层面是word级的字边界对齐。ISERDESE2把串行数据转成并行数据时,并行输出的起始位置是任意的。比如1:8模式下,发送端发送的8-bit并行数据为D0~D7,但接收端解出的并行数据可能是D3~D0再拼接上后面的D7~D4,总之是旋转错位的。BITSLIP就是干这个的,通过滑动并行数据的位序来找到正确的字边界。
这两个维度缺一不可。只调BITSLIP而不调IDELAY2的话,如果采样点不在眼图中心,就算字边界对了,还是会有bit采样错误。只调IDELAY2而不调BITSLIP的话,每个bit都采得很准,但并行字节还是对不齐。所以自动校准机制的完整流程必然是:先扫IDELAY2找眼图中心,再滑BITSLIP找字边界。
这个逻辑想通之后,整个自动校准框架就清晰了。下面先拆解每个原语的具体职责,再讲状态机的完整实现。
2. 原语角色拆解:这四个家伙在链路里各管什么事
有很多刚接触LVDS接收的同学搞混ISERDESE2和IDELAY2的关系,其实两者完全不在一个层次上。ISERDESE2是解串器,负责把串行bit流变成并行数据;IDELAY2是延迟链,负责对单个bit的采样时刻进行微调;OSERDESE2是发送端的并串转换器;BITSLIP是ISERDESE2内部的一个功能端口,负责字对齐。
2.1 ISERDESE2与OSERDESE2的收发通道搭建
先看完整的收发链路。发送端FPGA内部并行数据进入OSERDESE2,在高速时钟驱动下按bit顺序发出去;接收端ISERDESE2用DDR模式在时钟上下沿分别采样,把串行数据拼成并行数据输出。
ISERDESE2有几个关键端口需要特别注意。D是串行数据输入,OCLK是高速采样时钟(通常等于线路速率),CLK是并行域时钟(OCLK除以并行宽度),CE是时钟使能,RST是复位。在DDR模式下,1:8配置意味着每个CLK周期输出8位并行数据。
例化时有个容易踩的坑:NUM_CE和INTERFACE_TYPE必须匹配。如果用INTERFACE_TYPE=NETWORKING,NUM_CE只能等于1;如果设成2,综合时会报错。另外DATA_RATE=DDR时,CLKDIV的频率必须是OCLK频率的1/8(对应1:8模式),这个比例必须严格满足,否则并行数据会出现错位采样的现象。
OSERDESE2相对简单一些,把并行数据在OCLK的上下沿依次发送出去。有一点值得注意:OSERDESE2的T_OUT端口用来控制三态输出,普通LVDS数据发送直接固定为0即可,但如果是双向总线就需要动态控制。我之前做过一次LVDS双向传输,忘记把T_OUT拉低,结果发送端一直被三态隔离,信号根本出不去。
2.2 IDELAY2的配置模式选择:为什么自动校准必须用可加载模式
IDELAY2有几种工作模式,选择错误会让自动校准机制根本无法实现。
| 模式 | 延迟值可否动态修改 | 适用场景 |
|---|---|---|
| FIXED | 否,综合时固定 | 时延已通过仿真约束确定,不需要调整 |
| VARIABLE | 可以通过CE和INC动态增减 | 需要运行时微调,但校准逻辑较复杂 |
| VAR_LOAD | 可以通过CNTVALUEIN直接加载任意值 | 自动校准推荐,支持跳变到指定tap |
| VAR_LOAD_PIPE | 带流水线寄存器的VAR_LOAD | 需要多个延迟值同时更新的高速场景 |
我推荐自动校准用VAR_LOAD模式,原因很直接:扫描眼图时需要在不同tap值之间快速跳变,VARIABLE模式的移位加减操作要一个一个tap地走,扫描32个点要32个时钟周期,虽然也不慢,但控制逻辑不直观;而VAR_LOAD模式直接把目标tap值写到CNTVALUEIN端口,一个周期就能跳到目标位置,状态机写起来干净利落。
IDELAY2的tap分辨率在7系列上大约是78ps,这是由参考时钟频率(通常是200MHz)和工艺参数决定的。一个UI(Unit Interval,即1bit宽度)在700Mbps下约1428ps,也就是说一个bit窗口大约覆盖18个tap。假设你扫到tap12到tap22之间误码率都不高,说明眼图中心大致在tap17附近,那最佳采样点就设在这个区间中点,这个逻辑后面在扫描状态机里会用到。
2.3 BITSLIP到底是怎么"滑动"的
BITSLIP是ISERDESE2的一个特殊功能输入端口。当BITSLIP信号在CLKDIV的上升沿被拉高一个周期,输出的并行数据会向左移动一位,也就是把数据宽度范围内的bit整体偏移1bit,等效于把串行输入流的采样起始点推进一个bit。
举个具体例子,1:8模式下,如果当前并行输出是{D7,D6,D5,D4,D3,D2,D1,D0},拉高一次BITSLIP后变成{D8,D7,D6,D5,D4,D3,D2,D1},注意这里的D8是下一个串行bit。所以每次BITSLIP操作相当于让并行数据的字边界向后错一位。
这意味着什么?在1:8模式下,连续执行8次BITSLIP操作,并行输出又会回到原来的位序(因为8bit一循环)。所以在字对齐检测逻辑中,最多滑动8次就能找遍所有可能的字边界。这也是为什么训练模式不能太短,至少要能保证在这8次滑动中能检测到对齐成功。
一个工程经验:BITSLIP不要在数据有效传输期间随意触发,否则当前并行输出会瞬间错位,导致后端FIFO或状态机收到脏数据。BITSLIP应该只在训练模式下使用,正常数据阶段必须保持BITSLIP端口为低电平。
3. 自动校准状态机设计:从眼图扫描到BITSLIP字对齐的完整流程
接下来是这篇的核心。自动校准机制看起来复杂,其实拆开就是一台状态机加两个子模块:眼图扫描模块和字对齐模块。整体流程是发散训练序列,接收端先扫IDELAY2找到最佳采样点,然后锁定延迟值,再通过BITSLIP找到字边界,最后进入锁定状态。
3.1 校准状态机的状态定义与转换
我习惯把校准状态机设计成5个状态,状态定义如下。
| 状态 | 名称 | 主要操作 |
|---|---|---|
| S0 | IDLE | 等待校准时序,空闲时链路保持复位 |
| S1 | DELAY_SCAN | 发送训练序列,扫描IDELAY2 tap值 |
| S2 | DELAY_LOCK | 锁存最佳tap值,准备字对齐 |
| S3 | BITSLIP_ALIGN | 维持最佳tap,循环滑动BITSLIP |
| S4 | LOCKED | 校准完成,切换正常数据模式 |
状态转换条件也很明确:IDLE收到校准使能信号后进入DELAY_SCAN;DELAY_SCAN扫描完整个tap范围并计算出最佳值后进入DELAY_LOCK;DELAY_LOCK把最佳tap值写入IDELAY2,等待延迟链稳定后进入BITSLIP_ALIGN;BITSLIP_ALIGN检测到字对齐成功,或者滑动次数超过阈值(1:8模式下最多8次)后进入LOCKED;LOCKED状态下如果误码率持续超过门限,回到DELAY_SCAN重新校准。
这个状态机看起来简单,但一个关键点是:状态转换时机的控制。尤其是在DELAY_SCAN切换到DELAY_LOCK、以及BITSLIP_ALIGN切换回数据模式时,不能简单地在某个cycle后直接跳转,而是要和发送端有一个握手协议。具体做法是发送端和接收端之间设置一个训练使能信号和训练完成信号,二者配合完成模式切换。
3.2 眼图扫描模块:不是简单找第一个无错点
DELAY_SCAN状态下的操作是纯粹的扫描统计。核心思路是:外部控制模块通过寄存器接口写入一个起始tap值,然后触发扫描,接收端对每个tap值统计固定窗口长度内的误码情况,扫描完成后把统计结果通过寄存器总线回传。
这里的难点在于"固定窗口长度"怎么选。太短了,偶发误码会被平均掉,导致误判;太长了,整个扫描时间会特别久。以700Mbps为例,如果每个tap统计8K字节(约91us),32个tap全扫完大约2.9ms,这个时间可以接受。如果链路速率更低,统计时间会等比拉长,可以考虑动态调整统计长度。
扫描得到的结果是一组误码率数据,需要注意的坑是:不要选"误码率最低的单点"作为最佳tap值。因为单点无错可能是偶然,而且实际工作环境会漂移,选在窗口边缘很容易跑飞。正确做法是找出连续的、误码率为0的tap区间(通常叫"无错窗口"),然后取窗口中心作为最佳tap值。如果窗口宽度不足4~5个tap(约300ps+),说明信号质量或PCB设计可能有问题,这时候即使校准成功,长期稳定性也堪忧。
这个窗口取中心的逻辑在设计上可以用一个简单的比较器加寄存器组实现。对每个扫描点记录误码数,如果连续N个点误码数为0,就记录窗口起点;找到所有连续零误码窗口后,选最宽的一个,取中点。
3.3 字对齐模块:BITSLIP循环滑动与对齐检测
当IDELAY2的延迟锁定后,进入BITSLIP_ALIGN状态。发端继续发送训练序列,接收端的任务是通过BITSLIP操作找到正确的字边界。
最直接的做法是:接收端先拉高BITSLIP一次(滑动1bit),然后连续接收并比对训练序列。如果比对失败,再滑动一次,再比对,直到对齐成功。因为1:8模式最多滑动8次必然回到初始位置,最多尝试8轮。
这里有个提速技巧:不需要每次对比完整个训练序列。可以先对比前几个字节,如果前2字节都匹配不上,直接进入下一次滑动。一个典型的检测逻辑如下:
always @(posedge clk_div or posedge rst) begin if (rst) begin slip_cnt <= 3'd0; align_done <= 1'b0; end else if (state == BITSLIP_ALIGN && !align_done) begin if (align_check_fail) begin slip_cnt <= slip_cnt + 1'b1; bit_slip_pulse <= 1'b1; end else if (align_check_pass) begin align_done <= 1'b1; bit_slip_pulse <= 1'b0; end end end注意bit_slip_pulse只能拉高一个CLKDIV周期,不能一直保持高电平,否则ISERDESE2会每周期都滑动一位,永远对齐不上。
训练序列选择也有讲究。不能用全0、全1或者周期太短的pattern,比如01010101这种,因为这种pattern在滑动1bit后看起来和原来一样,对齐检测根本区分不出来。推荐使用类似0x1F、0xE0交替的pattern,或者直接用PRBS序列。PRBS的优点是随机性接近真实数据,但检测逻辑稍复杂;固定pattern简单可靠,建议先从固定pattern开始调通,再换成PRBS做压力测试。
3.4 校准总线接口与上层交互
一套自动校准机制要真正可用,必须能给外部CPU(比如ARM)或上位机提供控制与状态接口。通常做法是挂一组寄存器,几个关键寄存器如下:
| 偏移 | 名称 | 读写 | 功能描述 |
|---|---|---|---|
| 0x00 | CAL_CTRL | RW | 校准使能、启动校准、模式选择 |
| 0x04 | CAL_STATUS | RO | 校准状态、锁定标志、错误计数 |
| 0x08 | IDELAY_VALUE | RW | 手动或自动模式下的tap值 |
| 0x0C | SCAN_RESULT | RO | 最优tap值、无错窗口宽度 |
| 0x10 | ERROR_CNT | RO | 校准后的累计误码数 |
软件侧的流程是写启动位,然后轮询状态位,等校准完成后读取结果。这套接口我前后做过两个版本,第一个版本只做了自动校准没有开放手动模式,结果调试PCB信号质量时很痛苦,每次想固定一个tap值看波形都做不到,后来加了IDELAY_VALUE寄存器支持手动覆盖,Debug效率大幅提升。所以强烈建议自动校准模块务必保留手动读写延迟值和手动触发BITSLIP的调试后门。
4. 训练序列、误码统计和时序细节:决定校准成败的隐藏因素
前面把状态机和模块结构讲清楚了,但这套机制能不能稳定工作,还取决于一些很容易被忽略的细节。这章专门把这些隐藏因素翻出来晒一晒。
4.1 训练序列模式的设计选择
训练序列在自动校准中承担两个任务:一是提供误码统计的参考pattern,二是作为字对齐检测的基准。因此对训练序列有两条硬性要求:
误码统计时,训练序列要有足够的随机性,不能周期太短,否则部分bit的翻转频率过低,误码无法暴露。说白了就是20101010这种pattern只会锻炼到第0和第1bit的采样,其他bit采错也发现不了。
字对齐检测时,训练序列在滑动1~7bit之后必须明显失配,否则对齐检测会得出多个假阳性结果。
推荐的做法是让训练序列由两级组成:先发一段固定训练头(比如连续发送0x1F、0xE0交替pattern),用于识别字边界;再发一段PRBS15序列,用于精确的误码统计。字边界一旦锁定,接收端就进入PRBS校验状态,通过本地同样产生PRBS15序列做比对,就可以得到精准的误码率。
PRBS生成在FPGA中实现非常简单,一个15级LFSR就够了。关键是要保证发送端和接收端的PRBS初始状态一致,否则误码统计会误报。最简单的方案是在训练头中约定一个同步时刻,比如接收端检测到连续4个正确的0x1F、0xE0后,按固定的时序关系去复位本地PRBS生成器,这样两端PRBS就能对齐。
4.2 误码统计窗口参数的工程取值
误码统计不能全凭感觉设,要根据期望的误码率量级来反推。工程上通常要求校准后的误码率低于1e-12量级,但校准过程中不可能统计那么多数据,一般做到1e-9的判定水平就够了,所以统计窗口就按这个标准算。
以700Mbps为例,并行数据宽度8bit,并行时钟87.5MHz。如果统计1M字节,耗时约11.4ms。1M字节中有8M个bit,允许出现1个误码相当于误码率1.25e-7,如果期望判据更严格可以统计4M字节,允许1bit误码,对应误码率3e-8。这个时间长度对于上电初始化来说是可以接受的。
要注意的是,训练期间的误码统计窗口和正常工作时的误码监控窗口应该分开设置。正常工作时的监控不宜过于敏感,否则温度小幅波动引起的一两个误码就会触发重新校准,反而影响用户体验。我一般把运行时的误码监控阈值放宽到训练时的10倍,并且连续超过阈值才触发重校准。
4.3 校准阶段的跨时钟域与复位处理
再有就是状态机模块和ISERDESE2所在的时钟域问题。ISERDESE2输出的是并行时钟域(CLKDIV)的数据,而校准状态机通常也跑在CLKDIV域,这个没问题。但寄存器总线往往是慢速的APB或AXI-Lite总线时钟域,从总线域到状态机域的控制信号需要做打拍同步和脉冲转换。
这里必须提醒一个我曾经吃过大亏的点:复位释放顺序。IDELAY2和ISERDESE2的复位释放不能和状态机复位同时进行。我实测中发现,如果IDELAY2的复位释放过早,延迟链可能还没稳定,这时候写入的CNTVALUEIN值会丢失或者错乱。正确做法是:先释放IDELAY2复位,等待至少16个参考时钟周期,确认IDELAY2锁定正常后,再释放ISERDESE2复位,最后才允许状态机启动校准流程。
还有一个细节是BITSLIP的时序关系。BITSLIP只在CLKDIV的上升沿采样有效,所以触发BITSLIP的脉冲必须和CLKDIV对齐。如果状态机是纯组合逻辑产生脉冲,可能会出现亚稳态。稳妥的做法是在CLKDIV域内打一拍,确保脉冲宽度正好一个CLKDIV周期。
5. 上板实测与调试验证:怎么判断一个校准机制是否真的好用
仿真通过的自动校准机制,上板后往往会暴露一堆问题。这一章没有任何代码,都是实打实的硬件调试经验。分享一下我的实测流程和数据判断方法。
5.1 自回环测试:最简单的链路自检方法
在正式对接远端设备之前,先让FPGA自发自收。把OSERDESE2的串行输出直接通过PCB回环(走线短接)或FPGA内部IOB回环到ISERDESE2的输入,然后跑一遍完整的自动校准流程。
回环测试能验证哪些东西?首先验证校准状态机本身的逻辑正确性;其次能大致看出板级信号质量。如果回环测试都要扫描很长时间才能锁定,或者锁定的无错窗口非常窄,那大概率不是算法问题,而是单板硬件设计有缺陷。
我会记下回环测试时的最佳tap值和无错窗口宽度。比如700Mbps下,回环测试的最佳tap值是tap14,窗口宽度12个tap(约936ps),说明板级设计良好。后续对接远端设备时,如果最佳tap值偏离超过4~5个tap,就要怀疑连接器、线缆或者对端驱动能力有影响。
5.2 扫描数据怎么解读:一个典型的实测表格
下面是一组我实测的IDELAY2扫描数据(700Mbps,每个tap统计4K字节),不同tap值对应的误码情况如下:
| Tap值 | 误码数 | 说明 |
|---|---|---|
| 0~6 | 持续误码 | 采样点落在数据跳变沿之前 |
| 7 | 0 | 进入无错窗口 |
| 8 | 0 | 窗口内 |
| 9 | 0 | 窗口内 |
| 10 | 0 | 窗口内 |
| 11 | 0 | 窗口内 |
| 12 | 0 | 窗口内 |
| 13 | 0 | 窗口内 |
| 14 | 0 | 窗口内 |
| 15 | 0 | 窗口内 |
| 16 | 0 | 窗口内 |
| 17 | 0 | 窗口内 |
| 18 | 0 | 窗口内 |
| 19 | 0 | 窗口内 |
| 20 | 0 | 窗口内,但接近边界 |
| 21 | 2 | 边缘不稳定 |
| 22~31 | 持续误码 | 越过窗口,采样点进入相邻bit |
这个数据里无错窗口从tap7到tap20,宽度14个tap,约1.09ns,占700Mbps下bit宽度的76%,说明信号质量非常好。最佳tap值取窗口中心,也就是tap13或tap14附近,留出的裕量两边各约7个tap,这个裕量足以应对温度和电压漂移。
如果实测数据出现窗口宽度只有2~3个tap,甚至没有连续无错点,不用怀疑,先回去查硬件。最常见的几个原因:LVDS差分对走线过长而没有做端接匹配、连接器接触不良、接收端差分端接电阻值不对(LVDS需要100欧跨接在差分对上)。
5.3 运行中的稳定性监控
校准完成后并不是一劳永逸。前面说过温度和电压漂移会导致采样点偏移,所以实机运行时要加一个轻量级的误码监控模块。
我的做法是:正常数据模式中,如果数据使能有效,每收到N个字节就计算一次CRC,CRC错误计到错误计数器。当错误计数器在100ms内超过了阈值,状态机自动触发重新校准。重新校准不需要整个链路离线,可以先暂停数据通路,拉高训练使能让对端进入训练模式,跑完校准流程后再恢复数据。
这个过程中要处理好一个问题:重新校准期间到达的数据怎么处理。我的方案是让后端FIFO保持读使能拉低,并把FIFO写指针恢复到校准前的快照位置,等校准完成后再继续接收新数据。如果对端数据是连续流无法暂停,就只能退而求其次,用滑窗的方式边校准边接收,但这会显著增加复杂度。实际项目中,大多数LVDS链路都支持短时间的训练握手,这取决于对端设备是否配合。
5.4 一个差点漏掉的坑:BITSLIP成功后的第一个字
最后分享一个调试中最难发现的bug。理论上BITSLIP对齐成功后,ISERDESE2并行输出应该是连续正确的训练序列。但我当时遇到的情况是:检测到对齐成功后,训练头的前两个字节是正确的,第三个字节开始偶尔错位,而且是隔一段时间才出现一次。
排查了整整一天,最后用逻辑分析仪抓ISERDESE2内部信号才发现:对齐成功的那一刻,并行输出数据本身是好的,但输出使能信号(OFB和Q输出)与数据之间有一个固定延迟差。后端逻辑看到使能就立即开始采数据,实际上数据还没稳定,导致采到了前一个并行数据的尾巴。
解决方式是在使能信号和采样数据之间加一级流水线延迟,让数据经过一级寄存器后再输出到后端。简单说:使能打一拍,数据也打一拍,保证时序对齐。这种问题在仿真中几乎不会暴露,因为仿真模型没有实际的IOB延迟差。这个经验让我明白一个道理:凡是涉及硬件原语的数据通路,使能信号和数据信号一定不能出现管理延迟和物理延迟的不一致,否则就会有随机偶发的错位数据。
6. 项目落地经验:从原型验证到多通道并行校准的扩展方案
如果前面说的都是单个LVDS通道的自动校准实现,最后这部分聊一下怎么把它扩展到一个实际项目中。因为在真实产品里(比如FPGA做MIPI转LVDS桥接,或者RK3566主板外接LVDS屏幕),往往不止一对差分线,而是4对数据线加1对时钟线,每一对都要独立做校准,还需要保证通道间字节对齐,这不是简单复制4份逻辑那么简单。
6.1 逐通道校准与整体握手的配合
多通道LVDS接收的自动校准有两种思路。一种是4个通道独立校准,每个通道各自完成IDELAY2扫描和BITSLIP对齐,然后以时钟通道为基准做跨通道对齐。另一种是选定一个主通道先校准,然后把主通道的校准结果分发给其他通道做微调。
实际推荐前一种,因为不同通道的走线长度、连接器接触电阻、对端驱动器的通道间偏差都不完全一样,强行让所有通道使用同一个tap值,只要有一路偏了,整个链路就挂了。独立校准的好处是每一路都能拿到自己的最佳tap值,同时保证字边界对齐在各自通道上完成。
跨通道对齐是在所有通道都完成BITSLIP匹配后做的。因为BITSLIP滑动是整字节级别的(严格说是整字级别的操作),不同通道的并行数据边界虽然各自对上了,但彼此之间可能还差几个并行时钟周期的相位差。做法是以CLK通道的帧同步信号为参考,对每个数据通道的并行FIFO做相位补偿,通过调整FIFO读指针实现。
6.2 校准参数的归档与回滚
量产环境里校准机制的可靠性直接关系到直通率。如果你的产品每台单板在出厂前都要跑一遍自动校准,那校准模块必须有参数归档能力。具体做法是:把每台单板校准出来的最佳tap值、无错窗口宽度、误码统计值、校准耗时通过寄存器接口读出来,写入单板的存储介质(比如EEPROM或eMMC),并存到产测系统里。
这些参数有两大用处。第一,如果后续单板在客户现场出现不稳定,可以把历史校准数据和当前实时校准数据做对比,判断是器件老化还是温度漂移导致的问题。第二,通过观察大批量单板的校准参数分布,可以反推PCB来料质量的一致性,如果某批板子的最佳tap值分布方差突然变大,说明PCB制造环节大概率出了问题。
6.3 向其他FPGA平台迁移的注意点
最后说一句迁移问题。这套方案基于Xilinx 7系列的ISERDESE2/OSERDESE2/IDELAY2原语,如果你后续换到UltraScale系列,原语名称会变为ISERDESE3、OSERDESE3和IDELAYE3,配置参数有差异。比如UltraScale的IDELAYE3的tap分辨率不再是固定的78ps,而是可以通过参考时钟频率配置的,延迟步进更细,校准精度可以更高,但状态机的扫描范围和控制逻辑也需要相应调整。
对于从7系列往UltraScale迁移的项目,建议先把原语封装层抽离,只暴露通用的tap设置、BITSLIP脉冲、数据输入输出接口,这样底层原语替换时,上层校准状态机可以完全复用。封装层的设计要预留好参数化配置的余地。我在一个项目里就是靠这层封装,只花了不到两天时间就把整套校准机制从7系列迁移到了UltraScale平台,而更早的版本里所有原语直接裸写在业务代码中,光是找替换点就花了一周。
LVDS高速传输的自动校准机制,做到这一步基本就完整了。回过来看,整套系统的核心并不复杂:用IDELAY2找到正确的采样相位,用BITSLIP找到正确的字节边界,再用一个状态机把这两个动作自动串起来。难的是想清楚每一步在链路中解决什么问题、统计窗口如何设定、异常情况如何处理、以及如何在量产中保证可维护性。换一个链路速率、换一个FPGA平台,这套思路是通用的。希望这些实战经验能帮你少走一些弯路,尤其是文中提到的那些时序细节和隐藏的坑,当年要是有人能提前告诉我,我能省下好几个通宵。