资讯详情

FPGA项目三:PWM呼吸灯

文章目录

    • 第一节 项目背景
    • 第二节 设计目标
    • 第三节 设计实现
      • 3.1顶层设计
      • 3.2 信号设计
      • 3.3 信号定义
    • 第四节 综合和上板
      • 4.1 新建工程
      • 4.2 综合
      • 4.3 配置管脚
      • 4.4 再次综合
      • 4.5 连接开发板
      • 4.6 上板

第一节 项目背景

随着照明领域需求的不断扩大,LED 随着技术的快速发展,其控制方法越来越多样化,可以产生各种视觉效果。与只有开和关功能的传统相比 LED 照明,可以实现从 0 到 100%灯光亮度调节 LED 灯具在家装照明、舞美照明等领域的需求更加突出。这种灯的亮度可以通过调节控制由高到低逐渐变化,就像人在呼吸一样,所以叫呼吸灯。呼吸分为两个过程,一个是呼吸,个是吸。所谓呼吸灯,就是通过光线的强度来表现人的呼吸频率,广泛应用于手机,成为各大品牌手机的卖点之一。当手机上有未处理的通知时,如未接到电话或未接收的短信,呼吸灯会像呼吸一样有节奏地从黑暗变为明亮,从而起到通知提醒的作用。 呼吸灯的设计方法有很多,比如采用 555 定时器的设计方案,电路采用电容充放电的原理比较简单,。本案采用 PWM 驱动 LED 设计灯具的方法。

微处理器/FPGA 控制模拟电路的数字输出是一种有效的技术,它广泛应用于测量、通信、功率控制和变换等领域。PWM 从处理器到被控系统的数字信号采用数字形式,无需数模转换。航模中的控制信号大多是 PWM 信号,比如 FUTABA、JR 使用等舵机的控制 PWM 发射机向接收机输送脉冲后,接收机会控制舵机旋转。例如,假设基础脉宽是 100ms,当发射机的脉宽增加(如增加到 150ms)接收机控制舵机正向旋转;相反,发射机的脉宽减小(如减小到 50ms)接收机控制舵机逆向旋转。 PWM 这是一种数字编码模拟信号电平的方法。用高分辨率计数器调制方波的占空比,从而编码特定模拟信号的电平。由于在给定的任何时刻,满幅值的直流供电只存在有(ON)和无(OFF)因此,两种状态 PWM 信号仍然是数字信号。电压或电流源是一种通过(ON)或断(OFF)将重复脉冲序列添加到模拟负载中。当直流供电被添加到负载上时,它是通过,当负载供电被切断时,它是断开。任何模拟值都可以使用,只要有足够的带宽 PWM 进行编码。

通俗来说,PWM 它是一个具有一定比例的连续脉冲信号,可以通过控制比例来改变。简单地说,可以认为 PWM 是方波,如图所示 3.3-1 所示。 在这里插入图片描述


以单片机为例,我们知道单片机IO口输出是数字信号,IO只能输出高电平和低电平

假设高电平为5V 低电平则为0V 所以我们需要输出不同的模拟电压PWM,通过改变IO使用数字信号模拟的模拟电压信号获得口输出方波的比例

众所周知,电压被夹在模拟负载中,以连接1或断开0的重复脉冲序列(例如LED灯、直流电机等。),连接是直流电源输出,断开是直流电源断开。通过控制连接和断开时间,理论上可以输出任何不大于最大电压值(即0~5V模拟电压之间的任何大小)

比方说 占空比为50% 也就是高电平时间的一半,低电平时间的一半,在一定频率下,可以模拟2.5V输出电压 那75%的占空比 电压为3.75V

pwm调整的作用来自于对占周期的宽度控制。当占周期变宽时,输出能量增加,电阻变换电路获得的平均电压值增加,占周期变窄,输出电压信号的平均电压值降低,电阻变换电路获得的平均电压值降低 也就是说,在一定的频率下,通过不同的空比 可以获得不同的输出模拟电压 pwm通过这一原理实现这一原理D/A转换的。

总结: PWM在适当的信号频率下,输出的有效电压是通过在一个周期内改变空比来改变的 PWM频率越大,理解速度越快。 PWM 之后。


