一、概述
关于呼吸灯的设计其实在前面的文章中就已经提到过,这篇文章更多的针对前面的实现方式进行一个改良。在前面的呼吸灯的设计使用的是us、ms、s的三级计数器进行功能实现,这种实现方法应该是我们最后理解也是最常用的方式。但经过蜂鸣器的音乐播放器的设计之后突然一想,既然呼吸灯也用的PWM进行设计,为什么不直接使用调制占空比的方式进行实现呢。经过系统的总结,其实前面文章实现的方式虽然通俗易懂,但严格来说不算是PWM调制,只能说刚好踩在了点上,所以也能实现。
在本次的呼吸灯设计中,我们直接采取改变占空比的方式,对于呼吸灯进行一个实现。
二、工程实现
1、基本思路
这里和前面实现的时间一样也采用2s完成LED呼吸灯的全部过程,私用ms的计数器对于计数器进行1000次技术,接着对于这1000个m计数周期进行占空比的一个调试。在呼吸灯有灭——亮变为亮——灭的状态切换时使用一个一秒计数器对状态标志位进行一个划分,最后对于LED进行一个输出就实现了呼吸灯的设计。
2、设计文件的编写
见闻思意,新建一个breath_led.v文件,如下:
//实现2s呼吸灯,1s呼,1s吸。
module breath_led (input clk ,input rst_n ,output reg led
);
//
parameter TIME_1MS = 50000;
//
reg [15:0] cnt_1ms ;//1个pwm周期计数器
wire add_cnt_1ms ;
wire end_cnt_1ms ;reg [9:0] cnt_1s ;//以1ms为基准,计数1000次
wire add_cnt_1s ;
wire end_cnt_1s ;reg state_flag ;//状态标志位reg [15:0] duty ;//占空比//1ms计数器
always@(posedge clk or negedge rst_n)if(!rst_n)begincnt_1ms <= 'd0;endelse if(add_cnt_1ms)beginif(end_cnt_1ms)begincnt_1ms <= 'd0;endelse begincnt_1ms <= cnt_1ms + 1'b1;endend
assign add_cnt_1ms = 1'b1;
assign end_cnt_1ms = add_cnt_1ms && (cnt_1ms == (TIME_1MS - 1));//1s计数器
always@(posedge clk or negedge rst_n)if(!rst_n)begincnt_1s <= 'd0;endelse if(add_cnt_1s)beginif(end_cnt_1s)begincnt_1s <= 'd0;endelse begincnt_1s <= cnt_1s + 1'b1;endend
assign add_cnt_1s = end_cnt_1ms;
assign end_cnt_1s = add_cnt_1s && (cnt_1s == (1000 - 1));//LED呼吸灯状态切换
always@(posedge clk or negedge rst_n)beginif(!rst_n)beginstate_flag <= 0;//表示从渐灭到渐亮的状态endelse if(end_cnt_1s)beginstate_flag <= ~state_flag;//当1s时间到来 状态翻转end
end//占空比改变
always@(posedge clk or negedge rst_n)beginif(!rst_n)beginduty <= 0;endelse if(end_cnt_1ms && (!state_flag))begin//在从渐灭到渐亮的状态下, 占空比比较值每1ms加1/1000个pwmduty <= duty + TIME_1MS/1000;endelse if(end_cnt_1ms && (state_flag))begin//在从渐亮到渐灭的状态下, 占空比比较值每1ms减1/1000个pwmduty <= duty - TIME_1MS/1000; end
endalways@(posedge clk or negedge rst_n)beginif(!rst_n)beginled <= 0;endelse if(cnt_1ms >= duty)beginled <= 0;endelse beginled <= 1; end
endendmodule
3、测试文件的编写
`timescale 1ns/1ps
module breath_led_tb();
reg clk ;
reg rst_n ;//模块例化
breath_led led_inst(/* input */.clk (clk ),/* input */.rst_n (rst_n ),/* output reg */.led ()
);//重定义
defparam led_inst.TIME_1MS = 5000;
//时钟
parameter CLK_CYCLE = 20;
initial clk = 1;
always #(CLK_CYCLE/2) clk = ~clk;
//复位
initial beginrst_n = 1'b0;#(CLK_CYCLE*2);#3;rst_n = 1'b1;
end//激励
initial beginendendmodule
三、仿真波形图
在第一章图中我们可以看到LED的占空比duty在不断增加,上面的led输出波形高电平也是在不断变大 ,实现的是LED吸的状态,而在第二章图中是1秒过后LED进行呼的状态,占空比duty在不断减小,相应的波形图高电平占空比也在不断变小。在最后进行下板验证时我们观察到LED在进行灭——亮,亮——灭的显示,呼吸灯设计完成。