1、 按键消抖实验 1. 2. 3. 4. 5. 6. 7. 8. 9. module anjianxiaodou(clk,rst_n,sw1_n,sw2_n,sw3_n,led_d1,led_d2,led_d3); input clk; //主时钟信号,50MHZ input rst_n; //复位信号,低电平有效 input sw1_n,sw2_n,sw3_n; //3个独立按键,低表示按下 output led_d1,led_d2,led_d3; //发光二极管,分别由按键控制 //---------------------------------------------------------- 10. reg[2:0] key_rst; //按键复位,低电平有效 11. 12. always @(posedge clk or negedge rst_n) 13. 14. 15. 16. reg[2:0] key_rst_r; //每个时钟周期的上升沿将key_rst信号所存到key_rst_r中 17. 18. always @(posedge clk or negedge rst_n) 19. 20. 21. if(!rst_n) key_rst_r <= 3'b111; else key_rst_r <= key_rst; //key_rst_r为key_rst延迟一个时钟周期 if (!rst_n) key_rst <= 3'b111; else key_rst <= {sw3_n,sw2_n,sw1_n}; 22. wire[2:0] key_an = key_rst_r & (~key_rst); //当寄存器key_rst由1变为0时,key_an的值为高并维持一个时钟周期,实际上时获取key_rst的下降沿 23. 24. //------------------------------------------------------------- 25. 26. reg[19:0] cnt; //计数寄存器2^20约等于10^6 27. 28. always @ (posedge clk or negedge rst_n) //该always进程用来判断是抖动还是真的有按键按下,若真的按键按下,则计数会达到20‘hfffff 29. 30. if(!rst_n) cnt <= 20'd0; //异步复位 else if (key_an) cnt <= 20'd0;//key_an为1可能是因为抖动产生,此处若是抖动,时间必定小于20ms,则计数清零,下面不锁存按键的值 31. else cnt <= cnt + 1'b1;//(10^6)*20ns = 20ms,若是人为按下按键,按下持续时间必定大于20ms。下面判断大于20ms才保存按键的值
32. 33. reg [2:0] low_sw; 34. 35. always @ (posedge clk or negedge rst_n) //判断是否真的按键按下,若真的按下,保存按键值 36. 37. 38. if(!rst_n) low_sw <= 3'b111; else if(cnt == 20'hfffff) low_sw <= {sw3_n,sw2_n,sw1_n};//满20ms,将按键值锁存到low_sw中 39. reg [2:0] low_sw_r; //每个时钟周期的上升沿将low——sw信号锁存到low_sw_r中 40. 41. always @ (posedge clk or negedge rst_n) 42. 43. 44. if(!rst_n) low_sw_r <= 3'b111; else low_sw_r <= low_sw; 45. wire [2:0] led_ctrl = low_sw_r[2:0] & (~low_sw[2:0]);//当寄存器low_sw由1变为0时,led_ctrl的值变为高,维持1个时钟周期 46. 47. reg d1; 48. reg d2; 49. reg d3; 50. 51. always @ (posedge clk or negedge rst_n) 52. 53. 54. 55. 56. 57. 58. 59. 60. 61. 62. 63. 64. if(!rst_n) begin d1 <= 1'b0; d2 <= 1'b0; d3 <= 1'b0; end else begin end if(led_ctrl[0]) d1 <= ~ d1; if(led_ctrl[1]) d2 <= ~ d2; if(led_ctrl[2]) d3 <= ~ d3; 65. assign led_d3 = d1 ? 1'b1 : 1'b0;//LED翻转 66. assign led_d2 = d2 ? 1'b1 : 1'b0;
67. assign led_d1 = d3 ? 1'b1 : 1'b0; 68. 69. endmodule