type
status
date
slug
summary
tags
category
icon
password
9.1 章节导读
这一章里我们将通过建立一个完整的工程来验证软件安装是否正确,是否可以实现软件的基本操作。
9.2 正确的设计流程
正确的设计流程是开发项目的关键,大概主要分为以下几个步骤: 1. 首先我们要进行设计前的规划,即对项目要有一个全局的考虑,分析项目的具体需求来设计系统的结构、划分系统的层次,确定各个子模块的结构关系和信号之间的相互关系,然后确定模块的端口信号有哪些; 2. 根据每个模块的功能和自己的理解并结合芯片、接口的时序手册我们使用 Visio 画出该模块能正常工作的时序波形图; 3. 根据所画的波形图严格设计代码,所谓的严格就是要保证设计代码的仿真结果要和所画的波形保持一致; 4. 代码编写完成后对代码进行编译,目的是检查代码中的语法错误。若代码存在语法错误,对代码进行修改,再次编译,直至通过编译; 5. 根据 RTL 代码设计合理的 Testbench 进行逻辑仿真(也称为前仿真、功能仿真); 6. 使用仿真工具进行仿真(可以使用软件自带的仿真工具,也可以使用其他的第三方仿真工具,本教程中我们使用 ModelSim),并将仿真出来的波形和用 Visio 画出的时序波形图进行对比,如果对比有差别则修改代码直至相同; 7. 绑定管脚后进行分析综合、布局布线,然后下载到硬件板卡中,此时如果硬件板卡能够正常工作,则说明前期的设计和编写的代码都正确;如果硬件板卡不能够正常工作,查找并解决问题,反复迭代直至正确实现功能,并重复后面的流程,最终保证硬件板卡能够正常工作。
9.3 工程文件夹的管理
doc:该文件夹主要放置一些文档资料,如数据手册,使用 Visio 画的波形图、自己写的文档等都可以存放到这个文件夹里面。
quartus_prj:该文件夹主要放置的是工程文件,使用 Quartus II 新建的工程就保存到这里,如果是使用的 Xilinx 的 ISE 开发工具,就可以命名为 ise_prj,这样能很清晰的知道是用的什么开发软件进行开发的。
rtl:该文件夹主要放置可综合的代码,就是最后可以生成硬件电路的代码,因为这部分代码主要是寄存器描述的寄存器传输级的代码所以文件夹取名为 rtl(register transport level),因为也是我们的设计文件,所以也可以取名为 design。
sim::该文件夹放置对可综合代码的仿真文件,即不可综合的代码,也叫 testbench, 所以也可以将文件夹取名为 testbench 或者 tb 都可以。
主要的文件夹就是这四个,后期的一些项目有可能还会用到 Matlab、IP 核,届时可以再新建一个单独管理 Matlab 文件和 IP 核文件的文件夹,文件数量可以根据自己的需求进行分类管理
9.4 一个完整的设计过程
这一小节不详细讲解语法、代码编写和思想结构,主要目的是测试软件安装激活后能否正常使用以及软件的基本操作步骤,通过第一个例子介绍后面所有设计实例的规范流程和方法
9.4.1 功能简介
拿到一个项目后首先进行项目分析,分析实现的功能是什么、如何进行系统的结构和层次划分、每一部分用什么方法实现
9.4.2 硬件资源
明确工程要实现的功能后,就要了解工程设计的硬件资源。
由原理图可知,征途 Mini 开发板的按键未按下时为高电平、按下后为低电平;LED 灯则为低电平点亮。
9.4.3 新建一个 Visio 文件及其配置
为了画图时更好的对齐,我们可以把“视图”下的“网格”勾选上
9.4.5 波形设计
框图结构和端口信号设计完毕后就需要设计框图结构下模块功能的实现,也就是输入和输出之间怎么样的影响关系。输入和输出满足信号与系统的关系,这种关系是一种时序的、逻辑的关系,即既有时间上的关系又有逻辑上的关系。这种关系不再是结构的关系, 对于这种时序的、逻辑的关系,我们用波形图的方式表达最为清晰直观。因为 FPGA 本身就是并行执行的,当信号较多时,我们仅靠人脑的记忆和联想如此众多信号的并行时序关系的效果可能并不是非常好,所以我们要通过绘制波形图的方法来将这种关系表达出来。
波形画出来后一切时序和逻辑关系就清晰明了,无论是代码实现,还是日后再次拿过来分析代码,只要有波形图作为辅助参照,一切都是如此简单。但是如何根据数据手册、设计要求来绘制波形图,也是我们设计方法中重点,需要跟着本教程长久的练习并加以总结才能够熟练掌握并运用自如。
为了使绘制的波形图更加直观,在绘制波形图前我们先统一定义输入信号用绿色标注,输出信号用红色标注,中间变量信号用黄色标注表示(本章不涉及中间变量,后面章节会有体现),本教程所有波形设计均是按照这个规范作图的,当然如果学习者有自己的颜色喜好也可以自定义配置,只要能够有所区分就可以。绘制波形图时首先要设计完善的测试激励以模拟最接近真实情况的输入信号,然后根据输入信号的波形画出相应的输出信号的波形。在画波形的过程中,你会详细了解到各信号之间的关系,这样先画波形的好处是能够在写代码之前对一些细节的问题做到预先了解,方便后面编写代码和调试时做到胸有成竹,在大型复杂的项目中其优点更为明显,我们还有一个写代码的诀窍,就是如何根据波形图快速的编写出的代码,如果波形图正确,我们编写代码的速度会又快又正确,如果你基本功扎实,画图认真准确,毫不夸张的讲,根据波形图编写完的代码直接就是正确的,几乎不用调试,这在项目开发过程中的效率是相当高的。
9.4.6 新建工程
![notion image](https://bu.dusays.com/2023/09/19/650987ae75f85.png?t=041a4626-c7b1-41fb-9e6b-cac5c09e5277)
![notion image](https://bu.dusays.com/2023/09/19/650987af6fb47.png?t=32a24a13-8a52-48bb-bd29-406ceed2d88f)
![notion image](https://bu.dusays.com/2023/09/19/650987b05e900.png?t=ee07a5cf-c3f0-453f-aacf-e6956471a449)
![notion image](https://bu.dusays.com/2023/09/19/650987b18f9ad.png?t=d4a177dc-0d7b-42dd-a6ba-59d9823a19cd)
9.4.7 RTL 代码的编写
![notion image](https://bu.dusays.com/2023/09/19/650987b2742a3.png?t=d1f22ae4-243f-42fe-9947-4a4c9f9ddd02)
9.4.10 Testbench 的原理
Testbench 是测试脚本,测试谁?当然是测试我们用硬件描述语言(HDL)设计的电路,测试设计电路的整体功能、部分性能是否与预期的目标相符。有些初学者没有养成编写 Testbench 的习惯,总以为这是繁琐的、无用的,或者他们习惯用在线逻辑分析仪器来调试,其实不然,当你在编写大型工程代码的时候,综合一次所用的时间少则十几分钟, 多则几个小时,这种无用时间的消耗是我们所不允许的,在线逻辑分析仪虽然好用但是每修改一次代码我们就看结果就要综合一次,并不能节省时间,而使用 Testbench 做仿真的速度就很快,修改后即可马上看到结果,从而节省了我们大量的开发时间,所以大家务必养成从学习 FPGA 的一开始就编写 Testbench 的好习惯。
编写 Testbench 进行测试的过程如下: 1. 产生模拟激励(输入波形); 2. 将产生的激励加入到被测试模块并观察其输出响应; 3. 将输出响应与期望进行比较,从而判断设计的正确性。
接下来就是仿真激励 Testbench 的编写,首先给大家介绍下 Testbench 的原理。
我们通常给 Testbench 的取名是在被测试的模块名前加个 tb_(也可以在被测试的模块名后面加_tb),容易识别出具体验证的是哪个模块。如图 9-42 所示:蓝色的框中的区域就表示一个测试系统,我们要写的 Testbench 就是用代码实现该区域的功能,这个功能是只针对待测试 led 模块,如果换成其他的模块,需要在单独设计专门针对其他待测试系统的 Testbench。
![notion image](https://bu.dusays.com/2023/09/19/650987b35869f.png?t=6b7144b2-96a7-48b3-b329-a3c7c8c40d90)
9.4.11 Testbench 代码的编写
开始 Testbench 代码的编写
![notion image](https://bu.dusays.com/2023/09/19/650987b456173.png?t=3dd70e14-2d6c-4df1-8718-26013d604801)
9.4.12 仿真设置
首先打开“Assignments”下的“Setting...”,
![notion image](https://bu.dusays.com/2023/09/19/650987b566612.png?t=50d4589c-ed17-4b9f-a472-670d7208d916)
9.4.14 打开 ModelSim 观察波形
因为第一个 led 工程实例相对简单,使用到 ModelSim 中的也是一些基本操作,所以本节只会对 ModelSim 软件的部分功能的使用进行讲解。但后期随着工程实例复杂度的提高,我们将会用到 ModelSim 中更高级的功能
![notion image](https://bu.dusays.com/2023/09/19/650987b666a29.png?t=a2e9ee18-f566-4d8c-8548-6dccdf3cd2bd)
![notion image](https://bu.dusays.com/2023/09/19/650987b764d56.png?t=438af210-ab1c-485d-9198-e41d9232ecfa)
![notion image](https://bu.dusays.com/2023/09/19/650987b85f6a1.png?t=7af96e3e-d7cf-4b9d-b974-8fb46630acfb)
9.4.15 仿真波形分析
我们使用 ModelSim 仿真出来波形后可以直接观察出波形和预期之间的正确性,因为这个项目工程比较简单,只有两个信号,也没有内部信号,也不容易出错,所以可以直接分析得出,但是试想一下,如果有上百个信号,然后最后的输出结果还出现了错误,那你凭着自己的理解和观察就很难进行判断了,所以我们一开始就养成良好的学习习惯,将ModelSim 仿真出来的波形图和之前用根据自己理解用 Visio 画出来的波形图进行对比,既可以发现之前对整体设计的理解错误又能够方便的进行改错。
9.4.16 引脚约束
仿真结束后即验证了代码设计的正确性,也就是说可以进行上板验证了,但是在上板之前还需要进行引脚约束,就是根据硬件原理图确定按键和 led 分别与 FPGA 芯片的哪个引脚对应。由原理图知上板上一共有四个普通按键和四个 led 灯我们选择其中一对按键和led 灯,按键选择连接的 FPGA 管脚为 M2,led 灯选择连接的 FPGA 管脚为 L7。
点击如图 9-80 所示按钮,打开管脚绑定界面
![notion image](https://bu.dusays.com/2023/09/19/650987b954d84.png?t=93ee4c56-217d-4fd2-ab72-18ef55cd7a0e)
![notion image](https://bu.dusays.com/2023/09/19/650987ba46ce9.png?t=3ef41f0d-3ac5-440b-99f1-78dd25fae22a)
9.4.17 全编译
全编译和分析综合的不同是全编译需要进行布局布线,管脚绑定后就可以对全局进行布局布线了。点击如图 9-86 所示的按钮进行全部的分析综合布局布线。
○1 框是综合后的资源使用率报告; ○2 框是综合后提示的错误警告数,这里没有错误,只有警告和严重警告存在,一共 7 个; ○3 框是编译时每一步详细的过程,包括执行每一个部分所使用的具体时间,从上到下顺序执行,第一个是之前进行过的分析与综合,第二个是布局和布线,第三个是生成程序文件,第四个是静态时序分析,第五个是写入网表,这 5 个步骤编译后都是自动完成的不需要进行干涉,如果后期自动完成不能满足需求是需要手动进行设置以实现优化;
○4 框中从左往右依次是错误、严重警告、警告,只要不出现错误就暂时先不用管,当警告或者严重警告影响功能时再去分析; ○5 框是编译的总进度; ○6 框是在编译过程中实时显示的时间,该时间随着工程量对增大而增大,硬件的编译一次的时间是非常慢的,不像软件那样瞬间就完成了,所以这也是需要进行仿真的原因之一。
![notion image](https://bu.dusays.com/2023/09/19/650987bb37229.png?t=90de70bd-aef6-4343-aad7-9829774cd2a0)
9.4.18 通过 JTAG 将网表下载到开发板
开发板连接 5V 直流电源,USB-Blaster 下载器 JTAG 端连接开发板JTAG 接口,另一端连接电脑 USB 接口。线路正确连接后,打开开关为板卡上电。
打开下载界面如图 9-92 所示:○1 框是硬件连接设置,当前显示的是“No Hardware”即 没 有 连 接 到 硬 件 , 我 们 需 要 选 择 连 接 的 硬 件 是 USB-Blaster , 点 击 “ Hardware Setup...”,在弹出的界面中(如图 9-93 所示)的“Currently selected hardware:”选择“USB-Blaster[USB-0]”,然后点击“Close”,此时会发现○1 框处发生变化如图 9-92 所示“Hardware Setup...”处已经变成了“USB-Blaster[USB-0]”;○2 框是选择下载的方式,我们选择“JTAG”下载模式;○3 框是下载的进度表,下载成功后会在框内显示绿色并出现“100%(Successful)”;○4 框是下载的文件,这里是“led.sof”文件。
注意:尽量不要带电插拔 JTAG 口,否则容易烧坏 FPGA 的 JTAG 口。如果用万用表测到 JTAG 号 TDI TDO TMS TCK 任意一个与地短路了,那你的 FPGA 可能已经被烧坏了。并不是每次热插拔 JTAG 口都一定会烧坏,但是至少会有一定烧坏的可能性,为了能让开发板陪伴我们学习完本教程,所以最好谨慎行事!
9.4.19 未使用管脚的默认设置
我们使用的开发板上面有很多功能,在做一个个例子的时候不可能同时全部用上所有的 FPGA 管脚,而在 Quartus 软件中默认未使用管脚的状态为弱上拉输入,所以未使用到的管脚上也是有电压的,只是驱动能力很弱,这往往会导致一些不安全的隐患,所以我们需要将未使用管脚的状态设置为三态输入。具体操作如下: 如图 9-100 所示,鼠标右击“Cyclone IV E: EP4CE10F17C8”选择“Device...”。
我们在“Reserve all unused pins:”框中选择“As input tri-stated”即三态输入,然后点击“OK”完成设置,如图 9-103、图 9-104 所示。在本例中,默认的选择 “As input trstated with week pull-up”是一个安全的选项,除此之外,“As input tri-stated”等也是安全的选项。但是“ As output driving ground ”是一个危险选项,意思是未用到的 FPGA 引脚会被下拉到地。危险在于如果这些引脚在被 PCB 上的外围电路上拉到高电位,则可能会产生一个强烈的灌入电流,可能会烧毁 FPGA 的引脚。因此为了避免经济损失,无论如何请你注意一下这里的选择,不要莫名其妙地把 FPGA 烧坏了。
![notion image](https://bu.dusays.com/2023/09/19/650987bc3bbec.png?t=9050cac9-38d8-4612-b793-57aa0c5b6327)
![notion image](https://bu.dusays.com/2023/09/19/650987bd4d367.png?t=5399d87b-737a-4874-9dc8-26bd58cbac8c)
![notion image](https://bu.dusays.com/2023/09/19/650987be3c412.png?t=eb5b46d2-1c00-4f47-9133-653efd0e82ab)
![notion image](https://bu.dusays.com/2023/09/19/650987bf38100.png?t=8fa92bb7-f058-46d8-b011-73d3817abe3b)
9.4.20 程序的固化
当你把下载网表的上板断电后再重新上电发现之前的功能已经不存在了,也就是说下载后的网表消失了。为什么会这样子呢,很多人不禁问道,其实我们使用的这款 FPGA 芯片是基于 SRAM 的结构,即下载后的网表存储在FPGA 内部的 SRAM 中,我们也知道 SRAM 有掉电易失的特性,这也就是我们为什么掉电后功能就消失的原因。所以我们要想使网表重新上电后仍然存在就需要将网表存储到片外的 flash 中,flash 芯片型号为 WinBond 25Q16,存储容量为 16Mbit(2M 字节),采用 SPI 协议和 FPGA 进行通信,可做为 FPGA 的配置芯片(完全兼容 EPCS16 芯片),以保证FPGA 在重新上电后仍能继续工作。具体操作如下:
![notion image](https://bu.dusays.com/2023/09/19/650987c02bf1b.png?t=2ab61e3f-3697-4406-a05f-146b2e9e91b7)
![notion image](https://bu.dusays.com/2023/09/19/650987c186880.png?t=3e5770ac-3179-4f7d-b52a-a8c878366fc9)
![notion image](https://bu.dusays.com/2023/09/19/650987c28f2da.png?t=b28d87a9-d941-4a3b-a5fe-aa94128ffa96)
![notion image](https://bu.dusays.com/2023/09/19/650987c3a61e0.png?t=21dc8fb7-3bb0-4b32-ae43-39b0d263bb30)
![notion image](https://bu.dusays.com/2023/09/19/650987c4b2712.png?t=78eb7a73-ba34-445e-8e8c-3cd4f4756915)
![notion image](https://bu.dusays.com/2023/09/19/650987c5ae479.png?t=45d223a0-c6d7-4571-9816-6aca07c630f9)
![notion image](https://bu.dusays.com/2023/09/19/650987c6ae6d0.png?t=dcbfbbbd-4ec7-481f-80dd-7d3a91050d2a)
![notion image](https://bu.dusays.com/2023/09/19/650987c7b00ea.png?t=8652b13b-b23d-4537-bc77-240a9ac9fd4b)
![notion image](https://bu.dusays.com/2023/09/19/650987c8b8a5c.png?t=0309f7ad-4581-471a-b779-56c59f1258b2)
![notion image](https://bu.dusays.com/2023/09/19/650987c9a1456.png?t=13e95f2f-b9c8-44b0-9bc5-eb56febb9d5f)
9.5 章末总结
本章通过 led 灯的例子让大家了解了一个完整的 FPGA 开发流程,其中有几个步骤是非常关键的,涉及到 FPGA 的开发方法,如:模块和端口信号划分、波形设计、RTL 代码的编写、Testbench 代码的编写、仿真波形分析。我们会在后面的章节和实例中重点对以上提到的关键步骤做详细的分析。
- Author:非常6+1
- URL:https://matrixcore.top/article/FPGA009
- Copyright:All articles in this blog, except for special statements, adopt BY-NC-SA agreement. Please indicate the source!