zoukankan      html  css  js  c++  java
  • 矩阵按键的试验---verilog

    矩阵键盘的试验,采用三段式状态机处理方法。

    难点在于检测状态机中:按键消抖以后逐列检测。

    电路图:

    代码

    /********************************Copyright**************************************                           
    **----------------------------File information--------------------------
    ** File name  :keyboard.v  
    ** CreateDate :2015.04
    ** Funtions   :4x4矩阵键盘
    ** Operate on :M5C06N3L114C7
    ** Copyright  :All rights reserved. 
    ** Version    :V1.0
    **---------------------------Modify the file information----------------
    ** Modified by   :
    ** Modified data :        
    ** Modify Content: 2015.6
    *******************************************************************************/
     
    module keyboard(
                      clk,
                                        rst_n,
                                        
                                        l_in,
                                        h_out,
                                        
                                        test_1,
                                        test_2,
                                        
                                        key_val,
                                        key_val_flag
                                        );
     input             clk;          /* clk = 24M */
     input             rst_n;
     input   [3:0]     l_in;             //列输入,一般接上拉,为高电平
     
     output            test_1;
     output            test_2;
     
     output  [3:0]     h_out;            //行输出信号,低有效 
     output  [3:0]     key_val;          //按键值,输出   
     output            key_val_flag;
                
     wire    [3:0]     key_val; 
     reg               test_1;
     reg               test_2;
     //*************************************
     /* 分频Ƶ*20ms,用于消抖 .状态机直接用clk_20ms,则可以跳过消抖*/
     
    //  `define   CLK_24M 
       `define   CLK_20M 
        
        `ifdef  CLK_24M
            parameter  t_20ms = 20'd479999;         
         `endif
         
         `ifdef  CLK_20M
            parameter  t_20ms = 20'd399999;         
         `endif
         
      reg    [19:0]   cnt;
     always @(posedge clk or negedge rst_n)
      begin
        if(!rst_n)
          begin
               cnt <= 'd0;
            end
          else 
           begin
             if(cnt == t_20ms)  cnt <= 'd0;
             else cnt <= cnt + 'd1;                 
             end
      end
      wire    shake_over = (cnt == t_20ms);
     //******************状态机******************
     localparam NO_KEY_pressed  =  3'd0;        /* 初始化 */
     localparam key_shake_1     =  3'd1;        /* 消抖1 */
     localparam KEY_h_1         =  3'd2;        /* 检测第一列 */
     localparam KEY_h_2         =  3'd3;        /* 检测第二列 */
     localparam KEY_h_3         =  3'd4;        /* 检测第三列 */ 
     localparam KEY_h_4         =  3'd5;        /* 检测第四列 */
     localparam KEY_pressed     =  3'd6;        /* 按键值输出*/
     localparam key_shake_2     =  3'd7;        /* 消抖2 */ 
     
     /* 3-1 */
     reg     [2:0]      current_state;
     reg     [2:0]      next_state;
     reg                key_pressed_flag; 
     always @(posedge clk or negedge rst_n)
     begin
      if(!rst_n)
       begin
          current_state <= 0;
        end
      else if(shake_over)
        begin
          current_state <= next_state;
        end
        else 
             current_state <=  current_state ;    
      end
        
     /* 3-2 */
    always @(*) 
     begin
         next_state     = NO_KEY_pressed;
       case(current_state)
        NO_KEY_pressed:
                  begin
                            if(l_in != 4'hf)   next_state = key_shake_1;
                     else  next_state = NO_KEY_pressed;
               end
            key_shake_1:     
             begin
                            if(l_in != 4'hf)   next_state = KEY_h_1;
                     else  next_state = NO_KEY_pressed;
               end
        KEY_h_1:
                begin
                            if(l_in != 4'hf)   next_state = KEY_pressed;
                     else  next_state = KEY_h_2;
              end
            KEY_h_2:
                begin
                            if(l_in != 4'hf)   next_state = KEY_pressed;
                     else  next_state = KEY_h_3;
              end
        KEY_h_3:
                begin
                            if(l_in != 4'hf)   next_state = KEY_pressed;
                     else  next_state = KEY_h_4;
              end
        KEY_h_4:
                begin
                            if(l_in != 4'hf)   next_state = KEY_pressed;
                     else  next_state = NO_KEY_pressed;
              end
       KEY_pressed:
              begin
                            if(l_in != 4'hf)   next_state = key_shake_2;
                     else  next_state = NO_KEY_pressed;
              end
         key_shake_2:
              begin
                            if(l_in != 4'hf)   next_state = key_shake_2;
                     else  next_state = NO_KEY_pressed;
              end
         default:;
        endcase
    end
    
    /* 3-3  */
    
     reg    [3:0]      l_in_reg;
     reg    [3:0]   h_out_reg;
     reg    [3:0]   h_out; 
    always @(posedge clk or negedge rst_n)
     begin
      if(!rst_n)
       begin
          l_in_reg <= 4'd0;
                h_out_reg<= 4'd0;
                h_out <= 4'd0;
                key_pressed_flag <= 0;
        end
      else if(shake_over)
        begin
         case(next_state)
             NO_KEY_pressed:
                begin
                  l_in_reg <= l_in_reg;
                        h_out_reg<= h_out_reg;
                        h_out <= 4'd0;   
                        key_pressed_flag <= 0;
                 end
             KEY_h_1:
                  begin
                         h_out <= 4'b1110;                             
                        end
             KEY_h_2:
                  begin
                         h_out <= 4'b1101;                             
                        end
             KEY_h_3:
                  begin
                         h_out <= 4'b1011;                             
                        end
             KEY_h_4:
                  begin
                         h_out <= 4'b0111;                             
                        end
    
             KEY_pressed:
               begin
                         l_in_reg <= l_in;
                       h_out_reg<= h_out;
                    end
             key_shake_2:  begin key_pressed_flag <= 1;   end
             default:;
            endcase
       end
     end
        
          
     
     reg      [3:0]      temp_key_val; 
     always @(posedge clk or negedge rst_n)
      begin
       if(!rst_n)
           temp_key_val <= 4'd0;
        else 
             begin
                if(key_pressed_flag) 
                  begin
                      case ({h_out_reg,l_in_reg})
                            8'b1110_1110 :  temp_key_val <= 4'd0;
                            8'b1110_1101 :    temp_key_val <= 4'd1;
                            8'b1110_1011 :    temp_key_val <= 4'd2;
                            8'b1110_0111 :    temp_key_val <= 4'd3;
                                
                            8'b1101_1110 :    temp_key_val <= 4'd4;
                            8'b1101_1101 :    temp_key_val <= 4'd5;
                            8'b1101_1011 :    temp_key_val <= 4'd6;
                            8'b1101_0111 :    temp_key_val <= 4'd7;
                                
                            8'b1011_1110 :    temp_key_val <= 4'd8;
                            8'b1011_1101 :    temp_key_val <= 4'd9;
                            8'b1011_1011 :    temp_key_val <= 4'd10;
                            8'b1011_0111 :    temp_key_val <= 4'd11;
    
                            8'b0111_1110 :    temp_key_val <= 4'd12;
                            8'b0111_1101 :    temp_key_val <= 4'd13;
                            8'b0111_1011 :    temp_key_val <= 4'd14;
                            8'b0111_0111 :    temp_key_val <= 4'd15;
                         
                        default: temp_key_val <= 4'd0;
                    endcase    
        end
       end
     end
     assign   key_val = ~temp_key_val;
     assign   key_val_flag =  ~key_pressed_flag;
     endmodule  
     
    View Code

    测试代码:

    module  testbench;
    
     reg             clk;          /* clk = 24M */
     reg             rst_n;
     reg   [3:0]     l_in;             //列输入,一般接上拉,为高电平
     
     wire            test_1;
     wire            test_2;
     
     wire  [3:0]     h_out;            //行输出信号,低有效 
     wire  [3:0]     key_val;          //按键值,输出   
     wire            key_val_flag;
    
    keyboard  u1(
                      .clk,
                                        .rst_n,
                                        
                                        .l_in,
                                        .h_out,
                                        
                                        .test_1,
                                        .test_2,
                                        
                                        .key_val,
                                        .key_val_flag
                                        );
            defparam  u1.    t_20ms = 399;                        
                                        
     parameter  tck = 100;
     parameter  t = 1000/tck;
     
     always 
         #(t/2)   clk = ~clk;
    
    
     task     key_test;
     input [3:0]   data_key;
      begin
            #(3*t)     l_in = data_key;
            #(5000*t) l_in = 4'b1111;
            #(2500*t);
            end
        endtask
        
        
    initial 
      begin
        clk = 0;
        rst_n = 0;
        l_in  = 4'd0;
        
        #(6*t)  rst_n = 1; 
        
        #(60*t);
        key_test(4'B1101); 
        key_test(4'B1011); 
     
      end
     
    endmodule 
    View Code

    仿真波形:

  • 相关阅读:
    1833: [ZJOI2010]count 数字计数——数位dp
    【模板】BZOJ 3685: 普通van Emde Boas树——Treap
    【模板】解决二分图匹配的强力算法——Hopcroft-Karp算法
    BZOJ 4516: [Sdoi2016]生成魔咒——后缀数组、并查集
    【模板】二分图匹配/一般图匹配——匈牙利算法/随机匈牙利算法
    【模板】BZOJ 1692:队列变换—后缀数组 Suffix Array
    BZOJ 4241: 历史研究——莫队 二叉堆
    【模板】BZOJ 3781: 小B的询问 莫队算法
    BZOJ 3656: 异或 (组合数取模 CRT)
    【模板】SPOJ FACT0 大数分解 miller-rabin & pollard-rho
  • 原文地址:https://www.cnblogs.com/fhyfhy/p/4390573.html
Copyright © 2011-2022 走看看