VHDL’de ROM Bloğu Oluşturmak

ROM (Read Only Memory – Sadece Okunabilir Hafıza) sadece okunabilen sayısal verilerin saklanması için kullanılan depolama birimidir. Şekil 1’de NxM bitlik ROM gösterimi verilmiştir. Şekil 9‑22’den de görüleceği üzere in_rom_aktif giriş portunun aktif olması ile birlikte ile ROM’dan in_data_addr adresindeki data out_data çıkış portuna aktarılmaktadır.

Şekil 1 NxM bitlik ROM

Hafıza elemanları tasarlanırken genel olarak kullanılan bazı terimlere aşina olmak gerekmektedir. Bu bölümde verilen örneklerde geçen VERI_UZUNLUGU tanımlaması tasarladığımız hafıza biriminin veri yolu genişliğini bildirmektedir. Örneğin bu değer 8 ise tasarlanan hafıza elemanı her bir adreste 8 bit uzunluğunda veri saklayabiliyor demektir.

Hafıza elemanları ile ilgili bir diğer tanımlama ise ROM_DERINLIGI’dir. Bu tanımlama ile tasarladığımız hafıza elemanının kaç adet veri saklayacabileği belirtilmektedir. Bu değer aynı zaman doğrudan adresleme hattının uzunluğunun da belirlenmesini sağlamaktadır. Örneklemek gerekirse; 30 adet veri saklamak istersek ROM_DERINLIGI tanımlamasının değerinin 30 olması gerekmektedir. 30 adet veriyi adreslemek için gereken adres yolu genişliği ise ceil(log2N) = ceil(log230) => n = 5 hesaplarında gösterildiği şekilde 5 bit olacaktır. Bu işlemin gerçeklenmesi için kullanılcak olan log2_int fonksiyonu ornekler_paket.vhd paket dosyasında tanımlanmıştır. Örnek 1 ve Örnek 2’de tanımlı ornekler_paket.vhd paket dosyası aşağıda verilmiştir.

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
	
package ornekler_paket is
  function log2_int(in_giris : integer) return integer;
end ornekler_paket;
	
package body ornekler_paket is
	
  function log2_int(in_giris : integer) return integer is
    variable sonuc : integer;
  begin
    for n_i in 0 to 31 loop
      if (in_giris <= (2 ** n_i)) then
        sonuc := n_i;
        exit;
      end if;
    end loop;
    return sonuc;
  end log2_int;
end package body;

Örnek 1: ROM datalarının değiştirlemez olmasından dolayı dataların constant veri nesnesinde tanımlandığı rom.vhd VHDL kodu aşağıda verilmiştir. rom varlığımıza ilişkin generic bildirimleri 7-10. satırlarda, port bildirimleri 11-16. satırları arasında yapılmaktıdır. ROM tasarımında 1 bitlik saat darbesi giriş portu, 1 bitlik ROM aktif giriş portu, generic ROM_DERINLIGI parametresine bağlı olarak hesaplanan adres giriş portu ve okununan adresindeki datanın ROM dışına aktarılması için VERI_UZUNLUGU uzunluğunda çıkış portu mevcuttur. ROM adres uzunluğunun belirlenmesi için kullanılacak olan log2_int fonskiyonu 4. satırda tanımlanan ornekler_paket paketi içerisinde tanımlanmıştır. 21. satırda VERI_UZUNLUGU genişliğine sahip ROM_DERINLIGI derinliğinde tip tanımlama işlemi yapılmıştır. 22. satırda ise ROM değerlerinin atama işlemleri yapılmaktadır.

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
use work.ornekler_paket.all;
	
entity rom is
  Generic(
    ROM_DERINLIGI : integer := 30;
    VERI_UZUNLUGU : integer := 4                
  );
  Port ( 
    in_clk : in std_logic;
    in_rom_aktif : in std_logic;
    in_data_addr : in std_logic_vector(log2_int(ROM_DERINLIGI) - 1 downto 0);
    out_data : out std_logic_vector(VERI_UZUNLUGU - 1 downto 0)
  );
end rom;
	
