问答 店铺
热搜: ZYNQ FPGA discuz

QQ登录

只需一步,快速开始

微信登录

微信扫码,快速开始

微信扫一扫 分享朋友圈

已有 14089 人浏览分享

开启左侧

按键去抖

  [复制链接]
14089 10
module Button(Clk,Rst,Sw,Led);// 模块接口
        input Clk;        //时钟信号
        input Rst;        //复位信号
        input [4 : 1] Sw;        //按钮SW输入,按下为0,抬起为1
        output [4 : 1] Led; // 4个led 输出
       
        reg [4 : 1] Led;
       
        reg [4 : 1] Sw1;
        reg [4 : 1] Sw1_r;
        wire [4 : 1] Sample1;
        reg [4 : 1] Sw2;
        reg [4 : 1] Sw2_r;
        wire [4 : 1] Sample2;
       
        reg [19 : 0] cnt;
       
        //第一次读取按键状态
        always @ (posedge Clk , negedge Rst)
                if(!Rst) Sw1 <= 4'b1111;
                else Sw1 <= Sw;
               
        //第一次读取的按键状态放入锁存器
        always @ (posedge Clk , negedge Rst)
                if(!Rst) Sw1_r <= 4'b1111;
                else Sw1_r <= Sw1;
               
        //Sample仅保持一个时钟周期
        assign Sample1 = Sw1_r & (!Sw1);
       
        //延时20MS后,第二次读取按键状态
        always @ (posedge Clk , negedge Rst)
                if(!Rst) Sw2 <= 4'b1111;
                else if (cnt == 20'hF_FFFF) Sw2 <= Sw;
                else Sw2 <= 4'b1111;
               
        //第二次读取的按键状态放入锁存器
        always @ (posedge Clk , negedge Rst)
                if(!Rst) Sw2_r <= 4'b1111;
                else Sw2_r <= Sw2;
       
        //Sample2仅保持一个时钟周期
        assign Sample2 = Sw2_r & (!Sw2);
       
        //计数器,定时20MS
        always @ (posedge Clk , negedge Rst)
                if(!Rst) cnt <= 0;
                else if (Sample1) cnt <= 0;
                else cnt <= cnt + 1'b1;
       
        //LED控制
        always @ (posedge Clk , negedge Rst)
                if(!Rst) Led <= 4'b0000;
                else if (Sample2) Led <= Sample2;
                else Led <= 4'b0000;
               
endmodule





求大神帮忙看看,我这个按键去抖有什么问题,我发现在sample1就出不来正确的波形。
另外,求大神讲下教程里的去抖程序,我有点看不懂。

评论 10

贾文洋  新手上路  发表于 2016-1-6 11:07:48 | 显示全部楼层
你程序是有问题的,sw你也没有用上,你两次采样之后必须判断。建议参考教程状态机那种写法!
贾文洋  新手上路  发表于 2016-1-6 11:18:51 | 显示全部楼层
教程上的意思是五个状态,每10ms检测一次,如果第一次检测是低电平,第二次检测还是低电平,则说明按键被按下,low_flg置1;然后继续检测当检测到一次高电平,又隔10ms检测到高电平,则说明按键被释放,high_flag置1。即完成一次按下与释放的过程。看懂这个程序,你得熟悉状态机的写法!
Damon  新手上路  发表于 2016-1-6 11:20:49 | 显示全部楼层
贾文洋 发表于 2016-1-6 11:07
你程序是有问题的,sw你也没有用上,你两次采样之后必须判断。建议参考教程状态机那种写法!

谢谢大神。
还有几个问题。
以下是第一次采样的程序。
关于你说的SW没有用的问题,这边SW用上了。

     //第一次读取按键状态
        always @ (posedge Clk , negedge Rst)
                if(!Rst) Sw1 <= 4'b1111;
                else Sw1 <= Sw;      //这边SW用上了呀。
               
        //第一次读取的按键状态放入锁存器
        always @ (posedge Clk , negedge Rst)
                if(!Rst) Sw1_r <= 4'b1111;
                else Sw1_r <= Sw1;
               
        //Sample仅保持一个时钟周期
        assign Sample1 = Sw1_r & (!Sw1);
仿真出来的波形,也是到sample1就没有了 ,貌似是   assign Sample1 = Sw1_r & (!Sw1);没有执行的样子。
   
Damon  新手上路  发表于 2016-1-6 11:21:21 | 显示全部楼层
这是仿真出来的波形,大神可以参考下。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
贾文洋  新手上路  发表于 2016-1-6 11:31:38 | 显示全部楼层
你这样写的话,也正确,但不可能没有sample1.你这程序我仔细看了一下没有问题,仿真没出波形?
Damon  新手上路  发表于 2016-1-6 11:34:45 | 显示全部楼层
贾文洋 发表于 2016-1-6 11:31
你这样写的话,也正确,但不可能没有sample1.你这程序我仔细看了一下没有问题,仿真没出波形?

对的,而且是前仿真,就是sample1出不来,好像assign不运行。
而且SW1,SW1_R都有,就是在他们2个有差异的时钟周期,没有sample1.
贾文洋  新手上路  发表于 2016-1-6 14:06:01 | 显示全部楼层
本帖最后由 贾文洋 于 2016-1-6 14:14 编辑

你试试把前两个always语句合并一下!
Damon  新手上路  发表于 2016-1-6 14:28:44 | 显示全部楼层
贾文洋 发表于 2016-1-6 14:06
你试试把前两个always语句合并一下!

还是不行,仿真出来的,跟之前的一样。
贾文洋  新手上路  发表于 2016-1-6 15:47:41 | 显示全部楼层
QQ上回复我,给你解决一下!
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

0

关注

1

粉丝

4

主题
精彩推荐
热门资讯
网友晒图
图文推荐

  • 微信公众平台

  • 扫描访问手机版