【FPGA】状态机_闹钟

一、功能硬件说明

二、状态图

三、时序图

四、代码

五、图片展示

一、功能硬件说明

1、芯片:EP4CE6F17C8
2、复位按键:复位
3、按键 1:退出时间设置模式或闹钟设置模式
4、按键 2:进入时间设置模式,在时间设置模式和闹钟设置模式进 行位选操作
5、按键 3:进入闹钟设置模式,在时间设置模式和闹钟设置模式进 行时间设置操作 6、数码管:时间设置模式显示时间设置的值,闹钟设置模式显示闹 钟预设值,默认模式显示时间
7、LED 灯:时间等于闹钟预设值 LED 亮,否则不亮
8、BEEP:蜂鸣器,时间等于闹钟预设值蜂鸣器响,否则不响

二、状态图

状态图
在这里插入图片描述

三、时序图

我没画

四、代码

顶层代码

// A code block
var foo = 'bar';
// An highlighted block
/**************************************
---------------------------------------
Component name:top
Author        :lcyyds 
time          :2021/12/7 
Description   :时钟顶层模块
src           :
---------------------------------------
**************************************/
module top( 
    input				clk		,
    input				rst_n	,
    input 	 [2:0]	    key_in	,
    output              beep    ,
    output   [3:0]      led     ,
    output   [5:0]      seg_sel ,
    output   [7:0]      segment

);								 
    //参数定义			 
                        
    //中间信号定义		 

wire [2:0]      key_down;
wire [23:0]     din     ;

//时钟
 state_ta #(.TIME_CNT(50_000_000))u_state_ta
( 
    /*input				  */    .clk	 (clk     ),
    /*input				  */    .rst_n	 (rst_n   ),
    /*input		    [2:0] */    .key_down(key_down),
    /*output  reg         */    .beep    (beep    ),
    /*output	reg	[23:0]*/    .din	 (din     ),
                                .led     (led     )
);

//按键消抖
 key_filter #(.KEY_W(3),.TIME_20MS(1000000))u_key_filter
 (
    /*input 			         */ .clk    (clk     ),
    /*input 			         */ .rst_n	(rst_n   ),
    /*input 		[KEY_W - 1:0]*/	.key_in	(key_in  ),
    /*output 		[KEY_W - 1:0]*/	.key_out(key_down)	        
);

//数码管驱动
  seg u_seg
  (
   /*input             */ .clk    (clk      ),
   /*input             */ .rst_n  (rst_n    ),
   /*input       [23:0]*/ .din    (din      ),
   /*input       [5:0] */ .point  (6'b110101),
   /*output  reg [5:0] */ .seg_sel(seg_sel  ),
   /*output  reg [7:0] */ .segment(segment  )
);



endmodule

按键消抖
按键消抖也是用状态机写的

// A code block
var foo = 'bar';
// An highlighted block
/****************************************
-----------------------------------------
Component name:key_filter
Author        :lcyyds 
time          :2021/12/7 
Description   :Mealy型三段式状态机按键消抖
src           :
-----------------------------------------
****************************************/
module key_filter # (parameter KEY_W = 3,TIME_20MS = 1000000)(
    input 			            clk		,
    input 			            rst_n	,
    input 		[KEY_W - 1:0]	key_in	,
    output 		[KEY_W - 1:0]	key_out	         
);
    // 参数定义
    localparam IDLE  = 4'b0001;     //初始状态 
    localparam DOWN  = 4'b0010;     //按键按下抖动
    localparam HOLD  = 4'b0100;     //按键按下后稳定
    localparam UP    = 4'b1000;     //按键上升抖动
    // 信号定义
    reg     [3:0]           state_c         ;   //现态
    reg     [3:0]           state_n         ;   //次态

    // 状态转移条件定义
    wire                    idle2down       ;
    wire                    down2idle       ;
    wire                    down2hold       ;
    wire                    hold2up         ;
    wire                    up2idle         ;

    reg     [KEY_W - 1:0]   key_r0          ;   //同步
    reg     [KEY_W - 1:0]   key_r1          ;   //打拍
    wire    [KEY_W - 1:0]   nedge           ;   //下降沿
    wire    [KEY_W - 1:0]   pedge           ;   //上升沿

    // 20ms计数器
    reg     [19:0]          cnt_20ms        ;
    wire                    add_cnt_20ms    ;
    wire                    end_cnt_20ms    ;

    reg [KEY_W - 1:0] key_out_r;    // 输出寄存

    always@(posedge clk or negedge rst_n)begin
        if(!rst_n)begin
            state_c <= IDLE;
        end
        else begin
            state_c <= state_n;
        end
    end

