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。整个链路层的数据传输,都以多帧为周期来组织。
经验之谈:我个人习惯把帧看作是“心跳”,多帧则是“呼吸”。心跳要平稳,呼吸要有节奏。调试时先看帧是否对齐,再看多帧边界是否稳定。
多帧结构有什么用?
- 同步:链路建立时,接收方通过识别多帧边界来锁定数据流
- 确定性延迟:多帧的起始位置固定,使所有通道的延迟可测量、可补偿
- 错误监测:每个多帧内可以插入校验信息,用于链路质量监控
嗯,这里要注意:多帧并不是简单地给帧加一层包装。它定义了帧与帧之间的关系——哪些帧属于同一个多帧,多帧的编号如何变化,这些都是由应用层配置的。
4.3 控制字符(K码)——JESD204B的“暗号系统”
K码,全称是控制字符(Control Character),是JESD204B链路层通信的关键工具。普通的8B/10B编码可以表示256个数据字符;K码则用剩余的“编码空间”来表示特定的控制意图。
注意:K码不能被当作数据对待。接收端检测到K码时,必须按控制命令进行处理,而不是当成普通数据送入FIFO。
JESD204B主要使用以下几个K码:
| K码名称 | 8位值 | 10位编码 | 功能描述 |
|---|---|---|---|
| K28.5 | 0xBC | 001111 1010 | 多帧对齐标志(核心同步码) |
| K28.0 | 0x1C | 001111 0100 | ILAS开始 |
| K28.1 | 0x3C | 001111 1001 | ILAS结束 |
| K28.7 | 0xFC | 001111 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链路层的运行骨架:
- 每个字节在发送前经过8B/10B编码,变成10位码字
- F个字节组成一个帧,帧边界由接收端的逗号检测器锁定
- K个帧组成一个多帧,多帧边界由K28.5码标识
- 在ILAS阶段,K28.0和K28.1分别在多帧边界出现,用于链路握手
我个人建议你在调试时按这个顺序来:先确认8B/10B编码正确(检查离散点),再验证帧对齐(看帧边界是否有毛刺),最后检查多帧同步(K码出现的位置是否对)。
总结:帧定义数据粒度,多帧定义同步周期,K码提供控制命令,8B/10B保障传输质量。这四个要素构成了JESD204B链路层的全景。设计时给每个要素都留出调试接口,能让你在联调中少走弯路。
我曾经就是因为少留了一个K码检测点的测试引脚,结果出了问题只能靠猜。现在的板子,我至少会在FPGA内部把K码捕获、帧计数、多帧计数这三个信号都引出来观察。这个习惯帮我快速定位了许多链路层问题。