1.概述
本文是用於總結PCIE ip例程的學習成果。主要是從ip的設置,ip核的例程代碼構成及其來源兩方面介紹pcie的使用情況。
2.參考文檔
《pg054-7series-pcie》
《PCI_Express_Base_Specification_Revision_3.0》
3. pcie ip設置
3.1 本例程使用環境
編譯環境:vivado 2017.4
選用FPGA:xc7k325t-2ffg900i
3.2 IP界面設置情況
本例程主要是使用Basic模式,下面是IP設置情況。
3.2.1 IP第1頁設置情況
- Devie port type:即設備的類型,一般用FPGA這邊做的PCIE板卡都是endpoint device;
- Lane width:即常說的x幾的幾,對應接口連接就是高速GTX的對數;
- Link speed:即lane rate,這個速度與使用pcie版本相關,最大值有限制;
- AXI Frequency:不用自己設置,其值是根據link speed自動變化設置的;
- AXI interface width:即傳輸數據的位寬,此位寬受限於link speed,2.5G時只能選擇64bit;
- Reference clock frequency:即GTX上的參考時鐘;
3.2.2 IP第2頁設置情況
- ID initial values:是一個PCIE卡的識別碼,只有一張板子時可以不修改;
- Class code:種類等級碼,根據使用修改base class menu即可,其他可以不修改;
3.2.3 IP第3頁設置情況
這一頁主要是BAR的設置,即辦卡內存的大小設置,數量設置,與使用位數設置;
這裏選擇64bit,則程序中選擇使用的爲4DW頭,若沒勾選則使用的是3DW頭;
3.2.4 IP第4頁設置情況
這一頁主要是PCIE device的buff能力的設置與設備類型的總結;基本上可以不做改變;
3.2.5 IP第5頁設置情況
這一頁主要是中斷的選擇,常用的是下面的MSI中斷;
4. IP例程代碼情況
這裏例程的代碼結構是PIO形式的,所謂PIO就是Programmed Input/Output,更通俗的解釋就是從機模式,無論是讀寫都是需要CPU發送信號過來,FPGA這邊根據接收到的命令進行讀或者寫。
此外本例程是每次只發送一個數據長度的數據,即一個包只發送32bit的數據。
這裏用3DW頭,64bit數據位寬作爲講解。4DW頭、128bit數據位寬的類容基本類似,類推即可。
4.1 代碼結構
由上圖可以知道PCIE的例程是由兩部分組成,一個是support模塊,一個是app部分。主要結構如下圖所示:
Support模塊主要是由PCIE的ip與時鐘兩部分組成,這一部分是不用修改的,直接沿用即可,所以這裏不做過多介紹。
APP模塊主要是由3部分組成:
- PIO_RX:用於接收CPU發送過來的命令與數據;
- PIO_TX:用於向CPU發送數據;
- EP_MEM:內存情況,即IP設置中BAR的對應區域,也是緩存數據的區域;
4.2 PIO_RX模塊介紹
在實際運用過程中PIO_RX模塊是很可能改變的一個模塊,我們並不是要把接收到的數據存儲在mem中,也可能將其發送到其他地方,比如說通過DAC發給其他設備,因此這裏作爲一個重點講解。
4.2.1 PIO_RX接口部分說明
4.2.2 PIO_RX代碼內容說明
RX裏的代碼主要是分兩部分編寫,首先識別是哪一種包,然後根據包的類型接收數據。
其代碼流程如下圖所示:
其包頭類型識別狀態機說明如下圖所示:
接收包的數據格式如下圖所示:
需要注意的是這個“endpoint integrated block byte order”中的包格式只是32位的格式,即這個頭是3DW的頭。若是64位的格式(4DW)則途中的data[31:0]換成address[63:32],數據放到下一個時鐘去(這也是PIO_RX_MEM_WR64_DW3狀態的來源)。
其包頭類型的劃分依據如下所示:
4.3 PIO_TX模塊介紹
PIO_TX模塊也是實際使用中很可能改變的模塊,因爲在實際使用中不一定只是上傳內存中的數據,還可能是上傳其他地方過來的數據,比如上傳ADC採集到的數據。
4.3.1 PIO_TX接口部分說明
4.3.2 PIO_TX代碼內容說明
TX部分代碼得到了整合,無論是回傳帶數據的格式包還是不帶數據的包格式都相同,因爲可以用用有效位區分開。
其代碼流程如下圖所示:
其回傳數據的包頭依據如下圖所示:
回傳數據的幀頭部分代碼如下圖所示:
其回傳的數據包部分如下所示:
下面我們來說說代碼中的信號來源:
代碼中的req_tc,req_td,req_ep,req_attr,req_len,req_rid,req_tag都比較清楚,它們是來自RX模塊從CPU那邊接收過來的數據。
rd_data:是我們要回傳的數據。
completer_id:是來至於cfg_completer_id = { cfg_bus_number, cfg_device_number, cfg_function_number };即ip的cfg_status輸出的狀態;
byte_count:是根據length與byte enables計算的。其計算的依據是:
其計算的代碼爲:
lower_addr:是來至於接收到的請求地址的5位+(1st DW BE)計算出來的值。
其計算依據爲:
其代碼組成爲:
5. 代碼注意事項
需要注意的是:
2017.4版本vivado基於K7的FPGA 產生的IP其數據(s_axis_tx_tdata,m_axis_rx_tdata)中的高32位低32位與《PCI_Express_Base_Specification _Revision_3.0》中的包格式相反;