4 物理层逻辑子模块
4.1 介绍
物理层分为两部分,逻辑子块(Logical Sub-block)和电气子块(Electrical Sub-block)。
逻辑子块负责与数据链路层连接,电气子块负责链路上的电气问题。与事务层和数据链路层一样,物理层在内部也分为发送和接收两个部分。
PCIe Gen 1 的链路速率是 2.5GT/s;Gen 2 的链路速率是 5.0GT/s;Gen 3 的链路速率是 8.0GT/s;从 Gen 3 往后,每一新版本的速率翻倍。
虽然在物理层上 Gen 1/2 和后面的版本差别较大。但是 PCIe 新版本需要向前兼容旧版本,而且 PCIe 的链路训练始终是从 2.5GT/s 开始,逐渐向上提高速率至链路两端支持的最高速率。比如,对于 Gen 5,链路速率是从 2.5GT/s -> 5GT/s -> 8GT/s -> 16GT/s -> 32GT/s。虽然在 Gen 4 开始支持旁路均衡(Bypass Equalization)功能,比如对与 Gen 5 允许链路训练 2.5GT/s -> 5GT/s -> 32GT/s,但最初的速率依然是 2.5GT/s。综上,物理层的学习有必要考虑 Gen 1/2。
本章介绍逻辑子块,第八章介绍电气子块。
4.2 逻辑子块
逻辑子块有两个主要部分:发送部分,用于从数据链路层接收数据,以供电气子块传输;接收部分,用于在将接收信息传递到数据链路层。
当链路速率为 2.5GT/s(Gen-1)或 5.0GT/s(Gen-2)时,逻辑子块采用 8b/10b 编码;当链路速率为 8GT/s(Gen-3)或者更高时,逻辑子块采用 128b/130b 编码。
在物理层逻辑子块的发送部分中,数据流向参考下图。流入的数据源有四个
- TLP 或 DLLP
- 控制字符,指示数据包的起始和结束标志
- 逻辑空闲,当链路上没有数据传输,处于逻辑空闲状态时,为了防止链路接收端的 PLL 发生漂移,发送端需要在链路的所有 Lane 上持续发送逻辑空闲序列
- 有续集,用于链路管理
只有 TLP 和 DLLP 是从数据链路层传输过来的,需要保存在 Tx Buffer 中;其余三个源都是逻辑子块内部产生的。后面会介绍什么是控制字符,逻辑空闲,有续集。
接下来是字节条带化(Byte Stripping)。PCIe 的一对收发链路称作一条 Lane。虽然 PCIe 是串行总线,但协议允许链路上存在多 Lane。比如 x8 表示该 PCIe 链路有 8 条 Lane。对于多 Lane 的链路,逻辑子块会将 TLP 或者 DLLP 拆分成字节,然后按照顺序分配给每条 Lane 进行传输,这一拆分过程称作字节条带化。
然后是数据加扰和编码过程。所谓加扰是将源数据流与一个随机序列异或后,再发送出去。此时被发出的数据流也基本是伪随机的,从而降低了发送数据时产生的 EMI 噪声。当链路速率为 2.5GT/s(Gen-1)或 8GT/s(Gen-2)时,逻辑子块采用 8b/10b 编码;当链路速率为 8GT/s(Gen-3)或者更高时,逻辑子块采用 128b/130b 编码。实际上,128b/130b 编码只是在原始的 128-bit 前面加上 Sync Header,所以下图中 Gen3 Scrambler 后面没有画出编码模块。
这里需要注意,PCIe 链路上不会传输时钟信号,链路的发送端将时钟信息隐藏在数据流中,而链路的接收端需要从数据流中提取出时钟信息,这一技术称为 CDR(Clock Data Recovery)。原理其实不难理解,发送端的数据信号是随着时钟频率变化的,只要数据信号变化足够多(即连续 1 或者 0 的机率少且短),那么数据流是能够反应出时钟信息的。对于 Gen1/2,逻辑子块的发送部分就是通过编码来完成数据流中加入时钟信息的,所以其数据流要先加扰再编码。反过来的话,编码过程的时钟信息就会被加扰过程破坏。但是对于 Gen 3 和后续版本,128b/130b 并没有对数据进行编码,因此可能会存在连续 0 或者 1 的情况。为了解决这一问题,要通过加扰来完成。加扰的算法不展开了。对于多 Lane 情况,每条 Lane 可以用自己的加扰种子(Seed),以降低相邻 Lane 间的电气干扰。如果是 x16 或者 x32,可以循环使用加扰种子,比如 Lane 0/8/16 用相同的种子,Lane 1/9/17 用相同的种子,以此类推。对于有续集来说,PCIe 协议规定了有续集的数据格式,已经考虑了消除连续 0 或 1 的情况。因此除了 TS1 和 TS2,其它的有续集不用加扰。对于 TS1 和 TS2,Symbol 0 不会加扰,Symbol 1-13 会加扰,Symbol 14-15 是否加扰取决于扰码器逻辑。
最后,要对数据流做并串转换,将每条 Lane 对应并行的数据转换成串行数据发送出去。
逻辑子块的接收部分的数据流向刚好与发送部分反过来,先将接收到的串行数据流转成并行;然后做解码和解扰;再然后是字节反条带化,将所有 Lane 的字节数据组在一起,恢复出完整 TLP 和 DLLP,保存在 Rx Buffer 中。
4.2.1 编码(2.5 GT/s,5.0 GT/s)
4.2.1.1 字符编码(8b/10b)
在 PCIe Gen-1/2 中,采用 8b/10b 编码。在发送部分中,将从数据链路层传递过来的每 8-bit 编码成 10-bit;相应的,接收部分需要将接收到的 10-bit 解码成 8-bit。编码后的 10-bit 被称为一个字符(Symbol)。
8b/10b 编码是 IBM 公司发明的,其基本原理是将原始的 8-bit 拆分成 3-bit 和 5-bit 两部分,分别编码成 4-bit 和 6-bit,即分别做 3b/4b 和 5b/6b 编码,最后合成 10-bit。8b/10b 编码的好处是:
- 减少连续 0 或 1 的长度,有利于时钟恢复
- 有利于直流均衡
- 有利于错误检测
8b/10b 编码具体原理略过。
在 8b/10b 编码中,有数字字符(Data Symbol)和控制字符(Control Symbol)之分,分别用 D 和 K 表示。所谓控制字符,是 8b/10b 编码方案提供的一些特殊字符,这些特殊字符用于后面会介绍的各种链路管理机制,也叫 K 字符。PCIe 协议中使用的 K 字符如下表所示。
8b/10b 带来一个问题,就是链路利用效率不高,直接浪费了 20%。
4.2.1.2 字符应用
字符有两种应用:一是构成有续集(Ordered Sets),二是构成 TLP/DLLP。有续集和 TLP/DLLP 在 multi-Lane 链路上的发送规则不一样。
完整的有序集同时出现在 multi-Lane 链路的所有 Lane 上。
对于 TLP 和 DLLP 来说,会包含很多字符,形成一个字符流。某些 K 字符用于指示 TLP 或者 DLLP 的起始或停止边界,这些 K 字符也叫做“帧字符(Framing Symbol)”。SDP(K28.2)用于指示 DLLP 起始,STP(K27.7)用于指示 TLP 起始,END(K29.7)用于指示 TLP 或 DLLP 结束,EDB(K30.7)用于指示格式错误的 TLP 结束。
对于 multi-Lane 链路来说,第一个字符放在 Lane 0 发送,第二个字符放在 Lane 1 发送,以此类推。
4.2.1.3 数据加扰
在逻辑子块的发送部分中,要对数据进行加扰(scrambling),打乱原来的比特流;相应的在接收部分就要做解扰(de-scrambling)。
加扰的好处是降低 EMI 干扰。具体的加扰算法和规则就不介绍了。
4.2.2 编码(8.0 GT/s,及更高速率)
在 PCIe Gen3 和更高版本中,采用 128b/130b 编码。
4.2.2.1 Lane 编码(128b/130b)
128b/130b 编码的原理是在原始的每 128-bit 作为有效负载,前面加上 2-bit 的 Sync Header。这个 130b 被称为一个“块(block)”。Sync Header 为 01b 表示后面的 128-bit 是 Ordered Sets;10b 表示后面是数据(TLP,DLLP 等);00b 和 11b 是非法值。
所以在 128b/130b 编码中,一个字符是 8-bit。
4.2.2.2 有续集块
有续集块是由 Sync Header(01b)和有续集组成。有续集的第一个字符指明了该有续集的类型,随后的字符需要遵守该有续集类型的定义。关于有续集,会在后面详细说明。
Gen 3 中的有续集包括:
- SOS(Skip Ordered Set):
- EIOS(Electrical Idle Ordered Set)
- EIEOS(Electrical Idle Ordered Set)
- TS1/TS2
- FTS(Fast Training Sequence Ordered Sets)
- SDS(Start of Data Stream Ordered Sets)
除了 SOS 外,其余有续集均为 16-byte 大小。下图左侧是 FTS 有续集的格式,右侧是有续集指示字符,也就是有续集中的第一个字符。
与 Gen 1/2 中不同,Gen 3 的发送端在发送数据流前,需要先发送 SDS 有续集,指示后面将开始发送数据流;在所有数据流发完后要有 EDS 令牌,表示数据发完了,随后发送的是 EIOS 或者 EIEOS 有续集。EDS 令牌总是占据数据块的最后四个符号。例外情况是 SOS(SKP),可以穿插在数据流中发送,用来做链路发送端与接收端的时钟偏差补偿。
4.2.2.3 数据块
数据块的有效负载是数据流,数据流包含帧令牌(Framing Tokens),TLP,DLLP。
Gen 3 没有继续用 8b/10b 编码,因此也就没有控制字符。要是想在数据块中增加额外信息,就必然要定义一些特殊的数据结构,就是帧令牌,也可以简称令牌。在 PCIe 协议基础规范中,术语 Framing Token 和 Token 是一个意思。
帧令牌指定相关的字符数量,和下一个帧令牌的位置。帧令牌有以下五种:
每种帧令牌的具体定义如下图。
TLP 或 DLLP 数据块的布局如下图所示。TLP 数据块起始是 4 个字符的 STP,然后是 TLP,最后是 4 字符的 LCRC。
数据流的第一个帧令牌总是占用第一个数据块的 Lane 0 的 Symbol 0 中。下图是 x8 链路的示例,可以看到,STP 占用 Lane 0-3 的 Symbol 0。
4.2.2.4 加扰
略过
4.2.2.5 预编码(Precoding)
接收端采用 DFE(决策反馈均衡器)进行判决,在 32 GT/s 速率下比 16 GT/s 更容易发生连续突发错误(Burst Error)。为了减少 Burst Error 的发生,Gen 5 速率下可以选配预编码(Precoding)。Precoding 仅适用于 32 GT/s 及以上速率,其他速率时不开启。PCIe 链路的 Rx 通过 EQ TS2 请求 Tx 开启 Precoding。
Precoding 可以把连续多比特的 Burst Error 拆分为 2-bit 的 Entry Error 及 Exit Error,从而达到消除 Burst Error 的目的。对于单比特的突发错误,开启 Precoding 后会变成 2-bit 错误,从而使系统误码率 BER 会提升为之前的两倍。
Precoding 发生于 Tx Scramble 之后,Rx De-scramble 之前。开启 Precoding 不会影响信号质量及完整性。
4.2.2.6 128b/130b 环回
环回用于测试和故障隔离。PCIe 协议仅指定了进入环回模式和退出环回模式的行为,所有其他细节都是特定于实现的。
4.2.3 链路均衡(8.0 GT/s,及更高速率)
在 PCIe 链路传输中,由于电磁干扰,信号衰减失真或比特同步错误等原因,会改变数据流的比特数据,造成错误。比特出错概率(Bit Error Ratio,BER),是一个时间间隔内错误比特的数目与传送的总比特数的比值,通常以百分比表示。当 BER 过高,说明链路质量很差,可能会导致链路重新训练或者是链路不能正常工作。
在 Gen 1/2 中,使用固定的 Tx 去加重参数即可实现良好的信号质量。但是到了 Gen 3,链路速率达到 8GT/s,信号完整性问题变得严重。
链路均衡过程使组件能够在 8.0GT/s 和更高的数据速率下运行时,调整每个 Lane 的发射机和接收机设置,以提高信号质量。
链路均衡过程必须在第一次数据速率改变为 8.0GT/s 或更高的任何数据速率期间执行。如果链路上的组件不需要此过程,则需要在链路训练期间通过 TS1/TS2 有续集向对端组件公布此信息,从而绕过链路均衡过程。PCIe 协议要求,当组件的物理层通知数据链路层其已准备好时(LinkUp=1),组件的物理层发射机参数必须提前设置好,也就是均衡过程完成。
概念介绍
在分析链路均衡之前,需要介绍几个概念。
为了实现更好的波形整形,PCIe 协议规范要求发射机使用 3 抽头的 FIR(有限脉冲响应)滤波器。
FIR 滤波器的三个输入可以通过它们的时间位置描述为“pre-cursor”C‐1、 “cursor”C0,“post-cursor”C+1,它们组合起来产生基于即将到来的输入、当前值,先前值的输出。调整抽头的系数可以使输出波得到最佳的整形。
滤波器根据分配给每个抽头的系数值(或抽头权重)对输出进行整形。三个系数幅度的绝对值之和是 1,因此只需要给出其中的两个,就可以计算第三个。因此,规范中只给出了 C-1 和 C+1,因此 C0 总是隐含的,并且总是正的。
系数值的作用是调整输出电压,以创建多达四个不同的电压电平,以适应不同的信号环境。
下图显示了要传输的四种通用电压电平,它们是:maximum‐height (Vd),normal (Va),de‐emphasized (Vb),pre‐shoot (Vc)。
如果 C-1 和 C+1 都为 0(C0 为 1.0),则 Vc 最大值就是信号的大小。
当链路准备好从 5.0GT/s 变为 8.0GT/s,下游端口 DSP 需要通过 EQ TS2 向上游端口 USP 发送一组预设值(preset)值,作为测试信号质量的起点。PCIe 协议规范定义了 11 组预设值,如下图。
如果使用预设值,链路的 BER 达到了 10-12,则无需进一步训练。但是,如果 BER 过高,则使用均衡序列来微调系数设置,尝试不同的 C‐1 和 C+1 值并重新评估结果,并重复该序列直到达到所需的信号质量或错误率。
链路均衡阶段
链路均衡过程最多由四个阶段(Phase)组成,使用 TS1 有序集中的均衡控制(Equalization Control,EC)字段来传递 Phase 信息。
在 PCIe 协议规范中,使用下游端口和上游端口来分析链路均衡。如果理解不方便,可以将下游端口换成 RC,上游端口换成 EP,可能会更好理解下面的分析。
Phase 0
Phase 0,下游端口的 LTSSM 进入 Recovery.RcvrCfg 状态,通关 EQ TS2 向上游端口发送 Tx Presets 和 Rx Hints。下游端口发送的 Tx Presets 值是基于自己的 Equalization Control 寄存器。需要注意的是,可能每条 Lane 的均衡值不同。下游端口将其 Equalization Control 寄存器中 DSP 值用于自己的发射机和接收机,将 USP 值发送给上游端口。
Tx Preset 字段的编码如下表:
Rx Hint 字段的编码如下表:
一旦链路速率变化,下游端口开始进入 Phase 1,发送 TS1(EC=01b),等待上游端口也进入 Phase 1。此时上游端口启动 Phase 0,发送 TS1 与先前从 EQ TS1 和 EQ TS2 接收到的 Preset 值相呼应的 TS1。上游端口使用下游端口请求的 Tx Preset 和 Rx Hints。上游端口在评估输入信号之前可以等待 500ns,但一旦能够识别出连续两个 TS1,就可以为下一步做好准备,因为这意味着信号质量满足 10-4 的 BER。随后,上游端口在其 TS1 中设置 EC=01b,从而也进入第 Phase 1,并将下一步的控制权交给下游端口。
Phase 1
Phase 1 同样的,下游端口识别出上游端口发出的连续两个 TS1,意味着信号质量满足 10-4 的 BER。一旦下游端口识别出上游端口发过来的 TS1(EC=01b),确信链路工作良好,则 Phase 1 完成。下游端口通过设置其 EC=10b 启动 Phase 2,并将下一步的控制权交给上游端口。当上游端口响应 EC=10b 时,两个端口都进入 Phase 2。作为一个替代方案,下游端口如果确定信号质量已经足够好,不需要进一步调整,在这种情况下,它将其设置 EC=00b 直接退出均衡过程。
Phase 2
Phase 2,上游端口可以请求下游端口设置其 Tx 参数,评估信号质量,并重复该过程,直到达到当前环境的最佳设置。为了进行请求,上游端口改变在其 TS1 中发送的均衡系数值,并根据接收到的下游端口的有续集评估链路质量。
Phase 3
Phase 3,下游端口通过发送 EC=11b 进行响应,现在可以对上游端口的发射机进行相同的信号评估过程。
综上所述,Phase 0 和 1 是对链路系数进行粗调,Phase 2 和 3 是对链路系数进行细调。如果粗调就能满足链路 BER 要求,可以放弃 Phase 2 和 3,直接退出链路均衡过程。
整个链路均衡过程在 LTSSM 状态机的 Recovery 状态控制下。
物理层是 PCIe 里面最复杂的,我的理解有限,估计有的地方理解不到位或者就错了,大家尽管指出,帮我提升,哈哈~~
【待续】
作者:老秦谈芯
文章来源:老秦谈芯
推荐阅读
- PCIe 学习(四)
- 一文读懂虚拟化原理
- m_sequencer 和 p_sequencer 到底谁大
- protocol——命令行绘制协议图大杀器
- PCIe 调试:超级好用的 rescan 与 remove 命令
更多 IC 设计干货请关注IC 设计专栏。欢迎添加极术小姐姐微信(id:aijishu20)加入技术交流群,请备注研究方向。