FPGA学习altera 系列 第二十篇 呼吸灯设计

今天给大侠带来“FPGA学习系列 altera"系列,持续更新。此学习心得是本人之前所写,所用设计软件为Quartus II 13.1,现Quartus II 新版本已更新到19+,以下仅供初学者学习参考。后续会更新其他系列,敬请关注。话不多说,上货。

 

 

对于每一个的小实验,我们都可以把它看作是一个小项目,逐步的去分析,设计,调试,最后完成功能。下面我们就开始我们的“小项目”。

项目名称:呼吸灯

具体要求:led灯在由亮到暗以及由暗到亮的逐渐变化。

项目分析: 

1. 要求分析

灯光在微电脑的控制之下完成由亮到暗的逐渐变化,感觉好像是人在呼吸。根据不同人群以及不用情况下的呼吸频率不同,笔者这里采取一分钟呼吸15次,呼气2秒钟,吸气2秒钟。

2. 实现原理

由于LED的亮度与流过的电流成正比,如果能够去控制流经LED的电流,使电流在2秒钟内从i=0A(0A:0安培)逐渐递增到i=XA(XA:一定的电路强度),就实现了LED的由暗到亮的逐渐变化;使电流在2秒钟内从i=XA逐渐递增到i=0A就实现了LED的由亮到暗的逐渐变化。以此为周期,不断地变化下去,就实现了呼吸灯的功能。

在数字电路中,控制电流的大小几乎是不能实现的。如果将LED在T/2内点亮,将LED在T/2内熄灭,我们会看到什么呢?人的眼睛有视觉暂留(人眼在观察景物时,光信号传入大脑神经,需经过一段短暂的时间,光的作用结束后,视觉形象并不立即消失,这种残留的视觉称“后像”,视觉的这一现象则被称为“视觉暂留”),若T的时间足够短,那么将会看到一直亮着的LED,亮度由点亮的时间所占T的比例决定的。

3. 实现方案

一分钟呼吸15次,呼气2秒钟,吸气2秒钟。我们先做由暗到亮,将2秒钟分成1000个时间段,每个时间段2ms。第一个时间段全部熄灭;第二个时间段2us的时间点亮,其余时间熄灭;第三个时间段4us的时间点亮,其余时间熄灭······

每个时间段为2ms,相邻两个时间段增加2us,可以理解为点亮的比例每个时间段增加千分之一。这样的话,就可以完成由暗到亮。将上述的输出波形取反,就是点亮的比例每个时间段减少千分之一,完成由亮到灭。

 

 

架构图如下:

FPGA学习altera 系列 第二十篇 呼吸灯设计_第1张图片

 

系统设计:

1. 工程的名称:breathe_led

2. 实现方法:用计数器1实现2us的计时,用计数器1驱动计数器2,实现2ms的计数。用计数器1和计数器2驱动计数器3,实现2s的计数。用计数器2和计数器3进行比较,来完成占空比的调节。计数器3每增加1,计数器2都会从0增加到999,如果将计数器3数值大于计数器2数值的时间段,当作点亮的时间,那么就可以实现由暗到亮的过程了。

 

 

设计代码如下:

/*模块名称:breathe_led模块功能:呼吸灯 作者:郝旭帅邮箱:[email protected]*/module breathe_led (clk, rst_n, led);  input clk;//50MHz,周期为20ns  input rst_n;  output led;  parameter T2us = 100;  parameter T2ms = 1000;  parameter T2s = 1000;  reg [6:0] cnt1;//2us的计数器  always @ (posedge clk or negedge rst_n)    begin      if (!rst_n)        begin          cnt1 <= 7'd0;        end      else        begin          if (cnt1 < T2us - 1)            begin              cnt1 <= cnt1 + 1'b1;            end          else            begin              cnt1 <= 7'd0;            end        end    end  wire flag;//计时到2us时,产生一个同步脉冲  assign flag = (cnt1 == T2us - 1) ? 1'b1 : 1'b0;  reg [9:0] cnt2;//2ms计数器  always @ (posedge clk or negedge rst_n)    begin      if (!rst_n)        begin          cnt2 <= 10'd0;        end      else        begin          if ((cnt2 < T2ms - 1)&&(flag))            begin              cnt2 <= cnt2 + 1'b1;            end          else            begin              if (flag)                begin                  cnt2 <= 10'd0;                end              else                begin                  cnt2 <= cnt2;                end            end        end    end  reg [9:0] cnt3;//2s的计数器  reg change;//控制占空比由大变小或者由小变大  always @ (posedge clk or negedge rst_n)    begin      if (!rst_n)        begin          cnt3 <= 10'd0;          change <= 1'b0;        end      else        begin        if ((cnt3 < T2s - 1)&&(cnt2 == T2ms - 1) && (flag))            begin              cnt3 <= cnt3 + 1'b1;            end          else            begin              if ((cnt2 == T2ms - 1) && (flag))                begin                  change <= ~change;                  cnt3 <= 10'd0;                end              else                begin                  cnt3 <= cnt3;                end            end        end    end  reg led_n;  always @ (posedge clk or negedge rst_n)    begin      if (!rst_n)        begin          led_n <= 1'b0;        end      else        begin          if (cnt3 > cnt2)            begin              led_n <= 1'b0;            end          else            begin              led_n <= 1'b1;            end        end    end  assign led = (change == 1) ? ~led_n : led_n;endmodule

代码解析:

1. assign led = (change == 1) ? ~led_n : led_n;

代表:当change=1时,led=~led_n,当change=0时,led=led_n。

2. cnt2清零时,必须等待flag。如果没有flag,那么cnt2的最后一个数值将只会存在一个周期。cnt3同理。

3. 当cnt3计时到最后一刻时,将change取反,输出的占空比变化情况发生改变。

 

 

激励代码如下:

/*模块名称:breathe_led_tb模块功能:为breathe_led模块提供激励信号作者:郝旭帅邮箱:[email protected]*/`timescale 1ns/1psmodule breathe_led_tb;  reg clk;  reg rst_n;    wire led;  parameter T2us = 2;//仿真时,时间缩短  parameter T2ms = 5;  parameter T2s = 5;  initial begin    clk = 1'b1;    rst_n = 1'b0;    # 200.1    rst_n = 1'b1;    # 3000    $stop;  end    always # 10 clk = ~clk;//50MHz    breathe_led    #(      .T2us(T2us),//传递仿真参数      .T2ms(T2ms),      .T2s(T2s)    )    breathe_led_dut(      .clk(clk),       .rst_n(rst_n),      .led(led)    );    endmodule

 

仿真波形如下:

FPGA学习altera 系列 第二十篇 呼吸灯设计_第2张图片

 

led的占空比从大到小,再从小到大,一直不断地变化下去。

如果设计要求或者本地晶振与笔者的设计不同,请自行更改设计,以保证设计的正确性。如果还是有不明白的读者可以发邮件到我邮箱或者加群询问。

你可能感兴趣的:(FPGA学习系列)