PWM Breathing Light Design

Breathing light:
Breathing light is a special lighting effect, which can simulate the effect of breathing, that is, the light gradually changes from dark to bright and then from bright to dark, and the cycle goes on and on. This effect gives people a soft, soothing feeling and is often used in decoration, lighting and display and other fields.

PWM breathing light design:
In digital circuit design, pulse width modulation (PWM) technology is usually used to achieve the breathing light effect. PWM controls the brightness of the output by changing the high time ratio of the signal. The key to realize the breathing light effect is to change the duty cycle of PWM, that is, the ratio of high level time to cycle time.

Use the four LED lights on the development board to realize the breathing light at intervals of 1s.

code:

/*
2023.7.13
呼吸灯设计pwm_led
实现1s间隔的呼吸灯
*/
module breath_led(
    input       wire        clk         ,
    input       wire        rst_n       ,

    output      reg[3:0]    led 

);

parameter TIME_US = 6'd49;//50*20ns=1us
parameter TIME_MS = 10'd999;//1us*1000=1ms
parameter TIME_S = 10'd999;//1ms*1000=1s

reg [5:0] cnt_us;
reg [9:0] cnt_ms;
reg [9:0] cnt_s;

wire add_cnt_us;//us计数器开始计数标志
wire end_cnt_us;//us计数器结束计数标志

wire add_cnt_ms;//ms计数器开始计数标志
wire end_cnt_ms;//ms计数器结束计数标志

wire add_cnt_s;
wire end_cnt_s;

reg flag;//闪烁标志

//1us计时器
always @(posedge clk or negedge rst_n) begin
    if(!rst_n)begin
        cnt_us <= 6'd0;
    end

    else if (add_cnt_us) begin//add_cnt_us 为 1 时开始计数
        if(end_cnt_us)begin//end_cnt_us 为 1 时为计满,重新置零
            cnt_us <= 6'd0;
        end
        else begin
            cnt_us <= cnt_us +1'd1;
        end
    end

    else begin
        cnt_us <= cnt_us;
    end
    
end

assign add_cnt_us = 1'b1;
assign end_cnt_us = add_cnt_us && cnt_us == TIME_US;



//1ms计时器
always @(posedge clk or negedge rst_n) begin
    if(!rst_n)begin
        cnt_ms <= 10'd0;
    end
    else if(add_cnt_ms) begin
        if(end_cnt_ms) begin
            cnt_ms <= 10'd0;
        end
        else begin
            cnt_ms <= cnt_ms + 1'd1;
        end
    end
    else begin
        cnt_ms <= cnt_ms;
    end
end

assign add_cnt_ms = end_cnt_us;
assign end_cnt_ms = add_cnt_ms && cnt_ms == TIME_MS;

//1s计数器
always @(posedge clk or negedge rst_n) begin
    if(!rst_n) begin
        cnt_s <= 10'd0;
    end
    else if (add_cnt_s) begin
        if(end_cnt_s) begin
            cnt_s <= 10'd0;
        end
        else begin
            cnt_s <= cnt_s + 1'd1;
        end
    end
    else begin
        cnt_s <= cnt_s;
    end
end

assign add_cnt_s = end_cnt_ms;
assign end_cnt_s = add_cnt_s && cnt_s == TIME_S;

//flag值判断
always @(posedge clk or negedge rst_n) begin
    if(!rst_n) begin
        flag <= 1'b0;
    end
    else if(end_cnt_s) begin//1s取反
        flag <= ~flag;
    end
    else begin
        flag <= flag;
    end
end

always @(posedge clk or negedge rst_n) begin
    if(!rst_n) begin
        led <= 4'b0000;
    end
    else begin
        if(flag == 1'b1)begin//电亮
             led <= (cnt_s > cnt_ms) ? 4'b1111 : 4'b0000;
        end
        else begin
            led <= (cnt_s > cnt_ms) ? 4'b0000 : 4'b1111;
        end
    end
end

endmodule 

Test file:

`timescale 1ns/1ns
module breath_led_tb();

    reg clk;
    reg rst_n;

    wire [3:0] led;

    parameter CYCLE = 20;
    parameter TIME_US = 5;
    parameter TIME_MS = 10;
    parameter TIME_S = 10;

    always #(CYCLE/2) clk = ~clk;

    initial begin
        clk = 1'b0;
        rst_n = 1'b0;//开始复位
        #(CYCLE);
        rst_n = 1'b1;//结束复位
        #((TIME_US + 1)*(TIME_MS + 1)*(TIME_S + 1)*CYCLE*2);
        $stop;
    end

    breath_led #(
        .TIME_US    (TIME_US),
        .TIME_MS    (TIME_MS),
        .TIME_S     (TIME_S)
    )u_breath_led(
        .clk    (clk),
        .rst_n  (rst_n),

        .led    (led)

    );

endmodule 

Our simulation results through modelsim are as follows:
insert image description here
Among them, we can clearly see that when the flag value is 0, the high-level time ratio is getting smaller and smaller, indicating that the light is gradually turning off; when the flag value is 1, the high-level time ratio is getting larger and larger, indicating that the light is gradually turning on.

The result display:

insert image description here

Guess you like

Origin blog.csdn.net/weixin_53573350/article/details/131709231