当前位置:   article > 正文

小梅哥Xilinx FPGA学习笔记12——使用状态机实现按键消抖_xilinx 复位按键需要消抖

xilinx 复位按键需要消抖

目录

一、按键工作原理

二 状态机转移图

三 状态机按键消抖代码实现步骤分析

1.设计文件

2.激励文件

3.仿真图


一、按键工作原理

       按键原理图如下图所示。 由原理图可以看出,按键未按下时 IO 口为高电平,按键按下时则变为低电平, 因此系统即可通过检测 IO 的电平来判断按键的状态。
        
       从下图中可以看到按键存在一个反作用弹簧,因此当按下或者松开时均会产生额外的物理抖动,物理抖动便会产生电平的抖动。在按键从按下再到松开的过程中,其电平变化如下图所示,上为理想波形输出,下为实际波形输出。
       上图中,产生的抖动次数以及间隔时间均是不可预期的,这就需要通过滤波来消除抖动可能对外部其他设备造成的影响。一般情况下抖动的总时间会持 20ms 以内。这种抖动,可以通过硬件电路或者逻辑设计的方式来消除,也可 以通过软件的方式完成。其中硬件电路消除抖动适用于按键数目较少的场合。

状态机转移图

首先是处于空闲状态(IDLE),此时等待下降沿的到来,如果下降沿没有到来,那就继续等待;如果下降沿到来了就进入

按下消抖状态(P_FILTER),在P_FILTER状态下要做三件事,第一件事是计时大于20ms则表明按键已经按下,则进入下一状态;第二件事是20ms内检测到上升沿,则表明此时处于抖动状态,立即退回空闲状态。第三件事是20ms内未检测到上升沿,就干巴巴的等待20ms,直至20ms结束仍未有上升沿就进入第一件事。

第三个状态是等待状态(WAIT_R),此时按键已经被按下,这个状态要做的事就是一直检测上升沿的到来,如果上升沿没到来就一直待在等待状态,如果一旦检测到上升沿出现,则立即进入

释放消抖状态R_FILTER),此状态同样要做三件事:第一件事是计时大于20ms则表明按键已经释放,则进入下一状态;第二件事是20ms内检测到下降沿,则表明此时处于抖动状态,立即退回等待状态。第三件事是20ms内未检测到下降沿,就干巴巴的等待20ms,直至20ms结束仍未有下降沿就进入第一件事。

三 状态机按键消抖代码实现步骤分析

1.设计文件

  1. //基于状态机思维的按键消抖功能verilog实现思路
  2. //1.对异步输入信号打拍消除亚稳态
  3. //2.寄存打拍后信号,对比得出上升沿与下降沿标志信号
  4. //3.列出所有状态,编写状态机整体框架
  5. //4.编写各状态间跳转方向以及对应跳转条件
  6. //5.编写状态输出逻辑,在正确时刻输出信号赋值
  7. module key_filter(
  8. input Key,
  9. input Clk,
  10. input Reset_n,
  11. output reg Key_P_Flag,
  12. output reg Key_R_Flag,
  13. output reg Key_State//向外输出过滤后的电平信号,使得输出电平比较干净。
  14. );
  15. reg [29:0]cnt_20ms;//定时20ms计数器
  16. reg [1:0]state;
  17. reg sync_d0_key,sync_d1_key;//定义两个同步D触发器的输出作为输入是为了消除未知信号Key的亚稳态,以及将异步信号Key变为同步信号
  18. reg r_key;//定义下降沿
  19. wire nedge_key;//下降沿定义
  20. wire pedge_key;//下降沿定义
  21. //进行打拍来减小亚稳态
  22. always@(posedge Clk)
  23. sync_d0_key <= Key;
  24. always@(posedge Clk)
  25. sync_d1_key <= sync_d0_key;
  26. always@(posedge Clk)
  27. r_key <= sync_d1_key;
  28. assign nedge_key = (sync_d1_key == 0)&&(r_key == 1);//边沿检测下降沿实现
  29. assign pedge_key = (sync_d1_key == 1)&&(r_key == 0);//边沿检测上升沿实现
  30. localparam IDLE = 0;//localparam是本地参数定义,用于定义一个标识符代表常量,无法进行参数传递,不可修改
  31. localparam P_FILTER = 1; //parameter可以进行参数传递,就是可修改的意思。
  32. localparam WAIT_R = 2;
  33. localparam R_FILTER = 3;
  34. parameter Dly_20ms_cnt = 1000_000-1;
  35. wire time_20ms_reached;
  36. assign time_20ms_reached = (cnt_20ms >= Dly_20ms_cnt);//20ms到来的脉冲信号
  37. //time_20ms_reached脉冲信号的产生
  38. // always@(posedge Clk or negedge Reset_n)
  39. // if(!Reset_n)begin
  40. // cnt_20ms <= 0;
  41. // time_20ms_reached <= 0;
  42. // end
  43. // else if(state==P_FILTER || state==R_FILTER )begin
  44. // if(cnt_20ms == Dly_20ms_cnt)begin
  45. // cnt_20ms <= 0;
  46. // time_20ms_reached <=1;
  47. // end
  48. // else begin
  49. // cnt_20ms <= cnt_20ms +1;
  50. // time_20ms_reached <= 0;
  51. // end
  52. // end
  53. // else begin
  54. // cnt_20ms <= 0;
  55. // time_20ms_reached <= 0;
  56. // end
  57. // wire time_20ms_reached;
  58. // assign time_20ms_reached = cnt_20ms >= Dly_20ms_cnt;
  59. // always@(posedge Clk or negedge Reset_n)
  60. // if(!Reset_n)
  61. // cnt_20ms <= 0;
  62. // else if(state==P_FILTER || state==R_FILTER)
  63. // cnt_20ms <= cnt_20ms + 1;
  64. // else
  65. // cnt_20ms <= 0;
  66. always@(posedge Clk or negedge Reset_n)
  67. if(!Reset_n)begin
  68. state <= IDLE;//复位开始状态处于IDLE空闲态
  69. Key_R_Flag <= 0;
  70. Key_P_Flag <= 0;
  71. cnt_20ms <= 0;//在状态机里面实现,防止计数到1000000
  72. Key_State <= 1;
  73. end
  74. else begin
  75. case(state)
  76. IDLE:
  77. if(nedge_key)
  78. state <= P_FILTER;
  79. else begin
  80. state <= IDLE;
  81. Key_R_Flag <= 0; //告知外界按键已经松开的信号变为0
  82. end
  83. P_FILTER:
  84. if(time_20ms_reached)begin//顺利到达20ms说明按键已经顺利按下
  85. state <= WAIT_R;
  86. Key_P_Flag <= 1; //告知外界按键已经按下
  87. cnt_20ms <= 0;//计时到20ms后直接清零。
  88. Key_State <= 0;//此时外界按键已经按下,所以输出低电平
  89. end
  90. else if(pedge_key)begin
  91. state <= IDLE;
  92. cnt_20ms <= 0;//回到IDLE后清零重新计数
  93. end
  94. else begin
  95. state <= state;
  96. cnt_20ms <= cnt_20ms+1;//其他状态开始计数
  97. end
  98. WAIT_R:
  99. if(pedge_key)
  100. state <= R_FILTER;
  101. else begin
  102. state <= WAIT_R;
  103. Key_P_Flag <= 0;
  104. end
  105. R_FILTER:
  106. if(time_20ms_reached)begin
  107. state <= IDLE;
  108. Key_R_Flag <= 1; //告知外界按键已经松开
  109. cnt_20ms <= 0;//计时到20ms后直接清零。
  110. Key_State <= 1; //此时外界按键已经松开,所以Key_State为高电平,这样输出电平就比较干净
  111. end
  112. else if(nedge_key)begin
  113. state <= WAIT_R;
  114. cnt_20ms <= 0;//回到WAIT_R后清零重新计数
  115. end
  116. else begin
  117. state <= state;
  118. cnt_20ms <= cnt_20ms+1;//其他状态开始计数
  119. end
  120. endcase
  121. end
  122. endmodule

2.激励文件

  1. `timescale 1ns / 1ps
  2. module key_filter_tb();
  3. reg Key;
  4. reg Clk;
  5. reg Reset_n;
  6. wire Key_P_Flag;
  7. wire Key_R_Flag;
  8. wire Key_State;
  9. key_filter key_filter(
  10. .Key(Key),//一个输入信号
  11. .Clk(Clk),
  12. .Reset_n(Reset_n),
  13. .Key_P_Flag(Key_P_Flag),
  14. .Key_R_Flag(Key_R_Flag),
  15. .Key_State(Key_State)
  16. );
  17. initial Clk = 1;
  18. always #10 Clk = ~Clk;
  19. initial begin
  20. Reset_n = 0;
  21. Key = 1;
  22. #201;
  23. Reset_n = 1;
  24. //第一次按下测试
  25. //空闲稳定
  26. Key = 1; #100000000;
  27. //按下抖动
  28. Key = 0; #18000000;//按下抖动 低 18ms
  29. Key = 1; #2000000;//按下抖动 高 2ms
  30. Key = 0; #1000000;//按下抖动 低 1ms
  31. Key = 1; #200000;//按下抖动 高 0.2ms
  32. Key = 0; #20000000;//按下稳定 低 20ms
  33. //按下稳定
  34. Key = 0; #50000000;//按下稳定 低 50ms
  35. //释放抖动
  36. Key = 1; #2000000;//释放抖动 高 2ms
  37. Key = 0; #1000000;//释放下抖动 低 1ms
  38. Key = 1; #20000000;//释放稳定 高 20ms
  39. //释放稳定
  40. Key = 1; #50000000;//释放稳定 高 50ms
  41. //第二次按下测试
  42. //空闲稳定
  43. Key = 1; #100000000;
  44. //按下抖动
  45. Key = 0; #18000000;//按下抖动 低 18ms
  46. Key = 1; #2000000;//按下抖动 高 2ms
  47. Key = 0; #1000000;//按下抖动 低 1ms
  48. Key = 1; #200000;//按下抖动 高 0.2ms
  49. Key = 0; #20000000;//按下稳定 低 20ms
  50. //按下稳定
  51. Key = 0; #50000000;//按下稳定 低 50ms
  52. //释放抖动
  53. Key = 1; #2000000;//释放抖动 高 2ms
  54. Key = 0; #1000000;//释放下抖动 低 1ms
  55. Key = 1; #20000000;//释放稳定 高 20ms
  56. //释放稳定
  57. Key = 1; #50000000;//释放稳定 高 50ms
  58. $stop;
  59. end
  60. endmodule

3.仿真图

从图中可以看见其生成了非常干净标准的Key_State信号。
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Gausst松鼠会/article/detail/402665
推荐阅读
相关标签
  

闽ICP备14008679号