简单介绍下矩阵键盘的原理:
矩阵键盘4个输入端口ROW[3:0] 接收由FPGA产生的键盘扫描输入信号,而4个输出COL[3:0] 将按键操作的信息变化输入到FPGA扫描分析电路,进而得到按键的操作码。
输入端口分别接了4个上拉电阻,当4个输入端口输入若都为1时,则有无论按哪个按键,输出都为1,所以 若刚开始的时候对四个输入端口赋0,则只要按下任何一个按键,键盘上的4个输出则肯定有1变为0,而且能够判断到是哪一列,但是并不知道是哪一行,所以此时就要用到键盘扫描,何为键盘扫描,就是只要让输入端口的一行为0,其余三行全为1,轮流扫描一遍,便可以方便的确定按键按下的准确值。
又因为实际运用的时候按键按下会有抖动现象,所以要对其进行消抖处理,消抖模块可以有很多种方法,例如状态机的消抖方法以及打拍延时,然后相或,因为这个是键值输入,若要用到打拍延时的方法进行消抖处理的话,需要对其进行一些改动,相或改为两两相等并相与 以增加时钟时间。
以下给出矩阵键盘实现的两种代码,其中一种参照赵然的书籍中提到的夏宇闻老师提供的代码。 这里用到了状态机模块进行消抖。
`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 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
时间: 2024-10-03 20:32:50