问答 店铺
热搜: ZYNQ FPGA discuz

QQ登录

只需一步,快速开始

微信登录

微信扫码,快速开始

微信扫一扫 分享朋友圈

已有 118 人浏览分享

开启左侧

[MILIANPAI-F01-EG4D]FPGA程序设计基础实验连载-06 PWM呼吸灯实验

[复制链接]
118 0
安路-FPGA课程
安路课程: 基础入门 » 新手入门实验
安路系列: EG4
本帖最后由 UT发布 于 2025-4-8 13:55 编辑

软件版本:TD_5.6.4_Release_97693
操作系统:WIN11 64bit
硬件平台:适用安路(Anlogic)FPGA
登录米联客”FPGA社区-www.uisrc.com视频课程、答疑解惑!
1概述

小小呼吸灯在很多设备上我们可以看到,我们可以在FPGA的控制主板上也可以加入呼吸灯,指示我们的FPGA主板正在运行。一般呼吸灯的亮灭周期是2S,呼吸灯的亮度可以通过PWM来调节。本文实现一个实用的小程序,读者完全可以自己编写代码,并且通过仿真测试代码的正确性,然后下载到开发板看实际运行效果。

在完成本实验前,请确保已经完成前面的实验,包括已经掌握以下能力:

1:完成了TD软件安装

2:完成了modelsim安装以及TD库的编译

3:掌握了TD仿真环境的设置

4:掌握了modelsim通过do文件启动仿真

1.1呼吸灯简介

呼吸灯,就是指灯光设备的亮度随着时间由暗到亮逐渐增强,再由亮到暗逐渐衰减。呼吸灯最早是被苹果公司开发出来的,一经面世,立刻吸引众多科技公司效仿并广泛应用于各类电子产品上。本章课程将通过PWM的方式实现呼吸灯效果

脉冲宽度调制(PWM),是英文“Pulse Width Modulation”的缩写,简称脉宽调制,是利用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术,广泛应用在从测量、通信到功率控制与变换的许多领域。

PWM的频率f是指1秒钟内信号从高电平到低电平再回到高电平的次数(一个周期),单位为Hz

PWM的周期是指频率的倒数,T = 1/f,如果频率为50Hz,即一个周期是20ms,那么1s中有1s/20ms=50PWM周期;

占空比是指高电平在一个周期之内所占的时间比率。若信号的周期为T,每周期高电平时间为t1,低电平时间为t2,T=t1+t2,则占空比D=t1/T

image.jpg

呼吸灯采用 PWM 的方式,在固定的频率下,通过调整占空比的方式来控制 LED 灯亮度的变化。一般人眼睛对于80Hz以上刷新频率则完全没有闪烁感。频率太小的话,LED灯看起来就会闪烁,当频率大于50Hz的时候,人眼就会产生视觉暂留效果,基本就看不到闪烁了,就是一个常亮的LED灯。如果高电平点亮LED灯,低电平熄灭LED灯,占空比为100%LED 灯最亮,占空比为0%LED 灯最暗。所以,在频率一定下,可以用不同占空比改变LED灯的亮度。

1.2硬件电路分析

参照流水灯硬件电路分析部分

2PWM呼吸灯程序设计
2.1系统框图

本次实验目的为1LED实现呼吸灯的效果,LED变换间隔时间需要基于系统时钟来计数,实现间隔时间的计时,除此之外,添加系统复位使程序恢复至默认状态,输出结果由1LED灯显示。命名模块名为pwm_light,此模块需要两个输入的端口,分别为系统时钟和系统复位,输出为1位的 LED 端口。

呼吸灯是由两个部分组成,一个是由亮到暗的过程,一个是由暗到亮的过程,再由简介可知我们是在固定的频率下通过调整高电平的占空比来调控 LED 灯的亮度。第一个过程由亮到暗的过程为t=2s,如果高电平点亮LED灯,低电平熄灭LED灯,不同的占空比显示不同的亮度,占空比就要在2s之间逐渐由100%减小至0%,如果我们把2s划分成100份,那么每一个占空比就要保持t1=2s/100=20ms。由于占空比100%减小到0%一共变化了100次,占空比=高电平周期/整个周期t1,所以需要将一个占空比周期t1划分成100份,从而达到高电平周期每减小一个周期t2,占空比就减少1%t2=20ms/100=200us

image.jpg

PWM呼吸灯程序设计中包含了3个定时计数器:

200us定时器,作为本系统的基本定时器,产生时间基准。

20ms定时器,通过200us定时器,计数100次完成20ms定时计数

2s定时器,通过20ms定时器,计数100次完成2S定时计数

PWM每间隔2ms更新一次,共计更新100次即2S后切换PWM的占空比调整方向。因此PWM占空比的调整是和2ms定时计数器和2S定时计数器相关。系统框图如下:

