简体   繁体   中英

Use of Array Slices in VHDL

I'm trying to design a synthesizable VHDL code which uses some multi dimensional array features. The RTL has a 64 word deep array( called big_array_s , 64 x 16 bits ) used for storing some initial LUT values. Also there is a 4 word deep array( small_array_s , 4 x 16 bits ) which is used in the design. There is a requirement to assign a slice of the big array into the small array. It is illustrated in the following snippets of code.

type small_array is array (0 to 3) of bit_vector(15 downto 0);
type big_array is array (0 to 64) of bit_vector(15 downto 0);

signal small_array_s : small_array;
signal big_array_s : big_array := init_array_func("test.dat");

The init_array_func() is a VHDL function which initializes the big_array_s with data from the "test.dat" ascii file. The section where I'm stuck is assigning a portion of the big_array_s to the small_array_s. For example something like,

small_array_s  <= big_array_s(0 to 3);

is what I need to achieve with the RTL. But this direct assignment is not possible as the LHS and RHS are of different array types. My question is how do I achieve this kind of array slicing in VHDL?


Another method I could have used is to declare the big_array type as an array of small_array. For example,

type small_array is array (0 to 3) of bit_vector(15 downto 0);
type big_array is array (0 to 15) of small_array;

signal small_array_s : small_array;
signal big_array_s : big_array;

In this case, the statement

small_array_s  <= big_array_s(0);

would work smoothly. But I'm doubtful on how to initialize the array big_array_s considering the synthesis support.

There are no multidimensional (3D) array types declared in your question. Your 2nd declaration of big_array has one index.

IEEE Std 1976-2008

5.3.2 Array types
5.3.2.1 General

An array object is characterized by the number of indices (the dimensionality of the array); the type, position, and range of each index; and the type and possible constraints of the elements. The order of the indices is significant.

A one-dimensional array has a distinct element for each possible index value. A multidimensional array has a distinct element for each possible sequence of index values that can be formed by selecting one value for each index (in the given order). The possible values for a given index are all the values that belong to the corresponding range; this range of values is called the index range .

For your first method you can declare subtypes instead of independent types. The consequence is that they are the same type.

It's not a risk to do so, in VHDL assignment requires a matching element in the right hand expression for each element in the left hand side target. Code with mismatched numbers of elements can analyze and elaborate but will cause a run time error reporting bounds mismatch (and synthesis is required to adhere to VHDL semantics).

Creating a working Minimal, Complete and Verifiable example would look something like this for your first snippet:

entity some_array is
end entity;

architecture fuu of some_array is
    -- type small_array is array (0 to 3) of bit_vector(15 downto 0);
    -- type big_array is array (0 to 64) of bit_vector(15 downto 0);
    type some_array is array (natural range <>) of bit_vector(15 downto 0);
    subtype small_array is some_array(0 to 3);
    subtype big_array is some_array (0 to 64);

    impure function init_array_func (init_file:  in string) return 
             big_array is
        use std.textio.all;
        file big_array_file: text is in init_file;
        variable file_line:         line;
        variable big_array_val:     big_array;
    begin
        for i in big_array'range  loop
            readline (big_array_file, file_line);
            read (file_line, big_array_val(i));
        end loop;
        return big_array_val;
    end function;

    function to_string (inp: bit_vector) return string is
        variable image_str: string (1 to inp'length);
        alias input_str:  bit_vector (1 to inp'length) is inp;
        begin
        for i in input_str'range loop
            image_str(i) := character'VALUE(bit'IMAGE(input_str(i)));
        end loop;
        return image_str;
    end function;

    signal small_array_s : small_array;
    signal big_array_s : big_array := init_array_func("test.dat");

begin
    small_array_s  <= big_array_s(0 to 3);

MONITOR:
    process
    begin
        wait on small_array_s;
        wait for 0 ns; -- not the default value;
        for i in small_array_s'range loop
            report "small_array_s(" & integer'image(i) & ") = " &
                    to_string(small_array_s(i));
        end loop;
    end process;

end architecture;

And that gives:

ghdl -r some_array
some_array.vhdl:47:13:@0ms:(report note): small_array_s(0) = 0000000000000000
some_array.vhdl:47:13:@0ms:(report note): small_array_s(1) = 0000000000000001
some_array.vhdl:47:13:@0ms:(report note): small_array_s(2) = 0000000000000010
some_array.vhdl:47:13:@0ms:(report note): small_array_s(3) = 0000000000000011

Which properly shows the first four values initialized to signal big_array_s for known test.dat contents.

The functions are compatible with revisions of the VHDL standard earlier than -2008 and are cut, paste and edited from other examples.

Note that the init_array_func function requires a test.dat file containing at least 65 lines of valid values for a big_array element and such a function could be generalized by passing the number of big_array elements (length) as well, returning a value of an arbitrary subtype of some_array.

You can also do explicit type conversion between array types with same dimensionaly (number of indexes) with element types that are closely related:

9.3.6 Type conversions

Explicit type conversions are allowed between closely related types. In particular, a type is closely related to itself. Other types are closely related only under the following conditions:

...
— Array types—Two array types are closely related if and only if the types have the same dimensionality and the element types are closely related

Note the element type that is array type must obey the same requirement, as it's element (a subelement, here type bit).

Using your original type declarations without the subtype declarations the only other change would be to the assignment:

small_array_s  <= small_array(big_array_s(0 to 3));

Where the type conversion operand expression big_array_s(0 to 3) has the same dimensionality as small_array_s and the element type is closely related (both bit_vector(15 downto 0)).

And with these changes the above code analyzes, elaborates and simulates with the same results.

Note that type conversion also counts on assignment semantics insuring matching elements for both the assignment target and right hand side expression:

14.7.3.4 Signal update

In order to update a signal during a given simulation cycle, the kernel process first determines the driving and effective values of that signal. The kernel process then updates the variable containing the driving value with the newly determined driving value. The kernel also updates the variable containing the current value of the signal with the newly determined effective value, as follows:

...
b) If S is a composite signal (including a slice of an array), the effective value of S is implicitly converted to the subtype of S. The subtype conversion checks that for each element of S there is a matching element in the effective value and vice versa. An error occurs if this check fails. The result of this subtype conversion is then assigned to the variable representing the current value of S.

And the bit about subtype conversion means the index ranges don't have to match, the expression and target must have matching elements.

To do the array slicing you could use a generate statement copying one bit_vector(15 downto 0) at a time.

Regarding the 3D array, then I have bad experience with synthesis using Xilinx Vivado. Vivado recognizes it as a 3D array, tells you that it isn't supported and implements a bunch of registers.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM