PWM 是一种调节输出功率的技术(俗称调压),其原理在于改变输出方波的占空比,具体输出见下图:

输出信号为电压值,当负载为恒阻时,上图中的输出功率分别为 25%、50%、75%。

实现方法如下:

  • 设置一个计数器,上图中的第一行就是个 4 位的计数器,每满 15 自动变为 0。那么可以得到输出频率等于时钟的 1/16。
  • 当计数器的值小于某个值的时候输出 0,高于或者等于某个值的时候输出 1。

假设控制的是一个小灯为 1/8 功率输出,那么我们需要的值就是 13 (4'hD),当计数器小于等于 13 输出 0,否则输出 1。

具体代码如下:

如果时钟为 50MHz,一个时钟周期为 2ns,根据推算可以得出上述的 PWM 输出信号的周期为 32 ns,频率大约 1.5MHz。由于 1.5MHz 的频率远远的超过了人眼 100Hz 的分辨极限,所以在人看来 LED 会一直发光但亮度较低。

然而并不是所有的外设都能承受 1.5MHz 这么高的频率。很多器件内包含有三极管,但三极管是存在截止频率上限问题,当输出管脚通过三极管来放大输出电流时,过高的频率会导致输出失效,所以绝大多数情况下我们需要降低 PWM 的输出频率。

使用环形计数器可以得到任意整数分频的电路,这在电子钟篇中已经试用过了。我们可以把分频模块的输出作为另一个电路的时钟输入,可是这种方法生成的时钟信号不够稳定。锁相环可以对时钟信号进行任意比例分频,倍频和移相等操作。锁相环分为数字式(DLL)和模拟式(PLL)两种,Altera 公司在 FPGA 里集成了模拟式锁相环,Xilinx 公司的器件集成的既有模拟的也有用数字式的。

与 ASICS 的自由布线相比,FPGA 内部可用的时钟就显得十分有限了。FPGA 可用的时钟牵扯到全局时钟网络的问题。由于这里不涉及画板子的问题,对于时钟网络就不多做赘述了。

锁相环的使用方法: 首先在 tools 菜单栏找到并打开 MegaWizard Plug-In Manager,按照下面的步骤配置使用 PLL IP 核

这个 IP 核输出多达 5 个 信号,由于我们只需要用到一个输出 c0,所以 c1 ~ c4 设置为默认(不开启)即可。

这样的话 PLL 核就配置好了,原理图连接方法:

本文中时钟为 50MHz,可以计算得到输出频率

50M = 50_000_000 –> 50_000_000 / 25_000 = 2000 –> 2000/16 = 125

125Hz 的一个周期为 0.008s = 0ms = 8_000 us,使用图形仿真输入来验证显然不太现实,此外我们在工程中使用了 IP 核,出于效率的考虑应当选用 Modelsim。但我在使用 Modelsim 仿真时出现了问题,Modelsim 总是报告分频系数不正确,然而当我把分频系数降为 10 ,仿真器却可以正常工作。我猜测可能是因为 Modelsim 在仿真 Cyclone IV E 系列 PLL 的时候调用的是 Cyclone III 的仿真文件,而 Cyclone IV 的 PLL 与 Cyclone III 也许并不完全一致,也有可能是仿真库文件出现了问题。

觉得效果不够明显可以在 pwm 代码中添加一个全亮的灯作为参照也可以把 duty 改为 4'hE(1/16 功率),此外还可以尝试增大锁相环中的分频系数让小灯闪动(只要锁相环配置时出现 able to implement the requested PLL 就表示配置可行)。

我的 FPGA 学习历程(14)—— PWM 脉冲宽度调制的更多相关文章

  1. 我的 FPGA 学习历程(01)—— FPGA 基础知识和 Quartus 的安装

    高级的嵌入式市场主要分为以下三类:ARM.DSP 和 FPGA. 其中 ARM 是行业内的佼佼者,目前几乎所有的安卓智能手机都使用 ARM 授权的 CPU架构:而 DSP(数字信号处理器) 早年就被大 ...

  2. 我的 FPGA 学习历程(09)—— 时序逻辑入门

    讲到这篇时,组合逻辑就告一段落了,下面是一些总结: 描述组合逻辑时,always 语句中的敏感信号列表中需要列出全部的可能影响输出的变量 描述组合逻辑时,always 语句中的赋值总是使用阻塞赋值符号 ...

  3. 我的 FPGA 学习历程(07)—— BCD 编码:移位加 3 算法

    2-10 进制码,也称为 BCD 码,它的编码方式则是通过一个 4 位二进制来表示一个 10 进制数,部分十进制对应的 BCD 码如下 十进制数 | BCD 码 13 --> 0001_0011 ...

  4. 我的 FPGA 学习历程(05)—— 使用 Modelsim 仿真工具

    在第 3 篇中讲到了如何使用图形进行仿真激励输入,图形输入法尽管简单易学,但如若要求复杂的仿真输入激励.较长的仿真时间或是要求打印输出信息乃至输出文件日志则显得不够用了. 本篇以上一篇的 3-8 译码 ...

  5. 我的 FPGA 学习历程(02)—— 实验:点亮 LED 灯

    关于 Quartus 的操作可以使用 Quartus 自带的帮助,帮助中带有全套的操作教程. 中文网络教程链接(链接至 altera中文官网,点击观看) Quartus II 软件设计系列:基础 Qu ...

  6. 我的 FPGA 学习历程(12)—— 电子钟项目准备

    初学 FPGA 的时候,我们总是存在很多疑问,比如:xilinx 和 altera 的 FPGA 那种比较好.verilog 语言被如何综合成具体硬件电路.RTL 级电路是什么意思等等.现在我们就不会 ...

  7. 我的 FPGA 学习历程(11)—— 实验:按键消抖

    按键是一个输入设备,在理论上可以归为开关一类,理想的按键波形如下: 然而由于按键的机械特性,断开和闭合动作是不可能在一瞬间完成的,实际的波形如下: 抖动期间电平处于临界值,由于晶振的频率相当的高,数字 ...

  8. 我的 FPGA 学习历程(08)—— 实验:点亮单个数码管

    数码管是一种常见的用于显示的电子器件,根据数码管大致可以分为共阴极和共阳极两种,下图所示的是一个共阳极的数码管的电路图(摘自金沙滩工作室的 51 开发板电路图),我的 AX301 开发板与这张图的情况 ...

  9. 我的 FPGA 学习历程(03)—— 使用 Quaruts 自带仿真工具

    在上一篇中详细的介绍了怎样创建原理图工程,这篇同样使用原理图工程新建一个多路选择器,目的是学习使用图形输入的仿真工具输入仿真激励. 新建工程,并绘制以下的原理图. 编译项目,会多出一个警告: Crit ...

随机推荐

  1. python flsak 框架

    1.flask  轻量级微型web框架 优点:微框架.简单.可扩展 将flask变量实例化到app变量中 如果想要flask自动加载修改后的代码,要app.run(debug=True) 2.路由和视 ...

  2. JMX/RMI Nice ENGAGE <= 6.5 Remote Command Execution

    CVE ID : CVE-2019-7727 JMX/RMI Nice ENGAGE <= 6.5 Remote Command Execution description=========== ...

  3. js数字串传参时变科学计数法

    例1:onclick=channel_info_listFt(\"'+val.gid+'\",'+val.deviceIdOwner+','+val.gname+') 当长度过长的 ...

  4. vue项目打包笔记

    我的需求是在同一个代码目录下,可以同时放入两个项目包,通过运行不同的命令,运行相应的项目页面以及打包相应的项目. 这样的话,代码管理比较方便,用于多个项目在同一时间开发,类型一样,但在功能上有所区分的 ...

  5. 论文阅读笔记(七)YOLO

    You Only Look Once: Unified, Real-Time Object Detection Joseph Redmon, CVPR, 2016 1. 之前的目标检测工作将分类器用作 ...

  6. python时间模块小结

    1.datetime 模块 为日期和时间处理同时提供了简单和复杂的方法.支持日期和时间算法的同时,实现的重点放在更有效的处理和格式化输出.该模块还支持时区处理: 简单例子: from datetime ...

  7. L2-007 家庭房产 (25 分) (并查集)

    链接:https://pintia.cn/problem-sets/994805046380707840/problems/994805068539215872 题目: 给定每个人的家庭成员和其自己名 ...

  8. Mock.js简易教程,脱离后端独立开发,实现增删改查功能(转)

    在我们的生产实际中,后端的接口往往是较晚才会出来,并且还要写接口文档,于是我们的前端的许多开发都要等到接口给我们才能进行,这样对于我们前端来说显得十分的被动,于是有没有可以制造假数据来模拟后端接口呢, ...

  9. day13 Python数据基本类型

    算数运算 / x除以y // 取整除 %返回除法的余数 !=   不等于 <> 不等于 赋值运算 c+= a等价于c=c+a c-= a等价于c=c-a 逻辑运算 and or not 基 ...

  10. Vue + Element UI项目初始化

    1.安装相关组件 1.1安装Node 检查本地是否安装node node -v 如果没有安装,从Node官网下载 1.2安装npm npm -v 如果没有安装:使用该指令安装: npm install ...