呼吸灯:
呼吸灯是一种特殊的灯光效果,它可以模拟呼吸的效果,即灯光逐渐由暗变亮再由亮变暗,循环往复。这种效果给人一种柔和、舒缓的感觉,常被应用在装饰、照明和显示等领域。
PWM呼吸灯设计:
在数字电路设计中,通常使用脉宽调制(PWM)技术来实现呼吸灯效果。PWM通过改变信号的高电平时间比例来控制输出的亮度。实现呼吸灯效果的关键是改变PWM的占空比,也就是高电平时间与周期时间的比例。
使用开发板上的四个led灯实现1s间隔的呼吸灯。
代码:
/*
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=1sreg [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) beginif(!rst_n)begincnt_us <= 6'd0;endelse if (add_cnt_us) begin//add_cnt_us 为 1 时开始计数if(end_cnt_us)begin//end_cnt_us 为 1 时为计满,重新置零cnt_us <= 6'd0;endelse begincnt_us <= cnt_us +1'd1;endendelse begincnt_us <= cnt_us;endendassign add_cnt_us = 1'b1;
assign end_cnt_us = add_cnt_us && cnt_us == TIME_US;//1ms计时器
always @(posedge clk or negedge rst_n) beginif(!rst_n)begincnt_ms <= 10'd0;endelse if(add_cnt_ms) beginif(end_cnt_ms) begincnt_ms <= 10'd0;endelse begincnt_ms <= cnt_ms + 1'd1;endendelse begincnt_ms <= cnt_ms;end
endassign 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) beginif(!rst_n) begincnt_s <= 10'd0;endelse if (add_cnt_s) beginif(end_cnt_s) begincnt_s <= 10'd0;endelse begincnt_s <= cnt_s + 1'd1;endendelse begincnt_s <= cnt_s;end
endassign 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) beginif(!rst_n) beginflag <= 1'b0;endelse if(end_cnt_s) begin//1s取反flag <= ~flag;endelse beginflag <= flag;end
endalways @(posedge clk or negedge rst_n) beginif(!rst_n) beginled <= 4'b0000;endelse beginif(flag == 1'b1)begin//电亮led <= (cnt_s > cnt_ms) ? 4'b1111 : 4'b0000;endelse beginled <= (cnt_s > cnt_ms) ? 4'b0000 : 4'b1111;endend
endendmodule
测试文件:
`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 beginclk = 1'b0;rst_n = 1'b0;//开始复位#(CYCLE);rst_n = 1'b1;//结束复位#((TIME_US + 1)*(TIME_MS + 1)*(TIME_S + 1)*CYCLE*2);$stop;endbreath_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
我们通过modelsim仿真结果如下:
其中我们能清晰看出在flag值为0的时候,高电平时间比例越来越小,说明灯在逐渐熄灭,在flag值为1的时候,高电平时间比列越来越大,说明灯在逐渐电亮。
结果展示: