HLS设计步骤

HLS设计步骤
1) HLS介绍
1. 什么是HLS
High level synthesis, 能够将高级语言(C/C++)综合为HDL。
2. 为什么使用HLS
在算法层面,高级语言通常比HDL开发效率更高, 因此使用HLS可以大大加速原型验证。高级语言进行程序设计可以脱离硬件, HLS可以将项目的软件, 硬件开发分离, 更加灵活, 利于项目的管理。
2) 了解Vivado HLS的设计流程
在这里插入图片描述

开发流程:
C/C++ source code + Testbench-> C功能仿真 -> C综合 -> C/RTL联合仿真 -> 导出RTL,生成IP核 -> Vivado工程中调用这个IP核
在这里插入图片描述
如图, Vivado HLS界面的设计也体现了这样的设计流程。

1. 实例演示
我们将用HLS实现一个detection模块。
Vivado HLS只能对一个顶层函数进行综合, 而且这个函数名不能是main。 所以我们应该将我们想要综合的功能封装成一个函数 detection。
我们一个图像识别模块为例。我们将实现一个快速圆心识别模块,输入一帧包含一个圆的黑白二值图像,输出圆心的估计坐标。
下面是一个示例:我们用MATLAB创建了一个测试图像,模块输出的坐标应该接近(128, 73)。
在这里插入图片描述
我们简略地提供一种实现算法。算法过程如下:
 将图像分成一系列正方形网格
 对于每个网格Block,计算网格中白点的个数
 如果白点的个数大于某个阈值Threshold, 并且该Block比周围所有的Block计数值都大(处在中心),那么就认为圆心可能位于该Block
 在该Block周围的邻域内,求白点的重心。即,以周围的Block的白点个数为权重,求Block位置的加权平均(分别在x, y方向)。
 返回求得的平均值

2. 工程建立步骤
首先准备好源文件之后, 我们打开HLS创建工程
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
创建完之后,首先执行C仿真:
在这里插入图片描述
在这里插入图片描述

跳出如下界面,并显示没有错误
在这里插入图片描述
第二步执行综合:
在这里插入图片描述
综合之后会生成综合报告, 其中可以看到生成HDL的latency参数, 和硬件资源用量。
在这里插入图片描述
然后执行cosimulation

在这里插入图片描述
等待cosimulation结束
点这里可以查看波形:
在这里插入图片描述

3. 在Vivado中调用HLS生成的IP核。
上面我们完成了从工程的创建一直到C/RTL联合仿真, 那么我们该如何将生成的代码应用到Vivado里面去呢?
Solution > Export RTL,或者点击工具栏快捷按钮
在这里插入图片描述
然后默认ok
在这里插入图片描述
然后在以下目录下发现ip
在这里插入图片描述

4. 接口综合
首先我们要了解以下, HLS是怎么综合函数的输入输出变量的。
在这里插入图片描述
在综合报告中, 我们会看到一栏描述接口的表格。
可以看到, 除了模块自动生成的控制信号, 我们的三个输入变量和一个返回变量分别被综合成了四个ap_none协议, 32bits的变量。 这些在生成IP核之后, 就会成为四组32根的数据线。 ap_none是最简单的接口协议, 也是最常用的协议之一。
除了采用默认的接口协议, 我们也可以在directive窗口手动指定想要综合的接口协议。
以上的例子中, 函数被综合成了一个组合逻辑电路。 我们再来看一个时序逻辑电路的例子。
在这里插入图片描述
可以看到, 输入输出数组都被综合成了ap_memory协议的接口。
从仿真结果也可以看到各个信号的作用:
在这里插入图片描述
ap_memory是另一个非常常用的协议, 所有的数组都会综合成这样的协议。 而在生成IP核之后, 我们需要为这些接口手动分配memory, 这是尤其需要注意的一点。 我们在下面实例中将演示方法。
此外,为了提高读取效率,数组还可以进行分组partition,这样可以多路并行读写,提高数据吞吐量,这点在后文也有体现。

5. 数据类型
值得注意的一点是数据类型。 Int数据类型占用4个Byte, 因此自然会生成32根信号线, 但是实际应用中, 我们的变量往往不用这么大的位宽。 比如某个变量mode的取值范围是0~3, 显然我们只需要2根信号线就够了。怎么实现呢?
HLS内置了任意精度的数据类型。
在这里插入图片描述
#include <ap_int.h>
ap_uint<2> mode;
这样, 变量mode就会被综合成2 bits
不仅是接口, 对中间变量合理使用数据类型也可以大大节约资源使用, 这是非常必要的。

6. 综合并导出RTL
上面的算法能够识别一个圆心,我们这里提供一个更复杂的例子,它使用同样的算法识别四个圆心。
在这里插入图片描述
顶层函数有四个变量。
输入:第一个是img数组,是图像输入,数组长度是图像的长宽乘积。
输出:第二个和第三个变量是x, y坐标,用于输出识别到的物体坐标,这里最多可以识别四个物体,因此数组长度是4。
第四个变量输出识别到物体的个数。

注意到右侧directive窗口,我们对这些接口的综合方式做了一些指定。
在这里插入图片描述
对img, 我们使用了RESOURCE方式,它能够自动生成支持各类memory的接口。一般来说,Vivado中最简单的RAM就是单口BRAM了,因此我们core一栏选择RAM_1P_BRAM。
在这里插入图片描述
对于第二个和第三个变量,如果我们采用默认设置,HLS会自动为这些数组也综合成memory接口。而在这里,数组的长度仅为4,而且每个坐标变量位宽仅为9。所以,我们希望HLS把这个数组所有元素直接引出到模块IO口。我们采用的方法是partition。
在这里插入图片描述
方式设为complete, 维度设置为1,这样数组就会被完全展开。
我们执行综合,在综合报告interface一栏看一看生成的接口。
在这里插入图片描述
Img被综合成了ap_memory类型,支持单口BRAM。 X, y所有元素都被展开,引出了8组9bits位宽的数据线, 跟我们希望的一样。

7. 调用IP
通过block design添加ip
首先create block design
在这里插入图片描述
在添加IP核之前,我们要将生成的IP核目录加入项目目录。打开Project Settings
在这里插入图片描述
在这里插入图片描述
我们生成的IP核会出现在HLS工程对应solution下的impl/ip目录。将该目录添加到IP Repository。
完成之后,在Block design中就可以顺利找到我们的IP核了。把它添加。
在这里插入图片描述
在这里插入图片描述
选中它,按下CTRL+T,就可以一键引出所有端口。
在这里插入图片描述
回到source窗口,右键我们刚刚创建的block design, 点击Create HDL Wrapper, 我们就可以生成Vivado可以调用的.v文件了
在这里插入图片描述
在这里插入图片描述
那么,我们的img数组是从RAM读取的,怎么创建这个RAM呢?添加Block Memory Generator。
在这里插入图片描述
双击生成的模块。
在这里插入图片描述
这里选择简单双口RAM(一路只读,一路只写), A口可以作为数据的输入,B口可以给我们的detection模块读取,就可以成为缓冲了。
在这里插入图片描述
设置好位宽和大小,并确定。
在这里插入图片描述
将port B对应数据线 地址线和控制线与img的接口连好。
引出Port A供外部调用。再执行一次上述的create HDL Wrapper, 这样模块。v文件就创建完成了,可以在你的Vivado顶层文件中调用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值