Verilog实现呼吸灯效果

呼吸灯的效果采用PWM调波的形式,即快速的改变每个周期的占空比(一个周期内高电平时间占一个周期时间的比值)来实现点亮到熄灭的效果。示意如下图

而关于整个波形图,用50MHz的晶振,从0开始计数到49则为1us。

而1ms是1us的1000倍,以1us为基准,从0开始计数到999则为1ms。

同理,以1ms为基准,从0开始计数到999则为1s。

cnt_en为使能信号,当其为0的时候,实现【完全熄灭】——【完全点亮】过程

当cen_en为1的时候,实现【完全点亮】——【完全熄灭】过程

下图实现的是以2s为周期,前1s实现【完全熄灭】——【完全点亮】,后1s实现【完全点亮】——【完全熄灭】。

 Verilog代码为

module breath_led
#(
	parameter CNT_1US_MAX=6'd49,
	parameter CNT_1MS_MAX=10'd999,
	parameter CNT_1S_MAX=10'd999
)
 (
	input wire sys_clk,
	input wire sys_rst_n,
	output reg led_out	
    );
	
	reg [5:0]cnt_1us;
	reg [9:0]cnt_1ms;
	reg [9:0]cnt_1s;
	reg cnt_en;
	
always@(posedge sys_clk or negedge sys_rst_n)//1us计数器的波形变化过程
	if(sys_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;

always@(posedge sys_clk or negedge sys_rst_n)//1ms计数器的波形变化过程
	if(sys_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;
			
always@(posedge sys_clk or negedge sys_rst_n)//1s计数器的波形变化过程
	if(sys_rst_n==1'b0)
		cnt_1s<=10'd0;
	else if((cnt_1ms==CNT_1MS_MAX)&&(cnt_1us==CNT_1US_MAX)&&(cnt_1s==CNT_1S_MAX))
		cnt_1s<=10'd0;
	else if((cnt_1ms==CNT_1MS_MAX)&&(cnt_1us==CNT_1US_MAX))
		cnt_1s<=cnt_1s+10'd1;
	else
		cnt_1s<=cnt_1s;
			
always@(posedge sys_clk or negedge sys_rst_n)//呼吸灯的两个状态
	if(sys_rst_n==1'b0)
		cnt_en<=1'b0;
	else if((cnt_1ms==CNT_1MS_MAX)&&(cnt_1us==CNT_1US_MAX)&&(cnt_1s==CNT_1S_MAX))
		cnt_en<=~cnt_en;
	else
		cnt_en<=cnt_en;
			
always@(posedge sys_clk or negedge sys_rst_n)//LED灯的效果
	if(sys_rst_n==1'b0)
		led_out<=1'b1;
	else if((cnt_en==0)&&(cnt_1ms<=cnt_1s)||(cnt_en==1)&&(cnt_1ms>cnt_1s))
		led_out<=1'b0;
	else
		led_out<=1'b1;
endmodule

 仿真测试代码如下

`timescale 1ns / 1ns

module tb_breath_led();
reg sys_clk;
reg sys_rst_n;
wire led_out;

initial
 begin
	sys_clk=1'b1;
	sys_rst_n<=1'b0;
	#20
	sys_rst_n<=1'b1;
 end
 always #10 sys_clk=~sys_clk;
 
 breath_led
#(
.CNT_1US_MAX(6'd4),
.CNT_1MS_MAX(10'd9),
.CNT_1S_MAX(10'd9)//仿真测试的过程中将初值设置小一点
)
 breath_led_inst(
.sys_clk(sys_clk),
.sys_rst_n(sys_rst_n),
.led_out(led_out)	
    );

endmodule

vivado仿真波形图

三个计数器的计数波形 

使能端和呼吸效果

注:LED灯为低电平点亮,高电平熄灭。