ZYNQ学习笔记(六)---呼吸灯实验

这两天做了呼吸灯实验,今天和大家分享一下。我们采用PWM脉冲宽度调制输出连续的、占空比变化的脉冲信号来实现LED由灭到亮,再由亮到灭。

1.呼吸灯的原理

首先我们要知道,影响呼吸灯亮灭有2个因素:1.PWM波的占空比;2.PWM波的周期。

需要两者配合,方能实现效果较佳的呼吸灯。

我们假设占空比为50%,周期为2s,那么我们看到的就是LED亮一秒,灭一秒。但是如果我们把周期缩小到10ms,占空比仍然是50%。由于人眼的视觉残留效应,那么我们看见的就是LED的亮度会低一些,并不会出现亮一会灭一会的情况。

所以,根据上述分析,我们可以把PWM波的周期缩小到一个很小的值(比如10ms),然后让占空比每个周期都产生变化。(比如:从灭到亮时,每10ms占空比增加1%,增加到100%时再每10ms占空比减小1%,实现从亮到灭。这样整个亮灭过所需时间就是2s=10ms*100+10ms*100。)

2.源文件

首先我们需要两个计数器,一个10ms计数,另一个其实只要统计10ms的次数,200次就是2s。

然后因为在1s时我们需要将状态从灭到亮改为从亮到灭,所以我们需要一个用来切换状态的标志位及相应代码。

剩下就是占空比的调节和pwm的输出。

占空比在相应状态下,通过每次步进5000的计数值来每10ms改变一次1%的占空比;另外,我们要注意到PWM的信号输出应该和10ms计数器同步,10ms计数值小于dutycycle时,pwm输出0。反之,输出1。

`timescale 1ns / 1ps
module BreathLed(clk,rst_n,led);input wire clk;input wire rst_n;output wire led;//定义一些常量,时钟主频50M,计满10ms需要计数50_0000次,计数满2s,只要重复200次即可parameter CLK_10ms = 500000-1;parameter Times_2s = 200-1;parameter ChangeTime =100-1;//每次占空比改变整个周期的1%,0.01*500000parameter pwm_offset = 5000;//需要两个计数器,一个工作状态改变标志位reg [19:0] CLK_10MS;reg [7:0] Times2s;reg pwm;reg [19:0] dutyCycle;reg changeflag;assign led = ~pwm;/*--------10ms计数器---*/always @(posedge clk or negedge rst_n)beginif(rst_n==1'b0)beginCLK_10MS <='d0;endelse if(CLK_10MS==CLK_10ms) CLK_10MS <='d0;else beginCLK_10MS <= CLK_10MS+1'b1;endend/*-----2s计数器----*/always @(posedge clk or negedge rst_n)beginif(rst_n==1'b0) Times2s <='d0;else if(CLK_10MS==CLK_10ms)beginif(Times2s==Times_2s) Times2s <='d0;else Times2s <= Times2s+1'b1;          endend//-------亮灭状态管理切换----always @(posedge clk or negedge rst_n)beginif(rst_n==1'b0) changeflag <= 'b0;else if(Times2s==ChangeTime && CLK_10MS==CLK_10ms)beginchangeflag <= 1'b1;//状态改为:从亮到灭endelse if(Times2s==Times_2s && CLK_10MS==CLK_10ms)beginchangeflag <= 1'b0;//状态改为:从灭到亮endend//-----占空比调节always @(posedge clk or negedge rst_n)beginif(rst_n==1'b0)dutyCycle='d0;else if(changeflag==1'b0)beginif(CLK_10MS==CLK_10ms) dutyCycle <= dutyCycle+pwm_offset;else dutyCycle <= dutyCycle;endelse if(changeflag ==1'b1)beginif(CLK_10MS==CLK_10ms) dutyCycle <= dutyCycle-pwm_offset;else dutyCycle <= dutyCycle;endendalways @(posedge clk or negedge rst_n)beginif(rst_n==1'b0) pwm <= 1'b0;else if(CLK_10MS < dutyCycle) pwm <= 1'b0;else pwm <= 1'b1;endendmodule

3.Testbench代码

/*-------testbench编写基本流程------*/
//* module Test_bench(); 
//通常无输入出 通常无输入出//信号或变量声明定义//逻辑设计中输入对应 reg型//逻辑设计中输出对应 wire 型//使用 initial  或 always语句产生激励 语句产生激励//例化待测试模块//监控和比较输出响应
//module BreathLed_simul();//变量和信号的声明reg clk;reg rst_n;wire led;parameter CLK_10ms = 500000-1;parameter Times_2s = 200-1;parameter ChangeTime =100-1;//每次占空比改变整个周期的1%,0.01*500000parameter pwm_offset = 5000;//例化一个我们之前写的模块
BreathLed #(.CLK_10ms(CLK_10ms),.Times_2s(Times_2s),.ChangeTime(ChangeTime),
.pwm_offset(pwm_offset)) 
u1(          .clk(clk),.rst_n(rst_n),.led(led)
);
initial
begin
//初始化激励(时钟和复位信号)clk=1'b0;rst_n=1'b0;#10rst_n=1'b1;endalways #(10) clk=~clk;endmodule


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部