DEV Community

Hedy
Hedy

Posted on

1

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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;
Enter fullscreen mode Exit fullscreen mode

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]
Enter fullscreen mode Exit fullscreen mode

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;
Enter fullscreen mode Exit fullscreen mode

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.

Heroku

Built for developers, by developers.

Whether you're building a simple prototype or a business-critical product, Heroku's fully-managed platform gives you the simplest path to delivering apps quickly — using the tools and languages you already love!

Learn More

Top comments (0)

ACI image

ACI.dev: The Only MCP Server Your AI Agents Need

ACI.dev’s open-source tool-use platform and Unified MCP Server turns 600+ functions into two simple MCP tools on one server—search and execute. Comes with multi-tenant auth and natural-language permission scopes. 100% open-source under Apache 2.0.

Star our GitHub!

👋 Kindness is contagious

Engage with a wealth of insights in this thoughtful article, cherished by the supportive DEV Community. Coders of every background are encouraged to bring their perspectives and bolster our collective wisdom.

A sincere “thank you” often brightens someone’s day—share yours in the comments below!

On DEV, the act of sharing knowledge eases our journey and forges stronger community ties. Found value in this? A quick thank-you to the author can make a world of difference.

Okay