行列按键控制(FPGA学习笔记五)

对行列按键的学习与实现,包含行列按键的原理、FPGA的完整实现过程,使用FPGA开发板artix-7A35ftg256-1。


一、行列按键基本原理

1.原理图分析

  4行4列,共8个引脚,控制16个按键。其中每一列需要额外添加下拉电阻。行输入,列输出,根据输入输出的结果判断按键的位置

示例:pandas 是基于NumPy 的一种工具,该工具是为了解决数据分析任务而创建的。
在这里插入图片描述

下拉电阻可以在约束文件中体现。
设计思路:1.逐行扫描,检测被按下的键,输出至一个8维数组中
2.将数组与key0~key15对应起来

2.按键消抖

  按键消抖通常的按键所用开关为机械弹性开关,当机械触点断开、闭合时,由于机械触点的弹性作用,一个按键开关在闭合时不会马上稳定地接通,在断开时也不会一下子断开。因而在闭合及断开的瞬间均伴随有一连串的抖动,一般来说,抖动会持续5ms~20ms(取决于机械特性)。为了不产生这种现象而作的措施就是按键消抖。

在这里插入图片描述


去抖设计:声明3个寄存器btn0、btn1、btn2,并将它们组合成移位寄存器,将移位方向定义为btn0->btn1->btn2。将按键输入送btn0。每隔20ms执行一次移位。在每20ms后,btn0中存储的是当前的按键电平,btn1中存储的是20ms之前的按键电平,btn2中存储的是40ms之前的按键电平。

在这里插入图片描述


若判断按下,则结果为1
[btn0,btn1,btn2]若检测到011,111,110,则认为当前按键被按下;
反之[btn0,btn1,btn2]若检测到001,100,000,则认为当前按键松开
至于010和101则认为状态不存在

  assign btn_out = (btn2&btn1&btn0)|(~btn2&btn1&btn0)|(btn2&btn1&~btn0); //当40ms内按键的值不发生变化,认为输出为高电平

二、FPGA实现

