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

这篇具有很好参考价值的文章主要介绍了ZYNQ——脉宽调制之呼吸灯实现。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。


原理简介

呼吸灯的实现过程就是把不同占空比的脉冲输出后加在LED上,LED灯就会显示不同的亮度,通过不断地调节方波的占空比,LED灯的亮度也会跟着变化,看起来就像是“呼吸”一样。
要得到不同占空比的脉冲,就要采用脉宽调制(Pulse Width Modulation, PWM)的方法,脉宽调制是比较常用的模块,实际应用中比如电机转速的控制,电灯亮暗的调节等,脉宽调制的示意图如下。
ZYNQ——脉宽调制之呼吸灯实现,zynq,zynq,Vivado
用一个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

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


板上验证

本实验中的引脚分配如下图所示。
ZYNQ——脉宽调制之呼吸灯实现,zynq,zynq,Vivado
通过上面的仿真,只看输出信号led的波形,其波形的占空比在不断地变化,表现在开发板的LED亮灭特性上就像“呼吸”一般,呼吸灯实现的动图如下图所示。
ZYNQ——脉宽调制之呼吸灯实现,zynq,zynq,Vivado


以上就是ZYNQ——脉宽调制之呼吸灯实现的全部内容了!
参考资料:
ZYNQ 开发平台 FPGA 教程 AX7020文章来源地址https://www.toymoban.com/news/detail-524081.html

到了这里,关于ZYNQ——脉宽调制之呼吸灯实现的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • zynq7000学习(1)——vivado环境下PL配置

    一、新建工程:       现开发板型号为xc7z100ffg900-2  选择芯片 (选择芯片7100的话,就输入xc7z100  后面的-1和-2是速度等级), 更改项目名为system 。 Create Block Design (创建模块化的设计)——设置设计名称为system。     这时会出现design窗口和source窗口、画布窗口,source中出

    2024年02月13日
    浏览(58)
  • ZYNQ-XC7Z020 JTAG 连接不上 Vivado

    平台: 【ALINX黑金开发板,板载JTAG】 【Vivado 2017.4】 最近项目需要使用到FPGA,没接触过被迫学习,第一关就遇到了困难。 具体情况: Vivado   Auto Connect 连接不上板子。 解决: 运行安装目录下 install_digilent.exe 程序。 G:XilinxVivado2017.4dataxicomcable_driversnt64digilentinstall_di

    2024年02月21日
    浏览(45)
  • ZYNQ-Linux开发之(三)Vivado SDK使用,裸机开发调试,不带linux

    生成bit文件时候的开发和调试需要使用SDK,导出工程到SDK: 包含bit文件,点击OK:  工程目录下会新增一个.sdk的目录: 启动SDK: 使用SDK进行调试,SDK中,新建应用工程,选择File-New-Application Project: 在弹出的窗口中,输入Project name,单击Next: 在弹出的窗口中,默认选择He

    2024年02月10日
    浏览(60)
  • Zynq UltraScale+ XCZU5EV 纯VHDL解码 IMX214 MIPI 视频,2路视频拼接输出,提供vivado工程源码和技术支持

    Zynq UltraScale+ XCZU5EV 纯VHDL解码 IMX214 MIPI 视频,2路视频拼接输出,提供vivado工程源码和技术支持 FPGA图像采集领域目前协议最复杂、技术难度最高的应该就是MIPI协议了,MIPI解码难度之高,令无数英雄竞折腰,以至于Xilinx官方不得不推出专用的IP核供开发者使用,不然太高端的操

    2024年02月07日
    浏览(81)
  • ZYNQ——PL端流水灯的实现

    本文介绍的是在ZYNQ 7020黑金开发板上实现PL端流水灯的例子,开发板上PL端的LED灯总共有4个,在原理图中找到 PL LED 如下图所示,通过看图可知,给 LED 置低电平时灯才亮。 这里预想的实验结果是:在1秒钟内,4个LED各亮0.25秒,看起来就像流水灯一样。 LED:4个,赋值为0时即点

    2024年02月09日
    浏览(50)
  • Zynq7020 使用 Video Processing Subsystem 实现图像缩放

    没玩过图像缩放都不好意思说自己玩儿过FPGA,这是CSDN某大佬说过的一句话,鄙人深信不疑。。。 目前市面上主流的FPGA图像缩放方案如下:1:Xilinx的HLS方案,该方案简单,易于实现,但只能用于Xilinx自家的FPGA;2:非纯Verilog方案,大部分代码使用Verilog实现,但中间的fifo或

    2024年01月16日
    浏览(41)
  • 12.[STM32]PWM脉宽调制-舵机控制(一篇足以)

    🍌 🍌🍌 作者简介:大家好啊,我叫DW,每天分享一些我新学到的知识,期待和大家一起进步 🍋 🍋🍋 系列专栏: STM32 🍎 🍎🍎 🍎🍎🍎 🌞小实验目标:控制舵机旋转🌞 🍊如有写得不好的地方欢迎大家指正🍊 创作时间:🍊🍊🍊2022年5月2日🍊🍊🍊 在机器人机电控

    2023年04月15日
    浏览(40)
  • zynq+LWIP 裸机双网口实现(MIO+EMIO)+程序下载

    一、 简介 : 为实现 Zynq 裸机双网口通信功能,其中 ENET0 连接 PS 端网口,ENET1 通过 EMIO 扩展连接 PL 端网口 二、环境介绍 芯片型号: ZYNQ: XC7Z010clg400 开发软件:Vivado2022 + Xilinx Vitis 2022 网卡芯片:RTL8211FDI LWIP库 :lwip官方下载地址:http://savannah.nongnu.org/projects/lwip/(需要根据网

    2024年02月09日
    浏览(105)
  • 基于ZYNQ FPGA的8路ADC数据采集与存储实现

    基于ZYNQ FPGA的8路ADC数据采集与存储实现 概述: 在工程设计和科学研究中,数据采集与存储是一个重要的任务。为了满足高速、高精度和大容量的数据采集需求,本文将介绍如何基于ZYNQ FPGA平台实现8路ADC数据采集与存储。通过合理的硬件设计和软件开发,我们可以实现快速而

    2024年02月11日
    浏览(49)
  • ZYNQ ARM+FPGA双目立体视觉控制器设计与实现(一)

    通过 ZYNQ 板卡实现 FPGA+ARM 架构的双目立体视觉系统 本设计采用实验室自主开发的 Zynq-7020 板卡,提出了基于 FPGA+ARM 架构的双 目立体视觉的软硬件系统设计方案。根据对系统软硬件功能划分, PL(FPGA) 端主要实现 了双目摄像头图像的采集存储和 HDMI 显示, PS(ARM) 端主要实现了

    2024年02月10日
    浏览(53)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包