How to implement a PWM in VHDL

Introduction to PWM

Pulse width modulation (PWM) is a digital technique used for controlling an analog circuit.

A PWM controller can be implemented either using a microcontroller or an FPGA digital outputs.

The PWM is employed in a wide multiplicity of applications, ranging from measurement and communications to power control, conversion.

Figure1 PWM typical waveform
Figure1 – PWM typical waveform

How can PWM control an analog circuit?

Let’s imagine we want to dimmer the intensity of a lamp. First simple possibility is to implement a partition using a variable resistor as in Figure2. Doing this the light intensity vary proportionally to the voltage present on the lamp pin, varying the resistor R2. In this approach the voltage on lamp VL is the partition of Vs on R1 and RLT, where RLT is the total resistance given by the parallel of R2 and RL This approach is not so efficient in terms of power consumption, in fact when we want use maximum power on the lamp R2 is set to have high impedance, i.e. can be considered open, and all the current flows on R1 and the lamp. When the lamp light is attenuated this means that R2 values is low, i.e. few ohms. This means that the current flows on R1 and R2. Using this approach, when we need light attenuation, R1 and R2 shall be able to dissipate all the power not used in the lamp.

As you can understand this is not an optimal approach!

Figure2 - Lamp dimmer using variable resistor
Figure2 – Lamp dimmer using variable resistor


A more efficient approach can be this one. Imagine that you can be able to turn on and off your lamp very fast. In this case, you can modulate the light simply modifying the duty cycle of your switch. If you need max light leave the switch always on, if you want to attenuate the light vary the duty proportionally. The average voltage on the lamp pin is the average voltage in the PWM period:

VL = (Vs x Ton)/Tp = Vs x DutyCycle

Figure3 - Dimmer a lamp using digital control like PWM
Figure3 – Dimmer a lamp using digital control like PWM

Of course, when the switch is off, no current flow on your circuit and no power is wasted!

This is a very simple method for using PWM to control a lamp. You can use the same approach to control a motor.

The PWM parameter

Let’ see what are the main parameter to define a PWM waveform of Figure1:

  • Modulating Period: the time between two consecutive ON period
  • Duty Cycle: the ratio of the on-time to the period;
  • Modulating Frequency: is the inverse of the period.


VHDL implementation of PWM

In order to implement a PWM in VHDL, we need a simple counter as in Figure4.

Figure4 - Example on hardware PWM architecture
Figure4 – Example on hardware PWM architecture

The PWM period is defined as the number of clock counter we want the counter counts before restart counting. When the counter value is less than the PWM-width value the PWM output is high, else is low.

So let’ see an example of a VHDL code for a PWM:

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity pwm_prog is
  N                     : integer := 8);      -- number of bit of PWM counter
port (
  i_clk                       : in  std_logic;
  i_rstb                      : in  std_logic;
  i_sync_reset                : in  std_logic;
  i_pwm_module                : in  std_logic_vector(N-1 downto 0);  -- PWM Freq  = clock freq/ (i_pwm_module+1); max value = 2^N-1
  i_pwm_width                 : in  std_logic_vector(N-1 downto 0);  -- PWM width = (others=>0)=> OFF; i_pwm_module => MAX ON 
  o_pwm                       : out std_logic);
end pwm_prog;

architecture rtl of pwm_prog is

signal r_max_count                           : unsigned(N-1 downto 0);
signal r_pwm_counter                         : unsigned(N-1 downto 0);
signal r_pwm_width                           : unsigned(N-1 downto 0);
signal w_tc_pwm_counter                      : std_logic;


w_tc_pwm_counter  <= '0' when(r_pwm_counter<r_max_count) else '1';  -- use to strobe new word

p_state_out : process(i_clk,i_rstb)
  if(i_rstb='0') then
    r_max_count     <= (others=>'0');
    r_pwm_width     <= (others=>'0');
    r_pwm_counter   <= (others=>'0');
    o_pwm           <= '0';
  elsif(rising_edge(i_clk)) then
    r_max_count     <= unsigned(i_pwm_module);
    if(i_sync_reset='1') then
      r_pwm_width     <= unsigned(i_pwm_width);
      r_pwm_counter   <= to_unsigned(0,N);
      o_pwm           <= '0';
      if(r_pwm_counter=0) and (r_pwm_width/=r_max_count) then
        o_pwm           <= '0';
      elsif(r_pwm_counter<=r_pwm_width) then
        o_pwm           <= '1';
        o_pwm           <= '0';
      end if;
      if(w_tc_pwm_counter='1') then
        r_pwm_width      <= unsigned(i_pwm_width);
      end if;
      if(r_pwm_counter=r_max_count) then
        r_pwm_counter   <= to_unsigned(0,N);
        r_pwm_counter   <= r_pwm_counter + 1;
      end if;
    end if;
  end if;
end process p_state_out;

end rtl;


Parameter of VHDL PWM code

The generic parameter “N” set at compile time the number of bit of the PWM counter. This parameter set the maximum number of bit of the PWM counter.

The input signal “i_pwm_module” is used as the terminal counter value for the PWM counter. Every time the PWM counter reaches the value “i_pwm_module” it restarts from zero. The PWM period is:

Tclk x (i_pwm_module+1)

Or the PWM frequency is

Fpwm = Fclk / (i_pwm_module+1)


The PWM HIGH/LOW time is set using input signal “i_pwm_width

When “i_pwm_width” is

  • Zero => PWM output is always LOW
  • i_pwm_module => PWM output is always HIGH
  • K => PWM is K clock cycle HIGH and (i_pwm_width-K) LOW


VHDL implementation of the programmable PWM on DE0 Altera BOARD

In this video, you can learn how to implement the VHDL code of the PWM described above. The PWM is implemented on a DE0 Altera board. The PWM code is tested using the DE0 board LED: varying PWM duty cycle the light intensity will vary. You can download the complete PWM VHDL project files here below.



PWM VHDL code simulation results

Figure5 reports the PWM VHDL code simulation where the number of PWM counter is set to 8, PWM period is 256 clock cycle and PWM width is  set to 10. In the simulation, the clock period is 10 ns.

Figure5 - simulation of VHDL PWM code
Figure5 – simulation of VHDL PWM code


Layout results

Just to have a feedback on PWM implementation on FPGA, in Figure6 is reported the RTL viewer results for the PWM VHDL code above. The examples is relative to an Altera Cyclone II  FPGA

Figure6 - PWM layout example, RTL viewer
Figure6 – PWM layout example, RTL viewer


If you appreciated this post, please help us to share it with your friend.

If you need to contact us, please write to:

We appreciate any of your comment, please post below:

One thought to “How to implement a PWM in VHDL”

  1. hi
    is it possible to know how to use the PWM signal with gpio in order to controle a moter,

    best regards

Leave a Reply

Your email address will not be published. Required fields are marked *