让我们学习一下 PWM 实现呼吸灯的原理: 可以控制信号的高低电平变化 LED 灯的明灭状态。当输出信号低电时, LED 相反,当输出信号为高电时 LED 灯灭。当输出电平持续较低时,灯保持亮;当输出电平持续较高时,灯保持熄灭。若输出信号 50%是低电平,50%是高电平 PWM 在合适的周期下LED 灯光会变暗,这也说明占空比对 LED 影响灯光的明暗。 另一个影响 LED 亮度的因素是 PWM 波形周期。想象一下,如果 PWM 的周期是 2 秒,占空比为 此时观察到50% LED 的状态是暗 1 秒、亮 1 秒,而不是半亮。只有缩短 PWM 只能看到 LED 半亮状态。根据经验,如果要达到改变亮度的效果PWM 的周期以 10 毫秒为宜。 综上所述,通过控制高低电平的时间,即占空比(高电平占周期的百分比)和控制 PWM 的周期,就可以改变灯的明暗程度。


所以要实现的话PWM如何输出信号输出?

1)可通过芯片内部模块直接输出PWM这是信号的前提I/O口腔应该有一个集成模块,只需要几个简单的步骤来操作,这是自己的PWM程序设计中输出的功能模块更简单,数据更准确。如下图所示,一般IC口是否会标明这一点PWM口; 2)但是如果IC内部没有PWM如果功能模块要求不高,可以使用I/O设置一些参数来输出口PWM信号,因为PWM 信号实际上是一系列高低电平的组合。,用定时器中断计数,但一般不采用这种方法,除非精度、频率等要求不是很高。


第二节 设计目标

了解 PWM 本设计的功能目标后来明确了呼吸灯的运行原理。 确定功能目标是本书和简单设计方法的特点。只有对设计的功能目标有一定的理解和期望,才能更好地讨论如何逐步设计和实现代码。后续设计的每一步都围绕着设计目标的实现展开。如果你对设计目标知之甚少,在后续的设计理念中可能很难形成系统的思维模式,只能碎片化地接收知识。设计目标就像建筑的设计图纸。如果你甚至不能确定你最终想要实现的目标,那么后续的讨论就没有意义了。因此,在学习完整设计案例的过程中,冷静下来,从明确的设计目标开始,一步一步地咀嚼,逐渐掌握,可以用一半的努力得到两倍的结果。

本工程旨在实现控制 LED 具体要求为:。简单来说就是以 20 秒是一个循环,每隔一秒 2 秒变一次,前 10 秒亮度逐渐增加,之后 10 秒亮度逐渐降低。 开发板硬件原理图如下图所示。

本设计的上板效果如图 3.3-3 所示

如果想要观看上板后的演示视频,可以登录至简设计法官方网站进行观看。

第三节 设计实现

3.1顶层设计

新建目录:D:\mdy_book\mdyBookPwmled,并在此目录中新建一个名为 mdyBookPwmled.v的文件。 用 GVIM 打开该文件后开始编写代码。在这里再次强调,初学者按照本书提供的路径名和文 件名创建文件,不要对路径名或文件名进行任何更改。因为对于初学者来说,如果贸然按照自己的意 愿更名,后续操作中可能会出现中文路径、空格路径等非法路径的问题,或者有些文件名更改后会出 现报错的现象。因此建议先按照要求更名保存,在多次进行工程练习熟悉了各个步骤后再进行自主更 名操作。在操作中不要想当然,细心操作以避免不必要的错误。

首先对板子上的 LED 灯进行分析,每个 LED 灯都与一个信号相连。这个信号一端连接 LED,另一端连接 FPGA。FPGA 通过控制这一信号的输出就可以控制 LED 灯的亮、灭以及亮度。当 FPGA 输出信号为 0 时,LED 灯点亮,反之,当 FPGA 输出信号为 1 时,LED 灯熄灭。通过输出 PWM波形并控制其占空比,FPGA 可以实现对 LED 灯的亮度进行控制。硬件电路图的连接关系如下表所示。本工程中 LED1 灯连接的 FPGA 管脚为 AA4,对应 FPGA工程信号为 led;工程的时钟管脚为 G1,对应 FPGA 工程信号为 clk;复位管脚为 G1,对应 FPGA工程信号为 rst_n。

综上所述,本工程一共需要三个信号,时钟 clk,复位 rst_n 和输出信号 led。将 module 的名称 定义为 mdyBookPwmled,在顶层信号代码中需要将与外部相连接的输入/输出信号列出,从而实现 信号与管脚的连接,其具体代码如下: 随后对信号的输入输出属性进行声明,指出对于 FPGA 来说这一信号属于输入还是输出,若为输入声明则为 input,若为输出声明则为 output。在本设计中,由于 clk 是外部晶振输送给 FPGA 的,因此在 FPGA 中 clk 为输入信号 input;同样地,rst_n 是外部按键给 FPGA 的,在 FPGA 中 rst_n 也为输入信号 input;同时可知 led 是 FPGA 输出控制 LED1 显示状态的,因此 led 为输出信号 output。

根据三个信号的属性将输入输出端口定义补充完整,其代码如下:

3.2 信号设计

在进行信号设计之前先按照至简设计法的思路来进行架构设计。回顾一下设计需求:通电后,LED 灯显示接近于灭,在之后的 10 秒内,每隔 2 秒钟亮度变化一次,逐渐变亮;在下一个 10 秒内,依旧是每隔 2 秒亮度变化一次,但是会逐渐变暗。可以将其总结为:本设计以 20 秒为一次循环,每隔 2 秒变化一次,前 10 秒亮度逐渐增大,后 10 秒亮度逐渐减小。

前文中详细的介绍过 PWM 的原理,可以得知通过控制 PWM 的占空比可以实现 LED 灯的亮度控制。PWM 占空比越大(高电平时间越长,低电平时间越低),灯的亮度越暗。可以这样理解:FPGA 控制 led 信号的输出,可以输出为 PWM 波形并通过调整占比来达到改变 LED 灯亮度的效果。

根据设计目标可以得出设计方案:每 20 秒一次循环,每隔 2 秒改变一次 led 的占空比,前 10 秒占空比逐渐变小,LED 灯逐渐变亮,后 10 秒占空比逐渐变大,LED 灯也随之逐渐变暗。由于设计目标只对亮度改变进行要求,并没有说明具体的占空比是多少,因此本书自行设定占空比。可以在上板时根据观察到的视觉效果,调整占空比的大小。本书设定占空比如下:

第 1 个 2 秒内,占空比为 95%; 第 2 个 2 秒内,占空比为 85%; 第 3 个 2 秒内,占空比为 70%; 第 4 个 2 秒内,占空比为 50%; 第 5 个 2 秒内,占空比为 20%; 第 6 个 2 秒内,占空比为 20%; 第 7 个 2 秒内,占空比为 50%; 第 8 个 2 秒内,占空比为70%; 第 9 个 2 秒内,占空比为 85%; 第 10 个 2 秒内,占空比为 95%。 之后以此为规律循环往复。

经过多次的实验和测试后发现:PWM 每 10 毫秒刷新一次,LED 灯显示的亮度效果是最好的。因此根据经验值,本书将 PWM 波周期设为 10 毫秒。建议初学者按照书中提供经验值来进行操作,在完全掌握了设计原理可以独立完成设计后,可以再进行不同波型以及不同占空比的尝试。

根据前文分析,得到 led 信号的变化波形图如下图所示。

第 1 次持续时间 2 秒,每 10 毫秒输出一个 PWM 波(9.5 毫秒时变低); 第 2 次持续时间 2 秒,每 10 毫秒输出一个 PWM 波(8.5 毫秒时变低); 第 3 次持续时间 2 秒,每 10 毫秒输出一个 PWM 波(7.0 毫秒时变低); 第 4 次持续时间 2 秒,每 10 毫秒输出一个 PWM 波(5.0 毫秒时变低); 第 5 次持续时间 2 秒,每 10 毫秒输出一个 PWM 波(2.0 毫秒时变低); 第 6 次持续时间 2 秒,每 10 毫秒输出一个 PWM 波(2.0 毫秒时变低); 第 7 次持续时间 2 秒,每 10 毫秒输出一个 PWM 波(5.0 毫秒时变低); 第 8 次持续时间 2 秒,每 10 毫秒输出一个 PWM 波(7.0 毫秒时变低); 第 9 次持续时间 2 秒,每 10 毫秒输出一个 PWM 波(8.5 毫秒时变低); 第 10 次持续时间 2 秒,每 10 毫秒输出一个 PWM 波(9.5 毫秒时变低);

此处PWM 波变低的时间是根据 10 毫秒 PWM 波的占空比算出来的,例如占空比为 95%时可以得出 10ms×95%=9.5ms,以此类推,可以得出所有 PWM 波的变化值。

