实验设计
PWM模块设计非常简单,在上面的原理中已经讲到,这里不再说原理。
信号名称 | 方向 | 说明 |
clk | in | 时钟输入 |
rst | in | 异步复位输入,高复位 |
period | in | PWM脉宽周期(频率)控制。period = PWM输出频率 * (2 的N次方) / 系统时钟频率。显然N越大,频率精度越高。 |
duty | in | 占空比控制,占空比 = duty / (2的N次方)* 100% |
PWM模块(ax_pwm)端口
`timescale1ns/1ps
moduleax_pwm
#(
parameterN=16//pwmbitwidth
)
(
inputclk,
inputrst,
input[N-1:0]period, //pwmstepvalue
input[N-1:0]duty, //dutyvalue
outputpwm_out //pwmoutput
);
reg[N-1:0]period_r; //periodregister
reg[N-1:0]duty_r; //dutyregister
reg[N-1:0]period_cnt; //periodcounter
regpwm_r;
assignpwm_out=pwm_r;
always@(posedgeclkorposedgerst)
begin
if(rst==1)
begin
period_r《={N{1‘b0}};
duty_r《={N{1’b0}};
end
else
begin
period_r《=period;
duty_r《=duty;
end
end
//periodcounter,stepisperiodvalue
always@(posedgeclkorposedgerst)
begin
if(rst==1)
period_cnt《={N{1‘b0}};
else
period_cnt《=period_cnt+period_r;
end
always@(posedgeclkorposedgerst)
begin
if(rst==1)
begin
pwm_r《=1’b0;
end
else
begin
if(period_cnt》=duty_r) //ifperiodcounteri***iggerorequalstodutyvalue,thensetpwmvaluetohigh
pwm_r《=1‘b1;
else
pwm_r《=1’b0;
end
end
那么如何实现呼吸灯的效果呢?我们知道呼吸灯效果是由暗不断的变亮,再由亮不断的变暗的过程,而亮暗效果是由占空比来调节的,因此我们主要来控制占空比,也就是控制duty的值。
在下面的测试代码中,通过设置period的值,设定PWM的频率为200Hz,PWM_PLUS状态即是增加duty值,如果增加到最大值,将pwm_flag置1,并开始将duty值减少,待减少到最小的值,则开始增加duty值,不断循环。其中PWM_GAP状态为调整间隔,时间为100us。
`timescale1ns/1ps
modulepwm_test(
inputclk,//25MHz
inputrst_n,//lowactive
outputled//high-off,low-on
);
localparamCLK_FREQ=25;//25MHz
localparamUS_COUNT=CLK_FREQ;//1uscounter
localparamMS_COUNT=CLK_FREQ*1000;//1mscounter
localparamDUTY_STEP=32‘d100000;//dutystep
localparamDUTY_MIN_VALUE=32’h6fffffff;//dutyminimumvalue
localparamDUTY_MAX_VALUE=32‘hffffffff;//dutymaximumvalue
localparamIDLE=0;//IDLEstate
localparamPWM_PLUS=1;//PWMdutyplusstate
localparamPWM_MINUS=2;//PWMdutyminusstate
localparamPWM_GAP=3;//PWMdutyadjustmentgap
wirepwm_out;//pwmoutput
reg[31:0]period;//pwmstepvalue
reg[31:0]duty;//dutyvalue
regpwm_flag;//dutyvalueplusandminusflag,0:plus;1:minus
reg[3:0]state;
reg[31:0]timer;//dutyadjustmentcounter
assignled=~pwm_out;//ledlowactive
always@(posedgeclkornegedgerst_n)
begin
if(rst_n==1’b0)
begin
period《=32‘d0;
timer《=32’d0;
duty《=32‘d0;
pwm_flag《=1’b0;
state《=IDLE;
end
else
case(state)
IDLE:
begin
period《=32‘d17179;//Thepwmstepvalue,pwm200Hz(period=200*2^32/50000000)
state《=PWM_PLUS;
duty《=DUTY_MIN_VALUE;
end
PWM_PLUS:
begin
if(duty》DUTY_MAX_VALUE-DUTY_STEP)//ifdutyi***iggerthanDUTYMAXVALUEminusDUTY_STEP,begintominusdutyvalue
begin
pwm_flag《=1’b1;
duty《=duty-DUTY_STEP;
end
else
begin
pwm_flag《=1‘b0;
duty《=duty+DUTY_STEP;
end
state《=PWM_GAP;
end
PWM_MINUS:
begin
if(duty《DUTY_MIN_VALUE+DUTY_STEP)//ifdutyislittlethanDUTYMINVALUEplusdutystep,begintoadddutyvalue
begin
pwm_flag《=1’b0;
duty《=duty+DUTY_STEP;
end
else
begin
pwm_flag《=1‘b1;
duty《=duty-DUTY_STEP;
end
state《=PWM_GAP;
end
PWM_GAP:
begin
if(timer》=US_COUNT*100)//adjustmentgapis100us
begin
if(pwm_flag)
state《=PWM_MINUS;
else
state《=PWM_PLUS;
timer《=32’d0;
end
else
begin
timer《=timer+32‘d1;
end
end
default:
begin
state《=IDLE;
end
endcase
end
//Instantiatepwmmodule
ax_pwm
#(
.N(32)
)
ax_pwm_m0(
.clk(clk),
.rst(~rst_n),
.period(period),
.duty(duty),
.pwm_out(pwm_out)
);
endmodule
实验设计
PWM模块设计非常简单,在上面的原理中已经讲到,这里不再说原理。
信号名称 | 方向 | 说明 |
clk | in | 时钟输入 |
rst | in | 异步复位输入,高复位 |
period | in | PWM脉宽周期(频率)控制。period = PWM输出频率 * (2 的N次方) / 系统时钟频率。显然N越大,频率精度越高。 |
duty | in | 占空比控制,占空比 = duty / (2的N次方)* 100% |
PWM模块(ax_pwm)端口
`timescale1ns/1ps
moduleax_pwm
#(
parameterN=16//pwmbitwidth
)
(
inputclk,
inputrst,
input[N-1:0]period, //pwmstepvalue
input[N-1:0]duty, //dutyvalue
outputpwm_out //pwmoutput
);
reg[N-1:0]period_r; //periodregister
reg[N-1:0]duty_r; //dutyregister
reg[N-1:0]period_cnt; //periodcounter
regpwm_r;
assignpwm_out=pwm_r;
always@(posedgeclkorposedgerst)
begin
if(rst==1)
begin
period_r《={N{1‘b0}};
duty_r《={N{1’b0}};
end
else
begin
period_r《=period;
duty_r《=duty;
end
end
//periodcounter,stepisperiodvalue
always@(posedgeclkorposedgerst)
begin
if(rst==1)
period_cnt《={N{1‘b0}};
else
period_cnt《=period_cnt+period_r;
end
always@(posedgeclkorposedgerst)
begin
if(rst==1)
begin
pwm_r《=1’b0;
end
else
begin
if(period_cnt》=duty_r) //ifperiodcounteri***iggerorequalstodutyvalue,thensetpwmvaluetohigh
pwm_r《=1‘b1;
else
pwm_r《=1’b0;
end
end
那么如何实现呼吸灯的效果呢?我们知道呼吸灯效果是由暗不断的变亮,再由亮不断的变暗的过程,而亮暗效果是由占空比来调节的,因此我们主要来控制占空比,也就是控制duty的值。
在下面的测试代码中,通过设置period的值,设定PWM的频率为200Hz,PWM_PLUS状态即是增加duty值,如果增加到最大值,将pwm_flag置1,并开始将duty值减少,待减少到最小的值,则开始增加duty值,不断循环。其中PWM_GAP状态为调整间隔,时间为100us。
`timescale1ns/1ps
modulepwm_test(
inputclk,//25MHz
inputrst_n,//lowactive
outputled//high-off,low-on
);
localparamCLK_FREQ=25;//25MHz
localparamUS_COUNT=CLK_FREQ;//1uscounter
localparamMS_COUNT=CLK_FREQ*1000;//1mscounter
localparamDUTY_STEP=32‘d100000;//dutystep
localparamDUTY_MIN_VALUE=32’h6fffffff;//dutyminimumvalue
localparamDUTY_MAX_VALUE=32‘hffffffff;//dutymaximumvalue
localparamIDLE=0;//IDLEstate
localparamPWM_PLUS=1;//PWMdutyplusstate
localparamPWM_MINUS=2;//PWMdutyminusstate
localparamPWM_GAP=3;//PWMdutyadjustmentgap
wirepwm_out;//pwmoutput
reg[31:0]period;//pwmstepvalue
reg[31:0]duty;//dutyvalue
regpwm_flag;//dutyvalueplusandminusflag,0:plus;1:minus
reg[3:0]state;
reg[31:0]timer;//dutyadjustmentcounter
assignled=~pwm_out;//ledlowactive
always@(posedgeclkornegedgerst_n)
begin
if(rst_n==1’b0)
begin
period《=32‘d0;
timer《=32’d0;
duty《=32‘d0;
pwm_flag《=1’b0;
state《=IDLE;
end
else
case(state)
IDLE:
begin
period《=32‘d17179;//Thepwmstepvalue,pwm200Hz(period=200*2^32/50000000)
state《=PWM_PLUS;
duty《=DUTY_MIN_VALUE;
end
PWM_PLUS:
begin
if(duty》DUTY_MAX_VALUE-DUTY_STEP)//ifdutyi***iggerthanDUTYMAXVALUEminusDUTY_STEP,begintominusdutyvalue
begin
pwm_flag《=1’b1;
duty《=duty-DUTY_STEP;
end
else
begin
pwm_flag《=1‘b0;
duty《=duty+DUTY_STEP;
end
state《=PWM_GAP;
end
PWM_MINUS:
begin
if(duty《DUTY_MIN_VALUE+DUTY_STEP)//ifdutyislittlethanDUTYMINVALUEplusdutystep,begintoadddutyvalue
begin
pwm_flag《=1’b0;
duty《=duty+DUTY_STEP;
end
else
begin
pwm_flag《=1‘b1;
duty《=duty-DUTY_STEP;
end
state《=PWM_GAP;
end
PWM_GAP:
begin
if(timer》=US_COUNT*100)//adjustmentgapis100us
begin
if(pwm_flag)
state《=PWM_MINUS;
else
state《=PWM_PLUS;
timer《=32’d0;
end
else
begin
timer《=timer+32‘d1;
end
end
default:
begin
state《=IDLE;
end
endcase
end
//Instantiatepwmmodule
ax_pwm
#(
.N(32)
)
ax_pwm_m0(
.clk(clk),
.rst(~rst_n),
.period(period),
.duty(duty),
.pwm_out(pwm_out)
);
endmodule
举报