001_雾盈FPGA笔记之一呼吸灯简单实验(Verilog)
呼吸灯实验报告
呼吸灯实验报告呼吸灯实验报告引言:呼吸灯是一种具有艺术性和实用性的装饰灯具,其灯光可以模拟人类呼吸的节奏,给人一种温馨、舒适的感觉。
本次实验旨在探究呼吸灯的工作原理、设计思路以及实际应用情况,进一步了解其在日常生活中的潜在价值。
一、实验设备和原理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实验报告引言:Verilog是一种硬件描述语言(HDL),用于设计和模拟数字电路。
它是一种高级语言,能够描述电路的行为和结构,方便工程师进行数字电路设计和验证。
本实验报告将介绍我在学习Verilog过程中进行的实验内容和所获得的结果。
实验一:基本门电路设计在这个实验中,我使用Verilog设计了基本的逻辑门电路,包括与门、或门和非门。
通过使用Verilog的模块化设计,我能够轻松地创建和组合这些门电路,以实现更复杂的功能。
我首先创建了一个与门电路的模块,定义了输入和输出端口,并使用逻辑运算符和条件语句实现了与门的功能。
然后,我创建了一个测试模块,用于验证与门的正确性。
通过输入不同的组合,我能够验证与门的输出是否符合预期。
接下来,我按照同样的方法设计了或门和非门电路,并进行了相应的测试。
通过这个实验,我不仅学会了使用Verilog进行基本门电路的设计,还加深了对逻辑电路的理解。
实验二:时序电路设计在这个实验中,我学习了如何使用Verilog设计时序电路,例如寄存器和计数器。
时序电路是一种具有状态和时钟输入的电路,能够根据时钟信号的变化来改变其输出。
我首先设计了一个简单的寄存器模块,使用触发器和组合逻辑电路实现了数据的存储和传输功能。
然后,我创建了一个测试模块,用于验证寄存器的正确性。
通过输入不同的数据和时钟信号,我能够观察到寄存器的输出是否正确。
接下来,我设计了一个计数器模块,使用寄存器和加法电路实现了计数功能。
我还添加了一个复位输入,用于将计数器的值重置为初始状态。
通过测试模块,我能够验证计数器在不同的时钟周期内是否正确地进行计数。
通过这个实验,我不仅学会了使用Verilog设计时序电路,还加深了对触发器、寄存器和计数器的理解。
实验三:组合电路设计在这个实验中,我学习了如何使用Verilog设计组合电路,例如多路选择器和加法器。
组合电路是一种没有状态和时钟输入的电路,其输出只取决于当前的输入。
ne呼吸灯实验报告
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的基本原理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)
实验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)
(原创)⽤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的呼吸灯
用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三色彩虹呼吸灯
[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了⽆数个版本,回滚了⽆数次,⼀遍⼀遍修改,最后才得到了你看到的这些代码.我的⽔平有限,所以就算如此⽂中的代码和讲解⼀定有所缺漏,还请希望⼤家多多包涵,并指出不⾜之处,改进这篇⽂章,来帮助更多的⼈.。
基于CPLDFPGA的呼吸灯效果实现(附全部verilog源码)
1. 讲废话而有时候,当我闲下来,默默凝视它的时候,又觉得它冷冰冰的,像个沉睡的宝宝。
在这个激情四射的年纪,我多想让每天陪伴我的“宝宝”能够有一份春意盎然的生机,让我感受她的呼吸,她的心跳。
咳咳。
此处省略9999个字。
说点正事儿,那就是如何让你的板子上那颗晶莹剔透的LED,摇身变成一个会呼吸的小精灵,像你智能手机上的呼吸灯一样,每一次闪烁都给你暖暖的感觉。
现在,电脑前的你,不要犹豫,果断的把下面的干货放到你的CPLD/FPGA里吧,瞬间实现你盼望已久的呼吸灯效果,赋予她(LED)生命的气息!2. 晒干货例化时,仅需要按您的需求修改代码中带★号的参数 ps. 只有一处需要修改哦亲/***************************************** Declaration ***************************************************File Name: breathe_led.vFunction: 实现呼吸灯功能Author: Bob LiuE-mail: shuangfeiyanworld@Version: V1.0Update: 2013-04-07************************************************************************ **********************************/module breathe_led(input clk,output reg led);parameter FREQUENCE=50_000_000; //★此默认值是基于50MHZ的系统时钟设置的,当您调用此呼吸灯模块的时候,// 仅仅需要将此值改为连接到clk端口上的实际频率值即可(这样使得呼吸一次的时间为2s),以下所有参数均不需改动;// 如果想加快呼吸速度,可减小此值,反之增大此值parameter WIDTH=9;reg [WIDTH:0] state0;reg [WIDTH-1:0] state1;//============================================= //控制每个占空比的持续时间//============================================= reg [31:0] cnt0;always @ (posedge clk)beginif(cnt0==(FREQUENCE/(2**WIDTH)))begincnt0<=0;state0<=state0+1'b1;endelsebegincnt0<=cnt0+1'b1;endend//============================================= //控制占空比增大与减小//============================================= always @ (posedge clk)beginif(state0[WIDTH])state1<=state0[WIDTH-1:0];elsestate1<=~state0[WIDTH-1:0];end//============================================= //生成与state1进行大小比较的计数器cnt1//============================================= wire [WIDTH-1:0] time_over;assign time_over={WIDTH{1'b1}};reg [WIDTH-1:0] cnt1;always @ (posedge clk)beginif(cnt1==time_over)begincnt1<=0;endelsebegincnt1<=cnt1+1'b1;endend//=============================================//计数器cnt1与state1进行大小比较,以使led脉冲的占空比实现渐变//=============================================always @ (posedge clk)beginif((cnt1+time_over/3)<=state1) //其实写成if(cnt1<=state1)即可实现led的渐亮与渐灭,但为了真实的模拟呼吸灯(可参考手机上的呼吸灯),//在此增加了time_over/3这个量,是为了使led呼吸一次之后保持1/3时间的熄灭状态led<=0; //led亮; 如果led高电平亮,此处改为led<=1;elseled<=1; //led灭; 如果led低电平灭,此处改为led<=0;endendmodule。
呼吸灯实验报告
一、实验目的1. 了解呼吸灯的工作原理和制作方法。
2. 掌握使用Arduino开发板、LED灯、电阻、电容等电子元件搭建呼吸灯电路的技能。
3. 通过调整电阻和电容的大小,研究呼吸灯的速度和亮度变化。
二、实验原理呼吸灯是一种利用PWM(脉宽调制)技术控制LED灯亮度的电路。
PWM技术通过改变信号的占空比来控制LED灯的亮度,占空比越高,LED灯越亮;占空比越低,LED灯越暗。
呼吸灯电路主要由Arduino开发板、LED灯、电阻、电容等元件组成。
三、实验器材1. Arduino开发板:1块2. LED灯:1个3. 电阻:2个(10kΩ、220Ω)4. 电容:1个(100μF)5. 面包板:1块6. 导线:适量四、实验步骤1. 搭建电路:将Arduino开发板、LED灯、电阻、电容等元件按照图1所示连接好。
2. 编写程序:在Arduino IDE中编写以下代码,实现呼吸灯效果。
```cppint ledPin = 9; // 定义LED灯连接的引脚int delayTime = 100; // 定义呼吸灯变化的时间间隔void setup() {pinMode(ledPin, OUTPUT); // 设置引脚模式为输出}void loop() {for (int brightness = 0; brightness <= 255; brightness += 5) {analogWrite(ledPin, brightness); // 设置PWM占空比,调整LED灯亮度delay(delayTime); // 等待一段时间}for (int brightness = 255; brightness >= 0; brightness -= 5) {analogWrite(ledPin, brightness); // 设置PWM占空比,调整LED灯亮度delay(delayTime); // 等待一段时间}}```3. 编译程序:将编写好的程序编译并上传到Arduino开发板。
呼吸灯实验报告
呼吸灯实验报告呼吸灯实验报告引言:呼吸灯是一种常见的电子装置,它能够模拟人类的呼吸节奏,给人一种温暖而舒适的感觉。
在本次实验中,我们将探索呼吸灯的工作原理、构造和应用,并通过实际搭建一个呼吸灯电路来验证其效果。
一、呼吸灯的工作原理呼吸灯的工作原理基于PWM(脉宽调制)技术。
PWM技术是一种通过改变信号的脉冲宽度来控制电路输出的技术。
在呼吸灯中,通过改变LED灯的亮度来模拟人类的呼吸节奏。
二、呼吸灯的构造呼吸灯主要由以下几个部分构成:电源、微控制器、LED灯和电阻。
电源提供电流给呼吸灯电路,微控制器控制LED灯的亮度变化,LED灯则负责发光,电阻用于限制电流。
三、呼吸灯的应用1. 装饰灯:呼吸灯的柔和的光线可以为室内环境增添温馨和浪漫的氛围,常被用于家庭装饰、商业场所和婚庆等场合。
2. 健康照护:呼吸灯的柔和光线可以帮助人们放松身心,缓解压力,对于失眠、焦虑和抑郁症等问题有一定的辅助疗效。
3. 儿童安抚:呼吸灯的呼吸效果可以模拟婴儿在母亲子宫中的安全感,对于儿童的安抚和入睡有一定的帮助。
四、呼吸灯的实验搭建1. 实验材料:面包板、LED灯、电阻、导线、Arduino开发板。
2. 实验步骤:a. 将LED灯和电阻连接到面包板上,连接方式为正极连接到Arduino的数字引脚,负极连接到电阻,电阻再连接到Arduino的GND引脚。
b. 将Arduino开发板连接到电脑,并打开Arduino IDE软件。
c. 编写代码,使用PWM技术控制LED灯的亮度变化,模拟呼吸效果。
d. 上传代码到Arduino开发板,观察LED灯的亮度变化,验证呼吸灯的效果。
五、实验结果与分析在实验中,我们成功地搭建了一个呼吸灯电路,并通过控制代码实现了呼吸效果。
LED灯的亮度随着时间的推移逐渐增加,再逐渐减小,循环往复,给人一种呼吸的感觉。
这种渐变的光线可以有效地调节环境氛围,给人带来一种舒适和放松的感觉。
六、实验总结通过本次实验,我们深入了解了呼吸灯的工作原理、构造和应用。
VerilogFPGA入门笔记(源于学习经验积累)
FPGA入门笔记(源于学习经验积累)17.verilog特点:区分大小写,所有关键字都要求小写不是强类型语言,不同类型数据之间可以赋值和运算//是单行注释可以跨行注释描述风格有系统级描述、行为级描述、RTL级描述、门级描述,其中RTL级和门级别与具体电路结构有关,行为级描述要遵守可综合原则门级描述使用门级模型或者用户自定义模型UDP来代替具体基本元件,在IDE中针对不同FPGA器件已经有对应的基本元件原语18.verlog语法要点:module endmodule之间由两部分构成:接口描述和逻辑功能描述IO端口种类:input output inout相同位宽的输入输出信号可以一起声明,input[3:0] a,b; 不同位宽的必须分开写内部信号为reg类型,内部信号信号的状态:0 1 x z,3'bx1=3'bxx1 x/z会往左扩展3'b1=3'b001 数字不往左扩展逻辑功能描述中常用assign描述组合逻辑电路,always既可以描述组合逻辑电路又可以描述时序逻辑电路,还可以用元件调用方法描述逻辑功能always之间、assign之间、实例引用之间以及它们之间都是并行执行,always内部是顺序执行常量格式:<+/-><二进制位宽><'><进制><该进制的数值>:默认进制为10进制默认位宽为32位位宽是从二进制宽度角度而言的由位宽决定从低位截取二进制数2'hFF=2'b11,通常由被赋值的reg变量位宽决定parameter常用于定义延迟和变量位宽,可用常量或常量表达式定义变量种类:wire reg memoryIO信号默认为wire类型,除非指定为reg类型wire可以用作任何输入输出端口wire包括input output inoutwire不带寄存功能assign赋值语句中,被赋值的信号都是wire类型assign之所以称为连续赋值,是因为不断检测表达式的变化reg类型可以被赋值后再使用,而不是向wire一样只能输出,类似VHDL中的buffer端口reg类型变量初始值为x (VHDL中初始值为本类型最小值,通常是0)always模块里被赋值的信号都必须定义为reg类型,因为always可以反复执行,而reg表示信号的寄存,可以保留上次执行的值reg类型变量与integer变量不同,即使赋负值,实质上也是按二进制无符号数存储的,integer是有符号数verilog中所有内部信号都是静态变量,因为它们的值都在reg中存储起来了memory型只有一维数组,由reg型变量组成memory初始化只能按地址赋值,不能一次性赋值1*256的memory写法:reg mema[255:0] mema[3]=0;不同位宽的变量之间赋值,处理之前都以被赋值的变量位宽为准扩展或截取A[a:b] 无论a b谁大,a总是实际电路的信号高位,b总是实际电路的信号低位算术运算中如果有X值则结果为Xfor循环中的变量另外定义成integer,因为它不是实际信号,有正负;reg则以无符号数存在== 和!=只比较0、1,遇到z或x时结果都为x (x在if中算做假条件),结果可能是1、0、x===和!==比较更加苛刻,包括x和z的精确比较,结果可能是0、1&&的结果只有1'b1或1'b0两种,A&A的结果位宽则是与A相同的{1,0}为64'h100000000,所以拼接运算中各信号一定要指定位宽移位运算左移将保留4'b1000<<1等于5'b10000,右移则舍弃4'b0011等于4'b0001数字电路里位运算应用普遍,包括按位逻辑运算、移位运算、拼接运算、缩减运算非阻塞式赋值<=与阻塞式赋值=阻塞:在同一个always过程中,后面的赋值语句要等待前一个赋值语句执行完,后面的语句被该赋值语句阻塞非阻塞:在同一个always过程中,非阻塞赋值语句是同时进行的,排在后面的语句不会被该赋值语句阻塞<=:块结束后才能完成赋值块内所有<=语句在always块结束时刻同时赋值<=右边各变量的值是上一次时钟边沿时,这些变量当时的值用于描述可综合的时序电路=:=语句结束之后过程always才可能结束在always过程中,begin end块内按先后顺序立即赋值,在fork join内同时赋值(可能造成冲突)与assign连用描述组合电路begin end中阻塞的含义:begin ...@(A) B=C...; end 如果A事件不发生则永远不能执行下去,被阻塞了由于时钟的延时(往往在ps级),多个always(posedge)之间究竟谁先执行是个未知数使用原则:同一个always过程块内建立时序电路用<=纯组合逻辑电路用=,生成的电路结构最简单,执行速度最快同一个always块内不要混用<=和=不要在多个always块内对同一个变量赋值(多源驱动)if else的三种形式,第三种形式适合描述优先编码器if条件中0/x/z当成假,1当成真,非0的数值也当成真case语句的三种:case(四种状态的比较) casez(忽略z) casex(忽略x和z,只看哪些位的信号有用)case语句中所有表达式值的位宽必须相等,default中不能将n'bx用'bx代替避免生成锁存器的方法:电平触发时if后加else case中加default ?使用casex会将不必要的状态视为无关项,使得综合出来的电路最简单两种特殊的括号:begin 顺序语句... end fork 并行语句... join,其差别在于块内语句的起止时间、执行顺序、相对延时块被命名后,其内部变量可以被调用,因为变量都是静态的(调用信号:对应电路中的一个信号线被引到另一处)initial块只无条件执行一次always块在满足条件时不断执行initial常用来写测试文件,always块常用来写电路描述always既可以描述组合逻辑电路又可以描述时序逻辑电路always如果后面有敏感信号列表则不能用wait语句always既可以描述电平触发又可以描述边沿触发,wait只能描述电平触发assign常用于描述组合逻辑电路测试文件中一般都是现initial 后always生成语句:生成快的本质是使用循环内的一条语句代替多条重复的verilog语句,简化了用户的编程genvar用于声明生成变量,生成变量只能用在生成快之间仿真时,仿真器会将生成块中的代码展平,在确立后的方针代码中,生成变量是不存在的最好是先想象出来循环生成语句被展平后的电路样子,再写相关的描述语句task和function的区别:task可以定义自己的仿真时间单位,function与主模块共用同一个仿真时间单位函数不能启动任务,任务能够启动函数函数至少要有一个输入变量,任务没有输入变量函数返回一个值,任务不返回值一个模块的设计包括3个部分:电路模块的设计测试模块的设计设计文档的编写设计者通过布局布线工具生成具有布线延迟的电路,再进行后仿真,得到时序分析报告从时序分析报告中可以知道电路的实际延迟t,同步电路内每个时钟周期要大于t,从而可确定该运算逻辑的最高频率综合器之所以能够实现加法器、乘法器是因为库中已经存在可配置的参数化器件模型FPGA内总线宽度容易自定义,以便实现高速数据流,三态数据总线相当于数据流的控制阀门数字系统内数据流的控制:开关(或三态数据总线)、数据暂存部件(寄存器)、同步状态机控制(整个系统在一个时钟域内)流水线操作pipe line:K级流水线就是从组合逻辑的输入到输出恰好有K个寄存器组,上一级的输出是下一级的输入流水线操作获得第一个结果的时间要比不用流水线操作的时间长,但以后结果获得时间都只需要一个时钟周期,提高了数据吞吐量流水线操作的保证:Tclk>K*(组合逻辑延迟+触发器的建立保持时间/触发时间),即时间片段要长于最大路径延迟体现了面积换速度的思想,在综合时考虑的是以面积小为主还是以速度为主本质上是一种同步逻辑同步时序逻辑和异步时序逻辑:同步时序逻辑指所有寄存器组由唯一时钟触发always@(posedge clk) 或always@(negedage clk)异步时序逻辑指触发条件不唯一,任意一个条件都会引起触发always@(posedge clk or posedage reset)目前的综合器是以同步时序逻辑综合的,因为同步时序逻辑较异步时序逻辑可靠严格的同步要求时钟信号传递速度远远大于各部分的延迟,实际中clk要单独用线,而不要经过反相器等部件always @(posedge.. ) begin ...<=... end 表示同步时序逻辑(同时刻赋值)不同速率数据接口的处理方法(异步数据的处理方法):帧同步FIFO 双端口RAM同步状态机:包括moore和mealy型两种,及其反馈模型(是一种反馈控制系统,当前状态就是其内部状态变量)状态机的开发步骤:根据实际问题列出输入输出变量和状态数画出状态图并化简写出状态转移真值表得到逻辑表达式用D触发器或JK触发器构建电路(目前用D触发器多)verilog描述时只需要得到简化的状态图就可以描述状态编码方式:独热码格雷码状态机主体程序有单always描述方式和多always描述方式采用case/casez/casex建立模型最好,因为x是无关态,生成的电路最简单default: state='bx与实际情况更一致,效果等同于default: state<=idle只有同步状态机才能被目前的综合for语句会将所有变量的情况展开,占用巨量逻辑资源,替代办法是用计数器和case语句说明所有情况有优先级的if else结构会消耗更多资源,建议用无优先级的case替代模块的复用往往比代码上修改节省的资源多PLL的分频、倍频、移相操作会增加设计精度同步时序电路的延时:#x通常用于仿真测试,实际硬件延时是:长延迟用计数器,小延迟用D触发器,此方法用来取代延迟链同步电路中,稳定的数据采用必须满足采样寄存器的建立和保持时间reg类型在always中不一定综合成时序电路,也可能是组合逻辑电路乒乓操作与作用异步时钟域同步问题延迟包括门延迟和线延迟组合逻辑产生的时钟仅能应用在时钟频率较低、精度要求不高的情况下增减敏感信号得到的结果一样补充部分:verilog HDL起初是作为写testbench而产生的verilog 有1995进入IEEE标准,为IEEE-1364, 于2001年进行了扩展,为IEEE 1364-2001;verilog AMS可用于模拟电路和数字电路的综合,目前正在不断发展和完善中;verilog的标识符区分大小写,关键字使用小写;用\\来进行单行注释,用\* *\来进行跨行注释;标识符由字母、数字、下划线构成,并以字母开头;关键字又叫保留字,只有小写的关键字才是保留字;信号的状态有4种:0 1 x zx和z在描述电路时不区分大小写,在仿真时大小写有不同意义;常量表达式中:x z不区分大小写;进制符号h o d b与H O D B不区分大小写;十六进制中a~f不区分大小写;下划线_用于提高可读性;?在数中可以代替z;x和z的左端补位;字符和字符串都以ASICII码形式存在,也可以当成电路内的信号;字符串必须包含在同一行,不能分成多行书写;如果表达式或者赋值语句中将字符串当成操作数,则字符串中的每个字符都被看成8位的ASCII值序列;可综合的信号类型:wire reg memory 它们用来描述数字电路不可综合的数据类型:integer real 它们只用仿真,位于testbench中wire是连线的抽象模型,不能保存数据,其值由驱动元的值决定;wire不能用在always或initial块中;wire的默认值为高阻z;wire的使用情形: 1.作为模块的输出端口2.用连续赋值语句assign赋值;reg是1位寄存器(触发器)的抽象模型,可以保存数据;reg必须用在always或initial块中;reg的默认值为x;reg的使用情形:1.阻塞赋值<= 2.非阻塞赋值=memory只能是一维的;memory只能对每个单元分别初始化,方法:1.一个一个赋值2. 通过系统任务$readmem赋值reg[3:0] fc;//一个4位寄存器reg fc[3:0] //4个一位寄存器parameter的作用:仿真开始以前对其进行赋值,整个仿真过程中保持其值不变;关系运算符将以逻辑1或逻辑0返回比较的结果;== !=的返回值有0 1 x三种情况,=== !==的返回值只有0 1两种情况;verilog由于是描述电路的,用于位的操作较多,有: 位逻辑操作,移位操作,并置操作,归约操作;位逻辑运算的结果中,位数与原操作数一样多;归约符是在原操作数的所有位上进行操作,并产生1位结果;并置运算可以发生在bit与bit之间bit与矢量之间矢量与矢量之间用于仿真的系统任务:所有系统任务都必须在initial或always内;所有系统任务都必须以$开头;常见系统任务:显示任务($diplay系列和$write系列)监控任务($monitor系列)探测任务($strobe系列)文件打开、输入、关闭任务(&fopen &fclose &fdisplay...)读取文件任务($readmemb $readmemh)仿真结束控制任务($finish $stop)随即信号任务($random)过程块:initial块和always块一个module内可以包含多个initial或always模块;所有initial或always块在0时刻开始并行执行,各initial或always块内部顺序执行;initial过程块主要是面向testbench的,通常不具有可综合性;always过程块在描述电路时既可以描述组合逻辑电路(电平敏感)又可以描述时序逻辑电路(边沿敏感);写testbench时initial通常用于初始化以及顺序波形的描述,always通常用于重复波形的描述;任务task与函数function: 为了描述模块中被多次执行的部分以及为了增强代码的易读性verilog中的高级程序语句如for循环语句只用在写testbench中;begin end和fork join是两种特殊的括号if语句的第三种形式适合描述优先编码器,case语句适合描述数据选择器和状态机;case的条件表达式如果与分支项表达式长度不同,则在比较前将所有表达式都统一为这些表达式的最长长度;casez忽略z,casex忽略z和x;assign语句只在右端表达式发生变化时才重新计算并重新赋值,其余时间都是连续赋值;assign语句可以指定bit、vector或是任意拼接操作的结果;assign语句是连续赋值的,用于驱动网线wire,reg类型不需要连续赋值,reg 类型一旦被赋值就会一直保存;过程赋值语句有两种:阻塞式=和非阻塞式<=,只能在过程块initial和always中使用;@对事件触发的控制与wait语句不能同时使用;FPGA学习心得(二)V erilog的两个误区:使用Reg类型还是Net类型:Reg类型只在过程块中被赋值;而Net类型则在过程块外面被赋值或者驱动. 阻塞赋值和非阻塞赋值:V erilog中竞争发生的条件:两个或多个语句在执行顺序不同时导致不同的结果,则存在竞争.Nonblocking不是一个类型;Blocking赋值是一个单步过程,计算RHS,并更形LHS是不可中断的.七条准则:1.时序逻辑和锁存器,使用非阻塞赋值2.always块中的组合逻辑,使用阻塞赋值3.同一always块,时序组合混合逻辑使用非阻塞赋值4.通常情况下,在同一always块中不要混合使用阻塞与非阻塞赋值5.不要在多个always块中对同一变量进行赋值6.使用$strobe显示非阻塞赋值得信号7.不要用#0的过程赋值V erilog中的分层事件队列:活动事件:阻塞赋值;计算非阻塞赋值的RHS;连续赋值;$display命令;计算输入并改变原语的输出.这些事件可能按照任意次序调度.非活动事件:#0的阻塞赋值非阻塞事件:更新非阻塞赋值的LHS监视事件:$monitor命令;$strobe命令经验:在always块中使用非阻塞赋值来产生时序逻辑和锁存器在always块中使用阻塞赋值来产生组合逻辑在always块中使用非阻塞赋值来产生同一块中的时序和组合逻辑在纯组合逻辑中使用非阻塞赋值可能会导致功能错误阻塞赋值和非阻塞赋值混合使用的方式:将组合逻辑赋值通过时序表达式表示或者将组合逻辑赋值与时序逻辑分开,在独立的语句块中描述不推荐在同一always块中混合使用阻塞和非阻塞赋值几个关于非阻塞赋值的错误理解:错误1:无法使用$display命令显示非阻塞赋值变量正解:非阻塞赋值变量的更新在所有$display命令之后错误2:#0让一个赋值在每个时间步的最后执行正解:#0只会让赋值语句进入非活动事件队列错误3:在同一always块中对同一变量进行多次非阻塞赋值是不允许的正解:在IEEE 1364 verilog标准中定义了上述赋值,最后一个非阻塞赋值起作用模拟开始时候的困难:不同的模拟器,不同的模拟选项导致开始模拟时现象不同建议: 在0时刻通过非阻塞赋值设置reset信号;第一个半周期设置clock为0编写V erilog代码的一些经验:V erilog文件名和模块名相同不要在可综合代码中使用casex语句当在可综合代码中使用casez语句时要小心当写case语句时,对存在不关心的cases时使用casez,使用?代替Z来表示不关心的casesV erilog编写状态机相关:状态机分类:Moore(输出只与当前状态相关)和Mealy(输出与当前状态和输入相关)二进制编码和One-Hot编码状态机的基本块:下一状态度组合逻辑;时钟同步的当前状态逻辑;输出组合逻辑两个always块写状态机,使用三个always块,如果输出需要寄存使用高效的One-Hot状态编码,组合输出经验:每个状态机作为一个独立的V erilog模块对状态进行预定义,状态赋值使用状态名作参数,不要使用`define,多使用parameter两个always语句块的状态机,一个always用来描述状态向量寄存器的时序逻辑.一个用来描述下一状态度组合逻辑.组合输出可以通过连续赋值语句或者在下一状态度组合always块中描述.verilog语法规则1.V erilog分以下四个层次:l 低阶交换模型:电路由开关与储存点所组成l 逻辑间层次描述:用and ,or, buf , not 等l 资料处理模型或暂存器转移层次:用于说明资料如何在暂存器中储存与传送。
基于PWM的呼吸灯设计(Verilog版)
基于PWM的呼吸灯设计(Verilog版)module Breath_Led(clk,rst,led);input clk,rst;output reg led;reg[19:0] count;reg[19:0] duty_cycle;always @(posedge clk)beginif(!rst)beginled<=1'b0;count<=1'b0;endelsebeginif(count<20'd999_999)begincount<=count+1'b1;if(count<duty_cycle)led<=1'b1;elseled<=1'b0;endelsecount<=1'b0;endendreg flag;always @(posedge led)beginif(!rst)beginduty_cycle<=1'b1;flag<=1'b0;endelsebeginif(flag==1'b0)beginif(duty_cycle<20'd979_511)beginduty_cycle<=duty_cycle+15'd9990;flag<=1'b0;endelsebeginduty_cycle<=duty_cycle-15'd9990;flag<=1'b1;endendelsebeginif(duty_cycle>1'b1)beginduty_cycle<=duty_cycle-15'd9990;flag<=1'b1;endelsebeginduty_cycle<=duty_cycle+15'd9990;flag<=1'b0;endendendendendmodule记录⾃⼰写的呼吸灯⼩程序,程序未经重构,总体较粗糙,望看官见谅。
《FPGA设计与应用》pwm实现呼吸灯实验
《FPGA设计与应用》pwm实现呼吸灯实验1实验目的1.学习动态数码管的工作原理;2.实现 FPGA 对四位动态数码管的控制;3.熟悉模块化编程的操作流程。
2实验内容1.实现 FPGA 对四位动态数码管的控制,使其能够正常工作;2.时钟计数。
3.按键控制4.时钟分频5.扫描显示3操作方法与步骤1.启动软件,构造开发环境2.建立新项目3.设置参数4.编写源程序5.编辑代码6.运行检验7.仿真;4实验方案及实现1、秒表的设计共分 3 个模块:(1)、数码管显示模块(2)、计时模块(3)、顶层模块数码管显示模块程序即上述实验五中的数码管封装模块,请同学自行参考并编写。
计时模块module time_counter(clk,key1,rst,data);input clk;input key1;input rst;output [15:0] data;reg [15:0] data;reg clk_1Hz;integer clk_1Hz_cnt;if(clk_1Hz_cnt==32'd2*******-1)begin clk_1Hz_cnt <= 1'b0;clk_1Hz <= ~clk_1Hz;endelseclk_1Hz_cnt <= clk_1Hz_cnt + 1'b1;reg[3:0] time_1=0,time_10=0,time_100=0,time_1000=0; always@(posedge clk_1Hz)beginif(rst) begintime_1<=0;time_10<=0;time_100<=0;time_1000<=0;data[15:0] <={time_1000,time_100,time_10,time_1};endelsebeginif(key1==0)beginIf(time_1 < 4'b1001)begintime_1 <= time_1+1'b1;data[15:0] <={time_1000,time_100,time_10,time_1}; endElse if(time_10 < 4'b1001)begintime_10 <= time_10+1'b1;time_1 <= 4'b0000;data[15:0] <={time_1000,time_100,time_10,time_1};endelse if(time_100 < 4'b1001)begintime_100 <= time_100+1'b1;time_10 <= 4'b0000;time_1 <= 4'b0000;data[15:0] <={time_1000,time_100,time_10,time_1};endelse if(time_1000 < 4'b1001)beginTime_1000<=time_1000+1’b1time_100 <= 4'b0000;time_10 <= 4'b0000;time_1 <= 4'b0000;data[15:0] <={time_1000,time_100,time_10,time_1};endElsebegintime_1000 <= 4'b0000;time_100 <= 4'b0000;time_10 <= 4'b0000;time_1 <= 4'b0000;data[15:0] <={time_1000,time_100,time_10,time_1};endElse andbegintime_1000 <= time_1000;time_100 <= time_100;time_10<= time_10;time_1<= time_1;data[15:0] <={time_1000,time_100,time_10,time_1}; endEndEndEndmodule顶层模块module mb(clk,key1,rst,sm_wei,sm_duan);input clk;input key1;input rst;output [3:0]sm_wei;output [7:0]sm_duan;wire [15:0]data;wire [3:0]sm_wei;wire [7:0]sm_duan;time_counter U0 (.clk(clk),.rst(rst),.key1(key1),.data(data)); smg_ip_model U1(.clk(clk),.data(data),.sm_wei(sm_wei),.sm_duan(sm_duan)); endmodule一. 实验结果Vivado仿真:上实验板现象:二. 实验心得程序的设计、软件的仿真还是上板子的实操都比第一次熟练了很多,在实验中学习动态数码管的工作原理。
基于FPGA的呼吸灯
用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。
呼吸灯的实验报告
呼吸灯的实验报告呼吸灯的实验报告引言:呼吸灯是一种常见的电子装置,通过控制LED灯的亮度逐渐增加和减小,模拟人的呼吸过程。
本实验旨在通过搭建呼吸灯电路,理解呼吸灯的工作原理,并探索不同元器件对呼吸灯效果的影响。
实验步骤:1. 准备材料:LED灯、电阻、电容、开关、面包板、导线等。
2. 搭建电路:将LED灯、电阻和电容连接在面包板上,使用导线连接各个元器件。
3. 连接电源:将电路连接到电源上,确保电路能正常工作。
4. 调试电路:通过改变电阻和电容的数值,观察呼吸灯的效果变化。
5. 记录观察结果:记录不同参数下的呼吸灯效果,包括亮度变化的速度和幅度。
实验结果:在实验中,我们发现改变电阻和电容的数值会对呼吸灯的效果产生影响。
当电阻较大或电容较小时,呼吸灯的亮度变化速度较慢,呼吸效果不明显;而当电阻较小或电容较大时,呼吸灯的亮度变化速度较快,呼吸效果更加明显。
此外,我们还发现改变LED灯的颜色和亮度也会对呼吸灯的效果产生影响,不同颜色和亮度的LED灯呈现出不同的呼吸效果。
讨论:通过本次实验,我们深入了解了呼吸灯的工作原理和影响因素。
呼吸灯的实现依赖于电容的充放电过程,当电容充电时,LED灯逐渐变亮;当电容放电时,LED灯逐渐变暗。
电阻的大小决定了充放电的速度,电容的大小则决定了充放电的幅度。
因此,通过调整电阻和电容的数值,可以改变呼吸灯的效果。
此外,LED灯的颜色和亮度也会对呼吸灯的效果产生影响。
不同颜色的LED灯在充放电过程中呈现出不同的亮度变化,例如红色LED灯在变暗时会呈现出橙色的效果。
而LED灯的亮度则决定了呼吸灯的明暗程度,较高亮度的LED灯呼吸效果更加明显。
结论:通过本次实验,我们成功搭建了呼吸灯电路,并观察到了不同参数下呼吸灯的效果变化。
我们发现电阻和电容的数值、LED灯的颜色和亮度都会对呼吸灯的效果产生影响。
这些发现对于设计和调试呼吸灯电路具有重要意义,可以根据实际需求选择合适的元器件参数,以达到理想的呼吸效果。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
基于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。