- 为了便于仿真的实现,定义周期数值period_cnt缩小为50,每次改变的数值duty_cycle定义为5,这两个数值本来可以定义在参数中,懒得重写代码直接修改了数值。
module breathe_led(
input clk, // 时钟信号
input rst, // 复位信号
output wire led
);
// reg define
reg [16:0] period_cnt; // 周期计数器 1khz = 1ms 1_000_000ns / 10ns(100mhz) = 100_000(17位二进制)
reg [16:0] duty_cycle; // 设置高电平占空比的计数点
reg inc_dec_flag; // 用于表示高电平占空比的计数值,是递增还是递减
// 为1时表示占空比递减,为0时表示占空比递增
// 将周期信号计数值与占空比计数值进行比较,以输出驱动led的PWM信号
assign led = (period_cnt <= duty_cycle) ? 1'b1 : 1'b0;
// 周期信号计数器在0-100_000之间计数
always @(posedge clk or posedge rst) begin
if(rst)
period_cnt <= 17'd0;
else if(period_cnt == 17'd50)
period_cnt <= 17'd0;
else
period_cnt <= period_cnt + 17'd1;
end
// 设置高电平占空比的数
always @(posedge clk or negedge rst) begin
if(rst == 1'b1) begin
duty_cycle <= 17'd0;
inc_dec_flag <= 1'b0;
end
// 每次计数完一个周期,就调节占空比计数值
else if(period_cnt == 17'd50) begin
if(inc_dec_flag) begin // 为1占空比递减
if(duty_cycle == 17'd0)
inc_dec_flag <= 1'b0;
else
duty_cycle <= duty_cycle - 17'd 5;
end
else begin // 占空比递增
if(duty_cycle == 17'd50)
inc_dec_flag <= 1'b1;
else
duty_cycle <= duty_cycle + 17'd5;
end
end
else // 未计数完一个周期,占空比保持不变
duty_cycle <= duty_cycle;
end
endmodule
module testbench(
);
reg clk;
reg rst;
wire led;
initial begin
clk = 1'b1;
rst <= 1'b1;
#20;
rst <= 1'b0;
end
always #10 clk = ~clk;
breathe_led
breathe_led_inst
(
.clk(clk),
.rst(rst),
.led(led)
);
endmodule
- 仿真波形可以拆成两部分来看,第一部分inc_dec_flag=0时表示占空比递增,每经过一个周期增加一份duty_cycle直到计数到最大为period_cnt然后调整inc_dec_flag=1进入第二部分,占空比递减,每经过一个周期减少一份duty_cycle直到为0调整inc_dec_flag=1占空比开始递增。