使用小脚丫FPGA开发板设计简易数字时钟 (具备调时、整点报时、闹钟功能,额外实现了倒计时加整点提示功能,附带基本和创新部分的verilog代码)

(以下内容是我们3人小组完成大作业时共同合力完成的,每个人耗费心血很多,发篇文章纪念一下)

开发板要完成基本工作:

  1. 能正常完成时钟的时、分、秒走时,并及时进位;
  2. 使用1Hz 闪烁频率的LED闪烁或者1Hz颜色切换频率改变颜色等方式实现秒的指示;
  3. 使用两位七段数码管显示时、分和秒,其切换方式为:默认显示“分钟”,按住K4键显示“小时”,按住K3键显示“秒”;
  4. 使用K1和K2键调整时间,分别为“+”和“-”,当K4按下,则K1和K2调整“小时”,当K4放开,则K1和K2调整“分钟”,当K3按下,则K1和K2调整“秒”;
  5. 整点报时:当时间到达每个整点,则全彩LED以某种固定颜色按1Hz频率闪烁相应次数(按24小时制);

下面是我们的设计创新部分(代码附后)

  • 整点报时:时钟走到哪一小时,则全彩LED闪烁相应次数。
  • 完成闹钟功能:将sw3开关设置为1,开始设置固定时钟和分钟,当时间计时到达时,八个led灯闪烁一分钟;
  • 完成倒计时功能:sw4开关设置为1,进入倒计时设置环节,sw2关闭调整时间,K1 K2 K3 K4 与时钟功能一样;sw4关闭进入时钟功能;sw1倒计时与时钟清零互不干扰。同时带有预警效果(倒计时最后一分钟红灯闪烁)。     

        管脚分配图如下:

基本功能的完整代码展示:

        下面附上代代相传的代码,代码主体是分频部分和时钟计时的代码,很多代码都是重复的,结合AI比较容易能读懂。(创新功能的代码在后面)


// 小脚丫FPGA开发板设计简易数字时钟
 
module time_clock (CLK,reset,seg_led_1,seg_led_2,led,key,sw2,sw3,RGB1,RGB2);         //定义时钟信号,复位信号,两个数字显示器,按键,开关,三色灯
 
    input CLK,reset;
    input [3:0]key;            
    input sw2,sw3;
    output reg [8:0] seg_led_1;
    output reg [8:0] seg_led_2;    
 
    output reg [7:0] led;           //8个led灯,用于闹钟闪烁   
    output reg [2:0] RGB1=3'b 111;              //初始化所有通道都被设置为高电平,最亮
    output reg [2:0] RGB2=3'b 111;
    
        
        reg   [3:0] num1 ;                              //num i 是走时的位,count i 是计数,limiti 是闹钟位
        reg   [3:0] count1;
        reg   [3:0] limit1;
        reg   [3:0] num2 ;
        reg   [3:0] count2;
        reg   [3:0] limit2;
        reg   [3:0] num3 ;                              
        reg   [3:0] count3;
        reg   [3:0] limit3;
        reg   [3:0] num4 ;
        reg   [3:0] count4;
        reg   [3:0] limit4;
        reg   [3:0] num5 ;                               
        reg   [3:0] count5;
        reg   [3:0] limit5;
        reg   [3:0] num6 ;
        reg   [3:0] count6;
        reg   [3:0] limit6;
        reg   [30:0]cnt_1s;
        reg   [30:0]cnt_05s;
        reg [15 : 0] count;
        reg [15 : 0] count0;
        reg [8:0] seg [9:0];                        // reg [8:0] seg [9:0];放在一起:  一个包含10个元素的数组,每个元素都是一个9位宽的寄存器,用于显示数字0到9
                                             
 
        wire CLK_1s;                                     //定义1s分频得到的时钟秒针计数器的触发        
        
        
        //1s间隔脉冲模块,产生一个1s的秒针时钟信号
        parameter T1 = 12000000;         //小脚丫自带的时钟信号12MHz,1/T1=1Hz,生成一个秒的指示
    always@(posedge CLK) begin           //检测到时钟上升,触发always块内部的语句
    if(!reset) 
        cnt_1s <= 0;                             //如果复位信号reset为低电平(即复位被激活),则计数器cnt_1s将被重置为0 。确保系统能够在需要时从头开始计时的常见做法
    else if(cnt_1s == T1-1)              //如果马上要到切换的时刻
        cnt_1s<=0;                               //置零
    else                                                    //如果不是就进1s
        cnt_1s<= cnt_1s + 1;
    end
    //间隔脉冲模块,产生一个调整间隔时钟信号             //用于产生另一个分频来用于调整时钟时的指示,可以使得调整更加顺滑
    parameter T2 = 1500000;
    always@(posedge CLK) begin
    if(!reset) 
        cnt_05s <= 0;
    else if(cnt_05s == T2-1)
        cnt_05s<= 0;
    else
        cnt_05s<= cnt_05s + 1;
    end
 
       
     
    divide #(.WIDTH(32),.N(12000000)) u2 (         //传递参数                         // 会输出1Hz分频用于秒针走时指示
            .CLK(CLK),
            .reset_n(reset),                   //例化的端口信号都连接到定义好的信号
            .clkout(CLK_1s)
            );   
 
     
     
       always @(posedge CLK or negedge reset)                 //时钟信号的上升沿或者复位信号的下降沿触发
begin
            
            if (!reset)                                                               //复位信号为低电平的时候,全部清零,异步清零
                 begin
                    num1 <= 0;
                    num2<=0;
                    num3 <= 0;
                    num4<=0;
                    num5 <= 0;
                    num6<=0;
                 end

            //计时部分

        else
        begin
            if(sw2==1)                                       //sw2是调整时间的开关,当sw2=1,开启:开始计时   sw2=0,关闭:调整时间   
            begin						     //sw3为闹钟设置开关 ,sw3=1,开启:设置闹钟模式  sw3=0,关闭:退出设置闹钟模式
                            if(cnt_1s==T1-1 )
                                begin							//num1,2:秒针的第二位和第一位;num3,4:分针的第二位和第一位;num5,6:时针的第二位和第一位
                                     if((num2==5)&&(num1==9))             //秒针走到59时,如果马上切换则置零
                                        begin
                                            num1<=0;
                                            num2<=0;
                                            if((num4==5)&&(num3==9))         //分针走到59时,如果马上切换则置零
                                                begin
                                                    num3<=0;
                                                    num4<=0;
                                                    if((num6==2)&&(num5==3))    //时针走到24时,如果马上切换则置零
                                                        begin
                                                        num5<=0;
                                                        num6<=0;
                                                        end
                                                    else if(num5==9)                       //时针第二位走到9就进位,比如9->10       
                                                        begin
                                                        num5<=0;
                                                        num6<=num6+1;
                                                        end
                                                     else						//否则时针第二位正常进位,比如10->11
                                                        begin
                                                        num5<=num5+1;
                                                        end
                                                end
                                            else if(num3==9)					//分针第二位走到9就进位,比如49->50
                                                begin
                                                num3<=0;
                                                num4<=num4+1;
                                                end
                                             else							//否则分针第二位正常进位,比如50->51
                                                begin
                                                num3<=num3+1;
                                                end
                                        end
                                    else if(num1==9)						//秒针第二位走到9就进位,比如49->50
                                        begin
                                        num1<=0;
                                        num2<=num2+1;
                                        end
                                     else								//否则分针第二位正常进位,比如50->51
                                        begin
                                        num1<=num1+1;
                                        end
                                end
                           
            end

            //调整时间部分模块,切换为T2-1,即更加顺滑的切换

            if(sw2==0 && sw3==0)                            //关闭sw2和sw3,进入调时部分
            begin
                if(key[2]==1 && key[3]==1)		//调整分针(K3和K4默认弹起)
                    begin
                        if(key[0]==0)    //K1按下,加1s
                            begin                                                      //后面都是进位
                                if(cnt_05s==T2-1)
                                begin
                                    if((num4==5)&&(num3==9))
                                            begin
                                            num3<=0;
                                            num4<=0;
                                            end
                                    else if(num3==9 )
                                            begin
                                            num3<=0;
                                            num4<=num4+1;
                                            end
                                    else
                                            begin
                                            num3<=num3+1;
                                            end
                                end
                                
                                
                            end
                        else if(key[1]==0)                                  //K2按下,减1s
                         
                            begin                                                        //后面都是进位
                                if(cnt_05s==T2-1)
                                begin
                                    if(num3==0 && num4==0)
                                        begin
                                        num3<=9;
                                        num4<=5;
                                        end
                                    else if(num3==0)
                                        begin
                                        num3<=9;
                                        num4<=num4-1;
                                        end
                                    else
                                        num3<=num3-1;
                                end
                            
                    end
                    else        //不按就是不变
                        begin
                        num3<=num3;
                        num4<=num4;
                        end
                    end
            
                else if(key[2]==1 && key[3]==0)			//调整时针(K3弹起,K4按下)
                    begin
                        if(  key[0]==0 )                              //K1按下加1s
                            begin
                                if(cnt_05s==T2-1)
                                begin
                                    if((num6==2)&&(num5==3))
                                            begin
                                            num5<=0;
                                            num6<=0;
                                            end
                                    else if(num5==9)
                                            begin
                                            num5<=0;
                                            num6<=num6+1;
                                            end
                                    else
                                            begin
                                            num5<=num5+1;
                                            end
                                end
                            end
                        else if(key[1]==0)                          //K2按下减1s
                         
                            begin
                                if(cnt_05s==T2-1)
                                begin
                                    if(num5==0 && num6==0)
                                        begin
                                        num5<=3;
                                        num6<=2;
                                        end
                                    else if(num5==0)
                                        begin
                                        num5<=9;
                                        num6<=num6-1;
                                        end
                                    else
                                        num5<=num5-1;
                                end
                                
                            end
                        else
                            begin
                            num5<=num5;
                            num6<=num6;
                            end
                    end

                else if(key[2]==0 && key[3]==1)			//调整秒针(K3按下,K4弹起)
                    begin
                        if(  key[0]==0 )                           //K1按下加1s
                            begin
                                if(cnt_05s==T2-1)
                                begin
                                    if((num2==5)&&(num1==9))
                                            begin
                                            num1<=0;
                                            num2<=0;
                                            end
                                    else if(num1==9)
                                            begin
                                            num1<=0;
                                            num2<=num2+1;
                                            end
                                    else
                                            begin
                                            num1<=num1+1;
                                            end
                                end
                            end
                        else if(key[1]==0)                        //K2按下减1s
                         
                            begin
                                if(cnt_05s==T2-1)
                                begin
                                    if(num1==0 && num2==0)
                                        begin
                                        num1<=9;
                                        num2<=5;
                                        end
                                    else if(num1==0)
                                        begin
                                        num1<=9;
                                        num2<=num2-1;
                                        end
                                    else
                                        num1<=num1-1;
                                end
                                
                            end
                        else
                            begin
                            num1<=num1;
                            num2<=num2;
                            end
                    end
 
                
 
            end
            //闹钟设置模块,默认为分针的闹钟,即不设置秒钟 
         
            if(sw3==1 )         //sw3打开,开始闹钟设置
            begin
                if(key[2]==1 && key[3]==1)				//调整分针,后面部分和上面调时一样,只不过cnt换成了limit
                    begin
                        if(  key[0]==0 )
                            begin
                                if(cnt_05s==T2-1)
                                begin
                                    if((limit4==5)&&(limit3==9))
                                            begin
                                            limit3<=0;
                                            limit4<=0;
                                            end
                                    else if(limit3==9 )
                                            begin
                                            limit3<=0;
                                            limit4<=limit4+1;
                                            end
                                    else
                                            begin
                                            limit3<=limit3+1;
                                            end
                                end
                                
                                
                            end
                        else if(key[1]==0)
                         
                            begin
                                if(cnt_05s==T2-1)
                                begin
                                    if(limit3==0 && limit4==0)
                                        begin
                                        limit3<=9;
                                        limit4<=5;
                                        end
                                    else if(limit3==0)
                                        begin
                                        limit3<=9;
                                        limit4<=limit4-1;
                                        end
                                    else
                                        limit3<=limit3-1;
                                end
                            
                    end
                    else
                        begin
                        limit3<=limit3;
                        limit4<=limit4;
                        end
                    end
            
                else if(key[2]==1 && key[3]==0)				//调整时针
                    begin
                        if(  key[0]==0 )
                            begin
                                if(cnt_05s==T2-1)
                                begin
                                    if((limit6==2)&&(limit5==3))
                                            begin
                                            limit5<=0;
                                            limit6<=0;
                                            end
                                    else if(limit5==9)
                                            begin
                                            limit5<=0;
                                            limit6<=limit6+1;
                                            end
                                    else
                                            begin
                                            limit5<=limit5+1;
                                            end
                                end
                            end
                        else if(key[1]==0)
                         
                            begin
                                if(cnt_05s==T2-1)
                                begin
                                    if(limit5==0 && limit6==0)
                                        begin
                                        limit5<=3;
                                        limit6<=2;
                                        end
                                    else if(limit5==0)
                                        begin
                                        limit5<=9;
                                        limit6<=limit6-1;
                                        end
                                    else
                                        limit5<=limit5-1;
                                end
                                
                            end
                        else
                            begin
                            limit5<=limit5;
                            limit6<=limit6;
                            end
            
                    end
            
            
            end
 
        end         
