一、呼吸灯简介
呼吸灯:由灭渐亮,再由亮渐灭,模仿人呼吸方式的LED灯。
呼吸灯原理:PWM(Pulse Width Modulation),脉冲宽度调制。
在一定周期内改变高低电平占空比达到亮度渐变效果,高电平占比越多,LED灯越亮。(由亮渐灭为相反过程)
二、实验任务
本节实验任务是使用正点原子FPGA开发板上的LED,实现呼吸灯效果,即由灭渐亮,再由亮渐灭(渐亮和渐灭的时间为2s)。
三、程序设计
1.思维导图
2.波形图
3.代码编写
module breath_led(
input sys_clk,
input sys_rst_n,
output reg led
);
parameter CNT_2US_MAX = 7'd100;
parameter CNT_2MS_MAX = 10'd1000;
parameter CNT_2S_MAX = 10'd1000;
reg [6:0] cnt_2us;
reg [9:0] cnt_2ms;
reg [9:0] cnt_2s;
reg inc_dec_flag; //亮度递增/递减标志位 0:递增 1:递减
//计数器计时2us
always @(posedge sys_clk or negedge sys_rst_n)begin
if(!sys_rst_n)
cnt_2us <= 7'b0;
else if(cnt_2us == (CNT_2US_MAX - 7'b1))
cnt_2us <= 7'b0;
else
cnt_2us <= cnt_2us + 7'b1;
end
//计数器计时2ms
always @(posedge sys_clk or negedge sys_rst_n)begin
if(!sys_rst_n)
cnt_2ms <= 10'b0;
else if(cnt_2us == (CNT_2US_MAX - 7'b1)
&& cnt_2ms == (CNT_2MS_MAX - 10'b1))
cnt_2ms <= 10'b0;
else if(cnt_2us == (CNT_2US_MAX - 7'b1))
cnt_2ms <= cnt_2ms + 10'b1;
end
//计数器计时2s
always @(posedge sys_clk or negedge sys_rst_n)begin
if(!sys_rst_n)
cnt_2s <= 10'b0;
else if(cnt_2us == (CNT_2US_MAX - 7'b1)
&& cnt_2ms == (CNT_2MS_MAX - 10'b1)
&& cnt_2s == (CNT_2S_MAX - 10'b1))
cnt_2s <= 10'b0;
else if(cnt_2us == (CNT_2US_MAX - 7'b1)
&& cnt_2ms == (CNT_2MS_MAX - 10'b1))
cnt_2s <= cnt_2s + 10'b1;
end
//亮度递增/递减标志位
always @(posedge sys_clk or negedge sys_rst_n)begin
if(!sys_rst_n)
inc_dec_flag <= 1'b0;
else if(cnt_2us == (CNT_2US_MAX - 7'b1)
&& cnt_2ms == (CNT_2MS_MAX - 10'b1)
&& cnt_2s == (CNT_2S_MAX - 10'b1))
inc_dec_flag <= ~inc_dec_flag;
else
inc_dec_flag <= inc_dec_flag;
end
//控制LED灯PWM输出
always @(posedge sys_clk or negedge sys_rst_n)begin
if(!sys_rst_n)
led <= 1'b0;
else if(inc_dec_flag == 1'b0 && cnt_2ms <= cnt_2s)
led <= 1'b1;
else if(inc_dec_flag == 1'b1 && cnt_2ms >= cnt_2s)
led <= 1'b1;
else
led <= 1'b0;
end
endmodule
4.实验仿真
编写tb_breath_led文件
'timescale 1ns/1ns //仿真单位/仿真精度
module tb_breath_led();
parameter CLK_PERIOD = 20;
parameter CNT_2US_MAX = 7'd1;
parameter CNT_2MS_MAX = 10'd10;
parameter CNT_2S_MAX = 10'd10;
reg sys_clk; //周期20ns
reg sys_rst_n;
wire led;
initial begin
sys_clk <= 1'b0;
sys_rst_n <= 1'b0;
#200
sys_rst_n <= 1'b1;
end
always #(CLK_PERIOD/2) sys_clk = ~sys_clk;
breath_led #(
.CNT_2US_MAX (CNT_2US_MAX),
.CNT_2MS_MAX (CNT_2MS_MAX),
.CNT_2S_MAX (CNT_2S_MAX )
)
u_breath_led(
.sys_clk (sys_clk ),
.sys_rst_n (sys_rst_n),
.led (led ),
);
endmodule
在modulesim仿真,以500ns为周期(减少仿真时间),下图为部分放大后仿真结果。
cnt_2s缩小后为2000ns。
cnt_2ms缩小后为200ns。
实验验证为预期输出。
四、下载验证
通过vivado创建工程,配置IO口和约束文件。
编译之后下载到开发板。
显示编译成功。
通过open target自动连接开发板再选择到指定文件(代码)下载
开发板实现控制效果。