VHDL中可综合化的多维数组

10

我需要使用多维数组来表示我的设计中的矩阵。我已经尝试了两种可用的选项:

  1. Declaring array of arrays

    type t11 is array (0 to c1_r2) of std_logic_vector(31 downto 0);
    type t1 is array (0 to r1) of t11; --r1*c1_r2 matrix
    
  2. Multidimensional arrays.

    type matrix  is array (natural range <>, natural range <>)
                   of std_logic_vector(31 downto 0);
    
然而,在这两种情况下,我的Xilinx后综合模拟会出现错误:“仅允许在单维数组上使用切片名称”。 在可综合的VHDL设计中正确使用多维数组的方法是什么?欢迎任何建议。 我正在使用附带Xilinx ISE的XST综合器。 我对i和j都进行了索引,因为我的矩阵维度是m * n * 32。 我的实体中有一个名为a_in的网络。
    a_in: in  matrix (0 to size - 1, 0 to size - 1);

被修改为

    a_in : in STD_LOGIC_VECTOR3 ( 1 downto 0 , 1 downto 0 , 31 downto 0 );

在我的程序中,我通过两个生成语句来访问矩阵内的k和m的值,如下所示:
    add_instx: add 
            port map (
                a => a_in(k,m),
                b => b_in(k,m),
                clk => clk,
                sclr => clr,
                ce => start,
                result => temp_out(k,m),
                rdy => add_over(k,m)
            );

我的测试台输入为a_in:

    a_in <= (("00111111100000000000000000000000", "00000000000000000000000000000000"),("00000000000000000000000000000000", "00111111100000000000000000000000"));

我的综合生成了Xst:387类型的警告 - 附加到该网的KEEP属性可能会妨碍时序优化。通过删除此属性,您可以获得更好的结果。然而,我没有设置任何keep属性,也不确定在哪里查找此属性。请帮忙!非常感谢。
对不起,我没有添加完整的代码。请查看下面的代码和包。
    library IEEE;
    use IEEE.STD_LOGIC_1164.ALL;
    use IEEE.NUMERIC_STD.ALL;
    use work.mat_pak.all;


    entity newproj is
        generic ( size:  natural := 2 );
        port ( 
            clk:                in  std_logic;
            clr:                in  std_logic;
            start:              in  std_logic;
            a_in:               in  matrix (0 to size - 1, 0 to size - 1);
            b_in:               in  matrix (0 to size - 1, 0 to size - 1);
            aplusb:             out matrix (0 to size - 1, 0 to size - 1);
            parallel_add_done:  out std_logic);
    end newproj;

    architecture Behavioral of newproj is
    COMPONENT add --This is a 32 bit floating point add IP core
      PORT (
        a : IN STD_LOGIC_VECTOR(31 DOWNTO 0);
        b : IN STD_LOGIC_VECTOR(31 DOWNTO 0);
        clk : IN STD_LOGIC;
         sclr : IN STD_LOGIC;
         ce : IN STD_LOGIC;
        result : OUT STD_LOGIC_VECTOR(31 DOWNTO 0);
         rdy: OUT STD_LOGIC
      );
    END COMPONENT;

        signal temp_out: matrix (0 to size - 1, 0 to size - 1) :=  (others => (others => (others => '0')));  
        signal add_over: bmatrix (0 to size - 1, 0 to size - 1) := (others => (others => '0'));  

    begin

        g0: 
            for k in  0 to mat_dim generate 
            g0x: 
                for m in 0 to mat_dim generate
                add_instx: add 
                    port map (
                        a => a_in(k,m),
                        b => b_in(k,m),
                        clk => clk,
                        sclr => clr,
                        ce => start,
                        result => temp_out(k,m),
                        rdy => add_over(k,m)
                    );
            end generate;   
        end generate;

        aplusb <= temp_out;

         p1_add:
        process (add_over)
            variable check_all_done: std_logic;
        begin
            check_all_done := '1';
            for k in 0 to mat_dim loop
                for m in 0 to mat_dim loop
                    check_all_done := check_all_done and add_over(k)(m);
                end loop;
            end loop;
            parallel_add_done <= check_all_done;
        end process;

    end Behavioral;

