数字系统设计课程设计报告.docx
《数字系统设计课程设计报告.docx》由会员分享,可在线阅读,更多相关《数字系统设计课程设计报告.docx(20页珍藏版)》请在冰豆网上搜索。
![数字系统设计课程设计报告.docx](https://file1.bdocx.com/fileroot1/2022-11/20/151e2463-2d3d-4037-addd-4c4d6a44fb32/151e2463-2d3d-4037-addd-4c4d6a44fb321.gif)
数字系统设计课程设计报告
《数字系统设计》课程设计报告
多功能数字钟
一:
设计任务
1.能正常计时。
显示模式分为24小时制和12小时制。
其中12小时制须显示上、下午。
“时”、“分”、“秒”都要显示。
2.具有快速校准时、分、秒的功能。
手动校准,用一个功能键选择校时、校分功能,用另一功能键调校对应时、分数值。
3.整点自动报时。
在离整点10s时,便自动发出鸣叫声,步长1s,每隔1s鸣叫一次,前四响是低音,最后一响为高音,最后一响结束为整点。
二:
设计方案
对于这个比较大型的系统,我认为应该将各个功能都设计为模块,而后再组合在一些,这样就会使设计思路清晰,同时也不容易出错,因此,我根据实验要求设计如下:
1.数字钟顶层设计
外部输入信号有
(1)、1kHz时钟信号clk(由硬件分频得到),
(2)、按键的行与列的输入信号col[3..0]与row[3..0](作为按键扫描用),
外部输出有:
(3)、整点报时信号braz(59分51/3/5/7秒时未500Hz低频声,59分59秒时为1kHz高频声)、
(4)、显示信号led的位选weiH,weiL,hourH,hourL,minH,minL,secH,secL、
(5)、显示信号的数据:
mux_out[4..0](经过一译码器)
2.内部功能模块主要有:
1、div1000的分频模块:
作为时钟的秒计时,因为总输入信号是1000HZ,分频后,变为1HZ,时间下好为1S。
2、fz500Hz的分频模块:
用作整点报时的低频输出信号。
3、day:
用作对24小时制和12小时制模式的切换与判断,当为12小时制时,上午,最高二位显示10,下午时,最高两位显示01。
当为24小时制时,一直显示00。
count60:
用于秒钟的计数,当计数到60时,输出一个脉冲给分钟计数模块。
同时将计数值转换为bcd译码器的输入
4、mincount60:
用于分钟的计数,当计数到60时,输出一个脉冲给小时计数模块
同时用于分钟的调整加1。
同时将计数值转换为bcd译码器的输入
5、count24:
用于小时的计数,同时用于小时的调整加1。
同时将计数值转换为bcd译码器的输入
6、i24bcd:
将count24的计数值转换为bcd译码器的输入
7、alert:
用于整点报时,输出两个信号,用来控制braz输给蜂鸣器的信号到底时高频还是低频。
8、braz:
接收alert的控制,用来决定输给蜂鸣器的信号到底时高频还是低频。
9、key_scan:
矩阵按键的扫描
10、debounce:
按键的消抖,缓冲有32ms;
11、display:
显示模块,输出信号给译码器,和LED,用来显示数据。
整体:
CLK
模块说明:
1、键盘扫描因为只用扫三个按键,因此我们只输出一个信号“1110”,而后将读取的扫描码编号为00(S6),01(S10),10(S14)。
同时为了便于消抖,设置一个标志信号key_pressed,当键按下,key_pressed为‘1’,放开为‘0’。
因此就可通过判key_pressed脉冲的持续时间来决定按键是否有效。
(在这里我设置为32ms)
2、显示中,基本计时单元是由分频得来的1HZ信号,当有60个该脉冲,分钟就可以加1,当分钟信号也到60了,小时就可加1,如此循环。
因为在后面判断中10进制处理比较简便,所以分钟与时钟信号都处理为10进制。
而因为秒钟不用进行处理,因此我们直接用二进制进行处理,如此一来,少消耗了不少资源。
3、本来分钟与小时的十进制转二进制(为了译码器显示的方便)我们都单独写了两个模块,但是由于资源用得太多,整个程序完成时,编译器显示超资源的错误,没办法,我们就将分钟的数制转换模块与分钟处理模块合并在一起,以此减少多余信号。
4、显示上,因为有译码器,只用输入十进制对就的二进制码就可以了。
同时,因为每次只能显示一个数,所以用循环扫描进行处理,每个数码管每次亮1ms,不断循环。
这样做的同时也节省了能源消耗。
5、天处理上(即12小时与24小时模式转换),因为数码管的显示经过了译码器,显示不了字母,我们就用10与01分别代表上午与下午。
而在24小时模式中,这两个数码管就显示00。
在这个程序中,起判断作用的信号是modem,当S14键有效按下时,modem就取反。
而modem为‘1’就代表这12小时模式,modem为‘0’就代表着24小时模式。
6、整点报时,分别用500HZ代表低音,1KHZ代表高音,经过判断分钟与秒钟的数值,来决定蜂鸣器的信号输入。
用的资源很少。
7、整个程序中,键盘、时间处理、整点报时的思路很清晰,写的也很满意。
只有按键调整中,写的不是很好。
因为分钟这个信号要被时钟信号触发的同时也要被按键的加1触发。
我开始是将这两个触发放在一个进程里,结果,编译时老报错,好像是说,一个信号不能同时被两个信号触发。
没办法,我最后分别用两个时间信号min_temp,min_temp2来代表按键的触发值和时钟的触发值,然后将两个信号进行相加,然后才成功。
三:
仿真分析
显示模块:
display
由此可看出weiH,weiL,hourH,hourL,minH,minL,secH,secL是依次被选中并持续几ms.而数据输出mux_out则对就着被选中位的数据。
蜂鸣器输出模块:
braz
蜂鸣器输出音频控制模块:
alert
m1是分钟的高位,m0是分钟的低位,s1为秒钟的高位,s0是秒钟的低位,
当分钟为59分,秒为51秒,53秒,55秒,57秒时,q500输出脉冲,
即低频信号,当秒为59秒时,qlk输出脉冲,即为高频信号。
以此来控制蜂鸣器的声音。
观察此图,完全符合。
小时计数模块:
count24
其中:
key为按键的扫描码,key_valid为消抖确认信号,当key为00同时key_voliad是高电平时,小时就得加1。
由仿真来看完全符合。
秒钟计数模块:
count60
其中:
carry是时钟的经过1000分频的信号,频率为1hz。
tiems是计数,从0~59。
one和ten分别是十位和个位
分钟计数模块:
mincount60
输出为分钟的十位数与个位数ten和one.还有进位full.
同时判断第二个键是否有效输入,若有效,分钟也加1.观察仿真结果,完全相符。
12小时与24小时转换:
day
24小时制
由1到24,dayH与dayL为00
12小时制:
由1到12,dayH与dayL为01或10。
分频模块:
fz500Hz
由图可看出,输出频率为CLK的一半。
分频模块:
div1000
每1000个时钟脉冲,f1hz产生一个脉冲。
按键扫描:
key_scan
col是按键扫描的输入信号,当为0111,1011,1101时表示有按键按下,此时,
scan_out输出按键的代号,相应为0,1,2。
而key_pressed输出脉冲,表示有按键按下。
按键消抖:
debounce:
key_pressed为输入的按键信号,当其持续时间不超过32ms时,判为无效按键,此时key_valid为低电平,而当超过这个值时,为有效按键,key_valid为高电平。
由图可看出,完全符合。
四:
源程序
1、div1000分频
libraryieee;
useieee.std_logic_1164.all;
useieee.std_logic_unsigned.all;
useieee.std_logic_arith.all;
entitydiv1000is
port(clk:
instd_logic;
f1hz:
outstd_logic);
endentity;
architecturebehavofdiv1000is
signalcount:
integerrange0to1000;
begin
process(clk)
begin
ifrising_edge(clk)then
count<=count+1;
ifcount=1000thenf1hz<='1';
elsef1hz<='0';
endif;
endif;
endprocess;
endbehav;
2、count60
libraryieee;
useieee.std_logic_1164.all;
useieee.std_logic_unsigned.all;
useieee.std_logic_arith.all;
entitycount60is
port(carry:
instd_logic;
one:
outstd_logic_vector(3downto0);
ten:
outstd_logic_vector(3downto0);
full:
outstd_logic);
endcount60;
architecturebehaveofcount60is
begin
process(carry)
variableones:
std_logic_vector(3downto0):
="0000";
variabletens:
std_logic_vector(3downto0):
="0000";
begin
ifrising_edge(carry)then
ones:
=ones+1;
if(tens="0101"andones="1010")thenones:
=(others=>'0');tens:
=(others=>'0');full<='1';
elsif(ones="1010")thentens:
=tens+1;ones:
="0000";full<='0';
endif;
endif;
one<=ones;
ten<=tens;
endprocess;
endbehave;
3、mincount60:
分钟计时:
libraryieee;
useieee.std_logic_1164.all;
useieee.std_logic_unsigned.all;
useieee.std_logic_arith.all;
entitymincount60is
port(carry:
instd_logic;
key:
instd_logic_vector(1downto0);
key_valid:
instd_logic;
full:
outstd_logic;
ten:
outstd_logic_vector(3downto0);
one:
outstd_logic_vector(3downto0));
endmincount60;
architecturebehaveofmincount60is
signalmin_temp:
integerrange0to59;
signalmin_temp2:
integerrange0to59;
signalmin:
integerrange0to59;
begin
process(carry,key,key_valid)
begin
ifrising_edge(key_valid)then
if(key="01")then
if(min_temp>=59)thenmin_temp<=0;
elsemin_temp<=min_temp+1;
en