呼吸灯
呼吸灯,就是控制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 = 1000ms
parameter CNT_1mS_MAX = 10'd999 , //1ms = 1000ms
parameter 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)begin
if(rst_n == 1'b0)
cnt_1us <= 6'd0;
else if(cnt_1us == CNT_1US_MAX)
cnt_1us <= 6'd0;
else
cnt_1us <= cnt_1us + 6'd1;
end
always@(posedge sys_clk or negedge rst_n)begin
if(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;
else
cnt_1ms <= cnt_1ms;
end
always@(posedge sys_clk or negedge rst_n)begin
if(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;
else
cnt_1s <= cnt_1s;
end
always@(posedge sys_clk or negedge rst_n)begin
if(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;
else
cnt_en <= cnt_en;
end
always@(posedge sys_clk or negedge rst_n)begin
if(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;
end
endmodule
仿真文件如下:
`timescale 1ns/1ns
module breath_led_tb();
reg sys_clk ;
reg rst_n ;
wire led_out ;
parameter CYCLE = 20;
initial begin
sys_clk = 1'b0;
forever #(CYCLE/2) sys_clk = ~sys_clk;
end
initial begin
rst_n <= 1'b0;
#20
rst_n <= 1'b1;
end
breath_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
仿真结果如图,可以看出低电平持续时间由少增多,再由多减少的过程。和所绘制波形图(二图首尾结合)一致。