Featured post

Top 5 books to refer for a VHDL beginner

VHDL (VHSIC-HDL, Very High-Speed Integrated Circuit Hardware Description Language) is a hardware description language used in electronic des...

Monday, 31 December 2012

Composite Type

Formal Definition

A composite type object is one having multiple elements. There are two classes of composite types: array types and record types.

Syntax:

composite_type_definition ::= array_type_definition | record_type_definition

Description

An object of a composite type is a collection of other objects, called elements. The elements can be of any scalar, composite or access type. It is not allowed to use file types as elements of a composite type.

The difference between arrays and records lies in that all elements of an array must be of the same type. For example, each array element can be a voltage value. On the other hand, each element of a record can be of a different type (Voltage1, current1, resistance1,Voltage2,&ldots;). Each element of an array is referred to by its array name and position (index). On the other hand, the record elements (called fields) are referred to through their individual names (together with the name of entire record), or through an aggregate.

See array and record for details.

Examples

Example 1

type T_MonthlyIncome is array (1 to 12) of Integer;
type T_PersonalData is
record
      FirstName : String (1 to 6);
      LastName : String (1 to 10);
      IDNumber : String (1 to 5);
      Incomes : T_MonthlyIncome;
      TaxPaid : Boolean;
end record;

The two types above illustrate two classes of composite type. The first one defines a 12-position array of integer values, while the second one is a record with five fields. First four fields are of composite types, while the very last one is of a scalar type.

Example 2

Signal Year97Inc : T_MonthlyIncome;
Signal SomeEmployee : T_PersonalData;
   . . .
Year97Inc(12) <= 5500;
SomeEmployee.FirstName <= "Gordon";

The signals are declared to be of the types declared in Example 1. Note the way elements of the composite types are accessed: in case of arrays through the position index, while in record through the field name (preceded by a dot).

Concatenation

Formal Definition

Predefined adding operator for any one-dimensional array type.

Description

The concatenation operator (denoted as &) composes two one-dimensional arrays into a larger one of the same type. A single element can be used as any of the two operands of concatenation. If two single elements are concatenated, then the result can be of any array type (as long as it is compatible with the type of the operands).

The resulting array is composed of the elements of the left operand (in left-to-right order) followed by the elements of the right operand (in the same order). The direction of the resulting array is the same as of the left operand, unless the left operand is a null array, in which case the direction of the result is that of the right operand.

Examples

variable ByteDat : Bit_Vector(7 downto 0);
alias Sign : Bit is ByteDat(7);
alias Modulus : Bit_Vector(6 downto 0) is ByteDat(6 downto 0);
constant FourZeros : Bit_Vector(3 downto 0) := "0000";
constant ResetHigh : Bit_Vector(7 downto 0) := FourZeros & "1111";
constant ResetAll : Bit_Vector(7 downto 0) := FourZeros & FourZeros;
ByteDat := '1' & Modulus;

Important Notes

· The declared number of elements in the result array must be large enough to cover the number of both operands added.

Configuration Declaration

Formal Definition

A configuration is a construct that defines how component instances in a given block are bound to design entities in order to describe how design entities are put together to form a complete design.

Simplified Syntax

configuration configuration_name of entity_name is

   -- configuration declarations

for architecture_name

for instance_label:component_name

use entity library_name.entity_name(arch_name);

end for;

    -- other for clauses

end for;

end [configuration] [configuration_name];

configuration configuration_name of entity_name is

   -- configuration declarations

for architecture_name

for instance_label:component_name

use configuration library_name.config_name;

end for;

    -- other for clauses

end for;

end [configuration] [configuration_name];

Description

Each component instantiation refers to some design entity (entity/architecture pair) and the association is specified by a configuration specification. Component specification appears in the declarative part of the unit, where the instances are used. If for some reasons, however, it is appropriate (or desired) to postpone (or defer) such association until later,configuration declaration can be used for specifying such deferred component specifications.

The configuration declaration starts with the configuration name and then it is associated to a given design entity. Declarative part of the configuration may contain use clauses,attribute specifications and group declarations. The main part of the configuration declaration contains so called block configuration. It indicates which architecture will be used with the entity specified earlier, as well as which configuration elements will be used in the component instantiation. This declaration may contain other blocks' configurations, allowing this way to specify hierarchical structures. Such a configuration can be called hierarchical, while a configuration without hierarchy can be called simple.

A simple configuration contains reference to only one architecture body (Example 1).

Hierarchical configurations, on the other hand, allow to nest block configurations (Example 2). This mechanism allows binding component instantiation statements with the design entities down the hierarchy.

