3. 训练序列结构:帧格式、同步码与训练码、收发时序

好,咱们接着聊训练序列的结构。这部分内容,说白了就是搞清楚训练序列长什么样、怎么发、怎么收。我刚开始接触链路训练时,总觉得这东西很玄乎,后来亲手抓了几次波形,才明白——嗯,其实就是一套约定好的握手流程。

3.1 训练序列的帧格式

先看帧格式。训练序列不是乱发的,它有固定的结构。我个人习惯把它拆成三个部分:前导、同步码、训练码。你想想看,就像寄快递,得有收件人地址(同步)、包裹内容(训练)、还有签收确认(响应)。

典型的训练帧格式如下:

| 前导 (Preamble) | 同步码 (Sync Code) | 训练码 (Training Code) | 校验 (CRC) |
|     8 UI        |      16 UI         |       64 UI            |    8 UI    |

这里UI是Unit Interval,也就是一个比特的时间宽度。前导部分我一般用来做信号检测,告诉接收端“嘿,我要开始发训练序列了”。同步码负责对齐时钟和数据,训练码才是真正用来调整均衡器、时钟恢复这些参数的。

关键点:帧格式的长度不是固定的。不同协议(比如PCIe、MIPI、HDMI)会有差异。但核心思想一致——先同步,再训练。

3.2 同步码与训练码

同步码和训练码,这两个容易搞混。我简单说说区别。

同步码,目的是让接收端找到数据的边界。它通常是一串有特殊自相关特性的序列,比如巴克码(Barker Code)或者伪随机序列(PRBS)。我在项目中遇到过一个问题:同步码选得太短,抗干扰能力差;选得太长,又浪费带宽。后来我建议用16位的巴克码,效果还不错。

训练码,目的是让接收端调整自己的参数。比如均衡器的抽头系数、时钟恢复的相位。训练码一般是已知的固定序列,接收端收到后跟自己期望的值做对比,算出误差,然后调整。

类型 作用 典型长度 常用序列
同步码 帧边界检测、时钟对齐 8~32 UI 巴克码、PRBS7
训练码 均衡器训练、信道估计 32~256 UI PRBS9、PRBS15

小技巧:我曾经在调试MIPI D-PHY时,发现同步码总是检测失败。后来抓波形一看,原来是前导部分的电平没稳定。加了个简单的延迟电路,问题就解决了。所以啊,同步码之前的前导部分,一定要留够稳定时间。

3.3 训练序列的发送与接收时序

时序这块,是很多工程师容易踩坑的地方。我画个简单的时序图,你感受一下:

发送端:
        |--- 前导 ---||--- 同步码 ---||--- 训练码 ---||--- 等待 ---|
        |  8 UI      |   16 UI       |   64 UI       |   8 UI     |

接收端:
        |--- 检测 ---||--- 对齐 ---||--- 训练 ---||--- 响应 ---|
        |  检测到信号 |   同步完成   |   参数更新   |   发送ACK  |

这里要注意几个时间点:

  • 前导检测时间:接收端需要在前导期间完成信号检测。如果前导太短,检测没完成,后面的同步码就收不到了。
  • 同步对齐时间:同步码发送期间,接收端要完成比特对齐。我建议同步码至少重复发送两次,防止单次误码。
  • 训练时间:训练码发送期间,接收端要完成参数调整。如果训练码长度不够,参数可能还没收敛,链路质量就差了。

避坑指南:我曾经遇到一个案例,训练序列的发送时序和接收时序没对齐。发送端发完训练码后立刻发数据,但接收端还在调整参数。结果前几个数据包全丢了。解决方案很简单——在训练码后面加一段保护间隔(Guard Interval),给接收端留足处理时间。

收发时序的另一个关键点是握手。训练不是单向的,接收端训练完成后,要发一个确认信号(ACK)给发送端。发送端收到ACK后,才能开始发正常数据。如果ACK丢失,发送端会重发训练序列。这个重传机制,说白了就是保证链路训练的可靠性。

嗯,这里我再补充一句。实际项目中,训练序列的时序参数(比如前导长度、同步码重复次数)通常可以在芯片的寄存器里配置。我建议你在调试阶段把这些参数都开放出来,方便抓波形分析。等链路稳定了,再固化到代码里。

好了,训练序列的结构就聊到这儿。下一节咱们讲链路训练的状态机,那个更有意思。