<meter id="pryje"><nav id="pryje"><delect id="pryje"></delect></nav></meter>
          <label id="pryje"></label>

          新聞中心

          EEPW首頁 > 嵌入式系統(tǒng) > 設計應用 > FPGA:PCI Express接口

          FPGA:PCI Express接口

          作者: 時間:2024-01-10 來源:EEPW編譯 收藏

          隨著 PCI Express 在高端 中變得司空見慣,讓我們看看 供應商如何輕松實現(xiàn)該技術。特別是,我們更仔細地研究了的 PCI Express 解決方案。

          本文引用地址:http://www.ex-cimer.com/article/202401/454643.htm

          PCI Express 1 - 連接器

          PCI Express 通常有兩種尺寸:1 通道和 16 通道,其中 1 通道用于普通主板,16 通道用于顯卡。

          連接器

          1 通道連接器有 36 個觸點,排列成兩排,每排 18 個觸點。
          這是俯視圖。

          在 36 個觸點中,只有 6 個對數(shù)據(jù)傳輸有用,其余是電源引腳和其他輔助信號。 6 個功能觸點以 3 對使用:

          • 名為 REFCLK 的時鐘對。

          • 名為 PER 的接收對。

          • 稱為 PET 的傳輸對。

          這些信號對通常被稱為“差分對”,因為來自一對的每個信號都攜帶相同的信號,但一個信號與另一個信號相反。 使用差分對的原因主要是傳輸?shù)目煽啃?,稍后將更詳細地討論?/span>

          在 PCI Express 第 1 代(或簡稱為“Gen1”)中,PET 和 PER 對的數(shù)據(jù)傳輸速度為 2.5Gbps。 Gen2 將這一數(shù)字翻了一番。

          查看 Dragon-E 板,我們可以識別出 下方的 PET 對。

          為了正常工作,差分對中的線路需要電耦合并且沒有阻抗不連續(xù)性,這在實踐中意味著“保持緊密”和“沒有銳角”。 這就是 Dragon-E 的 PET 對蛇形形狀的原因。 板的另一側顯示了另外兩對蛇形對 REFCLK 和 PER。

          PCI Express x16 插槽

          為了提高速度,可以使用多條車道。 不需要復制 REFCLK 對,例如,具有 2 個通道的 PCI Express 使用 5 個對(1 個 REFCLK + 2 個 PET + 2 個 PER)。

          圖形板通常使用 16 通道連接器,通常稱為 PCI Express x16。

          PCI Express 2 - 拓撲

          點對點架構

          在 2.5Gsps 時,PCI Express Gen1 線路速度比 75MHz 傳統(tǒng) PCI 速度快 33 倍。
          這怎么可能?只是因為 PCI express 是點對點總線。

          還記得PCI是共享總線嗎?

          使用PCI時,必須指定足夠的時間,讓信號在每個時鐘周期內穩(wěn)定下來。 這是因為PCI總線的每條線路都在同一總線上的PCI連接器和板上共享。 使用PCI Express,每個信號都是點對點的,這意味著不再有建立時間,線路速度可以更高。

          例如,如果主板有兩個 1 通道連接器和一個 16 通道連接器,則需要橋接器上有 6+6+34=46 個引腳,僅用于 REFCLK、PER 和 PET(因為不允許共享)。

          時鐘恢復

          在2.5GHz開始的速度下,點對點架構仍然是一個挑戰(zhàn),因為每個位的持續(xù)時間非常短,以至于時序抖動(圍繞每個位到達的時間不確定性)成為一個問題。 即使每個信號對都有相關的時鐘對同時傳輸,時鐘對也會受到定時抖動的影響。 因此,使用了一種稱為“時鐘恢復”的新技術。

          時鐘恢復很簡單。 基本上,對于每個信號對,接收器對都會查看信號轉換(位 0 后跟位 1,反之亦然),從中可以推斷出周圍位的位置。 一個問題是,如果許多連續(xù)的位以相同的值傳輸(如許多0),則看不到信號轉換。 因此,傳輸額外的位以確保信號轉換不會相距太遠(這會“重新同步”時鐘恢復機制)。

          額外的比特使用一種稱為 8b/10b 編碼的方案發(fā)送,因此對于每 8 位有用數(shù)據(jù),實際上有 10 位以特定方式傳輸(開銷為 20%),以保證足夠的信號轉換。 但這也意味著,在2.5GHz時,我們每對只能獲得250MBps的有用帶寬(而不是沒有編碼開銷的312MBps)。

          差分對

          現(xiàn)在還記得信號是在差分對上發(fā)送的事實嗎? 這有很多優(yōu)點:

          • 它更不受外部干擾。

          • 它能夠在低電壓下工作(=更低的功耗)。

          • ...最后但并非最不重要的一點是:這有助于時鐘恢復獲得精確的信號轉換。

          差分對有一個明顯的缺點:傳輸信號需要兩倍的導線。

          PCI Express 3 - 數(shù)據(jù)包、堆棧和網(wǎng)絡的故事

          分組事務

          PCI express 是串行總線。 或者是嗎? 從計算機的角度來看,它是一種可以實現(xiàn)讀寫事務的傳統(tǒng)總線。

          訣竅是所有操作都已打包。 假設 CPU 想要將一些數(shù)據(jù)寫入設備。 它將訂單轉發(fā)到 PCI Express 網(wǎng)橋,然后 PCI Express 網(wǎng)橋創(chuàng)建一個數(shù)據(jù)包。 數(shù)據(jù)包包含要寫入的地址和數(shù)據(jù),并串行轉發(fā)到目標設備,目標設備將寫入順序解包并執(zhí)行。

          如果 CPU 想要讀取怎么辦? 同樣,網(wǎng)橋將數(shù)據(jù)包轉發(fā)到目標設備,目標設備現(xiàn)在必須執(zhí)行讀取,創(chuàng)建返回數(shù)據(jù)包并將其發(fā)送到網(wǎng)橋。
          所有這一切都在實踐中非常容易做到,感謝來自...

          PCI Express 協(xié)議棧

          讓數(shù)據(jù)包沿著線路可靠地流動需要一些魔力。 由于數(shù)據(jù)包以非常高的速度串行傳輸,因此必須對它們進行反序列化/匯編、在目的地解碼(刪除 8b/10b 編碼)、去交錯(如果使用多個通道)并檢查線路損壞(CRC 檢查)。

          聽起來很復雜? 大概是這樣。 問題是,我們并不真正關心,因為大部分復雜性都是在由三層組成的“PCI Express堆棧”中處理的。

          1. 物理層。

          2. 數(shù)據(jù)鏈路層。

          3. 事務層。

          前兩層是在PCI Express FPGA內核(通常是硬核和軟核的組合)中為我們實現(xiàn)的,用于處理所有復雜性。 作為用戶,我們只在交易層工作,那里的生活很輕松,天空很藍,女孩很漂亮。

          更多細節(jié):

          1. 物理層:這是引腳切換的地方。8b/10b 編碼/解碼和通道拆卸/重組都在那里完成。

          2. 數(shù)據(jù)鏈路層:檢查數(shù)據(jù)完整性 (CRC) 并在需要時重新傳輸數(shù)據(jù)包(希望這種情況很少發(fā)生)。

          3. 交易層:即用戶級別。一旦數(shù)據(jù)包到達這里,它就可以保證是好數(shù)據(jù)。

          好數(shù)據(jù)?太好了,這就是我們想要的!

          讓我們看看在事務層中工作是什么樣的。

          PCI Express 4 - 事務層

          在交易層,我們接收“數(shù)據(jù)包”。 有一個 32 位總線,數(shù)據(jù)包到達總線(數(shù)據(jù)包長度始終是 32 位的倍數(shù))。 也許一個數(shù)據(jù)包會說“在地址0xABCD寫入數(shù)據(jù)1234x0”,另一個數(shù)據(jù)包會說“從地址0xDCBA讀?。ú⒎祷仨憫獢?shù)據(jù)包)”。

          數(shù)據(jù)包有很多種類型:內存讀取、內存寫入、I/O 讀取、I/O 寫入、消息、完成等...... 我們在事務層的工作是接受數(shù)據(jù)包和發(fā)出數(shù)據(jù)包。 數(shù)據(jù)包以稱為“事務層數(shù)據(jù)包”(TLP)的特定格式呈現(xiàn)給我們,到達總線的每個 32 位數(shù)據(jù)稱為“雙字”(或簡稱 DW)。

          所以一個數(shù)據(jù)包(哎呀,對不起,一個 TLP)是一堆 DW。

          TLP 的外觀

          TLP 的解釋非常簡單。 以下是其結構的一般視圖。

          標頭包含 3 或 4 個 DW,但最重要的字段是第一個 DW 的一部分。

          “Fmt”字段表示標頭的長度,以及是否存在數(shù)據(jù)有效負載。

          然后與“類型”一起描述TLP操作。 TLP 標頭內容的其余部分取決于 TLP 操作。

          例如,下面是一個 32 位內存寫入 TLP 標頭,您可以在其中看到寫入地址位于標頭的末尾(并且要寫入的數(shù)據(jù)位于標頭之后的有效負載中)。

          “Fmt”字段為“10”,表示“3 DW,有數(shù)據(jù)”。 這是有道理的,內存寫入需要寫入數(shù)據(jù),因此在標頭之后獲得數(shù)據(jù)有效負載后,我們將該數(shù)據(jù)寫入某個內存(或以某種方式使用它),然后我們就完成了它。 字段“長度”表示有效負載中有多少 DW(從 0 到 1023)。 通常,要寫入的是單個 DW,在這種情況下,長度等于 1,總 TLP 長度為 4 DW(標頭為 3,有效負載為 1)。

          現(xiàn)在內存讀取呢?不知何故,我們必須返回數(shù)據(jù)。

          用數(shù)據(jù)完成

          如果 TLP 是內存讀取而不是寫入,我們必須執(zhí)行讀取,然后做出響應。 該響應有一個特殊的 TLP,它稱為 CplD(數(shù)據(jù)完成),其有效負載包含我們要返回的數(shù)據(jù)。

          讓我們仔細看看 32 位內存讀取 TLP 標頭 - 它與我們之前的 32 位內存寫入非常相似。

          一個區(qū)別是 Fmt=00,這意味著“沒有數(shù)據(jù)”。 有道理,我們不需要數(shù)據(jù)來讀取,只需要一個地址。 但我們現(xiàn)在必須用數(shù)據(jù)來回應。 同樣重要的是,響應需要路由回請求讀取的人...... 你看到問題了嗎?

          好的,我們收到了一個讀取請求。 它來自CPU嗎? 還是來自中斷控制器? 還是從顯卡? 畢竟,許多設備都能夠發(fā)出這樣的請求。 答案在“請求者 ID”中給出 - 它顯示誰請求讀取。 因此,當我們創(chuàng)建 CplD TLP 時,我們必須重新復制其中的“請求者 ID”。 這樣,它將通過PCI Express網(wǎng)橋路由到它所屬的位置。 順便說一句,我們還必須重新復制“標簽”(這在多次讀取待處理的情況下很有用)。

          TLP 大小

          典型的 32 位地址/數(shù)據(jù)存儲器讀取 TLP 由報頭中的 3 個 DW 組成,沒有有效載荷(因此總共 96 位),而類似的內存寫入由 4 個 DW(3 個用于報頭,1 個用于有效負載)組成。 由于 TLP 標頭開銷,這在帶寬方面效率不高,因此最好盡可能使用更大的 TLP 有效負載。 TLP 有效負載理論上可以達到 1023 DW,這對于突發(fā)讀取和寫入非常方便,盡管 PC 可以將最大大小限制為較低的值(通常為 32 DW)。

          有關更多信息,請通過谷歌搜索 PCI Express 規(guī)范來查看官方 PCI Express 規(guī)范,例如PCI_Express_Base_11.pdf

          理論已經夠多了,讓我們玩得開心,玩玩 Xilinx PCI Express 向導。

          PCI Express 5 - Xilinx 向導

          Xilinx 使 PCI express 的使用變得簡單 - 它們提供了一個免費的 PCI Express 內核(稱為“Endpoint Block Plus”)和一個用于配置它的向導。 所有這些都在他們的免費版 ISE - ISE WebPack 中。

          因此,讓我們啟動Xilinx CORE生成器,選擇Endpoint Block Plus。

          內核處于非活動狀態(tài),我們需要使用 File --> New Project 創(chuàng)建一個項目并選擇一個 FPGA(這里我們使用的是 Dragon-E,所以我們選擇 Virtex-5)...

          ...,然后選擇您喜歡的語言(在“生成”選項卡中)。

          現(xiàn)在,Endpoint Block Plus內核變?yōu)榛顒訝顟B(tài),您可以雙擊它以啟動向導。
          在第一頁上,為組件命名。在這里,我們選擇了“my_endpoint_blk_plus”。 剩下的對 Dragon-E 來說沒問題,所以點擊“下一步>”。

          現(xiàn)在,您可以更改供應商/設備 ID...

          ...和地址空間。

          接下來的頁面沒有太多興趣,所以點擊“生成”來生成核心及其文檔。

          現(xiàn)在,我們已準備好創(chuàng)建第一個PCI Express FPGA位文件,在FPGA中對其進行編程,并生成真正的PCI Express流量。

          PCI Express 6 - 簡單事務

          讓我們嘗試從 PCI Express 總線控制 LED。

          Xilinx 的“Endpoint Block Plus”內核允許我們在事務層級別工作,因此只需幾行代碼即可。
          “Endpoint Block Plus”不是在32位總線上提供數(shù)據(jù),而是使用64位總線(因此我們在每個時鐘周期獲得的數(shù)據(jù)量是原來的兩倍)。 這不是問題,一個簡單的狀態(tài)機將處理簡單的內存讀取和寫入。

          // we use signals from Xilinx's "Endpoint Block Plus"
          // first we declare that we are always ready to get data
          assign trn_rdst_rdy_n = 1'b0;

          // then we create a state machine that triggers when we get a PCI Express memory read or write
          reg RXstate;
          reg [63:0] RXrd;always @(posedge clk)case(RXstate)
             // we are going to handle simple memory reads & writes
             // we know that with the "Endpoint Block Plus" core, such simple transactions always happens
             //  using two cycles so we just need a two-states state machine
             // first, we wait for the beginning of a memory transaction with up to 32-bit data (i.e. with length=1)
             1'b0: if(~trn_rsrc_rdy_n && ~trn_rsof_n && trn_rd[61:56]==6'b0_00000 && trn_rd[41:32]==10'h001)    begin
              RXstate <= 1'b1;
              RXrd <= trn_rd;    
           end
             // then the second state waits for the end of the transaction
             1'b1: if(~trn_rsrc_rdy_n) RXstate <= 1'b0;
          endcase

          現(xiàn)在我們準備更新 LED。

          wire [31:0] RXaddr = trn_rd[63:32];   
          // memory address (read or write) (valid during the second state of the state machine)

          wire [31:0] RXdata = trn_rd[31:0];  
          // memory data (for a write) (valid during the second state of the state machine)

          wire RXrdwr = RXrd[62];  
          // 0 for a read, 1 for a write

          wire RXRead = ~trn_rsrc_rdy_n & RXstate & ~RXrdwr;
          // true when a read is happeningwire RX

          write = ~trn_rsrc_rdy_n & RXstate & RXrdwr;
          // true when a write is happening

          // update two LEDs using the two LSBs from the data written
          reg [1:0] LEDs;
          always @(posedge clk) if(RXwrite) LEDs <= RXdata[1:0];

          對于內存寫入,僅此而已。 對于內存讀取,您需要使用要返回的數(shù)據(jù)創(chuàng)建響應數(shù)據(jù)包。 生成中斷也非常容易 - 只需斷言一個名為“cfg_interrupt_n”的信號即可。

          想要更多?請查看 Dragon-E 的啟動套件以獲取更完整的示例,并查看 Xilinx 的 UG341 Endpoint Block Plus 規(guī)范文檔,了解所有信號的描述。

          享受PCI Express的樂趣!



          評論


          相關推薦

          技術專區(qū)

          關閉
          看屁屁www成人影院,亚洲人妻成人图片,亚洲精品成人午夜在线,日韩在线 欧美成人 (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })();