毋高峰
(焦作師范高等專科學(xué)校,河南 焦作 454000)
PCI Express 總線(以下簡(jiǎn)稱“PCIe”)總線采用點(diǎn)對(duì)點(diǎn)串行連接方式,使用高速差分信號(hào)線傳輸數(shù)據(jù),提高了抗干擾能力,保障了數(shù)據(jù)傳輸?shù)耐暾院涂煽啃裕瑫r(shí)也可以根據(jù)設(shè)計(jì)性能需求,將一個(gè)PCIe 物理鏈接靈活地配置成x1、x2、x4、x8、x16 及x32 多種鏈路模式,以及PCIe 1.0、PCIe 2.0、PCIe 3.0、PCIe 4.0和PCIe 5.0 不同的比特率[1]。其層次結(jié)構(gòu)分明,從上到下分為事務(wù)傳輸層(Transaction Layer)、數(shù)據(jù)鏈路層(Data Link Layer)和物理層(Physical Layer),PCIe層次結(jié)構(gòu)如圖1 所示。事務(wù)傳輸層將設(shè)備核心層的數(shù)據(jù)和請(qǐng)求封裝成TLP(Transaction Layer packet)數(shù)據(jù)包發(fā)送給數(shù)據(jù)鏈路層,并解析出來(lái)自數(shù)據(jù)鏈路層的TLP 數(shù)據(jù)包上報(bào)給設(shè)備核心層;數(shù)據(jù)鏈路層通過(guò)發(fā)送和接收DLLP(Data Link Layer packet)實(shí)現(xiàn)Ack/Nak應(yīng)答處理機(jī)制,實(shí)現(xiàn)數(shù)據(jù)包的鏈路層校驗(yàn)和流控管理,同時(shí)將來(lái)自事務(wù)傳輸層的TLP 添加前綴和后綴發(fā)送到物理層,將來(lái)自物理層的數(shù)據(jù)包刪除前綴和后綴上報(bào)給事務(wù)傳輸層;物理層完成數(shù)據(jù)流的加解擾、編解碼和串并轉(zhuǎn)換,實(shí)現(xiàn)將數(shù)據(jù)鏈路層的數(shù)據(jù)包以比特流的形式通過(guò)物理鏈路發(fā)送到對(duì)端物理層,并將來(lái)自對(duì)端物理層的比特流轉(zhuǎn)換成數(shù)據(jù)包上報(bào)給數(shù)據(jù)鏈路層,同時(shí)物理層還要負(fù)責(zé)鏈路的協(xié)商。

圖1 PCIe 層次結(jié)構(gòu)圖
PCIe 總線是基于請(qǐng)求和響應(yīng)的通信機(jī)制,設(shè)備A要訪問(wèn)設(shè)備B 的內(nèi)存,則設(shè)備A 要向設(shè)備B 發(fā)送一個(gè)請(qǐng)求,而設(shè)備B 需要一個(gè)完成向設(shè)備A 反饋請(qǐng)求結(jié)果。作為PCIe總線結(jié)構(gòu)最高層的事務(wù)傳輸層則是負(fù)責(zé)請(qǐng)求和響應(yīng)TLP 的生成,一個(gè)完整的TLP 由1 個(gè)或者多個(gè)TLP Prefix、TLP 頭(Header)、1 個(gè)可選數(shù)據(jù)負(fù)載(Payload)以及1 個(gè)可選的端到端CRC(ECRC)組成[2]。Header 指定事務(wù)類型、優(yōu)先級(jí)、路由信息及其它數(shù)據(jù)包特征,TLP Header 如圖2 所示,數(shù)據(jù)負(fù)載是TLP 要傳輸?shù)臄?shù)據(jù),長(zhǎng)度最小為0,最大為1 024 DW,而ECRC 是對(duì)TLP 傳輸正確性的校驗(yàn)。