根据至简设计法原理,总结需求可知,这次设计需要以下三个计数器: 计算输出 10 毫秒 PWM波的计数器; 计算每一个持续 2 秒时间的计数器; 计算次数(1-10 次)的计数器。 来思考一下:既然设计目标为 2 秒改变一次状态,那么为什么除了计算 2 秒的计数器之外还要增加次数的计数器,这样岂不是更麻烦吗?实际上增加计数器的操作正是采用了至简设计法的设计思路,让信号代码更加有条理并便于设计师确定位置。

举个生活中常见的例子,如下图所示,可以把每一次 20 秒的循环看做楼层,把每 2 秒一次的状 态改变看做门牌号,循环中的 2 秒、4 秒、6 秒时间即在对应门牌 1 号 2 号 3 号,以此类推。如果只 用一个计数器的话,那么一楼门牌号为 1、2、3、4、5、6、7、8,二楼门牌号为 9、10、11、12、 13、14、15、16、17、18,三楼以此类推。随着楼层的变高,这种计数方式的弊端就会显露出来。 比如在这种情况下想要寻找 76 号,就可能需要很久才能找到。 如果在一个计数单位的基础上再加一个计数单位,即采用两种技术模式,一个记楼层,一个记门牌号,如下图所示。在同样的门牌号计数中,可以记为一楼的 1、2、3、4、5、6、7、8 号,二楼的 1、2、3、4、5、6、7、8、9、10 号,以此类推,每一层都有对应的房间号。在这种计数模式下, 如果想要找到七层的 6 号房间,不需要多做思考就可以一下定位到正确位置。 此外,如果想要定位到每一层固定位置的房间,同样可以使用两种计数单位复合的模式:用 cnt 0 来表示房间号,其范围是 0-9,用 cnt1 来表示楼层号,其范围是 0-1,通过 cnt0 和 cnt1 两个计数 器可以找到任何一个房间。如果想找同一个位置的房间,也可以直接用 cnt0 来表示。例如 cnt04 可以统一表示每层楼的四号房间。但如果只有房间号这一计数模式而没有楼层的话,想表示每层楼的 四号房间,则表示方式为“cnt04”、“cnt0=12”,更高楼层以此类推。两种表现形式的难易程度 显而易见。

通过案例分析可以发现复合计数并不是多此一举,反而是最简单的计数方式。因此,除计算输出10 毫秒 PWM 波的计数器外,本设计会使用一个计数 2 秒的计数器和一个表示次数的计数器。这是最适合本设计的计数器方案,在后续遇到问题时可以快速的定位到相应位置,从而避免很多麻烦。不论是简单设计还是复杂设计,至简设计法都会全面的考虑设计需求,在每一个环节采用最适合的设计方案,尽量为后续的步骤减少不必要的麻烦。

确定了三个计数器后来讨论一下每个计数器的实现。至简设计法的设计规则中有讲过,计数器的设计只考虑两个因素:加 1 条件和计数数量。只要确定好相应逻辑,就能完成计数器代码设计。首先来讨论计数 10 毫秒 PWM 波的计数器 cnt0,由于 cnt0 始终不停地进行计数,因此可以认为其加 1 条件是一直有效的,可写成:assign add_cnt0==1。

可能会有同学提出疑问:加 1 条件的概念是什么?这里以停车位来进行比喻,一般情况下对每个停车位置会进行对应编号,但是如果某个位置上放置了一块石头无法作为停车位时,该位置就不能获得对应的编号。反之则可以认为停车位编号的加 1 条件就是:对应位置上没有石头,其可以继续的进行编号,即 assign add_cnt0 = “没有石头”。因此如果在设计中计数器一直没有阻碍地进行计数工作,则可以认为加 1 条件是一直有效的。

接着讨论计数器 cnt0 的计数数量:本工程的工作时钟是 50MHz,即周期为 20ns,当计数器计数到第 10_000_000/20=500_000 个时,就代表 10 毫秒时间到了,因此 cnt0 的计数数量为 500_000。

确定好 cnt0 的加 1 条件和计数数量后开始进行代码编写,以往都是一行行的输入相应代码。但是至简设计法有一个小技巧,可以节省代码编写时间的同时在一定程度上降低了代码的出错率。至简设计法将日常代码中常用到的固定部分制作成模板,进行代码编程时可以调用相应模板后根据逻辑输入对应设计的变量将代码补充完整。这处就可以用模板编写计数器代码,感受一下这个炫酷的功能。打开 GVIM 工具,在命令模式下输入“:Mdyjsq”后点击回车就调出了对应模板,如下图所示。之后再将本案例中的变量填到模板里面,就可以得到完整正确的计数器代码。 按照上文方法,得出计数器 cnt0 的代码设计如下:

