以驱动led灯实现呼吸灯为例
RTL代码:
module breath_led(
input sys_clk,
input sys_rst,
output led
);
reg [15:0] divider; // frequency divider, 50Mhz/20ns -> 1Khz/1ms about 50000 clk
reg [15:0] D; // duty cycle
reg flag; // 1 for increment
// 通过D和divider的比较得到驱动led的PWM波
assign led = (divider >= D) ? 1'd1 : 1'd0;
// 方便仿真观察时序,将50000计数改成50
always @(posedge sys_clk or negedge sys_rst) begin
if(!sys_rst)
divider <= 16'd0;
else if (divider == 16'd50)
divider <= 16'd0;
else
divider <= divider + 1'd1;
end
// 占空比根据flag标志位递增或递减
always @(posedge sys_clk or negedge sys_rst) begin
if (!sys_rst) begin
D <= 16'd0;
flag <= 1'd1;
end
else begin
if (flag == 1'd1) begin
if (D < 16'd50) begin
if (divider == 16'd50)
D <= D + 16'd5;
else
D <= D;
end
else
flag <= 1'd0;
end
else begin
if (D > 16'd0) begin
if (divider == 16'd50)
D <= D - 16'd5;
else
D <= D;
end
else
flag <= 1'd1;
end
end
end
endmodule
Testbench:
`timescale 1 ns/ 1 ns
module breath_led_vlg_tst();
reg sys_clk;
reg sys_rst;
reg [15:0] divider;
reg [15:0] D;
wire led;
parameter T = 10;
always #T sys_clk = ~ sys_clk;
initial begin
sys_clk <= 1'b0;
sys_rst <= 1'b0;
# 40 sys_rst <= 1'b1;
end
breath_led i1(
sys_clk,
sys_rst,
led
);
endmodule
仿真时序分析: