所用器材
EP4CE6E22C8N板子,下载器。
PWM方波生成原理
根据输入时钟信号,设置PWM方波的周期(即计数多少个时钟信号周期为一个PWM方波周期),然后设置占空比时长(修改在该PWM信号内高电平持续时间或者低电平持续时间)。使用Verilog编写该PWM生成模块的过程,与使用51单片机利用定时器中断生成PWM方波的原理有点像。
原理框架
假如,输入时钟频率是50MHz,这里设定1ms为一个PWM周期,也就是需要数50000个时钟上升沿(或者下降沿)为一个周期。然后设定一个占空比数值,数值为0~50000。例如:设置了占空比为25000,则当前计数量(当前周期开始到现在一共数了多少个上升沿)和占空比数值作比较,若当前计数量<=占空比数值,则输出高电平;若当前计数量>占空比数值,则输出低电平(高低电平反转也可以,逻辑调转即可)。
呼吸灯例子
代码如下:
module breath_led(
input sys_clk , //时钟信号50Mhz
input sys_rst_n , //复位信号
output led //LED
);
//reg define
reg [15:0] period_cnt ;
//周期计数器频率:1khz 周期:1ms 计数值:1ms/20ns=50000
reg [15:0] duty_cycle ;
//占空比数值
reg inc_dec_flag ;
//0 递增 1 递减
//根据占空比和计数值之间的大小关系来输出LED,相当于比较器
assign led = (period_cnt <= duty_cycle)?1'b1:1'b0;
//周期计数器
always @(posedge sys_clk or negedge sys_rst_n) begin
if(!sys_rst_n)//如果复位了,PWM周期period_cnt清零
period_cnt <= 16'd0;
else if(period_cnt == 16'd50000)//PWM周期period_cnt满1ms,清零
period_cnt <= 16'd0;
else
period_cnt <= period_cnt + 1'b1;
end
always @(posedge sys_clk or negedge sys_rst_n) begin
if(!sys_rst_n) //如果复位了,PWM占空比清零,增减标志位清零
begin
duty_cycle <= 16'd0;//如果复位了,占空比清零
inc_dec_flag <= 1'b0;//如果复位了,标志位清零
end
else
begin
if(period_cnt == 16'd50000) //计满1ms
begin
if(inc_dec_flag == 1'b0)//满足本周期
begin
if(duty_cycle == 16'd50000)
//如果占空比已递增至最大
inc_dec_flag <= 1'b1;
//则占空比开始递减
else//否则占空比以25为单位递增
duty_cycle <= duty_cycle + 16'd50;
end
else
begin//占空比递减状态
if(duty_cycle == 16'd0)//如果占空比已递减至0
inc_dec_flag <= 1'b0; //则占空比开始递增
else//否则占空比以25为单位递减
duty_cycle <= duty_cycle - 16'd50;
end
end
else;
end
end
endmodule
本代码中,有一个PWM占空比增减标志位。根据这个增减标志位,每次一个PWM周期结束时,这个占空比就会根据这个占空比增减标志位对占空比进行修改。占空比从刚开始的0增加到50000,然后从50000减少到0,从而达到呼吸灯的效果。
标签:cnt,period,生成,sys,else,模块,占空比,PWM From: https://www.cnblogs.com/chapman-fpga/p/17056792.html