用FPGA设计矩阵键盘

矩阵键盘介绍:

矩阵键盘是使用8个io口来进行16个按键的控制读取,用4条I/O线作为行线,4条I/O线作为列线组成的键盘。在行线和列线的每个交叉点上,设置一个按键。
如图所示:

矩阵键盘扫描的方式有两种: 1.行列扫描2.逐行/逐列扫描

行列扫描:

将P口的高四位(代表四个行)设置为高电平,将P口的低四位(代表四个列)设置为输入口;行扫描,等待按键被按下,读取P1口的低四位,检查哪一位从低电平变为高电平。列扫描:将P口的高四位(四个行)设置为低电平,将P口的低四位(四个列)设置为高电平。读取P口的低四位,检查哪一位从高电平变为低电平。将两次读取结果组合起来就可以得到当前按键的特征编码。

逐行/逐列扫描:

是给某一行/某一列,高电平,其余七个全部为底电平,这时候读取电平变换,有电平变高表示按键按下,结合给出的行列关系,即可读取按键数据。

实验目的:设计一个可以读取按键按下数据的矩阵键盘

(本实验用的是逐行/逐列扫描方式)

模块框图:

key4x4模块代码

module key4x4
(
    input wire clk_50Mhz          ,    //系统时钟50Mhz
    input wire rst_n              ,    //全局复位
    input wire [3:0]data_in       ,    //输入逐行扫描信号
    
    output reg flag_data          ,    //flag_data为1时表示消抖后检测到按键被按下,维持一个时钟的高电平
    output reg [3:0]data          ,    //输出按键的特征编码
    output reg [3:0]data_out           //输出逐列扫描信号

);
    
     //SUM_MAX> SUM_KEY_20MS               
parameter SUM_MAX =21'd1_999_999;            
parameter SUM_KEY_20MS =22'd999_999;      
    

reg [20:0] num;
reg [19:0] num_10ms;

reg [1:0] qs;


//每隔40ms产生一次内部触发信号
always@(  posedge  clk_50Mhz or negedge rst_n) begin 
    if (rst_n==1'b0) begin
        num <= 22'd0;
    end
    else if (num == SUM_MAX) begin
        num <= 22'd0;
    end
    else begin
        num <= num +22'd1;
    end
end 

//产生逐列扫描信号
always@(  posedge  clk_50Mhz or negedge rst_n) begin 
    if (rst_n==1'b0) begin
        qs <=2'd0; 
    end      
    else if(num_10ms == SUM_KEY_20MS) begin
        qs <= qs ;
    end     
    else if(num == SUM_MAX) begin
        qs <= qs +2'd1;
    end       
end 

//输出逐列扫描信号
always @(posedge clk_50Mhz or negedge rst_n) begin  
    if(rst_n ==1'b0) begin
        data_out<= 4'b1111;
    end
    else begin
        case (qs)
            2'b00:data_out<= 4'b0001; 
            2'b01:data_out<= 4'b0010; 
            2'b10:data_out<= 4'b0100; 
            2'b11:data_out<= 4'b1000; 
            default:data_out<= 4'b1111;        
        endcase          
    end 
end
                  
//得到当前按键的特征编码    
always @(posedge clk_50Mhz or negedge rst_n) begin   
    if(rst_n==1'b0)begin
        data <=4'b0000;
    end
    else begin
            case ({data_out,data_in})         
                8'b0001_0001 :          data <=4'b0000; //0
                8'b0001_0010 :          data <=4'b0001; //1
                8'b0001_0100 :          data <=4'b0010; //2
                8'b0001_1000 :          data <=4'b0011; //3

                8'b0010_0001 :          data <=4'b0100; //4                    
                8'b0010_0010 :          data <=4'b0101; //5
                8'b0010_0100 :          data <=4'b0110; //6
                8'b0010_1000 :          data <=4'b0111; //7

                8'b0100_0001 :          data <=4'b1000; //8
                8'b0100_0010 :          data <=4'b1001; //9
                8'b0100_0100 :          data <=4'b1010; //10
                8'b0100_1000 :          data <=4'b1011; //11

                8'b1000_0001 :          data <=4'b1100; //12
                8'b1000_0010 :          data <=4'b1101; //13
                8'b1000_0100 :          data <=4'b1110; //14
                8'b1000_1000 :          data <=4'b1111; //15

                default: data <= data; 
            endcase     
    end
end  

//消抖部分
always@(  posedge  clk_50Mhz or negedge rst_n) begin 
    if (rst_n==1'b0) begin
        num_10ms <=22'd0;
    end   
    else if (data_in== 4'b0000) begin
        num_10ms <=22'd0;
    end   
    else if ((num_10ms == SUM_KEY_20MS)&&(data_in !=4'b0000)) begin
        num_10ms <= num_10ms;
    end
    else begin
        num_10ms <= num_10ms+22'd1;
    end
end

//flag_data,产生一个时钟的高电平
always@(  posedge  clk_50Mhz or negedge rst_n) begin 
    if (rst_n==1'b0) begin
        flag_data <=1'd0;
    end   
    else if (num_10ms == SUM_KEY_20MS-1) begin
        flag_data <=1'd1;
    end
    else begin
        flag_data <=1'd0; 
    end
end 
endmodule

  • 7
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值