VHDL’de FIFO tasarımı

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;

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir