使用PWM技术实现呼吸灯。利用占空比每1ms递增1us的占空比来点亮LED。没隔1s实现灯由逐渐变亮到逐渐变暗,或者逐渐变暗到逐渐变量的转换。使用的语言是verilog。
module led_breath
//#(
// parameter LED_WIDTH = 4
//)
(
input clk, //global clock
input rst_n, //global reset
output led_data
);
//-----------------------------------
//counter for 1us
localparam T1US = 6'd100;
//localparam T1US = 6'd5; //just for simulation
reg [5:0] delay_1us_cnt;
always @ ( posedge clk or posedge rst_n )
begin
if ( rst_n )
delay_1us_cnt <= 6'd0;
else if ( delay_1us_cnt < T1US )
delay_1us_cnt <= delay_1us_cnt + 1'b1;
else
delay_1us_cnt <= 6'd1;
end
wire delay_1us = ( delay_1us_cnt == T1US ) ? 1'b1 : 1'b0;
//-----------------------------------
//counter for 1ms
localparam T1MS = 10'd1000;
//localparam T1MS = 10'd100; //just for simulation
reg [9:0] delay_1ms_cnt;
always @ ( posedge clk or posedge rst_n )
begin
if ( rst_n )
delay_1ms_cnt <= 10'd0;
else if ( delay_1us )
delay_1ms_cnt <= ( delay_1ms_cnt < T1MS ) ? ( delay_1ms_cnt + 1'b1 ) : 10'd1;
else
delay_1ms_cnt <= delay_1ms_cnt;
end
wire delay_1ms = ( delay_1ms_cnt == T1MS && delay_1us ) ? 1'b1 : 1'b0;
//-----------------------------------
//counter for 1s
localparam T1S = 10'd1000;
//localparam T1S = 10'd100; //just for simulation
reg [9:0] delay_1s_cnt;
always @ ( posedge clk or posedge rst_n )
begin
if ( rst_n )
delay_1s_cnt <= 10'd0;
else if ( delay_1ms )
delay_1s_cnt <= ( delay_1s_cnt < T1S ) ? ( delay_1s_cnt + 1'b1 ) : 10'd1;
else
delay_1s_cnt <= delay_1s_cnt;
end
wire delay_1s = ( delay_1s_cnt == T1S && delay_1ms ) ? 1'b1 : 1'b0;
//-----------------------------------
//PWM parameter
wire [9:0] duty_cnt = delay_1ms_cnt;
wire [9:0] period_cnt = delay_1s_cnt;
//-----------------------------------
//switch mode
reg display_mode;
always @ ( posedge clk or posedge rst_n )
begin
if ( rst_n )
display_mode <= 1'b0;
else if ( delay_1s )
display_mode <= ~ display_mode;
else
display_mode <= display_mode;
end
//-----------------------------------
//generate PWM
reg pwm_on;
always @ ( posedge clk or posedge rst_n )
begin
if ( rst_n )
pwm_on <= 1'b0;
else
case ( display_mode )
1'b0: pwm_on <= ( duty_cnt < period_cnt ) ? 1'b1 : 1'b0;
1'b1: pwm_on <= ( duty_cnt < period_cnt ) ? 1'b0 : 1'b1;
default:;
endcase
end
//-----------------------------------
//output to LED
assign led_data = pwm_on;
endmodule