Intel® Quartus® Prime Software
Intel® Quartus® Prime Design Software, Design Entry, Synthesis, Simulation, Verification, Timing Analysis, System Design (Platform Designer, formerly Qsys)
Announcements
The Intel sign-in experience is changing in February to support enhanced security controls. If you sign in, click here for more information.
15806 Discussions

Initializing array of structs from file | VHDL

Christian_Woznik
391 Views

Hello,

as I just figured out Quartus does not support any textIO functions during synthesis. Why? What is the reason?

I want to instantiate a group of modules with different generics for each of them. The generics are in a file with a given format, easily parsable. In Vivado I just write the function to parse it, set the parsed values as constant and use this array in a for generate loop to instantiate my modules.

How should I do that in Quartus if I can not read files during synthesis? What options do I have?

I really would like to avoid writing a script that just converts the file format that I have into an VHDL file to then import the constant values. That seems unnecessary and adds one more step that could cause problems.

Best regards
Christian

0 Kudos
1 Reply
Dagobah
Novice
339 Views

I am also looking into this decade old problem of no support in Quartus for file input for initialization.  So far, it seems that file_open() from std.textio.all returns a NULL value or EOF as the subsequent call to endfile() exits my looping procedure immediately with no errors or warnings.  I can load algorithmically computed constants in VHDL into an array as an initialization function with no problems and the Quartus Auto MIF generator creates the initialization MIF file and loads the array as expected.  When using a file for input, the Quartus Auto MIF generator knows about the file name and stores that information as part of the MIF signature as though it is attempting to read the file.  The following snippet is from the Quartus Auto MIF generator output, but the coefficients are all zero and the file was not actually read, so I left them out of the snippet example to save space.  Replacing the textio read input variable with a constant value, all other things being equal, fills the Auto generated MIF file with the constant value as expected and stores the unread file name as part of the MIF signature.

 

-- begin_signature
-- ram_dptrue_core(ram_bits
-- 1152
-- dq1_bits
-- 18
-- dq2_bits
-- 18
-- hex_file
-- 1 to 10
-- "coeffs.dat")
-- end_signature
WIDTH=18;
DEPTH=64;

ADDRESS_RADIX=UNS;
DATA_RADIX=BIN;

CONTENT BEGIN
...
END;

 

It is possible the file_open() requires a search path setting in Quartus that is not set but I've placed the file coeffs.dat in many locations throughout the project directory structure and tried absolute paths on a Linux file system.  I am wondering if there is an alternate VHDL 93 package to std.textio such as VHDL 2008 that works.  The usual methods of file read to load an array has been working in my VHDL applications with several other reputable synthesis tools and GHDL for simulation with no issues.  Some of the Quartus workarounds posted include loading MIF files with vendor specific extended attributes that would in effect break my existing code structure and no longer allow compatible GHDL simulation.  Another work around method I've come across involves creating VHDL packages with data coefficients but I've yet to try that method and see if I can create a compatible solution that satisfies code portability and GHDL simulation.

 

The usual method that has been working in other synthesis tools and simulators except for Quartus is posted here:

https://vhdlwhiz.com/initialize-ram-from-file/

 

Also, this method is straight out of the Lattice Diamond Synthesis Engine User Guide as a design reference and uses similar concepts from the above link:

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use std.textio.all;
entity rams_20c is
port(clk : in std_logic;
we : in std_logic;
addr : in std_logic_vector(5 downto 0);
din : in std_logic_vector(31 downto 0);
dout : out std_logic_vector(31 downto 0));
end rams_20c;
architecture syn of rams_20c is
type RamType is array(0 to 63) of bit_vector(31 downto 0);
impure function InitRamFromFile (RamFileName : in string)
return RamType is
FILE RamFile : text is in RamFileName;
variable RamFileLine : line;
variable RAM : RamType;
begin
for I in RamType'range loop
readline (RamFile, RamFileLine);
read (RamFileLine, RAM(I));
end loop;
return RAM;
end function;
signal RAM : RamType := InitRamFromFile("rams_20c.data");
begin
process (clk)
begin
if clk'event and clk = '1' then
if we = '1' then
RAM(conv_integer(addr)) <= to_bitvector(din);
end if;
dout <= to_stdlogicvector(RAM(conv_integer(addr)));
end if;
end process;
end syn;

 

If anyone has a solution or suggestion to solve this problem in Quartus with VHDL code portability in mind, it would be appreciated by many VHDL developers.  I will continue experimenting and if a viable solution is found, will post an update.

Reply