安德鲁

[笔记].驱动4x4矩阵键盘的思路.[Verilog]

0
阅读(3717)

SCH

图1 4x4矩阵键盘的SCH(箭头表示输入输出方向)

如图1所示,将ROW[3:0]设为输入,COL[3:0]设为输出。如果没有任何键被按下,则ROW[3:0]一直被上拉为高电平。只有当有键被按下,且COL[3:0]中有低电平输出,ROW[3:0]中才有可能有低电平输入,也可说是被动地输入。

 

流程图

图2 流程图

 

HDL

001 module matrixKeyboard_drive(
002   input            i_clk,
003   input            i_rst_n,
004   input      [3:0] row,                 // 矩阵键盘 行
005   output reg [3:0] col,                 // 矩阵键盘 列
006   output reg [3:0] keyboard_val         // 键盘值     
007 );
008  
009 //++++++++++++++++++++++++++++++++++++++
010 // 分频部分 开始
011 //++++++++++++++++++++++++++++++++++++++
012 reg [19:0] cnt;                         // 计数子
013  
014 always @ (posedge i_clk, negedge i_rst_n)
015   if (!i_rst_n)
016     cnt <= 0;
017   else
018     cnt <= cnt + 1'b1;
019  
020 wire key_clk = cnt[19];                // (2^20/50M = 21)ms 
021 //--------------------------------------
022 // 分频部分 结束
023 //--------------------------------------
024  
025  
026 //++++++++++++++++++++++++++++++++++++++
027 // 状态机部分 开始
028 //++++++++++++++++++++++++++++++++++++++
029 // 状态数较少,独热码编码
030 parameter NO_KEY_PRESSED = 6'b000_001// 没有按键按下  
031 parameter SCAN_COL0      = 6'b000_010// 扫描第0列 
032 parameter SCAN_COL1      = 6'b000_100// 扫描第1列 
033 parameter SCAN_COL2      = 6'b001_000// 扫描第2列 
034 parameter SCAN_COL3      = 6'b010_000// 扫描第3列 
035 parameter KEY_PRESSED    = 6'b100_000// 有按键按下
036  
037 reg [5:0] current_state, next_state;    // 现态、次态
038  
039 always @ (posedge key_clk, negedge i_rst_n)
040   if (!i_rst_n)
041     current_state <= NO_KEY_PRESSED;
042   else
043     current_state <= next_state;
044  
045 // 根据条件转移状态
046 always @ *
047   case (current_state)
048     NO_KEY_PRESSED :                    // 没有按键按下
049         if (row != 4'hF)
050           next_state = SCAN_COL0;
051         else
052           next_state = NO_KEY_PRESSED;
053     SCAN_COL0 :                         // 扫描第0列 
054         if (row != 4'hF)
055           next_state = KEY_PRESSED;
056         else
057           next_state = SCAN_COL1;
058     SCAN_COL1 :                         // 扫描第1列 
059         if (row != 4'hF)
060           next_state = KEY_PRESSED;
061         else
062           next_state = SCAN_COL2;    
063     SCAN_COL2 :                         // 扫描第2列
064         if (row != 4'hF)
065           next_state = KEY_PRESSED;
066         else
067           next_state = SCAN_COL3;
068     SCAN_COL3 :                         // 扫描第3列
069         if (row != 4'hF)
070           next_state = KEY_PRESSED;
071         else
072           next_state = NO_KEY_PRESSED;
073     KEY_PRESSED :                       // 有按键按下
074         if (row != 4'hF)
075           next_state = KEY_PRESSED;
076         else
077           next_state = NO_KEY_PRESSED;                      
078   endcase
079  
080 reg       key_pressed_flag;             // 键盘按下标志
081 reg [3:0] col_val, row_val;             // 列值、行值
082  
083 // 根据次态,给相应寄存器赋值
084 always @ (posedge key_clk, negedge i_rst_n)
085   if (!i_rst_n)
086   begin
087     col              <= 4'h0;
088     key_pressed_flag <=    0;
089   end
090   else
091     case (next_state)
092       NO_KEY_PRESSED :                  // 没有按键按下
093       begin
094         col              <= 4'h0;
095         key_pressed_flag <=    0;       // 清键盘按下标志
096       end
097       SCAN_COL0 :                       // 扫描第0列
098         col <= 4'b1110;
099       SCAN_COL1 :                       // 扫描第1列
100         col <= 4'b1101;
101       SCAN_COL2 :                       // 扫描第2列
102         col <= 4'b1011;
103       SCAN_COL3 :                       // 扫描第3列
104         col <= 4'b0111;
105       KEY_PRESSED :                     // 有按键按下
106       begin
107         col_val          <= col;        // 锁存列值
108         row_val          <= row;        // 锁存行值
109         key_pressed_flag <= 1;          // 置键盘按下标志  
110       end
111     endcase
112 //--------------------------------------
113 // 状态机部分 结束
114 //--------------------------------------
115  
116  
117 //++++++++++++++++++++++++++++++++++++++
118 // 扫描行列值部分 开始
119 //++++++++++++++++++++++++++++++++++++++
120 always @ (posedge key_clk, negedge i_rst_n)
121   if (!i_rst_n)
122     keyboard_val <= 4'h0;
123   else
124     if (key_pressed_flag)
125       case ({col_val, row_val})
126         8'b1110_1110 : keyboard_val <= 4'h0;
127         8'b1110_1101 : keyboard_val <= 4'h4;
128         8'b1110_1011 : keyboard_val <= 4'h8;
129         8'b1110_0111 : keyboard_val <= 4'hC;
130          
131         8'b1101_1110 : keyboard_val <= 4'h1;
132         8'b1101_1101 : keyboard_val <= 4'h5;
133         8'b1101_1011 : keyboard_val <= 4'h9;
134         8'b1101_0111 : keyboard_val <= 4'hD;
135          
136         8'b1011_1110 : keyboard_val <= 4'h2;
137         8'b1011_1101 : keyboard_val <= 4'h6;
138         8'b1011_1011 : keyboard_val <= 4'hA;
139         8'b1011_0111 : keyboard_val <= 4'hE;
140          
141         8'b0111_1110 : keyboard_val <= 4'h3
142         8'b0111_1101 : keyboard_val <= 4'h7;
143         8'b0111_1011 : keyboard_val <= 4'hB;
144         8'b0111_0111 : keyboard_val <= 4'hF;        
145       endcase
146 //--------------------------------------
147 //  扫描行列值部分 结束
148 //--------------------------------------
149        
150 endmodule