Bu kısma kadar olan örneklerde genelde sayısal tasarımla alakalı uygulamalar gerçekleştirdik. Uygulamalarla VHDL ile ilgili kullanım şekillerini ve tasasrım yollarını göstermeye çalıştık.
Bu örnekte ise temel bir işaret işleme uygulamasına geçiş yapıyoruz. Bu kısımda bahsedilen kavramları anlayabilmek için temel seviyede işaret işleme ile alakalı konuların bilinmesi gerekmektedir. Bu bölüme devam etmeden önce lütfen işaret işleme ile alakalı kaynakları gözden geçriniz.
İşaret işlemede çok kullanışlı olan araçlardan biri de konvolüsyon işlemidir. Konvolusyon, giriş sinyali ve doğrusal sistemin dürtü tepki (impulse response) fonksiyonu bilindiğinde çıkış işaretini bulmaya yarayan bir işlemdir. Sistemin dürtü tepki fonksiyonu ‘in N tane çarpanlı bir sonlu filtre olduğunu varsayarsak, giriş işareti sonsuz uzunlukta olduğu durumda dahi, filtrenin çıkış işareti konvolüsyon işlemi ile aşağıda verilen deknklemde gösterilmiştir.

Dürtü tepki fonksiyonu katsayıları ve katsayıların sayısı tasarım aşamsından önce belirlenmelidir. Örneğin sonlu dürtü yanıtlı bir (N -1). dereceden filtrenin katsayısı N adettir. Bu tepki fonksiyonu için tasarımda N uzunluğunda bellek bloğu (h) ayrılması gerekmektedir.
Giriş işaretinin dürtü tepki fonksiyonu ile konvolüsyon işleminin yapılabilmesi için dürtü fonksiyonu katsayıları uzunluğunda giriş örneğinin saklaması gerekmektedir. Yukarıda verilen filtre örneği için N uzunluğunda bellek bloğu (x) ayrılması gerekmektedir. Giriş sinyali hafıza bloğu ile dürtü tepki fonksiyonunun katsayılarının bulunduğu bellek bloğu ile konvolüsyon işlemi, Şekil 1’de gösterilmiştir.

