file read and write function fails to execute in functions
Working on migrating old code into the next FPGA generation. That means the code worked fine over the last twenty years and had a few migration since utilizing non Altera FPGAs and tools. Now I am trying to compile the code, that was written as standard IEEE 93 VHDL into Altera’s Max 10 family, using the Quartus Prime Version 15.1.0.
I got a lot of surprises during compiling and found that standard code is not executing correctly. However, for most of the issues I was able to work around. But this one is such a trivial standard code, that I think Altera has an issue in its internal code in conjunction when file operations and report calls are made in a function.
The code example below is supposed to save hex data from a file into ROM, for later read out into a special SPI interface that initializes the analog ASICS on the board. Wasting hours of simulating and testing I found out that the following one or two line(s) is (are) not correctly executed. < readline (RomFile, RomFileLine) ; > respective < read(RomFileLine, zahl); >. All values in the AnaConfigROM are 0. If I pass the instruction < Zahl := "A5"; > before the call to < ROM(add_i) := Hex2Vector(Zahl); > then the ROM will be initialized with the value hex A5 (see code) so the rest of the code works. Also the count of the number of hex values in the file with the number of ROM values is correctly, in other words the EOF statement of the file is correctly.
I try to add an output file "debug.txt” to dump “Zahl” back but it does not execute those write statements either.
Does someone know what the issue is, and how to work around? (Going into the schematic editor and using lpm_rom or so is not an option.)
Please find below the code ( I deleted stuff out to keep it short)
-- Memory ROM File for configuration of the Analog ASICS
LIBRARY ieee;
USE ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use std.textio.all; -- used for file access and manipulation
-- Entity Declaration
ENTITY AnalogConfigROMFile IS
-- {{ALTERA_IO_BEGIN}} DO NOT REMOVE THIS LINE!
PORT
(
DigtalReset, AddressClock : In std_Ulogic;
Data : out std_ulogic_vector ( 7 downto 0 );
FileEnd : out std_Ulogic
);
-- {{ALTERA_IO_END}} DO NOT REMOVE THIS LINE!
END AnalogConfigROMFile;
-- Architecture Body
ARCHITECTURE RTL_AnalogConfigROMFile OF AnalogConfigROMFile IS
signal Addr : integer range 0 to 4096; -- 4kByte address space (12 bit addressing)
type ROM_Table is array (Natural range <>) of std_ulogic_vector(7 downto 0); -- undifined size array with 8 bit data value
type ROM_int_Table is array (Natural range <>) of integer;
type FileType is file of text;
SUBTYPE NIBBLE IS std_ulogic_vector (3 DOWNTO 0);
SUBTYPE BYTE IS std_ulogic_vector (7 DOWNTO 0);
SUBTYPE WORD IS std_ulogic_vector (15 DOWNTO 0);
SUBTYPE decimal_digit IS INTEGER RANGE 0 TO 9;
-- translate Hex string to vector
function Hex2Vector(stringZahl : in string ) return BYTE is
variable NibbHigh, Nibb : NIBBLE;
--debug variable
variable debugstr : line;
Begin
-- this is a debug test that does not work too.
report ("Alfa Zahl is =" & stringZahl); -- error --> does not report
write(debugstr, "Alfa Zahl is = "); -- error --> does not write
write(debugstr, stringZahl); -- error --> does not write
writeline(output, debugstr); -- error --> does not write to stdout
-- end not woring debug test
for i in 1 to 2 loop
NibbHigh := Nibb;
Case (stringZahl(i)) is
when '0' => Nibb := "0000";
When '1' => Nibb := "0001";
When '2' => Nibb := "0010";
When '3' => Nibb := "0011";
When '4' => Nibb := "0100";
When '5' => Nibb := "0101";
When '6' => Nibb := "0110";
When '7' => Nibb := "0111";
When '8' => Nibb := "1000";
When '9' => Nibb := "1001";
When 'A' => Nibb := "1010";
When 'B' => Nibb := "1011";
When 'C' => Nibb := "1100";
When 'D' => Nibb := "1101";
When 'E' => Nibb := "1110";
When 'F' => Nibb := "1111";
When 'a' => Nibb := "1010";
When 'b' => Nibb := "1011";
When 'c' => Nibb := "1100";
When 'd' => Nibb := "1101";
When 'e' => Nibb := "1110";
When 'f' => Nibb := "1111";
when others => Nibb := "0000";
end case;
end loop;
return NibbHigh & Nibb;
end function;
-- *** Read a file into the ROM ***
impure function InitRomFromFile (RomFileName : in string) return ROM_Table is
--file RomFile : text is in RomFileName;
file RomFile : text;
file debugfile : text;
variable RomFileLine : line;
variable ROM : ROM_Table (0 to 4095);
variable Zahl : string (1 to 2);
variable add_i : integer;
-- file outputfile : TEXT open WRITE_MODE is "verify_out.txt";
-- file debugfile : TEXT is out "debug.txt";
variable debugstr : line;
begin
file_open (RomFile, RomFileName, read_mode);
file_open (debugfile, "debug.txt", write_mode);
add_i := 0;
while ( (add_i <= 4095) And (not endfile (RomFile)) ) loop -- Note Reads the eof correctly - loop count is correct!!
-- Note a forced ending for loop <10000 is required;
-- !!! Note the forced ending must be first in the statement or you receive a compiler error
-- !!! while ( (not (endfile (RomFile))) AND (add_i <= 4200) ) loop gives an analysis error !!!
readline (RomFile, RomFileLine); -- error --> unknown if statment works correctly
read(RomFileLine, Zahl); -- error --> the loop is counted correctly but value of zahl is unknown
-- added some debug code -- not working
report ("Beta Zahl is =" & Zahl); -- error --> does not report zahl
write(debugstr, "Beta Zahl is = ");
write(debugstr, Zahl);
writeline(output, debugstr); -- error --> does not write to stdout
writeline(debugfile, debugstr); -- error --> does not create and write to debugfile
-- end debug code
-- Zahl := "A5"; -- using this statment will initialize the ROM with all A5
ROM(add_i) := Hex2Vector(Zahl);
add_i := add_i + 1;
end loop;
file_close(RomFile);
file_close(debugfile);
return ROM;
end function;
-- constant AnaConfigROM : ROM_Table := (X"00",X"FF",X"02",X"03",X"04",X"05",X"D5",X"00" );
constant AnaConfigROM : ROM_Table := InitRomFromFile("AnaROMConfig.txt");
BEGIN
-- Main Process this process is used to return data to the SPI Shift Register
ROM_Read: Process (DigtalReset, AddressClock)
Begin
if DigtalReset = '0' then
Addr <= 0;
Data <= "00000000";
FileEnd <= '0';
elsif rising_edge (AddressClock) then
Data <= AnaConfigROM(Addr);
if Addr < AnaConfigROM'high then
Addr <= Addr + 1;
else
Addr <= 0;
FileEnd <= '1';
end if;
end if;
End Process ROM_Read;
END RTL_AnalogConfigROMFile;