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

Bit_Vector

Definition:

The Bit_Vector type is predefined in the Standard package as a standard one-dimensional array type with each element being of the Bit type.

Syntax:

type bit_vector is array (natural range <>) of bit;

Description

The Bit_vector type is an unconstrained vector of elements of the bit type. The size of a particular vector is specified during its declaration (see the example below). The way the vector elements are indexed depends on the defined range and can be either ascending or descending (see range).

Assignment to an object of the Bit_vector type can be performed in the same way as in case of any arrays, i.e. using single element assignments, concatenation, aggregates, slices or any combination of them.

Examples

Example 1

signal DataBus : Bit_vector(7 downto 0);
signal FlagC : Bit;
DataBus(0) <= '1';                           -- 1
DataBus <= '0' & "111000" & FlagC;           -- 2
DataBus <= ('0', others => '1');             -- 3
DataBus <= DataBus(6 downto 0) & DataBus(7); -- 4
DataBus <= "01110001";                       -- 5

There is one bit_vector defined in this example - DataBus. Its range is defined as descending, therefore the most significant bit will be DataBus(7). Line 1, marked in the comment field, illustrates assignment of a single element (bit). The line 2 shows typical use of concatenation. Note that both single bits, groups of bits (with double quotes!) and other signals (as long as their type is compatible) can be used. The line 3 demonstrates the use of aggregates. The line 4 illustrates how slices can be used together with concatenation. The value of DataBus will be rotated left in this example. Finally, in line 5 DataBus is assigned an explicit value, specified with double quotes.

Despite that each of the numbered lines above is correct, it would be illegal to put them together in one specification as shown above, due to the fact that bit_vector is an unresolved type and there can be only one assignment to an object of this type in an architecture.

Important Notes

· Logical values for objects of the Bit_vector type MUST be written in double quotes. Single elements, however, are of the bit type, therefore all values assigned to single elements are specified in single quotes.

Block Statement

Formal Definition

The block statement is a representation of design or hierarchy section, used for partitioning architecture into self-contained parts.

Simplified Syntax

block_label : block (optional_guard_condition)

   declarations

begin

   concurrent statements

end block block_label;

Description

The block statement is a way of grouping concurrent statements in an architecture. There are two main purposes for using blocks: to improve readability of the specification and to disable some signals by using the guard expression (see guard for details).

The main purpose of block statement is organizational only - introduction of a block does not directly affect the execution of a simulation model. For example, both the upper and lower sections of code in Example 1 will generate the same simulation results.

Each block must be assigned a label placed just before the block reserved word. The same label may be optionally repeated at the end of the block, right after the end block reserved words.

A block statement can be preceded by two optional parts: a header and a declarative part. The latter allows to introduce declarations of subprograms, types, subtypes, constants, signals, shared variables, files, aliases, components, attributes, configurations, disconnections, use clauses and groups (i.e. any of the declarations possible for an architecture). All declarations specified here are local to the block and are not visible outside it.

A block header may contain port and generic declarations (like in an entity), as well as so called port map and generic map declarations. The purpose of port map and generic map statements is to map signals and other objects declared outside of the block into the ports and generic parameters that have been declared inside of the block, respectively. This construct, however, has only a small practical importance. The Example 2 illustrates typical block declarations.

If an optional guard condition is specified at the beginning of the block then this block becomes a guarded block. See guard for details.

The statements part may contain any concurrent constructs allowed in an architecture. In particular, other block statements can be used here. This way, a kind of hierarchical structure can be introduced into a single architecture body.

Examples

Example 1

A1: OUT1 <= '1' after 5 ns;
LEVEL1 : block
begin
A2: OUT2 <= '1' after 5 ns;
A3: OUT3 <= '0' after 4 ns;
end block LEVEL1;
A1: OUT1 <= '1' after 5 ns;
A2: OUT2 <= '1' after 5 ns;
A3: OUT3 <= '0' after 4 ns;

Both pieces of code above will behave in exactly the same way during simulation - block construct only separates part of the code without adding any functionality.

Example 2

entity X_GATE is
generic (LongTime : Time; ShortTime : Time);
port (P1, P2, P3 : inout BIT);
end X_GATE;
architecture STRUCTURE of X_GATE is
-- global declarations of signal:
signal A, B : BIT;
begin
LEVEL1 : block
-- local declaration of generic parameters
generic (GB1, GB2 : Time);
-- local binding of generic parameters
generic map (GB1 => LongTime, GB2 => ShortTime);
-- local declaration of ports
port (PB1: in BIT; PB2 : inout BIT );
-- local binding of ports and signals
port map (PB1 => P1, PB2 => B);
-- local declarations:
constant Delay : Time := 1 ms;
signal S1 : BIT;
begin
   S1 <= PB1 after Delay;
   PB2 <= S1 after GB1, P1 after GB2;
end block LEVEL1;
end architecture STRUCTURE;

The signals PB1 and PB2 have here the same values as P1 and B (in port map statement), respectively, and the generics GB1 and GB2 (see generic map statement) have the same values as Long Time and Short Time, respectively. However, such assignment is redundant because a block may use any declarations of an entity, including generics and ports. The Example 2 is presented here only for illustration purpose of the block syntax.

Important Notes

· Guarded blocks are generally not synthesizable.

· Unguarded blocks are usually ignored by synthesis tools.

· It is strongly recommended NOT to use blocks in non-VITAL designs - the package Std_logic_1164 supports mechanisms and multiple value logic which make the reserved words bus, disconnect, guarded and register unnecessary. Also, instead of guarded blocks for modeling sequential behavior it is recommended to used clocked processes.

· VITAL specifications require the use of blocks.

· VHDL supports a more powerful mechanism of design partitioning which is called component instantiation. Component instantiation allows connecting a component reference in one entity with its declaration in another entity.

Boolean

Definition:

The Boolean type is predefined in the Standard package as an enumerated data type with two possible values: false and true.

Syntax:

type boolean is (false,true);

Description

The boolean type is used for conditional operations. Boolean objects can be used with any of the relational operators <, >, <=, >=, = or /=.

According to the definition type, the leftmost value of the Boolean type is false, therefore the default value of any object of the Boolean type is false.

Since the boolean type is defined in the Standard package, it can be used in any VHDL specification without additional declarations.

Examples

Example 1

signal CondSup : boolean;
. . .
CondSup <= true;
. . .
if CondSup then -- could be: if CondSup = true then

The CondSup signal is declared as boolean but without any initial value. Therefore, by default it will be assigned the false value. A conditional operation could have been used instead as shown in the comment, but such a form would contain useless redundancy and should be avoided.

Important Notes

· Unlike in traditional ("hand-based") digital design, boolean values (false and true) are NOT identical to logical 0 and 1, respectively. In VHDL, the latter form is a completely different type and is called the Bit type.

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.