講講FPGA中矩陣鍵盤的應用了。這個思維和電路在FPGA中有所不同,在此,在此做詳細解釋,Bingo用自己設計的成熟的代碼作為案例,希望對你有用。
一、FPGA矩陣鍵盤電路圖
在FPGA中的電路,與單片機雷同,如下所示:
在上電默認情況下,L[3:0] =4''b1,因為上拉了3.3V,而默認情況下H.[3:0]為低電平;一旦有某一個按鍵被按下,便是是的該路電路流向該按鍵的H,是的L檢測不到電流。因此可以通過對每一行H輸出的控制,來檢索是哪一個按鍵被按下了,這也原理和單片機中一樣,只是寫法不一樣罷了。
二、FPGA矩陣鍵盤FSM
1. 代碼
代碼如下所示,采用了三段式狀態(tài)機來描述矩陣鍵盤。本模塊形式與上一張按鍵消抖動雷同,方便移植。
/*************************************************
* Module Name : matrix_key_design.v
* Engineer : Crazy Bingo
* Target Device : EP2C8Q208C8
* Tool versions : Quartus II 11.0
* Create Date : 2011-6-26
* Revision : v1.0
* Description :
**************************************************/
module matrix_key_design
(
input clk,
input rst_n,
input [3:0] col_data,
output reg [3:0] row_data,
output key_flag, //the mark of key is pressed
output reg [3:0] key_value
);
//generate for 2ms signal
reg [19:0] cnt; //fffff,≈50Hz 20ms
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
cnt <= 0;
else
cnt <= cnt+1'b1;
end
/*****************************************************
* R3 >---0----1----2----3
* | | | |
* R2 >---4----5----6----7
* | | | |
* R1 >---8----9----A----B
* | | | |
* R0 >---C----D----E----F
* | | | |
* C3 C2 C1 C0
*****************************************************/
parameter SCAN_IDLE = 3'b000;
parameter SCAN_JITTER= 3'b001;
parameter SCAN_COL0 = 3'b011;
parameter SCAN_COL1 = 3'b010;
parameter SCAN_COL2 = 3'b110;
parameter SCAN_COL3 = 3'b100;
parameter SCAN_READ = 3'b101;
parameter SCAN_JTTTER2= 3'b111;
reg [2:0] current_state;
reg [2:0] next_state;
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
current_state <= SCAN_IDLE;
else if(cnt == 20'hfffff)
current_state <= next_state;
end
always@*
begin
case(current_state)
SCAN_IDLE : //init
if(col_data != 4'b1111) next_state = SCAN_JITTER;
else next_state = SCAN_IDLE;
SCAN_JITTER: //escape the jitter
if(col_data != 4'b1111) next_state = SCAN_COL0;
else next_state = SCAN_IDLE;
SCAN_COL0 : //1th row
if(col_data != 4'b1111) next_state = SCAN_READ;
else next_state = SCAN_COL1;
SCAN_COL1 : //2th row
if(col_data != 4'b1111) next_state = SCAN_READ;
else next_state = SCAN_COL2;
SCAN_COL2 : //3th row
if(col_data != 4'b1111) next_state = SCAN_READ;
else next_state = SCAN_COL3;
SCAN_COL3 : //4th row
if(col_data != 4'b1111) next_state = SCAN_READ;
else next_state = SCAN_IDLE;
SCAN_READ : //lock the vaule
if(col_data != 4'b1111) next_state = SCAN_JTTTER2;
else next_state = SCAN_IDLE;
SCAN_JTTTER2: //when your hand is gone
if(col_data != 4'b1111) next_state = SCAN_JTTTER2;
else next_state = SCAN_IDLE;
endcase
end
reg [3:0] col_data_r;
reg [3:0] row_data_r;
reg key_flag_r0;
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
row_data <= 4'b0000;
Key_flag_r0 <= 0;
end
else if(cnt == 20'hfffff)
begin
case(next_state)
SCAN_IDLE : begin
row_data <= 4'b0000;
key_flag_r0 <= 0;
end
//SCAN_JITTER:
SCAN_COL0 : row_data <= 4'b1110;
SCAN_COL1 : row_data <= 4'b1101;
SCAN_COL2 : row_data <= 4'b1011;
SCAN_COL3 : row_data <= 4'b0111;
SCAN_READ : begin
row_data_r <= row_data;
col_data_r <= col_data;
key_flag_r0 <= 1;
end
//SCAN_JTTTER2:
default:; //default vaule
endcase
end
end
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
key_value <= 0;
else if(cnt == 20'hfffff)
begin
if(key_flag_r0 == 1'b1) //the mark of key is pressed
begin
case ({row_data_r,col_data_r}) //row_data Row, col_data Col
8'b0111_0111: key_value <= 4'h0;
8'b0111_1011: key_value <= 4'h1;
8'b0111_1101: key_value <= 4'h2;
8'b0111_1110: key_value <= 4'h3;
8'b1011_0111: key_value <= 4'h4;
8'b1011_1011: key_value <= 4'h5;
8'b1011_1101: key_value <= 4'h6;
8'b1011_1110: key_value <= 4'h7;
8'b1101_0111: key_value <= 4'h8;
8'b1101_1011: key_value <= 4'h9;
8'b1101_1101: key_value <= 4'hA;
8'b1101_1110: key_value <= 4'hB;
8'b1110_0111: key_value <= 4'hC;
8'b1110_1011: key_value <= 4'hD;
8'b1110_1101: key_value <= 4'hE;
8'b1110_1110: key_value <= 4'hF;
default : key_value <= key_value;
endcase
end
else
key_value <= key_value;
end
end
//Capture the falling endge
reg key_flag_r2,key_flag_r1;
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
key_flag_r1 <= 0;
key_flag_r2 <= 0;
end
else
begin
key_flag_r1 <= key_flag_r0;
key_flag_r2 <= key_flag_r1;
end
end
assign key_flag = key_flag_r2 & ~key_flag_r1; //when your hand is gone
endmodule
2. 狀態(tài)機說明
(1)以下是該電路的state machine。