下面来设计记录 2 秒时间的计数器 cnt1。本工程的工作时钟是 50MHz,即周期为20ns,因此当计数器计数到第 2_000_000_000/20=100_000_000 个时,就代表 2 秒时间计时结束。这是第一种设计思路,至简设计法在这里也提供另外一种设计思路:与 cnt0 复合使用,以 10 毫秒为小周期,通过数 2_000_000_000/10_000_000=200 个 10 毫秒时间,就能确定 2 秒时间计时结束。在这种思路下可以得出计数器 cnt1 的加 1 条件是 end_cnt0,计数数量为 200。此时继续调用至简设计法模板,在 GVIM 命令模式下输入“:Mdyjsq”,点击回车后调出对应模板,将“add_cnt1”和“end_cnt1”补充完整,得到计数器 cnt1 的代码如下: 最后是次数计数器 cnt2 的设计。根据设计目标可知,每隔 2 秒为 1 次改变,计数器的值应加 1,即 cnt2 的加 1 条件为 end_cnt1;每个周期该计数器应计数 10 次,即 cnt2 的计数数量为 10。继续调用至简设计法模板,在命令模式下输入“:Mdyjsq”,点击回车,调出对应模板后将“add_cnt1”和 “end_cnt1”补充完整,得到计数器 cnt2 的代码如下:

确定好三个计数器的代码后来思考一下输出信号 led 的变化。回想设计目标可知 led 有两个变化点:变 0 和变 1。当 10 毫秒计数器计数到一定个数时 led 信号值变为 0,但由于占空比不断进行变化,该计数值也会发生变化。可以假设该值为 x,也就是当计数器数到第 x 个时,led 的值变 0。led 值变为 1 则是由于 10 毫秒计数时间到了,也就是当 end_cnt0 时,led 的值变 1 。依旧调用至简设计法模板,在编辑模式下输入“Shixu2”回车,调出模板并将代码补充完整,得出 led 信号的代码如下:


为什么Led的变零条件是add_cnt0&&cnt0==x-1? 在这个地方add_cnt0始终等于1 。写不写是无所谓的,但是写了绝对不会错。 看前面内容: 计数器规则 3:只有在加 1 条件有效时,才能表示计数器的计数值。 假定加 1 条件为 add_cnt,计数器当前值为 cnt,则  add_cnt&&cntx-1 表示计数器计数到 x 个。  cntx-1 不能表示计数器计数到 x 个。 计数器是从 0 开始计数的,因此计数器的默认值即初始值是 0。那么当计数器的值为 0 时要如何区分这是开始计数的第 1 个值,还是并未计数的默认值呢? 这种情况下可以通过加 1 条件来进行区分。当加 1 条件无效时,计数器值为 0 表示未开始计数,此时的 0 为默认值;当加 1 条件有效时,计数器值为 0 表示计的第 1 个数。同理,当 cntx-1,不能表示计数到 x;只有当 cntx-1 且加 1 条件有效时,才表示计数到 x。 因此,当 add_cnt&&cnt5-1 时,表示计数到 5 个。而当 add_cnt0 &&cnt==5-1 时,不能表示计数到 5 个


最后再来思考一下变量 x。x 代表 led 信号值变为 0 的条件,即 PWM 波变低的时刻。由于不同次数中 PWM 波的占空比是不断变化的,其对应的 x 值会有所变化。也就是说 x 的值与闪烁次数有关,即与计数器 cnt2 有关。在第 1 次闪烁(cnt2=0)时,led 信号在 9.5 毫秒时刻变为 0,即在第一次闪烁中,当 cnt0 数到第9_500_000/20=475_000 个时 led 信号变为 0。因此当 cnt2=0 时,x 的值为 4 75_000。同样的,第 2 次闪烁(cnt2=1)时,led 信号在 8.5 毫秒时刻变为 0。8_500_000/20=425_000,因此 cnt2=1 时,x=425_000。同理可得第三次 x=350_000,第四次 x=250_000,第五次 x=100_000,第六次 x=100_000,第七次 x=250_000,第八次 x=350_000,第九次 x=425_000,第十次 x=475_000。 综上所述,可得 x 的代码如下: 至此,主体程序已经完成。回顾一下思考过程会发现设计的每一步都要按照设计目标逐步展开,看似在讨论一个个小问题,但实际上每个问题都是围绕设计目标来进行讨论的,这也是本书最开始强调制定和理解设计目标的重要性的原因。

