矩阵按键的试验---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等通信的试验,可以在时钟上升沿接收数据并且在时钟下降沿发送数据,模仿全双工模式.接收的 数据作为地址,通过 ...
随机推荐
- Laravel5.1 启动详解
借鉴: Laravel所有请求的入口文件是:/public/index.php,代码如下 <?php /*|------------------------------------------- ...
- Java_观察者模式(Observable和Observer)
http://blog.csdn.net/tianjf0514/article/details/7475164/ 一.观察者模式介绍 在Java中通过Observable类和Observer接口实现了 ...
- javascript面向对象方式,调用属性和方法
1.定义一个Person类,其中的属性和方法如果想对外开放,需要使用this,如: var Person=function(name,age,sex){ var psex='Boy'; if(sex) ...
- Idea 添加lib文件夹,并添加至项目Libary
在WEB-INF文件夹下新建lib文件夹,在lib文件夹上右键选择Add as Libary...,然后填写library名称,选择作用级别,选择作用项目,OK 注意:lib文件夹下需要有jar包后才 ...
- Hibernate动态更新
Hibernate一级缓存: Hibernate有一级和二级缓存.一级缓存就是Session. 在Hibernate启动的时候,SessionFactory解析映射文件的时候,会根据映射文件中的字段生 ...
- gcc/g++ 参数
-static 此选项将禁止使用动态库,所以,编译出来的东西,一般都很大,也不需要什么 动态连接库,就可以运行. -share 此选项将尽量使用动态库,所以生成文件比较小,但是需要系统由动态库.
- vm虚拟机自定义安装centOS找不到网卡
问题:自定义简化安装后执行ifconfig无法找到eth0网卡 1.查看eth0网络配置: [root@minion1 ~]# cat /etc/sysconfig/network-scripts/i ...
- iOS多线程介绍
一.线程概述 有些程序是一条直线,起点到终点:有些程序是一个圆,不断循环,直到将它切断.直线的如简单的Hello World,运行打印完,它的生命周期便结束了,像昙花一现那样:圆如操作系统,一直运行直 ...
- jar包与lib包的区别
jar包是编译时使用,假如编译出错代码没问题一定是jar包的问题,lib是运行时使用,比如程序启动后出错了但是编译没有问题,就可能是lib出错了,不会是jar包的问题.
- 微信内置浏览器的 User Agent的判断
如何判断微信内置浏览器,首先需要获取微信内置浏览器的User Agent,经过在 iPhone 上微信的浏览器的检测,它的 User Agent 是: Mozilla/5.0 (iPhone; CPU ...