When the ports and generics in component declaration do not match with their counterparts in entity declaration, so called binding indication can be applied. Simply speaking this is an explicit notification on how the ports and generics in the entity should be bound to ports and generics of the component instance. The generic map and port map clauses are used for this purpose. This technique is used in Example 1. In practice, however, it is recommended to match the generics and ports of components and respective entities as this improves readability.

Two main binding methods that can be applied in configuration specifications: binding of entities and binding configurations. They are illustrated in Examples 1 and 3, respectively.

Examples

Example 1

entity INVERTER is
generic (PropTime : TIME := 5 ns);
port ( IN1 : in BIT; OUT1 : out BIT);
end INVERTER;
architecture STRUCT_I of INVERTER is
begin
OUT1 <= not IN1 after PropTime;
end STRUCT_I;
entity TEST_INV is end TEST_INV;
architecture STRUCT_T of TEST_INV is
signal S1, S2 : BIT := '1';
-- INV_COMP component declaration:
component INV_COMP is
generic (TimeH : TIME);
port ( IN_A : in BIT; OUT_A : out BIT );
end component;
begin
-- instantiation of INV_COMP component:
LH:INV_COMP generic map (10 ns) port map (S1,S2);
end STRUCT_T;
configuration CONFIG_TINV of TEST_INV is
for STRUCT_T -- indicates architecture body of TEST_INV
  -- indicates design entity for LH instantiation statement:
for LH : INV_COMP
use entity WORK.INVERTER (STRUCT_I)
    -- indicates generic and port aspects:
generic map (PropTime => TimeH)
port map (IN1 => IN_A, OUT1 => OUT_A);
end for;
end for ;
end CONFIG_TINV;

The CONFIG_TINV configuration declaration can be used as an example of the basic configuration declaration. There is only one block configuration in the configuration declaration. This block contains a component declaration INV_COMP. In the component instantiation statement LH, the design entity INVERTER is assigned to INV_COMP component.

There is one block configuration in the CONFIG_TINV configuration declaration, it indicates that STRUCT_T architecture body will be used. INV_COMP component configuration appears in the block configuration. The CONFIG_TINV configuration for the TEST_INV design entity allows associating LG component: INV_COMP with INVERTER design entity and its STRUCT_1 architecture body.

VHDL_Configuration_declaration

Figure 1. Example of configuration declaration

Example 2

-- block configuration for architecture body STRUCT:
for STRUCT
-- component configuration specified in architecture body STRUCT:
for SPEECH_CPU: SPEECH
use entity SP_LIB.DIG_REC(ISD)
generic map (TimeRec => 20 sec);
      -- block configuration for architecture body ISD of DIG_REC:
for ISD
      -- component configuration specified in architecture body ISD:
for AD_CONV : ADC_1 -- relates to instance AD_CONV of ADC_1
use entity ANALOG_DEV.ADC;
end for; -- for AD_CONV
end for; -- for ISD
end for; -- for SPEECH_CPU
end for; -- for STRUCT

The block configuration, indicating architecture body STRUCT, appears in the configuration declaration. Next, in the block configuration there is the component configuration SPEECH, which also contains block configuration IST. The block configuration IST configures the architecture body IST which contain an instantiation statement with label AD_CONV. The entire block is hierarchically specified here.

Example 3

configuration Conf_Test of Test is
for STRUCTURE_T
for T_1 : DEC use configuration CONF_E;
end for;
end for;
end configuration Conf_Test;

In this example, the configuration declaration of design entity EXAMPLE is used. It binds EXAMPLE design entity to DEC component by using its configuration CONF_E as an entity aspect for T_1 component instance in the body architecture STRUCTURE_T.

VHDL_Configuration_declaration

Figure 2. Example of configuration declaration

Important Notes

· Configuration assigns one and only one architecture to a given entity.

· Synthesis tools do generally not support configurations.

· For a configuration of some design entity, both the entity and the configuration must be declared in the same library.

Configuration Specification

Formal Definition

A configuration is a construct that defines how component instances in a given block are bound to design entities in order to describe how design entities are put together to form a complete design.

Simplified Syntax

for instance_label:component_name

use entity library_name.entity_name(arch_name);

for instance_label:component_name

use configuration library_name.config_name;

Description

Each component instantiation refers to some design entity (entity/architecture pair) and the association is specified by a configuration specification. Component specification appears in the declarative part of the unit, where the instances are used. This way components can be configured within architecture which instances them without using a separate configuration declaration. The specification is simpler, but also less flexible. Example 1 contains a configuration specification for the same component as in the Example 1 in theconfiguration declaration description.

