赞
踩
1. 具有显示时、分、秒、计时功能,按24小时制计时;(本例实现)
2. 具有校时功能,能够对“时”和“分”进行校时;
3. 具有闹钟功能;
通过FPGA晶振产生的50MHz时钟产生1hz的时钟信号;
得到的1hz时钟作为计时模块的时钟输入,得到时钟模块的时,分,秒的输出;
通过对应的输出通过转换模块将其转换为双位十进制数据;
最后通过LCD数码管显示;
1. 分频模块
2. 计数器模块
顶层模块:
module timer( input sys_clk, input rst, output light, output S_l, output S_h, output M_l, output M_h, output H_l, output H_h ); wire clk_1hz; wire count_s; wire count_m; wire en_s; wire en_m; wire en_h; assign en_s=1'b1; assign en_m=count_s && en_s; assign en_h=count_m && en_m; clk1hz( .clk(sys_clk), .rst(rst), .a(clk_1hz) ); CNT60 u1( .clk(clk_1hz), .rst(rst), .en(en_s), .cnt(Sec), .count(count_s) ); CNT60 u2( .clk(clk_1hz), .rst(rst), .en(en_m), .cnt(Min), .count(count_m) ); CNT24( .clk(clk_1hz), .rst(rst), .en(en_h), .cnt(Hour) ); endmodule
分频模块
module clk1hz( input clk, input rst, output reg a ); reg [32:0] tmp; always @(posedge clk or negedge rst) begin if(!rst) begin tmp <= 0; a<=0; end else begin if(tmp<29)begin tmp<=tmp+1; a<=a; end else begin tmp <=0; a<=~a; end end end endmodule
60计数模块
module CNT60( input clk, input rst, input en, output reg [5:0] cnt, output reg count) ; always @(posedge clk or negedge rst)begin if(!rst) begin cnt<=0; end else begin if(en==1) begin if(cnt<59)begin if(cnt==58)begin count<=1; cnt<=cnt+1; end else begin cnt<=cnt+1; count<=0; end end else begin cnt<=0; end end end end endmodule
24计数模块
module CNT24( input clk, input rst, input en, output reg [4:0] cnt ); always @(posedge clk or negedge rst) begin if(!rst) begin cnt<=0; end else begin if(en==1) begin if(cnt<23)begin cnt<=cnt+1; end else begin cnt<=0; end end end end endmodule
该部分实验板测板测式可用。
//多功能时钟 //时钟,调整时间,整点报时,闹钟,秒表 /* input clk, //50MHz input rst_n, input [2:0] key_in, //按键输入 output [5:0] sel, //数码管位选 output [6:0] seg, //数码管段选 output time_led, //整点报时(闪烁) output all_led //闹钟 */ // module top(input clk, //50MHz input rst_n, input [2:0] key_in, //按键输入 input [1:0] sw, output [6:0] h0, output [6:0] h1, output [6:0] h2, output [6:0] h3, //数码管段选 output time_led //整点报时(闪烁) //output all_led //闹钟 ); endmodule //按键消抖 module key_filter( input clk, input rst_n, input key_in, output reg key_state, //预留 output key_flag ); parameter CNT_MAX = 5; //20ms计数值 1_000_000 reg [19:0] key_H, key_L; //计数变量 //------------------按键为低 计数------------------------------------------------------------------------------------------------- always@(posedge clk, negedge rst_n) begin if(!rst_n) key_H <= 20'd0; else begin if(key_in) key_H <= key_H + 1; else key_H <= 20'd0; end end //-------------------按键为高 计数----------------------------------------------------------------------------------------------------- always@(posedge clk, negedge rst_n) begin if(!rst_n) key_L <= 20'd0; else begin if(!key_in) key_L <= key_L + 1; else key_L <= 20'd0; end end //-------------------key_state输出判断------------------------------------------------------------------------------------------------------- always@(posedge clk, negedge rst_n) begin if(!rst_n) key_state <= 1'b1; else begin if(key_H > CNT_MAX) key_state <= 1'b1; else if(key_L > CNT_MAX) key_state <= 1'b0; end end //---------------------按键按下 下降沿判断------------------------------------------------------------- reg state1, state2; always@(posedge clk, negedge rst_n) begin if(!rst_n) begin state1 <= 1'b0; state2 <= 1'b0; end else begin state1 <= key_state; state2 <= state1; end end assign key_flag = (!state1) & state2; //按键按下,flag为高 endmodule //模式转换 状态机 module model_change( input clk, input rst_n, input key_in, output [1:0] model ); //------------------------------------------- 模式:00:时钟,01:闹钟,10:秒表,11:调时 -------------------------------------------------------------------------- reg [1:0] cnt; always@(posedge clk, negedge rst_n) begin if(!rst_n) begin cnt <= 2'd0; end else if(key_in) //按键按下 cnt <= cnt + 1'b1; // 00 01 10 11循环 else cnt <= cnt; end assign model = cnt; endmodule //---- key1 模式切换 (时间显示,校准时间,闹钟, 秒表) //---- key2 调时和设置闹钟时,小时、分钟左右切捯 //---- key3 +1 //---- sw0 秒表暂停(开始)切换 //---- sw1 秒表清除 module key_module( input clk, input rst_n, input [2:0] key_in, input [2:0]sw, output [1:0] model, //模式:00:时钟,01:闹钟,10:秒表,11:调时 output reg [1:0] adjust_shif, //调整时间时,调整位置:00:秒个位,01:分个位,10:时个位 output key_up, //调整时间+ output reg pause, //秒表暂停/开始 0:暂停,1:开始 output clear //秒表清除 ); //-------------------------------------- 例化key_filter,产生按键对应的高电平脉冲 ---------------------------------------------------------------- wire [2:0] key_out; genvar i; generate for(i = 0; i < 3; i = i + 1) begin: specify7_key_filter //块名 key_filter fliter1( .clk (clk), .rst_n (rst_n), .key_in (key_in[i]), .key_state (), .key_flag (key_out[i]) ); end endgenerate assign key_up = key_out[3]; assign clear = sw[2]; //-------------------------------------------- 例化 model_change ------------------------------------------------------------------------------------------- model_change model1( .clk (clk), .rst_n (rst_n), .key_in (key_out[1]), .model (model) ); //-------------------------------------------- adjust_shif 调整时间位置 ------------------------------------------------------------------------------------ always@(posedge clk, negedge rst_n) begin if(!rst_n) begin adjust_shif <= 2'b00; end else begin if(key_out[2]) begin adjust_shif <= adjust_shif + 1'b1; //非阻塞赋值,需要到过程块结束才赋新值,所以 adjust_shif == 2'b10,而不是11 if(adjust_shif == 2'b10) adjust_shif <= 2'b00; end if(key_out[1]) // model模式改变时,回到初始位 adjust_shif <= 2'b00; end end //------------------------------------------------ pause 秒表暂停/开始 -------------------------------------------------------------------------------------------------- always@(posedge clk, negedge rst_n) begin if(!rst_n) pause <= 1'b0; else if(sw[1]) pause <= ~pause; else if(model != 2'b10) //退出秒表模式暂停 pause <= 1'b0; else pause <= pause; end endmodule //分频 module clk_div( //clk_out的周期,可在上层模块例化时修改 input clk_in, input rst_n, output clk_out ); //-------------------------------------------------------------------------------- parameter CNT_MAX = 25_000_000; //计数值/2 reg clk_reg; reg [27:0] cnt; //------------------------------------------------------------------------------------- assign clk_out = clk_reg; always@(posedge clk_in, negedge rst_n) begin if(!rst_n) begin clk_reg <= 1'b0; cnt <= 28'd0; end else begin if(cnt == CNT_MAX - 1) begin cnt <= 28'd0; clk_reg <= ~clk_reg; end else begin cnt <= cnt + 1'b1; clk_reg <= clk_reg; end end end endmodule module time_counter( input clk, //input clk_1s, input rst_n, input [1:0] model, input date_time_ch, //时间和日期切换标志位D?o时间,1为日朠 input [23:0] adjust_time_num, //时间调整倠 input [23:0] adjust_date_num, //日期调整倠 output [23:0] time_num, output [23:0] data_num, output time_led ); //---------------------------- 秒表显示变量 -------------------------------- reg [3:0] toc_10ms; reg [3:0] toc_100ms; reg [3:0] toc_1s; reg [3:0] toc_10s; reg [3:0] toc_1m; reg [3:0] toc_10m; //------------------------- 1s时钟上升沿检浭---------------------------------------- wire clk_1s; clk_div #(.CNT_MAX(10)) clk_div_1s( .clk_in (clk), .rst_n (rst_n), .clk_out (clk_1s) ); reg clk_reg1, clk_reg2; wire pos_1s; always@(posedge clk, negedge rst_n) begin if(!rst_n) begin clk_reg1 <= 1'b0; clk_reg2 <= 1'b0; end else begin clk_reg1 <= clk_1s; clk_reg2 <= clk_reg1; end end assign pos_1s = clk_reg1 & (!clk_reg2); //---------------------正常时间计数(时、分、秒M----------------------------- reg [3:0] sec0; reg [3:0] sec1; reg [3:0] min0; reg [3:0] min1; reg [3:0] hour0; reg [3:0] hour1; always@(posedge clk, negedge rst_n) begin if(!rst_n) begin sec0 <= 4'd9; //默认时间23:56:49 sec1 <= 4'd4; min0 <= 4'd8; min1 <= 4'd5; hour0 <= 4'd3; hour1 <= 4'd2; end else begin if(pos_1s) begin sec0 <= sec0 + 1'b1; if(sec0 == 4'd9) begin sec0 <= 4'd0; sec1 <= sec1 + 1'b1; if(sec1 == 4'd5) begin sec1 <= 4'd0; min0 <= min0 + 1'b1; if(min0 == 4'd9) begin min0 <= 4'd0; min1 <= min1 + 1'b1; if(min1 == 4'd5) begin min1 <= 4'd0; hour0 <= hour0 + 1'b1; if(hour0 == 4'd9) begin hour0 <= 4'd0; hour1 <= hour1 + 1'b1; end end end end end end if(hour1 ==4'd2 && hour0 == 4'd4) begin hour1 <= 4'd0; hour0 <= 4'd0; end if((model == 2'b11) && !date_time_ch) begin //时间校准模式 {hour1, hour0, min1, min0, sec1, sec0} <= adjust_time_num[23:0]; end end end //--------------------- 日期时间(年、月、日M------------------------------ reg [3:0] day0; reg [3:0] day1; reg [3:0] month0; //年、月、日计数变量 reg [3:0] month1; reg [3:0] year0; reg [3:0] year1; localparam mon1 = 8'h31, //每个月天敠 mon2 = 8'h28, mon3 = 8'h31, mon4 = 8'h30, mon5 = 8'h31, mon6 = 8'h30, mon7 = 8'h31, mon8 = 8'h31, mon9 = 8'h30, mon10 = 8'h31, mon11 = 8'h30, mon12 = 8'h31; always@(posedge clk, negedge rst_n) begin if(!rst_n) begin day0 <= 4'd8; //为了方便仿真看到变化,默认日期为2020-12-28 day1 <= 4'd2; month0 <= 4'd2; month1 <= 4'd1; year0 <= 4'd0; year1 <= 4'd2; end else begin if(hour1 ==4'd2 && hour0 == 4'd4) begin //24小时删 day0 <= day0 + 1; if(day0 == 4'd9) begin day0 <= 4'd0; day1 <= day1 + 1'b1; end case({month1, month0}) //根据月份,来改变 8'h01: if({day1, day0} == mon1) begin day0 <= 4'd1; day1 <= 4'd0; month0 <= month0 + 1'b1; end 8'h02: if({day1, day0} == mon2) begin day0 <= 4'd1; day1 <= 4'd0; month0 <= month0 + 1'b1; end 8'h03: if({day1, day0} == mon3) begin day0 <= 4'd1; day1 <= 4'd0; month0 <= month0 + 1'b1; end 8'h04: if({day1, day0} == mon4) begin day0 <= 4'd1; day1 <= 4'd0; month0 <= month0 + 1'b1; end 8'h05: if({day1, day0} == mon5) begin day0 <= 4'd1; day1 <= 4'd0; month0 <= month0 + 1'b1; end 8'h06: if({day1, day0} == mon6) begin day0 <= 4'd1; day1 <= 4'd0; month0 <= month0 + 1'b1; end 8'h07: if({day1, day0} == mon7) begin day0 <= 4'd1; day1 <= 4'd0; month0 <= month0 + 1'b1; end 8'h08: if({day1, day0} == mon8) begin day0 <= 4'd1; day1 <= 4'd0; month0 <= month0 + 1'b1; end 8'h09: if({day1, day0} == mon9) begin day0 <= 4'd1; day1 <= 4'd0; month0 <= 4'd0; month1 <= 4'd1; //月份高位也变 end 8'h10: if({day1, day0} == mon10) begin day0 <= 4'd1; day1 <= 4'd0; month0 <= month0 + 1'b1; end 8'h11: if({day1, day0} == mon11) begin day0 <= 4'd1; day1 <= 4'd0; month0 <= month0 + 1'b1; end 8'h12: if({day1, day0} == mon12) begin //12月最后一夠 day0 <= 4'd1; day1 <= 4'd0; month0 <= 4'd1; month1 <= 4'd0; year0 <= year0 + 1'b1; //下一幠 if(year0 == 4'd9) begin year0 <= 4'd0; year1 <= year1 + 1'b1; end end default: begin day0 <= 4'hx; //为了方便仿真,设为x day1 <= 4'hx; month0 <= 4'hx; month1 <= 4'hx; year0 <= 4'hx; year1 <= 4'hx; end endcase end if((model == 2'b11) && date_time_ch) //时间校准模式,并且处于日期显示下 {year1, year0, month1, month0, day1, day0} <= adjust_date_num[23:0]; end end //------------------------------------------------------------ 整点报时 --------------------------------------------------------------------- reg len_flag; always@(posedge clk, negedge rst_n) begin if(!rst_n) len_flag <= 1'b0; else if(time_num[15:0] == 16'b0) //分钟和秒都归零 len_flag <= 1'b1; else if(min0 == 4'd1) //1分钟 len_flag <= 1'b0; else len_flag <= len_flag; end assign time_led = len_flag ? clk_1s : 1'b0; //1s闪烁,持续1分钟 //---------------------------------------------------------- 输出赋值----------------------------------------------------------------------- assign time_num = {hour1, hour0, min1, min0, sec1, sec0}; assign data_num = {year1, year0, month1, month0, day1, day0}; endmodule module adjust_module( input clk, input rst_n, input [1:0] model, //模式P:时钟,01:闹钟,10:秒表,11:调无 input date_time_ch, input [1:0] adjust_shif, //调整时间时,调整位置P:秒个位Q:分个位P:时个位 input key_up, //调整时间+ input key_down, //调整时间- input [23:0] time_num, input [23:0] data_num, output [23:0] adjust_time_num, output [23:0] adjust_date_num, output [15:0] adjust_clock_num ); //---------------------------- 闹钟变量 ------------------------------------------------------------------------------------------- reg [3:0] clock_min0; reg [3:0] clock_min1; reg [3:0] clock_hour0; reg [3:0] clock_hour1; //----------------------------- 闹钟设置 ------------------------------------------------------------------------------------------------ always@(posedge clk, negedge rst_n) begin if(!rst_n) begin clock_min0 <= 4'd0; clock_min1 <= 4'd0; clock_hour0 <= 4'd0; clock_hour1 <= 4'd0; end else if(model == 2'b01) begin //闹钟模式,只有小时、分钟 if(adjust_shif == 2'b00) begin //调分钟个位 if(key_up) begin clock_min0 <= clock_min0 + 1'b1; if(clock_min0 == 4'd9) clock_min0 <= 4'd0; end else if(key_down) begin clock_min0 <= clock_min0 - 1'b1; if(clock_min0 == 4'd0) clock_min0 <= 4'd9; end end else if(adjust_shif == 2'b01) begin //调分钟十位 if(key_up) begin clock_min1 <= clock_min1 + 1'b1; if(clock_min1 == 4'd5) clock_min1 <= 4'd0; end else if(key_down) begin clock_min1 <= clock_min1 - 1'b1; if(clock_min1 == 4'd0) clock_min1 <= 4'd5; end end else begin //小时个位 if(key_up) begin clock_hour0 <= clock_hour0 + 1'b1; if(clock_hour0 == 4'd9) begin clock_hour0 <= 4'd0; clock_hour1 <= clock_hour1 + 1'b1; end if(clock_hour1 ==4'd2 && clock_hour0 == 4'd3) begin clock_hour1 <= 4'd0; clock_hour0 <= 4'd0; end end else if(key_down) begin clock_hour0 <= clock_hour0 - 1'b1; if(clock_hour0 == 4'd0) begin clock_hour0 <= 4'd9; clock_hour1 <= clock_hour1 - 1'b1; end if(clock_hour1 ==4'd0 && clock_hour0 == 4'd0) begin clock_hour1 <= 4'd2; clock_hour0 <= 4'd3; end end end end end //-------------------------- 校准时间变量 ------------------------------------------------------------------------------------------------ reg [3:0] adj_sec0; reg [3:0] adj_sec1; reg [3:0] adj_min0; reg [3:0] adj_min1; reg [3:0] adj_hour0; reg [3:0] adj_hour1; /*------------------------*/ reg [3:0] adj_day0; reg [3:0] adj_day1; reg [3:0] adj_month0; reg [3:0] adj_month1; reg [3:0] adj_year0; reg [3:0] adj_year1; //----------------------------- 校准时间和日期-------------------------------------------------------------------------------------------------------- always@(posedge clk, negedge rst_n) begin if(!rst_n) begin adj_sec0 <= 4'd9; adj_sec1 <= 4'd4; adj_min0 <= 4'd6; adj_min1 <= 4'd5; adj_hour0 <= 4'd3; adj_hour1 <= 4'd2; adj_day0 <= 4'd8; adj_day1 <= 4'd0; adj_month0 <= 4'd6; adj_month1 <= 4'd0; adj_year0 <= 4'd0; adj_year1 <= 4'd2; end else if((model == 2'b11) && !date_time_ch)begin case(adjust_shif) //调时 位置 2'b00: begin //秒个位 if(key_up) begin adj_sec0 <= adj_sec0 + 1'b1; if(adj_sec0 == 4'd9) begin adj_sec0 <= 4'd0; adj_sec1 <= adj_sec1 + 1'b1; if(adj_sec1 == 4'd5) begin adj_sec1 <= 4'd0; end end end else if(key_down) begin adj_sec0 <= adj_sec0 - 1'b1; if(adj_sec0 == 4'd0) begin adj_sec0 <= 4'd9; adj_sec1 <= adj_sec1- 1'b1; if(adj_sec1 == 4'd0) begin adj_sec1 <= 4'd5; end end end end 2'b01: begin //分个位 if(key_up) begin adj_min0 <= adj_min0 + 1'b1; if(adj_min0 == 4'd9) begin adj_min0 <= 4'd0; adj_min1 <= adj_min1 + 1'b1; if(adj_min1 == 4'd5) begin adj_min1 <= 4'd0; end end end else if(key_down) begin adj_min0 <= adj_min0 - 1'b1; if(adj_min0 == 4'd0) begin adj_min0 <= 4'd9; adj_min1 <= adj_min1- 1'b1; if(adj_min1 == 4'd0) begin adj_min1 <= 4'd5; end end end end 2'b10: begin //时个位 if(key_up) begin adj_hour0 <= adj_hour0 + 1'b1; if(adj_hour0 == 4'd9) begin adj_hour0 <= 4'd0; adj_hour1 <= adj_hour1 + 1'b1; end if(adj_hour1 ==4'd2 && adj_hour0 == 4'd3) begin adj_hour1 <= 4'd0; adj_hour0 <= 4'd0; end end if(key_down) begin adj_hour0 <= adj_hour0 - 1'b1; if(adj_hour0 == 4'd0) begin adj_hour0 <= 4'd9; adj_hour1 <= adj_hour1 - 1; end if(adj_hour1 ==4'd0 && adj_hour0 == 4'd0) begin adj_hour1 <= 4'd2; adj_hour0 <= 4'd3; end end end default: begin adj_sec0 <= 4'dx; adj_sec1 <= 4'dx; adj_min0 <= 4'dx; adj_min1 <= 4'dx; adj_hour0 <= 4'dx; adj_hour1 <= 4'dx; end endcase end else if((model == 2'b11) && date_time_ch) begin case(adjust_shif) //调时 位置 2'b00: begin//日个位 if(key_up) begin adj_day0 <= adj_day0 + 1'b1; if(adj_day0 == 4'd9) begin adj_day0 <= 4'd0; adj_day1 <= adj_day1 + 1; end if(adj_day1 == 4'd3 && adj_day0 == 4'd1) begin //为了简化逻辑,调整天数,在0-31号之间 adj_day1 <= 4'd0; adj_day0 <= 4'd1; end end if(key_down) begin adj_day0 <= adj_day0 - 1'b1; if(adj_day0 == 4'd0) begin adj_day0 <= 4'd9; adj_day1 <= adj_day1 - 1; end if(adj_day1 == 4'd0 && adj_day0 == 4'd1) begin //1号再减一,31号 adj_day1 <= 4'd3; adj_day0 <= 4'd1; end end end 2'b01: begin //月个位 if(key_up) begin adj_month0 <= adj_month0 + 1'b1; if(adj_month0 == 4'd9) begin adj_month0 <= 4'd0; adj_month1 <= adj_month1 + 1; end if(adj_month1 == 4'd1 && adj_month0 == 4'd2) begin //十二月加一,到十二月 adj_month1 <= 4'd0; adj_month0 <= 4'd1; end end if(key_down) begin adj_month0 <= adj_month0 - 1'b1; if(adj_month0 == 4'd0) begin adj_month0 <= 4'd9; adj_month1 <= adj_month1 - 1; end if(adj_month1 == 4'd0 && adj_month0 == 4'd1) begin //一月再减一,到十二月 adj_month1 <= 4'd1; adj_month0 <= 4'd2; end end end 2'b10: begin //年个位 if(key_up) begin adj_year0 <= adj_year0 + 1'b1; if(adj_year0 == 4'd9) begin adj_year0 <= 4'd0; adj_year1 <= adj_year1 + 1; if(adj_year1 == 4'd9) begin adj_year1 <= 4'd0; end end end if(key_down) begin adj_year0 <= adj_year0 - 1'b1; if(adj_year0 == 4'd0) begin adj_year0 <= 4'd9; if(adj_year1 > 4'd0) adj_year1 <= adj_year1 - 1; end end end default: begin adj_day0 <= 4'hx; //方便仿真时能看到错误 adj_day1 <= 4'hx; adj_month0 <= 4'dx; adj_month1 <= 4'dx; adj_year0 <= 4'dx; adj_year1 <= 4'dx; end endcase end else begin {adj_hour1, adj_hour0, adj_min1, adj_min0, adj_sec1, adj_sec0} <= time_num; //将当前时间赋给调节变量 {adj_year1, adj_year0, adj_month1, adj_month0, adj_day1, adj_day0} <= data_num; //即:在当前时间的基础上调节 end end //------------------------------------------- 输出 --------------------------------------------------------------------------------- assign adjust_time_num = {adj_hour1, adj_hour0, adj_min1, adj_min0, adj_sec1, adj_sec0}; assign adjust_date_num = {adj_year1, adj_year0, adj_month1, adj_month0, adj_day1, adj_day0}; assign adjust_clock_num = {clock_hour1, clock_hour0, clock_min1, clock_min0}; endmodule module stop_watch( input clk, input rst_n, input [1:0] model, input pause, //秒表暂停/开始 0:暂停,1:开始 input clear, //秒表清除 output [23:0] stop_watch_num //输出显示 ); //-------------------------------------- 10ms上升沿 -------------------------------------------------------------------------- wire clk_10ms; reg clk_10ms_reg1, clk_10ms_reg2; wire pos_10ms; clk_div #(.CNT_MAX(20)) clk_div_10ms( //为了缩短仿真时间,参数设为1,即为一个时钟周期 .clk_in (clk), .rst_n (rst_n), .clk_out (clk_10ms) ); always@(posedge clk, negedge rst_n) begin if(!rst_n) begin clk_10ms_reg1 <= 1'b0; clk_10ms_reg2 <= 1'b0; end else begin clk_10ms_reg1 <= clk_10ms; clk_10ms_reg2 <= clk_10ms_reg1; end end assign pos_10ms = clk_10ms_reg1 & (~clk_10ms_reg2); //-------------------------------------- 10ms_计数 -------------------------------------------------------------------------------- reg [3:0] cnt_ms0; reg [3:0] cnt_ms1; reg [3:0] cnt_s0; reg [3:0] cnt_s1; reg [3:0] cnt_m0; reg [3:0] cnt_m1; always@(posedge clk, negedge rst_n) begin if(!rst_n) begin //异步复位 cnt_ms0 <= 4'd0; cnt_ms1 <= 4'd0; cnt_s0 <= 4'd0; cnt_s1 <= 4'd0; cnt_m0 <= 4'd0; cnt_m1 <= 4'd0; end else if(clear) begin //同步清零 cnt_ms0 <= 4'd0; cnt_ms1 <= 4'd0; cnt_s0 <= 4'd0; cnt_s1 <= 4'd0; cnt_m0 <= 4'd0; cnt_m1 <= 4'd0; end else if(pos_10ms) begin if(model == 2'b10) begin //秒表模式 if(pause) begin //开始 cnt_ms0 <= cnt_ms0 + 1'b1; if(cnt_ms0 == 4'd9) begin cnt_ms0 <= 4'd0; cnt_ms1 <= cnt_ms1 + 1'b1; if(cnt_ms1 == 4'd9) begin //99, 1s时间到 cnt_ms1 <= 4'd0; cnt_s0 <= cnt_s0 + 1'b1; if(cnt_s0 == 4'd9) begin cnt_s0 <= 4'd0; cnt_s1 <= cnt_s1 + 1'b1; if(cnt_s1 == 4'd5) begin //59s cnt_s1 <= 4'd0; cnt_m0 <= cnt_m0 + 1'b1; if(cnt_m0 == 4'd9) begin cnt_m0 <= 4'd0; cnt_m1 <= cnt_m1 + 1'b1; end end end end end end end end else begin cnt_ms0 <= cnt_ms0; cnt_ms1 <= cnt_ms1; cnt_s0 <= cnt_s0; cnt_s1 <= cnt_s1; cnt_m0 <= cnt_m0; cnt_m1 <= cnt_m1; end end //------------------------------------------------------ 输出 -------------------------------------------------------------------- assign stop_watch_num = {cnt_m1, cnt_m0, cnt_s1, cnt_s0, cnt_ms1, cnt_ms0}; endmodule module alarm_music( input clk, input rst_n, input [15:0] adjust_clock_num, //闹钟调整值,只有小时和分钟 input [23:0] time_num, output led ); //------------------------------------- 闹钟使能逻辑 --------------------------------------------------------------------------------------- reg flag_en; reg [7:0] state; always@(posedge clk, negedge rst_n) begin if(!rst_n) flag_en <= 1'b0; else if({adjust_clock_num, 8'd0} == time_num) //闹钟时间到 flag_en <= 1'b1; else if(state == 8'd63) flag_en <= 1'b0; else flag_en <= flag_en; end endmodule //----------------------------数码管显示------------------------------------------------------------- module led_seg7_display( input clk, input rst_n, input [1:0] model, input [23:0] time_num, // 时钟数据 input [23:0] data_num, // 日期数据 input [23:0] adjust_time_num, // 调整时钟数据 input [15:0] adjust_clock_num,// 调整闹钟数据 input [23:0] stop_watch_num, // 秒表 output [3:0] sel, // 数码管位选(选择当前要显示的数码管) output reg [6:0] seg // 数码管段选(当前要显示的内容) ); //--------------------------------------------- 显示数据选择 ------------------------------------------------------------------------------- reg [23:0] show_num; always@(posedge clk, negedge rst_n) begin if(!rst_n) show_num <= 24'h0; else begin if(model == 2'b00) //常规显示 //显示时间 show_num <= time_num; else if(model == 2'b01) //闹钟显示 show_num <= {adjust_clock_num, 8'b00000000}; //闹钟只有小时和分钟,这里默认秒位 else if(model == 2'b10) //秒表显示 show_num <= stop_watch_num; else //调整时间 //调整时间显示 show_num <= adjust_time_num; end end //--------------------------------------------- 数码管显示逻辑 ---------------------------------------------------------------------------------- wire clk_1ms; //数码管扫描1ms clk_div #(.CNT_MAX(1)) clk_div_1ms( //为了缩短仿真时间 .clk_in (clk), .rst_n (rst_n), .clk_out (clk_1ms) ); reg [3:0]sel_r; //位选缓存 reg [3:0]data_tmp; //数据缓存 always@(posedge clk_1ms or negedge rst_n) if(!rst_n) sel_r <= 3'b00_01; else if(sel_r == 6'b10_00) sel_r <= 6'b00_01; else sel_r <= sel_r << 1; always@(*) case(sel_r) 4'b00_01:data_tmp = show_num[3:0]; 4'b00_10:data_tmp = show_num[7:4]; 4'b01_00:data_tmp = show_num[11:8]; 4'b10_00:data_tmp = show_num[15:12]; default: data_tmp = 4'b0000; endcase always@(*) case(data_tmp) 4'h0:seg = 7'b1000000; 4'h1:seg = 7'b1111001; 4'h2:seg = 7'b0100100; 4'h3:seg = 7'b0110000; 4'h4:seg = 7'b0011001; 4'h5:seg = 7'b0010010; 4'h6:seg = 7'b0000010; 4'h7:seg = 7'b1111000; 4'h8:seg = 7'b0000000; 4'h9:seg = 7'b0010000; default: seg = 7'b1000000; endcase assign sel = sel_r; endmodule
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。