找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 3257|回复: 0
打印 上一主题 下一主题
收起左侧

基于FPGA的按键消抖源代码

[复制链接]
跳转到指定楼层
楼主
ID:210107 发表于 2017-6-11 14:52 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
完整代码下载:
正确程序段.docx (31.06 KB, 下载次数: 14)

FPGA中,基于下面的程序,理解如下:在这个程序里检测按键是否按下的方法是脉冲边沿检法。第一次检测到后,启动20ms计数器,时间到后再检测。这里的检测方法跟脉冲边沿检测法有异曲同工之处,FPGA20ms检测按键是否按下,存储检测到的值,并且按位取反与前一个20ms检测的值相与,得到一个值,如果为1,则判断按键按下,否则则无按下。           
                          FPGA按键的理解示意图
    其中key_an寄存器的功能是检测第一次的“按下”,是cnt的启动标志位。通过也能滤除干扰信号。led_ctrl是确实有按键按下的信号,维持一个时钟周期


`timescale 1ns/1ns
module sw_xiaodou(
    clk,  
    rst_n,
    sw1_n,
    sw2_n,
sw3_n,
sw4_n,
    //output
    led_d1,
led_d2,
led_d3
    led_d4
    );
  input   clk;  //主时钟信号50MHz
  input   rst_n; //复位信号低有效。可将其绑为开关开关拨下有效。
  input   sw1_n,sw2_n,sw3_n,Sw4_n; //三个独立按键低表示按下
  output  led_d1,led_d2,led_d3,led_d4; //发光二极管分别由按键控制

// ----------------------------------------------------------------

reg[3:0] key_rst;  

always @(posedge clk  or negedge rst_n)

    if (!rst_n) key_rst <= 4'b1111;

else key_rst <= {sw4_n,sw3_n,sw2_n,sw1_n};

reg[3:0] key_rst_r;       //每个时钟周期的上升沿将low_sw信号锁存到low_sw_r

always @ ( posedge clk  or negedge rst_n )

    if (!rst_n) key_rst_r <= 4'b1111;

    else key_rst_r <= key_rst;


//当寄存器key_rst1变为0时,key_an的值变为高,维持一个时钟周期

wire[3:0] key_an = key_rst_r & ( ~key_rst); //检测到按下的第一次(cnt的启动信号)


  reg [19:0]  cnt; //计数寄存器
  always @ (posedge clk  or negedge rst_n)/*alwaysclk时钟的上升沿
                                     rst_n复位信号的下降沿触发执行*/
    if (!rst_n)   /*异步复位rst_n为低电平即rst_n为高电平时。*/
      cnt <= 20'd0;/*cnt付初值为0*/
else
  if(key_an) cnt <=20'd0;
    else  
      cnt <= cnt + 1'b1;/*cnt计数器自加1*/

  reg  [3:0] low_sw;
always @(posedge clk  or negedge rst_n)/*同上一个always*/
    if (!rst_n)
      low_sw <= 4'b1111;/*赋初值为1111*/
    else if (cnt == 20'hfffff) /*20ms将按键值锁存到寄存器low_sw
                         20hfffff=d1048575  t=1/48000000*1048575=0.021s*/
      low_sw <= {sw4_n,sw3_n,sw2_n,sw1_n};/*将按键sw3_n.sw2_n,sw1_n,用位拼
                                 接符{   }拼接为一个三位的数传给low_sw*/

  // ---------------------------------------------------------------------------

  reg  [3:0] low_sw_r;  /*每个时钟周期的上升沿将low_sw信号锁存到low_sw_r*/
  always @ ( posedge clk  or negedge rst_n )
    if (!rst_n)
      low_sw_r <= 4'b1111;/*初值为1111*/
else
      low_sw_r <= low_sw;

   /*当寄存器low_sw1变为0时led_ctrl的值变为高维持一个时钟周期 */
  wire [3:0] led_ctrl = low_sw_r[3:0] & ( ~low_sw[3:0]);/*找出变化的键存到led_ctrl*/

  reg d1;
  reg d2;
  reg d3;
  reg d4;
always @ (posedge clk or negedge rst_n)
    if (!rst_n)
      begin
        d1 <= 1'b0;
        d2 <= 1'b0;
        d3 <= 1'b0;
        d4 <= 1'b0;
      end
    else  
      begin  //某个按键值变化时LED将做亮灭翻转
        if ( led_ctrl[0] ) d1 <= ~d1;  
        if ( led_ctrl[1] ) d2 <= ~d2;
        if ( led_ctrl[2] ) d3 <= ~d3;
        if ( led_ctrl[3] ) d4<= ~d4;
      end

  assign led_d4 = d1 ? 1'b1 : 1'b0;  //LED翻转输出
  assign led_d3 = d2 ? 1'b1 : 1'b0;
  assign led_d2 = d3 ? 1'b1 : 1'b0;
  assign led_d1 = d4 ? 1'b1 : 1'b0;
endmodule


评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表