现代电子技术综合实验
电子秒表设计
学生姓名:学 号:指导老师:学 院:提交时间:
摘要
本文介绍了使用VHDL开发FPGA的一般流程,重点介绍了电子秒表的设计。该设计以VHDL作为硬件开发语言,以ISE作为软件开发平台,准确地实现了秒表计数、清零、暂停等功能,并使用ModelSim仿真软件对VHDL程序实现了
仿真,完成了综合布局布线,最终将程序下载到芯片Spartan-3A,测试结果良好。
关键字:FPGA VHDL ISE ModelSim 电子秒表
目 录
第一章 引言————————————————————————————4
第二章 基于FPGA的VHDL设计流程——————————————————4
2.1 时间的概念及计时方法————————————————————4
2.2 VHDL语言简介———————————————————————4
2.2.1 VHDL语言特点————————————————————-4
2.2.2 VHDL语言优势————————————————————-6
2.3 FPGA简介—————————————————————————6
2.3.1 FPGA的主要特点———————————————————-6
2.3.2 FPGA的开发流程————————————————————6
第三章 电子秒表的软件开发环境———————————————————6
3.1 ModelSim简介————————————————————————7
3.1.1 ModelSim的特点————————————————————-7
3.2 ISE简介——————————————————————————-7
第四章 电子秒表的设计与实现————————————————————-7
4.1 实验任务——————————————————————————9
4.2 实验条件——————————————————————————9
4.3 系统需求和解决方案—————————————————————9
4.4 各模块的实现————————————————————————9
4.4.1 分频器————————————————————————10
4.4.1.1 分频得到1KHz的时钟信号—————————————10
4.4.1.2 分频得到100Hz的时钟信号————————————10
4.4.2 输入控制电路—————————————————————11
4.4.2.1 防抖电路————————————————————11
4.4.2.2 控制电路————————————————————11
4.4.3 计数模块———————————————————————12
4.4.3.1 十进制计数器——————————————————12
4.4.3.2 六进制计数器——————————————————13
4.4.4 锁存器————————————————————————13
4.4.5 显示模块———————————————————————13
4.4.5.1 扫描器—————————————————————13
4.4.5.2 数据选择器———————————————————14
4.4.5.3 七段译码器———————————————————14
4.5 分配引脚和下载实现————————————————————-14
4.6 实验结果及仿真——————————————————————-15
第五章 结论———————————————————————————15
5.1 实验结论—————————————————————————15
5.2 心得体会—————————————————————————15 参考文献———————————————————————————16 致谢—————————————————————————————16 附 录————————————————————————————17
第一章 引言
随着现代电子科技的发展,各种新型的电子产品层出不穷,而高精度的电子秒表作为电子产品的一部分,在人们的日常生产、生活中发挥着极其重要的作用。
本文主要任务是针对设计的要求,基于FPGA利用硬件描述语言VHDL完成秒表的设计,并且通过仿真、分析、综合从而实现计数、清零、暂停等功能。该系统具有高速、精确、可靠、抗干扰性强和现场可编程等优点,且系统成本非常低廉,适用于大规模地生产和应用。
第二章 基于FPGA的VHDL设计流程
2.1 时间的概念及计时方法
时间是物理学中的七个基本量纲之一,符号t。
在国际单位制(SI)中,时间的额吉本单位是秒,符号s,在1967年召开的第13届国际度量衡大会对秒的定义是:銫133原子基态的两个超精细能阶间跳跃对应辐射的9,192,631,770个周期的持续时间。这个定义提到的铯原子必须在绝对零度是静止的,而且在地面上的环境是零磁场。在这样的情况下被定义的秒,在天文学上的历书时所定义的秒是等效的。
中国古代的计时器有太阳钟和机械钟两种。太阳钟是以太阳的投影和方位来计时的。代表有土圭、圭表、日晷等。而由于地球轨道偏心率以及地球倾角的影响,真太阳时和平太阳时是不一致的,机械钟应运而生,代表有水钟、沙漏等。 时间已经走到21世纪,为了更加精确的测量时间,现代人使用了很多方法。最常用的包括有机械时钟和电子时钟。本文介绍的电子秒表便是电子时钟的一种。我们将基于FPGA和EDA软件来制作一款秒表,已达到计时的目的。
2.2 VHDL语言简介 VHDL语言是一种用于电路设计的高级语言。它在80年代的后期出现。最初是由美国国防部开发出来供美军用来提高设计的可靠性和缩减开发周期的一种使用范围较小的设计语言 。
VHDL翻译成中文就是超高速集成电路硬件描述语言,主要是应用在数字电路的设计中。它在中国的应用多数是用在FPGA/CPLD/EPLD的设计中。当然在一些实力较为雄厚的单位,它也被用来设计ASIC。
VHDL主要用于描述数字系统的结构,行为,功能和接口。除了含有许多具有硬件特征的语句外,VHDL的语言形式、描述风格以及语法是十分类似于一般的计算机高级语言。VHDL的程序结构特点是将一项工程设计,或称设计实体(可以是一个元件,一个电路模块或一个系统)分成外部(或称可视部分,及端口)和内部(或称不可视部分),既涉及实体的内部功能和算法完成部分。在对一个
设计实体定义了外部界面后,一旦其内部开发完成后,其他的设计就可以直接调用这个实体。这种将设计实体分成内外部分的概念是VHDL系统设计的基本点。
2.2.1 VHDL语言特点 与其他硬件描述语言相比,VHDL具有以下特点:
功能强大、设计灵活
VHDL具有功能强大的语言结构,可以用简洁明确的源代码来描述复杂的逻辑控制。它具有多层次的设计描述功能,层层细化,最后可直接生成电路级描述。VHDL支持同步电路、异步电路和随机电路的设计,这是其他硬件描述语言所不能比拟的。VHDL还支持各种设计方法,既支持自底向上的设计,又支持自顶向下的设计;既支持模块化设计,又支持层次化设计。
支持广泛、易于修改
由于VHDL已经成为IEEE标准所规范的硬件描述语言,大多数EDA工几乎都支持VHDL,这为VHDL的进一步推广和广泛应用奠定了基础。在硬件电路设计过程中,主要的设计文件是用VHDL编写的源代码,因为VHDL易读和结构化,所以易于修改设计。
强大的系统硬件描述能力
VHDL具有多层次的设计描述功能,既可以描述系统级电路,又可以描述门级电路。而描述既可以采用行为描述、寄存器传输描述或结构描述,也可以采用三者混合的混合级描述。另外,VHDL支持惯性延迟和传输延迟,还可以准确地建立硬件电路模型。VHDL支持预定义的和自定义的数据类型,给硬件描述带来较大的自由度,使设计人员能够方便地创建高层次的系统模型。
独立于器件的设计、与工艺无关
设计人员用VHDL进行设计时,不需要首先考虑选择完成设计的器件,就可以集中精力进行设计的优化。当设计描述完成后,可以用多种不同的器件结构来实现其功能。
很强的移植能力
VHDL是一种标准化的硬件描述语言,同一个设计描述可以被不同的工具所支持,使得设计描述的移植成为可能。
易于共享和复用
VHDL采用基于库(Library)的设计方法,可以建立各种可再次利用的模块。这些模块可以预先设计或使用以前设计中的存档模块,将这些模块存放到库中,就可以在以后的设计中进行复用,可以使设计成果在设计人员之间进行交流和共享,减少硬件电路设计。
2.2.2 VHDL语言优势 (1)与其他的硬件描述语言相比,VHDL具有更强的行为描述能力,从而决定了他成为系统设计领域最佳的硬件描述语言。强大的行为描述能力是避开具体的器件结构,从逻辑行为上描述和设计大规模电子系统的重要保证。
(2)VHDL丰富的仿真语句和库函数,使得在任何大系统的设计早期就能查验设计系统的功能可行性,随时可对设计进行仿真模拟。
(3)VHDL语句的行为描述能力和程序结构决定了他具有支持大规模设计的分解和已有设计的再利用功能。符合市场需求的大规模系统高效,高速的完成必须有多人甚至多个代发组共同并行工作才能实现。
(4)对于用VHDL完成的一个确定的设计,可以利用EDA工具进行逻辑综合和优化,并自动的把VHDL描述设计转变成门级网表。
(5)VHDL对设计的描述具有相对独立性,设计者可以不懂硬件的结构,也不必管理最终设计实现的目标器件是什么,而进行独立的设计。
2.3 FPGA简介
FPGA是英文Field Programmable Gate Array的缩写,即现场可编程门阵列,它是在PAL、GAL、EPLD等可编程器件的基础上进一步发展的产物。它是作为专门集成电路(ASIC)领域中的一种半定制电路而出现的,既解决了定制电路的不足,又克服了原有可编程器件门电路数有限的缺点。
FPGA采用了逻辑单元阵列LCA(Logic Cell Array)这样一个新概念,内部包括可配置逻辑模块CLB(Configurable Logic Block)、输出输入模块IOB(Input Output Block)和内部连线(Interconnect)三个部分。
2.3.1 FPGA的主要特点
(1)采用FPGA设计ASIC电路,用户不需要投片生产,就能得到合用的芯片。
(2)FPGA可做其它全定制或半定制ASIC电路的中试样片。
(3)FPGA内部有丰富的触发器和I/O引脚。
(4)FPGA是ASIC电路中设计周期最短、开发费用最低、风险最小的器件之一。
(5)FPGA采用高速CHMOS工艺,功耗低,可以与CMOS、TTL电平兼容。 可以说,FPGA芯片是小批量系统提高系统集成度、可靠性的最佳选择之一。
2.3.2 FPGA的开发流程
FPGA开发一般可分为以下七部分:
1、文本编辑:用任何文本编辑器都可以进行,也可以用专用的HDL编辑环境。通常VHDL文件保存为.vhd文件
2、功能仿真:将文件调入HDL仿真软件进行功能仿真,检查逻辑功能是否正确(也叫前仿真,对简单的设计可以跳过这一步,只在布线完成以后,进行时序仿真)
3、逻辑综合:将源文件调入逻辑综合软件进行综合,即把语言综合成最简的布尔表达式。逻辑综合软件会生成.edf(edif)的EDA工业标准文件。
4、布局布线:将.edf文件调入PLD厂家提供的软件中进行布线,即把设计好的逻辑安放到PLD/FPGA内。
5、时序仿真:需要利用在布局布线中获得的精确参数,用仿真软件验证电路的时序。(也叫后仿真)
6、编程下载:确认仿真无误后,将文件下载到芯片中
7、硬件测试:硬件测试的目的是为了在更真实的环境中检验HDL设计的运行情况,特别是对于HDL程序设计上不是十分规范,语义上含有一定歧义的程序。
第三章 电子秒表的软件开发环境
本章主要介绍项目中将要用到了一系列软件,包括用于VHDL语言编写和编译的ISE软件和用于程序仿真的仿真软件ModelSim。
3.1 ModelSim简介
Mentor公司的ModelSim是业界最优秀的HDL语言仿真软件,它能提供友好的仿真环境,是业界唯一的单内核支持VHDL和Verilog混合仿真的仿真器。它采用直接优化的编译技术、Tcl/Tk技术、和单一内核仿真技术,编译仿真速度快,编译的代码与平台无关,便于保护IP核,个性化的图形界面和用户接口,为用户加快调错提供强有力的手段,是FPGA/ASIC设计的首选仿真软件。
3.1.1 ModelSim的特点 · RTL和门级优化,本地编译结构,编译仿真速度快,跨平台跨版本仿真; · 单内核VHDL和Verilog混合仿真;
· 源代码模版和助手,项目管理;
· 集成了性能分析、波形比较、代码覆盖、数据流ChaseX、Signal Spy、虚拟对象Virtual Object、Memory窗口、Assertion窗口、源码窗口显示信号值、信号条件断点等众多调试功能;
· C和Tcl/Tk接口,C调试;
· 对SystemC的直接支持,和HDL任意混合;
· 支持SystemVerilog的设计功能;
· 对系统级描述语言的最全面支持,SystemVerilog,SystemC,PSL; · ASIC Sign off。
· 可以单独或同时进行行为(behavioral)、RTL级、和门级(gate-level)的代码。
3.2 ISE简介
ISEt是Xilinx公司提供的集成化FPGA开发软件,它的主要功能包括设计 输入、综合、仿真、实现和下载。
(1)设计输入
ISE软件提供的设计输入工具包括用于HDL代码输入和报告查看的ISE文本编辑器(TextEditor),用于原理图编辑的工具ECS(Engineering CaptureSystem),用于P CORE的COREGenerator,用于状态机设计的StateCAD,以及用于约束文件编辑的Constraint Editor等。
(2)综合
ISE的综合工具不但包括了Xilinx自身提供的综合工具xsr,同时还可以集成MentorGraphics公司的LeonardoSpectrum和Synplicity公司的Synplify。
(3)仿真
ISE本身自带了图形化波形编辑功能的仿真工具HDL Bencher,同时又提供了使用ModelTechnology公司的ModelSim进行仿真的接口。
(4)实现
ISE的实现功能包括了翻译(Translate)、映射(Map)、布局布线(Place andRoute)等。
(5)下载
下载功能包括了BitGen,用于将布局布线后的设计文件转换为比特流(Bitstream)文件。还包括了iMPACT功能,用于进行设备配置和通信,控制将程序烧写到FPGA芯片中去。
使用ISE进行FPGA开发大致可以分为3个步骤。
(1)设计输入和仿真
设计输入(Design Entry)是指以HDL代码、原理图、波形图以及状态机的形式输入设汁源文件,而设计仿真(Simdmion)是指通过仿真工具对设计的整体模块或局部模块进行仿真来检验设计的功能和性能。
(2)用户约束条件、综合和实现
用户约束条件(User Constraints)的作用是对综合、实现过程进行控制,满足速度、面积、引脚位置等需求。编辑约束条件又包括了4个子项,意义分别为:创建时间约束、配置引脚、创建面积约束、以文本方式编辑约束。综合(Synthesize)是FPGA设计流程中的重要环节,综合结果的优劣直接影响到设计的最终性能。
ISE自带的综合工具是XST,同时它也支持Synplify/Synplify Pro等第三方综合工具,但是由于Xilinx对于其器件的底层最为了解,所以使用XST综合往往会得到比较满意的结果。综合包含了3个子项,意义分别为:查看综合报告、查看综合器件的RTL级原理图和检查语法。实现(Implementation)过程也包含了3个子项,ImplementDesign项所对应的子项,意义分别是:翻译、映射和布局布线。需要注意,进行实现步骤之前必须进行约束条件的编辑,否则实现可能会出错。
(3)硬件编程
硬件编程(Programming)是指生成编辑比特流文件bit,并将其下载到FPGA芯片内部的过程。硬件编程对应图2--5所示的Generate Programming File项。
第四章 电子表秒的设计与实现
4.1 实验任务
设计一个秒表,秒表的计时范围为00’00”00 ~
59’59”99。有两个按钮开关Start/Stop和
Split/Reset,控制秒表的启动、停止、分段和复位:
1. 在秒表已经被复位的情况下,按下
“Start/Stop”键,秒表开始计时。
2. 在秒表正常运行的情况下,如果按下
“Start/Stop”键,则秒表暂停计时。
3. 再次按下该键,秒表继续计时。
4. 在秒表正常运行的情况下,如果按下
“Split/Reset”键,显示停止在按键时的时
间,但秒表仍然在计时。
5. 再次按下该键,秒表恢复正常显示。
6. 在秒表暂停计时的情况下,按下
“Split/Reset”键,秒表复位归零。
4.2 实验条件
我们将利用EDA软件和
HDL语言在EEC-FPGA实验板上完成秒表的设计与实现,实验板原理如图1所示。在项目开始设计时,首先要确定系统的需求并发展出一个针对这些需求的计划。设计方案以及系统需求必须按照设计要求并根据客
观条件来确定。
图1 实验板原理图
4.3 系统需求和解决方案
根据实验板原理图可以发现,数码管为共阳极输出,因此,为了能够使八盏数码管同时显示时间,我们需要设置一个扫描显示控制模块以进行扫频。由于计时精度精确到0.01秒,因此根据数据采集定理,分频后的频率应至少为计时精度的两倍,即200赫兹。由于实验板仅具备48MHz晶振,因此需要设计一个分频器对时钟信号进行分频。根据设计要求,需要具备可以暂停计时的功能,因此秒表系统中需要加入一个锁存器模块以对数据进行锁存。考虑到实际按键过程中经常出现按键抖动的情况,这对精确计时造成了极大的危害,因此,在计时系统中需要具备按键消抖模块。此外,由于秒表工作时具备4种不同的状态,因此,状态控制模块也是必不可少的。
按照以上需求,可以得到整个电路的原理图如下图所示:
图2 系统模块图
从原理图可知,系统需要以下模块:
1.分频器:对晶体振荡器产生的时钟进行分频,产生时间基准信号。
2.计数器:对时间基准脉冲进行计数,完成计时功能。
3.数据锁存器:锁存数据,使显示保持暂停。
4.控制器:控制计数器的运行、停止以及复位,产生锁存器的使能信号。
5.扫描显示的控制电路:包括扫描计数器、数据选择器和七段译码器,控制8个数码管以扫描方式,显示结果。
6.按键消抖电路:消除按键输入信号,输出单脉冲。
4.4 各模块的实现
4.4.1 分频器
XC3S200A芯片的外部有源晶振频率为48MHz,而计时器的最小单位为0.01s,即100Hz。考虑到系统的稳定性,本设计选择了1KHz的信号作为各模块的时钟信号,即对晶振信号进行1/48000、1/480000分频。
4.4.1.1 分频得到1KHz的时钟信号
对晶振时钟信号进行计数,标志位选择信号的上升沿:对每个上升沿,计数器加1;当计数达到23999时,下个上升沿计数器,当前电平取反,此时获得即为1KHZ的信号,源程序见附录2.
仿真结果如下图所示,时钟周期为48000。
图3 1KHz信号仿真图
4.4.1.2 分频得到100Hz的时钟信号
对晶振时钟信号进行计数,标志位选择信号的上升沿:对每个上升沿,计数器加1;当计数达到239999时,下个上升沿计数器,当前电平取反,此时获得即 为100HZ的信号,获得100HZ的源程序见附录3。
仿真结果如图4所示,时钟周期刚好为480000。
图4 100Hz信号仿真图
4.4.2 输入控制电路
输入控制模块的功能是识别有效地按键输入和实现输入的按键信号对电子秒表不同状态的控制。,秒表的状态可分为计数开/关,显示锁定开/关和清零。考到有两个输入按键,所以必须有输入控制电路,同时考虑到按下按键以及松开按键会出现抖动,所以必须设计防抖动电路。即按键输入信号,必须先经过防抖电路,然后进入控制电路。
4.4.2.1 防抖电路
由于按键输入,在按下过程中电平可能会有一个不确定的抖动状态。由于识别的有效按键电平为持续的低电平,在此设计一个计数器,具体思路为:当输入为低电平时候开始计数;当输入转为高电平时计数清零;初始输出值为‘0’;当低电平持续三个时钟周期,即计数为“10”时,停止计数,改变输出的状态(即‘0’变‘1’,‘1’变‘0’)。这种设计把一个瞬时信号变为持续信号,简化了之后的模块对信号的处理。去抖电路程序见附录4。
4.4.2.2 控制电路
图5 控制电路状态图
两个去抖动电路传入两个信号,将其组合成一个2bit输入(Start/Stop为高位,Split/Reset为低位),分别代表4个状态:
①“00”状态:锁定关,计数关,清零关,输出“111”;
②“10”状态:锁定关,计数开,清零关,输出“101”;
③“11”状态:锁定开,计数开,清零关,输出“001”;
④“01”状态:锁定关,计数关,清零开,输出“110”;处在“01”状态时,过一个时钟周期自动回到“00”状态。状态图如图5所示。源程序为见附录5。
4.4.3 计数模块
由设计指标可知,秒表由六位显示最大计时为59min59s99,所以需要4个10进制计数器,还有两个6进制计数器。其中有暂定,以及锁存的功能,所以需要每个计数器还需对应一个锁存器才能完成暂定以及锁存的功能。
4.4.3.1 十进制计数器
计数器迁入端每识别一个上升沿,就依次从“0000”计数到“1001”。当计数变为“1001”时,进位端从‘1’变为‘0’,在下个迁入的上升沿“1001”变为“0000”,进位端恢复‘1’。如此,将进位端连入下一级的迁入端时,可以实现低位由9变为0时高位进1。当清零信号有效时,计数器强制将计数值变为“0000”。源程序为见附录6.
4.4.3.2 六进制计数器
六进制计数范围是“0000”到“0110”,在“0110”时进位端发生变低,之后计数变为“0000”,进位端恢复高电平。对于六进制来说,三个二进制位就能够满足计数需要,但是考虑到后面译码器的输入均为四个二进制位,所以计数用4bit,方便译码。源程序为见附录7。
4.4.4 锁存器
锁存器实现电子秒表的显示锁定功能。其输入时钟为外部时钟(1kHz)。当锁定信号无效时,在每个时钟上升沿将输入的数据信号输出;当锁定信号有效时,输出的数据信号保持当前值,无视输入数据的改变,源程序见附录8。
4.4.5 显示模块
显示模块主要完成显示扫描和编码翻译的功能。其中需要用到扫描器,多路选择器和译码器, 时钟信号连接一个扫描器,用计数原理输出3bit扫描信号。该信号一方面接到外部的3-8译码器中,实现对八位数码管的扫描;另一方面选择信号接入一个4bit8输入1输出的多路选择器中,把数码管和相应位的数字信号联系起来。多路选择器的信号输出接译码器,把二进制信号编译成数码管上显示的十进制数。
4.4.5.1 扫描器
扫描器实现了八位数码管共用一组输入数据的可能性,其原理图如图6所示。其通过一个计数器,在每个时钟信号的上升沿,其输出的三位二进制信号加一,从“000”计数到“111”。当输出为“111”时,下一个时钟上升沿输出变为“000”,源程序见附录9。
图6 扫描电路原理图
4.4.5.2 数据选择器
多路选择器输入八组四位数据信号和一组三位扫描信号,通过扫描信号的状态选择相应的数据信号进行输出源程序,源程序见附录10。
4.4.5.3 七段译码器
译码器对四位二进制输入数据进行处理,将其转化成适合于数码管显示的八位二进制数据,如图7所示。源程序见附录11。
图7七段译码器电路图
4.5 分配引脚和下载实现
全部仿真通过后,就运行ISE的设计实现,然后再打开XILINX PACE,在里面分配引脚,即实现设计的输入输出端口与实际芯片的输入输出端口的对应连接。比如七段LED管的控制信号就连接到实际电路的七个引脚。
总的电路图如图8所示
图8 电子秒表总电路图
4.6 实验结果
在成功下载并运行后,进行了各按钮功能的检测(包括计数、暂停、复位、清零等功能的检查),以及与标准时间进行了对比,符合实验预估的各项指标,如图9所示。
图9 实验结果
第五章 结论
5.1 实验结论
本文主要介绍了利用VHDL语言完成基于FPGA的数字秒表的设计与实现。详细介绍了测量原理,设计方案以及各模块的设计过程及其实现的功能,并对设计中遇到的问题作了分析和处理;利用ISE和ModelSim对设计进行了仿真,分析,综合,并最终下载到芯片中,实现了预计的各项指标。
5.2 心得体会
经过这次的课程设计,我对课题设计的基本流程有了一定的认识。原本以为VHDL是无法掌握的语言,刚开始的时候不知道从何下手,所以进度会非常慢人也比较着急。但是后来静下心一个模块的设计,自己的自信心也开始建立了, 经过一周的努力和实践发现掌握XILINX ISE软件的基本语言和操作时可以实现 的。在老师给的指导下,我学习了软件的操作、基本的语句 、正规的编程方法, 把原来所学的书本知识和实践相联系。将秒表这个看似很大的工程,分成若干个小块各击破,最终通过了老师的验收。所以做这个秒表最重要的就是耐心和毅力, 只一步坚持就一定会得到自己满意的结果。而在通过时序逻辑编写电路的各个模块过程中建立起了学习编程语言的浓厚兴趣。在设计中也深刻体会到了清晰编程思路和适当注释的重要性。为以后更好的学习VHDL打下了基础 ,通过这次课程设计 ,我意识到了对这门课程掌握还有一定的不足, 比如经常嵌套多层if,导 致电路过于复杂,逻辑混乱软件最终无法达到最终目的。因为个人能力和知识的限制,还有许多的知识我不了解。
参考文献
[1]. 阎石.数字电子技术基础.北京:高等教育出版社,1998.
[2]. John F. Wakerly 数字设计原理与实践 第四版 机械工业出版社
[3]. 徐文波/田耘 Xillinx FPGA开发使用教程 清华大学出版社
[4]. www.xilinx.com.
致谢
首先必须感谢的是刘曦老师对我的教导,在实验过程中对我的帮助,在此对刘曦老师致于最衷心的感谢。其次感谢我的同学们,在我遇到问题时,能给我分析以及解决。
附 录
附录1 电子秒表的顶层文件
--Device utilization summary:
-----------------------------
--
--Selected Device : 3s200aft256-4
--
-- Number of Slices: 57 out of 1792 3% -- Number of Slice Flip Flops: 81 out of 3584 2% -- Number of 4 input LUTs: 108 out of 3584 3% -- Number of IOs: 14
-- Number of bonded IOBs: 14 out of 195 7% -- Number of GCLKs: 3 out of 24 12%
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
---- Uncomment the following library declaration if instantiating ---- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;
entity top4 is
port(clk_in:in std_logic:='0';
clr_in,start_in:in std_logic:='0';
shuma:out std_logic_vector(6 downto 0);
xuan:out std_logic_vector(3 downto 0));
end top4;
architecture Behavioral of top4 is
signal a,b,c,d,e,f,a1,b1,c1,d1,e1,f1: std_logic_vector(3 downto 0); signal clk_in_1k : std_logic;
signal clr_out,start_out : std_logic;
signal kong0,kong1,kong2 : std_logic;
COMPONENT fenpin
PORT(
clk : IN std_logic;
clk_1k : OUT std_logic
);
END COMPONENT;
COMPONENT xiaodou
PORT(
clk : IN std_logic;
key_in1 : IN std_logic;
key_in2 : IN std_logic;
key_out_start : OUT std_logic;
key_out_reset : OUT std_logic
);
END COMPONENT;
COMPONENT suocun
PORT(
msec0 : IN std_logic_vector(3 downto 0);
msec1 : IN std_logic_vector(3 downto 0);
second0 : IN std_logic_vector(3 downto 0);
second1 : IN std_logic_vector(3 downto 0);
minute0 : IN std_logic_vector(3 downto 0);
minute1 : IN std_logic_vector(3 downto 0);
con : IN std_logic;
omsec0 : OUT std_logic_vector(3 downto 0);
omsec1 : OUT std_logic_vector(3 downto 0);
osecond0 : OUT std_logic_vector(3 downto 0); osecond1 : OUT std_logic_vector(3 downto 0); ominute0 : OUT std_logic_vector(3 downto 0); ominute1 : OUT std_logic_vector(3 downto 0) );
END COMPONENT;
COMPONENT xianshikongzhi
PORT(
clk_1k : IN std_logic;
msec0 : IN std_logic_vector(3 downto 0);
msec1 : IN std_logic_vector(3 downto 0);
second0 : IN std_logic_vector(3 downto 0);
second1 : IN std_logic_vector(3 downto 0);
minute0 : IN std_logic_vector(3 downto 0);
minute1 : IN std_logic_vector(3 downto 0); shumaguan : OUT std_logic_vector(6 downto 0); n : OUT std_logic_vector(3 downto 0)
);
END COMPONENT;
COMPONENT kongzhi
PORT(
clk_1k : IN std_logic;
rst : IN std_logic;
state : IN std_logic;
kongclr : OUT std_logic;
kongen : OUT std_logic;
kongnormal : OUT std_logic
);
END COMPONENT;
COMPONENT jishu
PORT(
clk_1k : IN std_logic;
clr : IN std_logic;
cou : IN std_logic;
msec0 : OUT std_logic_vector(3 downto 0); msec1 : OUT std_logic_vector(3 downto 0); second0 : OUT std_logic_vector(3 downto 0); second1 : OUT std_logic_vector(3 downto 0); minute0 : OUT std_logic_vector(3 downto 0); minute1 : OUT std_logic_vector(3 downto 0) );
END COMPONENT;
begin
Inst_fenpin: fenpin PORT MAP(
clk => clk_in,
clk_1k => clk_in_1k
);
Inst_xiaodou: xiaodou PORT MAP(
clk => clk_in_1k,
key_in1 => start_in,
key_in2 => clr_in,
key_out_start => start_out,
key_out_reset => clr_out
);
Inst_suocun: suocun PORT MAP(
msec0 => a,
msec1 => b,
second0 => c,
second1 => d,
minute0 => e,
minute1 => f,
con => kong2,
omsec0 => a1,
omsec1 => b1,
osecond0 => c1,
osecond1 => d1,
ominute0 => e1,
ominute1 => f1
);
Inst_xianshikongzhi: xianshikongzhi PORT MAP( clk_1k => clk_in_1k,
msec0 => a1,
msec1 => b1,
second0 => c1,
second1 => d1,
minute0 => e1,
minute1 => f1,
shumaguan => shuma,
n => xuan
);
Inst_kongzhi: kongzhi PORT MAP(
clk_1k => clk_in_1k,
rst => clr_out,
state => start_out,
kongclr => kong0,
kongen => kong1,
kongnormal => kong2
);
Inst_jishu: jishu PORT MAP(
clk_1k => clk_in_1k,
clr => kong0,
cou => kong1,
msec0 => a,
msec1 => b,
second0 => c,
second1 => d,
minute0 => e,
minute1 => f
);
end Behavioral;
附录2 分频得到1KHZ时钟信号
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity fenpin is
port(clk:in std_logic;
clk_1k:out std_logic);
end fenpin;
architecture Behavioral of fenpin is
--signal count:integer range 0 to 47999:=0;
signal count:std_logic_vector(15 downto 0):=(others=>'0'); signal cl:std_logic:='1';
begin
process(clk)
begin
if rising_edge(clk) then
if count=47999 then
count'0');
else
count
end if;
else
count
end if;
end process;
--cl
clk_1k
end Behavioral;
附录3 消抖电路
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
---- Uncomment the following library declaration if instantiating ---- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;
entity xiaodou is
port(clk,key_in1,key_in2:in std_logic;
key_out_start,key_out_reset:out std_logic);
end xiaodou;
architecture Behavioral of xiaodou is
signal cnt,cnt1:std_logic_vector(1 downto 0);
signal k1,k2,k3,k4:std_logic;
begin
process(key_in1,clk)
begin
if clk'event and clk='0' then
if cnt=3 then
k1
else k1
cnt
end if;
k2
end if;
if key_in2='0' then
cnt
end if;
end process;
process(key_in2,clk)
begin
if clk'event and clk='0' then
if cnt1=3 then
k3
else k3
cnt1
end if;
k4
end if;
if key_in1='0' then
cnt1
end if;
end process;
key_out_start
key_out_reset
end Behavioral;
附录4 锁存程序
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
---- Uncomment the following library declaration if instantiating ---- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;
entity suocun is
port(msec0,msec1,second0,second1,minute0,minute1:in
std_logic_vector(3 downto 0);
con:in std_logic;
omsec0,omsec1,osecond0,osecond1,ominute0,ominute1:out std_logic_vector(3 downto 0));
end suocun;
architecture Behavioral of suocun is
signal a,b,c,d,e,f:std_logic_vector(3 downto 0);
begin
process(con,msec0,msec1,second0,second1,minute0,minute1)
begin
if con='1' then
a
b
c
d
e
f
end if;
end process;
omsec0
omsec1
osecond0
osecond1
ominute0
ominute1
end Behavioral;
附录5 显示控制程序
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
---- Uncomment the following library declaration if instantiating ---- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;
entity xianshikongzhi is
port(clk_1k:in std_logic;
msec0,msec1,second0,second1,minute0,minute1:in
std_logic_vector(3 downto 0);
shumaguan:out std_logic_vector(6 downto 0):=
n:out std_logic_vector(3 downto 0));
end xianshikongzhi;
architecture Behavioral of xianshikongzhi is
signal weixuan:std_logic_vector(3 downto 0):=
signal number:std_logic_vector(2 downto 0):=
signal xianshi:std_logic_vector(6 downto 0):=
signal shu:std_logic_vector(3 downto 0):=
begin
p1:process(clk_1k,number)
begin
if rising_edge(clk_1k) then
number
end if;
end process;
process(number,msec0,msec1,second0,second1,minute0,minute1) begin
case number is
when
when
when
when
when
when
when
when
when others=>weixuan
end case;
end process;
n
process(weixuan)
begin
case weixuan is
when
when
when
when
when
when
when
when
when others=>shu
end case;
end process;
p2:process(shu)
begin
case shu is
when
when
when
when
when
when
when
when
when
when
when others=>xianshi
end case;
end process;
shumaguan
end Behavioral;
附录6 控制程序
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
---- Uncomment the following library declaration if instantiating ---- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;
entity kongzhi is
port(clk_1k,rst,state:in std_logic;
kongclr,kongen,kongnormal:out std_logic);
end kongzhi;
architecture Behavioral of kongzhi is
signal c_com:std_logic_vector(2 downto 0):=
signal c:std_logic_vector(1 downto 0);
begin
c
process(c)
begin
case c_com is
when
when
when others=>n_com
when
when
when
when others=>n_com
when
when
when
when others=>n_com
when
when
when others=>n_com
when others=> n_com
end case;
end process;
process(clk_1k)
begin
if rising_edge(clk_1k) then
c_com
end if;
end process;
kongclr
kongen
kongnormal
end Behavioral;
附录8 译码器程序
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity jishu is
port(clk_1k:in std_logic:='0';
clr:in std_logic;
cou:in std_logic;
msec0,msec1,second0,second1,minute0,minute1:out std_logic_vector(3 downto 0):=
end jishu;
architecture Behavioral of jishu is
signal a,b,c,d,e,f:std_logic_vector(3 downto 0);
--signal clk_100: std_logic:='0';
signal count:std_logic_vector(3 downto 0):=(others=>'0'); begin
process(clk_1k)
begin
if rising_edge(clk_1k) then
if count=9 then
count
--clk_100
else
count
end if;
end if;
end process;
process(count(3),clr)
begin
if clr='1' then
a
b
c
d
e
f
else
if rising_edge(count(3)) then
if cou='1' then
if a=
a
if b=
b
if c=
c
if d=
d
if e=
e
if f=
else f
end if;
else e
end if;
else d
end if;
else c
end if;
else b
end if;
else a
end if;
else a
else a
end if;
end process;
msec0
msec1
second0
second1
minute0
minute1
end Behavioral;
现代电子技术综合实验
电子秒表设计
学生姓名:学 号:指导老师:学 院:提交时间:
摘要
本文介绍了使用VHDL开发FPGA的一般流程,重点介绍了电子秒表的设计。该设计以VHDL作为硬件开发语言,以ISE作为软件开发平台,准确地实现了秒表计数、清零、暂停等功能,并使用ModelSim仿真软件对VHDL程序实现了
仿真,完成了综合布局布线,最终将程序下载到芯片Spartan-3A,测试结果良好。
关键字:FPGA VHDL ISE ModelSim 电子秒表
目 录
第一章 引言————————————————————————————4
第二章 基于FPGA的VHDL设计流程——————————————————4
2.1 时间的概念及计时方法————————————————————4
2.2 VHDL语言简介———————————————————————4
2.2.1 VHDL语言特点————————————————————-4
2.2.2 VHDL语言优势————————————————————-6
2.3 FPGA简介—————————————————————————6
2.3.1 FPGA的主要特点———————————————————-6
2.3.2 FPGA的开发流程————————————————————6
第三章 电子秒表的软件开发环境———————————————————6
3.1 ModelSim简介————————————————————————7
3.1.1 ModelSim的特点————————————————————-7
3.2 ISE简介——————————————————————————-7
第四章 电子秒表的设计与实现————————————————————-7
4.1 实验任务——————————————————————————9
4.2 实验条件——————————————————————————9
4.3 系统需求和解决方案—————————————————————9
4.4 各模块的实现————————————————————————9
4.4.1 分频器————————————————————————10
4.4.1.1 分频得到1KHz的时钟信号—————————————10
4.4.1.2 分频得到100Hz的时钟信号————————————10
4.4.2 输入控制电路—————————————————————11
4.4.2.1 防抖电路————————————————————11
4.4.2.2 控制电路————————————————————11
4.4.3 计数模块———————————————————————12
4.4.3.1 十进制计数器——————————————————12
4.4.3.2 六进制计数器——————————————————13
4.4.4 锁存器————————————————————————13
4.4.5 显示模块———————————————————————13
4.4.5.1 扫描器—————————————————————13
4.4.5.2 数据选择器———————————————————14
4.4.5.3 七段译码器———————————————————14
4.5 分配引脚和下载实现————————————————————-14
4.6 实验结果及仿真——————————————————————-15
第五章 结论———————————————————————————15
5.1 实验结论—————————————————————————15
5.2 心得体会—————————————————————————15 参考文献———————————————————————————16 致谢—————————————————————————————16 附 录————————————————————————————17
第一章 引言
随着现代电子科技的发展,各种新型的电子产品层出不穷,而高精度的电子秒表作为电子产品的一部分,在人们的日常生产、生活中发挥着极其重要的作用。
本文主要任务是针对设计的要求,基于FPGA利用硬件描述语言VHDL完成秒表的设计,并且通过仿真、分析、综合从而实现计数、清零、暂停等功能。该系统具有高速、精确、可靠、抗干扰性强和现场可编程等优点,且系统成本非常低廉,适用于大规模地生产和应用。
第二章 基于FPGA的VHDL设计流程
2.1 时间的概念及计时方法
时间是物理学中的七个基本量纲之一,符号t。
在国际单位制(SI)中,时间的额吉本单位是秒,符号s,在1967年召开的第13届国际度量衡大会对秒的定义是:銫133原子基态的两个超精细能阶间跳跃对应辐射的9,192,631,770个周期的持续时间。这个定义提到的铯原子必须在绝对零度是静止的,而且在地面上的环境是零磁场。在这样的情况下被定义的秒,在天文学上的历书时所定义的秒是等效的。
中国古代的计时器有太阳钟和机械钟两种。太阳钟是以太阳的投影和方位来计时的。代表有土圭、圭表、日晷等。而由于地球轨道偏心率以及地球倾角的影响,真太阳时和平太阳时是不一致的,机械钟应运而生,代表有水钟、沙漏等。 时间已经走到21世纪,为了更加精确的测量时间,现代人使用了很多方法。最常用的包括有机械时钟和电子时钟。本文介绍的电子秒表便是电子时钟的一种。我们将基于FPGA和EDA软件来制作一款秒表,已达到计时的目的。
2.2 VHDL语言简介 VHDL语言是一种用于电路设计的高级语言。它在80年代的后期出现。最初是由美国国防部开发出来供美军用来提高设计的可靠性和缩减开发周期的一种使用范围较小的设计语言 。
VHDL翻译成中文就是超高速集成电路硬件描述语言,主要是应用在数字电路的设计中。它在中国的应用多数是用在FPGA/CPLD/EPLD的设计中。当然在一些实力较为雄厚的单位,它也被用来设计ASIC。
VHDL主要用于描述数字系统的结构,行为,功能和接口。除了含有许多具有硬件特征的语句外,VHDL的语言形式、描述风格以及语法是十分类似于一般的计算机高级语言。VHDL的程序结构特点是将一项工程设计,或称设计实体(可以是一个元件,一个电路模块或一个系统)分成外部(或称可视部分,及端口)和内部(或称不可视部分),既涉及实体的内部功能和算法完成部分。在对一个
设计实体定义了外部界面后,一旦其内部开发完成后,其他的设计就可以直接调用这个实体。这种将设计实体分成内外部分的概念是VHDL系统设计的基本点。
2.2.1 VHDL语言特点 与其他硬件描述语言相比,VHDL具有以下特点:
功能强大、设计灵活
VHDL具有功能强大的语言结构,可以用简洁明确的源代码来描述复杂的逻辑控制。它具有多层次的设计描述功能,层层细化,最后可直接生成电路级描述。VHDL支持同步电路、异步电路和随机电路的设计,这是其他硬件描述语言所不能比拟的。VHDL还支持各种设计方法,既支持自底向上的设计,又支持自顶向下的设计;既支持模块化设计,又支持层次化设计。
支持广泛、易于修改
由于VHDL已经成为IEEE标准所规范的硬件描述语言,大多数EDA工几乎都支持VHDL,这为VHDL的进一步推广和广泛应用奠定了基础。在硬件电路设计过程中,主要的设计文件是用VHDL编写的源代码,因为VHDL易读和结构化,所以易于修改设计。
强大的系统硬件描述能力
VHDL具有多层次的设计描述功能,既可以描述系统级电路,又可以描述门级电路。而描述既可以采用行为描述、寄存器传输描述或结构描述,也可以采用三者混合的混合级描述。另外,VHDL支持惯性延迟和传输延迟,还可以准确地建立硬件电路模型。VHDL支持预定义的和自定义的数据类型,给硬件描述带来较大的自由度,使设计人员能够方便地创建高层次的系统模型。
独立于器件的设计、与工艺无关
设计人员用VHDL进行设计时,不需要首先考虑选择完成设计的器件,就可以集中精力进行设计的优化。当设计描述完成后,可以用多种不同的器件结构来实现其功能。
很强的移植能力
VHDL是一种标准化的硬件描述语言,同一个设计描述可以被不同的工具所支持,使得设计描述的移植成为可能。
易于共享和复用
VHDL采用基于库(Library)的设计方法,可以建立各种可再次利用的模块。这些模块可以预先设计或使用以前设计中的存档模块,将这些模块存放到库中,就可以在以后的设计中进行复用,可以使设计成果在设计人员之间进行交流和共享,减少硬件电路设计。
2.2.2 VHDL语言优势 (1)与其他的硬件描述语言相比,VHDL具有更强的行为描述能力,从而决定了他成为系统设计领域最佳的硬件描述语言。强大的行为描述能力是避开具体的器件结构,从逻辑行为上描述和设计大规模电子系统的重要保证。
(2)VHDL丰富的仿真语句和库函数,使得在任何大系统的设计早期就能查验设计系统的功能可行性,随时可对设计进行仿真模拟。
(3)VHDL语句的行为描述能力和程序结构决定了他具有支持大规模设计的分解和已有设计的再利用功能。符合市场需求的大规模系统高效,高速的完成必须有多人甚至多个代发组共同并行工作才能实现。
(4)对于用VHDL完成的一个确定的设计,可以利用EDA工具进行逻辑综合和优化,并自动的把VHDL描述设计转变成门级网表。
(5)VHDL对设计的描述具有相对独立性,设计者可以不懂硬件的结构,也不必管理最终设计实现的目标器件是什么,而进行独立的设计。
2.3 FPGA简介
FPGA是英文Field Programmable Gate Array的缩写,即现场可编程门阵列,它是在PAL、GAL、EPLD等可编程器件的基础上进一步发展的产物。它是作为专门集成电路(ASIC)领域中的一种半定制电路而出现的,既解决了定制电路的不足,又克服了原有可编程器件门电路数有限的缺点。
FPGA采用了逻辑单元阵列LCA(Logic Cell Array)这样一个新概念,内部包括可配置逻辑模块CLB(Configurable Logic Block)、输出输入模块IOB(Input Output Block)和内部连线(Interconnect)三个部分。
2.3.1 FPGA的主要特点
(1)采用FPGA设计ASIC电路,用户不需要投片生产,就能得到合用的芯片。
(2)FPGA可做其它全定制或半定制ASIC电路的中试样片。
(3)FPGA内部有丰富的触发器和I/O引脚。
(4)FPGA是ASIC电路中设计周期最短、开发费用最低、风险最小的器件之一。
(5)FPGA采用高速CHMOS工艺,功耗低,可以与CMOS、TTL电平兼容。 可以说,FPGA芯片是小批量系统提高系统集成度、可靠性的最佳选择之一。
2.3.2 FPGA的开发流程
FPGA开发一般可分为以下七部分:
1、文本编辑:用任何文本编辑器都可以进行,也可以用专用的HDL编辑环境。通常VHDL文件保存为.vhd文件
2、功能仿真:将文件调入HDL仿真软件进行功能仿真,检查逻辑功能是否正确(也叫前仿真,对简单的设计可以跳过这一步,只在布线完成以后,进行时序仿真)
3、逻辑综合:将源文件调入逻辑综合软件进行综合,即把语言综合成最简的布尔表达式。逻辑综合软件会生成.edf(edif)的EDA工业标准文件。
4、布局布线:将.edf文件调入PLD厂家提供的软件中进行布线,即把设计好的逻辑安放到PLD/FPGA内。
5、时序仿真:需要利用在布局布线中获得的精确参数,用仿真软件验证电路的时序。(也叫后仿真)
6、编程下载:确认仿真无误后,将文件下载到芯片中
7、硬件测试:硬件测试的目的是为了在更真实的环境中检验HDL设计的运行情况,特别是对于HDL程序设计上不是十分规范,语义上含有一定歧义的程序。
第三章 电子秒表的软件开发环境
本章主要介绍项目中将要用到了一系列软件,包括用于VHDL语言编写和编译的ISE软件和用于程序仿真的仿真软件ModelSim。
3.1 ModelSim简介
Mentor公司的ModelSim是业界最优秀的HDL语言仿真软件,它能提供友好的仿真环境,是业界唯一的单内核支持VHDL和Verilog混合仿真的仿真器。它采用直接优化的编译技术、Tcl/Tk技术、和单一内核仿真技术,编译仿真速度快,编译的代码与平台无关,便于保护IP核,个性化的图形界面和用户接口,为用户加快调错提供强有力的手段,是FPGA/ASIC设计的首选仿真软件。
3.1.1 ModelSim的特点 · RTL和门级优化,本地编译结构,编译仿真速度快,跨平台跨版本仿真; · 单内核VHDL和Verilog混合仿真;
· 源代码模版和助手,项目管理;
· 集成了性能分析、波形比较、代码覆盖、数据流ChaseX、Signal Spy、虚拟对象Virtual Object、Memory窗口、Assertion窗口、源码窗口显示信号值、信号条件断点等众多调试功能;
· C和Tcl/Tk接口,C调试;
· 对SystemC的直接支持,和HDL任意混合;
· 支持SystemVerilog的设计功能;
· 对系统级描述语言的最全面支持,SystemVerilog,SystemC,PSL; · ASIC Sign off。
· 可以单独或同时进行行为(behavioral)、RTL级、和门级(gate-level)的代码。
3.2 ISE简介
ISEt是Xilinx公司提供的集成化FPGA开发软件,它的主要功能包括设计 输入、综合、仿真、实现和下载。
(1)设计输入
ISE软件提供的设计输入工具包括用于HDL代码输入和报告查看的ISE文本编辑器(TextEditor),用于原理图编辑的工具ECS(Engineering CaptureSystem),用于P CORE的COREGenerator,用于状态机设计的StateCAD,以及用于约束文件编辑的Constraint Editor等。
(2)综合
ISE的综合工具不但包括了Xilinx自身提供的综合工具xsr,同时还可以集成MentorGraphics公司的LeonardoSpectrum和Synplicity公司的Synplify。
(3)仿真
ISE本身自带了图形化波形编辑功能的仿真工具HDL Bencher,同时又提供了使用ModelTechnology公司的ModelSim进行仿真的接口。
(4)实现
ISE的实现功能包括了翻译(Translate)、映射(Map)、布局布线(Place andRoute)等。
(5)下载
下载功能包括了BitGen,用于将布局布线后的设计文件转换为比特流(Bitstream)文件。还包括了iMPACT功能,用于进行设备配置和通信,控制将程序烧写到FPGA芯片中去。
使用ISE进行FPGA开发大致可以分为3个步骤。
(1)设计输入和仿真
设计输入(Design Entry)是指以HDL代码、原理图、波形图以及状态机的形式输入设汁源文件,而设计仿真(Simdmion)是指通过仿真工具对设计的整体模块或局部模块进行仿真来检验设计的功能和性能。
(2)用户约束条件、综合和实现
用户约束条件(User Constraints)的作用是对综合、实现过程进行控制,满足速度、面积、引脚位置等需求。编辑约束条件又包括了4个子项,意义分别为:创建时间约束、配置引脚、创建面积约束、以文本方式编辑约束。综合(Synthesize)是FPGA设计流程中的重要环节,综合结果的优劣直接影响到设计的最终性能。
ISE自带的综合工具是XST,同时它也支持Synplify/Synplify Pro等第三方综合工具,但是由于Xilinx对于其器件的底层最为了解,所以使用XST综合往往会得到比较满意的结果。综合包含了3个子项,意义分别为:查看综合报告、查看综合器件的RTL级原理图和检查语法。实现(Implementation)过程也包含了3个子项,ImplementDesign项所对应的子项,意义分别是:翻译、映射和布局布线。需要注意,进行实现步骤之前必须进行约束条件的编辑,否则实现可能会出错。
(3)硬件编程
硬件编程(Programming)是指生成编辑比特流文件bit,并将其下载到FPGA芯片内部的过程。硬件编程对应图2--5所示的Generate Programming File项。
第四章 电子表秒的设计与实现
4.1 实验任务
设计一个秒表,秒表的计时范围为00’00”00 ~
59’59”99。有两个按钮开关Start/Stop和
Split/Reset,控制秒表的启动、停止、分段和复位:
1. 在秒表已经被复位的情况下,按下
“Start/Stop”键,秒表开始计时。
2. 在秒表正常运行的情况下,如果按下
“Start/Stop”键,则秒表暂停计时。
3. 再次按下该键,秒表继续计时。
4. 在秒表正常运行的情况下,如果按下
“Split/Reset”键,显示停止在按键时的时
间,但秒表仍然在计时。
5. 再次按下该键,秒表恢复正常显示。
6. 在秒表暂停计时的情况下,按下
“Split/Reset”键,秒表复位归零。
4.2 实验条件
我们将利用EDA软件和
HDL语言在EEC-FPGA实验板上完成秒表的设计与实现,实验板原理如图1所示。在项目开始设计时,首先要确定系统的需求并发展出一个针对这些需求的计划。设计方案以及系统需求必须按照设计要求并根据客
观条件来确定。
图1 实验板原理图
4.3 系统需求和解决方案
根据实验板原理图可以发现,数码管为共阳极输出,因此,为了能够使八盏数码管同时显示时间,我们需要设置一个扫描显示控制模块以进行扫频。由于计时精度精确到0.01秒,因此根据数据采集定理,分频后的频率应至少为计时精度的两倍,即200赫兹。由于实验板仅具备48MHz晶振,因此需要设计一个分频器对时钟信号进行分频。根据设计要求,需要具备可以暂停计时的功能,因此秒表系统中需要加入一个锁存器模块以对数据进行锁存。考虑到实际按键过程中经常出现按键抖动的情况,这对精确计时造成了极大的危害,因此,在计时系统中需要具备按键消抖模块。此外,由于秒表工作时具备4种不同的状态,因此,状态控制模块也是必不可少的。
按照以上需求,可以得到整个电路的原理图如下图所示:
图2 系统模块图
从原理图可知,系统需要以下模块:
1.分频器:对晶体振荡器产生的时钟进行分频,产生时间基准信号。
2.计数器:对时间基准脉冲进行计数,完成计时功能。
3.数据锁存器:锁存数据,使显示保持暂停。
4.控制器:控制计数器的运行、停止以及复位,产生锁存器的使能信号。
5.扫描显示的控制电路:包括扫描计数器、数据选择器和七段译码器,控制8个数码管以扫描方式,显示结果。
6.按键消抖电路:消除按键输入信号,输出单脉冲。
4.4 各模块的实现
4.4.1 分频器
XC3S200A芯片的外部有源晶振频率为48MHz,而计时器的最小单位为0.01s,即100Hz。考虑到系统的稳定性,本设计选择了1KHz的信号作为各模块的时钟信号,即对晶振信号进行1/48000、1/480000分频。
4.4.1.1 分频得到1KHz的时钟信号
对晶振时钟信号进行计数,标志位选择信号的上升沿:对每个上升沿,计数器加1;当计数达到23999时,下个上升沿计数器,当前电平取反,此时获得即为1KHZ的信号,源程序见附录2.
仿真结果如下图所示,时钟周期为48000。
图3 1KHz信号仿真图
4.4.1.2 分频得到100Hz的时钟信号
对晶振时钟信号进行计数,标志位选择信号的上升沿:对每个上升沿,计数器加1;当计数达到239999时,下个上升沿计数器,当前电平取反,此时获得即 为100HZ的信号,获得100HZ的源程序见附录3。
仿真结果如图4所示,时钟周期刚好为480000。
图4 100Hz信号仿真图
4.4.2 输入控制电路
输入控制模块的功能是识别有效地按键输入和实现输入的按键信号对电子秒表不同状态的控制。,秒表的状态可分为计数开/关,显示锁定开/关和清零。考到有两个输入按键,所以必须有输入控制电路,同时考虑到按下按键以及松开按键会出现抖动,所以必须设计防抖动电路。即按键输入信号,必须先经过防抖电路,然后进入控制电路。
4.4.2.1 防抖电路
由于按键输入,在按下过程中电平可能会有一个不确定的抖动状态。由于识别的有效按键电平为持续的低电平,在此设计一个计数器,具体思路为:当输入为低电平时候开始计数;当输入转为高电平时计数清零;初始输出值为‘0’;当低电平持续三个时钟周期,即计数为“10”时,停止计数,改变输出的状态(即‘0’变‘1’,‘1’变‘0’)。这种设计把一个瞬时信号变为持续信号,简化了之后的模块对信号的处理。去抖电路程序见附录4。
4.4.2.2 控制电路
图5 控制电路状态图
两个去抖动电路传入两个信号,将其组合成一个2bit输入(Start/Stop为高位,Split/Reset为低位),分别代表4个状态:
①“00”状态:锁定关,计数关,清零关,输出“111”;
②“10”状态:锁定关,计数开,清零关,输出“101”;
③“11”状态:锁定开,计数开,清零关,输出“001”;
④“01”状态:锁定关,计数关,清零开,输出“110”;处在“01”状态时,过一个时钟周期自动回到“00”状态。状态图如图5所示。源程序为见附录5。
4.4.3 计数模块
由设计指标可知,秒表由六位显示最大计时为59min59s99,所以需要4个10进制计数器,还有两个6进制计数器。其中有暂定,以及锁存的功能,所以需要每个计数器还需对应一个锁存器才能完成暂定以及锁存的功能。
4.4.3.1 十进制计数器
计数器迁入端每识别一个上升沿,就依次从“0000”计数到“1001”。当计数变为“1001”时,进位端从‘1’变为‘0’,在下个迁入的上升沿“1001”变为“0000”,进位端恢复‘1’。如此,将进位端连入下一级的迁入端时,可以实现低位由9变为0时高位进1。当清零信号有效时,计数器强制将计数值变为“0000”。源程序为见附录6.
4.4.3.2 六进制计数器
六进制计数范围是“0000”到“0110”,在“0110”时进位端发生变低,之后计数变为“0000”,进位端恢复高电平。对于六进制来说,三个二进制位就能够满足计数需要,但是考虑到后面译码器的输入均为四个二进制位,所以计数用4bit,方便译码。源程序为见附录7。
4.4.4 锁存器
锁存器实现电子秒表的显示锁定功能。其输入时钟为外部时钟(1kHz)。当锁定信号无效时,在每个时钟上升沿将输入的数据信号输出;当锁定信号有效时,输出的数据信号保持当前值,无视输入数据的改变,源程序见附录8。
4.4.5 显示模块
显示模块主要完成显示扫描和编码翻译的功能。其中需要用到扫描器,多路选择器和译码器, 时钟信号连接一个扫描器,用计数原理输出3bit扫描信号。该信号一方面接到外部的3-8译码器中,实现对八位数码管的扫描;另一方面选择信号接入一个4bit8输入1输出的多路选择器中,把数码管和相应位的数字信号联系起来。多路选择器的信号输出接译码器,把二进制信号编译成数码管上显示的十进制数。
4.4.5.1 扫描器
扫描器实现了八位数码管共用一组输入数据的可能性,其原理图如图6所示。其通过一个计数器,在每个时钟信号的上升沿,其输出的三位二进制信号加一,从“000”计数到“111”。当输出为“111”时,下一个时钟上升沿输出变为“000”,源程序见附录9。
图6 扫描电路原理图
4.4.5.2 数据选择器
多路选择器输入八组四位数据信号和一组三位扫描信号,通过扫描信号的状态选择相应的数据信号进行输出源程序,源程序见附录10。
4.4.5.3 七段译码器
译码器对四位二进制输入数据进行处理,将其转化成适合于数码管显示的八位二进制数据,如图7所示。源程序见附录11。
图7七段译码器电路图
4.5 分配引脚和下载实现
全部仿真通过后,就运行ISE的设计实现,然后再打开XILINX PACE,在里面分配引脚,即实现设计的输入输出端口与实际芯片的输入输出端口的对应连接。比如七段LED管的控制信号就连接到实际电路的七个引脚。
总的电路图如图8所示
图8 电子秒表总电路图
4.6 实验结果
在成功下载并运行后,进行了各按钮功能的检测(包括计数、暂停、复位、清零等功能的检查),以及与标准时间进行了对比,符合实验预估的各项指标,如图9所示。
图9 实验结果
第五章 结论
5.1 实验结论
本文主要介绍了利用VHDL语言完成基于FPGA的数字秒表的设计与实现。详细介绍了测量原理,设计方案以及各模块的设计过程及其实现的功能,并对设计中遇到的问题作了分析和处理;利用ISE和ModelSim对设计进行了仿真,分析,综合,并最终下载到芯片中,实现了预计的各项指标。
5.2 心得体会
经过这次的课程设计,我对课题设计的基本流程有了一定的认识。原本以为VHDL是无法掌握的语言,刚开始的时候不知道从何下手,所以进度会非常慢人也比较着急。但是后来静下心一个模块的设计,自己的自信心也开始建立了, 经过一周的努力和实践发现掌握XILINX ISE软件的基本语言和操作时可以实现 的。在老师给的指导下,我学习了软件的操作、基本的语句 、正规的编程方法, 把原来所学的书本知识和实践相联系。将秒表这个看似很大的工程,分成若干个小块各击破,最终通过了老师的验收。所以做这个秒表最重要的就是耐心和毅力, 只一步坚持就一定会得到自己满意的结果。而在通过时序逻辑编写电路的各个模块过程中建立起了学习编程语言的浓厚兴趣。在设计中也深刻体会到了清晰编程思路和适当注释的重要性。为以后更好的学习VHDL打下了基础 ,通过这次课程设计 ,我意识到了对这门课程掌握还有一定的不足, 比如经常嵌套多层if,导 致电路过于复杂,逻辑混乱软件最终无法达到最终目的。因为个人能力和知识的限制,还有许多的知识我不了解。
参考文献
[1]. 阎石.数字电子技术基础.北京:高等教育出版社,1998.
[2]. John F. Wakerly 数字设计原理与实践 第四版 机械工业出版社
[3]. 徐文波/田耘 Xillinx FPGA开发使用教程 清华大学出版社
[4]. www.xilinx.com.
致谢
首先必须感谢的是刘曦老师对我的教导,在实验过程中对我的帮助,在此对刘曦老师致于最衷心的感谢。其次感谢我的同学们,在我遇到问题时,能给我分析以及解决。
附 录
附录1 电子秒表的顶层文件
--Device utilization summary:
-----------------------------
--
--Selected Device : 3s200aft256-4
--
-- Number of Slices: 57 out of 1792 3% -- Number of Slice Flip Flops: 81 out of 3584 2% -- Number of 4 input LUTs: 108 out of 3584 3% -- Number of IOs: 14
-- Number of bonded IOBs: 14 out of 195 7% -- Number of GCLKs: 3 out of 24 12%
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
---- Uncomment the following library declaration if instantiating ---- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;
entity top4 is
port(clk_in:in std_logic:='0';
clr_in,start_in:in std_logic:='0';
shuma:out std_logic_vector(6 downto 0);
xuan:out std_logic_vector(3 downto 0));
end top4;
architecture Behavioral of top4 is
signal a,b,c,d,e,f,a1,b1,c1,d1,e1,f1: std_logic_vector(3 downto 0); signal clk_in_1k : std_logic;
signal clr_out,start_out : std_logic;
signal kong0,kong1,kong2 : std_logic;
COMPONENT fenpin
PORT(
clk : IN std_logic;
clk_1k : OUT std_logic
);
END COMPONENT;
COMPONENT xiaodou
PORT(
clk : IN std_logic;
key_in1 : IN std_logic;
key_in2 : IN std_logic;
key_out_start : OUT std_logic;
key_out_reset : OUT std_logic
);
END COMPONENT;
COMPONENT suocun
PORT(
msec0 : IN std_logic_vector(3 downto 0);
msec1 : IN std_logic_vector(3 downto 0);
second0 : IN std_logic_vector(3 downto 0);
second1 : IN std_logic_vector(3 downto 0);
minute0 : IN std_logic_vector(3 downto 0);
minute1 : IN std_logic_vector(3 downto 0);
con : IN std_logic;
omsec0 : OUT std_logic_vector(3 downto 0);
omsec1 : OUT std_logic_vector(3 downto 0);
osecond0 : OUT std_logic_vector(3 downto 0); osecond1 : OUT std_logic_vector(3 downto 0); ominute0 : OUT std_logic_vector(3 downto 0); ominute1 : OUT std_logic_vector(3 downto 0) );
END COMPONENT;
COMPONENT xianshikongzhi
PORT(
clk_1k : IN std_logic;
msec0 : IN std_logic_vector(3 downto 0);
msec1 : IN std_logic_vector(3 downto 0);
second0 : IN std_logic_vector(3 downto 0);
second1 : IN std_logic_vector(3 downto 0);
minute0 : IN std_logic_vector(3 downto 0);
minute1 : IN std_logic_vector(3 downto 0); shumaguan : OUT std_logic_vector(6 downto 0); n : OUT std_logic_vector(3 downto 0)
);
END COMPONENT;
COMPONENT kongzhi
PORT(
clk_1k : IN std_logic;
rst : IN std_logic;
state : IN std_logic;
kongclr : OUT std_logic;
kongen : OUT std_logic;
kongnormal : OUT std_logic
);
END COMPONENT;
COMPONENT jishu
PORT(
clk_1k : IN std_logic;
clr : IN std_logic;
cou : IN std_logic;
msec0 : OUT std_logic_vector(3 downto 0); msec1 : OUT std_logic_vector(3 downto 0); second0 : OUT std_logic_vector(3 downto 0); second1 : OUT std_logic_vector(3 downto 0); minute0 : OUT std_logic_vector(3 downto 0); minute1 : OUT std_logic_vector(3 downto 0) );
END COMPONENT;
begin
Inst_fenpin: fenpin PORT MAP(
clk => clk_in,
clk_1k => clk_in_1k
);
Inst_xiaodou: xiaodou PORT MAP(
clk => clk_in_1k,
key_in1 => start_in,
key_in2 => clr_in,
key_out_start => start_out,
key_out_reset => clr_out
);
Inst_suocun: suocun PORT MAP(
msec0 => a,
msec1 => b,
second0 => c,
second1 => d,
minute0 => e,
minute1 => f,
con => kong2,
omsec0 => a1,
omsec1 => b1,
osecond0 => c1,
osecond1 => d1,
ominute0 => e1,
ominute1 => f1
);
Inst_xianshikongzhi: xianshikongzhi PORT MAP( clk_1k => clk_in_1k,
msec0 => a1,
msec1 => b1,
second0 => c1,
second1 => d1,
minute0 => e1,
minute1 => f1,
shumaguan => shuma,
n => xuan
);
Inst_kongzhi: kongzhi PORT MAP(
clk_1k => clk_in_1k,
rst => clr_out,
state => start_out,
kongclr => kong0,
kongen => kong1,
kongnormal => kong2
);
Inst_jishu: jishu PORT MAP(
clk_1k => clk_in_1k,
clr => kong0,
cou => kong1,
msec0 => a,
msec1 => b,
second0 => c,
second1 => d,
minute0 => e,
minute1 => f
);
end Behavioral;
附录2 分频得到1KHZ时钟信号
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity fenpin is
port(clk:in std_logic;
clk_1k:out std_logic);
end fenpin;
architecture Behavioral of fenpin is
--signal count:integer range 0 to 47999:=0;
signal count:std_logic_vector(15 downto 0):=(others=>'0'); signal cl:std_logic:='1';
begin
process(clk)
begin
if rising_edge(clk) then
if count=47999 then
count'0');
else
count
end if;
else
count
end if;
end process;
--cl
clk_1k
end Behavioral;
附录3 消抖电路
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
---- Uncomment the following library declaration if instantiating ---- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;
entity xiaodou is
port(clk,key_in1,key_in2:in std_logic;
key_out_start,key_out_reset:out std_logic);
end xiaodou;
architecture Behavioral of xiaodou is
signal cnt,cnt1:std_logic_vector(1 downto 0);
signal k1,k2,k3,k4:std_logic;
begin
process(key_in1,clk)
begin
if clk'event and clk='0' then
if cnt=3 then
k1
else k1
cnt
end if;
k2
end if;
if key_in2='0' then
cnt
end if;
end process;
process(key_in2,clk)
begin
if clk'event and clk='0' then
if cnt1=3 then
k3
else k3
cnt1
end if;
k4
end if;
if key_in1='0' then
cnt1
end if;
end process;
key_out_start
key_out_reset
end Behavioral;
附录4 锁存程序
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
---- Uncomment the following library declaration if instantiating ---- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;
entity suocun is
port(msec0,msec1,second0,second1,minute0,minute1:in
std_logic_vector(3 downto 0);
con:in std_logic;
omsec0,omsec1,osecond0,osecond1,ominute0,ominute1:out std_logic_vector(3 downto 0));
end suocun;
architecture Behavioral of suocun is
signal a,b,c,d,e,f:std_logic_vector(3 downto 0);
begin
process(con,msec0,msec1,second0,second1,minute0,minute1)
begin
if con='1' then
a
b
c
d
e
f
end if;
end process;
omsec0
omsec1
osecond0
osecond1
ominute0
ominute1
end Behavioral;
附录5 显示控制程序
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
---- Uncomment the following library declaration if instantiating ---- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;
entity xianshikongzhi is
port(clk_1k:in std_logic;
msec0,msec1,second0,second1,minute0,minute1:in
std_logic_vector(3 downto 0);
shumaguan:out std_logic_vector(6 downto 0):=
n:out std_logic_vector(3 downto 0));
end xianshikongzhi;
architecture Behavioral of xianshikongzhi is
signal weixuan:std_logic_vector(3 downto 0):=
signal number:std_logic_vector(2 downto 0):=
signal xianshi:std_logic_vector(6 downto 0):=
signal shu:std_logic_vector(3 downto 0):=
begin
p1:process(clk_1k,number)
begin
if rising_edge(clk_1k) then
number
end if;
end process;
process(number,msec0,msec1,second0,second1,minute0,minute1) begin
case number is
when
when
when
when
when
when
when
when
when others=>weixuan
end case;
end process;
n
process(weixuan)
begin
case weixuan is
when
when
when
when
when
when
when
when
when others=>shu
end case;
end process;
p2:process(shu)
begin
case shu is
when
when
when
when
when
when
when
when
when
when
when others=>xianshi
end case;
end process;
shumaguan
end Behavioral;
附录6 控制程序
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
---- Uncomment the following library declaration if instantiating ---- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;
entity kongzhi is
port(clk_1k,rst,state:in std_logic;
kongclr,kongen,kongnormal:out std_logic);
end kongzhi;
architecture Behavioral of kongzhi is
signal c_com:std_logic_vector(2 downto 0):=
signal c:std_logic_vector(1 downto 0);
begin
c
process(c)
begin
case c_com is
when
when
when others=>n_com
when
when
when
when others=>n_com
when
when
when
when others=>n_com
when
when
when others=>n_com
when others=> n_com
end case;
end process;
process(clk_1k)
begin
if rising_edge(clk_1k) then
c_com
end if;
end process;
kongclr
kongen
kongnormal
end Behavioral;
附录8 译码器程序
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity jishu is
port(clk_1k:in std_logic:='0';
clr:in std_logic;
cou:in std_logic;
msec0,msec1,second0,second1,minute0,minute1:out std_logic_vector(3 downto 0):=
end jishu;
architecture Behavioral of jishu is
signal a,b,c,d,e,f:std_logic_vector(3 downto 0);
--signal clk_100: std_logic:='0';
signal count:std_logic_vector(3 downto 0):=(others=>'0'); begin
process(clk_1k)
begin
if rising_edge(clk_1k) then
if count=9 then
count
--clk_100
else
count
end if;
end if;
end process;
process(count(3),clr)
begin
if clr='1' then
a
b
c
d
e
f
else
if rising_edge(count(3)) then
if cou='1' then
if a=
a
if b=
b
if c=
c
if d=
d
if e=
e
if f=
else f
end if;
else e
end if;
else d
end if;
else c
end if;
else b
end if;
else a
end if;
else a
else a
end if;
end process;
msec0
msec1
second0
second1
minute0
minute1
end Behavioral;