IC每日一题:PCIE协议简介
- 1 PCIE协议
- 1.1 PCIE总体架构
- 1.1.1 Root Complex
- 1.1.2 PCIe Bus
- 1.1.3 Endpoint
- 1.1.4 Port and Bridge
- 1.1.5 Switch
- 1.2 PCIe的分层结构
- 1.2.1 事务层
- 1.2.2 数据链路层
- 1.2.3 物理层
- 1.2.4 层与层之间的交互--接收和发送
- 1.2.5 PCIe的Demo
- 2 PCIE分层
- 2.1 TLP事务层
- 2.2 TLP包结构
- 2.2.1 TLP Header--4DW
- 2.2.2 TLP事务路由
- 2.3 数据链路层
- 2.3.1 数据包格式和数据发送
- 2.3.2 数据接收
- 2.3.3 控制消息DLLP
- 2.3.4 流量控制
- 2.4 物理层
- 2.4.1 逻辑子块
- 2.4.2 电气子块
- 3 PCIE具体示例
【博客首发于微信公众号《漫谈芯片与编程》,欢迎专注一下,多谢大家】
PCIE是高速串行计算机扩展总线标准,用于连接计算机内部的各种硬件设备,如显卡、网卡、存储设备等。
PCIE_5">1 PCIE协议
PCIE_6">1.1 PCIE总体架构
PCIE 总体框图:PCIE的架构主要有:Root Complex,PCIE Bus,EndPoint,Port and Bridge,Swith;
1.1.1 Root Complex
- RC(Root Complext):Root Complext是整个PCIe设备树的根节点,CPU通过RC与PCIE的总线相连,并最终连接到所有的PCIe设备中;
功能: - 初始化:负责初始化和配置整个 PCIe 拓扑结构。
- 管理:管理和控制所有的 PCIe 设备,包括配置空间的访问、中断处理等。
- 仲裁:处理多个设备之间的资源共享和访问仲裁。
- 桥接:作为 PCIe 系统与其他系统总线(如 CPU 总线)之间的桥梁。
1.1.2 PCIe Bus
- PCIE Bus:这个不是那种共享的数据总线,而是一个点对点的网络,表示一组连接路径;
即当Root Complex或者PCIe上的设备之间需要通信的时候,它们会与对方直接连接或者通过交换电路进行点对点的信号传输。
功能: - 数据传输:提供数据在不同设备之间传输的路径。
- 地址空间:定义了 PCIe 系统中的地址空间,包括内存地址空间、I/O 地址空间和配置空间。
- 事务管理:管理事务包(TLP)的生成、传输和解析。
1.1.3 Endpoint
- Endpoint 是 PCIe 系统中的终端设备,如显卡、网卡、存储控制器等。
功能: - 数据处理:处理来自 Root Complex 或其他设备的数据请求和响应。
- 配置:通过配置空间进行设备配置和状态查询。
- 中断:支持中断请求,通知 Root Complex 或其他设备有关事件的发生
1.1.4 Port and Bridge
Port and Bridge 是 PCIe 系统中的中间节点,用于连接不同的 PCIe 设备或子系统。
功能:
- 桥接:将 PCIe 信号从一个域转换到另一个域,例如将 PCIe 信号转换为其他类型的总线信号。
- 扩展:通过桥接器扩展 PCIe 系统的拓扑结构,增加更多的设备或子系统。
- 路由:负责数据包的路由和转发,确保数据正确地到达目标设备。
1.1.5 Switch
Switch 是 PCIe 系统中的多端口设备,用于扩展 PCIe 拓扑结构,允许多个设备通过不同的链路连接到根复合体。
功能:
- 多端口:支持多个 PCIe 端口,每个端口可以连接到不同的设备或子系统。
- 路由:负责数据包的路由和转发,确保数据正确地到达目标设备。
- 带宽管理:根据需要动态分配带宽,优化数据传输效率。
- 配置:支持配置和管理多个端口和链路,提供灵活的拓扑结构。
一个典型的 PCIe 系统,包括以下组件:
- Root Complex:位于主板上,由 CPU 和北桥芯片组组成。
- Switch:用于扩展 PCIe 拓扑结构,连接多个设备。
- Endpoints:包括显卡、网卡和 NVMe SSD。
- Bridge:用于将 PCIe 信号转换为其他类型的总线信号,例如连接到 SATA 控制器。
1.2 PCIe的分层结构
PCIE协议也是分层结构:物理层、数据链路层和事务层;每个层次专门负责自己层次的职责;
1.2.1 事务层
功能:
- 事务包(TLP)生成与解析:事务层负责生成和解析事务包(Transaction Layer Packet, TLP),这些包包含了读写请求、配置请求、消息等。
- 地址映射:将逻辑地址映射到物理地址,确保数据能够正确地传输到目标设备。
- 事务管理:管理事务的状态,包括请求的发起、完成和重试机制。
常见事务类型:
- 内存读写(Memory Read/Write):用于访问内存地址空间的数据读写操作。
- I/O 读写(I/O Read/Write):用于访问 I/O 地址空间的数据读写操作。
- 配置读写(Configuration Read/Write):用于访问 PCIe 设备的配置寄存器,进行设备配置和状态查询。
- 消息(Message):用于传递控制信息,如中断请求、电源管理命令等。
1.2.2 数据链路层
功能:
- 链路管理:负责链路的建立、维护和关闭,包括链路训练和状态管理。
- 错误检测与纠正:使用循环冗余校验(CRC)进行数据完整性检查,确保数据的可靠传输。
- 流量控制:通过接收方的信用机制(Credit-based Flow Control)管理数据流,防止数据拥塞。
- 重传机制:如果数据包传输失败,数据链路层会请求重传,确保数据的完整性和顺序。
关键机制: - 链路训练:在链路建立时进行一系列协商过程,确保链路的稳定性和性能。
- 信用机制:接收方通过信用机制告知发送方其缓冲区的可用空间,防止数据溢出
1.2.3 物理层
功能:
- 信号传输:负责电气信号的发送和接收,包括时钟恢复、信号编码和解码等。
- 链路管理:物理层负责链路的物理连接和断开,包括电气特性、时钟同步等。
- 低功耗管理:支持多种电源管理状态,如 L0、L1、L2 等,以降低功耗。
关键技术:
- 差分信号:使用差分对进行高速串行通信,提高抗干扰能力和传输距离。
- 8b/10b 编码:早期 PCIe 版本使用 8b/10b 编码,将 8 位数据编码为 10 位符号,以确保直流平衡和时钟恢复。
- 128b/130b 编码:从 PCIe 3.0 开始,使用 128b/130b 编码,提高传输效率。
- 时钟恢复:物理层使用时钟恢复技术,从数据流中提取时钟信号,确保数据的正确接收。
1.2.4 层与层之间的交互–接收和发送
1.事务层:
- 生成事务包(TLP),将其传递给数据链路层。
- 解析从数据链路层接收到的 TLP,执行相应的操作。
2.数据链路层:
- 将事务层生成的 TLP 封装成数据链路层包(DLLP),添加 CRC 校验。
- 通过物理层将 DLLP 发送出去。
- 接收物理层传来的 DLLP,进行 CRC 校验和错误检测。
- 将解析后的 TLP 传递给事务层。
3.物理层:
- 将数据链路层生成的 DLLP 转换为差分信号,通过物理链路发送。
- 接收差分信号,恢复时钟和数据,将 DLLP 传递给数据链路层。
1.2.5 PCIe的Demo
假设一个 PCIe 系统中的 CPU 通过 Root Complex 发起一个内存读取请求,该请求将通过以下步骤在各个层次中传递:
//=====发送
事务层:CPU 生成一个内存读取请求 TLP。TLP 被传递到数据链路层。
数据链路层:数据链路层将 TLP 封装成 DLLP,添加 CRC 校验。DLLP 被传递到物理层。
物理层:物理层将 DLLP 转换为差分信号,通过 PCIe 链路发送。//=====接收
物理层:目标设备的物理层接收差分信号,恢复时钟和数据,将 DLLP 传递给数据链路层。数据链路层:目标设备的数据链路层进行 CRC 校验和错误检测。解析后的 TLP 被传递到事务层。
事务层:目标设备的事务层解析 TLP,执行内存读取操作。读取的数据被封装成新的 TLP,通过相同的过程返回到 CPU。
流程描述:应用层提出一个需求(data),将数据打包发送给设备A的事务层(TLP),然后将TLP扩充为DLLP发送给设备A的数据链路层,最后扩充为PLP发送到设备A的物理层,然后发送到设备B的物理层,将其解包变成DLLP,然后发送至设备B的数据链路层,最后解包变成TLP发送至设备B的事务层。
PCIE_134">2 PCIE分层
2.1 TLP事务层
PCIe的协议栈最上层叫做事务层,这一层定义了所有和用户相关的PCIe的操作。
PCIE的所有操作都称为一个事务,这种事务可以分为四种类型:
- 内存事务
- IO事务
- 配置师事务
- 消息事务
一个事务根据其请求处理的方式被分为两种:
- Non-Posted: 每个事务的请求消息发送出去后,需要一个完成消息(completion)来完成事务。比如:读内存呢;
- Posted: 请求发送后不需要完成消息,比如:写内存和所有的消息事务(唯二的两类请求);
2.2 TLP包结构
PCIe的事务请求和完成消息都是以TLP为单位传输的。
- TLP Header: 4DW或者3DW–主要区别在于地址部分;
- TLP Payload: TLP中的数据部分,根据不同的事务类型,其大小也不同;读事务不需要Payload;
2.2.1 TLP Header–4DW
Fmt: TLP头的格式
Bit 7:如果是1,则Fmt必须是100,表示这个头是TLP Prefix
Bit 6:1 = 读事务(TLP头之后没有Payload),0 = 写事务(TLP头之后有Payload)
Bit 5:1 = 使用32位地址,头部长度12字节(3DW Header),0 = 使用64位地址,头部长度16字节(4DW Header)
Type:事务类型,表示这个事务是什么类型的事务,比如内存事务、IO事务、配置事务、消息事务等
LN(Lightweight Notification):用于标识当前这个内存请求或者完成消息是不是一个轻量级通知
TH(TLP Hints):用于表示TPH(TLP Processing Hint)是否启用和TPH TLP Prefix是否存在
TD(TLP Digest):1 = 有TLP Digest,0 = 没有TLP Digest
EP(Error Poisoning):1 = 有错误,0 = 没有错误
AT(Address Translation):虚拟化相关的字段,00 = 无地址转换,01 = 需要地址转换,10 = 地址转换已完成,11 = 保留
Length:Payload的长度,单位为DW(Double Word),1DW = 4字节
2.2.2 TLP事务路由
有了事务ID,我们可以很容易的了解当前事务的源是谁,然而为了能让通信双方通信,我们还需要知道事务的目的地是哪里,这样我们才能把事务发送到正确的地方。
在PCIE中,不同类型的事务中使用不同的字段和方法来指定目的的,总结起来就是:
-
通过具体的地址来指定目的地:基于地址的路由,主要用于内存事务和IO事务;
-
通过BDF来指定目的地:基于ID的路由。这种方式主要用于非内存访问型的事务:配置事务(Configuration Transaction),消息事务(Message Transaction)和事务完成的消息通知(Completion)。
2.3 数据链路层
当事务层将事务消息准备好之后,就会向下传递给数据链路层。数据链路层主要负责一件事情:保证事务消息能正确的传输到目的地。
数据链路层传输的包主要包括两种,一种用于传输TLP事务消息,一种用于传输数据链路层的控制消息,比如功能(Feature)控制,流量控制,电源管理等等。
2.3.1 数据包格式和数据发送
数据链路层会对数据包进行再一层发送:
1.在包的前方添加一个序列号(Sequence Number),占用2个字节,用于保证包发送的顺序。这个序列号是每个Link独立的,只有上下游两端保存的序列号(NEXT_RCV_SEQ)一致,才会被对端接收。
2.在包的后方添加一个CRC校验码,叫做LCRC(Link CRC),占用4个字节,用于保证包中数据的正确性。注意,计算CRC的时候,刚刚添加的序列号也会被纳入计算范围中。
封装完成后,为了保证成功的发送,数据链路层会先将包保存在Retry Buffer中,再转交给物理层(Physical Layer)进行发送。在每条消息发送完毕之后,发送方会等待接收方发送ACK消息,如果接收到的返回消息是失败消息,比如Seq错误,CRC校验错误,或者任何物理层的错误,发送方就会把Retry Buffer中的消息拿出来重新发送。
2.3.2 数据接收
对于数据的接收方,操作流程则相反。接收方会检查接收到的数据包的序列号和CRC是否正确,如果不正确,就会发送一个Nak消息,要求发送方进行重传。如果正确,就会回发一个Ack消息,表示接收成功,而此时发送方在收到了ACK消息后也可以将其从Retry Buffer中移除。这样,数据链路层就保证了TLP的正确传输。
2.3.3 控制消息DLLP
除了传输TLP数据包之外,数据链路层还需要很多专门用于控制的数据包,比如Ack和Nak,这些数据包叫做DLLP。
1.ack/nak
在TLP事务消息传输的里就提到过Ack和Nak消息,ack表示接收成功,nak表示接收失败,需要重传;
AckNak_Seq_Num表示当前已经收到的最新的消息序号,所以和TCP类似,PCIe的Ack和Nak可以进行批量操作:无论是Ack还是Nak,当发送方收到这个消息之后,就可以将Retry Buffer中比这个序号老的消息全部移除了,所以Ack/Nak时只需要将最新的序号带上即可。Ack/Nak的差别在于:如果是Nak,那么发送方在移除之后,需要对Retry Buffer中这个序号之后的消息全部进行重传。
2.3.4 流量控制
PCIe的流量控制是通过将TC(Traffic Class)映射到VC(Virtual Channel),并且利用VC的信用机制来实现的。
数据链路层中的信用额度管理有两个重要的特点:
- 不同处理方式是的TLP消息有着单独的信用额度管理:Posted(P),Non-Posted(NP)和Completion(Cpl)。这三种消息的信用额度是独立的,互不影响。
- 每个VC都有着自己的独立的信用额度管理,而不是Link。也就是说,如果一个Link上有多个VC,那么每个VC都需要单独的初始化和更新。
2.4 物理层
物理层更多的是设计电气知识部分。在这里介绍数字逻辑部分相关;
当数据链路层将上层数据封装好后,就会将其交给物理层进行传输。而物理层的主要目的将数据转换为易于介质传输的电信号,并发送出去,或者将接收到的转换后的信号,转变为上层能处理的数据包。
链路Link和通道Lane的概念:
对于一个多通道(Lane)的PCIe设备而言,比如16通道(x16),虽然通道是多个,但是这些通道是连向同一个设备的,所以链路(Link)只有一个。在传输数据时,PCIe会将数据分配给所有通道并行传输,但是每个通道内部的数据传输是串行的,而接收方会将所有通道的数据最后重新汇总在一起,这样就利用了并行的多通道(Lane)建立起了一个串行的通信链路(Link)。
物理层主要包含逻辑子块和电气子块:
2.4.1 逻辑子块
由于一个链路(Link)中可能存在多个通道(Lane),所以我们需要将一个Link中的数据预先分配到多个通道中去。这里,物理层会将数据根据链路(Link)上通道的数量,将数据按字节分配给各个通道,然后再将其转化为串行的Bits,交给之后的逻辑进行处理和发送。
主要功能包括:链路串行化、数据加扰、编码(例8b/10b);
2.4.2 电气子块
电气子块主要包括:并行传串行、调制、预加重、差分信号、时钟和信号恢复;
PCIE_221">3 PCIE具体示例
使用一个内存事务(Memory Transaction)来举例子。
- 首先,CPU发起一个内存读请求,需要读取4字节内存
- 内存控制器收到该请求后发现其不在DRAM空间中,于是转交给PCIe Root Complex
- Root Complex检查其主桥(Host Bridge)配置空间的信息,确认地址在其连接的设备的内存空间内,开始创建数据包
- Root Complex使用其地址构造读内存的内存事务的TLP,长度3DW,设置好各个字段:Fmt = 0,Type = 0,RequesterID = 0(表示Root Complex),和Length = 1(单位为DW),另外,根据规则设置好TC用于流控,我们这里使用默认值0
- TLP构造完毕后会将TC(Traffic Class)映射到VC(Virtual Channel),从根据数据链路层中上报上来的每个VC中每种TLP的信用额度,进行流控,如果没有问题,则会将事务层发送给数据链路层
- 数据链路层收到TLP后,会为其分配一个唯一的12bits的序列号,然后加上一个2字节的包含该序列号的报头,然后计算包括新报头和TLP报文的4字节CRC,将其放在包尾,交给物理层处理
现在进入物理层的逻辑子块(Logical Sub-block),如果需要,物理层会其进行再次封包(framing),在报文前加上两字节STP token,并再次计算FCRC,将其写入数据链路层发来的包的第一个字节的高四位 - 然后,物理层根据链路的通道数量进行链路序列化,假设我们这里的链路使用8通道进行传输,那么这个请求将会平均分配给这8个通道。到这里我们的包一共20个字节,所以前4个通道会分配3字节,后4个通道会被分配2字节
- 接着,物理层会开始使用LFSR进行数据加扰,让数据看上去像是一堆随机数,用于保证最后链路中的DC平衡
- 然后,物理层会对每个通道上的数据进行编码(Encoding),这里根据PCIe版本的不同,会使用不同的编码,比如:8b/10b,128b/130b和242B/256B编码,对于空闲的区域,需要补齐的话,也会使用IDL token进行补齐
- 现在,我们来到了物理层的电气子块(Electrical Sub-block),首先,电气子块会讲每个通道发来的字节流转换为比特流,这一步叫做并行转串行(P2S)
- 然后,电子子块会对每个bit进行调制,根据PCIe版本的不同,可以选择NRZ或者PAM4的调制方法
- 然后,电气子块会对信号进行预加重(Pre-emphasis),以保证高频信号能很好的被传输线路传输
- 最后,发送给传输线路之前,PCIe还会将其变换为差分信号,以避免外部线路中的干扰
【REF】
1.http://r12f.com/posts/pcie-3-tl-dll/#PCIe%E5%8D%8F%E8%AE%AE%E6%A0%88
2.https://blog.csdn.net/qq_39815222/article/details/121732888