状态机的练习:按键控制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
相关推荐
Hello-FPGA12 小时前
基于RFSOC FPGA ZCU216 的CoaXPress 采集demo
fpga开发
9527华安14 小时前
FPGA基于ADV7182解码PAL视频,Video Processing Subsystem去隔行,提供6套工程源码和技术支持
fpga开发·音视频·pal·adv7182
hahaha601614 小时前
数字图像时域滤波或者3D降噪算法FPGA实现
算法·计算机视觉·fpga开发
GateWorld14 小时前
Xilinx 7系列FPGA时钟网络详解
fpga开发·时钟网络·xilinx 7系列
szxinmai主板定制专家1 天前
X86 工控机 vs RK3588 异构主控:AMR 控制器 BOM、散热、长期运维对比
运维·stm32·单片机·嵌入式硬件·fpga开发·am62x
szxinmai主板定制专家2 天前
AMR 项目落地:机器人控制器硬件定制化需求复盘
arm开发·单片机·fpga开发·系统架构·机器人·am62x
FPGA小迷弟3 天前
FPGA 与卫星:从星载硬件到在轨智能的完整技术解析
fpga开发·架构·fpga·1024程序员节·无线电
NamoAmitabha1283 天前
CPU 内部结构是什么?---deepseek
fpga开发
abc light3 天前
ARM 裸机开发(6)——时钟树与定时器
arm开发·单片机·fpga开发
156082072193 天前
JFMZQ28DR、JFMZQ68DR、RFsoc XCZU47DR、XCZU48DR 信号处理板
fpga开发·信号处理