VHDL:Vivado 2016.4:通用映射中需要常量表达式

VHDL:Vivado 2016.4:通用映射中需要常量表达式,vhdl,Vhdl,作为我描述的一部分,在包装器组件中,我生成了N个rom组件。这些rom是从包含rom映像的文本文件初始化的。我传递了文件名,希望使用该文件将每个组件初始化为通用参数 下面是描述的充分摘录: library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.NUMERIC_STD.ALL; package lnx1_types is type lnx1_cs is array (integer range <>) of std_logic

作为我描述的一部分,在包装器组件中,我生成了N个rom组件。这些rom是从包含rom映像的文本文件初始化的。我传递了文件名,希望使用该文件将每个组件初始化为通用参数

下面是描述的充分摘录:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;

package lnx1_types is
    type lnx1_cs is array (integer range <>) 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 <= 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 <>) of string;

    constant rom_path: lnx1_rom_names := (
        0 => "r0.hex",
        1 => "r1.hex",
        2 => "r2.hex",
        3 => "r3.hex",
        4 => "r4.hex",
        5 => "r5.hex",
        6 => "r6.hex",
        7 => "r7.hex",
        8 => "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 => uc_addr,
            uc_q => 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 => uc_addr,
        cs_q => cs_q
    );

    main: process
        variable index: integer range 0 to 255 := 0;
    begin
        uc_addr <= 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;
第1080行是指

type lnx1\u rom\u names是字符串的数组(整数范围)


因此,我做了以下更改:

- type lnx1_rom_names is array (integer range <>) of string;
+ type lnx1_rom_names is array (integer range <>) of string(0 to 32);
这意味着在
generate
循环的第一次迭代期间,
rom_路径(i)
确实指向第一个项目,但是根本没有元素的定界-简单地说,以
字符串(0到32)传递从该点开始的整个线性数据段

当我写这篇文章时,我意识到我有两个问题,后一个问题来自于试图回答第一个问题:

  • 为什么无约束图元类型错误持续存在
  • 为什么会出现上述数组行为,即传递数组的线性数据块,而不是实际的数组成员

我怀疑后者的答案可能是因为VHDL没有初始化
字符串(0到32)
中剩余的备用插槽,因此随后立即分配下一个元素;但是,我不相信VHDL包含这样的破坏性功能。

正如user1155120在评论中指出的,问题是由于数组元素类型的长度不正确,如果我确实尝试先进行模拟,我会收到一些非常有用的错误消息:

因此,改变路线

type lnx1_rom_name是字符串(1到32)的数组(整数范围)

type lnx1_rom_name是字符串(1到6)的数组(整数范围)

消除了所有错误,模拟产生了预期的结果

此外,字符串必须具有自然索引范围,因此
string(0到n)
无效,应该是
string(1到n)
;以下所有代码均已相应修订


由于我在这个问题上投入了(或者可能浪费了)太多时间,我认为至少不记录我关于字符串连接的发现是一种浪费

在合成过程中,当试图将数组元素作为参数传递给
通用映射
成员时,Vivado决定将尽可能多的顺序数组元素连接到大小不正确的数组元素中:

    ...
    type lnx1_rom_names is array (integer range <>) of string(1 to 32);

    constant rom_path: lnx1_rom_names := (
        0 => "r0.hex",
        1 => "r1.hex",
        2 => "r2.hex",
        3 => "r3.hex",
        4 => "r4.hex",
        5 => "r5.hex",
        6 => "r6.hex",
        7 => "r7.hex",
        8 => "r8.hex",
    );
begin

ucgen: for i in rom_path'range generate
    rom0: lnx1_romblk
    generic map (
        file_name => rom_path(i) -- << rom_path(i) evalues to "r0.hexr1.hexr2.hex ... "
    ) port map (
        addr => uc_addr,
        data => cs_q(i)
    );
end generate ucgen;
...
不会导致出现该错误

合成/模拟期间的日志比较(图像):


以下是我使用的说明,仅供参考。它与OP略有不同,因为我已经有时间来处理它,并且没有使用版本控制,但仍然演示了这个问题

顶层实体和体系结构位于底部,如果合适,应重命名

r0.hex文件示例:

内容并不重要,只需复制并重命名为r1、r2。。。等等

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;

package lnx1_types is
    type lnx1_cs is array (integer range <>) of std_logic_vector(7 downto 0);
    constant rom_count: integer := 2;
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_romblk is
    generic ( file_name : string := "";
          awidth : integer := 8;
          dwidth : integer := 8 );
    port (  addr    : in    std_logic_vector(AWIDTH-1 downto 0);
        data    : out   std_logic_vector(DWIDTH-1 downto 0) );
