状态机的练习:按键控制led灯

2023-12-14 14:59:30

设计思路:

三个按键控制led输出。

三个按键经过滤波(消抖),产生三个按键标志信号。

三个led数据的产生模块(流水,跑马,闪烁模块),分别产生led信号。

这六路信号(三路按键信号,三路led信号),接入state_led_ctrl模块,进行led_out的控制。

状态机:

?

模块框图:

代码:

/*
    1位按键消抖
*/ 
module key_filter (
    input       wire            sys_clk     ,
    input       wire            sys_rst_n   ,
    input       wire            key_in      ,

    output      reg             key_flag    
);
    // 参数定义
    parameter   MAX_CNT_10MS = 500_000   ;
    localparam  IDLE         = 4'b0001   ,
                FILTER_UP    = 4'b0010   ,
                SAMPLING     = 4'b0100   ,
                FILTER_BACK  = 4'b1000   ;
    // reg signal define 
    reg                 key_in_r1 ;  
    reg                 key_in_r2 ;
    reg     [18:0]      cnt_core  ;
    reg     [3:0]       state_c   ;
    reg     [3:0]       state_n   ;
    // wire signal define 
    wire                nege                  ;
    wire                pose                  ;
    wire                IDLEtoFILTER_UP       ;
    wire                FILTER_UPtoIDLE       ;
    wire                FILTER_UPtoSAMPLING   ;
    wire                SAMPLINGtoFILTER_BACK ;
    wire                FILTER_BACKtoIDLE     ;
    wire                filter_done           ; 
    /******************************************************************/
    // reg                 key_in_r1 ; 
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) 
            key_in_r1 <= 1'b1 ;
        else
            key_in_r1 <= key_in ;
    end 
    // reg                 key_in_r2 ;
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) 
            key_in_r2 <= 1'b1 ;
        else
            key_in_r2 <= key_in_r1 ;
    end 
    // wire                nege      ;
    assign  nege = ~key_in_r1 &&  key_in_r2 ;
    // wire                pose      ;  
    assign  pose =  key_in_r1 && ~key_in_r2 ;
    // reg     [3:0]       state_c   ;
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) 
            state_c <= IDLE ;
        else
            state_c <= state_n ;
    end
    // reg     [3:0]       state_n   ;
    always @(*) begin
        case(state_c)
        IDLE      : if(IDLEtoFILTER_UP)
                        state_n = FILTER_UP ;
                    else 
                        state_n = IDLE ;
        FILTER_UP : if(FILTER_UPtoIDLE)
                        state_n = IDLE ;
                    else if(FILTER_UPtoSAMPLING)
                        state_n = SAMPLING ;
                    else 
                        state_n = FILTER_UP ;
        SAMPLING  : if(SAMPLINGtoFILTER_BACK)
                        state_n = FILTER_BACK ;
                    else 
                        state_n = SAMPLING ;
        FILTER_BACK:if(FILTER_BACKtoIDLE)
                        state_n = IDLE ;
                    else
                        state_n = FILTER_BACK ;
        default   :     state_n = IDLE ;
        endcase
    end
    assign  IDLEtoFILTER_UP         = (state_c == IDLE)       && (nege) ;
    assign  FILTER_UPtoIDLE         = (state_c == FILTER_UP)  && (pose) ;
    assign  FILTER_UPtoSAMPLING     = (state_c == FILTER_UP)  && (filter_done) ;
    assign  SAMPLINGtoFILTER_BACK   = (state_c == SAMPLING)   && (pose) ;
    assign  FILTER_BACKtoIDLE       = (state_c == FILTER_BACK)&& (filter_done) ;
    // reg     [18:0]      cnt_core  ;
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) 
            cnt_core <= 19'd0 ;
        else
        case (state_c)
        IDLE       :cnt_core <= 19'd0 ; 
        FILTER_UP  :if(filter_done)
                        cnt_core <= 19'd0 ;
                    else 
                        cnt_core <= cnt_core + 1'b1 ;
        SAMPLING   :cnt_core <= 19'd0 ; 
        FILTER_BACK:if(filter_done)
                        cnt_core <= 19'd0 ;
                    else 
                        cnt_core <= cnt_core + 1'b1 ;
        default    :    cnt_core <= 19'd0 ;
        endcase
    end
    // wire                filter_done
    assign  filter_done = (cnt_core == MAX_CNT_10MS - 1) ;
    // output reg key_flag
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) 
            key_flag <= 1'b0 ;
        else if(FILTER_UPtoSAMPLING)
            key_flag <= ~key_in_r2 ;
        else 
            key_flag <= 1'b0 ;
    end

