ZYNQ——脉宽调制之呼吸灯实现

文章目录

  • 原理简介
  • 实验代码
  • 软件仿真
  • 板上验证


原理简介

呼吸灯的实现过程就是把不同占空比的脉冲输出后加在LED上,LED灯就会显示不同的亮度,通过不断地调节方波的占空比,LED灯的亮度也会跟着变化,看起来就像是“呼吸”一样。
要得到不同占空比的脉冲,就要采用脉宽调制(Pulse Width Modulation, PWM)的方法,脉宽调制是比较常用的模块,实际应用中比如电机转速的控制,电灯亮暗的调节等,脉宽调制的示意图如下。
在这里插入图片描述
用一个N比特的计数器,其最大值可以表示为2的N次方,最小值0,计数器以一个给定的值为步进值进行累加,加到最大值后会溢出,然后进入下一个累加周期。当计数器的值大于某一门限时(注意,这里的门限值不是固定不变的,而是变化的),脉冲输出高,否则输出低,这样就可以完成上面图中红色线所示的脉冲占空比可调的脉冲输出。
计数器的步进值可以根据输出频率计算:step value = 输出频率 × 2 n 系统时钟频率 \frac{输出频率×2^n}{系统时钟频率} 系统时钟频率输出频率×2n


实验代码

本次实验中用到的代码有两个模块,首先第一个模块是脉宽调制模块,其代码如下。

`timescale 1ns / 1ps

module pwm 
# (parameter N = 16)   //端口使用的参数在这里定义
(
    input clk,
    input rst,
    input[N-1:0] period,  //步进值,根据想要的输出频率计算得到
    input[N-1:0] threshold,  //与count进行比较的门限值(可变的)
    output pwm_out
);

reg[N-1:0] period_reg;   //接收输入值对应的寄存器
reg[N-1:0] threshold_reg;
reg[N-1:0] count;  //以period为步进值的计数器
reg pwm_reg; 

assign pwm_out = pwm_reg;

always@(posedge clk or negedge rst)
begin
    if(rst == 0)
    begin
        period_reg <= {N{1'b0}};  //将N位二进制的0拼接
        threshold_reg <= {N{1'b0}};
    end
    else
    begin
        period_reg <= period;  //将输入值存放在各自的寄存器中
        threshold_reg <= threshold;
    end
end

always@(posedge clk or negedge rst)
begin
    if(rst == 0)
        count <= {N{1'b0}};
    else
        count <= count + period_reg;  //计数器累加
end

always@(posedge clk or negedge rst)
begin
    if(rst == 0)
        pwm_reg <= 1'b0;
    else
    begin
        if(count >= threshold_reg)  //将count值与输入的门限值比较,大于门限则将脉冲输出置为1,小于则置为0
            pwm_reg <= 1'b1;    
        else
            pwm_reg <= 1'b0;
    end
end

第二个模块是用来设置输入参数的,其代码如下。

`timescale 1ns / 1ps

module led_breathing(
    input clk,
    input rst,
    output led
);

localparam STEP = 32'd100000;   //threshold对应的步进值
localparam MIN_VALUE = 32'h6fffffff; //threshold最小值,减到比此值更小时就进行加操作 
localparam MAX_VALUE = 32'hffffffff; //threshold最大值,加到比此值更大时就进行减操作 

localparam IDLE = 0;      //空闲
localparam PWM_PLUS = 1;  //加操作
localparam PWM_MINUS = 2;  //减操作 
localparam PWM_GAP = 3;    //间隔,判断下次是加操作是减操作

wire pwm_out;  //脉冲输出
reg pwm_flag;  //加减操作的标志位,加操作设置为0,减操作设置为1
reg [1:0] state;  //四个状态
reg [31:0] period; //count的步进值
reg [31:0] threshold; 
reg [31:0] timer;    //PWM_GAP状态下使用

assign led = ~pwm_out;  //pwm_out输出高电平时,led亮,led是低电平有效的

