vivado万年历设计,下面代码还少了什么模块,麻烦补齐
module key_filter
#(parameter WIDTH = 20'd99) //因为是仿真,所以该值要小一点。如果是下载到实物上,这个值就改为999_999
(
input sys_clk,sys_rest,key_in,
output reg key_flag
);
reg[19:0] CNT_20MS;
always @(posedge sys_clk or negedge sys_rest) begin
if(!sys_rest)
CNT_20MS<=20'd0;
else if(key_in==1'b1) //按键未按下为1 按下为0
CNT_20MS<=20'd0;
else if(CNT_20MS==WIDTH)
CNT_20MS<=WIDTH;
else
CNT_20MS<=CNT_20MS+1;
end
always @(posedge sys_clk or negedge sys_rest) begin
if(!sys_rest)
key_flag<=1'b0;
else if(CNT_20MS==WIDTH-1)
key_flag<=1'b1;
else
key_flag<=1'b0;
end
endmodule
//按键驱动模块
//实现功能:检测按键并转换状态。按键按下为0
//输入信号:系统时钟、复位、翻页按键、数码管闪烁选择按键、加一按键
//输出信号:翻页选择状态、数码管闪烁选择状态、时分秒和年月日和闹钟时分秒的加一脉冲信号
//当按下翻页按键时,转换翻页状态、当按下数码管闪烁选择按键时转换当前数码管闪烁选择状态、当按下加一按键时生成每个部分的专属增一脉冲信号(秒分时....的增一信号都分开)
//显示状态有三个(一共有三页)状态转换为:00-->01-->10
//数码管显示状态有四个(一个没选中和三个不同得选择)状态转换:00-->01-->10-->11(00是谁也没选的状态)
module key_drive_module(system_clk,reset,key_turn,key_switch,key_add,flag_switch,flag_turn,second_add,minute_add,hour_add,day_add,month_add,year_add,alarm_second_add,alarm_minute_add,alarm_hour_add,select_sign);
input key_turn,key_switch,key_add,system_clk,reset;
output [1:0] flag_switch,flag_turn;
output select_sign;
output second_add,minute_add,hour_add,day_add,month_add,year_add,alarm_second_add,alarm_minute_add,alarm_hour_add;
reg [3:0] flag_add=0;
reg second_add,minute_add,hour_add,day_add,month_add,year_add,alarm_second_add,alarm_minute_add,alarm_hour_add;
reg [1:0] flag_turn=0,turn_state=0,turn_next_state=0; //翻页状态机(分别是输出、现态、次态)
reg [1:0] flag_switch=0,switch_state=0,switch_next_state=0;//当前选择数码管状态机
assign select_sign=(flag_add==4'b0000);
//页面切换的状态机
//次态电路
always@(negedge key_turn or negedge reset) //敏感信号为页面切换按键(按下按键切换状态) 页面切换状态:00-->01-->10
begin
if(!reset) turn_next_state=2'b00;
else
case(turn_state)
2'b00:turn_next_state=2'b01;
2'b01:turn_next_state=2'b10;
2'b10:turn_next_state=2'b00;
default:turn_next_state=2'b00;
endcase
end
//次态到现态转换
always@(posedge system_clk or negedge reset)
begin
if(!reset) turn_state<=2'b00;
else turn_state<=turn_next_state;
end
//输出电路
always@(reset or turn_state)
begin
if(!reset) flag_turn= 2'b00;
else
case(turn_state)
2'b00:flag_turn=2'b00;
2'b01:flag_turn=2'b01;
2'b10:flag_turn=2'b10;
default:flag_turn=2'b00;
endcase
end
//数码管闪烁选择的状态机
//次态电路
always@(negedge key_switch or negedge reset) //敏感信号为选项切换按键(按下按键切换状态) 页面切换状态:00-->01-->10-->11
begin
if(!reset) switch_next_state=2'b00;
else
case(switch_state)
2'b00:switch_next_state=2'b01;
2'b01:switch_next_state=2'b10;
2'b10:switch_next_state=2'b11;
2'b11:switch_next_state=2'b00;
default:switch_next_state=2'b00;
endcase
end
//次态-->现态转换
always@(posedge system_clk or negedge reset)
begin
if(!reset) switch_state<=2'b00;
else switch_state<=switch_next_state;
end
//输出电路
always@(reset or switch_state)
begin
if(!reset) flag_switch= 2'b00;
else
case(switch_state)
2'b00:flag_switch=2'b00;
2'b01:flag_switch=2'b01;
2'b10:flag_switch=2'b10;
2'b11:flag_switch=2'b11;
default:switch_next_state=2'b00;
endcase
end
//增一选择项目
always@(turn_state or switch_state or reset) //敏感信号为当前页面状态、数码管闪烁选择状态(当选择项目变动时,增一选择项目也随之变化)
begin
if(!reset) flag_add=4'b0000;//0000代表空状态(都没选)
else
case(turn_state)//当前页面
2'b00: //第一页(时分秒)
case(switch_state)//当前数码管闪烁选择
2'b00:flag_add=4'b0000;
2'b01:flag_add=4'b0001;//选中秒
2'b10:flag_add=4'b0010;//选中分
2'b11:flag_add=4'b0011;//选中时
endcase
2'b01: //第二页(年月日)
case(switch_state)
2'b00:flag_add=4'b0000;
2'b01:flag_add=4'b0101;//选中日
2'b10:flag_add=4'b0110;//选中月
2'b11:flag_add=4'b0111;//选中年
endcase
2'b10: //第三页(闹钟)
case(switch_state)
2'b00:flag_add=4'b0000;
2'b01:flag_add=4'b1001;//选中闹钟秒
2'b10:flag_add=4'b1010;//选中闹钟分
2'b11:flag_add=4'b1011;//选中闹钟时
endcase
default:flag_add=4'b0000;
endcase
end
//生成增一的专属信号
always@(key_add)//敏感信号为增一按键,当按键按下时,专属增一脉冲为0;当按键抬起时,专属增一脉冲为1;
begin
case(flag_add)
4'b0001:second_add=key_add;
4'b0010:minute_add=key_add;
4'b0011:hour_add=key_add;
4'b0101:day_add=key_add;
4'b0110:month_add=key_add;
4'b0111:year_add=key_add;
4'b1001:alarm_second_add=key_add;
4'b1010:alarm_minute_add=key_add;
4'b1011:alarm_hour_add=key_add;
default:; //其它的都什么也不执行
endcase
end
endmodule
//时钟模块
//实现功能:计时功能及其时钟设置功能
//输入信号:系统时钟、复位按键、时分秒年月日的加一信号
//输出信号:年月日和时分秒、秒脉冲
module clock(system_clk,reset,select_sign,second_add,minute_add,hour_add,day_add,month_add,year_add,second,minute,hour,day,month,year);
input system_clk,reset,second_add,minute_add,hour_add,day_add,month_add,year_add;
input select_sign;
output [5:0] second;//最大59
output [5:0] minute;//最大59
output [4:0] hour;//最大23
output [4:0] day;//最大31
output [3:0] month;//最大12
output [6:0] year;//最大99
reg [31:0]p;//最大24999999
wire pulse_second;//秒脉冲
reg [5:0] second;
reg [5:0] second_set;
wire pulse_minute; //分脉冲
reg [5:0] minute;
reg [5:0] minute_set;
wire pulse_hour;//小时脉冲
reg [4:0] hour;
reg [4:0] hour_set;
wire pulse_day;//日脉冲
reg [4:0] day=5'd8;
reg [4:0] day_set;
reg [3:0] day_month;
reg [6:0] day_year;
wire pulse_month;//月脉冲
reg [3:0] month;
reg [3:0] month_set;
wire pulse_year;//年脉冲
reg [6:0] year;
reg [6:0] year_set;
always@(posedge system_clk or negedge reset)//敏感信号:系统时钟和复位
begin
if(!reset)
p<=0;
else
if(p==49999999)
p<=0;
else
p<=p+1;
end
assign pulse_second=(p==49999999 && (select_sign==1'b1)); //秒脉冲
//秒部分
always@(posedge system_clk)
begin
if(!reset)
second<=6'd35;
else
if(pulse_second) //秒脉冲
if(second>=59)
second<=0;
else
second<=second+1;
else if(!second_add) //增一信号
second<=second_set;
else
second<=second;
end
//分脉冲信号的生成
assign pulse_minute=(second==6'd59 && pulse_second==1'b1); //分脉冲
//秒设置
always@(negedge second_add)
begin
second_set=second; //先读取当前秒
if(second_set>=59)
second_set=0;
else
second_set=second_set+1;
end
//分部分
always@(posedge system_clk)
begin
if(!reset)
minute<=6'd24;
else
if(pulse_minute)
if(minute>=59)
minute<=0;
else
minute<=minute+1;
else if(!minute_add)
minute<=minute_set;
else
minute<=minute;
end
//小时脉冲的生成
assign pulse_hour=(minute==6'd59 && pulse_minute==1'b1); //小时脉冲
//分设置
always@(negedge minute_add)
begin
minute_set=minute;
if(minute_set>=59)
minute_set=0;
else
minute_set=minute_set+1;
end
//小时部分
always@(posedge system_clk)
begin
if(!reset)
hour<=5'd16;
else
if(pulse_hour)
if(hour>=23)
hour<=0;
else
hour<=hour+1;
else if(!hour_add)
hour<=hour_set;
else
hour<=hour;
end
//天脉冲的生成
assign pulse_day=(hour==5'd23 && pulse_hour==1'b1);
//小时的设置
always@(negedge hour_add)
begin
hour_set=hour;
if(hour_set>=23)
hour_set=0;
else
hour_set=hour_set+1;
end
//天部分
always@(posedge system_clk)
begin
if(!reset)
day<=5'd8;
else
if(pulse_day) //天脉冲
if(month==1 || month==3 ||month==5 || month==7 || month==8 || month==10 || month==12)
if(day>=31)
day<=1;
else
day<=day+1;
else if(month==4 || month==6 ||month==9 || month==11)
if(day>=30)
day<=1;
else
day<=day+1;
else if(month==2 && (year%4==0))
if(day>=29)
day<=1;
else
day<=day+1;
else
if(day>=28)
day<=1;
else
day<=day+1;
else if(!day_add)
day<=day_set;
else
day<=day;
end
//月脉冲的生成
assign pulse_month=((day==5'd28 && month==4'd2 && (year%4!=0) && pulse_day==1'b1)
||(day==5'd29 && month==4'd2 && (year%4==0) && pulse_day==1'b1)
||(day==5'd30 && (month==4'd4 || month==4'd6 ||month==4'd9 || month==4'd11) && pulse_day==1'b1)
||(day==5'd31 && (month==4'd1 || month==4'd3 ||month==4'd5 || month==4'd7 || month==4'd8 || month==4'd10 || month==4'd12) && pulse_day==1'b1));
//天的设置
always@(negedge day_add)
begin
day_set=day;
day_month=month;
day_year=year;
if(day_month==1 || day_month==3 ||day_month==5 || day_month==7 || day_month==8 || day_month==10 || day_month==12)
if(day_set>=31)
day_set<=1;
else
day_set<=day_set+1;
else if(day_month==4 || day_month==6 ||day_month==9 || day_month==11)
if(day_set>=30)
day_set<=1;
else
day_set<=day_set+1;
else if(day_month==2 && (day_year%4==0)) //闰年
if(day_set>=29)
day_set<=1;
else
day_set<=day_set+1;
else
if(day_set>=28)
day_set<=1;
else
day_set<=day_set+1;
end
//月部分
always@(posedge system_clk)
begin
if(!reset)
month<=4'd12;
else
if(pulse_month)
if(month>=12)
month<=1;
else
month<=month+1;
else if(!month_add)
month<=month_set;
else
month<=month;
end
//年脉冲的生成
assign pulse_year=(month==4'd12 && pulse_month==1'b1);
//月设置
always@(negedge month_add)
begin
month_set=month;
if(month_set>=12)
month_set=1;
else
month_set=month_set+1;
end
//年部分
always@(posedge system_clk)
begin
if(!reset)
year<=7'd21;
else
if(pulse_year)
if(year>=99)
year<=0;
else
year<=year+1;
else if(!year_add)
year<=year_set;
else
year<=year;
end
//年设置
always@(negedge year_add)
begin
year_set=year;
if(year_set>=99)
year_set=0;
else
year_set=year_set+1;
end
endmodule
//闹钟模块
//实现功能:设置闹钟,闹钟时间到时闹钟响1分钟
//输入信号:拨码开关(使能信号)、时钟模块的时分秒、按键驱动模块的时分秒专属增一脉冲信号
//输出信号:LED灯、蜂鸣器、当前的设置时间(给显示模块来显示)
module alarm(sys_clk,reset,second,minute,hour,switch_alarm,alarm_second_add,alarm_minute_add,alarm_hour_add,led,beep,alarm_second,alarm_minute,alarm_hour);
input sys_clk,reset,switch_alarm,alarm_second_add,alarm_minute_add,alarm_hour_add;
input [5:0] second;
input [5:0] minute;
input [4:0] hour;
output led,beep;
output [5:0] alarm_second;
output [5:0] alarm_minute;
output [4:0] alarm_hour;
reg [5:0] alarm_second;
reg [5:0] alarm_minute;
reg [4:0] alarm_hour;
assign led=switch_alarm; //拨码开关开时亮
assign beep=((minute==alarm_minute&&hour==alarm_hour&&switch_alarm==1'b1)||(minute==6'd59 && second==6'd59));
//设置秒
always@(negedge alarm_second_add or negedge reset)
begin
if(!reset)
alarm_second<=6'd30;
else
if(alarm_second>=59)
alarm_second<=0;
else
alarm_second<=alarm_second+1;
end
//设置分
always@(negedge alarm_minute_add or negedge reset)
begin
if(!reset)
alarm_minute<=6'd30;
else
if(alarm_minute>=59)
alarm_minute<=0;
else
alarm_minute<=alarm_minute+1;
end
//设置时
always@(negedge alarm_hour_add or negedge reset)
begin
if(!reset)
alarm_hour<=6'd12;
else
if(alarm_hour>=23)
alarm_hour<=0;
else
alarm_hour<=alarm_hour+1;
end
endmodule
module seg(
input sys_clk,sys_rest,
input [15:0] data,
output reg [3:0] sel,
output reg [6:0] seg_led
);
parameter CLK_NUM=4'd10;
parameter MSNUM=14'd5000;
reg [3:0] CNT_NUM;
reg CLK;
reg [12:0] MSCNT;
reg MS_flag;
reg [3:0] num_display;
reg [15:0] num;
reg [2:0] sel_num; //选择哪一位数码管被点亮
//wire define
wire [3:0] data0 ; // 个位数
wire [3:0] data1 ; // 十位数
wire [3:0] data2 ; // 百位数
wire [3:0] data3 ; // 千位数
//提取显示数值所对应的十进制数的各个位
assign data0 = data[3:0]; // 个位数
assign data1 = data[7:4]; // 十位数
assign data2 = data[11:8]; // 百位数
assign data3 = data[15:12]; // 千位数
always @(posedge sys_clk or negedge sys_rest) begin
if(!sys_rest)
begin
CNT_NUM<=4'd0;
CLK<=1'd1;
end
else if(CNT_NUM<=CLK_NUM/2-1'b1)
begin
CLK<=~CLK;
CNT_NUM<=4'd0;
end
else
begin
CNT_NUM<=CNT_NUM+1;
CLK<=CLK;
end
end
always @(posedge CLK or negedge sys_rest) begin
if(!sys_rest)
num<=16'd0;
else
begin
num[15:12] <= data3; //则依次给4位数码管赋值
num[11:8] <= data2;
num[ 7:4] <= data1;
num[ 3:0] <= data0;
end
end
always @(posedge CLK or negedge sys_rest) begin //产生1ms脉冲
if(!sys_rest)
begin
MSCNT<=13'd0;
MS_flag<=1'b0;
end
else if(MSCNT==MSNUM-1)
begin
MSCNT<=13'd0;
MS_flag<=1'b1;
end
else
begin
MSCNT<=MSCNT+1;
MS_flag<=1'b0;
end
end