赞
踩
目录
完成一个呼吸灯,要求从亮到灭的时间位2s,从灭到亮的时间为2s,完成呼吸灯的一个过程需要四秒。
呼吸灯的实现主要是利用人眼视觉差来实现“呼”“吸”过程的效果,我们只需产生一个逐渐改变占空比的方波即可,即PWM。我们可以将2秒等分为1000份,这样每一个份即为2/1000s,假设第一份2/1000s为高电平(占空比100%),然后逐渐减少占空比,经过1000次以后,该方波占空比变为0,我们设定方波为高电平时,led灯亮,否则灭,这样我们就实现了从亮到灭的“”呼“”过程,类似的对于“吸”这个过程,我们需要设置一个flag_r标志信号,使其亮灭与“呼”过程相反即可。下图给出了该方波占空比的波形图。
整个呼吸效果的时序图如如下:
由上图可见有两个“1000”和一个“100”,要注意的是这三者间的关系,pwm_cyc_cnt的1000指的是将亮--->灭的整个2s的过程分为1000份(2/1000s),clk50mcnt_1000中的1000指的是(2/1000s)的“小块”进一步分1000份(2/1000/1000s)=2000ns,这个2000ns需要频率为50mhz的晶振抖动100次,故clk50mcnt中的100表示此含义。需要注意的是clk50mcnt使在基准时钟的基础上产生的,clk50mcnt_1000是在clk50mcnt的基础上产生的,pwm_cyc_cnt是在clk50mcnt_1000的基础上产生的。
进行1000次等分的就是为了在短时间内快速变化,由于人眼的视觉差,使得整个过程平滑流畅。
用我们所期望的pwm波形对比可发现,当clk50mcnt_1000<pwm_cyc_cnt时将led电平拉低/高就能产生我们所需要的由亮到暗/由暗到亮的呼吸效果。
- module led_breath(
-
- input wire clk,
- input wire rst_n,
-
- output wire [3:0]led
- );
- reg [6:0] clk50mcnt;
- reg [9:0] clk50mcnt_1000;
- reg [9:0] pwm_cyc_cnt;
- reg flag_r;
- wire rst;
- wire [3:0]led_wave;
- assign rst = ~rst_n;
-
- //lk50mcnt counter
- always@(posedge clk)begin
- if(rst == 1'b1)begin
- clk50mcnt <= 'd0;
- end
- else if (clk50mcnt == 'd99)begin
- clk50mcnt <= 'd0;
- end
- else begin
- clk50mcnt <= clk50mcnt + 1'b1;
- end
- end
-
- //clk50mcnt_1000 counter
- always@(posedge clk)begin
- if(rst == 1'b1)begin
- clk50mcnt_1000 <= 'd0;
- end
- else if (clk50mcnt == 'd99 && clk50mcnt_1000 == 'd999)begin
- clk50mcnt_1000 <= 'd0;
- end
- else if (clk50mcnt == 'd99)begin
- clk50mcnt_1000 <= clk50mcnt_1000 + 1'b1;
- end
- end
-
- //pwm_cyc_cnt counter
- always@(posedge clk)begin
- if(rst == 1'b1)begin
- pwm_cyc_cnt <= 'd0;
- end
- else if (clk50mcnt == 'd99 && clk50mcnt_1000 == 'd999 && pwm_cyc_cnt == 'd999)begin
- pwm_cyc_cnt <= 'd0;
- end
- else if (clk50mcnt == 'd99 && clk50mcnt_1000 == 'd999)begin
- pwm_cyc_cnt <= pwm_cyc_cnt + 1'b1;
- end
- end
-
- always@(posedge clk)begin
- if(rst == 1'b1)begin
- flag_r <= 1'b0;
- end
- else if (clk50mcnt == 'd99 && clk50mcnt_1000 == 'd999 && pwm_cyc_cnt == 'd999)begin
- flag_r <= ~flag_r;
- end
- else begin
- flag_r <= flag_r;
- end
- end
-
- assign led_wave = ( clk50mcnt_1000 < pwm_cyc_cnt)?4'b0000:4'b1111;
- assign led = (flag_r <= 4'b0000)?led_wave:~led_wave;
-
- endmodule

由于呼吸的速度是由clk50mcnt控制的,若两个呼吸单程分别为2s和1s,故我们需要重新设定一个7位宽的now_cnt变量来储存不同速率的clk50mcnt(us_2s_cnt、us_1s_cnt),和一个两位宽的输入信号(key_in).
- input [1:0] key_in;
-
- reg [6:0] now_cnt;
-
- parameter us_2s_cnt = 'd99;
- parameter us_1s_cnt = 'd49;
最后利用key_in来切换呼吸速率
- always@(posedge clk)begin
- if(rst == 1'b1)begin
- now_cnt <= 7'd0;
- end
- else if (key_in[0]==1&&key_in[1]==0) begin
- now_cnt <= us_2s_cnt ;
- end
- else if (key_in[1]==1&&key_in[0]==0) begin
- now_cnt <= us_1s_cnt ;
- end
-
- end
- module led_breath(
-
- input wire clk,
- input wire rst_n,
- input [1:0] key_in,
-
- output wire [3:0]led
- );
- reg [6:0] clk50mcnt;
- reg [9:0] clk50mcnt_1000;
- reg [9:0] pwm_cyc_cnt;
- reg flag_r;
- reg [6:0] now_cnt;
-
- wire rst;
- wire [3:0] led_wave;
- assign rst = ~rst_n;
-
- parameter us_2s_cnt = 'd99;
- parameter us_1s_cnt = 'd49;
-
- //lk50mcnt counter
- always@(posedge clk)begin
- if(rst == 1'b1)begin
- clk50mcnt <= 'd0;
- end
- else if (clk50mcnt == now_cnt-1)begin
- clk50mcnt <= 'd0;
- end
- else begin
- clk50mcnt <= clk50mcnt + 1'b1;
- end
- end
-
- //clk50mcnt_1000 counter
- always@(posedge clk)begin
- if(rst == 1'b1)begin
- clk50mcnt_1000 <= 'd0;
- end
- else if (clk50mcnt == now_cnt-1 && clk50mcnt_1000 == 'd999)begin
- clk50mcnt_1000 <= 'd0;
- end
- else if (clk50mcnt == now_cnt-1)begin
- clk50mcnt_1000 <= clk50mcnt_1000 + 1'b1;
- end
- end
-
- //pwm_cyc_cnt counter
- always@(posedge clk)begin
- if(rst == 1'b1)begin
- pwm_cyc_cnt <= 'd0;
- end
- else if (clk50mcnt == now_cnt-1 && clk50mcnt_1000 == 'd999 && pwm_cyc_cnt == 'd999)begin
- pwm_cyc_cnt <= 'd0;
- end
- else if (clk50mcnt == now_cnt-1 && clk50mcnt_1000 == 'd999)begin
- pwm_cyc_cnt <= pwm_cyc_cnt + 1'b1;
- end
- end
-
- // flag_r
- always@(posedge clk)begin
- if(rst == 1'b1)begin
- flag_r <= 1'b0;
- end
- else if (clk50mcnt == now_cnt-1 && clk50mcnt_1000 == 'd999 && pwm_cyc_cnt == 'd999)begin
- flag_r <= ~flag_r;
- end
- else begin
- flag_r <= flag_r;
- end
- end
-
- //key control
- always@(posedge clk)begin
- if(rst == 1'b1)begin
- now_cnt <= 7'd0;
- end
- else if (key_in[0]==1&&key_in[1]==0) begin
- now_cnt <= us_2s_cnt ;
- end
- else if (key_in[1]==1&&key_in[0]==0) begin
- now_cnt <= us_1s_cnt ;
- end
-
- end
-
-
- assign led_wave = ( clk50mcnt_1000 < pwm_cyc_cnt)?4'b0000:4'b1111;
- assign led = (flag_r <= 4'b0000)?led_wave:~led_wave;
-
- endmodule
-

如需按键消抖,加入按键消抖模块即可。
在代码编写中flag标志信号没有理解到位导致实验现象只有“吸”没有“呼”的现象。
错误示范:
- always@(posedge clk)begin
- if(rst == 1'b1)begin
- flag_r <= 1'b0;
- end
- else if (clk50mcnt == 'd99 && clk50mcnt_1000 == 'd999 && pwm_cyc_cnt == 'd999)begin
- flag_r <= 1'b1;
- end
- else begin
- flag_r <= 1'b0;
- end
- end
修改后:
- always@(posedge clk)begin
- if(rst == 1'b1)begin
- flag_r <= 1'b0;
- end
- else if (clk50mcnt == 'd99 && clk50mcnt_1000 == 'd999 && pwm_cyc_cnt == 'd999)begin
- flag_r <= ~flag_r;
- end
- else begin
- flag_r <= flag_r;
- end
- end
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。