ZYNQ_project:key_beep

通过按键控制蜂鸣器工作。

模块框图:

ZYNQ_project:key_beep_第1张图片

时序图:

ZYNQ_project:key_beep_第2张图片

ZYNQ_project:key_beep_第3张图片 ZYNQ_project:key_beep_第4张图片

ZYNQ_project:key_beep_第5张图片

代码:

/*
    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

/*
    蜂鸣器驱动模块,NPN三极管,beep_en == 1 鸣叫。有源电磁式。
    1, 初始状态鸣叫,按键每按下一次,蜂鸣器状态翻转。
    2.  初始状态蜂鸣器工作,响100ms , 不响100ms, 响100ms, 不响300ms.按键每按下一次,蜂鸣器工作状态翻转。
*/ 
module beep (
    input       wire            sys_clk     ,
    input       wire            sys_rst_n   ,
    input       wire            key_flag    ,

    output      reg             beep_en     
);
    // // output reg beep_en
    // always @(posedge sys_clk or negedge sys_rst_n) begin
    //     if(~sys_rst_n) 
    //         beep_en <= 1'b1 ;
    //     else if(key_flag)
    //         beep_en <= ~beep_en ;
    // end

    // parameter
    parameter   MAX_CNT_100MS = 5_000_000  ,
                MAX_CNT_300MS = 15_000_000 ;
    localparam  RING          = 3'b001     ,
                NO_RING_MOD1  = 3'b010     ,
                NO_RING_MOD2  = 3'b100     ;
    // reg signal define
    reg                 beep_work ;
    reg     [23:0]      cnt_core  ;
    reg     [2:0]       state_c   ;
    reg     [2:0]       state_n   ;
    reg                 mod1_flag ;
    // wire signal define
    wire                RINGtoNO_RING_MOD1 ;
    wire                RINGtoNO_RING_MOD2 ;
    wire                NO_RING_MOD1toRING ;
    wire                NO_RING_MOD2toRING ;
    wire                no_ring_done       ;
    /*****************************************************/
    // reg                 beep_work ;
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) 
            beep_work <= 1'b1 ;
        else if(key_flag)
            beep_work <= ~beep_work ;
        else 
            beep_work <= beep_work ;
    end
    // reg     [2:0]       state_c   ;
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) 
            state_c <= RING ;
        else 
            state_c <= state_n ;
    end
    // reg     [2:0]       state_n   ;
    always @(*) begin
        if(beep_work) begin
            case(state_c)
            RING        :   if(RINGtoNO_RING_MOD1)
                                state_n = NO_RING_MOD1 ;
                            else if(RINGtoNO_RING_MOD2)
                                state_n = NO_RING_MOD2 ;
                            else
                                state_n = RING ;
            NO_RING_MOD1:   if(NO_RING_MOD1toRING)
                                state_n = RING ;
                            else 
                                state_n = NO_RING_MOD1 ;
            NO_RING_MOD2:   if(NO_RING_MOD2toRING)
                                state_n = RING ;
                            else 
                                state_n = NO_RING_MOD2 ;
            default     :       state_n = RING ;
            endcase
            end
        else
            state_n = RING ;
    end
    assign  RINGtoNO_RING_MOD1 = (state_c == RING)         && (no_ring_done && (mod1_flag))    ;
    assign  RINGtoNO_RING_MOD2 = (state_c == RING)         && (no_ring_done && (!mod1_flag))   ;
    assign  NO_RING_MOD1toRING = (state_c == NO_RING_MOD1) && (no_ring_done) ;
    assign  NO_RING_MOD2toRING = (state_c == NO_RING_MOD2) && (no_ring_done) ;
    // reg     [23:0]      cnt_core  ;
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) 
            cnt_core <= 24'd0 ;
        else
        if(beep_work) begin
            case (state_c)
            RING        :   if(no_ring_done)
                                cnt_core <= 24'd0 ;
                            else 
                                cnt_core <= cnt_core + 1'b1 ; 
            NO_RING_MOD1:   if(no_ring_done)
                                cnt_core <= 24'd0 ;
                            else 
                                cnt_core <= cnt_core + 1'b1 ; 
            NO_RING_MOD2:   if(no_ring_done)
                                cnt_core <= 24'd0 ;
                            else 
                                cnt_core <= cnt_core + 1'b1 ;  
            default     :   cnt_core <= 24'd0 ;
            endcase
        end
        else 
            cnt_core <= 24'd0 ;
    end
    // reg                 mod1_flag ;
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) 
            mod1_flag <= 1'b1 ;
        else if(beep_work) begin
            if((state_c != RING) && (no_ring_done))
                mod1_flag <= ~mod1_flag ;
            else 
                mod1_flag <= mod1_flag ;
            end
        else 
            mod1_flag <= 1'b1 ;
    end
    // wire                no_ring_done;
    assign  no_ring_done = (((state_c != NO_RING_MOD2)&&(cnt_core == MAX_CNT_100MS - 1))||((state_c == NO_RING_MOD2)&&(cnt_core == MAX_CNT_300MS - 1))) ? 1'b1 : 1'b0 ;
    // output reg beep_en
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) 
            beep_en <= 1'b1 ;
        else if(beep_work) begin
            if(state_c == RING)
                beep_en <= 1'b1 ;
            else 
                beep_en <= 1'b0 ;
        end
        else 
            beep_en <= 1'b0 ; 
    end

