CrazyBingo

矩阵键盘Verilog程控简析

0
阅读(4120)

矩阵键盘Verilog程控简析

目 录

1. 写在前面的话 1

2. 矩阵键盘程控简析 1

2.1. PCB原理图设计 1

2.2. 键盘工作简析 2

2.2.1. 工作流程 2

2.2.2. 状态机 3

2.2.3. 仿真图 4

2.3. 时序及编码 4

1.写在前面的话

NND当年写的代码让我恶心了半死,瞅了半天时间重新开始架构!以前没用Mdelsim瞎JB乱搞,现在会了Modelsim各种不放心,没有仿真过的代码不是一个可靠的代码!

问题是以前的代码Load进去竟然不行,可是神奇的是重新搞原理,Modelsim完美之后一下再进去就Perfect,得出一个结论:“永远不要相信任何人,包括你自己!”

2.矩阵键盘程控简析

2.1.PCB原理图设计

wps_clip_image-22530

wps_clip_image-23979

wps_clip_image-18686

wps_clip_image-27660

2.2.键盘工作简析

2.2.1.工作流程

1) 默认:

Row[3:0]为输入,默认为4'b1111,因为电阻上拉

Col[3:0]为输出,默认输出4'b0000,保证按键按下时电流流向Col[3:0]

2) 当某一按键按下时,电流流向Col[x]=1,相应Row[x]=0

3) 通过循环Col键值扫描,代码如下:

case(next_state) SCAN_IDLE : begin col_data <= 4'b0000; //ensure current can flow when key is down row_data_r <= 4'b0000; col_data_r <= 4'b0000; end //SCAN_JITTER1: SCAN_COL0 : col_data <= 4'b1110;//scan the 1th row if the key is downSCAN_COL1 : col_data <= 4'b1101; //scan the 2th row if the key is down SCAN_COL2 : col_data <= 4'b1011;//scan the 3th row if the key is downSCAN_COL3 : col_data <= 4'b0111;//scan the 4th row if the key is downSCAN_READ : begin row_data_r <= row_data;//register the sudden col_datacol_data_r <= col_data;//register the sudden row_dataend//SCAN_JITTER2:default:;//default vauleEndcase

当col_data为某一值的时候,若row_data!=4'b1111,则可确定是该列的键被按下!从而可以通过{row_data,col_data}来确定被按下的键。

1.1.1. 状态机

采用三段式状态机描述整个矩阵键盘的扫描状态控制,状态如下:

parameter SCAN_IDLE = 3'd0; 表示初始化状态 parameter SCAN_JITTER1= 3'd1; 表示消抖动状态 parameter SCAN_COL0 = 3'd2; 表示Col0检测状态 parameter SCAN_COL1 = 3'd3; 表示Col1检测状态 parameter SCAN_COL2 = 3'd4; 表示Col2检测状态 parameter SCAN_COL3 = 3'd5; 表示Col3检测状态 parameter SCAN_READ = 3'd6; 表示读取{Row[3:0],Col[3:0]}键值 parameter SCAN_JITTER2= 3'd7; 表示按键松手检测

其中消抖动为了简便,做了20ms状态检测计,如下:

//---------------------------------------//generate for 20ms signallocalparam KEY_DELAY = 20'hf_ffff; //50MHz, 20ms reg [19:0] delay_cnt; always @(posedge clk or negedge rst_n) begin if(!rst_n) delay_cnt <= 0; else if(delay_cnt < KEY_DELAY) //(current_state == SCAN_JITTER1) delay_cnt <= delay_cnt + 1'b1;elsedelay_cnt <= 20'd0; end wire delay_20ms = (delay_cnt == KEY_DELAY) ? 1'b1 : 1'b0;//keyisdown

状态机如下:

wps_clip_image-22801

1.1.1. 仿真图

通过testbench仿真,符合预期目标,结果如下:

wps_clip_image-31361

时序及编码

case({row_data_r, col_data_r}) 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

每次接受到key_flag一个触发的高电平,表示按键按下,可以直接读取键值,进行相应的操作!接口如下:

//----------------------------------------------//the target component instantiationmatrix_key_scan u_matrix_key_scan ( .clk (clk),//global clock.rst_n (rst_n),//global reset.row_data (row_data),//row data: pull-up with 3.3V.col_data (col_data),//column data: for key scan.key_flag (key_flag),//the mark of key is pressed.key_value (key_value)//the returned value of matrix key);
Baidu
map