正点原子学习小组
直播中

jf_1137202360

8年用户 1359经验值
擅长:嵌入式技术
私信 关注
[经验]

【正点原子DFPGL22G开发板体验】模块化设置-按键控制蜂鸣器

前言
模块化设计是FPGA设计中一个很重要的设计原则,它能够使一个大型设计的分工协作和仿真测试更加容易,使代码维护和升级更加便利。本篇体验由蜂鸣器和按键两个模块组成的按键控制蜂鸣器演示,并考虑按键消抖。
代码分析
1_Verilog3_top_key_beep
模块划分如下,由两个模块key_debouncebeep_control组成
图片1.png
Key_debounce模块
实现消抖,在按键变化时开始定时1000000CLK,
每个CLK递减1,直到减少到1,则认为有按键变化且稳定,设置标志key_flag
如果递减到1之前按键又有变化,则重新从1000000开始递减。
如果递减到0则认为按键一直没变,不再递减,直到等待下一次按键变化。
  1. module key_debounce(

  2. input sys_clk, //外部50M时钟

  3. input sys_rst_n, //外部复位信号,低有效

  4. input key, //外部按键输入

  5. output reg key_flag, //按键数据有效信号

  6. output reg key_value //按键消抖后的数据

  7. );



  8. //reg define

  9. reg [31:0] delay_cnt;

  10. reg key_reg0;

  11. reg key_reg1;



  12. //*****************************************************

  13. //** main code

  14. //*****************************************************

  15. always @(posedge sys_clk or negedge sys_rst_n) begin

  16. if (!sys_rst_n) begin

  17. key_reg0 <= 1'b1;

  18. key_reg1 <= 1'b1;

  19. delay_cnt <= 32'd0;

  20. end

  21. else begin

  22. key_reg0 <= key; //将按键值延迟一拍

  23. key_reg1 <= key_reg0; //将按键值延迟两拍

  24. if(key_reg1 != key_reg0) //一旦检测到按键状态发生变化(有按键被按下或释放)

  25. delay_cnt <= 32'd1000000; //给延时计数器重新装载初始值(计数时间为20ms)

  26. else if(key_reg1 == key_reg0) begin //在按键状态稳定时,计数器递减,开始20ms倒计时

  27. if(delay_cnt > 32'd0)

  28. delay_cnt <= delay_cnt - 1'b1;

  29. else

  30. delay_cnt <= delay_cnt;

  31. end

  32. end

  33. end



  34. always @(posedge sys_clk or negedge sys_rst_n) begin

  35. if (!sys_rst_n) begin

  36. key_flag <= 1'b0;

  37. key_value <= 1'b1;

  38. end

  39. else begin

  40. if(delay_cnt == 32'd1) begin //当计数器递减到1时,说明按键稳定状态维持了20ms

  41. key_flag <= 1'b1; //此时消抖过程结束,给出一个时钟周期的标志信号

  42. key_value <= key_reg1; //并寄存此时按键的值

  43. end

  44. else begin

  45. key_flag <= 1'b0;

  46. key_value <= key_value;

  47. end

  48. end

  49. end

  50. endmodule

beep_contral模块
在按键按下时翻转蜂鸣器输出
  1. module beep_control(

  2. //input

  3. input sys_clk, //系统时钟

  4. input sys_rst_n, //复位信号,低电平有效

  5. input key_flag, //按键有效信号

  6. input key_value, //消抖后的按键信号

  7. output reg beep //蜂鸣器控制信号

  8. );

  9. //*****************************************************

  10. //** main code

  11. //*****************************************************

  12. always @ (posedge sys_clk or negedge sys_rst_n) begin

  13. if(!sys_rst_n)

  14. beep <= 1'b1;

  15. else if(key_flag && (~key_value)) //判断按键是否有效按下

  16. beep <= ~beep;

  17. end

  18. endmodule

顶层模块
例化两个模块
  1. module top_key_beep(

  2. input sys_clk, //时钟信号50Mhz

  3. input sys_rst_n, //复位信号

  4. input key, //按键信号

  5. output beep //蜂鸣器控制信号

  6. );

  7. //wire define

  8. wire key_value;

  9. wire key_flag;



  10. //*****************************************************

  11. //** main code

  12. //*****************************************************



  13. //例化按键消抖模块

  14. key_debounce u_key_debounce(

  15. .sys_clk (sys_clk),

  16. .sys_rst_n (sys_rst_n),

  17. .key (key),

  18. .key_flag (key_flag),

  19. .key_value (key_value)

  20. );

  21. //例化蜂鸣器控制模块

  22. beep_control u_beep_control(

  23. .sys_clk (sys_clk),

  24. .sys_rst_n (sys_rst_n),

  25. .key_flag (key_flag),

  26. .key_value (key_value),

  27. .beep (beep)

  28. );

  29. endmodule

测试
生成bit文件下载,和之前一样不再赘述
测试:按键KEY0,可以开关蜂鸣器,功能OK
总结
这一篇,体验了模块化设计思想和按键消抖的思路,测试了蜂鸣器和按键。

更多回帖

发帖
×
20
完善资料,
赚取积分