基于FPGA 的PCIe 3.0 高速DMA 控制器实现
2022-07-14毋高峰
毋高峰
(焦作师范高等专科学校,河南 焦作 454000)
1 PCI Express 总线概述
PCI Express 总线(以下简称“PCIe”)总线采用点对点串行连接方式,使用高速差分信号线传输数据,提高了抗干扰能力,保障了数据传输的完整性和可靠性,同时也可以根据设计性能需求,将一个PCIe 物理链接灵活地配置成x1、x2、x4、x8、x16 及x32 多种链路模式,以及PCIe 1.0、PCIe 2.0、PCIe 3.0、PCIe 4.0和PCIe 5.0 不同的比特率[1]。其层次结构分明,从上到下分为事务传输层(Transaction Layer)、数据链路层(Data Link Layer)和物理层(Physical Layer),PCIe层次结构如图1 所示。事务传输层将设备核心层的数据和请求封装成TLP(Transaction Layer packet)数据包发送给数据链路层,并解析出来自数据链路层的TLP 数据包上报给设备核心层;数据链路层通过发送和接收DLLP(Data Link Layer packet)实现Ack/Nak应答处理机制,实现数据包的链路层校验和流控管理,同时将来自事务传输层的TLP 添加前缀和后缀发送到物理层,将来自物理层的数据包删除前缀和后缀上报给事务传输层;物理层完成数据流的加解扰、编解码和串并转换,实现将数据链路层的数据包以比特流的形式通过物理链路发送到对端物理层,并将来自对端物理层的比特流转换成数据包上报给数据链路层,同时物理层还要负责链路的协商。
图1 PCIe 层次结构图
2 事务传输层协议
PCIe 总线是基于请求和响应的通信机制,设备A要访问设备B 的内存,则设备A 要向设备B 发送一个请求,而设备B 需要一个完成向设备A 反馈请求结果。作为PCIe总线结构最高层的事务传输层则是负责请求和响应TLP 的生成,一个完整的TLP 由1 个或者多个TLP Prefix、TLP 头(Header)、1 个可选数据负载(Payload)以及1 个可选的端到端CRC(ECRC)组成[2]。Header 指定事务类型、优先级、路由信息及其它数据包特征,TLP Header 如图2 所示,数据负载是TLP 要传输的数据,长度最小为0,最大为1 024 DW,而ECRC 是对TLP 传输正确性的校验。
图2 TLP Header 数据格式
3 循环队列
为了充分利用PC 内存,减少数据传输延时,PC软件程序采用循环队列缓存DMA 读写的关键信息,DMA 控制器读取循环队列,开启DMA 的读写操作,进行数据传输。循环队列是由多个元素组成的一个首尾相连圆环,如图3 所示,在循环队列结构中,当队列的最后一个存储单元已被使用,想要再插入新的元素时,只有当队列的第一个存储单元空闲时,才可将新元素插入到第一个存储单元,即将队列的第一个存储作为队尾。循环队列是通过2 个指针front 和rear 判断队列的空满防止队列溢出的。
图3 循环队列示意图
4 DMA 控制器设计
DAM 控制器是基于PCIe IP 硬核,添加对事物传输层数据包TLP 的收发控制,来实现FPGA 和PC 之间的数据高速传输。本设计是由PC 申请2 个独立的内存空间,搭建出DMA 的读写循环队列,循环队列的front 和rear 指针分别由FPGA 和PC 控制。在进行数据传输时,PC 在循环队列中插入DMA 读写的描述符,并更新循环队列指针,FPGA 通过存储器读TLP 获取描述符,发起DMA 读写操作实现数据从PC 到FPGA之间的数据传输,数据传输完成后,FPGA 更新循环队列指针,结束此次DMA 读写操作。
4.1 DMA 读操作实现数据从PC 到FPGA 的传输
PC 申请一段物理地址连续的内存空间[3],填充需要发送的数据,将数据长度和内存地址封装成DMA读描述符插入到DMA 读队列中,DMA 读描述符如图4 所示[4],更新DMA 读队列front 指针,并发送存储器写请求TLP 将front 指针发送给FPGA;FPGA 接收到DMA 读队列的front 指针,封装存储器读请求TLP,将DMA 读描述符从PC 中读出,然后解析出DMA 读描述符中的内存地址和数据长度,按照PCIe 总线协商的最大读取长度,向PCIe 总线发起一个或多个存储器读请求TLP,接收读完成TLP 将数据从内存中搬移到FPGA;数据搬移完成后,FPGA 更新DMA 读队列rear指针,发起DMA 写请求,TLP 将rear 指针发送给PC,完成了一次PC 到FPGA 的数据传输。
图4 DMA 读描述符数据格式
4.2 DMA 写操作实现数据从FPGA 到PC 的传输
PC 申请一段物理地址连续的内存空间,将内存地址封装成DMA 写描述符插入到DMA 写队列中,DMA写描述符如图5 所示,更新DMA 写队列front 指针,并发送存储器写请求TLP 将front 指针发送给FPGA;FPGA 接收到DMA 写队列的front 指针,封装存储器读请求TLP,将DMA 写描述符从PC 中读出,缓存到FIFO 中;FPGA 需要发送数据时,将DMA 写描述符从FIFO 中读出并解析,按照PCIe 总线协商的最大负载能力,向PCIe 总线发起一个或多个存储器写请求TLP,将数据写入到PC 申请好的内存中;在数据包完全发送后,FPGA 更新DMA 写队列rear 指针,并发起DMA 写请求TLP 将rear 指针发送给PC,通知PC 数据传输完,完成了一次FPGA 到PC 的数据传输。
图5 DMA 写描述符数据格式
5 DMA 控制器硬件实现
根据上述的DMA 控制器的设计方案,硬件设计采用DMA 读操作和DMA 写操作2 个单独的通道,如图6 所示,来实现DMA 控制器,共分为TLP 接收模块、TLP 发送模块、存储器读控制模块、存储器写控制模块、DMA 读队列读取模块、DMA 读数据模块,DMA 写队列读取模块和DMA 写数据模块[5]。
图6 DMA 控制器硬件实现框图
TLP 接收模块实现对来自PCIe IP 硬核事务传输层接口TLP 的接收控制,并对TLP 数据包进行解析。该模块有2 个单独的控制通道CQ 接口和RC 接口[6],CQ 接口通道接收PC 到FPGA 的存储器写TLP,实现对FPGA 内部的寄存器的配置;RC 接口通道接收PC到FPGA 的读完成包TLP,并根据TLP 携带的tag 号,将读完成包的数据发送给存储器读的请求者,实现将数据从内存到FPGA 的搬移。
TLP 发送模块实现向PCIe IP 硬核事务传输层接口的TLP 发送控制。该模块分别从存储器读控制模块和存储器写控制模块获取已封装完成的TLP 数据包,向PCIe 总线发送存储器读写请求。
存储器读控制模块实现存储器读请求TLP 的封装和发送控制,该模块轮询读取DMA 读队列模块、DMA读数据模块和DMA 写队列模块FIFO 中的数据,解析出存储器读请求TLP 所需的内存地址和数据长度,添加tag 号,封装成存储器读请求TLP,传输给TLP 发送模块,并将存储器读的请求者和对应的tag 号记录下来,发送给TLP 接收模块。
存储器写控制模块实现存储器写请求TLP 的封装和发送控制,该模块获取DMA 写数据模块FIFO 中的数据,获取存储器写请求TLP 的内存地址和数据长度以及要发送的数据,封装成存储器写请求TLP,发送给TLP 发送模块。
DMA 读队列读取模块实现读取DMA 读队列的信息生成,该模块查询DMA 读队列的空满状态,判断是否需要发起DMA 读操作,当DMA 读队列不空时,则可以生成存储器读信息,发起存储器读请求,获取读描述符,将描述符缓存到FIFO 中。
DMA 读数据模块实现DMA 读数据信息的生成和DMA 读队列rear 指针的控制,该模块读取DMA 读队列读取模块中的描述符缓存FIFO,解析出描述符中的数据地址和长度,并对数据长度进行最大为512 字节分片处理,然后依次将数据地址和长度封装成DMA读的信息写入FIFO 中,发送给存储器读控制模块,其中每写入一个DMA 读信息,地址要递增512,数据长度递减512;当读取的数据依次从TLP 接收模块接收完成后,则将DMA 读队列rear 指针递增1,并主动发起一次存储器写TLP 将rear 指针发送给PC。
DMA 写队列读取模块实现读取DMA 写队列的信息生成,该模块查询DMA 写队列的空满状态,判断是否需要发起DMA 写操作,当DMA 写队列不空时,则可以生成存储器读信息,发起存储器读请求,获取写描述符,将描述符缓存到FIFO 中。
DMA 写数据模块实现DMA 写数据信息的生成和DMA 写队列rear 指针的控制,该模块读取DMA 写队列读取模块中的描述符缓存FIFO,解析出描述符中的数据地址,并对要发送的数据长度进行最大为256 字节分片处理,然后依次将数据地址、长度和数据封装成DMA 写的信息写入FIFO 中,发送给存储器写控制模块,其中每写入一个DMA 写信息,地址要递增256,数据长度递减256;当待发送数据完整发送后,DMA写队列rear 指针递增1,并主动发起一次存储器写TLP将rear 指针发送给PC。
6 DMA 控制器验证
控制器的验证采用的是Xilinx XCKU040 FPGA,PC 采用DELL 7050 台式主机,其中FPGA 开发环境为Vivado 2018.3,本设计采用PCIe 3.0x4 IP 硬核,用户时钟为250 MHz,用户数据位宽为128 bit,理论上最大速率为32 Gbps。本设计采用LINUX 系统,搭建PCIe 测试的上位机程序,经大量的测试表明,DMA控制器的稳定性得以验证;性能测试采用的是2 KB 大小的随机数据,通过计算固定时间内传输的数据包个数计算出该控制器的DMA 读操作带宽为23.8 Gbps,DMA 写操作带宽为25.2 Gbps。
7 总结
本文阐述了DMA 控制器的设计和实现方法,提出了一种基于PCIe 3.0 IP 硬核的DMA 高速传输方案,通过对DMA 读写操作的控制的实现,完成了FPGA和PC 之间数据的高速传输,本设计可为数据存储、高清视频传输和信息安全等采用CPU+FPGA 架构方案的产品提供良好的参考。