题目:
在FPGA中设计实现一个多功能数字钟,具备以下功能:
1.准确计时。能显示时分秒,小时的计时为24进制,分和秒的计时为 60 进制。
2.准点报时。当“时-分-秒” 为“ XX-59-55、 XX-59-56、 XX-59-57、 XX-59-58、XX-59-59” 时, 蜂鸣器发“ 嘀” ; 当“时-分-秒” 为“ XX-00-00” 时,扬声器发“ 嗒” 。
3.校时功能。能够对数字钟的时分秒进行精确的调节。
(本实验基于Altera EP4CE10 征途Pro开发板设计实现)
一.设计思路
该工程主要包括顶层模块Digitalclock和若干个底层模块。计时模块Timer_gen,数码管显示模块display,595控制模块hc595_ctrl,按键消抖模块key_filter,调时模块Adjust以及蜂鸣器控制模块buzzer。
整体的RTL视图如下:
其中display_595模块中包含了对数码管显示模块display,595控制模块hc595_ctrl的例化。
二.FPGA板硬件部分电路原理图
1. 六位八段数码管
其具体使用方法见文章:Altera EP4CE10 征途Pro开发板数码管显示原理(以实现模60计数器为例)-优快云博客
2. 无源蜂鸣器buzzer
相对于有源蜂鸣器,无源蜂鸣器的成本更低,声音频率可控。而有源蜂鸣器因其内部自带振荡源,只要加上适当的直流电源即可发声,程序控制较为方便。无源蜂鸣器与有源蜂鸣器不同,因其内部不带震荡源,所以其无法向有缘蜂鸣器那样直接用直流信号驱动,这里需要使用PWM方波才能驱动其发声。
其具体使用方法见文章:无源蜂鸣器的驱动实验-优快云博客
3. 按键key
开发板上使用的机械按键也是按键的一种,特点是:接触电阻小 ,手感好,按键按下或弹起时有“滴答”清脆声;但由于其构造和原理,在按键闭合及断开的瞬间均伴随有一连串的抖动。
具体按键消抖方法的设计请参阅文章:按键消抖模块设计实现-优快云博客
三.Verilog代码实现各个模块
1. 计时模块Timer_gen
计时模块主要包含对时间数据的生成及其如何计数的设计。本模块内包含一个分频器产生标准秒脉冲。模块中同样包含调时信号输入时数字时间的变化。
调时信号输入时,时间保持不变,由按键进行调时。
核心部分代码如下:
always@( posedge sys_clk or negedge sys_rst_n )
if( sys_rst_n == 1'b0 )
cnt_1s <= 1'b0 ;
else if( cnt_1s == CNT_MAX )
cnt_1s <= 1'b0 ;
else
cnt_1s <= cnt_1s + 1'b1 ;
always@( posedge sys_clk or negedge sys_rst_n )
if( sys_rst_n == 1'b0 )
clk1 <= 1'b0;
else if( cnt_1s == CNT_MAX )
clk1 <= ~clk1 ;
else
clk1 <= clk1 ;
always@( posedge clk1 or negedge sys_rst_n )
if( sys_rst_n == 1'b0 )
begin
timer[23:20] <= 4'd0;
timer[19:16] <= 4'd0;
timer[15:12] <= 4'd0;
timer[11:8] <= 4'd0;
timer[7:4] <= 4'd0;
timer[3:0] <= 4'd0;
end
else if( adjust_h == 1'b0 && adjust_m == 1'b0 && adjust_s == 1'b0)
begin
if( (timer[23:20] == 4'd2) && (timer[19:16] == 4'd3) && (timer[15:12] == 4'd5) && (timer[11:8] == 4'd9) && (timer[7:4] == 4'd5) && (timer[3:0] == 4'd9 ) )
begin
timer[23:20] <= 4'd0;
timer[19:16] <= 4'd0;
timer[15:12] <= 4'd0;
timer[11:8] <= 4'd0;
timer[7:4] <= 4'd0;
timer[3:0] <= 4'd0;
end
else if( (timer[19:16] == 4'd3) && (timer[15:12] == 4'd5) && (timer[11:8] == 4'd9) && (timer[7:4] == 4'd5) && (timer[3:0] == 4'd9 ) )
begin
timer[23:20] <= timer[23:20] + 1'b1 ;
timer[19:16] <= 4'd0;
timer[15:12] <= 4'd0;
timer[11:8] <= 4'd0;
timer[7:4] <= 4'd0;
timer[3:0] <= 4'd0;
end
else if( (timer[15:12] == 4'd5) && (timer[11:8] == 4'd9) && (timer[7:4] == 4'd5) && (timer[3:0]