//说明:呼吸灯,灯慢慢的由亮到灭,再由灭到亮,(1ms亮灭程度变化,由亮到灭实现用1s,由灭到亮的实现用1s)
//定义一个1us其实是时钟的作用,如果直接对系统时钟周期计数的话,1ms和1s的最大阈值会变大很多,要用的储存器宽度增大,所以要1us是为了节省存储空间
//定义一个使能信号,呼吸灯是两个过程,由使能信号控制高低电平的翻转,
//整个过程其实就是pwm的原理,只是使用方式要注意
module breathe_led
#(
parameter count_1us_max=6'd49,
parameter count_1ms_max=10'd999,
parameter count_1s_max=10'd999
)
(
input wire sys_clk,
input wire rst_n,
output reg led
);
reg [9:0] count_1s;
reg [9:0] count_1ms;
reg [5:0] count_1us;
reg count_en;//使能信号
always@(posedge sys_clk or negedge rst_n)
if (~rst_n)
count_1us <= 6'd0;
else if (count_1us == count_1us_max)
count_1us <= 6'd0;
else
count_1us <= count_1us +6'd1;
always@(posedge sys_clk or negedge rst_n)
if (~rst_n)
count_1ms <= 10'd0;
else if ((count_1ms == count_1ms_max) && (count_1us == count_1us_max)) //细节 跳到最大值之后变为最小值,但是最大值持续时间不是一个系统时钟周期啊,仔细想想
count_1ms<= 10'd0;
else if (count_1us == count_1us_max)
count_1ms <= count_1ms+10'd1;
else
count_1ms <= count_1ms;
always@(posedge sys_clk or negedge rst_n)
if (~rst_n)
begin
count_1s <= 10'd0;
count_en <= 1'b0;
end
else if ((count_1s == count_1s_max)&&(count_1ms == count_1ms_max) && (count_1us == count_1us_max)) //同理
begin
count_1s<= 10'd0;
count_en <= ~count_en;
end
else if ((count_1ms == count_1ms_max) && (count_1us == count_1us_max)) //同理
count_1s <= count_1s+10'd1;
else
count_1s <= count_1s;
always@(posedge sys_clk or negedge rst_n) //led的高低电平变化会延后一个时钟周期
if (~rst_n)
led <= 1'd1;
else if(((count_1ms<= count_1s) && (count_en==1'b1)) ||((count_1ms> count_1s) && (count_en==1'b0))) //具体要看那个时序图,有点巧妙的
led <=1'd1;
else
led <=1'd0;
endmodule
module vtf_breathe_led;
// Inputs
reg sys_clk;
reg rst_n;
// Outputs
wire led;
// Instantiate the Unit Under Test (UUT)
breathe_led
#(
.count_1us_max(6'd4),
.count_1ms_max(10'd9),
.count_1s_max(10'd9)
)
uut (
.sys_clk(sys_clk),
.rst_n(rst_n),
.led(led)
);
initial begin
// Initialize Inputs
sys_clk = 0;
rst_n = 0;
// Wait 100 ns for global reset to finish
#100;
rst_n <= 1'b1;
// Add stimulus here
end
always #10 sys_clk = ~sys_clk;
endmodule