信号名称 | I/O | 功能描述 |
Clk | I | 模块时钟,50MHz |
Rst_n | I | 模块复位,低电平有效 |
Key_Board_row_i | I | 矩阵按键行输入信号 |
Key_Flag | O | 按键检测完成标志信号 |
Key_Value | O | 按键值 |
Key_Board_col_o | O | 矩阵按键输出列信号 |
状态机及功能描述
状态机编码 | 状态机名称 | 功能描述 |
1 | IDLE | 检测按键是否按下,若按下则开始按键消抖 |
2 | P_FILTER | 按键消抖检测,消抖完成开始读取行状态 |
3 | READ_ROW_P | 读取行状态信号值,并开始列扫描 |
4 | SCAN_C0 | 扫描第一列,并判断按下按键是否在当前列,若否则开始扫描下一列 |
5 | SCAN_C1 | 扫描第二列,并判断按下按键是否在当前列,若否则开始扫描下一列 |
6 | SCAN_C2 | 扫描第三列,并判断按下按键是否在当前列,若否则开始扫描下一列 |
7 | SCAN_C3 | 扫描第三列,并输出按键值 |
8 | PRESS_RESULT | 输出扫描结果 |
9 | WAIT_R | 等待按键释放 |
10 | R_FILTER | 释放检测 |
11 | READ_ROW_R | 释放结束后,回到初始态 |
reg [19:0] counter; reg En_Cnt; reg Cnt_Done; always@(posedge Clk or negedge Rst_n) if(!Rst_n) counter <= 20'd0; else if(En_Cnt)begin if(counter == 20'd999999) counter <= 20'd0; else counter <= counter + 1'b1; end else counter <= 20'd0; always@(posedge Clk or negedge Rst_n) if(!Rst_n) Cnt_Done <= 1'b0; else if(counter == 20'd999999) Cnt_Done <= 1'b1; else Cnt_Done <= 1'b0; |
reg [3:0]Col_Tmp; reg [3:0]Key_Value; reg [7:0]Key_Value_tmp; reg Key_Flag_r; reg [10:0]state; always@(posedge Clk or negedge Rst_n) if(!Rst_n)begin En_Cnt <= 1'b0; state <= IDEL; Key_Board_Col_o <= 4'b0000; Col_Tmp <= 4'd0; Key_Flag_r <= 1'b0; Key_Value_tmp <= 8'd0; Key_Board_Row_r <= 4'b1111; end else begin case(state) //////此部分见下 default:; endcase end |
IDEL: if(Key_Board_Row_i != 4'b1111)begin En_Cnt <= 1'b1; state <= P_FILTER; end else begin En_Cnt <= 1'b0; state <= IDEL; end |
P_FILTER: if(Cnt_Done) begin En_Cnt <= 1'b0; state <= READ_ROW_P; end else begin En_Cnt <= 1'b1; state <= P_FILTER; end |
READ_ROW_P: if(Key_Board_Row_i != 4'b1111)begin Key_Board_Row_r <= Key_Board_Row_i; state <= SCAN_C0; Key_Board_Col_o <= 4'b1110; end else begin state <= IDEL; Key_Board_Col_o <= 4'b0000; end |
SCAN_C0: begin state <= SCAN_C1; Key_Board_Col_o <= 4'b1101; if(Key_Board_Row_i != 4'b1111) Col_Tmp <= 4'b0001; else Col_Tmp <= 4'b0000; end |
SCAN_C1: begin state <= SCAN_C2; Key_Board_Col_o <= 4'b1011; if(Key_Board_Row_i != 4'b1111) Col_Tmp <= Col_Tmp | 4'b0010; else Col_Tmp <= Col_Tmp; end |
SCAN_C2: begin state <= SCAN_C3; Key_Board_Col_o <= 4'b0111; if(Key_Board_Row_i != 4'b1111) Col_Tmp <= Col_Tmp | 4'b0100; else Col_Tmp <= Col_Tmp; end |
SCAN_C3: begin state <= PRESS_RESULT; if(Key_Board_Row_i != 4'b1111) Col_Tmp <= Col_Tmp | 4'b1000; else Col_Tmp <= Col_Tmp; end |
PRESS_RESULT: begin state <= WAIT_R; Key_Board_Col_o <= 4'b0000; if(((Key_Board_Row_r[0] + Key_Board_Row_r[1] + Key_Board_Row_r[2] + Key_Board_Row_r[3]) == 4'd3) || ((Col_Tmp[0] + Col_Tmp[1] + Col_Tmp[2] + Col_Tmp[3]) == 4'd1))begin Key_Flag_r <= 1'b1; Key_Value_tmp <= {Key_Board_Row_r,Col_Tmp}; end else begin Key_Flag_r <= 1'b0; Key_Value_tmp <= Key_Value_tmp; end end |
WAIT_R: begin Key_Flag_r <= 1'b0; if(Key_Board_Row_i == 4'b1111)begin En_Cnt <= 1'b1; state <= R_FILTER; end else begin state <= WAIT_R; En_Cnt <= 1'b0; end end |
R_FILTER: if(Cnt_Done) begin En_Cnt <= 1'b0; state <= READ_ROW_R; end else begin En_Cnt <= 1'b1; state <= R_FILTER; end |
READ_ROW_R: if(Key_Board_Row_i == 4'b1111) state <= IDEL; else begin En_Cnt <= 1'b1; state <= R_FILTER; end |
always@(posedge Clk or negedge Rst_n) if(!Rst_n)begin Key_Flag <= 1'd0; Key_Value <= 4'd0; end else begin Key_Flag <= Key_Flag_r; case(Key_Value_tmp) 8'b1110_0001 : Key_Value = 4'h0; 8'b1110_0010 : Key_Value = 4'h1; 8'b1110_0100 : Key_Value = 4'h2; 8'b1110_1000 : Key_Value = 4'h3; 8'b1101_0001 : Key_Value = 4'h4; 8'b1101_0010 : Key_Value = 4'h5; 8'b1101_0100 : Key_Value = 4'h6; 8'b1101_1000 : Key_Value = 4'h7; 8'b1011_0001 : Key_Value = 4'h8; 8'b1011_0010 : Key_Value = 4'h9; 8'b1011_0100 : Key_Value = 4'hA; 8'b1011_1000 : Key_Value = 4'hB; 8'b0111_0001 : Key_Value = 4'hC; 8'b0111_0010 : Key_Value = 4'hD; 8'b0111_0100 : Key_Value = 4'hE; 8'b0111_1000 : Key_Value = 4'hF; default:begin Key_Value = Key_Value;Key_Flag <= Key_Flag;end endcase end |
更多回帖