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”