呼吸灯
功能目标:实现Led灯由熄灭逐渐变亮至完全点亮,再逐渐变暗至完全熄灭,循环往复。
1.输入输出原理图
将系统时钟与复位按键作为输入,led灯状态作为输出,直观显示最终结果。
2.波形图绘制(visio)
首先根据实现目标明确led灯在熄灭->点亮->熄灭过程中的波形图,其中低电平代表点亮,高电平代表熄灭;在熄灭->点亮过程,想要实现“呼吸”效果,就需要在每个周期T内逐渐增加led灯的点亮时间,最终将各个周期合并,实现“呼吸”效果。
那么,有了点亮时的呼吸效果,熄灭的呼吸效果就是将熄灭、点亮时间反过来就可以实现了。
接下来,我们利用上文提到的时钟与复位按键,同时引入中间变量绘制完整的波形图:
由灭到亮:
由亮到灭:
sys_clk是频率为50Mhz的系统时钟;
sys_rst_n:复位按键,低电平有效,这里我们设除开始一小段时间外,按键始终处于高电平即无效状态;
cnt_1s:1s计数器 ; cnt_1ms : 1ms计数器:以此类推…
特定时间计数器的模值在其他文章里已经说明过,这里不再赘述。
cnt_en : 使能信号,这里的作用是判断led灯何时转换状态,例如上图,当led由亮逐渐熄灭时,当led完全熄灭,cnt_en则由高电平进入低电平,从而使led开始逐渐点亮。
led_out: led输出波形。
代码实现:
module breath_led
#(
parameter CNT_1us_MAX = 6'd49 , //The maximum modulus of the counter
parameter CNT_1ms_MAX = 11'd999 ,
parameter CNT_1s_MAX = 11'd999
)
(
input wire sys_clk ,
input wire sys_rst_n ,
output reg led_out
);
reg [10:0] cnt_1s;
reg [10:0] cnt_1ms;
reg [5:0] cnt_1us;
reg cnt_en ;
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
cnt_1us <= 6'd0;
else if(cnt_1us == CNT_1us_MAX)
cnt_1us <= 6'd0;
else
cnt_1us <= 6'd1 + cnt_1us ;
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
cnt_1ms <= 11'd0;
else if(cnt_1us == CNT_1us_MAX && cnt_1ms == CNT_1ms_MAX)
cnt_1ms <= 11'd0;
else if(cnt_1us == CNT_1us_MAX)
cnt_1ms <= 11'd1 + cnt_1ms ;
else
cnt_1ms <= cnt_1ms ;
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
cnt_1s <= 11'd0;
else if(cnt_1ms == CNT_1ms_MAX &&
cnt_1s == CNT_1s_MAX && cnt_1us == CNT_1us_MAX )
cnt_1s <= 11'd0;
else if(cnt_1ms == CNT_1ms_MAX && cnt_1us == CNT_1us_MAX)
cnt_1s <= 11'd1 + cnt_1s ;
else
cnt_1s <= cnt_1s ;
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
cnt_en <= 1'd0;
else if((cnt_1us == CNT_1us_MAX) && (cnt_1ms == CNT_1ms_MAX)
&& (cnt_1s == CNT_1s_MAX) )
cnt_en <= ~cnt_en;
else
cnt_en <= cnt_en ;
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
led_out <= 1'b1 ;
else if(((cnt_en == 1'b0) && (cnt_1ms <= cnt_1s))
|| ((cnt_en == 1'b1)&& (cnt_1ms > cnt_1s)))
led_out<= 1'b1 ;
else
led_out <= 1'b0;
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
/*initial
begin
$timeformat(-9,0,"ns",6);
$monitor("@time %t :in_1=%b,in_2=%b,cin=%b,sum=%b,count=%b" ,$time,in_1,in_2,cin,sum,count);
end*/
always #10 sys_clk = ~sys_clk; //clk frequency
breath_led
#(
.CNT_1us_MAX (7'd100),
.CNT_1ms_MAX (10'd500),
.CNT_1s_MAX (10'd500)
)
breath_led_inst
(
.sys_clk (sys_clk) ,
.sys_rst_n(sys_rst_n) ,
.led_out (led_out)
);
endmodule
没有回复内容