工学EDA课程设计.docx
《工学EDA课程设计.docx》由会员分享,可在线阅读,更多相关《工学EDA课程设计.docx(40页珍藏版)》请在冰豆网上搜索。
工学EDA课程设计
用VHDL语言实现数字钟的设计
2011年12月21日
一、EDA课程设计的目的与任务
(一)、掌握利用可编程逻辑器件和EDA设计工具进行电子系统设计的方法,内容包括:
(1)VHDL程序设计、输入——在ise平台上用VHDL描述系统的功能
(2)逻辑综合——将源程序编译后,为设计系统选择一个电路实现方案,按照这个方案进行逻辑综合和优化,生成1个电路网表文件
(3)功能仿真——检查自己的设计是否达到和完成要求的逻辑功能
(4)设计实现——布局、布线及配置,最后生成可以写到芯片中的目标文件
(5)时序仿真——是适配到选定的芯片后进行的仿真,它模拟芯片的实际动作,仿真时间模型严格将门级延时计算在内,可以分析出竞争与冒险,时序仿真验证过的电路与实际电路基本上已致。
(6)器件编程——对器件编程下载
(7)测试
二、EDA课程设计的要求
设计实现一个具有带预置数的数字钟,具有显示年月日时分秒的功能。
用6个数码管显示时分秒,set按钮产生第一个脉冲时,显示切换年月日,第2个脉冲到来时可预置年份,第3个脉冲到来时可预置月份,依次第4、5、6、7个脉冲到来时分别可预置日期、时、分、秒,第8个脉冲到来后预置结束,正常工作,显示的是时分秒。
Up为高电平时,upclk有脉冲到达时,预置位加1.否则减1,还可以在此基础上增加其它功能。
用VHDL语言实现数字钟的设计
摘要
随着IT行业的不断发展EDA技术在很多行业得到了广泛的应用,在很多大学也开设了相应的课程,但只有理论知识不足以应对实际项目的开发,不足以胜任更加庞大的系统开发。
本次课程设计旨在提高学生的实际动手能力和解决问题的能力。
本文在该项目的实际设计中,就整体框架的设计,软件的开发,仿真,下载,调试等过程进行了一一验证。
在数字钟的设计中应用了元件例化的整体思路实现,实现过程可分为分频,时分秒计数,时分秒置数,年月日计数,年月日置数共五个部分,其中在年月日的计数中应用状态机的计数方法实现设计。
关键字:
VHDL,元件例化,数字钟
一、EDA课程设计的目的与任务····························Ⅰ
二、EDA课程设计的要求··································Ⅱ
三、摘要···············································Ⅲ
第一章系统方案·········································1
1.1设计思路·············································
第二章各个模块实现······································
2.1分频模块··············································
2.2时分秒计数模块········································
2.3时分秒置数模块········································
2.4年月日计数模块········································
2.5年月日置数模块········································
2.6元件例化整体模块······································
第三章整体电路图·········································
3.1quartus生成的整体电路图······························
第四章课程设计总结········································
第五章实验代码···········································
5.1实验代码··············································
第一章系统方案
1.1设计思路
VHDL数字钟的设计可采用多种设计方法,各个设计方法各有其优缺点。
一,采用一个结构体,多个进程的设计方法。
其优点是速度快,但是一个结构体,各个进程的逻辑关系比较复杂,而且代码的可读性,可移植性较差。
二,状态机的设计方法,状态机结构简单,当各个状态之间的转换不易处理。
三,元件例化的设计方法,元件例化使各个模块之间分得更加有层次,易于读,缺点有可能使各个模块之间存在逻辑关系的冲突。
本此设计,主要采用了元件例化的设计方法,在年月日计数模块采用了状态机的设计方法实现。
第二章各个模块的实现
2.1分频模块
直接将实验箱的频率用于数字钟的计数,可能会导致错误,实验箱直接给出的1hz频率可能不够稳定,故需要将1khz的频率输出进行1000分频。
本模块直接采用单进程实现设计,本模块还包括一个置数脉冲的设置upd0,upd0按下一次lock加1,lock为000时显示时分秒,为001时显示年月日,为010对年进行置数,为011对月进行置数,为100对日进行置数,为101对时进行置数,为110对分进行置数,为111对秒进行置数,lock,也连接着后面四个计数,置数,模块的lock,以进行模块显示的选择。
f10设置的周期为5ns,在2.5us处实现1000分频,1000分频后的f_clk连接时分秒,年月日计数模块的计数时钟,置数时钟则直接输入,连接两个置数模块。
以下程序是实体部分
entitylo_covis
port(upd0:
instd_logic;//置数脉冲输入
f10:
instd_logic;//1khz时钟输入
f_clk:
outstd_logic;//分频时钟输出
lock:
outstd_logic_vector(2downto0)//输入脉冲的选择
);
endlo_cov;
以下是分频模块的仿真图像,
2.2时分秒计数模块
时分秒可选用多进程或者单进程的方法,多进程速度快,但是结构复杂。
故本设计选用单进程方法。
当秒计数到59时向分进位,分计到59且秒为59时向时进位,当计到23时59分59秒时向天进位,同时对时分秒进行清零。
程序中主要使用了ifelsifendif;的语句。
最后验证表明此设计方法可实现题目要求的功能。
以下是程序的实体部分
entitys_m_houris
port(
clk0,clk1:
instd_logic;--clk0工作时钟,clk1预置脉冲lock:
instd_logic_vector(2downto0);//置数显示切换
s0,s1:
outstd_logic_vector(3downto0);//秒的地位高位
m0,m1:
outstd_logic_vector(3downto0);//分的低位高位
h0,h1:
outstd_logic_vector(3downto0);//时的低位高位
co:
outstd_logic;--hour产生进位
en:
instd_logic//使能端
);ends_m_hour;
以下是仿真的电路图
2.3时分秒置数模块
时分秒置数模块不同于计数模块,置数模块我选用了另一个置数时钟,也可以说是置数脉冲。
时分秒置数有使能端口en(高有效),置数使能端口tn,通过tn(tn=0时置数是减1模式,tn=1时是加1模式)判定是加1还是减1。
当输入长度为三位的lock为101时对时进行置数,当lock为110时对分进行置数,当lock为111时对秒进行置数。
时分秒的置数实现方式可有多种方法,可用状态机,多进程和单进程等方法实现,相比于别的设计方法,单进程的设计方法易于实现,没有复杂的对应关系,而且本功能的实现不许过于复杂的逻辑关系。
本设计使用了单进程内部使用嵌套的ifelsifendif语句实现预期的功能。
以下是该功能的输入输出端口:
entitys_m_yuz1is
port(
clk0,clk1:
instd_logic;--clk0工作时钟,clk1预置脉冲
lock:
instd_logic_vector(2downto0);--置数选择
s0,s1:
outstd_logic_vector(3downto0);--秒输入端口
m0,m1:
outstd_logic_vector(3downto0);--分输入端口
h0,h1:
outstd_logic_vector(3downto0);--时输入端口
tn:
instd_logic;--tn=1预置数加1,tn=0预置数减1
en:
instd_logic--使能端口,高有效
);
ends_m_yuz1;
以下分别是时分秒的置数仿真波形图
对时进行置数的功能仿真波形图
对分的置数的功能仿真波形图
对秒的置数的功能仿真波形图
2.4年月日计数模块
年月日的计数模块与时分秒的计数模块稍有不同,年月日需要考虑闰年2月份的情况,闰年到来时2月份为29天,其他情况2月份为28天。
本设计同样可采用多种设计方法,由于出现不同月份的天数有可能天数不一样的情况,故本设计采用状态机的设计方法实现,每个月份作为一个状态,采用了两个进程的设计方法,一个为组合逻辑设计,另一个为时序控制进程,已达到最优化,同时设计了进位脉冲,当计满12个月时向年产生进位,年数加1。
以下是实体部分
entitydaymony1is
port(
clk0,clk1:
instd_logic;
da0,da1:
outstd_logic_vector(3downto0);
mo0,mo1:
outstd_logic_vector(3downto0);
ya0,ya1:
outstd_logic_vector(3downto0);
co:
outstd_logic;--月向年产生进位的进位端
en:
instd_logic;
lock:
instd_logic_vector(2downto0)
);
enddaymony1;
以下是年月日计数功能仿真波形
2.5年月日置数模块
年月日置数模块不同于时分秒的置数模块,在年月日的置数模块中我们需要考虑闰年相对应的闰月的情况,就会出现不同的年份对应的2月的天数的不同,其他的可将1,3,5,7,8,10,12归成一类,这几个月每个月的天数是31天,而4,6,9,11这几个月又归为一类,每个月有30天,二月分为特殊的一类,视是否为闰年而定天数,闰年有29天,非闰年为28天。
En使能端,高有效。
tn为置数模式的选择控制端,tn=1时置数处于加1模式,tn=0置数处于减1模式,lock为置数对象的选择。
Lock=010时对年进行置数,lock=011时对月进行置数,lock=100时对天进行置数。
本设计对于本模块使用了单进程,内部使用了ifelsifendif;语句实现预期的功能。
以下是该置数模块的实体部分:
entityyuzhisis
port(
clk1,tn:
instd_logic;--clk1为置数时钟,tn=1置数处于加模式
en:
instd_logic;--使能端口
lock:
instd_logic_vector(2downto0);--置数的对象选择
da0,da1:
outstd_logic_vector(3downto0);
mo0,mo1:
outstd_logic_vector(3downto0);
ya0,ya1:
outstd_logic_vector(3downto0)
);
endyuzhis;
对年进行置数的功能仿真波形
对月进行置数功能的仿真波形
对天进行置数功能的仿真波形
2.6元件例化模块
该模块将分立的五个模块连接起来,运用端口映射的方式,将各个模块通过相应的信号线相连,这也是一个容易出现问题的地方,很容易造成连接失败。
F10为实验箱频率输入,tn直接与各个两个置数端口的tn相连,upd0为输入脉冲,直接与分频模块的upd0相连,同时分频模块的lock对其进行计数。
以下是实体部分:
ENTITYdigital_clockIS
PORT
(
clk1:
INSTD_LOGIC;
upd0:
INSTD_LOGIC;
f10:
INSTD_LOGIC;
tn:
INSTD_LOGIC;
en:
INSTD_LOGIC;
H_Year:
OUTSTD_LOGIC_VECTOR(3DOWNTO0);--数码管的显示
H_Year1:
OUTSTD_LOGIC_VECTOR(3DOWNTO0);
M_Mon:
OUTSTD_LOGIC_VECTOR(3DOWNTO0);
M_Mon1:
OUTSTD_LOGIC_VECTOR(3DOWNTO0);
S_Day:
OUTSTD_LOGIC_VECTOR(3DOWNTO0);
S_Day1:
OUTSTD_LOGIC_VECTOR(3DOWNTO0)
);
ENDdigital_clock;
第三章整体电路图
此部分为此设计的整个电路部分,用quartus连接完成。
第四章课程设计总结
本次设计为运用EDA技术,用VHDL设计数字钟。
数字钟在我们的生活中并不少见,这一次我真正的深入的用所学的知识去联系生活中的事情,将理论与实际结合,在学习的同时也激发了我们的学习兴趣。
在这三天的课程设计中,并不枯燥,在调试的过程发现了不少问题,比如逻辑关系的不明确很容易造成设计的失败,又如在元件例化的过程中出现逻辑关系上的冲突,逻辑关系上的冲突看似简单,但真正的找出问题在什么地方并不容易。
虽然问题最终没有得以解决,但在这个过程中学会了找问题的方法,解决问题的方法。
在设计的过程中更应该细心,每一步的不注意,就有可能导致整个系统的连接失败。
这些都是将来我们走上社会,进入企业所会面对的的问题。
在学校我们学到的东西更多的是偏向理论基础的知识,每一次实践的机会,都会对我们的的学习上有进一步的提高,珍惜每一次课程设计的机会。
本次设计虽然没有获得很好的成绩,但是在其中学到知识才是最重要的,通过本次课程设计大大提高了对于EDA技术的理解,对以后进一步的学习有很大的帮助。
第五章实验代码
以下分别是时分秒计数,时分秒置数,年月日计数,年月日置数,分频及例化共六个模块的实验代码:
libraryIEEE;
useIEEE.STD_LOGIC_1164.ALL;
useIEEE.STD_LOGIC_ARITH.ALL;
useIEEE.STD_LOGIC_UNSIGNED.ALL;
--Uncommentthefollowinglinestousethedeclarationsthatare
--providedforinstantiatingXilinxprimitivecomponents.
--libraryUNISIM;
--useUNISIM.VComponents.all;
entitys_m_houris
port(
clk0,clk1:
instd_logic;--clk0工作时钟,clk1预置脉冲
lock:
instd_logic_vector(2downto0);--工作模式选择
s0,s1:
outstd_logic_vector(3downto0);
m0,m1:
outstd_logic_vector(3downto0);
h0,h1:
outstd_logic_vector(3downto0);
co:
outstd_logic;--_vector(2downto0);--hour产生进位
en:
instd_logic
);
ends_m_hour;
architectureBehavioralofs_m_houris
signalts0:
std_logic_vector(3downto0):
="0100";
signalts1:
std_logic_vector(3downto0):
="0101";
signaltm0:
std_logic_vector(3downto0):
="1001";
signaltm1:
std_logic_vector(3downto0):
="0101";
signalth0:
std_logic_vector(3downto0):
="0011";
signalth1:
std_logic_vector(3downto0):
="0010";
signalclk:
std_logic;
signalcc:
std_logic;
begin
s0<=ts0;s1<=ts1;m0<=tm0;m1<=tm1;h0<=th0;h1<=th1;co<=cc;
process(clk,en)
begin
ifen='1'then
iflock="000"orlock="001"then
clk<=clk0;
else
clk<=clk1;
endif;
endif;
endprocess;
process(clk0,lock,en)
begin
ifen='1'then
iflock="000"then
ifclk0'eventANDclk0='1'then
ifts1="0101"andts0="1001"then
ts1<="0000";ts0<="0000";
--endif;
elsifts0="1001"then
ts0<="0000";ts1<=ts1+1;
else
ts0<=ts0+1;--如果ts0不等于9则ts1保持不变
endif;
ifts0="1001"andts1="0101"then
iftm1="0101"andtm0="1001"then
tm1<="0000";tm0<="0000";
--endif;
elsiftm0="1001"then
tm0<="0000";tm1<=tm1+1;
else
tm0<=tm0+1;
endif;
endif;
ifts0="1001"andts1="0101"andtm0="1001"andtm1="0101"then
ifth1="0010"ANDth0="0011"thenth1<="0000";th0<="0000";cc<='1';
elsifth0="1001"then
th0<="0000";th1<=th1+1;
else
th0<=th0+1;cc<='0';
endif;
endif;
endif;
endif;
endif;
endprocess;
endBehavioral;
libraryIEEE;
useIEEE.STD_LOGIC_1164.ALL;
useIEEE.STD_LOGIC_ARITH.ALL;
useIEEE.STD_LOGIC_UNSIGNED.ALL;
--Uncommentthefollowinglinestousethedeclarationsthatare
--providedforinstantiatingXilinxprimitivecomponents.
--libraryUNISIM;
--useUNISIM.VComponents.all;
entitys_m_yuz1is
port(
clk0,clk1:
instd_logic;--clk0工作时钟,clk1预置脉冲
lock:
instd_logic_vector(2downto0);
s0,s1:
outstd_logic_vector(3downto0);
m0,m1:
outstd_logic_vector(3downto0);
h0,h1:
outstd_logic_vector(3downto0);
tn:
instd_logic;--tn=1预置数加1,tn=0预置数减1
en:
instd_logic
);
ends_m_yuz1;
architectureBehavioralofs_m_yuz1is
signalts10:
std_logic_vector(3downto0):
="0100";
signalts11:
std_logic_vector(3downto0):
="0101";
signaltm10:
std_logic_vector(3downto0):
="1001";
signaltm11:
std_logic_vector(3downto0):
="0101";
signalth10:
std_logic_vector(3downto0):
="0011";
signalth11:
std_logic_vector(3downto0):
="0010";
begin
s0<=ts10;s1<=ts11;m0<=tm10;m1<=tm11;h0<=th10;h1<=th11;
process(clk1,lock,tn)
begin
ifen='1'then
ifclk1'eventandclk1='1'then--选择置数时钟为clk1
iflock="101"andtn='0'then--对时进行置数(减1)
ifth10="0000"andth11="0000"then
th10<="0011";th11<="0010";
elsifth10="0000"and(th11="0010"orth11="0001")then
th10<="1001";th11<=th11-1;
endif;
elsiflock="101"andtn='1'then--对时置数加1
ifth10="1001"then
th10<="0000";th11<=th11+1;
else