end

 //数码管显示部分模块
    initial                                                      //定义一个初始过程块,它只会在仿真开始时执行一次,且只执行一次。
        begin
          seg[0] = 9'h3f;                                           //7段显示数字  0
          seg[1] = 9'h06;                                           //7段显示数字  1
          seg[2] = 9'h5b;                                           //7段显示数字  2
          seg[3] = 9'h4f;                                           //7段显示数字  3
          seg[4] = 9'h66;                                           //7段显示数字  4
          seg[5] = 9'h6d;                                           //7段显示数字  5
          seg[6] = 9'h7d;                                           //7段显示数字  6
          seg[7] = 9'h07;                                           //7段显示数字  7
          seg[8] = 9'h7f;                                           //7段显示数字  8
          seg[9] = 9'h6f;                                           //7段显示数字  9
     end

always @(posedge CLK)				//这个部分是显示部分
begin 
    if(sw3==0)            //sw3关闭
    begin                                                            //普通计时
        if(key[2]==1 && key[3]==0)                //K3弹起,K4按下,显示小时
            begin
            count5<=num5;
            count6<=num6;
            seg_led_1<=seg[count6];
            seg_led_2<=seg[count5]; 
    
            end
        else if(key[2]==0 && key[3]==1)       //K3按下,K4弹起,显示秒
        begin
            count1<=num1;
            count2<=num2;
            seg_led_1<=seg[count2];
            seg_led_2<=seg[count1]; 
        end
        else                                                            //默认显示分钟
        begin
            count4<=num4;
            count3<=num3;
            seg_led_1<=seg[count4];
            seg_led_2<=seg[count3]; 
        end
    end

    else			//sw3开启,显示闹钟的数字管
    begin
        if(key[2]==1 && key[3]==0)
            begin
            count5<=limit5;
            count6<=limit6;
            seg_led_1<=seg[count6];
            seg_led_2<=seg[count5]; 
    
            end
        else if(key[2]==0 && key[3]==1)
        begin
            count1<=limit1;
            count2<=limit2;
            seg_led_1<=seg[count2];
            seg_led_2<=seg[count1]; 
        end
        else
        begin
            count4<=limit4;
            count3<=limit3;
            seg_led_1<=seg[count4];
            seg_led_2<=seg[count3]; 
        end
    end
    
end
 
//整点报时:三色灯闪烁1min红色信号不停翻转,实现三色灯秒钟闪烁
always @(posedge CLK_1s)
begin
    RGB2[0]<=~RGB2[0];			//平时一个三色灯随着秒针走动在闪烁
    if(num3==0 && num4==0)				//整点的时候,即分针为00时,另一个三色灯开始翻转闪烁1min直到变为01
        begin
            RGB1[0]<=~RGB1[0];
        end
    else
        begin
            RGB1[0]<=1;
            
        end
        
 
