| |
特效呼吸灯
1 功能概述
顾名思义,特效呼吸灯是指在电路控制之下,LED灯光完成由灭到亮、由亮到灭的逐渐变化,感觉像是在呼吸一样。最原始的表现形式是指一种通过相对简单的电路组织形成的灯光效果。呼吸灯效果的LED每时每刻都在以不同的功率工作,以不同的亮度值拟合亮度变化,从而形成非常平顺柔和的灯光特效。除广泛应用于智能手机上之外,电脑、音响、汽车等各个领域也会经常应用。比如,鼠标的闪闪亮就是呼吸灯,起到很好的视觉装饰效果。
优秀的设计作品都是有“生命”的。从这个意义上来说,设计师即造物者。我们可以展开拟人化的想象,流水灯像一个快乐奔跑的孩子,闪烁灯就像他眨巴着眼睛讲着童话。而特效呼吸灯,则是安静的躺在床上睡觉,一起一伏的呼吸显示睡得非常安详平静。
本模块的功能要求是,实现8个灯前1s慢慢变暗,后1s慢慢变亮,不断重复以上操作。
2 设计思路
设计中,通过生成1us的延时电路,提取1us的标志信号delays_1us;接着在delays_1us信号的驱动下,通过1ms的延时电路,提取生成1ms的标志信号delays_1us;最后在delays_1us信号的驱动下,生成1s的驱动电路。
亮度变化实际上是通过占空比的变化周期来确定的。占空比通过cnt2的计数来变换,而每次变化为1ms,因此PWM的周期是1ms。
(1)在第1s中,随着cnt2由0到999逐渐增大,每一个1ms的占空比通过cnt1去调节。当cnt1<cnt2时,为高电平;反之,当cnt1≥cnt2时,为低电平。
(2)在第2s中,随着cnt2由0到999逐渐增大,每一个1ms的占空比同样通过cnt1去调节。当,cnt1<cnt2时,为低电平;反之,当cnt1>cnt2时,为高电平。
信号列表如下:
信号名 |
I/O |
位宽 |
说明 |
clk |
I |
1 |
系统工作时钟100MHz。 |
rst_n |
I |
1 |
系统复位信号,低电平有效。 |
led |
O |
8 |
8位led灯,低电平亮。 |
3 程序设计
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 |
module led_breathe (
clk ,
rst_n ,
led );
parameter DATA_W =
8 ;
parameter DELAY_1US = 50 ;
parameter DELAY_1MS = 1000 ;
parameter DELAY_1S = 1000
;
parameter DATA_A =
6 ;
parameter DATA_B =
10 ;
input clk ;
input rst_n ;
output [DATA_W-1:0] led
;
reg [DATA_W-1:0] led
;
reg [DATA_A-1:0] cnt
;
reg [DATA_B-1:0] cnt1
;
reg [DATA_B-1:0] cnt2
;
reg
dis_mode ;
reg pwm_change
;
wire
add_cnt ;
wire
add_cnt1 ;
wire
add_cnt2 ;
wire
end_cnt ;
wire
end_cnt1 ;
wire
end_cnt2 ;
wire on ;
always @(posedge clk or negedge rst_n)begin if(!rst_n)begin cnt <= 0; end else if(add_cnt)begin if(end_cnt) cnt <= 0; else cnt <= cnt + 1; end
end
assign add_cnt = 1;
assign end_cnt = add_cnt && cnt== DELAY_1US-1;
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin cnt1 <= 0; end else if(add_cnt1)begin if(end_cnt1) cnt1 <= 0; else cnt1 <= cnt1 + 1; end
end
assign add_cnt1 = end_cnt;
assign end_cnt1 = add_cnt1 && cnt1== DELAY_1MS-1;
always @(posedge clk or negedge rst_n)begin if(!rst_n)begin cnt2 <= 0; end else if(add_cnt2)begin if(end_cnt2) cnt2 <= 0; else cnt2 <= cnt2 + 1; end
end
assign add_cnt2 = end_cnt1;
assign end_cnt2 = add_cnt2 && cnt2== DELAY_1S-1;
always @(posedge clk or negedge
rst_n)begin if(rst_n==1'b0)begin dis_mode <= 0 ; end else if(end_cnt2)begin dis_mode <= ~dis_mode ; end else begin dis_mode <= dis_mode ; end
end
always @(*)begin if(cnt1 < cnt2) pwm_change = 1 ; else pwm_change = 0 ;
end
always @(posedge clk or negedge
rst_n)begin if(rst_n==1'b0)begin led <= 0 ; end else if(on)begin led <= 8'b1111_1111 ; end else begin
led <= 0 ; end
end
assign n = (dis_mode==0 && pwm_change) ||(dis_mode &&
pwm_change==0) ; endmodule |