搜索
bottom↓
回复: 31

矩阵键盘.[Verilog]

[复制链接]

出0入0汤圆

发表于 2010-2-20 00:21:33 | 显示全部楼层 |阅读模式
新近写的,水平有限,欢迎拍砖。


(原文件名:矩阵键盘.png)


module matrixKeyboard_drive(
  input            i_clk,
  input            i_rst_n,
  input      [3:0] row,                 // 矩阵键盘 行
  output reg [3:0] col,                 // 矩阵键盘 列
  output reg [3:0] keyboard_val         // 键盘值     
);

//++++++++++++++++++++++++++++++++++++++
// 分频部分 开始
//++++++++++++++++++++++++++++++++++++++
reg [19:0] cnt;                         // 计数子

always @ (posedge i_clk, negedge i_rst_n)
  if (!i_rst_n)
    cnt <= 0;
  else
    cnt <= cnt + 1'b1;

wire key_clk = cnt[19];                // (2^20/50M = 21)ms
//--------------------------------------
// 分频部分 结束
//--------------------------------------


//++++++++++++++++++++++++++++++++++++++
// 状态机部分 开始
//++++++++++++++++++++++++++++++++++++++
// 状态数较少,独热码编码
parameter NO_KEY_PRESSED = 6'b000_001;  // 没有按键按下  
parameter SCAN_COL0      = 6'b000_010;  // 扫描第0列
parameter SCAN_COL1      = 6'b000_100;  // 扫描第1列
parameter SCAN_COL2      = 6'b001_000;  // 扫描第2列
parameter SCAN_COL3      = 6'b010_000;  // 扫描第3列
parameter KEY_PRESSED    = 6'b100_000;  // 有按键按下

reg [5:0] current_state, next_state;    // 现态、次态

always @ (posedge key_clk, negedge i_rst_n)
  if (!i_rst_n)
    current_state <= NO_KEY_PRESSED;
  else
    current_state <= next_state;

// 根据条件转移状态
always @ *
  case (current_state)
    NO_KEY_PRESSED :                    // 没有按键按下
        if (row != 4'hF)
          next_state = SCAN_COL0;
        else
          next_state = NO_KEY_PRESSED;
    SCAN_COL0 :                         // 扫描第0列
        if (row != 4'hF)
          next_state = KEY_PRESSED;
        else
          next_state = SCAN_COL1;
    SCAN_COL1 :                         // 扫描第1列
        if (row != 4'hF)
          next_state = KEY_PRESSED;
        else
          next_state = SCAN_COL2;   
    SCAN_COL2 :                         // 扫描第2列
        if (row != 4'hF)
          next_state = KEY_PRESSED;
        else
          next_state = SCAN_COL3;
    SCAN_COL3 :                         // 扫描第3列
        if (row != 4'hF)
          next_state = KEY_PRESSED;
        else
          next_state = NO_KEY_PRESSED;
    KEY_PRESSED :                       // 有按键按下
        if (row != 4'hF)
          next_state = KEY_PRESSED;
        else
          next_state = NO_KEY_PRESSED;                     
  endcase

reg       key_pressed_flag;             // 键盘按下标志
reg [3:0] col_val, row_val;             // 列值、行值

// 根据次态,给相应寄存器赋值
always @ (posedge key_clk, negedge i_rst_n)
  if (!i_rst_n)
  begin
    col              <= 4'h0;
    key_pressed_flag <=    0;
  end
  else
    case (next_state)
      NO_KEY_PRESSED :                  // 没有按键按下
      begin
        col              <= 4'h0;
        key_pressed_flag <=    0;       // 清键盘按下标志
      end
      SCAN_COL0 :                       // 扫描第0列
        col <= 4'b1110;
      SCAN_COL1 :                       // 扫描第1列
        col <= 4'b1101;
      SCAN_COL2 :                       // 扫描第2列
        col <= 4'b1011;
      SCAN_COL3 :                       // 扫描第3列
        col <= 4'b0111;
      KEY_PRESSED :                     // 有按键按下
      begin
        col_val          <= col;        // 锁存列值
        row_val          <= row;        // 锁存行值
        key_pressed_flag <= 1;          // 置键盘按下标志  
      end
    endcase
//--------------------------------------
// 状态机部分 结束
//--------------------------------------


   
//++++++++++++++++++++++++++++++++++++++
// 扫描行列值部分 开始
//++++++++++++++++++++++++++++++++++++++
always @ (posedge key_clk, negedge i_rst_n)
  if (!i_rst_n)
    keyboard_val <= 4'h0;
  else
    if (key_pressed_flag)
      case ({col_val, row_val})
        8'b1110_1110 : keyboard_val <= 4'h0;
        8'b1110_1101 : keyboard_val <= 4'h4;
        8'b1110_1011 : keyboard_val <= 4'h8;
        8'b1110_0111 : keyboard_val <= 4'hC;
        
        8'b1101_1110 : keyboard_val <= 4'h1;
        8'b1101_1101 : keyboard_val <= 4'h5;
        8'b1101_1011 : keyboard_val <= 4'h9;
        8'b1101_0111 : keyboard_val <= 4'hD;
        
        8'b1011_1110 : keyboard_val <= 4'h2;
        8'b1011_1101 : keyboard_val <= 4'h6;
        8'b1011_1011 : keyboard_val <= 4'hA;
        8'b1011_0111 : keyboard_val <= 4'hE;
        
        8'b0111_1110 : keyboard_val <= 4'h3;
        8'b0111_1101 : keyboard_val <= 4'h7;
        8'b0111_1011 : keyboard_val <= 4'hB;
        8'b0111_0111 : keyboard_val <= 4'hF;        
      endcase
//--------------------------------------
//  扫描行列值部分 结束
//--------------------------------------
      
endmodule


(原文件名:current_state.jpg)

阿莫论坛20周年了!感谢大家的支持与爱护!!

知道什么是神吗?其实神本来也是人,只不过神做了人做不到的事情 所以才成了神。 (头文字D, 杜汶泽)

出0入143汤圆

发表于 2010-2-20 01:38:03 | 显示全部楼层
sofa,good!

出0入0汤圆

发表于 2010-2-20 11:46:30 | 显示全部楼层
很好,要学习。

出0入0汤圆

发表于 2010-2-20 16:56:53 | 显示全部楼层
顶下

出0入0汤圆

发表于 2010-2-27 10:49:06 | 显示全部楼层
顶啊

出0入0汤圆

发表于 2010-2-27 11:10:42 | 显示全部楼层
顶!!艾米电子!!

出0入0汤圆

发表于 2010-3-5 13:42:38 | 显示全部楼层
good,正需要呢!

出0入0汤圆

发表于 2010-5-14 23:37:34 | 显示全部楼层
法规和加快

出0入0汤圆

 楼主| 发表于 2010-7-23 12:32:58 | 显示全部楼层

出0入0汤圆

发表于 2010-7-24 08:02:06 | 显示全部楼层
请教
列输出的脚是否要设为开漏型,如何设?
如果列是推挽输出型,同时按下多个键可能会有冲突,相当于列输出1和列输出0的线短接在一起

出0入0汤圆

发表于 2010-7-24 10:02:20 | 显示全部楼层
mark

出0入0汤圆

 楼主| 发表于 2010-7-24 11:28:17 | 显示全部楼层
回复【10楼】shinehjx  
-----------------------------------------------------------------------

暂时没有考虑,不好意思。

出0入0汤圆

发表于 2010-8-3 11:23:10 | 显示全部楼层
always @ (posedge i_clk, negedge i_rst_n)
  if (!i_rst_n)
    cnt <= 0;
  else
    cnt <= cnt + 1'b1;

wire key_clk = cnt[19];                // (2^20/50M = 21)ms  

tear086 .COM 缺氧 ,这里怎么会是21ms呢??应该是(2^19/50M = 10)ms 吧?

出0入0汤圆

发表于 2010-8-3 13:03:59 | 显示全部楼层
写的不错,10楼提的问题真是透彻

出0入0汤圆

 楼主| 发表于 2010-8-3 18:13:43 | 显示全部楼层
回复【13楼】STM_FPGA  
-----------------------------------------------------------------------

您再好好想想。

出0入0汤圆

发表于 2010-8-3 19:45:36 | 显示全部楼层
回复【15楼】tear086 .COM 缺氧
--------------------------------------------------------
恩,对。粗心啦!

出0入0汤圆

发表于 2010-9-29 17:05:29 | 显示全部楼层
顶一个

出0入0汤圆

发表于 2010-12-16 21:08:38 | 显示全部楼层
always @ *
是什么意思啊?
每次执行都是列先输出,再行输入的么?这个时序能够保证么?

出0入300汤圆

发表于 2010-12-17 00:10:14 | 显示全部楼层
正要用到,非常感谢

出0入0汤圆

发表于 2010-12-17 00:19:07 | 显示全部楼层
10楼提的问题真是透彻

出0入0汤圆

发表于 2010-12-22 16:27:42 | 显示全部楼层
我觉得这个程序有问题,当行值为2时,进入第0列扫描时,就判断当前值是第2行第0列的值被按下了吗

出0入0汤圆

发表于 2010-12-23 21:27:10 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-12-28 19:05:36 | 显示全部楼层
这个怎样与12864的液晶显示连在一起啊  弄了好就了都没弄出来

出0入0汤圆

发表于 2010-12-29 21:56:12 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-1-7 10:47:21 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-2-18 21:56:41 | 显示全部楼层
学习

出0入0汤圆

发表于 2011-2-24 23:47:51 | 显示全部楼层
正好要用到,可以参考

出0入0汤圆

发表于 2011-7-3 23:42:59 | 显示全部楼层
good  参考 

出0入0汤圆

发表于 2011-10-27 19:35:59 | 显示全部楼层
哈哈哈哈,都是没有消抖的,哈哈哈哈哈

出0入0汤圆

发表于 2011-12-14 16:52:32 | 显示全部楼层
mark

出0入0汤圆

发表于 2013-4-19 00:20:37 | 显示全部楼层
FPGA开漏输出怎么设置呢?怎么设置上拉输入?这样就可以翻转扫描矩阵键盘了。
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片。注意:要连续压缩2次才能满足要求!!】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-7-24 07:17

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表