architecture Behavioral of rom is
	
  type t_ROM_DATA is array (0 to ROM_DERINLIGI - 1) of std_logic_vector(VERI_UZUNLUGU - 1 downto 0) ; 
  constant r_ROM_DATA : t_ROM_DATA := ( X"0", X"3", X"6", X"9", X"C", X"F", X"C", X"9", X"6", X"3", X"0", X"3", X"6", X"9", X"C", X"F", X"C", X"9", X"6", X"3", X"0", X"3", X"6", X"9", X"C", X"F", X"C", X"9", X"6", X"3" );
	
begin
  
  process(in_clk)
  begin
    if rising_edge(in_clk) then
      if in_rom_aktif = '1' then
        out_data <= r_ROM_DATA(conv_integer(in_data_addr));
      end if;
    end if;
  end process;
end Behavioral;

Örnek 2: Aşağıda ROM datalarının dosyadan okuyan rom_dosya.vhd VHDL kodu verilmiştir. rom_dosya varlığımıza ilişkin generic bildirimleri 9-12. satırlarda, port bildirimleri 13-18. satırları arasında yapılmaktıdır. ROM tasarımında 1 bitlik saat darbesi giriş portu, 1 bitlik ROM aktif giriş portu, generic ROM_DERINLIGI parametresine bağlı olarak hesaplanan adres giriş portu ve okununan adresdeki datanın ROM dışına aktarılması için VERI_UZUNLUGU uzunluğunda çıkış portu mevcuttur. ROM adres uzunluğunun belirlenmesi için kullanılacak olan log2_int fonskiyonu 4. satırda tanımlanan ornekler_paket paketi içerisinde tanımlanmıştır. 24. satırda VERI_UZUNLUGU genişliğine sahip ROM_DERINLIGI derinliğinde tip tanımlama işlemi yapılmıştır. 27-41. satırlar arasında tanımlı ROM_DATA_YUKLE procedure tanımlaması ile sinüs örneklerinin bulunduğu dosyadan datalar alınmaktadır. 45. satırda tanımlı söz dizimi ile procedure çağrılarak dosyadan okunan datalar ROM’a yüklenmektedir.

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use std.textio.ALL;
use work.ornekler_paket.all;
	
entity rom_dosya is
  Generic(
    ROM_DERINLIGI : integer := 500;
    VERI_UZUNLUGU : integer := 24                
  );
  Port ( 
    in_clk : in std_logic;
    in_rom_aktif : in std_logic;
    in_data_addr : in std_logic_vector(log2_int(ROM_DERINLIGI) - 1 downto 0);
    out_data : out std_logic_vector(VERI_UZUNLUGU - 1 downto 0)
  );
end rom_dosya;
	
architecture Behavioral of rom_dosya is
	
  constant VERI_YOLU : string := "C:\sin.txt";
  type t_ROM_DATA is array (0 to ROM_DERINLIGI - 1) of std_logic_vector(VERI_UZUNLUGU - 1 downto 0) ; 
  signal r_ROM_DATA : t_ROM_DATA;
	
  procedure ROM_DATA_YUKLE(signal r_ROM_DATA : inout t_ROM_DATA) is
    file dosya : text open read_mode is VERI_YOLU;
    variable satir  :line;
    variable data : integer;
  begin
    for n_i in 0 to ROM_DERINLIGI - 1 loop
      if endfile(dosya) then
        exit;
      else
        readline(dosya, satir);
        read(satir, data);
        r_ROM_DATA(n_i) <= conv_std_logic_vector(data, VERI_UZUNLUGU);
      end if;
    end loop;
  end procedure;
	
begin
	
  ROM_DATA_YUKLE(r_ROM_DATA);
	  
  process(in_clk)
  begin
    if rising_edge(in_clk) then
      if in_rom_aktif = '1' then
        out_data <= r_ROM_DATA(conv_integer(in_data_addr));
      end if;
    end if;
  end process;
end Behavioral;

