数字钟(按钮版)(含演示视频)

  1. 因为开关IO口太多,这是介于我第一次写的开关版本的改进按钮版,一共用了5个按钮,两个按钮用来调位置(即时分秒位),两个按钮用来调大小(即9~0)。一个按钮用来复位。
  2. 既然是按钮首先要使用消抖电路,基于自动机的理念,设置了消抖电路。
    1. module Eli_jlt(
          input clk,
          input sw,
          output reg et
          );
      parameter N=24;
      parameter[2:0]  s0=3'b000,
      				s1=3'b001,
      				s2=3'b010,
      				s3=3'b011,
      				s4=3'b100,
      				s5=3'b101,
      				s6=3'b110,	
      				s7=3'b111;				
      reg[2:0] state;//state_next;
      reg[2:0] state_next;
      reg [N-1:0] st_tick;
      wire tick;
      always @(posedge clk)
      if(st_tick<10**6)
      	st_tick<=st_tick+1;
      else
      	st_tick<=0;
      always @(posedge clk)
      	state<=state_next;
      assign tick=(st_tick==0)? 1'b1:0'b0;
      always @(*)
      case(state)
      s0:
          begin
          	et=0;
      		if(sw)
      		begin
      			state_next=s1;//当前状态为0检测状态为1,并等待它稳定20~30ms
      		end
      	end
      s1:
      	if(~sw)
      	state_next=s0;
      	else if(tick)
      	state_next=s2;
      s2:
          if(~sw)
      	state_next=s0;
      	else if(tick)
      	state_next=s3;
      s3:
          if(~sw)
      	state_next=s0;
      	else if(tick)
      	state_next=s4;
      s4:
          begin
      	et=1;
          if(~sw)
      	state_next=s5;//当前状态为1检测状态为0,并等待它稳定20~30ms
      	end
      s5:
      	if(sw)
      	state_next=s4;
      	else if(tick)
      	state_next=s6;
      s6:
      	if(sw)
      	state_next=s4;
      	else if(tick)
      	state_next=s7;
      default:
      	if(sw)
      	state_next=s4;
      	else if(tick)
      	state_next=s0;
      endcase
      endmodule

主要改进模块为output_reset。

