本文是该系列的第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
static PixelType pixelWindowBuffer[WINDOW_SIZE*WINDOW_SIZE];
PixelType sortBuffer[WINDOW_SIZE*WINDOW_SIZE];
for (int i = 0 ;ifor(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 ];
}
}
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大小的彩 {MOD}图片。将仿真时间设置为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接口。