矩阵按键的试验---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 [:] 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的更多相关文章
- C51 矩阵按键 个人笔记
矩阵按键 电路 每个按键一端和同行一端相连(JP4的高4位),另一端和同列一端相连(JP4的低4位) 判断按键是否按下: 法一:逐行扫描 for(int i = 8 ; i>3 ; i-- ) ...
- 按键消抖-----verilog
实际系统中常用的按键大部分都是轻触式按键,如下图所示.该按键内部由一个弹簧片和两个固定触点组成,当弹簧片被按下,则两个固定触点接通,按键闭合.弹簧片松开,两个触点断开,按键也就断开了.根据这种按键的机 ...
- 【C51】单片机独立按键与矩阵按键
独立按键 首先既然是检测输入,对于当然要用到拉电阻,来检测引脚电平变化变化.51单片机中,除了P0口外,P2,P3,P4都是内置上拉电阻的准双向IO口,一般 的 51 P0引脚都外接了上拉电阻,当然也 ...
- AD按键-矩阵按键:
原理:利用数组分压+AD采集: 优点:一个IO口可以做成多个按键,节省IO口(矩阵键盘在>4时优点才能体现出来):可备用作为AD基准输入. 缺点:不能做成组合按键(或者电阻要精确选择):且离IO ...
- AD按键-矩阵按键-独立按键:
原理:利用数组分压+AD采集: 优点:一个IO口可以做成多个按键,节省IO口(矩阵键盘在>4时优点才能体现出来):可备用作为AD基准输入. 缺点:不能做成组合按键(或者电阻要精确选择):且离IO ...
- C51 原创电子琴 (蜂鸣器/计时器/中断/矩阵按键)
需求分析 用C51的16个矩阵按键当作两个八度的琴键 按下时发出相应音调的声音,静态数码管显示相应音符的数字. 为了解锁更多曲目,两个多的琴键设计成#4,显示时加上小数点 下图分别为1和#4的显示,其 ...
- 【.NET 与树莓派】矩阵按键
欢迎收看火星卫视,本期节目咱们严重探讨一下矩阵按键. 所谓矩阵按键,就是一个小键盘(其实一块PCB板),上面有几个 Key(开关),你不按下去的时候,电路是断开的,你按下去电路就会接通.至于说有多少个 ...
- ARDUINO入门按键通信试验
1.1按键实验 1.需要学习的知识: 1) Arduino 的输入口配置方法,配置函数的用法 通过pinMode()函数,可以将ADUINO的引脚配置(INPUT)输入模式 2) 搞懂什么是抖动 机械 ...
- SPI的通信试验 --verilog (从机-全双工)
SPI的 有关知识参考FPGA作为主机的通信实验. 本实验中FPGA作为从机通过SPI与MCU等通信的试验,可以在时钟上升沿接收数据并且在时钟下降沿发送数据,模仿全双工模式.接收的 数据作为地址,通过 ...
随机推荐
- MySQL 中 where id in (1,2,3,4,...) 的效率问题讨论
MySQL ACMAIN_CHM06-26 16:36 等级 84次回复 [求证&散分]MySQL 中 where id in (1,2,3,4,...) 的效率问题讨论 庆祝本月大版得 ...
- Java Socket 网络编程心跳设计概念
Java Socket 网络编程心跳设计概念 1.一般是用来判断对方(设备,进程或其它网元)是否正常动行,一 般采用定时发送简单的通讯包,如果在指定时间段内未收到对方响应,则判断对方已经当掉.用于 ...
- mysql字符串截取
mysql字符串截取 update zcat ) where lev1 is null; update zcat ) where lev2 is null; 函数: 1.从左开始截取字符串 left( ...
- PHP正则表达式基础入门
思维导图 介绍 正则表达式,大家在开发中应该是经常用到,现在很多开发语言都有正则表达式的应用,比如JavaScript.Java..Net.PHP 等,我今天就把我对正则表达式的理解跟大家唠唠,不当之 ...
- sh脚本学习之: sh脚本 、sed、awk
sh脚本 sh命令的批处理文件,支持更复杂的逻辑. Shell中的变量 参数 $0 当前脚本路径 $1....$n 脚本执行对应的第n个参数 条件判断 文件判断 test [op] path e存在 ...
- GNU make 升级
网上下载新版本的make文件后 在make目录下 ./configure make make install mv make /opt/mv_pro_5.0.0/montavista/common/b ...
- CocoStudio基础教程(4)骨骼动画的动态换肤
1.概述 游戏中人物的状态会发生改变,而这种改变通常要通过局部的变化来表现出来.比如获得一件装备后人物形象的改变,或者战斗中武器.防具的损坏等.这些变化的实现就要通过动态换肤来实现. 2.运行到程序 ...
- [转]uses-permission权限列表
android.permission.ACCESS_CHECKIN_PROPERTIES允许读写访问”properties”表在checkin数据库中,改值可以修改上传 android.permiss ...
- HNU 12845 Ballot Analyzing Device
题目链接:http://acm.hnu.cn/online/?action=problem&type=show&id=12845&courseid=270 解题报告:有m个认给 ...
- Can't connect to local MySQL Server throught socket '/var/run/mysqld/mysqld.sock'(2)
www.iwangzheng.com 由于之前调整了/etc/mysql/my.cnf试图修复数据库不能存中文的问题,这个问题没解决,以至于数据库连接不上了. tail -f /var/log/mys ...