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

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

电路图:

代码

/********************************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 [:] l_in; //列输入,一般接上拉,为高电平 output test_1;
output test_2; output [:] h_out; //行输出信号,低有效
output [:] key_val; //按键值,输出
output key_val_flag; wire [:] key_val;
reg test_1;
reg test_2;
//*************************************
/* 分频Ƶ*20ms,用于消抖 .状态机直接用clk_20ms,则可以跳过消抖*/ // `define CLK_24M
`define CLK_20M `ifdef CLK_24M
parameter t_20ms = 'd479999;
`endif `ifdef CLK_20M
parameter t_20ms = 'd399999;
`endif reg [:] 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 = 'd0; /* 初始化 */
localparam key_shake_1 = 'd1; /* 消抖1 */
localparam KEY_h_1 = 'd2; /* 检测第一列 */
localparam KEY_h_2 = 'd3; /* 检测第二列 */
localparam KEY_h_3 = 'd4; /* 检测第三列 */
localparam KEY_h_4 = 'd5; /* 检测第四列 */
localparam KEY_pressed = 'd6; /* 按键值输出*/
localparam key_shake_2 = 'd7; /* 消抖2 */ /* 3-1 */
reg [:] current_state;
reg [:] next_state;
reg key_pressed_flag;
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
current_state <= ;
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 != 'hf) next_state = key_shake_1;
else next_state = NO_KEY_pressed;
end
key_shake_1:
begin
if(l_in != 'hf) next_state = KEY_h_1;
else next_state = NO_KEY_pressed;
end
KEY_h_1:
begin
if(l_in != 'hf) next_state = KEY_pressed;
else next_state = KEY_h_2;
end
KEY_h_2:
begin
if(l_in != 'hf) next_state = KEY_pressed;
else next_state = KEY_h_3;
end
KEY_h_3:
begin
if(l_in != 'hf) next_state = KEY_pressed;
else next_state = KEY_h_4;
end
KEY_h_4:
begin
if(l_in != 'hf) next_state = KEY_pressed;
else next_state = NO_KEY_pressed;
end
KEY_pressed:
begin
if(l_in != 'hf) next_state = key_shake_2;
else next_state = NO_KEY_pressed;
end
key_shake_2:
begin
if(l_in != 'hf) next_state = key_shake_2;
else next_state = NO_KEY_pressed;
end
default:;
endcase
end /* 3-3 */ reg [:] l_in_reg;
reg [:] h_out_reg;
reg [:] h_out;
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
l_in_reg <= 'd0;
h_out_reg<= 'd0;
h_out <= 'd0;
key_pressed_flag <= ;
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 <= 'd0;
key_pressed_flag <= ;
end
KEY_h_1:
begin
h_out <= 'b1110;
end
KEY_h_2:
begin
h_out <= 'b1101;
end
KEY_h_3:
begin
h_out <= 'b1011;
end
KEY_h_4:
begin
h_out <= 'b0111;
end KEY_pressed:
begin
l_in_reg <= l_in;
h_out_reg<= h_out;
end
key_shake_2: begin key_pressed_flag <= ; end
default:;
endcase
end
end reg [:] temp_key_val;
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
temp_key_val <= 'd0;
else
begin
if(key_pressed_flag)
begin
case ({h_out_reg,l_in_reg})
'b1110_1110 : temp_key_val <= 4'd0;
'b1110_1101 : temp_key_val <= 4'd1;
'b1110_1011 : temp_key_val <= 4'd2;
'b1110_0111 : temp_key_val <= 4'd3; 'b1101_1110 : temp_key_val <= 4'd4;
'b1101_1101 : temp_key_val <= 4'd5;
'b1101_1011 : temp_key_val <= 4'd6;
'b1101_0111 : temp_key_val <= 4'd7; 'b1011_1110 : temp_key_val <= 4'd8;
'b1011_1101 : temp_key_val <= 4'd9;
'b1011_1011 : temp_key_val <= 4'd10;
'b1011_0111 : temp_key_val <= 4'd11; 'b0111_1110 : temp_key_val <= 4'd12;
'b0111_1101 : temp_key_val <= 4'd13;
'b0111_1011 : temp_key_val <= 4'd14;
'b0111_0111 : temp_key_val <= 4'd15; default: temp_key_val <= '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 [:] l_in; //列输入,一般接上拉,为高电平 wire test_1;
wire test_2; wire [:] h_out; //行输出信号,低有效
wire [:] 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 = ; parameter tck = ;
parameter t = /tck; always
#(t/) clk = ~clk; task key_test;
input [:] data_key;
begin
#(*t) l_in = data_key;
#(*t) l_in = 'b1111;
#(*t);
end
endtask initial
begin
clk = ;
rst_n = ;
l_in = 'd0; #(*t) rst_n = ; #(*t);
key_test('B1101);
key_test('B1011); end endmodule

仿真波形:

矩阵按键的试验---verilog的更多相关文章

  1. C51 矩阵按键 个人笔记

    矩阵按键 电路 每个按键一端和同行一端相连(JP4的高4位),另一端和同列一端相连(JP4的低4位) 判断按键是否按下: 法一:逐行扫描 for(int i = 8 ; i>3 ; i-- ) ...

  2. 按键消抖-----verilog

    实际系统中常用的按键大部分都是轻触式按键,如下图所示.该按键内部由一个弹簧片和两个固定触点组成,当弹簧片被按下,则两个固定触点接通,按键闭合.弹簧片松开,两个触点断开,按键也就断开了.根据这种按键的机 ...

  3. 【C51】单片机独立按键与矩阵按键

    独立按键 首先既然是检测输入,对于当然要用到拉电阻,来检测引脚电平变化变化.51单片机中,除了P0口外,P2,P3,P4都是内置上拉电阻的准双向IO口,一般 的 51 P0引脚都外接了上拉电阻,当然也 ...

  4. AD按键-矩阵按键:

    原理:利用数组分压+AD采集: 优点:一个IO口可以做成多个按键,节省IO口(矩阵键盘在>4时优点才能体现出来):可备用作为AD基准输入. 缺点:不能做成组合按键(或者电阻要精确选择):且离IO ...

  5. AD按键-矩阵按键-独立按键:

    原理:利用数组分压+AD采集: 优点:一个IO口可以做成多个按键,节省IO口(矩阵键盘在>4时优点才能体现出来):可备用作为AD基准输入. 缺点:不能做成组合按键(或者电阻要精确选择):且离IO ...

  6. C51 原创电子琴 (蜂鸣器/计时器/中断/矩阵按键)

    需求分析 用C51的16个矩阵按键当作两个八度的琴键 按下时发出相应音调的声音,静态数码管显示相应音符的数字. 为了解锁更多曲目,两个多的琴键设计成#4,显示时加上小数点 下图分别为1和#4的显示,其 ...

  7. 【.NET 与树莓派】矩阵按键

    欢迎收看火星卫视,本期节目咱们严重探讨一下矩阵按键. 所谓矩阵按键,就是一个小键盘(其实一块PCB板),上面有几个 Key(开关),你不按下去的时候,电路是断开的,你按下去电路就会接通.至于说有多少个 ...

  8. ARDUINO入门按键通信试验

    1.1按键实验 1.需要学习的知识: 1) Arduino 的输入口配置方法,配置函数的用法 通过pinMode()函数,可以将ADUINO的引脚配置(INPUT)输入模式 2) 搞懂什么是抖动 机械 ...

  9. SPI的通信试验 --verilog (从机-全双工)

    SPI的 有关知识参考FPGA作为主机的通信实验. 本实验中FPGA作为从机通过SPI与MCU等通信的试验,可以在时钟上升沿接收数据并且在时钟下降沿发送数据,模仿全双工模式.接收的 数据作为地址,通过 ...

随机推荐

  1. servlet 中 web.xml

    <servlet> <servlet-mapping> 他们之间的关系可以使一对一,也可是一对多的关系. <servlet> <servlet-name> ...

  2. IOS基础之 (九) Foundation框架

    一NSNumber 类型转换 NSNumber 把基本数据类型包装成一个对象类型.NSNumber之所以可以(只能)包装基本数据类型,是因为继承了NSValue. @20 等价于 [NSNumber ...

  3. 嵌入式实时操作系统μCOS原理与实践任务控制与时间的解析

    /*************************************************************************************************** ...

  4. MyEclipse2014中SVN的使用方法

    MyEclipse中的SVN操作手册 1.导入项目 点击工具栏上的[File-Import],进入下图 (如果你的对话框中没有SVN这一条目,可能是因为你没有安装SVN插件,请安装完成后,在看这篇博客 ...

  5. 本地与在线图片转Base64及图片预览

    查看效果:http://sandbox.runjs.cn/show/tgvbo9nq 本地图片转Base64(从而可以预览图片): function localImgLoad() { var src ...

  6. ALTER 语句修改数据表

    1.修改数据表名:alter table 表名 rename 新表名; 2.修改列名: alter table 表名 change 列名 新列名(可以与旧的一样) 类型 默认值; 3.修改类型: al ...

  7. [Asp.Net]状态管理(Session、Application、Cache)

    上篇博文介绍了在客户端状态管理的两种方式:http://www.cnblogs.com/wolf-sun/p/3329773.html.除了在客户端上保存状态外,还可以在服务器上保存状态.使用客户端的 ...

  8. 保存知乎收藏夹功能的NodeJS版本

    前两天发现知乎收藏夹中的答案正在不断减少..看来需要保存一下了,但之前别人的方式是用chrome插件(浏览器无法自动保存本地文件)+wget前后端配合来完成这个工作的,而且还有一些缺点(比如保存的ht ...

  9. LDA(Linear discriminate analysis)线性判别分析

    LDA 线性判别分析与Fisher算法完全不同 LDA是基于最小错误贝叶斯决策规则的. 在EMG肌电信号分析中,... 未完待续:.....

  10. 基于Redis的短链接设计思路

    [Markdown阅读][1] 今天上班的时候收到一个需要短链接的需求,之前的做法都是使用了新浪的短链接API(https://api.weibo.com/2/short_url/shorten.js ...