圖2 TLP Header 數(shù)據(jù)格式
為了充分利用PC 內(nèi)存,減少數(shù)據(jù)傳輸延時(shí),PC軟件程序采用循環(huán)隊(duì)列緩存DMA 讀寫的關(guān)鍵信息,DMA 控制器讀取循環(huán)隊(duì)列,開(kāi)啟DMA 的讀寫操作,進(jìn)行數(shù)據(jù)傳輸。循環(huán)隊(duì)列是由多個(gè)元素組成的一個(gè)首尾相連圓環(huán),如圖3 所示,在循環(huán)隊(duì)列結(jié)構(gòu)中,當(dāng)隊(duì)列的最后一個(gè)存儲(chǔ)單元已被使用,想要再插入新的元素時(shí),只有當(dāng)隊(duì)列的第一個(gè)存儲(chǔ)單元空閑時(shí),才可將新元素插入到第一個(gè)存儲(chǔ)單元,即將隊(duì)列的第一個(gè)存儲(chǔ)作為隊(duì)尾。循環(huán)隊(duì)列是通過(guò)2 個(gè)指針front 和rear 判斷隊(duì)列的空滿防止隊(duì)列溢出的。

圖3 循環(huán)隊(duì)列示意圖
DAM 控制器是基于PCIe IP 硬核,添加對(duì)事物傳輸層數(shù)據(jù)包TLP 的收發(fā)控制,來(lái)實(shí)現(xiàn)FPGA 和PC 之間的數(shù)據(jù)高速傳輸。本設(shè)計(jì)是由PC 申請(qǐng)2 個(gè)獨(dú)立的內(nèi)存空間,搭建出DMA 的讀寫循環(huán)隊(duì)列,循環(huán)隊(duì)列的front 和rear 指針?lè)謩e由FPGA 和PC 控制。在進(jìn)行數(shù)據(jù)傳輸時(shí),PC 在循環(huán)隊(duì)列中插入DMA 讀寫的描述符,并更新循環(huán)隊(duì)列指針,F(xiàn)PGA 通過(guò)存儲(chǔ)器讀TLP 獲取描述符,發(fā)起DMA 讀寫操作實(shí)現(xiàn)數(shù)據(jù)從PC 到FPGA之間的數(shù)據(jù)傳輸,數(shù)據(jù)傳輸完成后,F(xiàn)PGA 更新循環(huán)隊(duì)列指針,結(jié)束此次DMA 讀寫操作。
PC 申請(qǐng)一段物理地址連續(xù)的內(nèi)存空間[3],填充需要發(fā)送的數(shù)據(jù),將數(shù)據(jù)長(zhǎng)度和內(nèi)存地址封裝成DMA讀描述符插入到DMA 讀隊(duì)列中,DMA 讀描述符如圖4 所示[4],更新DMA 讀隊(duì)列front 指針,并發(fā)送存儲(chǔ)器寫請(qǐng)求TLP 將front 指針發(fā)送給FPGA;FPGA 接收到DMA 讀隊(duì)列的front 指針,封裝存儲(chǔ)器讀請(qǐng)求TLP,將DMA 讀描述符從PC 中讀出,然后解析出DMA 讀描述符中的內(nèi)存地址和數(shù)據(jù)長(zhǎng)度,按照PCIe 總線協(xié)商的最大讀取長(zhǎng)度,向PCIe 總線發(fā)起一個(gè)或多個(gè)存儲(chǔ)器讀請(qǐng)求TLP,接收讀完成TLP 將數(shù)據(jù)從內(nèi)存中搬移到FPGA;數(shù)據(jù)搬移完成后,F(xiàn)PGA 更新DMA 讀隊(duì)列rear指針,發(fā)起DMA 寫請(qǐng)求,TLP 將rear 指針發(fā)送給PC,完成了一次PC 到FPGA 的數(shù)據(jù)傳輸。

圖4 DMA 讀描述符數(shù)據(jù)格式
PC 申請(qǐng)一段物理地址連續(xù)的內(nèi)存空間,將內(nèi)存地址封裝成DMA 寫描述符插入到DMA 寫隊(duì)列中,DMA寫描述符如圖5 所示,更新DMA 寫隊(duì)列front 指針,并發(fā)送存儲(chǔ)器寫請(qǐng)求TLP 將front 指針發(fā)送給FPGA;FPGA 接收到DMA 寫隊(duì)列的front 指針,封裝存儲(chǔ)器讀請(qǐng)求TLP,將DMA 寫描述符從PC 中讀出,緩存到FIFO 中;FPGA 需要發(fā)送數(shù)據(jù)時(shí),將DMA 寫描述符從FIFO 中讀出并解析,按照PCIe 總線協(xié)商的最大負(fù)載能力,向PCIe 總線發(fā)起一個(gè)或多個(gè)存儲(chǔ)器寫請(qǐng)求TLP,將數(shù)據(jù)寫入到PC 申請(qǐng)好的內(nèi)存中;在數(shù)據(jù)包完全發(fā)送后,F(xiàn)PGA 更新DMA 寫隊(duì)列rear 指針,并發(fā)起DMA 寫請(qǐng)求TLP 將rear 指針發(fā)送給PC,通知PC 數(shù)據(jù)傳輸完,完成了一次FPGA 到PC 的數(shù)據(jù)傳輸。

