呼吸灯
呼吸灯,就是控制led灯的亮度从弱变强、从强变弱的循环往复,从而实现像呼吸一样的效果。改变电压即可改变led灯的亮度,但是用代码控制led灯两端电压显然是不现实的,我们可以用控制脉冲宽度的方式来控制led灯点亮的时间,从完全熄灭到完全点亮,再从完全熄灭到完全点亮,从而实现呼吸灯的效果。
如下图是led从完全熄灭到完全点亮的过程。中间变量cnt_1s[9:0]、cnt_1ms[9:0]、cnt_1us[5:0],以1s为周期来实现led亮度的渐变,第一个1s时间led灯点亮了1ms,第二个1s点亮了2ms…以此类推,到第一千个1s,led灯完全点亮。cnt_en是改变led从完全熄灭到完全点亮,再从完全熄灭到完全点亮状态的标志信号,它将在计数到达1000个1s周期时,进行翻转电平,实现亮度从弱变强(图一)到从强变弱(图二)(或从强变弱到从弱变强)的切换。
代码如下:
module breath_led
#( parameter CNT_1S_MAX = 10'd999 , //1s = 1000msparameter CNT_1mS_MAX = 10'd999 , //1ms = 1000msparameter CNT_1US_MAX = 6'd49 //50*20ns=1us
)
(input sys_clk ,input rst_n ,output reg led_out
);reg [9:0] cnt_1s ;
reg [9:0] cnt_1ms ;
reg [5:0] cnt_1us ;
reg cnt_en ;always@(posedge sys_clk or negedge rst_n)beginif(rst_n == 1'b0)cnt_1us <= 6'd0; else if(cnt_1us == CNT_1US_MAX)cnt_1us <= 6'd0;elsecnt_1us <= cnt_1us + 6'd1;
endalways@(posedge sys_clk or negedge rst_n)beginif(rst_n == 1'b0)cnt_1ms <= 10'd0;else if((cnt_1ms==CNT_1mS_MAX) && (cnt_1us==CNT_1US_MAX))cnt_1ms <= 10'd0;else if(cnt_1us==CNT_1US_MAX)cnt_1ms <= cnt_1ms + 10'd1;elsecnt_1ms <= cnt_1ms;
endalways@(posedge sys_clk or negedge rst_n)beginif(rst_n == 1'b0)cnt_1s <= 10'd0;else if((cnt_1s == CNT_1S_MAX) && (cnt_1ms == CNT_1mS_MAX) && (cnt_1us==CNT_1US_MAX))cnt_1s <= 10'd0;else if((cnt_1us == CNT_1US_MAX) && (cnt_1ms == CNT_1mS_MAX))cnt_1s <= cnt_1s + 10'd1;elsecnt_1s <= cnt_1s;
endalways@(posedge sys_clk or negedge rst_n)beginif(rst_n == 1'b0)cnt_en <= 1'd0;else if((cnt_1s == CNT_1S_MAX) && (cnt_1ms == CNT_1mS_MAX) && (cnt_1us==CNT_1US_MAX))cnt_en <= ~cnt_en;elsecnt_en <= cnt_en;
endalways@(posedge sys_clk or negedge rst_n)beginif(rst_n == 1'b0)led_out <= 1'd0;else if( ((cnt_en == 1'd0) && (cnt_1ms <= cnt_1s) ) || ((cnt_en == 1'd1) && (cnt_1ms > cnt_1s) ) )led_out <= 1'd0;else led_out <= 1'd1;
endendmodule
仿真文件如下:
`timescale 1ns/1ns
module breath_led_tb();reg sys_clk ;
reg rst_n ;wire led_out ;parameter CYCLE = 20;initial beginsys_clk = 1'b0;forever #(CYCLE/2) sys_clk = ~sys_clk;
endinitial beginrst_n <= 1'b0;#20rst_n <= 1'b1;
endbreath_led
#( .CNT_1S_MAX (10'd9), //1s = 1000ms.CNT_1mS_MAX(10'd9), //1ms = 1000ms.CNT_1US_MAX(6'd4) //50*20ns=1us
)
breath_led_inst
(. sys_clk (sys_clk),. rst_n (rst_n ),. led_out (led_out )
);
endmodule
仿真结果如图,可以看出低电平持续时间由少增多,再由多减少的过程。和所绘制波形图(二图首尾结合)一致。