PWM频率: Freq = clk / (period+1)
PWM占空比: Duty = duty / (period + 1)
PWM模块由三部分构成,赋初值、计数、输出
module PWM
#(parameter N = 32)
(
input clk,
input rst_n,
input [N-1:0] duty,
input [N-1:0] period,
output pwm_out
);
reg [N-1:0] count;
reg [N-1:0] duty_reg;
reg [N-1:0] period_reg;
reg pwm_reg;
assign pwm_out=pwm_reg;
always @(posedge clk or negedge rst_n)//赋初值
begin
if(!rst_n)
begin
duty_reg <= 0;
period_reg <= 0;
end
else
begin
duty_reg <= duty;
period_reg <= period;
end
end
always @(posedge clk or negedge rst_n)//计数
begin
if(!rst_n)
begin
count <= 0;
end
else
begin
if(count == period_reg)
begin
count <= 0;
end
else
begin
count <= count + 1;
end
end
end
always @(posedge clk or negedge rst_n)//输出
begin
if(!rst_n)
begin
pwm_reg <= 0;
end
else
begin
if(count >= duty_reg)
begin
pwm_reg <= 0;
end
else
begin
pwm_reg <= 1;
end
end
end
endmodule
仿真图像
调用pwm模块输出在4个led上,占空比分别为1%,5%,10%,50%
`timescale 1ns / 1ps
module pwm_test
(
input sys_clk_p,
input sys_clk_n,
input rst_n,
output [3:0] led
);
wire clk;
IBUFDS #(
.DIFF_TERM("FALSE"), // Differential Termination
.IBUF_LOW_PWR("TRUE"), // Low power="TRUE", Highest performance="FALSE"
.IOSTANDARD("DEFAULT") // Specify the input I/O standard
) IBUFDS_inst (
.O(clk), // Buffer output
.I(sys_clk_p), // Diff_p buffer input (connect directly to top-level port)
.IB(sys_clk_n) // Diff_n buffer input (connect directly to top-level port)
);
reg [31:0] duty;
reg [31:0] period;
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
duty <= 0;
period <= 0;
end
else
begin
duty <= 32'd2_000;//精度为2000/2000000=0.1%
period <= 32'd2_000_000;
end
end
//调用pwm模块输出在4个led上,占空比分别为1%,5%,10%,50%
PWM PWM_1 (
.clk(clk),
.rst_n(rst_n),
.duty(10*duty),
.period(period),
.pwm_out(led[0])
);
PWM PWM_2 (
.clk(clk),
.rst_n(rst_n),
.duty(50*duty),
.period(period),
.pwm_out(led[1])
);
PWM PWM_3 (
.clk(clk),
.rst_n(rst_n),
.duty(100*duty),
.period(period),
.pwm_out(led[2])
);
PWM PWM_4 (
.clk(clk),
.rst_n(rst_n),
.duty(500*duty),
.period(period),
.pwm_out(led[3])
);