簡單介紹下矩陣鍵盤的原理:spa
矩陣鍵盤4個輸入端口ROW[3:0] 接收由FPGA產生的鍵盤掃描輸入信號,而4個輸出COL[3:0] 將按鍵操做的信息變化輸入到FPGA掃描分析電路,進而獲得按鍵的操做碼。code
輸入端口分別接了4個上拉電阻,當4個輸入端口輸入若都爲1時,則有不管按哪一個按鍵,輸出都爲1,因此 若剛開始的時候對四個輸入端口賦0,則只要按下任何一個按鍵,鍵盤上的4個輸出則確定有1變爲0,並且可以判斷到是哪一列,可是並不知道是哪一行,因此此時就要用到鍵盤掃描,何爲鍵盤掃描,就是隻要讓輸入端口的一行爲0,其他三行全爲1,輪流掃描一遍,即可以方便的肯定按鍵按下的準確值。blog
又由於實際運用的時候按鍵按下會有抖動現象,因此要對其進行消抖處理,消抖模塊能夠有不少種方法,例如狀態機的消抖方法以及打拍延時,而後相或,由於這個是鍵值輸入,若要用到打拍延時的方法進行消抖處理的話,須要對其進行一些改動,相或改成兩兩相等並相與 以增長時鐘時間。input
如下給出矩陣鍵盤實現的兩種代碼,其中一種參照趙然的書籍中提到的夏宇聞老師提供的代碼。 這裏用到了狀態機模塊進行消抖。 class
`define OK 1'b1 `define NO 1'b0 `define NoKeyIsPressed 17 module keyscan0(clk,rst_n,keyscan,keyin,real_number); input clk,rst_n; input [3:0]keyin; output [3:0] keyscan; output [4:0] real_number; reg [3:0] state; reg [3:0] four_state; reg [3:0] scancode,scan_state; reg [4:0] numberout,number_reg,number_reg1,number_reg2, real_number; reg AnyKeyPressed; assign keyscan = scancode; always @(posedge clk or negedge rst_n) if (!rst_n) begin scancode <=4'b0000; scan_state<= 4'b0000; end else if(AnyKeyPressed) case (scan_state) 4'b0000: begin scancode<=4'b1110; scan_state<= 4'b0001; end 4'b0001: begin scancode <= {scancode[0],scancode[3:1]}; end endcase else begin scancode <=4'b0000; scan_state<= 4'b0000; end always @(posedge clk ) if( !(&keyin)) begin AnyKeyPressed <= `OK ; four_state <= 4'b0000; end else if(AnyKeyPressed) case(four_state) 4'b0000: begin AnyKeyPressed <= `OK ; four_state<=4'b0001; end 4'b0001: begin AnyKeyPressed <= `OK ; four_state<=4'b0010; end 4'b0010: begin AnyKeyPressed <= `OK ; four_state<=4'b0100; end 4'b0100: begin AnyKeyPressed <= `OK ; four_state<=4'b1000; end 4'b1000: begin AnyKeyPressed <= `NO ; end default: AnyKeyPressed <= `NO ; endcase else four_state <= 4'b0000; always @(posedge clk or negedge rst_n) if(!rst_n) numberout<=`NoKeyIsPressed; else casex({scancode,keyin}) 8'b0111_1110: numberout <= 5'd10; 8'b1011_1110: numberout <= 5'd3; 8'b1101_1110: numberout <= 5'd2; 8'b1110_1110: numberout <= 5'd1; 8'b0111_1101: numberout <= 5'd11; 8'b1011_1101: numberout <= 5'd6; 8'b1101_1101: numberout <= 5'd5; 8'b1110_1101: numberout <= 5'd4; 8'b0111_1011: numberout <= 5'd12; 8'b1011_1011: numberout <= 5'd9; 8'b1101_1011: numberout <= 5'd8; 8'b1110_1011: numberout <= 5'd7; 8'b0111_0111: numberout <= 5'd13; 8'b1011_0111: numberout <= 5'd15; 8'b1101_0111: numberout <= 5'd14; 8'b1110_0111: numberout <= 5'd0; default: numberout <=`NoKeyIsPressed; endcase always @(posedge clk or negedge rst_n) begin if (!rst_n) begin number_reg <= 0; end else if( numberout<=5'd15 && numberout>=5'd0) begin number_reg <= numberout; end else begin if(AnyKeyPressed == `NO) number_reg <= `NoKeyIsPressed; end end always @(posedge clk or negedge rst_n) if (!rst_n) state <= 4'b0000; else case (state) 4'd0: begin number_reg1 <= number_reg; state <=4'd1; end 4'd1: begin if(number_reg == number_reg1) state <= 4'd2; else state <= 4'd0; end 4'd2: begin if (number_reg == number_reg1) state <= 4'd3; else state <= 4'd0; end 4'd3: begin if (number_reg == number_reg1) state <= 4'd4; else state <= 4'd0; end 4'd4: begin if(number_reg == number_reg1) state <=4'd5; else state <= 4'd0; end 4'd5: begin if(number_reg == number_reg1) state <= 4'd6; else state <= 4'd0; end 4'd6: begin if (number_reg == number_reg1) state <= 4'd7; else state <= 4'd0; end 4'd7: begin if (number_reg == number_reg1) state <= 4'd8; else state <= 4'd0; end 4'd8: begin if (number_reg == number_reg1) state <=4'd9; else state <= 4'd0; end 4'd9: begin if(number_reg == number_reg1) state <= 4'd10; else state <= 4'd0; end 4'd10: begin if (number_reg == number_reg1) state <= 4'd11; else state <= 4'd0; end 4'd11: begin if (number_reg == number_reg1) state <= 4'd12; else state <= 4'd0; end 4'd12: begin if(number_reg == number_reg1) state <= 4'd13; else state <= 4'd0; end 4'd13: begin if (number_reg == number_reg1) state <= 4'd14; else state <= 4'd0; end 4'd14: begin if (number_reg == number_reg1) state <= 4'd15; else state <= 4'd0; end 4'd15: begin if (number_reg == number_reg1 ) begin state <= 4'd0; real_number <=number_reg; end else state <= 4'b0000; end default: state <= 4'b0000; endcase endmodule
另外一種:module
module key_bd( input CLK_1K, input RSTN, input [3:0]ROW, output reg[3:0]COL, output [3:0]real_num, output flag_pos //output reg[3:0]key_value, //output reg[23:0]num_out ); reg [3:0]state; reg [3:0]four_state; reg [3:0]key_value; reg flag; parameter NO = 6'b000_001; parameter S0 = 6'b000_010; parameter S1 = 6'b000_100; parameter S2 = 6'b001_000; parameter S3 = 6'b010_000; parameter YES= 6'b100_000; reg [5:0]CS,NS; always@(posedge CLK_1K or negedge RSTN) begin if(~RSTN) CS <= NO; else CS <= NS; end always@(*) case(CS) NO:if(ROW != 4'hF) NS <= S0; else NS <= NO; S0:if(ROW != 4'hF) NS <= YES; else NS <= S1; S1:if(ROW != 4'hF) NS <= YES; else NS <= S2; S2:if(ROW != 4'hF) NS <= YES; else NS <= S3; S3:if(ROW != 4'hF) NS <= YES; else NS <= NO; YES:if(ROW != 4'hF) NS <= YES; else NS <= NO; endcase reg [3:0]ROW_val,COL_val; always@(posedge CLK_1K or negedge RSTN) begin if(!RSTN) begin COL <= 0; flag <= 0; end else case(NS) NO:begin COL <= 0; flag <= 0; end S0:begin COL <= 4'b1110; end S1:begin COL <= 4'b1101; end S2:begin COL <= 4'b1011; end S3:begin COL <= 4'b0111; end YES:begin COL_val <= COL; ROW_val <= ROW; flag <= 1; end endcase end ///////////////////////////////////////////////////////// reg flag_pre; always@(posedge CLK_1K or negedge RSTN) begin if(~RSTN) flag_pre <= 0; else flag_pre <= flag; end //assign flag_pos = (~flag_pre)&flag; assign flag_pos = flag_pre & (~flag); ///////////////////////////////////////////////////////// always@(posedge CLK_1K or negedge RSTN) begin if(~RSTN) key_value <= 0; else if(flag) case({ROW_val,COL_val}) 8'b1110_1110: key_value <= 4'h1; 8'b1110_1101: key_value <= 4'h2; 8'b1110_1011: key_value <= 4'h3; 8'b1110_0111: key_value <= 4'ha; 8'b1101_1110: key_value <= 4'h4; 8'b1101_1101: key_value <= 4'h5; 8'b1101_1011: key_value <= 4'h6; 8'b1101_0111: key_value <= 4'hb; 8'b1011_1110: key_value <= 4'h7; 8'b1011_1101: key_value <= 4'h8; 8'b1011_1011: key_value <= 4'h9; 8'b1011_0111: key_value <= 4'hc; 8'b0111_1110: key_value <= 4'h0; 8'b0111_1101: key_value <= 4'he; 8'b0111_1011: key_value <= 4'hf; 8'b0111_0111: key_value <= 4'hd; endcase end key_esk #(4) K1( .CLK_1K(CLK_1K), .key_in(key_value), .key_out(real_num) ); endmodule