09 呼吸灯

呼吸灯简介

呼吸灯实际展示的效果就是一个 LED 灯的亮度由亮到暗,再由暗到亮的变化过程,并且该过程是循环往复的,像呼吸一样那么有节奏。 呼吸灯通常是采用 PWM(Pulse Width Modulation,即脉冲宽度调制) 的方式实现,在 PWM 频率固定的情况下,通过调整其占空比来控制 LED 灯亮度的变化。
在固定周期的 PWM 信号下,如果其占空比为 0,则 LED 灯不亮;如果其占空比为100%,则 LED 灯最亮。将占空比从 0 到 100%,再从 100%到 0 不断变化,就可以实现 LED 灯的“呼吸”效果,PWM 占空比调节示意图如下所示:
在这里插入图片描述

PWM信号的产生

可以使用1个寄存器和一个比较值来控制 PWM 信号的产生,寄存器进行周期计数,控制 PWM 的周期,在计数器周期计数过程中同时将计数值与比较值比较,当周期计数器的值小于比较寄存器时输出低电平,否则输出高电平,此时通过调节比较值便可调节 PWM 占空比,调节周期计数器的最大计数值便可调节 PWM 的周期,PWM 信号产生原理如下图所示:
在这里插入图片描述

原理图

LED0 到 LED3 这 4 个发光二极管的阴极分别连到 S8050(NPN 三极管)的集电极上,阳极都与 3.3V 电压相连,三极管的基极分别与 FPGA 相连,这是由于 FPGA 的 IO 口的电压只有 1.5V,电压较低,所以此处连接三极管是为了起到放大电压的作用。这样就可以通过改变三极管的状态来控制 LED 的亮灭。当 FPGA 输出到为高电平时,三极管导通,LED 灯亮;当 FPGA 输出到为低电平时,三极管截止,LED 灯灭。
在这里插入图片描述
在这里插入图片描述
此实验中只用到了LED0

系统框图

系统框图如下,包括两部分,分别是产生PWM信号的PWM模块和控制PWM占空比的呼吸灯模块
在这里插入图片描述

编写代码

PWM信号生成模块

PWM信号生成模块包含一个周期计数器和一个比较值,比较值通过模块外部输入的占空比结合PWM周期转换得到(这里由呼吸灯模块进行占空比控制),模块代码如下:

`timescale 1ns / 1nsmodule pwm_generate
(input sys_clk,							//系统时钟input sys_rst_n,						//系统复位,低电平有效input [31:0] period,					//PWM周期input [31:0] duty_cycle,				//PWM占空比output pwm_out							//输出的PWM信号
);//PWM周期
wire [31:0] pwm_period;
//PWM比较值
wire [31:0] pwm_compare;
//周期计数器,用于控制PWM周期
reg [31:0] count;//PWM周期,不能小于1
assign pwm_period = (period < 1) ? 1 : period;
//将PWM占空比转换为比较值
assign pwm_compare = (duty_cycle < period) ? (period - duty_cycle) : 0;//周期计数器的值小于比较寄存器时输出低电平,否则输出高电平
assign pwm_out = (count < pwm_compare) ? 0 : 1;//进行周期计数,用于控制PWM输出周期
always @(posedge sys_clk) beginif(!sys_rst_n)count <= 0;else if(count < (period - 1))count = count + 1;elsecount <= 0;
endendmodule

PWM信号生成模块仿真激励代码

PWM信号生成模块仿真激励代码很简单,就是在周期产生时钟信号的同时调整PWM占空比即可,代码如下:

`timescale 1ns / 1ns	//仿真单位/仿真精度module tb_pwm_generate();reg sys_clk;					//时钟
reg sys_rst_n;					//复位
reg [31:0] duty_cycle;			//占空比
wire pwm_out;					//PWWM信号initial beginsys_clk = 1'b0;sys_rst_n = 1'b0;duty_cycle = 0;#200sys_rst_n = 1'b1;//占空比为1#1000duty_cycle = 1;//占空比为2#1000duty_cycle = 2;//占空比为3#1000duty_cycle = 3;//占空比为4#1000duty_cycle = 4;//占空比为5#1000duty_cycle = 5;//占空比为6#1000duty_cycle = 6;//占空比为7#1000duty_cycle = 7;//占空比为8#1000duty_cycle = 8;//占空比为9#1000duty_cycle = 9;//占空比为10#1000duty_cycle = 10;
end//产生时钟
always #10 sys_clk = ~sys_clk;pwm_generate u_tb_pwm_generate_inst (.sys_clk(sys_clk),					//系统时钟.sys_rst_n(sys_rst_n),				//系统复位,低电平有效.period(10),						//PWM周期.duty_cycle(duty_cycle),			//PWM占空比.pwm_out(pwm_out)					//输出的PWM信号
);endmodule

