安德鲁

[笔记].驱动4x4矩阵键盘的思路.[Verilog]

0
阅读(3471)

SCH

图1 4x4矩阵键盘的SCH(箭头表示输入输出方向)

如图1所示,将ROW[3:0]设为输入,COL[3:0]设为输出。如果没有任何键被按下,则ROW[3:0]一直被上拉为高电平。只有当有键被按下,且COL[3:0]中有低电平输出,ROW[3:0]中才有可能有低电平输入,也可说是被动地输入。

流程图

图2 流程图

HDL

001 modulematrixKeyboard_drive(
002 inputi_clk,
003 inputi_rst_n,
004 input[3:0] row,// 矩阵键盘 行
005 outputreg[3:0] col,// 矩阵键盘 列
006 outputreg[3:0] keyboard_val// 键盘值
007 );
008
009 //++++++++++++++++++++++++++++++++++++++
010 // 分频部分 开始
011 //++++++++++++++++++++++++++++++++++++++
012 reg[19:0] cnt;// 计数子
013
014 always@ (posedgei_clk,negedgei_rst_n)
015 if(!i_rst_n)
016 cnt <= 0;
017 else
018 cnt <= cnt +1'b1;
019
020 wirekey_clk = cnt[19];// (2^20/50M = 21)ms
021 //--------------------------------------
022 // 分频部分 结束
023 //--------------------------------------
024
025
026 //++++++++++++++++++++++++++++++++++++++
027 // 状态机部分 开始
028 //++++++++++++++++++++++++++++++++++++++
029 // 状态数较少,独热码编码
030 parameterNO_KEY_PRESSED =6'b000_001;// 没有按键按下
031 parameterSCAN_COL0 =6'b000_010;// 扫描第0列
032 parameterSCAN_COL1 =6'b000_100;// 扫描第1列
033 parameterSCAN_COL2 =6'b001_000;// 扫描第2列
034 parameterSCAN_COL3 =6'b010_000;// 扫描第3列
035 parameterKEY_PRESSED =6'b100_000;// 有按键按下
036
037 reg[5:0] current_state, next_state;// 现态、次态
038
039 always@ (posedgekey_clk,negedgei_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 regkey_pressed_flag;// 键盘按下标志
081 reg[3:0] col_val, row_val;// 列值、行值
082
083 // 根据次态,给相应寄存器赋值
084 always@ (posedgekey_clk,negedgei_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@ (posedgekey_clk,negedgei_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
Baidu
map