module output_reset(
	input clk,
	input butt1,
	input butt2,
	input butt3,
	input butt4,
	input [3:0] second_l,
	input [3:0] second_h,
	input [3:0]minute_l,
	input [3:0]minute_h,
	input [3:0]hour_l,
	input [3:0]hour_h,
	output reg [3:0] second_l_r,
	output reg [3:0] second_h_r,
	output reg [3:0]minute_l_r,
	output reg [3:0]minute_h_r,
	output reg [3:0]hour_l_r,
	output reg [3:0]hour_h_r
    );
	wire et1,et2,et3,et4;
	wire le1,le2,le3,le4;
	reg [3:0] second_l1;
    reg [3:0] second_h1;
    reg [3:0]minute_l1;
    reg [3:0]minute_h1;
    reg [3:0]hour_l1;
    reg [3:0]hour_h1;
    reg [3:0] second_ll;
    reg [3:0] second_hh;
    reg [3:0]minute_ll;
    reg [3:0]minute_hh;
    reg [3:0]hour_ll;
    reg [3:0]hour_hh;
	reg [3:0] pos;//表示位置
	Eli_jlt one(.clk(clk),.sw(butt1),.et(et1));
	Eli_jlt two(.clk(clk),.sw(butt2),.et(et2));
	Eli_jlt three(.clk(clk),.sw(butt3),.et(et3));
	Eli_jlt four(.clk(clk),.sw(butt4),.et(et4));//消除抖动
	trans tone(.clk(clk),.le(le1),.et(et1));
	trans ttwo(.clk(clk),.le(le2),.et(et2));
	trans tthree(.clk(clk),.le(le3),.et(et3));
	trans tfour(.clk(clk),.le(le4),.et(et4));
	always @(posedge clk)
	if(le3)
		begin
			if(pos==5)
				pos=5;
			else
				pos=pos+1;
		end
	else if(le4)
	    begin
			if(pos==0)
				pos=0;
			else
				pos=pos-1;
		end
	always @(posedge clk)
        begin
        second_h1<=second_h;
        second_hh<=second_h1;
        second_l1<=second_l;
        second_ll<=second_l1;
        minute_h1<=minute_h;
        minute_hh<=minute_h1;
        minute_l1<=minute_l;
        minute_ll<=minute_l1;
        hour_h1<=hour_h;
        hour_hh<=hour_h1;
        hour_l1<=hour_l;
        hour_ll<=hour_l1;
        end
	always @(posedge clk)
            case(pos)
            5:
            if(le1)
			    if(hour_l1<4)
					if(hour_hh<2)
						hour_h_r<=hour_hh+1;
					else
						hour_h_r<=2;
				else
					if(hour_hh<1)
						hour_h_r<=hour_hh+1;
					else
						hour_h_r<=1;
            else if(le2)
                if(hour_hh>0)
                    hour_h_r<=hour_hh-1;
                else
                    hour_h_r<=0;
            4:
            if(le1)
                begin
                    if(hour_hh==2)
                        if(hour_ll<3)
                            hour_l_r<=hour_ll+1;
                        else
                            hour_l_r<=3;
                    else
                        if(hour_ll<9)
                            hour_l_r<=hour_ll+1;
                        else
                            hour_l_r<=9;
                end
            else if(le2)
                if(hour_ll>0)
                    hour_l_r<=hour_ll-1;
                else
                    hour_l_r<=0;
            3:
            if(le1)
                if(minute_hh<5)
                    minute_h_r<=minute_hh+1;
                else
                    minute_h_r<=5;
            else if(le2)
                if(minute_hh>0)
                    minute_h_r<=minute_hh-1;
                else
                    minute_h_r<=0;
            2:
            if(le1)
                if(minute_ll<9)
                    minute_l_r<=minute_ll+1;
                else
                    minute_l_r<=9;
            else if(le2)
                if(minute_ll>0)
                    minute_l_r<=minute_ll-1;
                else
                    minute_l_r<=0;
            1:
            if(le1)
                if(second_hh<5)
                    second_h_r<=second_hh+1;
                else
                    second_h_r<=5;
            else if(le2)
                if(second_hh>0)
                    second_h_r<=second_hh-1;
                else
                    second_h_r<=0;
            default:
            if(le1)
                if(second_ll<9)
                    second_l_r<=second_ll+1;
                else
                    second_l_r<=9;
            else if(le2)
                if(second_ll>0)
                    second_l_r<=second_ll-1;
                else
                    second_l_r<=0;
            endcase
        endmodule

 

  

4.现在来解析output_reset,首先从trans说起,它的目的是把按钮信号的沿信号,转换成电平信号,为什么这么做呢,因为你希望两个按钮同时控制一个信号,比如数字的加减你是没办法同时检测两个posedge 沿信号的,但是你可以同时检测两个电平信号,

module trans(
    input clk,
    input et,
    output reg le
    );
reg sync_et;
always @(posedge clk)
  sync_et<=et;
always @(*)
if((et==1)&(sync_et==0))
	le=1;
else
	le=0;
endmodule

5.然后剩下的就是非法判断,我用一个always块干掉了这件事,注意pos是另外两个按钮控制的位置即时分秒位

always @(posedge clk)
            case(pos)
            5:
            if(le1)
			    if(hour_l1<4)
					if(hour_hh<2)
						hour_h_r<=hour_hh+1;
					else
						hour_h_r<=2;
				else
					if(hour_hh<1)
						hour_h_r<=hour_hh+1;
					else
						hour_h_r<=1;
            else if(le2)
                if(hour_hh>0)
                    hour_h_r<=hour_hh-1;
                else
                    hour_h_r<=0;
            4:
            if(le1)
                begin
                    if(hour_hh==2)
                        if(hour_ll<3)
                            hour_l_r<=hour_ll+1;
                        else
                            hour_l_r<=3;
                    else
                        if(hour_ll<9)
                            hour_l_r<=hour_ll+1;
                        else
                            hour_l_r<=9;
                end
            else if(le2)
                if(hour_ll>0)
                    hour_l_r<=hour_ll-1;
                else
                    hour_l_r<=0;
            3:
            if(le1)
                if(minute_hh<5)
                    minute_h_r<=minute_hh+1;
                else
                    minute_h_r<=5;
            else if(le2)
                if(minute_hh>0)
                    minute_h_r<=minute_hh-1;
                else
                    minute_h_r<=0;
            2:
            if(le1)
                if(minute_ll<9)
                    minute_l_r<=minute_ll+1;
                else
                    minute_l_r<=9;
            else if(le2)
                if(minute_ll>0)
                    minute_l_r<=minute_ll-1;
                else
                    minute_l_r<=0;
            1:
            if(le1)
                if(second_hh<5)
                    second_h_r<=second_hh+1;
                else
                    second_h_r<=5;
            else if(le2)
                if(second_hh>0)
                    second_h_r<=second_hh-1;
                else
                    second_h_r<=0;
            default:
            if(le1)
                if(second_ll<9)
                    second_l_r<=second_ll+1;
                else
                    second_l_r<=9;
            else if(le2)
                if(second_ll>0)
                    second_l_r<=second_ll-1;
                else
                    second_l_r<=0;
            endcase