呼吸灯模块

呼吸灯模块用于向PWM模块输出一个占空比,内部包含以下几个部分:

  • 一个周期计数器,用于控制PWM占空比调节的间隔
  • 根据占空比调节方向调节占空比
  • 记录占空比调节次数
  • 当占空比连续递增(递减)到指定次数时说明占空比达到最大(最小),此时改变占空比调节方向标志
    完整的代码如下:
`timescale 1ns / 1nsmodule breath_led #(parameter PWM_PERIOD = 100_000,				//pwm信号的周期parameter BREATH_PERIOD = 100_000_000,		//呼吸灯周期parameter BRIGHT_LEVEL = 100				//亮度等级
)
(input sys_clk,								//系统时钟input sys_rst_n,							//系统复位,低电平有效output reg [31:0] duty_cycle				//PWM占空比
);//PWM占空比调节步进,分100个亮度等级进行占空比调节
localparam DUTY_CYCLE_STEP = PWM_PERIOD / BRIGHT_LEVEL;
//PWM占空比调节间隔,分100个亮度等级进行占空比调节
localparam STEP_INTERVAL = BREATH_PERIOD / BRIGHT_LEVEL;//周期计数器,用于控制PWM占空比调节间隔
reg [31:0] period_count;
//占空比调节次数计数器,用于记录调节占空比的次数
reg [31:0] step_count;
//占空比调节方向控制,为0占空比加,为1占空比减
reg inc_dec_flag;//进行周期计数,用于控制PWM占空比调节间隔
always @(posedge sys_clk) beginif(!sys_rst_n)period_count <= 0;else if(period_count < (STEP_INTERVAL - 1))period_count <= period_count + 1;elseperiod_count <= 0;
end//根据占空比调节方向标志进行占空比调节,控制LED亮度
always @(posedge sys_clk) beginif(!sys_rst_n)duty_cycle <= 0;else if(period_count == (STEP_INTERVAL - 1)) beginif((inc_dec_flag == 1'b0) && ((PWM_PERIOD - duty_cycle) >= DUTY_CYCLE_STEP))duty_cycle <= duty_cycle + DUTY_CYCLE_STEP;else if((inc_dec_flag == 1'b1) && (duty_cycle >= DUTY_CYCLE_STEP))duty_cycle <= duty_cycle - DUTY_CYCLE_STEP;end
end//记录调节占空比的次数
always @(posedge sys_clk) beginif(!sys_rst_n)step_count <= 0;else if(period_count == (STEP_INTERVAL - 1)) beginif(step_count < (BRIGHT_LEVEL - 1))step_count <= step_count + 1;elsestep_count <= 0;end
end//占空比调节方向控制,为0占空比加,为1占空比减
//当占空比连续递增(递减)到指定次数时说明占空比达到最大(最小),此时改变占空比调节方向标志
always @(posedge sys_clk) beginif(!sys_rst_n)inc_dec_flag <= 0;else if(period_count == (STEP_INTERVAL - 1)) beginif(step_count == (BRIGHT_LEVEL - 1))inc_dec_flag <= ~inc_dec_flag;end
endendmodule

呼吸灯模块仿真激励代码

呼吸灯模块仿真激励代码非常简单,只需要产生激励时钟即可,代码如下:

`timescale 1ns / 1ns	//仿真单位/仿真精度module tb_breath_led();reg sys_clk;					//时钟
reg sys_rst_n;					//复位
wire [31:0] duty_cycle;			//占空比initial beginsys_clk = 1'b0;sys_rst_n = 1'b0;#200sys_rst_n = 1'b1;
end//产生时钟
always #10 sys_clk = ~sys_clk;breath_led #(.PWM_PERIOD(100),				//pwm信号的周期.BREATH_PERIOD(10_000),			//呼吸灯周期.BRIGHT_LEVEL(10)				//亮度等级
)
u_tb_breath_led_inst(.sys_clk(sys_clk),					//系统时钟.sys_rst_n(sys_rst_n),				//系统复位,低电平有效.duty_cycle(duty_cycle)				//PWM占空比
);endmodule

