title: VHDL: Vivado 2016.4: Constant expression required in generic map
body: <p>As part of my description, within a wrapper component I generate N number of rom components. These roms are initialized from a text file containing the rom image. I pass the name of the file with which I wish to initialize each component as a generic parameter.</p>
  
  <p>A hopefully sufficient excerpt of the description is as follows:</p>
  
  <pre><code>library IEEE;
  use IEEE.STD_LOGIC_1164.ALL;
  use IEEE.NUMERIC_STD.ALL;
  
  package lnx1_types is
      type lnx1_cs is array (integer range &lt;&gt;) of std_logic_vector(7 downto 0);
      constant rom_count: integer := 9;
  end package lnx1_types;
  
  library IEEE;
  use IEEE.STD_LOGIC_1164.ALL;
  use IEEE.NUMERIC_STD.all;
  use STD.textio.all; -- For reading ucode roms from filesystem
  use ieee.std_logic_textio.all;
  
  use work.lnx1_types.all;
  
  entity lnx1_uc_rom is
      generic ( file_name : string := "" );
      port (  uc_addr : in    std_logic_vector(7 downto 0);
          uc_q    : out   std_logic_vector(7 downto 0) );
  end entity lnx1_uc_rom;
  
  architecture dataflow of lnx1_uc_rom is
      type lnx1_rom is array (0 to 2 ** 8 - 1) of std_logic_vector(7 downto 0);
  
      impure function lnx1_load_rom(file_name : in string)
          return lnx1_rom
      is
          file curr_rom_file: text;
  
          variable curr_il : line;
          variable curr_hx : std_logic_vector(7 downto 0);
  
          variable rom : lnx1_rom;
          variable good : boolean := TRUE;
      begin
          file_open (curr_rom_file, file_name, READ_MODE);
  
          for i in rom'range(1) loop
          if not endfile(curr_rom_file) then
              readline(curr_rom_file, curr_il); -- Read line
              read(curr_il, curr_hx, good); -- Read hex code
  
              rom(i) := curr_hx;
          end if;
          end loop;
  
          return rom;
      end function lnx1_load_rom;
  
      signal rom: lnx1_rom := lnx1_load_rom(file_name);
  begin
      uc_q &lt;= rom(to_integer(unsigned(uc_addr)));
  end architecture dataflow;
  
  
  library IEEE;
  use IEEE.STD_LOGIC_1164.ALL;
  use IEEE.NUMERIC_STD.all;
  use work.lnx1_types.all;
  
  entity lnx1_uc is
      port (  uc_addr : in    std_logic_vector(7 downto 0);
          cs_q    : out   lnx1_cs(rom_count - 1 downto 0)
      );
  end entity lnx1_uc;
  
  architecture dataflow of lnx1_uc is
  
      component lnx1_uc_rom is
          generic ( file_name : string := "" );
          port (  uc_addr : in    std_logic_vector(7 downto 0);
                  uc_q    : out   std_logic_vector(7 downto 0) );
      end component lnx1_uc_rom;
  
      type lnx1_rom_names is array (integer range &lt;&gt;) of string;
  
      constant rom_path: lnx1_rom_names := (
          0 =&gt; "r0.hex",
          1 =&gt; "r1.hex",
          2 =&gt; "r2.hex",
          3 =&gt; "r3.hex",
          4 =&gt; "r4.hex",
          5 =&gt; "r5.hex",
          6 =&gt; "r6.hex",
          7 =&gt; "r7.hex",
          8 =&gt; "r8.hex"
      );
  begin
      ucgen: for i in rom_path'range(1) generate
          rom0: lnx1_uc_rom
          generic map ( rom_path(i) )
          port map (
              uc_addr =&gt; uc_addr,
              uc_q =&gt; cs_q(i)
          );
      end generate ucgen;
  end architecture dataflow;
  
  
  entity intro_main is
  end intro_main;
  
  library IEEE;
  use IEEE.STD_LOGIC_1164.ALL;
  use IEEE.NUMERIC_STD.all;
  use work.lnx1_types.all;
  
  architecture testbench_lnx1_uc of intro_main is
      component lnx1_uc is
          port (  uc_addr : in    std_logic_vector(7 downto 0);
              cs_q    : out   lnx1_cs(rom_count - 1 downto 0)
          );
      end component lnx1_uc;
  
      signal uc_addr: std_logic_vector(7 downto 0);
      signal cs_q: lnx1_cs(rom_count - 1 downto 0);
  
  begin
      uc0: lnx1_uc
      port map (
          uc_addr =&gt; uc_addr,
          cs_q =&gt; cs_q
      );
  
      main: process
          variable index: integer range 0 to 255 := 0;
      begin
          uc_addr &lt;= std_logic_vector(to_unsigned(index, uc_addr'length(1)));
          wait for 5 ns;
  
          index := index + 1;
      end process main;
  
  end architecture testbench_lnx1_uc;
  </code></pre>
  
  <hr>
  
  <p>Although the description synthesis is without errors, attempt at simulation fails with the following message:</p>
  
  <pre><code>[VRFC 10-322] array element type cannot be unconstrained ["...":1080]
  [XSIM 43-3321] Static elaboration of top level VHDL design unit intro_main in library work failed.
  </code></pre>
  
  <p>line 1080 is referring to </p>
  
  <p><code>type lnx1_rom_names is array (integer range &lt;&gt;) of string;</code></p>
  
  <hr>
  
  <p>I accordingly made the following change:</p>
  
  <pre><code>- type lnx1_rom_names is array (integer range &lt;&gt;) of string;
  + type lnx1_rom_names is array (integer range &lt;&gt;) of string(0 to 32);
  </code></pre>
  
  <p>Now, by definition, <code>lnx_rom_names</code> no longer has an unconstrained element type. However, not only does this change not remove the previous simulation error, it also introduces some very curious errors during synthesis:</p>
  
  <pre><code>[Synth 8-3302] unable to open file 'r0.hexr1.hexr2.hexr3.hexr4.hexr5.' in 'r' mode ["...":1026]
  </code></pre>
  
  <p>This implies that during the first iteration of the <code>generate</code> loop, <code>rom_path(i)</code> indeed points to the first item, however there is no delimitation of elements at all - simply, the entire linear segment of data beginning at that point is passed, in a <code>string(0 to 32);</code>.</p>
  
  <p>As I write this, I realize that I have two questions, the latter borne out of trying to answer the first:</p>
  
  <ul>
  <li>Why does the unconstrained element type error persist?</li>
  <li>Why is the aforementioned array behavior present, namely the passing of a linear block of data of the array, rather than the actual array member?</li>
  </ul>
  
  <p>I suspect the answer in the latter may be due to VHDL simply not initializing the spare slots left in the <code>string(0 to 32)</code>, and thus the next element being allocated immediately afterwards; However, I would not believe VHDL to contain such broken functionality.</p>