FPGA是一种特殊的集成电路。这种特殊性体现在它的电路功能在芯片被制造出来以后,可以通过编程配置进行调整,而传统的 专用集成电路 (Application Specific Integrated Circuit,ASIC)则不具备这种特性。打个比方,传统的专用集成电路芯片设计就像是在一张纸上画画,画好之后就没办法再修改了;而FPGA芯片设计就像是在黑板上画画,画好以后觉得不合适可以擦掉重新画。FPGA的这种可编程的特点为我们开展数字电路、组成原理、体系结构等实验课程提供了绝佳的硬件平台。首先,它是一个实实在在的集成电路芯片,不是仿真软件下电路行为的模拟,可以让硬件实验课能够真正“硬”起来,让学习者的实践经历更加贴近工业界的实际研发工作流程。其次,在FPGA上调整设计不需要重新流片或是重新设计焊接PCB(印制电路板),只需要调整设计代码后重新运行一遍FPGA的综合实现流程,短到几分钟长不过数天就可以获得一个功能调整后的芯片用于调试,省时又省钱。
FPGA是一种特殊的集成电路,这意味着它首先是一种集成电路。现在的集成电路绝大多数都是晶体管集成电路,大家日常接触最多的是CMOS晶体管集成电路。晶体管集成电路是什么?通俗一点来说,就是用金属导线把许许多多由晶体管构成的逻辑门、存储单元连接成一个电路,该电路具备一定的逻辑功能。不过,这并不意味着我们在设计数字逻辑电路时需要亲手用导线去连接晶体管。通常使用HDL语言(比如Verilog)编写代码,然后运行综合软件(比如Vivado),完成电路设计。这一流程其实与现在工业界常见的ASIC设计流程很相似。FPGA的设计流程一般有如下5个步骤。
1) 电路设计 。
2) 代码编写 。
3) 功能仿真 。
4) 综合实现 。
5) 上板调试 。
首先,需要根据需求规格制定电路设计方案。例如,需求是设计一个LoongArch CPU,我们要把这个需求一步步分解、细化,得到一个能够满足需求的电路设计方案。我们要决定分成几个流水级,这里放几个触发器,那里放几个运算器,它们之间怎么连接,整个电路的状态转换行为是怎样的,等等。通常,我们将电路设计细化到RT L级就可以了,无须精确到逻辑门级别或是晶体管级别。
代码编写阶段的工作是把第1步中完成的电路设计方案用HDL语言表述出来,让EDA工具能够看得懂。本书中我们使用Verilog语言。
功能仿真阶段的工作是对第2步中用HDL语言描述出来的设计进行功能仿真验证。所谓功能仿真验证,就是通过软件仿真模拟的方式查看电路的逻辑功能行为是否符合最初的设计需求。通常我们给电路输入指定的激励,观察电路输出是否符合预期,如果不符合则表明电路逻辑功能有错误。这种错误要么是因为第1步的电路设计有错误,要么是第2步编写的代码不符合电路设计。发现功能错误后需要返回前面相应的步骤进行修正,然后再按照流程一步步推进。如此不断迭代,直到不再发现错误,就可以进入下一阶段了。
需要指出的是,由于我们是在RT L级进行电路建模的,因此功能仿真阶段不考虑电路的延迟。
综合实现阶段完成从HDL代码到真实芯片电路的转换过程。这个过程类似于编译器把高级编程语言代码转换成目标机器的二进制代码的过程。这个阶段分为综合和实现两个子阶段。综合阶段将HDL描述的设计编译为由基本逻辑单元连接而成的逻辑网表,不过此时的网表还不是最终的门级电路网表。实现阶段才会将综合出的逻辑网表映射为FPGA中的具体电路,即将逻辑网表中的基本逻辑单元映射到FPGA芯片内部固有的硬件逻辑模块上(称为“布局”)。随后,基于布局的拓扑,利用FPGA芯片内部的连线资源,将各个映射后的逻辑模块连接起来(称为“布线”)。
如果整个综合实现过程没有发生异常,EDA工具将生成一个二进制码流文件。通俗来说,这个二进制码流文件描述了最终的电路实现,只不过这个文件是让FPGA芯片来看的。
俗话说,“是骡子是马拉出来遛遛”。不管功能仿真得多正确,最终还是要看实际电路能否正常工作。在上板调试阶段,首先要将综合实现阶段生成的二进制码流文件下载到FPGA芯片中,随后运行电路观察其工作是否正常,如果发生问题就要调试,并定位出错的原因。
以上简要介绍了FPGA一般设计流程的主要步骤,以便读者先建立一个正确的整体概念。FPGA设计流程中还包含很多细节,我们会在后续章节中陆续介绍这些细节,以免读者一时间难以全部消化吸收。实际上,FPGA设计流程中还有一些步骤,因为在本书实践任务中不涉及,所以没有列举出来,读者在今后的学习、工作中可以根据实际需要再行学习。
在前面提到的FPGA的一般设计流程中,“功能仿真”“综合实现”和“上板调试”这三个步骤都要使用EDA工具。我们的硬件实验平台选用的是Xilinx公司的FPGA芯片,因此很自然地会使用Xilinx公司提供的Vivado集成设计开发环境。尽管Vivado这个软件的功能仿真和波形调试功能不是特别丰富,但是我们设计的CPU比较小,使用Vivado也能满足要求。如果读者进行实验的环境中还没有Vivado软件,可以参考附录B的说明安装Vivado。
Vivado针对FPGA设计提供了两种工作方式: Project方式 和 Non-Project方式 。其中Project方式可以在Vivado的图形界面下操作或以Tcl脚本方式在Vivado Tcl Shell中运行,Non-Project方式只能以Tcl脚本方式运行,而且Non-Project方式和Project方式下的脚本中使用的命令是不同的。考虑到相比Tc l脚本这种适合大规模工程开发的进阶开发方式,图形界面操作方式更适合初学者,所以本书所述示例以及提供的配套实验环境均采用Project方式下的图形界面操作模式。
如果读者之前没有使用过Vivado软件进行FPGA的开发实现,可以参考附录C的示例来熟悉其基本操作。
根据以往的使用情况,我们总结了一些Vivado的使用建议。
1)尽量不要在运行于VMWare、VirtualBox等系统级虚拟机下的系统中安装并使用Vivado。Vivado在综合实现过程中需要较大的内存,因此在虚拟机下运行Vivado的时间会增加,而且是非线性增加,特别是当分配给虚拟机的内存只有区区1GB的时候,等待的时间会长得让人难以忍受。如果你并不是在系统级虚拟机下运行Vivado,同时机器的内存容量也够(譬如不小于4GB)且处理器的性能也不弱(譬如不低于Intel 10代酷睿的性能水平),但是运行Vivado的速度仍然很慢,那么建议你查看一下计算机的磁盘访问性能是否过低。
2)如果计算机上已经安装了Vivado,那么不需要重新安装。如果版本过低,直接升级到最新版本即可。
3)如果在裸机上安装了Linux系统,那么直接安装Linux版的Vivado即可,这比Windows版的Vivado速度要快一点。不过,这时很有可能会在FPGA下载电缆驱动的安装上出现问题。因为这方面问题的原因五花八门,请自行上网查找解决方法。不过,既然你已经在裸机上安装Linux系统了,相信你早已经有了相应的思想准备。
4)不要让工程所在位置的路径上出现中文字符,也不要让工程所在目录太深导致路径过长。
5)计算机的用户名不要设置为中文,否则会出现各种诡异的问题。虽然在网上可以找到一些解决的方法,但并不能保证对所有问题都适用。
在上板调试环节如果发现Vivado不能正常识别开发板,请按照下列步骤排查。
1)检查FPGA开发板是否上电。如果确实已上电,但仍然不放心的话,可以断电后再上一次电。
2)检查FPGA下载适配器的USB线缆是否与计算机以及适配器正常连接。
3)检查Cable Driver是否正常安装。
●如果是在Windows系统下,若驱动正常安装,就可以在设备管理器的界面中看到“Programming cables→Xilinx USB Cable”这样的条目。如果在设备管理器界面中找不到该条目,说明下载适配器的USB Cable的驱动未正常安装,参考下面的步骤4进行安装。
●如果是在虚拟机上安装的系统(尽管我们已经强烈不推荐在虚拟机下运行Vivado),还需要检查虚拟机软件中与USB相关的配置,确保USB全部转发到虚拟机。对于VirtualBox而言,选择“指定虚拟机→设置→USB设备→添加筛选器”。(默认添加一个各个域的值都为空的USB筛选器,此筛选器将会匹配所有连接到计算机上的USB设备。)
4)如果在Windows或Linux下发现下载适配器的USB Cable的驱动未正常安装,请参考https://china.xilinx.com/support/answers/59128.html安装驱动。如果该方法不行,推荐在Xilinx官网上寻找针对问题的解决方法。
5)在Vivado Tcl Console面板下输入disconnect_hw_server命令,并选择“Open target→Auto Connect”。
6)重启Vivado软件,重复步骤5。
7)重启你的计算机,重复步骤3~步骤5。
8)如果条件允许,用另外一台计算机试试该实验箱,或用另一个实验箱试试当前计算机,以确认是实验箱有问题还是计算机有问题。