Şekil 1 Konvolüsyon işlemi
Örnek 1: Aşağıda sinyal işleme uygulamaları için katsayıların yüklenembilme özelliğine sahip ve konvolüsyon işlemi yapan konvolusyon_signal.vhd VHDL kodu verilmiştir. Uygulamada konvolüsyon işlemi için kullanıcı kendi oluşturduğu dürtü tepki fonksiyonun katsayılarını, katsayı hafıza bloğuna yükleyebilmektedir. Bu özellik ile konvolusyon_signal varlığı farklı dütrü tepki fonksiyonlarının gerçeklenebilmesine olanak sağlamaltadır.
konvolusyon_signal varlığına ilişkin generic tanımlamaları 8-13. satırlar arasında yapılmaktadır.
- 9. satırda tanımlı VERI_UZUNLUGU parametresi ile giriş data uzunluğu belirlenmektedir.
- 10. satırda tanımlı KATSAYI parametresi ile konvolüsyon için kullılacak katsayıların sayısı tanımlanmaktadır.
- 11. satırda tanımlı KATSAYI_UZUNLUGU parametresi ile katsayıların data uzunluğu belirlenmektedir.
- 12. satırda tanımlı KATSAYI_CARPIM paramatresi ise hesaplanan katsayıların 2’nin kaçıncı kuvveti ile çarpıldığını belirtmektedir. Bu parametre filtre çıkışında kullanılmaktadır.
konvolusyon_signal varlığına ilişkin port tanımlama işlemleri 14-26. satırlarda yapılmaktadır. 37. satırda KATSAYI_UZUNLUGU bit uzunluğunda ve KATSAYI boyunda tip tanımlama işlemi yapılarak konvolüsyon katsayılarının saklanacağı bellek tipi oluşturulmuştur.
40. satırda VERI_UZUNLUGU bit uzunluğunda KATSAYI boyunda tip tanımlama işlemi yapılarak giriş datalarının saklanacağı bellek tipi oluşturulmuştur.
Giriş datalarının saklanma işleminde giriş örnek datası belleğin 0. adresine yazılacak şekilde tasarım yapılmıştır. Bu nedenle 43-52. satırlarda tanımlı fonksiyon ile giriş datalarının tutulduğu bellekte dataların sağa kaydırma işlemi gerçekleştirilmektedir.
68-77. satırlarda tanımlı process ile konvolüsyon katsayılarının belleğe yazılma işlemi yapılmaktadır. Katsayı ve katsayı adres bilgisi ile birlikte aktif sinyali olması durumunda katsayı değeri r_katsayi_bellek sinyalinde ilgili adresadresteki yerine yazılmaktadır.
79-104. satırlarda tanımlı process’de data aktif sinyali ile f_Bellek_kaydir fonksiyonu çağrılarak r_data_bellek sinyali dataları sağa kayırdama işlemi yapılır ve giriş datası ilgili yerine yazılır. Data yazma işleminin tamamlanması ile birlikte r_hesap_basla sinyali aktif edilerek 106-144. satırlarda tanımlı process’de tanımlı konvolüsyon işlemi başlatılır.
library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_SIGNED.all; use IEEE.STD_LOGIC_ARITH.all; use work.ornekler_paket.all; entity konvolusyon_sinyal is Generic( VERI_UZUNLUGU : integer := 24; KATSAYI : integer := 5; KATSAYI_UZUNLUGU : integer := 8; KATSAYI_CARPIM : integer := 3 ); Port ( in_clk : in std_logic; in_rst : in std_logic; in_en : in std_logic; in_katsayi_vld : in std_logic; in_katsayi_addr : in std_logic_vector(log2_int(KATSAYI) downto 0); in_katsayi_data : in std_logic_vector(KATSAYI_UZUNLUGU - 1 downto 0); in_data : in std_logic_vector(VERI_UZUNLUGU - 1 downto 0); in_data_vld : in std_logic; out_data : out std_logic_vector(VERI_UZUNLUGU - 1 downto 0); out_data_vld : out std_logic; out_calisiyor : out std_logic ); end konvolusyon_sinyal; architecture Behavioral of konvolusyon_sinyal is type t_Kayma_Ctrl is (BOSTA, DATA_KAYDIR); signal r_Kayma_Ctrl : t_Kayma_Ctrl := BOSTA; type t_Filtre_Hesap is (BOSTA, HESAPLA, TAMAM); signal r_Filtre_Hesap : t_Filtre_Hesap := BOSTA; type t_katsayi_bellek is array (0 to KATSAYI - 1 ) of std_logic_vector(KATSAYI_UZUNLUGU - 1 downto 0); signal r_katsayi_bellek : t_katsayi_bellek := (others => (others => '0')); type t_data_bellek is array (0 to KATSAYI - 1 ) of std_logic_vector(VERI_UZUNLUGU - 1 downto 0); signal r_data_bellek : t_data_bellek := (others => (others => '0')); function f_Bellek_Kaydir(r_data_bellek : t_data_bellek; in_data : std_logic_vector(VERI_UZUNLUGU - 1 downto 0)) return t_data_bellek is variable v_data_bellek : t_data_bellek; begin v_data_bellek := r_data_bellek; for n_i in KATSAYI - 2 downto 0 loop v_data_bellek(n_i + 1) := v_data_bellek(n_i); end loop; v_data_bellek(0) := in_data; return v_data_bellek; end f_Bellek_Kaydir; signal r_hesap_basla : std_logic := '0'; signal r_data : std_logic_vector(VERI_UZUNLUGU - 1 downto 0) := (others => '0'); signal r_toplam : std_logic_vector(VERI_UZUNLUGU + KATSAYI_UZUNLUGU + log2_int(KATSAYI) - 1 downto 0) := (others => '0'); signal r_data_out : std_logic_vector(VERI_UZUNLUGU - 1 downto 0) := (others => '0'); signal r_data_out_vld : std_logic := '0'; signal r_calisiyor : std_logic := '0'; signal n_i : integer := 0; begin out_data <= r_data_out; out_data_vld <= r_data_out_vld; out_calisiyor <= r_calisiyor; process(in_clk, in_rst) begin if in_rst = '1' then r_katsayi_bellek <= (others => (others => '0')); elsif rising_edge(in_clk) then if in_katsayi_vld = '1' then r_katsayi_bellek(conv_integer(in_katsayi_addr)) <= in_katsayi_data; end if; end if; end process; process(in_clk, in_rst) begin if in_rst = '1' then r_Kayma_Ctrl <= BOSTA; r_data_bellek <= (others => (others => '0')); r_hesap_basla <= '0'; r_data <= (others => '0'); elsif rising_edge(in_clk) then r_hesap_basla <= '0'; case r_Kayma_Ctrl is when BOSTA => if in_data_vld = '1' then r_data <= in_data; r_Kayma_Ctrl <= DATA_KAYDIR; end if; when DATA_KAYDIR => r_data_bellek <= f_Bellek_Kaydir(r_data_bellek, r_data); r_Kayma_Ctrl <= BOSTA; r_hesap_basla <= '1'; when others => NULL; end case; end if; end process; process(in_clk, in_rst) begin if in_rst = '1' then r_Filtre_Hesap <= BOSTA; r_toplam <= (others => '0'); r_data_out_vld <= '0'; r_data_out <= (others => '0'); r_calisiyor <= '0'; n_i <= 0; elsif rising_edge(in_clk) then r_data_out_vld <= '0'; case r_Filtre_Hesap is when BOSTA => r_calisiyor <= '0'; if r_hesap_basla = '1' and in_en = '1' then r_Filtre_Hesap <= HESAPLA; r_calisiyor <= '1'; end if; when HESAPLA => r_toplam <= r_toplam + sxt((r_data_bellek(n_i)) * (r_katsayi_bellek(KATSAYI - 1 - n_i)), r_toplam'length); n_i <= n_i + 1; if n_i = KATSAYI - 1 then n_i <= 0; r_Filtre_Hesap <= TAMAM; end if; when TAMAM => r_toplam <= (others => '0'); r_calisiyor <= '0'; r_data_out_vld <= '1'; r_data_out <= r_toplam(KATSAYI_CARPIM + VERI_UZUNLUGU - 1 downto KATSAYI_CARPIM); r_Filtre_Hesap <= BOSTA; when others => NULL; end case; end if; end process; end Behavioral;
Örnekte tanımlı ornekler_paket.vhd paket dosyası VHDL’de ROM Bloğu oluşturma yazımızda verilmiştir.
konvolusyon_signal varlığının benzetiminin yapılabilmesi için aşağıda tb_konvolusyon_signal.vhd VHDL sınama kodu verilmiştir. Kodda tanımlı alçak geçiren süzgeç parametreleri öncelikle konvolusyon_signal varlığına yazılmaktadır. Yazma işleminin bitiminde konvolusyon hesaplama işlemi aktif hale gelmektedir. konvolusyon_signal varlığına giriş olarak 10 Hz ve 10 Khz frekansında iki sinüs sinyalinin toplamı100 KHz ile örneklenerek verilmiştir. Şekil 2’den de görüleceği üzere ornek_data sinyali’nin giriş olarak verildiği konvolusyon_signal varlığı çıkışında elde edilen out_data sinyali incelendiğinde filtreleme işlemi başarılı bir şekilde gerçekleştirilmiştir.

Şekil 2 Alçak geçiren filtre uygulaması
library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_UNSIGNED.all; use IEEE.STD_LOGIC_ARITH.all; use work.ornekler_paket.all; use std.textio.ALL; entity tb_konvolusyon_signal is end tb_konvolusyon_signal; architecture Behavioral of tb_konvolusyon_signal is component konvolusyon_sinyal is Generic( VERI_UZUNLUGU : integer := 24; KATSAYI : integer := 5; KATSAYI_UZUNLUGU : integer := 8; KATSAYI_CARPIM : integer := 3 ); Port ( in_clk : in std_logic; in_rst : in std_logic; in_en : in std_logic; in_katsayi_vld : in std_logic; in_katsayi_addr : in std_logic_vector(log2_int(KATSAYI) downto 0); in_katsayi_data : in std_logic_vector(KATSAYI_UZUNLUGU - 1 downto 0); in_data : in std_logic_vector(VERI_UZUNLUGU - 1 downto 0); in_data_vld : in std_logic; out_data : out std_logic_vector(VERI_UZUNLUGU - 1 downto 0); out_data_vld : out std_logic; out_calisiyor : out std_logic ); end component; constant CLK_PERIOD : time := 10 ns; constant ORNEKLEME_PERIOD : time := 10 us; constant VERI_YOLU : string := "C:\sin.txt"; constant VERI_UZUNLUGU : integer := 24; constant KATSAYI : integer := 17; constant KATSAYI_UZUNLUGU : integer := 8; constant KATSAYI_CARPIM : integer := 7; signal in_clk : std_logic := '0'; signal ornekleme_clk : std_logic := '0'; signal ornek_data : std_logic_vector(23 downto 0) := (others => '0'); signal clk_domain : std_logic_vector(3 downto 0) := (others => '0'); signal son_data : std_logic := '0'; signal in_rst : std_logic := '0'; signal in_en : std_logic := '0'; signal in_katsayi_vld : std_logic := '0'; signal in_katsayi_addr : std_logic_vector(log2_int(KATSAYI) downto 0) := (others => '0'); signal in_katsayi_data : std_logic_vector(KATSAYI_UZUNLUGU - 1 downto 0) := (others => '0'); signal in_data : std_logic_vector(VERI_UZUNLUGU - 1 downto 0) := (others => '0'); signal in_data_vld : std_logic := '0'; signal out_data : std_logic_vector(VERI_UZUNLUGU - 1 downto 0) := (others => '0'); signal out_data_vld : std_logic := '0'; signal out_calisiyor : std_logic := '0'; type t_Katsayi_Kontrol is (BOSTA, YUKLE); signal r_Katsayi_Kontrol : t_Katsayi_Kontrol := BOSTA; type t_Filtre_Katsayi is array (0 to KATSAYI - 1) of integer; signal r_Filtre_Katsayi : t_Filtre_Katsayi := (1, 2, 3, 5, 8, 10, 13, 14, 15, 14, 13, 10, 8, 5, 3, 2, 1); signal katsayi_yukle : std_logic := '0'; signal n_i : integer := 0; begin process begin in_clk <= '1'; wait for CLK_PERIOD / 2; in_clk <= '0'; wait for CLK_PERIOD / 2; end process; process begin ornekleme_clk <= '1'; wait for ORNEKLEME_PERIOD / 2; ornekleme_clk <= '0'; wait for ORNEKLEME_PERIOD / 2; end process; process begin katsayi_yukle <= '0'; wait for CLK_PERIOD * 2; katsayi_yukle <= '1'; wait for CLK_PERIOD ; katsayi_yukle <= '0'; wait; end process; process (ornekleme_clk) file dosya : text open read_mode is VERI_YOLU ; variable satir : line; variable data : integer; begin if rising_edge(ornekleme_clk) then if not(endfile(dosya)) then readline(dosya, satir); read(satir, data); ornek_data <= conv_std_logic_vector(data, 24) ; son_data <= '0'; else ornek_data <= conv_std_logic_vector(0, 24) ; son_data <= '1'; end if; end if; end process; process(in_clk) begin if rising_edge(in_clk) then clk_domain <= clk_domain(2 downto 0) & ornekleme_clk; end if; end process; process (in_clk) begin if rising_edge(in_clk) then if son_data = '0' and clk_domain(3 downto 2) = "01" then in_data_vld <= '1' ; in_data <= ornek_data ; else in_data_vld <= '0' ; in_data <= (others=>'0') ; end if; end if; end process; process(in_clk) begin if rising_edge(in_clk) then in_katsayi_vld <= '0'; case r_Katsayi_Kontrol is when BOSTA => if katsayi_yukle = '1' then r_Katsayi_Kontrol <= YUKLE; end if; when YUKLE => in_katsayi_vld <= '1'; in_katsayi_addr <= conv_std_logic_vector(n_i, log2_int(KATSAYI) + 1); in_katsayi_data <= conv_std_logic_vector( r_Filtre_Katsayi(n_i), KATSAYI_UZUNLUGU); if n_i = KATSAYI - 1 then r_Katsayi_Kontrol <= BOSTA; n_i <= 0; in_en <= '1'; else n_i <= n_i + 1; end if; when others => NULL; end case; end if; end process; konvolusyon_sinyal_map : konvolusyon_sinyal Generic map( VERI_UZUNLUGU => VERI_UZUNLUGU, KATSAYI => KATSAYI, KATSAYI_UZUNLUGU => KATSAYI_UZUNLUGU, KATSAYI_CARPIM => KATSAYI_CARPIM ) Port map( in_clk => in_clk, in_rst => in_rst, in_en => in_en, in_katsayi_vld => in_katsayi_vld, in_katsayi_addr => in_katsayi_addr, in_katsayi_data => in_katsayi_data, in_data => in_data, in_data_vld => in_data_vld, out_data => out_data, out_data_vld => out_data_vld, out_calisiyor => out_calisiyor ); end Behavioral;