[FPGA入门笔记](二):LED呼吸灯实验

1、简介

今天购买了AXLINX AX7020的开发板,从今天开始每一个例程都要做文档记录,为自己加油。
本实验,基于ALINX AX7020开发板,芯片为xc7z020clg400-2。

项目介绍:
呼吸灯,就是想人们呼吸频率的一种led灯亮灭的一种表现形式。过程是慢慢变亮,然后变亮以后又慢慢变灭的一种过程。很多初学者会认为硬件逻辑语言怎么能控制电流的高低呢,让灯有多亮就调多亮,所以觉得不好实现,其实不用担心,呼吸灯捅破窗户纸就知道,其实是一个很简单的一个小项目,下面我将一步一步的讲解,并且实现。
PWM(Pluse Width Modulation)脉冲宽度调制,是一种对模拟信号电平进行数字编码的方法。
需要回顾一下占空比的小知识,通过高分辨率计数器的使用,方波的占空比被调制用来对一个具体模拟信号的电平进行编码。并广泛应用在从测量、通信、功率控制与变换及LED照明等许多领域中。顾名思义,就是占空比可调的信号,那么什么是占空比呢?
占空比(Duty Cycle or Duty Ratio),可以解释为,在一脉冲序列中(方波),正脉冲序列的持续时间与脉冲总周期的比值。也可理解为,电路释放能量的有效时间与总释放时间的比值。PWM是怎样实现调光呢?想要调节LED的亮度变化,实则是调节控制流经LED的电流。电流增大则LED亮度增强,反之减弱。但由于电流为模拟信号,所以这时就用到了PWM。
[FPGA入门笔记](二):LED呼吸灯实验_第1张图片
假设刚开始时占空比为1%,慢慢的占空比为2%、3%、4%……56%、57%……98%、99%、100%。
这就是LED灯亮的一个过程,我们可以让占空比为1%时,令LED灯亮,其余的部分让LED灭,慢慢的占空比越来越大,亮的部分也越来越多,这就是一个由灭到亮的一个过程。
假设刚开始时占空比为100%,慢慢的占空比为99%、98%、97%……64%、63%……2%、1%、0%。
这就是LED灯灭的一个过程,我们可以让占空比为99%时,令LED灯灭,其余的部分让LED亮,慢慢的占空比越来越小,灭的部分也越来越多,这就是一个由亮到灭的一个过程。
[FPGA入门笔记](二):LED呼吸灯实验_第2张图片
时钟只对着2us计数的一个时钟周期的;比如说晶振为50MHZ,那么每一个时钟周期相当于1/50M=20ns,故第一个计数器为一个2us的计数器,每计100次之后清零;第二个计数器为1ms计数器,每当2us计数器计数100次时,1ms就会增加一次。同理1s计数器也是一样。
将1s分成1000份,每一个周期为1ms,前500份由暗变亮,后500份由亮变暗
将1ms分成500份,每一个周期为2us,
将2us分成100份,每一份为20ns

我们可以看出,当cnt_1s>=cnt_1ms的部分刚好是我们上面所说的占空比的位置,而且当cnt_1s加到499的时候刚好占空比为100%,所以我们就会多了一个条件,当cnt_1s>=cnt_1ms,我们让LED亮,cnt_1s

一个完整的呼吸灯时间为1s,也就是,由亮变暗需要0.5s,由暗变亮需要0.5s;将 1s分为1000等份,也就是由亮变暗,需要500次的变化,每次为1ms,将,1ms分为500等份,占空比100%过渡到0%,需要100次的变化,每次为2us;

