Yaptığımız tasarımlarda zaman zaman farklı hızlarda çalışan modüller arasında veri alış-verişi yapmamız gerekebilir. Ya da bazı durumlarda işlenmesi gereken verilerin önce belli bir miktar biriktirilip daha sonra işlenmesi gerekebilir. Bu ve bunun gibi durumlarda en sık tercih edilen yaklaşım FIFO (First In First Out – İlk Giren İlk Çıkar) kullanımıdır. FIFO’ya giren veriler giriş sırasına çıkışından alınır. FIFO elemanını, hafıza adresini otomatik olarak ayarlayan, verileri geldiği sıraya göre çıkışa aktaran bir hafıza türü olarak da düşünmek mümkündür.
Şekil 1’den de görüleceği üzere FIFO okuma ve yazma aktif giriş portlarına, data giriş portuna, data çıkış portuna, çıkış data yürürlülükte portuna, FIFO dolu ve boş çıkış protlarına, FIFO doluyor ve boşalıyor çıkış portlarına sahiptir.
Şekil 1 NxM bitlik FIFO
Örnek 1: Şekil 1’de gösterilen FIFO tasarımın yapıldığı FIFO.vhd VHDL kodu aşağıda verilmiştir. FIFO varlığımıza ilişkin generic bildirimleri 6-11. satırlarda, port bildirimleri 12-24. satırları arasında yapılmaktıdır.
FIFO tasarımında 1 bitlik saat darbesi giriş portu, 1 bitlik FIFO reset giriş portu, 1 bitlik FIFO yazma aktif giriş portu, 1 bitlik FIFO okuma aktif giriş portu, VERI_UZUNLUGU uzunluğunda data giriş portu, VERI_UZUNLUGU uzunluğunda data çıkış portu, 1 bitlik çıkış datası gerçerli portu, 1 bitlik FIFO dolu uyarı portu, 1 bitlik FIFO boş uyarı portu, , 1 bitlik FIFO doluyor uyarı portu ve 1 bitlik FIFO boşalıyor uyarı portu mevcuttur.
29. satırda VERI_UZUNLUGU genişliğine sahip FIFO_DERINLIGI derinliğinde tip tanımlama işlemi yapılmıştır. 63-67. satırlarda tanımlı koşul ifadeleri ile yazma işleminde r_fifo_sayac sinyalinin değerinin bir artırılması, okuma işleminde ise r_fifo_sayac sinyalinin değerinin bir azaltılması işlemleri gerçekleştirilmektedir.
43-50. satırlar arasında ise r_fifo_sayac sinyalinin her saat darbesinde kontrolü ile FIFO doluluk boşluk durumları belirlenmektedir.
69-75. satırlarda her yazma işlemi yapıldığında ind_yaz sinyalinin değeri bir artırılmaktadır. ind_yaz sinyai değeri FIFO_DERINLIGI – 1 değerine ulaştığında değeri sıfırlanmaktadır. 76-87. satırlarda her yazma işlemi yapıldığında ind_oku sinyalinin değeri bir artırılmaktadır.
ind_oku sinyali değeri FIFO_DERINLIGI – 1 değerine ulaştığında kendi değerini sıfırlamaktadır. r_FIFO_DATA sinyalinin ind_oku adresindeki veri değeri r_data sinyaline atanmaktadır. Atama işlemi ile birlikte r_data_vld sinyali ‘1’ değerini almaktadır. 88-90. satırlarda r_FIFO_DATA sinyalinin ind_yaz adresine in_data sinyali atanmaktadır.
library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; entity FIFO is Generic( FIFO_DERINLIGI : integer := 250; VERI_UZUNLUGU : integer := 24; FIFO_DOLUYOR : integer := 250; FIFO_BOSALIYOR : integer := 10 ); Port ( in_clk : in std_logic; in_rst : in std_logic; in_yaz : in std_logic; in_oku : in std_logic; in_data : in std_logic_vector(VERI_UZUNLUGU - 1 downto 0); out_doluyor : out std_logic; out_dolu : out std_logic; out_data : out std_logic_vector(VERI_UZUNLUGU - 1 downto 0); out_data_vld : out std_logic; out_bosaliyor : out std_logic; out_bos : out std_logic ); end FIFO; architecture Behavioral of FIFO is type t_FIFO_DATA is array (0 to FIFO_DERINLIGI - 1) of std_logic_vector(VERI_UZUNLUGU - 1 downto 0) ; signal r_FIFO_DATA : t_FIFO_DATA := (others =>(others => '0')); signal r_fifo_sayac : integer range -1 to FIFO_DERINLIGI + 1 := 0; signal ind_yaz : integer range 0 to FIFO_DERINLIGI - 1 := 0; signal ind_oku : integer range 0 to FIFO_DERINLIGI - 1 := 0; signal bayrak_dolu : std_logic := '0'; signal bayrak_bos : std_logic := '0'; signal r_data_vld : std_logic := '0'; signal r_data : std_logic_vector(VERI_UZUNLUGU - 1 downto 0) := (others => '0'); begin out_data <= r_data; out_data_vld <= r_data_vld; out_dolu <= '1' when r_fifo_sayac = FIFO_DERINLIGI else '0'; out_bos <= '1' when r_fifo_sayac = 0 else '0'; bayrak_dolu <= '1' when r_fifo_sayac = FIFO_DERINLIGI else '0'; bayrak_bos <= '1' when r_fifo_sayac = 0 else '0'; out_doluyor <= '1' when r_fifo_sayac > FIFO_DOLUYOR else '0'; out_bosaliyor <= '1' when r_fifo_sayac < FIFO_BOSALIYOR else '0'; process(in_clk, in_rst) begin if in_rst = '1' then r_fifo_sayac <= 0; ind_yaz <= 0; ind_oku <= 0; r_data_vld <= '0'; r_data <= (others => '0'); elsif rising_edge(in_clk) then if in_yaz = '1' and in_oku = '0' then r_fifo_sayac <= r_fifo_sayac + 1; elsif in_yaz = '0' and in_yaz = '1' then r_fifo_sayac <= r_fifo_sayac - 1; end if; if in_yaz = '1' and bayrak_dolu = '0' then if ind_yaz = FIFO_DERINLIGI - 1 then ind_yaz <= 0; else ind_yaz <= ind_yaz + 1; end if; end if; if (in_oku = '1' and bayrak_bos = '0') then if ind_oku = FIFO_DERINLIGI - 1 then ind_oku <= 0; else ind_oku <= ind_oku + 1; end if; r_data <= r_FIFO_DATA(ind_oku); r_data_vld <= '1'; else r_data_vld <= '0'; end if; end if; if in_yaz = '1' then r_FIFO_DATA(ind_yaz) <= in_data; end if; end process; end Behavioral;
Aşağıda verilen tb_FIFO.vhd VHDL kodu ile FIFO varlığının benzetim işlemleri yapılmaktadır. Benzetim işlemlerinde, sinüs örneklerinin kaydedildiği sin.txt dosyasından okuma işlemleri yapılmakta ve okunan datalar FIFO’ya yazılmaktadır. 100. örneğin FIFO’ya yazılmasından sonra FIFO’dan okuma aktif edilmektedir. Okuma işlemin aktif olması ile birlikte FIFO’ya yazılmış olması sinüs örnekleri out_data çıkış portunda görülmektedir (Şekil 2).
Şekil 2 FIFO varlığı benzetim çıktısı
library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_ARITH.ALL; use std.textio.ALL; entity tb_fifo is end tb_fifo; architecture Behavioral of tb_fifo is component FIFO Generic( FIFO_DERINLIGI : integer := 250; VERI_UZUNLUGU : integer := 24; FIFO_DOLUYOR : integer := 250; FIFO_BOSALIYOR : integer := 10 ); Port ( in_clk : in std_logic; in_rst : in std_logic; in_yaz : in std_logic; in_oku : in std_logic; in_data : in std_logic_vector(VERI_UZUNLUGU - 1 downto 0); out_doluyor : out std_logic; out_dolu : out std_logic; out_data : out std_logic_vector(VERI_UZUNLUGU - 1 downto 0); out_data_vld : out std_logic; out_bosaliyor : out std_logic; out_bos : out std_logic ); end component; constant CLK_PERIOD : time := 150 ns; constant FIFO_DERINLIGI : integer := 250; constant VERI_UZUNLUGU : integer := 24; constant FIFO_DOLUYOR : integer := 250; constant FIFO_BOSALIYOR : integer := 10; constant VERI_YOLU : string := "C:\sin.txt"; signal in_clk : std_logic := '0'; signal in_rst : std_logic := '0'; signal in_oku : std_logic := '0'; signal in_yaz : std_logic := '0'; signal in_data : std_logic_vector(VERI_UZUNLUGU - 1 downto 0) := (others => '0'); signal out_doluyor : std_logic := '0'; signal out_dolu : 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_bosaliyor : std_logic := '0'; signal out_bos : std_logic := '0'; signal sayac : integer := 0; begin process begin in_clk <= '1'; wait for CLK_PERIOD / 2; in_clk <= '0'; wait for CLK_PERIOD / 2; end process; process(in_clk) file dosya : text open read_mode is VERI_YOLU; variable satir : line; variable data : integer; begin if rising_edge(in_clk) then if (not endfile(dosya)) then readline(dosya, satir); read(satir, data); in_data <= conv_std_logic_vector(data, VERI_UZUNLUGU); in_yaz <= '1'; sayac <= sayac + 1; if sayac > 100 then in_oku <= '1'; end if; end if; end if; end process; FIFO_map : FIFO generic map( FIFO_DERINLIGI => FIFO_DERINLIGI, VERI_UZUNLUGU => VERI_UZUNLUGU, FIFO_DOLUYOR => FIFO_DOLUYOR, FIFO_BOSALIYOR => FIFO_BOSALIYOR ) port map( in_clk => in_clk, in_rst => in_rst, in_yaz => in_yaz, in_oku => in_oku, in_data => in_data, out_doluyor => out_doluyor, out_dolu => out_dolu, out_data => out_data, out_data_vld => out_data_vld, out_bosaliyor => out_bosaliyor, out_bos => out_bos ); end Behavioral;