001_雾盈FPGA笔记之一呼吸灯简单实验(Verilog)
- 格式:docx
- 大小:139.77 KB
- 文档页数:12
呼吸灯实验报告呼吸灯实验报告引言:呼吸灯是一种具有艺术性和实用性的装饰灯具,其灯光可以模拟人类呼吸的节奏,给人一种温馨、舒适的感觉。
本次实验旨在探究呼吸灯的工作原理、设计思路以及实际应用情况,进一步了解其在日常生活中的潜在价值。
一、实验设备和原理1. 实验设备:本次实验所需设备包括Arduino开发板、LED灯、电阻、电容、面包板、导线等。
2. 实验原理:呼吸灯的工作原理基于PWM(脉宽调制)技术,通过改变信号的占空比来控制LED灯的亮度。
PWM技术可以使LED灯在亮度变化时产生平滑的过渡效果,模拟人类呼吸的节奏。
二、实验过程1. 连接电路:将Arduino开发板与面包板连接,将LED灯、电阻、电容等元件按照电路图连接在面包板上。
2. 编写程序:使用Arduino开发环境编写程序,通过设置PWM信号的占空比来控制LED灯的亮度。
可以根据需要设置呼吸灯的亮度和变化速度。
3. 上传程序:将编写好的程序上传到Arduino开发板上,使其开始执行。
4. 观察实验结果:通过观察LED灯的亮度变化情况,验证呼吸灯的设计效果。
三、实验结果与分析经过实验观察,我们可以看到LED灯的亮度在一定时间内逐渐增强,然后再逐渐减弱,如同人类呼吸的节奏一般。
这种变化过程给人一种温暖、舒适的感觉,增添了房间的氛围。
通过调整程序中PWM信号的占空比,我们可以控制呼吸灯的亮度和变化速度。
较大的占空比会使呼吸灯的亮度增强和变化速度加快,而较小的占空比则会使呼吸灯的亮度减弱和变化速度减慢。
因此,通过合理调整占空比,我们可以根据实际需要设计出不同风格的呼吸灯。
四、呼吸灯的应用前景呼吸灯作为一种独特的灯具,具有广泛的应用前景。
以下是几个可能的应用领域:1. 家居装饰:呼吸灯可以用于家居装饰,为房间营造出温馨、舒适的氛围。
无论是客厅、卧室还是书房,都可以通过呼吸灯的设计和安装,使空间更加温暖宜人。
2. 商业场所:呼吸灯在商业场所的应用也非常广泛。
一、实训目的本次实训旨在通过实际操作,学习和掌握呼吸灯电路的设计与制作方法,加深对电子电路原理的理解,提高动手实践能力。
同时,通过实训,了解呼吸灯电路在日常生活和工业中的应用,培养创新意识和团队协作精神。
二、实训内容1. 电路原理学习- 研究呼吸灯电路的工作原理,包括电路组成、元件功能及相互关系。
- 了解双稳态振荡器、555定时器等电子元件在呼吸灯电路中的应用。
2. 电路设计与绘制- 根据呼吸灯电路原理,设计电路图,选择合适的元件。
- 使用电子设计软件(如Proteus)进行电路仿真,验证电路设计。
3. 电路制作与调试- 按照电路图,焊接电路板,组装呼吸灯电路。
- 对电路进行调试,确保电路正常工作。
4. 实验与分析- 观察呼吸灯电路的呼吸效果,分析影响呼吸效果的参数。
- 通过改变电路参数,如电容、电阻等,调整呼吸灯的呼吸频率和亮度。
三、实训过程1. 电路原理学习- 通过查阅资料、上网搜索等方式,了解呼吸灯电路的原理和元件功能。
- 分析双稳态振荡器、555定时器等元件的工作原理,理解其在呼吸灯电路中的作用。
2. 电路设计与绘制- 根据呼吸灯电路原理,绘制电路图,选择合适的元件。
- 使用Proteus软件进行电路仿真,验证电路设计,确保电路能够正常工作。
3. 电路制作与调试- 按照电路图,焊接电路板,组装呼吸灯电路。
- 在组装过程中,注意元件的焊接质量,确保电路板整洁、可靠。
- 对电路进行调试,观察呼吸灯的呼吸效果,调整电路参数,使呼吸效果达到预期。
4. 实验与分析- 观察呼吸灯电路的呼吸效果,分析影响呼吸效果的参数,如电容、电阻等。
- 通过改变电路参数,调整呼吸灯的呼吸频率和亮度,验证电路设计的灵活性。
四、实训结果与分析1. 电路工作正常- 通过调试,呼吸灯电路工作正常,能够实现呼吸效果。
2. 参数调整效果- 通过改变电容、电阻等参数,可以调整呼吸灯的呼吸频率和亮度,满足不同需求。
3. 电路设计优化- 在实训过程中,发现电路设计存在一些不足,如元件布局不合理、焊接质量有待提高等。
verilog实验报告Verilog实验报告引言:Verilog是一种硬件描述语言(HDL),用于设计和模拟数字电路。
它是一种高级语言,能够描述电路的行为和结构,方便工程师进行数字电路设计和验证。
本实验报告将介绍我在学习Verilog过程中进行的实验内容和所获得的结果。
实验一:基本门电路设计在这个实验中,我使用Verilog设计了基本的逻辑门电路,包括与门、或门和非门。
通过使用Verilog的模块化设计,我能够轻松地创建和组合这些门电路,以实现更复杂的功能。
我首先创建了一个与门电路的模块,定义了输入和输出端口,并使用逻辑运算符和条件语句实现了与门的功能。
然后,我创建了一个测试模块,用于验证与门的正确性。
通过输入不同的组合,我能够验证与门的输出是否符合预期。
接下来,我按照同样的方法设计了或门和非门电路,并进行了相应的测试。
通过这个实验,我不仅学会了使用Verilog进行基本门电路的设计,还加深了对逻辑电路的理解。
实验二:时序电路设计在这个实验中,我学习了如何使用Verilog设计时序电路,例如寄存器和计数器。
时序电路是一种具有状态和时钟输入的电路,能够根据时钟信号的变化来改变其输出。
我首先设计了一个简单的寄存器模块,使用触发器和组合逻辑电路实现了数据的存储和传输功能。
然后,我创建了一个测试模块,用于验证寄存器的正确性。
通过输入不同的数据和时钟信号,我能够观察到寄存器的输出是否正确。
接下来,我设计了一个计数器模块,使用寄存器和加法电路实现了计数功能。
我还添加了一个复位输入,用于将计数器的值重置为初始状态。
通过测试模块,我能够验证计数器在不同的时钟周期内是否正确地进行计数。
通过这个实验,我不仅学会了使用Verilog设计时序电路,还加深了对触发器、寄存器和计数器的理解。
实验三:组合电路设计在这个实验中,我学习了如何使用Verilog设计组合电路,例如多路选择器和加法器。
组合电路是一种没有状态和时钟输入的电路,其输出只取决于当前的输入。
ne呼吸灯实验报告一、实验目的本次实验的主要目的是深入了解和掌握 ne 呼吸灯的工作原理,通过实际操作和调试,实现呼吸灯效果,并对其性能和特点进行评估。
二、实验原理ne 呼吸灯的实现原理基于脉冲宽度调制(PWM)技术。
PWM 是通过改变脉冲信号的占空比来控制输出的平均电压,从而实现对灯光亮度的调节。
在呼吸灯中,通过逐渐改变 PWM 信号的占空比,使灯光亮度逐渐增强和减弱,营造出类似于呼吸的效果。
三、实验设备与材料1、单片机开发板(如 Arduino、STM32 等)2、 LED 灯(颜色可根据需求选择)3、电阻(用于限流,保护 LED 灯)4、杜邦线若干5、电脑及相关编程软件四、实验步骤(一)硬件连接1、将 LED 灯的阳极通过电阻连接到单片机的数字输出引脚,阴极连接到地。
2、使用杜邦线确保连接牢固,避免接触不良。
(二)软件编程1、选择适合的开发环境,如 Arduino IDE 或 Keil。
2、编写控制程序,主要包括以下几个部分:初始化设置:包括设置引脚模式、PWM 频率等。
呼吸效果实现:通过循环逐渐改变 PWM 占空比,实现亮度的渐变。
以下是一个简单的 Arduino 示例代码:```cint ledPin = 9; //定义 LED 连接的引脚void setup(){pinMode(ledPin, OUTPUT);//设置引脚为输出模式}void loop(){for (int dutyCycle = 0; dutyCycle <= 255; dutyCycle++){//亮度逐渐增强analogWrite(ledPin, dutyCycle);delay(10);}for (int dutyCycle = 255; dutyCycle >= 0; dutyCycle) {//亮度逐渐减弱analogWrite(ledPin, dutyCycle);delay(10);}}```(三)编译与上传将编写好的程序编译,并上传到单片机开发板。
呼吸灯原理fpga呼吸灯原理FPGA一、引言在现代高科技应用中,呼吸灯已成为一种被广泛采用的照明效果。
呼吸灯通过不断变化的亮度给人一种灵动、生动的感觉。
而实现呼吸灯效果的核心技术之一就是FPGA,即可编程逻辑门阵列。
二、FPGA的基本原理FPGA,全称为Field Programmable Gate Array,是一种基于逻辑门阵列的可编程逻辑器件。
FPGA拥有巨大的逻辑门数量和可编程性,可以灵活地实现各种数字电路功能,充分发挥其计算和控制的能力。
具体而言,FPGA通过控制可编程逻辑门和可编程逻辑单元的开关状态,实现了数字电路的自由编程。
三、呼吸灯实现原理呼吸灯实现的基本原理是通过控制LED的亮度,使其不断地从暗到亮,再从亮到暗,形成一种类似人类呼吸的效果。
具体而言,FPGA通过调节PWM(脉宽调制)信号的占空比来实现。
PWM信号可以控制LED灯亮度的高低,高占空比对应亮的状态,低占空比对应暗的状态。
四、FPGA实现呼吸灯的步骤实现FPGA驱动呼吸灯效果的步骤如下:1.配置FPGA开发板。
首先,需要将需要的开发板步骤下载到FPGA芯片中。
2.设置FPGA时钟。
设置一个合适的时钟频率,用于控制呼吸灯的变化。
时钟信号的频率决定了呼吸灯的速度。
3.设计PWM模块。
通过使用FPGA的计数功能,可以实现一个自动递增的计数器。
该计数器可以实现控制PWM信号的占空比,从而控制LED的亮度。
通过不断增大计数值,LED逐渐变亮;通过减小计数值,LED逐渐变暗。
4.编写控制逻辑。
在FPGA中,可以使用Verilog或VHDL等硬件描述语言编写控制逻辑。
通过该逻辑,可以根据时钟信号和PWM模块的输出,实现呼吸灯效果的控制。
五、FPGA的优势与应用FPGA作为一种可编程逻辑器件,具有以下优势:1.灵活性强。
FPGA可以根据不同的需求进行编程,可适应多样化的应用场景。
2.性能优异。
FPGA的逻辑门数量庞大,能够处理复杂的计算和控制任务。
实验3 呼吸灯设计实验一、实验目的1、会使用单片机4个并行I/O端口连接外部设备并构建单片机最小应用系统。
2、能使用工具软件绘制单片机硬件原理图、能编写简单的C语言程序。
3、会编写常见的循环程序和延时子程序。
二、实验内容采用STC89C52单片机构建最小系统,在P1.0口外接1只发光二极管,编程实现二极管出现呼吸灯的显示效果。
三、实验原理1、P1口为准双向口,每一位都可独立地定义为输出线或输入线。
2、延时子程序采用指令循环指令来实现,在系统时间允许的情况下采用此方法。
循环时间=机器周期×指令所需机器周期×循环次数(其中机器周期:晶振频率为12MHz时为1us,晶振频率为6MHz时为2us)四、思考题(1)采用任务1的单灯控制电路,编程实现P1端口连接的8个发光二极管闪动频率控制。
(2)采用任务1的单灯控制电路,编程实现P1端口连接的8个发光二极管自动变频控制。
表4 项目二考核标准任务名称任务一:单灯闪烁控制设计序号考核内容考核方式分值评分1 工具软件使用Kile软件操作使用实际操作 5 会操作使用3-5分不会操作0-3分2 Proteus软件操作使用5 会操作使用3-5分不会操作0-3分3 下载工具使用 5 会操作使用3-5分不会操作0-3分4 硬件电路晶振电路绘制原理图4 正确4分不正确0分复位电路 4 正确4分不正确0分5 电源电路 2 正确2分不正确0分6 I/O口分配存储器选择2 正确2分不正确0分7 输出显示电路8 正确4-8分不正确0-4分8 程序设计程序设计思路编写程序 5 可行3-5分不可行0-3分9 流程图绘制、存储器分配5 正确3-5分不正确0-3分10 源程序编写10 编译正确10分编译不正确4-6分无法编译0-3分11 程序调试调试、仿真运行效果10 实现功能指标10分能仿真,没实现功能指标0-3分12 电路调试制作硬件调试连接实验板电路或电路制作5 电路正常运行5分不正常0-3分联合调试 5 达到功能指标5分没达到0-3分13 加分 5 小组讨论、独立完成5分不能独立完成0-3分说明:具体评分标准可根据教学过程中的实际情况进行合理调整。
(原创)⽤Verilog实现⼀个参数化的呼吸灯(Verilog,CPLDFPGA)1.Abstract观察到⼀个有趣的现象,每当把Apple笔记本合上的时候,那个⽩⾊的呼吸灯就会反复地由暗渐明,然后⼜由明渐暗,乍⼀看就像Apple笔记本在打盹休息⼀样,⼗分可爱!于是突发奇想,要不⽤Verilog也写⼀个吧,资源也不需要太多,⼀个LED灯就可以了。
为了使⽤⽅便,可以把它做成参数化的,可以根据时常进⾏参数调节;深睡、浅睡跟清醒的时候呼吸频率似乎是不⼀样的…下⾯就来分析和实践⼀下。
2.Content2.1 理论分析根据上述描述的现象,仔细分析⼀下,就是对LED灯亮的占空⽐设置,画张图来表⽰更直观⼀些。
FIG2.1 LED灯占空⽐⽰意图为了表达得更明晰⼀些,将LED这根信号线⽤红⾊凸显出来。
从左边往右边看吧,在RST的复位信号之前是⼀个不确定的逻辑(前⼀个状态,可能是0,也可能是1),所以⽤⿊⾊块加深表⽰,复位后LED输出低电平(将电路设计为LED信号为1时驱动灯管亮)。
过⼀段时间以后,输出⼀个占空⽐为1%的⾼电平,再过⼀段时间,输出为2%的⾼电平,依次往后直到输出为100%的⾼电平,这样现象就是灯管逐渐变亮;要是灯管逐渐变暗,直接将逻辑反过来就可以了。
2.2 整体设计纵观整个灯的变化过程,可以归结为4个过程,依次为逐渐变亮、亮保持、逐渐变灭、灭保持,依次⽤S0,S1,S2,S3表⽰;若有复位信号产⽣,则所有状态⽴刻转到S0;若没有复位信号产⽣,那么就在这个状态机⾥边循环。
⽤状态转换表和状态图来表⽰就容易理解得多。
TAB2.1 状态转换表当前状态跳转条件下⼀个状态S0RST / !S0_end S0S0S0_end S1S1RST S0S1!S0_end S1S1S0_end S2S2RST S0S2!S0_end S2S2S0_end S3S3RST / S3_end S0S3!S3_end S3⽤状态图来表⽰。
呼吸灯电路原理报告引言呼吸灯是一种常见的电子元件实验项目,广泛应用于LED灯的控制。
本报告将介绍呼吸灯电路的原理和实现方法。
电路原理呼吸灯电路的核心原理是利用脉宽调制(PWM)技术来控制LED灯的亮度。
通过不断改变LED灯的亮度,可以实现呼吸般的效果。
基本原理呼吸灯电路基于以下两个基本原理:1.脉宽调制(PWM):脉宽调制技术是一种将模拟信号转化为数字信号的方法。
通过改变数字信号的高电平时间(即脉冲宽度),可以控制输出信号的平均值,从而改变LED灯的亮度。
2.电容充放电:利用电容器的充放电特性,可以实现呼吸灯电路的效果。
通过改变电容器的充电时间和放电时间,可以控制LED灯的亮度变化。
电路图下面是一种常见的呼吸灯电路的示意图:+5V|R|| |-----+---+------|------+-------> LED| | |C | || | || | |----- || |----- || | || | |GND GND GND实现步骤以下是实现呼吸灯电路的步骤:1.连接电路元件:按照电路图连接电路元件。
将电阻(R)连接到+5V电源,将电容器(C)连接到电阻和LED之间,将LED连接到电容器的正极。
2.编程准备:根据硬件平台的要求,选择合适的编程语言和开发环境。
3.初始化引脚:在程序中初始化用于控制LED灯的引脚。
根据电路图,将LED灯所在的引脚设为输出模式。
4.设置脉宽调制:使用合适的脉宽调制函数,设置PWM输出的频率和占空比。
占空比决定了LED灯的亮度。
5.实现呼吸灯效果:在一个循环中,不断改变PWM的占空比,从而实现呼吸灯效果。
可以通过逐渐增大或逐渐减小占空比的方式实现呼吸效果。
6.程序运行:编译和下载程序到硬件平台,运行程序。
LED灯应该开始呼吸般地变亮和变暗。
结论通过脉宽调制技术和电容充放电原理,我们可以实现呼吸灯电路。
这种电路可以控制LED灯的亮度,使其呼吸般地变亮和变暗。
呼吸灯电路广泛应用于LED灯的控制,是一个简单而有趣的电子元件实验项目。
用FPGA作呼吸灯简单简直爽歪歪,RTL级视图如下:代码如下:/******************************************模块名:呼吸灯顶层模块作者:善水不善争时间:2015.3.15软件版本:QUARTUS II 11.0(32BIT)系统时钟:50MHz******************************************/ module PWM_test(clk_sys, rst_n ,PWM_out);input clk_sys, rst_n;output PWM_out;wire [7:0] ctr_Duty;wire clk_w;PWM_gen u1PWM_gen(.clk_sys(clk_sys),.rst_n(rst_n),.ctr_Duty(ctr_Duty),.PWM_out(PWM_out));cnt_fb_auto u2ct_fb(.clk(clk_w),.rst_n(rst_n),.CNT_out(ctr_Duty));fre_div u3fre_div(.clk_sys(clk_sys),.rst_n(rst_n),.clk_l(clk_w));endmodule/************************************模块名:分频计数器作者:善水不善争时间:2015.3.15软件版本:QUATUS II 11.0(32BIT)时钟频率:50MHz************************************/module fre_div(clk_sys, rst_n, clk_l);input clk_sys, rst_n;output clk_l;reg [19:0] cnt_clk;reg clk_w;/******************************************************PWM模块中最大值为FF,需要其在0~FF(即占空比0~100%)之间循环,循环时间为3秒(一呼吸的时间),所以其所需时钟频率为:255/1.5=170Hz系统时钟为50MHz,所以分频模块的计数最大值为:50000000/170=294118********************************************************/ parameter maxcnt = 20'd294118;always @(posedge clk_sys, negedge rst_n) beginif(!rst_n) begincnt_clk <= 20'd0;clk_w <= 1'b0;endelse if(cnt_clk == maxcnt) beginclk_w <= 1'b1;cnt_clk <= 20'd0;endelse beginclk_w <= 1'b0;cnt_clk <= cnt_clk + 1'b1;endendassign clk_l = clk_w;endmodule/*******************************模块名:自动可逆加减计数器作者:善水不善争时间:2015.3.15软件版本:QUARTUS II 11.0(32BIT)*********************************/module cnt_fb_auto(clk, rst_n, CNT_out);input clk, rst_n;output [7:0] CNT_out;//输出计数范围00~ffreg [7:0] cnt;reg ud_f;//ud_f=1,加法计数;ud_f=0,减法计数//计数单元,ud_f=1时,计数器cnt加1,否则减1 always @(posedge clk, negedge rst_n) beginif(!rst_n) begincnt <= 8'b00;endelse if(ud_f) begincnt <= cnt + 1'b1;endelse begincnt <= cnt - 1'b1;endend//cnt加到最大值时,ud_f赋1;cnt减到最小时,ud_f赋0 always @(posedge clk, negedge rst_n) beginif(!rst_n) ud_f <= 1'b1;else if(cnt == 8'hfe) ud_f <= 1'b0;else if(cnt == 8'h01) ud_f <= 1;endassign CNT_out = cnt;endmodule/**************************************************模块名:PWM波产生模块作者:善水不善争时间:2015.3.15软件版本:QUARTUS II 11.0(32BIT)**************************************************/ module PWM_gen(clk_sys, rst_n, ctr_Duty, PWM_out); input clk_sys,rst_n;input [7:0] ctr_Duty;//输入高电平持续时间output PWM_out;reg PWM_w;reg [7:0] cnt;//cnt从0到FF计数always @(posedge clk_sys, negedge rst_n) begin if(!rst_n) cnt <= 8'h00;else if(cnt == 8'hff) cnt <= 8'h00;else cnt <= cnt + 1'b1;end//当cnt<=ctr_Duty时输出高电平,否则输出低电平always @(posedge clk_sys, negedge rst_n) begin if(!rst_n) PWM_w <= 1'b0;else if(cnt <= ctr_Duty) PWM_w <= 1'b1;else PWM_w <= 1'b0;endassign PWM_out = PWM_w;endmodule。
[FPGA]Verilog利⽤PWM调制完成RGB三⾊彩虹呼吸灯概述实现彩虹呼吸灯题⽬就是这么简短,但这是⽬前我碰到的最有意思的⼀道题⽬,因为他有⽆数种解决⽅法,并且每⼀种都是那么⾼级或者巧妙,⽐如可以利⽤3路不同初相的PWM调制信号驱动三颗RGB灯重叠呼吸利⽤1路PWM信号以及状态机,将⼀个周期分为3个状态,分别是[R降G升B灭],[R灭,G降,B升]和[R升,G灭,B降],依次往复实现重叠呼吸将PWM拆分为3段,分别为升,降,灭,在不同时间周期性的输送给RGB实现重叠呼吸当然,不只这⼏种,还有更⾼级的⽅法或者⽣成语句也可以更加简练的完成题⽬,在这⾥,我将采取上⾯罗列的⼏种⽅法的⼀种折中⽅案,采取"拆分PWM","三元运算符实现单⾏条件信号分配","监视模块内运⾏情况并以监视信号作为状态转换的触发条件"来实现彩虹呼吸灯.题⽬分析题⽬只有七个字:"实现彩虹呼吸灯",其中"呼吸两个字",已经确定了这个实验和脉宽调制扯不开⼲系,另外"彩虹"也说明这个实验需要很多的⾊彩,单单靠单⾊LED是完成不了的,⼀定需要三⾊RGB完成,并且只是让R,G,B三个LED交替呼吸,也达不到"彩虹"的效果,所以需要让三⾊灯按照⼀定的规律重叠呼吸,这⾥为了⽅便,我按照下图⽰意的样式进⾏编程(抱歉画⼯实在⽋缺,咳咳)意思就是在R灯最亮时,G灯开始升,R灯开始降,在G灯最亮时,R灯已灭,B灯开始升,G灯开始降,以此类推.通过这个图也可以容易的分成三个情况,⽤以实现状态机.PWMPWM是个啥?PWM( Pulse width modulation )就是脉冲宽度调制,是⼀种通过数字信号对模拟信号控制的有效技术.简单来说,规律的进⾏脉宽调制,⽐如将⼀束⽅波的占空⽐不断减⼩,那么这束⽅波的有效值也相应的减⼩,占空⽐增⼤,有效值也增⼤,借此来对LED的亮度进⾏控制,加以周期性的增减,即可实现呼吸灯.呼吸灯只是PWM的⼀个具体应⽤.PWM咋实现?在之前的学习早已接触过PWM调制的实现⽅法,在这⾥直接给出代码,可以通过注释回忆PWM实现过程module PWM(input CLK,input FLAG//标志位,控制输出的PWM是升还是降(1升0降),output STT//监视信号(脉冲),output PWM);reg[24:0]cnt1;reg[24:0]cnt2;parameter freq=2400;//通过这个freq来控制PWM的周期reg stt;//监视状态always@(posedge CLK)if(cnt2==freq-1)//cnt2满,则状态为1(只持续⼀个时钟周期)stt<=1'b1;elsestt<=1'b0;assign STT=stt;always@(posedge CLK)if(cnt1>=freq-1)//满则清零cnt1<=1'b0;elsecnt1<=cnt1+1'b1;always@(posedge CLK)if(cnt1==freq-1)//cnt1满,以cnt1从空到满为⼀个周期执⾏操作if(FLAG)//升的情况if(cnt2>=freq-1)cnt2<=1'b0;elsecnt2<=cnt2+1'b1;//升else//降的情况if(cnt2<=0)cnt2<=freq-1;elsecnt2<=cnt2-1'b1;//降elsecnt2<=cnt2;assign PWM=(cnt1<cnt2)?1'b0:1'b1;//PWM的核⼼,输出调制好的PWM信号endmodule代码中的stt和STT是监视脉冲,不影响PWM输出;输⼊信号FLAG控制PWM输出信号是升还是降.⼆者作⽤在顶层代码处详细解释.顶层模块PWM很容易实现,需要动脑⼦的就是如何通过例化模块来实现交替呼吸.下⾯给出我的算法.例化模块先看代码wire UP;wire DW;wire STT0;wire STT1;PWM up(CLK,1,STT0,UP);PWM dw(CLK,0,STT1,DW);其中up例化模块中的1代表FLAG,在此表⽰这个up例化模块是⼀个"升"模块,即为可以产⽣控制LED亮度从灭到亮的PWM信号,dw例化模块则代表可以产⽣⼀个可以控制从亮到暗的PWM信号.通过这个设计可以将PWM模块的功能拆分,提供两种模式供主模块灵活调⽤.代码中的UP和DW分别为代表亮度升和亮度降的PWM信号.状态分析这⾥不按照⽂⾸的那种状态机思路来写,⽽是将RGB三⾊灯分成3路对待,这⾥先以R为例.对R来说,他的亮灭规律为:升(⼀单位时间),降(⼀单位时间),灭(⼀单位时间).然后可以以此来写条件语句进⾏信号分配,可能第⼀时间想到的就是直接定义⼀个分频,不同时间显⽰不同状态即可,但是这种写法不利于后期拓展,易读性和可维护性也稍差,在这⾥采⽤很⽅便的"三元运算符"解决.先来看这段代码reg[1:0]flag0=2'b00;always@(posedge STT0)if(flag0==2'b10)flag0<=1'b0;elseflag0<=flag0+1'b1;这⾥定义了⼀个标志为flag0,它是以上⽂提到过的监视脉冲STT为触发进⾏递增计数的,STT是⼀个在PWM模块内每⼀个⼯作周期完成后就输出⼀单位时间⾼电平的监视脉冲,通过这个脉冲可以知道PWM已经⼯作完⼀个周期,可以进⾏下⼀周期的⼯作,在顶层代码⾥则充当了状态转移的触发条件.再来看这⼀⾏代码assign LED[0]=(flag0==2'b00)?UP:((flag0==2'b01)?DW:1'b1);这⼀⾏是实现RGB灯⼯作状态的核⼼代码,通过(两层)三元运算符在⼀条表达式内就完成了条件赋值.这条代码的意思就是,如果标志位flag0是2'b00,则R亮度升,若不是,则检测标志为是否为2'b01,若是,则R亮度降,如不是,则灭.然后通过上⼀个代码块中的代码可以知道,每⼀个PWM周期完成后(表现为R已到达最亮或者最暗),状态发⽣转移,标志为变为下⼀个状态,R也就在完成了亮度升之后⽴刻开始亮度降,宏观表现为"呼吸"的状态.代码整合上⽂⾥两个代码块就⾜以让⼀个灯完成⼀个状态的⼯作,这部分代码如下reg[1:0]flag0=2'b00;always@(posedge STT0)if(flag0==2'b10)flag0<=1'b0;elseflag0<=flag0+1'b1;assign LED[0]=(flag0==2'b00)?UP:((flag0==2'b01)?DW:1'b1);reg[1:0]flag1=2'b01;always@(posedge STT0)if(flag1==2'b10)flag1<=1'b0;elseflag1<=flag1+1'b1;assign LED[1]=(flag1==2'b00)?UP:((flag1==2'b01)?DW:1'b1);reg[1:0]flag2=2'b10;always@(posedge STT0)if(flag2==2'b10)flag2<=1'b0;elseflag2<=flag2+1'b1;assign LED[2]=(flag2==2'b00)?UP:((flag2==2'b01)?DW:1'b1);三个灯就相当于将这⼀段代码例化三次,就可以让三⾊灯分别进⾏互相不影响的状态转移(呼吸变化),但是我们的⽬的是让他们按照⽂⾸图中的规律重叠呼吸,该怎么实现呢?这很简单,很容易想到,三段⼀样的代码⾥都分别有⼀个独⽴的标志为flag,他是reg类型数据,所以可以在定义时给他分配⼀个初始状态,这样就相当于给三个灯设置了不同的初相,在后⾯⼯作的时候由于⼯作周期相同,就会⼀直保持最开始的相位差,周期性的进⾏⽂⾸图中的交替呼吸.⾄此,彩虹呼吸灯已经完成.效果最后的效果图,图⽚较⼤,加载可能⽐较慢.(因为灯实在是太亮了,就蒙了⼀层纸来观察颜⾊变化)后话这篇⽂章是⽬前写过的第⼆费⼒的了,其中的代码更新了很多很多次,在琢磨更精简更巧妙的算法上和修Bug上花了很多的时间和精⼒,前前后后烧录上板测试不下50次(不夸张T_T),在本地commit了⽆数个版本,回滚了⽆数次,⼀遍⼀遍修改,最后才得到了你看到的这些代码.我的⽔平有限,所以就算如此⽂中的代码和讲解⼀定有所缺漏,还请希望⼤家多多包涵,并指出不⾜之处,改进这篇⽂章,来帮助更多的⼈.。
基于FPGA的呼吸灯简单实验程序(Verilog)
2016-07-27雾盈
1.呼吸灯
呼吸灯最早是由苹果公司发明并应用于笔记本睡眠提示上,一经展出,立刻吸引众多科技厂商争相效仿。
将其广泛用于各种电子产品中,尤其是智能手机。
呼吸灯其实是微电脑控制下,由暗渐亮,然后再由亮渐暗,模仿人呼吸方式的LED灯
2.呼吸灯原理
LED的亮度与流过的电流成正比。
在一定的频率之下,如果占空比是0,则LED不亮;如果占空比是100%,则LED最亮;如果占空比刚好是50%,则LED亮度适中。
如果我们让占空比从0~100%变化,再从100%~0不断变化,就可以实现LED一呼一吸的效果。
其波形占空比示意图如下所示:
3.呼吸灯程序设计思路
(1)首先确定PWM的频率为1Khz
(2)由频率算出周期T = 1/f = 1ms
(3)根据每次呼1s,吸1s,算出计数值1s/1ms=1000
(4)然后将1ms分成1000份,每一份是1us
(5)写三个1us、1ms、1s的3个计数器count1、count2、Count3,最后count2和count3进行比较
4.程序框图
5.状态机设计
可以将呼吸灯运行过程归为两个状态:S0:由灭渐亮;S1:由亮渐灭。
这里就会有两个问题需要我们解决,
1.状态的翻转
2.在一个状态里如何使pwm波的占空比实现逐增或逐减。
先说第一个问题,两个状态的翻转
由下面的时序图可以看出来,两个状态的翻转只是由时间决定的,S0状态和S1状态分别持续1s, 可以将它看成周期为2s 的时钟信号,每当flag_1s 信号到来一次,状态就翻转一次。
然后再来说第二个问题,在一个状态下如何实现PWM 波占空比逐增逐减的过程。
以S0状态下,LED 由灭渐亮,PWM 波占空比由百分之百逐渐减小至零为例:
我们发现让count2与count3比较,其结果clk_out 会出现这种占空比逐渐减小的结果。
此段代码如下:
1
TimeGen
flag_1s
state
于是,由反逻辑可以轻易知道在S1状态下,如何使其输出的clk_out占空比由小到大的方法,这样就可以实现LED 的由亮渐灭。
记:整个呼吸灯程序设计主要内容大致如此,末尾附上源代码及其仿真波形,以下为程序设计中我所遇到的问题,给可能出现同样问题的童鞋提供一些参考。
Q 1:
flag_1us尖峰脉冲信号,仿真出现如下波形:
注:在用modelsim仿真波形时,我为了加快仿真速度和方便查看波形,我将所有的count的计数最大值都改为了9。
当count1 计数10拍后,count2 波形从9 跳为0 ,但是仔细一看就会发现,count2 波形的9 跳为0 时,count1 只计数了一拍,中间少了9拍。
错误的代码如下:
修改后的代码:
加入那部分代码的意思是当(count2 == 9 & count1 == 9)时,count2 才计入下一拍。
正确的波形如下:
同理,在count3 归零时也应如此。
Q 2:flag_1ms 和flag_1s 两个尖峰脉冲信号,高电平保持时间不是一个时钟周期。
如下图所示:
这里介绍一个老师讲的技巧,让flag_1ms 的波形与flag_1us 的波形相与,就可以得到flag_1ms 的波形为一个时钟周期的尖峰脉冲。
代码如下:
关于呼吸灯的问题,我遇到的就是这些了,还有其他问题欢迎童鞋们补充交流。
附:仿真波形图
全局图附:源代码
module breathe_led(
input clk,
input rst_n,
output reg[3:0] led
);
parameter COUNT_MAX =10'd999;//
parameter COUNT_LIT =6'd45;
// parameter COUNT_LIT = 6'd9;
// parameter COUNT_MAX = 10'd9;
//
reg[5:0] count1;
reg[9:0] count2;
reg[9:0] count3;
wire flag_1ms;
wire flag_1s;
wire flag_1us;
reg state;
reg clk_out;
//count1
always@(posedge clk or negedge rst_n) begin
if(!rst_n)
begin
<=1'b0;
end
else begin
if(<)
begin
<=+1'b1;
end
else begin
<=6'd0;
end
end
end
assign=(==)?1'b1:1'b0;
//count2
always@(posedge or negedge)
begin
if(!)
begin
<=10'd0;
end
else begin
/* if(flag_1us)
begin
if(count2 == COUNT_MAX)
begin
count2 <= 10'd0;
end
else begin
count2 <= count2 + 1'b1;
end
end
else begin
count2 <= 10'd0;
end */
if(&<)
begin
<=+1'b1;
end
else if(==&==) begin
<=1'b0;
end
end
end
assign=(==)?(1'b1&):1'b0;
// count3
always@(posedge or negedge)
begin
if(!)
begin
<=10'd0;
end
else begin
/* if(flag_1ms)
begin
if(count3 == COUNT_MAX)
begin
count3 <= 10'd0;
end
else begin
count3 <= count3 + 1'b1;
end
end
else begin
count3 <= 10'd0;
end */
if(&<)
begin
<=+1'b1;
end
else if(==&==&==
)
begin
<=1'b0;
end
end
end
assign=(==)?(1'b1&):1'b0;
always@(posedge or negedge)
begin
if(!)
begin
<=1'b0;
<=1'b0;
end
else begin
case()
0:begin// led from low to high
if(<)
begin
<=1'b0;
end
else begin
<=1'b1;
end
if()
<=~;
else
<=;
end
1:begin// led from high to low
if(<)
begin
<=1'b1;
end
else begin
<=1'b0;
end
if()
<=~;
else
<=;
end
default:<=1'b0;
endcase
end
end
always@(posedge or negedge)
begin
if(!)
begin
<=4'b1111;
end
else begin
<={4{}};
end
end
// assign led = (!rst_n)?1'b0:{4{clk_out}}; endmodule。