电路原理图如下:其中ROW[3:0]为处理器输入,COL[3:0]为处理器输出
矩阵键盘实验代码一共包括四个部分:1.按键检测(matrix_key_scan) 2.读取数据(led_input_display) 3.74HC595显示(led_74595_driver) 4.顶层模块(KEY_Scan_Design)。整体RTL视图如下:
按键检测部分(matrix_key_scan)检测原理如下:
按键检测(matrix_key_scan)状态机如下:
1 //===================================================================================================================================================================================== 2 `timescale 1ns/1ns 3 module matrix_key_scan 4 ( 5 //global clk 6 input clk, 7 input rst_n, 8 9 //matrix keyboard interface 10 input [3:0] row_data, 11 output reg [3:0] col_data, 12 13 //user interface 14 output reg key_flag, 15 output reg [3:0] key_value 16 ); 17 18 localparam SCAN_IDLE = 3‘d0; 19 localparam SCAN_JITTER1 = 3‘d1; 20 localparam SCAN_COL1 = 3‘d2; 21 localparam SCAN_COL2 = 3‘d3; 22 localparam SCAN_COL3 = 3‘d4; 23 localparam SCAN_COL4 = 3‘d5; 24 localparam SCAN_READ = 3‘d6; 25 localparam SCAN_JITTER2 = 3‘d7; 26 27 //------------------------------------------------- 28 //delay for 20ms 29 localparam DELAY_TOP = 1000_000; 30 reg [19:0] delay_cnt; 31 always@(posedge clk or negedge rst_n) 32 begin 33 if(!rst_n) 34 delay_cnt <= 0; 35 else if(delay_cnt < DELAY_TOP - 1‘b1) 36 delay_cnt <= delay_cnt + 1‘b1; 37 else 38 delay_cnt <= 0; 39 end 40 wire delay_done = (delay_cnt == DELAY_TOP - 1‘b1) ? 1‘b1 : 1‘b0; 41 42 //----------------------------------------------------- 43 //FSM always1 44 reg [2:0] current_state; 45 reg [2:0] next_state; 46 always@(posedge clk or negedge rst_n) 47 begin 48 if(!rst_n) 49 current_state <= SCAN_IDLE; 50 else if(delay_done) 51 current_state <= next_state; 52 else 53 current_state <= current_state; 54 end 55 56 //--------------------------------------------------- 57 //FSM always2 58 always@(*) 59 begin 60 next_state = SCAN_IDLE; //state initialization 61 case(current_state) 62 SCAN_IDLE : 63 if(row_data != 4‘b1111) next_state = SCAN_JITTER1; 64 else next_state = SCAN_IDLE; 65 SCAN_JITTER1 : 66 if(row_data != 4‘b1111) next_state = SCAN_COL1; 67 else next_state = SCAN_IDLE; 68 SCAN_COL1 : 69 if(row_data != 4‘b1111) next_state = SCAN_READ; 70 else next_state = SCAN_COL2; 71 SCAN_COL2 : 72 if(row_data != 4‘b1111) next_state = SCAN_READ; 73 else next_state = SCAN_COL3; 74 SCAN_COL3 : 75 if(row_data != 4‘b1111) next_state = SCAN_READ; 76 else next_state = SCAN_COL4; 77 SCAN_COL4 : 78 if(row_data != 4‘b1111) next_state = SCAN_READ; 79 else next_state = SCAN_IDLE; 80 SCAN_READ : 81 if(row_data != 4‘b1111) next_state = SCAN_JITTER2; 82 else next_state = SCAN_IDLE; 83 SCAN_JITTER2 : 84 if(row_data != 4‘b1111) next_state = SCAN_JITTER2; 85 else next_state = SCAN_IDLE; 86 endcase 87 end 88 89 //------------------------------------------------ 90 //FSM always3 91 reg [3:0] col_data_r; 92 reg [3:0] row_data_r; 93 always@(posedge clk or negedge rst_n) 94 begin 95 if(!rst_n) 96 begin 97 col_data <= 4‘b0000; 98 col_data_r <= 4‘b0000; 99 row_data_r <= 4‘b0000; 100 end 101 else if(delay_done) 102 begin 103 case(next_state) 104 SCAN_IDLE : 105 begin 106 col_data <= 4‘b0000; 107 col_data_r <= col_data_r; 108 row_data_r <= row_data_r; 109 end 110 //SCAN_JITTER1 : 111 SCAN_COL1 : col_data <= 4‘b0111; 112 SCAN_COL2 : col_data <= 4‘b1011; 113 SCAN_COL3 : col_data <= 4‘b1101; 114 SCAN_COL4 : col_data <= 4‘b1110; 115 SCAN_READ : begin 116 col_data_r <= col_data; 117 row_data_r <= row_data; 118 end 119 120 //SCAN_JITTER2 : 121 default : ; 122 endcase 123 end 124 else 125 begin 126 col_data <= col_data; 127 col_data_r <= col_data_r; 128 row_data_r <= row_data_r; 129 end 130 end 131 132 //------------------------------------- 133 wire key_trigger = (current_state == SCAN_JITTER2 && next_state == SCAN_IDLE && delay_done == 1‘b1) ? 1‘b1 : 1‘b0; 134 //------------------------------------- 135 //decode the matrix keyboard 136 always@(posedge clk or negedge rst_n) 137 begin 138 if(!rst_n) 139 key_value <= 0; 140 else if(key_trigger == 1‘b1) 141 begin 142 case({row_data,col_data}) 143 8‘b0111_0111 : key_value <= 4‘h0; 144 8‘b0111_1011 : key_value <= 4‘h1; 145 8‘b0111_1101 : key_value <= 4‘h2; 146 8‘b0111_1110 : key_value <= 4‘h3; 147 148 8‘b1011_0111 : key_value <= 4‘h4; 149 8‘b1011_1011 : key_value <= 4‘h5; 150 8‘b1011_1101 : key_value <= 4‘h6; 151 8‘b1011_1110 : key_value <= 4‘h7; 152 153 8‘b1101_0111 : key_value <= 4‘h8; 154 8‘b1101_1011 : key_value <= 4‘h9; 155 8‘b1101_1101 : key_value <= 4‘ha; 156 8‘b1101_1110 : key_value <= 4‘hb; 157 158 8‘b1110_0111 : key_value <= 4‘hc; 159 8‘b1110_1011 : key_value <= 4‘hd; 160 8‘b1110_1101 : key_value <= 4‘he; 161 8‘b1110_1110 : key_value <= 4‘hf; 162 default : key_value <= key_value; 163 endcase 164 end 165 else 166 key_value <= key_value; 167 end 168 169 //----------------------------------------- 170 //read enable 171 always@(posedge clk or negedge rst_n) 172 begin 173 if(!rst_n) 174 key_flag <= 0; 175 else 176 key_flag <= key_trigger; 177 end 178 179 endmodule 180 //========================================================================================================================================================================================= 181 `timescale 1ns/1ns 182 module led_input_display 183 #( 184 parameter LED_WIDTH = 8 185 ) 186 ( 187 input clk, 188 input rst_n, 189 input led_en, 190 input [LED_WIDTH-1:0] led_value, 191 192 output reg [LED_WIDTH-1:0] led_data 193 194 ); 195 //----------------------------- 196 //led input with enable signal 197 always@(posedge clk or negedge rst_n) 198 begin 199 if(!rst_n) 200 led_data <= {LED_WIDTH{1‘b0}}; 201 else if (led_en) 202 led_data <= led_value; 203 else 204 led_data <= led_data; 205 end 206 endmodule 207 //===================================================================================================================================================================================================== 208 `timescale 1ns/1ns 209 module led_74595_driver 210 ( 211 //global clock 212 input clk,//50MHz 213 input rst_n, 214 215 //user led output 216 input [7:0] led_data, 217 218 output led595_clk, 219 output led595_dout, 220 output led595_latch 221 ); 222 //----------------------------- 223 //update display when led_data is update 224 //generate led_data_r and update_flag 225 reg [7:0] led_data_r; 226 reg update_flag; 227 always@(posedge clk or negedge rst_n) 228 begin 229 if(!rst_n) 230 begin 231 led_data_r <= 0; 232 update_flag <= 1; 233 end 234 else 235 begin 236 led_data_r <= led_data; 237 update_flag <= (led_data_r == led_data)?1‘b1:1‘b0; 238 end 239 end 240 //------------------------------ 241 //74HC595 clk delay for enough setup time 242 // generate shift_flag and shift_clk 243 localparam DELAY_CNT = 3‘d7; 244 reg shift_state; 245 reg [2:0] delay_cnt; 246 always@(posedge clk or negedge rst_n) 247 begin 248 if(!rst_n) 249 delay_cnt <= 0; 250 else if(shift_state == 1‘b1) 251 delay_cnt <= (delay_cnt < DELAY_CNT) ? (delay_cnt+1‘b1):3‘d0; 252 else 253 delay_cnt <= 0; 254 end 255 wire shift_clk = (delay_cnt > DELAY_CNT/2) ? 1‘b1 : 1‘b0; 256 wire shift_flag = (delay_cnt == DELAY_CNT) ? 1‘b1 : 1‘b0; 257 //---------------------------------------- 258 //74HC595 shift data output state 259 reg [3:0] led_cnt; 260 always@(posedge clk or negedge rst_n) 261 begin 262 if(!rst_n) 263 begin 264 shift_state <= 0; 265 led_cnt <= 0; 266 end 267 else 268 begin 269 case(shift_state) 270 0: begin 271 led_cnt <= 0; 272 if(update_flag) 273 shift_state <= 1‘b1; 274 else 275 shift_state <= 0; 276 end 277 1: begin 278 if(shift_flag) 279 begin 280 if(led_cnt < 4‘d8) 281 begin 282 led_cnt <= led_cnt + 1‘b1; 283 shift_state <= 1‘d1; 284 end 285 else 286 begin 287 led_cnt <= 0; 288 shift_state <= 0; 289 end 290 end 291 else 292 begin 293 led_cnt <= led_cnt; 294 shift_state <= shift_state; 295 end 296 end 297 endcase 298 end 299 end 300 assign led595_dout = (led_cnt < 4‘d8&&shift_state == 1‘b1) ? led_data[3‘d7-led_cnt]: 1‘b0; 301 assign led595_clk = (led_cnt < 4‘d8&&shift_state == 1‘b1) ? shift_clk : 1‘b0; 302 assign led595_latch = (led_cnt ==4‘d8&&shift_state == 1‘b1) ? 1‘b1 : 1‘b0; 303 304 305 endmodule 306 //==================================================================================================================================================================================================== 307 `timescale 1ns/1ns 308 module KEY_Scan_Design 309 ( 310 input clk, 311 input rst_n, 312 313 //matrix keyboard interface 314 input [3:0] row_data, 315 output [3:0] col_data, 316 317 output led595_clk, 318 output led595_dout, 319 output led595_latch 320 ); 321 322 //------------------------------------- 323 wire key_flag; 324 wire [3:0] key_value; 325 matrix_key_scan u_matrix_key_scan 326 ( 327 //global clk 328 .clk(clk), 329 .rst_n(rst_n), 330 331 //matrix keyboard interface 332 .row_data(row_data), 333 .col_data(col_data), 334 335 //user interface 336 .key_flag(key_flag), 337 .key_value(key_value) 338 ); 339 340 //------------------------------------------ 341 wire [7:0] led_data; 342 led_input_display 343 #( 344 .LED_WIDTH (8) 345 ) 346 u_led_input_display 347 ( 348 .clk (clk), 349 .rst_n (rst_n), 350 .led_en (key_flag), 351 352 .led_value ({4‘d0,key_value}), 353 354 .led_data (led_data) 355 ); 356 357 //------------------------------------------- 358 led_74595_driver u_led_74595_driver 359 ( 360 //global clock 361 .clk (clk),//50MHz 362 .rst_n (rst_n), 363 364 //user led output 365 .led_data (led_data), 366 367 .led595_clk (led595_clk), 368 .led595_dout (led595_dout), 369 .led595_latch (led595_latch) 370 ); 371 372 endmodule
时间: 2024-10-03 00:01:41