码迷,mamicode.com
首页 > 其他好文 > 详细

矩阵键盘的试验---verilog

时间:2015-04-03 18:48:06      阅读:493      评论:0      收藏:0      [点我收藏+]

标签:

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

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

电路图:

技术分享

代码:

技术分享
/********************************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:
*******************************************************************************/
 
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,则可以跳过消抖*/
 
// localparam  t_20ms = 17‘d239999;
 localparam  t_20ms = 17d23;
  reg    [17: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  =  3d0;        /* 初始化 */
 localparam key_shake_1     =  3d1;        /* 消抖1 */
 localparam KEY_h_1         =  3d2;        /* 检测第一列 */
 localparam KEY_h_2         =  3d3;        /* 检测第二列 */
 localparam KEY_h_3         =  3d4;        /* 检测第三列 */ 
 localparam KEY_h_4         =  3d5;        /* 检测第四列 */
 localparam KEY_pressed     =  3d6;        /* 按键值输出*/
 localparam key_shake_2     =  3d7;        /* 消抖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 != 4hf)   next_state = key_shake_1;
                 else  next_state = NO_KEY_pressed;
           end
        key_shake_1:     
         begin
                        if(l_in != 4hf)   next_state = KEY_h_1;
                 else  next_state = NO_KEY_pressed;
           end
    KEY_h_1:
            begin
                        if(l_in != 4hf)   next_state = KEY_pressed;
                 else  next_state = KEY_h_2;
          end
        KEY_h_2:
            begin
                        if(l_in != 4hf)   next_state = KEY_pressed;
                 else  next_state = KEY_h_3;
          end
    KEY_h_3:
            begin
                        if(l_in != 4hf)   next_state = KEY_pressed;
                 else  next_state = KEY_h_4;
          end
    KEY_h_4:
            begin
                        if(l_in != 4hf)   next_state = KEY_pressed;
                 else  next_state = NO_KEY_pressed;
          end
   KEY_pressed:
          begin
                        if(l_in != 4hf)   next_state = key_shake_2;
                 else  next_state = NO_KEY_pressed;
          end
     key_shake_2:
          begin
                        if(l_in != 4hf)   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 <= 4d0;
            h_out_reg<= 4d0;
            h_out <= 4d0;
            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 <= 4d0;   
                    key_pressed_flag <= 0;
             end
//         key_shake_1:  begin    end
         KEY_h_1:
              begin
                     h_out <= 4b0111;                             
                    end
         KEY_h_2:
              begin
                     h_out <= 4b1011;                             
                    end
         KEY_h_3:
              begin
                     h_out <= 4b1101;                             
                    end
         KEY_h_4:
              begin
                     h_out <= 4b1110;                             
                    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 <= 4d0;
    else 
         begin
            if(key_pressed_flag) 
              begin
                  case ({h_out_reg,l_in_reg})
                        8b0111_0111 :  temp_key_val <= 4d0;
                        8b0111_1011 :    temp_key_val <= 4d1;
                        8b0111_1101 :    temp_key_val <= 4d2;
                        8b0111_1110 :    temp_key_val <= 4d3;
                            
                        8b1011_0111 :    temp_key_val <= 4d4;
                        8b1011_1011 :    temp_key_val <= 4d5;
                        8b1011_1101 :    temp_key_val <= 4d6;
                        8b1011_1110 :    temp_key_val <= 4d7;
                            
                        8b1101_0111 :    temp_key_val <= 4d8;
                        8b1101_1011 :    temp_key_val <= 4d9;
                        8b1101_1101 :    temp_key_val <= 4d10;
                        8b1101_1110 :    temp_key_val <= 4d11;

                        8b1110_0111 :    temp_key_val <= 4d12;
                        8b1110_1011 :    temp_key_val <= 4d13;
                        8b1110_1101 :    temp_key_val <= 4d14;
                        8b1110_1110 :    temp_key_val <= 4d15;
                     
                    default: temp_key_val <= 4d0;
                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
                                    );
 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;
        #(200*t) l_in = 4b1111;
        #(50*t);
        end
    endtask
    
    
initial 
  begin
    clk = 0;
    rst_n = 0;
    l_in  = 4d0;
    
    #(6*t)  rst_n = 1; 
    
    
    key_test(4B1101); 
    key_test(4B0111); 
 
  end
 
endmodule 
View Code

 

仿真波形:

技术分享

矩阵键盘的试验---verilog

标签:

原文地址:http://www.cnblogs.com/fhyfhy/p/4390573.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!