3.3 信号定义

下来将 module 补充完整,首先来定义信号类型。对类型 reg 和 wire 的判断总会有多余的联想,比如认为 reg 是寄存器,wire 是线;或者认为 reg 类型会综合成寄存器,wire 类型不会综合成寄存器。

但是这些其实和 reg 型还是 wire 型都并无关系。实际上对信号类型的判断不需要做任何的联想,只 要记住一个规则“用 always 实现的是 reg 型,其他都是 wire 型”就可以了。

cnt0 是用 always 产生的信号,因此类型为 reg。cnt0 计数的最大值为 500_000,需要用 19 根线表示,即位宽是 19 位。关于信号位宽的获取,至简设计法在此分享一个非常实用的技巧:打开计算器,点击“查看”,选择“程序员”模式,在“十进制”下将信号值输入,就会获得对应的信号位宽。如下图所示,将 cnt0 的值 500_000 输入,可以看出其位宽为 19。 综上所述,cnt0 的信号定义代码如下: cnt1 也是用 always 产生的信号,因此类型为 reg。cnt1 计数的最大值为 200,需要用 8 根线表 示,即位宽是 8 位。编辑模式下输入“Reg8”调用模板,得到代码表示如下:

同理,cnt2 信号也由 always 产生,其类型为 reg。cnt2 计数的最大值为 9,需要用 4 根线表示, 251 即位宽是 4 位。编辑模式下输入“Reg4”调用模板,得到代码表示如下: add_cnt0 和 end_cnt0 都是用 assign 方式设计的,因此类型为 wire。其值是 0 或者 1,用 1 根 线表示即可,位宽为 1。编辑模式下输入“Wire1”调用模板,得到代码表示如下: add_cnt1 和 end_cnt1 也是用 assign 方式设计的,因此类型为 wire。其值是 0 或者 1,用 1 根 线表示即可,位宽为 1。编辑模式下输入“Wire1”调用模板,得到代码表示如下: 同样,add_cnt2 和 end_cnt2 是用 assign 方式设计,类型为 wire。其值是 0 或者 1,用 1 根线 表示即可,位宽为 1。编辑模式下输入“Wire1”调用模板,得到代码表示如下: led 信号是用 always 方式设计的,因此类型为 reg。其值是 0 或者 1,用 1 根线表示即可,位宽 为 1。编辑模式下输入“Reg1”调用模板,得到代码表示如下: x 是用 always 方式设计的,因此类型为 reg。其值是最大是 475_000,需要 19 根线表示,即位 宽为 19,其代码表示如下: 完整代码如下

module pwmled(
    clk,
    rst_n,
        led
    );

input clk;
input rst_n;
output led;


reg [ 18:0]  cnt0     ;
wire        add_cnt0 ;
wire        end_cnt0 ;

reg [ 7:0]  cnt1     ;
wire        add_cnt1 ;
wire        end_cnt1 ;


reg [ 3 :0]  cnt2     ;
wire        add_cnt2 ;
wire        end_cnt2 ;

reg          led;
reg[18:0]    x;



always @(posedge clk or negedge rst_n) begin 
    if (rst_n==0) begin
        cnt0 <= 0; 
    end
    else if(add_cnt0) begin
        if(end_cnt0)
            cnt0 <= 0; 
        else
            cnt0 <= cnt0+1 ;
   end
end
assign add_cnt0 = 1;
assign end_cnt0 = add_cnt0  && cnt0 == 500_000-1 ;


always @(posedge clk or negedge rst_n) begin 
    if (rst_n==0) begin
        cnt1 <= 0; 
    end
    else if(add_cnt1) begin
        if(end_cnt1)
            cnt1 <= 0; 
        else
            cnt1 <= cnt1+1 ;
   end
end
assign add_cnt1 = end_cnt0;
assign end_cnt1 = add_cnt1  && cnt1 == 200-1 ;


always @(posedge clk or negedge rst_n) begin 
    if (rst_n==0) begin
        cnt2 <= 0; 
    end
    else if(add_cnt2) begin
        if(end_cnt2)
            cnt2 <= 0; 
        else
            cnt2 <= cnt2+1 ;
   end
