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*500000
    parameter 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)
   begin
    if(rst_n==1'b0)
        begin
        CLK_10MS <='d0;
        end
    else if(CLK_10MS==CLK_10ms) CLK_10MS <='d0;
    else begin
        CLK_10MS <= CLK_10MS+1'b1;
    end
   end
    
    /*-----2s计数器----*/
    always @(posedge clk or negedge rst_n)
    begin
        if(rst_n==1'b0) Times2s <='d0;
       else if(CLK_10MS==CLK_10ms)begin
                if(Times2s==Times_2s) Times2s <='d0;
                else Times2s <= Times2s+1'b1;          
        end
    end
    
    //-------亮灭状态管理切换----
     always @(posedge clk or negedge rst_n)
     begin
        if(rst_n==1'b0) 
            changeflag <= 'b0;
        else if(Times2s==ChangeTime && CLK_10MS==CLK_10ms)
        begin
            changeflag <= 1'b1;//状态改为:从亮到灭
        end
        else if(Times2s==Times_2s && CLK_10MS==CLK_10ms)
        begin
            changeflag <= 1'b0;//状态改为:从灭到亮
        end
     end
     
     //-----占空比调节
     always @(posedge clk or negedge rst_n)
     begin
        if(rst_n==1'b0)dutyCycle='d0;
        else if(changeflag==1'b0)
        begin
            if(CLK_10MS==CLK_10ms) dutyCycle <= dutyCycle+pwm_offset;
            else dutyCycle <= dutyCycle;
        end
        else if(changeflag ==1'b1)
        begin
            if(CLK_10MS==CLK_10ms) dutyCycle <= dutyCycle-pwm_offset;
            else dutyCycle <= dutyCycle;
        end
     end
     
        
     always @(posedge clk or negedge rst_n)
     begin
        if(rst_n==1'b0) pwm <= 1'b0;
        else if(CLK_10MS < dutyCycle) pwm <= 1'b0;
        else pwm <= 1'b1;
     end
    
endmodule

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*500000
    parameter 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;
    #10
    rst_n=1'b1;
 end
     always #(10) clk=~clk;

endmodule

  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值