本文记录了利用FPGA加速图像处理中的卷积计算的设计与实现。实现环境为Altera公司的Cyclone IV型芯片,NIOS II软核+FPGA架构。
由于这是第一次设计硬件加速模块,设计中的瑕疵以及问题欢迎前来讨论。
更新记录:
- D0423 记录FPGA核心计算模块和控制模块
- D0426 记录FPGA核心计算模块的控制驱动,性能与功能测试
Part1 : 卷积相关
软件实现卷积
- 卷积是将原来矩阵的对应部分与
卷积核
对位乘法再加起来,形成新的矩阵中的一个位。 - 图中红色的框是
卷积操作
当前所在位置,对位乘法相加之后得到中间的小红框的值。 - 利用C语言实现核心代码如下
void Conv(int filter[100][100], int arr[100][100], int res[100][100], int filterW, int filterH, int arrW, int arrH){
int temp;
for (int i=0; i<filterH+arrH-1; i++){
for (int j=0; j<filterW+arrW-1; j++){
printf("Start %d %d \n",i,j);
temp = 0;
for (int m=0; m<filterH; m++){
for (int n=0; n<filterW; n++){
printf("m %d n %d ",m,n);
if ((i-m)>=0 && (i-m)<arrH && (j-n)>=0 && (j-n)<arrW){
printf("%d * %d",filter[m][n],arr[i-m][j-n]);
temp += filter[m][n]*arr[i-m][j-n];
}
printf("\n");
}
}
printf("End\n");
res[i][j] = temp;
}
}
}
***********************************************
Filter:
2 1 2
0 5 0
1 3 1
***********************************************
***********************************************
Matrix:
17 24 1 8 15
23 5 7 14 16
4 6 13 20 22
10 12 19 21 3
11 18 25 2 9
***********************************************
***********************************************
Result:
17 75 90 35 40 53 15
23 159 165 45 105 137 16
38 198 120 165 205 197 52
56 95 160 200 245 184 35
19 117 190 255 235 106 53
20 89 160 210 75 90 6
22 47 90 65 70 13 18
***********************************************
针对具体的(3,4)
Start 3 4
m 0 n 0 1 * 3
m 0 n 1 3 * 21
m 0 n 2 1 * 19
m 1 n 0 0 * 22
m 1 n 1 5 * 20
m 1 n 2 0 * 13
m 2 n 0 2 * 16
m 2 n 1 1 * 14
m 2 n 2 2 * 7
End
硬件实现思路和可能的加速
- 这是一个卷积处理单元的顶层图。
- 还是同滑动窗口思路类似,右边三位输入为控制器,使得该处理单元在3行上向右滑动。
- 不同于软件实现,这里的乘法底层应该是查找表实现的,所有9个DFF的乘法,可以并行计算。
- 计算结构用最下面的加法模块加上后输出当前位。
- 这个加法可能会通过拆分加优化(加法树之类)
最简单的实现就是将这个模块运算玩一行后继续算下一行。但是这样没有充分利用这些数据不相关的特性,有两种思路。
- 一个是如上图多放几个卷积模块
- 另一个是通过级联将
3*3
的卷积模块扩大 比如说6*6
的,可以通过4个3*3
的处理模块级联实现。具体多大,和板子资源和具体矩阵尺寸有关。这个还要再考虑。
与软件比较
3*3
处理模块中软件9个乘法串行,这里并行。- 多个级联后可以达到
36
或者更高的优化
Part2 : FPGA卷积核心计算模块
Convolution Calculate Moudle
该模块是卷积计算的核心模块,模块顶层图如下:
输入输出端口说明
Din0
~ Din8
是当前计算矩阵3*3
的输入
参数Filter0
~ Filter8
是卷积核3*3
的参数。这里不选择动态输入是为了FPGA
构造更小的LUT
Start
和Rst
是该模块的控制输入
Finish
是该模块的完成输出,可以作为中断信号。
防止溢出,这里Dout给的16
位
详细设计与分析
该模块包含一个自动机,用于跟踪计算状态,提供与上层同步的时序依据。
在RUNING过程中包括两个子状态,用于并行计算乘与并行计算加,利用两个变量来控制。
该模块在Quartus 13
的RTL
如下:
虽然看起来加法链那里由于没有优化拉的很长,但是由于与时序无关,下一个时钟周期来的时候计算一定会完成,所以没有太大影响。
测试该模块
书写Test Bench
仿真测试
利用NIOS II
软核测试
烧录Cyclone IV
JTAG输出测试
测试程序如下:
#include <stdio.h>
#include "system.h"
#include "altera_avalon_pio_regs.h"
int main() {
//Test For Conv_cal