前言
本文首发:FPGA的设计艺术(1)FPGA的硬件架构[1]FPGA是一个很神奇的器件,工程师可以在上面做游戏或者说工程师每天都在上面做游戏,通过搭积木的方式,还能设计出精美绝伦,纷繁复杂,奇妙无比的电路,这使用器件搭建几乎是做不到的,因为太庞大!这种设计也只能在FPGA或者专用的IC中能够实现,IC只能定制,可是FPGA却可以反复使用,每一次都可以是不同的电路,因此,FPGA目前的应用十分广泛,在很多关键领域,也是香饽饽一样的存在。
既然FPGA如此之妙,那么对FPGA有一个清晰地认识很有必要!
什么是FPGA?
FPGA是什么?这是一种官方的解释:
FPGA是一种集成电路(IC),在制造后可以对不同的算法进行编程。现代FPGA由多达200万个逻辑单元组成,可以配置实现各种软件算法。虽然传统的FPGA设计流程更类似于普通的IC(都是适用硬件描述语言设计电路并验证电路)而非处理器,但与IC开发工作相比,FPGA具有显著的成本优势(电路设计完成之后可以直接使用,而不需要继续流片),并在大多数情况下提供相同的性能水平。与IC相比,FPGA的另一个优势是它可以动态地重新配置(FPGA的名字就是现场可编程门阵列,即可随时重新编程,重新配置)。这个过程与在处理器中加载程序一样,可以影响FPGA结构中的部分或全部可用资源。
FPGA的硬件架构
Xilinx FPGA是异构计算平台(所谓异构,就是有很多不同的部分组成),包括Block RAM、DSP Slices、PCI Express支持和可编程结构。由于所有这些计算资源都可以同时使用,因此它们可以在整个平台上实现应用的并行化和流水线化。
FPGA的基本结构由以下元素组成。
- 查找表(LUT)--该元件执行逻辑运算。
- 触发器(FF)--这个寄存器元素存储LUT的结果。
- 布线资源--将各种元件彼此连接。
- 输入/输出(I/O)引脚 - 这些物理端口将数据输入和输出FPGA。
这些元素的组合形成了下图所示的基本FPGA结构。虽然这种结构足以实现任何算法,但从计算吞吐量、所需资源和可实现的时钟频率来看,所产生的实现效率是有限的。
FPGA的结构
当代FPGA架构将基本元素与附加的计算和数据存储块结合在一起,提高了器件的计算密度和效率。这些附加的元素包括:
- 用于分布式数据存储的嵌入式存储器(Distributed RAM)
- 锁相环(PLL),用于以不同的时钟速率驱动FPGA结构。(PLL/MMCM)
- 高速串行收发器(Transceiver)
- 片外存储器控制器(MIG)
- 乘累加模块
当代FPGA架构
上图显示了这些元素在当代FPGA架构上的组合。这为FPGA提供了实现在处理器上运行的任何软件算法的灵活性。请注意,整个FPGA上的所有这些元素都可以并发使用。
LUT资源
LUT是FPGA的基本构件,能够实现N个布尔变量的任何逻辑功能。本质上,这个元素是一个真值表,在这个真值表中,不同的输入组合实现不同的功能,从而产生输出值。真值表的大小限制为N,其中N代表LUT的输入数。对于一般的N个输入的LUT,表所访问的内存位置数为2的N次方。注意,Xilinx FPGA中N的典型值是6。
LUT的功能表示为内存单元的集合
LUT的硬件实现可以被认为是连接到一组多路复用器的存储器单元的集合。LUT的输入作为多路复用器上的选择位,在给定的时间点选择结果。牢记这种表示方法很重要,因为LUT既可以作为函数计算引擎,也可以作为数据存储元素。
Flip-Flop
触发器的基本结构包括数据输入、时钟输入、时钟使能、复位和数据输出。在正常工作时,数据输入端口的任何值都会被锁存,并在时钟的每个脉冲上传递到输出端。时钟使能引脚的目的是允许触发器在一个以上的时钟脉冲中保持一个特定的值。只有当时钟和时钟使能都等于1时,新的数据输入才会被锁存并传递到数据输出端口。
触发器的结构
触发器也是FPGA中的存储资源的一种,一个触发器可以存储1bit数据,别看它存储量小,但是它在FPGA中却是十分重要的资源,可以这么说,FPGA如果没有了触发器,就像水没有了流动,岂不成了死水,那对于FPGA,岂不成了砖头。
DSP48 块
Xilinx FPGA中可用的最复杂的计算块是下图所示的DSP48块。
DSP48块是嵌入FPGA结构中的算术逻辑单元(ALU),由三个不同的块组成的链。DSP48中的计算链包含一个加/减单元,连接到一个乘法器,再连接到最后的加/减/累加引擎。这条链允许单个DSP48单元实现如下形式的函数。
P=Bx(A D) C
或
P =Bx(A D)
Block RAM以及其他存储资源
FPGA结构包括可用作随机存取存储器(RAM)、只读存储器(ROM)或移位寄存器的嵌入式存储器元件。这些元件是块RAM(BRAM)、LUT和移位寄存器。
BRAM是实例化到FPGA结构中的双端口RAM模块,为相对较大的数据集提供片上存储。器件中可用的两种类型的BRAM存储器可以容纳18k或36k位,这些存储器的可用量是器件特定的。这些存储器的双端口性质允许对不同位置进行并行的、同时钟周期的访问。
块RAM(或BRAM)代表块随机存取存储器。块RAM用于存储FPGA内部的大量数据。它们是FPGA数据表上四个常见的识别元件之一。其他三个是触发器、查找表(LUT)和数字信号处理器(DSP)。通常FPGA越大、越贵,它的块状RAM就越多。既然这在FPGA产品概述的顶部就能找到,那么它一定很重要!
块状RAM(有时称为嵌入式存储器,或嵌入式块状RAM(EBR)),是FPGA的一个分立部分,这意味着芯片上只有这么多块状RAM可用。每个FPGA都有不同的数量,所以根据您的应用,您可能需要更多或更少的块状RAM。当你成为一个更好的数字设计师时,知道你需要多少就会变得更容易。正如我之前所说,它是用来在FPGA内部存储 "大量 "数据的。也可以将数据存储在你的FPGA之外,但那要通过SRAM、DRAM、EPROM、SD卡等设备来完成。
BRAM
在RAM配置中,数据可以在电路运行期间的任何时间进行读写。相反,在ROM配置中,数据只能在电路运行期间读取。ROM的数据是作为FPGA配置的一部分写入的,不能以任何方式修改。
如前所述,LUT是一个小存储器,在器件配置时,将真值表的内容写入其中。由于Xilinx FPGA中LUT结构的灵活性,这些块可以作为64位存储器使用,通常被称为分布式存储器。这是FPGA上最快的一种存储器,因为它可以在结构的任何部分实例化,从而提高了实现电路的性能。
可寻址的移位寄存器结构
移位寄存器是一个相互连接的寄存器链。这种结构的目的是提供沿计算路径的数据重用,例如与滤波器一起。例如,一个基本的滤波器是由一个乘法器链组成的,该乘法器将数据样本与一组系数相乘。通过使用移位寄存器来存储输入数据,内置的数据传输结构在每个时钟周期将数据样本移动到链中的下一个乘法器。
其他资源
上面也说了,FPGA中一些其他的资源,例如Serdes,或者称为Transceiver,我们在这方面讲了太多,也有相应的专题:例如:
什么是MGTs[2]
MGT
注:Serdes通常位于FPGA的专门Bank上,Xilinx称为MGT BANK,一般位于IOB附近。
BRAM的应用
单端口BRAM配置
块RAM单端口配置
当只有一个接口需要检索数据时,单端口块RAM配置是很有用的。这也是最简单的配置,对某些应用很有用。一个例子是存储只读数据,当FPGA被编程时,这些数据会被写入一个固定的值。这就是Block RAM的一个特点,就是它们都可以被初始化(这里的例外是Microsemi FPGA,因为它们是不同的架构,所以不能被初始化。)
也许你的应用有一堆校准参数,这些参数只写一次,并在启动时读出,那么一个单端口块RAM就可以很好的完成这个任务! 或者你需要做8B/10B编码/解码,这在以太网,HDMI,SATA,USB等中是很常用的。这些都将是单端口Block RAM的伟大应用。
它们的工作方式都是基于时钟的。只要Wr En信号不激活,数据将在时钟周期的正边沿读出,地址由Addr指定。读取值在Rd Data上出来,这是存储在BRAM中的数据。注意,每个时钟周期只能读取一个Rd Data值。因此,如果你的Block RAM有1024个值深,那么至少需要1024个时钟周期才能读出全部内容。
在某些应用中,您可能希望将一些数据写入Block RAM缓冲区,然后在稍后时间将其读出。这就需要将Wr En高电平驱动一个时钟周期,而Wr Data将拥有您的写入数据。对于单端口配置,你可以在端口A上读或写数据,你不能同时做这两件事。如果你想同时读和写数据,你将需要一个双端口块RAM!
双端口BRAM配置
块RAM双端口配置
块RAM双端口配置
双端口块RAM(或DPRAM)配置的行为方式与单端口配置完全相同,只是您有另一个端口可用于读取和写入数据。端口A和端口B的行为完全相同。端口A可以在端口B向地址200写入的同一时钟周期内对地址0进行读取。因此,DPRAM能够在一个地址上执行写入,同时从一个完全不同的地址上进行读取。我个人发现DPRAM的用例比单端口RAM的用例多。
一个可能的用例是存储外部设备的数据。例如,你想从SD卡上读取数据,你可以把它存储在双端口RAM中,然后再读出来。或者您想连接模数转换器(ADC),并需要一些地方来存储转换后的ADC值。DPRAM将是很好的选择。此外,双端口RAM通常被转化为FIFO,这可能是FPGA上Block RAM最常见的使用情况之一。
FIFO BRAM配置
块RAM FIFO配置
FIFO的意思是First In First Out,它们在FPGA设计中使用得很普遍。任何时候你需要在两个接口之间缓冲一些数据,你都会用到FIFO。或者如果你想跨时钟域,或者你想缓冲一行图像数据并对其进行操作,或者你想把数据送到片外的DDR存储器上,这些都需要使用Block RAM FIFO。我有专门的CDC处理就用到了FIFO,可见:FPGA逻辑设计回顾(6)多比特信号的CDC处理方式之异步FIFO[3]
参考资料
[1]
FPGA的设计艺术(1)FPGA的硬件架构: https://www.ebaina.com/articles/140000005583
[2]
什么是MGTs: https://www.ebaina.com/articles/140000005042
[3]
FPGA逻辑设计回顾(6)多比特信号的CDC处理方式之异步FIFO: https://www.ebaina.com/articles/140000005375