基于Verilog实现呼吸灯

时间的单位换算

首先掌握秒的单位换算,这里总结一些。因为笔者目前用的大多为50MHz,所以介绍以此为例。但关于秒的转换全世界都是一样的。

1MHz = 1,000kHz = 1,000,000Hz

频率:是用单位时间内完成的周期性变化的次数,是描述周期运动频繁程度的量。

因此结合以上内容,50MHz,就是说,(两个相邻时钟上升沿算一个周期)1s内有50,000,000Hz个时钟上升沿。所以一个周期有多久就可以计算出来了1/50,000,000 = 0.000,000,02s

而常见的时间单位换算

1s = 1,000ms毫秒

1s = 1,000ms = 1,000,000us 微秒      1ms = 1,000us

1s = 1,000ms = 1,000,000us = 1,000,000,000ns 纳秒   1us = 1,000ns

下面还有皮秒和飞秒。进制都是1,000

0,000,000,02s = 0,000,02ms = 0,02us = 20ns

所以可得,50MHz时钟频率下的一个周期是20ns!!!

呼吸灯设计原理

原理就我理解,总的来说,就是先分频,再控制占空比。通过控制led的亮灯时间来实现呼吸功能。

功能就是让led灯2s为从暗到亮,下一个2s从亮到暗。

具体实现为将2s分为1000份。在这1000份里边,依次增加亮灯的时间。2s的1000份就是2ms

所以将2ms再分为1000份,就是2us。第一个2ms,亮led2us 第二个2ms,亮led4us......

然后依次增加。

仿真截图

由于分的太细,,可能看的不是很清楚。基于Verilog实现呼吸灯_第1张图片

代码

module pwm_led(
	clk,rst_n,pwm_led
    );
input clk;
input rst_n;

output pwm_led;


//两秒计时器
reg time_2s;
reg [27:0] cnt_2s;
always@(posedge clk or negedge rst_n)
begin
	if(!rst_n)
		begin 
			cnt_2s <= 28'd0;
			time_2s  <= 1'b0;
		end
	else 
		if(cnt_2s == 28'd50_000_000 - 1'b1)
			begin
				cnt_2s <= 28'd0;
				time_2s <= 1'b1;
			end
		else 
			begin
				cnt_2s <= cnt_2s + 1'b1;
				time_2s <= 1'b0;
			end
end

//2ms计时器
reg time_2ms;
reg [16:0] cnt_2ms;
always@(posedge clk or negedge rst_n)
begin
	if(!rst_n)
		begin 
			cnt_2ms <= 17'd0;
			time_2ms  <= 1'b0;
		end
	else 
		if(cnt_2ms == 17'd100_000 - 1'b1)
			begin
				cnt_2ms <= 17'd0;
				time_2ms <= 1'b1;
			end
		else 
			begin
				cnt_2ms <= cnt_2ms + 1'b1;
				time_2ms <= 1'b0;
			end
end
//计数是第几个2ms
reg [9:0] number_2ms;
always@(posedge clk or negedge rst_n)
begin
	if(!rst_n)
		number_2ms <= 10'd0;
	else 
		if( number_2ms == 10'd999 )
			number_2ms <= 10'd0;
		else 
			if(time_2ms)
				number_2ms <= number_2ms + 1'b1;
			else 
				number_2ms <= number_2ms;
end

//2us计时器
reg time_2us;
reg [6:0] cnt_2us;
always@(posedge clk or negedge rst_n)
begin
	if(!rst_n)
		begin 
			cnt_2us <= 7'd0;
			time_2us  <= 1'b0;
		end
	else 
		if(cnt_2us == 7'd100 - 1'b1)
			begin
				cnt_2us <= 7'd0;
				time_2us <= 1'b1;
			end
		else 
			begin
				cnt_2us <= cnt_2us + 1'b1;
				time_2us <= 1'b0;
			end
end

//计数2us,数是第几个2us
reg [9:0] number_2us;
always@(posedge clk or negedge rst_n)
begin
	if(!rst_n)
		number_2us <= 10'd0;
	else 
		if(number_2us == 10'd999 )
			number_2us <= 10'd0;
		else 
			if(time_2us)
				number_2us <= number_2us + 1'b1;
			else 
				number_2us <= number_2us;
end

wire led_flag0;//暗到亮
wire led_flag1;//亮到暗
assign led_flag0 = (number_2us < number_2ms) ? 1 : 0;  
assign led_flag1 = (number_2us < number_2ms) ? 0 : 1;

reg led_flag;
always@(posedge clk or negedge rst_n)
begin
	if(!rst_n)
		led_flag <= 1'b1;
	else 
		if(time_2s)
			led_flag <= ~led_flag;
		else 
			led_flag <= led_flag;
end

assign pwm_led = (led_flag) ? led_flag0 : led_flag1;

endmodule

代码经验证可以实现功能,还是很好玩的。

你可能感兴趣的:(FPGA逻辑篇)