Here is a cut down version of an old design where I tried to use a 2D array of bits as a signal, to implement a shift register. -------------------------------------------------------------------------------- library ieee; use ieee.std_logic_1164.all; architecture behav of test2darray is constant tpd : time := 2 ns; constant DELAY : NATURAL := 5; type shift_reg_type is array (natural range 0 to DELAY) of std_logic_vector (7 downto 0); signal shift_reg : shift_reg_type; begin shift_reg(shift_reg'low) <= din; process (clk) begin if (clk'event and clk = '1') then for i in shift_reg'high downto shift_reg'low+1 loop shift_reg(i) <= shift_reg(i-1) after tpd; end loop; end if; end process; dout <= shift_reg(shift_reg'high); end; -- of architecture behav of test2darray -------------------------------------------------------------------------------- When I simulated it, the outputs and the contents of the signal shift_reg were always undefined. With Leapfrog, I could only discover this from inside of the GUI for simulating Leapfrog, not with the waveform viewer, because the waveform viewer doesn't have a way to display 2D arrays of signal, at least not one that I have discovered. That is almost enough of a reason not to use them right there. Some time ago I saw some messages in the VHDL news group comp.lang.vhdl that using 'std_ulogic/std_ulogic_vector' instead of 'std_logic/std_logic_vector', and mode 'buffer' instead of 'out' for signals with single drivers (the majority of signals in a design, unless you have lots of tristate wires) is "safer". I tried it out, and at least Cadence Leapfrog warns you during the elaboration phase if you accidentally drive the same signal from two different processes, if it has type std_ulogic/std_ulogic_vector. Using mode 'buffer' is nice in that you can read and use the signal inside of the entity that it is an output of, without having to make a local copy of the signal. Unfortunately, it doesn't warn you when you compile the individual VHDL source files, only when you elaborate a test bench containing the design. That isn't too big of a deal, because it is easy to create an empty test bench that just instantiates the design and doesn't drive any inputs -- I create it merely to have something to elaborate. When you really do want a tristate line, as we often do in the SE chip, use std_logic/std_logic_vector, and mode 'out'. When I took the example above and changed all std_logic_vector's to std_ulogic_vector's and tried elaborating it, Leapfrog gave a bunch of warnings like: ev: *E,1122: multiple sources for unresolved signal: SHIFT_REG [4.3.1.2]. Building driver for signal /TESTBENCH2DARRAY(TEST).THETEST2DARRAY/BEHAV.SHIFT_REG from process: /TESTBENCH2DARRAY(TEST).THETEST2DARRAY/BEHAV.$PROCESS_001 Apparently, Leapfrog doesn't like that some bits of shift_reg are being driven inside of one process, and some in another (the continuous assignment to shift_reg(shift_reg'low) is effectively another process for this purpose), even though no individual bit is driven inside of both of them. I suspect that is why the simulation always had undefined values, because multiple drivers on a signal make the result undefined. Actually, a tristate driver works just fine on a std_logic signal as long as every driver except one is driving it as 'Z' (high impedance). To fix this, I changed the code to the following. It simulates as expected whether I use std_logic_vector or std_ulogic_vector, so the problem I was having before wasn't really with 2D arrays, but with this multiple driver problem that the simulator wasn't even warning me about. -------test2darray-behav.vhd--------------------------------------------------- library ieee; use ieee.std_logic_1164.all; architecture behav of test2darray is constant tpd : time := 2 ns; constant DELAY : NATURAL := 5; type shift_reg_type is array (natural range 1 to DELAY) of std_ulogic_vector (7 downto 0); signal shift_reg : shift_reg_type; begin process (clk) begin if (clk'event and clk = '1') then for i in shift_reg'high downto shift_reg'low+1 loop shift_reg(i) <= shift_reg(i-1) after tpd; end loop; shift_reg(shift_reg'low) <= din after tpd; end if; end process; dout <= shift_reg(shift_reg'high); end; -- of architecture behav of test2darray -------------------------------------------------------------------------------- Oh, by the way, here is the entity definition, in case you want to play around with this stuff, followed by a miniature test bench. Both of them are for the std_ulogic version, but a global search and replace is easy. -------test2darray.vhd-------------------------------------------------------- library ieee; use ieee.std_logic_1164.all; entity test2darray is port ( clk : in std_ulogic; din : in std_ulogic_vector (7 downto 0); dout : buffer std_ulogic_vector (7 downto 0) ); end; -------------------------------------------------------------------------------- --------testbench2darray.vhd---------------------------------------------------- entity testbench2darray is end; library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_textio.all; library test2darraylib; use std.textio.all; architecture test of testbench2darray is component test2darray port ( clk : in std_ulogic; din : in std_ulogic_vector (7 downto 0); dout : buffer std_ulogic_vector (7 downto 0) ); end component; for thetest2darray: test2darray use entity test2darraylib.test2darray (behav); constant tpd : time := 2 ns; constant clock_period : time := 100 ns; signal clk : std_ulogic; signal din : std_ulogic_vector (7 downto 0); signal dout : std_ulogic_vector (7 downto 0); signal tick : integer := 0; begin process begin clk <= '1'; wait for clock_period / 2; clk <= '0'; wait for clock_period / 2; end process; process (clk) file f : text is out "testbench2darray.log"; variable l : line; begin if (clk'event and clk = '1') then write (l, "din=" & NUL); write (l, din); write (l, " dout=" & NUL); write (l, dout); writeline (f, l); end if; end process; process begin wait until (clk'event and clk = '1'); din <= "00000000"; tick <= tick + 1 after tpd; wait until (clk'event and clk = '1'); din <= "11111111"; tick <= tick + 1 after tpd; wait until (clk'event and clk = '1'); din <= "00000000"; tick <= tick + 1 after tpd; wait until (clk'event and clk = '1'); din <= "11111111"; tick <= tick + 1 after tpd; wait until (clk'event and clk = '1'); din <= "00000000"; tick <= tick + 1 after tpd; wait until (clk'event and clk = '1'); din <= "11111111"; tick <= tick + 1 after tpd; wait until (clk'event and clk = '1'); din <= "00000000"; tick <= tick + 1 after tpd; wait until (clk'event and clk = '1'); din <= "11111111"; tick <= tick + 1 after tpd; wait until (clk'event and clk = '1'); din <= "00000000"; tick <= tick + 1 after tpd; wait until (clk'event and clk = '1'); din <= "11111111"; tick <= tick + 1 after tpd; assert false report "Simulation terminated normally." severity error; end process; thetest2darray: test2darray port map ( clk => clk, din => din, dout => dout ); end; --------------------------------------------------------------------------------