4*4矩陣鍵盤的FPGA驅動
一、硬件原理
4*4矩陣鍵盤有4行與4列,在按鍵按下時一行與一列即導通。其驅動方法非常簡單。本設計中以一定的時間頻率分別將每一行的引腳電平拉高,並在拉高某個引腳的同時檢測每一列的電平變化,當檢測到某列引腳有上升沿跳變時,即爲該行與該列導通對應的那個按鍵被按下。
例如上圖中,拉高PD4,此時檢測到PD2引腳有上升沿電平跳變,則按鍵S5被按下。其餘同理。
二、Verilog代碼實現
//////////////////////////////////////////////////////////////////////////////////
// Company: NanJing University of Information Science & Technology
// Engineer: Yang Cheng Yu
//
// Create Date: 2020/01/13 20:01:50
// Design Name: keyboard_4_4
// Module Name: keyboard_4_4
// Project Name: Clock
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module keyboard_4_4(
input clk,//時鐘
input rst,//復位
output reg[3:0] c_pin,//行引腳
input[3:0] r_pin,//列引腳
output reg[3:0] key_out//按鍵編號輸出
);
reg[15:0] div_cnt;//分頻計數器
reg[2:0] state;
reg cnt_full;//分頻計數器計滿邏輯
localparam CHECK_R1=3'b000;//檢測R1
localparam CHECK_R2=3'b001;//檢測R2
localparam CHECK_R3=3'b011;//檢測R3
localparam CHECK_R4=3'b010;//檢測R4
//分頻計數器邏輯
always@(posedge clk or negedge rst)begin//此處設計每次拉高一行時間爲1ms
if(!rst)begin
div_cnt <= 16'd0;
cnt_full <= 1'b0;
end
else
if(div_cnt==16'd49999)begin
div_cnt <= 16'd0;
cnt_full <= 1'b1;
end
else begin
div_cnt <= div_cnt + 1'b1;
cnt_full <= 1'b0;
end
end
//狀態組合判斷
always@(posedge cnt_full or negedge rst)begin
if(!rst)
state <= CHECK_R1;
else
case(state)
CHECK_R1:
if(cnt_full)
state <= CHECK_R2;
else
state <= CHECK_R1;
CHECK_R2:
if(cnt_full)
state <= CHECK_R3;
else
state <= CHECK_R2;
CHECK_R3:
if(cnt_full)
state <= CHECK_R4;
else
state <= CHECK_R3;
CHECK_R4:
if(cnt_full)
state <= CHECK_R1;
else
state <= CHECK_R4;
default:
state <= state;
endcase
end
//狀態機輸出邏輯
always@(posedge clk or negedge rst)begin
if(!rst)
c_pin <= 4'b0000;
else
case(state)
CHECK_R1:begin
c_pin <= 4'b1000;
case(r_pin)
4'b1000:key_out <= 4'd0;
4'b0100:key_out <= 4'd1;
4'b0010:key_out <= 4'd2;
4'b0001:key_out <= 4'd3;
endcase
end
CHECK_R2:begin
c_pin <= 4'b0100;
case(r_pin)
4'b1000:key_out <= 4'd4;
4'b0100:key_out <= 4'd5;
4'b0010:key_out <= 4'd6;
4'b0001:key_out <= 4'd7;
endcase
end
CHECK_R3:begin
c_pin <= 4'b0010;
case(r_pin)
4'b1000:key_out <= 4'd8;
4'b0100:key_out <= 4'd9;
4'b0010:key_out <= 4'd10;
4'b0001:key_out <= 4'd11;
endcase
end
CHECK_R4:begin
c_pin <= 4'b0001;
case(r_pin)
4'b1000:key_out <= 4'd12;
4'b0100:key_out <= 4'd13;
4'b0010:key_out <= 4'd14;
4'b0001:key_out <= 4'd15;
endcase
end
default:begin
c_pin <= 4'b0000;
key_out <= 4'd0;
end
endcase
end
endmodule
狀態轉移圖