目前我們已經單獨使用 HLS 創建了IP(見上一節)。在本實踐中,我們將實際實現 HLS 組件作為 FPGA 設計的一部分。首先我們將學習如何做到這一點,然后我們將創建硬件來解決一些實際問題。
首先使用上一節的文件創建一個新的 HLS 項目:
重新綜合一下
每次我們更改硬件時,我們都需要告訴 HLS 將其導出為硬件描述語言并生成 Vivado 需要的所有各種源數據。
選擇Solution → Export RTL → 選擇 "Vivado IP for System Generator" → 單擊確定
接下來我們需要告訴 Vivado 我們的新 IP 在哪里
回到 Vivado,打開 Block Design。單擊Window -> IP Catalog以打開 IP 目錄。單擊左側 Flow Navigator 中的設置。選擇 IP,然后選擇存儲庫。按加號圖標。從文件瀏覽器中選擇 HLS 項目目錄,然后單擊選擇。Vivado 將掃描 HLS 項目,并彈出一個框,顯示 IP 已添加到項目中。單擊確定。
回到 Block Design,單擊圖表左側的 Add IP 按鈕。IP 核將被稱為之前創建IP時輸入的顯示名稱,或者 Toplevel 。雙擊 IP 進行添加。
要允許 IP 內核訪問 DDR 存儲器,需要在 Zynq 處理系統上啟用 AXI 從接口。雙擊 Zynq IP ,選擇“PS-PL Configuration”,展開“HP Slave AXI Interface”,勾選 S AXI HP0 interface. 單擊確定,應該會看到 Zynq 模塊上出現一個新端口。
現在可以使用連接自動化來完成連接。運行連接自動化并檢查 S_AXI_HP0. 應該建議連接到 m_axi IP 核上的端口。
同樣在連接自動化檢查 s_axi_AXILiteS和s_axi_control. 應該連接到M_AXI_GP0 處理系統上。單擊確定。
現在,IP將通過其從接口連接到processing_system7_0_AXI_periph,并通過其主接口連接到AXI_mem_intercon。
現在可以保存模塊設計、生成比特流并再次導出硬件。覆蓋現有的硬件規范(XSA 文件)。
連接自動化問題
如果對使用連接自動化生成的 AXI 總線有問題(即,如果它們與上述結構不同),請嘗試刪除所有AXI 互連模塊并再次運行它。
一般原則是, Zynq 模塊的 M_AXI 應該可追溯至 IP 內核上的所有 S_AXI,而 IP 內核的 M_AXI 應可追溯至 Zynq 模塊上的 S_AXI_HP0。
在 Vitis 中使用 IP
當 HLS 導出我們的 IP 時,它幫助我們自動生成了一個軟件驅動程序。但是我們需要告訴 Vitis 在哪里可以找到這個驅動程序。
在 Vitis 中,選擇 Xilinx → Repositories。在 Local Repositories 下,單擊 New 并選擇 HLS 項目的文件夾。單擊重新掃描存儲庫,然后單擊確定。
右鍵單擊design_1_wrapper 平臺并單擊“Update Hardware Specification”以更新我們已更改硬件的問題。
我們現在應該能夠看到新 IP 及其驅動程序。
在 Board Support Package 設置下的platform.spr 文件中,應該能夠看到列出的 IP,以及它使用驅動程序.
現在可以與IP進行交互了,如下例所示。
#include#include"platform.h" #include"xil_printf.h" #include"xparameters.h" #include"xtoplevel.h" #include"xil_cache.h" u32shared[1000]; intmain(){ inti; XToplevelhls; init_platform(); Xil_DCacheDisable(); print(" HLStest "); for(i=0;i100;?i++)?{ ????????shared[i]?=?i; ????} ????shared[0]?=?8000; ? ????XToplevel_Initialize(&hls,?XPAR_TOPLEVEL_0_DEVICE_ID); ????XToplevel_Set_ram(&hls,?(u32)?shared); ????XToplevel_Start(&hls); ????while(!XToplevel_IsDone(&hls)); ? ????printf("arg2?=?%lu arg3?=?%lu ",?XToplevel_Get_arg2(&hls),?XToplevel_Get_arg3(&hls)); ? ????cleanup_platform(); ????return?0; }
對 FPGA 進行編程并啟動此代碼,應該會看到以下內容:
HLStest arg2=12950 arg3=3050
如您所見,目前組件可以使用XToplevel_Start啟動,xtopleevel_IsDone會告訴你何時完成。XToplevel_Set_ram告訴HLS組件共享內存在主內存中的位置。允許HLS讀寫,就像RAM從0開始一樣,但實際上它將指向我們的共享內存。不要忘記設置RAM偏移量,否則HLS組件將寫入隨機內存位!
當更改 HLS 時
當更改 HLS 代碼時,請執行以下步驟以確保的最終文件已更新。
重新運行綜合。
重新導出 IP 核。
在 Vivado 中,應該已經識別到了變化,并且會出現一條消息說“IP Catalog is out-of-date”。
如果沒有,請單擊 IP Status,然后單擊重新運行報告
單擊刷新 IP 目錄
在“Generate Output Products”對話框中,單擊“Generate”。
單擊生成比特流。
導出硬件(包括比特流)。
在 Vitis 中重新編程 FPGA 并運行軟件。
如果更改了硬件接口,可能需要重新生成系統并將應用程序項目移入其中。
測量執行時間
下面將舉例使用 ARM 處理系統中的計時器來測量執行一段代碼需要多長時間,然后演示可以在硬件中更快地執行相同的操作。我們要測量的代碼實現了對Collatz(柯拉茲) 猜想的測試。該猜想指出:
柯拉茲猜想
取任何 正整數n(其中n不為0)。如果 n 是偶數,則除以 2 得到 n / 2。如果 n 是奇數,則將其乘以 3 并加 1 得到 3 n + 1。無限重復該過程。猜想是,無論你從哪個數字開始,你最終總會達到 1。
創建一個 HLS 組件來測試前 1000 個整數,以驗證如果執行上述步驟,它們最終都會收斂到 1。將在共享數組中輸出每個數字達到 1 所需的步數。
下面的代碼是使用的ARM軟件:
#include#include"platform.h" #include"xil_printf.h" #include"xparameters.h" #include"xtoplevel.h" #include"xil_cache.h" intshared[1000]; XToplevelhls; unsignedintcollatz(unsignedintn){ intcount=0; while(n!=1){ if(n%2==0){ n/=2; }else{ n=(3*n)+1; } count++; } returncount; } voidsoftware(){ inti; for(i=0;i1000;?i++)?{ ????????shared[i]?=?collatz(i?+?1); ????} } ? void?hardware()?{ ????//Start?the?hardware?IP?core ????XToplevel_Start(&hls); ????//Wait?until?it?is?done ????while(!XToplevel_IsDone(&hls)); } ? void?print_shared()?{ ????int?i; ????for(i?=?0;?i?1000;?i++)?{ ????????xil_printf("%d?",?shared[i]); ????} ????xil_printf(" "); } ? void?setup_shared()?{ ????int?i; ????for(i?=?0;?i?1000;?i++)?{ ????????shared[i]?=?i+1;?//(we?use?i+1?because?collatz?of?0?is?an?infinite?loop) ????} } ? int?main()?{ ????init_platform(); ????Xil_DCacheDisable(); ????//Initialise?the?HLS?driver ????XToplevel_Initialize(&hls,?XPAR_TOPLEVEL_0_DEVICE_ID); ????XToplevel_Set_ram(&hls,?(int)?shared); ????xil_printf(" Start "); ?? ????setup_shared(); ????software(); ????print_shared(); ? ????setup_shared(); ????hardware(); ????print_shared(); ? ????cleanup_platform(); ????return?0; }
檢查此代碼。該函數software()是前 1000 個整數的 Collatz 迭代階段的軟件實現,將迭代計數放在全局數組shared中。該main函數設置 shared為 1 到 1001 的整數,運行software(),然后將結果打印出來。然后它重置共享并運行hardware()并打印結果。
在 HLS 中實現一個硬件組件來計算前 1000 個整數的 Collatz 計數(就像 ARM 軟件一樣)。從以下頂級結構開始:
#include//Requiredformemcpy() uint32workingmem[1000]; uint32toplevel(uint32*ram,uint32*arg1,uint32*arg2,uint32*arg3,uint32*arg4){ #pragmaHLSINTERFACEm_axiport=ramoffset=slavebundle=MAXI #pragmaHLSINTERFACEs_axiliteport=arg1bundle=AXILiteS #pragmaHLSINTERFACEs_axiliteport=arg2bundle=AXILiteS #pragmaHLSINTERFACEs_axiliteport=arg3bundle=AXILiteS #pragmaHLSINTERFACEs_axiliteport=arg4bundle=AXILiteS #pragmaHLSINTERFACEs_axiliteport=returnbundle=AXILiteS //Readinstartingvalues memcpy(workingmem,ram,4000); //CalculatetheCollatzresults. //workingmem[x]=collatz(workingmem[x]); //...yourcodehere... //Burstcopyworkingmemtomainmemory memcpy(ram,workingmem,4000); return0; }
因為 Collatz 循環是無界的,所以 HLS 將只有問號而不是時間估計。
然后將 IP 核放入設計中并運行 IP 核以測試它是否輸出正確的答案。以上main.c應該可以驅動 IP 內核。
那么,硬件或軟件更快?
審核編輯:劉清
-
FPGA設計
+關注
關注
9文章
428瀏覽量
26628 -
Vivado
+關注
關注
19文章
815瀏覽量
66887 -
HLS
+關注
關注
1文章
130瀏覽量
24208
原文標題:在 Vivado 中使用 HLS 創建的IP
文章出處:【微信號:Open_FPGA,微信公眾號:OpenFPGA】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論