Verilog实现PWM呼吸灯代码 | FPGA呼吸灯控制与占空比调节教程

通过Verilog代码详解PWM呼吸灯的实现原理,提供完整可运行的模块代码(含时钟分频、占空比动态调节功能),适用于FPGA开发板(如Xilinx、Altera)的LED呼吸灯项目。涵盖仿真步骤、关键参数配置及硬件调试技巧,适合FPGA初学者、电子工程师快速掌握PWM波形生成与硬件描述语言应用。

一、设计文件

  1. module breathing_led
  2. //---------------------<端口声明>---------------------------------------
  3. (
  4. input wire clk , //时钟,50Mhz
  5. input wire rst_n , //复位,低电平有效
  6. output wire led //led灯
  7. );
  8. //---------------------<参数定义>---------------------------------------
  9. parameter TIME_2MS = 100_000 ; //2ms时间
  10. parameter TIME_2MS_W = 17 ; //2ms时间位宽
  11. parameter NUM = 1000 ; //2ms到2s为1000份
  12. parameter NUM_W = 10 ; //份数位宽
  13. parameter STEP = 100 ; //2ms也分成1000份,每份为步长100
  14. //---------------------<信号定义>---------------------------------------
  15. reg [TIME_2MS_W-1:0] cnt0 ;
  16. wire add_cnt0 ;
  17. wire end_cnt0 ;
  18. reg [NUM_W:0] cnt1 ;
  19. wire add_cnt1 ;
  20. wire end_cnt1 ;
  21. reg [1:0] cnt2 ;
  22. wire add_cnt2 ;
  23. wire end_cnt2 ;
  24. reg [TIME_2MS_W-1:0] pwm_high ;
  25. //----------------------------------------------------------------------
  26. //-- 2ms时间计时
  27. //----------------------------------------------------------------------
  28. always @(posedge clk or negedge rst_n)begin
  29. if(!rst_n)
  30. cnt0 <= 0;
  31. else if(add_cnt0)begin
  32. if(end_cnt0)
  33. cnt0 <= 0;
  34. else
  35. cnt0 <= cnt0 + 1;
  36. end
  37. else
  38. cnt0 <= cnt0;
  39. end
  40. assign add_cnt0 = 1;
  41. assign end_cnt0 = add_cnt0 && cnt0==TIME_2MS-1 ;
  42. //----------------------------------------------------------------------
  43. //-- 每2ms计1次,计到2秒共需计NUM次
  44. //----------------------------------------------------------------------
  45. always @(posedge clk or negedge rst_n)begin
  46. if(!rst_n)
  47. cnt1 <= 0;
  48. else if(add_cnt1)begin
  49. if(end_cnt1)
  50. cnt1 <= 0;
  51. else
  52. cnt1 <= cnt1 + 1;
  53. end
  54. else
  55. cnt1 <= cnt1;
  56. end
  57. assign add_cnt1 = end_cnt0;
  58. assign end_cnt1 = add_cnt1 && cnt1==NUM-1 ;
  59. //----------------------------------------------------------------------
  60. //-- 每2秒计1次,计到4秒共需计2次
  61. //----------------------------------------------------------------------
  62. always @(posedge clk or negedge rst_n)begin
  63. if(!rst_n)begin
  64. cnt2 <= 0;
  65. end
  66. else if(add_cnt2)begin
  67. if(end_cnt2)
  68. cnt2 <= 0;
  69. else
  70. cnt2 <= cnt2 + 1;
  71. end
  72. else
  73. cnt2 <= cnt2;
  74. end
  75. assign add_cnt2 = end_cnt1;
  76. assign end_cnt2 = add_cnt2 && cnt2==2-1 ;
  77. //----------------------------------------------------------------------
  78. //-- 设置pwm的占空比时间
  79. //----------------------------------------------------------------------
  80. always @(posedge clk or negedge rst_n) begin
  81. if(!rst_n)
  82. pwm_high <= 0;
  83. else if(cnt2==0 && end_cnt0)
  84. pwm_high <= pwm_high + STEP;
  85. else if(cnt2==1 && end_cnt0)
  86. pwm_high <= pwm_high - STEP;
  87. else
  88. pwm_high <= pwm_high;
  89. end
  90. //----------------------------------------------------------------------
  91. //-- 输出led灯
  92. //----------------------------------------------------------------------
  93. assign led = (cnt0 < pwm_high) ? 1'b1 : 1'b0;
  94. endmodule

二、仿真文件

  1. `timescale 1ns/1ps //时间精度
  2. `define Clock 20 //时钟周期
  3. module breathing_led_tb;
  4. //---------------------<端口定义>---------------------------------------
  5. reg clk ; //时钟,50Mhz
  6. reg rst_n ; //复位,低电平有效
  7. wire led ;
  8. //----------------------------------------------------------------------
  9. //-- 模块例化
  10. //----------------------------------------------------------------------
  11. breathing_led
  12. #(
  13. .TIME_2MS (1000 ), //2ms时间 100_000
  14. .NUM (100 ), //2ms到2s为1000份
  15. .STEP (10 ) //2ms也分成1000份,每份为步长100
  16. )
  17. u_breathing_led
  18. (
  19. .clk (clk ),
  20. .rst_n (rst_n ),
  21. .led (led )
  22. );
  23. //----------------------------------------------------------------------
  24. //-- 时钟信号和复位信号
  25. //----------------------------------------------------------------------
  26. initial begin
  27. clk = 1;
  28. forever
  29. #(`Clock/2) clk = ~clk;
  30. end
  31. initial begin
  32. rst_n = 0; #(`Clock*20+1);
  33. rst_n = 1;
  34. end
  35. endmodule

三、仿真波形

可以看到led信号的占空比先不断增加后不断减少,循环反复。

Verilog实现PWM呼吸灯代码 | FPGA呼吸灯控制与占空比调节教程 - 第1张

四、上板验证

经过上板验证,最终成功!

本文原创,作者:FPGA小白,其版权均为FPGA线上课程平台|最全栈的FPGA学习平台|FPGA工程师认证培训所有。
如需转载,请注明出处:https://z.shaonianxue.cn/8327.html

"愿我的文字能带给您一丝美好"

还没有人赞赏,支持一下

评论

A 为本文作者,G 为游客总数:0
加载中…

提交评论

游客,您好,欢迎参与讨论。

我的购物车

购物车为空

优惠券

没有优惠券