1.时钟分频

  对于FPGA开发板artix-7A35ftg256-1,一般设置为50Mhz,通过下列代码实现(因为系统 #1=1ns)

assign #10 clk=~clk;

  之后在50MHz时钟的基础上,又进行了25000分频和500000分频,得到1KHz和50HZ时钟

代码如下:

module v_divclk(
    input clk,
    output clk_ms,
    output clk_btn
    );
    parameter  divclk_ms=25000,divclk_btn=500000;
    reg clk_ms=1;
    reg clk_btn=1;
    reg [31:0]cnt_ms=0;
    reg [31:0]cnt_btn=0;
    always @(posedge clk) begin
        if(cnt_ms==divclk_ms)begin
            cnt_ms=0;
            clk_ms=~clk_ms;
        end    
        else begin
            cnt_ms=cnt_ms+1;
        end
    end
    always @(posedge clk) begin
        if(cnt_btn==divclk_btn)begin
            cnt_btn=0;
            clk_btn=~clk_btn;
        end    
        else begin
            cnt_btn=cnt_btn+1;
        end
    end
endmodule

2.按键模块

2.1 设计代码

module v_xd_test(
    input clk,
    input clk_btn,
    input [3:0]col,
   output [3:0]row,
    output [15:0]btn_out
    );
    reg [3:0]row=4'b0001;
    reg[15:0]btn0,btn1,btn2,btn3;
    wire[3:0]col;
    wire[15:0]btn_out;
    
    //*********scan the row**********//
   always @(posedge clk)begin
       if (row[3:0]==4'b1000) begin
           row[3:0]=4'b0001;
       end
      else begin
          row[3:0]=row[3:0]<<1;
      end
    end

        
    //************assign the value***************//
    always @(posedge clk)begin
        case(row[3:0])
            4'b0001:btn0[3:0]=col[3:0];
            4'b0010:btn0[7:4]=col[3:0]; 
            4'b0100:btn0[11:8]=col[3:0];
            4'b1000:btn0[15:12]=col[3:0]; 
            default:btn0=16'b0;
         endcase
  
    end
    
    //************** disappears shakes**************//
    always@ (posedge clk_btn) begin
          btn1<=btn0;
          btn2<=btn1;
          btn3<=btn2;
                  
    end
    assign btn_out= (btn2&btn1&btn3)|(~btn3&btn1&btn2);
   
 
endmodule


3.数码管显示

module v_smg(
    input clk,
    input [15:0]sw,
    output [7:0]seg,
    output [3:0]DIG
    );
    reg clkDiv=0;
    reg [31:0]clkCnt=0;
    reg [2:0]bit=0;
    reg [3:0]disp_bat;
    reg [5:0]DIG;
    reg [7:0]seg;
    parameter clkNum=25000;
    always@(posedge clk) begin
        if (clkCnt==clkNum) begin
            clkDiv=~clkDiv;
            clkCnt=0;
        end
        else begin
            clkCnt=clkCnt+1;
        end
    end
    always@(posedge clkDiv) begin
        if(bit>5) begin
            bit=0;
        end
        else begin
        bit=bit+1;
        end
        case (bit)
            3'h0: 
            begin
            disp_bat=sw[3:0];
            DIG=6'b111110;
            end
            3'h1: 
            begin
            disp_bat=sw[7:4];
             DIG=6'b111101;
            end
            3'h2: 
            begin
            disp_bat=sw[11:8];
            DIG=6'b111011;
            end
            3'h3: 
            begin
            disp_bat=sw[15:12];
            DIG=6'b110111;
            end
            default: 
            begin
            disp_bat=sw[3:0];
             DIG=6'b111111;
            end
       endcase
  end
       always@(disp_bat) begin
            case(disp_bat) 
               4'h0: seg=8'h3f;
               4'h1: seg=8'h06;     
               4'h2: seg=8'h5b;
               4'h3: seg=8'h4f;
               4'h4: seg=8'h66;
               4'h5: seg=8'h6d;
               4'h6: seg=8'h7d;
               4'h7: seg=8'h07; 
               4'h8: seg=8'h7f;
               4'h9: seg=8'h6f;
               4'ha: seg=8'h88;
               4'hb: seg=8'h83;
               4'hc: seg=8'hc6;
               4'hd: seg=8'ha1;
               4'he: seg=8'h86;
               4'hf : seg=8'h8e;
            endcase
       end
endmodule

4.顶层文件

module v_keyboard(
    input clk,
    input [7:0]sw,
    output [3:0]row,
    input [3:0]col,
    output [5:0]DIG,
    output [7:0]seg,
    output [11:0]led
    );

    reg [31:0]divclk_cnt=0;
    reg [31:0]btn_clk=0;
    reg [11:0]led;                     

    reg [9:0]ms=0;
    wire [15:0]dispdata;
    wire [15:0]btnout;
    reg [15:0]btn_out0,btn_out1,btn_down;
    reg [3:0]sec_l=0,sec_h=0,min_l=0,min_h=0;      //minute,second
    assign dispdata={min_h,min_l,sec_h,sec_l};      // display time   
    
    v_smg ttra(
    .clk(clk),
    .sw(dispdata),
    .seg(seg),
    .DIG(DIG)
    );
        
    v_divclk uuc(
    .clk(clk),
    .clk_ms(divclk),   //1khz
    .clk_btn(btnclk)   //50hz
    );
     v_xd_test ctta(
    .clk(clk),
    .clk_btn(btnclk),
    .col(col),
    .row(row),
    .btn_out(btnout)
    );
    
 /***************use led to test the button**********************/   

always @ (posedge divclk)begin    
    led<=btnout[11:0];
end 

    
   always @(posedge divclk) begin
        btn_out0<=btnout;     //after finshing the block,the value of btn_out0 changes
     btn_out1<=btn_out0;
      btn_down<=btn_out0&~btn_out1;
    end
    // if sw[0]==0, it's timer;else you can set the value of second,minute...
    always@ (posedge divclk) begin
        if(sw[0]==0)  begin//fisplay the time
            ms=ms+1;
            if(ms==1000) begin
                ms=0;
                sec_l=sec_l+1;
            end        
            if(sec_l==10) begin
                sec_h=sec_h+1;
                sec_l=0;
            end
            if (sec_h==6) begin
                sec_h=0;
                min_l=min_l+1;
            end
            if(min_l==10) begin
                min_l=0;
                min_h=min_h+1;
            end
            if (min_h==6) begin
                min_h=0;
            end
        end   
        else begin
          // set the four buttons,they have the different fuctions
            if(btn_down[0]==1) begin
                sec_l=0;
                sec_h=0;
                min_l=0;
                min_h=0;
            end 
            else begin
                if(btn_down[1]==1) begin
                    sec_l=sec_l+1;
                    if(sec_l==10) begin
                        sec_l=0;
                    end
                end
                if(btn_down[2]==1) begin
                    sec_h=sec_h+1;
                    if(sec_h==6) begin
                        sec_h=0;
                    end
                end
                if(btn_down[3]==1) begin
                    min_l=min_l+1;
                    if(min_l==10) begin
                        min_l=0;
                    end
                end
                if(btn_down[4]==1) begin
                    min_h=min_h+1;
                    if(min_h==6) begin
                        min_h=0;
                    end
                end        
            end
        end        
   end
endmodule


5.约束文件

## CLK
set_property PACKAGE_PIN D4 [get_ports clk]
set_property IOSTANDARD LVCMOS33 [get_ports clk]  

## switches 
set_property PACKAGE_PIN F3 [get_ports {sw[11]}]
set_property IOSTANDARD LVCMOS33 [get_ports {sw[11]}]  
set_property PACKAGE_PIN H4 [get_ports {sw[10]}]
set_property IOSTANDARD LVCMOS33 [get_ports {sw[10]}]  
set_property PACKAGE_PIN N4 [get_ports {sw[9]}]
set_property IOSTANDARD LVCMOS33 [get_ports {sw[9]}]  
set_property PACKAGE_PIN R2 [get_ports {sw[8]}]
set_property IOSTANDARD LVCMOS33 [get_ports {sw[8]}]  
set_property PACKAGE_PIN R3 [get_ports {sw[7]}]
set_property IOSTANDARD LVCMOS33 [get_ports {sw[7]}]  
set_property PACKAGE_PIN P4 [get_ports {sw[6]}]
set_property IOSTANDARD LVCMOS33 [get_ports {sw[6]}]  
set_property PACKAGE_PIN R5 [get_ports {sw[5]}]
set_property IOSTANDARD LVCMOS33 [get_ports {sw[5]}]  
set_property PACKAGE_PIN P6 [get_ports {sw[4]}]
set_property IOSTANDARD LVCMOS33 [get_ports {sw[4]}]  
set_property PACKAGE_PIN R6 [get_ports {sw[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {sw[3]}]  
set_property PACKAGE_PIN T7 [get_ports {sw[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {sw[2]}]  
set_property PACKAGE_PIN T8 [get_ports {sw[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {sw[1]}]  
set_property PACKAGE_PIN T9 [get_ports {sw[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports {sw[0]}]  
## SEG  A~G DP=seg[0]~seg[7]
set_property PACKAGE_PIN P11 [get_ports {seg[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports {seg[0]}]
set_property PACKAGE_PIN N12 [get_ports {seg[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {seg[1]}]
set_property PACKAGE_PIN L14 [get_ports {seg[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {seg[2]}]
set_property PACKAGE_PIN K13 [get_ports {seg[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {seg[3]}]
set_property PACKAGE_PIN K12 [get_ports {seg[4]}]
set_property IOSTANDARD LVCMOS33 [get_ports {seg[4]}]
set_property PACKAGE_PIN P13 [get_ports {seg[5]}]
set_property IOSTANDARD LVCMOS33 [get_ports {seg[5]}]
set_property PACKAGE_PIN M14 [get_ports {seg[6]}]
set_property IOSTANDARD LVCMOS33 [get_ports {seg[6]}]
set_property PACKAGE_PIN L13 [get_ports {seg[7]}]
set_property IOSTANDARD LVCMOS33 [get_ports {seg[7]}]
##  DIG
set_property PACKAGE_PIN G12 [get_ports {DIG[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports {DIG[0]}]
set_property PACKAGE_PIN H13 [get_ports {DIG[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {DIG[1]}]
set_property PACKAGE_PIN M12 [get_ports {DIG[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {DIG[2]}]
set_property PACKAGE_PIN N13 [get_ports {DIG[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {DIG[3]}]
set_property PACKAGE_PIN N14 [get_ports {DIG[4]}]
set_property IOSTANDARD LVCMOS33 [get_ports {DIG[4]}]
set_property PACKAGE_PIN N11 [get_ports {DIG[5]}]
set_property IOSTANDARD LVCMOS33 [get_ports {DIG[5]}]
## col
set_property PACKAGE_PIN R12  [get_ports {col[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports {col[0]}] 
set_property PACKAGE_PIN T12  [get_ports {col[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {col[1]}] 
set_property PACKAGE_PIN R11  [get_ports {col[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {col[2]}] 
set_property PACKAGE_PIN T10 [get_ports {col[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {col[3]}] 
set_property PULLDOWN true [get_ports {col[3]}]
set_property PULLDOWN true [get_ports {col[2]}]
set_property PULLDOWN true [get_ports {col[1]}]
set_property PULLDOWN true [get_ports {col[0]}]

##  row
set_property PACKAGE_PIN K3  [get_ports {row[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports {row[0]}] 
set_property PACKAGE_PIN M6  [get_ports {row[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {row[1]}] 
set_property PACKAGE_PIN P10  [get_ports {row[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {row[2]}] 
set_property PACKAGE_PIN R10  [get_ports {row[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {row[3]}] 
## LED  
set_property PACKAGE_PIN E3 [get_ports {led[11]}]
set_property IOSTANDARD LVCMOS33 [get_ports {led[11]}]
set_property PACKAGE_PIN H3 [get_ports {led[10]}]
set_property IOSTANDARD LVCMOS33 [get_ports {led[10]}]
set_property PACKAGE_PIN G5 [get_ports {led[9]}]
set_property IOSTANDARD LVCMOS33 [get_ports {led[9]}]
set_property PACKAGE_PIN R1 [get_ports {led[8]}]
set_property IOSTANDARD LVCMOS33 [get_ports {led[8]}]
set_property PACKAGE_PIN T2 [get_ports {led[7]}]
set_property IOSTANDARD LVCMOS33 [get_ports {led[7]}]
set_property PACKAGE_PIN T3 [get_ports {led[6]}]
set_property IOSTANDARD LVCMOS33 [get_ports {led[6]}]
set_property PACKAGE_PIN T4 [get_ports {led[5]}]
set_property IOSTANDARD LVCMOS33 [get_ports {led[5]}]
set_property PACKAGE_PIN N6 [get_ports {led[4]}]
set_property IOSTANDARD LVCMOS33 [get_ports {led[4]}]
set_property PACKAGE_PIN T5 [get_ports {led[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {led[3]}]
set_property PACKAGE_PIN R7  [get_ports {led[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {led[2]}]
set_property PACKAGE_PIN R8 [get_ports {led[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {led[1]}]
set_property PACKAGE_PIN P9 [get_ports {led[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports {led[0]}]
endmodule
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值