The PWM module varies the duration (time) of the high and low states of an output signal based on an internal count (modifiable Nbits) and a comparison (duty and period). This has various applications in the field of electronics, ranging from control to digital communications. PWM can be used to control the speed of a motor, among other applications.

Figure 1 – PWM Module.

 

Equations:

 

FRECpwm=output frequency of the module in Hz

CLKin= Input clock frequency in Hz

PERIODOpwm=Max value of the internal counter of the PWM.

Note: The maximum value of Duty[n:0] is determined by the value of the Period.

 

Example 1 (Modular instantiation):

If you want Frec_pwm = 20KHz and you have a period = 250, what should be the input clock frequency to the PWM module?

 

 

If we apply the formula given earlier:

 

Example 2:

Let's assume CLK_in = 50MHz, Nbits = 3, Period = 7, and a fixed duty = 3.

 

How would the output signal of the PWM module look and what is the period of the signal?

 

Figure 2 - Annotated simulation of the PWM module.

 

Figure 3 - Simulation of the PWM module

 

Applying the formula, it would be:

 

 

 

Verilog Module(PWM.v):

`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date:    18:31:09 06/04/2009 
// Design Name:    Jose Pablo Pinilla & Holguer A Becerra
// Module Name:    PWM 
// Project Name:   
// Target Devices: 
// Tool versions: 
// Description: 
//
// Dependencies: 
//
// Revision:  
// Revision 0.01 - File Created
// Additional Comments: 
//
//////////////////////////////////////////////////////////////////////////////////

module PWM #(parameter Bits_counter = 7, Periodo=3'd7)
	 (	input  clk, output motor, input  [Bits_counter-1:0] duty_cycle);	
   
   reg [Bits_counter-1:0] Timer1=0;
   reg PWM_OUTPUT;
	
	assign motor = PWM_OUTPUT; 
	
   always @(posedge clk)
	begin
		if (Timer1 >= Periodo)
			begin
					Timer1 <= 0;
					PWM_OUTPUT<=PWM_OUTPUT;
			end		
		else
		   begin
				  Timer1 <= Timer1+1; 
				  if (Timer1 >= duty_cycle)
						 PWM_OUTPUT<=1'b0;
				  else 
						PWM_OUTPUT <= 1'b1;		  
		   end
	end	
	
endmodule