Loading

FPGA呼吸灯

呼吸灯时序图如下图所示,cnt_1us=49(即1us)时,cnt_1ms加一;当cnt_1ms=999(即1ms)时,cnt_1s加一;当cnt_1s=999(即1s)时,en翻转;要实现led逐渐由灭到亮,即led每次低电平的时间逐渐有规律的增加。利用PWM改变占空比达到实现呼吸灯。

当满足cnt_1ms<=cnt_1s时,led低电平时间可以满足逐渐增加的条件,1s后en翻转,灯从亮-->灭。满足的条件应该是cnt_1ms>cnt_1s。

使用Verilog语言实现1个呼吸灯,led由灭逐渐变亮,再逐渐熄灭,源码如下:

module breath_led
#(
	parameter CNT_1US_MAX = 6'd49,
	parameter CNT_1MS_MAX = 10'd999,
	parameter CNT_1S_MAX = 10'd999
)
(
	input 	wire	clk,
	input 	wire	reset_n,
	output 	reg		led
);

reg [5:0] cnt_1us;	//1us计时器,记满50个时钟周期=50*20ns=1us
reg [9:0] cnt_1ms;	//1ms计数器,cnt_1ms=999为1ms
reg [9:0] cnt_1s;		//1s计数器,1000*cnt_1ms
reg cnt_1s_en;		//1s使能信号

always@(posedge clk or negedge reset_n)	//20ns*50=1us
	if(!reset_n)
		cnt_1us <= 6'b0;
	else if(cnt_1us == CNT_1US_MAX)
		cnt_1us <= 6'b0;
	else
		cnt_1us <= cnt_1us + 1;
		
always@(posedge clk or negedge reset_n)	
	if(!reset_n)
		cnt_1ms <= 6'b0;
	else if(cnt_1us == CNT_1US_MAX && cnt_1ms == CNT_1MS_MAX)	//记满一秒
		cnt_1ms <= 6'b0;
	else if(cnt_1us == CNT_1US_MAX)	//记满一毫秒
		cnt_1ms <= cnt_1ms + 1;
		
always@(posedge clk or negedge reset_n)	
	if(!reset_n)
		cnt_1s <= 6'b0;
	else if(cnt_1us == CNT_1US_MAX && cnt_1ms == CNT_1MS_MAX
								   && cnt_1s == CNT_1S_MAX)	//记满一秒
		cnt_1s <= 6'b0;
	else if(cnt_1us == CNT_1US_MAX && cnt_1ms == CNT_1MS_MAX)
		cnt_1s <= cnt_1s + 1;
		
//cnt_1s_en:1s计数器标志信号		
always@(posedge clk or negedge reset_n)	
	if(!reset_n)
		cnt_1s_en <= 1'b0;
	else if(cnt_1us == CNT_1US_MAX && cnt_1ms == CNT_1MS_MAX
								   && cnt_1s == CNT_1S_MAX)	//记满一秒
		cnt_1s_en <= ~cnt_1s_en;	//每1s翻转使能信号一次

//输出led灯状态
always@(posedge clk or negedge reset_n)	
	if(!reset_n)
		led <= 1'b1;	//复位熄灭
	else if((cnt_1s_en && cnt_1ms <= cnt_1s) || 	//en为高电平时,灯灭-->灯亮,en为低电平时,灯亮-->灯灭
			(!cnt_1s_en && cnt_1ms > cnt_1s))	//记满一秒
		led <= 1'b0;	//点亮
	else
		led <= 1'b1;	//熄灭

endmodule
posted @ 2023-06-06 12:12  记录学习的Lyx  阅读(124)  评论(0编辑  收藏  举报