endmodule

?

module led_paoma (
    input		wire				sys_clk      ,
    input		wire				sys_rst_n    ,

    output		reg     [3:0]       led_out     
);

    parameter   MAX_CNT_500MS = 25_000_000 ;
    // reg signal define
    reg     [24:0]      cnt_500ms ;
    reg     [ 1:0]      cnt_state ;
    // wire signal define
    wire                add_cnt_500ms ;
    wire                end_cnt_500ms ;
    wire                add_cnt_state ;
    wire                end_cnt_state ;
/******************************************************************************************
********************************************main code**************************************
*******************************************************************************************/
    // reg     [24:0]      cnt_500ms ;
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) 
            cnt_500ms <= 25'd0 ;
        else if(add_cnt_500ms) begin
            if(end_cnt_500ms)
                cnt_500ms <= 25'd0 ;
            else 
                cnt_500ms <= cnt_500ms + 1'b1 ;
        end
        else 
            cnt_500ms <= 25'd0 ;
    end
    // reg     [ 1:0]      cnt_state ;
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) 
            cnt_state <= 2'd0 ;
        else if(add_cnt_state) begin
            if(end_cnt_state)
                cnt_state <= 2'd0 ;
            else 
                cnt_state <= cnt_state + 1'b1 ;
        end 
        else 
            cnt_state <= cnt_state ;
    end
    // // wire signal define
    // wire                add_cnt_500ms ;
    assign  add_cnt_500ms = 1'b1 ;
    // wire                end_cnt_500ms ;
    assign  end_cnt_500ms = add_cnt_500ms && (cnt_500ms == (MAX_CNT_500MS - 1)) ;
    // wire                add_cnt_state ;
    assign  add_cnt_state = end_cnt_500ms ;
    // wire                end_cnt_state ;
    assign  end_cnt_state = ((add_cnt_state && (cnt_state == 2'b11 )) ) ; 
    // output reg [3:0]     led_out 
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) 
            led_out <= 4'b0000 ;
        else 
        case (cnt_state)
        2'b00 :     led_out <= 4'b0001 ;
        2'b01 :     led_out <= 4'b0010 ;
        2'b10 :     led_out <= 4'b0100 ;
        2'b11 :     led_out <= 4'b1000 ;
        default:    led_out <= 4'b0000 ;
        endcase
    end
endmodule

?

module shanshuo (
    input		wire				sys_clk      ,
    input		wire				sys_rst_n    ,

    output		reg     [3:0]       led_out     
);

    parameter   MAX_CNT_500MS = 25_000_000 ;
    // reg signal define
    reg     [24:0]      cnt_500ms ;
    // wire signal define
    wire                add_cnt_500ms ;
    wire                end_cnt_500ms ;
/******************************************************************************************
********************************************main code**************************************
*******************************************************************************************/
    // reg     [24:0]      cnt_500ms ;
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) 
            cnt_500ms <= 25'd0 ;
        else if(add_cnt_500ms) begin
            if(end_cnt_500ms)
                cnt_500ms <= 25'd0 ;
            else 
                cnt_500ms <= cnt_500ms + 1'b1 ;
        end
        else 
            cnt_500ms <= 25'd0 ;
    end

    // // wire signal define
    // wire                add_cnt_500ms ;
    assign  add_cnt_500ms = 1'b1 ;
    // wire                end_cnt_500ms ;
    assign  end_cnt_500ms = add_cnt_500ms && (cnt_500ms == (MAX_CNT_500MS - 1)) ;

    // output reg [3:0]     led_out 
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) 
            led_out <= 4'b0000 ;
        else if(end_cnt_500ms)
            led_out <= ~led_out ;
        else 
            led_out <=  led_out ;
    end
    
endmodule

?

module led_water (
    input		wire				sys_clk      ,
    input		wire				sys_rst_n    ,

    output		reg     [3:0]       led_out     
);

    parameter   MAX_CNT_500MS = 25_000_000 ;
    // reg signal define
    reg     [24:0]      cnt_500ms ;
    reg     [ 2:0]      cnt_state ; 
    // wire signal define
    wire                add_cnt_500ms ;
    wire                end_cnt_500ms ;
    wire                add_cnt_state ;
    wire                end_cnt_state ;
/******************************************************************************************
********************************************main code**************************************
*******************************************************************************************/
    // reg     [24:0]      cnt_500ms ;
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) 
            cnt_500ms <= 25'd0 ;
        else if(add_cnt_500ms) begin
            if(end_cnt_500ms)
                cnt_500ms <= 25'd0 ;
            else 
                cnt_500ms <= cnt_500ms + 1'b1 ;
        end
        else 
            cnt_500ms <= 25'd0 ;
    end
    // reg     [ 1:0]      cnt_state ;
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) 
            cnt_state <= 2'd0 ;
        else if(add_cnt_state) begin
            if(end_cnt_state)
                cnt_state <= 2'd0 ;
            else 
                cnt_state <= cnt_state + 1'b1 ;
        end 
        else 
            cnt_state <= cnt_state ;
    end
    // // wire signal define
    // wire                add_cnt_500ms ;
    assign  add_cnt_500ms = 1'b1 ;
    // wire                end_cnt_500ms ;
    assign  end_cnt_500ms = add_cnt_500ms && (cnt_500ms == (MAX_CNT_500MS - 1)) ;
    // wire                add_cnt_state ;
    assign  add_cnt_state = end_cnt_500ms ;// && led_flag
    // wire                end_cnt_state ;
    assign  end_cnt_state = ((add_cnt_state && (cnt_state == 3'b101 )) ) ; 
    // output reg [3:0]     led_out 
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) 
            led_out <= 4'b0000 ;
        else 
        case (cnt_state)
        3'b000 :     led_out <= 4'b0001 ;
        3'b001 :     led_out <= 4'b0010 ;
        3'b010 :     led_out <= 4'b0100 ;
        3'b011 :     led_out <= 4'b1000 ;
        3'b100 :     led_out <= 4'b0100 ;
        3'b101 :     led_out <= 4'b0010 ;
        default:     led_out <= 4'b0000 ;
        endcase
    end
endmodule

?

module state_led_ctrl (
    input		wire				sys_clk         ,
    input		wire				sys_rst_n       ,
    input       wire                water_flag      ,
    input       wire                paoma_flag      ,
    input       wire                shanshuo_flag   ,
    input       wire    [3:0]       led_water       ,
    input       wire    [3:0]       led_paoma       ,
    input       wire    [3:0]       led_shanshuo    ,

    output	    reg     [3:0]       led_out         
);

    localparam          IDLE        = 4'b0001 ,
                        WATER       = 4'b0010 ,
                        PAOMA       = 4'b0100 ,
                        SHANSHUO    = 4'b1000 ;

    // reg signal define
    reg     [3:0]       state_c ;
    reg     [3:0]       state_n ;
    // wire signal
    wire                IDLEtoWATER         ;
    wire                IDLEtoPAOMA         ;
    wire                IDLEtoSHANSHUO      ;
    wire                WATERtoPAOMA        ;
    wire                WATERtoSHANSHUO     ;
    wire                PAOMAtoWATER        ;
    wire                PAOMAtoSHANSHUO     ;
    wire                SHANSHUOtoPAOMA     ;
    wire                SHANSHUOtoWATER     ;
/******************************************************************************************
********************************************main code**************************************
*******************************************************************************************/
    // // reg signal define
    // reg         state_c ;
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) 
            state_c <= IDLE ;
        else
            state_c <= state_n ;
    end
    // reg         state_n ;
    always @(*) begin
        case(state_c)
        IDLE     :  if(IDLEtoWATER)
                        state_n = WATER ;
                    else if(IDLEtoPAOMA)
                        state_n = PAOMA ;
                    else if(IDLEtoSHANSHUO)
                        state_n = SHANSHUO ;
                    else 
                        state_n = IDLE ;
        WATER    :  if(WATERtoPAOMA)
                        state_n = PAOMA ;
                    else if(WATERtoSHANSHUO)
                        state_n = SHANSHUO ;
                    else 
                        state_n = WATER ;
        PAOMA    :  if(PAOMAtoWATER)
                        state_n = WATER ;
                    else if(PAOMAtoSHANSHUO)
                        state_n = SHANSHUO ;
                    else 
                        state_n = PAOMA ;
        SHANSHUO :  if(SHANSHUOtoPAOMA)
                        state_n = PAOMA ;
                    else if(SHANSHUOtoWATER)
                        state_n = WATER ;
                    else 
                        state_n = SHANSHUO ;
        default  :  state_n = IDLE ;
        endcase
    end

    assign  IDLEtoWATER         = (state_c == IDLE      ) && (water_flag   ) ;
    assign  IDLEtoPAOMA         = (state_c == IDLE      ) && (paoma_flag   ) ;
    assign  IDLEtoSHANSHUO      = (state_c == IDLE      ) && (shanshuo_flag) ;
    assign  WATERtoPAOMA        = (state_c == WATER     ) && (paoma_flag   ) ;
    assign  WATERtoSHANSHUO     = (state_c == WATER     ) && (shanshuo_flag) ;
    assign  PAOMAtoWATER        = (state_c == PAOMA     ) && (water_flag   ) ;
    assign  PAOMAtoSHANSHUO     = (state_c == PAOMA     ) && (shanshuo_flag) ;
    assign  SHANSHUOtoPAOMA     = (state_c == SHANSHUO  ) && (paoma_flag   ) ;
    assign  SHANSHUOtoWATER     = (state_c == SHANSHUO  ) && (water_flag   ) ;

    // led_out
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) 
            led_out <= 4'hf ;
        else 
        case (state_c)
        IDLE    :   led_out <= 4'hf ;
        WATER   :   led_out <= led_water    ;
        PAOMA   :   led_out <= led_paoma    ;
        SHANSHUO:   led_out <= led_shanshuo ;
        default:    led_out <= 4'hf ;
        endcase
    end

