I'm trying to model a RAM chip in VHDL with generic parameters for the address and data bus widths and for the base address where the RAM is placed in the address space. My problem is that I cannot figure out how to get a slice of an generic unconstrained array parameter to compare it against a std_logic_vector signal.
This the reduced code that is intended to compute the "chip select" signal:
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity e is
generic (
BASE_ADDR :std_logic_vector := x"C000";
CELL_ADDR_WIDTH :integer := 4
);
port (
address :in std_logic_vector (BASE_ADDR'length-1 downto 0)
);
end;
architecture behavioral of e is
constant ADDR_WIDTH :integer := BASE_ADDR'length;
signal cs :std_logic;
begin
cs <= '1' when address(ADDR_WIDTH-1 downto CELL_ADDR_WIDTH) = BASE_ADDR(ADDR_WIDTH-1 downto CELL_ADDR_WIDTH) else '0';
end behavioral;
The Lattice ispLEVER VHDL compiler reports the following error:
23:64:23:110|Slice range direction does not match argument range
The message is caused by the expression BASE_ADDR(ADDR_WIDTH-1 downto CELL_ADDR_WIDTH).
How is a slice of the generic unconstrained array BASE_ADDR accessed correctly in VHDL?
Both solutions suggested by #Paebbels and #user1155120 resolve the VHDL compilation error. I quote the suggestions here with the code updated accordingly.
#Paebbels: Use to in slice
Your unconstrained array defaults to a "to" range because the index type of std_logic_vector is integer and integer in turn is defined with a to range :). So use the to keyword in your slice.
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity e is
generic (
BASE_ADDR :std_logic_vector := x"C000";
CELL_ADDR_WIDTH :integer := 4
);
port (
address :in std_logic_vector (BASE_ADDR'length-1 downto 0)
);
end;
architecture behavioral of e is
constant ADDR_WIDTH :integer := BASE_ADDR'length;
signal cs :std_logic;
begin
cs <= '1' when address(ADDR_WIDTH-1 downto CELL_ADDR_WIDTH) = BASE_ADDR(ADDR_WIDTH-1 to CELL_ADDR_WIDTH) else '0';
end behavioral;
#user1155120: Declare an alias to define a direction
You'll could also add an alias to your architecture declarative region - alias BASEADDR: std_logic_vector(BASE_ADDR'LENGTH - 1 downto 0) is BASE_ADDR; to define a direction and use that - cs <= '1' when address(ADDR_WIDTH-1 downto CELL_ADDR_WIDTH) = BASEADDR(ADDR_WIDTH-1 downto CELL_ADDR_WIDTH) else '0';
I used a more prominent name for the alias:
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity e is
generic (
BASE_ADDR :std_logic_vector := x"C000";
CELL_ADDR_WIDTH :integer := 4
);
port (
address :in std_logic_vector (BASE_ADDR'length-1 downto 0)
);
end;
architecture behavioral of e is
constant ADDR_WIDTH :integer := BASE_ADDR'length;
signal cs :std_logic;
alias BASE_ADDR_ALIAS: std_logic_vector(BASE_ADDR'LENGTH - 1 downto 0) is BASE_ADDR;
begin
cs <= '1' when address(ADDR_WIDTH-1 downto CELL_ADDR_WIDTH) = BASE_ADDR_ALIAS(ADDR_WIDTH-1 downto CELL_ADDR_WIDTH) else '0';
end behavioral;
Related
How do you use record arrays in generate statements in VHDL? Below is what I have done, which passes synthesis and implementation in Vivado (2021.1). However, when I simulate it, it shows none of the record signals getting assigned and are always "U". I can also not find any examples of record fields used in port maps in generate statements.
type record_a_t is record
a : std_logic;
b : std_logic_vector(7 downto 0);
c : std_logic_vector(3 downto 0);
d : std_logic;
e : std_logic;
end record record_a_t;
type record_a_array_t is array (0 to 3) of record_a_t;
signal record_a_array : record_a_array_t;
Then, I generate the modules with signal mapping like:
GEN_MODULES : for i in 0 to 3 generate
modules : entity work.module
port map(
clk => clk,
rst_n => rst_n,
a => record_a_array(i).a,
b => record_a_array(i).b,
c => record_a_array(i).c,
d => record_a_array(i).d,
e => record_a_array(i).e
);
end generate GEN_MODULES;
Again, the above seems to pass all the tools syntax checking and builds in Vivado, but simulation (RivPro 2018) and implementation show signals not getting assigned or changing. They are always "U", even if driven from the module. For example, if port a is an output that is initialized in the module, record_a_array(i).c is always "U". Even the module output port is "U", as if the internal initialization is ignored, which makes no sense to me.
Below is an example.
Test Module:
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity module is
port(
clk : in std_logic;
rst_n : in std_logic;
a : in std_logic;
b : out std_logic_vector(7 downto 0);
c : out std_logic_vector(3 downto 0);
d : out std_logic;
e : out std_logic
);
end module;
architecture rtl of module is
begin
process(clk, rst_n)
begin
if(rst_n = '0') then
b <= (others=> '0');
c <= (others=> '0');
d <= '0';
e <= '0';
elsif(rising_edge(clk)) then
if(a = '1') then
b <= b + '1';
c <= c + '1';
d <= not d;
e <= not e;
end if;
end if;
end process;
end rtl;
Test Bench:
library ieee;
use ieee.std_logic_1164.all;
entity testbench is
end entity testbench;
---------------------------------------------------
architecture arch of testbench is
---------------------------------------------------
type record_a_t is record
a : std_logic;
b : std_logic_vector(7 downto 0);
c : std_logic_vector(3 downto 0);
d : std_logic;
e : std_logic;
end record record_a_t;
type record_a_array_t is array (0 to 3) of record_a_t;
signal record_a_array : record_a_array_t;
signal clk : std_logic := '1';
signal rst_n : std_logic := '0';
---------------------------------------------------
begin
clk <= not clk after 5 ns;
rst_n <= '1' after 20 ns;
GEN_MODULES : for i in 0 to 3 generate
modules : entity work.module
port map(
clk => clk,
rst_n => rst_n,
a => record_a_array(i).a,
b => record_a_array(i).b,
c => record_a_array(i).c,
d => record_a_array(i).d,
e => record_a_array(i).e
);
end generate GEN_MODULES;
process(clk, rst_n)
begin
if(rst_n = '0') then
for i in 0 to 3 loop
record_a_array(i).a <= '0';
end loop;
elsif(rising_edge(clk)) then
for i in 0 to 3 loop
record_a_array(i).a <= not record_a_array(i).a;
end loop;
end if;
end process;
end arch;
Simulation:
Simulation of module example
Notice how the record signals wired to the module outputs in at the TestBench level are never defined and how the outputs of the generated module instances themselves are not driven, even though they all get asserted in the reset condition. The only signal that gets driven is the 'a' signal from the test bench level.
Since the record is not crossing into the RTL space, unwanted drivers can be turned off using std_logic using 'Z':
constant REC_INIT : record_a_t := (
a => 'Z',
b => "ZZZZZZZZ",
c => "ZZZZ",
d => 'Z',
e => 'Z'
) ;
. . .
signal record_a_array : record_a_array_t := (0 to 3 => REC_INIT) ;
As you start to look at the issue in the LRM, you might also note you can find the issues the IEEE VHDL working group has recorded at: : https://gitlab.com/IEEE-P1076/VHDL-Issues/-/issues. There is a remotely related issue in https://gitlab.com/IEEE-P1076/VHDL-Issues/-/issues/275 that may be able to address both its issue and this one - though time will tell on that.
For verification, I use Open Source VHDL Verification Methodology (OSVVM). We use records on ports and as a result, use special resolution functions with them so they do not require initialization.
Is it posible to make array of unconstrained array in vhdl? I am using XCELIUM 18.03-s001.
This is how I declare signal type in pkg_test.vhd:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
package pkg_test is
type t_data_bus_array is array(natural range <>) of std_logic_vector;
end pkg_test;
This is entity test_entity.vhd
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library work;
use work.pkg_test.all;
entity test_entity is
generic (
DATA_WIDTH : natural := 9; -- Data width of single input
NUMBER_OF_INPUTS : natural := 4 -- Number of inputs
);
port
(
pi_data : in t_data_bus_array(NUMBER_OF_INPUTS-1 downto 0)(DATA_WIDTH-1 downto 0);
po_data : out t_data_bus_array(NUMBER_OF_INPUTS-1 downto 0)(DATA_WIDTH-1 downto 0)
);
end test_entity;
architecture test_entity_behav of test_entity is
begin
po_data <= pi_data;
end test_entity_behav;
And this is my error.
[saka#serbia workspace]$ xrun -top test_entity -f filelist -elaborate -clean -sv -access +rwc -v200x
xrun: 18.03-s001: (c) Copyright 1995-2018 Cadence Design Systems, Inc.
xrun: *N,CLEAN: Removing existing directory ./xcelium.d.
pkg_test.vhd:
errors: 0, warnings: 0
test_entity.vhd:
pi_data : in t_data_bus_array(NUMBER_OF_INPUTS-1 downto 0)(DATA_WIDTH-1 downto 0);
|
xmvhdl_p: *E,MISRPN (test_entity.vhd,42|73): expecting a right parenthesis (')') [1.1.1].
pi_data : in t_data_bus_array(NUMBER_OF_INPUTS-1 downto 0)(DATA_WIDTH-1 downto 0);
|
xmvhdl_p: *E,MISCOL (test_entity.vhd,42|84): expecting a colon (':') 87[4.3.3] 93[4.3.2].
pi_data : in t_data_bus_array(NUMBER_OF_INPUTS-1 downto 0)(DATA_WIDTH-1 downto 0);
|
xmvhdl_p: *E,EXPEND (test_entity.vhd,42|98): expecting the reserved word 'END' [1.1].
end test_entity;
|
xmvhdl_p: *E,EXPACE (test_entity.vhd,47|0): expecting a library unit [11.1].
architecture test_entity_behav of test_entity is
|
xmvhdl_p: *E,ENNOFN (test_entity.vhd,49|44): Intermediate file for entity 'TEST_ENTITY' could not be loaded, entity may require re-analysis.
errors: 5, warnings: 0
xrun: *E,VHLERR: Error during parsing VHDL file (status 1), exiting.
It is obviously, that I make some mistake
If I use this declaration
type t_data_bus_array is array(natural range <>) of std_logic_vector(DATA_WIDTH-1 downto 0);
and in entity like this
pi_data : in t_data_bus_array(NUMBER_OF_INPUTS-1 downto 0);
There is no error.
If you are not using the VHDL2008 the unconstrained arrays of std_logic_vector are not supported.
You could define a vector array of std_logic type like this:
type SlVectorArray is array (natural range<>, natural range<>) of std_logic;
I have written a program in modelsim that add to numbers and put the result in Ra/Sum. I have used a tristate buffer, but I get this: Fatal: (vsim-3420) Array lengths do not match. Left is 16 (15 downto 0). Right is 8 (7 downto 0). I understand that this is because they have different lengths. But they cant have the same length either, because then I get an error when adding add1 and add2 and putting them in Sum. So what can I do to make this work?
library IEEE;
use IEEE.STD_LOGIC_1164.all;
use IEEE.numeric_std.all;
entity MAC is
generic (width: integer := 8);
port(
clk, reset : in STD_LOGIC;
MLS_select : in STD_LOGIC;
Rn, Rm, Ra : in STD_LOGIC_VECTOR(width-1 downto 0);
Rd : out STD_LOGIC_VECTOR(width-1 downto 0)
);
end;
architecture behavioral of MAC is
signal mul1, mul2, add1 : UNSIGNED(width-1 downto 0);
signal add2, sum : UNSIGNED(width*2-1 downto 0);
begin
process(clk, reset)
begin
if reset = '1' then Rd <= (others => '0');
elsif rising_edge(clk) then
Rd <= STD_LOGIC_VECTOR(sum(width-1 downto 0));
end if;
end process;
mul1 <= UNSIGNED(Rn);
mul2 <= UNSIGNED(Rm);
add1 <= UNSIGNED(Ra);
add2 <= mul1*mul2;
sum <= add2 when clk = '1' else add2;
sum <= add1+add2;
end architecture;
At first, ... when clk = '1' else ... will create a latch, but no flip-flop.
You need to use ... when rising_edge(clk);.
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
entity MAC is
generic (width: integer := 8);
port(
clk, reset : in STD_LOGIC;
MLS_select : in std_logic;
Rn, Rm, Ra : in std_logic_vector(width - 1 downto 0);
Rd : out std_logic_vector(width - 1 downto 0) := (others => '0')
);
end entity;
architecture rtl of MAC is
signal mul1, mul2, add1 : unsigned(width - 1 downto 0);
signal add2, sum : unsigned(width * 2 - 1 downto 0);
begin
process(clk, reset)
begin
if (reset = '1') then
Rd <= (others => '0');
elsif rising_edge(clk) then
Rd <= std_logic_vector(sum(Rd'range));
end if;
end process;
mul1 <= unsigned(Rn);
mul2 <= unsigned(Rm);
add1 <= unsigned(Ra);
add2 <= (mul1 * mul2) when rising_edge(clk);
sum <= resize(add1, add'length) + add2;
end architecture;
Signal MLS_select is unused. There is no need to calculate the sum with so many bits. I suggest to truncate add2 before the addition, to reduce the number of unused bits (and warnings generated by them).
I am working on creating processing element in VHDL that have variable bit inputs. I try to use a generate statement to instantiate more components of the processing element and need the inputs to be std_logic_vectors so it can be parameterized but I get errors when trying to synthesize. Please can you help show why I am getting the synthesis error and what can be done to solve the error.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
package logic_array_type is
constant number_of_PE: integer := 16; -- number of processing elements
constant data_width: integer := 8; -- size of datapath, can be changed.
type vector_array is array (natural range <>) of std_logic_vector(data_width-1 downto 0);--to allow use of signal as CurBlk(i) to connect to the ith generated instanciation of entity/component.
type vector_array2 is array (natural range <>) of std_logic_vector(data_width downto 0);
end package logic_array_type;
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
use work.logic_array_type.all;
entity MEengine is
Generic(
number_of_PE: integer := 16; -- number of processing elements
data_width: integer := 8; -- size of data_width, can be changed.
w: integer := 8); -- w value(size of datapath) can be changed.
Port ( reset : in STD_LOGIC;------ To be indexed in future instantiations
clk : in STD_LOGIC;
sel : in STD_LOGIC;
mv : out STD_LOGIC_VECTOR (w-1 downto 0));
end MEengine;
architecture Behavioral of MEengine is
component ProEle is
Generic(w: integer := 8); -- w value can be changed
Port ( CurBlk : in STD_LOGIC_VECTOR (w-1 downto 0);
RefBlk1 : in STD_LOGIC_VECTOR (w-1 downto 0);
RefBlk2 : in STD_LOGIC_VECTOR (w-1 downto 0);
Sad : out STD_LOGIC_VECTOR (w downto 0);
SEL : in STD_LOGIC;
clk : in STD_LOGIC;
reset : in STD_LOGIC;
lat_en : in STD_LOGIC; -------------- future control for delay latches
Dlat : out STD_LOGIC_VECTOR (w-1 downto 0));
end component ProEle;
---component specification--
for all : ProEle use entity work.ProEle(behavioral);
----internal signals-------
signal CurBlk : vector_array(data_width-1 downto 0);
signal RefBlk1 :vector_array (data_width-1 downto 0);
signal RefBlk2 : vector_array (data_width-1 downto 0);
signal Sad : vector_array2 (data_width downto 0);
signal lat_en : STD_LOGIC; -------------- future control for delay latches
signal Dlat : vector_array (data_width-1 downto 0);
begin
-----------create the processing elements---------
gen_pro_ele: for i in 0 to number_of_PE-1 generate
Processing_Element : ProEle port map( CurBlk => CurBlk(i), ------- pins to wires or sinals
RefBlk1 => RefBlk1(i),
RefBlk2 => RefBlk2(i),
Sad => Sad(i),
SEL => SEL,
clk => clk,
reset => reset,
lat_en => lat_en,
Dlat => Dlat(i));
end generate gen_pro_ele;
end Behavioral;
The Error after synthesis is
Line 100: Index value <8> is out of range [7:0] of array < curblk >
ERROR:HDLCompiler:1316 - Line 101: Index value <8> is out of range [7:0] of array< refblk1 >
ERROR:HDLCompiler:1316 - Line 102: Index value <8> is out of range [7:0] of array< refblk2 >
ERROR:HDLCompiler:1316 - Line 108: Index value <8> is out of range [7:0] of array < dlat >
For which Line100 is - Processing_Element : ProEle port map( CurBlk => CurBlk(i), ------- pins to wires or sinals
Line101 - RefBlk1 => RefBlk1(i),
Line102 - RefBlk2 => RefBlk2(i),
Line108 - Dlat => Dlat(i));
I expect the component ProEle to be generated 16 times having inputs(CurBlk, RefBlk1, RefBlk2) as 8bits wide.
The rtl schematic for ProEle component can be found in this link
What I really do not understand is why synthesis tool produces error
Index value <8> is out of range [7:0] of array < curblk > etc. rather than generate 16 instances of ProEle component, as the type vector_array has a range natural of 8bits(current data_width)and should be able to cope with index 8-16, producing the 16 instances of the component.
package logic_array_type is
constant number_of_PE: integer := 16; -- number of processing elements
constant data_width: integer := 8; -- size of datapath, can be changed.
type vector_array is array (natural range <>) of std_logic_vector(data_width-1 downto 0);--to allow use of signal as CurBlk(i) to connect to the ith generated instanciation of entity/component.
type vector_array2 is array (natural range <>) of std_logic_vector(data_width downto 0);
end package logic_array_type;
The error is in the package. Array range declaration suggests that I am using the maximum length of the vector as the number of times I want to loop.
(natural range <>).
whereas I am requesting the loop for more than these number of times in the generate statement .......
gen_pro_ele: for i in 0 to number_of_PE-1 generate.
hence it was necessary to change (natural range <>) to (0 to number_of_PE) in the package.
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.
In the mean time Xilinx has added some information in it's [Vivado synthesis user guide (UG901)](xilinx website offline at time of writing)
For example:
-- 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;