verilog实现万年历
` 模块分为:时间产生模块,时钟模块,报警模块
项目要求
设计要求:
- 6个数码管显示年月日或者时分秒,通过外部一个按键A可以切换显示;
- 按键A长按可以进入时间设置;短按B按键可以切换要设置的内容;
- 外部第二个按键 B,长按 2s,显示闹钟设置界面:
- 闹钟显示时,数码管会闪烁(0.5s亮0.5s 灭),设置小时,小时闪烁:设置分钟,分钟闪烁:闹钟可设置小时和分钟,闹钟显示 形式可以是xx0000显示,也可以是0000xx显示,其中xx就是全黑;设置闹钟模式下,短按B键,切换设置小时或者分钟;
- 外部第三第四个按键C和D,设置小时时,C加D减,设置分钟时,同样是C加D减:设置完毕,长按B键2s退出设置闹钟模式,回到正常显示模式:
- 当前时间和闹钟时间(小时和分钟)一致时,蜂鸣器响3s,(程序已经改成led闪烁3s)
整体架构流程
在时间产生模块,产生 年月日, 时分秒;时钟模块实现 设置时钟的时间;报警模块实现,声光报警
例如:
在语言模型中,编码器和解码器都是由一个个的 Transformer 组件拼接在一起形成的。
程序实现
1.顶层文件
module top(
input wire clk,
input wire rst_n,
input wire [3:0] key,
output wire [5:0] sel,
output wire [7:0] seg,
output wire [3:0] led
);
wire [5:0] code;
wire switch_flag;
wire alarm_flag;
wire add_flag;
wire reduce_flag;
wire [7:0] hour_data;
wire [7:0] min_data;
wire [7:0] s_data;
wire day_add;
wire [7:0] year_data;
wire [7:0] mon_data;
wire [7:0] day_data;
wire [7:0] seg_data_12;
wire [7:0] seg_data_34;
wire [7:0] seg_data_56;
wire [5:0] code_alarm;
wire [7:0] alarm_hour_data;
wire [7:0] alarm_min_data;
wire alarm_set_flag;
wire alarm_switch_flag;
wire time_set_flag;
wire time_switch_flag;
wire adjust_time_en;
wire [5:0] time_code;
wire display_day_time;
wire [5:0] day_code;
wire adjust_day_en;
jitter_alarm jitter_alarm_inst(
.clk (clk),
.rst_n (rst_n),
.key (key[1]),
.long_flag (alarm_set_flag),
.short_flag (alarm_switch_flag)
);
jitter_alarm jitter_time_inst(
.clk (clk),
.rst_n (rst_n),
.key (key[0]),
.long_flag (time_set_flag),
.short_flag (time_switch_flag)
);
jitter jitter_inst_add(
.clk (clk),
.rst_n (rst_n),
.key (key[2]),
.flag (add_flag)
);
jitter jitter_inst_reduce(
.clk (clk),
.rst_n (rst_n),
.key (key[3]),
.flag (reduce_flag)
);
time_data time_data_inst(
.clk (clk),
.rst_n (rst_n),
.add_flag (add_flag),
.reduce_flag (reduce_flag),
.time_set_flag (~time_set_flag),
.time_switch_flag (~time_switch_flag),
.hour_data (hour_data),
.min_data (min_data),
.s_data (s_data),
.day_add_flag (day_add),
.adjust_time_en (adjust_time_en),
.time_code (time_code),
.display_day_time (display_day_time)
);
year_data year_data_inst(
.clk (clk),
.rst_n (rst_n),
.day_add_flag (day_add),
.add_flag (add_flag),
.reduce_flag (reduce_flag),
.day_set_flag (~time_set_flag),
.day_switch_flag (~time_switch_flag),
.display_day_time (display_day_time),
.year_data (year_data),
.mon_data (mon_data),
.day_data (day_data),
.adjust_day_en (adjust_day_en),
.day_code (day_code)
);
alarm_set alarm_set_inst(
.clk (clk),
.rst_n (rst_n),
.add_flag (add_flag),
.alarm_set_flag (~alarm_set_flag),
.alarm_switch_flag (~alarm_switch_flag),
.reduce_flag (reduce_flag),
.hour_data (hour_data),
.min_data (min_data),
.code_alarm (code_alarm),
.alarm_hour_data (alarm_hour_data),
.alarm_min_data (alarm_min_data)
);
mux3_1 mux3_1_inst(
.clk (clk),
.rst_n (rst_n),
.hour_data (hour_data),
.min_data (min_data),
.s_data (s_data),
.yeat_data (year_data),
.mon_data (mon_data),
.day_data (day_data),
.switch_flag (~time_switch_flag),
.alarm_hour_data (alarm_hour_data),
.alarm_min_data (alarm_min_data),
.code_alarm (code_alarm),
.alarm_set_flag (~alarm_set_flag),
.adjust_time_en (adjust_time_en),
.adjust_day_en (adjust_day_en),
.time_code (time_code),
.day_code (day_code),
.seg_data_12 (seg_data_12),
.seg_data_34 (seg_data_34),
.seg_data_56 (seg_data_56),
.code (code),
.display_day_time (display_day_time)
);
seven_tube_driver seven_tube_driver_inst(
.clk (clk),
.rst_n (rst_n),
.data12 (seg_data_12),
.data34 (seg_data_34),
.data56 (seg_data_56),
.code (code),
.sel (sel),
.seg (seg)
);
warn warn_inst(
.clk (clk),
.rst_n (rst_n),
.hour_data (hour_data),
.min_data (min_data),
.s_data (s_data),
.alarm_h (alarm_hour_data),
.alarm_m (alarm_min_data),
.led (led)
);
endmodule
- 按键模块(长按 短按)
`timescale 1ns / 1ps
module jitter_alarm (
input wire clk,
input wire rst_n,
input wire key,
output reg long_flag,
output reg short_flag
);
parameter t = 500_000; //10_000_000/20
parameter T_2s = 2_000_000_000 / 20;
parameter T = 500_000;
// reg temp1, temp2;
// wire pos_edge, neg_edge;
reg state;
reg [18:0] cnt;
reg [26:0] cnt_push;
reg flag;
reg [29:0] cnt_long;
reg flag_r;
wire flag_neg;
/*
always @ (posedge clk, negedge rst_n)
begin
if(rst_n == 1'b0)
begin
temp1 <= 1'b1;
temp2 <= 1'b1;
end
else
begin
temp1 <= key;
temp2 <= temp1;
end
end
assign pos_edge = temp1 & (~temp2);
assign neg_edge = (~temp1) & temp2;
*/
always @ (posedge clk, negedge rst_n)
begin
if(rst_n == 1'b0)
begin
cnt <= 19'd0;
state <= 1'b0;
flag <= 1'b1;
cnt_push <= 27'd0;
end
else
case(state)
1'd0 : begin
if(key == 1'b0)
begin
if(cnt_push == T - 1)
begin
cnt_push <= 27'd0;
state <= 1'b1;
flag <= 1'b0;
end
else
begin
cnt_push <= cnt_push + 1'b1;
state <= 1'b0;
flag <= 1'b1;
end
end
else
begin
cnt_push <= 27'd0;
state <= 1'b0;
flag <= 1'b1;
end
end
1'b1 : begin
if(key == 1'b1)
begin
if(cnt == t - 1)
begin
cnt <= 19'd0;
state <= 1'b0;
flag <= 1'b1;
end
else
begin
cnt <= cnt + 1'b1;
state <= 1'b1;
flag <= 1'b0;
end
end
else
begin
cnt <= 19'd0;
state <= 1'b1;
flag <= 1'b0;
end
end
endcase
end
always @ (posedge clk) flag_r <= flag;
assign flag_neg = flag & ~flag_r;
always @ (posedge clk, negedge rst_n) begin
if (rst_n == 1'b0)
cnt_long <= 30'd0;
else
if (flag == 1'b0)
cnt_long <= cnt_long + 1'b1;
else
cnt_long <= 30'd0;
end
always @ (posedge clk,negedge rst_n) begin
if (rst_n == 1'b0)
begin
long_flag <= 1'b0;
short_flag <= 1'b0;
end
else
if (flag_neg == 1'b1)
if (cnt_long > T_2s)
long_flag <= 1'b1;
else
short_flag <= 1'b1;
else
begin
long_flag <= 1'b0;
short_flag <= 1'b0;
end
end
endmodule
3. top文件里面例化的按键消抖模块(低有效)
module jitter(
input wire clk,
input wire rst_n,
input wire key,
output reg flag
);
parameter t = 500_000; //10_000_000/20
// reg temp1, temp2;
// wire pos_edge, neg_edge;
reg state;
reg [18:0] cnt;
/*
always @ (posedge clk, negedge rst_n)
begin
if(rst_n == 1'b0)
begin
temp1 <= 1'b1;
temp2 <= 1'b1;
end
else
begin
temp1 <= key;
temp2 <= temp1;
end
end
assign pos_edge = temp1 & (~temp2);
assign neg_edge = (~temp1) & temp2;
*/
always @ (posedge clk, negedge rst_n)
begin
if(rst_n == 1'b0)
begin
cnt <= 19'd0;
state <= 1'b0;
flag <= 1'b1;
end
else
case(state)
1'd0 : begin
if(key == 1'b0)
begin
if(cnt == t - 1)
begin
cnt <= 19'd0;
state <= 1'b1;
flag <= 1'b0;
end
else
begin
cnt <= cnt + 1'b1;
state <= 1'b0;
flag <= 1'b1;
end
end
else
begin
cnt <= 19'd0;
state <= 1'b0;
flag <= 1'b1;
end
end
1'b1 : begin
if(key == 1'b1)
begin
if(cnt == t - 1)
begin
cnt <= 19'd0;
state <= 1'b0;
flag <= 1'b1;
end
else
begin
cnt <= cnt + 1'b1;
state <= 1'b1;
flag <= 1'b1;
end
end
else
begin
cnt <= 19'd0;
state <= 1'b1;
flag <= 1'b1;
end
end
endcase
end
endmodule
4. 时间计时模块
module time_data (
input wire clk,
input wire rst_n,
input wire add_flag,
input wire reduce_flag,
input wire time_set_flag,
input wire time_switch_flag,
input wire display_day_time,
output wire [7:0] hour_data,
output wire [7:0] min_data,
output wire [7:0] s_data,
output wire day_add_flag,
output reg adjust_time_en,
output reg [5:0] time_code
);
parameter T_1s = 1_000_000_000 / 20;
reg [25:0] cnt;
reg [5:0] cnt_s;
reg [5:0] cnt_min;
reg [5:0] cnt_hour;
wire s_flag;
wire min_flag;
wire hour_falg;
wire day_flag;
reg [1:0] state_set_time;
reg [2:0] state_switch_time;
reg [25:0] cnt_set_time;
always @ (posedge clk, negedge rst_n) begin
if (rst_n == 1'b0)
cnt <= 26'd0;
else
if (adjust_time_en == 1'b0)
if (cnt < T_1s)
cnt <= cnt + 1'b1;
else
cnt <= 26'd0;
else
cnt <= cnt;
end
assign s_flag = (cnt == T_1s) ? 1'b1 : 1'b0;
always @ (posedge clk, negedge rst_n) begin
if (rst_n == 1'b0)
cnt_s <= 6'd0;
else
if (adjust_time_en == 1'b0)
if (s_flag == 1'b1)
if (cnt_s < 6'd59)
cnt_s <= cnt_s + 1'b1;
else
cnt_s <= 6'd0;
else
cnt_s <= cnt_s;
else if (adjust_time_en == 1'b1 && display_day_time == 1'b0)
if (state_switch_time == 3'd1)
if (add_flag == 1'b0)
if (cnt_s < 6'd59)
cnt_s <= cnt_s + 1'b1;
else
cnt_s <= 6'd0;
else if (reduce_flag == 1'b0)
if (cnt_s > 6'd0)
cnt_s <= cnt_s - 1'b1;
else
cnt_s <= 6'd59;
else
cnt_s <= cnt_s;
else
cnt_s <= cnt_s;
else
cnt_s <= cnt_s;
end
assign min_flag = (cnt_s == 6'd59 && cnt == T_1s)? 1'b1 : 1'b0;
always @ (posedge clk, negedge rst_n) begin
if (rst_n == 1'b0)
cnt_min <= 6'd59;
else
if (adjust_time_en == 1'b0)
if (min_flag == 1'b1)
if (cnt_min < 6'd59)
cnt_min <= cnt_min + 1'b1;
else
cnt_min <= 6'd0;
else
cnt_min <= cnt_min;
else if (adjust_time_en == 1'b1 && display_day_time == 1'b0)
if (state_switch_time == 3'd2)
if (add_flag == 1'b0)
if (cnt_min < 6'd59)
cnt_min <= cnt_min + 1'b1;
else
cnt_min <= 6'd0;
else if (reduce_flag == 1'b0)
if (cnt_min == 6'd0)
cnt_min <= 6'd59;
else
cnt_min <= cnt_min - 1'b1;
else
cnt_min <= cnt_min;
else
cnt_min <= cnt_min;
else
cnt_min <= cnt_min;
end
assign hour_falg = (cnt_min == 6'd59 && cnt_s == 6'd59 && cnt == T_1s)? 1'b1 : 1'b0;
always @ (posedge clk, negedge rst_n) begin
if (rst_n == 1'b0)
cnt_hour <= 6'd10;
else
if (adjust_time_en == 1'b0)
if (hour_falg == 1'b1)
if (cnt_hour < 6'd23)
cnt_hour <= cnt_hour + 1'b1;
else
cnt_hour <= 6'd0;
else
cnt_hour <= cnt_hour;
else if (adjust_time_en == 1'b1 && display_day_time == 1'b0)
if (state_switch_time == 3'd3)
if (add_flag == 1'b0)
if (cnt_hour < 6'd23)
cnt_hour = cnt_hour + 1'b1;
else
cnt_hour <= 6'd0;
else if (reduce_flag == 1'b0)
if (cnt_hour == 6'd0)
cnt_hour <= 6'd23;
else
cnt_hour <= cnt_hour - 1'b1;
else
cnt_hour <= cnt_hour;
else
cnt_hour <= cnt_hour;
else
cnt_hour <= cnt_hour;
end
assign day_add_flag = (cnt_hour == 6'd23 && cnt_min == 6'd59 && cnt_s == 6'd59 && cnt == T_1s) ? 1'b1 : 1'b0;
assign hour_data = cnt_hour;
assign min_data = cnt_min;
assign s_data = cnt_s;
always @ (posedge clk, negedge rst_n) begin
if (rst_n == 1'b0)
cnt_set_time <= 26'd0;
else
if (adjust_time_en == 1'b1 && display_day_time == 1'b0)
if (cnt_set_time < T_1s)
cnt_set_time <= cnt_set_time + 1'b1;
else
cnt_set_time <= 26'd0;
else
cnt_set_time <= 26'd0;
end
always @ (posedge clk, negedge rst_n) begin
if (rst_n == 1'b0)
begin
adjust_time_en <= 1'b0;
state_set_time <= 2'd0;
end
else
if (display_day_time == 1'b0)
case (state_set_time)
2'd0 : if (time_set_flag == 1'b0)
state_set_time <= 2'd1;
else
begin
state_set_time <= 2'd0;
adjust_time_en <= 1'b0;
end
2'd1 : if (time_set_flag == 1'b0)
state_set_time <= 2'd0;
else
begin
state_set_time <= 2'd1;
adjust_time_en <= 1'b1;
end
endcase
else
begin
adjust_time_en <= 1'b0;
state_set_time <= 2'd0;
end
end
always @ (posedge clk, negedge rst_n) begin
if (rst_n == 1'b0)
begin
state_switch_time <= 3'd0;
time_code <= 6'b11_11_11;
end
else
case (state_switch_time)
3'd0 : if (state_set_time == 2'd1 && display_day_time == 1'b0)
state_switch_time <= 3'd1;
else
state_switch_time <= 3'd0;
3'd1 : if (time_switch_flag == 1'b0)
state_switch_time <= 3'd2;
else
if (cnt_set_time < T_1s / 2)
time_code <= 6'b11_11_11;
else
time_code <= 6'b11_11_00;
3'd2 : if (time_switch_flag == 1'b0)
state_switch_time <= 3'd3;
else
if (cnt_set_time < T_1s / 2)
time_code <= 6'b11_11_11;
else
time_code <= 6'b11_00_11;
3'd3 : if (time_switch_flag == 1'b0)
state_switch_time <= 3'd1;
else
if (cnt_set_time < T_1s / 2)
time_code <= 6'b11_11_11;
else
time_code <= 6'b00_11_11;
endcase
end
endmodule
5. 年月日计时模块
module year_data (
input wire clk,
input wire rst_n,
input wire day_add_flag,
input wire add_flag,
input wire reduce_flag,
input wire day_set_flag,
input wire day_switch_flag,
input wire display_day_time,
output wire [7:0] year_data,
output wire [7:0] mon_data,
output wire [7:0] day_data,
output reg adjust_day_en,
output reg [5:0] day_code
);
parameter T_1s = 1_000_000_000 / 20;
reg [5:0] cnt_day;
reg [3:0] cnt_mon;
reg [7:0] cnt_year;
wire mon_flag;
wire year_flag;
reg [5:0] num_day;
reg [1:0] state_set_day;
reg [2:0] state_switch_day;
reg [25:0] cnt_set_day;
always @ (posedge clk, negedge rst_n) begin
if (rst_n == 1'b0)
num_day <= 6'd0;
else
if (cnt_mon == 4'd1 && cnt_mon == 4'd3 && cnt_mon == 4'd5 && cnt_mon == 4'd7 && cnt_mon == 4'd8 && cnt_mon == 4'd10 && cnt_mon == 4'd12)
num_day <= 6'd31;
else if (cnt_mon == 4'd2)
if (year_data % 4 == 1'b0)
num_day <= 6'd29;
else
num_day <= 6'd28;
else
num_day <= 6'd30;
end
always @ (posedge clk, negedge rst_n) begin
if (rst_n == 1'b0)
cnt_day <= 6'd31;
else
if (adjust_day_en == 1'b0)
if (day_add_flag == 1'b1)
if (cnt_day < num_day)
cnt_day <= cnt_day + 1'b1;
else
cnt_day <= 6'd0;
else
cnt_day <= cnt_day;
else if (adjust_day_en == 1'b1 && display_day_time == 1'b1)
if (state_switch_day == 3'd1)
if (add_flag == 1'b0)
if (cnt_day < num_day)
cnt_day <= cnt_day + 1'b1;
else
cnt_day <= 6'd0;
else if (reduce_flag == 1'b0)
if (cnt_day == 6'd0)
cnt_day <= num_day;
else
cnt_day <= cnt_day - 1'b1;
else
cnt_day <= cnt_day;
else
cnt_day <= cnt_day;
else
cnt_day <= cnt_day;
end
assign mon_flag = (cnt_day == num_day && day_add_flag) ? 1'b1 : 1'b0;
always @ (posedge clk, negedge rst_n) begin
if (rst_n == 1'b0)
cnt_mon <= 5'd12;
else
if (adjust_day_en == 1'b0)
if (mon_flag == 1'b1)
if (cnt_mon < 5'd12)
cnt_mon <= cnt_mon + 1'b1;
else
cnt_mon <= 5'd1;
else
cnt_mon <= cnt_mon;
else if (adjust_day_en == 1'b1 && display_day_time == 1'b1)
if (state_switch_day == 3'd2)
if (add_flag == 1'b0)
if (cnt_mon < 5'd12)
cnt_mon <= cnt_mon + 1'b1;
else
cnt_mon <= 5'd1;
else if (reduce_flag == 1'b0)
if (cnt_mon == 5'd1)
cnt_mon <= 5'd12;
else
cnt_mon <= cnt_mon - 1'b1;
else
cnt_mon <= cnt_mon;
else
cnt_mon <= cnt_mon;
end
assign year_flag = (cnt_mon == 5'd12 && cnt_day == num_day && day_add_flag == 1'b1) ? 1'b1 : 1'b0;
always @ (posedge clk, negedge rst_n) begin
if (rst_n == 1'b0)
cnt_year <= 8'd24;
else
if (adjust_day_en == 1'b0)
if (year_flag == 1'b1)
if (cnt_year < 8'd99)
cnt_year <= cnt_year + 1'b1;
else
cnt_year <= 8'd0;
else
cnt_year <= cnt_year;
else if (adjust_day_en == 1'b1 && display_day_time == 1'b1)
if (state_switch_day == 3'd3)
if (add_flag == 1'b0)
if (cnt_year < 8'd99)
cnt_year <= cnt_year + 1'b1;
else
cnt_year <= 8'd0;
else if (reduce_flag == 1'b0)
if (cnt_year == 8'd0)
cnt_year <= 8'd99;
else
cnt_year <= cnt_year - 1'b1;
else
cnt_year <= cnt_year;
else
cnt_year <= cnt_year;
end
assign year_data = cnt_year;
assign mon_data = cnt_mon;
assign day_data = cnt_day;
always @ (posedge clk, negedge rst_n) begin
if (rst_n == 1'b0)
cnt_set_day <= 26'd0;
else
if (adjust_day_en == 1'b1 && display_day_time == 1'b1)
if (cnt_set_day < T_1s)
cnt_set_day <= cnt_set_day + 1'b1;
else
cnt_set_day <= 26'd0;
else
cnt_set_day <= 26'd0;
end
always @ (posedge clk, negedge rst_n) begin
if (rst_n == 1'b0)
begin
adjust_day_en <= 1'b0;
state_set_day <= 2'd0;
end
else
if (display_day_time == 1'b1)
case (state_set_day)
2'd0 : if (day_set_flag == 1'b0)
state_set_day <= 2'd1;
else
begin
state_set_day <= 2'd0;
adjust_day_en <= 1'b0;
end
2'd1 : if (day_set_flag == 1'b0)
state_set_day <= 2'd0;
else
begin
state_set_day <= 2'd1;
adjust_day_en <= 1'b1;
end
endcase
else
begin
adjust_day_en <= 1'b0;
state_set_day <= 2'd0;
end
end
always @ (posedge clk, negedge rst_n) begin
if (rst_n == 1'b0)
begin
state_switch_day <= 3'd0;
day_code <= 6'b11_11_11;
end
else
case (state_switch_day)
3'd0 : if (state_set_day == 2'd1 && display_day_time == 1'b1)
state_switch_day <= 3'd1;
else
state_switch_day <= 3'd0;
3'd1 : if (day_switch_flag == 1'b0)
state_switch_day <= 3'd2;
else
if (cnt_set_day < T_1s / 2)
day_code <= 6'b11_11_11;
else
day_code <= 6'b11_11_00;
3'd2 : if (day_switch_flag == 1'b0)
state_switch_day <= 3'd3;
else
if (cnt_set_day < T_1s / 2)
day_code <= 6'b11_11_11;
else
day_code <= 6'b11_00_11;
3'd3 : if (day_switch_flag == 1'b0)
state_switch_day <= 3'd1;
else
if (cnt_set_day < T_1s / 2)
day_code <= 6'b11_11_11;
else
day_code <= 6'b00_11_11;
endcase
end
endmodule
7. 设置闹钟模块
module alarm_set (
input wire clk,
input wire rst_n,
input wire add_flag,
input wire alarm_set_flag,
input wire alarm_switch_flag,
input wire reduce_flag,
input wire [7:0] hour_data,
input wire [7:0] min_data,
output reg [5:0] code_alarm,
output reg [7:0] alarm_hour_data,
output reg [7:0] alarm_min_data
);
parameter T = 1_000_000_000 / 20;
reg [26:0] cnt;
reg [1:0] state_s;
reg [1:0] state_code;
reg half_flag;
reg [2:0] state_data;
always @ (posedge clk, negedge rst_n) begin //produce 0.5 time
if (rst_n == 1'b0)
begin
cnt <= 27'd0;
state_s <= 2'd0;
half_flag <= 1'b0;
end
else
case (state_s)
2'd0 : if (alarm_set_flag == 1'b0)
state_s <= 2'd1;
else
begin
state_s <= 2'd0;
cnt <= 27'd0;
end
2'd1 : if (alarm_set_flag == 1'b0)
state_s <= 2'd0;
else
if (cnt == T - 1'b1)
begin
half_flag <= 1'b1;
cnt <= 27'd0;
end
else
begin
cnt <= cnt + 1'b1;
half_flag <= 1'b0;
end
endcase
end
always @ (posedge clk, negedge rst_n) begin //0.5 light or close
if (rst_n == 1'b0)
begin
code_alarm <= 6'b00_1111;
state_code <= 2'd0;
end
else
case (state_code)
2'd0 : if (alarm_set_flag == 1'b0)
state_code <= 2'd1;
else
state_code <= 2'd0;
2'd1 : if (alarm_switch_flag == 1'b0)
state_code <= 2'd2;
else
if (cnt < T / 2 - 1'b1)
code_alarm <= 6'b00_11_11;
else
code_alarm <= 6'b00_11_00;
2'd2 : if (alarm_switch_flag == 1'b0)
state_code <= 2'd1;
else
if (cnt < T / 2 - 1'b1)
code_alarm <= 6'b00_11_11;
else
code_alarm <= 6'b00_00_11;
default : code_alarm <= code_alarm;
endcase
end
always @ (posedge clk, negedge rst_n) begin //key control add or reduce
if (rst_n == 1'b0)
begin
state_data <= 3'd0;
alarm_hour_data <= 8'd0;
alarm_min_data <= 8'd0;
end
else
case (state_data)
3'd0 : if (alarm_set_flag == 1'b0)
begin
alarm_hour_data <= hour_data;
alarm_min_data <= min_data;
state_data <= 3'd1;
end
else
begin
alarm_hour_data <= alarm_hour_data;
alarm_min_data <= alarm_min_data;
end
3'd1 : if (state_code == 2'd1)
if (add_flag == 1'b0)
if (alarm_min_data < 8'd59)
alarm_min_data <= alarm_min_data + 1'b1;
else
alarm_min_data <= 8'd0;
else if (reduce_flag == 1'b0)
if (alarm_min_data > 8'd0)
alarm_min_data <= alarm_min_data - 1'b1;
else
alarm_min_data <= 8'd59;
else
alarm_min_data <= alarm_min_data;
else if (state_code == 2'd2)
if (add_flag == 1'b0)
if (alarm_hour_data < 8'd23)
alarm_hour_data <= alarm_hour_data + 1'b1;
else
alarm_hour_data <= 8'd0;
else if (reduce_flag == 1'b0)
if (alarm_hour_data > 8'd0)
alarm_hour_data <= alarm_hour_data - 1'b1;
else
alarm_hour_data <= 8'd23;
else
alarm_hour_data <= alarm_hour_data;
else
begin
alarm_hour_data <= alarm_hour_data;
alarm_min_data <= alarm_min_data;
end
endcase
end
endmodule
8. 具体给数码管显示的内容模块(年月日 / 时分秒/ 闹钟调时 三选一要显示的数据)
module mux3_1 (
input wire clk,
input wire rst_n,
input wire [7:0] hour_data,
input wire [7:0] min_data,
input wire [7:0] s_data,
input wire [7:0] yeat_data,
input wire [7:0] mon_data,
input wire [7:0] day_data,
input wire switch_flag,
input wire [7:0] alarm_hour_data,
input wire [7:0] alarm_min_data,
input wire [5:0] code_alarm,
input wire alarm_set_flag,
input wire adjust_time_en,
input wire adjust_day_en,
input wire [5:0] time_code,
input wire [5:0] day_code,
output reg [7:0] seg_data_12,
output reg [7:0] seg_data_34,
output reg [7:0] seg_data_56,
output reg [5:0] code,
output reg display_day_time
);
reg [3:0] state;
always @ (posedge clk, negedge rst_n) begin
if (rst_n == 1'b0)
begin
state <= 4'd0;
seg_data_12 <= 8'd0;
seg_data_34 <= 8'd0;
seg_data_56 <= 8'd0;
code <= 6'b11_11_11;
display_day_time <= 1'b0;
end
else
case (state)
4'd0 : if (switch_flag == 1'b0 && adjust_time_en == 1'b0)
state <= 4'd1;
else if (alarm_set_flag == 1'b0)
state <= 4'd2;
else
begin
if (adjust_time_en == 1'b0)
begin
code <= 6'b11_11_11;
seg_data_12 <= hour_data;
seg_data_34 <= min_data;
seg_data_56 <= s_data;
display_day_time <= 1'b0;
end
else
begin
code <= time_code;
seg_data_12 <= hour_data;
seg_data_34 <= min_data;
seg_data_56 <= s_data;
display_day_time <= 1'b0;
end
end
4'd1 : if (switch_flag == 1'b0 && adjust_day_en == 1'b0)
state <= 4'd0;
else
if (adjust_day_en == 1'b0)
begin
state <= 4'd1;
seg_data_12 <= yeat_data;
seg_data_34 <= mon_data;
seg_data_56 <= day_data;
code <= 6'b11_11_11;
display_day_time <= 1'b1;
end
else
begin
seg_data_12 <= yeat_data;
seg_data_34 <= mon_data;
seg_data_56 <= day_data;
display_day_time <= 1'b1;
code <= day_code;
end
4'd2 : if (alarm_set_flag == 1'b0)
state <= 4'd0;
else
begin
state <= 4'd2;
seg_data_34 <= alarm_hour_data;
seg_data_56 <= alarm_min_data;
code <= code_alarm;
end
default : begin
seg_data_12 <= seg_data_12;
seg_data_34 <= seg_data_34;
seg_data_56 <= seg_data_56;
end
endcase
end
endmodule
9. 数码管显示(七段数码管)
module seven_tube_driver(
input wire clk,
input wire rst_n,
input wire [7:0] data12,
input wire [7:0] data34,
input wire [7:0] data56,
input wire [5:0] code,
output reg [5:0] sel,
output wire [7:0] seg
);
parameter t = 50_000;
//parameter code = 6'b111_111;
// parameter data = 24'h641691;
reg [15:0] cnt;
reg [3:0] show_data;
wire seg_point;
reg [7:0] seg_temp;
always @ (posedge clk, negedge rst_n)
begin
if(rst_n == 1'b0)
cnt <= 16'd0;
else if(cnt == t - 1)
cnt <= 16'd0;
else
cnt <= cnt + 1'b1;
end
always @ (posedge clk, negedge rst_n)
begin
if(rst_n == 1'b0)
sel <= 6'b111_110;
else if(cnt == t - 1)
sel <= {sel[4:0],sel[5]};
else
sel <= sel;
end
always @ (*)
begin
case(sel)
6'b011_111 : begin
if(code[5])
show_data = data12/10;
else
show_data = 4'hf;
end
6'b101_111 : begin
if(code[4])
show_data = data12%10;
else
show_data = 4'hf;
end
6'b110_111 : begin
if(code[3])
show_data = data34/10;
else
show_data = 4'hf;
end
6'b111_011 : begin
if(code[2])
show_data = data34%10;
else
show_data = 4'hf;
end
6'b111_101 : begin
if(code[1])
show_data = data56/10;
else
show_data = 4'hf;
end
6'b111_110 : begin
if(code[0])
show_data = data56%10;
else
show_data = 4'hf;
end
default : show_data = 4'hf;
endcase
end
always @ (*)
begin
case(show_data)
4'd0 : seg_temp = 8'b1100_0000;
4'd1 : seg_temp = 8'b1111_1001;
4'd2 : seg_temp = 8'b1010_0100;
4'd3 : seg_temp = 8'b1011_0000;
4'd4 : seg_temp = 8'b1001_1001;
4'd5 : seg_temp = 8'b1001_0010;
4'd6 : seg_temp = 8'b1000_0010;
4'd7 : seg_temp = 8'b1111_1000;
4'd8 : seg_temp = 8'b1000_0000;
4'd9 : seg_temp = 8'b1001_0000;
default : seg_temp = 8'hff;
endcase
end
assign seg_point = (sel == 6'b101_111 || sel == 6'b111_011)? 1'b0 : 1'b1;
assign seg = {seg_temp[7] & seg_point, seg_temp[6:0]};
endmodule
10. 闹钟报警 (板子没有蜂鸣器,用了led灯闪光代替)
功能: 间隔0.5s闪烁,闪烁三秒
module warn (
input wire clk,
input wire rst_n,
input wire [7:0] hour_data,
input wire [7:0] min_data,
input wire [7:0] alarm_h,
input wire [7:0] alarm_m,
input wire [7:0] s_data,
output reg [3:0] led
);
parameter T_warn = 1_000_000_000 / 20 / 4;
reg [25:0] cnt_warm;
wire warn_flag;
assign warn_flag = (hour_data == alarm_h && min_data == alarm_m && s_data < 8'd4)? 1'b1 : 1'b0;
always @ (posedge clk, negedge rst_n) begin
if (rst_n == 1'b0)
cnt_warm <= 26'd0;
else
if (warn_flag == 1'b1)
if (cnt_warm < T_warn)
cnt_warm <= cnt_warm + 1'b1;
else
cnt_warm <= 26'd0;
else
cnt_warm <= 26'd0;
end
always @ (posedge clk, negedge rst_n) begin
if (rst_n == 1'b0)
led <= 4'b1111;
else
if (warn_flag == 1'b1)
if (cnt_warm == T_warn)
led <= ~led;
else
led <= led;
else
led <= 4'b1111;
end
endmodule
## 小结
本项目是基于黑金xc7a35t 开发,数码管可以正常显示时间,按键可以正常使用(按键包含长按和短按),可以正常设置闹钟。