FPGA数字时钟1
本代码借鉴了一些,网上资源。
1.设计目的
(1)掌握数字电子钟的设计方法;
(2)掌握常用数字集成电路的功能和使用;
(3)巩固数字电路理论知识,掌握逻辑电路和真值表的画法;
2.数字钟的功能以及要求
(1) 该电子钟项目为信号电路,计时电路,校时电路以及显示电路部分;
(2) 使用数码管显示时,分,秒;
(3) 通过按键对时,分,秒进行设置调时;
(4) 要求走时精准;
图片: EP2C8Q208C8
// top文件
module top(
input sys_clk,
input rst_n,
input key,
input key1,input key2,
output reg [5:0]sel_seg,
output reg [7:0]seg_led
);localparam MAX_NUM = 14'd5000;
reg [7:0]sec;
reg [7:0]min;
reg [7:0]hour;
reg flag_sec;
reg flag_min;parameter CLK_DIV=4'd10;
reg clk;
reg [3:0]div_cnt;//分频计数
reg [23:0]sec_cnt;
wire [3:0]shuju0;//秒个位
wire [3:0]shuju1;//秒十位
wire [3:0]shuju2;//分个位
wire [3:0]shuju3;//分十位
wire [3:0]shuju4;//时个位
wire [3:0]shuju5;//时十位
assign shuju5=hour/4'd10;
assign shuju4=hour%4'd10;
assign shuju3=min/4'd10;
assign shuju2=min%4'd10;
assign shuju1=sec/4'd10;
assign shuju0=sec%4'd10;wire key_value;
wire key_flag;
wire key_value1;
wire key_flag1;
wire key_value2;
wire key_flag2;key_debounce u_key_debounce(
.sys_clk(clk),.sys_rst_n(rst_n),
.key(key),.key_flag(key_flag),.key_value(key_value));
key_debounce u_key_debounce1(
.sys_clk(clk),.sys_rst_n(rst_n),
.key(key1),.key_flag(key_flag1),.key_value(key_value1)); key_debounce u_key_debounce2(
.sys_clk(clk),.sys_rst_n(rst_n),
.key(key2),.key_flag(key_flag2),.key_value(key_value2)); always @(posedge sys_clk or negedge rst_n)beginif(!rst_n)begindiv_cnt<=1'b0;clk<=1'b0;endelse if(div_cnt==CLK_DIV/2-1)beginclk<=~clk;div_cnt<=4'd0;endelse begindiv_cnt<=div_cnt+1'b1;clk<=clk;end
end//秒计数模块
always @(posedge clk or negedge rst_n)beginif(!rst_n)beginsec_cnt<=1'b0;sec<=8'd0;flag_sec<=1'b0;endelse if(key_flag1&&(~key_value1))beginif(sec==8'd59)beginsec<=8'd0;flag_sec<=1'b1;endelse beginflag_sec<=1'b0;sec<=sec+1'b1;endendelse if(sec_cnt==24'd500_0000)beginif(sec==8'd59)beginsec_cnt<=24'd0;sec<=8'd0;flag_sec<=1'b1; endelse beginflag_sec<=1'b0;sec_cnt<=24'd0;sec<=sec+1'b1; endendelse beginflag_sec<=1'b0;sec<=sec;sec_cnt<=sec_cnt+1'b1;end
end//分计数模块
always @(posedge clk or negedge rst_n)beginif(!rst_n)beginmin<=8'd0;flag_min<=1'b0;endelse if(key_flag&&(~key_value)) beginif(min==8'd59)beginmin<=8'd0;flag_min<=1'b1;endelse beginflag_min<=1'b0;min<=min+1'b1;endendelse if(flag_sec)begin if(min==8'd59)beginflag_min<=1'b1;min<=8'd0;end else beginflag_min<=1'b0;min<=min+1'b1;endendelse begin flag_min<=1'b0;min<=min;end
end
//时计数模块
always @(posedge clk or negedge rst_n)beginif(!rst_n)beginhour<=8'd0;endelse if(key_flag2&&(~key_value2)) beginif(hour==8'd59)beginhour<=8'd0;endelse beginhour<=hour+1'b1;endendelse if(flag_min)begin if(hour==8'd23)beginhour<=8'd0;end else beginhour<=hour+1'b1;endendelse begin hour<=hour;end
endreg [3:0]display_num;
reg [2:0]cnt0;//位选计数
reg [13:0]cnt1;
//数码管位选
reg flag;
always @(posedge clk or negedge rst_n)beginif(!rst_n)begincnt1<=14'd0;flag<=1'b0;endelse if(cnt1==MAX_NUM-1)begincnt1<=14'd0;flag<=1'b1; endelse beginflag<=1'b0;cnt1<=cnt1+1'b1;end
endalways @(posedge clk or negedge rst_n)beginif(!rst_n)begincnt0<=3'd0;endelse if(flag)beginif(cnt0==3'd5)cnt0<=3'd0;else cnt0<=cnt0+1'b1;endelse cnt0<=cnt0;
endalways @(posedge clk or negedge rst_n)beginif(!rst_n)beginsel_seg<=6'b111111;display_num<=4'd0;endelse begincase(cnt0)3'd0:beginsel_seg<=6'b111110;display_num<=shuju0;end3'd1:beginsel_seg<=6'b111101;display_num<=shuju1;end3'd2:beginsel_seg<=6'b111011;display_num<=shuju2;end3'd3:beginsel_seg<=6'b110111;display_num<=shuju3; end 3'd4:beginsel_seg<=6'b101111;display_num<=shuju4;end3'd5:beginsel_seg<=6'b011111;display_num<=shuju5;enddefault:beginsel_seg<=6'b111111;display_num<=4'd0;endendcaseend
end
//数码管显示
always@(posedge clk or negedge rst_n)beginif(!rst_n)seg_led<=8'd1111111;else begincase(display_num)4'd0:beginif(cnt0==3'd2||cnt0==3'd4)seg_led<=8'b01000000;else seg_led<=8'b11000000;end4'd1:begin if(cnt0==3'd2||cnt0==3'd4) seg_led<=8'b01111001;else seg_led<=8'b11111001;end4'd2:beginif(cnt0==3'd2||cnt0==3'd4)seg_led<=8'b00100100;else seg_led<=8'b10100100;end4'd3:beginif(cnt0==3'd2||cnt0==3'd4)seg_led<=8'b00110000;else seg_led<=8'b10110000;end 4'd4:beginif(cnt0==3'd2||cnt0==3'd4)seg_led<=8'b00011001;else seg_led<=8'b10011001;end4'd5:beginif(cnt0==3'd2||cnt0==3'd4)seg_led<=8'b00010010; elseseg_led<=8'b10010010; end4'd6:beginif(cnt0==3'd2||cnt0==3'd4)seg_led<=8'b00000010;else seg_led<=8'b10000010;end4'd7:beginif(cnt0==3'd2||cnt0==3'd4)seg_led<=8'b01111000;else seg_led<=8'b11111000;end4'd8:beginif(cnt0==3'd2||cnt0==3'd4)seg_led<=8'b00000000;else seg_led<=8'b10000000;end4'd9:beginif(cnt0==3'd2||cnt0==3'd4)seg_led<=8'b00010000;else seg_led<=8'b10010000;enddefault:seg_led<=8'b1111111;endcaseend
endendmodule// 子文件
module key_debounce(input sys_clk,input sys_rst_n,input key,output reg key_value,output reg key_flag
);reg [31:0] delay_cnt;
reg key_reg;always @(posedge sys_clk or negedge sys_rst_n)beginif(!sys_rst_n)beginkey_reg <= 1'b1;delay_cnt <= 32'd0;endelse beginkey_reg <= key;if(key_reg != key)delay_cnt <= 32'd100_0000; else if(key_reg == key)beginif(delay_cnt > 32'd0)delay_cnt <= delay_cnt - 1'b1;elsedelay_cnt <= delay_cnt;endend
endalways @(posedge sys_clk or negedge sys_rst_n)beginif(!sys_rst_n)beginkey_flag <= 1'b0;key_value <= 1'b1;endelse begin if(delay_cnt == 32'd1)beginkey_flag <= 1'b1;key_value <= key;endelse beginkey_flag <= 1'b0;key_value <= key_value;endend
endendmodule