[笔记].驱动4x4矩阵键盘的思路.[Verilog]
0赞
发表于 2010/7/25 0:09:57
阅读(3471)
SCH
图1 4x4矩阵键盘的SCH(箭头表示输入输出方向)
如图1所示,将ROW[3:0]设为输入,COL[3:0]设为输出。如果没有任何键被按下,则ROW[3:0]一直被上拉为高电平。只有当有键被按下,且COL[3:0]中有低电平输出,ROW[3:0]中才有可能有低电平输入,也可说是被动地输入。
流程图
图2 流程图
HDL
001 |
module matrixKeyboard_drive( |
002 |
input i_clk, |
003 |
input i_rst_n, |
004 |
input [3:0] row, // 矩阵键盘 行 |
005 |
output reg [3:0] col, // 矩阵键盘 列 |
006 |
output reg [3:0] keyboard_val // 键盘值 |
007 |
); |
008 |
|
009 |
//++++++++++++++++++++++++++++++++++++++ |
010 |
// 分频部分 开始 |
011 |
//++++++++++++++++++++++++++++++++++++++ |
012 |
reg [19:0] cnt; // 计数子 |
013 |
|
014 |
always @ ( posedge i_clk, negedge i_rst_n) |
015 |
if (!i_rst_n) |
016 |
cnt <= 0; |
017 |
else |
018 |
cnt <= cnt + 1'b1 ; |
019 |
|
020 |
wire key_clk = cnt[19]; // (2^20/50M = 21)ms |
021 |
//-------------------------------------- |
022 |
// 分频部分 结束 |
023 |
//-------------------------------------- |
024 |
|
025 |
|
026 |
//++++++++++++++++++++++++++++++++++++++ |
027 |
// 状态机部分 开始 |
028 |
//++++++++++++++++++++++++++++++++++++++ |
029 |
// 状态数较少,独热码编码 |
030 |
parameter NO_KEY_PRESSED = 6'b000_001 ; // 没有按键按下 |
031 |
parameter SCAN_COL0 = 6'b000_010 ; // 扫描第0列 |
032 |
parameter SCAN_COL1 = 6'b000_100 ; // 扫描第1列 |
033 |
parameter SCAN_COL2 = 6'b001_000 ; // 扫描第2列 |
034 |
parameter SCAN_COL3 = 6'b010_000 ; // 扫描第3列 |
035 |
parameter KEY_PRESSED = 6'b100_000 ; // 有按键按下 |
036 |
|
037 |
reg [5:0] current_state, next_state; // 现态、次态 |
038 |
|
039 |
always @ ( posedge key_clk, negedge i_rst_n) |
040 |
if (!i_rst_n) |
041 |
current_state <= NO_KEY_PRESSED; |
042 |
else |
043 |
current_state <= next_state; |
044 |
|
045 |
// 根据条件转移状态 |
046 |
always @ * |
047 |
case (current_state) |
048 |
NO_KEY_PRESSED : // 没有按键按下 |
049 |
if (row != 4'hF ) |
050 |
next_state = SCAN_COL0; |
051 |
else |
052 |
next_state = NO_KEY_PRESSED; |
053 |
SCAN_COL0 : // 扫描第0列 |
054 |
if (row != 4'hF ) |
055 |
next_state = KEY_PRESSED; |
056 |
else |
057 |
next_state = SCAN_COL1; |
058 |
SCAN_COL1 : // 扫描第1列 |
059 |
if (row != 4'hF ) |
060 |
next_state = KEY_PRESSED; |
061 |
else |
062 |
next_state = SCAN_COL2; |
063 |
SCAN_COL2 : // 扫描第2列 |
064 |
if (row != 4'hF ) |
065 |
next_state = KEY_PRESSED; |
066 |
else |
067 |
next_state = SCAN_COL3; |
068 |
SCAN_COL3 : // 扫描第3列 |
069 |
if (row != 4'hF ) |
070 |
next_state = KEY_PRESSED; |
071 |
else |
072 |
next_state = NO_KEY_PRESSED; |
073 |
KEY_PRESSED : // 有按键按下 |
074 |
if (row != 4'hF ) |
075 |
next_state = KEY_PRESSED; |
076 |
else |
077 |
next_state = NO_KEY_PRESSED; |
078 |
endcase |
079 |
|
080 |
reg key_pressed_flag; // 键盘按下标志 |
081 |
reg [3:0] col_val, row_val; // 列值、行值 |
082 |
|
083 |
// 根据次态,给相应寄存器赋值 |
084 |
always @ ( posedge key_clk, negedge i_rst_n) |
085 |
if (!i_rst_n) |
086 |
begin |
087 |
col <= 4'h0 ; |
088 |
key_pressed_flag <= 0; |
089 |
end |
090 |
else |
091 |
case (next_state) |
092 |
NO_KEY_PRESSED : // 没有按键按下 |
093 |
begin |
094 |
col <= 4'h0 ; |
095 |
key_pressed_flag <= 0; // 清键盘按下标志 |
096 |
end |
097 |
SCAN_COL0 : // 扫描第0列 |
098 |
col <= 4'b1110 ; |
099 |
SCAN_COL1 : // 扫描第1列 |
100 |
col <= 4'b1101 ; |
101 |
SCAN_COL2 : // 扫描第2列 |
102 |
col <= 4'b1011 ; |
103 |
SCAN_COL3 : // 扫描第3列 |
104 |
col <= 4'b0111 ; |
105 |
KEY_PRESSED : // 有按键按下 |
106 |
begin |
107 |
col_val <= col; // 锁存列值 |
108 |
row_val <= row; // 锁存行值 |
109 |
key_pressed_flag <= 1; // 置键盘按下标志 |
110 |
end |
111 |
endcase |
112 |
//-------------------------------------- |
113 |
// 状态机部分 结束 |
114 |
//-------------------------------------- |
115 |
|
116 |
|
117 |
//++++++++++++++++++++++++++++++++++++++ |
118 |
// 扫描行列值部分 开始 |
119 |
//++++++++++++++++++++++++++++++++++++++ |
120 |
always @ ( posedge key_clk, negedge i_rst_n) |
121 |
if (!i_rst_n) |
122 |
keyboard_val <= 4'h0 ; |
123 |
else |
124 |
if (key_pressed_flag) |
125 |
case ({col_val, row_val}) |
126 |
8'b1110_1110 : keyboard_val <= 4'h0 ; |
127 |
8'b1110_1101 : keyboard_val <= 4'h4 ; |
128 |
8'b1110_1011 : keyboard_val <= 4'h8 ; |
129 |
8'b1110_0111 : keyboard_val <= 4'hC ; |
130 |
|
131 |
8'b1101_1110 : keyboard_val <= 4'h1 ; |
132 |
8'b1101_1101 : keyboard_val <= 4'h5 ; |
133 |
8'b1101_1011 : keyboard_val <= 4'h9 ; |
134 |
8'b1101_0111 : keyboard_val <= 4'hD ; |
135 |
|
136 |
8'b1011_1110 : keyboard_val <= 4'h2 ; |
137 |
8'b1011_1101 : keyboard_val <= 4'h6 ; |
138 |
8'b1011_1011 : keyboard_val <= 4'hA ; |
139 |
8'b1011_0111 : keyboard_val <= 4'hE ; |
140 |
|
141 |
8'b0111_1110 : keyboard_val <= 4'h3 ; |
142 |
8'b0111_1101 : keyboard_val <= 4'h7 ; |
143 |
8'b0111_1011 : keyboard_val <= 4'hB ; |
144 |
8'b0111_0111 : keyboard_val <= 4'hF ; |
145 |
endcase |
146 |
//-------------------------------------- |
147 |
// 扫描行列值部分 结束 |
148 |
//-------------------------------------- |
149 |
|
150 |
endmodule |