FPGA是一种可编程芯片。其结构可以想象成小朋友的电子积木玩具。底板就像FPGA芯片晶圆,一段段电路连线就像FPGA芯片的可编程布线资源。与各种电路元器件类似,FPGA芯片上也有”元器件“:
- 查找表(Look-Up Table):可编程配置为不同的逻辑功能;
- DSP(Digital Signal Processor):可编程实现复杂的乘/加计算;
- 寄存器register/BRAM/SRAM:存储0/1电平信号;
- 各种特定功能IP硬核:如pcie接口硬核等。
与每款电子积木玩具类似,每款FPGA芯片生产出来后,也包含一定数量连线资源,”元器件“。FPGA在结构上更进一步,连线资源和“元器件”的位置也固定了下来。而FPGA工程师不仅需要设计不同的逻辑功能,而且还需要考虑合理的使用这些“元器件”以及确保这些“元器件”工作在正常稳定状态下,这就是FPGA工程师常说的“资源优化”和“时序优化”。
资源优化
资源的合理使用(资源优化)贯穿着整个FPGA开发的流程:
- 需求阶段:做好资源预估和需求裁剪
- 设计阶段:满足性能要求前提下,架构上需考虑资源的分配和共享
- 编码阶段:同一个逻辑功能,不同的编码方式,资源消耗不同
需求阶段不同的项目需求不同,需求裁剪带来的优化效果最明显。但也很难有统一的方法论去概括,核心的思想就是权衡。这里主要介绍一些设计阶段和编码阶段资源优化的方法。
设计阶段资源优化方法
设计阶段从方案上对FPGA整体资源进行规划,实现资源的合理应用。以下2种方法常常用到。
资源腾挪
资源腾挪利用合适的资源做适合的事。简单例子,调用DSP硬核资源实现数据的加减法(或乘法)。这里详细介绍以下Intel MLAB、BRAM、eSRAM的使用方法以实现memory资源的合理分配。
intel Agilex器件包含三种类型的memory,分别如下:
- 432Mb eSRAM模块:
- 高带宽和高随机传输率。
- 每个模块包含8个通道,每个通道32个bank。
- 每个BANK可配置成1024深度64bit数据位宽。
- 每个channel可以同时读写访问(类似简单双口ram)。
- 20Kb M20K模块
- 适用较大存储器阵列,提供大量独立端口。
- 640bit MLAB模块
- 适用于宽而浅的存储阵列
- 每个MLAB由10个自适应逻辑块(ALM)组成。每个ALM可以配置成32深度2bit位宽模块。
三种存储器支持配置表如下:
类型 |
深度 |
位宽(bits) |
MLAB |
32 |
x16,x18,x20 |
M20K |
512 |
x32,x40 注:仅用于简单双口 |
1024 |
x20 注:用于简单双端口和真双口 |
|
2048 |
x10 注:用于简单双端口、真双口和简单四端口 |
|
eSRAM |
1024 |
x64 |
注:MLAB/M20k的配置都是指单个MLAB/M20K,可以通过多个MLAB/M20K的拼接实现更大位宽和深度的memory。eSRAM虽然不能灵活配置,但是可以多通道拼接使用实现更大存储容量。
根据上面描述的intel RAM的配置使用方式,在设计阶段就可以对RAM的使用进行合理规划。举个例子,一个512bit位宽,32深度的ram,应该设计为MLAB还是M20K?根据前文描述:
使用MLAB:一个MLAB可以拼成16bit位宽,32深度的memory。那么只需要32个MLAB即可实现,消耗ALM个数为320个。
使用M20K:一个M20K可以拼成40bit位宽,512深度的memory。需要13块M20K拼接而成。由于只使用了32深度,造成很大的空间浪费。
由此可见,对于512bit,32深度memory可以采用MLAB替代M20K使用,从而节省M20K资源消耗。实际项目中,大位宽且深度不超过64深度的memory设计都可以考虑MLAB替代M20K。当然反过来也可以使用M20K替代MLAB减少ALM的占用。
资源共享
FPGA设计(RTL设计)和软件设计在资源消耗上是很大的不同。FPGA的每1行有效代码都意味着占用一定量的逻辑资源(查找表/寄存器/memory),相比之下,软件代码在CPU资源和内存资源的占用上多是时分复用共享的方式。所以FPGA在设计阶段需要考虑资源共享问题,这里介绍几个针对memory的共享使用方式:
时分复用
intel 提供的BRAM可以提供真双口模式,在真双口模式下可支持2个口同时对BRAM的内容进行访问。这样可以简单的支持2个模块访问共享表项或是共享内容。对于多于2个口的访问可以采用下两种时分复用的设计:
方式一:接口固定时间切片访问,满足访问带宽的前提下,访问时序设计如下:
这种方法是将BRAM接口上的访问时序切成固定的时间片(示例是1个cycle),每个时间片由不同的通道进行共享访问。每个通道访问的带宽需求小等于BRAM理论带宽的1/n,且每个通道访问的内容是共享的,则可以采用这种设计。该设计简单,但BRAM带宽分配不灵活,适用于CPU指令处理等固定访问时序场景。
方式二:接口仲裁机制访问。即在BRAM接口处提供多通道仲裁机制,实现多通道灵活调度。
仲裁器可以使用SP/RR/WRR/DWRR实现灵活的调度,从而实现BRAM共享。
数控分离
这里说的数控分离是指数据的存储和控制信息的存储要分离。
在FPGA设计中通常是以数据包的方式缓存在RAM中的。同时也会缓存一些数据包的描述信息用于读侧控制(如数据包长度等)。这些信息通常是一个报文对应一个描述信息。如果将这些信息和每1拍的数据一起缓存,则需要构造很大位宽的缓存,造成资源的浪费。例如,一个数据包为4096字节传输位宽为512bit数据,数据包描述信息为128bit数据缓存:
- 混合存储:所需BRAM容量为640x64,则需要占用16块BRAM;
- 分离存储:所需BRAM容量为512x64 + 128x1,则需要占用13块BRAM+1块MLAB即可
代码阶段资源优化方法
代码阶段资源优化主要是一些优化资源的写法,不同写法可能占用资源不同。这里举几个例子进行简单的说明。
同步复位异步复位
通常FPGA芯片的寄存器都是带有异步复位接口的,采用异步复位的方式可以充分利用寄存器的异步复位接口,也可以节省同步复位带来的LUT资源开销。
- 同步复位写法:
- 异步复位写法:
优先级和case
在实现分支判断逻辑的时候,采用带优先级的分支判断逻辑资源大于不带优先级判断逻辑。
- 带优先级的分支判断逻辑
- 不带优先级的分支判断逻辑
位选择和移位
位选择从一组信号中选择其中的某些bit位。通常实现方式是用case语法实现一个mux,也可以利用移位的方式实现,这样可以利用移位资源,从而减少lut占用。
- case位选择
- 移位位选择
运算和比较
2^n常数比较大小,可以使用以下运算方式化简一些比较大小资源占用,代码如下:
任意数比较大小,可以使用以下运算方式化简一些比较大小资源占用,代码如下:
FPGA的资源优化贯穿整个FPGA开发的过程,优化的方式也是多种多样,每一个FPGA开发工程师都有自己一套优化的方法,这里仅抛个砖,大家有更多的方法,评论区多多交流!