endmodule

?

module top (
    input		wire				sys_clk         ,
    input		wire				sys_rst_n       ,
    input       wire                key_water       ,
    input       wire                key_paoma       ,
    input       wire                key_shanshuo    ,

    output		wire    [3:0]       led_out         
);

    // inst wire
    wire                water_flag      ;
    wire                paoma_flag      ;
    wire                shanshuo_flag   ;
    wire    [3:0]       led_water       ;
    wire    [3:0]       led_paoma       ;
    wire    [3:0]       led_shanshuo    ;

    // inst
key_filter key_filter_inst_water(
    .sys_clk                ( sys_clk       ) ,
    .sys_rst_n              ( sys_rst_n     ) ,
    .key_in                 ( key_water     ) ,

    .key_flag               ( water_flag    )  
);

key_filter key_filter_inst_paoma(
    .sys_clk                ( sys_clk       ) ,
    .sys_rst_n              ( sys_rst_n     ) ,
    .key_in                 ( key_paoma     ) ,

    .key_flag               ( paoma_flag    )  
);

key_filter key_filter_inst_shanshuo(
    .sys_clk                ( sys_clk       ) ,
    .sys_rst_n              ( sys_rst_n     ) ,
    .key_in                 ( key_shanshuo  ) ,

    .key_flag               ( shanshuo_flag )  
);

