====== 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 [[arx:component|component]], is instantiated twice.
# 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:
* The subcomponent ''reg'' is the register that is instatiated twice in top-level component ''top''.
* Instantiation follows after the keyword ''generate''.
* When an instance of a subcomponent is created, the instance receives a name. In this case the names of the two instances are ''r1'' and ''r2''.
* When instantiating, the generics and generic types of a component need to be bound. Binding is expressed by means of an equal sign ''='' with a generic (type) at its left and a value at its right. Here, it is the intention to use bitvectors of length 12, overriding the default length of 8. For the first instance ''r1'', this is done by binding generic type ''T_IO'' to ''T_IOtop''. In ''r2'', the same effect is achieved by binding generic ''word_length'' of the instance to ''word_length'' in the instaniating component.
* Instantiation also requires that the ports of the instance are wired. This is indicated by the arrow symbol ''%%=>%%'' with a local port name at its left and a wire of the instantiating environment at its right. In this case, the ''data_in'' input of ''r1'' is wired to the ''data_in'' of ''top'' and ''data_out'' of ''r1'' is wired to the wire ''data_internal''.
===== 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 [[datatypes|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.
# 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.