Table of Contents

Instantiation

The use of a component inside another component is called instantiation. The component that is instantiated, is the instance.

A complex design becomes manageable by subdividing it into smaller subcomponents. Recursively subdividing these subcomponents results in a hierarchical decomposition of the design. Instantiation is a key mechanism for the creation of hierarchical descriptions.

Example 1: Cascade of Two Registers

The example below shows how the register, as presented in the explanation of a component, is instantiated twice.

reg-cascade.arx
# subcomponent
component reg
  word_length: generic integer = 8
  T_IO       : generic type = bitvector(word_length)
  data_in    : in T_IO
  data_out   : out T_IO
 
register
  storage  : T_IO = 0
 
begin
  storage = data_in
  data_out = storage
end
 
# top-level component
component top
  word_length: generic integer = 12
  T_topIO    : generic type = bitvector(word_length)
  data_in    : in T_topIO
  data_out   : out T_topIO
 
variable
  data_internal: T_topIO
 
generate
  r1: reg
    T_IO = T_topIO
    data_in  => data_in
    data_out => data_internal
 
  r2: reg
    word_length = word_length
    data_in  => data_internal
    data_out => data_out
 
begin
  # no functionality at this level
end

The example illustrates the following points:

Example 2: Cascade of Two Registers with Different Types

The example below is a slight variant of the example above. It shows how instances of subcomponents can be created that use different types. The default generic type of the register is now signed instead of bitvector. The type is changed to bitvector when instantiating r1. Instantiation of r2 leaves the signed type intact, but only changes the vector length. The reinterpret function is used to make the design consistent (see the page on data types for a detailed discussion of the Arx data types and reinterpretation).

Note that the generated VHDL description of this circuit will use two different entities for the two register instances.

cascade_2types.arx
# subcomponent
component reg
  word_length: generic integer = 8
  T_IO       : generic type = signed(word_length)
  data_in    : in T_IO
  data_out   : out T_IO
 
register
  storage  : T_IO = 0
 
begin
  storage = data_in
  data_out = storage
end
 
# top-level component
component top
  word_length: generic integer = 12
  T_topIO    : generic type = bitvector(word_length)
  data_in    : in T_topIO
  data_out   : out T_topIO
 
type
  T_num: signed(word_length)
 
variable
  data_internal: T_topIO
  r2_in, r2_out: T_num
 
generate
  r1: reg
    T_IO = T_topIO
    data_in  => data_in
    data_out => data_internal
 
  r2: reg
    word_length = word_length
    data_in  => r2_in
    data_out => r2_out
 
begin
  r2_in = reinterpret(T_num, data_internal)
  data_out = reinterpret(T_topIO, r2_out)
end

Known Issues

The Arx code generators can only process a single Arx file. The current version of Arx does not have an include command to compose a design from sources distributed across multiple files.

An alternative design strategy is to describe different parts of a design with separate Arx files and generate C++ and VHDL for each of them. The different parts of the design can then be combined at the C++ or VHDL level. This is, actually, the only way to deal with multiple clock domains. In the current version of Arx, multiple instantiations of the same Arx component in a C++ simulation does not work due to name conflicts. A possible workaround is to create a wrapper model in Arx that instantiates a component as often as needed.