FPGA的呼吸灯设计案例(verilog实现)

案例1:呼吸灯0

实现功能:4个LED同时改变,亮度由PWM信号控制。

实验现象:

4个LED,灭→亮,逐渐变亮,到达最亮后熄灭,再从灭→亮,重复进入下一次循环。

代码实现:

module pwm(
    input clk,
    input rst_n,
    
    output reg  [3:0] led
);

reg [15:0] pwm0,count;

always @(posedge clk or negedge rst_n) begin
    if(!rst_n)
        count <= 16'b0;
    else begin
        count <= count + 1'b1;
        if(count[15]==1)    //打到周期预设定的数值,就清零
           count <= 16'b0;

        if(count < pwm0)        //如果本周期中,周期小于PWM脉宽计数,那么LED就=1
            led <= 4'b1111;
        else 
            led <= 4'b0000;            //PWM的低脉冲时候,就为0
        end
 end
 
 
 always @(posedge count[14]) begin         //一个周期前面一点,产生PWM加/减 信号
 
   pwm0 <= pwm0 + 1'b1;                                //PWM 在一个周期完成之前加1,用于下一个周期的信号宽度
   if(pwm0[13]==1)                               //脉宽达到预设定的数值
    pwm0 <= 16'b0;
    
 end 

endmodule

案例2:呼吸灯1

实现功能:4个LED同时改变,亮度由PWM信号控制。

实验现象:

第1秒:灭→亮,逐渐变亮,达到最亮,

第2秒:亮→灭,逐渐变暗;

……

2s一个周期,重复进入下一次循环。

代码实现:

module breath_led(
   input        clk,
   input        rst_n,
   output  reg [3:0] led
 );
 
 reg flag;
 
 // 计数器cnt_2us循环计数,计到99为2us 
 parameter cnt_2us_max = 7'd100 - 1'b1;
 reg [6:0] cnt_2us;

 always @(posedge clk or negedge rst_n) begin
   if (!rst_n)
     cnt_2us <= 7'd0;
   else if(cnt_2us == cnt_2us_max)
     cnt_2us <= 7'd0;
   else
     cnt_2us <= cnt_2us + 1'b1;
 end

 // 计数器cnt_2ms循环计数,计到999为2ms 
 parameter cnt_2ms_max = 10'd1000 - 1'b1;
 reg [9:0] cnt_2ms;

 always @(posedge clk or negedge rst_n) begin
   if (!rst_n)
      cnt_2ms <= 10'd0;
   else if(cnt_2us == cnt_2us_max && cnt_2ms == cnt_2ms_max)
      cnt_2ms <= 10'd0;
   else if(cnt_2us == cnt_2us_max)
      cnt_2ms <= cnt_2ms + 1'b1;
   else
      cnt_2ms <= cnt_2ms;
 end

 // 计数器cnt_2s循环计数,计到999为2s 
 parameter cnt_2s_max = 10'd1000 - 1'b1;
 reg [9:0] cnt_2s;

 always @(posedge clk or negedge rst_n) begin
   if (!rst_n)
      cnt_2s <= 10'd0;
   else if(cnt_2us == cnt_2us_max && cnt_2ms == cnt_2ms_max && cnt_2s == cnt_2s_max)
      cnt_2s <= 10'd0;
   else if(cnt_2us == cnt_2us_max && cnt_2ms == cnt_2ms_max)
      cnt_2s <= cnt_2s + 1'b1;
   else
      cnt_2s <= cnt_2s;
 end
 
 //flag标志
 always @(posedge clk or negedge rst_n) begin
   if (!rst_n)
      flag <= 1'd0;
   else if(cnt_2us == cnt_2us_max && cnt_2ms == cnt_2ms_max && cnt_2s == cnt_2s_max)
      flag <= ~flag;
   else 
      flag <= flag;
 end 
 

 //brearh_led控制
 always @(posedge clk or negedge rst_n) begin
   if (!rst_n)
      led <= 4'b0000;
   else if(cnt_2s >= cnt_2ms && flag == 1'b0)
      led <= 4'b1111;
   else if(cnt_2s < cnt_2ms && flag == 1'b0)
      led <= 4'b0000; 
    else if(cnt_2s >= cnt_2ms && flag == 1'b1)
      led <= 4'b0000;  
   else if(cnt_2s < cnt_2ms && flag == 1'b1)
      led <= 4'b1111;      
   else 
      led <= 4'b0000;
 end
 
 endmodule

案例3:呼吸灯2

实现功能:4个LED同时改变,亮度由PWM信号控制。

实验现象:

占空比越大,LED灯越暗;
占空比越小,LED灯越亮。

第1个2秒: pwm_time <= 19’d450_000;//占空比90%

第2个2秒: pwm_time <= 19’d350_000;//占空比70%

第3个2秒:pwm_time <= 19’d250_000;//占空比50%

第4个2秒:pwm_time <= 19’d100_000;//占空比20%

第5个2秒:pwm_time <= 19’d50_000;//占空比10%

第6个2秒: pwm_time <= 19’d5_000;//占空比1%

第7个2秒: pwm_time <= 19’d100_000;//占空比20%

第8个2秒:pwm_time <= 19’d250_000;//占空比50%

第9个2秒:pwm_time <= 19’d350_000;//占空比70%

第10个2秒: pwm_time <= 19’d450_000;//占空比90%

……

20s一个周期,重复进入下一次循环。

代码实现:

module breathing_led(
   input        clk,
   input        rst_n,
   output  reg [3:0] led
 );
 
 reg flag;
 
 // 计数器cnt_10ms循环计数,计到499999为10ms 
 parameter cnt_10ms_max = 19'd500_000 - 1'b1;
 reg [18:0] cnt_10ms;

 always @(posedge clk or negedge rst_n) begin
   if (!rst_n)
     cnt_10ms <= 19'd0;
   else if(cnt_10ms == cnt_10ms_max)
     cnt_10ms <= 19'd0;
   else
     cnt_10ms <= cnt_10ms + 1'b1;
 end

 // 计数器cnt_2s循环计数,计到199为2s 
 parameter cnt_2s_max = 8'd200 - 1'b1;
 reg [7:0] cnt_2s;

 always @(posedge clk or negedge rst_n) begin
   if (!rst_n)
      cnt_2s <= 8'd0;
   else if(cnt_10ms == cnt_10ms_max && cnt_2s == cnt_2s_max)
      cnt_2s <= 8'd0;
   else if(cnt_10ms == cnt_10ms_max)
      cnt_2s <= cnt_2s + 1'b1;
   else
      cnt_2s <= cnt_2s;
 end

 // 计数器cnt_20s循环计数,计到9为20s 
 parameter cnt_20s_max = 4'd10 - 1'b1;
 reg [3:0] cnt_20s;

 always @(posedge clk or negedge rst_n) begin
   if (!rst_n)
      cnt_20s <= 4'd0;
   else if(cnt_10ms == cnt_10ms_max && cnt_2s == cnt_2s_max && cnt_20s == cnt_20s_max)
      cnt_20s <= 4'd0;
   else if(cnt_10ms == cnt_10ms_max && cnt_2s == cnt_2s_max)
      cnt_20s <= cnt_20s + 1'b1;
   else
      cnt_20s <= cnt_20s;
 end

 
reg [18:0] pwm_time;

 //pwm控制brearhing_led
 always @(posedge clk or negedge rst_n) begin
   if (!rst_n)
      led <= 4'b0000;
   else if(cnt_10ms == pwm_time-1'b1)
      led <= 4'b1111;     
   else if(cnt_10ms == cnt_10ms_max) 
      led <= 4'b0000;
   else
      led <= led;
 end
 
 //改变pwm信号的占空比
 always @(*) begin
   case(cnt_20s)
      4'd0: pwm_time <= 19'd450_000;//90%     
      4'd1: pwm_time <= 19'd350_000;//70% 
      4'd2: pwm_time <= 19'd250_000;//50% 
      4'd3: pwm_time <= 19'd100_000;//20%
      4'd4: pwm_time <= 19'd50_000;//10%
      4'd5: pwm_time <= 19'd5_000;//1%
      4'd6: pwm_time <= 19'd100_000;//20% 
      4'd7: pwm_time <= 19'd250_000;//50% 
      4'd8: pwm_time <= 19'd350_000;//70%  
      4'd9: pwm_time <= 19'd450_000;//90% 
      default: pwm_time <= 19'd0;
 endcase 
 end
 
 endmodule

说明:

本文的3个案例,在正点原子FPGA开拓者开发板上亲测有效。

案例中LED的管脚分配如下:
在这里插入图片描述
参考资料0: 最简单的FPGA verilog写的 PWM 例子.

参考资料1: FPGA实现呼吸灯功能实验.

  • 6
    点赞
  • 80
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值