//状态转换条件
    assign idle2down = (state_c == IDLE) && nedge;                      // 检测到下降沿
    assign down2idle = (state_c == DOWN) && (pedge && ~end_cnt_20ms);   // 计时未到20ms时且出现上升沿表示按键意外抖动,回到初始态
    assign down2hold = (state_c == DOWN) && (~pedge && end_cnt_20ms);   // 计时到20ms时没有出现上升沿标志按键按下后保持稳定
    assign hold2up   = (state_c == HOLD) && (pedge);                    // 检测到上升沿跳转到上升态
    assign up2idle   = (state_c == UP)   && end_cnt_20ms;               // 计数器计数到20ms跳转到初始态

//次状态
    always@(*)begin
        case(state_c)
            IDLE: begin
                if(idle2down)begin
                    state_n = DOWN;
                end
                else begin
                    state_n = state_c;
                end
            end
            DOWN: begin
                if(down2idle)begin
                    state_n = IDLE;
                end
                else if(down2hold)begin
                    state_n = HOLD;
                end
                else begin
                    state_n = state_c;
                end
            end
            HOLD: begin
                if(hold2up)begin
                    state_n = UP;
                end
                else begin
                    state_n = state_c;
                end
            end
            UP: begin
                if(up2idle)begin
                    state_n = IDLE;
                end
                else begin
                    state_n = state_c;
                end
            end
            default:state_n = state_c;
        endcase
    end


    // 20ms计数器
    always@(posedge clk or negedge rst_n)begin
        if(!rst_n)begin
            cnt_20ms <= 0;
        end
        else if(add_cnt_20ms)begin
            if(pedge || end_cnt_20ms)begin
                cnt_20ms <= 0;
            end
            else begin
                cnt_20ms <= cnt_20ms + 1'b1;
            end
        end
    end
    assign add_cnt_20ms = state_c == DOWN || state_c == UP;             // 当按键按下或上弹时开始计数
    assign end_cnt_20ms = add_cnt_20ms && (cnt_20ms == TIME_20MS - 1);  // 当计数到最大值或检测到上升沿计数器清零


    // 同步打拍
    always@(posedge clk or negedge rst_n)begin
        if(!rst_n)begin
            key_r0 <= {KEY_W{1'b1}};
            key_r1 <= {KEY_W{1'b1}};
        end
        else begin
            key_r0 <= key_in;
            key_r1 <= key_r0;
        end
    end

    assign nedge = ~key_r0 &  key_r1;   // 检测下降沿
    assign pedge =  key_r0 & ~key_r1;   // 检测上升沿


    // 按键赋值
    always@(posedge clk or negedge rst_n)begin
        if(!rst_n)begin
            key_out_r <= {KEY_W{1'b0}};
        end
        else if(hold2up) begin
            key_out_r <= ~key_r1;
        end
        else begin
            key_out_r <= {KEY_W{1'b0}};
        end
    end

    assign key_out = key_out_r;

endmodule

数码管驱动

// A code block
var foo = 'bar';
// An highlighted block

/*******************************************
-------------------------------------------
Component name:seg
Author        :lcyyds 
time          :2021/12/7 
Description   :seg数码管驱动
src           :
--------------------------------------------
********************************************/

module  seg (
    input               clk      ,
    input               rst_n    ,
    input       [23:0]  din      ,
    input       [5:0]   point    ,      //数码管小数点
    output  reg [5:0]   seg_sel  ,
    output  reg [7:0]   segment
);

parameter DELAY = 1_000_00;
//数码管显示0-F
localparam  ZER = 7'b100_0000,
            ONE = 7'b111_1001,
            TWO = 7'b010_0100,
            THR = 7'b011_0000,
            FOU = 7'b001_1001,
            FIV = 7'b001_0010,
            SIX = 7'b000_0010,
            SEV = 7'b111_1000,
            EIG = 7'b000_0000,
            NIN = 7'b001_0000,
            A   = 7'b000_1000, 
            B   = 7'b000_0011,
            C   = 7'b100_0110,
            D   = 7'b010_0001,
            E   = 7'b000_0110,
            F   = 7'b000_1110;

reg [3:0] num;
reg       seg_point;

reg [19:0] cnt;

wire add_cnt;
wire end_cnt;

//片选延时计数器
always @(posedge clk or negedge rst_n)begin 
   if(!rst_n)begin
        cnt <= 0;
    end 
    else if(add_cnt)begin 
            if(end_cnt)begin 
                cnt <= 0;
            end
            else begin 
                cnt <= cnt + 1;
            end 
    end
   else  begin
       cnt <= cnt;
    end
end 

assign add_cnt = 1'b1;
assign end_cnt = add_cnt && cnt == DELAY - 1;

//数码管片选
always @(posedge clk or negedge rst_n)begin 
    if(!rst_n)begin
        seg_sel <= 6'b111110;
    end 
    else if(end_cnt)begin
        seg_sel <= {seg_sel[4:0],seg_sel[5]};
        end
    else begin 
        seg_sel <= seg_sel;
    end 
end

//数码管片选
always @(posedge clk or negedge rst_n)begin 
    if(!rst_n)begin
        num <= 4'b0;
        seg_point <= 1'b1;
    end 
    else begin
        case (seg_sel)
            6'b111110 : begin num <= din[3:0];seg_point <= point [0];end
            6'b111101 : begin num <= din[7:4];seg_point <= point [1];end
            6'b111011 : begin num <= din[11:8];seg_point <= point [2];end
            6'b110111 : begin num <= din[15:12];seg_point <= point [3];end
            6'b101111 : begin num <= din[19:16];seg_point <= point [4];end
            6'b011111 : begin num <= din[23:20];seg_point <= point [5];end
        default: begin num <= 4'b0;seg_point <= 1'b1;end
        endcase 
        
    end 
end

//数码管段选
always @(posedge clk or negedge rst_n)begin 
    if(!rst_n)begin
        segment <= 8'b10100_0000;
    end 
    else begin 
        case (num)
            4'd0:  segment <= {seg_point,ZER};
            4'd1:  segment <= {seg_point,ONE}; 
            4'd2:  segment <= {seg_point,TWO}; 
            4'd3:  segment <= {seg_point,THR};     
            4'd4:  segment <= {seg_point,FOU};     
            4'd5:  segment <= {seg_point,FIV};     
            4'd6:  segment <= {seg_point,SIX};         
            4'd7:  segment <= {seg_point,SEV};     
            4'd8:  segment <= {seg_point,EIG};     
            4'd9:  segment <= {seg_point,NIN};
            4'd10: segment <= {seg_point,A};            
            4'd11: segment <= {seg_point,B};
            4'd12: segment <= {seg_point,C};
            4'd13: segment <= {seg_point,D};
            4'd14: segment <= {seg_point,E};
            4'd15: segment <= {seg_point,F};
            default: segment <= 8'b10100_0000;
        endcase
    end 
end

endmodule


时钟显示

// A code block
var foo = 'bar';
// An highlighted block

/**************************************************
---------------------------------------------------
Component name:state_ta
Author        :lcyyds 
time          :2021/12/7 
Description   :Mealy型三段式状态机时钟显示
               key_down[1]按下进入设置时间模式:
               key_down[1]时钟时间位选
               key_down[2]时钟时间设置
               key_down[0]返回初始模式.
               key_down[2]按下进入设置闹钟模式:
               key_down[1]时钟闹钟时间位选
               key_down[2]时钟闹钟时间设置
               key_down[0]返回初始模式.
               当时间到达闹钟值led灯亮,beep蜂鸣器响
src           :
----------------------------------------------------
***************************************************/

module state_ta #(parameter TIME_CNT = 50_000_000)
( 
    input				    clk		,
    input				    rst_n	,
    input		    [2:0]   key_down,
    output  reg             beep,
    output  reg     [3:0]   led,
    output	reg 	[23:0]	din	

);								 
    //参数定义			 
    parameter IDLE = 3'b001, 
              STET = 3'b010,
              STEA = 3'b100;

    //中间信号定义
    reg   [2:0]  state_c;    
    reg   [2:0]  state_d;
    //状态转换条件
    wire        IDLE_STET;
    wire        IDLE_STEA;
    wire        STET_IDLE;
    wire        STEA_IDLE;


    //1s计数器
    reg   [25:0]     cnt_1s;
    wire             add_cnt_1s;
    wire             end_cnt_1s;
    //s的个位
    reg   [3:0]      cnt_s_g;
    wire             add_s_g;
    wire             end_s_g;
    //s的十位
    reg   [3:0]      cnt_s_s;
    wire             add_s_s;
    wire             end_s_s;
    //m的个位
    reg   [3:0]      cnt_m_g;
    wire             add_m_g;
    wire             end_m_g;
    //m的十位
    reg   [3:0]      cnt_m_s;
    wire             add_m_s;
    wire             end_m_s;
    //h的个位
    reg   [3:0]      cnt_h_g;
    wire             add_h_g;
    wire             end_h_g;
    //h的十位
    reg   [3:0]      cnt_h_s;
    wire             add_h_s;
    wire             end_h_s;
    //时间手动设置
    reg     [3:0]        sele;      //位选
    reg     [3:0]        cnt_s0;    
    reg     [3:0]        cnt_s1;
    reg     [3:0]        cnt_m0;
    reg     [3:0]        cnt_m1;
    reg     [3:0]        cnt_h0;
    reg     [3:0]        cnt_h1;
    //闹钟时间设置
    reg     [3:0]        sele1;     //位选  
    reg     [3:0]        cnt_sa0;
    reg     [3:0]        cnt_sa1;
    reg     [3:0]        cnt_ma0;
    reg     [3:0]        cnt_ma1;
    reg     [3:0]        cnt_ha0;
    reg     [3:0]        cnt_ha1;

    reg     [7:0]           bug;

//当前状态
always @(posedge clk or negedge rst_n)begin 
    if(!rst_n)begin
        state_c <= IDLE;
    end 
    else begin 
        state_c <= state_d;
    end 
end

//次状态
always @(*)begin 
    case (state_c)
    IDLE : begin if (IDLE_STET) begin
        state_d = STET;
    end else if (IDLE_STEA) begin
        state_d = STEA;
    end else begin
        state_d = state_c;
    end
        
    end
    STET : begin if (STET_IDLE) begin
        state_d = IDLE;
    end else begin
        state_d = state_c;
    end  
    end
    STEA : begin if (STEA_IDLE) begin
        state_d = IDLE;
    end else begin
        state_d = state_c;
    end   
    end  
        default: begin
            state_d = state_c;
        end
    endcase
end


assign IDLE_STET = state_c ==IDLE && key_down[1];           //按键2从IDLE状态进入STET状态.    
assign IDLE_STEA = state_c ==IDLE && key_down[2];           //按键3从IDLE状态进入STEA状态.
assign STET_IDLE = state_c ==STET && key_down[0];           //按键1从STET状态进入IDLE状态.
assign STEA_IDLE = state_c ==STEA && key_down[0];           //按键1从STEA状态进入IDLE状态.

//1s计数器
always @(posedge clk or negedge rst_n)begin 
   if(!rst_n)begin
        cnt_1s <= 0;
    end 
    else if(add_cnt_1s)begin 
            if(end_cnt_1s||STET_IDLE)begin          //重新设置时间回到IDLE状态1s计数器清零
                cnt_1s <= 0;
            end
            else begin 
                cnt_1s <= cnt_1s + 1;
            end 
    end
   else  begin
       cnt_1s <= cnt_1s;
    end
end 

assign add_cnt_1s = (state_c == IDLE||(state_c == STEA));                        //当在IDLE和STEA时时间流逝
assign end_cnt_1s = add_cnt_1s && cnt_1s == TIME_CNT-1;

//秒的个位
always @(posedge clk or negedge rst_n)begin 
   if(!rst_n)begin
        cnt_s_g <= 4'b0;
    end
    else if (STET_IDLE) begin
        cnt_s_g <= cnt_s0;
    end 
    else if(add_s_g)begin 
            if(end_s_g)begin 
                cnt_s_g <= 0;
            end
            else begin 
                cnt_s_g <= cnt_s_g + 1;
            end 
    end
   else  begin
       cnt_s_g <= cnt_s_g;
    end
end 

assign add_s_g = end_cnt_1s;
assign end_s_g = add_s_g && cnt_s_g == 10-1;

//秒的十位
always @(posedge clk or negedge rst_n)begin 
   if(!rst_n)begin
        cnt_s_s <= 4'b0;
    end 
    else if (STET_IDLE) begin
        cnt_s_s <= cnt_s1;
    end 
    else if(add_s_s)begin 
            if(end_s_s)begin 
                cnt_s_s <= 0;
            end
            else begin 
                cnt_s_s <= cnt_s_s + 1;
            end 
    end
   else  begin
       cnt_s_s <= cnt_s_s;
    end
end 

assign add_s_s = end_s_g;
assign end_s_s = add_s_s && cnt_s_s == 6-1;


//分的个位
always @(posedge clk or negedge rst_n)begin 
   if(!rst_n)begin
        cnt_m_g <= 4'b0;
    end 
    else if (STET_IDLE) begin
            cnt_m_g <= cnt_m0;
    end 
    else if(add_m_g)begin 
            if(end_m_g)begin 
                cnt_m_g <= 0;
            end
            else begin 
                cnt_m_g <= cnt_m_g + 1;
            end 
    end
   else  begin
       cnt_m_g <= cnt_m_g;
    end
end 

assign add_m_g = end_s_s;
assign end_m_g = add_m_g && cnt_m_g == 10-1;

//分的十位
always @(posedge clk or negedge rst_n)begin 
   if(!rst_n)begin
        cnt_m_s <= 4'b0;
    end
    else if (STET_IDLE) begin
       cnt_m_s <= cnt_m1;
    end  
    else if(add_m_s)begin 
            if(end_m_s)begin 
                cnt_m_s <= 0;
            end
            else begin 
                cnt_m_s <= cnt_m_s + 1;
            end 
    end
   else  begin
       cnt_m_s <= cnt_m_s;
    end
end 

assign add_m_s = end_m_g;
assign end_m_s = add_m_s && cnt_m_s == 6-1;

//时的个位
always @(posedge clk or negedge rst_n)begin 
   if(!rst_n)begin
        cnt_h_g <= 4'b0;
    end
    else if (STET_IDLE) begin
        cnt_h_g <= cnt_h0;
    end   
    else if(add_h_g)begin 
            if(end_h_g)begin 
                cnt_h_g <= 0;
            end
            else begin 
                cnt_h_g <= cnt_h_g + 1;
            end 
    end
   else  begin
       cnt_h_g <= cnt_h_g;
    end
end 

assign add_h_g = end_m_s;
assign end_h_g = add_h_g && (cnt_h_g==(cnt_h_s == 4'd2)?4'd3:4'd9);

//时的十位
always @(posedge clk or negedge rst_n)begin 
   if(!rst_n)begin
        cnt_h_s <= 4'b0;
    end
    else if (STET_IDLE) begin
        cnt_h_s <= cnt_h1;
    end    
    else if(add_h_s)begin 
            if(end_h_s)begin 
                cnt_h_s <= 0;
            end
            else begin 
                cnt_h_s <= cnt_h_s + 1;
            end 
    end
   else  begin
       cnt_h_s <= cnt_h_s;
    end
end 

assign add_h_s = end_h_g;
assign end_h_s = add_h_s && cnt_h_s == 2;

//设置时间
/***********************
当进入STET状态
key_down[1]手动调时位选
key_down[2]调时
*************************/

//位选
always @(posedge clk or negedge rst_n)begin 
    if(!rst_n)begin
        sele <=4'b0;
    end 
    else if(state_c == STET )begin 
            if(key_down[1])begin
                if(sele ==4'd5)begin
                    sele <=4'b0;
                end 
                else begin
                    sele <=sele +1'b1;
                end
            end   
    end 
    else if (IDLE_STET) begin
        sele <=4'b0;
    end
    else begin 
        sele <= sele;
    end 
end

//秒的个位设置
always @(posedge clk or negedge rst_n)begin 
    if(!rst_n)begin
        cnt_s0 <= 0;
    end 
    else if(state_c == STET && sele ==4'b0000 && key_down[2])begin 
            if(cnt_s0==4'd9)begin
                cnt_s0 <= 0;
            end 
            else begin
                cnt_s0 <= cnt_s0+1'b1;
            end
    end 
    else begin 
            cnt_s0 <= cnt_s0;
    end 
end

//秒的十位设置
always @(posedge clk or negedge rst_n)begin 
    if(!rst_n)begin
        cnt_s1 <= 0;
    end 
    else if(state_c == STET && sele ==4'b0001 && key_down[2])begin 
            if(cnt_s1==4'd5)begin
                cnt_s1 <= 0;
            end 
            else begin
                cnt_s1 <= cnt_s1+1'b1;
            end
    end 
    else begin 
            cnt_s1 <= cnt_s1;
    end 
end

//分的个位设置
always @(posedge clk or negedge rst_n)begin 
    if(!rst_n)begin
        cnt_m0 <= 0;
    end 
    else if(state_c == STET && sele ==4'b0010 && key_down[2])begin 
            if(cnt_m0==4'd9)begin
                cnt_m0 <= 0;
            end 
            else begin
                cnt_m0 <= cnt_m0+1'b1;
            end
    end 
    else begin 
            cnt_m0 <= cnt_m0;
    end 
end

//分的十位设置
always @(posedge clk or negedge rst_n)begin 
    if(!rst_n)begin
        cnt_m1 <= 0;
    end 
    else if(state_c == STET && sele ==4'b0011 && key_down[2])begin 
            if(cnt_m1==4'd5)begin
                cnt_m1 <= 0;
            end 
            else begin
                cnt_m1 <= cnt_m1+1'b1;
            end
    end 
    else begin 
            cnt_m1 <= cnt_m1;
    end 
end
//时的个位设置
always @(posedge clk or negedge rst_n)begin 
    if(!rst_n)begin
        cnt_h0 <= 0;
    end 
    else if(state_c == STET && sele ==4'b0100 && key_down[2])begin 
            if(cnt_h0==4'd9)begin
                cnt_h0 <= 0;
            end
            else if (cnt_h0==4'd3&&cnt_h1==4'd2) begin          //当h的十位为2时个位最大值为3
                cnt_h0 <= 0;
            end 
            else begin
                cnt_h0 <= cnt_h0+1'b1;
            end
    end 
    else begin 
            cnt_h0 <= cnt_h0;
    end 
end

//时的十位设置
always @(posedge clk or negedge rst_n)begin 
    if(!rst_n)begin
        cnt_h1 <= 0;
    end 
    else if(state_c == STET && sele ==4'b0101 && key_down[2])begin 
            if(cnt_h1==4'd2)begin
                cnt_h1 <= 0;
            end 
            else begin
                cnt_h1 <= cnt_h1+1'b1;
            end
    end 
    else begin 
            cnt_h1 <= cnt_h1;
    end 
end

//设置闹钟时间
/***********************
当进入STEA状态
key_down[1]闹钟位选
key_down[2]闹钟调时
*************************/

//位选
always @(posedge clk or negedge rst_n)begin 
    if(!rst_n)begin
        sele1 <=4'b0000;
    end 
    else if(state_c == STEA )begin 
            if(key_down[1])begin
                if(sele1 ==4'd5)begin
                    sele1 <=4'b0000;
                end 
                else begin
                    sele1 <=sele1 +1'b1;
                end
            end   
    end 
    else if (IDLE_STEA) begin
        sele1 <=4'b0000;
    end
    else begin 
        sele1 <= sele1;
    end 
end

//秒的个位设置
always @(posedge clk or negedge rst_n)begin 
    if(!rst_n)begin
        cnt_sa0 <= 0;
    end 
    else if(state_c == STEA && sele1 ==4'b0000 && key_down[2])begin 
            if(cnt_sa0==4'd9)begin
                cnt_sa0 <= 0;
            end 
            else begin
                cnt_sa0 <= cnt_sa0+1'b1;
            end
    end 
    else if (IDLE_STEA) begin
        cnt_sa0 <= 0;
    end 
    else begin 
            cnt_sa0 <= cnt_sa0;
    end 
end

//秒的十位设置
always @(posedge clk or negedge rst_n)begin 
    if(!rst_n)begin
        cnt_sa1 <= 0;
    end 
    else if(state_c == STEA && sele1 ==4'b0001 && key_down[2])begin 
            if(cnt_sa1==4'd5)begin
                cnt_sa1 <= 0;
            end 
            else begin
                cnt_sa1 <= cnt_sa1+1'b1;
            end
    end
    else if (IDLE_STEA) begin
       cnt_sa1 <= 0;
    end 
    else begin 
            cnt_sa1 <= cnt_sa1;
    end 
end

//分的个位设置
always @(posedge clk or negedge rst_n)begin 
    if(!rst_n)begin
        cnt_ma0 <= 0;
    end 
    else if(state_c == STEA && sele1 ==4'b0010 && key_down[2])begin 
            if(cnt_ma0==4'd9)begin
                cnt_ma0 <= 0;
            end 
            else begin
                cnt_ma0 <= cnt_ma0+1'b1;
            end
    end 
    else if (IDLE_STEA) begin
           cnt_ma0 <= 0;
    end
    else begin 
            cnt_ma0 <= cnt_ma0;
    end 
end
//分的十位设置
always @(posedge clk or negedge rst_n)begin 
    if(!rst_n)begin
        cnt_ma1 <= 0;
    end 
    else if(state_c == STEA && sele1 ==4'b0011 && key_down[2])begin 
            if(cnt_ma1==4'd5)begin
                cnt_ma1 <= 0;
            end 
            else begin
                cnt_ma1 <= cnt_ma1+1'b1;
            end
    end 
     else if (IDLE_STEA) begin
        cnt_ma1 <= 0;
     end
    else begin 
            cnt_ma1 <= cnt_ma1;
    end 
end
//时的个位设置
always @(posedge clk or negedge rst_n)begin 
    if(!rst_n)begin
        cnt_ha0 <= 0;
    end 
    else if(state_c == STEA && sele1 ==4'b0100 && key_down[2])begin 
            if(cnt_ha0==4'd9)begin
                cnt_ha0 <= 0;
            end 
            else if (cnt_ha0==4'd3&&cnt_ha1==4'd2) begin        //当h的十位为2时个位最大值为3
                cnt_ha0 <= 0;
            end
            else begin
                cnt_ha0 <= cnt_ha0+1'b1;
            end
    end 
    else if (IDLE_STEA) begin
        cnt_ha0 <= 0;
    end
    else begin 
            cnt_ha0 <= cnt_ha0;
    end 
end

//时的十位设置 
always @(posedge clk or negedge rst_n)begin 
    if(!rst_n)begin
        cnt_ha1 <= 0;
    end 
    else if(state_c == STEA && sele1 ==4'b0101 && key_down[2])begin 
            if(cnt_ha1==4'd2)begin
                cnt_ha1 <= 0;
            end 
            else begin
                cnt_ha1 <= cnt_ha1+1'b1;
            end
    end 
    else if (IDLE_STEA) begin
        cnt_ha1 <= 0;
    end
    else begin 
            cnt_ha1 <= cnt_ha1;
    end 
end


//时钟数码管显示
always @(posedge clk or negedge rst_n)begin 
    if(!rst_n)begin
        din <= {24'b0000_0000_0000_0000_0000_0000};
    end 
    else if(state_c ==IDLE)begin        //正常运行时间
        din <= {cnt_s_g,cnt_s_s,cnt_m_g,cnt_m_s,cnt_h_g,cnt_h_s};
    end 
    else if (state_c ==STET) begin      //设置时间
        din <= {cnt_s0,cnt_s1,cnt_m0,cnt_m1,cnt_h0,cnt_h1};
    end
    else if (state_c ==STEA) begin      //闹钟时间
            din <= {cnt_sa0,cnt_sa1,cnt_ma0,cnt_ma1,cnt_ha0,cnt_ha1};
        end
    
    else begin 
        din <= din;
    end 
end

//闹钟
always @(posedge clk or negedge rst_n)begin 
    if(!rst_n)begin
        beep <= 1'b1;
        led <= 4'b0000;
    end 
    else if(state_d ==IDLE && {cnt_ha1,cnt_ha0,cnt_ma1,cnt_ma0,cnt_sa1,cnt_sa0}=={cnt_h_s,cnt_h_g,cnt_m_s,cnt_m_g,cnt_s_s,cnt_s_g})begin 
        beep <= 1'b0;
        led <= 4'b1111;
        if(key_down[2])begin
            beep <= 1'b1;
            led <= 4'b0000; 
        end 
    end 
    else  begin
        beep <= 1'b1;
        led <= 4'b0000;
    end
end
                     
endmodule



五、图片展示

在这里插入图片描述

  • 3
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值