学fpga(hls之平均值算法编写)

Posted 费晓行

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了学fpga(hls之平均值算法编写)相关的知识,希望对你有一定的参考价值。

【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】

        一些soc中的fpga,本身除了作为硬件使用之外,还可以作为硬件加速使用。如果是cpu上做的比较慢的一些操作,那么就可以用fpga来加速,这个时候hls就能排上用场了。可以以求平均值作为举例,看看fpga上面是怎么用hls做平均值的计算。

1、一般写法

#include <ap_cint.h>
uint32 _average_int(uint32* array, int num)

	uint32 sum = 0;
	int i;

	for(i = 0; i < num; i++)
	
		sum += array[i];
	

	return sum / num;


uint32 average_int(uint32* array, int num)

#pragma HLS INTERFACE s_axilite port=return
#pragma HLS INTERFACE s_axilite port=num
#pragma HLS INTERFACE m_axi depth=1024 port=array

	uint32 result = _average_int(array, num);
	return result;

        和之前一篇文章有所不同的是,这里的函数return接口是s_axilite,函数返回值也是uint32。此外,除了num还是s_axilite之外,array已经变成了m_axi,毕竟可能需要从ddr读取数据来进行操作。可以看一下编译后的一个中断接口,

2、添加pipeline 

#include <ap_cint.h>
uint32 _average_int(uint32* array, int num)

	uint32 sum = 0;
	int i;

	for(i = 0; i < num; i++)
	
#pragma HLS PIPELINE
		sum += array[i];
	

	return sum / num;


uint32 average_int(uint32* array, int num)

#pragma HLS INTERFACE s_axilite port=return
#pragma HLS INTERFACE s_axilite port=num
#pragma HLS INTERFACE m_axi depth=1024 port=array

	uint32 result = _average_int(array, num);
	return result;

        1中的代码虽然能实现功能,但是毕竟不是并行的。一种简单的方法,就是在for循环里面添加pipeline,这样可以提供数据的吞吐量。流水线的加速原理比较简单。就是假设一件事情需要三个步骤,那么在前一件事情开始做第二个步骤的时候,第二件事情没有必要等第一件事情做完,就可以开始第一步骤的操作。

3、进一步添加cache和dataflow

#include <ap_cint.h>
#include <string.h>
uint32 sum;

void _average_int(uint32* array, int num)

	sum = 0;
	uint32 cache[64];
#pragma HLS STREAM variable=cache depth=64
	int i;
	int j;
	int len;

	for(i = 0; i < num; i+= 64)
	
#pragma HLS LOOP_TRIPCOUNT min=0 max=1024
#pragma HLS DATAFLOW

		if((num - i) >= 64)
		
			len = 64;
		
		else
		
			len = num - i;
		

		memcpy(cache, array+i, len);

		for(j = 0; i < len; j++)
		
#pragma HLS PIPELINE
			sum += cache[j];
		
	



uint32 average_int(uint32* array, int num)

#pragma HLS INTERFACE s_axilite port=return
#pragma HLS INTERFACE s_axilite port=num
#pragma HLS INTERFACE m_axi depth=1024 port=array

	_average_int(array, num);
	return sum;

        和1、2相比较而言,3改动较大。除了添加了全局变量sum之外,还添加了cache和dataflow。添加cache,主要是因为总线资源比较宝贵,可以一次性加载多个数据进行处理,不用每次只加载一个,这样太浪费资源。另外,添加了dataflow之后,memcpy和后面的for循环可以进行数据流操作,进一步提高数据的并行性。

4、优化的步骤和方法

        一般来说,hls的优化并不是一蹴而就的。这中间不断的迭代和改进是不可或缺的。通常,第一步是完成基本功能开发,接着完成接口的设定,最后是数据、for循环、流水线的优化。当然,所有这一切还是要上机进行实际环境的验证。资料里面直接给出代码的做法缺少了思考的过程,这方面恰恰是自己需要进行补齐和锻炼的。

以上是关于学fpga(hls之平均值算法编写)的主要内容,如果未能解决你的问题,请参考以下文章

学fpga(hls之系统开发)

学fpga(hls之图像处理)

学fpga(hls之BlockDesign)

学fpga(hls之花式led配置)

学fpga(hls之unroll的使用)

学fpga(从verilog到hls)