When the ports and generics in component declaration do not match with their counterparts in entity declaration, so called binding indication can be applied. Simply speaking this is an explicit notification on how the ports and generics in the entity should be bound to ports and generics of the component instance. The generic map and port map clauses are used for this purpose. This technique is used in Example 1. In practice, however, it is recommended to match the generics and ports of components and respective entities as this improves readability.

If no configuration (either in the form of a declaration or specification) is supported for a component, so called default binding will occur. This means that for such a component an entity will be selected such that its name, port names, port types, generics etc. match those in the corresponding component declaration. If the entity has more than one architecture, the last analyzed of them will be used.

Examples

Example 1

entity INVERTER is
generic (PropTime : TIME := 5 ns);
port ( IN1 : in BIT; OUT1 : out BIT);
end INVERTER;
architecture STRUCT_I of INVERTER is
begin
OUT1 <= not IN1 after PropTime;
end STRUCT_I;
entity TEST_INV is end TEST_INV;
architecture STRUCT_T of TEST_INV is
signal S1, S2 : BIT := '1';
-- INV_COMP component declaration:
component INV_COMP is
generic (TimeH : TIME);
port ( IN_A : in BIT; OUT_A : out BIT );
end component;
for LH : INV_COMP
use entity INVERTER (STRUCT_I)
   -- indicates generic and port aspects:
generic map (PropTime => TimeH)
port map (IN1 => IN_A, OUT1 => OUT_A);
begin
-- instantiation of INV_COMP component:
LH : INV_COMP generic map (10 ns)
  port map (S1, S2);
end STRUCT_T;

Architecture STRUCT_T of the entity TEST_INV uses a component INV_COMP. The binding of the component to the entity INVERTER and architecture STRUCT_I is realized by the configuration specification which appears in the declarative part of the architecture.

Important Notes

  • Synthesis tools do generally not support configurations. Users are required to ensure that component and entity names, ports and generics match (default binding).
  • For a configuration of some design entity, both the entity and the configuration must be declared in the same library.

Saturday, 29 December 2012

Constant

Formal Definition

Constant is an object whose value cannot be changed once defined for the design. Constants may be explicitly declared or they may be sub-elements of explicitly declared constants, or interface constants. Constants declared in packages may also be deferred constants.

Simplified Syntax

constant constant_name : type := value;

Description

A constant is an object whose value may never be changed during the simulation process.

The constant declaration contains one or more identifiers, a subtype indication and an expression which specifies the value of the constant declared in the particular statement. The identifiers specify names of the constants. Each name appearing in the identifier list creates a separate object.

The object type in the constant declaration can be of scalar or composite type and it can be constrained. A constant cannot be of the file or access type. If a constant is an array or a record then none of its elements can be of the file or access type.

The expression used in the constant declaration must refer to a value of the same type as specified for the constant (Example 1).

If a constant is declared an array other than string, bit_vector or std_logic_vector, then the value for the constant must be specified using aggregates (Example 2).

A constant declared in a package can be deferred, i.e. it can be declared without specifying its value, which is given later on, in the package body (Example 3).

Constants improve the clarity and readability of a project. Moreover, they simplify incorporating changes in the project. For example, if a design contains a bus with a fixed width, aconstant representing the number of bits in the bus can be used. When the width of the bus is to be changed, it is sufficient to alter the constant declaration only.

The visibility of constants depends on the place of their declaration. The constants defined in the package can be used by several design units. The constant declaration in the design entity is seen by all the statements of the architecture bodies of this entity. The constants defined in the declaration part of the design unit is seen in all bodies related to this design, including the process statement. The constant defined in the process can only be used in this process.

Examples

Example 1

type WeekDay is (Mon,Tue,Wed,Thu,Fri,Sat,Sun);
constant StartDay : WeekDay := Sat;
constant LogicalGND : Bit := '0';
constant BusWidth, QueueLength : Integer := 16;
constant CLKPeriod : Time := 15 ns;
constant MaxSimTime : Time := 200 * CLKPeriod;

Each of the six constants above is of a scalar type. Both BusWidth and QueueLength are expected to be integer numbers of the same value, therefore they were specified using one declaration. Note that you can either explicitly specify the constant's value or using an expression based on other constants (see the MaxSimTime constant).

Example 2

