一、PCIe概況
隨著現(xiàn)代處理器技術(shù)的發(fā)展,使用高速差分總線替代并行總線已是大勢所趨。與單端并行信號相比,高速差分信號可以使用更高的時鐘頻率,從而可以使用更少的信號線達到更高的通訊速度。PCIe總線解決了PCI總線的不足,它的發(fā)展將取代PCI成為新型的數(shù)據(jù)總線,其提供了更加完善的性能,更多的功能,更強的可擴展性和更低的成本 。
在PCIE中有兩種數(shù)據(jù)傳輸方式:
1>DMA(Direct Memory Access)模式:直接內(nèi)存訪問,該模式下數(shù)據(jù)傳送不是由CPU負(fù)責(zé)處理,而是由一個DMA控制器來完成,占用較少的CPU資源
2>PIO(Programmed Input-Output)模式:可編程IO,該模式下數(shù)據(jù)傳送由CPU執(zhí)行I/O端口指令來處理,占用大量的CPU資源,數(shù)據(jù)傳輸速度也大大低于DMA模式
使用DMA模式時,計算機的運行速度會比使用PIO模式快很多
二、PCIe層次結(jié)構(gòu)
PCIe 規(guī)范對于設(shè)備的設(shè)計采用分層的結(jié)構(gòu),主要分為事務(wù)層、數(shù)據(jù)鏈路層和物理層,在設(shè)備的發(fā)送時,首先根據(jù)來自FPGA的信息,在事務(wù)層形成事務(wù)層包(TLP),儲存在發(fā)送緩沖器里,等待傳給下層;數(shù)據(jù)鏈路層中,在 TLP 包上串接一些附加信息成為數(shù)據(jù)鏈路層包(DLLP),這些信息是接收方接受 TLP 包時進行錯誤檢查要用到的;物理層中,對DLLP包進行編碼成物理層包(PLP),占用鏈路中的可用通道發(fā)送出去。TLP、DLLP、PLP產(chǎn)生于各自所在層,最后通過電或光等介質(zhì)和另一方通訊。這其中DLLP、PLP平常不需要關(guān)心,在IP核中封裝好了,在FPGA上做PCIe的功能,就變成對TLP的處理。
事務(wù)層(Transaction Layer):
TLP由幀頭、數(shù)據(jù)、摘要組成,7系列FPGA 開始,使用標(biāo)準(zhǔn)的 AXI4 總線協(xié)議進行通信,因此 PCIe的TLP采用AXI4-S接口協(xié)議進行傳輸,數(shù)據(jù)的傳輸以大端方式對齊(高位放在低地址)
頭標(biāo): 長度為3或4個DW(double word),格式和內(nèi)容隨事務(wù)類型變化
數(shù)據(jù): (若該 TLP 不攜帶數(shù)據(jù),那該段為空)
摘要: 是基于頭標(biāo)、數(shù)據(jù)而計算出來的CRC,稱為 ECRC,一般該段由 IP核填充,所以用戶只需處理TLP中頭標(biāo)和數(shù)據(jù)段
Fmt[1:0]段 是關(guān)于頭標(biāo)長度和該 TLP 是否有數(shù)據(jù)在的信息:
Fmt[1:0] | 頭標(biāo)長度 | 有無數(shù)據(jù) |
---|---|---|
00 | 3DW | 無數(shù)據(jù) |
01 | 4DW | 無數(shù)據(jù) |
10 | 3DW | 有數(shù)據(jù) |
11 | 4DW | 有數(shù)據(jù) |
Type與 Fmt字段:一起用于規(guī)定事務(wù)類型、頭標(biāo)長度和是否有數(shù)據(jù)載荷
Non-Posted命令:若設(shè)備發(fā)出一個Non-Posted請求,一段時間后,接收端需回復(fù)一個完成包,若不回復(fù)則可能遇到異常
Posted命令:不需要回復(fù)完成包給發(fā)送端
TYPE [4:0] | FMT[1:0] | TLP | Posted? |
---|---|---|---|
00000 | 00/01 (無數(shù)據(jù)) | 存儲器讀請求(MRd) | Non- |
00000 | 10/11 (寫數(shù)據(jù)) | 存儲器寫請求(MWr) | Posted |
00001 | 00/01 (無數(shù)據(jù)) | 鎖定存儲器讀請求(MRdLk) | Non- |
00010 | 00 (無數(shù)據(jù)) | IO 讀請求(IORd) | Non- |
00010 | 10 (寫數(shù)據(jù)) | IO 寫請求(IOWr) | Non- |
00100 | 00 (無數(shù)據(jù)) | Type0 配置讀請求(CfgRd0) | Non- |
00100 | 10 (寫數(shù)據(jù)) | Type0 配置寫請求(CfgWr0) | Non- |
00101 | 00 (無數(shù)據(jù)) | Type1 配置讀請求(CfgRd1) | Non- |
00101 | 10 (寫數(shù)據(jù)) | Type1 配置寫請求(CfgWr1) | Non- |
10xxx | 01 (無數(shù)據(jù)) | 消息請求(Msg) | Posted |
10xxx | 11 (寫數(shù)據(jù)) | 帶數(shù)據(jù)的消息請求(MsgD) | |
01010 | 00 (無數(shù)據(jù)) | 完成(Cpl) | |
01010 | 10 (寫數(shù)據(jù)) | 帶數(shù)據(jù)的完成(CplD) | |
01011 | 00 (無數(shù)據(jù)) | 鎖定完成(CplLk) | |
01011 | 10 (寫數(shù)據(jù)) | 帶數(shù)據(jù)的鎖定完成(CplDLk) |
例如:發(fā)送的數(shù)據(jù)為0x4a00_0001_01a0_0004,0x01a0_0a10_0403_0201
則:Fmt是2’b10,Type 是5’b01010,判斷為 3DW 帶數(shù)據(jù)的完成包,0x4a00_0001_01a0_0004_01a0_0a10是頭標(biāo),0x0403_0201是所帶的數(shù)據(jù)
Length字段: 在讀存儲器請求報文中,表示需要從目標(biāo)設(shè)備數(shù)據(jù)區(qū)域讀取的數(shù)據(jù)長度;在寫存儲器請求報文中,表示當(dāng)前報文的DataPayload長度,長度單位為DW
last/1st DW BE字段: PCIe總線以字節(jié)為基本單位進行數(shù)據(jù)傳遞,但是Length字段以DW為最小單位,該字段用于規(guī)定第一個和最后一個的有效字節(jié)的位置
Requester ID : 該TLP包的產(chǎn)生設(shè)備,的總線號(Bus Number)、設(shè)備號(Device Number)、功能號(Function Number)等
Tag: Requester ID、Tag合起來組成Transaction ID,在同一時間段內(nèi),PCIe設(shè)備發(fā)出的每一個Non-Posted數(shù)據(jù)請求TLP,其Transaction ID必須唯一,即Tag必須唯一
讀寫TLP包的格式:
上圖中的兩個格式,前者是針對64位地址的讀寫包,后者則是針對32位地址的讀寫包
完成包的格式:
Completer ID: 該完成包的產(chǎn)生設(shè)備的ID號
Byte Count: 記錄源設(shè)備還需要從目標(biāo)設(shè)備中獲得多少字節(jié)的數(shù)據(jù)才能完成全部數(shù)據(jù)傳遞
Lower Address: 接收端必須使用存儲器讀寫完成TLP的Low Address 字段,識別該TLP中包含有效數(shù)據(jù)的起始地址
三、事務(wù)層空間
PCI配置空間:主要用于向系統(tǒng)提供設(shè)備自身的基本信息,并接受系統(tǒng)對設(shè)備全局狀態(tài)的控制和查詢(設(shè)備只有在系統(tǒng)軟件初始化配置空間之后,才能夠被其他主設(shè)備訪問,當(dāng)配置空間被初值化后,該設(shè)備在當(dāng)前的PCI總線樹上將擁有一個獨立的BAR空間)
I/O空間:主要包括設(shè)備的控制狀態(tài)寄存器,一般用于控制查詢設(shè)備的工作狀態(tài)及少量數(shù)據(jù)交換
存儲器空間:一般用于大量數(shù)據(jù)的交換(內(nèi)存、顯存、擴展ROM、設(shè)備緩沖區(qū)等)
消息空間 : 傳遞消息的空間
PCIe通訊是靠發(fā)送TLP包,讀寫包里都會有地址信息,若FPGA向PC發(fā)送TLP 包,例如 MWr 包,那么地址信息就是PC的物理地址;若發(fā)送的是 MRd 包,那PC收到后會回復(fù)一個完成包,F(xiàn)PGA從完成包提取出數(shù)據(jù)即可
PC 如何讀寫板卡的數(shù)據(jù):
PC啟動時,BIOS探測PCIe設(shè)備有多少個BAR空間,每個空間有多大,然后對應(yīng)為這些空間分配地址
以上圖為例,BAR2的空間大小為0x1000,PC上的起始地址為0xFDEFF000,若想通過PC訪問BAR2的0x40地址,則在PC上直接訪問0xFDEFF040即可,起始地址在不同的PC上是不一樣的(但是偏移地址是相同的),在 FPGA 中,BAR 空間的設(shè)置,是根據(jù)用戶需求在IP核里定義大小的
四、發(fā)送中斷
PCIe可以發(fā)出兩種中斷:虛擬INTx信號線(PCI的信號)和MSI(消息)
虛擬INTx信號線:
發(fā)送的數(shù)據(jù)為:0x3400_0000_0100_0020, 0x0000_0000_0000_0000
則:Fmt為 2’b01,Type 為5’b10100,判斷為消息請求包,Message Code 為0x20(8’b0010_0000),判斷為中斷(INTx)消息
發(fā)送的數(shù)據(jù)為:0x3400_0000_0100_0024, 0x0000_0000_0000_0000時,
則:Fmt 為2’b01,Type 為 5’b10100,判斷為消息請求包,Message Code 為0x24 (8’b0010_0100),判斷為中斷(INTx)撤銷消息
這個之后有需要的話,可以做實驗測試,現(xiàn)階段就先只找到這兩個信號線(如圖直接搜索int_(x))
MSI中斷:
是基于消息機制的,PC啟動后會為 PCIe 板卡分配消息地址,板卡發(fā)送中斷的話,只需向?qū)?yīng)的地址發(fā)送消息即可(消息內(nèi)容中包含消息號,每個消息號對應(yīng)在PC 端的某一地址)
注:在Xilinx平臺上,中斷和其他包是分開的,中斷發(fā)送是非常簡單的,只需要簡單操作幾條信號線,PCIe 核就可以自己組織需要的中斷包向外發(fā)送
五、PCIe的IP核
使用環(huán)境:VIVADO 2017.4
IP核版本:7 Series FPGAs Integrated Block for PCI Express v3.3
官方文檔:pg054
IP核概覽圖:
IP核接口定義:
System Interface:
信號 | I/O | 功能 |
---|---|---|
sys_clk | I | 有3個可選頻率,輸入時鐘要和IP配置的值一致 |
sys_rst_n | I | (異步復(fù)位、低有效),至少1500ns |
PCI Express Interface:
上圖為4X模式下的,外部引腳的接口,共4組,每組都有收發(fā)信號,且收發(fā)信號線均為差分線
Configuration Interface:
這類信號名稱一般以cfg_開頭,主要用于檢測PCIE終端的configuration space狀態(tài),詳情見手冊,此類信號在IP核上有很多很多,比如:
其中的中斷接口信號一般以cfg_interrupt開頭
其中的異常報告信號一般以cfg_err_開頭
Physical Layer Interface:
此類信號一般以pl_開頭,詳情見手冊,用于控制和檢測PCIE物理層,可以改變速度、位寬等,一般不使用
Dynamic Reconfiguration Port Interface:
DRP接口,此類信號一般以pcie_drp_開頭,詳情見手冊,用于動態(tài)配置PCIE核的寄存器,用于調(diào)試
Debug Interface:
user_和fc_開頭的信號,輸出系統(tǒng)工作狀態(tài),用于調(diào)試
AXI4-S Interface:
以m_axis_rx_、s_axis_tx_、tx_、rx_開頭,用于傳輸數(shù)據(jù),詳情見手冊
六、DMA傳輸模式XAPP1052官方例程解析
xapp1052是xilinx官方給出的一個有關(guān)DMA數(shù)據(jù)傳輸?shù)臉永?,用于PC端和FPGA端之間的DMA數(shù)據(jù)傳輸,雖然xapp1052并不是一個完整的DMA數(shù)據(jù)傳輸?shù)慕K端硬件設(shè)計,但是還是有很大參考價值的
文件層次:
主要包括PCIe硬核和應(yīng)用邏輯,硬核由軟件生成,應(yīng)用邏輯主要包括發(fā)送引擎、接收引擎和存儲器訪問模塊
RX_ENGINE: 用于解析IP核的數(shù)據(jù)包,負(fù)責(zé)DMA讀接收數(shù)據(jù)包
TX_ENGINE: 負(fù)責(zé)DMA寫發(fā)送數(shù)據(jù)包和中斷控制
BMD_EP_MEM_ACCESS: 存儲訪問模塊,包含DMA狀態(tài)及控制寄存器用以控制DMA讀寫,這里的寄存器是以PIO的方式寫入配置,在RC中設(shè)置的TLP長度、TLP數(shù)量信息等會寫入到這些寄存器中
BMD_GEN2、BMD_RD_THROTTLE、BMD_TO_CTRL、BMD_CFG_CTRL:BMD的一些相關(guān)的配置和控制信號的處理模塊
axi_trn_top:負(fù)責(zé)axi協(xié)議和trn協(xié)議的相互轉(zhuǎn)換
DMA寫流程:
一次DMA寫的過程是由FPGA的數(shù)據(jù)寫入RC端的存儲器中的過程,具體步驟為:
0>在RC端申請一塊物理地址連續(xù)的內(nèi)存,EP端準(zhǔn)備好寫數(shù)據(jù)后向RC端發(fā)送中斷
1>在RC端分析中斷,并向BAR0空間設(shè)置本次DMA寫的TLP大小、TLP數(shù)量、寫地址等,(通過PIO的方式,將帶有上述信息的TLP包發(fā)送給EP端,寫入FPGA的DMA控制狀態(tài)寄存器中),并且啟動DMA
2>根據(jù)DMA狀態(tài)控制寄存器的內(nèi)容,在收到DMA寫啟動命令后,TX引擎開始從FPGA中讀取數(shù)據(jù)并按第一步設(shè)置的DMA大小數(shù)量來組裝TLP包然后發(fā)送到PCIe核
3>FPGA發(fā)送完數(shù)據(jù)后通過中斷等形式通知主機DMA完成,主機讀取 BAR0 空間狀態(tài)寄存器判斷中斷類型做出相應(yīng)判斷,同時主機從內(nèi)存讀出數(shù)據(jù)
狀態(tài)機:
BMD_64_TX_RST_STATE:初始的復(fù)位狀態(tài),在該狀態(tài)判斷該進入發(fā)送完成包、存儲器寫和存儲器讀 的其中一個狀態(tài)
發(fā)送完成包:
BMD_64_TX_CPLD_QW1:發(fā)送完成包 — 返回存儲器地址和指定數(shù)據(jù)
BMD_64_TX_CPLD_WIT:發(fā)送完成包 — 等待完成
存儲器寫:
BMD_64_TX_MWR_QW1:DMA存儲器寫請求(32bit地址),發(fā)送3DW長度的頭+1DW數(shù)據(jù)
BMD_64_TX_MWR64_QW1:DMA存儲器寫請求(64bit地址),發(fā)送4DW長度的頭
BMD_64_TX_MWR_QWN:發(fā)送剩余的數(shù)據(jù)到RC端
存儲器讀:
BMD_64_TX_MRD_QW1:DMA存儲器讀請求(然后在RX引擎接收相應(yīng)數(shù)據(jù))
DMA讀流程:
一次DMA讀的過程是將RC端存儲空間的數(shù)據(jù)讀入到FPGA中的過程,具體步驟為:
0>在RC端申請一塊物理地址連續(xù)的內(nèi)存,并向該內(nèi)存寫入數(shù)據(jù),EP端準(zhǔn)備好讀數(shù)據(jù)后向RC端發(fā)送中斷
1>在RC端分析中斷,并向BAR0空間設(shè)置本次DMA讀的TLP大小、TLP數(shù)量、讀地址等,(通過PIO的方式,將帶有上述信息的TLP包發(fā)送給EP端,并寫入DMA控制狀態(tài)寄存器中),并啟動DMA
2>根據(jù)DMA狀態(tài)與控制寄存器的內(nèi)容,在收到DMA讀啟動命令后,在TX引擎中組裝存儲器讀TLP包后,發(fā)送給PCIe核,RC端根據(jù)收到的存儲器讀包,在指定的地址讀取數(shù)據(jù)后形成帶數(shù)據(jù)的完成包(CPLD)返回給FPGA,F(xiàn)PGA在RX引擎中接收數(shù)據(jù)
3>FPGA接收完數(shù)據(jù)后通過中斷形式通知主機DMA讀完成,主機讀取 BAR0 空間狀態(tài)寄存器判斷中斷類型做出相應(yīng)判斷
狀態(tài)機:
BMD_64_RX_RST:根據(jù)trn_rd[62:56]來判斷包的類型:
32位地址讀請求 (BMD_MEM_RD32_FMT_TYPE)
32位地址寫請求 (BMD_MEM_WR32_FMT_TYPE)
不帶數(shù)據(jù)的完成包 (BMD_CPL_FMT_TYPE)
帶數(shù)據(jù)的完成包 (BMD_CPLD_FMT_TYPE)
32位地址讀請求:
BMD_64_RX_MEM_RD32_QW1:解析RC端的讀TLP包 — 通知TX引擎發(fā)送完成包
BMD_64_RX_MEM_RD32_WT:解析RC端的讀TLP包 — 等待完成包發(fā)送完畢
32位地址寫請求
BMD_64_RX_MEM_WR32_QW1:解析RC端的寫TLP包 — 寫入寄存器
BMD_64_RX_MEM_WR32_WT:解析RC端的寫TLP包 — 等待寫寄存器完畢
不帶數(shù)據(jù)的完成包
BMD_64_RX_CPL_QW1:解析出完成包的tag,送至MEM模塊
帶數(shù)據(jù)的完成包
BMD_64_RX_CPLD_QW1:解析RC端的完成包 — 獲得數(shù)據(jù)
BMD_64_RX_CPLD_QWN:解析RC端的完成包 — 直至完成
axi-trn互轉(zhuǎn):
由于7系列的PCIe核的數(shù)據(jù)是通過AXI-S協(xié)議傳輸?shù)?,但是XAPP1052中的信號的相關(guān)處理是對trn_信號進行處理,所以會有一個協(xié)議轉(zhuǎn)換的模塊
以接收類信號為例,發(fā)送類信號類比:
trn_rsrc_rdy: 表示RC端(接收的源)準(zhǔn)備就緒
trn_rdst_rdy: 表示EP端(接收的目的)準(zhǔn)備就緒
trn_rsrc_dsc: 表示RC端(接收的源)將當(dāng)前包丟掉
trn_rsof: 接收幀開始標(biāo)志,(僅在trn_rsrc_rdy低時有效)
trn_reof: 接收幀結(jié)束標(biāo)志,(僅在trn_rsrc_rdy低時有效)
trn_rd: 接收到的數(shù)據(jù),(僅在trn_rsrc_rdy低時有效)
trn_rrem: 接收數(shù)據(jù)余數(shù),為0表示數(shù)據(jù)在trn_rd[63:0],為1表示數(shù)據(jù)在trn_rd[63:32](僅在trn_reof 、trn_rsrc_rdy、trn_rdst_rdy同時低時有效)
trn_rbar_hit[6:0]: 表示當(dāng)前包在哪個BAR空間,低有效(僅在trn_rsof、trn_reof低時有效)
trn_rbar_hit[0]——>BAR0
trn_rbar_hit[1]——>BAR1
trn_rbar_hit[2]——>BAR2
trn_rbar_hit[3]——>BAR3
trn_rbar_hit[4]——>BAR4
trn_rbar_hit[5]——>BAR5
trn_rbar_hit[6]——>Expansion ROM Addres
編輯:hfy
-
cpu
+關(guān)注
關(guān)注
68文章
10781瀏覽量
210517 -
PCIe
+關(guān)注
關(guān)注
15文章
1176瀏覽量
82267 -
狀態(tài)機
+關(guān)注
關(guān)注
2文章
490瀏覽量
27438 -
Zynq
+關(guān)注
關(guān)注
9文章
607瀏覽量
47084 -
數(shù)據(jù)總線
+關(guān)注
關(guān)注
2文章
56瀏覽量
17525
發(fā)布評論請先 登錄
相關(guān)推薦
評論