目前在做FPGA移植加速CNN卷积神经网络Inference相关的学习,使用的是Xilinx公司的ZYNQ-7000系列的FPGA开发板,该博客为记录相关学习内容,如有问题欢迎指教。

概念

FPGA是一种集成电路(IC),可以在制造后针对不同的算法进行编程。现代FPGA器件由多达200万个逻辑单元组成,可配置为实现各种软件算法。虽然传统的FPGA设计流程与常规IC相比更像处理器,但与IC开发工作相比,FPGA提供了显着的成本优势,并且在大多数情况下提供相同级别的性能。与IC相比,FPGA的另一个优点是可以动态重新配置。此过程与在CPU处理器中加载程序相同,但是这样可能会影响FPGA架构中可用的部分或全部资源。

FPGA架构

FPGA的基本结构由以下单元组成:

  • 查找表(LUT):执行逻辑运算;
  • 触发器(FF):该寄存器存储LUT的结果;
  • 乘加器(DSP48等):乘加计算单元;
  • 线路(Wires):连接不同的单元;
  • 输入/输出(I/O):数据进出FPGA的物理端口。

这些元素的组合产生了基本的FPGA架构,如图所示。尽管该结构足以实现任何算法,但是实现的效率、吞吐量、所需的资源和可实现的时钟频率方面会受到一定的限制。

vega架构和rdna2架构 fiji架构和vega架构_寄存器

LUT

查找表(Look-Up-Table)简称为LUT,LUT本质上就是一个RAM。目前FPGA中多使用4输入的LUT,所以每一个LUT可以看成一个有4 位地址线的RAM。 当用户通过原理图或HDL语言描述了一个逻辑电路以后,FPGA开发软件(HLS)会自动计算逻辑电路的所有可能结果,并把真值表(即结果)事先写入 RAM,这样,每输入一个信号进行逻辑运算就等于输入一个地址进行查表,找出地址对应的内容,然后输出即可。 对于在一般N-input LUT,LUT的硬件实现可以被认为是连接到一组多路复用的存储器单元的集合。LUT的输入充当多路复用器上的选择器位,以选择给定时间点的结果。下图为LUT的功能表示:

vega架构和rdna2架构 fiji架构和vega架构_FPGA_02

Flip-Flop

触发器(Flip-Flop)是FPGA架构中的基本存储单元。此单元始终与上述的LUT配对,以帮助进行逻辑流水线操作和数据存储。触发器的基本结构包括数据输入,时钟输入,时钟使能,复位和数据输出。在正常操作期间,数据输入端口上的任何值都被锁存并在时钟的每个脉冲上传递到输出,时钟使能引脚的目的是允许触发器保持多个时钟脉冲的特定值,新的数据输入仅锁存并传递到上述数据输出端口时,当且仅当时钟和使能时钟是同一个。下图显示了触发器的结构:

vega架构和rdna2架构 fiji架构和vega架构_数据_03

DSP Block

Xilinx FPGA中最复杂的计算模块是DSP模块,如下图所示。DSP模块是嵌入到FPGA结构中的算术逻辑单元(ALU),它由三个不同模块组成。DSP中的计算链由加/减单元组成,该单元连接到最终加/减/累加引擎的乘法器。该计算链允许单个DSP单元实现以下形式的功能:

vega架构和rdna2架构 fiji架构和vega架构_数据_04

Storage Elements

FPGA存储单元包括嵌入式存储器元件,可用作随机存取存储器(RAM),只读存储器(ROM)或移位寄存器。这些单元其实就是FPGA中常见的Block RAM(BRAM),UltraRAM块(URAMS),LUT和移位寄存器(SRL)。

BRAM是一个双端口RAM模块,专为相对较大的数据集提供片上存储。设备中可用的两种类型的BRAM存储器可以保持18k或36k位。这些存储器的数量是特定于设备的。这些存储器的双端口性质允许平行,即同一时钟周期访问到不同的位置。

就如何用C / C ++代码表示数组而言,BRAM可以实现RAM或ROM。唯一的区别是数据写入存储元素。在RAM 中,可以在电路运行期间的任何时间读取和写入数据。相反,在ROM中,只能在电路运行期间读取数据。ROM的数据是作为FPGA配置的一部分写入的,不能以任何方式进行修改。

