4. 链路层核心概念:帧(Frame)与多帧(Multiframe)结构、控制字符(K码)、8B/10B编码

好,我们进入链路层。这一层说白了,就是让数据在物理线上跑得稳、跑得对的核心环节。

我个人觉得,链路层是JESD204B协议中最考验硬件工程师基本功的部分。帧结构、多帧、K码、8B/10B编码,这几个概念环环相扣。你搞懂了它们,就等于拿到了调试JESD204B链路的钥匙。

4.1 帧(Frame)——链路层的基本单元

先看帧。什么是帧?在JESD204B里,帧是链路层传输数据的最小基本单元。每个帧由固定数量的字节组成,这个数量由参数F决定。

参数含义典型值
F每帧包含的字节数1, 2, 4
帧时钟帧传输的基准时钟由采样率与F决定

举个例子你就明白了。假设一个ADC采样率是1GSPS,配置F=2,那帧时钟就是500MHz。每个帧里装2个字节的转换数据。

关键理解:帧是数据的分割单位,也是链路同步的基本参考。帧边界不对齐,后续所有解码都会错位。

我在项目中遇到过这样的案例:一块板子的JESD204B链路总是不稳定,抓眼图看不出问题。后来发现是FPGA里的帧计数器初始化时序没做好,导致帧边界漂移。修复后链路就稳定了。所以,不要小看帧边界的建立过程。

4.2 多帧(Multiframe)——跨帧的“大周期”

单帧能做的事情有限。尤其是当你需要实现确定性延迟(Deterministic Latency)时,必须有一个更大的周期性结构。这就是多帧出场的理由。

多帧由K个连续帧组成。K是链路配置参数,取值范围通常是4到32。整个链路层的数据传输,都以多帧为周期来组织。

经验之谈:我个人习惯把帧看作是“心跳”,多帧则是“呼吸”。心跳要平稳,呼吸要有节奏。调试时先看帧是否对齐,再看多帧边界是否稳定。

多帧结构有什么用?

  • 同步:链路建立时,接收方通过识别多帧边界来锁定数据流
  • 确定性延迟:多帧的起始位置固定,使所有通道的延迟可测量、可补偿
  • 错误监测:每个多帧内可以插入校验信息,用于链路质量监控

嗯,这里要注意:多帧并不是简单地给帧加一层包装。它定义了帧与帧之间的关系——哪些帧属于同一个多帧,多帧的编号如何变化,这些都是由应用层配置的。

帧与多帧结构 帧 0 帧 1 帧 2 帧 3 帧 4 帧 5 帧 6 一个多帧(K = 7) 多帧 0 多帧 1 多帧 2 多帧 3 多帧 4 帧内数据字节 帧内K码/控制位 8B/10B编码:每个字节映射为10位编码 多帧边界由K码标识 帧内可混合数据与控制字符 8B/10B保证直流平衡

4.3 控制字符(K码)——JESD204B的“暗号系统”

K码,全称是控制字符(Control Character),是JESD204B链路层通信的关键工具。普通的8B/10B编码可以表示256个数据字符;K码则用剩余的“编码空间”来表示特定的控制意图。

注意:K码不能被当作数据对待。接收端检测到K码时,必须按控制命令进行处理,而不是当成普通数据送入FIFO。

JESD204B主要使用以下几个K码:

K码名称8位值10位编码功能描述
K28.50xBC001111 1010多帧对齐标志(核心同步码)
K28.00x1C001111 0100ILAS开始
K28.10x3C001111 1001ILAS结束
K28.70xFC001111 1000快速同步请求

你可能会问:为什么会选择K28.5作为主同步码?因为它的10位编码中含有逗号序列(Comma),接收端在比特流中可以唯一识别。这是8B/10B编码特性的巧妙利用。

我记得第一次调JESD204B时,抓了很长时间的波形却看不到K码。后来发现是发送端的K码插入条件没理解对——K码不是每帧都插,只在多帧边界和ILAS阶段出现。这个细节后来我写在项目组的调试手册里了。

4.4 8B/10B编码——线路传输的“翻译官”

为什么要把8位数据转成10位来传输?说白了,是为了解决三个问题:

  • 直流平衡:减少信号中的低频分量,适配交流耦合电路
  • 保证跳变:避免长串的连续0或1导致时钟恢复失败
  • 提供K码空间:编码空间有1024个码字,256个给数据,剩余给控制用

8B/10B编码的规则其实不复杂。发送端把一个字节拆成3位(高3位)和5位(低5位),分别查表映射成4位和6位编码,合在一起成为10位码字。

// 8B/10B编码示意(伪代码)
function encode_8b10b(input_8b, is_kchar):
    // 分解字节
    lower_5b = input_8b & 0x1F      // 低5位
    upper_3b = (input_8b >> 5) & 0x7 // 高3位
    
    // 查5B/6B表
    encoded_6b = look_up_5b6b(lower_5b, is_kchar)
    
    // 查3B/4B表(依赖当前极性)
    encoded_4b = look_up_3b4b(upper_3b, current_disparity)
    
    // 输出10位码字
    return (encoded_6b << 4) | encoded_4b

实践建议:调试8B/10B编码时,别自己去推导每个码字。用现成的参考实现验证发送码流是否正确。我遇到过开发人员手写编码表时写错了一个比特,结果链路完全不通,查了两天才发现。

4.5 三个概念的协作关系

帧、多帧、K码和8B/10B编码不是孤立存在的。它们一起构成了JESD204B链路层的运行骨架:

  1. 每个字节在发送前经过8B/10B编码,变成10位码字
  2. F个字节组成一个帧,帧边界由接收端的逗号检测器锁定
  3. K个帧组成一个多帧,多帧边界由K28.5码标识
  4. 在ILAS阶段,K28.0和K28.1分别在多帧边界出现,用于链路握手

我个人建议你在调试时按这个顺序来:先确认8B/10B编码正确(检查离散点),再验证帧对齐(看帧边界是否有毛刺),最后检查多帧同步(K码出现的位置是否对)。

总结:帧定义数据粒度,多帧定义同步周期,K码提供控制命令,8B/10B保障传输质量。这四个要素构成了JESD204B链路层的全景。设计时给每个要素都留出调试接口,能让你在联调中少走弯路。

我曾经就是因为少留了一个K码检测点的测试引脚,结果出了问题只能靠猜。现在的板子,我至少会在FPGA内部把K码捕获、帧计数、多帧计数这三个信号都引出来观察。这个习惯帮我快速定位了许多链路层问题。