Warm tip: This article is reproduced from serverfault.com, please click

How to return record with unconstrained 2d array from a function

发布于 2020-12-09 18:43:33

I have a record type(REC) which contains an element of type VECTOR which is an unconstrained 2d array of STD_LOGIC:


package TEST is

    type VECTOR is array (NATURAL range <>, NATURAL range <>) of STD_LOGIC;

    type REC is record

        data : VECTOR;

    end record REC;

    function con(
        a : REC;
        b : REC)
        return REC;

end package TEST;

When declaring the body of the con function I want to specify the size of the REC.data array like so:


package body TEST is

    function con(
     a : REC;
     b : REC)
        return REC is variable r : REC(
            data(a.data'length(1) + b.data'length(1) - 1 downto 0, a.data'length(2) - 1 downto 0));

        begin

            -- . . . do things

    end function con;

end package body TEST;

but in the line where I attempt to set the size of data it Vivado throws the following error:

Sliced name is allowed only on single-dimensional arrays

Does this mean I cannot have an unconstrained 2d arraign in a record or is there a different method for defining the size of it in the con function ?

---- EDIT ----

Since I now understand that it is not possible to use 2d arrays in this context what method should I use to create a function which:

  • Takes two 2d arrays (or arrays of arrays) of size [x][y] and [z][y] as inputs
  • Outputs an array of size [x+z][y]
  • With both input arrays being unconstrained and the output array being constrained to size [x+z][y]
  • And all arrays (input and return) be a record type
Questioner
Mercury
Viewed
0
user1155120 2020-12-10 11:54:41
user1155120 I don't think I fully understand what you are trying to say. Are you saying my code is not
a minimal reproducible example, because except for me forgetting to include the STD_LOGIC library
the code reproduces the problem when I paste it into Vivado, and it is about as minimal as I can get it.
Or are you saying that the code you linked as this works works for you, because at least in my
Vivado it still throws the same error ? – Mercury 4 hours ago

The original comment was meant for Tricky. There's a missing return statement in the function con which would prevent use in an example.

It isn't clear if record constraints (a -2008 feature) are supported in Vivado Simulator. In Vivado Synthesis Guide UG901 2020.1 we see all sorts of wonderful uses of record types from everything to inferring ram to record elements of record types. Xilinx has been busy.

It'd seems odd if unconstrained elements in record type declarations were supported but not record constraints (they're pretty much a package deal, pun aside). Note the comment called it a -2008 feature.

A record constraint is limited to supply the constraint of an element or subelement that is of an unconstrained type (typically arrays). VHDL has always been capable of supplying multi-dimensional array constraints. The language of the standard is particular based on the flexibility of the syntax.

This code is VHDL -2008 compliant and provides your record constraint:

library ieee;                  -- ADDED for MCVe
use ieee.std_logic_1164.all;   -- ADDED

package TEST is
    type VECTOR is array (NATURAL range <>, NATURAL range <>) of STD_LOGIC;

    type REC is record
        data: VECTOR;
    end record REC;
    
    function con (a: REC; b: REC) return REC;
end package TEST;

package body TEST is
    function con (a: REC; b: REC) return REC is 
        variable r: 
            REC (         -- record constraint:
              data (
                natural range a.data'length(1) + b.data'length(1) - 1 downto 0,
                natural range a.data'length(2) - 1 downto 0
              )
          );
    begin
        -- . . . do things 
        return r;     -- ADDED required return statement
    end function con;
end package body TEST;

You'll note the changes to the record constraint from yours is the addition of natural range before each range of the element data constraint.

From IEEE Std 1076-2008 5.3.3 Record types:

record_constraint ::=
    ( record_element_constraint { , record_element_constraint } )

record_element_constraint ::= record_element_simple_name element_constraint

From 6.3 Subtype declarations:

element_constraint ::=
      array_constraint
    | record_constraint

Here the element data is an array so an array_constraint is appropriate.

From 5.3.2 Array types, 5.3.2.1:

array_constraint ::=

    index_constraint [ array_element_constraint ]
    | ( open ) [ array_element_constraint ]

Because element data array elements are scalar (enumeration type STD_LOGIC) we follow index_constraint.

index_constraint ::= ( discrete_range { , discrete_range } )

discrete_range ::= discrete_subtype_indication | range

The code shown above uses a discrete subtype indication for the index ranges of the element data dimensions and successfully analyzes (compiles).

From 5.2.2 Scalar types, 5.2.2.1:

range ::=
      range_attribute_name
    | simple_expression direction simple_expression

direction ::= to | downto

The constraint in the question uses a range with simple expressions and direction.

So why did it produce the error message about multi-dimensional slices?

In 9. Expressions, 9.1 the BNF, simple_expression -> term -> factor -> primary -> name.

In 8. Names, 8.1 name -> slice_name, only multi-dimensional slices are not allowed semantically in 8.5 Slice names who's BNF tells us it's syntactically valid:

slice_name ::= prefix ( discrete_range )

The prefix of a slice shall be appropriate for a one-dimensional array object. The base type of this array type is the type of the slice.

and semantically the prefix data is not appropriate for a one-dimensional array object.

These comments provide bit more context for the problem although it isn't clear which version the record constraint you used in the reported eventual success:

@Mercury when you add a (VHDL) file to Vivado, it's by default set to use VHDL 93, but not 2008. Go
to the property Window and change the file type from VHDL to VHDL 2008. I'm not sure why it
prints the wrong error message in your case. (Vivado likes to confuse users with wrong error messages
...). Anyhow, it should have reported your feature is only supported in 2008 mode. – Paebbels 3 hours
ago

@Paebbels Thank you, that fixed the problem, maybe add it as a sub note to your response so I can
mark it as accepted answer. You just saved me hours of frustration. And I'm already getting familiar with
Vivado's shenanigans, my Favorit one of which is "ERROR close to ..." which has to be one of the most
useless error messages I have experience in a long time :) – Mercury 3 hours ago

As far as detecting -2008 source, there are no -1993 syntax errors and no -2008 new reserved word, delimiters, separators or graphics characters in either the primary unit or the secondary.

That leaves you at the mercy of semantic analysis which failed. You could also note the unconstrained record element wasn't reported during analysis of the package declaration. It occurred during evaluation of the variable r. All declared objects are required to be constrained. VHDL doesn't have a recital of all features, semantics can be restrictive as well. It's legal in places to have unconstrained elements and objects.

Associating semantics rules found in the text of the standard with an textual element of the particular declaration or statement can be tough and the squeaky wheel gets the lubricant. Record constraints are relatively new to VHDL implementations.

The problem appears to have been one of tool familiarity.