欢迎各位朋友关注“郝旭帅电子设计团队”,本篇为各位朋友介绍基于FPGA的数字钟设计---第三版。
功能说明:
1. 在数码管上面显示时分秒(共计六个数码管,前两个显示小时;中间两个显示分钟;最后两个显示秒)。
2. 利用按键可以切换24/12小时制(默认24小时制)。
3. led1的亮灭表示24小时制(亮)还是12小时制(灭)。
4. led2的亮灭表示上午(亮)还是下午(灭),24小时制时,一直灭。
5. 增加调整按键和加减按键。
6. 调整按键不按下时,正常显示时分秒。
按下第一次,进入调整状态,时间停止,并且小时开始闪烁,通过加减按键可以进行调整。
按下第二次,分钟开始闪烁,通过加减按键可以进行调整。
按下第三次,秒开始闪烁,通过加减按键可以进行调整。
按下第四次,进入正常运行状态。
后续再按下时,重复以上的过程
使用平台:本次设计应用Altera的平台设计(芯片:EP4CE10F17C8N)。
仿真平台:Modelsim。
作者QQ:746833924
说明:本篇设计中不涉及到IP和原语,代码在其他平台依然可以适用;当其他板卡电路不同时,会导致不同的现象出现,如有需要修改代码请联系作者;如需作者使用的板卡,请联系作者;
设计思想如下:
key_ctrl模块负责将外部的按键信号进行消抖,并且产生对应边沿变化时的脉冲;digital_clock_ctrl模块负责根据脉冲信号和设计逻辑产生对应数字逻辑和led的状态;seven_tube_drive(七段数码管驱动)模块负责将digital_clock_ctrl模块产生的数字逻辑显示到数码管上。
key_ctrl模块设计思想为:按键信号是由外部机械式按键产生,每次按下或者抬起时,会产生一定的抖动。如果直接对其进行边沿检测就会导致多次触发。故而需要设计按键消抖,进而对消抖之后的波形进行边沿检测。消抖原理为:外部按键信号发生改变后,如果能够持续20ms,没有新的改变,就认为此次改变不是抖动,而是真正的按下,然后进行采样即可。
// 记录任意边沿之后没有遇到新的边沿的时间长度是否达到20Ms //--------------------------------------------------------------------------------------- always@(posedgeclk)begin if(rst_n ==1'b0) cnt_20ms <=20'd0; else if(pulse_key_negedge ==1'b1||pulse_key_posedge ==1'b1) cnt_20ms <=20'd1; else if(cnt_20ms >20'd0&&cnt_20ms <T_20ms) cnt_20ms <=cnt_20ms +1'b1; else cnt_20ms <=20'd0; end // --------------------------------------------------------------------------------------- // 任意边沿之后没有遇到新的边沿的时间长度达到20Ms,认为按键稳定,此时采样 //-------------------------------------------------------------------------------------- always@(posedgeclk)begin if(rst_n ==1'b0) key_wave <=1'b1; else if(cnt_20ms ==T_20ms) key_wave <=key_rr; else key_wave <=key_wave; end //-------------------------------------------------------------------------------------- // 对消抖之后的按键信号进行边沿检测 //--------------------------------------------------------------------------------------------- initialkey_wave_r =1'b1; always@(posedgeclk)key_wave_r <=key_wave; assignflag_neg =(key_wave_r ==1'b1&&key_wave ==1'b0)?1'b1:1'b0; assignflag_pos =(key_wave_r ==1'b0&&key_wave ==1'b1)?1'b1:1'b0; //--------------------------------------------------------------------------------------------
digital_clock_ctrl模块的设计思想:首先根据外部的调整脉冲,确定工作状态。
reg[1:0] state_adjust;// 0 : 正常模式 1:小时调整 2 :分钟调整 3 :秒调整 // 切换调整模式和正常模式 always@(posedgeclk)begin if(rst_n ==1'b0) state_adjust <=2'b00; else if(key_adjust_flag ==1'b1) state_adjust <=state_adjust +1'b1; // 0-3无限循环 else state_adjust <=state_adjust; end
根据基本逻辑、工作状态和外部加减脉冲产生24小时进制的时分秒。
// 1秒钟计时 // 只有正常模式才开始计时 always@(posedgeclk)begin if(rst_n ==1'b0) cnt <=26'd0; else if(cnt <T_1s -1'b1 &&state_adjust ==2'd0) cnt <=cnt +1'b1; else cnt <=26'd0; end // 秒计时 // 在秒调整模式中,加和减按键做对应的工作。 // 在正常模式,正常计时 always@(posedgeclk)begin if(rst_n ==1'b0) sec <=6'd50; else if(state_adjust ==2'd3) if(key_add_flag ==1'b1) if(sec <6'd59) sec <=sec +1'b1; else sec <=6'd0; else if(key_sub_flag ==1'b1) if(sec >6'd0) sec <=sec -1'b1; else sec <=6'd59; else sec <=sec; else if(cnt ==T_1s -1'b1) if(sec <6'd59) sec <=sec +1'b1; else sec <=6'd0; else sec <=sec; end
24小时进制和12小时进制在外部按键按下时切换;分和秒的显示没有改变,小时的显示需要调整。24小时制时,正常显示;12小时制时,时大于11时,需要减去12;并且利用led2进行表是为上午还是下午。
//根据显示模式,调整小时的显示 always@*begin if(state ==1'b0) hour_adjust =hour; else if(hour >6'd11) hour_adjust =hour -6'd12; else hour_adjust =hour; end //根据显示模式和小时值,计算是上午还是下午 always@*begin if(state ==1'b0) led2 =1'b0; else if(hour >6'd11) led2 =1'b0; else led2 =1'b1; end
如果在调整模式中,启动一个一秒钟的计时器。
// 处于调整模式时,开始计时一秒钟 always@(posedgeclk)begin if(rst_n ==1'b0) flash_cnt <=26'd0; else if(state_adjust ==2'd0) flash_cnt <=26'd0; else if(flash_cnt <T_1s -1'b1) flash_cnt <=flash_cnt +1'b1; else flash_cnt <=26'd0; end
分钟和小时类似,在这里不在赘述。
在正常模式下将需要显示的时、分、秒的十位和个位计算出来。在对应的调整模式下,需要前半秒输出对应的数字,后半秒输出全F。在数码管驱动中,当输入正常数字0~9显示数字,当输入F时数码管熄灭,此时数码管就闪烁起来了。
//计算得出小时、分钟、秒的个位和十位 always@(posedgeclk)hour_shi <=(state_adjust ==2'd1&&flash_cnt >T_1s/2)?4'hf:hour_adjust/10; always@(posedgeclk)hour_ge <=(state_adjust ==2'd1&&flash_cnt >T_1s/2)?4'hf:hour_adjust%10; always@(posedgeclk)min_shi <=(state_adjust ==2'd2&&flash_cnt >T_1s/2)?4'hf:min/10; always@(posedgeclk)min_ge <=(state_adjust ==2'd2&&flash_cnt >T_1s/2)?4'hf:min%10; always@(posedgeclk)sec_shi <=(state_adjust ==2'd3&&flash_cnt >T_1s/2)?4'hf:sec/10; always@(posedgeclk)sec_ge <=(state_adjust ==2'd3&&flash_cnt >T_1s/2)?4'hf:sec%10;
所有的逻辑在复位时,可以给予各种值,下板时,通过按下复位,可以让数字钟从自己想要的时间开始运行。
以上即为digital_clock_ctrl模块的设计思想;
七段数码管为普通六位一体的共阳极数码,采用动态驱动的方式,在此不再赘述。
按下复位后,立刻按下切换显示模式。此时led1熄灭(12小时制),led2点亮(上午)。经过10秒后,可以看到0时0分0秒,led2熄灭(下午)。
链接:https://pan.baidu.com/s/1Bo6GK1bm1vDXfahwZusKVg
提取码:i9xj
本篇内容中有部分资源来源于网络,如有侵权,请联系作者。
如果您觉得本公众号还不错的话,可以推给身边的朋友们,感谢并祝好!