FPGA自学笔记(四)呼吸灯
实现呼吸灯的效果,先灭渐亮,再亮渐灭。
呼吸灯简介:呼吸灯采用 PWM 的方式,在固定的频率下,通过调整占空比的方式来控制 LED 灯亮度的变化。由计数器产生的固定周期的 PWM 信号,如果其占空比为 0,则 LED 灯不亮;如果其占空比为100%,则 LED 灯最亮。所以将占空比从 0 到 100%,再从 100%到 0 不断变化,就可以实现 LED 灯的“呼 吸”效果。
由上图可知,LED 高电平的时间由长渐渐变短,再由短渐渐变长,如果 LED 灯是高电平点亮,则LED 灯会呈现出亮度由亮到暗,再由暗到亮的过程。
一、模块端口及信号连线图
计数器用于生成固定周期(假设为1Khz)。
二、代码
1.定义信号
思考:整体上(外部大绿框)有两个输入一个输出。内部有三条连线:计数值,占空比,计数值。在实验过程中,led亮的程度是变化的,所以也定义成一个变量inc_dec_flag;。
module breath_led(
input sys_clk,
input sys_rst_n,
output led
);
reg [15:0] period_cnt; //1kHZ=1ms 系统是20ns,cnt=1ms/20ns=50000=1100 0011 0101 0000
reg [15:0] duty_cycle; //占空比
reg inc_dec_flag; //0 inc(灭到亮) ,1 dec(亮到灭)
2.计数器模块
//计数器
always @(posedge sys_clk or negedge sys_rst_n)begin
if(!sys_rst_n)
period_cnt <= 16'b0;
else if(period_cnt == 16'd50000) //0 — 50000循环计数
period_cnt <= 16'b0;
else
period_cnt <= period_cnt + 1'b1;
end
3.占空比调节模块
//占空比调节
always @(posedge sys_clk or negedge sys_rst_n)begin
if(!sys_rst_n) begin
duty_cycle <= 16'b0;
inc_dec_flag <= 1'b0; //先灭到亮
end
else begin
if(period_cnt == 16'd50000)begin
if(inc_dec_flag == 1'b0) begin
if(duty_cycle == 16'd50000) //到50000就要开始递减了
inc_dec_flag <= 1'b1;
else
duty_cycle <= duty_cycle + 16'd25; //呼吸灯变换快慢,假设幅度是0.5% 则累加值为50000*0.5%=25
end
else begin
if(duty_cycle == 16'd0) //到0就要开始递增了
inc_dec_flag <= 1'b0;
else
duty_cycle <= duty_cycle - 16'd25;
...
end
4.波形输出模块
//根据占空比和计数值之间的大小关系来输出 LED
assign led = (period_cnt >= duty_cycle) ? 1'b1 : 1'b0;