end entity lnx1_romblk;

architecture dataflow of lnx1_romblk is
    type lnx1_rom is array (0 to 2 ** AWIDTH - 1) of std_logic_vector(DWIDTH-1 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(DWIDTH-1 downto 0);

        variable rom : lnx1_rom;
        variable good : boolean := TRUE;
    begin
        -- If no filename passed, initailize with 0
        if file_name = "" then
            for i in rom'range loop
                rom(i) := (others => '0');
            end loop;
            return rom;
        end if;

        file_open (curr_rom_file, file_name, READ_MODE);

        for i in rom'range loop
        if not endfile(curr_rom_file) then
            readline(curr_rom_file, curr_il); -- Read line
            read(curr_il, curr_hx, good); -- Read binary value

            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
    data <= rom(to_integer(unsigned(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_romblk is -- Needs testbench
        generic ( file_name : string := "";
              awidth : integer := 8;
              dwidth : integer := 8 );
        port (  addr    : in    std_logic_vector(awidth-1 downto 0);
            data    : out   std_logic_vector(dwidth-1 downto 0) );
    end component lnx1_romblk;

    type lnx1_rom_names is array (integer range <>) of string(1 to 32);

    constant rom_path: lnx1_rom_names := (
        0 => "r0.hex",
        1 => "r1.hex",
        2 => "r2.hex",
        3 => "r3.hex",
        4 => "r4.hex"
--      5 => "r5.hex" -- Uncomment this line to generate the error.
--      6 => "r6.hex",
--      7 => "r7.hex",
--      8 => "r8.hex",
    );
begin
    ucgen: for i in rom_path'range generate
        rom0: lnx1_romblk
        generic map (
            file_name => rom_path(i)
        ) port map (
            addr => uc_addr,
            data => cs_q(i)
        );
    end generate ucgen;
end architecture dataflow;

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.all;
use work.lnx1_types.all;

-- Here should go the top level entity declaration; I initially created
-- the project with the name "intro_main", so change to whatever is your case.

entity intro_main is
end entity intro_main;

architecture top_level 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, cs_q );
end architecture;
IEEE库;
使用IEEE.STD_LOGIC_1164.ALL;
使用IEEE.NUMERIC_STD.ALL;
包lnx1_类型为
lnx1_cs型是标准逻辑向量(7到0)的数组(整数范围);
常量rom_计数:整数:=2;
端封装lnx1_类型;
图书馆IEEE;
使用IEEE.STD_LOGIC_1164.ALL;
使用IEEE.NUMERIC_STD.all;
使用STD.textio.all;——用于从文件系统读取ucode ROM
使用ieee.std_logic_textio.all;
使用work.lnx1_types.all;
实体lnx1_romblk为
通用(文件名:字符串=“”);
awidth:整数:=8;
dwidth:整数:=8);
端口(地址:标准逻辑向量中(AWIDTH-1向下至0);
数据:输出标准逻辑向量(DWIDTH-1向下至0);
终端实体lnx1_romblk;
lnx1_romblk的架构数据流为
lnx1_rom型是标准逻辑_矢量(DWIDTH-1向下至0)的阵列(0至2**AWIDTH-1);
不纯函数lnx1_加载_rom(文件名:字符串形式)
返回lnx1_rom
是
文件当前rom文件:文本;
可变货币:行;
变量curr_hx:std_逻辑_向量(DWIDTH-1向下至0);
变量rom:lnx1_-rom;
变量good:boolean:=TRUE;
开始
--如果未传递文件名,则使用0初始化
如果文件名为“”,则
在rom'range循环中的i
rom(i):=(其他=>“0”);
端环;
返回rom;
如果结束;
文件打开(当前rom文件、文件名、读取模式);
在rom'range循环中的i
如果不是endfile(curr\u rom\u文件),则
读线(当前rom文件,当前il);--读线
读(curr_il,curr_hx,good);-读取二进制值
rom(i):=电流hx;
如果结束;
端环;
返回rom;
端功能lnx1_加载_rom;
信号rom:lnx1_rom:=lnx1_加载_rom(文件名);
开始
数据“r0.hex”,
1=>“r1.hex”,
2=>“r2.hex”,
3=>“r3.hex”,
4=>“r4.hex”
--5=>“r5.hex”--取消注释此行以生成错误。
--6=>“r6.hex”,
--7=>“r7.hex”,
--8=>“r8.hex”,
);
开始
ucgen:为rom_路径范围内的i生成
rom0:lnx1u romblk
通用地图(
文件名=>rom路径(i)
)港口地图(
地址=>uc\U地址,
数据=>cs_q(i)
);
末端生成ucgen;
终端架构数据流;
图书馆IEEE;
使用IEEE.STD_LOGIC_1164.ALL;
使用IEEE.NUMERIC_STD.all;
使用work.lnx1_types.all;
--这里应该是顶级实体声明;我最初创建
--该项目名为“intro_main”,因此请根据您的情况进行更改。
实体简介主要是
结束实体介绍;
体系结构介绍的顶层是
组件lnx1_uc为
端口(uc地址:标准逻辑向量中(7到0);
cs_q:out lnx1_cs(rom_计数-1下降到0)
);
端部元件lnx1_uc;
    ...
    type lnx1_rom_names is array (integer range <>) of string(1 to 32);

    constant rom_path: lnx1_rom_names := (
        0 => "r0.hex",
        1 => "r1.hex",
        2 => "r2.hex",
        3 => "r3.hex",
        4 => "r4.hex",
        5 => "r5.hex",
        6 => "r6.hex",
        7 => "r7.hex",
        8 => "r8.hex",
    );
begin

ucgen: for i in rom_path'range generate
    rom0: lnx1_romblk
    generic map (
        file_name => rom_path(i) -- << rom_path(i) evalues to "r0.hexr1.hexr2.hex ... "
    ) port map (
        addr => uc_addr,
        data => cs_q(i)
    );
end generate ucgen;
...
type lnx1_rom_names is array (integer range <>) of string(1 to 32);

constant rom_path: lnx1_rom_names := (
    0 => "r0.hex",
    1 => "r1.hex",
    2 => "r2.hex",
    3 => "r3.hex",
    4 => "r4.hex",
    5 => "r5.hex"
);
constant rom_path: lnx1_rom_names := (
    0 => "r0.hex",
    1 => "r1.hex",
    2 => "r2.hex",
    3 => "r3.hex",
    4 => "r4.hex"
);
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;

package lnx1_types is
    type lnx1_cs is array (integer range <>) of std_logic_vector(7 downto 0);
    constant rom_count: integer := 2;
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_romblk is
    generic ( file_name : string := "";
          awidth : integer := 8;
          dwidth : integer := 8 );
    port (  addr    : in    std_logic_vector(AWIDTH-1 downto 0);
        data    : out   std_logic_vector(DWIDTH-1 downto 0) );
end entity lnx1_romblk;

architecture dataflow of lnx1_romblk is
    type lnx1_rom is array (0 to 2 ** AWIDTH - 1) of std_logic_vector(DWIDTH-1 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(DWIDTH-1 downto 0);

        variable rom : lnx1_rom;
        variable good : boolean := TRUE;
    begin
        -- If no filename passed, initailize with 0
        if file_name = "" then
            for i in rom'range loop
                rom(i) := (others => '0');
            end loop;
            return rom;
        end if;

        file_open (curr_rom_file, file_name, READ_MODE);

        for i in rom'range loop
        if not endfile(curr_rom_file) then
            readline(curr_rom_file, curr_il); -- Read line
            read(curr_il, curr_hx, good); -- Read binary value

            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
    data <= rom(to_integer(unsigned(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_romblk is -- Needs testbench
        generic ( file_name : string := "";
              awidth : integer := 8;
              dwidth : integer := 8 );
        port (  addr    : in    std_logic_vector(awidth-1 downto 0);
            data    : out   std_logic_vector(dwidth-1 downto 0) );
    end component lnx1_romblk;

    type lnx1_rom_names is array (integer range <>) of string(1 to 32);

    constant rom_path: lnx1_rom_names := (
        0 => "r0.hex",
        1 => "r1.hex",
        2 => "r2.hex",
        3 => "r3.hex",
        4 => "r4.hex"
--      5 => "r5.hex" -- Uncomment this line to generate the error.
--      6 => "r6.hex",
--      7 => "r7.hex",
--      8 => "r8.hex",
    );
begin
    ucgen: for i in rom_path'range generate
        rom0: lnx1_romblk
        generic map (
            file_name => rom_path(i)
        ) port map (
            addr => uc_addr,
            data => cs_q(i)
        );
    end generate ucgen;
end architecture dataflow;

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.all;
use work.lnx1_types.all;

-- Here should go the top level entity declaration; I initially created
-- the project with the name "intro_main", so change to whatever is your case.

entity intro_main is
end entity intro_main;

architecture top_level 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, cs_q );
end architecture;