矩阵键盘.[Verilog]
新近写的,水平有限,欢迎拍砖。http://cache.amobbs.com/bbs_upload782111/files_26/ourdev_534322.png
(原文件名:矩阵键盘.png)
module matrixKeyboard_drive(
input i_clk,
input i_rst_n,
input row, // 矩阵键盘 行
output reg col, // 矩阵键盘 列
output reg keyboard_val // 键盘值
);
//++++++++++++++++++++++++++++++++++++++
// 分频部分 开始
//++++++++++++++++++++++++++++++++++++++
reg cnt; // 计数子
always @ (posedge i_clk, negedge i_rst_n)
if (!i_rst_n)
cnt <= 0;
else
cnt <= cnt + 1'b1;
wire key_clk = cnt; // (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 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 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
http://cache.amobbs.com/bbs_upload782111/files_26/ourdev_534321.jpg
(原文件名:current_state.jpg) sofa,good! 很好,要学习。 顶下 顶啊 顶!!艾米电子!! good,正需要呢! 法规和加快 ./bbs_upload/files_31/ourdev_570182.png 请教
列输出的脚是否要设为开漏型,如何设?
如果列是推挽输出型,同时按下多个键可能会有冲突,相当于列输出1和列输出0的线短接在一起 mark 回复【10楼】shinehjx
-----------------------------------------------------------------------
暂时没有考虑,不好意思。 always @ (posedge i_clk, negedge i_rst_n)
if (!i_rst_n)
cnt <= 0;
else
cnt <= cnt + 1'b1;
wire key_clk = cnt; // (2^20/50M = 21)ms
tear086 .COM 缺氧 ,这里怎么会是21ms呢??应该是(2^19/50M = 10)ms 吧? 写的不错,10楼提的问题真是透彻 回复【13楼】STM_FPGA
-----------------------------------------------------------------------
您再好好想想。 回复【15楼】tear086 .COM 缺氧
--------------------------------------------------------
恩,对。粗心啦! 顶一个 always @ *
是什么意思啊?
每次执行都是列先输出,再行输入的么?这个时序能够保证么? 正要用到,非常感谢 10楼提的问题真是透彻 我觉得这个程序有问题,当行值为2时,进入第0列扫描时,就判断当前值是第2行第0列的值被按下了吗 mark 这个怎样与12864的液晶显示连在一起啊弄了好就了都没弄出来 mark mark 学习 正好要用到,可以参考 good参考 哈哈哈哈,都是没有消抖的,哈哈哈哈哈 mark FPGA开漏输出怎么设置呢?怎么设置上拉输入?这样就可以翻转扫描矩阵键盘了。
页:
[1]