Столкнулся с проблемой при синтезе ROM, инициализированного из текстового файла. Для инициализации использовал пару функций которые работают с textio и std_logic_textio и вычитывают нужные строки из mif-файла.
После синтеза Quartus выбрасывает всю внутреннюю логику и притягивает выходы к нулям. Пробовал сперва играться с настройками синтеза касательно ROM, потом и RAM, но результата не добился.
При инициализации памяти массивом прямо из кода модуль синтезируется правильно, на настройки синтеза реагирует (вставляет блоки или логику по настройкам). Кривые функции чтения из файла скажите вы... но они отлично работают в Modelsim, и даже автоматически распознаются как логика или как блочная память в зависимости от размера ROM.
Уверен что многие здесь инициализировали память из файлов. В общем буду признателен за любую помощь в задании настроек синтеза, поиске косяков в инициализации памяти или указании на иные причуды квартуса.
Код тестового модуля прикрепляю.
З.Ы. Quartus 17.0 Standard.
CODE
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
--use work.fir_gen_pkg.all;
use ieee.std_logic_textio.hread;
use std.textio.all;
entity tst_rom is
generic
(
COEF_WIDTH : integer := 16;
C_OFFSET : integer := 16;
C_NUMBER : integer := 16;
FILENAME : string := "TEST_FILE.mif"
);
port
(
clk : in std_logic;
data : out std_logic_vector(COEF_WIDTH - 1 downto 0);
addr : in natural range 0 to C_NUMBER - 1
);
end entity;
architecture beh of tst_rom is
type memory_t is array (0 to C_NUMBER - 1) of std_logic_vector(COEF_WIDTH - 1 downto 0);
impure function read_mif_line(
FILENAME : in string;
C_OFFSET : in integer;
COEF_WIDTH : in integer
)
return std_logic_vector is
file mif: text is FILENAME;
constant CONTENTBEGIN : string := "CONTENT BEGIN";
-- variables
variable mifLine : line;
variable mifMess : string(1 to 80);
variable addr : integer;
variable char : character;
variable data : std_logic_vector(COEF_WIDTH - 1 downto 0);
begin
for i in 0 to 2047 loop
readline(mif, mifLine);
read(mifLine, mifMess(1 to mifLine'length));
exit when (mifMess(1 to 13) = CONTENTBEGIN);
end loop;
for i in 0 to C_OFFSET - 1 loop
readline(mif, mifLine);
end loop;
readline(mif, mifLine);
read(mifLine, addr);
assert addr = C_OFFSET
report "Line address value does'n match input offset."
severity Warning;
for i in 0 to 79 loop
read(mifLine, char);
exit when (char = ':');
end loop;
hread(mifLine, data);
file_close(mif);
return data;
end read_mif_line;
impure function mem_init
return memory_t is
variable tmp : memory_t;-- := (others => (others => '0'));
begin
for i in 0 to C_NUMBER - 1 loop
tmp(i) := read_mif_line(FILENAME, C_OFFSET + i, COEF_WIDTH);
end loop;
return tmp;
end mem_init;
constant rom : memory_t := mem_init;
--constant rom : memory_t := (0 => x"F020",
-- 1 => x"001F",
-- 2 => x"E01E",
-- 3 => x"001D",
-- 4 => x"DD1C",
-- 5 => x"001B",
-- 6 => x"001A",
-- 7 => x"1019",
-- 8 => x"FF18",
-- 9 => x"0017",
-- 10 => x"5016",
-- 11 => x"0015",
-- 12 => x"2314",
-- 13 => x"0013",
-- 14 => x"5A12",
-- 15 => x"0011");
begin
process(clk)
begin
if rising_edge(clk) then
data <= rom(addr);
end if;
end process;
end beh;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
--use work.fir_gen_pkg.all;
use ieee.std_logic_textio.hread;
use std.textio.all;
entity tst_rom is
generic
(
COEF_WIDTH : integer := 16;
C_OFFSET : integer := 16;
C_NUMBER : integer := 16;
FILENAME : string := "TEST_FILE.mif"
);
port
(
clk : in std_logic;
data : out std_logic_vector(COEF_WIDTH - 1 downto 0);
addr : in natural range 0 to C_NUMBER - 1
);
end entity;
architecture beh of tst_rom is
type memory_t is array (0 to C_NUMBER - 1) of std_logic_vector(COEF_WIDTH - 1 downto 0);
impure function read_mif_line(
FILENAME : in string;
C_OFFSET : in integer;
COEF_WIDTH : in integer
)
return std_logic_vector is
file mif: text is FILENAME;
constant CONTENTBEGIN : string := "CONTENT BEGIN";
-- variables
variable mifLine : line;
variable mifMess : string(1 to 80);
variable addr : integer;
variable char : character;
variable data : std_logic_vector(COEF_WIDTH - 1 downto 0);
begin
for i in 0 to 2047 loop
readline(mif, mifLine);
read(mifLine, mifMess(1 to mifLine'length));
exit when (mifMess(1 to 13) = CONTENTBEGIN);
end loop;
for i in 0 to C_OFFSET - 1 loop
readline(mif, mifLine);
end loop;
readline(mif, mifLine);
read(mifLine, addr);
assert addr = C_OFFSET
report "Line address value does'n match input offset."
severity Warning;
for i in 0 to 79 loop
read(mifLine, char);
exit when (char = ':');
end loop;
hread(mifLine, data);
file_close(mif);
return data;
end read_mif_line;
impure function mem_init
return memory_t is
variable tmp : memory_t;-- := (others => (others => '0'));
begin
for i in 0 to C_NUMBER - 1 loop
tmp(i) := read_mif_line(FILENAME, C_OFFSET + i, COEF_WIDTH);
end loop;
return tmp;
end mem_init;
constant rom : memory_t := mem_init;
--constant rom : memory_t := (0 => x"F020",
-- 1 => x"001F",
-- 2 => x"E01E",
-- 3 => x"001D",
-- 4 => x"DD1C",
-- 5 => x"001B",
-- 6 => x"001A",
-- 7 => x"1019",
-- 8 => x"FF18",
-- 9 => x"0017",
-- 10 => x"5016",
-- 11 => x"0015",
-- 12 => x"2314",
-- 13 => x"0013",
-- 14 => x"5A12",
-- 15 => x"0011");
begin
process(clk)
begin
if rising_edge(clk) then
data <= rom(addr);
end if;
end process;
end beh;