Örnek 1 ve Örnek 2’de verilen rom ve rom_dosya varlıklarının benzetiminin yapılabilmesi için aşağıda tb_rom.vhd VHDL sınama kodu verilmiştir. 10-21. satırlarda rom varlığına ilişkin component tanımlamaları yapılmıştır. 23-34. satırlarda rom_dosya varlığına ilişkin component tanımlamaları yapılmıştır.  37-38. satırlardaki yapılan sabit tanmlamalarında rom varlığına ait derinlik değeri 30 ve veri uzunluğu 4 olarak tanımlanmıştır. 39-40. satırlardaki yapılan sabit tanmlamalarında rom_dosya varlığına ait derinlik değeri 500 ve veri uzunluğu 24 olarak tanımlanmıştır. Şekil 2’de rom ve rom_dosya varlıklarının benzetim sonuçları verilmiştir.

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
use work.ornekler_paket.all;
	
entity tb_rom is
end tb_rom;
	
architecture Behavioral of tb_rom is
  component rom 
    Generic(
      ROM_DERINLIGI : integer := 500;
      VERI_UZUNLUGU : integer := 24                
    );
    Port ( 
      in_clk : in std_logic;
      in_rom_aktif : in std_logic;
      in_data_addr : in std_logic_vector(log2_int(ROM_DERINLIGI) - 1 downto 0);
      out_data : out std_logic_vector(VERI_UZUNLUGU - 1 downto 0)
    );        
  end component;
	
  component rom_dosya 
    Generic(
      ROM_DERINLIGI : integer := 500;
      VERI_UZUNLUGU : integer := 24                
    );
    Port ( 
      in_clk : in std_logic;
      in_rom_aktif : in std_logic;
      in_data_addr : in std_logic_vector(log2_int(ROM_DERINLIGI) - 1 downto 0);
      out_data : out std_logic_vector(VERI_UZUNLUGU - 1 downto 0)
    );        
  end component;
	
  constant CLK_PERIOD : time := 150 ns;
  constant ROM_DERINLIGI : integer := 30;
  constant VERI_UZUNLUGU : integer := 4;
  constant ROM_DERINLIGI_DOSYA : integer := 500;
  constant VERI_UZUNLUGU_DOSYA : integer := 24;
	  
  signal in_clk : std_logic := '0';
  signal in_rom_aktif : std_logic := '0';
  signal in_data_addr_rom : std_logic_vector( log2_int(ROM_DERINLIGI) - 1 downto 0) := (others => '0');
  signal out_data_rom :  std_logic_vector(VERI_UZUNLUGU - 1 downto 0) := (others => '0');
  signal in_data_addr_rom_dosya: std_logic_vector( log2_int(ROM_DERINLIGI_DOSYA) - 1 downto 0) := (others => '0');
  signal out_data_rom_dosya :  std_logic_vector( VERI_UZUNLUGU_DOSYA - 1 downto 0) := (others => '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)
  begin  
    if rising_edge(in_clk) then
      in_data_addr_rom <= in_data_addr_rom + 1;
      if in_data_addr_rom = ROM_DERINLIGI - 1 then
        in_data_addr_rom <= (others => '0');
      end if;
      in_data_addr_rom_dosya <= in_data_addr_rom_dosya + 1;
	      
      if in_data_addr_rom_dosya = ROM_DERINLIGI_DOSYA - 1 then
        in_data_addr_rom_dosya <= (others => '0');
      end if;
    end if;
  end process;
  in_rom_aktif <= '1';
  rom_map : rom generic map(
    ROM_DERINLIGI => ROM_DERINLIGI,
    VERI_UZUNLUGU => VERI_UZUNLUGU   )
  port map ( 
    in_clk => in_clk,
    in_rom_aktif => in_rom_aktif,
    in_data_addr => in_data_addr_rom,
    out_data => out_data_rom  );    
	
  rom_dosya_map : rom_dosya generic map(
    ROM_DERINLIGI => ROM_DERINLIGI_DOSYA,
    VERI_UZUNLUGU => VERI_UZUNLUGU_DOSYA  )
  port map ( 
    in_clk => in_clk,
    in_rom_aktif => in_rom_aktif,
    in_data_addr => in_data_addr_rom_dosya,
    out_data => out_data_rom_dosya);
	
end Behavioral;

Şekil 2  rom ve rom_dosya varlıklarının benzetim çıktısı

1 thought on “VHDL’de ROM Bloğu Oluşturmak

Bir yanıt yazın

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