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

设计思路:

三个按键控制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
相关推荐
乌恩大侠2 小时前
O-RAN Fronthual CU/Sync/Mgmt 平面和协议栈
5g·平面·fpga开发·架构
DS小龙哥15 小时前
基于Zynq FPGA的雷龙SD NAND存储芯片性能测试
fpga开发·sd nand·雷龙·spi nand·spi nand flash·工业级tf卡·嵌入式tf卡
上理考研周导师1 天前
第二章 虚拟仪器及其构成原理
fpga开发
FPGA技术实战1 天前
《探索Zynq MPSoC》学习笔记(二)
fpga开发·mpsoc
bigbig猩猩2 天前
FPGA(现场可编程门阵列)的时序分析
fpga开发
Terasic友晶科技2 天前
第2篇 使用Intel FPGA Monitor Program创建基于ARM处理器的汇编或C语言工程<二>
fpga开发·汇编语言和c语言
码农阿豪2 天前
基于Zynq FPGA对雷龙SD NAND的测试
fpga开发·sd nand·spi nand·spi nand flash·工业级tf卡·嵌入式tf卡
江山如画,佳人北望2 天前
EDA技术简介
fpga开发
淘晶驰AK2 天前
电子设计竞赛准备经历分享
嵌入式硬件·fpga开发