最近研究需要用到4X4薄膜鍵盤設計。
就稍微研究了一下,有些資料參考介紹還蠻清楚的。
原理就是,行1~行4送掃描碼,列1~列4讀值。
例如:
1. 行1~行4送 (0111)2進制的值,如果列1~列4讀到(0111)就表示Key 1被按下了。
2. 行1~行4送 (1101)2進制的值,如果列1~列4讀到(1011)就表示Key 6被按下了。
所以Verilog在寫程式的時候就要看現在是送那一列的掃描碼, 讀進來後是哪一個為0代表被按下。
[Note] 其中每個列的訊號端需要接一個pull high電組 ,以防止腳位浮接。
程式碼如下:
1 // -------------------------------------------------------------------- 2 // Copyright (c) 2011 by TKU ICLAB. 3 // -------------------------------------------------------------------- 4 /* use follow instruction to call the function 5 6 4X4 Keypad 7 Pin1 Pin2 Pin3 Pin4 Pin5 Pin6 Pin7 Pin8 8 function row1 row2 row3 row4 col1 col2 col3 col4 9 10 FPGA PIN iKey_Read[3] ~ iKey_Read[0] | oKey_Scan[3] ~ oKey_Scan[0] 11 12 */ 13 `define default_netype none 14 module Keypad4X4_top ( 15 iClk_50M, // 50Mhz 16 iRst_n, // reset_n 17 18 iKey_Read, // Key Read 19 oKey_Scan, // Key Scan code 20 21 oDval, // a trigger 22 oKeyCode, // Key code4 23 oKey 24 25 ); 26 //=========================================================================== 27 // PORT declarations 28 //=========================================================================== 29 input iClk_50M; 30 input iRst_n; 31 32 input [3:0] iKey_Read; // Key Read 33 output [3:0] oKey_Scan; // Key Scan code 34 35 output oDval; // a trigger 36 output [4:0] oKeyCode; // Key code 37 output [15:0] oKey; 38 //============================================================================= 39 // REG/WIRE declarations 40 //============================================================================= 41 reg [15:0] oKey; 42 reg oDval, rDval; 43 reg [3:0] oKey_Scan; 44 reg [4:0] oKeyCode; 45 wire wClk_1khz; 46 wire [2:0] wKey_Dly; 47 reg [1:0] rCnt, rSt; 48 reg [4:0] rKeyCode, rKeyCode_d1, rKeyCode_d2, rKeyCode_d3; 49 reg [3:0] rKey_Read_Dly0, rKey_Read_Dly1; 50 reg [3:0] rKey_Read; 51 wire wclk4X; 52 reg rPressKey; 53 //============================================================================= 54 // Structural coding 55 //============================================================================= 56 ///* 57 Clkdiv #( .CLKFREQ(50000000), .EXCEPTCLK(500000), .multipleX(4) ) UX1 58 ( 59 .iClk50M(iClk_50M), // 50Mhz clock 60 .iRst_n(iRst_n), 61 .oClk(wClk_1khz), // 1ms clock 62 .oSampClk(wclk4X), // multipleX expect clock, for SignalTap use 63 ); 64 //*/ 65 66 //// send column scan 67 always@(posedge wClk_1khz or negedge iRst_n) begin 68 if(!iRst_n) begin 69 rCnt <= 0; 70 oKey_Scan <= 0; 71 rSt <= 0; 72 end 73 else begin 74 case(rSt) 75 2'b00: begin oKey_Scan <= 4'b0111; rCnt <= rCnt+2'b1; 76 if(rCnt == 3) rSt <= rSt + 1; 77 else rSt <= rSt; end // 1 column 78 2'b01: begin oKey_Scan <= 4'b1011; rCnt <= rCnt+2'b1; 79 if(rCnt == 3) rSt <= rSt + 1; 80 else rSt <= rSt; 81 end // 2 column 82 2'b10: begin oKey_Scan <= 4'b1101; rCnt <= rCnt+2'b1; 83 if(rCnt == 3) rSt <= rSt + 1; 84 else rSt <= rSt; end // 3 column 85 default: begin oKey_Scan <= 4'b1110; rCnt <= rCnt+2'b1; 86 if(rCnt == 3) rSt <= rSt + 1; 87 else rSt <= rSt; end // 4 column 88 endcase 89 end 90 end 91 92 // send column scan 93 always@(posedge wClk_1khz or negedge iRst_n) begin 94 if(!iRst_n) begin 95 oKey <= 0; 96 rDval <= 0; 97 rKeyCode <= 0; 98 rPressKey <= 0; 99 end100 else begin101 oKey <= oKey;102 // read row103 case(iKey_Read)104 4'b0111: begin // 1 row105 oKey[3:0] <= 0;106 case(oKey_Scan)107 4'b0111: begin rDval <= 1; rKeyCode <= 5'd1; oKey[0] <= 1; end//'1'108 4'b1011: begin rDval <= 1; rKeyCode <= 5'd2; oKey[1] <= 1; end//'2'109 4'b1101: begin rDval <= 1; rKeyCode <= 5'd3; oKey[2] <= 1; end//'3'110 4'b1110: begin rDval <= 1; rKeyCode <= 5'd10; oKey[3] <= 1; end//'A'111 default: begin rDval <= 0; rKeyCode <= 5'd16; oKey[3:0] <= 0;end//'E'112 endcase113 end 114 4'b1011: begin // 2 row115 oKey[7:4] <= 0;116 case(oKey_Scan)117 4'b0111: begin rDval <= 1; rKeyCode <= 5'd4; oKey[4] <= 1;end//'4'118 4'b1011: begin rDval <= 1; rKeyCode <= 5'd5; oKey[5] <= 1;end//'5'119 4'b1101: begin rDval <= 1; rKeyCode <= 5'd6; oKey[6] <= 1;end//'6'120 4'b1110: begin rDval <= 1; rKeyCode <= 5'd11; oKey[7] <= 1;end //'B'121 default: begin rDval <= 0; rKeyCode <= 5'd16; oKey[7:4] <= 0;end //'E'122 endcase123 end 124 4'b1101: begin // 3 row125 oKey[11:8] <= 0;126 case(oKey_Scan)127 4'b0111: begin rDval <= 1; rKeyCode <= 5'd7; oKey[8] <= 1;end//'7'128 4'b1011: begin rDval <= 1; rKeyCode <= 5'd8; oKey[9] <= 1;end//'8'129 4'b1101: begin rDval <= 1; rKeyCode <= 5'd9; oKey[10] <= 1;end//'9'130 4'b1110: begin rDval <= 1; rKeyCode <= 5'd12; oKey[11] <= 1;end//'C'131 default: begin rDval <= 0; rKeyCode <= 5'd16; oKey[11:8] <= 0;end //'E'132 endcase133 end 134 4'b1110: begin // 4 row135 oKey[15:12] <= 0;136 case(oKey_Scan)137 4'b0111: begin rDval <= 1;rKeyCode <= 5'd14; oKey[12] <= 1; end//'*'138 4'b1011: begin rDval <= 1;rKeyCode <= 5'd0; oKey[13] <= 1;end//'0'139 4'b1101: begin rDval <= 1;rKeyCode <= 5'd15; oKey[14] <= 1;end//'#'140 4'b1110: begin rDval <= 1;rKeyCode <= 5'd13; oKey[15] <= 1;end//'D'141 default: begin rDval <= 0;rKeyCode <= 5'd16; oKey[15:12] <= 0;end//'E'142 endcase143 end144 4'b1111: begin // 4 row145 rDval <= 0; rKeyCode <= 5'd16; oKey <= oKey;146 case(oKey_Scan)147 4'b0111: begin rDval <= 1; rKeyCode <= 5'd1; oKey[0] <= 0; 148 oKey[4] <= 0;oKey[8] <= 0;oKey[12] <= 0;end//'1'149 4'b1011: begin rDval <= 1; rKeyCode <= 5'd2; oKey[1] <= 0; 150 oKey[5] <= 0;oKey[9] <= 0;oKey[13] <= 0;end//'1'end//'2'151 152 4'b1101: begin rDval <= 1; rKeyCode <= 5'd3; oKey[2] <= 0; 153 oKey[6] <= 0;oKey[10] <= 0;oKey[14] <= 0;end//'1'end//'3'154 4'b1110: begin rDval <= 1; rKeyCode <= 5'd10; oKey[3] <= 0; 155 oKey[7] <= 0;oKey[11] <= 0;oKey[15] <= 0;end//'1'end//'A'156 default: begin rDval <= 0; rKeyCode <= 5'd16; oKey <= oKey;end//'E'157 endcase158 159 160 end 161 default: begin162 rDval <= 0; rKeyCode <= 5'd16; 163 oKey <= oKey;// No key press164 end165 endcase166 end167 end168 169 170 171 // disbounce172 always@(posedge wClk_1khz or negedge iRst_n) begin173 if(!iRst_n) begin174 oDval <= 0;175 oKeyCode <= 5'd16;176 end177 else begin178 if( rDval ) begin179 oKeyCode <= rKeyCode;180 oDval <= 1;181 end182 else begin183 oKeyCode <= oKeyCode;184 oDval <= 0;185 186 end187 end188 end189 190 endmodule