image.jpg
2.2程序源码
  1. module pwm_light#
  2. (
  3. parameter REF_CLK      = 32'd25000000
  4. )
  5. (
  6. input                 I_sysclk,
  7. input       I_rstn,
  8. output      O_pwm
  9. );
  10. localparam T20US_SET     = REF_CLK/5000 - 1;  //set 200us,可根据实际晶振频率进行修改
  11. localparam T20MS_SET     = 100 - 1;           //set 20ms
  12. localparam PWM_SET       = 100 - 1;           //Set PWM duty cycle adjustment times
  13. reg [23:0] t20us_cnt;
  14. reg [9 :0] t20ms_cnt;
  15. reg [9 :0] pwm_cnt;
  16. reg PWM_S;
  17. //记录计数状态
  18. wire t20us_done;
  19. wire t20ms_done;
  20. //是否计满200us
  21. assign t20us_done = (t20us_cnt == T20US_SET);
  22. //是否计满20ms
  23. assign t20ms_done = t20us_done & (t20ms_cnt == T20MS_SET) ;
  24. //1us base timer
  25. always @(posedge I_sysclk or negedge I_rstn)begin               //系统时钟的上升沿以及复位的下降沿触发
  26.     if(I_rstn == 1'b0)                                          //复位清零
  27.         t20us_cnt <= 0;                                             
  28.     else if(t20us_cnt < T20US_SET)                              //t20us_cnt目标值T20US_SET
  29.         t20us_cnt <= t20us_cnt + 1'b1;                          //本轮计数未完成则+1
  30.     else
  31.         t20us_cnt <= 24'd0;                                     //若达目标值则清零,进行新一轮计数
  32. end
  33. //1ms pwm compare timer,based on 1us base timer
  34. always @(posedge I_sysclk or negedge I_rstn)begin
  35.     if(I_rstn == 1'b0)
  36.          t20ms_cnt <= 0;   
  37.     else if(t20us_done)                                                  //前一级(200us)的一轮计数完成则+1
  38.          t20ms_cnt <= (t20ms_cnt < T20MS_SET) ? (t20ms_cnt + 1'b1) : 10'd0;   
  39.     else                                                                 //否则保持
  40.          t20ms_cnt <= t20ms_cnt;
  41. end
  42. //PWM counter for generating duty cycle parameters as well as PWM adjustment count
  43. always @(posedge I_sysclk or negedge I_rstn)begin
  44.     if(I_rstn == 1'b0)                                             
  45.         pwm_cnt <= 0;
  46.     else if(t20ms_done)                                                
  47.         pwm_cnt <= (pwm_cnt < PWM_SET) ? (pwm_cnt + 1'b1) : 10'd0;      //前一级(20ms)的一轮计数完成则+1
  48.     else                                                                        
  49.         pwm_cnt <= pwm_cnt;                                              //否则保持         
  50. end
  51. //switch breathing state
  52. always @(posedge I_sysclk or negedge I_rstn)begin
  53.     if(I_rstn == 1'b0)
  54.         PWM_S <= 0;
  55.     else if(t20ms_done && (pwm_cnt == PWM_SET))                             //pwm_cnt == PWM_SET时(即计满2s),PWM_S状态进行翻转
  56.         PWM_S <= ~PWM_S;                                                     
  57.     else
  58.         PWM_S <= PWM_S;
  59. end
  60. //PWM wave generating
  61. assign  O_pwm = PWM_S ? (pwm_cnt >= t20ms_cnt) : (pwm_cnt < t20ms_cnt);         
  62. //在一轮计数中,t20ms_cnt逐渐增大
  63. //若PWM_S==1,O_pwm输出为1的频率越来越小,表现为LED灯逐渐变暗
  64. //若PWM_S==0,O_pwm输出为1的频率越来越大,表现为LED灯逐渐变亮
  65. endmodule  
复制代码
3FPGA工程

fpga工程的创建过程不再重复,如有不清楚的请看前面实验


image.jpg

米联客的代码管理规范,在对应的FPGA工程路径下创建uisrc路径,并且创建以下文件夹

01_rtl:放用户编写的rtl代码

02_sim:仿真文件或者工程

03_ip:放使用到的ip文件

04_pin:fpgapin脚约束文件或者时序约束文件

05_boot:放编译好的bit或者bin文件(一般为空)

06_doc:放本一些相关文档(一般为空)

image.jpg
4 Modelsim仿真4.1准备工作

Modelsim仿真的创建过程不再重复,如有不清楚的请看前面实验


仿真测试文件源码如下,对于led这种低速仿真,仿真精度可以设置为1ns,另外仿真阶段可以把间隔时间设置小一些,这样仿真速度就快了:

  1. module tb_pwm_light();
  2. reg I_sysclk,I_rstn;
  3. wire  O_pwm;
  4. pwm_light#
  5. (
  6. .REF_CLK(25000)//可缩小间隔时间,提高仿真速度
  7. )
  8. pwm_light_inst
  9. (
  10. .I_sysclk(I_sysclk),
  11. .I_rstn(I_rstn),
  12. .O_pwm(O_pwm)
  13. );
  14. initial begin
  15.    I_sysclk  <= 1'b0;
  16.    I_rstn    <= 1'b0;
  17.    #100;
  18.    I_rstn    <= 1'b1;   
  19. end
  20. always #20 I_sysclk=~I_sysclk;
  21. endmodule
复制代码
4.2启动modelsim仿真

启动后,右击需要观察的信号,添加到波形窗口

image.jpg

点击restart

image.jpg

设置运行10ms。从仿真结果可以看到PWM占空比的调整

image.jpg

5下载演示

下载程序前,先确保FPGA工程已经编译。

5.1硬件连接

(该教程为通用型教程,教程中仅展示一款示例开发板的连接方式,具体连接方式以所购买的开发板型号以及结合配套代码管脚约束为准。)

请确保下载器和开发板已经正确连接,并且开发板已经上电(注意JTAG端子不支持热插拔,而USB接口支持,所以在不通电的情况下接通好JTAG后,再插入USB到电脑,之后再上电,以免造成JTAG IO损坏)

image.jpg
5.2运行结果

(该教程为通用型教程,教程中仅展示一款示例开发板的上板现象,具体现象以所购买的开发板型号以及配套代码上板现象为准。)

image.jpg



































您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

0

关注

0

粉丝

293

主题
精彩推荐
热门资讯
网友晒图
图文推荐

  • 微信公众平台

  • 扫描访问手机版