案例1:呼吸灯0
实现功能:4个LED同时改变,亮度由PWM信号控制。
实验现象:
4个LED,灭→亮,逐渐变亮,到达最亮后熄灭,再从灭→亮,重复进入下一次循环。
代码实现:
module pwm(
input clk,
input rst_n,
output reg [3:0] led
);
reg [15:0] pwm0,count;
always @(posedge clk or negedge rst_n) begin
if(!rst_n)
count <= 16'b0;
else begin
count <= count + 1'b1;
if(count[15]==1) //打到周期预设定的数值,就清零
count <= 16'b0;
if(count < pwm0) //如果本周期中,周期小于PWM脉宽计数,那么LED就=1
led <= 4'b1111;
else
led <= 4'b0000; //PWM的低脉冲时候,就为0
end
end
always @(posedge count[14]) begin //一个周期前面一点,产生PWM加/减 信号
pwm0 <= pwm0 + 1'b1; //PWM 在一个周期完成之前加1,用于下一个周期的信号宽度
if(pwm0[13]==1) //脉宽达到预设定的数值
pwm0 <= 16'b0;
end
endmodule
案例2:呼吸灯1
实现功能:4个LED同时改变,亮度由PWM信号控制。
实验现象:
第1秒:灭→亮,逐渐变亮,达到最亮,
第2秒:亮→灭,逐渐变暗;
……
2s一个周期,重复进入下一次循环。
代码实现:
module breath_led(
input clk,
input rst_n,
output reg [3:0] led
);
reg flag;
// 计数器cnt_2us循环计数,计到99为2us
parameter cnt_2us_max = 7'd100 - 1'b1;
reg [6:0] cnt_2us;
always @(posedge clk or negedge rst_n) begin
if (!rst_n)
cnt_2us <= 7'd0;
else if(cnt_2us == cnt_2us_max)
cnt_2us <= 7'd0;
else
cnt_2us <= cnt_2us + 1'b1;
end
// 计数器cnt_2ms循环计数,计到999为2ms
parameter cnt_2ms_max = 10'd1000 - 1'b1;
reg [9:0] cnt_2ms;
always @(posedge clk or negedge rst_n) begin
if (!rst_n)
cnt_2ms <= 10'd0;
else if(cnt_2us == cnt_2us_max && cnt_2ms == cnt_2ms_max)
cnt_2ms <= 10'd0;
else if(cnt_2us == cnt_2us_max)
cnt_2ms <= cnt_2ms + 1'b1;
else
cnt_2ms <= cnt_2ms;
end
// 计数器cnt_2s循环计数,计到999为2s
parameter cnt_2s_max = 10'd1000 - 1'b1;
reg [9:0] cnt_2s;
always @(posedge clk or negedge rst_n) begin
if (!rst_n)
cnt_2s <= 10'd0;
else if(cnt_2us == cnt_2us_max && cnt_2ms == cnt_2ms_max && cnt_2s == cnt_2s_max)
cnt_2s <= 10'd0;
else if(cnt_2us == cnt_2us_max && cnt_2ms == cnt_2ms_max)
cnt_2s <= cnt_2s + 1'b1;
else
cnt_2s <= cnt_2s;
end
//flag标志
always @(posedge clk or negedge rst_n) begin
if (!rst_n)
flag <= 1'd0;
else if(cnt_2us == cnt_2us_max && cnt_2ms == cnt_2ms_max && cnt_2s == cnt_2s_max)
flag <= ~flag;
else
flag <= flag;
end
//brearh_led控制
always @(posedge clk or negedge rst_n) begin
if (!rst_n)
led <= 4'b0000;
else if(cnt_2s >= cnt_2ms && flag == 1'b0)
led <= 4'b1111;
else if(cnt_2s < cnt_2ms && flag == 1'b0)
led <= 4'b0000;
else if(cnt_2s >= cnt_2ms && flag == 1'b1)
led <= 4'b0000;
else if(cnt_2s < cnt_2ms && flag == 1'b1)
led <= 4'b1111;
else
led <= 4'b0000;
end
endmodule
案例3:呼吸灯2
实现功能:4个LED同时改变,亮度由PWM信号控制。
实验现象:
占空比越大,LED灯越暗;
占空比越小,LED灯越亮。
第1个2秒: pwm_time <= 19’d450_000;//占空比90%
第2个2秒: pwm_time <= 19’d350_000;//占空比70%
第3个2秒:pwm_time <= 19’d250_000;//占空比50%
第4个2秒:pwm_time <= 19’d100_000;//占空比20%
第5个2秒:pwm_time <= 19’d50_000;//占空比10%
第6个2秒: pwm_time <= 19’d5_000;//占空比1%
第7个2秒: pwm_time <= 19’d100_000;//占空比20%
第8个2秒:pwm_time <= 19’d250_000;//占空比50%
第9个2秒:pwm_time <= 19’d350_000;//占空比70%
第10个2秒: pwm_time <= 19’d450_000;//占空比90%
……
20s一个周期,重复进入下一次循环。
代码实现:
module breathing_led(
input clk,
input rst_n,
output reg [3:0] led
);
reg flag;
// 计数器cnt_10ms循环计数,计到499999为10ms
parameter cnt_10ms_max = 19'd500_000 - 1'b1;
reg [18:0] cnt_10ms;
always @(posedge clk or negedge rst_n) begin
if (!rst_n)
cnt_10ms <= 19'd0;
else if(cnt_10ms == cnt_10ms_max)
cnt_10ms <= 19'd0;
else
cnt_10ms <= cnt_10ms + 1'b1;
end
// 计数器cnt_2s循环计数,计到199为2s
parameter cnt_2s_max = 8'd200 - 1'b1;
reg [7:0] cnt_2s;
always @(posedge clk or negedge rst_n) begin
if (!rst_n)
cnt_2s <= 8'd0;
else if(cnt_10ms == cnt_10ms_max && cnt_2s == cnt_2s_max)
cnt_2s <= 8'd0;
else if(cnt_10ms == cnt_10ms_max)
cnt_2s <= cnt_2s + 1'b1;
else
cnt_2s <= cnt_2s;
end
// 计数器cnt_20s循环计数,计到9为20s
parameter cnt_20s_max = 4'd10 - 1'b1;
reg [3:0] cnt_20s;
always @(posedge clk or negedge rst_n) begin
if (!rst_n)
cnt_20s <= 4'd0;
else if(cnt_10ms == cnt_10ms_max && cnt_2s == cnt_2s_max && cnt_20s == cnt_20s_max)
cnt_20s <= 4'd0;
else if(cnt_10ms == cnt_10ms_max && cnt_2s == cnt_2s_max)
cnt_20s <= cnt_20s + 1'b1;
else
cnt_20s <= cnt_20s;
end
reg [18:0] pwm_time;
//pwm控制brearhing_led
always @(posedge clk or negedge rst_n) begin
if (!rst_n)
led <= 4'b0000;
else if(cnt_10ms == pwm_time-1'b1)
led <= 4'b1111;
else if(cnt_10ms == cnt_10ms_max)
led <= 4'b0000;
else
led <= led;
end
//改变pwm信号的占空比
always @(*) begin
case(cnt_20s)
4'd0: pwm_time <= 19'd450_000;//90%
4'd1: pwm_time <= 19'd350_000;//70%
4'd2: pwm_time <= 19'd250_000;//50%
4'd3: pwm_time <= 19'd100_000;//20%
4'd4: pwm_time <= 19'd50_000;//10%
4'd5: pwm_time <= 19'd5_000;//1%
4'd6: pwm_time <= 19'd100_000;//20%
4'd7: pwm_time <= 19'd250_000;//50%
4'd8: pwm_time <= 19'd350_000;//70%
4'd9: pwm_time <= 19'd450_000;//90%
default: pwm_time <= 19'd0;
endcase
end
endmodule
说明:
本文的3个案例,在正点原子FPGA开拓者开发板上亲测有效。
案例中LED的管脚分配如下:
参考资料0: 最简单的FPGA verilog写的 PWM 例子.
参考资料1: FPGA实现呼吸灯功能实验.