圖5 DMA 寫描述符數(shù)據(jù)格式
根據(jù)上述的DMA 控制器的設(shè)計(jì)方案,硬件設(shè)計(jì)采用DMA 讀操作和DMA 寫操作2 個(gè)單獨(dú)的通道,如圖6 所示,來(lái)實(shí)現(xiàn)DMA 控制器,共分為TLP 接收模塊、TLP 發(fā)送模塊、存儲(chǔ)器讀控制模塊、存儲(chǔ)器寫控制模塊、DMA 讀隊(duì)列讀取模塊、DMA 讀數(shù)據(jù)模塊,DMA 寫隊(duì)列讀取模塊和DMA 寫數(shù)據(jù)模塊[5]。

圖6 DMA 控制器硬件實(shí)現(xiàn)框圖
TLP 接收模塊實(shí)現(xiàn)對(duì)來(lái)自PCIe IP 硬核事務(wù)傳輸層接口TLP 的接收控制,并對(duì)TLP 數(shù)據(jù)包進(jìn)行解析。該模塊有2 個(gè)單獨(dú)的控制通道CQ 接口和RC 接口[6],CQ 接口通道接收PC 到FPGA 的存儲(chǔ)器寫TLP,實(shí)現(xiàn)對(duì)FPGA 內(nèi)部的寄存器的配置;RC 接口通道接收PC到FPGA 的讀完成包TLP,并根據(jù)TLP 攜帶的tag 號(hào),將讀完成包的數(shù)據(jù)發(fā)送給存儲(chǔ)器讀的請(qǐng)求者,實(shí)現(xiàn)將數(shù)據(jù)從內(nèi)存到FPGA 的搬移。
TLP 發(fā)送模塊實(shí)現(xiàn)向PCIe IP 硬核事務(wù)傳輸層接口的TLP 發(fā)送控制。該模塊分別從存儲(chǔ)器讀控制模塊和存儲(chǔ)器寫控制模塊獲取已封裝完成的TLP 數(shù)據(jù)包,向PCIe 總線發(fā)送存儲(chǔ)器讀寫請(qǐng)求。
存儲(chǔ)器讀控制模塊實(shí)現(xiàn)存儲(chǔ)器讀請(qǐng)求TLP 的封裝和發(fā)送控制,該模塊輪詢讀取DMA 讀隊(duì)列模塊、DMA讀數(shù)據(jù)模塊和DMA 寫隊(duì)列模塊FIFO 中的數(shù)據(jù),解析出存儲(chǔ)器讀請(qǐng)求TLP 所需的內(nèi)存地址和數(shù)據(jù)長(zhǎng)度,添加tag 號(hào),封裝成存儲(chǔ)器讀請(qǐng)求TLP,傳輸給TLP 發(fā)送模塊,并將存儲(chǔ)器讀的請(qǐng)求者和對(duì)應(yīng)的tag 號(hào)記錄下來(lái),發(fā)送給TLP 接收模塊。
存儲(chǔ)器寫控制模塊實(shí)現(xiàn)存儲(chǔ)器寫請(qǐng)求TLP 的封裝和發(fā)送控制,該模塊獲取DMA 寫數(shù)據(jù)模塊FIFO 中的數(shù)據(jù),獲取存儲(chǔ)器寫請(qǐng)求TLP 的內(nèi)存地址和數(shù)據(jù)長(zhǎng)度以及要發(fā)送的數(shù)據(jù),封裝成存儲(chǔ)器寫請(qǐng)求TLP,發(fā)送給TLP 發(fā)送模塊。
DMA 讀隊(duì)列讀取模塊實(shí)現(xiàn)讀取DMA 讀隊(duì)列的信息生成,該模塊查詢DMA 讀隊(duì)列的空滿狀態(tài),判斷是否需要發(fā)起DMA 讀操作,當(dāng)DMA 讀隊(duì)列不空時(shí),則可以生成存儲(chǔ)器讀信息,發(fā)起存儲(chǔ)器讀請(qǐng)求,獲取讀描述符,將描述符緩存到FIFO 中。
DMA 讀數(shù)據(jù)模塊實(shí)現(xiàn)DMA 讀數(shù)據(jù)信息的生成和DMA 讀隊(duì)列rear 指針的控制,該模塊讀取DMA 讀隊(duì)列讀取模塊中的描述符緩存FIFO,解析出描述符中的數(shù)據(jù)地址和長(zhǎng)度,并對(duì)數(shù)據(jù)長(zhǎng)度進(jìn)行最大為512 字節(jié)分片處理,然后依次將數(shù)據(jù)地址和長(zhǎng)度封裝成DMA讀的信息寫入FIFO 中,發(fā)送給存儲(chǔ)器讀控制模塊,其中每寫入一個(gè)DMA 讀信息,地址要遞增512,數(shù)據(jù)長(zhǎng)度遞減512;當(dāng)讀取的數(shù)據(jù)依次從TLP 接收模塊接收完成后,則將DMA 讀隊(duì)列rear 指針遞增1,并主動(dòng)發(fā)起一次存儲(chǔ)器寫TLP 將rear 指針發(fā)送給PC。
DMA 寫隊(duì)列讀取模塊實(shí)現(xiàn)讀取DMA 寫隊(duì)列的信息生成,該模塊查詢DMA 寫隊(duì)列的空滿狀態(tài),判斷是否需要發(fā)起DMA 寫操作,當(dāng)DMA 寫隊(duì)列不空時(shí),則可以生成存儲(chǔ)器讀信息,發(fā)起存儲(chǔ)器讀請(qǐng)求,獲取寫描述符,將描述符緩存到FIFO 中。
DMA 寫數(shù)據(jù)模塊實(shí)現(xiàn)DMA 寫數(shù)據(jù)信息的生成和DMA 寫隊(duì)列rear 指針的控制,該模塊讀取DMA 寫隊(duì)列讀取模塊中的描述符緩存FIFO,解析出描述符中的數(shù)據(jù)地址,并對(duì)要發(fā)送的數(shù)據(jù)長(zhǎng)度進(jìn)行最大為256 字節(jié)分片處理,然后依次將數(shù)據(jù)地址、長(zhǎng)度和數(shù)據(jù)封裝成DMA 寫的信息寫入FIFO 中,發(fā)送給存儲(chǔ)器寫控制模塊,其中每寫入一個(gè)DMA 寫信息,地址要遞增256,數(shù)據(jù)長(zhǎng)度遞減256;當(dāng)待發(fā)送數(shù)據(jù)完整發(fā)送后,DMA寫隊(duì)列rear 指針遞增1,并主動(dòng)發(fā)起一次存儲(chǔ)器寫TLP將rear 指針發(fā)送給PC。
控制器的驗(yàn)證采用的是Xilinx XCKU040 FPGA,PC 采用DELL 7050 臺(tái)式主機(jī),其中FPGA 開(kāi)發(fā)環(huán)境為Vivado 2018.3,本設(shè)計(jì)采用PCIe 3.0x4 IP 硬核,用戶時(shí)鐘為250 MHz,用戶數(shù)據(jù)位寬為128 bit,理論上最大速率為32 Gbps。本設(shè)計(jì)采用LINUX 系統(tǒng),搭建PCIe 測(cè)試的上位機(jī)程序,經(jīng)大量的測(cè)試表明,DMA控制器的穩(wěn)定性得以驗(yàn)證;性能測(cè)試采用的是2 KB 大小的隨機(jī)數(shù)據(jù),通過(guò)計(jì)算固定時(shí)間內(nèi)傳輸?shù)臄?shù)據(jù)包個(gè)數(shù)計(jì)算出該控制器的DMA 讀操作帶寬為23.8 Gbps,DMA 寫操作帶寬為25.2 Gbps。
本文闡述了DMA 控制器的設(shè)計(jì)和實(shí)現(xiàn)方法,提出了一種基于PCIe 3.0 IP 硬核的DMA 高速傳輸方案,通過(guò)對(duì)DMA 讀寫操作的控制的實(shí)現(xiàn),完成了FPGA和PC 之間數(shù)據(jù)的高速傳輸,本設(shè)計(jì)可為數(shù)據(jù)存儲(chǔ)、高清視頻傳輸和信息安全等采用CPU+FPGA 架構(gòu)方案的產(chǎn)品提供良好的參考。