这里使用的软件包是:
    library IEEE;
    use IEEE.STD_LOGIC_1164.all;
    use IEEE.NUMERIC_STD.ALL;


    package mat_pak is

        CONSTANT mat_dim : natural := 2;

        type matrix  is array (natural range <>, natural range <>)
                   of std_logic_vector(31 downto 0);
        type bmatrix is array (natural range <>, natural range <>) 
                   of std_logic;                      


    end mat_pak;

后综合仿真模型文件自行修改了实体的排序和数据类型。该实体如下:

    library IEEE;
    use IEEE.STD_LOGIC_1164.ALL;
    library UNISIM;
    use UNISIM.VCOMPONENTS.ALL;
    use UNISIM.VPKG.ALL;

    entity newproj is
      port (
        clk : in STD_LOGIC := 'X'; 
        clr : in STD_LOGIC := 'X'; 
        start : in STD_LOGIC := 'X'; 
        parallel_add_done : out STD_LOGIC; 
        a_in : in STD_LOGIC_VECTOR3 ( 1 downto 0 , 1 downto 0 , 31 downto 0 ); 
        b_in : in STD_LOGIC_VECTOR3 ( 1 downto 0 , 1 downto 0 , 31 downto 0 ); 
        aplusb : out STD_LOGIC_VECTOR3 ( 1 downto 0 , 1 downto 0 , 31 downto 0 ) 
      );
    end newproj;

你使用的是哪个综合工具? - Jonathan Drolet
1
请展示一下您尝试使用的多维数组。您是在尝试索引i和j两个指数吗?mysignal(i)(j)?还是其他什么? - Josh
我想强调Josh的评论。请向我们展示i和j的使用和声明位置。上述内容不是最小、完整和可验证的示例。也请向我们展示嵌套的generate语句。你的问题很可能源于从未分配矩阵的某些部分,听起来像是因为它有一个固定值而被吃掉了。请参阅约束指南(cgd.pdf)。请查看保留保留层次结构(特别是)。切片仅适用于一维数组(请参阅IEEE Std 1076-2008, 8.5 切片名称)。 - user1155120
阅读Paebbels关于他的PoC库的插件(他在回答中没有做出不正确的声明),它引起了对a_in信号声明中缺少STD_LOGIC_VECTOR3类型标记的关注。您的问题不是最小,完整和可验证的示例。该问题无法被复制或完全理解。 - user1155120
对于我的问题中不完整的信息,向David Koontz先生表示道歉。我已经添加了程序和软件包数据。std_logic_vector3是由Xilinx综合工具在综合后自动生成的。根据您的建议,我也会查看约束指南。如果有更多意见,不胜感激!非常感谢你。 - Soumya
显示剩余2条评论
2个回答

12

你的第一个数组并不是多维数组,而是嵌套了两次的一维数组。

你的示例:

type t11 is array (0 to c1_r2) of std_logic_vector(31 downto 0);
type t1 is array (0 to r1) of t11;

这个定义更加清晰明了:

subtype t_dim1 is std_logic_vector(31 downto 0);
type t_dim1_vector is array(natural range <>) of t_dim1;
subtype t_dim2 is t_dim1_vector(0 to c1_r2);
type t_dim3_vector is array(natural range <>) of t_dim2;
subtype t_dim3 is t_dim3_vector(0 to r1);

你可以通过索引每个维度来访问这个结构:

signal matrix3 : t_dim3;
signal matrix2 : t_dim2;
signal matrix1 : t_dim1;
signal slv : std_logic_vector(31 downto 0);
signal sl : std_logic;

matrix2 <= matrix3(i);
matrix1 <= matrix2(j);
matrix1 <= matrix3(i)(j);
slv <= matrix3(i)(j);
sl <= matrix3(i)(j)(k);

您也可以对每个维度进行切片:

signal matrix3 : t_dim3;
signal slice3 : t_dim3_vector(0 to 3);
signal slice2 : t_dim2_vector(0 to 3);
signal slv : std_logic_vector(7 downto 0);

