from:FPGA并行编程
HLS自动化能力
- 算法:自动分析并利用一个算法中潜在的并发性
- 时钟路径:自动在需要的路径上插入寄存器,并自动选择最理想的时钟
- 数据方向:自动产生控制数据在一个路径上出入方向的逻辑
- 接口:自动完成设计的部分与系统中其他部分的接口
- 数据映射:自动映射数据到储存单位以平衡资源使用与带宽
- 逻辑映射:自动将程序中计算的部分对应到逻辑单位,在实现等效计算的前提下自动选取最有效的实施方式
HLS编程限制
- 内存:不使用动态内存分配(不使用malloc(),free(),new和delete())
- 指针:
- 减少使用指针对指针的操作
- 减少使用C++中的函数指针和虚拟函数
- 调用:
- 不使用系统调用(例如abort(),exit(),printf()),我们可以在其他代码例如测试平台上使用这些指令,但是综合的时候这些指令会被无视(或直接删掉)
- 减少使用其他标准库里的内容(支持math.h里常用的内容,但还是有一些不兼容)
- 逻辑:不使用递归方程
- 接口:精准的表达我们的交互接口
FPGA构造
- 查找表(LUT):把地址信号输入进去,对应内存位置的内容会直接被输出出来。
- 一个N位查找表可以以一个N位输入真值表的方式来表示。
- 一个2位输入查找表,共有2^2比特。

- 可配置逻辑块(CLB)或逻辑矩阵块(LAB)。有些设计工具中还会把它称作片(Slice)。
- 触发器(FF)是FPGA最基本的内存单位,通常触发器是配有查找表的,这样是为方便查找表之间的复制与组合。
- 函数逻辑

- 连线通道和开关盒:可编写的互联是FPGA最关键的特性之一

- IO模块
- 微控制器(通过AXI接口连接片上ARM处理器 )
- 传感器(通过A/D接口连接天线)
- 作动器(通过D/A接口连接电机)etc

- 块RAM(BRAM):支持多种内存形式和接口的可配置随机储存器。
- 芯片上各部分的数据转移
- 储存大一些的数据集
可以把这些数据传给本地片上总线(与可编程逻辑交流)或处理器总线(与片上处理器交流)等接口。
可以储存字节,对字,全字,双字等。
| 属性 | 外部内存 | BRAM | 触发器 |
|---|---|---|---|
| 数量 | 1-4 | 几千 | 几百万 |
| 单个大小 | GB级 | KB级 | bit级 |
| 总量 | GB级 | MB级 | 100KB级 |
| 宽度 | 8-64 | 1-16 | 1 |
| 总带宽 | GB每秒 | TB每秒 | 100TB每秒 |
容量配置
- 拆分:32000 x 1比特,16000 x 2比特,8000 x 4比特等形式存在。
- 串联:形成更大容量
设计使用:
- BRAM想成一个寄存器堆,它可以直接输出到一个自定义的数据路径(DSP48),可以与处理器交流;
- 也可以像可编程逻辑上的数据路径传输数据。
FPGA设计与处理

- I/O接口核:通常以RTL的形式构架并需要加上其他的时序限制
整个设计的外围临近I/O引脚的地方通常是一些少量的逻辑,它们一般用来完成关键时序和协议,比如内存控制模块,视频接口核心或模拟数字转换器。
- 标准核
- 处理器核心
- 片上内存核连接开关
- 原生的函数处理部件:滤波器,FFT,编解码器,etc
PS:标准核心主要是同步电路,它除了时钟时序限制之外不大有限制。这些特点让标准核更容易在不同FPGA中兼容,当然,被转移到另一种FPGA结构中时还是需要一定优化的。
- 加速器核:同标准核一样,加速核通常是由时钟限制而规定的同步电路,但这些核却是系统设计师们在具体应用中不可避免要接触的部分。
- 使用:
- 以核为基础的设计方法:用HLS创造出这种核之后把他们与IO接口核和标准核组合到一起(可以通过Vivado IP Inegrator这样的软件)
- 以平台为基础的设计方法:设计师先用IO接口核和标准核组合出一个样板,然后再用HLS通过壳(shell)的接口将各式算法或对象组合进去。只要壳支持双边的接口,加速器核在平台与平台之间的移动也非常容易。
- 使用:
设计优化
衡量标准
我们用任务(task)这个术语来表示一个行为的基本单位,用户可以在Vivado HLS中发现与之对应的是调用函数。

设计空间与限制
- 空间
HLS的一个特点就是在决定结构上的一些此消彼长的设计时,不再需要考虑让它适用于指令集的结构限制。在HLS设计中,设计出一个在同周期内执行成百上千个RISC级指令外加几百个周期程度流水的系统是非常常见的。
- 限制
HLS设计师需要考虑流水,内存排布,I/O接口
流水举例:
顺序化的结构很难解析码流,主要出于控制逻辑的复杂度。另外,控制逻辑负责规定任务延迟和任务间隔。顺序化结构的性能有时取决于处理的数据。
Vivado HLS可以产出更加流水,平行,性能上也更好的结构。其中之一叫做函数流水。函数流水结构是把函数内所有的代码都当作计算数据路径的一部分,再加上少量的控制逻辑。*循环和分支被转换成无限制的结构。*这种结构特点分明,容易分析,一般用于处理连续而简单的高码率数据。
限制举例:
- 递归(recurrence),这里是指某个部件的计算需要这个部件之前一轮计算的结果
- 资源限制
-
硬件
如果 int32_t f(int32_t x)这样形式的函数作为一个单独模块在100MHz的频率和1的任务间隔下运行,它最大的数据处理量就是3.2G比特。
-
用户设置
如果用户规定了在综合中可用的操作数,这其实是给处理率添加了限制条件。
-
优化策略:重构代码