It depends on if it is Design or Verification. For Design until your vendors support VHDL-2019 interfaces you need one record for in and one record for out.
For verification is better with VHDL-2019 interfaces, but you can take liberties with the resolution functions of your records. In Open Source VHDL Verification Methodology (OSVVM), we use maximum resolution function to resolve record elements.
Step 1: Record + Elements with Resolved Types
OSVVM interfaces use records whose elements are a resolved type from the OSVVM package ResolutionPkg.
type AddressBusMasterTransactionRecType is record
Rdy : bit_max ;
Ack : bit_max ;
Address : std_logic_vector_max ;
AddrWidth : integer_max ;
DataToModel : std_logic_vector_max ;
DataFromModel : std_logic_vector_max ;
. . .
end record AddressBusMasterTransactionRecType ;
Types in ResolutionPkg use “maximum” as a resolution function and add the suffix “_max” to the type names. Maximum resolution picks the largest value driven on each element of signal object that has multiple drivers. The largest value is the right most value of a type (‘-‘ for std_ulogic). This works in conjunction with the left most value being the smallest and the default value for an object of that type.
ResolutionPkg provides the following (as subtypes): std_logic_max, std_logic_vector_max, unsigned_max, signed_max, bit_max, bit_vector_max, integer_max, integer_vector_max, time_max, time_vector_max, real_max, real_vector_max, character_max, string_max, boolean_max, and boolean_vector_max.
Step 2: Use Mode InOut on Interfaces
If all of the elements of the record are a type from ResolutionPkg, then the interface signal can have mode InOut and nothing more is needed. If an element of the record is not driven, then the value it contributes is the left most value of the type – which again is the smallest value.
entity Axi4LiteMaster is
port (
-- Globals
Clk : in ;
nReset : in ;
-- Testbench Transaction Interface
TransRec : inout AddressBusMasterTransactionRecType ;
-- AxiLite Interface
AxiLiteBus : inout Axi4LiteRecType -- **
) ;
end entity Axi4LiteMaster ;
On the OSVVM Axi4Master, we handle the AxiBus using std_logic_1164 types instead. In this case, all elements of Axi4 that are not directly driven by Axi4Master are driven to ‘Z’ to resolve them.
Step 3: Instantiate the Design
Exactly what you do with an ordinary type. If you use unconstrained elements, you will need to add range constraints to the signals that use the record type, but that does not impact the usage at the interface (port map).
Step 4: Work Arounds
Not all simulators support the VHDL-2008 method of applying an element resolution function to an array (as done by vector subtypes of the form “_max”). As a result, ResolutionPkg provides a type of the form “_max_c”. It is simply an array whose element is of the form “_max”.
OSVVM verification components all use “_max_c” because it allows our models to work on a wider range of simulators. There is a small cost. Since types like std_logic_vector_max_c are types, when assigning between them and std_logic_vector, a type conversion, such as the following are required.
-- assigning a std_logic_vector to a std_logic_vector_max_c
TransactionRec.DataToModel <= std_logic_vector_max_c(Data) ;
-- assigning a std_logic_vector_max_c to a std_logic_vector
ReadData := std_logic_vector(TransactionRec.DataFromModel) ;
Subtypes like std_logic_vector_max and std_logic_vector do not require a conversion function since they are both subtypes of std_ulogic_vector (since VHDL-2008), and hence, they convert automatically.
If you are interested in previewing VHDL-2019 interfaces, see my article at https://osvvm.org/archives/1668 that covers both of these topics.