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.
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”