前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >FPGA学习altera 系列 第二十篇 呼吸灯设计

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

作者头像
FPGA技术江湖
发布2020-12-29 17:28:11
8490
发布2020-12-29 17:28:11
举报
文章被收录于专栏:FPGA技术江湖FPGA技术江湖

大侠好,欢迎来到FPGA技术江湖,江湖偌大,相见即是缘分。大侠可以关注FPGA技术江湖,在“闯荡江湖”、"行侠仗义"栏里获取其他感兴趣的资源,或者一起煮酒言欢。

今天给大侠带来“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,可以理解为点亮的比例每个时间段增加千分之一。这样的话,就可以完成由暗到亮。将上述的输出波形取反,就是点亮的比例每个时间段减少千分之一,完成由亮到灭。

架构图如下:

系统设计:

1. 工程的名称:breathe_led

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

设计代码如下:

代码语言:javascript
复制
/*
模块名称:breathe_led
模块功能:呼吸灯 
作者:郝旭帅
邮箱:746833924@qq.com
*/
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取反,输出的占空比变化情况发生改变。

激励代码如下:

代码语言:javascript
复制
/*
模块名称:breathe_led_tb
模块功能:为breathe_led模块提供激励信号
作者:郝旭帅
邮箱:746833924@qq.com
*/
`timescale 1ns/1ps

module 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

仿真波形如下:

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

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

END

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-03-20,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 FPGA技术江湖 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档