Zaman zaman tasarımlarımızda kullandığımız saat kaynağından daha yavaş çalışan, daha düşük frekanslı saat kaynaklarına ihtiyaç duyarız. Bu durumda kullanabileceğimiz çeşitli yöntemler mevcuttur. Örneğin FPGA üzreticileri tarafından sağlanan PLL (Phase Locked Loop), DCM (Digital Clock Manager) gibi hazır tasarım kütüphaneleri kullanılabilir. Bir diğer basit yaklaşım ise bir sayıcı kullanarak frekansı düşürmektir. Sayıcı kullanarak frekans bölmenin birden fazla yolu mevcuttur. Bu örnek uygulamada kullandığımız yol ise sayıcının her bir bitini saat kaynağı olarak kullanılması şeklindedir.
Bu kullanımın temelinde yatan fikir son derece basittir. Örneğin elimizde 3 bitlik bir sayıcı olduğunu kabul edelim. Bu sayıcının tüm durumları Tablo 1’de verildiği gibi olacaktır:
Tablo 1 3 bitlik sayıcının tüm durumları
Frekans bölme işleminin mantığını anlamak için şu kabulleri yapalım:
- Çalışma frekansımız f olsun.
- Sayıcımın yükselen kenar tetiklemeli çalışsın.
Bu durumda sayıcımızın bir çalışma döngüsünün uzunluğu (clock cycle), yani yükselen iki kenar arasındaki süremiz aşağıda verilen formül ile gösterilebilir. t süreyi temsil etmek üzere, frekans ve süre arasındaki ilişki:
t=1/f f=1/t
Bu durumda sayıcının her sayma işlemi için t kadar süre gerekmektedir. Bu durumda Tablo 1’deki 0 ve 1 değişimlerine bakarsak şu yorumları yapabiliriz:
- Bit_0 için iki yükselen kenar arasındaki süre 2t olmaktadır. ‘0’ için t , ‘1’ için t .
- Bit_1 için iki yükselen kenar arasındaki süre 4t olmaktadır. ‘0’ için 2t , ‘1’ için 2t .
- Bit_2 için iki yükselen kenar arasındaki süre 8t olmaktadır. ‘0’ için 4t , ‘1’ için 4t .
Yukarıda verilen formülü düzenleyip yeni frekans değerlerimizi hesaplarsak aşağıdaki bağıntıları elde ederiz:
- Bit_0 için : fyeni = 1 / 2t
- Bit_1 için : fyeni = 1 / 4t
- Bit_2 için : fyeni = 1 / 8t
Bu yöntemi genelleştirerek 2’nin kuvvetleri şeklinde istenilen frekans bölme değerleri elde edilebilmektedir. Eğer daha hassas bir şekilde çalışılmak isteniyor ve bu yöntemle istenilen frekans değeri elde edilemiyor ise FPGA üreticisi tarafından sağlanan PLL, DCM gibi hazır tasarım kütüphanelerinin kullanılması daha iyi olacaktır.
Örnek 1 : Şekil 1’de blok diyagramı verilen saat frekans bölücü devresi tasarımının gerçekleştirildiği saat_frekans_bolucu.vhd VHDL kodu aşağıda verilmiştir. Şekil 1’den de görüleceği üzere saat_frekans_bolucu varlığımız saat darbe frekansını 2, 4, 8, 16 ve generic olaran belirlenen N parametresine bölerek çıkış üretmektedir.
Şekil 1 sayac_generic varlığı benzetim çıktısı
sayac_generic varlığımıza ilişkin generic bildirimleri 6-8. satırlarda, port bildirimleri 9-17. satırları arasında yapılmaktıdır. generic atama işleminde N parametresi değerine 16 atanmaktadır. Bunun anlamı saat darbe frekansının 16’ya bölüneceğidir. Port tanımlama işlemlerindende görüleceği üzere sayac_generic varlığı in_clk ve in_rst giriş portlarına, out_clk_2, out_clk_4, out_clk_8, out_clk_16 ve out_clk_N çıkış portlarına sahiptir. 21. satırda tanımlanan 4 bitlik r_sayac sinyali ile out_clk_2, out_clk_4, out_clk_8 ve out_clk_16 çıkış portlarınının değerleri tanımlanmaktadır. 22. satırda tanımlan r_sayac_N sinyali ise de out_clk_N sinyalinin değerinin belirlenmesinde kullanılır.
25. satırda r_sayac değerinin 0. biti out_clk_2 değerine atanmarak frekans değeri 2’ye bölünmektedir.
26. satırda r_sayac değerinin 1. biti out_clk_4 değerine atanmarak frekans değeri 4’e bölünmektedir.
27. satırda r_sayac değerinin 2. biti out_clk_8 değerine atanmarak frekans değeri 8’e bölünmektedir.
28. satırda r_sayac değerinin 3. biti out_clk_16 değerine atanmarak frekans değeri 16’ya bölünmektedir.
29. satırda ise r_sayac_N değeri eğer generic parametre N / 2 değerinden küçün ise out_clk_N çıkışına ‘0’ değeri atanmaktadır. Aksi durumda ise out_clk_N çıkışına ‘1’ değeri atanmaktadır.
38. satırda ise her saat darbesi yükselen kenarında r_sayac değeri bir artırılmkatadır. 39-43 satırları asında saat darbesi yükselen kenar darbesi ile birlikte r_sayac_N değeri N – 1 değerine eşit ise r_sayac_N değeri sıfırlanmakatadır. Aksi durumlar da ise r_sayac_N değeri bir artırılmaktadır.
library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_SIGNED.ALL; entity saat_frekans_bolucu is generic( N : integer := 16 ); Port ( in_clk : in std_logic; in_rst : in std_logic; out_clk_2 : out std_logic; out_clk_4 : out std_logic; out_clk_8 : out std_logic; out_clk_16 : out std_logic; out_clk_N : out std_logic ); end saat_frekans_bolucu; architecture Behavioral of saat_frekans_bolucu is signal r_sayac : std_logic_vector(3 downto 0) := (others => '0'); signal r_sayac_N : integer := 0; begin out_clk_2 <= r_sayac(0); out_clk_4 <= r_sayac(1); out_clk_8 <= r_sayac(2); out_clk_16 <= r_sayac(3); out_clk_N <= '0' when r_sayac_N < N / 2 else '1'; process(in_clk, in_rst) begin if in_rst = '1' then r_sayac <= (others => '0'); r_sayac_N <= 0; elsif rising_edge(in_clk) then r_sayac <= r_sayac + 1; if r_sayac_N = N - 1 then r_sayac_N <= 0; else r_sayac_N <= r_sayac_N + 1; end if; end if; end process; end Behavioral;
Aşağıda ise sayac_generic varlığının benzetim yapılabilmesi için tb_sayac_generic.vhd sınama kodu verilmiştir ve benzetim çıktıları Şekil 2 ve Şekil 3’de gösterilmiştir. Şekil 2’de gösterilen benzetim sonucunda:
1. adım:in_rst giriş portunundeğeri ‘1’ olması nedeniyle r_sayac ve r_sayac_N sinyallerinin değerleri sıfırlanmatakdır. Bu nedenle tüm çıkışlara ‘0’ değeri atanmatakdır.
2. adım:in_rst giriş portunundeğerinin ‘0’ olması ve in_clk giriş portunun yükselen kenarı ile birlikte r_sayac sinyalinin değeri bir artırılmaktadır ve değeri “0001” olmaktadır. Bu nedenle out_clk_2 cikis çıkış portu değeri ‘1’ ve out_clk_4 çıkış portu değeri ‘0’ olmaktadır.
3. adım:in_rst giriş portunundeğerinin ‘0’ olması ve in_clk giriş portunun yükselen kenarı ile birlikte r_sayac sinyalinin değeri bir artırılmaktadır ve değeri “0010” olmaktadır. Bu nedenle out_clk_2 cikis çıkış portu değeri ‘0’ ve out_clk_4 çıkış portu değeri ‘1’ olmaktadır.
4. adım:in_rst giriş portunundeğerinin ‘0’ olması ve in_clk giriş portunun yükselen kenarı ile birlikte r_sayac sinyalinin değeri bir artırılmaktadır ve değeri “0011” olmaktadır. Bu nedenle out_clk_2 cikis çıkış portu değeri ‘1’ ve out_clk_4 çıkış portu değeri ‘1’ olmaktadır.
5. adım:in_rst giriş portunundeğerinin ‘0’ olması ve in_clk giriş portunun yükselen kenarı ile birlikte r_sayac sinyalinin değeri bir artırılmaktadır ve değeri “0100” olmaktadır. Bu nedenle out_clk_2 cikis çıkış portu değeri ‘0’ ve out_clk_4 çıkış portu değeri ‘0’ olmaktadır.
6. adım: in_rst giriş portunundeğerinin ‘0’ olması ve in_clk giriş portunun yükselen kenarı ile birlikte r_sayac sinyalinin değeri bir artırılmaktadır ve değeri “0101” olmaktadır. Bu nedenle out_clk_2 cikis çıkış portu değeri ‘1’ ve out_clk_4 çıkış portu değeri ‘0’ olmaktadır.
7. adım: in_rst giriş portunundeğerinin ‘0’ olması ve in_clk giriş portunun yükselen kenarı ile birlikte r_sayac sinyalinin değeri bir artırılmaktadır ve değeri “0110” olmaktadır. Bu nedenle out_clk_2 cikis çıkış portu değeri ‘0’ ve out_clk_4 çıkış portu değeri ‘0’ olmaktadır.
Şekil 9‑2’dende görüleceği üzere out_clk_2 çıkış portunun 1 periyodluk zaman dilimi, in_clk giriş portunun 2 tam periyodluk zaman dilimine denk gelmektedir. Aynı şekilde out_clk_4 çıkışının 1 periyodluk zaman dilimi, in_clk giriş portunun 4 tam periyodluk zaman dilimine denk eglmektedir.
Şekil 2 saat_frekans_bolucu varlığı benzetim çıktısı-1
Şekil 3’de gösterilen benzetim sonucunda:
1. adım: r_sayac sinyalinin değerleri “0000” ile “0011” aralığında ve r_sayac_N sinyalinin değerleri 0 ile 3 aralığında olmaktadır. Bu nedenle out_cikis_8 çıkış portu değeri ‘0’, out_cikis_16 çıkış portu değeri ‘0’ ve out_cikis_N çıkış değeri ‘0’ olmaktadır.
2. adım: r_sayac sinyalinin değerleri “0100” ile “0111” aralığında ve r_sayac_N sinyalinin değerleri 4 ile 7 aralığında olmaktadır. Bu nedenle out_cikis_8 çıkış portu değeri ‘1’, out_cikis_16 çıkış portu değeri ‘0’ ve out_cikis_N çıkış değeri ‘0’ olmaktadır.
3. adım: r_sayac sinyalinin değerleri “1000” ile “1011” aralığında ve r_sayac_N sinyalinin değerleri 8 ile 11 aralığında olmaktadır. Bu nedenle out_cikis_8 çıkış portu değeri ‘0’, out_cikis_16 çıkış portu değeri ‘1’ ve out_cikis_N çıkış değeri ‘1’ olmaktadır.
4. adım: r_sayac sinyalinin değerleri “1100” ile “1111” aralığında ve r_sayac_N sinyalinin değerleri 12 ile 15 aralığında olmaktadır. Bu nedenle out_cikis_8 çıkış portu değeri ‘1’, out_cikis_16 çıkış portu değeri ‘1’ ve out_cikis_N çıkış değeri ‘1’ olmaktadır.
5. adım: r_sayac sinyalinin değerleri “0000” ile “0011” aralığında ve r_sayac_N sinyalinin değerleri 0 ile 3 aralığında olmaktadır. Bu nedenle out_cikis_8 çıkış portu değeri ‘0’, out_cikis_16 çıkış portu değeri ‘0’ ve out_cikis_N çıkış değeri ‘0’ olmaktadır.
Şekil 3 saat_frekans_bolucu varlığı benzetim çıktısı-2
library IEEE; use IEEE.STD_LOGIC_1164.ALL; entity tb_saat_frekans_bolucu is end tb_saat_frekans_bolucu; architecture Behavioral of tb_saat_frekans_bolucu is component saat_frekans_bolucu generic( N : integer := 16 ); Port ( in_clk : in std_logic; in_rst : in std_logic; out_clk_2 : out std_logic; out_clk_4 : out std_logic; out_clk_8 : out std_logic; out_clk_16 : out std_logic; out_clk_N : out std_logic ); end component; constant CLK_PERIOD : time := 150 ns; signal in_clk : std_logic := '0'; signal in_rst : std_logic := '0'; signal out_clk_2 : std_logic := '0'; signal out_clk_4 : std_logic := '0'; signal out_clk_8 : std_logic := '0'; signal out_clk_16 : std_logic := '0'; signal out_clk_N : std_logic := '0'; begin process begin in_clk <= '1'; wait for CLK_PERIOD / 2; in_clk <= '0'; wait for CLK_PERIOD / 2; end process; process begin in_rst <= '1'; wait for 120 ns; in_rst <= '0'; wait; end process; saat_frekans_bolucu_map : saat_frekans_bolucu generic map( N => 16 ) port map ( in_clk => in_clk, in_rst => in_rst, out_clk_2 => out_clk_2, out_clk_4 => out_clk_4, out_clk_8 => out_clk_8, out_clk_16 => out_clk_16, out_clk_N => out_clk_N ); end Behavioral;