一、设计目标
本次实验要实现的工程,旨在实现控制LED灯亮度的功能,具体要求为:上电后,LED灯显示接近于灭,随后每隔2秒亮度发生一次变化,在前10秒时间内,每隔2秒逐渐变亮。在下一个10秒时间内,每隔2秒,亮度逐渐变暗。简单来说即是以20秒为一次循环,每隔2秒变化一次,前10秒亮度逐渐增大,后10秒亮度逐渐减小。
二、设计实现
根据PWM的原理,可以得知通过控制PWM的占空比可以实现LED灯的亮度控制。PWM占空比越大(高电平时间越长,低电平时间越低),灯的亮度越暗。可以这样理解:FPGA控制led信号的输出,可以输出为PWM波形并通过调整占比来达到改变LED灯亮度的效果。根据设计目标可以得出设计方案:每20秒一次循环,每隔2秒改变一次led的占空比,前10秒占空比逐渐变大,LED灯逐渐变亮,后10秒占空比逐渐变小,LED灯也随之逐渐变暗。
设计时设定的占空比如下:
第1个2秒内,占空比为95%; |
第2个2秒内,占空比为85%; |
第3个2秒内,占空比为70%; |
第4个2秒内,占空比为50%; |
第5个2秒内,占空比为20%; |
第6个2秒内,占空比为20%; |
第7个2秒内,占空比为50%; |
第8个2秒内,占空比为70%; |
第9个2秒内,占空比为85%; |
第10个2秒内,占空比为95%。 |
之后以此为规律循环往复。
根据经验值,建议PWM波周期设为10毫秒,LED灯显示的亮度效果是最好的。在完全掌握了设计原理可以独立完成设计后,可以再进行不同波型以及不同占空比的尝试。
三、代码
(1)顶层模块
module pwm_light(
clk,
rst_n,
led
);
input clk ;
input rst_n;
output led ;
wire [7:0] led ;
wire [3:0] x;
wire m;
//pwm灯的例化
pwm uut_pwm(
.clk(clk),
.rst_n(rst_n),
.x_in(x), //接收控制占空比的条件
.m_out(m),//输出计数2s的加一条件
.led(led)
);
//计数20次的例化
count uut_count(
.clk(clk),
.rst_n(rst_n),
.m_in(m),//接收计数2s的加一条件
.x_out(x)//输出控制占空比的条件
);
endmodule
(2)pwm模块(用于产生周期10ms的脉冲波)
module pwm(
clk,
rst_n,
m_out,
x_in,
led
);
input clk ;
input rst_n ;
input x_in ;
output m_out ;
output led ;
reg [18:0] cnt ;
wire add_cnt ;
wire end_cnt ;
wire [3:0] x_in ;
reg [7:0] led ;
wire m_out ;
reg [18:0] f ;
parameter TIME_10ms = 500_000;
//计数pwm的10ms周期
always @(posedge clk or negedge rst_n)begin
if(!rst_n) begin
cnt <= 0;
end
else if(add_cnt) begin
if(end_cnt)
cnt <= 0;
else
cnt <= cnt + 1;
end
end
assign add_cnt = 1; //加一条件
assign end_cnt = add_cnt && cnt== TIME_10ms - 1; //结束条件
assign m_out = end_cnt; //赋值2s计数器的加一条件
//led灯
always @(posedge clk or negedge rst_n)begin
if(rst_n==1'b0) begin
led <= 8'b00000000;
end
else if(add_cnt && cnt == f-1) begin
led <= 8'b11111111;
end
else if(end_cnt) begin
led <= 8'b00000000;
end
end
//控制占空比
always@(*) begin
if(x_in==1-1)begin
f=475_000;
end
else if(x_in==2-1)begin
f=425_000;
end
else if(x_in==3-1)begin
f=350_000;
end
else if(x_in==4-1)begin
f=250_000;
end
else if(x_in==5-1)begin
f=100_000;
end
else if(x_in==6-1)begin
f=100_000;
end
else if(x_in==7-1)begin
f=250_000;
end
else if(x_in==8-1)begin
f=350_000;
end
else if(x_in==9-1)begin
f=425_000;
end
else if(x_in==10-1)begin
f=475_000;
end
end
endmodule
(3)count模块(用于led的控制)
module count(
clk,
rst_n,
m_in,
x_out
);
input clk ;
input rst_n ;
input m_in ;
output x_out ;
reg [7:0] cnt1 ;
wire add_cnt1 ;
wire end_cnt1 ;
reg [3:0] cnt2 ;
wire add_cnt2 ;
wire end_cnt2 ;
wire [3:0] x_out ;
wire m_in ;
parameter TIME_1s = 200;
parameter TIME_20 = 10;
//计数2s
always @(posedge clk or negedge rst_n)begin
if(!rst_n) begin
cnt1 <= 0;
end
else if(add_cnt1) begin
if(end_cnt1)
cnt1 <= 0;
else
cnt1 <= cnt1 + 1;
end
end
assign add_cnt1 = m_in; //加一条件
assign end_cnt1 = add_cnt1 && cnt1== TIME_1s - 1; //结束条件
//计数10次
always @(posedge clk or negedge rst_n)begin
if(!rst_n) begin
cnt2 <= 0;
end
else if(add_cnt2) begin
if(end_cnt2)
cnt2 <= 0;
else
cnt2 <= cnt2 + 1;
end
end
assign add_cnt2 = end_cnt1; //加一条件
assign end_cnt2 = add_cnt2 && cnt2== TIME_20 - 1; //结束条件
assign x_out = cnt2; //赋值控制占空比的条件
endmodule
四、仿真代码及图像
(1)仿真代码
`timescale 1 ps/ 1 ps
module pwm_light_vlg_tst();
reg clk;
reg rst_n;
wire [7:0] led;
parameter CYCLE=20;
pwm_light i1 (
.clk(clk),
.led(led),
.rst_n(rst_n)
);
initial begin
clk=0;
forever#(CYCLE/2)begin
clk=~clk;
end
end
initial begin
#1;
rst_n=0;
#(CYCLE*10);
rst_n=1;
end
endmodule
仿真时,更改了计数器的计数次数,为了波形的更快输出。
(2)图像
五、综合图像
六、上板
pwm呼吸灯