【Verilog HDL 训练】第 09 天(按键消抖)

举报
李锐博恩 发表于 2021/07/15 03:14:58 2021/07/15
【摘要】 5月7日 按键防抖 1. 用verilog实现按键抖动消除电路,抖动小于15ms,输入时钟12MHz。 在编写Verilog代码之前,先分析下一些前提问题,首先是几个按键(1个,多个),我们以1个和三个为例; 其次是算下按键按下后计数多少后,采样按键值,这个需要简单的运算:输入时钟为12MHz,也就是大约80ns的周期,那么去除15ms的抖动,需要计数多少次呢? 经...

5月7日

按键防抖

1. 用verilog实现按键抖动消除电路,抖动小于15ms,输入时钟12MHz。

在编写Verilog代码之前,先分析下一些前提问题,首先是几个按键(1个,多个),我们以1个和三个为例;

其次是算下按键按下后计数多少后,采样按键值,这个需要简单的运算:输入时钟为12MHz,也就是大约80ns的周期,那么去除15ms的抖动,需要计数多少次呢?

经过计算,大约180000次,换成16进制为:2BF20,如此以来,计数器20位足够保险了。

有了以上的准备工作了,我们开始编写一个按键的按键消抖程序了:


  
  1. `timescale 1ns / 1ps
  2. //
  3. // Company:
  4. // Engineer:
  5. //
  6. // Create Date: 2019/05/07 19:29:37
  7. // Design Name:
  8. // Module Name: key
  9. //
  10. //
  11. module key(
  12. input clk,
  13. input rst_n,
  14. input sw_in,
  15. output reg sw_out
  16. );
  17. //按键本身值为1,按下按键后键值为0.
  18. reg sw_in_r0;
  19. always @ (posedge clk or negedge rst_n) begin
  20. if(!rst_n) begin
  21. sw_in_r0 <= 1;
  22. end
  23. else begin
  24. sw_in_r0 <= sw_in;
  25. end
  26. end
  27. wire edge_l, edge_h;
  28. assign edge_l = sw_in_r0 & (~sw_in); //下降沿检测
  29. assign edge_h = sw_in & (~sw_in_r0);//上升沿检测
  30. wire edge_en; //键值变化后,edge_en变为高
  31. assign edge_en = edge_l | edge_h;
  32. reg [19:0] count;
  33. always @ (posedge clk or negedge rst_n) begin
  34. if(!rst_n) begin
  35. count <= 0;
  36. end
  37. else if(edge_en) begin
  38. count <= 0;
  39. end
  40. else begin
  41. count <= count + 1;
  42. end
  43. end
  44. always @ (posedge clk or negedge rst_n) begin
  45. if(!rst_n) begin
  46. sw_out <= 1'b1;
  47. end
  48. else if(count == 20'h2BF20) begin
  49. sw_out <= sw_in;
  50. end
  51. else begin
  52. ;
  53. end
  54. end
  55. endmodule

再给出3个按键的Verilog描述:(这个之前写过:《按键消抖与LED控制》实验的个人思考与总结


  
  1. `timescale 1ns / 1ps
  2. module sw_debounce(
  3. clk,rst_n,
  4. sw1_n,sw2_n,sw3_n,
  5. sw_out
  6. );
  7. input clk; //主时钟信号
  8. input rst_n; //复位信号,低有效
  9. input sw1_n,sw2_n,sw3_n; //三个独立按键,低表示按下
  10. output [2:0] sw_out;
  11. //---------------------------------------------------------------------------
  12. reg key_rst;
  13. always @(posedge clk or negedge rst_n)
  14. if (!rst_n) key_rst <= 1'b1;
  15. else key_rst <= sw3_n&sw2_n&sw1_n;
  16. reg key_rst_r; //每个时钟周期的上升沿将low_sw信号锁存到low_sw_r中
  17. always @ ( posedge clk or negedge rst_n )
  18. if (!rst_n) key_rst_r <= 1'b1;
  19. else key_rst_r <= key_rst;
  20. //当寄存器key_rst由1变为0时,led_an的值变为高,维持一个时钟周期
  21. wire key_an = key_rst_r & (~key_rst);
  22. /*
  23. key_rst 1 1 1 0 0 1
  24. ~key_rst 0 0 0 1 1 0
  25. key_rst_r 1 1 1 0 0 1
  26. key_an 0 0 1 0 0
  27. */
  28. //---------------------------------------------------------------------------
  29. reg[19:0] cnt; //计数寄存器
  30. always @ (posedge clk or negedge rst_n)
  31. if (!rst_n) cnt <= 20'd0; //异步复位
  32. else if(key_an) cnt <=20'd0;
  33. else cnt <= cnt + 1'b1;
  34. reg[2:0] low_sw;
  35. always @(posedge clk or negedge rst_n)
  36. if (!rst_n) low_sw <= 3'b111;
  37. else if (cnt == 20'h2BF20) //满12ms,将按键值锁存到寄存器low_sw中
  38. low_sw <= {sw3_n,sw2_n,sw1_n};
  39. assign sw_out = low_sw;
  40. endmodule

 

 

2. 记录题目1中用到的工具,操作步骤,遇到的错误和提示信息。

 

工具:Vivado 2018,Notepad++ 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

文章来源: reborn.blog.csdn.net,作者:李锐博恩,版权归原作者所有,如需转载,请联系作者。

原文链接:reborn.blog.csdn.net/article/details/89927569

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。