gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-12-01 06:34:55 34 4
gpt4 key购买 nike

作为我描述的一部分,在一个包装器组件中,我生成了 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;

尽管描述合成没有错误,但尝试模拟失败并显示以下消息:
[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.

第 1080 行是指
type lnx1_rom_names is array (integer range <>) of string;
我相应地进行了以下更改:
- type lnx1_rom_names is array (integer range <>) of string;
+ type lnx1_rom_names is array (integer range <>) of string(0 to 32);

现在,根据定义, lnx_rom_names不再具有不受约束的元素类型。然而,这种变化不仅没有消除之前的仿真错误,而且还在综合过程中引入了一些非常奇怪的错误:
[Synth 8-3302] unable to open file 'r0.hexr1.hexr2.hexr3.hexr4.hexr5.' in 'r' mode ["...":1026]

这意味着在 generate 的第一次迭代期间循环, rom_path(i)确实指向第一项,但是根本没有元素的定界 - 简单地说,从该点开始的整个线性数据段在 string(0 to 32); 中传递.

在我写这篇文章时,我意识到我有两个问题,后者是为了回答第一个问题:
  • 为什么不受约束的元素类型错误仍然存​​在?
  • 为什么会出现上述数组行为,即传递数组的线性数据 block ,而不是实际的数组成员?

  • 我怀疑后者的答案可能是由于 VHDL 根本没有初始化 string(0 to 32) 中留下的备用插槽。 ,因此之后立即分配下一个元素;但是,我不相信 VHDL 包含这种损坏的功能。

    最佳答案

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

    enter image description here

    因此,改变线路
    type lnx1_rom_names is array (integer range <>) of string(1 to 32);

    type lnx1_rom_names is array (integer range <>) of string(1 to 6);
    消除了所有错误,模拟产生了预期的结果。

    此外,字符串必须有一个自然的索引范围,所以 string(0 to n)无效,应为 string(1 to n) ;以下所有代码已相应修改。

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

    在综合期间,当尝试将数组元素作为参数传递给 generic map 时,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;
    ...

    我又修改了一些描述,发现要复制串联行为, 字符串数组中存在的字符总数必须大于 单个数组元素的字符串长度 , IE。:
    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"
    );

    将失败并显示 [Synth 8-3302] unable to open file 'r0.hexr1.hexr2.hexr3.hexr4.hexr5.' in 'r' mode ["D:/...":48]
    然而
    constant rom_path: lnx1_rom_names := (
    0 => "r0.hex",
    1 => "r1.hex",
    2 => "r2.hex",
    3 => "r3.hex",
    4 => "r4.hex"
    );

    不会导致该错误出现。

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

    With concatenation error

    Without concatenation error

    作为引用,以下是我使用的描述。它与 OP 略有不同,因为我已经有时间研究它并且没有使用版本控制,但仍然证明了问题。

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

    r0.hex 文件示例: Click here

    内容不重要,简单复制并重命名为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;

    关于VHDL:Vivado 2016.4:通用映射中需要的常量表达式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44874635/

    34 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com