1. PCIe基础知识
PCI-Express(peripheral component interconnect express)是一种高速串行计算机扩展总线标准,它原来的名称为“3GIO”,是由英特尔在2001年提出的,旨在替代旧的PCI,PCI-X和AGP总线标准。
与大多数总线一样,PCIe总线也包括电气属性和协议组成两部分。完整地了解PCIe是相对复杂的,所以从应用角度来讲,我先从基本的协议入手,对PCIe有个初步的认识。拓展学习可以参考官方协议规范文档《PCI Express Base Specification》。
PCIe 规范对于设备的设计采用分层的结构,有事务层、数据链路层和物理层组成,各层有都分为发送和接收两功能块。
在发送端,应用程序(设备核A)在事务层形成事务层包(TLP——Transaction Layer Package),储存在发送缓冲器里,等待推向下层。在数据链路层,在TLP 包上再串接一些附加信息,这些信息是对方接收TLP 包时进行错误检查要用到的,形成数据链路层包(DLLP——Data Link Layer Package);在物理层,对DLLP 包进行编码,占用链路中的可用通道,从发送器发送出去。
在接收端,实际上是发送端的“逆”过程。如果说发送端是在不断组包,那么接收端就是不断的拆包,最后提取出有用的数据信息供B设备的应用程序使用。
整个过程实际上和以太网的过程很相似,都是在不同层级上进行数据的扩展。在FPGA的开发过程中,实际上从事务层到物理层都是封装好了的,组成标准IP核。用户通过IP核要求的总线协议(如AXI4-Stream)与之进行数据交换。
2. 事务层协议
2.1 数据包结构
有了IP核之后,实际上我们最关心的就是事务层包的数据格式。
事务层数据包(TLP)主要由:一个或多个可选的前缀(TLP Prefixes)、一个帧头(TLP Header)、一个数据有效负载(Data Payload)和一个可选的摘要(TLP Dignest)组成,下面简单介绍一下各部分。
- 前缀(TLP Prefixes)
有PCIe V2.1总规范引入,主要起扩展帧头的作用。如果用不到,可以省去该字段。
- 帧头(TLP Header)
TLP Header是TLP中最重要的标志,不同的TLP其头的定义并不相同。TLP 头标长3 或者4 个DW(DW = double word——双字,32位),格式和内容随事物类型变化;
- 数据有效负载(Data Payload)
即主设备要传输的数据。数据的长度最小为0,最大为1024DW,视具体情况而定。该字段也是一个可选项,因为有些TLP并不需要传递数据,如存储器读请求、配置和I/O写完成TLP也不需要。
- 摘要(TLP Dignest)
摘要是一个可选项,长度为1DW。一个TLP是否需要Dignes是由Header中TD字段决定。如果接受设备支持ECRC校验的功能的话,则该字段用来防止TLP中的数据校验码ECRC。
2.2 帧头含义详述
TLP Header长3 DW或者4 DW,格式和内容随事务类型的不同而不同。但是对于所有TLP Header来讲,都拥有相同的第一个DW定义,如下图所示(R:Reserved,为0)。
- Fmt([31:29])——Format of TLP
Fmt是关于头标长度和该TLP是否有数据(字段)的信息,如下图所示。实际上是3 DW还是4 DW是根据要访问目标的地址位宽有关。
-
Type([28:24])
Type的5位编码与Fmt字段一起用于规定事务类型、头标长度和是否有数据负载,如下图所示,只列举了一部分常用的类型,完整版可以查阅官方协议规范。
-
TC([22:20])
Traffic Class,传输类型也代表优先级,优先级高的先得到服务。这里是3比特,说明可以分为8个等级,0-7,TC默认是0,数字越大,优先级越高。
-
Attr([18]、[13:12])
该字段表述TLP的属性,由3位组成,注意不是连续的。具体含义见规范。
-
TH([16])
位为 1 表示当前 TLP 中含有 TPH(TLP Processing Hint)信息,TPH 是 PCIe V2.1 总线规范引入的一个重要功能。TLP 的发送端可以使用 TPH 信息,通知接收端即将访问数据的特性,以便接收端合理地预读和管理数据。
-
TD([15])
表示 TLP 中的 TLP Digest(之前说ECRC可选)是否有效,如果这个这个bit置起来,说明该TLP包含ECRC,接收端应该做CRC校验;
-
EP([14])
表示当前 TLP 中的数据是否有效,为 1 表示无效,为 0 表示有效。
-
AT([11:10])
Address Type,地址种类,与 PCIe 总线的地址转换相关,可暂时不考虑。
-
Length([9:0])
用来描述 TLP 的有效负载(Data Payload)大小。PCIe 总线设置 Length 字段的目的是提高总线的传送效率。Length 字段以 DW 为单位,其最小单位为 1 个 DW。
3. 报文举例
因为PICe的报文种类非常多,只举两个进行举例说明。
3.1 寄存器读报文
如下图所示,是一个32位寻址的寄存器读的完整报文(上节只介绍了第一个DW)。首先解释一下多的几个字段的含义。
- Requester ID
该字段字段包含生成TLP报文的PCIe设备的总线号(Bus Number)、设备号(Device Number)和功能号(Function Number)。唯一的找到目标设备,那是因为不同的Endpoint设备空间会映射到Host内存空间的不同位置。
- Tag
Requester ID、Tag合起来组成Transaction ID,在同一时间段内,PCIe设备发出的每一个Non-Posted数据请求TLP,其Transaction ID必须唯一。也就是Tag必须唯一。
- Last DW BE和1st DW BE
在PCIe 总线以字节为基本单位迕行数据传递,但是 Length 字段以 DW 为最小单位。为此TLP 使用 Last DW BE 和 First DW BE 返两个字段迕行字节使能,使得在一个 TLP中,有效数据以字节为单位。
- Address
对一个PCIe设备来说,它开放给Host访问的设备空间首先会映射到Host的内存空间,Host如果想访问设备的某个空间,TLP Header当中的地址应该设置为该访问空间在Host内存的映射地址。
值得注意的是:报文是以DW划分来进行说明,但实际过程中,顶层应用与PCIe IP核采用64位数据的AXI4通信,所以在发送TLP所需字段数据时,主要大小端的问题。
3.2 完成报文
有non-posted request TLP,才有Completion TLP。有因才有果。前面看到,Requester 的TLP当中都有Requester ID和Tag,来告诉接收者发起者是谁。那么响应者的目标地址就很简单,照抄发起者的源地址就可以了。因此,Completion TLP的Header如下:
- compl Status
完成情况指示。000--成功完成;001--不支持该请求。其余情况可查阅规范。
- Byte Count
是指还剩下多少字节的数据需要读取。其余字段可自行查阅规范。
4. 机制简述
4.1 Non-Posted和Posted
PCIe总线规定了两类数据传送方式,分别是Non-Posted和Posted数据传送方式。
在PCIe总线中,Non-Posted总线事务分两部分进行,首先是发送端向接收端提交总线读写请求,之后接收端再向发送端发送完成(Completion)报文。PCIe总线使用Split传送方式处理所有Non-Posted总线事务,存储器读、I/O读写和配置读写这些Non-Posted总线事务都使用Split传送方式。简单的说就是“一问一答”的方式。
而Posted总线事务,是只向终端发送报文,而终端无需反馈完成报文,所以是一种“单向发送”的机制。