0
0
VhdlHow-ToBeginner · 3 min read

VHDL Code for PWM Generator: Syntax and Example

A PWM generator in VHDL uses a counter and a compare value to create a pulse-width modulated signal. The process block increments a counter and sets the output high when the counter is less than the duty cycle value, otherwise low. This creates a PWM signal with adjustable duty cycle.
📐

Syntax

The basic syntax for a PWM generator in VHDL includes a clock input, a counter, a duty cycle input, and a PWM output signal. The process block runs on the clock's rising edge, increments the counter, and compares it to the duty cycle to set the output.

  • clk: Clock input signal.
  • reset: Resets the counter to zero.
  • duty_cycle: Input controlling the pulse width.
  • pwm_out: Output PWM signal.
  • counter: Counts clock cycles to generate PWM period.
vhdl
process(clk, reset)
begin
  if reset = '1' then
    counter <= (others => '0');
    pwm_out <= '0';
  elsif rising_edge(clk) then
    if counter < MAX_COUNT then
      counter <= counter + 1;
    else
      counter <= (others => '0');
    end if;

    if counter < duty_cycle then
      pwm_out <= '1';
    else
      pwm_out <= '0';
    end if;
  end if;
end process;
💻

Example

This example shows a PWM generator with a 8-bit counter and adjustable duty cycle input. The PWM output changes its high time based on the duty cycle value.

vhdl
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;

entity pwm_generator is
  Port (
    clk        : in  STD_LOGIC;
    reset      : in  STD_LOGIC;
    duty_cycle : in  UNSIGNED(7 downto 0); -- 8-bit duty cycle
    pwm_out    : out STD_LOGIC
  );
end pwm_generator;

architecture Behavioral of pwm_generator is
  signal counter : UNSIGNED(7 downto 0) := (others => '0');
  constant MAX_COUNT : UNSIGNED(7 downto 0) := "11111111"; -- 255
begin
  process(clk, reset)
  begin
    if reset = '1' then
      counter <= (others => '0');
      pwm_out <= '0';
    elsif rising_edge(clk) then
      if counter < MAX_COUNT then
        counter <= counter + 1;
      else
        counter <= (others => '0');
      end if;

      if counter < duty_cycle then
        pwm_out <= '1';
      else
        pwm_out <= '0';
      end if;
    end if;
  end process;
end Behavioral;
Output
The output is a PWM signal on pwm_out with a period of 256 clock cycles and a high pulse width controlled by duty_cycle input.
⚠️

Common Pitfalls

Common mistakes when writing a PWM generator in VHDL include:

  • Not resetting the counter properly, causing unpredictable PWM output.
  • Using a duty cycle value larger than the counter max, which can cause the output to stay high or low incorrectly.
  • Not using unsigned types for counters and duty cycle, leading to comparison errors.
  • Forgetting to use rising_edge(clk) for synchronous counting.

Always ensure the counter resets and the duty cycle is within valid range.

vhdl
process(clk, reset)
begin
  if reset = '1' then
    counter <= (others => '0'); -- Correct reset
  elsif rising_edge(clk) then
    if counter < MAX_COUNT then
      counter <= counter + 1;
    else
      counter <= (others => '0');
    end if;

    -- Wrong: duty_cycle > MAX_COUNT can cause issues
    if counter < duty_cycle then
      pwm_out <= '1';
    else
      pwm_out <= '0';
    end if;
  end if;
end process;
📊

Quick Reference

PWM Generator Key Points:

  • Use an unsigned counter to count clock cycles.
  • Reset counter synchronously or asynchronously.
  • Compare counter with duty cycle to set output.
  • Duty cycle controls pulse width (0 to max count).
  • Use rising edge of clock for synchronous operation.

Key Takeaways

Use a counter and compare it with the duty cycle to generate PWM output.
Reset the counter properly to avoid glitches in the PWM signal.
Ensure duty cycle input is within the counter's range to prevent errors.
Use unsigned types and rising_edge(clk) for correct synchronous behavior.
Adjust duty cycle to control the pulse width of the PWM signal.