After talking about independent button detection, we should naturally talk about the application of matrix keyboards in FPGA. This idea is different from the circuit in FPGA. Here, we will explain in detail that bingo uses its own mature designCodeAs a case, I hope it will be useful to you.
I. FPGA matrix keyboard circuit diagram
The circuit in FPGA is similar to that in single-chip microcomputer, as shown below:
By default, L [3: 0] = 4'' B1 is powered on, because 3.3 V is pulled up, and H is used by default. [] is a low level. Once a key is pressed, the circuit is the H that flows to the key, and the current is not detected. Therefore, you can control the output of each line of H to retrieve which button is pressed. This is the same principle as that in single chip microcomputer, but it is different in writing.
Ii. FPGA matrix keyboard fsm1. code
The Code is as follows. A three-stage state machine is used to describe the matrix keyboard. The form of this module is the same as that of the previous button, which is convenient for transplantation.
/*************************************** **********
* 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 2 ms Signal
Reg [19:0] CNT; // fffff, ≈ 50Hz 20 ms
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. state machine description
(1) The following is the state machine of the circuit.
(2) The module can be divided into several states: