該項目介紹了如何在 PL 中的 HDL 與 FPGA 中的處理器上運行的嵌入式 C 之間傳輸數據的基本結構。
介紹
鑒于機器學習和人工智能等應用的 FPGA 設計中硬件加速的興起,現在是剝開幾層“云霧”并討論 HDL 之間來回傳遞數據(主要指FPGA 的可編程邏輯 (PL) 中運行的代碼以及 FPGA 中的硬核或軟核處理器上運行的相應軟件之間傳輸數據)的基礎知識的好時機。
硬件加速可以總結為在硬件(也稱為 FPGA 的可編程邏輯)中實現某些功能的基本思想,這些功能之前在位于主機 PC 上或在 FPGA 上處理器(軟核或者硬核)運行的軟件。因此,要成為一名高效的設計人員,就必須掌握如何在硬件和軟件之間來回傳遞數據的技巧。
在本例中,使用的是 Zynq SoC(片上系統)FPGA,它具有硬核 ARM 處理器。該 ARM 核心和外設稱為處理系統或 PS。
雖然有幾種不同的方法可以完成 PL 和 PS 之間的數據傳輸,包括編寫自己的自定義接口,但我認為最常見的機制是通過直接內存訪問 (DMA) 傳輸。這是因為 DMA 允許 ARM 內核的 CPU 簡單地啟動自身與 DDR 之間的數據傳輸,而 CPU 無需等待傳輸完成后再執行任何其他任務。DMA 還允許 CPU 啟動外部設備和 DDR 之間的傳輸。
在此項目中,將通過使用 Xilinx DMA IP 演示 DMA 的功能,該IP可通過 AXIS 總線將內存映射接口轉換為stream接口。將 32 字節寫入嵌入式 C 中的內存,然后通過內存映射將其傳輸到 PL 到流 (MM2S) AXIS,通過寄存器處理每個值,然后通過流將數據傳輸回內存DMA IP 的內存映射 (S2MM) 端口。
雖然這個示例對于重型硬件加速應用來說過于簡單,但當剛接觸 FPGA 時,這種高速數據傳輸水平可能會變得非常復雜/難以學習。該項目重點介紹 DMA 的使用及其行為。雖然打算讓這個項目更多地關注數據處理方面,但在 DMA 事務實現中發現了很多小“陷阱”,因此不得不將數據處理重點留給另一個項目。
使用 AXI DMA 控制 PL 中的 HDL 與 PS 中的 C 代碼之間的數據傳輸有兩個主要層:
Memory Map to Stream (MM2S) 和 Stream to Memory Map (S2MM) 通道上 PL 的 HDL 代碼中的 AXI 流握手信號(DMA 的控制通道是使用普通 AXI 寫入的,但這就是全部由 Vivado 自動處理,因此在這里只關注 AXI stream接口)。
PS 的 C 代碼中寄存器讀/寫 DMA 的順序。
Verilog 中的 AXI-Stream握手
AXI stream接口使用一組簡單的握手信號機制,用于嵌入式設計中的數據交換。AXI stream接口中有許多可選信號,但與 DMA MM2S 和 S2MM 數據交換相關且必需的信號是 tdata、tvalid、tready、tlast 和 tkeep。AXI stream中發送數據為主接口,接收數據為從接口。
tdata:數據總線
tvalid:當放置在 tdata 總線上的數據有效時,由主接口置位
tredy:當從機處于準備接收 tdata 總線上的數據的狀態時,由從機置位
tlast:由主設備在 tdata 總線上流中最后一個數據包的持續時間內斷言,以告訴從設備該數據包之后不會有數據
tkeep:由主設備設置的 tdata 總線上數據包的二次驗證,指示數據包是否是流的一部分
AXI DMA IP 究竟如何實現此握手接口將數據傳輸出內存 (MM2S) 并傳輸到內存 (S2MM),這一點非常變化無常,尤其是在 S2MM 方面……
然而,我們首先需要了解的是有關 AXI DMA 的 S2MM 事務的信息,大部分可以總結為一句話:必須設置 S2MM 事務,并且在嘗試向 DMA 發送任何數據之前,以適當的順序寫入 DMA 中的適當控制寄存器來啟動事務,一旦 S2MM 通道看到 tlast 信號,它就會停止事務。
數據傳輸發生在每個時鐘周期的 S2MM 和 MM2S 事務中的 tdata 總線上,其中tready 和 tvalid 均被置位(true)。因此,當負責斷言 tvalid 時,在 AXI 接口的主端必須小心,當從從機傳入的 trety 信號也為 tvalid 斷言時,不要讓 tvalid 斷言超過一個時鐘周期。否則,從設備將在同一個數據包計時兩次,作為兩個單獨的數據包。并且因為必須在控制寄存器中指定傳輸中有多少字節,所以 DMA 通道(在本例中為 S2MM)會在看到提供 tlast 信號之前認為交換已結束,因為計數已關閉。
我用 Verilog 編寫了一個簡單的狀態機,它實現了一個從 AXI stream接口來從 DMA 的 MM2S 通道接收數據,通過寄存器傳遞stream中的每個數據包,然后實現一個主 AXI strean接口來將數據流發回到S2MM通道。來自 tdata 總線的數據通過的寄存器旨在充當占位符,用于為硬件加速進行任何自定義數據處理。
從 Vivado 中的 ILA 中截取了一張屏幕截圖,顯示使用狀態機實現的時序圖。頂部是 MM2S 側,底部是 S2MM 側。
這是 Verilog 狀態機的流程圖,實際文件附在本文末尾。值得注意的是,流程圖中的主/從接口是從 Verilog 狀態機的角度來看的。
對于 DMA IP 的具體設置,因為在直接寄存器模式下使用 DMA,所以未選中分散收集選項。然后,將其他所有設置保留為默認設置,并選中允許未對齊傳輸的選項,我發現在將自定義 AXI 流接口寫入 DMA 時,這給了更多的自由空間。
為了將 Verilog 狀態機添加到模塊設計中,我右鍵單擊模塊設計的空白區域,然后選擇“添加模塊...”選項,該選項將顯示 Vivado 可以在設計源中找到的所有有效 Verilog 模塊在BD中使用的文件。
值得注意的是,信號命名約定分別遵循從接口和主接口的“s_axis”和“m_axis”標準。
DMA 寄存器讀/寫控制序列
以下是裸機使用 DMA 時更簡單的順序:
1.通過將 1 寫入 MM2S(偏移量 0x00)和 S2MM(偏移量 0x30)控制寄存器的位 2 來復位 DMA。
2.將 S2MM 通道要寫入數據的 DDR 中位置的目標地址寫入 S2MM DMA 目標地址寄存器(偏移量 0x48)。
3.通過將 1 寫入 S2MM 控制寄存器(偏移量 0x30)的位 0 來啟動 DMA S2MM 通道。
4.通過將 S2MM 通道上要讀入內存的總字節數值寫入 S2MM 緩沖區長度寄存器(偏移量 0x58),寫入 S2MM 通道緩沖區的長度。這將啟動 S2MM 傳輸,以便 DMA 準備好從 FPGA 邏輯中的設備接收數據流(直到實際饋送數據并且 AXI 流總線上的 tvalid 由 FPGA 邏輯中的設備斷言后,該過程才會真正啟動)邏輯)。
5.將 MM2S 通道要讀取的數據的 DDR 中的源地址寫入 MM2S DMA 源地址寄存器(偏移量 0x18)。
6.通過將 1 寫入 MM2S 控制寄存器的位 0(偏移量 0x00)來啟動 DMA MM2S 通道。
7.通過將要發送的總字節數值寫入 MM2S 傳輸長度寄存器(偏移量 0x28),寫入 MM2S 通道的傳輸長度。這將啟動從 DMA 到 FPGA 邏輯中的接收設備的 MM2S 傳輸。
還記得之前提到過,在 PL 中的設備嘗試向 S2MM 通道發送數據之前,必須啟動并運行 S2MM 通道嗎?嗯,這就是為什么要按順序執行上述步驟。步驟 2 - 4 配置并啟動 S2MM 通道,步驟 5 - 7 配置并啟動 MM2S 通道。
在步驟 4 和 5 之間發生一些其他進程是可以的,但步驟 2 - 4 必須在步驟 5 - 7 之前發生。執行步驟 4 后,S2MM AXI 流通道將斷言其 Tready 信號,此時 HDL 代碼可以開始向其發送數據。
這也解釋了當我第一次開始使用 DMA 時,在 SDK/Vitis 中的示例 DMA 項目中注意到的一些事情。總是認為示例代碼似乎是在使用 MM2S - XAXIDMA_DMA_TO_DEVICE 傳輸從 DDR 中寫入任何內容之前嘗試將數據拉入 DDR(通過首先執行 S2MM - XAXIDMA_DEVICE_TO_DMA 傳輸)。然而,S2MM 通道必須準備好并等待接收數據才能正常工作并且不會鎖定。
在 FPGA 設計中,DMA 似乎是一種棘手的入門方法,但一旦你弄清楚它就會非常有幫助。
審核編輯:劉清
-
FPGA
+關注
關注
1629文章
21744瀏覽量
603598 -
嵌入式
+關注
關注
5083文章
19131瀏覽量
305465 -
HDL
+關注
關注
8文章
327瀏覽量
47395 -
片上系統
+關注
關注
0文章
186瀏覽量
26819 -
dma
+關注
關注
3文章
561瀏覽量
100603
原文標題:使用 DMA 在 FPGA 中的 HDL 和嵌入式 C 之間傳輸數據
文章出處:【微信號:Open_FPGA,微信公眾號:OpenFPGA】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論