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 <= 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
- Oscilloscope: Check PWM waveform.
- LED: Vary duty to see brightness change.
- 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
- Motor Speed Control (H-Bridge driver).
- LED Dimming (adjust brightness).
- Servo Control (1-2 ms pulses @ 50 Hz).
- 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.
Top comments (0)