05. 基于Verilog的呼吸灯程序设计

发布于:2024-05-06 ⋅ 阅读:(26) ⋅ 点赞:(0)

05_led_breath_v0

一个基于Verilog的呼吸灯程序示例,该程序通过PWM(脉冲宽度调制)技术来模拟呼吸灯的效果,逐渐变亮再逐渐变暗的LED灯,给人一种灯光在“呼吸”的感觉。

原理解释:

  1. PWM(脉冲宽度调制):通过改变输出信号的占空比来模拟不同亮度的LED灯。

  2. 呼吸灯周期:呼吸灯的周期由breathing_cnt控制,这里假设周期为1/4秒钟。

  3. 呼吸灯亮度变化:呼吸灯的亮度变化通过改变占空比的值来模拟。

  • 当pwm_cnt小于当前pwm_duty时,LED亮;
  • 当pwm_cnt大于pwm_duty时,LED不亮。

知识点:

  • PWM(脉冲宽度调制)
  • Duty(占空比)
  • 位宽确定可表达的最大整数值
  • 位拼接语法 assign led = {6{led_breathing}};
module led_breath #(
    parameter CLK_FREQ = 50000000,
    parameter LED_ON = 1'b0
)(
    input wire clk,       
    input wire rst_n,     
    output wire [5:0] led      
);

// 定义一个计数器用于产生PWM波形
reg [11:0] pwm_cnt;
reg [11:0] pwm_duty;

reg [31:0] breath_cnt;

// 呼吸灯周期,假设为1秒钟4个周期
localparam CYCLE = CLK_FREQ/4;

always @(posedge clk) begin
    if (!rst_n) breath_cnt <= 0;
    else begin
        breath_cnt <= breath_cnt + 1'b1;
        if (breath_cnt == CYCLE-1) breath_cnt <= 0;
    end
end

wire breath_done = (breath_cnt == CYCLE-1);

//PWM CNT
always @(posedge clk) begin
    if (!rst_n) pwm_cnt <= 0;
    else pwm_cnt <= pwm_cnt + 1'b1;
end

//PWM Duty
//light to off
always @(posedge clk) begin
    if (!rst_n) pwm_duty <= 12'hFFF;
    else if(breath_done) begin
        if(pwm_duty == 0) pwm_duty <= 12'hFFF;
        else pwm_duty <= {1'b0,pwm_duty[11:1]};
    end
    //else pwm_duty <= pwm_duty;
end

/*
//off to light on
always @(posedge clk) begin
    if (!rst_n) pwm_duty <= 12'b0;
    else if(breath_done) begin
        if(pwm_duty == 12'hFFF) pwm_duty <= 12'b0;
        else pwm_duty <= {pwm_duty[10:0],1'b1};
    end
    //else pwm_duty <= pwm_duty;
end
*/

// 根据PWM计数器的值和呼吸灯的亮度变化来控制LED的亮度
reg led_breathing;
//parameter LED_ON = 1'b0; //led active low on our board
localparam LED_OFF = ~LED_ON;

always @(posedge clk) begin
    if (!rst_n) led_breathing <= LED_OFF;
    else if (pwm_cnt < pwm_duty) begin
        led_breathing <= LED_ON;
    end else led_breathing <= LED_OFF;
end

assign led = {6{led_breathing}};

endmodule

扩展思维

  1. 学习了点亮LED、LED闪烁、LED跑马灯和LED呼吸灯这样多种模式LED效果,思考如何将这些不同的效果在一个工程里全部实现,并利用DIP开关选择不同的运行模式,呈现不同的效果。

  2. 尝试修改代码实现6个LED分为两组,每组以不同的频率呼吸。