end

assign add_cnt2 = end_cnt1;
assign end_cnt2 = add_cnt2  && cnt2 == 10-1 ;

always  @(posedge clk or negedge rst_n)begin
    if(rst_n==1'b0)begin
        led <= 1;
      end
    else if(add_cnt0 && cnt0==x-1)begin
        led <= 0;
      end
        else if(end_cnt0)begin
        led <= 1;
    end
end

always  @(*)begin
    if(cnt2==0)begin
        x=475_000;
    end
    else if(cnt2==1)begin
        x=425_000;
    end
    else if(cnt2==2)begin
        x=350_000;
    end
     else if(cnt2==3)begin
        x=250_000;
    end
     else if(cnt2==4)begin
        x=100_000;
    end
     else if(cnt2==5)begin
        x=100_000;
    end
     else if(cnt2==6)begin
        x=250_000;
    end
     else if(cnt2==7)begin
        x=350_000;
    end
     else if(cnt2==8)begin
        x=425_000;
    end
     else begin
        x=475_000;
    end
end


endmodule


第四节 综合和上板

4.1 新建工程

打开软件“Quartus Ⅱ”,点击 File 下拉列表中的 New Project Wzard...新建工程选项,如下 图所示。 随后会出现 Quartus 新建工程介绍,如下图所示,直接点击“Next”。

此时会出现工程文件夹、工程名、顶层模块名设置界面,如图 3.3- 11 所示。设置目录为:D:/mdy_book/mdyBookPwmled,工程名和顶层名为 mdyBookPwmled。这里再次进行强调,为了避免初学者使用过程中出现报错情况,强烈建议按照本书的工程名和文件名进行设置,设置完成后点击“Next”。 新建工程类型设置选择“Empty project”,如下图所示,然后点击“Next”。

文件添加界面如图 3.3- 13 所示,点击右侧的“Add”按钮,添加之前写好的“mdyBookPwmled.v”文件,可以看到界面下方会显示出文件,随后点击“Next”。 芯片型号选择界面如图 3.3- 14 所示,“Device Family”选择“Cyclone ⅣE”,在芯片型号选择处选择“EP4CE15F23C8”,之后点击“Next”。

图 3.3- 15 为 QUARTUS 设置工具界面,不必做任何修改,直接点击“Next”即可。

新建工程的汇总情况如下图所示,点击“Finish”,完成新建工程。

4.2 综合

新建工程步骤完成后,会出现如下所示的 QUARTUS 界面。 点击编译按钮可以对整个工程进行编译。编译成功的界面如图 3.3- 18 所示

4.3 配置管脚

下面需要对相应管脚进行配置。如下图所示,在菜单栏中选中“Assignments”,然后选择“Pin Planner”,随后会弹出配置管脚的窗口。

在配置窗口最下方中的“location”一列,参考错误!未找到引用源。,按照表 3.3-1 中最右两列 配置好 FPGA 管脚,最终配置结果如图 3.3- 20。配置完成后,关闭“Pin Planner”,软件自动会保 存管脚配置信息。

4.4 再次综合

再次打开“QUARTUS”软件,在菜单栏中选中“Processing”,然后选择“Start Compilation”, 再次对整个工程进行编译和综合,如下图所示。 当出现图 3.1-70QUARTUS 编译成功标志时,说明已经成功完成编译综合。

4.5 连接开发板

完成编译后开始进行上板调试操作,按照下图的方式,将下载器接入电脑 USB 接口,接上开发 板电源后按下开发板下方蓝色开关,硬件连接完毕。

4.6 上板

打开 QUARTUS 界面,双击“Tasks”一栏中的”Program Device‘。 出现下载程序界面后点击“add file”添加“.sof”文件,点击“Start”,会在上方的“Progress”处显示进度,当进度条到 100%时提示成功,此时即可在开发板上观察相应现象。

如果操作步骤正确,此时可以在板子上看到 LED 灯在十秒内逐渐变亮,接下来的十秒又逐渐变暗,随后继续变亮,不断循环。如果观察到这一现象,可以判断此次设计成功。反之,如果 LED 灯没有正常显示或者按照设计目标的规律变暗变亮,就需要从头开始进行错误排查。如果无法自己完成错误排查的话,可以重新按照步骤操作一遍,相信一定可以达到想要的效果。

标签: 电容a475

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台