`timescale 1ns/1ps
module pwm_led(
    input           clk,
    input           rst_n,
    output [3:0]    leds_o
    );
    
    reg     [9:0] cnt_2us;  //将2us分成100份,每一份为20ns(50MHz);
    reg     [9:0] cnt_1ms;  //将1ms分成500份,每周期为2us;
    reg     [9:0] cnt_1s;   //将1s分成1000份,每周期为1ms,前500由暗变亮,后500由亮边暗
    reg           flag;
    reg           pwm;
    //生成一周期2us,1/50MHz=20*10-9=20ns,20ns*100=2us
    always@(posedge clk or negedge rst_n)
    begin
        if(!rst_n)
            cnt_2us <= 10'd0;
        else    begin
        if(cnt_2us>=10'd100)
            cnt_2us <= 10'd0;
        else
            cnt_2us <= cnt_2us+1'b1;
            end
    end
    
    //生成一周期1ms,2us*500=1ms,
    always@(posedge clk or negedge rst_n)
    begin
        if(!rst_n)
            cnt_1ms <= 10'd0;
        else    begin
            if(cnt_2us==10'd99 && cnt_1ms==10'd499)
                cnt_1ms <= 10'd0;
            else 
                if(cnt_2us==10'd99)
                cnt_1ms <= cnt_1ms+1'b1;
            end
    end
   //生成一周期1s,1ms*500+1ms*500=1s;
    always@(posedge clk or negedge rst_n)
    begin
        if(!rst_n)
            cnt_1s <= 10'd0;
        else    begin
            if(cnt_2us==10'd99 && cnt_1ms==10'd499 && cnt_1s==10'd499)
                cnt_1s <= 7'd0;
            else 
                if(cnt_2us==10'd99 && cnt_1ms==10'd499)
                cnt_1s <= cnt_1s+1'b1;
            end
    end
    //使用flag信号来控制亮暗变化;
    always@(posedge clk or negedge rst_n)
    begin
        if(!rst_n)
            flag <= 1'b0;
        else if(cnt_1s==10'd499 && cnt_1ms==10'd499 && cnt_2us == 10'd99)
            flag <= ~flag;
            else
            flag <= flag;
    end
    
    always@(posedge clk or negedge rst_n)
    begin
        if(!rst_n)
            pwm <= 1'b0;  
        else if(flag == 1'b0 && cnt_1s >= cnt_1ms)
            pwm <= 1'b1;
        else if(flag == 1'b0 && cnt_1s < cnt_1ms)
            pwm <= 1'b0;
        else if(flag == 1'b1 && cnt_1s >= cnt_1ms)
            pwm <= 1'b0;
        else if(flag == 1'b1 && cnt_1s < cnt_1ms)
            pwm <= 1'b1;
        else
            pwm <= 1'b0;
    end

    assign leds_o = {4{!pwm}};//开发板LED为低有效
    

endmodule

测试代码为:

`timescale 1ns/1ps
module tb_pwm_led;
    reg         clk;
    reg         rst_n;
    wire [3:0]  leds_o;

    always #10 clk=~clk;

    initial
        begin
            clk = 1'b0;
            rst_n = 1'b0;
            #100 rst_n = 1'b1;
        end

    pwm_led uut(
        .clk(clk),
        .rst_n(rst_n),
        .leds_o(leds_o)    
        );
endmodule

仿真结果为:
[FPGA入门笔记](二):LED呼吸灯实验_第3张图片

同理大家可以尝试更改一下代码,实现
将1s分成1000份,每一个周期为1ms,前500份由暗变亮,后500份由亮变暗
将1ms分成500份,每一个周期为2us,
将2us分成100份,每一份为20ns

将2s分成1000份,每一个周期为2ms,前500份由暗变亮,后500份由亮变暗
将2ms分成500份,每一个周期为4us,
将4us分成200份,每一份为20ns

将4s分成2000份,每一个周期为2ms,前1000份由暗变亮,后1000份由亮变暗
将2ms分成1000份,每一个周期为2us,
将2us分成100份,每一份为20ns

将2s分成2000份,每一个周期为1ms,前1000份由暗变亮,后1000份由亮变暗
将1ms分成1000份,每一个周期为1us,
将1us分成50份,每一份为20ns

你可能感兴趣的:(FPGA入门笔记,fpga,芯片)