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

Case Statement

Formal Definition

The case statement selects for execution one of several alternative sequences of statements; the alternative is chosen based on the value of the associated expression.

Simplified Syntax

case expression is

when choice => sequential_statements

when choice => sequential_statements

         . . .

end case;

Description

The case statement evaluates the listed expressions and selects one alternative sequence of statements according to the expression value. The expression can be of a discrete type or a one-dimensional array of characters (example 1).

The case statement contains a list of alternatives starting with the when reserved word, followed by one or more choices and a sequence of statements.

An alternative may contain several choices (example 2), which must be of the same type as the expression appearing in the case statement. For each expression there should be at least one locally static choice. The values of each choice must be unique (no duplication of values is allowed).

A choice can be either a simple name (example 1), a name of a simple element (example 2) or discrete range (a slice, example 3). The choice types can be mixed.

A subtype with a constraint range (example 4) can substitute a slice.

Another option is to use an object name as the choice. The object must be of the same type as the expression in the case statement. Example 5 shows it for a constant.

When all explicitly listed choices do not cover all the alternatives (all the values available for an expression of given type) the others choice must be used because the choicestatements must cover all the alternatives, see example 5).

Examples

Example 1

P1:process
variable x: Integer range 1 to 3;
variable y: BIT_VECTOR (0 to 1);
begin
C1: case x is
      when 1 => Out_1 <= 0;
      when 2 => Out_1 <= 1;
      when 3 => Out_1 <= 2;
  end case C1;
C2: case y is
      when "00" => Out_2 <= 0;
      when "01" => Out_2 <= 1;
      when "10" => Out_2 <= 2;
      when "11" => Out_2 <= 3;
  end case C2;
end process;

Depending on the values of the variable x and y, we assign the values 0, 1, 2 or 3 (in the second case) to the signals Out_1 and Out_2 (both of type Integer).

Example 2

P2:process
type Codes_Of_Operation is (ADD,SUB,MULT,DIV);
variable Code_Variable: Codes_Of_Operation;
begin
C3: case Code_Variable is
      when ADD | SUB => Operation := 0;
      when MULT | DIV => Operation := 1;
  end case C3;
end process;

When two or more alternatives lead to the same sequence of operations then they can be specified as a multiple choice in one when clause.

Example 3

P3:process
type Some_Characters is ('a','b','c','d','e');
variable Some_Characters_Variable: Some_Characters;
begin
C4: case Some_Characters_Variable is
      when 'a' to 'c' => Operation := 0;
      when 'd' to 'e' => Operation := 1;
   end case C4;
end process;

Slices can be used as choices. In such a case, the slice name must come from the discrete range of the expression type.

Example 4

P5:process
variable Code_of_Operation : INTEGER range 0 to 2;
constant Variable_1 : INTEGER := 0;
begin
C6: case Code_of_Operation is
      when Variable_1 | Variable_1 + 1 =>
Operation := 0;
      when Variable_1 + 2 =>
Operation := 1;
  end case C6;
end process;

Constant used as a choice.

Example 5

P6:process
type Some_Characters is ('a','b','c','d','e');
variable Code_of_Address : Some_Characters;
begin
C7:case Code_of_Address is
      when 'a' | 'c' => Operation := 0;
      when others => Operation := 1;
   end case C7;
end process;

If the Code_of_Address variable is equal to 'a' and 'c', then the assignment Operation:=0; will be chosen. For the 'b', 'd' and 'e' values, the assignment Operation:=1; will be performed.

Important Notes

· The case expression must be of a discrete type or of a one-dimensional array type, whose element type is a character type.

· Every possible value of the case expression must be covered by the specified alternatives; moreover, every value may appear only once (no duplicates or overlapping of ranges is allowed).

· The When others clause may appear only once and only as the very last choice.

Character Type

Formal Definition

The character type object is an enumeration type object with at least one literal character among its enumeration literals.

Syntax:

Type character is an enumeration type with all acceptable characters listed. Its specificatio can be found in the STANDARD package.

Description

The CHARACTER type is a predefined type declared in the STANDARD package and the values of this type are the 256 characters of the ISO 8859-1 (Latin 1).

The set of predefined operations for the CHARACTER type contains all relational functions: "=", "/=", "<', "<=", ">", ">=".

Component Declaration

Formal Definition

A component declaration declares a virtual design entity interface that may be used in component instantiation statement.

Simplified Syntax

component component_name [ is ]

generic (generic_list);

port (port_list);

end component component_name;

Description

A component represents an entity/architecture pair. It specifies a subsystem, which can be instantiated in another architecture leading to a hierarchical specification. Component instantiation is like plugging a hardware component into a socket in a board (Fig. 1 in Example 1).

A component must be declared before it is instantiated. The component declaration defines the virtual interface of the instantiated design entity ("the socket") but it does not directly indicate the design entity.

The binding of a design entity to a given component may be delayed and may be placed either in the configuration specification or configuration declaration.

The component can be defined in package, design entity, architecture, or block declarations. If the component is declared in an architecture, it must be declared before the beginstatement of the architecture. In such a case, the component can be used (instantiated) in the architecture only.

A more universal approach is to declare a component in the package. Such a component is visible in any architecture, which uses this package.

Generics and ports of a component are copies of generics and ports of the entity the component represents.

Examples

Example 1

architecture STRUCTURE_2 of EXAMPLE is
component XOR_4 is
port(A,B: in BIT_VECTOR(0 to 3);
   C: out BIT_VECTOR(0 to 3));
end component XOR_4;
signal S1,S2 : BIT_VECTOR(0 to 3);
signal S3 : BIT_VECTOR(0 to 3);
begin
X1 : XOR_4 port map(S1,S2,S3);
end architecture STRUCTURE_2;

The XOR_4 component has two 4-bit input ports (A and B) and the 4-bit output port C. The declaration of this component is located in the declaration part of the architecture body STRUCTURE_2. The component instantiation statement assigns the X1 label to instantiated XOR_4 component and it associates its input-output interface with the S1, S2 and S3 signals.

VHDL_Component_Declaration

Figure 1. Example of component declaration and instantiation

Important Notes

· A component declaration does not define which entity/architecture pair is bound to each instance. Such an information is defined by configuration.

Component Instantiation

Formal Definition

A component instantiation statement defines a subcomponent of the design entity in which it appears, associates signals or values with the ports of that subcomponent, and associates values with generics of that subcomponent.

Simplified Syntax

label : [ component ] component_name

generic map ( generic_association_list )

port map ( port_association_list );

label : entity entity_name [(architecture_identifier)]

generic map ( generic_association_list )

port map ( port_association_list );

label : configuration configuration_name

generic map ( generic_association_list )

port map ( port_association_list );

Description

A component represents an entity/architecture pair. It specifies a subsystem, which can be instantiated in another architecture, leading to a hierarchical specification. Component instantiation is like plugging a hardware component into a socket in a board (Fig. 1 in Example 1).

The component instantiation statement introduces a subsystem declared elsewhere, either as a component or as an entity/architecture pair (without declaring it as a component).

The component instantiation contains a reference to the instantiated unit and actual values for generics and ports. There are three forms of component instantiation:

· instantiation of a component;

· instantiation of a design entity;

· instantiation of a configuration;

See configuration for details on the third form.

The actual values of generic map aspect and port map aspect connections allow assigning the components of the actual values to generic parameters and ports.

INSTANTIATION OF A COMPONENT

Instantiation of a component introduces a relationship to a unit defined earlier as a component (see component declaration). The name of the instantiated component must match the name of the declared component. The instantiated component is called with the actual parameters for generics and ports. The association list can be either positional or named.

In the positional association list, the actual parameters (generics and ports) are connected in the same order in which ports were declared in the component (Example 1).

Named association allows to list the generics and ports in an order that is different from the one declared for the component. In such a case the ports have to be explicitly referenced (Example 2).

INSTANTIATION OF A DESIGN ENTITY

It is not necessary to define a component to instantiate it: the entity/architecture pair can be instantiated directly. In such a direct instantiation, the component instantiation statement contains the design entity name and optionally the name of the architecture to be used for this design entity. The reserved word entity follows the declaration of this type of the component instantiation statement (Example 3).

If architecture name is not specified in an instantiation of a design entity, the last compiled architecture associated with the entity will be taken.

Examples

Example 1

architecture Structural of ALU is
signal X,Y,S,C : bit;
component HalfAdder is
port (In1, In2 : in bit;
          Sum, Carry : out bit);
end component HalfAdder;
begin
HA : HalfAdder port map (X,Y,S,C);
. . .
end architecture Structural;

The structural specification of an arithmetic-logic unit ALU uses an instantiation of a HalfAdder component. Note that the component is instantiated with signals of the ALU system. The signals are associated positionally.

Example 2

architecture Structural of ALU is
signal X,Y,S,C : bit;
component HalfAdder is
port (In1, In2 : in bit;
         Sum, Carry : out bit);
end component HalfAdder;
begin
HA : HalfAdder port map (Sum=>S, Carry=>C,
In1=>X, In2=>Y);
. . .
end architecture Structural;

This structural architecture performs the same function as in the Example 1. The only difference lies in the way the association list is specified for the component ports - the signals are associated with named association.

Example 3

entity XOR_GATE_4 is
   port(IN1,IN2: in BIT_VECTOR(0 to 3);
        OUT1 : out BIT_VECTOR(0 to 3));
end entity XOR_GATE_4;
architecture XOR_BODY_4 of XOR_GATE_4 is
begin
OUT1 <= IN1 xor IN2 after 5 ns;
end architecture XOR_BODY_4;
entity EXAMPLE is
end entity EXAMPLE;
architecture STRUCTURE_1 of EXAMPLE is
signal S1,S2 : BIT_VECTOR(0 to 3);
signal S3 : BIT_VECTOR(0 to 3);
begin
X1 : entity WORK.XOR_GATE_4(XOR_BODY_4)
          port map (S1,S2,S3);
end architecture STRUCTURE_1;

Entity XOR_GATE_4 is directly instantiated here, without declaring a component. The architecture, which specifies the body of the entity XOR_GATE_4 is called XOR_BODY_4 and is supported in parentheses. Further specification is similar to the one in instantiation of a component. The entity and architecture instantiated here must be located in the WORK library prior to this instantiation.

Component_Instantiation

Figure 1. Example of a direct instantiation.

Important Notes

· The label for component instantiation is obligatory.

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.