FPGA学习笔记:verilog基础代码与modelsim仿真(四)——呼吸灯

呼吸灯

功能目标:实现Led灯由熄灭逐渐变亮至完全点亮,再逐渐变暗至完全熄灭,循环往复。

1.输入输出原理图

在这里插入图片描述
将系统时钟与复位按键作为输入,led灯状态作为输出,直观显示最终结果。

2.波形图绘制(visio)

led灯波形图
首先根据实现目标明确led灯在熄灭->点亮->熄灭过程中的波形图,其中低电平代表点亮,高电平代表熄灭;在熄灭->点亮过程,想要实现“呼吸”效果,就需要在每个周期T内逐渐增加led灯的点亮时间,最终将各个周期合并,实现“呼吸”效果。

那么,有了点亮时的呼吸效果,熄灭的呼吸效果就是将熄灭、点亮时间反过来就可以实现了。
在这里插入图片描述


接下来,我们利用上文提到的时钟与复位按键,同时引入中间变量绘制完整的波形图:

由灭到亮:

实现由灭到亮的呼吸效果

由亮到灭:

在这里插入图片描述
sys_clk是频率为50Mhz的系统时钟;

sys_rst_n:复位按键,低电平有效,这里我们设除开始一小段时间外,按键始终处于高电平即无效状态;

cnt_1s:1s计数器 ; cnt_1ms : 1ms计数器:以此类推…

特定时间计数器的模值在其他文章里已经说明过,这里不再赘述。

cnt_en : 使能信号,这里的作用是判断led灯何时转换状态,例如上图,当led由亮逐渐熄灭时,当led完全熄灭,cnt_en则由高电平进入低电平,从而使led开始逐渐点亮。

led_out: led输出波形。

代码实现:

 module breath_led
 #(
    parameter   CNT_1us_MAX = 6'd49 ,   //The maximum modulus of the counter
    parameter   CNT_1ms_MAX = 11'd999 ,
    parameter   CNT_1s_MAX = 11'd999 
    
 
 
 )
 (
    input   wire    sys_clk     ,
    input   wire    sys_rst_n   ,
    
    
    output  reg     led_out
   
    
 );
 
reg  [10:0]  cnt_1s;
reg  [10:0]  cnt_1ms;
reg  [5:0]  cnt_1us;
reg          cnt_en ;

always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        cnt_1us <= 6'd0;
    else if(cnt_1us == CNT_1us_MAX)
        cnt_1us <= 6'd0;
    else
        cnt_1us <= 6'd1 + cnt_1us ;
        
always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        cnt_1ms <= 11'd0;
    else if(cnt_1us == CNT_1us_MAX && cnt_1ms == CNT_1ms_MAX)
        cnt_1ms <= 11'd0;
    else if(cnt_1us == CNT_1us_MAX)
        cnt_1ms <= 11'd1 + cnt_1ms ;
    else
          cnt_1ms <=  cnt_1ms ;
          
always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        cnt_1s <= 11'd0;
    else if(cnt_1ms == CNT_1ms_MAX && 
            cnt_1s == CNT_1s_MAX && cnt_1us == CNT_1us_MAX )
        cnt_1s <= 11'd0;
    else if(cnt_1ms == CNT_1ms_MAX && cnt_1us == CNT_1us_MAX)
        cnt_1s <= 11'd1 + cnt_1s ;
    else
          cnt_1s <=  cnt_1s ;
          
          
          
always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        cnt_en <= 1'd0;
    else if((cnt_1us == CNT_1us_MAX) && (cnt_1ms == CNT_1ms_MAX) 
            && (cnt_1s == CNT_1s_MAX) )
        cnt_en <= ~cnt_en;
    
    else
          cnt_en <=  cnt_en ;  

          
          
always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        led_out <= 1'b1 ;
    else if(((cnt_en == 1'b0) && (cnt_1ms <= cnt_1s)) 
            || ((cnt_en == 1'b1)&& (cnt_1ms > cnt_1s)))
        led_out<= 1'b1 ;
 
    else
        led_out <= 1'b0;
          
          
          

  
 endmodule
 
实例化文件:
   `timescale 1ns/1ns
   module tb_breath_led();
   
   reg sys_clk;
   reg sys_rst_n;
   wire led_out;
   
  
   initial
      begin
          sys_clk = 1'b1;
          sys_rst_n <= 1'b0;
          #20
          sys_rst_n <= 1'b1;
      end
   
   
   /*initial 
      begin
          $timeformat(-9,0,"ns",6);
          $monitor("@time %t :in_1=%b,in_2=%b,cin=%b,sum=%b,count=%b" ,$time,in_1,in_2,cin,sum,count);
      end*/
      
      
  always #10 sys_clk = ~sys_clk; //clk frequency
 
  
 breath_led 
  #(
        
        .CNT_1us_MAX (7'd100),
        .CNT_1ms_MAX (10'd500),
        .CNT_1s_MAX  (10'd500)
                  
  
  )
 breath_led_inst
  (
          .sys_clk  (sys_clk)   ,
          .sys_rst_n(sys_rst_n)   ,
          .led_out (led_out) 
     
             
          
  );
      
  endmodule
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

保温杯配红牛

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值