UltraRAM 块是双端口,同步288K BRAM用的4096个比特和72个位宽固定的配置。它们可在UltraScale+ 设备上使用,并提供比BRAM多8倍的存储容量。

如前所述,LUT是一个小存储器,在设备配置期间写入真值表的内容。由于Xilinx FPGA中LUT结构的灵活性,这些模块可用作64位存储器,通常称为分布式存储器。这是FPGA器件上可用的最快内存类型,因为它可以在结构的任何部分实例化,从而提高实现电路的性能。

移位寄存器是相互连接的寄存器链。该结构的目的是沿计算路径提供数据重用,例如使用过滤器。例如,基本滤波器由一系列乘法器组成,这些乘法器将数据样本与一组系数相乘。通过使用移位寄存器来存储输入数据,内置数据传输结构在每个时钟周期将数据样本移动到链中的下一个乘法器。下图显示了一个移位寄存器:

vega架构和rdna2架构 fiji架构和vega架构_寄存器_05

FPGA并行架构与CPU架构比较

与CPU架构相比,构成FPGA架构的结构可在应用程序执行中实现高度并行性。

CPU上执行程序

对于处理器CPU而言,无论其类型如何,都将程序作为指令序列执行,该指令序列转换为软件应用程序的相关计算。这一系列指令由处理器编译器工具生成,例如GNU编译器集合(GCC),它将用C / C ++表示的算法转换为处理器本机的汇编语言结构。编译器的工作是采用以下形式的C函数:

vega架构和rdna2架构 fiji架构和vega架构_寄存器_06


转换为汇编语言如下:

vega架构和rdna2架构 fiji架构和vega架构_数据_07


该代码表示的是,输入存储在寄存器 R1 和R2中 ,结果存储在寄存器R3中。该代码很简单,但是并不能表达所有的指令。此代码只处理了计算的数据已经到达该处理器。因此,该编译器必须创建额外的汇编语言指令来加载寄存器数据,并写回结果到存储器。完整的程序实现如下:

vega架构和rdna2架构 fiji架构和vega架构_寄存器_08


上面代码表明,即使是简单的操作,例如添加两个值,也会产生多个汇编指令。如果要计算的值是在该处理器的高速缓存中,完成这些加载操作需要几十的时钟周期。如果该值是在DDR中,这种情况采取数百个、数以千计的时钟周期来完成。如果该值是在硬盘中,加载操作需要甚至更长来完成。 这是为什么软件工程师在高速缓存方面花费这么多的时间重组他们的算法,以提高对空间局部性数据在存储器中,增加对高速缓存的命中率,降低处理器花在每条指令上的时间。

FPGA上执行程序

FPGA 是能够本质上并行处理任何逻辑和算术功能,上述加法运算由相关工具(如HLS)综合编译,实现最后的输出只需几个LUT。例如,假设在原始软件程序中,变量a, b和z是用short int类型定义的。short int定义的数据为16位,由Vivado HLS 实现仅为16个LUT 。

注意 :作为一般规则,1 LUT相当于1位计算。

用于计算z的LUT 仅适用于此操作。与所有计算共享相同ALU的处理器不同,FPGA实现为软件算法中的每个计算实例化独立的LUT集。除了为每次计算分配唯一的LUT资源外,FPGA在内存架构和内存访问成本方面都与CPU不同。在FPGA 实现中,将Vivado HLS 编译器指定的内存到多个存储成为可能,这形成一个瞬时存储器带宽,远远超过了处理器。 例如,在 Xilinx公司的Kintex ®-7 410T有181,590 k比特的BRAM。就存储器带宽而言,该器件的存储器布局为软件工程师提供了寄存器级每秒0.5M位和BRAM级每秒23T位的容量。关于计算吞吐量和内存带宽,Vivado HLS 编译器通过调度,流水线和数据流的过程来运行FPGA架构的功能。

目前的FPGA架构

目前的FPGA架构包含基本单元以及额外的计算和数据存储块,可提高器件的计算密度和效率。这些附加单元部分如下:

  • 用于分布式数据存储的嵌入式内存块;
  • 用于驱动不同时钟速率的FPGA 的锁相回路(PLL);
  • 高速串行收发器;
  • 片外存储器控制器;
  • 乘累加块。

这些单元的组合使目前的FPGA处理器运行的任何软件算法更具有灵活性,架构图如下所示:

vega架构和rdna2架构 fiji架构和vega架构_数据_09