本
文
摘
要
1)实验平台:正点原子 DFZU2EG/4EV MPSoC开发板教程
2) 章节摘自【正点原子】DFZU2EG/4EV MPSoC之FPGA开发指南 V1.0
3)购买链接:https://detail.tmall.com/item.htm?id=692450874670
4)全套实验源码+手册+视频下载地址:MPSoC开发板 - 正点原子资料下载中心 1.0.0 文档
5)正点原子官方B站:正点原子官方的个人空间-正点原子官方个人主页-哔哩哔哩视频
6)FPGA技术交流QQ群:994244016
第四章Vivado软件的安装和使用
Vivado Design Suite是Xilinx公司的综合性FPGA开发软件,可以完成从设计输入到硬件配置的完整FPGA设计流程。本章我们将学习如何安装Vivado软件以及Vivado软件的使用方法,为大家在接下来学习实战篇打下基础。
本章包括以下几个部分:
4.1 Vivado软件的安装
4.2 Vivado软件的使用
4.3 在线逻辑分析仪的使用
4.4 在Vivado中进行功能仿真
4.1 Vivado软件的安装
X Xilinx公司每年都会对Vivado设计套件进行更新,各个版本之间除界面以及其它性能的优化之外,基本的使用功能都是一样的,我们光盘中提供的是最新版Vivado 19.2版本,接下来安装Vivado 19.2(以下简称Vivado)版本的软件。
首先在DFZU2EG/4EV MPSoC开发板资料盘(B盘)→Vivado 19.2文件夹下找到Vivado 19.2的安装包文件,文件列表如下图所示:
图 4.1.1 Vivado安装包文件夹将压缩包解压出来(注意,解压目录的路径名称只能够包含字母、数字、下划线,否则安装程序有可能出问题),为避免在安装过程中出错,在开始安装之前,请先关闭安全或杀毒软件。双击解压出来的文件夹下的“xsetup.exe”,开始安装Vivado软件,如下图所示:
图 4.1.2 双击“xsetup.exe”进入Vivado的安装引导页面,如下图所示:
图 4.1.3 Vivado软件的安装引导页面在接下来的页面中,勾选3个“I Agree”,然后点击“next”如下图所示:
图 4.1.4 勾选“I Agree”接下来是选择版次,这里我们选择全功能的版次,即“System Edition”,其包含最多的子组件。如下图所示:
图 4.1.5 选择版次接下来是选择工具组件和器件库。为了节省存储空间,我们将用不到的工具组件和器件库去掉,如下图所示:
图 4.1.6 选择组件和器件库最下面的“Disk Space Required”表示在当前选项下Vivado在安装完成后所占用的磁盘空间大小,为76.42GB。由此可见,Vivado对硬盘存储空间的占用相对来说还是挺大的。
点击Next,进入安装目录设置页面,如下图所示:
图 4.1.7 安装目录设置图中红色方框内是对安装目录的设置,默认安装在C盘下的“Xilinx”文件夹下,如果需要,可以点击后面的三个点来修改安装目录(注意,安装路径只能够包含字母、数字、下划线,否则安装程序有可能出问题)。其他的设置保持默认即可。
点击Next,进入Summary界面,该界面总结了前面所有安装的配置信息,供用户浏览确认。确认无误后,点击“Install”开始安装Vivado设计套件,如下图所示。(由于Vivado在安装期间会占用大量的电脑CPU资源和内存资源,所以笔者建议在开始安装之前,尽量关闭电脑中其他的不必要的应用软件)
图 4.1.8 开始安装之后会出现下面的正在安装界面:
图 4.1.9 正在安装安装过程可能会耗费一些时间,请读者耐心等待。
在安装期间可能会出面如下消息:
图 4.1.10 点击确定即可弹出的这个界面是提示我们断开所有的Xilinx下载器与电脑的连接。值得注意是,在安装Vivado软件的过程中,会安装Xilinx下载器的驱动程序,这里必须断开Xilinx下载器和电脑的连接,否则下载器的驱动可能安装失败。断开连接后,点击确定即可。
最后出现了安装成功的消息窗口,如下图所示:
图 4.1.11 安装成功我们直接点击确定即可。一同弹出的还有“Vivado License Manager”窗口,我们可以选择30天试用期,也可以通过购买Xilinx正版的License等途径来正常使用(请查看安装包目录下“安装说明.txt”)。如下图所示:
图 4.1.12 “Vivado License Manager”窗口至此,Vivado设计套件的安装就成功完成了,我们可以在电脑桌面上看到Vivado2019.2的图标,如下图所示:
图 4.1.13 Vivado 2019.2的桌面图标4.2 Vivado软件的使用
在开始使用Vivado软件之前,我们先来了解一下Vivado软件的使用流程,如下图所示:
图 4.2.1 Vivado软件使用流程从上图可以看出,首先打开Vivado软件,新建一个工程,在新建工程的时候,我们可以通过新建工程向导的方式来创建工程;工程建立完成后,我们需要新建一个Verilog顶层文件,然后我们将设计的代码输入到新建的Verilog顶层文件中;HDL源代码输入完毕之后,就是对设计文件进行分析与综合了。
在代码输入以及设计分析阶段,Vivado软件会检查代码,如果代码出现语法错误,那么Vivado软件将会给出相关 *** 。在FPGA设计中,综合(Synthesis)就是将RTL设计转变为由FPGA器件中的查找表(LUT)、触发器(FF)等各种底层电路单元所组成的网表,在这个过程中综合器也会对设计进行优化,例如,删除多余的逻辑等等。
综合完成后,我们需要进行约束的输入。约束表达了设计者期望满足的时序要求,规范了设计的时序行为,并在综合、实现阶段来指导工具进行布局、布线,工具会按照你的约束尽量去努力实现以满足时序要求,并在时序报告中给出结果。常用的约束包括时序约束、引脚约束等等。
接下来就可以实现整个设计了,包括布局和布线等。如果实现成功,则Vivado会给出提示结果。此时,就可以生成用于下载到器件中的比特流文件了。最后,我们会通过下载器来将这个比特流文件下载到FPGA中,完成整个开发流程。
在这里,我们只是简单的介绍了一下上述的流程图,让大家对Vivado软件的开发流程有个大致的了解。接下来我们就以LED灯闪烁实验的工程为例,对每个流程进行详细的操作演示,一步步、手把手带领大家学习使用Vivado软件。
4.2.1 新建工程
我们直接双击桌面上的Vivado 2019.2软件图标,打开Vivado软件,Vivado软件启动界面如下图所示,我们点击“Create Project来创建一个新的工程”。
图 4.2.2 Vivado软件启动界面出现下图所示窗口,我们直接点击“Next”,如下图所示。
图 4.2.3 新建工程向导接下来输入工程的名称和路径。名称要能反应出工程所实现的功能,本次工程实现了LED闪烁的功能,因此项目名称命名为“led_twinkle”。工程路径是指定本次工程存放在电脑磁盘中的位置,这个大家可以自行选择路径,需要说明的是,工程路径不能包含中文、空格或者其它一些特殊的符号,否则工程会创建失败。工程名和路径的设置如下图所示。
图 4.2.4 输入工程名称和路径注意,由于默认勾选了“Create project subdirectory”选项,Vivado会在所选工程目录下自动创建一个与工程名同名的文件夹,用于存放工程内的各种文件。并且Vivado会自动管理工程文件夹内的各种工程文件,并创建相应的子目录,这为我们的开发工作带来了很大的便捷。
我们继续点击“Next”按钮,接下来是工程类型的选择,我们选择“RTL Project”,如下图所示:
图 4.2.5 工程类型的选择这里简单介绍下各个工程类型的含义。“RTL Project”是指按照正常设计流程所选择的类型,这也是常用的一种类型,“RTL Project”下的“Do not specify sources at this time”用于设置是否在创建工程向导的过程中添加设计文件,如果勾选后,则不创建或者添加设计文件;“Post-synthesis Project”在导入第三方工具所产生的综合后网表时才选择;“I/O Planning Project”一般用于在开始RTL设计之前,创建一个用于早期IO规划和器件开发的空工程;“Imported Project”用于从ISE、XST或Synopsys Synplify导入现有的工程源文件;“Example Project”是指创建一个Vivado提供的工程模板。
选择了“RTL Project”后,我们点击“Next”,进入添加源文件页面。注意,如果勾选中图 4.2.5中“RTL Project”下的“Do not specify sources at this time”,则不会出现添加源文件的界面。
在弹出添加源文件的界面后,可以在此处创建/添加源文件,当然也可以直接点击“Next”,创建完工程后再创建/添加源文件。这里直接点击“Next”,如下图所示:
图 4.2.6 添加源文件接下来是添加约束文件,我们也是直接点击“Next”,创建完工程后再创建/添加约束文件,如下图所示:
图 4.2.7 添加约束文件接下来选择开发板的芯片型号,我们可以直接在搜素框中输入完整的芯片型号,大家根据自己所使用的开发板型号进行选择。如果使用的是XCZU4EV开发板,则输入“xczu4ev-sfvc784-1-i”,如下图所示:
图 4.2.8 MPSoC XCZU4EV开发板芯片型号如果使用的是XCZU2EG开发板,则输入“xczu2eg-sfvc784-2-i”,如下图所示:
图 4.2.9 MPSoC XCZU2EG开发板芯片型号在搜素框中输入完整的芯片型号后,在“Part”一栏会出现唯一匹配的型号,单击选中“Part”一栏的芯片型号,然后点击“Next”按钮。
需要说明的是,本次工程以XCZU4EV开发板为例,接下来的软件截图可能会出现XCZU4EV器件的芯片型号。大家使用XCZU4EV开发板和XCZU2EG开发板除了在创建工程向导选择的芯片型号不一样外,其余操作都是一样的,因此,我们接下来只贴XCZU4EV开发板器件的软件截图。
最后进入工程概览页面,这个页面将之前几个步骤中的设置全部列了出来,供用户检查,选择不同的芯片型号,概览页面列举的芯片型号也不一样,我们直接点击“Finish”按钮完成工程的创建,如图 4.2.10所示。
图 4.2.10 工程概览(Summary)页面工程创建完成后,就进入了Vivado的工程主界面,如下图所示:
图 4.2.11 Vivado工程主界面下面介绍Vivado工程主界面中的几个主要子窗口:
(1)Flow Navigator。Flow Navigator提供对命令和工具的访问,其包含从设计输入到生成比特流的整个过程。 在点击了相应的命令时,整个Vivado工程主界面的各个子窗口可能会作出相应的更改。
(2)数据窗口区域。默认情况下,Vivado IDE的这个区域显示的是设计源文件和数据相关的信息。
• Sources窗口:显示层次结构(Hierarchy)、IP源文件(IP Sources)、库(Libraries)和编译顺序(Compile Order)的视图。
• Netlist窗口:提供分析后的(elaborated)或综合后的(synthesized)逻辑设计的分层视图。
(3)Properties窗口:显示有关所选逻辑对象或器件资源的特性信息。
(4)工作空间(Workspace):工作区显示了具有图形界面的窗口和需要更多屏幕空间的窗口,包括:
• Project Summary。提供了当前工程的摘要信息,它在运行设计命令时动态地更新。
• 用于显示和编辑基于文本的文件和报告的Text Editor。
• 原理图(Schematic)窗口。
• 器件(Device)窗口。
• 封装(Package)窗口。
(5)结果窗口区域:在Vivado IDE中所运行的命令的状态和结果,显示在结果窗口区域中,这是一组子窗口的 *** 。在运行命令、生成消息、创建日志文件和报告文件时,相关信息将显示在此区域。默认情况下,此区域包括以下窗口:
• Tcl Console:允许您输入Tcl命令,并查看以前的命令和输出的历史记录。
• Messages:显示当前设计的所有消息,按进程和严重性分类,包括“Error”、“Critical Warning”、“Warning”等等
• Log:显示由综合、实现和仿真run创建的日志文件。
• Reports:提供对整个设计流程中的活动run所生成的报告的快速访问。
• Designs Runs:管理当前工程的runs。
(6)主工具栏:主工具栏提供了对Vivado IDE中最常用命令的单击访问。
(7)主菜单:主菜单栏提供对Vivado IDE命令的访问。
(8)窗口布局(Layout)选择器:Vivado IDE提供预定义的窗口布局,以方便设计过程中的各种任务。布局选择器使您能够轻松地更改窗口布局。或者,可以使用菜单栏中的“Layout”菜单来更改窗口布局。
4.2.2 设计输入
下面我们就来创建工程顶层文件,我们点击“Sources”窗口中的“+”号,如下图所示:
图 4.2.12 添加源文件按钮弹出下图所示界面,我们选择添加设计源文件(注意,Vivado不支持使用原理图的方式来输入设计),然后点击“Next”按钮,如下图所示。
图 4.2.13 选择添加设计源文件接下来在弹出的页面中添加或者创建一个文件。如果事先有编写好的代码,可以点击“Add Files”按钮来添加文件;如果没有,则点击“Create File”创建一个新的设计文件。由于我们事先没有编写好的设计文件,这里点击“Create File”来创建一个新的设计文件,如下图所示:
图 4.2.14 点击创建源文件接下来会弹出一个对话框,对创建的设计文件进行命名。这里我们输入源文件的名称“led_twinkle”,然后点击“OK”按钮,如下图所示:
图 4.2.15 输入源文件名称这时我们看到列表中已经出现了刚刚新创建的设计文件,点击“Finish”按钮,如下图所示:
图 4.2.16 添加的源文件接下来会弹出一个定义模块的页面,用于设置源文件的模块名称和端口列表,Vivado会根据在此窗口中的设置,自动地在HDL源文件中写入相应的verilog语句。我们会手动输入代码,所以这里不作任何设置,直接点击“OK”按钮即可,如下图所示。
图 4.2.17 定义顶层模块名和模块端口接下来会弹出一个模块定义确认的页面,直接点击“YES”即可,如下图所示:
图 4.2.18 模块定义确认页面这时工程主界面的“Sources”窗口中就出现了我们刚刚创建的源文件,如下图所示:
图 4.2.19 源文件创建完毕我们双击打开“led_twinkle”文件,删除文件中默认的代码,然后替换成LED灯闪烁代码,代码如下:
1 module led_twinkle( 2 input sys_clk_p, //系统差分输入时钟 3 input sys_clk_n, //系统差分输入时钟 4 input sys_rst_n, //系统复位,低电平有效 5 6 output [1:0] led //LED灯 7 ); 8 9 //reg define 10 reg [26:0] cnt; 11 12 //***************************************************** 13 //** main code 14 //***************************************************** 15 16 //对计数器的值进行判断,以输出LED的状态 17 assign led = (cnt < 27d5000_0000) ? 2b01 : 2b10; 18 //assign led = (cnt < 27d5) ? 2b01 : 2b10; //仅用于仿真 19 20 //转换差分信号 21 IBUFDS diff_clock 22 ( 23 .I (sys_clk_p), //系统差分输入时钟 24 .IB(sys_clk__n), //系统差分输入时钟 25 .O (sys_clk) //输出系统时钟 26 ); 27 28 //计数器在0~10000_0000之间进行计数 29 always @ (posedge sys_clk or negedge sys_rst_n) begin 30 if(!sys_rst_n) 31 cnt <= 27d0; 32 else if(cnt < 27d10000_0000) 33 //else if(cnt < 27d10) //仅用于仿真 34 cnt <= cnt + 1b1; 35 else 36 cnt <= 27d0; 37 end 38 39 endmodule这里需要注意的是,源代码前面的序号是为了方便大家查看代码的,在将源代码拷贝到软件编辑区的时候,需要去掉前面的序号,大家也可以直接从我们光盘中提供的源码代码中拷贝,源代码位于资料盘(A盘)下的4_SourceCODE\ MPSoC_XCZU4EV(MPSoC_XCZU2EG)\ 1_FPGA_Design\ 1_led_twinkle\ led_twinkle.srcs\ sources_1\ new\ led_twinkle.v(如果是压缩包的话,需要先解压)。
本章我们只是带领大家熟悉Vivado软件的使用流程,不对代码做讲解,在后面的例程中,再来对代码做详细的介绍。
代码编写完成后,软件中显示的界面如下图所示。
图 4.2.20 Verilog文件编写完成界面另外,如果读者认为Vivado的Text Editor默认的字体比较小,也可以依次点击“Settings”→“Text Editor” →“Fonts and Colors”,在窗口中的“Size”选项中来修改字体大小,默认是12,我们修改为20,如下图所示:
图 4.2.21 修改代码的字体大小接下来我们单击工作空间中的保存按钮或者按下键盘的“Ctrl+S”,来保存编辑完成后的代码,如下图所示:
图 4.2.22 保存源文件按钮每次保存后,Vivado都会对源文件进行部分语法的检查,如果有语法的错误,Vivado会给出提示。另外,在大多数情况下,Vivado IDE会自动识别设计的顶层模块,当然,用户也可以手动指定顶层模块。从“Sources”窗口的右击菜单中选择“Set as Top”来手动定义顶级模块。
4.2.3 分析与综合
代码输入完毕之后,就可以对设计进行分析(Elaborated)了。点击“Flow Navigator”窗口中的“Open Elaborated Design”按钮,如下图所示:
图 4.2.23 “Open Elaborated Design”按钮此时,Vivado会编译RTL源文件并进行全面的语法检查,并在Messages窗口中给出相应的“Error”和“Warning”。如果出现“Error”,则分析失败,用户必须修改设计文件,并重新编译源文件来取消“Error”。如果出现“Warning”,用户也可逐一查看,以确定哪些是设计缺陷,哪些是可以忽略的。打开分析后(Elaborated)的设计,Vivado会生成顶层原理图视图,并在默认view layout中显示设计,如下图所示:
图 4.2.24 打开的Elaborated Design可以看到,此时窗口布局已经发生了变化,新增了Schematic(原理图)、Netlist(网表)等窗口。此时,底部的Messages窗口会显示分析阶段产生的消息,如下图所示:
图 4.2.25 Messages窗口中的消息可以看出,我们LED闪烁实验的代码并没有产生警告或者错误。
此时,我们也可以进行I/O引脚分配,在右上角的窗口布局(Layout)选择器中选择“I/O Planing”,如下图所示:
图 4.2.26 点击“I/O Planing”Layout此时,窗口布局会打开IO相关的子窗口,如下图所示:
图 4.2.27 I/O Planing窗口布局在下方的“I/O Ports”窗口中,就可以进行IO的分配了。这里我们暂时不分配,先对设计进行综合,综合之后再统一输入时序约束和IO引脚的物理约束。
我们关闭分析后的界面。在工作区域的顶部标题栏处,用鼠标右击,在弹出的命令列表中选择“close”,如下图所示:
图 4.2.28 关闭分析后的设计接下来点击“Flow Navigator”窗口中的“Run Synthesis”按钮,来对代码进行综合,如下图所示:
图 4.2.29 “Run Synthesis”按钮在弹出的窗口中我们直接点击OK,如下图所示:
图 4.2.30 Launch Runs窗口这时可以看到在“Design Runs”窗口中显示正在综合,如下图所示:
图 4.2.31 “Design Runs”窗口综合完成后,弹出如下窗口:
图 4.2.32 综合完成我们关闭该窗口。接下来进行约束的输入。
4.2.4 约束输入
首先,我们需要先创建一个约束文件。点击“Sources”窗口中的“+”号,在弹出的窗口选择“Add or create constraints”,点击“NEXT”按钮,如下图所示:
图 4.2.33 添加约束文件在接下来的界面中点击“Create File”创建一个新的约束文件,如下图所示:
图 4.2.34 Create File在弹出的对话框中输入约束文件的名称“led_twinkle”,然后点击“OK”按钮,如下图所示:
图 4.2.35 输入约束文件的名称接下来点击“Finish”按钮,完成约束文件的创建,如下图所示:
图 4.2.36 点击Finish这时我们就可以在“Sources”窗口中看到添加的这个约束文件了,如下图所示:
图 4.2.37 添加完成的约束文件注意,Vivado的约束文件是以“.xdc”为后缀的文本文件,其中存储的是一条条的xdc约束命令。
我们双击打开led_twinkle.xdc文件,开始对工程进行约束。约束一般分为两种,一种是IO管脚的约束,另外一种是对时序进行约束。我们先来看下IO管脚的约束,约束语句如下:
#IO管脚约束 #时钟管脚 set_property IOSTANDARD DIFF_HSTL_I_12 [get_ports sys_clk_p] set_property IOSTANDARD DIFF_HSTL_I_12 [get_ports sys_clk_n] set_property PACKAGE_PIN AE5 [get_ports sys_clk_p] set_property PACKAGE_PIN AF5 [get_ports sys_clk_n] #复位管脚 set_property -dict {PACKAGE_PIN AH11 IOSTANDARD LVCMOS33} [get_ports sys_rst_n] #LED灯 set_property -dict {PACKAGE_PIN AE10 IOSTANDARD LVCMOS33} [get_ports {led[0]}] set_property -dict {PACKAGE_PIN AF10 IOSTANDARD LVCMOS33} [get_ports {led[1]}]第一行以“#”号开头,表示这是一条注释语句,每一条注释也单独占用一行。从第三行开始是有效的约束命令,每一个约束命令单独占用一行,命令的结尾不需要像verilog代码一样,添加分号“;”结束符号。命令的第一个关键字代表该命令的名称,其后的所有字段都是该命令的参数列表。IO管脚约束是对端口的引脚位置和电平标准进行约束,例如3-6行命令是对系统时钟的管脚进行约束,“set_property”是命令的名称;“PACKAGE_PIN AE5”与“PACKAGE_PIN AF5”是引脚位置参数,代表引脚位置分别是AE5与AF5;“[get_ports sys_clk_p]”与“[get_ports sys_clk_n]”代表该约束所要附加的对象是sys_clk_p与sys_clk_n引脚;“IOSTANDARD DIFF_HSTL_I_12”代表该引脚所使用的电平标准是DIFF_HSTL_I_12。
IO管脚约束比较好理解,就是我们的程序所驱动的IO和MPSoC芯片的IO对应起来。而时序约束(Timing Constraints)用来描述设计人员对时序的要求,比如时钟频率,输入输出的延时等,以满足设计的时序要求。约束语句如下:
#时钟周期约束
create_clock -name sys_clk_p -period 10.000 [get_ports sys_clk_p]“create_clock”是该命令的名称,它会创建一个时钟;其后的“-name clk”、“-period 5”、“[get_ports sys_clk_p]”都是该命令的各个参数,分别表示所创建时钟的名称是“sys_clk_p k”、时钟周期是10ns、时钟源是 sys_clk_p端口,一般只对输入的时钟做周期的约束。
对时钟的约束最简单的理解就是,设计者需要告诉EDA工具设计中所使用的时钟的频率是多少;然后工具才能按照所要求的时钟频率去优化布局布线,使设计能够在要求的时钟频率下正常工作。本次实验sys_clk_p的时钟频率为100MHz,周期为10ns,在做约束时可以等于这个值或者略低于这个值,不建议周期设置的太小,否则软件在布局布线时很难满足这个要求。
其实对于比较简单的设计,可以不对工程做时序约束,即使不进行时序约束,也不影响最终的功能。而当设计变得复杂起来,或者输入的时钟频率比较高的时候,如果不添加时序约束,那么就有可能在验证设计结果的时候出现一些意料之外的情况。本次实验我们对进行了时序约束。led_twinkle.xdc文件输入IO管脚约束语句后,点击“保持”的图标或者按下键盘的“Ctrl+S”进行保存。输入IO管脚约束语句后如下图所示:
图 4.2.38 输入IO管脚约束语句点击Text Editor中的保存按钮后,就完成了约束的输入。
另外,为了便于大家的查看,我们整理出了包含开发板上所有引脚分配的表格和XDC约束文件,位于资料盘(A盘)\3_正点原子DFZU2EG/4EV MPSoC开发板原理图文件夹下。
4.2.5 设计实现
约束输入完毕之后,就可以开始实现设计了。我们点击“Flow Navigator”窗口中的“Run Implementation”按钮,如下图所示:
图 4.2.39 点击“Run Implementation”按钮在弹出的界面中直接点击OK即可,如下图所示:
图 4.2.40 开始实现这时可以看到“Design Runs”窗口中显示正在进行实现,如下图所示:
图 4.2.41 正在实现实现完成后会弹出提示窗口,我们直接点击取消来关闭窗口,如下图所示:
图 4.2.42 实现完成这时我们再次查看“Design Runs”窗口中的实现结果,如下图所示:
图 4.2.43 实现结果4.2.6 下载比特流
在下载程序之前,首先要先生成用于下载到器件中的比特流文件,该文件的后缀为“.bit”。我们点击“Flow Navigator”窗口中的“Generate Bitstream”按钮,如下图所示:
图 4.2.44 “Generate Bitstream”按钮在弹出的窗口中直接点击OK,如下图所示:
图 4.2.45 开始生成比特流此时我们可以看到在“Design Runs”窗口中显示正在生成比特流,如下图所示:
图 4.2.46 正在生成比特流比特流生成完毕之后,Vivado会弹出提示窗口,我们点击取消关闭该窗口:
图 4.2.47 比特流生成完毕接下来我们开始下载比特流,点击“Flow Navigator”窗口中的“Open Hardware Manager”按钮,如下图所示:
图 4.2.48 “Open Hardware Manager”按钮接着Vivado就会打开Hardware Manager,同时窗口布局也跟着发生了变化,如下图所示:
图 4.2.49 Hardware Manager窗口布局接下来我们就要用到开发板和Xilinx下载器了。首先将Xilinx下载器一端连接电脑,另一端与开发板上的JTAG接口相连接,然后连接开发板电源线。
注意!一定要先把下载器的一端连接到了电脑、另一端连接了JTAG接口之后,再给开发板上电!否则,对开发板的JTAG接口进行带电热 *** ,有一定概率会损坏JTAG接口!
最后将开发板的电源拨码开关按键按照下图往电源指示灯的方向拨动对开发板进行上电,上电成功后开发板的电源指示灯会亮蓝灯。DFZU2EG/4EV MPSoC开发板的实物连接如下图所示:
图 4.2.50 DFZU2EG/4EV MPSoC开发板连接实物图开发板连接完成后,点击“Hardware”子窗口中的“Auto Connect”按钮,如下图所示:
图 4.2.51 “Auto Connect”按钮在“Hardware”子窗口中出现如下界面就表示Vivado就已经和下载器连接成功了,如下图所示:
图 4.2.52 与下载器连接成功我们点击上图中的“Program Device”,弹出的界面如下图所示:
图 4.2.53 下载比特流界面此时Bitstream File一栏会自动识别到工程的比特流文件,我们直接点击“Program”按钮下载程序,程序下载完成后,我们可以看到位于开发板上的LED灯在不断地闪烁了,如下图所示:
图 4.2.54 两个PL LED灯交替闪烁需要说明的是,下载完比特流后,如果开发板断电,程序会丢失。如果想要程序断电不丢失的话,需要将程序固化至开发板中,这个需要在嵌入式Vitis软件中完成,MPSoC芯片无法单独固化比特流文件(PL的配置文件)。这是由于MPSoC非易失性存储器的引脚(如SD卡、QSPI Flash)是MPSoC PS部分的专用引脚,这些非易失性存储器由PS的ARM处理器进行驱动,需要将bit流文件和elf文件(软件程序的下载文件)合成一个BOOT.BIN,才能进行固化,因此需要学习MPSoC嵌入式Vitis的开发流程。在《DFZU2EG/4EV MPSoC开发板之嵌入式开发指南.pdf》文档中“第七章 程序固化实验”,会有一个单独的章节向大家介绍程序固化的方法。
4.3 在线逻辑分析仪的使用
传统的FPGA板级调试是由外接的逻辑分析仪连接到FPGA的控制管脚,然后将内部信号引出至引脚IO上,进行板级调试。这种方法的缺点是首先我们需要一个逻辑分析仪,而逻辑分析仪一般价格都比较昂贵,且对于需要测试几十个引脚的时候,选择使用外接的逻辑分析仪就比较繁琐了。在线逻辑分析仪克服了以上所有的缺点,其借用了传统逻辑分析仪的理念以及大部分的功能,并利用FPGA中的逻辑资源,将这些功能植入到FPGA的设计当中。一般地,在线逻辑分析仪的应用原理框图如下图所示:
图 4.3.1 在线逻辑分析仪的应用原理框图其中,待测设计(Design Under Test,DUT)就是用户逻辑,它和片内的在线逻辑分析仪都位于FPGA中。在线逻辑分析仪通过一个或多个探针(Probe)来采集希望观察的信号,然后通过片内的JTAG硬核组件,来将捕获到的数据传送给下载器,进而上传到Vivado IDE以供用户查看。Vivado IDE也能够按照上述数据路径,反向地向FPGA中的在线逻辑分析仪传送一些控制信息。由此可见,在线逻辑分析仪不需要将待测信号引出至I/O上,也不需要电路板走线或者探测点,当然更不需要外部的逻辑分析仪的花费,在Vivado中就可以将在线逻辑分析仪添加到设计中。但是,在线逻辑分析仪会占用一定数量的内部逻辑资源,如块RAM、查找表、触发器等等。
在Vivado中,在线逻辑分析仪的功能被称为“集成逻辑分析器(Integrated Logic Analyzer,ILA)”,它以IP核的形式来加入到用户设计中。Vivado提供了三种具有不同集成层次的插入ILA方法,以满足不同Vivado用户群的不同需求:
第一种方法是直接在HDL代码中例化一个ILA IP核,也被称为“HDL实例化调试探针流程”,这是集成层次最高的方法。ILA IP核可以在IP Catalog(IP目录)中找到,并对其进行配置,以符合所需的调试需求。这是最直接的方法,但其灵活性也较差。在调试工作完毕之后,还需要在HDL源代码中删除ILA IP核,然后重新综合并实现,以生成最终的比特流。
第二种方法是在综合后的网表中,分别标记要进行调试观察的各个信号,然后通过一个简单的“Setup Debug”向导来设置各个探针和ILA IP核的工作参数,然后工具会根据用户设置的参数,自动地生成各个ILA IP核。这个方法也被称为“网表插入调试探针流程”。在此流程中,用户不需要修改HDL源代码,并且能够单独控制每个ILA IP核以及每个探针,这样就提供了很大的灵活性。用户设置的调试信息会以Tcl XDC调试命令的形式保存到XDC约束文件中,在实现阶段,Vivado会读取这些XDC调试命令,并在布局布线时加入这些ILA IP核。在调试工作完毕之后,用户就可以在综合后的网表中删除ILA IP核,或者在XDC文件中删除调试命令,然后再对设计进行实现,以生成最终的比特流。
第三种方法是手动地在XDC约束文件中书写对应的Tcl XDC调试命令,在实现阶段工具会自动读取这些命令,并在布局布线时加入这些ILA IP核。在调试工作完毕之后,用户还需要在XDC约束文件中删除这些命令,然后实现最终的设计。这种方法集成层次最低,一般不会使用这种方法。
本小节同样以LED灯闪烁实验的工程为例,介绍前两种ILA调试流程,即“HDL实例化调试探针流程”和“网表插入调试探针流程”。
4.3.1 HDL实例化调试探针流程
“HDL实例化调试探针流程”需要在HDL源代码中实例化ILA IP核。我们点击“Flow Navigator”窗口中的“IP Catalog”按钮,如下图所示:
图 4.3.2 “IP Catalog”按钮这时“IP Catalog”窗口就被打开了,如下图所示:
图 4.3.3 “IP Catalog”窗口我们在搜索栏中输入“ILA”,这时Vivado会自动根据关键词搜索出相应的结果,我们双击“ILA(Integrated Logic Analyzer)”,如下图所示:
图 4.3.4 搜索ILA接下来会弹出“ILA IP”核的配置页面,如下图所示:
图 4.3.5 “Customize IP”窗口“Component Name”一栏用于设置ILA IP核的名称。
IP核的配置包含两个子页面,分别是“General Options”和“Probe_Ports(0..0)”, “General Options” 页面用于设置ILA IP核的总体设置,“Probe_Ports(0..0)”页面用于对每个探针的参数进行设置。
在“General Options”页面中,“Number of Probes”一栏用于设置所需的探针数量,一般地,一个探针用于连接一个待测信号,例如,我们想要观察“sys_rst_n”、“led”和“cnt”这三个信号,则需要把“Number of Probes”设置为3;
“Sample Data Depth”用于设置采样深度,在每个采样时钟下,ILA都会将捕获到的探针信号的值送入RAM中,由于RAM的存储空间是有限的,所以此选项就用于设置RAM最大存储多少个探针信号的值,我们保持其默认1024,其数值越大,消耗的RAM资源也越多。其它选项保持默认即可。
在“Probe_Ports(0..0)”页面中,用于设置每个探针的参数,一般我们只需设置探针宽度“Probe Width [1..4096]”一栏即可,由于“sys_rst_n”、“led”和“cnt”这三个信号的位宽分别是1位、2位和27位,所以我们需要将其分别设置为1、2和27,然后点击“OK”按钮即可,如下图所示:
图 4.3.6 设置探针宽度在弹出的对话框中直接点击OK即可,如下图所示:
图 4.3.7 点击OK接下来就会弹出“Generate Output Products”对话框,我们保持默认设置,直接点击“Generate”即可,此时Vivado就开始对该ILA IP核进行OOC综合了。如下图所示:
图 4.3.8 开始为ILA IP核生成输出文件在这里,我们简要介绍一下Vivado的OOC(Out-of-Context)综合的概念。对于顶层设计,Vivado使用自顶向下的全局(Global)综合方式,将顶层之下的所有逻辑模块都进行综合,但是设置为OOC方式的模块除外,它们独立于顶层设计而单独综合。通常,在整个设计周期中,顶层设计会被多次修改并综合。但有些子模块在创建完毕之后不会因为顶层设计的修改而被修改,如IP,它们被设置为OOC综合方式。OOC模块只会在综合顶层之前被综合一次,这样在顶层的设计迭代过程中,OOC模块就不必跟随顶层模块,而一次次的产生相同结果的多余综合了。所以,OOC流程减少了设计的周期,并消除了设计迭代,使您可以保存和重用综合结果。
Out-of-Context(OOC) 综合是一种自底向上的设计流程,默认情况下,Vivado设计套件使用OOC的设计流程来综合OOC模块。OOC模块可以是来自IP Catalog的IP、来自Vivado IP Integrator的block design或者顶层模块下手动设置为OOC方式的任何子模块。
来自IP Catalog的IP就默认使用OOC的综合方式,例如上图中的“Synthesis Options”选项就设置为了“Out of Context Per IP”。这些IP会在顶层的全局综合之前,单独地进行OOC综合并生成输出产品(Generate Output Products),包括综合后的网表等各种文件。在对顶层进行综合时,OOC模块会被视为黑盒子,并且不会参与到顶层的综合中来。在综合之后的实现过程中,OOC模块的黑盒子才会被打开,这时其网表才是可见的,并参与到全局设计的实现过程中来。
介绍完了OOC综合的概念,现在我们回到ILA的调试流程中。在“Design Runs”窗口中可以看到Vivado正在为ILA IP核运行OOC综合,如下图所示:
图 4.3.9 ILA IP核正在进行OOC综合OOC综合完毕之后如下图所示:
图 4.3.10 OOC综合完毕这时可以在“Source”窗口中看到已经出现了ILA IP核,如下图所示:
图 4.3.11 添加的ILA IP核由于我们还没有把它例化到顶层的HDL代码中,所以在层次结构上它与顶层并排。下面我们将其例化到顶层的HDL代码中。在“Source”窗口中的“IP Sources”选项卡中双击ILA IP核的例化模板文本文件,找到例化模板的内容,如下图所示:
图 4.3.12 例化模板将图中的红色方框中的模板代码复制并粘贴到led_twinkle.v顶层HDL代码中,并将ILA的时钟和探针信号连接到顶层设计中,例化ILA IP核的代码如下:
ila_0 u_ila_0 ( .clk(sys_clk), // input wire clk .probe0(sys_rst_n), // input wire [0:0] probe0 .probe1(led), // input wire [1:0] probe1 .probe2(cnt) // input wire [26:0] probe2 );我们将ILA的时钟连接到了顶层时钟sys_clk信号上,probe0探针连接到了sys_rst_n,probe1探针连接到了led,probe2探针连接到了cnt。代码修改完成后如下图所示:
图 4.3.13 例化ILA IP核保存源文件之后就可以直接综合并实现设计,最后生成比特流。
至此,我们就成功地使用“HDL实例化调试探针流程”将ILA IP核添加到了设计中。接下来就可以将比特流下载到FPGA中,并对信号进行在线观察。
4.3.2 Hardware Manager中观察调试信号
生成比特流之后,我们打开Hardware Manager,连接到开发板,并下载比特流,如下图所示:
图 4.3.14 下载比特流在弹出的窗口中,Vivado会自动识别比特流文件和具有调试探针信息的.ltx文件,如下图所示:
图 4.3.15 下载比特流和调试文件.ltx文件存储了调试探针的信息,用来传递给Vivado IDE,它是从我们的设计中被提取出来的。通常,调试探测文件是在实现过程中自动创建的,并位于和比特流文件相同的目录下。若实现后的设计中包含了ILA IP核,则在下载比特流时,Vivado会自动识别出.ltx文件。这里我们不必太多地关注此文件,只要按照Vivado自动的设定来下载设计即可。
我们直接点击“Program”,此时Vivado会自动打开ILA的调试窗口,如下图所示:
图 4.3.16 ILA的调试窗口如果Waveform窗口中显示的信号不全,可以点击“Waveform – hw_ila_1”窗口中的加号,来将所有的探针信号添加到波形窗口中(如果默认已经显示所有待观察的信号,不用重复添加),如下图所示:
图 4.3.17 向波形窗口中添加探针信号我们直接点击触发采集信号的按钮,可以观察到此时信号的波形,如图 4.3.18和图 4.3.19所示:
图 4.3.18 点击运行触发的图标图 4.3.19 采集到的信号采集到信号后,可以点击上图中的放大和缩小的图标,来对波形数据进行放大和缩小。
波形默认以十六进制显示的,可以右击cnt计数器,选择“Radix”→“Unsigned Decimal”,即可切换到无符号的十进制显示,如下图所示:
图 4.3.20 更改成无符号十进制显示下面开始触发条件的设置,在这里简要介绍一个触发的概念。前面我们介绍过,ILA会将所采集到的探针数据存放在RAM中,然后通过JTAG和下载器上传到Vivado。那么触发就是决定ILA会在什么时候将RAM中的探针值数据上传到Vivado,当ILA检测到触发条件得到满足时,就会把RAM中的探针值数据上载到Vivado,然后Vivado将探针数据的波形显示出来。
我们在“Trigger Setup”窗口中添加触发条件,点击“+”号,将cnt信号添加进来,如下图所示:
图 4.3.21 添加counter信号到“Trigger Setup窗口中来之前我们在HDL代码中设置为了cnt计数器每计数到27d5000_0000和27d10000_0000时就改变两个led的状态,为了方便led翻转状态的查看,我们可以将触发条件设置为“cnt等于十进制数50_000_000”,即,当ILA检测到cnt计数器的值等于27d5000_0000时,就会将RAM中的数据上传到Vivado,如下图所示:
图 4.3.22 设置触发条件然后我们就可以开始进行触发动作了。在波形窗口中有4个触发动作,如下图所示:
图 4.3.23 触发动作从左至右依次是:(1)自动触发开关、(2)开始触发、(3)立即触发、(4)停止触发。下面对他们分别进行介绍:
(1)自动触发开关,它和“开始触发”按钮联合在一起使用。若打开了此选项,则在ILA开始运行触发(即点击了“开始触发”按钮)后,会不断地对触发条件进行检测,每次触发条件被满足时(即cnt计数到了50_000_000),都会将RAM中存储的所有的探针值数据上传到Vivado,Vivado上显示的波形也会随之不断更新,直到用户点击了“停止触发”按钮。若没有点击此选项,则在ILA开始运行触发(即点击了“开始触发”按钮)后,在检测到触发条件得到满足并完成了上传数据之后,就会停止触发,等待用户下一步的指令。
(2)开始触发,它和“自动触发开关”按钮联合在一起使用。点击之后ILA就会开始进行触发操作。
(3)立即触发,立即将当前ILA RAM中的数据上传到Vivado,而不管触发条件是否得到满足。
(4)停止触发,停止当前正在进行的触发活动。
我们这里直接点击“开始触发”按钮,而不打开“自动触发”开关。然后由于cnt计数器每隔500ms就会计数到50_000_000,所以我们几乎马上就可以看到波形窗口中出现了波形,如下图所示:
图 4.3.24 更新的波形将波形放大之后就可以看到counter的具体值,如下图所示:
图 4.3.25 将波形放大此时就可以看到,在当cnt计数到50_000_000时,led的状态就会发生跳变。读者也可以尝试再次点击“开始触发”按钮或打开“自动触发”按钮,来观察波形。
如果调试工作完毕之后,可以在led_twinkle.v源代码中删除对ILA IP核的例化,或者通过添加“/*”和“*/”注释掉这段代码,如下图所示:
图 4.3.26 注释掉对ILA IP核的例化然后重新综合并实现,以生成最终的比特流。
4.3.3 网表插入调试探针流程
网表插入调试探针有两种操作方式:
第一种方法是在综合之前在HDL代码中为想要观察的reg或wire信号添加“Mark Debug”综合属性,例如:
(* mark_debug = “true” *)reg [26:0] cnt ;
其中“(* mark_debug = “true” *)”必须紧挨在变量声明的前面。这样,在综合完成之后并打开综合后的设计时,cnt信号就自动被标记了“Mark Debug”属性。此外,被添加了(* mark_debug = “true” *)属性的reg或wire信号不会被工具优化掉。
在HDL代码中添加(* mark_debug = “true” *)综合属性,如下图所示:
图 4.3.27 在HDL代码中添加“Mark Debug”综合属性添加“Make Debug”属性之后,点击“Run Synthesis”进行综合,综合完之后我们点击“Flow Navigator”窗口中的“Open Synthesized Design”按钮,如下图所示:
图 4.3.28 点击“Open Synthesized Design”按钮然后点击“Open Synthesized Design”下的“Schematic”,进入如下图所示的页面。在HDL代码中已经添加了“Mark Debug”综合属性的信号会被自动出现在“Debug Nets”选项卡的“Unassigned Debug Nets”目录下,如下图所示:
图 4.3.29 “Debug”窗口布局接下来就可以进行ILA IP核的配置了。点击“Debug”子窗口中的“Setup Debug”按钮,如下图所示:
图 4.3.30 “Setup Debug”按钮弹出“Setup Debug”向导,我们直接点击“Next”按钮,如下图所示:
图 4.3.31 “Setup Debug”向导接下来的页面是选择用于采样待测信号的时钟域,Vivado会自动识别出各个待测信号所属的时钟域并将其自动设定为其采样时钟,本次添加的三个信号属于系统时钟(sys_clk)的时钟域,Vivado也已经自动将“sys_clk_IBUF”时钟设置为了这两个信号的采样时钟,如下图所示:
图 4.3.32 选择待测信号的时钟域当然,用户也可以手动指定各个用于采样待测信号的时钟域,右击待测信号,选择“Select Clock Domain”,弹出“Select Clock Domain”窗口,如图 4.3.33和图 4.3.34所示:
图 4.3.33 手动指定待测信号的时钟域1图 4.3.34 手动指定待测信号的时钟域2在图 4.3.33中“Select Clock Domain”窗口中就可以选择用于采样待测信号的时钟了。“Setup Debug”向导会为每个采样时钟生成一个单独的ILA IP核,由于本例程中只有一个时钟,所以这里最后只会生成一个ILA IP核。
设置完采样时钟后,我们点击next,接下来的页面用于设置ILA IP核的全局设置,如下图所示:
图 4.3.35 ILA IP核的全局设置其中“Sample of data depth”用于设置采样深度,“Input pipe stages”用于设置待测信号和其采样时钟之间的同步级数。如果在上一个设置时钟域页面中,存在与其采样时钟之间是异步的待测信号,则为了避免亚稳态,此数值最好不要低于2。由于本例中的两个待测信号的其采样时钟是同步的,所以可以设置为0。
我们点击next,就进入了最后的概览页面,确认无误后直接点击“Finish”按钮即可,如下图所示:
图 4.3.36 完成“Setup Debug”向导在“Debug”子窗口中的“Debug Cores”选项卡中,可以看到Vivado已经添加了ILA IP核,并且“Unassigned Debug Nets”目录下已经没有未被分配的信号了,如下图所示:
图 4.3.37 添加了ILA IP核的“Debug”子窗口网表中被标记为Mark Debug的信号也变为了虚线,以表示其完成了ILA IP核的分配,如下图所示:
图 4.3.38 网表中完成Setup Debug的信号前面我们提到过,在“网表插入调试探针流程”中,用户设置的调试信息最终会以Tcl XDC调试命令的形式保存到XDC约束文件中。在实现阶段,Vivado会从XDC约束文件中读取这些XDC调试命令,并在布局布线时加入这些ILA IP核。此时,我们所做出的所有的更改和设置,都还只是停留在电脑内存中,我们需要将其保存在硬盘的XDC约束文件中,以供Vivado在实现阶段读取。点击工具栏中的保存按钮,如下图所示:
图 4.3.39 保存按钮在出现的消息框中直接点击OK,如下图所示:
图 4.3.40 点击OK如果弹出“Save Constraints”对话框,询问用户将约束保存在哪个XDC约束文件中,本例的工程中只有一个XDC约束文件,选择“Select an existing file”,位于led_twinkle.xdc文件下,然后点击“OK”按钮即可(有时候也有可能没有弹出这个对话框)。
此时,我们打开led_twinkle.xdc文件,就会看如下图所示:
图 4.3.41 将要更新的约束文件在上图中点击箭头指示的“Reload”更新约束文件,更新后Vivado自动写入了用于debug的约束命令,如下图所示:
图 4.3.42 Vivado自动写入的用于debug的约束在实现阶段,Vivado会读取这些约束,并按照这些命令的参数来自动地加入ILA IP核。
至此,我们就成功地使用“网表插入调试探针流程”将ILA IP核添加到了设计中。接下来就可以实现设计并生成比特流,最后将比特流下载到FPGA中,以对信号进行在线观察。
对信号在线观察的方法请参考“4.3.2 Hardware Manager中观察调试信号”一节,操作方法和“HDL 实例化调试探针”的观察波形信号一样,没有任何区别。
如果调试工作完毕之后,可以删除led_twinkle.v源代码信号中的“Make Debug”属性和删除XDC文件中的包含调试信息的Tcl文件,然后重新综合并实现,以生成最终的比特流。至此,在线逻辑分析仪的使用介绍完毕。
网表插入调试探针的第二种方法是需要在综合后的网表中,将要进行调试观察的各个信号标记“mark_debug”属性,即在综合之后的网表中手动选择网络并点击“mark_debug”按钮然后通过“Setup Debug”向导来设置ILA IP核的参数,最后工具会根据参数来自动创建ILA IP核。操作步骤如下:
点击“Run Synthesis”进行综合,综合完之后我们点击“Flow Navigator”窗口中的“Open Synthesized Design”按钮,如下图所示:
图 4.3.43 点击“Open Synthesized Design”按钮在综合后设计的窗口布局选择器中,我们选择“Debug”窗口布局,如下图所示:
图 4.3.44 切换到“Debug”窗口布局此时,Vivado打开了“Netlist”子窗口、“Schematic”子窗口以及“Debug”子窗口。其中,“Netlist”子窗口和“Schematic”子窗口都可以用于标记要进行观察的信号,“Debug”子窗口用于显示并设置ILA IP核的各个参数。如下图所示:
图 4.3.45 “Debug”窗口布局在“Debug”子窗口中,又包含两个选项卡“Debug Cores”和“Debug Nets”,在上图红色箭头指示处。这两个选项卡都用于显示所有的已标记为“Mark_Debug”的信号。不同之处在于,“Debug Cores”选项卡是一个更加以ILA IP核为中心的视图,所有已标记为“Mark_Debug”的信号并且已经被分配到ILA探针的信号都会被显示在各个ILA IP核的视图树下,已标记为“Mark_Debug”的信号但是还没有被分配到ILA探针的信号被显示在“Unassigned Debug Nets”下,当然也可以在其中查看和设置ILA IP核的各种属性和参数。“Debug Nets”选项卡仅显示已标记为“Mark_Debug”的信号,但不显示ILA IP核,所有已标记为“Mark_Debug”的信号并且已经被分配到ILA探针的信号都会被显示在“Assigned Debug Nets”下,已标记为“Mark_Debug”的信号但是还没有被分配到ILA探针的信号被显示在“Unassigned Debug Nets”下。
在综合后的网表中手动为信号添加mark_debug属性
首先需要标记要进行观察的信号。在综合后的网表中,信号的名称可能会发生一定的变化,以led信号为例,在“Netlist”子窗口中的“Nets”目录下,找到“led_OBUF[0]”网络,右击该网络(此时右边的“Schematic”子窗口也会自动地高亮选择此网络,因为“Netlist”子窗口中的对象和“Schematic”子窗口中的对象,两者之间是交叉选择的),在弹出的菜单中心选择“Mark Debug”命令,如下图所示:
图 4.3.46 在“Netlist”子窗口中点击“Mark debug”命令也可以在“Schematic”子窗口中选择网络,然后右键选择“Mark Debug”命令,如下图所示:
图 4.3.47 在“Schematic”子窗口中点击“Mark debug”命令此时在“Debug”子窗口的“Debug Nets”选项卡的“Unassigned Debug Nets”目录下就会出现我们刚刚标记的“led_OBUF[0]”网络。,如下图所示:
图 4.3.48 Unassigned Debug Nets信号按照上面的操作一次添加需要观察的信号,完成后如下图所示,不过在添加信号的过程中我们会发现一些信号被工具优化掉了,例如“cnt”信号,所以在平时使用逻辑分析仪在线调试时不推荐使用这种手动选择网络并点击“mark_debug”按钮然后通过“Setup Debug”向导来设置ILA IP核的参数的办法。
从通过“Setup Debug”向导来设置ILA IP核的参数这里开始往后的操作步骤与图 4.3.30后面所有的操作是一致的,可以完全参考上面的资料。
4.4 在Vivado中进行功能仿真
在进行功能仿真之前,我们先看一下典型的FPGA设计流程,流程图如下:
图 4.4.1 FPGA的设计流程从上图可以看到,在设计输入之后、设计综合之前进行RTL级仿真,称为综合前仿真,也称为前仿真或功能仿真。前仿真也就是纯粹的功能仿真,主旨在于验证电路的功能是否符合设计要求,其特点是不考虑电路门延迟与线延迟。在完成一个设计的代码编写工作之后,可以直接对代码进行仿真,检测源代码是否符合功能要求。这时,仿真的对象为HDL代码,可以比较直观的观察波形的变化,在设计的最初阶段发现问题,节省大量的精力。
在布局布线后进行的仿真称为布局布线后仿真,也称为后仿真或时序仿真。时序仿真真实地反映了逻辑的时延与功能,综合考虑电路的路径延迟与门延迟的影响,验证电路能否在一定时序条件下满足设计构想的过程,是否存在时序违规。
Vivado设计套件内部集成了仿真器Vivado Simulator,能够在设计流程的不同阶段运行设计的功能仿真和时序仿真,结果可以在Vivado IDE集成的波形查看器中显示。Vivado还支持与诸如ModelSim、Verilog Compiler Simulator (VCS)、Questa Advanced Simulator等第三方仿真器的联合仿真。
功能仿真需要的文件:
1.设计HDL源代码,也被称为UUT(Unit Under Test):可以是VHDL语言或Verilog语言,既可以是设计的顶层模块,也可以是设计的下层子模块。
2.测试激励代码,也被称为TestBench:根据UUT顶层输入/输出接口的设计要求,来产生顶层输入接口的测试激励并监视顶层输出接口。由于不需要进行综合,书写具有很大的灵活性。
TestBench和UUT之间的关系如下图所示:
图 4.4.2 TestBench和UUT之间的关系3.仿真模型/库:根据设计内调用的器件供应商提供的模块而定,如:FIFO、ADD_SUB等。在使用Vivado Simulator时,仿真器所需的仿真模型/库是预编译好并集成在Vivado中的,因此不需要进行额外的预编译操作,直接加载HDL设计和TestBench即可执行仿真。
接下来我们开始在Vivado IDE中进行仿真,首先需要创建一个TestBench。我们点击“Sources”窗口中的“+”号(Add Sources命令),在弹出的窗口中选择“Add or Create Simulation Sources”,如图 4.4.3和图 4.4.4所示:
图 4.4.3 点击“Add Sources”图 4.4.4 选择添加仿真源文件点击“NEXT”按钮,在接下来的页面中点击“Create File”,如下图所示:
图 4.4.5 点击“Create File”在弹出的对话框中输入TestBench的文件名“tb_led_twinkle”,并点击“OK”按钮,如下图所示:
图 4.4.6 输入TestBench的文件名TestBench源文件名称的前缀“tb_”可以用来向用户示意:该源文件是一个TestBench源文件,仅用于仿真,并不能用于设计的综合和实现。建议大家按照这种规范来创建TestBench,以免设计源文件和仿真源文件相混淆。
接下来直接点击“Finish”按钮,如下图所示:
图 4.4.7 点击“Finish”按钮在弹出的自动定义模块窗口中我们直接点击“OK”按钮即可,结束TestBench源文件端口的定义,如下图所示:
图 4.4.8 结束TestBench的创建紧接着会弹出一个模块定义的确认按钮,点击“YES”按钮即可,如下图所示:
图 4.4.9 模块定义确认按钮此时我们就可以在Source窗口→Simulation Sources→sim_1下找到tb_led_twinkle.v文件,这个文件就是刚刚创建的TestBenc *** 件,双击打开后发现其模块内部只定义了模块名,如下图所示:
图 4.4.10 打开TestBenc *** 件我们删除tb_led_twinkle.v文件中默认的代码,然后替换成LED灯闪烁的TestBench(激励)代码,代码如下:
1 `timescale 1ns / 1ps 2 3 module tb_led_twinkle(); 4 5 //输入 6 reg sys_clk_p; 7 reg sys_clk_n; 8 reg sys_rst_n; 9 10 //输出 11 wire [1:0] led; 12 13 //信号初始化 14 initial begin 15 sys_clk_p = 1b0; 16 sys_clk_n = 1b1; 17 sys_rst_n = 1b0; 18 #200 19 sys_rst_n = 1b1; 20 end 21 22 //生成时钟 23 always #5 sys_clk_p = ~ sys_clk_p; 24 always #5 sys_clk_n = ~ sys_clk_n; 25 26 //例化待测设计 27 led_twinkle u_led_twinkle( 28 .sys_clk_p (sys_clk_p), 29 .sys_clk_n (sys_clk_n), 30 .sys_rst_n (sys_rst_n), 31 .led (led) 32 ); 33 34 endmodule编写完成后,单击保存按钮来保存TestBench。
为了让读者能够更好的理解,这里我们就简单介绍一下TestBench源代码。仿真代码首先要规定时间单位和精度,我们建议大家最好在Testbench里面统一规定时间单位,不要在工程代码里定义,因为不同的模块如果时间单位不同可能会为仿真带来一些问题。代码的第1行timescale是Verilog语法中的不可综合的语法,用于定义仿真文件中的单位,表示仿真的时间单位为1ns,精度为1ps,这是赛灵思官方推荐的仿真时间单位和精度。代码的第3行就是TestBench的模块名定义,其中第5行至第11行是我们的数据类型定义, 第13~19行是信号的初始化,第22-24行用于生成时钟信号,到了第26-32行是对被测模块(led_twinkle)的例化。
在开始仿真之前,有一点需要注意,我们在Vivado软件中实现的功能是LED闪烁效果,它的间隔时间是500ms,如果我们想要仿真这个功能,那么我们仿真软件运行时间最低就是500ms。这500ms在我们看来是很短的,而对仿真软件来说是很漫长的,毕竟我们的仿真时间单位可是1ns。为了便于我们仿真,这里我们需要稍微改动一下“led_twinkle.v”文件的代码,将计时器cnt的最大计时值设为10,如下图所示:
图 4.4.11修改源文件这里,我们通过双斜杠“//”将源代码注释掉,并将源代码复制一份放到源代码的后面,并修改计数器的值。待仿真结束后进行分析和综合时,再将标记为“仅用于仿真的”的语句注释掉或者直接删除。
在“Flow Navigator”窗口中点击“Run Simulation”并选择“Run Behavioral Simulation”,如下图所示:
图 4.4.12 Run Simulation命令之后我们就进入了仿真界面,如下图所示:
图 4.4.13 仿真界面下面分别介绍仿真界面中的各个子窗口:
(1)Scope窗口。Scope(范围)是HDL设计的层次划分。在Scope窗口中,您可以看到设计层次结构。当您选择了一个Scope层次结构中的作用域时,该作用域内的所有HDL对象,包括reg、wire等都会出现在“Objects”窗口中。您可以在“Objects”窗口中选择HDL对象,并将它们添加到波形窗口中。
(2)Object窗口。“Objects”窗口会显示在“Scopes”窗口中选择的范围内的所有HDL仿真对象。例如,我们在Scope窗口中选择“u_led_twinkle”,在“Objects”窗口中就会自动显示出led_twinkle模块中所有的对象。如下图所示:
图 4.4.14 “Objects”窗口中的对象可以看出,在led_twinkle顶层模块中除了顶层端口sys_clk_p、sys_clk_n、sys_rst_n、led之外,还包括在内部定义的计数器cnt,与差分输入转单端输出的系统时钟sys_clk。
(3)波形窗口。用于显示所要观察信号的波形。若要向波形窗口添加单个HDL对象或多个HDL对象,在“Objects”窗口中,右键单击一个或多个对象,然后从下拉菜单中选择“Add to Wave Window”选项。例如,我们把“u_led_twinkle”模块下的“cnt”计数器与系统时钟sys_clk添加到波形窗口中,如下图所示:
图 4.4.15 将“counter”计数器添加到波形窗口中图 4.4.16 将“sys_clk”系统时钟添加到波形图窗口中添加到波形窗口中的“cnt”计数器与系统时钟sys_clk如下图所示:
图 4.4.17 添加到波形窗口中的“cnt”计数器与系统时钟“sys_clk”一般地,每当我们进行一次仿真时,都会把当前波形的配置信息保存下来,包括波形窗口中具有哪些信号等等,以便在下一次打开仿真器进行仿真时,继续使用上一次仿真的配置信息。我们点击波形窗口中的保存按钮,如下图所示:
图 4.4.18 波形窗口中的保存按钮之后会弹出“Save Waveform”对话框,提示用户将当前波形配置信息保存为“.wcfg”后缀的文件,且工具已经自动地输入了文件名“tb_led_twinkle_behav”,文件的保存目录也被工具自动设置为了当前的工程目录,所以我们保持其默认状态即可,直接点击“Save”。如下图所示:
图 4.4.19 保存.wcfg文件注意,.wcfg文件只是包含波形窗口的配置信息,并不包含波形的数据文件,波形的数据文件被存储在另外的文件中。
之后会弹出一个消息框,询问用户是否将刚刚创建的波形配置信息文件tb_led_twinkle_behav.wcfg添加到当前工程中,我们直接点击“Yes” 即可。如下图所示:
图 4.4.20 将led_tb_behav.wcfg文件添加到工程中(4)仿真工具栏。仿真工具栏包含运行各个仿真动作的命令按钮,如下图所示:
图 4.4.21 仿真工具栏上图中的工具栏从左至右依次是:
• Restart:将仿真时间重置为零,此时波形窗口中原有的波形都会被清除。下次执行仿真时,会从0时刻重新开始。
• Run all:运行仿真,直到其完成所有事件或遇到HDL语句中的$stop或$finish命令为止。注意,如果没有在TestBench语句中加入$stop或$finish命令,当点击Run all命令时,仿真器会无休止地一直仿真下去,除非用户点击仿真工具栏中的“Break”按钮来手动地结束仿真。但是,如果此时需要仿真的设计比较复杂,则仿真器在运行仿真时会耗费电脑大量的CPU和内存资源,此时有可能会造成电脑卡顿甚至死机的情况。所以,如果设计比较复杂,且没有在TestBench语句中加入$stop或$finish命令,最好不要轻易点击Run all命令。
• Run For:运行特定的一段时间。紧随在后面的两个文本框用于设定仿真时长的数值大小和时间单位。
• Step:按步运行仿真,每一步仿真一个HDL语句。
• Break:暂停当前仿真。
• Relaunch:重新编译仿真源并重新启动仿真。在使用Vivado仿真器来调试HDL设计时,您可能会根据仿真结果来对您的HDL源代码进行修改。在修改完HDL源代码后,可以点击Relaunch按钮来重新加载UUT设计和TestBench,以重新对修改后的HDL源代码进行仿真。此时就不需要再关闭并重新打开仿真器了。
介绍完各个窗口和命令按钮的使用后,下面我们开始进行仿真。
在刚打开仿真器时,仿真器会将TestBench中的信号加入到波形窗口中,并执行一段时长的仿真,仿真的时长由Settings设置窗口中的参数值指定,如下图所示:
图 4.4.22 Settings窗口中设置默认仿真时长的参数值可以看到,仿真器启动后默认立即执行的仿真时长是1000ns。由于我们是在默认立即执行仿真结束之后,才加入了“cnt”计数器信号,所以新加入的cnt信号并没有波形。此时我们需要将仿真时刻重置为0,重新开始仿真。点击Restart按钮,波形窗口中的当前仿真时刻点(黄色标尺)就会回归到0ns,且原先的所有波形都被清除,如下图所示:
图 4.4.23 Restart仿真此时点击仿真工具栏中的Run For按钮,默认仿真时长是10us,如下图所示:
图 4.4.24 Run For按钮此时就可以看到波形窗口中就出现了波形,我们点击波形窗口中的显示工具栏中的“Zoom Fit”按钮,波形就会自动缩放到整个窗口,如下图所示:
图 4.4.25 “Zoom Fit”按钮按住“Ctrl”键并滚动鼠标滚轮,就可以放大/缩小波形,如下图所示:
图 4.4.26 放 *** 形cnt信号默认显示为16进制,为了方便观察,我们将其设置为10进制。对cnt信号右键,在弹出的菜单中依次选择“Radix”——“Unsigned Decimal”,如下图所示:
图 4.4.27 按无符号10进制显示修改显示后的波形如下图所示:
图 4.4.28 波形可以看出,cnt每计数到4和10,两个led的电平状态就切换一次。证明我们的HDL设计达到了我们想要的功能。
在仿真结束后,可以在Flow Navigator窗体中找到SIMULATION,鼠标右击SIMULATION,选择Close Simulation来关闭仿真的界面,如下图所示:
图 4.4.29 关闭仿真界面紧接着会弹出一个关闭仿真的确认窗口,点击“OK”按钮即可。