endmodule

module top(
    input       wire            sys_clk     ,
    input       wire            sys_rst_n   ,
    input       wire            key_in      ,

    output      wire            beep        
);
    // 例化间连线
    wire        key_flag ;
key_filter key_filter_inst(
    .sys_clk                ( sys_clk   ) ,
    .sys_rst_n              ( sys_rst_n ) ,
    .key_in                 ( key_in    ) ,

    .key_flag               ( key_flag  )  
);

beep beep_inst(
    .sys_clk                ( sys_clk   ) ,
    .sys_rst_n              ( sys_rst_n ) ,
    .key_flag               ( key_flag  ) ,

    .beep_en                ( beep      )  
);

endmodule

`timescale 1ns/1ns
module test_top();
    reg            sys_clk     ;
    reg            sys_rst_n   ;
    reg            key_in      ;

    wire           beep        ;

top top_inst(
    .sys_clk        ( sys_clk   ) ,
    .sys_rst_n      ( sys_rst_n ) ,
    .key_in         ( key_in    ) ,

    .beep           ( beep      )  
);

    parameter   CYCLE = 20 ;
    defparam    top_inst.key_filter_inst.MAX_CNT_10MS = 50 ;
    defparam    top_inst.beep_inst.MAX_CNT_100MS = 500  ;
    defparam    top_inst.beep_inst.MAX_CNT_300MS = 1500 ;

    initial begin
        sys_clk    = 1'b1 ;
        sys_rst_n <= 1'b0 ;
        key_in    <= 1'b1 ;
        #( CYCLE * 10 )   ;
        sys_rst_n <= 1'b1 ;
        #( CYCLE * 10 )   ;

        #( CYCLE * 3000 ) ;
        #( CYCLE * 500  ) ; // 检测蜂鸣器状态机是否正常工作。
        
        key_in    <= 1'b0 ;
        #( CYCLE * 50 * 3 ); // 按下足够长的时间,第一次按键按下。
        key_in    <= 1'b1 ;
        #( CYCLE * 3000 ) ;
        #( CYCLE * 500  ) ; // 检测蜂鸣器状态机是否正常工作。

        key_in    <= 1'b0 ;
        #( CYCLE * 50 * 3 ); // 按下足够长的时间,第二次按键按下。
        key_in    <= 1'b1 ;
        #( CYCLE * 3000 ) ;
        #( CYCLE * 500  ) ; // 检测蜂鸣器状态机是否正常工作。

        $stop             ;
    end

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


endmodule

仿真:

ZYNQ_project:key_beep_第6张图片

你可能感兴趣的:(正点原子领航者7020,fpga开发)