Xilinx supports Spartan-6 in ISE only.
From UG 687 XST User Guide for Virtex-6, Spartan-6, and 7 Series Devices RAM Initial Contents, Specifying Initial Contents in an External Data File (P.221):
type RamType is array(0 to 127) 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")
Note the UG687 version shown is from ISE 13.1 March 1, 2011.
The shortcoming here from the present question is the lack of support for reading hex values from a text file.
There are several ways to address this. ISE's unisim library supports the conversion of hex to binary in unisim_PKG.vhd (line 795), which would require a read procedure of type string with a subtype indication with a length of 8. Also an hread procedure can be written or imported (there is at least one open source example available).
In all cases UG687 Chapter 3 VHDL Support lists the suprograms required to implement a ROM initialization routine where we also note support for Synopsys package std_logic_textio procedure hread. (The table of supported subprograms begins on P.66.)
There are useful embelishments that can be added to an initialization function such as an endfile test which can abort the for loop and file_close to allow re-entrant calls.
Note the UG687 VHDL InitRamFromFile impure function (P.221) doesn't demonstrate the requirement for package textio declarations be made visible (use std.textio.all;
).
The memory array variable in the initialization function can also declare the object with an initial value of all zeros.
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity foo is
end entity;
architecture fum of foo is
constant rom_file_name: string := "rom_hex_file.txt";
use std.textio.all; -- declaration of text
use ieee.std_logic_textio.all; -- hread;
type PM_t is array(0 to 511) of unsigned(31 downto 0);
impure function init_rom_from_file (rom_filename: string) return PM_t is
FILE romfile: text is rom_filename;
variable rom: PM_t := (others => (others => '0'));-- zero fill
variable fileline: line; -- std.standard
variable rom_element: std_ulogic_vector (31 downto 0);
begin
for i in PM_t'range loop
if endfile(romfile) then
exit; -- the loop
end if;
readline (romfile, fileline); -- one entry per line
hread (fileline, rom_element); -- read hex
rom(i) := unsigned(rom_element);
end loop;
file_close (romfile);
return rom;
end function;
Constant PM_c: PM_t := init_rom_from_file(rom_file_name);
begin
process
-- for revisions earlier than -2008:
function to_string (inp: unsigned) return string is
variable image_str: string (1 to inp'length);
alias input_str: unsigned (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
for i in 0 to 12 loop -- arbitrary number of elements to show
-- zero filled array elements could be for i in PM_c'range loop
report LF & HT & "PM_c(" & integer'image(i) &") = "
& to_string(PM_c(i));
end loop;
wait;
end process;
end architecture;
With rom_hex_file.txt containing:
04000000
08000000
540007FE
0C000000
10000000
produces:
%: ghdl -a -fsynopsys foo.vhdl
%: ghdl -e -fsynopsys foo
%: foo
foo.vhdl:46:12:@0ms:(report note):
PM_c(0) = 00000100000000000000000000000000
foo.vhdl:46:12:@0ms:(report note):
PM_c(1) = 00001000000000000000000000000000
foo.vhdl:46:12:@0ms:(report note):
PM_c(2) = 01010100000000000000011111111110
foo.vhdl:46:12:@0ms:(report note):
PM_c(3) = 00001100000000000000000000000000
foo.vhdl:46:12:@0ms:(report note):
PM_c(4) = 00010000000000000000000000000000
foo.vhdl:46:12:@0ms:(report note):
PM_c(5) = 00000000000000000000000000000000
foo.vhdl:46:12:@0ms:(report note):
PM_c(6) = 00000000000000000000000000000000
foo.vhdl:46:12:@0ms:(report note):
PM_c(7) = 00000000000000000000000000000000
foo.vhdl:46:12:@0ms:(report note):
PM_c(8) = 00000000000000000000000000000000
foo.vhdl:46:12:@0ms:(report note):
PM_c(9) = 00000000000000000000000000000000
foo.vhdl:46:12:@0ms:(report note):
PM_c(10) = 00000000000000000000000000000000
foo.vhdl:46:12:@0ms:(report note):
PM_c(11) = 00000000000000000000000000000000
foo.vhdl:46:12:@0ms:(report note):
PM_c(12) = 00000000000000000000000000000000
%:
Notes:
- the format or report statements prior to user specified output is implementation dependent with required elements.
- The initial value of
rom
is supported by UG687 Chapter 3 VHDL Objects, VHDL Variables but not supported in the withdrawn standard IEEE Std 1076.6-2004 8.3.4.1 Object declarations (the standard was withdrawn due to the lack of vendor participation). If UG687 is in error a variable assignment (rom := (others => (others=> '0'));
) immediately prior to the for loop in the initialization function could be used. The initial value in the variable declaration would be ignored if 1076.6 compliant.