I am writing IPbus Transaction Verification Model for UVVM and I have encountered some problem. I know potential solution, but I don't like it and I am not sure if it can be handled better in some different way.

Here is some code snippet that is necessary to introduce the problem.

  type t_ipbus_tranaction_header is
    protocol_version : natural range 0 to 2**4  - 1;
    transaction_id   : natural range 0 to 2**12 - 1;
    words            : natural range 0 to 2**8  - 1;
    type_id          : t_ipbus_transaction_type_id;
    info_code        : t_ipbus_transaction_info_code;
  end record;

  -- Overload t_slv_array in order to enable unconstrained array in record.
  type t_slv_array is array (natural range <>) of std_logic_vector(31 downto 0);

  type t_ipbus_transaction is
    header : t_ipbus_tranaction_header;
    bodyy  : t_slv_array;
  end record;

  function ipbus_transaction (
    protocol_version : natural;
    transaction_id   : natural;
    words            : natural;
    type_id          : t_ipbus_transaction_type_id;
    info_code        : t_ipbus_transaction_info_code;
    bodyy            : t_slv_array
  ) return t_ipbus_transaction is
    variable trans : t_ipbus_transaction(bodyy(bodyy'length-1 downto 0));
    assert protocol_version = 2 report "Wrong IPbus protocol version." severity failure;

    trans.header.protocol_version := protocol_version;
    trans.header.transaction_id   := transaction_id;
    trans.header.words            := words;
    trans.header.type_id          := type_id;
    trans.header.info_code        := info_code;
    trans.bodyy                   := bodyy;

    return trans;
  end function;

  function ipbus_read_transaction (
    read_size : natural;
    base_address : std_logic_vector(31 downto 0)
  ) return t_ipbus_transaction is
    variable aux : t_slv_array(0 downto 0);
    aux(0) := base_address;
    return ipbus_transaction(2, 0, read_size, READ, OUTBOUND_REQUEST, aux);
  end function;

Now, I would like to define signal or variable in the testbench in the following way:

signal transaction : t_ipbus_transaction := ipbus_read_transaction(1, (others => '0'));

However this returns following error in the GHDL:

tb/ipbus_tvm_tb.vhd:40:12:error: declaration of signal "transaction" with unconstrained record type "t_ipbus_transaction" is not allowed
tb/ipbus_tvm_tb.vhd:40:12:error: (even with a default value)

I am not sure if it is because of lack of the support in the VHDL standard or in GHDL.

I have also tried the following definition:

signal transaction : t_ipbus_transaction := new ipbus_read_transaction(1, (others => '0'));

This returns error:

tb/ipbus_tvm_tb.vhd:41:53:error: a type mark must denote a type or a subtype
tb/ipbus_tvm_tb.vhd:41:53:error: (type mark denotes function "ipbus_read_transaction")

So it is not supported by the VHDL standard.

I am aware that the problem can be easily solved by the following definition:

signal transaction : t_ipbus_transaction(bodyy(0 downto 0)) := ipbus_read_transaction(1, (others => '0'));

However, this approach has few drawbacks for me. Namely:

  1. User has to type redundant information.
  2. User has to know transaction body length in advance.
  3. User has to have greater knowledge about the protocol itself.

So, this is the VHDL language issue I am facing right now.

I realize already in this moment, that there also will be problem with returning response transaction in the procedure via output argument, where length of the transaction body is also unknown.

I would like to ask you for advice, if my object oriented approach to model the IPbus transaction with variable body length is implementable in the VHDL language.

  • \$\begingroup\$ OSVVM uses records as a communication channel. How this is done today in OSVVM and in the future using VHDL-2019 is here: linkedin.com/pulse/vhdl-interfaces-vhdl-2019-osvvm-jim-lewis Also how to turn our record based approach into a virtual transaction connection (without wires in the test harness) is shown here: linkedin.com/pulse/… \$\endgroup\$
    – Jim Lewis
    Jan 25, 2022 at 14:32
  • \$\begingroup\$ Also both of the OSVVM approaches shown in the linkedin articles above are VHDL compliant, while the UVVM approach using shared variables of an ordinary type are not. Shared variables of an ordinary type was a temporary feature added in VHDL-93 and was replaced, deprecated, and removed in the next revision VHDL-2000. See linkedin.com/pulse/… \$\endgroup\$
    – Jim Lewis
    Jan 25, 2022 at 14:36

1 Answer 1


I'm about 98% that what you're attempting to do is not possible within VHDL. I've done a bit of digging, and every bit of evidence I can find corroborates my suspicion.

Of the scant information I can find, the only thing that comes close to addressing your question is this post on VHDLGuru where the author points out that you can't even use a generic to set the size of the array, so that doesn't bode well for the dynamic approach you're targeting. (The author does propose using a package to help solve the problem, but that's probably not helpful for your purposes.)

I am not sure if it is because of lack of the support in the VHDL standard or in GHDL.

I'm not sure either, but you've already proven GHDL doesn't support it and the evidence suggests that "most" tools don't support it so I'd recommend against trying an approach this sophisticated.

If this is just a simulation model, why not just declare bodyy to be an array of fixed size (i.e. the maximum size you would ever require)? You would of course need another variable to track the actual message size, but that could be easily defined using your approach. The only downside to this approach is that your simulation could slow down for super-huge messages, but if you're trying to simulate super-huge messages then you have a problem no matter what approach you take...

  • \$\begingroup\$ On the other hand, I'm sure. signal transaction : t_ipbus_transaction := ... provides no subtype indication constraint. IEEE Std 1076-2008 Index constraints and discrete ranges "The index range for each index of an array object or array subelement of a composite object is determined as follows: a) For a variable or signal declared by an object declaration, the subtype indication of the corresponding object declaration shall define a fully constrained subtype (and thereby, the index range for each index of the array object or subelement)." Shall has mandatory weight (1.3.1). \$\endgroup\$
    – user8352
    Mar 15, 2019 at 1:14
  • 1
    \$\begingroup\$ What I'm not sure of having read this is why someone wants to declare a signal object with a particular packet size (having seen the IPbus v2.0 Protocol specification). There are no transactions shown with the signal as a target of an assignment or as a value expression. It appears a solution in search of a problem with only snippets of an IPbus TVM shown in an otherwise non-disclosed "my object oriented approach". The question seems unclear and an answer premature. \$\endgroup\$
    – user8352
    Mar 15, 2019 at 1:32
  • \$\begingroup\$ @user8352 Here github.com/UVVM/UVVM_Community_VIPs/pull/1/files you can see how it looks right now. Maybe your ideas will help me to improve it. \$\endgroup\$
    – Al Bundy
    Apr 7, 2019 at 8:43

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.