
课程设计(论文)
课程名称: | EDA技术与应用 |
设计题目: | 基于FPGA的数字时钟实现 |
姓 名: | 黄培堃 |
系: | 物理与信息工程学院 |
专 业: | 电子信息工程 |
年 级: | 20级 |
学 号: | 20550618075 |
指导教师: | 陈艳 |
2022年12月8日
目 录
一、功能设计……………………………………………………………
二、模块分析……………………………………………………………
三、实验结果及源代码…………………………………………………
四、个人总结……………………………………………………………
一、功能设计
1、数码管显示拥有多个界面:
(1)时分秒:显示界面、设置界面;
(2)年月日:显示界面、设置界面;
(3)闹钟:状态界面、设置界面。
2、年月日:
(1)默认主界面为时分秒显示界面,通过按键可调出年月日界面,并显示三秒钟后自动跳转回主界面(时分秒界面);
(2)进入到年月日界面后,可通过设置按键设置年月日的值,设置完成后自动保存。
3、时分秒:
(1)默认主界面为时分秒显示界面,设置按键可设置当前显示界面时分秒的值,设置完成后自动保存。
4、闹钟:
(1)闹钟设置为闹钟显示界面,如果开启闹钟,则显示设置的闹钟时间,如果关闭闹钟,则显示连续的“-”,表示关闭了闹钟;
(2)当闹钟时间达到时,蜂鸣器发出声音。
5、按键功能说明:
(1)初始界面显示时分秒
(2)查看年月日:
点击一下KEY3,显示年月日3秒,3秒过后自动返回时分秒显示界面
(2)查看闹钟设置的值
点击一下KEY2,显示闹钟设的值,如果显示6个“-”,则表示闹钟关闭了,如果有值,则表示闹钟开启了。
(3)设置时分秒:
在时分秒界面下,按KEY1,进入设置时分秒的界面,需要设置的位在不断的闪烁,此时点击或长按KEY3累减,点击或长按KEY2累加,点击KEY1设置下一位。
(4)设置年月日:
点击KEY3进入年月日界面,在年月日界面下,按KEY1,进入设置年月日的界面,需要设置的位在不断的闪烁,此时点击或长按KEY3累减,点击或长按KEY2累加,点击KEY1设置下一位。
(5)设置闹钟:
点击KEY2进入闹钟界面,在闹钟界面,按KEY1,进入设置界面,此时点击KEY3可开启或关闭闹钟,再点击KEY2即可退出设置开启或关闭界面,等待3秒钟自动回到时分秒界面,如果在开启或关闭闹钟界面点击KEY1进入更深一步设置闹钟的值,同样点击KEY3或KEY2累加累减设置闹钟的值。
(6)闹铃:
当前时间若等于闹钟的值,则蜂鸣器响,以音乐《小星星》为闹钟铃声。按任意键关闭闹钟。
(7)重置
按下reset重置电子时钟。
二、模块分析:
EP4CE6F17C8N开发板中的数码管如图所示:

通过控制SEL 信号和DIG信号可以控制数码管的输出时间日期等。
系统设计:

故:笔者设计的时钟系统中共五个输入:clk、rst_n、key_in[2..0](3个)
十五个输出:DIG[7..0](8个)、SEL[5..0](6个)、buzzer
在蜂鸣器模块中,因为闹钟铃声为《小星星》,故要写入《小星星》的曲谱,曲谱如下:
0 : pre_set = M1;
1 : pre_set = M1;
2 : pre_set = M5;
3 : pre_set = M5;
4 : pre_set = M6;
5 : pre_set = M6;
6 : pre_set = M5;
7 : pre_set = M0;
8 : pre_set = M4;
9 : pre_set = M4;
10: pre_set = M3;
11: pre_set = M3;
12: pre_set = M2;
13: pre_set = M2;
14: pre_set = M1;
15: pre_set = M0;
16: pre_set = M5;
17: pre_set = M5;
18: pre_set = M4;
19: pre_set = M4;
20: pre_set = M3;
21: pre_set = M3;
22: pre_set = M2;
23: pre_set = M0;
24: pre_set = M5;
25: pre_set = M5;
26: pre_set = M4;
27: pre_set = M4;
28: pre_set = M3;
29: pre_set = M3;
30: pre_set = M2;
31: pre_set = M0;
32: pre_set = M1;
33: pre_set = M1;
34: pre_set = M5;
35: pre_set = M5;
36: pre_set = M6;
37: pre_set = M6;
38: pre_set = M5;
39: pre_set = M0;
40: pre_set = M4;
41: pre_set = M4;
42: pre_set = M3;
43: pre_set = M3;
44: pre_set = M2;
45: pre_set = M2;
46: pre_set = M1;
47: pre_set = M0;
引脚配置如图:

三、实验结果及源代码
源代码:
(1)时钟顶层模块clock_top:
module clock_top #(
parameter MS_1= 16'd50_000,
MS_20= 20'd1000_000,
MS_200= 25'd1000_0000,
MS_500= 25'd1250_0000,
S_1= 26'd5000_0000,
S_3= 28'd15000_0000)
(
input clk,
input rst_n,
input [2:0] key_in,
output [3:0] led,
output buzzer,
output [7:0] DIG,
output [5:0] SEL
);
wire [2:0] press
wire awaken
led_run U_led_run(
.clk (clk ),
.rst_n (rst_n ),
.key_in (key_in ),
.led (led )
);
key_filter #(.MS_20(MS_20),
.MS_200(MS_200))
U_key_filter(
.clk (clk ),
.rst_n (rst_n ),
.key_in (key_in ),
.press (press )
);
display #(.MS_1(MS_1),
.MS_500(MS_500),
.S_1(S_1),
.S_3(S_3))
U_display(
.clk (clk ),
.rst_n (rst_n ),
.press (press ),
.DIG (DIG ),
.SEL (SEL ),
.awaken (awaken )
);
pwm_buzzer U_pwm_buzzer(
.clk (clk),
.rst_n (rst_n),
.awaken (awaken),
.buzzer (buzzer)
);
endmodule
(2)时钟模块key_filter:
module key_filter #(
parameter MS_20 = 20'd1000_000,
MS_200 = 25'd1000_0000)
(
input clk,
input rst_n,
input [2:0] key_in,
output reg [2:0] press
);
localparam IDLE = 4'b0001,
FALL = 4'b0010,
HOLD = 4'b0100,
RISE = 4'b1000;
reg [ 3:0] state_c;
reg [ 3:0] state_n;
reg [19:0] cnt_delay;
reg [ 2:0] key_r0;
reg [ 2:0] key_r1;
wire [ 2:0] nedge;
wire [ 2:0] pedge;
wire idle2fall;
wire fall2idle;
wire fall2hold;
wire hold2rise;
wire rise2idle;
reg [24:0] cnt_long_press;
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
state_c <= IDLE;
end
else begin
state_c <= state_n;
end
end
always @(*) begin
case (state_c)
IDLE:
begin
if (idle2fall) begin
state_n = FALL;
end
else begin
state_n = state_c;
end
end
FALL:
begin
if (fall2idle) begin
state_n = IDLE;
end
else if (fall2hold) begin
state_n = HOLD;
end
else begin
state_n = state_c;
end
end
HOLD:
begin
if (hold2rise) begin
state_n = RISE;
end
else begin
state_n = state_c;
end
end
RISE:
begin
if (rise2idle) begin
state_n = IDLE;
end
else begin
state_n = state_c;
end
end
endcase
end
assign idle2fall = state_c == IDLE && nedge != 'd0;
assign fall2idle = state_c == FALL && pedge != 'd0 && cnt_delay <= MS_20 - 1;
assign fall2hold = state_c == FALL && cnt_delay >= MS_20 - 1;
assign hold2rise = state_c == HOLD && pedge != 'd0;
assign rise2idle = state_c == RISE && cnt_delay >= MS_20 - 1;
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
key_r0 <= 'b0;
key_r1 <= 'b0;
end
else begin
key_r0 <= key_in;
key_r1 <= key_r0;
end
end
assign nedge = ~key_r0 & key_r1;
assign pedge = key_r0 & ~key_r1;
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
cnt_delay <= 0;
end
else if (state_c == FALL || state_c == RISE) begin
if (cnt_delay >= MS_20 - 1 || (state_c == FALL && pedge) || (state_c == RISE && nedge)) begin
cnt_delay <= 0;
end
else begin
cnt_delay <= cnt_delay + 1;
end
end
else begin
cnt_delay <= cnt_delay;
end
end
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
cnt_long_press <= 'd0;
end
else if (state_c == HOLD) begin
if (cnt_long_press >= MS_200 - 'd1) begin
cnt_long_press <= 0;
end
else begin
cnt_long_press <= cnt_long_press + 'd1;
end
end
else begin
cnt_long_press <= p="" class="P12" always="" posedge="" clk="" or="" negedge="" span="" if="" press="" else="" fall2hold="=" b1="" cnt_long_press="">= MS_200 - 'd1) ? ~key_r0 : 'd0;
end
end
endmodule
(3)数码管显示模块display:
module display #(parameter MS_1 = 16'd50_000,
MS_500 = 25'd1250_0000,
S_1 = 26'd5000_0000,
S_3 = 28'd15000_0000)
(
input clk,
input rst_n,
input [ 2:0] press,
output reg [ 7:0] DIG,
output reg [ 5:0] SEL,
output reg awaken
);
parameter NUM_0=8'hc0,
NUM_1=8'hf9,
NUM_2=8'ha4,
NUM_3=8'hb0,
NUM_4=8'h99,
NUM_5=8'h92,
NUM_6=8'h82,
NUM_7=8'hf8,
NUM_8=8'h80,
NUM_9=8'h90,
NUM_10=8'hff,
NUM_11=8'hbf;
reg [15:0] cnt_SEL_flash;
wire end_cnt_SEL_flash;
reg [2:0] SEL_seq;
reg [3:0] DIG_now;
reg radix_point;
wire [ 6:0] year;
wire [ 3:0] month;
wire [ 4:0] day;
wire [ 4:0] hour;
wire [ 5:0] minute;
wire [ 5:0] second;
reg [ 1:0] show_status;
reg [27:0] cnt_interface;
wire nd_cnt_interface;
reg [ 1:0] select_place;
reg [24:0] cnt_glint;
wire end_cnt_glint;
reg glint_flag;
reg end_seting;
reg prepare_set_alarm;
reg set_alarm;
wire [ 5:0] alarm_second;
wire [ 5:0] alarm_minute;
wire [ 4:0] alarm_hour;
reg alarm_status;
reg is_alarm_value;
date_time #(.S_1(S_1)) U_date_time(
.clk (clk),
.rst_n (rst_n),
.press (press),
.select_place (select_place),
.show_status (show_status),
.end_seting (end_seting),
.now_second (second),
.now_minute (minute),
.now_hour (hour),
.now_day (day),
.now_month (month),
.now_year (year)
);
alarm U_alarm(
.clk (clk),
.rst_n (rst_n),
.press (press),
.select_place (select_place),
.show_status (show_status),
.second (alarm_second),
.minute (alarm_minute),
.hour (alarm_hour)
);
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
cnt_SEL_flash <= 'd0;
end
else if (end_cnt_SEL_flash) begin
cnt_SEL_flash <= 'd0;
end
else begin
cnt_SEL_flash <= cnt_SEL_flash + 'd1;
end
end
assign end_cnt_SEL_flash = cnt_SEL_flash >= MS_1 - 'd1 ? 1'b1 : 1'b0;
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
SEL_seq <= 'd0;
end
else if (end_cnt_SEL_flash) begin
if (SEL_seq >= 'd5) begin
SEL_seq <= 'd0;
end
else begin
SEL_seq <= SEL_seq + 'd1;
end
end
else begin
SEL_seq <= SEL_seq;
end
end
always @(*) begin
case (SEL_seq)
3'd0 :
begin
SEL = 6'b111_110;
if (select_place == 'd1 && !glint_flag) begin
DIG_now = 10;
end
else begin
if (show_status == 'd0) begin
DIG_now = hour / 10;
end
else if (show_status == 'd1) begin
DIG_now = year / 10;
end
else begin
if (alarm_status) begin
DIG_now = alarm_hour / 10;
end
else begin
DIG_now = 'd11;
end
end
end
radix_point = 1'b1;
end
3'd1 :
begin
SEL = 6'b111_101;
if (select_place == 'd1 && !glint_flag) begin
DIG_now = 10;
end
else begin
if (show_status == 'd0) begin
DIG_now = hour % 10;
end
else if (show_status == 'd1) begin
DIG_now = year % 10;
end
else begin
if (alarm_status) begin
DIG_now = alarm_hour % 10;
end
else begin
DIG_now = 'd11;
end
end
end
radix_point = 1'b0;
end
3'd2 :
begin
SEL = 6'b111_011;
if (select_place == 'd2 && !glint_flag) begin
DIG_now = 10;
end
else begin
if (show_status == 'd0) begin
DIG_now = minute / 10;
end
else if (show_status == 'd1) begin
DIG_now = month / 10;
end
else begin
if (alarm_status) begin
DIG_now = alarm_minute / 10;
end
else begin
DIG_now = 'd11;
end
end
end
radix_point = 1'b1;
end
3'd3 :
begin
SEL = 6'b110_111;
if (select_place == 'd2 && !glint_flag) begin
DIG_now = 10;
end
else begin
if (show_status == 'd0) begin
DIG_now = minute % 10;
end
else if (show_status == 'd1) begin
DIG_now = month % 10;
end
else begin
if (alarm_status) begin
DIG_now = alarm_minute % 10;
end
else begin
DIG_now = 'd11;
end
end
end
radix_point = 1'b0;
end
3'd4 :
begin
SEL = 6'b101_111;
if (select_place == 'd3 && !glint_flag) begin
DIG_now = 10;
end
else begin
if (show_status == 'd0) begin
DIG_now = second / 10;
end
else if (show_status == 'd1) begin
DIG_now = day / 10;
end
else begin
if (alarm_status) begin
DIG_now = alarm_second / 10;
end
else begin
DIG_now = 'd11;
end
end
end
radix_point = 1'b1;
end
3'd5 :
begin
SEL = 6'b011_111;
if (select_place == 'd3 && !glint_flag) begin
DIG_now = 10;
end
else begin
if (show_status == 'd0) begin
DIG_now = second % 10;
end
else if (show_status == 'd1) begin
DIG_now = day % 10;
end
else begin
if (alarm_status) begin
DIG_now = alarm_second % 10;
end
else begin
DIG_now = 'd11;
end
end
end
radix_point = 1'b1;
end
endcase
end
always @(*) begin
case (DIG_now)
4'd0 : DIG = {radix_point, NUM_0 [6:0]};
4'd1 : DIG = {radix_point, NUM_1 [6:0]};
4'd2 : DIG = {radix_point, NUM_2 [6:0]};
4'd3 : DIG = {radix_point, NUM_3 [6:0]};
4'd4 : DIG = {radix_point, NUM_4 [6:0]};
4'd5 : DIG = {radix_point, NUM_5 [6:0]};
4'd6 : DIG = {radix_point, NUM_6 [6:0]};
4'd7 : DIG = {radix_point, NUM_7 [6:0]};
4'd8 : DIG = {radix_point, NUM_8 [6:0]};
4'd9 : DIG = {radix_point, NUM_9 [6:0]};
4'd10: DIG = {radix_point, NUM_10[6:0]};
4'd11: DIG = {radix_point, NUM_11[6:0]};
default : DIG = 8'b1111_1111;
endcase
end
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
show_status <= 'd0;
end
else if (!awaken) begin
if (press == 3'b100 && !select_place && !show_status) begin
show_status <= 'd1;
end
else if (press == 3'b010 && !select_place) begin
show_status <= 'd2;
end
else if (end_cnt_interface) begin
show_status <= 'd0;
end
end
else begin
show_status <= show_status;
end
end
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
cnt_interface <= 'd0;
end
else if (show_status) begin
if (select_place || end_cnt_interface || set_alarm || press) begin
cnt_interface <= 'd0;
end
else begin
cnt_interface <= cnt_interface + 'd1;
end
end
else begin
cnt_interface <= 'd0;
end
end
assign end_cnt_interface = cnt_interface >= S_3 - 'd1 ? 1'b1 : 1'b0;
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
select_place <= 'd0;
end
else if (prepare_set_alarm) begin
select_place <= 'd0;
end
else if (press == 3'b001 && !awaken && !set_alarm) begin
if (select_place >= 'd3) begin
select_place <= 'd0;
end
else begin
select_place <= select_place + 'd1;
end
end
else begin
select_place <= select_place;
end
end
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
end_seting <= 'd0;
end
else if (select_place == 'd3 && press == 3'b001) begin
end_seting <= 'd1;
end
else begin
end_seting <= 'd0;
end
end
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
cnt_glint <= 'd0;
end
else if (select_place) begin
if (end_cnt_glint || press == 3'b100 || press == 3'b010) begin
cnt_glint <= 'd0;
end
else begin
cnt_glint <= cnt_glint + 'd1;
end
end
else begin
cnt_glint <= 'd0;
end
end
assign end_cnt_glint = cnt_glint >= MS_500 - 'd1 ? 1'b1 : 1'b0;
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
glint_flag <= 'd1;
end
else if (press == 3'b100 || press == 3'b010) begin
glint_flag <= 'd1;
end
else if (select_place) begin
if (end_cnt_glint) begin
glint_flag <= ~glint_flag;
end
else begin
glint_flag <= glint_flag;
end
end
else begin
glint_flag <= 'd1;
end
end
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
prepare_set_alarm <= 'd0;
end
else if (press == 3'b010 && !select_place && !set_alarm && !awaken) begin
prepare_set_alarm <= 'd1;
end
else if (press == 3'b001 || show_status < 2) begin
prepare_set_alarm <= 'd0;
end
else begin
prepare_set_alarm <= prepare_set_alarm;
end
end
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
set_alarm <= 'd0;
end
else if (prepare_set_alarm && press == 3'b001) begin
set_alarm <= 'd1;
end
else if (end_seting || press == 3'b001 || press == 3'b010) begin
set_alarm <= 'd0;
end
else begin
set_alarm <= set_alarm;
end
end
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
alarm_status <= 'd0;
end
else if (press == 3'b100 && set_alarm) begin
alarm_status <= ~alarm_status;
end
else begin
alarm_status <= alarm_status;
end
end
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
is_alarm_value <= 'd0;
end
else if (hour == alarm_hour && minute == alarm_minute && second == alarm_second && alarm_status) begin
is_alarm_value <= 'd1;
end
else begin
is_alarm_value <= 'd0;
end
end
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
awaken <= 'd0;
end
else if (is_alarm_value) begin
awaken <= 'd1;
end
else if (press) begin
awaken <= 'd0;
end
else begin
awaken <= awaken;
end
end
endmodule
(4)设置日期模块date_time:
module date_time #(parameter S_1 = 26'd5000_0000)(
input clk,
input rst_n,
input [2:0] press,
input [1:0] select_place,
input [1:0] show_status,
input end_seting,
output reg [6:0] now_year,
output reg [3:0] now_month,
output reg [4:0] now_day,
output reg [4:0] now_hour,
output reg [5:0] now_minute,
output reg [5:0] now_second
);
reg [25:0] cnt_1s;
wire end_cnt_1s;
wire end_year;
wire end_month;
wire end_day;
wire end_hour;
wire end_minute;
wire end_second;
wire is_leap_year;
wire is_leap_year2;
reg [4:0] day_MAX;
reg [4:0] day_MAX2;
reg [6:0] year;
reg [3:0] month;
reg [4:0] day;
reg [4:0] hour;
reg [5:0] minute;
reg [5:0] second;
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
cnt_1s <= 'd0;
end
else if (end_cnt_1s) begin
cnt_1s <= 'd0;
end
else begin
cnt_1s <= cnt_1s + 'd1;
end
end
assign end_cnt_1s = cnt_1s >= S_1 - 'd1 ? 1'b1 : 1'b0;
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
second <= 'd36;
end
else if (end_seting && show_status == 'd0) begin
second = now_second;
end
else if (end_cnt_1s) begin
if (end_second) begin
second <= 'd0;
end
else begin
second <= second + 'd1;
end
end
else begin
second <= second;
end
end
assign end_second = second >= 59 ? 1'b1 : 1'b0;
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
minute <= 'd16;
end
else if (end_seting && show_status == 'd0) begin
minute = now_minute;
end
else if (end_cnt_1s && end_second) begin
if (end_minute) begin
minute <= 'd0;
end
else begin
minute <= minute + 'd1;
end
end
else begin
minute <= minute;
end
end
assign end_minute = minute >= 59 ? 1'b1 : 1'b0;
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
hour <= 'd6;
end
else if (end_seting && show_status == 'd0) begin
hour = now_hour;
end
else if (end_cnt_1s && end_second && end_minute) begin
if (end_hour) begin
hour <= 'd0;
end
else begin
hour <= hour + 'd1;
end
end
else begin
hour <= hour;
end
end
assign end_hour = hour >= 23 ? 1'b1 : 1'b0;
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
day <= 'd29;
end
else if (end_seting && show_status == 'd1) begin
day = now_day;
end
else if (end_cnt_1s && end_second && end_minute && end_hour) begin
if (end_day) begin
day <= 'd1;
end
else begin
day <= day + 'd1;
end
end
else begin
day <= day;
end
end
assign end_day = day >= day_MAX ? 1'b1 : 1'b1;
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
month <= 'd7;
end
else if (end_seting && show_status == 'd1) begin
month = now_month;
end
else if (end_cnt_1s && end_second && end_minute && end_hour && end_day) begin
if (end_month) begin
month <= 'd1;
end
else begin
month <= month + 'd1;
end
end
else begin
month <= month;
end
end
assign end_month = month >= 12 ? 1'b1 : 1'b0;
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
year <= 'd22;
end
else if (end_seting && show_status == 'd1) begin
year = now_year;
end
else if (end_cnt_1s && end_second && end_minute && end_hour && end_day && end_month) begin
if (end_year) begin
year <= 'd0;
end
else begin
year <= year + 'd1;
end
end
else begin
year <= year;
end
end
assign end_year = year >= 99 ? 1'b1 : 1'b0;
assign is_leap_year = (2000 + year) % 4 == 0 || (2000 + year) % 400 == 0 ? 1'b1 : 1'b0;
always @(*) begin
case (month)
4'd2 : begin
if (is_leap_year) begin
day_MAX = 5'd29;
end
else begin
day_MAX = 5'd28;
end
end
4'd4, 4'd6, 4'd9, 4'd11 : day_MAX = 5'd30;
default: day_MAX = 5'd31;
endcase
end
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
now_hour <= 'd0;
end
else if (select_place) begin
if (select_place == 'd1 && show_status == 'd0) begin
if (press == 'b100) begin
if (now_hour <= 'd0) begin
now_hour = 'd23;
end
else begin
now_hour = now_hour - 'd1;
end
end
else if (press == 'b010) begin
if (now_hour >= 'd23) begin
now_hour = 'd0;
end
else begin
now_hour = now_hour + 'd1;
end
end
else begin
now_hour = now_hour;
end
end
else begin
now_hour = now_hour;
end
end
else begin
now_hour = hour;
end
end
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
now_minute <= 'd0;
end
else if (select_place) begin
if (select_place == 'd2 && show_status == 'd0) begin
if (press == 'b100) begin
if (now_minute <= 'd0) begin
now_minute = 'd59;
end
else begin
now_minute = now_minute - 'd1;
end
end
else if (press == 'b010) begin
if (now_minute >= 'd59) begin
now_minute = 'd0;
end
else begin
now_minute = now_minute + 'd1;
end
end
else begin
now_minute = now_minute;
end
end
else begin
now_minute = now_minute;
end
end
else begin
now_minute = minute;
end
end
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
now_second <= 'd0;
end
else if (select_place) begin
if (select_place == 'd3 && show_status == 'd0) begin
if (press == 'b100) begin
if (now_second <= 'd0) begin
now_second = 'd59;
end
else begin
now_second = now_second - 'd1;
end
end
else if (press == 'b010) begin
if (now_second >= 'd59) begin
now_second = 'd0;
end
else begin
now_second = now_second + 'd1;
end
end
else begin
now_second = now_second;
end
end
else begin
now_second = now_second;
end
end
else begin
now_second = second;
end
end
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
now_year <= 'd0;
end
else if (select_place) begin
if (select_place == 'd1 && show_status == 'd1) begin
if (press == 'b100) begin
if (now_year <= 'd0) begin
now_year = 'd99;
end
else begin
now_year = now_year - 'd1;
end
end
else if (press == 'b010) begin
if (now_year >= 'd99) begin
now_year = 'd0;
end
else begin
now_year = now_year + 'd1;
end
end
else begin
now_year = now_year;
end
end
else begin
now_year = now_year;
end
end
else begin
now_year = year;
end
end
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
now_month <= 'd0;
end
else if (select_place) begin
if (select_place == 'd2 && show_status == 'd1) begin
if (press == 'b100) begin
if (now_month <= 'd1) begin
now_month = 'd12;
end
else begin
now_month = now_month - 'd1;
end
end
else if (press == 'b010) begin
if (now_month >= 'd12) begin
now_month = 'd1;
end
else begin
now_month = now_month + 'd1;
end
end
else begin
now_month = now_month;
end
end
else begin
now_month = now_month;
end
end
else begin
now_month = month;
end
end
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
now_day <= 'd0;
end
else if (select_place) begin
if (select_place == 'd3 && show_status == 'd1) begin
if (press == 'b100) begin
if (now_day <= 'd1) begin
now_day = day_MAX2;
end
else begin
now_day = now_day - 'd1;
end
end
else if (press == 'b010) begin
if (now_day >= day_MAX2) begin
now_day = 'd1;
end
else begin
now_day = now_day + 'd1;
end
end
else begin
now_day = now_day;
end
end
else begin
now_day = now_day;
end
end
else begin
now_day = day;
end
end
assign is_leap_year2 = (2000 + now_year) % 4 == 0 || (2000 + now_year) % 400 == 0 ? 1'b1 : 1'b0;
always @(*) begin
case (now_month)
4'd2 : begin
if (is_leap_year2) begin
day_MAX2 = 5'd29;
end
else begin
day_MAX2 = 5'd28;
end
end
4'd4, 4'd6, 4'd9, 4'd11 : day_MAX2 = 5'd30;
default: day_MAX2 = 5'd31;
endcase
end
endmodule
(5)设置闹钟模块alarm:
module alarm (
input clk,
input rst_n,
input [2:0] press,
input [1:0] select_place,
input [1:0] show_status,
output reg [4:0] hour,
output reg [5:0] minute,
output reg [5:0] second
);
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
hour <= 'd7;
end
else if (select_place == 'd1 && show_status == 'd2) begin
if (press == 3'b100) begin
if (hour <= 'd0) begin
hour <= 'd23;
end
else begin
hour <= hour - 'd1;
end
end
else if (press == 3'b010) begin
if (hour >= 'd23) begin
hour <= 'd0;
end
else begin
hour <= hour + 'd1;
end
end
else begin
hour <= hour;
end
end
else begin
hour <= hour;
end
end
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
minute <= 'd15;
end
else if (select_place == 'd2 && show_status == 'd2) begin
if (press == 3'b100) begin
if (minute <= 'd0) begin
minute <= 'd59;
end
else begin
minute <= minute - 'd1;
end
end
else if (press == 3'b010) begin
if (minute >= 'd59) begin
minute <= 'd0;
end
else begin
minute <= minute + 'd1;
end
end
else begin
minute <= minute;
end
end
else begin
minute <= minute;
end
end
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
second <= 'd0;
end
else if (select_place == 'd3 && show_status == 'd2) begin
if (press == 3'b100) begin
if (second >= 'd0) begin
second <= 'd59;
end
else begin
second <= second - 'd1;
end
end
else if (press == 3'b010) begin
if (second >= 'd59) begin
second <= 'd0;
end
else begin
second <= second + 'd1;
end
end
else begin
second <= second;
end
end
else begin
second <= second;
end
end
endmodule
(6)蜂鸣器模块pwm_buzzer:
module pwm_buzzer(
input clk,
input rst_n,
input awaken,
output reg buzzer
);
parameter YINFU=48;
localparam M0=98800,
M1=95600,
M2=85150,
M3=75850,
M4=71600,
M5=63750,
M6=56800,
M7=50600;
reg [16:0] cnt0;
reg [10:0] cnt1;
reg [5 :0] cnt2;
reg [16:0] pre_set;
wire [16:0] pre_div;
reg [10:0] cishu;
wire [10:0] cishu_div;
always @(posedge clk or negedge rst_n) begin
if(!rst_n) begin
cnt0 <= 0;
end
else if (awaken) begin
if(cnt0 == pre_set - 1)
cnt0 <= 0;
else
cnt0 <= cnt0 + 1;
end
else
cnt0 <= 0;
end
always @(posedge clk or negedge rst_n) begin
if(!rst_n) begin
cnt1 <= 0;
end
else if (awaken) begin
if(cnt0 == pre_set - 1)begin
if(cnt1 == cishu)
cnt1 <= 0;
else
cnt1 <= cnt1 + 1;
end
end
else begin
cnt1 <= 0;
end
end
always @(posedge clk or negedge rst_n) begin
if(!rst_n) begin
cnt2 <= 0;
end
else if (awaken) begin
if(cnt1 == cishu && cnt0 == pre_set - 1) begin
if(cnt2 == YINFU - 1) begin
cnt2 <= 0;
end
else
cnt2 <= cnt2 + 1;
end
end
else begin
cnt2 <= 0;
end
end
always @(*) begin
case(pre_set)
M0:cishu = 242;
M1:cishu = 250;
M2:cishu = 281;
M3:cishu = 315;
M4:cishu = 334;
M5:cishu = 375;
M6:cishu = 421;
M7:cishu = 472;
endcase
end
always @(*) begin
case(cnt2)
0 : pre_set = M1;
1 : pre_set = M1;
2 : pre_set = M5;
3 : pre_set = M5;
4 : pre_set = M6;
5 : pre_set = M6;
6 : pre_set = M5;
7 : pre_set = M0;
8 : pre_set = M4;
9 : pre_set = M4;
10: pre_set = M3;
11: pre_set = M3;
12: pre_set = M2;
13: pre_set = M2;
14: pre_set = M1;
15: pre_set = M0;
16: pre_set = M5;
17: pre_set = M5;
18: pre_set = M4;
19: pre_set = M4;
20: pre_set = M3;
21: pre_set = M3;
22: pre_set = M2;
23: pre_set = M0;
24: pre_set = M5;
25: pre_set = M5;
26: pre_set = M4;
27: pre_set = M4;
28: pre_set = M3;
29: pre_set = M3;
30: pre_set = M2;
31: pre_set = M0;
32: pre_set = M1;
33: pre_set = M1;
34: pre_set = M5;
35: pre_set = M5;
36: pre_set = M6;
37: pre_set = M6;
38: pre_set = M5;
39: pre_set = M0;
40: pre_set = M4;
41: pre_set = M4;
42: pre_set = M3;
43: pre_set = M3;
44: pre_set = M2;
45: pre_set = M2;
46: pre_set = M1;
47: pre_set = M0;
endcase
end
assign pre_div = pre_set >> 1;
assign cishu_div = cishu * 4 / 5;
always @(posedge clk or negedge rst_n) begin
if(!rst_n) begin
buzzer <= 1'b1;
end
else if(pre_set != M0) begin
if(cnt1 < cishu_div) begin
if(cnt0 < pre_div) begin
buzzer <= 1'b1;
end
else begin
buzzer <= 1'b0;
end
end
else begin
buzzer <= 1'b1;
end
end
else begin
buzzer <= 1'b1;
end
end
endmodule
现象与结果:
编译无误后写入开发板,数码管显示时间,默认为06:16:36;

将时间修改为北京时间:

日期显示为22年12月8日;

闹钟设置为15点整:

当时间到15点整,蜂鸣器响:
此时按任意键关闭闹钟。
不论任何时候按reset按键重置电子时钟。
四、个人总结
起初学这门课程不明白这个课到底想干什么,也不认为有学习的必要,觉得在其他语言面前这些啥也算不上。但是经过一学期的学习,我慢慢得发现其实这门课学的可能会更好,每一种语言都有他的优势和劣势。我们作为学习者,我们学习一个语言不代表我们只用他,我们当然会用其他,但是学习其他语言可以让我们的思路更加开阔。在课设开始前本来想做音乐播放器,但是无从下手,只能放弃,又没有完全放弃,闹钟让我小试牛刀了一下,经过几次失败还是给我做出来了。