I need to use multidimensional arrays to represent matrices in my design. I have tried the two available options:
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
Multidimensional arrays.
type matrix is array (natural range <>, natural range <>)
of std_logic_vector(31 downto 0);
However, in both the cases my post synthesis simulation in xilinx gives me the error "Sliced name is allowed only on single-dimensional arrays". What is the correct way of using multidimensional arrays in synthesizable vhdl design? Any inputs would be welcome.
I am using the XST Synthesizer that comes with Xilinx ISE. I am indexing both i and j, as my matrix dimension is m * n * 32.
My net a_in in the entity
a_in: in matrix (0 to size - 1, 0 to size - 1);
got modified to
a_in : in STD_LOGIC_VECTOR3 ( 1 downto 0 , 1 downto 0 , 31 downto 0 );
In my program, I access values from the matrix inside two generate statements for k and m as:
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)
);
My test bench input for a_in is given as
a_in <= (("00111111100000000000000000000000", "00000000000000000000000000000000"),("00000000000000000000000000000000", "00111111100000000000000000000000"));
My synthesis generated warnings of the type: Xst:387 - The KEEP property attached to the net may hinder timing optimization. You may achieve better results by removing this property. However, I have not set any keep property and I am not sure where to look for this property. Please help! Thanks a lot.
I apologize for not adding the complete code. Please find below the code and package.
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;
The package used here is:
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;
The post synthesis simulation model file modified the entity in terms of ordering and data type, on its own. The entity looks as below:
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;
Your first array is not a multi dimensional array, it's a 2-times nested 1 dimensional array.
Your example:
type t11 is array (0 to c1_r2) of std_logic_vector(31 downto 0);
type t1 is array (0 to r1) of t11;
This definition is more clear:
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);
You can access this structure by indexing each dimension:
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);
You can also slice each dimension:
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);
Your second example:
type matrix is array (natural range <>, natural range <>) of std_logic_vector(31 downto 0);
This is a 2-dimensional array with a nested 1-dimensional array. This structure can be accessed as follows:
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);
Since VHDL-2008 slicing is also allowed in multi dimensional array. Before VHDL-2008 you have to employ functions for this job.
Have a look into my PoC.vectors package to see ways on how you can handle 1- and multi dimensional arrays.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With