FPGA的设计方法是伴随着芯片架构的演变而演变的。在FPGA诞生初期,由于其内部资源较为单一,故仅仅扮演着胶合逻辑的角色,在整个系统中只能起到协同作用。此时的设计方法也比较简单,如图1—24所示,设计输入使用RTL(Register Transfer Level,寄存器传输级)描述方式,功能仿真也称为前仿或行为级仿真,以验证设计功能是否正确;综合后仿真(Post Synthesis Simulation)则用于验证综合后的电路功能是否正确;时序仿真又称为后仿,仿真时反标了门级延迟和布线延迟信息,用于验证布线后的电路功能是否正确。综合后仿真和时序仿真比功能仿真更耗时,尤其是设计规模比较大时,因此,通常当设计出问题时才会执行这两个阶段的仿真。
图1—24
随着FPGA内部资源愈加丰富,嵌入了Block RAM,增大了其存储空间,嵌入了乘加器,增强了其计算能力,嵌入了高速收发器,提升了其数据传输带宽,进行FPGA设计时就要结合算法特征,分析哪些算法适合在FPGA上实现以充分发挥FPGA的性能,从而形成如图1—25所示的开发流程。这里软/硬件分割是设计的关键点。总体而言,数据流比较单一、运算密集但比较规整的算法,如FIR数字滤波器、FFT等就非常适合在FPGA上实现。进一步的细节划分,则要采取“缓存—计算—缓存”的模式,以适配FPGA的架构。而算法分支较多、判断条件复杂、数据路径形成反馈回路的更适合在CPU上实现。同时,FPGA更胜任处理定点数据类型(尽管目前FPGA也支持浮点类型)。图1—25中FPGA部分顶层功能验证的过程与图1—24一致,可采用Xilinx开发工具ISE(Integrated Software Environment)完成。
针对FPGA子系统,要从三个角度考虑,即物理级设计规范、时序设计规范和硬件设计规范,如图1—26所示。其中,物理级设计规范是为芯片选型服务的,根据资源评估结果、功耗预算和时钟频率确定芯片型号;时序设计规范是在确定时钟网络拓扑结构(时钟引脚位置、输入时钟频率、输出时钟频率、全局时钟还是区域时钟)的基础上,规划I/O时序(尤其是源同步设计和系统同步设计)和跨时钟域路径时序,基于此描述时序约束;硬件设计规范则是根据数据流合理规划RTL代码层级结构,在此基础上进行各子模块的开发,最终为时序收敛服务。
图1—25
图1—26
硬件设计规范中RTL代码层次结构是重点,这对综合、布局布线和时序收敛都会产生直接影响。通常应遵循的原则包括:
(1)需要实例化的输入/输出单元如IDDR、ODDR、ISERDES、OSERDES等尽可能靠近设计顶层,尽管IBUF、OBUF、IOBUF和OBUFT可由综合工具自动推断出来,但要确保IOBUF、OBUFT的使能信号和输入/输出信号在同一层次,以确保工具正确推断;
(2)时钟生成模块(通常采用Clocking Wizard IP生成时钟,不建议使用MMCM或PLL原语)放在顶层,方便其他模块使用时钟;
(3)在层次边界添加寄存器,对关键模块确保是寄存器输出,这样可将关键路径隔离在单一层次或模块之内,对于修复时序违例及设计调试大有裨益;
(4)确保需要手工布局的模块在同一层次之内。
图1—27给出了基于上述原则而形成的层次结构。图中每个子模块的阴影部分表示输出寄存器。
图1—27
随着FPGA中嵌入ARM核构成SoC芯片如Zynq-7000,SoC的设计方法也应运而生,如图1—28所示。软/硬件分割阶段,根据算法特征和系统需求(是否运行操作系统)将系统分为两大模块:硬件模块(在PL上实现)和软件模块(在PS上实现)。硬件模块的开发依然采用传统的FPGA开发模式,软件的开发则需要借助Xilinx开发工具SDK (Software Development Kit)。
图1—28
芯片架构和设计方法的演变也催生了Xilinx新一代开发工具Vivado的问世,随之问世的还有高层次综合工具Vivado HLS(现更名为Vitis HLS),而Vivado反过来又影响了设计方法。如图1—29所示,Vivado提出了以IP为核心的设计理念,进一步强调了设计的可复用性。在设计输入阶段,设计源文件可以是传统的RTL代码,可以是C/C++或OpenCL模型(采用Vitis HLS开发),也可以是Simulink下的AIE模型、HDL模型(原System Generator)或HLS模型(这三个模型隶属于同一个开发工具Vitis Model Composer,该开发工具嵌入在Simulink下)。其中,以高级语言(C/C++或OpenCL)描述的模型和以Vitis Model Composer搭建的模型均为高抽象度模型,需要借助相应的工具将其转化为HDL(Hardware Description Language)代码。而Vitis HLS或Vitis Model Composer最终都将其封装为IP,同时,传统的RTL代码描述的模型也可通过IP封装器(IP Packager)封装为IP,这些IP均可直接嵌入Vivado IP Catalog里当作常规IP使用,也可直接在IP集成器(IP Integrator,IPI)中以模块方式使用。这样,在IPI中进行设计开发就像搭积木一样。基于IPI开发的设计形成的文件为.bd文件,为了实现IPI模型的可复用性,Vivado又引入了BDC(Block Design Container)功能,即可以在一个IPI模型中实例化另一个IPI模型。在设计调试方面,可以借助VLA(Vivado Logic Analyzer,Vivado逻辑分析仪)。VLA取代了ISE时代的ChipScope。使用VLA需要在设计中添加ILA(Integrated Logic Analyzer)或VIO(Virtual Input/Output)。有三种方式可完成这一操作:①在代码中实例化ILA和VIO(VIO仅支持代码实例化);②在综合后的网表中插入ILA;③在布线后的网表中采用ECO(Engineering Change Order,工程变更命令)方式修改ILA。
图1—29
对比图1—29和图1—24不难发现,Vivado要求在综合之后就要对设计进行时序分析,确保建立时间时序收敛或接近收敛,这实际上是一个重大变化。这意味着若综合后依然存在建立时间违例,那么布线后时序收敛的可能性也不会大。
在软件开发方面,Xilinx于2019年推出了统一的软件开发平台Vitis,取代了原有的SDAccel,同时,功能也进一步增强了。SoC、MPSoC、AIE均可在Vitis下进行开发。
无论工具如何推陈出新,功能如何变化,目前为止FPGA设计始终遵循的一个思路是提高设计的可复用性。简言之,对于一些常用模块,通过参数化处理,使其可以适配不同项目的需求,达到可复用性目的。这样做的好处是避免了重复开发,从而缩短开发周期,同时,因为这些模块已经经过实际项目的验证,所以功能和质量都有所保障。这其实就是用户自己开发的IP。我们把“可复用性”的理念进一步扩大,如图1—30所示。设计输入阶段,从RTL代码到C/C++代码,再到Model Composer模型,都可以做成参数化形式;相应的功能仿真阶段用到的HDL测试平台、C/C++测试平台和Model Composer测试平台,也一样可以做成参数化形式。
图1—30
本书提供的很多SystemVerilog代码均已做参数化处理,可以方便快捷地实现设计复用。