工程教育中级课上老师把这道题作为延伸拓展题,在讲解了大致思路后我对呼吸灯也有了一定的了解,最开始尝试自己编写了一部分,但是并没有完全实现,后来想想还是自己对于概念上理解不够透彻,后面在网上参考别人优秀的代码和说明后渐渐明白了其中的机制,以下是自己写的呼吸灯代码以及一些思路过程。
实现流程
1、
呼吸灯分为两个部分,一个部分是 由亮变暗,
一个部分是 由暗变亮。
2、
当由亮变暗,也就是:
首先,占空比100%为零,
然后,占空比99%为零,1%为1;等于占空比100%
然后,占空比98%为零,2%为1;等于占空比100%
…
然后,占空比2%为零,98%为1;等于占空比100%
然后,占空比1%为零,99%为1;等于占空比100%
3、
当由暗变亮,也就是:
首先,占空比100%为1,
然后,占空比99%为1,1%为零;等于占空比100%
然后,占空比98%为1,2%为零;等于占空比100%
…
然后,占空比2%为1,98%为零;等于占空比100%
然后,占空比1%为1,99%为零;等于占空比100%
功能分解
1、定义:一个完整的呼吸灯时间为2s,也就是,由亮变暗需要1s,由暗变亮需要1s;
2、将1s分为1000等份,也就是 由亮变暗,需要100次的变化,每次为1ms;
3、将1ms分为1000等份,占空比100%过渡到0%,需要1000次的变化,每次为1us。
硬件开发板说明:
1、cyclone III:EP3C5E144C8
2、时钟24M
代码实现
module breath_light(
input clk, // 24M
output reg [2:0]led
);
// 寄存器
reg [9:0] cnt_s;
reg [9:0] cnt_ms;
reg [4:0] cnt_us;
reg a;
// 初始化
parameter T_s = 10'd999; // 1000
parameter T_ms = 10'd999; // 1000
parameter T_us = 5'd23; // 1us
initial
begin
a <= 1'b0;
led <= 3'b000;
cnt_s <= 10'd0;
cnt_ms <= 10'd0;
cnt_us <= 5'd0;
end
// 1us
always @ (posedge clk)
begin
if(cnt_us == T_us)
cnt_us <= 5'd0;
else
cnt_us <= cnt_us +5'd1;
end
// 1ms
always @ (posedge clk )
begin
if(cnt_us == T_us && cnt_ms == T_ms)
cnt_ms <= 10'd0;
else if(cnt_us == T_us)
cnt_ms <= cnt_ms + 10'd1;
end
// 1s
always @ (posedge clk)
begin
if(cnt_us == T_us && cnt_ms == T_ms && cnt_s == T_s)
cnt_s <= 10'd0;
else if(cnt_us == T_us && cnt_ms == T_ms)
cnt_s <= cnt_s + 10'd1;
end
// 标志位
always @ (posedge clk)
begin
if(cnt_us == T_us && cnt_ms == T_ms && cnt_s == T_s)
a <= ~a;
else
a <= a;
end
// 亮灯
always @ (posedge clk )
begin
if(cnt_s > cnt_ms && a ==1'b1)
led <= 3'b111;
else if(cnt_s < cnt_ms && a ==1'b1)
led <= 3'b000;
else if(cnt_s > cnt_ms && a ==1'b0)
led <= 3'b000;
else if(cnt_s < cnt_ms && a ==1'b0)
led <= 3'b111;
end
endmodule
经验证,该代码没有问题,后面有时间会出一篇用modelsim仿真验证的博客,敬请期待。