矩阵键盘的试验---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:
*******************************************************************************/

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 = 17‘d23;
  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  =  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_shake_1:  begin    end
         KEY_h_1:
              begin
                     h_out <= 4‘b0111;
                    end
         KEY_h_2:
              begin
                     h_out <= 4‘b1011;
                    end
         KEY_h_3:
              begin
                     h_out <= 4‘b1101;
                    end
         KEY_h_4:
              begin
                     h_out <= 4‘b1110;
                    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‘b0111_0111 :  temp_key_val <= 4‘d0;
                        8‘b0111_1011 :    temp_key_val <= 4‘d1;
                        8‘b0111_1101 :    temp_key_val <= 4‘d2;
                        8‘b0111_1110 :    temp_key_val <= 4‘d3;

                        8‘b1011_0111 :    temp_key_val <= 4‘d4;
                        8‘b1011_1011 :    temp_key_val <= 4‘d5;
                        8‘b1011_1101 :    temp_key_val <= 4‘d6;
                        8‘b1011_1110 :    temp_key_val <= 4‘d7;

                        8‘b1101_0111 :    temp_key_val <= 4‘d8;
                        8‘b1101_1011 :    temp_key_val <= 4‘d9;
                        8‘b1101_1101 :    temp_key_val <= 4‘d10;
                        8‘b1101_1110 :    temp_key_val <= 4‘d11;

                        8‘b1110_0111 :    temp_key_val <= 4‘d12;
                        8‘b1110_1011 :    temp_key_val <= 4‘d13;
                        8‘b1110_1101 :    temp_key_val <= 4‘d14;
                        8‘b1110_1110 :    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
 

测试代码:

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 = 4‘b1111;
        #(50*t);
        end
    endtask

initial
  begin
    clk = 0;
    rst_n = 0;
    l_in  = 4‘d0;

    #(6*t)  rst_n = 1; 

    key_test(4‘B1101);
    key_test(4‘B0111); 

  end

endmodule 

仿真波形:

时间: 2024-08-09 14:22:45

矩阵键盘的试验---verilog的相关文章

STM32 4x4矩阵键盘

可同时识别两个键值,并分别显示,用了自己的12864显示,有些注释的地方有乱码请忽略.基于STM32f103vct6. 主函数: #include "Rect_key.h" #include "12864.h" int main() { u16 keynum=0; delay_init(); lcd_gpio_init(); lcd_init(); Rect_key_Init(); lcd_6x8(0,0,"STM32 4x4 KEY Test :&quo

疑问----单片机矩阵键盘行列反转扫描法

学到矩阵键盘这一块对网上别人写的C代码有些疑问,希望有能看到的大牛帮助解答. 矩阵键盘和独立键盘原理图: 原理:对于图右侧的矩阵键盘,把P3口的低四位(P3.0 ~ P3.3)和高四位(P3.4 ~ P3.7)分别置1,只要有按键被按下,那么与之对应的P3口某一位将由高电平被拉低,两次分别测得了行值和列值即确定了哪一个按键被按下了. 比如:先把低四位赋高电平即 P3 = 0000_1111 假如 S15 被按下了,那么 P3.2 就被拉成低电平即 P3 = 0000_1011 ,此时再把高四位赋

矩阵键盘 数码管

开始时数码管不显示,顺序按下矩阵键盘后,在数码管上依次显示0~F,6个数码管同时静态显示. 数码管和矩阵键盘 首先关闭所有的数码管的段选不让数码管显示任何数字,然后位选中所有的数码管,接下来只需要选中所有的数码管,以后的操作的只需要送段选数据就行了,接着进入while()大循环不停的扫描键盘是否有被按下 #include<reg52.h> #define uchar unsigned char #define uint unsigned int sbit dula=P2^6; sbit wel

单片机入门-矩阵键盘控制数码管显示

任务简述:通过按下4X4矩阵键盘实现数码管对应显示数字 实现方式:通过行列分接法,可以节省使用单片机的I/O口,扫描矩阵键盘是否有按下,判断P2端口得到的值. protues 硬件系统 单片机晶振复位电路: 锁存器.上拉电阻: 4x4矩阵键盘: 代码实现: void key44scan(void)//键盘扫描函数 { uint t; P2=0xfe; t=P2; t=t&0xf0; if(t!=0xf0) { delay(); t=P2; switch(t) { case 0xee:keynum

51单片机第四弹---矩阵键盘

原理图: 原理: 和独立键盘相似 /******************************************************************************* * 实 验 名 : 矩阵键盘实验 * 使用的IO : 数码管使用P0 矩阵键盘使用P3 * 实验效果 : 显示独立键盘的按键值 * 注 意 : *******************************************************************************/

【转】 矩阵键盘的工作原理

在键盘中按键数量较多时,为了减少I/O口的占用,通常将按键排列成矩阵形式,在矩阵键盘中每条水平线和垂直线在交叉处不直接相连,而是通过一个按键相连接,这样在由N条水平线和M条垂直线最多可以有N *M 个按键,大大的减少了对于芯片I/O的占用. 键盘矩阵的按键识别方法 图1   矩阵键盘的结构 方法一 行扫描法 1.判断键盘中有无键按下 将全部行线P1.4-P1.7置低电平,当然P1.0-P1.3为高电平(或许芯片内部已经将这些引脚它上拉),然后检测列线的状态.只要有一列的电平为低,则表示键盘中有键

4x4矩阵键盘扫描

4x4矩阵键盘扫描 Windows 10 IoT Core 是微软针对物联网市场的一个重要产品,与以往的Windows版本不同,是为物联网设备专门设计的,硬件也不仅仅限于x86架构,同时可以在ARM架构上运行. 上一章我们讲了 Win10 IoT 如何对本地 IoT 设备内嵌 SQLite 数据库进行 CURD 操作 ,这章我们来学习如何使用 GPIO Pin 扫描4x4矩阵键盘按键状态.如果对安装部署过程还不熟悉可以参考前几篇文章,Raspberry安装 IoT系统及搭建开发环境(http:/

矩阵键盘扫描算法

函数的主体 unsigned char GetKey() { unsigned char i,j,k; static unsigned char backup[4][4]={ {1,1,1,1},{1,1,1,1},{1,1,1,1},{1,1,1,1} }; EA=1; TMOD=0x01;//设置T0为模式1 TH0=0xF8; TL0=0xCD; ET0=1;//使能T0中断 TR0=1;//启动T0 while(1) { for(i=0;i<4;i++)//循环检测4×4的矩阵按键 {

51单片机实现矩阵键盘行扫描

-------------------------------------------- 分类: 按结构原理分: 触点式开关按键 无触点开关按键 接入方式 独立式按键 矩阵式键盘 -------------------------------------------- 矩阵式键盘识别方法(行扫描法) 检测列线的状态: 列线Y4~Y7置高电平,行线Y0~Y3置低电平.只要有一列的电平为低,则表示键盘该列有一个或多个按键被按下.若所有列线全为高电平,则键盘中无按键按下. 判断闭合按键所在的位置: 行