FPGA基于village的呼吸灯设计

文章讲述了如何利用PWM技术,结合Verilog编程,设计一个计数器系统,以50MHz的频率控制LED灯在一秒钟内从开始点亮到完全亮起,再在下一秒钟从完全亮起逐渐熄灭,形成呼吸灯效果。占空比的变化决定了LED的亮度,通过调整计数器的值来改变占空比。
摘要由CSDN通过智能技术生成

注意:以下是本人学习笔记,仅供参考,如有问题请留言。

要求:实现led灯从开始点亮        >        完全点亮        >        开始熄灭        >        完全熄灭

一般的板载频率为50MHZ,也就是频率为20us,

第1秒实现从开始点亮到完全点亮,第二秒实现开始熄灭到完全熄灭

这里用到PWM的知识:

用数字信号表示模拟信号的效果,高电平所占的比例就是整个周期的占空比

1s中有多少这样的周期就是PWM的周期(f = 1/T)周期单位为HZ,频率单位为s

面积等效原理:输出 = 输入 * 占空比(输入电压为5V,占空比为20%,输出电压为1V)

与PWM来控制输出信号的电压,来实现led灯呼吸效果。

1s = 1000ms;        1ms = 1000ns;

因为clk的频率是50MHZ,也就是20us;

所以设计的cnt_1ns的计数周期是50;cnt_1ms的计数周期是999;cnt_1s的计数周期是999.

这里设置了一个使能信号led_en;通过高低电平来实现:开始点亮        >        完全点亮        >        开始熄灭        >        完全熄灭

通过判断cnt_1ms计数的大小来决定led_out的输出:

当使能信号   led_en==0;b0  计数cnt_1ms >= cnt_1s  ,输出低电平(低电平有效),这样来控制开始点亮        >        完全点亮;

当使能信号   led_en==1;b0  计数cnt_1ms > cnt_1s  ,输出低电平(低电平有效),这样来控制开始熄灭        >        完全熄灭.

参考图:

编写程序:

module  breath_led
#(
  parameter CNT_1S_MAX = 10'd999,
  parameter CNT_1MS_MAX = 10'd999,
  parameter CNT_1NS_MAX = 6'd49
)
  (
  input       sys_clk,
  input       sys_rst_n,
  
  output   reg   led_out
  );
  
  reg   [9:0]   cnt_1s;
  reg   [9:0]   cnt_1ms;
  reg   [5:0]   cnt_1ns;
  reg           led_en;

always@(posedge sys_clk or negedge sys_rst_n)
  if(sys_rst_n == 1'b0)
    cnt_1ns <= 6'd0;
  else if( cnt_1ns == CNT_1NS_MAX)
    cnt_1ns <= 6'd0;
  else
    cnt_1ns <= cnt_1ns + 5'd1;
    
always@(posedge sys_clk or negedge sys_rst_n)
  if(sys_rst_n == 1'b0)
    cnt_1ms <= 10'd0;
  else if((cnt_1ms == CNT_1MS_MAX) && (cnt_1ns == CNT_1NS_MAX))
    cnt_1ms <= 10'd0;
  else if(cnt_1ns == CNT_1NS_MAX)
    cnt_1ms <= cnt_1ms + 10'd1;
  else
    cnt_1ms <= cnt_1ms;
    
always@(posedge sys_clk or negedge sys_rst_n)
  if(sys_rst_n == 1'b0)
    cnt_1s <= 10'd0;
  else if((cnt_1s == CNT_1S_MAX) && (cnt_1ms == CNT_1MS_MAX) && (cnt_1ns == CNT_1NS_MAX))
    cnt_1s <= 10'd0;
  else if((cnt_1ns == CNT_1NS_MAX) && (cnt_1ms == CNT_1MS_MAX))
    cnt_1s <= cnt_1s + 10'd1;
  else
    cnt_1s <= cnt_1s;
    
always@(posedge sys_clk or negedge sys_rst_n)
  if(sys_rst_n == 1'b0)
    led_en <= 1'b0;
  else if((cnt_1s == CNT_1S_MAX) && (cnt_1ns == CNT_1NS_MAX) && (cnt_1ms == CNT_1MS_MAX))  
    led_en <= ~led_en;
  else
    led_en <= led_en;
    
always@(posedge sys_clk or negedge sys_rst_n)
  if(sys_rst_n == 1'b0)
    led_out <= 1'b1;
  else if(((led_en == 1'b0) && (cnt_1ms <= cnt_1s)) || ((led_en == 1'b1) && (cnt_1ms > cnt_1s))) 
    led_out <= 1'b0;
  else
    led_out <= 1'b1;
    

    

endmodule

因为ns,ms和s的计数是0~49,0~999,0~999计数比较大,编写测试代码时改成了0~4,0~9,0~9,这样以利于观察。

测试代码:

`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
  
always  #20   sys_clk = ~sys_clk;

breath_led
#(
    .CNT_1S_MAX   (10'd9),
    .CNT_1MS_MAX   (10'd9),
    .CNT_1NS_MAX   (6'd4)
)
tb_breath_led

  (
    .sys_clk    (sys_clk),
    .sys_rst_n  (sys_rst_n),
    .led_out    (led_out)
  );
  
endmodule


模拟仿真图:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值