新聞中心

EEPW首頁 > 嵌入式系統(tǒng) > 牛人業(yè)話 > 【從零開始走進FPGA】 基于PLD的矩陣鍵盤狀態(tài)機控制

【從零開始走進FPGA】 基于PLD的矩陣鍵盤狀態(tài)機控制

—— 零基礎(chǔ)學FPGA(十八)基于PLD的矩陣鍵盤狀態(tài)機控制
作者: 時間:2015-03-07 來源:網(wǎng)絡 收藏

  講過了獨立按鍵檢測,理所當然應該講講中矩陣鍵盤的應用了。這個思維和電路在中有所不同,在此,在此做詳細解釋,Bingo用自己設計的成熟的代碼作為案例,希望對你有用。

本文引用地址:http://butianyuan.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. 代碼

  代碼如下所示,采用了三段式狀態(tài)機來描述矩陣鍵盤。本模塊形式與上一張按鍵消抖動雷同,方便移植。

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

  * 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. 狀態(tài)機說明

  (1)以下是該電路的state machine。

  

wps_clip_image-15561

 

  (2)模塊可分為一下幾個狀態(tài):

  

image

fpga相關(guān)文章:fpga是什么




關(guān)鍵詞: FPGA PLD

評論


相關(guān)推薦

技術(shù)專區(qū)

關(guān)閉