type NumericCodeType is array (7 downto 0) of Integer range 0 to 9;
constant EntryCode : NumericCodeType := (2,6,4,8,0,0,1,3);
constant DataBusReset: Std_Logic_Vector(7 downto 0) := "00000000";

Both constants are of complex types, but DataBusReset is of the Std_Logic_Vector, thus it can be assigned its value directly. EntryCode is also a one-dimensional array, but its elements are integers so the value for the constant must be specified using an aggregate numeric code type (2,6,4,8...).

Example 3

package Timing is
constant Reset : Std_Logic;
end package Timing;
package body Timing is
constant Reset: Std_Logic := '0';
end package body Timing;

Note that the Reset constant is declared in the package without a concrete value assigned to it because the complete declaration of this constant is given in the package body.

Important Notes

· By definition, a constant may not be assigned any values by the simulation process.

· Use constants as often as possible as they create more readable and maintainable code.

· Use constants to define data parameters and lookup tables, which may substitute function calls the simulation time of such lookups is significantly shorter than that of function calls.

Delay

Formal Definition

Delay is a mechanism allowing introducing timing parameters of specified systems.

Syntax:

delay_mechanism ::= transport | [ reject time_expression ] inertial

Description

The delay mechanism allows introducing propagation times of described systems. Delays are specified in signal assignment statements. It is not allowed to specify delays in variable assignments.

There are two delay mechanism available in VHDL: inertial delay (default) and transport delay.

The transport delay is defined using the reserved word transport and is characteristic for transmission lines. New signal value is assigned with specified delay independently from the width of the impulse in waveform (i.e. the signal is propagated through the line - Example 1).

Inertial delay is defined using the reserved word inertial and is used to model the devices, which are inherently inertial. In practice this means, that impulses shorter than specified switching time are not transmitted (Example 2).

Inertial delay specification may contain a reject clause. This clause can be used to specify the minimum impulse width that will be propagated, regardless of the switching time specified (Example 3).

If the delay mechanism is not specified then by default it is inertial.

Examples

Example 1

B_OUT <= transport B_IN after 1 ns;

The value of the signal B_IN is assigned to the signal B_OUT with 1 ns delay. The distance between subsequent changes of B_IN is not important - all changes are transmitted to B_OUT with specified delay (Fig. 1).

VHDL_transport_delay

Figure 1. Example of transport delay

Example 2

L_OUT <= inertial L_IN after 1 ns;

The signal value L_IN is assigned to the signal L_OUT with 1 ns delay. Not all changes of the signal L_IN, however, will be transmitted: if the width of an impulse is shorter than 1 ns then it will not be transmitted. See Fig. 2 and the change of L_IN at 13 ns and again at 13.7 ns.

VHDL_inertial_delay

Figure 2. Example of inertial delay

Example 3

Q_OUT <= reject 500 ps inertial Q_IN after 1 ns;

The signal value Q_IN is assigned to the signal Q_OUT with 1 ns delay. Although it is an inertial delay with switching time equal to 1 ns, the reject time is specified to 500 ps (.5 ns) and only impulses shorter than 500 ps will not be transmitted (Fig. 3).

VHDL_inertial_delay_with_rejection

Figure 3. Example of inertial delay with rejection limit.

Important Notes

· Delay mechanisms can be applied to signals only. It is not allowed to specify delays in variable assignments.

· Delays are not synthesizable.

· The Inertial delay is the default delay and the reserved word inertial can be omitted.

Driver

Formal Definition

A container for a projected output waveform of a signal. The value of the signal is a function of the current values of its drivers. Each process that assigns to a given signal implicitly contains a driver for that signal. A signal assignment statement affects only the associated driver(s).

Description

Each signal assignment statement defines a driver for each scalar signal that is a target of this assignment. In case of signals of complex type, each element has its own driver. Inside processes each signal has only one driver, no matter how many assignment to it are specified.

When an assignment statement is executed, a new value is assigned to the signal driver. The value of the signal is determined based on all its drivers using the resolution function.

Examples

signal DataBus : Std_Logic_Vector (7 downto 0) := "ZZZZZZZZ";
P1: process (A,B)
begin
. . .
DataBus <= "11111111";
end process P1;
P2: process (A,B)
begin
. . .
DataBus <= "00000000";
end process P2;

Signal DataBus is assigned values in two processes, therefore it will have two drivers (one per each process). The assignments will result in a change of the value of respective drivers, which will result in assigning the "XXXXXXXX" value to the DataBus.

Important Notes

· Drivers are not associated with signal declarations but with signal assignments.

· If a signal has more than one driver in an architecture, it must be of a resolved type.