Generating a PWM Square Wave Using an FPGA

Generating a PWM (Pulse Width Modulation) signal with an FPGA involves configuring a counter-comparator logic block to control the duty cycle and frequency. Below is a step-by-step guide using Verilog/VHDL for implementation on Xilinx (Artix-7/Kintex-7) or Intel (Cyclone/MAX 10) FPGAs. 1. PWM Basics PWM = A square wave with adjustable duty cycle (pulse width) and frequency. Duty Cycle = (ON time) / (Total Period) × 100% Frequency = 1 / (Total Period) 2. Hardware Requirements FPGA Board (e.g., Xilinx Artix-7, Intel Cyclone IV). Clock Source (e.g., 50 MHz onboard oscillator). Output Pin (connected to LED, motor driver, or oscilloscope). 3. PWM Implementation in Verilog A. Simple PWM Generator verilog module pwm_generator ( input clk, // FPGA clock (e.g., 50 MHz) input reset, // Active-high reset input [7:0] duty, // 8-bit duty cycle (0-255 = 0%-100%) output reg pwm_out // PWM output signal ); reg [7:0] counter; // 8-bit counter (0-255) always @(posedge clk or posedge reset) begin if (reset) begin counter

May 7, 2025 - 09:17
 0
Generating a PWM Square Wave Using an FPGA

Generating a PWM (Pulse Width Modulation) signal with an FPGA involves configuring a counter-comparator logic block to control the duty cycle and frequency. Below is a step-by-step guide using Verilog/VHDL for implementation on Xilinx (Artix-7/Kintex-7) or Intel (Cyclone/MAX 10) FPGAs.

Image description

1. PWM Basics

  • PWM = A square wave with adjustable duty cycle (pulse width) and frequency.
  • Duty Cycle = (ON time) / (Total Period) × 100%
  • Frequency = 1 / (Total Period)

2. Hardware Requirements

  • FPGA Board (e.g., Xilinx Artix-7, Intel Cyclone IV).
  • Clock Source (e.g., 50 MHz onboard oscillator).
  • Output Pin (connected to LED, motor driver, or oscilloscope).

3. PWM Implementation in Verilog
A. Simple PWM Generator

verilog
module pwm_generator (
    input clk,          // FPGA clock (e.g., 50 MHz)
    input reset,        // Active-high reset
    input [7:0] duty,   // 8-bit duty cycle (0-255 = 0%-100%)
    output reg pwm_out  // PWM output signal
);

reg [7:0] counter;      // 8-bit counter (0-255)

always @(posedge clk or posedge reset) begin
    if (reset) begin
        counter <= 0;
        pwm_out <= 0;
    end
    else begin
        counter <= counter + 1;
        pwm_out <= (counter < duty) ? 1 : 0;  // Compare & set PWM
    end
end

endmodule

Key Points:

  • duty controls the ON time (e.g., duty = 128 → 50% duty cycle).
  • Frequency = clk_freq / (2^counter_bits) (e.g., 50 MHz / 256 ≈ 195.3 kHz for 8-bit counter).

B. Adjustable Frequency PWM
To control both frequency and duty cycle, add a period register:

verilog
module pwm_advanced (
    input clk,
    input reset,
    input [15:0] period,  // Total clock cycles per PWM period
    input [15:0] duty,    // ON time (must be ≤ period)
    output reg pwm_out
);

reg [15:0] counter;

always @(posedge clk or posedge reset) begin
    if (reset) begin
        counter <= 0;
        pwm_out <= 0;
    end
    else begin
        if (counter >= period - 1)
            counter <= 0;
        else
            counter <= counter + 1;

        pwm_out <= (counter < duty) ? 1 : 0;
    end
end

endmodule

Example Settings:
For 1 kHz PWM with 50 MHz clock:
period = 50,000,000 / 1,000 = 50,000
duty = 25,000 → 50% duty cycle.

4. PWM Implementation in VHDL

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  : in  STD_LOGIC_VECTOR (7 downto 0);
        pwm   : out STD_LOGIC
    );
end pwm_generator;

architecture Behavioral of pwm_generator is
    signal counter : unsigned(7 downto 0) := (others => '0');
begin
    process(clk, reset)
    begin
        if reset = '1' then
            counter <= (others => '0');
            pwm <= '0';
        elsif rising_edge(clk) then
            counter <= counter + 1;
            if counter < unsigned(duty) then
                pwm <= '1';
            else
                pwm <= '0';
            end if;
        end if;
    end process;
end Behavioral;

5. Testing PWM on Hardware
A. Pin Assignment
Connect pwm_out to an FPGA GPIO pin (check your board’s constraints file).

Example (Xilinx Artix-7):

tcl
set_property PACKAGE_PIN "R10" [get_ports pwm_out]
set_property IOSTANDARD LVCMOS33 [get_ports pwm_out]

B. Verification

  1. Oscilloscope: Check PWM waveform.
  2. LED: Vary duty to see brightness change.
  3. Logic Analyzer: Capture duty cycle transitions.

6. Advanced PWM Techniques
A. Dead-Time Insertion (For H-Bridge Motors)

  • Adds a small delay between PWM transitions to prevent shoot-through.
  • Requires two complementary PWM signals with adjustable delay.

B. Center-Aligned PWM

  • Used in motor control for symmetric waveforms.
  • Implemented with up/down counters:
verilog
if (direction == UP) 
    counter <= counter + 1;
else 
    counter <= counter - 1;

C. Using FPGA IP Cores
Xilinx "AXI Timer" or Intel "PWM IP Core" for hardware-optimized PWM.

7. Example Applications

  1. Motor Speed Control (H-Bridge driver).
  2. LED Dimming (adjust brightness).
  3. Servo Control (1-2 ms pulses @ 50 Hz).
  4. Audio Generation (class-D amplifiers).

Conclusion

  • Basic PWM = Counter + Comparator.
  • Frequency depends on clock speed and counter resolution.
  • Duty cycle is set by comparing counter to a threshold.
  • FPGAs excel at PWM due to parallel hardware control.