新闻中心

EEPW首页 > 嵌入式系统 > 牛人业话 > 【从零开始走进FPGA】 基于PLD的矩阵键盘状态机控制

【从零开始走进FPGA】 基于PLD的矩阵键盘状态机控制

—— 零基础学FPGA(十八)基于PLD的矩阵键盘状态机控制
作者:时间:2015-03-07来源:网络收藏

  讲过了独立按键检测,理所当然应该讲讲中矩阵键盘的应用了。这个思维和电路在中有所不同,在此,在此做详细解释,Bingo用自己设计的成熟的代码作为案例,希望对你有用。

本文引用地址:http://www.eepw.com.cn/article/270621.htm

  一、矩阵键盘电路图

  在FPGA中的电路,与单片机雷同,如下所示:

  

wps_clip_image-30864

 

  在上电默认情况下,L[3:0] =4''b1,因为上拉了3.3V,而默认情况下H.[3:0]为低电平;一旦有某一个按键被按下,便是是的该路电路流向该按键的H,是的L检测不到电流。因此可以通过对每一行H输出的控制,来检索是哪一个按键被按下了,这也原理和单片机中一样,只是写法不一样罢了。

  二、FPGA矩阵键盘FSM

  1. 代码

  代码如下所示,采用了三段式状态机来描述矩阵键盘。本模块形式与上一张按键消抖动雷同,方便移植。

  /*************************************************

  * 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 2ms signal

  reg [19:0] cnt; //fffff,≈50Hz 20ms

  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. 状态机说明

  (1)以下是该电路的state machine。

  

wps_clip_image-15561

 

  (2)模块可分为一下几个状态:

  

image

fpga相关文章:fpga是什么




关键词: FPGA PLD

评论


相关推荐

技术专区

关闭