設(shè)計(jì)規(guī)劃
呼吸燈的效果是LED燈在一段時(shí)間內(nèi)從完全熄滅的狀態(tài)逐漸變到最亮,再在同樣的時(shí)間段內(nèi)逐漸達(dá)到完全熄滅的狀態(tài)。這里我們需要實(shí)現(xiàn)1s內(nèi)實(shí)現(xiàn)從滅到亮,1s內(nèi)從亮到滅。
LED的明亮有兩種方式,第一種是在安全范圍內(nèi)給LED燈不同的供電電壓可以控制明滅;第二種是通過(guò)控制PWM的 占空比 ,同一時(shí)間段內(nèi)供給LED燈一個(gè)脈沖信號(hào)的低電平持續(xù)時(shí)間越長(zhǎng),LED燈越亮。我們?nèi)個(gè)相同的時(shí)間段,讓低電平的持續(xù)時(shí)間按照相等的時(shí)間間隔逐漸增多,led燈就會(huì)越來(lái)越亮了。
首先我們將1s分為1000個(gè)時(shí)間段,每段1ms。再將1ms分為1000個(gè)時(shí)間小段,每段1us。第一個(gè)1ms內(nèi)亮0us(滅),并在第二個(gè)1ms內(nèi)亮1us,...,在第1000個(gè)1ms內(nèi)亮999us。劃分的等級(jí)越多,看上去效果越好,但是人眼分辨率有限,大于這個(gè)分辨率就看起來(lái)幾乎沒(méi)有差異。
我們至少需要三個(gè)計(jì)數(shù)器,用來(lái)計(jì)時(shí)1s,1ms,1us。cnt_1us需要從0計(jì)數(shù)到49,不復(fù)位就計(jì)數(shù),計(jì)滿就清零。cnt_1ms完全沒(méi)必要重新產(chǎn)生,每當(dāng)cnt_1ms計(jì)數(shù)到999且cnt_1us計(jì)數(shù)到49,cnt_1ms就清零。cnt_1s同理在cnt_1ms計(jì)數(shù)到999且cnt_1us計(jì)數(shù)到49時(shí)就清零。
led_out要在不同時(shí)間段低電平持續(xù)時(shí)長(zhǎng)慢慢增加,需要一個(gè)小技巧。觀察上圖,LED為低電平時(shí),cnt_1s是0時(shí),cnt_1ms是1-999;cnt_1s是1時(shí),cnt_1ms是2-999...
LED燈從亮到滅是相反的過(guò)程,LED燈為高電平時(shí),cnt_1s>cnt_1ms。
區(qū)分從滅到亮和從亮到滅,可以使用一個(gè)電平標(biāo)志信號(hào)(使能)cnt_1s_en。cnt_1s_en為低電平時(shí)實(shí)現(xiàn)呼吸燈從滅到亮的過(guò)程,cnt_1s_en為高的時(shí)候?qū)崿F(xiàn)呼吸燈從亮到滅的過(guò)程,cnt_1s清零時(shí)cnt_1s_en取反。
編寫(xiě)代碼
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 define
reg [5:0] cnt_1us ;
reg [9:0] cnt_1ms ;
reg [9:0] cnt_1s ;
reg cnt_1s_en ;
//cnt_1us:1us計(jì)數(shù)器
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
cnt_1us <= 6'b0;
else if(cnt_1us == CNT_1US_MAX)
cnt_1us <= 6'b0;
else
cnt_1us <= cnt_1us + 1'b1;
//cnt_1ms:1ms計(jì)數(shù)器
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
cnt_1ms <= 10'b0;
else if(cnt_1ms == CNT_1MS_MAX && cnt_1us == CNT_1US_MAX)
cnt_1ms <= 10'b0;
else if(cnt_1us == CNT_1US_MAX)
cnt_1ms <= cnt_1ms + 1'b1;
//cnt_1s:1s計(jì)數(shù)器
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
cnt_1s <= 10'b0;
else if(cnt_1s == CNT_1S_MAX && cnt_1ms == CNT_1MS_MAX
&& cnt_1us == CNT_1US_MAX)
cnt_1s <= 10'b0;
else if(cnt_1ms == CNT_1MS_MAX && cnt_1us == CNT_1US_MAX)
cnt_1s <= cnt_1s + 1'b1;
//cnt_1s_en:1s計(jì)數(shù)器標(biāo)志信號(hào)
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
cnt_1s_en <= 1'b0;
else if(cnt_1s == CNT_1S_MAX && cnt_1ms == CNT_1MS_MAX
&& cnt_1us == CNT_1US_MAX)
cnt_1s_en <= ~cnt_1s_en;
//led_out:輸出信號(hào)連接到外部的led燈
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
led_out <= 1'b0;
else if((cnt_1s_en == 1'b1 && cnt_1ms < cnt_1s)||
(cnt_1s_en == 1'b0 && cnt_1ms > cnt_1s))
led_out <= 1'b0;
else
led_out <= 1'b1;
endmodule