FPGA ile PWM Sinyali Üretimi

PWM (Pulse Witdh Modulation) yani Darbe Genişlik Modülasyonu, \frac{\mathbf{t}_\mathbf{h}}{\mathbf{T}} oranının değiştirilebildiği sinyal modülasyondur. \frac{\mathbf{t}_\mathbf{h}}{\mathbf{T}} oranı Duty Cycle olarak adlandırılır ve \% ile ifade edilir. Aşağıda bir PWM sinyali görülmektedir.

M ortalama değer olmak üzere duty cycle oranının değişmesi ile sinyalin ortalama değeri değişir:

\begin{align*}M=\frac{1}{\mathit{T}}\int_0^\mathit{T}f(t)\,dt\end{align*}

\begin{align*}M=\frac{1}{\mathit{T}}\bigg[\int_0^\mathit{D}f(t)\,dt+\int_\mathit{D}^\mathit{T}f(t)\,dt\bigg]\end{align*}

\begin{align*}M=\frac{1}{\mathit{T}}\bigg[\int_0^\mathit{D}(0)\,dt+\int_\mathit{D}^\mathit{T}(1)\,dt\bigg]\end{align*}

\begin{align*}M=\frac{1}{\mathit{T}}\bigg[\mathit{T}-\mathit{D}\bigg]\end{align*}

\begin{align*}M=1-\frac{\mathit{D}}{\mathit{T}}=\mathit{Duty}\end{align*}

Bu sayede sinyalin gerilimini değiştirmeden yük üzerinde harcanan ortalama güç ayarlanmış olur.

FPGA üzerinde PWM sinyal üretebilmek için A ve B kontrol değişkenlerimiz olsun. Bu A ve B değişkenleri aşağıdaki gibi tanımlanmış olsun:

Tasarımın VHDL kodu:


--Kütüphaneler
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
USE ieee.numeric_std.ALL; 

entity PWM_Module is
    port(Clk : in std_logic;                        --Clk Girişi
        A, B : in std_logic_vector(15 downto 0);     --Kontrol Girişleri
                                                     --PWM Frekansı = Clk / A
                                                                    --Duty Cycle = 1 - B / A
        PWMOut : out std_logic);                     --PWM Çıkışı
end PWM_Module;

architecture Behavioral of PWM_Module is
    
begin

    --PWM Sinyalinin Üretildiği Process
    process(Clk, A, B)
    variable ClkCnt : unsigned(15 downto 0) := (others => '0');
    begin
        if rising_edge(Clk) then
            --ClkCnt, A'dan küçük ise ClkCnt değerini 1 arttır
            if ClkCnt < unsigned(A) then                 ClkCnt := ClkCnt + 1;             --Değil ise sıfırla             else                 ClkCnt := (others => '0');
            end if;
        end if;
        
        --ClkCnt, B'den küçük ise PWMOut'a '0' ata
        if ClkCnt < unsigned(B) then
            PWMOut <= '0';
        --Değil ise '1' ata
        else
            PWMOut <= '1';
        end if;
    end process;

end Behavioral;

Quartus II programı tarafından oluşturulan RTL şeması:

PWM ile Led Parlaklık Kontrolü

VHDL kodu:

--Kütüphaneler
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
USE ieee.numeric_std.ALL; 

entity PWM_Led is
    port(Clk : in std_logic;                        --Clk Girişi
        Led : out std_logic_vector(15 downto 0));    --Led çıkışı
end PWM_Led;

architecture Behavioral of PWM_Led is
    
--PWM komponentinin çağrılması
component PWM_Module
    port(Clk : in std_logic;                        --Clk Girişi
        A, B : in std_logic_vector(15 downto 0);     --Kontrol Girişleri
                                                     --PWM Frekansı = Clk / A
                                                                    --Duty Cycle = 1 - B / A
        PWMOut : out std_logic);                     --PWM Çıkışı
end component;    

    signal PWMOut : std_logic;
    signal B : std_logic_vector(15 downto 0) := (others => '0');
    
begin

    --PWM komponenti
    --PWM freknası 50Mhz / 0x01F4 = 100khz
    PWM : PWM_Module
        port map(Clk, X"01F4", B, PWMOut);
        
    process(Clk)
    variable ClkCnt : integer range 0 to 250000 := 0;
    variable YukariAsagi : boolean := true;
    begin
    
        --100khz çıkışlı clock bölücü
        if rising_edge(Clk) then
            if ClkCnt < 249999 then
                ClkCnt := ClkCnt + 1;
            else
                ClkCnt := 0;
                
                --YukarıAsagi değişkeni true ise B sinyalinin değerini 1 arttır
                if YukariAsagi then
                    B <= std_logic_vector(unsigned(B) + 1);
                
                --False ise 1 azalt
                else
                    B <= std_logic_vector(unsigned(B) - 1);                 end if;             end if;                          --Duty cycle %10 ile %80 arasında değişmekte             if unsigned(B) > 449 then
                YukariAsagi := false;
            elsif unsigned(B) < 101 then
                YukariAsagi := true;
            end if;
            
        end if;
    end process;
    
    --Bütün ledleri PWMOut sinyaline bağla
    Leds : for i in 0 to 15 generate
        Led(i) <= PWMOut;
    end generate;
    

end Behavioral;

Video:

2 thoughts on “FPGA ile PWM Sinyali Üretimi”

  1. Sanırım bölümün elektronik haberleme 🙂 FPGA eğitimine nereden nasık başladın bu konuda bilgi verebilir misin ?

    1. Bölümüm Elektrik-Elektronik. FPGA'ya uzun zamandır başlamak istemişimdir. Kitlerin fiyatlarında dolayı bu yılın başında ilk FPGA kitimi alabildim. Kiti aldığımdan beri çeşitli projeler yaparak kendimi geliştiriyorum.

Bir cevap yazın

E-posta hesabınız yayımlanmayacak.