第2章 UCIe协议基础:协议栈层次、物理层、数据链路层、事务层概述
做UCIe设计,第一关就是搞懂它的协议栈。说白了,UCIe跟PCIe、CXL这些高速互联一样,都是分层设计的。每一层各管一摊事,层与层之间通过标准接口通信。我入行时犯过一个错——直接拿着物理层的参数去调链路,结果链路死活不稳定。后来才发现,数据链路层的重传机制没打开。嗯,从那以后我再也不敢跳过协议栈了。
2.1 协议栈总体架构
UCIe协议栈严格分为三层,从下往上依次是:物理层(PHY)、数据链路层(DL层)、事务层(TL层)。这三层不是独立存在的。它们通过内部接口串联,最终对外以Die-to-Die连接的形式呈现。你想想看,整个协议栈就像一个高速公路:物理层是路面和桥梁,数据链路层是交通规则,事务层才是运输的货物。
下面这张图是我自己讲课常用的结构图,建议你多看几遍,把每层的职责记在心里。
你看,三层就是垂直堆叠。数据从上往下走,经过事务层拆包、数据链路层加校验和重传、物理层编码和串行化,最终通过Die-to-Die的微凸块送出。反过来接收时,物理层先把信号恢复,再一层层往上解析。
关键点:UCIe协议栈并不是完全独立的三片。每一层都会往数据里“加头”或“加尾”。这些附加信息在接收端一层层剥掉。我遇到过一个坑:调试时眼图很好,但是链路就是不通。后来发现是数据链路层的CRC没有正确使能,接收端直接丢弃了所有报文。
2.2 物理层(PHY)
物理层,说白了就是管“电”和“时钟”的。它决定信号怎么发、怎么收、怎么对齐。
UCIe物理层有两个关键配置:标准封装(Standard Package)和先进封装(Advanced Package)。标准封装距离几毫米,用差分线,速率相对低;先进封装距离短到几十微米,可以用单端信号,速率高。
| 参数 | 标准封装 | 先进封装(硅中介层) |
|---|---|---|
| 典型距离 | 2~25 mm | < 2 mm |
| 信号类型 | 差分(CML/SSTL) | 单端(SSTL) |
| 最大速率 | 16 GT/s(当前代) | 32 GT/s(计划) |
| 均衡方式 | CTLE + DFE | 简单CTLE 或 无均衡 |
| 功耗效率 | ~1 pJ/bit | ~0.5 pJ/bit |
我个人习惯在做PCB设计前先确定封装类型,因为这会直接影响走线规则。先进封装下,Die之间距离极短,几乎不用考虑传输线损耗,但布局精度要求极高——Bump的间距可能只有50μm,画封装时稍微偏一点就对不上。
小经验:物理层的训练流程非常重要。UCIe的初始化包括:时钟校准、眼图扫描、均衡器收敛、码型锁定。我见过有人直接跑数据不训练,结果误码率10⁻⁶都达不到。务必保留足够的训练时间,尤其是DFE(判决反馈均衡)的迭代次数。
2.3 数据链路层
数据链路层位于中间,它负责在不可靠的物理层之上提供可靠传输。
它的核心工作包括:
- CRC校验:每个Flit(流控制单元)都会配一个CRC字段,接收端重新计算并比对,不一致就要求重传。
- 重传机制:采用NACK-based或ACK-based。UCIe通常使用重传缓冲区,发送端保留每个Flit副本直到收到确认。
- 流控:利用Credit机制。发送端不能无限发,必须看接收端返回的Credit数量。
- 序列化/反序列化:实现Flit到物理层符号的对应。
我曾经调试过一个UCIe链路,现象是传输速率一高就丢包。用协议分析仪抓包发现,数据链路层的Credit更新逻辑有Bug——接收端明明还有满空间,Credit却一直显示0。后来查手册,原来是Credit粒度和Flit大小没对齐。避坑指南:一定要确认两端Credit参数完全一致,包括初始值和步进。
注意:数据链路层的超时重传机制不能随意关闭。有些开发者在评估板上为了简化验证,关掉了重传,结果误码率看起来很低但稳定度不够。量产时必须使能,否则高温/低频条件下的偶发性错误会导致整机挂死。
2.4 事务层
事务层是离软件应用最近的一层。它负责处理:内存请求(读/写)、配置请求、中断信号、数据一致性同步等。
UCIe事务层主要定义了两种类型的Flit:
- 数据Flit:携带有效载荷,大小通常是64B或128B。
- 控制Flit:用于配置状态、流控握手、中断通告。
事务层协议本身不关心底层怎么传的——它只负责把请求“打包”成一个标准格式,向下交给数据链路层。在设计PCB时,虽然我们不直接处理事务层的逻辑,但必须理解事务层的协议延迟要求。比如,不同Flit类型对电源噪声的敏感度不一样:数据Flit重传几次没大碍,但控制Flit(比如中断)如果重传,可能导致系统响应超时。
我建议你研究一下UCIe Transaction Layer的Flit格式(可以在公开标准文档中找到)。虽然PCB设计不写RTL,但了解Flit里的地址、数据、元数据字段,能帮你定位很多集成问题——比如看到某个地址段错误,你可能就知道是哪一路DDR访问出了问题。
2.5 三层间的交互:一个简单的请求流程
我们用一个读请求为例,走一遍:
- 事务层构造一个读请求Flit,包含目标地址、长度、标签。
- 数据链路层给这个Flit加上CRC,分配序列号,放入重传缓冲区。
- 数据链路层等待接收端返回Credit,然后把Flit切分(序列化)成物理层符号。
- 物理层把符号编码(比如NRZ或PAM-4),经过驱动器和通道发到对端Die。
- 对端物理层解码、去均衡、恢复时钟和数据。
- 对端数据链路层校验CRC,检查序列号,发送ACK或NACK。
- 对端数据链路层把Flit重组后交给事务层,事务层解析出读请求。
- 返回数据时,流程反过来,但增加了响应Flit类型。
你看,一步都不能少。我刚开始看这个流程时觉得好繁琐,但实际调试起来,每一层都有对应的调试手段:物理层看眼图,数据链路层看CRC错误计数,事务层看Flit类型计数器。只要有一个计数器异常,就能精准定位问题。
总结:UCIe协议栈的三层界定非常清楚。物理层负责“能不能传”,数据链路层负责“传得稳不稳”,事务层负责“传的内容对不对”。做PCB设计时,重点在物理层(电气、布局、阻抗),但如果你完全不理解上层,很容易在调试时走弯路。记住:改一个退耦电容可能治标,但查一下数据链路层的重传次数才能真正治本。