当前位置:   article > 正文

二、15【FPGA】呼吸灯实现_fpga呼吸灯实验报告

fpga呼吸灯实验报告

前言

学习说明此文档为本人的学习笔记,注重实践,关于理论部分会给出相应的学习链接。

学习视频:是根据野火FPGA视频教程——第十八讲
https://www.bilibili.com/video/BV1nQ4y1Z7zN?p=3

实战演练

一、设计规划

1.1 实验目标

开发板上实现LED灯实现呼吸灯效果,工作原理是利用PWM来控制小灯在相同的时间段内的不同占空比,即在同样小时间段内,小灯亮的时间依次增加到最大后再依次减少,从而实现渐亮到渐灭的“呼吸”效果。

1.2 硬件资源

这里采用野火的升腾mini板进行实验

led灯原理图

二、程序设计

2.1 波形图绘制 

PWM占空比控制灯亮的程度,假设led灯亮1s灭1s,实现渐亮与渐灭,由于两者类似只说渐亮。

为使渐亮的更细腻,这里将1s分为1000份,即1ms为一个时间周期,控制1ms时间内的导通时间即可以控制led灯的亮度,这里将1ms分为1000个小段(即1us),控制渐亮如:第一个1ms内让其导通1us;第二个1ms内导通2us;第三个1ms内导通3us;......;第1000个1ms内导通999us。逐渐,变灭与之相反。为区分渐亮与渐灭的时间,这里添加1s的时间标志cnt_en,1s后标志进行取反,当高电平时执行渐亮,当低电平时执行渐灭

2.2 代码编写

为了便于仿真代码对程序进行仿真,这里将计数器最大常数用parameter在模块前定义

  1. module breath_led
  2. #(
  3. parameter CNT_1US_MAX = 6'd49 ,
  4. parameter CNT_1MS_MAX = 10'd999 ,
  5. parameter CNT_1S_MAX = 10'd999
  6. )
  7. (
  8. input wire sys_clk ,
  9. input wire sys_rst_n,
  10. output reg led_out
  11. );
  12. reg [5:0] cnt_1us;
  13. reg [9:0] cnt_1ms;
  14. reg [9:0] cnt_1s;
  15. reg cnt_en;
  16. //us计数器
  17. always@(posedge sys_clk or negedge sys_rst_n)
  18. if(sys_rst_n == 1'b0)
  19. cnt_1us <= 6'd0;
  20. else if(cnt_1us == CNT_1US_MAX)
  21. cnt_1us <= 6'd0;
  22. else
  23. cnt_1us <= cnt_1us + 6'd1;
  24. //ms计数器
  25. always@(posedge sys_clk or negedge sys_rst_n)
  26. if(sys_rst_n == 1'b0)
  27. cnt_1ms <= 10'd0;
  28. else if((cnt_1ms == CNT_1MS_MAX) && (cnt_1us == CNT_1US_MAX))
  29. cnt_1ms <= 10'd0;
  30. else if(cnt_1us == CNT_1US_MAX)
  31. cnt_1ms <= cnt_1ms + 10'd1;
  32. else
  33. cnt_1ms <= cnt_1ms;
  34. //s计数器
  35. always@(posedge sys_clk or negedge sys_rst_n)
  36. if(sys_rst_n == 1'b0)
  37. cnt_1s <= 10'd0;
  38. else if((cnt_1us == CNT_1US_MAX)
  39. && (cnt_1ms == CNT_1MS_MAX)
  40. && (cnt_1s == CNT_1S_MAX))
  41. cnt_1s <= 10'd0;
  42. else if((cnt_1us == CNT_1US_MAX) && (cnt_1ms == CNT_1MS_MAX))
  43. cnt_1s <= cnt_1s + 10'd1;
  44. else
  45. cnt_1s <= cnt_1s;
  46. //添加渐亮与渐灭标志
  47. always@(posedge sys_clk or negedge sys_rst_n)
  48. if(sys_rst_n == 1'b0)
  49. cnt_en <= 1'b1;
  50. else if((cnt_1us == CNT_1US_MAX)
  51. &&(cnt_1ms == CNT_1MS_MAX)
  52. &&(cnt_1s == CNT_1S_MAX))
  53. cnt_en <= ~cnt_en;
  54. else
  55. cnt_en <= cnt_en;
  56. always@(posedge sys_clk or negedge sys_rst_n)
  57. if(sys_rst_n == 1'b0)
  58. led_out <= 1'b0; //led灯熄灭
  59. else if((cnt_en == 1'b1) && (cnt_1ms <= cnt_1s)
  60. ||(cnt_en == 1'b0) && (cnt_1ms > cnt_1s))
  61. led_out <= 1'b1;
  62. else
  63. led_out <= 1'b0;
  64. endmodule

在编写代码时遇到的问题: cnt_1us <= cnt_1us + 6'd1;            cnt_1us = cnt_1us + 6'd1;  

将代码中的阻塞赋值错写成了非阻塞赋值,“cnt_1us = cnt_1us + 6'd1;”该语句只有在执行完后才能执行后面的其他赋值语句,这样就会导致cnt_1us在最大时刻的前面和后面都会出现cnt_1ms出现跳变的现象,阻塞赋值判断的并不是该时刻的前状态,而是执行完的后状态。

三、逻辑仿真

3.1 仿真代码

为了方便仿真代码的实现,这里修改最大值常数变为2,5,5

  1. `timescale 1ns / 1ns
  2. //
  3. // Company: 追逐者——桥的小作坊
  4. // Create Date: 2022/05/13 21:26:31
  5. // Design Name: 呼吸灯
  6. // Module Name: tb_breath_led
  7. //
  8. module tb_breath_led();
  9. reg sys_clk;
  10. reg sys_rst_n;
  11. wire led_out;
  12. initial begin
  13. sys_clk = 1'b1;
  14. sys_rst_n <= 1'b0;
  15. #20
  16. sys_rst_n <= 1'b1;
  17. end
  18. always #10 sys_clk = ~sys_clk;
  19. breath_led
  20. #(
  21. .CNT_1US_MAX(6'd2 ),
  22. .CNT_1MS_MAX(10'd5),
  23. .CNT_1S_MAX (10'd5)
  24. )
  25. breath_led_inst
  26. (
  27. .sys_clk (sys_clk ),
  28. .sys_rst_n(sys_rst_n),
  29. .led_out (led_out )
  30. );
  31. endmodule

3.2 波形图对比

如图可知三个计数器的计数波形是正确的,输出与绘制的原理图也相同。

四、上板验证

4.1 管脚绑定

 Ctrl+s进行保存

4.2 程序下载

生成bit流文件,连接板卡,下载程序

PFGA—呼吸灯实现

五、总结

1 、深刻体会呼吸灯的分析过程,如何把一个复杂的问题简单化,然后顺着解决问题的思路
思考下去;
2 、继续深入体会 parameter 参数化常数所带来的好处,以及用法;
3 、多体会计数器如何控制,什么时候开始计数、什么时候清零,千万要考虑全面,不要忘
记条件。  
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/木道寻08/article/detail/791197
推荐阅读
相关标签
  

闽ICP备14008679号