Без объекта и архитектуры для ПЗУ, а также содержимого ROM_data.txt ваш вопрос и ответ не могут быть проверены. Помимо ПЗУ, содержащегося в массиве значений сигналов или переменных в нераскрытой архитектуре ПЗУ, в любом месте, где набор инструментов позволит вам указать начальное значение ОЗУ или значение ПЗУ программно (например, Xilinx, а не Intel), вы также можете использовать нечистая функция для предоставления значения константы типа массива в объявлении:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all; -- to_integer instead of std_logic_arith conv_integer
use ieee.math_real.all; -- for ceiling, log2
entity rom is -- generic ROM with std_logic_vector address and output
generic ( -- default values supplied for plugin to OPs usage
filename: string := "ROM_DATA.txt";
rom_width: natural := 8;
rom_depth: natural := 32
);
port (
address: in std_logic_vector
(integer(ceil(log2(real(rom_depth)))) - 1 downto 0);
data: out std_logic_vector (rom_width - 1 downto 0)
);
end entity;
architecture foo of rom is
type rom_array is array
(0 to rom_depth - 1) of std_logic_vector (rom_width - 1 downto 0);
impure function initromfromfile (romfilename: in string)
return rom_array is
use std.textio.all;
file romfile: text open read_mode is romfilename;
variable romfileline: line;
variable vrom: rom_array;
variable rom_value: bit_vector(7 downto 0);
begin
for i in vrom'range loop -- contents of file are ordered
if endfile(romfile) then -- file can be shorter than rom array
vrom(i) := (others => '0');
else
readline(romfile, romfileline); -- 1 datum per line
read(romfileline, rom_value);
vrom(i) := to_stdlogicvector(rom_value);
end if;
end loop;
return vrom;
end function;
constant romval: rom_array := initromfromfile(filename);
begin
data <= romval(to_integer(unsigned(address))); -- read
end architecture;
Здесь есть значения по умолчанию для универсального ПЗУ по ширине, глубине и имени файла инициализации.
Для файла ROM_DATA.txt:
11111110
11101101
11111010
11001110
11011110
10101101
10111110
11101111
который имеет меньше значений данных, чем размер массива ПЗУ, остальные значения будут заполнены нулями.
Инициализация выполняется в объявлении объекта, содержащего значение ROM (и тип массива).
Функционал можно легко протестировать:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity rom_tb is
end entity;
architecture foo of rom_tb is
signal address: std_logic_vector (4 downto 0);
signal data: std_logic_vector (7 downto 0);
-- for IEEE Std 1076 revisions earlier than 2008:
function to_string (inp: std_logic_vector) return string is
variable image_str: string (1 to inp'length);
alias input_str: std_logic_vector (1 to inp'length) is inp;
begin
for i in input_str'range loop
image_str(i) := character'VALUE(std_ulogic'IMAGE(input_str(i)));
end loop;
return image_str;
end function;
begin
ROM0:
entity work.rom -- no generic map and generic values will default
port map (
address => address,
data => data
);
ROM_DUMP:
process
begin
for i in 0 to 2 ** address'length - 1 loop
address <= std_logic_vector (to_unsigned(i, address'length));
wait for 0 ns; -- delta cycle for address to update
wait for 0 ns; -- delta cycle for data to update
report "rom(" & integer'image(i) & ") = " & to_string(data);
end loop;
wait;
end process;
end architecture;
При запуске:
ghdl -a rom.vhdl
ghdl -e rom_tb
ghdl -r rom_tb
../../src/ieee/v93/numeric_std-body.vhdl:2098:7:@0ms:(assertion warning): NUMERIC_STD.TO_INTEGER: metavalue detected, returning 0
rom.vhdl:80:13:@0ms:(report note): rom(0) = 11111110
rom.vhdl:80:13:@0ms:(report note): rom(1) = 11101101
rom.vhdl:80:13:@0ms:(report note): rom(2) = 11111010
rom.vhdl:80:13:@0ms:(report note): rom(3) = 11001110
rom.vhdl:80:13:@0ms:(report note): rom(4) = 11011110
rom.vhdl:80:13:@0ms:(report note): rom(5) = 10101101
rom.vhdl:80:13:@0ms:(report note): rom(6) = 10111110
rom.vhdl:80:13:@0ms:(report note): rom(7) = 11101111
rom.vhdl:80:13:@0ms:(report note): rom(8) = 00000000
rom.vhdl:80:13:@0ms:(report note): rom(9) = 00000000
rom.vhdl:80:13:@0ms:(report note): rom(10) = 00000000
rom.vhdl:80:13:@0ms:(report note): rom(11) = 00000000
rom.vhdl:80:13:@0ms:(report note): rom(12) = 00000000
rom.vhdl:80:13:@0ms:(report note): rom(13) = 00000000
rom.vhdl:80:13:@0ms:(report note): rom(14) = 00000000
rom.vhdl:80:13:@0ms:(report note): rom(15) = 00000000
...
rom.vhdl:80:13:@0ms:(report note): rom(31) = 00000000
Вы можете видеть, что ПЗУ было инициализировано и доступно в момент времени 0 (после обработки).
Предупреждение исходит от адреса, не имеющего значения по умолчанию, которое может быть интерпретировано как двоичное число (все буквы «U») во время инициализации. После назначения адреса предупреждение больше не появляется.
Использование пакета IEEE numeric_std вместо пакета Synopsys std_logic_arith учитывает, что пакет IEEE поддерживается (и расширяется по редакциям), а пакет Synopsys — нет.
Использование переменной bit_vector позволяет использовать std.standard.read без обращения к пакету Synopsys std_logic_textio.
IEEE Std 1076-2008 и более поздние версии предоставляют пакет std_logic_1164, который предоставляет процедуру READ, совместимую с подтипами std_logic_vector, а также восьмеричные и шестнадцатеричные процедуры чтения. Редакции -2008 и более поздние также предоставляют предопределенные функции to_string для всех типов одномерных массивов, а также пакеты IEEE numeric_std_unsigned, заменяющие пакет Synopsys std_logic_unsigned.
Объявление универсального ПЗУ позволяет поддерживать другие размеры ПЗУ, предоставляя значения глубины и ширины. Общая константа, предоставленная для имени файла, позволяет поддерживать несколько ПЗУ с использованием разных имен файлов.
Существует несколько различных способов предоставления начальных значений для ПЗУ и ОЗУ, доступных для vhdl в Stackoverflow по поиску.
Как правило, постоянное запоминающее устройство (ПЗУ) не должно быть доступно для записи.
person
Community
schedule
27.03.2021