學會System Generator(13)Vivado HLS呼叫C/C++程式碼
本文是該系列的第13篇。Vivado HLS是Xilinx FPGA開發套件中的一款軟體,可以使用C/C++語言進行設計,並轉換為RTL級模型。System Generator中的Vivado HLS block可以將HLS開發軟體設計的C/C++程式碼整合到Simulink環境中,利用Simulink強大的模擬特性對設計進行模擬測試。
ug948中提供的官方例程為影象的中值濾波,該設計將一副256*256大小的RGB影象,新增噪聲後提取出其中的Y通道,使用C++語言完成中值濾波。該設計將在Simulink環境下進行模擬。本文將完成改該設計,藉此介紹上述功能。
Vivado HLS完成中值濾波設計
中值濾波是一種常見的影象濾波方法,選取一個核(本設計為3*3)在影象上滑動,取核的中間值作為核中心畫素點的值。中值濾波在濾除椒鹽噪聲的同時模糊效應會明顯低於線性平滑濾波。Xilinx提供的C++設計原始檔程式碼清單如下:
#include "MedianFilter.h"
#define WINDOW_SIZE 3
typedef unsigned char PixelType;
#define PIX_SWAP(a,b) { PixelType temp=(a);(a)=(b);(b)=temp; }
#define PIX_SORT(a,b) { if ((a)>(b)) PIX_SWAP((a),(b)); }
PixelType OptMedian9(PixelType * p)
{
PIX_SORT(p[1], p[2]) ; PIX_SORT(p[4], p[5]) ; PIX_SORT(p[7], p[8]) ;
PIX_SORT(p[0], p[1]) ; PIX_SORT(p[3], p[4]) ; PIX_SORT(p[6], p[7]) ;
PIX_SORT(p[1], p[2]) ; PIX_SORT(p[4], p[5]) ; PIX_SORT(p[7], p[8]) ;
PIX_SORT(p[0], p[3]) ; PIX_SORT(p[5], p[8 ]) ; PIX_SORT(p[4], p[7]) ;
PIX_SORT(p[3], p[6]) ; PIX_SORT(p[1], p[4]) ; PIX_SORT(p[2], p[5]) ;
PIX_SORT(p[4], p[7]) ; PIX_SORT(p[4], p[2]) ; PIX_SORT(p[6], p[4]) ;
PIX_SORT(p[4], p[2]) ;
return(p[4]) ;
}
PixelType Mean(PixelType* buffer)
{
PixelType i, j, min;
unsigned int sum;
for (i = 0;i<9; i++) {
sum+=buffer[i];
}
sum/=(WINDOW_SIZE*WINDOW_SIZE);
return sum;
}
PixelType Min(PixelType* buffer)
{
PixelType i, j, min;
min = buffer[0];
for (i = 1;i<9; i++) {
if (min>buffer[i]) min = buffer[i];
}
return min;
}
void MedianFilter(PixelType row1, PixelType row2, PixelType row3, PixelType* V)
{
#pragma AP PIPELINE II=1
/*
* Create a local Pixel Buffer based on WindowSize
*/
static PixelType pixelWindowBuffer[WINDOW_SIZE*WINDOW_SIZE];
PixelType sortBuffer[WINDOW_SIZE*WINDOW_SIZE];
/*
* Each Iteration Interval Update the Pixel Buffers
*/
for(int i = 0;i<WINDOW_SIZE;++i) {
for(int j=0;j<(WINDOW_SIZE-1);++j) {
pixelWindowBuffer[WINDOW_SIZE*i + (WINDOW_SIZE-j-1)] = pixelWindowBuffer[WINDOW_SIZE*i + (WINDOW_SIZE-j-1)-1];
}
}
/*
* Update the first Pixel of each row
*/
pixelWindowBuffer[0] = row1;
pixelWindowBuffer[3] = row2;
pixelWindowBuffer[6] = row3;
for(int k = 0;k<9;++k) {
sortBuffer[k] = pixelWindowBuffer[k];
}
*V = OptMedian9(sortBuffer);
};
可以自己建立HLS工程,如對HLS的使用不熟悉也可以在Xilinx官網搜尋“ug948-design-files.zip”下載,其中有示例工程。
右鍵Solution->C Synthesis->Active Solution,綜合設計原始檔。完成後,再右鍵Solution->Export RTL,Format Selection選擇為“System Generator for DSP”,點選OK將設計原始檔打包為System Generator可以使用的形式。
將HLS設計匯入System Generator
新增一個Vivado HLS block,雙擊開啟該block:
點選Browse,將路徑指定到HLS工程的Solution資料夾下。如果路徑選擇錯誤,或者HLS工程綜合或匯出失敗導致solution資料夾下沒有可用的System Generator檔案,軟體會提示錯誤。
設定完畢後,block埠也會隨之改變,部分埠名稱以ap_開頭,表示與block之間的ap_hs通訊協議。model的整體連線圖如下:
其中包含幾個子系統,各子系統及其作用如下:
- Noisy Image:匯入一副256*256的影象,轉換為一維資料,併為其新增椒鹽噪聲;
- RGB2Y:將R、G、B通道轉換為Y通道(Y=0.299*R+0.587*G+0.114*B,可以簡化為只用兩個乘法器的形式Y=0.299*(R-G)+0.114*(B-G)+G);
- LineBuffer:快取器儲存資料;
- Noisy Input Image/Filtered Image:快取資料,將一維資料轉換為二維影象顯示。
模擬測試
在Noisy Image子系統下,開啟Image From File這個block(屬於Computer Vision System Toolbox庫)。點選Browse,將路徑指向一副256*256大小的彩色圖片。將模擬時間設定為256*256*2,確保可以完成一次影象濾波。執行結果如下:
可以看到經過中值濾波後,很好地濾除了影象中的椒鹽噪聲。
Vivado HLS block詳解
該block支援C、C++和System C三種設計原始檔。使用是首先需要在Vivado HLS開發環境下將設計原始檔打包到Solution目錄下,然後在block中指向該目錄,將設計匯入到System Generator設計中。
點選“Edit”可以開啟與該solution對應的Vivado HLS工程,允許設計者修改;修改後點選“Refresh”更新block的埠資訊。
block預設採用RTL-model進行模擬,如果HLS中包含C模擬模型,可以選中“Use C simulation model if available”,選擇C模擬模型。
當選中“Display signal types”時,輸入和輸出的資料型別會顯示在圖示上,設計者可以根據該提示設定向此block輸入的資料,如下圖:
C/C++資料型別和System Generator資料型別之間的轉換關係如下表:
在Vivado HLS中進行設計時有如下限制:
- 設計不能是純組合邏輯,綜合到RTL設計後必須包含一個時鐘和時鐘使能輸入訊號;
- 頂層模組中不能包含C/C++模板語法;
- C模擬模型與block通訊時支援ap_hs通訊協議,但不支援ap_memory和ap_bus介面。