4.3 基于Quartus II 18.0的4位计数器设计流程
4.3.1 Quartus II工程的创建
Quartus Ⅱ工程的创建步骤如下。
(1)新建Quartus Ⅱ工程。打开Quartus Ⅱ 18.0,在菜单栏中选择“File”→“New”,在弹出的对话框中选择“New Quartus Prime Project”,如图4.4所示,单击“OK”按钮。
图4.4 创建步骤1:新建Quartus Ⅱ工程
(2)目录的指定与文件架构的创建。在这一步首先需要选择工程文件目录(笔者关于本书的例程均存放在D:\Crazy_FPGA_Examples下)。选择01_Counter_Design文件夹,如图4.5所示。
图4.5 创建步骤2:选择工程目录
(3)新建工程架构文件夹。双击进入01_Counter_Design文件夹,参照笔者在第3章中规定的Quartus Ⅱ工程文件夹定制架构,新建5个文件夹,如图4.6所示。
图4.6 创建步骤3:新建工程架构文件夹
(4)输入工程名及顶层文件名。进入“dev”文件夹,并且将dev文件夹作为Quartus II的工程目录。输入工程名及顶层文件名,同为Counter_Design,如图4.7所示。
图4.7 创建步骤4:输入工程及顶层文件名
(5)选择目标器件EP4CE15F17C8N。一直单击“Next”按钮,指定目标FPGA型号。器件的选型只是Quartus II综合电路的目标,而Device既可在建立工程时指定,也可在工程创建后修改,这与Keil等软件的工程设置一样。在这里选择板卡Cyclone IV FPGA系列的EP4CE15F17C8N,如图4.8所示。
图4.8 创建步骤5:选择目标器件EP4CE15F17C8N
(6)选择屏蔽默认仿真工具。如图4.9所示进行选择(由于进行独立的Modelsim仿真,所以选择None),最后单击“Finish”按钮完成设置。
图4.9 创建步骤6:选择屏蔽默认仿真工具
(7)完成设置。返回Quartus II界面,工程建立完毕。建立完成的工程页面如图4.10所示。
图4.10 创建步骤7:建立完成的工程页面
4.3.2 4位计数器的逻辑电路设计
创建好第一个工程后,下一步就是开始设计4位计数器的逻辑电路。Quartus II进行逻辑电路设计有两种方法,最简单的方法是直接在Block中绘制原理图,而本书使用另一种方法—HDL描述方法。首先选择“File”→“New”,新建Verilog HDL File,然后开始设计电路,如图4.11所示。
图4.11 新建Verilog HDL File
此时需要一个4位计数器的设计思路。4位计数器的电路运行流程图如图4.12所示。
图4.12 4位计数器的电路运行流程图
流程说明:FPGA上电启动后,分别判断时钟上升沿与复位低电平信号(两者都是由时序电路的触发器驱动的信号)。当时钟上升沿到来时,判断cnt是否溢出,如果溢出则归零,反之则自加;当复位信号到来时,cnt直接复位为零。
Verilog HDL代码的主要流程如下所示。
(1)第一步并不是写module,而是添加文件头(这一部分在3.2.3节有详细的阐述)。在这里,笔者修改了文件头中关于文件名、功能描述及版本等信息,如下所示。
/*------------------------------------------------------------------------------------------ \\\|/// \\ -- // ( @@ ) +---------------------------------------oOOo-(_)-oOOo-------------------------------+ CONFIDENTIAL IN CONFIDENCE This confidential and proprietary software may be only used as authorized by a licensing agreement from CrazyBingo (Thereturnofbingo). In the event of publication, the following notice is applicable: Copyright (C) 2012-20xx CrazyBingo Corporation. The entire notice above must be reproduced on all authorized copies. Author : CrazyBingo Official Websites : http://www.crazyfpga.com Email Address : crazyfpga@qq.com Filename : Counter_Design.v Data : 2013-10-13 Description : Counter for 4bit data. Modification History : Data Author Version Change Description ======================================================= 13/10/13 CrazyBingo 1.0 Original --------------------------------------------------------------------------------------------- | Oooo | +-----------------------------------------oooO--( )----------------------------------+ ( ) )/ \( (_/ \_) --------------------------------------------------------------------------------------------*/
笔者认为文件头的添加比写出电路功能更为重要!由于篇幅有限,所以后续的章节在设计代码时均不再给出文件头,但这是Verilog HDL/testbench代码设计的必要部分。
(2)信号列表的定制。这一步同样遵循第3章介绍的module列表编写规范,这里用到了时钟信号、复位信号,还有一个4位的计数输出。列表的编写代码如下所示。
`timescale 1ns/1ns module Counter_Design ( //global clock input clk, //50MHz input rst_n, //user interface output reg[3:0] cnt ); … endmodule
其中,clk为外部时钟(本书配套硬件平台为50MHz), rst_n为全局复位信号,而cnt则为计数信号。
此外,“`timescale 1ns/1ns”是testbench要用到的仿真时间单位和精度的设定。虽然这在Quartus II中没有直接用到,但是笔者认为每一个电路都应该进行严格的仿真,每一位设计者都应该直接养成编写timescale的习惯,以方便testbench测试,不用再返回目标Verilog HDL文件中添加timescale。注意,用户代码存放在endmodule之前。
关于Verilog HDL代码编写设计风格,读者有疑问可以翻阅第3章,此处不再赘述。
(3)4位计数器模块的实现,代码如下所示。
//---------------------------- //Counter for 4 bit data always@(posedge clk or negedge rst_n) begin if(! rst_n) cnt <=0; else cnt <=cnt + 1'b1; end
Verilog HDL其实是和C语言类似的,因此在设计上很好理解。这里完全按照图4.12来设计电路,当复位信号(rst_n)到来时,cnt归零;反之,当时钟(clk)上升沿到来时,cnt实现自加;当cnt信号计数到4'd15时,溢出复位。
(4)保存电路设计。如果是顶层文件,则在执行“新建”→“编辑”操作后,直接保存默认文件名即可;反之,则需要用户自己设定文件名。需要注意的一点是,本书约定把用户文件存放在src目录下,如图4.13所示。
图4.13 保存用户文件
对于从Quartus II中编辑并保存的代码,软件会自动默认添加到文件列表中。反之,如果是已有的文件,则需要用户进行手动添加。用户可以单击Project Navigator中的File图标,再右键单击“Add/Romove Files...”按钮,然后进入src目录中指定目标文件,如图4.14所示。
图4.14 手动添加文件
当然,本工程中只有Counter_Design.v文件,文件列表如图4.15所示。
图4.15 文件列表
4.3.3 Quartus II编译流程与工程设置分析
本节将从初学者的角度从零开始解决Quartus II工程编译中遇到的问题,并且根据问题展开详细的分析,同时给出解决问题的方案。
1.工程的编译
首先单击Processing下的“Start Compilation”或按下“Ctrl+L”组合键,在Quartus II下进行全编译,如图4.16所示。
图4.16 Quartus II全编译
可以通过在任务栏右键单击选中“Message”,或者按下“Alt+3”组合键弹出Message窗口。编译结果如图4.17所示。
图4.17 Quartus II编译结果
Flow Summary中显示了编译日志,还包括工程名、器件特性、资源使用等信息。由图4.17可知,本设计的目标器件为EP4CE15F17C8,逻辑电路设计中总共使用了4个LEs及6个引脚,且不占用任何资源。
在全编译过程中,Quartus II总共要进行4个步骤,这4个步骤可以在Status窗口(Alt+4)中查看,如图4.18所示。
图4.18 Quartus II编译步骤
每一个步骤及完成的任务如下所示。
(1)Analysis & Synthesis:分析与综合器,主要是分析源文件的语法等错误,同时生成门级代码。
(2)Fitter:适配器,完成对RTL电路的布局布线。
(3)Assembler:装配器,产生汇编文件。
(4)Timing Analyzer:时序分析器,约束关键路径,以达到更完美的时序收敛。
在全编译进程中,器件的适配,即布局布线的优化耗费了大量的时间,但实际上,我们在进行Modelsim仿真,或者说在进行FPGA布局布线之前,为了节省开发的时间,语法编译后就应该进行功能仿真。可以只进行分析与综合(笔者一般利用快捷键“Ctrl+K”来执行分析与综合),以进行最基本的语法等修正(时序仿真必须完成全编译)。
接下来,开始分析警告信息。任何一个警告都必须慎重对待,除非警告本身无关紧要,可以忽略(ignore)。对于4位计数器工程的全编译,警告/错误信息如图4.19所示(新版本Quartus II不会跳出编译完成的Message窗口,用户需要自行查看Quartus II的Compile Message窗口)。
图4.19 Quartus II警告/错误信息
2.I/O引脚分配问题
首先解决引脚未分配警告信息,如图4.20所示。
图4.20 引脚未分配警告信息
从图4.20中的字面意思就可以推断出警告的原因:由于我们没有给器件clk、rst_n、cnt[3:0]分配确定的引脚,所以这几个信号没有确定的输入/输出,因此需要通过分配引脚来解决该问题。分配引脚的方法有很多,可以通过GUI、脚本(tcl窗口或直接在*.qsf中编写)实现,笔者在此先介绍最基本的引脚分配方法:GUI引脚分配(在菜单栏Assignments的“Pin Planner”下),如图4.21所示。
图4.21 GUI引脚分配
本书第2章2.5节已经介绍了配套硬件平台,板卡的clk与rst_n全局时钟信号分别位于EP4CE15F17C8N的E16、M2引脚,同时,指定4个任意的I/O作为cnt的输出引脚配置。分配完引脚后的Pin Planner如图4.22所示,此时每个信号均有了输入/输出的I/O。在理论上已经完成了引脚的分配后,再次按下“CTRL+L”组合键进行分析与综合,结果出现了错误,如图4.23所示。
图4.22 分配完引脚后的Pin_Planner
图4.23 引脚分配后编译错误信息
该错误信息的意思是用户不能在PIN_C1或PIN_D2上放置多个引脚,但事实是在Pin Planner中没有将两个信号同时定位到一个引脚,这是什么原因呢?实际上PIN_C1、PIN_D2是FPGA复用功能的引脚,复用引脚除具有特定功能外,还能被设置成用户引脚来使用。这两个脚的复用功能,可以在配置引脚时或EP4CE15F17C8N芯片原理图中查看到,如图4.24所示为IC原理图中的引脚示意。
图4.24 EP4CE15F17C8N的C1与D2复用功能引脚
在FPGA的硬件电路设计中,PIN_C1(ASDO)、PIN_D2(nCSO)与EPCS串行存储芯片直连,作为配置引脚。由于功能的限制,所以最好不要再将其作为普通I/O来使用(笔者一般将其用作配置引脚,这在FPGA的PCB设计中也需要格外注意)。本书选择了PIN_F3、PIN_D1来替换PIN_C1、PIN_D2,修改引脚后的Pin Planner如图4.25所示。
图4.25 修改引脚后的Pin Planner
引脚分配完毕,理论上应该不会再出现问题,再次全编译,前面引脚配置的问题已经得到解决。此时,引脚配置后的编译结果如图4.26所示。
图4.26 引脚配置后的编译结果
3.影响编译速度问题
在Message的Warning中,有一个影响编译速度的警告:“Warning (18236): Number of processors has not been specified which may cause overloading on shared machines. Set the global assignment NUM_PARALLEL_PROCESSORS in your QSF to an appropriate value for best performance.”该警告提示我们可以在QSF文件中设置适当的处理器的数目以达到最佳的性能。打开工程目录下的Counter_Design.qsf文件,添加以下约束,指定所有可用的处理器,当然还可以指定具体的处理器的数目,如将“ALL”改成数字1、2、4等。
set_global_assignment -name NUM_PARALLEL_PROCESSORS ALL
重新全编译,影响编译速度的警告得到解决。此时,解决影响编译速度问题后的编译结果如图4.27所示。
图4.27 解决影响编译速度问题后的编译结果
4.SDC时序约束文件
接下来解决时序约束文件的问题。在大型设计中或时序非常严谨的情况下,务必进行时序仿真,以验证时序是否违规,进而用timequest进行约束。可以使用Quartus II内嵌的静态时序分析(STA),或者第三方工具(Synopsys的Formality、PrimeTime),也可以使用Quartus II内嵌的Chip Editor分析芯片内部的连接与配置情况。
笔者在第3章关于Quartus II版本间的差异性分析中曾提到,Quartus II 9.1及之前版本的软件包括自动时序分析,即Settings中包含Classic Timing Analyzer,但从Quartus II 10.1版本开始只有Timing Analyzer,即只能手动添加时序约束,也就是SDC文件。
在Quartus II 9.1及其之前版本中,软件默认为使用“Use Classic Timing Analyzer during compilation”,如图4.28所示。对于“Counter_Design”这个工程,如果在Quartus II 9.1中编译,则不会出现SDC时序约束警告。
图4.28 软件默认设置
本书基于Quartus II 18.0平台,只能使用TimeQuest Timing Analyzer during compilation模式,用户只能进行手动约束,否则就会出现如图4.29所示的编译警告。
图4.29 Quartus II 18.0编译警告
时序约束是FPGA逻辑电路设计的精髓,是一个系统运行稳定、时钟可靠、时序收敛的决定性因素。FPGA逻辑电路设计到最后,需要完善的就是通过时序约束来优化布局布线,而这一步则需要设计者具备深厚的FPGA架构经验,熟练的数字电路开发基础,以及对FPGA布局布线有一个比较深入的了解。
由于篇幅有限及由浅到深的入门顺序,本节只介绍最基本、最快捷的脚本进行时钟/复位的约束方法,更深入详细的内容请参照本书第14章“TimeQuest时序分析与实战演练”。下面主要介绍几个最基本的约束。
(1)主时钟的约束。
#************************************************************** # Create Clock #************************************************************** create_clock -period 20 [get_ports clk]
约束输入为50MHz全局输入时钟。
(2)PLL时钟的自动约束。
#************************************************************** # Create Generated Clock #************************************************************** derive_pll_clocks
这里主要完成对锁相环输出的全局时钟的自动约束。如果在FPGA设计中调用了PLL,就需要用这句代码来实现对PLL输出全局时钟的约束。
(3)不确定时间的自动检测。
#************************************************************** # Set Clock Uncertainty #************************************************************** derive_clock_uncertainty
用于交互时钟(inter-clock)、内部时钟(intra-clock)和I/O接口的不确定时间的自动检测,一般只用在FPGA器件中。
如果在MAX II CPLD/Cyclone FPGA/Cyclone II FPGA器件工程中使用这句代码来约束,则会出现如下警告:“Warning (332153): Family doesn't support jitter analysis.”,这是由于在CPLD中不支持这一功能,因此软件会自动忽略不确定时间自动检测的约束。本书的目标器件为EP4CE15F17C8N,因此需要这个约束。
(4)不希望综合工具进行分析的路径。
#************************************************************** # Set Multicycle Path #************************************************************** set_false_path -from rst_n -to *
在这里指定复位信号rst_n为不需要Quartus II Analysis & Synthesis进行分析的路径,而复位信号作为全局信号,一般不希望编译对其做出优化,因此不允许综合工具对其分析。
(5)对于其他的一些时序约束,用户可以自己将其添加到SDC时序约束文件中。
完成时序约束的介绍、分析与解决方案后,再回到Quartus II中进行必要的时序约束,以优化编译器的布局布线,解决时序问题。首先,File-New新建一个SDC文件,输入最基本的时序约束脚本,并且保存为VIP_System.sdc文件,如图4.30所示。
图4.30 保存文件
当然,如果有现成的时序约束文件的备份(后面的工程都有),则可以直接在“Assignments”→“Settings”的“Timing Analyzer”中添加时序约束文件VIP_ System.sdc,如图4.31所示。
图4.31 添加时序约束文件VIP_System.sdc
最后重新进行Quartus II全编译(Ctrl+L),此时只剩下“某些I/O设置不完整”和“当前license不支持LogicLock功能”的警告,这两个警告都可以忽略,编译结果如图4.32所示。尽管时序约束目前不会影响我们的简单的设计,但严谨的设计永远会让我们在未来系统工程设计中事半功倍。
图4.32 Quartus II最终编译结果
5.Quartus II RTL电路的查阅
虽然现在可以通过Verilog HDL了解和掌握FPGA,但是我们仍然需要具有数字电路的基础。在代码正确但综合电路却不正确的情况下,我们往往需要检查设计的RTL电路是否正确。笔者设计完Verilog HDL,进行一系列的编译、综合及必要的软件设置后,想让读者了解一下底层RTL门级电路的分析流程。
如图4.33所示,执行“Tools”→“Netlist Viewers”→“RTL Viewer”选项,软件便会显示综合后得出的当前工程顶层设计的Counter_Design RTL电路,如图4.34所示。
图4.33 “Tools”→“Netlist Viewers”→“RTL Viewer”选项
图4.34 Counter_Design RTL电路
电路实现的功能分析如下所示。
(1)cnt[0]~reg[3..0]为D型触发器,在时钟信号(上升沿)到来时寄存输出信号,在复位(低电平)到来时对输出信号进行清零。Quartus II自动综合了4个DFF。
(2)clk作为电路的时钟驱动信号,在上升沿到来时,触发一次DFF进行寄存输出。
(3)rst_n作为电路的复位信号,在下降沿到来时,触发DFF进行清零操作。
(4)加法器Add0实现4位计数器的自加,输出结果输入4个触发器。
图4.34是一个很简单的RTL电路,但当设计变得复杂后,顶层电路必然是模块的例化设计,到那时,查阅RTL图进行分析更为重要。通过分析RTL能给逻辑电路设计提供一个更清晰的脉络,这在后面的设计中会经常用到。
请记住“Verilog HDL设计的是电路,而不是代码”,不要纠结HDL的写法如何高级,而要思考如何才能设计更完美的电路。