slice3 <= matrix3(4 to 7);
slice2 <= matrix3(i)(2 to 5);
slice2 <= slice3(i)(2 to 5);
slv <= matrix3(i)(j)(15 downto 8);

你的第二个示例:

type matrix is array (natural range <>, natural range <>) of std_logic_vector(31 downto 0);

这是一个嵌套了一维数组的二维数组。可以按以下方式访问此结构:

signal mat : matrix(0 to r1, p to c1_r2);
signal slv : std_logic_vector(31 downto 0);
signal sl : std_logic;

slv <= mat(i, j);
sl <= mat(i, j)(k);

由于 VHDL-2008 允许在多维数组中进行切片操作。在 VHDL-2008 之前,您必须使用函数来完成此工作。

请查看我的 PoC.vectors 包,了解如何处理一维和多维数组的方法。


注意Soumya没有展示用于a_in声明中使用的类型标记“STD_LOGIC_VECTOR3”的声明。他可能正在指定一个切片的切片,这是不合法的 - (8.5“切片的前缀应适用于一维数组对象。该数组类型的基本类型是切片的类型。”)切片的切片没有已声明的一维数组对象类型,如果您提供了一个,那么除了创建的切片的聚合之外,没有类型转换(注意您提到使用函数)或其他方法,这意味着元素的聚合。 - user1155120
这并不贬低你回答中概述的方法的有效性。问题在于问题本身不清楚。 - user1155120
非常感谢Paebbels先生。我会查看您的PoC.vectors包。我仍然不清楚定义,必须详细阅读您的帖子。再次感谢您。 - Soumya
有些编程语言没有多维数组。在这种情况下,可以通过将整个数组嵌入到另一个数组的元素中来模拟它。用户可以使用这个(在我的情况下是2D)结构来进行x和y的抽象。与真正的多维数组不同的是内存中的内部结构和语言中的元素索引:(x)(y) -> 选择整个列,然后选择该列中的一个元素,而 (x, y) -> 选择第x列和第y行的一个元素。 - Paebbels
请看这两张图片作为比较:1D数组在1D数组中真正的2D数组 - Paebbels

0
与此同时,Xilinx在其[Vivado综合用户指南(UG901)](Xilinx网站在撰写时处于离线状态)中添加了一些信息。
例如:
-- 3-D Ram Inference Example (Single port)
-- Compile this file in VHDL2008 mode
-- File:rams_sp_3d.vhd
library ieee;
use ieee.std_logic_1164.all;

package mypack is
    type myarray_t is array(integer range<>) of std_logic_vector;
    type mem_t is array(integer range<>) of myarray_t;
end package;

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.mypack.all;

entity rams_sp_3d is
    generic (
        NUM_RAMS : integer := 2;
        A_WID : integer := 10;
        D_WID : integer := 32
    );
    port (
        clk : in std_logic;
        we : in std_logic_vector(NUM_RAMS-1 downto 0);
        ena : in std_logic_vector(NUM_RAMS-1 downto 0);
        addr : in myarray_t(NUM_RAMS-1 downto 0)(A_WID-1 downto 0);
        din : in myarray_t(NUM_RAMS-1 downto 0)(D_WID-1 downto 0);
        dout : out myarray_t(NUM_RAMS-1 downto 0)(D_WID-1 downto 0)
    );
end rams_sp_3d;

architecture arch of rams_sp_3d is
    signal mem : mem_t(NUM_RAMS-1 downto 0)(2**A_WID-1 downto 0)(D_WID-1 downto 0);
begin
    process(clk)
    begin
        if(clk’event and clk=’1’) then
            for i in 0 to NUM_RAMS-1 loop
                if(ena(i) = ‘1’) then
                    if(we(i) = ‘1’) then
                        mem(i)(to_integer(unsigned(addr(i)))) <= din(i);
                    end if;
                    dout(i) <= mem(i)(to_integer(unsigned(addr(i))));
                end if;
            end loop;
        end if;
    end process;
end arch;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接