VHDL 中的可合成多维数组
Synthesizable multidimensional arrays in VHDL
我需要在我的设计中使用多维数组来表示矩阵。我已经尝试了两个可用选项:
正在声明数组的数组
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
多维数组。
type matrix is array (natural range <>, natural range <>)
of std_logic_vector(31 downto 0);
然而,在这两种情况下,我在 xilinx 中的 post 综合模拟都给出了错误 "Sliced name is allowed only on single-dimensional arrays"。
在可综合 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;
post 综合仿真模型文件根据顺序和数据类型自行修改了实体。该实体如下所示:
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;
您的第一个数组不是多维数组,它是 2 次嵌套的一维数组。
你的例子:
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 包,了解如何处理一维和多维数组。
同时 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;
我需要在我的设计中使用多维数组来表示矩阵。我已经尝试了两个可用选项:
正在声明数组的数组
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
多维数组。
type matrix is array (natural range <>, natural range <>) of std_logic_vector(31 downto 0);
然而,在这两种情况下,我在 xilinx 中的 post 综合模拟都给出了错误 "Sliced name is allowed only on single-dimensional arrays"。 在可综合 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;
post 综合仿真模型文件根据顺序和数据类型自行修改了实体。该实体如下所示:
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;
您的第一个数组不是多维数组,它是 2 次嵌套的一维数组。
你的例子:
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 包,了解如何处理一维和多维数组。
同时 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;