1

Annoyingly I know how to do this easily in C++ but not in VHDL. I want to quickly and easily transfer data from a constrained 3D array to a 2D array e.g:

2d_array[N][M]
3d_array[i][N][M]

2d_array=3d_array[i]

So my VHDL looks like this:

    type buff_array is array(2 downto 0, 7 downto 0) of std_logic_vector(31 downto 0);
    type ram_array is array(7 downto 0) of std_logic_vector(31 downto 0);
    shared variable ram: ram_array;
    shared variable buff: buff_array;

And I'd want to do something like this:

if we = '1' then
                buff(pua, addr) := d;
                ram:=buff(poa);
            end if;

Any ideas?

Also I know I could do a quick for loop but I wanted to try and avoid the extra logic

1
  • 1
    Don't use shared variables - you're storing up potential problems for the future! There's a couple of posts recently using them, who is teaching this?? Commented Dec 16, 2013 at 21:02

4 Answers 4

4

You can only assign entire arrays if they are of the same type. So given

type ram_array is array(7 downto 0) of std_logic_vector(31 downto 0);

you can declare variables - or even arrays - of that type.

signal buf : ram_array;
signal ram_2d: array(2 downto 0) of ram_array;

Now buf <= ram_2d(1) ought to work.

Sign up to request clarification or add additional context in comments.

Comments

4

Re:

I know I could do a quick for loop but I wanted to try and avoid the extra logic

A for loop just copying values from one place to another will not be any logic - the compiler will unroll the loop and just create the wiring you've described.

It's a common misconception that having a for loop makes for big logic. All it really means is that it duplicates the logic within the loop that many times, so if the logic in the loop is trivial, so is the unrolled version. It doesn't create counters and comparators etc.

(And, forgive the presumption, as a relative newbie to VHDL, don't fret about the amount of logic. Certainly, keep an eye on things by synthesising blocks as you go, but you may be surprised by a) how good the tools are and b) how big the devices are these days :) Avoid premature optimisation, just like in software!

2 Comments

wish I could tick multiple answers
@fiz: you could always ask a question about whether for loops infer extra logic, and I'll paste the answer in there too (just kidding :)
2

Quick fix is to declare buff_array as:

type buff_array is array(2 downto 0) of ram_array;

And then of course put declaration of buf_array after declaration of ram_array.

Example for 2D/3D array:

type array_2d_t is array(2 downto 0, 1 downto 0) of std_logic_vector(31 downto 0);
type array_3d_t is array(3 downto 0) of array_2d_t;
shared variable array_2d_v : array_2d_t;
shared variable array_3d_v : array_3d_t;
...
array_2d_v := array_3d_v(1);

4 Comments

And this would give me my 3D array that I desire?
Same principle apply if you extend this to 3D, of what ever N-D. Se added example in answer.
Thanks for the information. It worked, though the only problem with it is if I now try to write my std_logic_vector to e.g buff(3,1), it says "Indexed name prefix type buff_array expects 1 dimensions"
Technically that would be an array of 2-D arrays, not a 3-D array, but it works. The difference is that you access one of its members as buff(3)(1) instead of buff(3,1).
1

This merely illustrates Morten's answer for those wanting to understand the issue and solution otherwise obscured by shared variable name changes and lack of LRM reference.

This example analyzes:

library ieee;
use ieee.std_logic_1164.all;

package declare is 
--  type buff_array is array(2 downto 0, 7 downto 0) of std_logic_vector(31 downto 0);
    type ram_array is array(7 downto 0) of std_logic_vector(31 downto 0);
    type buff_array is array (2 downto 0) of ram_array;  -- added declaration
    shared variable ram: ram_array;
    shared variable buff: buff_array;
end package;

library ieee;
use ieee.std_logic_1164.all;
use work.declare.all;

entity ramarray is
end entity;

architecture foo of ramarray is
    signal we:   std_logic;
begin
    we <= '1';
SOMELABEL:
    process (we)
    begin
        if we = '1' then
            ram := buff(1);  -- unchanged
        end if;
    end process;

end architecture;

Multidimensional slices are not allowed[1]. Separating the indexes for each dimension by converting buff into an array of an array type of an array subtype allows you to have the same base type on both sides of the assignment operator providing a slice name to a single dimensional array whose element type is ram_array.


[1] IEEE Std 1076-2008, Section 8.5 Slice names "A slice name denotes a one-dimensional array composed of a sequence of consecutive elements of another one-dimensional array. A slice of a signal is a signal; a slice of a variable is a variable; a slice of a constant is a constant; a slice of a value is a value."

See also Fast Track Change Proposal FT-15 Slicing of multidimensional arrays and arrays of arrays from June 2004, still in progress.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.