Verilog实现PWM呼吸灯

前言

我认为在FPGA的设计中,理论联系实际是十分重要的。下面转载的PWM呼吸灯就是一个很好的例子——作者用Verilog实现了一个变化pwm占空比的电路,应用在呼吸灯上。设计并不复杂,作者的代码风格也好,是相当优秀的Project。

设计文件

//======================================================================
// --- 名称 : breathing_led
// --- 作者 : xianyu_FPGA
// --- 日期 : 2018-12-15
// --- 描述 : PWM频率调制实现真呼吸灯的效果,4秒1次循环,
//            每2ms秒变化1次,前2秒亮度增大,后2秒亮度减小
//======================================================================

module breathing_led
//---------------------<端口声明>---------------------------------------
(
input  wire              clk                , //时钟,50Mhz
input  wire              rst_n              , //复位,低电平有效
output wire              led                   //led灯
);
//---------------------<参数定义>---------------------------------------
parameter TIME_2MS      = 100_000           ; //2ms时间
parameter TIME_2MS_W    = 17                ; //2ms时间位宽
parameter NUM           = 1000              ; //2ms到2s为1000份
parameter NUM_W         = 10                ; //份数位宽
parameter STEP          = 100               ; //2ms也分成1000份,每份为步长100

//---------------------<信号定义>---------------------------------------
reg  [TIME_2MS_W-1:0]   cnt0                ;
wire                    add_cnt0            ;
wire                    end_cnt0            ;
reg  [NUM_W:0]          cnt1                ;
wire                    add_cnt1            ;
wire                    end_cnt1            ;
reg  [1:0]              cnt2                ;
wire                    add_cnt2            ;
wire                    end_cnt2            ;
reg  [TIME_2MS_W-1:0]   pwm_high            ;

//----------------------------------------------------------------------
//--   2ms时间计时
//----------------------------------------------------------------------
always @(posedge clk or negedge rst_n)begin
    if(!rst_n)
        cnt0 <= 0;
    else if(add_cnt0)begin
        if(end_cnt0)
            cnt0 <= 0;
        else
            cnt0 <= cnt0 + 1;
    end
    else
       cnt0 <= cnt0;
end

assign add_cnt0 = 1;
assign end_cnt0 = add_cnt0 && cnt0==TIME_2MS-1 ;

//----------------------------------------------------------------------
//--   每2ms计1次,计到2秒共需计NUM次
//----------------------------------------------------------------------
always @(posedge clk or negedge rst_n)begin
    if(!rst_n)
        cnt1 <= 0;
    else if(add_cnt1)begin
        if(end_cnt1)
            cnt1 <= 0;
        else
            cnt1 <= cnt1 + 1;
    end
    else
       cnt1 <= cnt1;
end

assign add_cnt1 = end_cnt0;
assign end_cnt1 = add_cnt1 && cnt1==NUM-1 ;

//----------------------------------------------------------------------
//--   每2秒计1次,计到4秒共需计2次
//----------------------------------------------------------------------
always @(posedge clk or negedge rst_n)begin
    if(!rst_n)begin
        cnt2 <= 0;
    end
    else if(add_cnt2)begin
        if(end_cnt2)
            cnt2 <= 0;
        else
            cnt2 <= cnt2 + 1;
    end
    else
       cnt2 <= cnt2;
end

assign add_cnt2 = end_cnt1;
assign end_cnt2 = add_cnt2 && cnt2==2-1 ;

//----------------------------------------------------------------------
//--   设置pwm的占空比时间
//----------------------------------------------------------------------
always @(posedge clk or negedge rst_n) begin
    if(!rst_n)
        pwm_high <= 0;
    else if(cnt2==0 && end_cnt0)
        pwm_high <= pwm_high + STEP;
    else if(cnt2==1 && end_cnt0)
        pwm_high <= pwm_high - STEP;
    else
        pwm_high <= pwm_high;
end

//----------------------------------------------------------------------
//--   输出led灯
//----------------------------------------------------------------------
assign led = (cnt0 < pwm_high) ? 1'b1 : 1'b0;



endmodule

仿真文件

`timescale 1ns/1ps  //时间精度
`define    Clock 20 //时钟周期

module breathing_led_tb;

//---------------------<端口定义>---------------------------------------
reg                     clk                 ; //时钟,50Mhz
reg                     rst_n               ; //复位,低电平有效
wire                    led                 ;

//----------------------------------------------------------------------
//--   模块例化
//----------------------------------------------------------------------
breathing_led
#(
    .TIME_2MS           (1000               ), //2ms时间 100_000
    .NUM                (100                ), //2ms到2s为1000份
    .STEP               (10                 )  //2ms也分成1000份,每份为步长100
)
u_breathing_led
(
    .clk                (clk                ),
    .rst_n              (rst_n              ),
    .led                (led                )
);

//----------------------------------------------------------------------
//--   时钟信号和复位信号
//----------------------------------------------------------------------
initial begin
    clk = 1;
    forever
        #(`Clock/2) clk = ~clk;
end

initial begin
    rst_n = 0; #(`Clock*20+1);
    rst_n = 1;
end




endmodule

仿真波形

可以看到led信号的占空比先不断增加后不断减少,循环反复。
在这里插入图片描述
本文转载自:
https://www.cnblogs.com/xianyufpga/p/11026878.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值