always@(posedge clk or negedge rst)
begin
    if(rst == 1'b0)
    begin
        pwm_flag <= 1'b0;
        period <= 32'd0;
        threshold <= 32'd0;
        timer <= 32'd0;
        state <= IDLE;
    end
    else
        case(state)
            IDLE:
            begin
                period <= 32'd17179;  //period = 200*2^32/50000000,pwm=200Hz
                state <= PWM_PLUS;    //状态设置为加
                threshold <= MIN_VALUE;  //threshold的初始值设置为最小值
            end
            PWM_PLUS:
            begin
                if(threshold > MAX_VALUE - STEP)  //判断threshold的值是否超过了最大值,超过了就将加减操作状态标志设为减操作状态
                begin
                   pwm_flag <= 1'b1; 
                   threshold <= threshold - STEP; 
                end
                else
                begin
                    pwm_flag <= 1'b0; 
                    threshold <= threshold + STEP;
                end
                state <= PWM_GAP;  //完成一次加操作后进入PWM_GAP状态
            end
            PWM_MINUS:
            begin
                if(threshold < MAX_VALUE + STEP) //判断threshold的值是否低于了最小值,小于了就将加减操作状态标志设为加操作状态
                begin
                   pwm_flag <= 1'b0; 
                   threshold <= threshold + STEP; 
                end
                else
                begin
                    pwm_flag <= 1'b1; 
                    threshold <= threshold - STEP;
                end
                state <= PWM_GAP;  //完成一次减操作后进入PWM_GAP状态
            end
            PWM_GAP:
            begin
                if(timer >= 5000)  //100us的计数次数,做仿真时,这里设置的小一点
                begin
                    if(pwm_flag)  //根据加减操作标志决定下一次执行的操作
                        state <= PWM_MINUS;
                    else
                        state <= PWM_PLUS;
                    timer <= 32'd0;
                end
                else
                    timer <= timer + 32'd1;  //计数到达规定的时长后再执行下次加或减操作
            end
            default: state <= IDLE;
        endcase
end

pwm      //将第一个模块在这里进行例化
# (.N(32))
pwm_inst(
    .clk(clk),
    .rst(rst),
    .period(period),
    .threshold(threshold),
    .pwm_out(pwm_out)
);
endmodule

软件仿真

本实验用到的仿真测试代码如下。

`timescale 1ns / 1ps

module led_breathing_sim();
reg clk;
reg rst;
wire led;

initial
begin 
    clk = 0;
    rst = 0;
    #100
    rst = 1;
end

always #10 clk = ~clk;

led_breathing uut_led_breathing(
    .clk(clk),
    .rst(rst),
    .led(led)
);
endmodule

仿真的结果如下图所示。
在这里插入图片描述
上图中,pwm_out就是脉宽调制之后的输出波形,而led就是pwm_out信号的翻转,可以看到,波形的占空比各不相同。
代码中设置的计数器的步进值period是200Hz对应的值,200Hz对应的周期就是5ms,将上面的仿真图放大可以看到,尽管每个方波的占空比不同,但是其周期都是5ms。
在这里插入图片描述
当时看代码的时候挺头晕的,搞不太懂为啥输出的方波波形的占空比各不相同。我将代码中的几个十六进制数转化为十进制数看,首先,threshold对应的最小值是1879048191(十六进制的6fffffff),最大值是4294967295(十六进制的ffffffff),而其步进值是100000,也就是说,从1879048191到4294967295,每次加100000,需要24159次;count对应的最小值是0,最大值就是自动溢出后,也就是4294967295,count的步进值是period=17179,从0到溢出需要250013次。两者差不多是十倍的关系,而且有一点不太一样的是threshold加到最大值后不是直接掉到最小值,而是一步步减下来,而count则是加满溢出,相当于从0开始新一轮的计数。
根据上面的分析,我简单的画了一个示意图,如下图所示。
在这里插入图片描述
按理说,count从0到溢出应该对应大概10个这样的波形,但是为了绘图清楚,这里绘制了简单的示意图,阐明其中的原理即可。而且这里我用直线替代了阶梯上升和阶梯下降,因为这些小的阶梯在宏观上来看可以抽象成一个点。上图中,蓝色线(count)高于黑色线(threshold)的部分,输出的脉冲为高;蓝色线低于黑色线的部分,输出脉冲为低。通过画一幅这样的示意图就能清楚地反映代码中是怎么生成占空比不同的波形了。


板上验证

本实验中的引脚分配如下图所示。
在这里插入图片描述
通过上面的仿真,只看输出信号led的波形,其波形的占空比在不断地变化,表现在开发板的LED亮灭特性上就像“呼吸”一般,呼吸灯实现的动图如下图所示。
请添加图片描述


以上就是ZYNQ——脉宽调制之呼吸灯实现的全部内容了!
参考资料:
ZYNQ 开发平台 FPGA 教程 AX7020

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

爬虫小白入门在服务器上-部署爬虫或者开服务接口并供给他人访问

目录 一、准备工作-服务器1、先准备一个服务器&#xff08;以阿里云为例子&#xff09;2、开通服务端口号访问权限 二、准备工作-Xshell登录服务器1、xshell基本登录操作2、xftp基本操作 三、部署代码到服务器上1、部署一个python爬虫脚本在服务器上定时运行等2、部署一个pytho…

【面试常见】JS继承与原型、原型链

前后端面试题库 &#xff08;面试必备&#xff09; 推荐&#xff1a;★★★★★ 地址&#xff1a;前端面试题库 web前端面试题库 VS java后端面试题库大全 在 JavaScript 中&#xff0c;继承是实现代码复用和构建对象关系的重要概念。本文将讨论原型链继承、构造函数继承以及…

SONY索尼MP4视频变RSV文件修复方法

索尼MP4变RSV的原因分析 索尼新型号相机或者摄像机&#xff0c;如SONY A7S3&#xff0c;A7M4&#xff0c;FX3, FX6, FX9等&#xff0c;如果录像过程中有发生如下异常情况&#xff0c;如断电&#xff0c;死机&#xff0c;电量不足&#xff0c;机器摔倒&#xff0c;非常规操作&a…

【接口测试】Postman —— 接口测试知识准备

1.0 前言 ​应用程序编程接口&#xff08;Application Programming Interface, API&#xff09;是这些年来最流行的技术之一&#xff0c;强大的Web应用程序和领先的移动应用程序都离不开后端强大的API。API技术的应用给系统开发带来了便利&#xff0c;但也对测试人员提出了更高…

CentOS7下载并安装mysql-8.0.33

CentOS7下载并安装mysql-8.0.33 一、官网下载mysql-8.0.33 MySQL下载路径 MySQL :: Download MySQL Community Server 自己百度mysql官网下载的话直接按照完整路径指示下载即可&#xff0c;如果点击上面的连接下载mysql的话&#xff0c;直接按照4、5、6步骤选择适合自己linu…

旅游卡景区购票小程序开发定制

旅游业的蓬勃发展&#xff0c;越来越多的景区开始推出自己的旅游卡&#xff0c;以吸引更多的游客前来观光。同时&#xff0c;为了更加便捷地服务游客&#xff0c;许多景区也开始启用小程序来进行门票售卖和游客管理。针对这种情况&#xff0c;专业的小程序开发公司推出了定制旅…

自定义注解,基于redis实现分布式锁

一、如何实现自定义注解 1.1、注解的基础知识 实现自定义注解其实很简单&#xff0c;格式基本都差不多。也就参数可能变一变。 Retention&#xff1a;取值决定了注解在什么时候生效&#xff0c;一般都是取运行时&#xff0c;也就是RetentionPolicy.RUNTIME。 Target&#xff…

初识Go语言25-数据结构与算法【堆、Trie树、用go中的list与map实现LRU算法、用go语言中的map和堆实现超时缓存】

文章目录 堆Trie树练习-用go中的list与map实现LRU算法练习-用go语言中的map和堆实现超时缓存 堆 堆是一棵二叉树。大根堆即任意节点的值都大于等于其子节点。反之为小根堆。   用数组来表示堆&#xff0c;下标为 i 的结点的父结点下标为(i-1)/2&#xff0c;其左右子结点分别为…

性能优化 :删除项目中没有引用关系的文件 useless-files-webpack-plugin

一般此类包不需要安装到项目中&#xff0c;减少node_modules体积&#xff08;以项目实际情况决定-S/-D&#xff09; npm i useless-files-webpack-plugin -S然后再vue.config.js中配置 const UselessFile require(useless-files-webpack-plugin) chainWebpack: config > …

【NLP模型】文本建模(2)TF-IDF关键词提取原理

一、说明 tf-idf是个可以提取文章关键词的模型;他是基于词频,以及词的权重综合因素考虑的词价值刻度模型。一般地开发NLP将包含三个层次单元:最大数据单元是语料库、语料库中有若干文章、文章中有若干词语。这样从词频上说,就有词在文章的频率,词在预料库的频率,文章在预…

SpringBoot3.0整合RocketMQ时出现未能加载bean文件

SpringBoot3.0整合RocketMQ时出现未能加载bean文件 问题 APPLICATION FAILED TO START Description: Field rocketMQTemplate in com.spt.message.service.MqProducerService required a bean of type ‘org.apache.rocketmq.spring.core.RocketMQTemplate’ that could not …

window debug ios webview

业务需求 在window上想要debug在ios的应用中的webview页面&#xff0c;毕竟页面是在安卓端和ios端都有webview的。安卓的页面使用edge的edge://inspect/#devices&#xff0c;手机开启调试模式就可以了。对于ios就没有办法&#xff0c;页面中已经使用了vconsole可以看到部分的信…

火山引擎 Iceberg 数据湖的应用与实践

在云原生计算时代&#xff0c;云存储使得海量数据能以低成本进行存储&#xff0c;但是这也给如何访问、管理和使用这些云上的数据提出了挑战。而 Iceberg 作为一种云原生的表格式&#xff0c;可以很好地应对这些挑战。本文将介绍火山引擎在云原生计算产品上使用 Iceberg 的实践…

XXX汽车ERP系统供应商索赔业务上线,助力业财数据快速闭环(投稿数据化月报四)

供应商三包索赔款项源起QMS质量系统&#xff0c;联动金税系统完成发票开具&#xff0c;最终在SAP系统中创建完成财务凭证。该流程上线前为手工操作&#xff0c;费时费力且效率低下容易出错。针对该业务现状&#xff0c;SAP与QMS业务顾问及开发团队组成开发小组&#xff0c;导入…

使用matplotlib制作动态图

使用matplotlib制作动态图 一、简介二、模块简介1. **FuncAnimation**类介绍2. 定义动画更新函数 三、使用matplotlib制作动画1.一步法制作动态图片2. 两步法制作动态图片 一、简介 matplotlib(https://matplotlib.org/)是一个著名的python绘图库&#xff0c;由于其灵活强大的…

计算机视觉 + Self-Supervised Learning 五种算法原理解析

计算机视觉领域下自监督学习方法原理 导语为什么在计算机视觉领域中进行自我监督学习&#xff1f; 自监督学习方法Generative methodsBEiT 架构 Predictive methodsContrastive methodsBootstraping methodsSimply Extra Regularization methods 导语 自监督学习是一种机器学习…

SQL Server SQL语句

在很多情况下&#xff0c;可以用CREATE TABLE语句创建数据表、使用ALTER TABLE语句修改表结构、使用DROP TABLE语句删除表&#xff1b; 可以使用CREATE DATABASE创建数据库、ALTER DATABASE修改文件或文件组、DROP DATABASE语句删除数据库&#xff1b; 1、数据定义语句&#x…

【MySQL】MySQL基本语句大全

个人主页&#xff1a;【&#x1f60a;个人主页】 系列专栏&#xff1a;【❤️MySQL】 文章目录 前言结构化查询语句分类MySQL语句大全&#x1f4da;DDL&#xff08;对数据库和表的操作&#xff09;&#x1f916;DQL&#xff08;查询语句&#xff09;&#x1f4bb;关键字&#x…

AI最新开源:LMSYS Org开源LongChat、法律大语言模型ChatLaw、中文医疗对话模型扁鹊

一周SOTA&#xff1a;LMSYS Org开源LongChat、法律大语言模型ChatLaw、中文医疗对话模型扁鹊 文章目录 1. LMSYS Org发布LongChat&#xff0c;上下文碾压64K开源模型2. 北大团队发布法律大模型 ChatLaw3. 扁鹊&#xff1a;指令与多轮问询对话联合微调的医疗对话大模型 1. LMSY…

目标检测的评估指标

Precision(精确率/查准率)&#xff1a;是指在所有被预测为正的样本中&#xff0c;确实是正样本的占比。当Precision越大时&#xff0c;FP越小&#xff0c;此时将其他类别预测为本类别的个数也就越少&#xff0c;可以理解为预测出的正例纯度越高。Precision越高&#xff0c;误检…