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