顶层模块

顶层模块主要用于例化PWM生成模块和呼吸灯模块,并将两个模块进行关联,代码如下:

`timescale 1ns / 1nsmodule top_breath_led #(parameter PWM_PERIOD = 100_000,				//pwm信号的周期parameter BREATH_PERIOD = 100_000_000,		//呼吸灯周期parameter BRIGHT_LEVEL = 100				//亮度等级
)
(input sys_clk,								//系统时钟input sys_rst_n,							//系统复位,低电平有效output led									//LED
);//PWM占空比
wire [31:0] duty_cycle;//例化呼吸灯模块
breath_led #(.PWM_PERIOD(PWM_PERIOD),				//pwm信号的周期.BREATH_PERIOD(BREATH_PERIOD),			//呼吸灯周期.BRIGHT_LEVEL(BRIGHT_LEVEL)				//亮度等级
)
u_breath_led_inst (.sys_clk(sys_clk),						//系统时钟.sys_rst_n(sys_rst_n),					//系统复位,低电平有效.duty_cycle(duty_cycle)					//PWM占空比
);//例化PWM发生模块
pwm_generate u_pwm_generate_inst (.sys_clk(sys_clk),						//系统时钟.sys_rst_n(sys_rst_n),					//系统复位,低电平有效.period(PWM_PERIOD),					//PWM周期.duty_cycle(duty_cycle),				//PWM占空比.pwm_out(led)							//PWM,用于控制LED
);endmodule

顶层模块仿真激励代码

顶层模块仿真激励代码非常简单,只需要产生激励时钟即可,代码如下:

`timescale 1ns / 1ns	//仿真单位/仿真精度module tb_top_breath_led();reg sys_clk;					//时钟
reg sys_rst_n;					//复位
wire led;						//LEDinitial beginsys_clk = 1'b0;sys_rst_n = 1'b0;#200sys_rst_n = 1'b1;
end//产生时钟
always #10 sys_clk = ~sys_clk;top_breath_led #(.PWM_PERIOD(10),					//pwm信号的周期.BREATH_PERIOD(1000),				//呼吸灯周期.BRIGHT_LEVEL(10)					//亮度等级
)
u_tb_top_breath_led_inst (.sys_clk(sys_clk),					//系统时钟.sys_rst_n(sys_rst_n),				//系统复位,低电平有效.led(led)							//LED
);endmodule

约束输入

管脚分配如下:
在这里插入图片描述
XDC 约束语句如下:

#时序约束
create_clock -period 20.000 -name sys_clk [get_ports sys_clk]#IO 管脚约束
set_property -dict {PACKAGE_PIN R4 IOSTANDARD LVCMOS15} [get_ports sys_clk]
set_property -dict {PACKAGE_PIN U7 IOSTANDARD LVCMOS15} [get_ports sys_rst_n]
set_property -dict {PACKAGE_PIN V9 IOSTANDARD LVCMOS15} [get_ports led]

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/492609.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

MySQL存储整数ip地址的优势

ipv4的地址字符串分布为0.0.0.0->255.255.255.255&#xff0c;其中最小长度为7&#xff0c;最大长度为15。 假设其均匀分布&#xff0c;则需要平均占用13.28125字符&#xff0c;计算方法如下&#xff0c;如果将这些字符串存储在数据库中&#xff0c;则还需要一个字符记录字符…

Wagtail安装运行并结合内网穿透实现公网访问本地网站界面

文章目录 前言1. 安装并运行Wagtail1.1 创建并激活虚拟环境 2. 安装cpolar内网穿透工具3. 实现Wagtail公网访问4. 固定的Wagtail公网地址 正文开始前给大家推荐个网站&#xff0c;前些天发现了一个巨牛的 人工智能学习网站&#xff0c; 通俗易懂&#xff0c;风趣幽默&#xf…

