注:学习笔记主要参考:
- 【野火】FPGA系列教学视频,真正的手把手教学,“波形图”教学法,现场画波形图写代码,硬件基于野火FPGA EP4CE10征途系列开发板,已完结
- 《Verilog HDL数字系统设计及实践》刘睿强等编著
- 工程及代码文件都会开源在本人的GitHub仓库,对大家有帮助的话,麻烦点个Star。
- 章节内容有一定编程语言基础的门槛,我也尽可能的对内容写的详细简单。如果不出意外,栏目会持续更新到FPGA的图像处理领域。目前FPGA发展情况来看,将来的潜力很大。大家积极留言交流
在这个教学内容中,我们将通过实现一个呼吸灯来学习如何使用Verilog HDL进行FPGA开发,并了解PWM(脉冲宽度调制)的使用。
呼吸灯原理
呼吸灯的效果是通过逐渐增加和减少LED的亮度来实现的。在硬件上,这可以通过调整LED的供电时间来实现,即调整脉冲宽度调制(PWM)信号的占空比。
PWM简介
PWM是一种通过调整脉冲的宽度(即占空比)来控制模拟电路的一种方法。占空比是指脉冲高电平的时间与整个脉冲周期的比例。通过调整占空比,我们可以控制LED的亮度。
实现步骤
-
生成PWM信号:首先,我们需要生成一个PWM信号。通常,这可以通过一个计数器实现,计数器的最大值决定了PWM信号的周期,而比较值则决定了占空比。当计数器的值小于比较值时,PWM输出为高电平;否则为低电平。这里我们使用3个计数器来实现,核心就是将50MHZ的时钟频率怎么换算成1s,然后前0.5s从熄灭到点亮,后0.5s从点亮到熄灭,通过占空比来调整灯的亮暗程度
-
调整占空比:为了实现呼吸效果,我们需要逐渐增加和减少占空比。这可以通过逐渐增加和减少比较值来实现。通常,我们可以设置一个方向标志,用于控制比较值是增加还是减少。
-
连接到LED:将生成的PWM信号连接到LED的控制引脚上,就可以看到呼吸灯效果了。
波形图绘制
示例代码
程序运行代码如下,代码进行绑定引脚后进行编译烧录,如何操作可以查看我的一片文章#1_按键点亮一个LED_FPGA的零基础入门学习与开发实践-CSDN博客
module breath_led
#(
parameter CNT_1US_MAX = 6'd49,
parameter CNT_1MS_MAX = 10'd999,
parameter CNT_1S_MAX = 10'd999
)
(
input wire sys_clk,
input wire sys_rst_n,
output reg led_out
);
reg [9:0] cnt_1s;
reg [9:0] cnt_1ms;
reg [5:0] cnt_1us;
reg cnt_en;
// 1us的计时器设置
always @(posedge sys_clk or negedge sys_rst_n) begin
if(!sys_rst_n)
cnt_1us <= 6'd0;
else if(cnt_1us == CNT_1US_MAX) begin
cnt_1us <= 6'd0;
end
else
cnt_1us <= cnt_1us + 6'd1;
end
// 1ms的计时器设置
always @(posedge sys_clk or negedge sys_rst_n) begin
if(!sys_rst_n)
cnt_1ms <= 10'd0;
else if((cnt_1ms == CNT_1MS_MAX) && (cnt_1us == CNT_1US_MAX))
cnt_1ms <= 10'd0;
else if(cnt_1us == CNT_1US_MAX)
cnt_1ms <= cnt_1ms + 10'd1;
else
cnt_1ms <= cnt_1ms;
end
// 1s计时器的设置
always@(posedge sys_clk or negedge sys_rst_n)begin
if(!sys_rst_n)
cnt_1s <= 10'd0;
else if((cnt_1s == CNT_1S_MAX) && (cnt_1ms == CNT_1MS_MAX) && (cnt_1us == CNT_1US_MAX))
cnt_1s <= 10'd0;
else if((cnt_1ms == CNT_1MS_MAX) && (cnt_1us == CNT_1US_MAX))
cnt_1s <= cnt_1s + 10'd1;
else
cnt_1s <= cnt_1s;
end
// 使能信号的设置
always@(posedge sys_clk or negedge sys_rst_n)begin
if(!sys_rst_n)
cnt_en <= 1'b0;
else if((cnt_1s == CNT_1S_MAX) && (cnt_1ms == CNT_1MS_MAX) && (cnt_1us == CNT_1US_MAX))
cnt_en <= ~cnt_en;
else
cnt_en <= cnt_en;
end
// 输出信号的编写
always@(posedge sys_clk or negedge sys_rst_n)
if(!sys_rst_n)
led_out <= 1'b1;
else if(((cnt_en == 1'b0)&&(cnt_1ms<=cnt_1s))
|| ((cnt_en == 1'b1)&&(cnt_1ms>cnt_1s)))
led_out <= 1'b0;
else
led_out <= 1'b1;
endmodule
PWM呼吸灯,FPGA实现