工會網(wǎng)站平臺建設(shè)/推廣普通話的宣傳標(biāo)語
🍎與其擔(dān)心未來,不如現(xiàn)在好好努力。在這條路上,只有奮斗才能給你安全感。你若努力,全世界都會為你讓路。
呼吸燈,簡而言之就像人類呼吸一樣,有節(jié)奏的讓LED燈從:滅->微微亮->微亮->亮->高亮,然后再從:高亮->亮->微亮->微微亮->滅的這樣一個(gè)過程。
而LED的亮暗程度取決與電壓的高低,在安全范圍內(nèi),電壓越高LED亮度越大,電壓越低LED亮度越小。但是我們沒辦法去自動控制電壓的高低,所以我們采用通過改變其占空比的方式來調(diào)節(jié),即PWM(脈沖寬度調(diào)制)技術(shù)。簡單來說就是在一定的時(shí)間周期內(nèi),改變高電平所占用的時(shí)間。
呼吸燈框架圖如下:

PWM調(diào)制原理如下圖所示:

對PWM有了了解以后,我們開始畫波形圖,然后對照波形圖編寫代碼,波形圖如下:


①sys_clk:時(shí)鐘信號;
②sys_rst_n:復(fù)位信號,低電平有效;
③cnt_1us:因?yàn)殚_發(fā)板為50MHz,所以一個(gè)時(shí)鐘周期為20ns,那1us秒即50個(gè)時(shí)鐘周期;
④cnt_1ms:1000個(gè)1us進(jìn)1;
⑤cnt_1s:1000個(gè)1ms進(jìn)1;
⑥cnt_en:使能信號標(biāo)志位,用來判斷LED狀態(tài)是否到了反轉(zhuǎn)時(shí)刻;
⑦led_out:LED狀態(tài)輸出。
源代碼如下:
module breath_led //模塊開始,定義名稱為waterfall_light
#(parameter CNT_1US_MAX = 6'd49 , //定義全局變量CNT_1US_MAX,時(shí)間周期為1us parameter CNT_1MS_MAX = 10'd999 , //定義全局變量CNT_1MS_MAX,時(shí)間周期為1ms parameter CNT_1S_MAX = 10'd999 //定義全局變量CNT_1S_MAX,時(shí)間周期為1s
)
(input wire sys_clk , //定義sys_clk為輸入模式 (時(shí)鐘)input wire sys_rst_n , //定義sys_rst_n為輸入模式 (復(fù)位)output reg led_out //定義led_out為寄存器類型的輸出模式
);reg [5:0] cnt_1us; //定義cnt_1us為6位寬的寄存器類型reg [9:0] cnt_1ms; //定義cnt_1ms為10位寬的寄存器類型reg [9:0] cnt_1s ; //定義cnt_1s為10位寬的寄存器類型reg cnt_en ; //定義cnt_en為寄存器類型always@(posedge sys_clk or negedge sys_rst_n)beginif(sys_rst_n == 1'b0) //復(fù)位信號到來begincnt_1us <= 6'd0; //使cnt_1us清零endelse if(cnt_1us == CNT_1US_MAX) //判斷cnt_1us是否計(jì)數(shù)到最大值begincnt_1us <= 6'd0; //使cnt_1us清零endelse cnt_1us <= cnt_1us + 6'd1; //使cnt_1us + 1endalways@(posedge sys_clk or negedge sys_rst_n)beginif(sys_rst_n == 1'b0) //復(fù)位信號到來begincnt_1ms <= 10'd0; //使cnt_1ms清零endelse if((cnt_1ms == CNT_1MS_MAX)&&(cnt_1us == CNT_1US_MAX)) //判斷cnt_1us和cnt_1ms是否同時(shí)計(jì)數(shù)到最大值 begincnt_1ms <= 10'd0; //使cnt_1ms清零endelse if(cnt_1us == CNT_1US_MAX) //判斷cnt_1us是否計(jì)數(shù)到最大值begincnt_1ms <= cnt_1ms + 10'd1; //使cnt_1ms + 1endelse cnt_1ms <= cnt_1ms;endalways@(posedge sys_clk or negedge sys_rst_n)beginif(sys_rst_n == 1'b0) //復(fù)位信號到來begincnt_1s <= 10'd0; //使cnt_1s清零endelse if((cnt_1s == CNT_1S_MAX)&& (cnt_1ms == CNT_1MS_MAX)&&(cnt_1us == CNT_1US_MAX)) //判斷cnt_1us,cnt_1ms,cnt_1s是否同時(shí)計(jì)數(shù)到最大值 begincnt_1s <= 10'd0; //使cnt_1s清零endelse if((cnt_1ms == CNT_1MS_MAX)&&(cnt_1us == CNT_1US_MAX)) //判斷cnt_1us和cnt_1ms是否同時(shí)計(jì)數(shù)到最大值 begincnt_1s <= cnt_1s + 10'd1; //使cnt_1s + 1endelse cnt_1s <= cnt_1s; //使cnt_1s保持不變endalways@(posedge sys_clk or negedge sys_rst_n)beginif(sys_rst_n == 1'b0) //復(fù)位信號到來begincnt_en <= 1'b0; //使cnt_1s清零endelse if((cnt_1s == CNT_1S_MAX)&& (cnt_1ms == CNT_1MS_MAX)&&(cnt_1us == CNT_1US_MAX)) //判斷cnt_1us,cnt_1ms,cnt_1s是否同時(shí)計(jì)數(shù)到最大值 begincnt_en <= ~cnt_en; //使cnt_en取反endelse cnt_en <= cnt_en; //使cnt_en保持不變 endalways@(posedge sys_clk or negedge sys_rst_n)beginif(sys_rst_n == 1'b0) //復(fù)位信號到來beginled_out <= 1'b1; //使led_out置1endelse if(((cnt_en == 1'b0)&&(cnt_1ms <= cnt_1s)) || ((cnt_en == 1'b1)&&(cnt_1ms > cnt_1s))) //判斷cnt_en為0且cnt_1ms計(jì)數(shù)值小于等于cnt_1sbegin //或者判斷cnt_en為1且cnt_1ms計(jì)數(shù)值大于cnt_1s執(zhí)行l(wèi)ed_out <= 1'b0; //使led_out置0endelse led_out <= 1'b1; //使led_out置1endendmodule //模塊結(jié)束
生成的RTL電路圖如下:

仿真代碼如下:
`timescale 1ns/1ns //時(shí)間尺度預(yù)編譯指令 時(shí)間單位/時(shí)間精度module tb_breath_led (); //定義模塊名稱為tb_breath_ledreg sys_clk ; //定義sys_clk為reg型
reg sys_rst_n ; //定義sys_rst_n為reg型
wire led_out ; //定義led_out為reg型breath_led //例化對象名稱
#(.CNT_1US_MAX (6'd4) , //改變parameter定義的參數(shù).CNT_1MS_MAX (10'd9) , //改變parameter定義的參數(shù).CNT_1S_MAX (10'd9) //改變parameter定義的參數(shù)
)
breath_led_inst //實(shí)例化名稱
(.sys_clk (sys_clk), //使sys_clk信號端口例化為sys_clk.sys_rst_n (sys_rst_n), //使sys_rst_n信號端口例化為sys_rst_n.led_out (led_out) //使led_out信號端口例化為led_out
);initial //初始化begin sys_clk = 1'b1 ; //使sys_clk初始化為高電平狀態(tài)sys_rst_n = 1'b0 ; //使sys_clk初始化為低電平狀態(tài)#20 //延時(shí)20nssys_rst_n = 1'b1 ; //使sys_rst_n電平拉高end always #10 sys_clk = ~sys_clk; //使sys_clk電平10ns電平狀態(tài)反轉(zhuǎn)一次endmodule //模塊結(jié)束
仿真波形如下:

從圖中可以看出,運(yùn)行后的仿真波形與設(shè)計(jì)需求保持一致,任務(wù)完成。
🔥🔥🔥本系列文章持續(xù)更新,喜歡的話可以關(guān)注收藏~🔥🔥🔥