led_water led_water_isnt (
    .sys_clk                ( sys_clk       ) ,
    .sys_rst_n              ( sys_rst_n     ) ,

    .led_out                ( led_water     )  
);

led_paoma led_paoma_inst(
    .sys_clk                ( sys_clk       ) ,
    .sys_rst_n              ( sys_rst_n     ) ,

    .led_out                ( led_paoma     )  
);

shanshuo shanshuo_inst(
    .sys_clk                ( sys_clk       ) ,
    .sys_rst_n              ( sys_rst_n     ) ,

    .led_out                ( led_shanshuo  )  
);

state_led_ctrl state_led_ctrl_inst(
    .sys_clk                ( sys_clk       ) ,
    .sys_rst_n              ( sys_rst_n     ) ,
    .water_flag             ( water_flag    ) ,
    .paoma_flag             ( paoma_flag    ) ,
    .shanshuo_flag          ( shanshuo_flag ) ,
    .led_water              ( led_water     ) ,
    .led_paoma              ( led_paoma     ) ,
    .led_shanshuo           ( led_shanshuo  ) ,

    .led_out                ( led_out       )  
);

endmodule

?

仿真:

`timescale 1ns/1ns
module test_top ();
    reg 				sys_clk         ;
    reg 				sys_rst_n       ;
    reg                 key_water       ;
    reg                 key_paoma       ;
    reg                 key_shanshuo    ;

    wire    [3:0]       led_out         ;

top top_inst(
    .sys_clk            ( sys_clk       ) ,
    .sys_rst_n          ( sys_rst_n     ) ,
    .key_water          ( key_water     ) ,
    .key_paoma          ( key_paoma     ) ,
    .key_shanshuo       ( key_shanshuo  ) ,

    .led_out            ( led_out       )  
);

    defparam    top_inst.key_filter_inst_water.MAX_CNT_10MS     = 50 ;
    defparam    top_inst.key_filter_inst_paoma.MAX_CNT_10MS     = 50 ;
    defparam    top_inst.key_filter_inst_shanshuo.MAX_CNT_10MS  = 50 ;
    defparam    top_inst.led_water_isnt.MAX_CNT_500MS           = 50 ;
    defparam    top_inst.led_paoma_inst.MAX_CNT_500MS           = 50 ;
    defparam    top_inst.shanshuo_inst.MAX_CNT_500MS            = 50 ;
    parameter   CYCLE = 20 ;

    initial begin
        sys_clk      = 1'b1 ;
        sys_rst_n   <= 1'b1 ;
        key_water   <= 1'b1 ;
        key_paoma   <= 1'b1 ;
        key_shanshuo<= 1'b1 ;
        #( CYCLE * 10 )     ;
        sys_rst_n <= 1'b0   ;
        #( 200 )            ;
        sys_rst_n <= 1'b1   ;
        #( CYCLE * 10 )     ;

        key_water <= 1'b0   ;
        #( CYCLE * 100 )    ;
        key_water <= 1'b1   ;
        #( CYCLE * 1000 )   ;

        key_paoma <= 1'b0   ;
        #( CYCLE * 100 )    ;
        key_paoma <= 1'b1   ;
        #( CYCLE * 1000 )   ;

        key_shanshuo <= 1'b0;
        #( CYCLE * 100 )    ;
        key_shanshuo <= 1'b1;
        #( CYCLE * 1000 )   ;
        
        $stop               ;
    end

    always #( CYCLE / 2 ) sys_clk = ~sys_clk ;


endmodule

文章来源:https://blog.csdn.net/Meng_long2022/article/details/134864272
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。