pwm信号生成电路

一、原理

我们需要两个计数器cnt1cnt2

  • cnt1随系统时钟同步计数(系统时钟上升沿时cnt1加1),范围为0~ T
  • cnt2cnt1的周期同步计数(每当cnt1等于T时,cnt2加1)范围也是0~ T

这样每次cnt10 ~ T的计数时,cnt2为一个固定值,相邻cnt1计数周期对应的cnt2的值逐渐增大,每次将cnt1cnt2进行大小比较,不同比较结果下设置pwm信号为高电平或者低电平即可。

我们将cnt1计数0~T的时间作为脉冲周期,cnt2的值作为脉冲宽度,则占空比 = cnt2/T,占空比从0%—100%(或者100%—0%)的时间 =cnt2*cnt1 = T^2 (单位是clk周期)
在这里插入图片描述

二、Verilog代码实现

1、RTL代码

module pwm_gen(clk,rst,pwm);
 
	input clk;             //系统时钟输入
	input rst;             //复位输出
	output pwm;            //pwm输出
 
	reg [24:0] cnt1;       //计数器1
	reg [24:0] cnt2;       //计数器2
	reg flag;              //呼吸灯变亮和变暗的标志位
 
 	//这里设置成4,意思就是pwm信号的占空比从100%---0%所需时间是4*4=16个clk周期
	parameter   CNT_NUM = 4;	//也即上文中提到的T值
	
	
	//产生计数器cnt1
	always@(posedge clk or negedge rst) begin 
		if(!rst) begin
			cnt1<=13'd0;
		end 
        else begin
		     if(cnt1>=CNT_NUM-1) 
                   cnt1<=1'b0;
		     else 
                   cnt1<=cnt1+1'b1; 
         end
	 end
 
	//产生计数器cnt2
	always@(posedge clk or negedge rst) begin 
		if(!rst) begin
			cnt2<=13'd0;
			flag<=1'b0;
			end 
        else begin
		     if(cnt1==CNT_NUM-1) begin //当计数器1计满时计数器2开始计数加一或减一
				if(!flag) begin //当标志位为0时计数器2递增计数,表示pwm信号占空比逐渐增加
					//计数器2计满时,表示占空比已最大,标志位变高,之后计数器2开始递减
					if(cnt2>=CNT_NUM-1) 
                         flag<=1'b1;
					else
                         cnt2<=cnt2+1'b1;
			 	end 
			 	else begin     //当标志位为高时计数器2递减计数
					if(cnt2<=0)//计数器2级到0,表示占空比已最小,标志位变低,之后计数器2开始递增
                     	flag<=1'b0;
					else 
                     	cnt2<=cnt2-1'b1;
			 	end
			 end
             else cnt2<=cnt2; //计数器1在计数过程中计数器2保持不变
		end
    end
 
	//比较计数器1和计数器2的值产生自动调整占空比输出的信号,即我们想要的pwm信号
	assign	pwm= (cnt1<cnt2)?1'b0:1'b1;
 
endmodule

2、仿真程序

`timescale  1ns / 1ps

module tb_pwm_gen;

// pwm_gen Parameters
parameter PERIOD   = 10  ;
parameter CNT_NUM  = 4;

// pwm_gen Inputs
reg   clk                                  = 0 ;
reg   rst_n                                = 0 ;

// pwm_gen Outputs
wire  pwm                                  ;


initial
begin
    forever #(PERIOD/2)  clk=~clk;
end

initial
begin
    #(PERIOD*2) rst_n  =  1;
end

pwm_gen #(
    .CNT_NUM ( CNT_NUM ))
 u_pwm_gen (
    .clk                     ( clk   ),
    .rst_n                   ( rst_n ),

    .pwm					 ( pwm   )
);


endmodule

3、仿真结果

在这里插入图片描述
仿真时将CNT_NUM设置成了比较小的一个值:4,也是为了方便快速看到结果。

posted @ 2020-10-31 20:36  耐心的小黑  阅读(306)  评论(0编辑  收藏  举报