end

//闹钟闪烁:1min,原理与三色灯类似
always @(posedge CLK_1s)
begin
    if(limit3 == num3 && limit4 == num4 && limit5 == num5 &&  limit6 == num6)		//时针和分针走到预定闹钟位置时触发
    begin
            
            led<=~led;				//8个led灯开始不停翻转闪烁1min直到分针变化
    end  
    else
    begin
            led<=8'b 11111111;		//其余时间常亮
    end
end
endmodule

// Module Function:任意整数时钟分频
 
module divide (	CLK,reset_n,clkout);
 
        input 	CLK,reset_n;                       //输入信号,其中clk连接到FPGA的C1脚,频率为12MHz
        output	clkout;                          //输出信号,可以连接到LED观察分频的时钟
 
        //parameter是verilog里常数语句
	parameter	WIDTH	= 24;             //计数器的位数,计数的最大值为 2**WIDTH-1
	parameter	N	= 12_000_000;             //分频系数,请确保 N < 2**WIDTH-1,否则计数会溢出
 
	reg 	[WIDTH-1:0]	cnt_p,cnt_n;     //cnt_p为上升沿触发时的计数器,cnt_n为下降沿触发时的计数器
	reg			CLK_p,CLK_n;     //CLK_p为上升沿触发时分频时钟,CLK_n为下降沿触发时分频时钟
 
	//上升沿触发时计数器的控制
	always @ (posedge CLK or negedge reset_n )         //posedge和negedge是verilog表示信号上升沿和下降沿
                                                         //当clk上升沿来临或者reset_n变低的时候执行一次always里的语句
		begin
			if(!reset_n)
				cnt_p<=0;
			else if (cnt_p==(N-1))
				cnt_p<=0;
			else cnt_p<=cnt_p+1;             //计数器一直计数,当计数到N-1的时候清零,这是一个模N的计数器
		end
 
         //上升沿触发的分频时钟输出,如果N为奇数得到的时钟占空比不是50%;如果N为偶数得到的时钟占空比为50%
         always @ (posedge CLK or negedge reset_n)
		begin
			if(!reset_n)
				CLK_p<=0;
			else if (cnt_p<(N>>1))          //N>>1表示右移一位,相当于除以2去掉余数
				CLK_p<=0;
			else 
				CLK_p<=1;               //得到的分频时钟正周期比负周期多一个clk时钟
		end
 
        //下降沿触发时计数器的控制        	
	always @ (negedge CLK or negedge reset_n)
		begin
			if(!reset_n)
				cnt_n<=0;
			else if (cnt_n==(N-1))
				cnt_n<=0;
			else cnt_n<=cnt_n+1;
		end
 
        //下降沿触发的分频时钟输出,和clk_p相差半个时钟
	always @ (negedge CLK)
		begin
			if(!reset_n)
				CLK_n<=0;
			else if (cnt_n<(N>>1))  
				CLK_n<=0;
			else 
				CLK_n<=1;                //得到的分频时钟正周期比负周期多一个clk时钟
		end
 
        assign clkout = (N==1)?CLK:(N[0])?(CLK_p&CLK_n):CLK_p;      //条件判断表达式
                                                                    //当N=1时,直接输出clk
                                                                    //当N为偶数也就是N的最低位为0,N(0)=0,输出clk_p
                                                                    //当N为奇数也就是N最低位为1,N(0)=1,输出clk_p&CLK_n。正周期多所以是相与
endmodule 

完成设计创新部分的完整代码展示:

        完整代码和解释如下:

  • // Module Function:时钟设计
    
    module time_clock (
        input CLK,          //CLK: 输入信号,连接到FPGA的时钟引脚,提供时钟信号。
        input reset,          //reset: 输入信号,连接到FPGA的复位引脚,用于异步复位。
        input [3:0] key,    //key: 输入信号,连接到按键,用于调整时间、设置闹钟等操作。
        input sw2, sw3, sw4,  
        output reg [8:0] seg_led_1, //seg_led_1, seg_led_2: 输出信号,分别连接到数码管的第1个和第2个七段显示。
        output reg [8:0] seg_led_2, 
        output reg [7:0] led,       //led: 输出信号,连接到LED灯,用于指示整点时间。
        output reg [2:0] RGB1 = 3'b111, //RGB1, RGB2: 输出信号,分别连接到两个三色LED灯,用于指示整点时间和闹钟时间
        output reg [2:0] RGB2 = 3'b111
    );
    
        //num1、num2、num3、num4、num5、num6:这些计数器分别用于实现秒、分钟、小时的时间计时,其中 num1 和 num2 组合用于实现秒,num3 和 num4 组合用于实现分钟,num5 和 num6 组合用于实现小时。
        //cnt1、cnt2、cnt3、cnt4、cnt5、cnt6:这些计数器与 num1~num6 对应,用于在调整时间模式下暂存 num1~num6 的值。
        //limit1、limit2、limit3、limit4、limit5、limit6:这些计数器用于设置闹钟时间。
        //cnt_1s 和 cnt_05s:这两个计数器用于产生1秒和0.5秒的时钟脉冲,用于计时和调整时间。
        //seg:这是一个数组,用于存储数字0-9对应的七段码,用于数码管显示。
            
        reg [3:0] num1;                               //定义了一个4位的计数器
        reg [3:0] cnt1;
        reg [3:0] limit1;
        reg [3:0] num2;
        reg [3:0] cnt2;
        reg [3:0] limit2;
        reg [3:0] num3;                               //定义了一个4位的计数器
        reg [3:0] cnt3;
        reg [3:0] limit3;
        reg [3:0] num4;
        reg [3:0] cnt4;
        reg [3:0] limit4;
        reg [3:0] num5;                               //定义了一个4位的计数器
        reg [3:0] cnt5;
        reg [3:0] limit5;
        reg [3:0] num6;
        reg [3:0] cnt6;
        reg [3:0] limit6;
        reg [30:0] cnt_1s;
        reg [30:0] cnt_05s;
        reg [15:0] cnt;
        reg [15:0] cnt0;
        reg [8:0] seg [9:0]; 
        //倒计时需要的变量
        reg [3:0] djs_num1; 
        reg [3:0] djs_num2; 
        reg [3:0] djs_num3; 
        reg [3:0] djs_num4; 
        reg [3:0] djs_num5; 
        reg [3:0] djs_num6; 
            
        wire CLK_1s; //定义一个中间变量,表示分频得到的时钟,用作计数器的触发        
            
        //间隔脉冲模块,产生一个   秒针    时钟信号
        parameter T1 = 12000000;
        always @(posedge CLK or negedge reset) begin
            if (!reset) 
                cnt_1s <= 0;
            else if (cnt_1s == T1 - 1)
                cnt_1s <= 0;
            else
                cnt_1s <= cnt_1s + 1;
        end
    
        //间隔脉冲模块,产生一个调整  间隔     信号时钟信号
        parameter T2 = 1500000;
        always @(posedge CLK or negedge reset) begin
            if (!reset) 
                cnt_05s <= 0;
            else if (cnt_05s == T2 - 1)
                cnt_05s <= 0;
            else
                cnt_05s <= cnt_05s + 1;
        end
    
        divide #(.WIDTH(32), .N(12000000)) u2 ( //传递参数
            .CLK(CLK),
            .reset_n(reset), //例化的端口信号都连接到定义好的信号
            .CLKout(CLK_1s)
        );
    
        always @(posedge CLK or negedge reset) begin
            if (!reset) begin // 在时钟状态下的异步清零
                num1 <= 0;
                num2 <= 0;
                num3 <= 0;
                num4 <= 0;
                num5 <= 0;
                num6 <= 0;
            end else if (sw4 == 0) begin
                if (sw2 == 1) begin // sw2调整时间的开关   1:开始计时   0:调整时间    sw3为闹钟设置开关 设置闹钟模式sw3:1  退出设置闹钟模式sw3:0 
                    if (cnt_1s == T1 - 1) begin
                        //秒
                        if ((num2 == 5) && (num1 == 9)) begin
                            num1 <= 0;
                            num2 <= 0;
                            //分钟
                            if ((num4 == 5) && (num3 == 9)) begin
                                num3 <= 0;
                                num4 <= 0;
                                //小时
                                if ((num6 == 2) && (num5 == 3)) begin
                                    num5 <= 0;
                                    num6 <= 0;
                                end else if (num5 == 9) begin
                                    num5 <= 0;
                                    num6 <= num6 + 1;
                                end else begin
                                    num5 <= num5 + 1;
                                end
                            end else if (num3 == 9) begin
                                num3 <= 0;
                                num4 <= num4 + 1;
                            end else begin
                                num3 <= num3 + 1;
                            end
                        end else if (num1 == 9) begin
                            num1 <= 0;
                            num2 <= num2 + 1;
                        end else begin
                            num1 <= num1 + 1;
                        end
                    end
                end
    
                if (sw2 == 0 && sw3 == 0) begin // 既要保证非倒计时状态和非闹钟设置状态
                    if (key[2] == 1 && key[3] == 1) begin // 调整分针
                        if (key[0] == 0) begin // K1按下加号
                            if (cnt_05s == T2 - 1) begin
                                if ((num4 == 5) && (num3 == 9)) begin
                                    num3 <= 0;
                                    num4 <= 0;
                                end else if (num3 == 9) begin
                                    num3 <= 0;
                                    num4 <= num4 + 1;
                                end else begin
                                    num3 <= num3 + 1;
                                end
                            end
                        end else if (key[1] == 0) begin
                            if (cnt_05s == T2 - 1) begin
                                if (num3 == 0 && num4 == 0) begin
                                    num3 <= 9;
                                    num4 <= 5;
                                end else if (num3 == 0) begin
                                    num3 <= 9;
                                    num4 <= num4 - 1;
                                end else begin
                                    num3 <= num3 - 1;
                                end
                            end
                        end else begin
                            num3 <= num3;
                            num4 <= num4;
                        end
                    end else if (key[2] == 1 && key[3] == 0) begin // 调整时针
                        if (key[0] == 0) begin
                            if (cnt_05s == T2 - 1) begin
                                if ((num6 == 2) && (num5 == 3)) begin
                                    num5 <= 0;
                                    num6 <= 0;
                                end else if (num5 == 9) begin
                                    num5 <= 0;
                                    num6 <= num6 + 1;
                                end else begin
                                    num5 <= num5 + 1;
                                end
                            end
                        end else if (key[1] == 0) begin
                            if (cnt_05s == T2 - 1) begin
                                if (num5 == 0 && num6 == 0) begin
                                    num5 <= 3;
                                    num6 <= 2;
                                end else if (num5 == 0) begin
                                    num5 <= 9;
                                    num6 <= num6 - 1;
                                end else begin
                                    num5 <= num5 - 1;
                                end
                            end
                        end else begin
                            num5 <= num5;
                            num6 <= num6;
                        end
                    end else if (key[2] == 0 && key[3] == 1) begin // 调整秒针
                        if (key[0] == 0) begin
                            if (cnt_05s == T2 - 1) begin
                                if ((num2 == 5) && (num1 == 9)) begin
                                    num1 <= 0;
                                    num2 <= 0;
                                end else if (num1 == 9) begin
                                    num1 <= 0;
                                    num2 <= num2 + 1;
                                end else begin
                                    num1 <= num1 + 1;
                                end
                            end
                        end else if (key[1] == 0) begin
                            if (cnt_05s == T2 - 1) begin
                                if (num1 == 0 && num2 == 0) begin
                                    num1 <= 9;
                                    num2 <= 5;
                                end else if (num1 == 0) begin
                                    num1 <= 9;
                                    num2 <= num2 - 1;
                                end else begin
                                    num1 <= num1 - 1;
                                end
                            end
                        end else begin
                            num1 <= num1;
                            num2 <= num2;
                        end
                    end
                end
    
                if (sw3 == 1) begin // 设置闹钟
                    if (key[2] == 1 && key[3] == 1) begin // 调整分针
                        if (key[0] == 0) begin
                            if (cnt_05s == T2 - 1) begin
                                if ((limit4 == 5) && (limit3 == 9)) begin
                                    limit3 <= 0;
                                    limit4 <= 0;
                                end else if (limit3 == 9) begin
                                    limit3 <= 0;
                                    limit4 <= limit4 + 1;
                                end else begin
                                    limit3 <= limit3 + 1;
                                end
                            end  
                        end else if (key[1] == 0) begin
                            if (cnt_05s == T2 - 1) begin
                                if (limit3 == 0 && limit4 == 0) begin
                                    limit3 <= 9;
                                    limit4 <= 5;
                                end else if (limit3 == 0) begin
                                    limit3 <= 9;
                                    limit4 <= limit4 - 1;
                                end else begin
                                    limit3 <= limit3 - 1;
                                end
                            end
                        end else begin
                            limit3 <= limit3;
                            limit4 <= limit4;
                        end
                    end else if (key[2] == 1 && key[3] == 0) begin // 调整时针
                        if (key[0] == 0) begin
                            if (cnt_05s == T2 - 1) begin
                                if ((limit6 == 2) && (limit5 == 3)) begin
                                    limit5 <= 0;
                                    limit6 <= 0;
                                end else if (limit5 == 9) begin
                                    limit5 <= 0;
                                    limit6 <= limit6 + 1;
                                end else begin
                                    limit5 <= limit5 + 1;
                                end
                            end
                        end else if (key[1] == 0) begin
                            if (cnt_05s == T2 - 1) begin
                                if (limit5 == 0 && limit6 == 0) begin
                                    limit5 <= 3;
                                    limit6 <= 2;
                                end else if (limit5 == 0) begin
                                    limit5 <= 9;
                                    limit6 <= limit6 - 1;
                                end else begin
                                    limit5 <= limit5 - 1;
                                end
                            end
                        end else begin
                            limit5 <= limit5;
                            limit6 <= limit6;
                        end
                    end
                end
            end else begin
                // 在倒计时状态下的异步清零
                if (!reset) begin
                    djs_num1 <= 0;
                    djs_num2 <= 0;
                    djs_num3 <= 0;
                    djs_num4 <= 0;
                    djs_num5 <= 0;
                    djs_num6 <= 0;
                end else begin // 开始计时
                    if (sw2 == 0) begin // 关闭sw2开始调整时间
                        if (key[2] == 1 && key[3] == 1) begin // 调整分针
                            if (key[0] == 0) begin
                                if (cnt_05s == T2 - 1) begin
                                    if ((djs_num4 == 5) && (djs_num3 == 9)) begin
                                        djs_num3 <= 0;
                                        djs_num4 <= 0;
                                    end else if (djs_num3 == 9) begin
                                        djs_num3 <= 0;
                                        djs_num4 <= djs_num4 + 1;
                                    end else begin
                                        djs_num3 <= djs_num3 + 1;
                                    end
                                end
                            end else if (key[1] == 0) begin
                                if (cnt_05s == T2 - 1) begin
                                    if (djs_num3 == 0 && djs_num4 == 0) begin
                                        djs_num3 <= 9;
                                        djs_num4 <= 5;
                                    end else if (djs_num3 == 0) begin
                                        djs_num3 <= 9;
                                        djs_num4 <= djs_num4 - 1;
                                    end else begin
                                        djs_num3 <= djs_num3 - 1;
                                    end
                                end
                            end else begin
                                djs_num3 <= djs_num3;
                                djs_num4 <= djs_num4;
                            end
                        end else if (key[2] == 1 && key[3] == 0) begin // 调整时针
                            if (key[0] == 0) begin
                                if (cnt_05s == T2 - 1) begin
                                    if ((djs_num6 == 2) && (djs_num5 == 3)) begin
                                        djs_num5 <= 0;
                                        djs_num6 <= 0;
                                    end else if (djs_num5 == 9) begin
                                        djs_num5 <= 0;
                                        djs_num6 <= djs_num6 + 1;
                                    end else begin
                                        djs_num5 <= djs_num5 + 1;
                                    end
                                end
                            end else if (key[1] == 0) begin
                                if (cnt_05s == T2 - 1) begin
                                    if (djs_num5 == 0 && djs_num6 == 0) begin
                                        djs_num5 <= 3;
                                        djs_num6 <= 2;
                                    end else if (djs_num5 == 0) begin
                                        djs_num5 <= 9;
                                        djs_num6 <= djs_num6 - 1;
                                    end else begin
                                        djs_num5 <= djs_num5 - 1;
                                    end
                                end
                            end else begin
                                djs_num5 <= djs_num5;
                                djs_num6 <= djs_num6;
                            end
                        end else if (key[2] == 0 && key[3] == 1) begin // 调整秒针
                            if (key[0] == 0) begin
                                if (cnt_05s == T2 - 1) begin
                                    if ((djs_num2 == 5) && (djs_num1 == 9)) begin
                                        djs_num1 <= 0;
                                        djs_num2 <= 0;
                                    end else if (djs_num1 == 9) begin
                                        djs_num1 <= 0;
                                        djs_num2 <= djs_num2 + 1;
                                    end else begin
                                        djs_num1 <= djs_num1 + 1;
                                    end
                                end
                            end else if (key[1] == 0) begin
                                if (cnt_05s == T2 - 1) begin
                                    if (djs_num1 == 0 && djs_num2 == 0) begin
                                        djs_num1 <= 9;
                                        djs_num2 <= 5;
                                    end else if (djs_num1 == 0) begin
                                        djs_num1 <= 9;
                                        djs_num2 <= djs_num2 - 1;
                                    end else begin
                                        djs_num1 <= djs_num1 - 1;
                                    end
                                end
                            end else begin
                                djs_num1 <= djs_num1;
                                djs_num2 <= djs_num2;
                            end
                        end
                    end
    
                    if (sw2 == 1) begin // 开始倒计时
                        if (cnt_1s == T1 - 1) begin
                            if ((djs_num2 == 0) && (djs_num1 == 0) && (djs_num4 == 0) && (djs_num3 == 0) && (djs_num6 == 0) && (djs_num5 == 0)) begin
                                // 确保不进入else里面,到达000000后停止
                                djs_num1 <= 0;
                                djs_num2 <= 0;
                                djs_num3 <= 0;
                                djs_num4 <= 0;
                                djs_num5 <= 0;
                                djs_num6 <= 0;
                            end else if ((djs_num2 == 0) && (djs_num1 == 0)) begin
                                djs_num1 <= 9;
                                djs_num2 <= 5;
                                // 分钟
                                if ((djs_num4 == 0) && (djs_num3 == 0)) begin
                                    djs_num3 <= 9;
                                    djs_num4 <= 5;
                                    // 小时
                                    if ((djs_num6 == 0) && (djs_num5 == 0)) begin
                                        djs_num5 <= 9;
                                        djs_num6 <= 5;
                                    end else if (djs_num5 == 0) begin
                                        djs_num5 <= 9;
                                        djs_num6 <= djs_num6 - 1;
                                    end else begin
                                        djs_num5 <= djs_num5 - 1;
                                    end
                                end else if (djs_num3 == 0) begin
                                    djs_num3 <= 9;
                                    djs_num4 <= djs_num4 - 1;
                                end else begin
                                    djs_num3 <= djs_num3 - 1;
                                end
                            end else if (djs_num1 == 0) begin
                                djs_num1 <= 9;
                                djs_num2 <= djs_num2 - 1;
                            end else begin
                                djs_num1 <= djs_num1 - 1;
                            end
                        end
                    end
                end
            end
        end
    
        //数码管显示
        initial begin // initial和always不同,其中语句只执行一次
            //对存储器中第一个数赋值9'b00_0011_1111,相当于共阴极接地,DP点变低不亮,7段显示数字  0//
            seg[0] = 9'h3f; 
            seg[1] = 9'h06; //7段显示数字  1
            seg[2] = 9'h5b; //7段显示数字  2
            seg[3] = 9'h4f; //7段显示数字  3
            seg[4] = 9'h66; //7段显示数字  4
            seg[5] = 9'h6d; //7段显示数字  5
            seg[6] = 9'h7d; //7段显示数字  6
            seg[7] = 9'h07; //7段显示数字  7
            seg[8] = 9'h7f; //7段显示数字  8
            seg[9] = 9'h6f; //7段显示数字  9
        end
    
        always @(posedge CLK) begin 
            if (sw4 == 0) begin
                if (sw3 == 0) begin // 没有设置闹钟 不是倒计时
                    if (key[2] == 1 && key[3] == 0) begin
                        cnt5 <= num5;
                        cnt6 <= num6;
                        seg_led_1 <= seg[cnt6];
                        seg_led_2 <= seg[cnt5]; 
                    end else if (key[2] == 0 && key[3] == 1) begin
                        cnt1 <= num1;
                        cnt2 <= num2;
                        seg_led_1 <= seg[cnt2];
                        seg_led_2 <= seg[cnt1]; 
                    end else begin
                        cnt4 <= num4;
                        cnt3 <= num3;
                        seg_led_1 <= seg[cnt4];
                        seg_led_2 <= seg[cnt3]; 
                    end
                end else begin
                    if (key[2] == 1 && key[3] == 0) begin
                        cnt5 <= limit5;
                        cnt6 <= limit6;
                        seg_led_1 <= seg[cnt6];
                        seg_led_2 <= seg[cnt5]; 
                    end else if (key[2] == 0 && key[3] == 1) begin
                        cnt1 <= limit1;
                        cnt2 <= limit2;
                        seg_led_1 <= seg[cnt2];
                        seg_led_2 <= seg[cnt1]; 
                    end else begin
                        cnt4 <= limit4;
                        cnt3 <= limit3;
                        seg_led_1 <= seg[cnt4];
                        seg_led_2 <= seg[cnt3]; 
                    end
                end
            end else begin // 是倒计时
                if (key[2] == 1 && key[3] == 0) begin
                    cnt5 <= djs_num5;
                    cnt6 <= djs_num6;
                    seg_led_1 <= seg[cnt6];
                    seg_led_2 <= seg[cnt5]; 
                end else if (key[2] == 0 && key[3] == 1) begin
                    cnt1 <= djs_num1;
                    cnt2 <= djs_num2;
                    seg_led_1 <= seg[cnt2];
                    seg_led_2 <= seg[cnt1]; 
                end else begin
                    cnt4 <= djs_num4;
                    cnt3 <= djs_num3;
                    seg_led_1 <= seg[cnt4];
                    seg_led_2 <= seg[cnt3]; 
                end
            end
        end
    
        //整点报时:三色灯闪烁1min红色信号不停翻转,实现三色灯秒钟闪烁
    always @(posedge CLK_1s)
    begin
        RGB1[2]<=~RGB1[2];			//平时一个三色灯随着秒针走动在闪烁
        if(num3==0 && num4==0)				//整点的时候,即分针为00时,另一个三色灯开始翻转闪烁1min直到变为01
            begin
                if(num1==0 && num2==0) 
                begin
                RGB2[2]<=0;
                RGB2[0]<=0;
                RGB2[1]<=1;
                end
                if(num2<num6&&~(num1==0 && num2==0))
                begin
                RGB2[1]<=~RGB2[1];
                end
                if(num1<num5 &&num2==num6)
                begin
                RGB2[1]<=~RGB2[1];
                end
                else
                begin
                RGB2[1]<=1;
                RGB2[0]<=1;
                RGB2[2]<=1;
                end
            end
        else
            begin
                RGB2[1]<=1;
                RGB2[0]<=1;
                RGB2[2]<=1;
            end
    end
        //-------------------------------------------闹钟闪烁
        always @(posedge CLK_1s) begin
            if (sw4 == 0) begin
                if (limit3 == num3 && limit4 == num4 && limit5 == num5 && limit6 == num6) begin
                    led <= ~led;
                end else begin
                    led <= 8'b11111111;
                end
            end else begin
                // 倒计时还有一分钟结束时结束led闪烁
                if ((djs_num3 == 0 && djs_num4 == 0 && djs_num5 == 0 && djs_num6 == 0) && (djs_num1 > 0 && djs_num2 > 0)) begin
                    led <= ~led;
                end else begin
                    led <= 8'b11111111;
                end
            end
        end
    
    endmodule
    
    // Module Function:任意整数时钟分频
    
    module divide (
        input CLK,      //输入信号,其中CLK连接到FPGA的C1脚,频率为12MHz
        input reset_n,    //输入信号,复位信号,低电平有效
        output CLKout   //输出信号,可以连接到LED观察分频的时钟
    );
    
        //parameter是verilog里常数语句
        parameter WIDTH = 24;   //计数器的位数,计数的最大值为 2**WIDTH-1
        parameter N = 12000000; //分频系数,请确保 N < 2**WIDTH-1,否则计数会溢出
    
        reg [WIDTH-1:0] num_p, num_n; //num_p为上升沿触发时的计数器,num_n为下降沿触发时的计数器
        reg CLK_p, CLK_n;             //CLK_p为上升沿触发时分频时钟,CLK_n为下降沿触发时分频时钟
    
        //上升沿触发时计数器的控制
        always @(posedge CLK or negedge reset_n) begin
            if (!reset_n)
                num_p <= 0;
            else if (num_p == (N - 1))
                num_p <= 0;
            else
                num_p <= num_p + 1; //计数器一直计数,当计数到N-1的时候清零,这是一个模N的计数器
        end
    
        //上升沿触发的分频时钟输出,如果N为奇数得到的时钟占空比不是50%;如果N为偶数得到的时钟占空比为50%
        always @(posedge CLK or negedge reset_n) begin
            if (!reset_n)
                CLK_p <= 0;
            else if (num_p < (N >> 1)) //N>>1表示右移一位,相当于除以2去掉余数
                CLK_p <= 0;
            else
                CLK_p <= 1; //得到的分频时钟正周期比负周期多一个CLK时钟
        end
    
        //下降沿触发时计数器的控制
        always @(negedge CLK or negedge reset_n) begin
            if (!reset_n)
                num_n <= 0;
            else if (num_n == (N - 1))
                num_n <= 0;
            else
                num_n <= num_n + 1;
        end
    
        //下降沿触发的分频时钟输出,和CLK_p相差半个时钟
        always @(negedge CLK) begin
            if (!reset_n)
                CLK_n <= 0;
            else if (num_n < (N >> 1))
                CLK_n <= 0;
            else
                CLK_n <= 1; //得到的分频时钟正周期比负周期多一个CLK时钟
        end
    
        assign CLKout = (N == 1) ? CLK : (N[0]) ? (CLK_p & CLK_n) : CLK_p; //条件判断表达式
        //当N=1时,直接输出CLK
        //当N为偶数也就是N的最低位为0,N(0)=0,输出CLK_p
        //当N为奇数也就是N最低位为1,N(0)=1,输出CLK_p&CLK_n。正周期多所以是相与
    
    endmodule
    
    

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值