teach09第9章 EDA技术综合应用设计实例文档格式.docx
《teach09第9章 EDA技术综合应用设计实例文档格式.docx》由会员分享,可在线阅读,更多相关《teach09第9章 EDA技术综合应用设计实例文档格式.docx(33页珍藏版)》请在冰豆网上搜索。
![teach09第9章 EDA技术综合应用设计实例文档格式.docx](https://file1.bdocx.com/fileroot1/2022-12/13/929f798d-bd3d-4f55-9c4d-d6738301abd0/929f798d-bd3d-4f55-9c4d-d6738301abd01.gif)
(5)扬声器,在当前时钟时间与闹钟时间相同时,发出蜂鸣声。
该数字闹钟的具体功能要求如下:
(1)计时功能:
这是本数字闹钟设计的基本功能,每隔1秒钟计时一次,并在显示屏上显示当前时间;
(2)闹钟功能:
:
如果当前时间与设置的闹钟时间相同,则扬声器发出蜂鸣声;
(3)设置新的计时器时间:
系统内部产生的周期性循环变化的待选预置数字,当用户按”YES”键后则该数字将作为预置数字输入;
在输入过程中,输入数字在显示屏上从右到左依次显示,例如,用户要设置新的时间12:
48:
56,则按顺序先后输入”1”,”2”,”4”,”8”,”5”,”6”,与之对应,显示屏依次显示的信息为:
”1”,”12”,”124”,”1248”,”12485”,”124856”。
如果用户在输入任意几个数字后较长时间内,例如5秒,没有按任何键,则计时器恢复到正常的计时显示状态。
(4)设置新的闹钟时间:
用户用YES键输入新的时间,然后按”ALARM”键确认,过程与3类似。
(5)显示所设置闹钟时间:
在正常计时显示状态下,用户直接按下“ALARM”键则已设置的闹钟时间显示在显示屏上。
根据该系统的设计功能要求,整个系统大致包括如下几个组成部分:
用于预置数字输入的预置数字缓冲器;
用于数字闹钟计时的计数器;
用于保存闹钟时间的寄存器;
用于显示的七段数码显示电路以及控制以上各个部分协同工作的控制器。
图9.1数字闹钟面板图
图9.2计时器的外部端口
根据该数字闹钟的设计要求,我们可得到其外部端口如图9.2所示。
各个输入/输出端口的作用如下:
(1) CLK为外部时钟信号,RESET为复位信号。
(2)当YES为高电平时(YES=‘1’),表示用户选择了某个预置数字。
(3)当ALARM_BUTTON为高电平时,表示用户按下ALARM键。
(4)当TIME_BUTTON为高电平时,表示用户按下TIME键。
(5) SEG7是数据动态扫描显示的公共八段数码显示管驱动端,而LEDW则是数码管的位选择端,它经过外接的3—8译码器译码后接数码管的公共端COM。
(6) SOUND_ALARM用于控制扬声器发声,当SOUND_ALARM=‘1’时,扬声器发出蜂鸣,表示到了设定的闹钟时间。
根据系统的设计要求,整个系统可分为闹钟控制器、预置寄存器、分频电路、时间计数器、闹钟寄存器、显示驱动控制器等6个模块,其总体设计原理图如图9.3所示。
各
图9.3系统总体设计原理图
个模块的作用介绍如下:
(1)闹钟控制器(CONTROL):
它是整个系统正常有序工作的核心,按设计要求产生相应的控制逻辑,以控制其他各部分的协调工作。
(2)预置寄存器(KEYBUFFER):
这时一个预置数字产生器和移位寄存器的结合体。
通过对YES进行操作,选择输入欲输入的数字,暂存用户输入的数字,并且用户每输入一个数字,暂存数字移位一次,实现用户输入数字在显示器上从右到左的依次显示。
(3)分频电路(DIVIDER):
将较高速的外部时钟频率分频成每秒钟一次的时钟频率,以便进行时钟计数。
(4)时间计数器(COUNTER):
实际上是一个异步复位、异步置数的累加器,通常情况下进行时钟累加计数,必要时可置入新的时钟值,然后从该值开始新的计数。
(5)闹钟寄存器(REG):
用于保存用户设置的闹钟时间,是一个异步复位寄存器。
(6)显示驱动器(DRIVER):
根据需要显示当前时间、用户设置的闹钟时间或用户输入的预置时间,同时判断当前时间是否已到了闹钟时间,实际上是一个多路选择器加比较器。
对具体数据的显示,采用的是动态扫描显示方式。
图9.4闹钟控制器的外部端口
闹钟控制器的外部端口如图9.4所示,各端口的作用如下:
(2)当KEY为高电平(KEY=‘1’)时,表示用户按下数字键(“0”~“9”)。
(3)当ALARM_BUTTON为高电平时,表示用户按下“ALARM”键。
(4)当TIME_BUTTON为高电平时,表示用户按下“TIME”键。
(5)当LOAD_NEW_A为高电平时,控制(闹钟时间寄存器)加载新的闹钟时间值。
(6)当LOAD_NEW_C为高电平时,控制(时钟计数器)设置新的时间值。
(7)当SHOW_NEW_TIME为高电平时,控制(七段数码显示电路)显示新的时间值,即用户输入的预置时间;
否则,当SHOW_NEW_TIME为低电平时,根据SHOW_A信号的值控制显示当前时间或闹钟时间。
此时,当SHOW_A为高电平时,控制显示闹钟时间,否则,显示当前时间。
控制器的功能可以通过有限状态自动机(FSM)的方式来实现。
根据设计要求及端口设置,需要五个状态来实现:
S0:
表示电路初态即正常时钟计数状态,完成计时功能。
S1:
接收预置数字输入状态。
在状态S0时用户按下“YES”键后进入此状态。
在此状态下,显示屏上显示的是用户预置的数字。
S2:
设置新的闹钟时间。
在状态S1时用户按下ALARM键后进入此状态。
S3:
设置新的计时器时间。
在状态S1时用户按下TIME键后进入此状态。
S4:
显示闹钟时间。
在状态S0时用户直接按下ALARM键后进入此状态。
在此状态下,显示屏上显示的是所设置的闹钟时间。
注意:
在此状态下,用户按下ALARM键后,显示屏上保持显示闹钟时间,经过一段时间以后,再返回状态S0显示计时器时间。
相应的状态转换及控制如表9.1所示。
表9.1控制器状态转换及控制输出表
当前状态
控制输入(条件)
下一状态
控制输出(动作)
S0
YES=‘1’
S1
SHOW_NEW_TIME<
=‘1’
ALARM_BUTTON=‘1’
S4
SHOW_A<
否则
--
S2
LOAD_NEW_A<
TIME_BUTTON=‘1’
S3
LOAD_NEW_C<
否则(超时)
否
=‘1’,“超时”判断处理
是
表9.1中没有显式说明的控制信号赋值,表示信号的值为零。
例如在状态S0,当信号YES=‘1’时,SHOW_NEW_TIME信号的赋值为‘1’,而其他信号LOAD_NEW_A、LOAD_NEW_C和SHOW_A的值此时都赋为‘0’。
另外,表中关于“超时”判断处理的处理细节见VHDL源程序中的有关部分。
由于在整个系统中有多个模块需要用到自行设计的数据类型,并且这些数据类型大部分相同,因此我们为了使用上的方便,可设计一个程序包P_ALARM,该程序既可加在调用该程序包的程序前面,也可加在整个系统的顶层设计程序的前面。
但是对于一个比较复杂系统的设计,一般是分模块进行设计和调试,所以加在各个调用该程序包的程序前面会比较方便写。
程序包P_ALARM的具体设计如下:
LIBRARYIEEE;
USEIEEE.STD_LOGIC_1164.ALL;
PACKAGEP_ALARMIS
SUBTYPET_DIGITALISINTEGERRANGE0TO9;
SUBTYPET_SHORTISINTEGERRANGE0TO65535;
TYPET_CLOCK_TIMEISARRAY(5DOWNTO0)OFT_DIGITAL;
TYPET_DISPLAYISARRAY(5DOWNTO0)OFT_DIGITAL;
ENDPACKAGEP_ALARM;
根据上面的设计分析,我们可将闹钟控制器的VHDL源程序设计如下:
--控制器源程序CONTROL.VHD
USEWORK.P_ALARM.ALL;
ENTITYCONTROLIS
PORT(KEY:
INSTD_LOGIC;
ALARM_BUTTON:
TIME_BUTTON:
CLK:
RESET:
LOAD_NEW_A:
OUTSTD_LOGIC;
LOAD_NEW_C:
SHOW_NEW_TIME:
SHOW_A:
OUTSTD_LOGIC);
ENDENTITYCONTROL;
ARCHITECTUREARTOFCONTROLIS
TYPET_STATEIS(S0,S1,S2,S3,S4);
CONSTANTKEY_TIMEOUT:
T_SHORT:
=500;
CONSTANTSHOW_ALARM_TIMEOUT:
SIGNALCURR_STATE:
T_STATE;
SIGNALNEXT_STATE:
SIGNALCOUNTER_K:
T_SHORT;
SIGNALENABLE_COUNT_K:
STD_LOGIC;
SIGNALCOUNT_K_END:
SIGNALCOUNTER_A:
SIGNALENABLE_COUNT_A:
SIGNALCOUNT_A_END:
BEGIN
PROCESS(CLK,RESET)IS
IFRESET='
1'
THEN
CURR_STATE<
=S0;
ELSIFRISING_EDGE(CLK)THEN
=NEXT_STATE;
ENDIF;
ENDPROCESS;
PROCESS(KEY,ALARM_BUTTON,TIME_BUTTON,CURR_STATE,COUNT_A_END,COUNT_K_END)
NEXT_STATE<
=CURR_STATE;
LOAD_NEW_A<
='
0'
;
LOAD_NEW_C<
SHOW_A<
SHOW_NEW_TIME<
ENABLE_COUNT_K<
ENABLE_COUNT_A<
CASECURR_STATEIS
WHENS0=>
IF(KEY='
)THEN
=S1;
ELSIF(ALARM_BUTTON='
=S4;
ELSE
WHENS1=>
)THEN
=S2;
ELSIF(TIME_BUTTON='
=S3;
ELSE
IF(COUNT_K_END='
WHENS2=>
IF(ALARM_BUTTON='
WHENS3=>
IF(TIME_BUTTON='
WHENS4=>
IF(COUNT_A_END='
WHENOTHERS=>
NULL;
ENDCASE;
COUNT_KEY:
PROCESS(ENABLE_COUNT_K,CLK)IS
IF(ENABLE_COUNT_K='
COUNTER_K<
=0;
COUNT_K_END<
ELSIF(RISING_EDGE(CLK))THEN
IF(COUNTER_K>
=KEY_TIMEOUT)THEN
=COUNTER_K+1;
COUNT_ALARM:
PROCESS(ENABLE_COUNT_A,CLK)IS
IF(ENABLE_COUNT_A='
COUNTER_A<
COUNT_A_END<
ELSIFRISING_EDGE(CLK)THEN
IF(COUNTER_A>
=SHOW_ALARM_TIMEOUT)THEN
=COUNTER_A+1;
ENDARCHITECTUREART;
图9.5为预置寄存器示意图。
图9.5预置寄存器示意图
--预置寄存器的VHDL源程序KEYBUFFER.VHD
USEIEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITYKEYBUFFERIS
KEYNUM:
OUTSTD_LOGIC_VECTOR(3DOWNTO0);
NEW_TIME:
OUTT_CLOCK_TIME);
ENDENTITYKEYBUFFER;
ARCHITECTUREARTOFKEYBUFFERIS
SIGNALN_T:
T_CLOCK_TIME;
SIGNALCNT:
STD_LOGIC_VECTOR(3DOWNTO0);
SIGNALTEMP:
T_DIGITAL;
PROCESS(CLK)IS
IF(CLK'
EVENTANDCLK='
IFCNT=9THEN
CNT<
="
0000"
=CNT+'
TEMP<
=CONV_INTEGER(CNT);
KEYNUM<
=CNT;
SHIFT:
PROCESS(RESET,KEY)IS
IF(RESET='
N_T(5)<
N_T(4)<
N_T(3)<
N_T
(2)<
N_T
(1)<
N_T(0)<
ELSIF(KEY'
EVENTANDKEY='
FORIIN5DOWNTO1LOOP
N_T(I)<
=N_T(I-1);
ENDLOOP;
=TEMP;
NEW_TIME<
=N_T;
9.1.5闹钟寄存器的设计
闹钟寄存器模块的功能是在时钟上升沿同步下,根据LOAD_NEW_A端口的输入信号控制ALARM_TIME端口的输出;
当控制信号有效(高电平)时,把NEW_ALARM_TIME端口的输入信号值输出;
RESET端口输入信号对ALARM_TIME端口的输出进行异步的清零复位。
图9.18是闹钟寄存器的示意图。
图9.18闹钟寄存器示意图
--闹钟寄存器的源程序REG.VHD
ENTITYREGIS
PORT(NEW_ALARM_TIME:
INT_CLOCK_TIME;
ALARM_TIME:
ENDENTITYREG;
ARCHITECTUREARTOFREGIS
ALARM_TIME(0)<
ALARM_TIME
(1)<
ALARM_TIME
(2)<
ALARM_TIME(3)<
ALARM_TIME(4)<
ALARM_TIME(5)<
IFRISING_EDGE(CLK)THEN
IFLOAD_NEW_A='
ALARM_TIME<
=NEW_ALARM_TIME;
图9.6分频器示意图
本模块的功能是将CLK_IN端口输入的时钟信号分频后送给CLK_OUT端口;
当RESET端口输入信号有效(高电平)时,CLK_OUT端口输出信号清零。
图9.6为分频电路示意图。
--分频电路的VHDL程序DIVIDER.VHD
ENTITYDIVIDERIS
PORT(CLK_IN:
CLK_OUT:
ENDENTITYDIVIDER;
ARCHITECTUREARTOFDIVIDERIS
CONSTANTDIVIDE_PERIOD:
=6000;
PROCESS(CLK_IN,RESET)IS
VARIABLECNT:
CNT:
CLK_OUT<
ELSIFRISING_EDGE(CLK_IN)THEN
IF(CNT<
=(DIVIDE_PERIOD/2))THEN
=CNT+1;
ELSIF(CNT<
(DIVIDE_PERIOD-1))THEN
时间计数器模块的功能是当RESET端口输入信号为高电平时,对CURRENT_TIME端口输出信号清零复位;
当LOAD_NEW_C端口输入信号为高电平时,将NEW_CURRENT_TIME端口的输入信号输出给CURRENT_TIME端口。
RESET端口的控制优先于LOAD_NEW_C端口。
当这两个控制信号都无效时,在时钟上升沿同步下,对CURRENT_TIME端口输出信号累加1,并根据小时、分钟、秒的规律处理进位。
图9.7是时间计数器模块的示意图。
图9.7