5.总模块和未解决的问题

module top(
	input clk,
	input reset,
	input butt1,
	input butt2,
	input butt3,
	input butt4,
	output [6:0] seeg,
	output [7:0] sctl,
	output seeg_p
    );
	wire [6:0]decode_hh;
	wire [6:0]decode_hl;
	wire [6:0]decode_mh;
	wire [6:0]decode_ml;
	wire [6:0]decode_sh;
	wire [6:0]decode_sl;
	wire [3:0] second_l;
	wire [3:0] second_h;
	wire [3:0]minute_l;
	wire [3:0]minute_h;
	wire [3:0]hour_l;
	wire [3:0]hour_h;
	wire [3:0] second_l_r;
	wire [3:0] second_h_r;
	wire [3:0]minute_l_r;
	wire [3:0]minute_h_r;
	wire [3:0]hour_l_r;
	wire [3:0]hour_h_r;
    wire [3:0] second_ll;
	wire [3:0] second_hh;
	wire [3:0]minute_ll;
	wire [3:0]minute_hh;
	wire [3:0]hour_ll;
	wire [3:0]hour_hh;
output_reset output_reset(.clk(clk),.butt1(butt1),.butt2(butt2),.butt3(butt3),.butt4(butt4),.second_l_r(second_l_r),.second_h_r(second_h_r),.minute_l_r(minute_l_r),.minute_h_r(minute_h_r),.hour_l_r(hour_l_r),.hour_h_r(hour_h_r),.hour_h(hour_h),.hour_l(hour_l),.minute_h(minute_h),.minute_l(minute_l),.second_h(second_h),.second_l(second_l));
output_r_cal r_cal(.clk(clk),.second_l_r(second_l_r),.second_h_r(second_h_r),.minute_l_r(minute_l_r),.minute_h_r(minute_h_r),.hour_l_r(hour_l_r),.hour_h_r(hour_h_r),.second_ll(second_ll),.second_hh(second_hh),.minute_ll(minute_ll),.minute_hh(minute_hh),.hour_ll(hour_ll),.hour_hh(hour_hh));
cnt cnt(.reset(reset),.clk(clk),.second_ll(second_ll),.second_hh(second_hh),.minute_ll(minute_ll),.minute_hh(minute_hh),.hour_ll(hour_ll),.hour_hh(hour_hh),.hour_h(hour_h),.hour_l(hour_l),.minute_h(minute_h),.minute_l(minute_l),.second_h(second_h),.second_l(second_l));
 decode h_h(.v(hour_h),.seegs(decode_hh));
 decode h_l(.v(hour_l),.seegs(decode_hl));
 decode m_h(.v(minute_h),.seegs(decode_mh));
 decode m_l(.v(minute_l),.seegs(decode_ml));
 decode s_h(.v(second_h),.seegs(decode_sh));
 decode s_l(.v(second_l),.seegs(decode_sl));
seegctl(.decode_hh(decode_hh),.decode_hl(decode_hl),.decode_mh(decode_mh),.decode_ml(decode_ml),.decode_sh(decode_sh),.decode_sl(decode_sl),.clk(clk),.seeg(seeg),.sctl(sctl),.seeg_p(seeg_p));
endmodule

  

注意r_cal我原先的想法是对按钮进行纠正,但是output_reset做了这件事情之后,它纯粹变成了触发器,注意到outputreset的输入信号,是cnt的信号,我希望复位的时候是当前的时间值,但实际却综合出了原先调的时间值,研究了好久没解决,但相比于上次开关来说,体验好了很多,也希望有大神能帮我找出错误。个人设计,诸多不良之处,请多指教!

6.演示及补充,

出了output_reset及top,其它模块和开关版均一样,r_cal就改成触发器打一拍。

演示视频地址:https://www.bilibili.com/video/av53854057?pop_share=1

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值