普中51单片机学习(LCD1602)

LCD1602 1602液晶也叫1602字符型液晶&#xff0c;它是一种专门用来显示字母、数字、符号的点阵型液晶模块。它是由若干个5x7或者5x10的点阵字符位组成&#xff0c;每个点阵字符位都可以用显示一个字符&#xff0c;每位之间有一个点距的间隔&#xff0c;每行之间也有间隔&#…

亿道丨三防平板丨手持平板丨加固平板丨助力地震救援

自土耳其发生7.8级大地震以来&#xff0c;一直都牵动着世人的心。2023年2月10日&#xff0c;据法新社最新消息&#xff0c;强震已造成土耳其和叙利亚两国超2万人遇难。报道称&#xff0c;相关官员和医护人员表示&#xff0c;地震造成土耳其17674人死亡&#xff0c;叙利亚则有33…

面试总结之JVM入门

文章目录 &#x1f412;个人主页&#x1f3c5;JavaEE系列专栏&#x1f4d6;前言&#xff1a;&#x1f380;你为什么要学习JVM&#xff1f;&#x1f380;JVM的作用 &#x1f380;JVM的构成&#xff08;5大类&#xff09;&#x1f3e8;1.类加载系统&#x1f415;类什么时候会被加…

游戏配置内存“瘦身”策略

背景 游戏配置数据绝对是游戏服务器进程的内存大头,有些游戏服务器单纯数据配置的容量就超过一个G。因此,这部分内存优化也就放在首要位置了。 优化策略 在《服务器进程如何降低内存》一文中,我们讲述了可以通过“优化游戏配置缓存”来降低游戏服务器进程的内存使用量。本…

linux系统---nginx基础

目录 一、Nginx的概念 二、Nginx常用功能 1、HTTP(正向)代理&#xff0c;反向代理 1.1正向代理 1.2 反向代理 2、负载均衡 2.1 轮询法&#xff08;默认方法&#xff09; 2.2 weight权重模式&#xff08;加权轮询&#xff09; 2.3 ip_hash 3、web缓存 三、基础特性 四…

品牌营销如何打破内卷?从价值出发

说起品牌营销&#xff0c;大家的想法是什么&#xff1f;有人认为最难的模块在推广&#xff0c;而说到推广&#xff0c;默认就是几个主流社媒的组合。然而在当下大家推广都陷入到同一个困境&#xff1a;那就是流量成本越来越高&#xff0c;转化率低等问题&#xff0c;媒介盒子认…

五招促进AI和ML实现自动化测试

近年来&#xff0c;人工智能(AI)和机器学习(ML)技术正在蓬勃发展&#xff0c;诸如&#xff1a;自动驾驶汽车、机器人、以及Amazon的Alexa等应用&#xff0c;都深刻地影响和改变着我们的日常生活。当然&#xff0c;随着此类智能应用和设备使得我们的生活越来越轻松&#xff0c;大…

鸿蒙开发 之 ArkTsUI基础组件

介绍 ArkTS是鸿蒙生态的应用开发语言。它在保持TypeScript&#xff08;简称TS&#xff09;基本语法风格的基础上&#xff0c;对TS的动态类型特性施加更严格的约束&#xff0c;引入静态类型。同时&#xff0c;提供了声明式UI、状态管理等相应的能力&#xff0c;让开发者可以以更…

vue2和vue3 setup beforecreate create生命周期时间比较

创建一个vue程序&#xff0c;vue3可以兼容Vue2的写法&#xff0c;很流畅完全没问题 写了一个vue3组件 <template><div></div> </template><script lang"ts"> import {onMounted} from vue export default{data(){return {}},beforeCr…

044-WEB攻防-PHP应用SQL盲注布尔回显延时判断报错处理增删改查方式

044-WEB攻防-PHP应用&SQL盲注&布尔回显&延时判断&报错处理&增删改查方式 #知识点&#xff1a; 1、PHP-MYSQL-SQL注入-方式增删改查 2、PHP-MYSQL-SQL注入-布尔&延迟&报错 3、PHP-MYSQL-SQL注入-数据回显&报错处理 演示案例&#xff1a; ➢PHP…