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, 17 December 2012

Type

Formal Definition

A set of values and a set of operations.

Simplified Syntax

type type_name is type_definition;

type type_name;

Description

Each object in VHDL has to be of some type, which defines possible values and operations that can be performed on this object (and other objects of the same type). The set of operations of a type consists of:

· explicitly declared subprograms that have a parameter or result of the particular type; such subprograms can be either predefined (in standard packages) or user-defined;

· basic operations (assignments, allocators, selected names, indexed names, slice names)

· numeric literals, literal null, string literal, bit string literals, aggregates or predefined attributes - depending on particular type.

· There are four classes of types in VHDL:

· scalar types (values of these types have no elements),

· composite types (values of these types consist of element values),

· access types (provide access to objects of a given type) and

· files (provide access to objects that contain a sequence of values of a given type).

See respective topics for details.

Apart from predefined types (available through the packages Standard and Std_Logic_1164), the user can define his/her own types. A user-defined type can be of any of the four classes mentioned above. The rules for defining types are described in detail in the corresponding topics.

Important Notes

· A type defines not only a set of values, but also a set of operators.

· VHDL is strongly typed language which causes that two types defined in exactly the same way (i.e. lexically identical) but differing only by names will be considered different.

· If a translation from one type to another is required, then type conversion must be applied, even if the two types are very similar (like assigning a natural variable to an integer variable).

Type Conversion

Formal Definition

An expression that converts the value of a subexpression from one type to the designated type of the type conversion.

Simplified Syntax

type_mark ( expression )

Description

VHDL is a strongly typed language. This causes that objects of even closely related types need a conversion, if they are supposed to be used together.

The result of the conversion is an object, which type is the same as the type specified by the type_mark (Example 1). The type of the operand (the expression) must be known independently from the context. Moreover, the operand cannot be an aggregate, an allocator, the literal null, or a string literal.

A type conversion is restricted to closely related types, i.e. must conform to the following rules::

  • All abstract numeric types (integers and floating point numbers) are closely related types. When a floating-point number is converted into an integer, the result is rounded to the nearest integer.
  • Two arrays are closely related types if:
    • Both arrays have the same dimensions,
    • their elements are of the same type,
    • for each range, the index types are the same or closely related.
  • No other types are closely related.

If the type_mark indicates an unrestricted array type, then after the conversion the range boundaries are moved from the operand. If the type_mark indicates a restricted array type, then the range boundaries of the array are described based on this type. After the conversion, the elements values of the array are equal to the elements values before the conversion.

Examples

Example 1

variable Data_Calc, Param_Calc : integer;
. . .
Data_Calc := Integer(74.94 * real(Param_Calc));

This assignment contains two type conversions: first Param_Calc is converted to a real value in order to multiply it with a universal real. Then the result of the multiplication is converted back to an integer and assigned to Data_Calc.

Important Notes

  • No conversion is needed between any type or subtype defined on its basis.
  • Two arrays may be closely related even if corresponding index positions have different directions.

Sunday, 16 December 2012

Use Clause

Formal Definition

Achieves direct visibility of declarations that are visible by selection.

Simplified Syntax

use library_name.package_name.item;

use library_name.package_name;

use library_name.package_name.all;

Description

The use clause makes visible items specified as suffixes in selected names listed in the clause. In practice, the use clause makes visible declarations specified in packages and has the following form:

use library_name.package_name.item

If a designer wants to have all declarations in a package visible, then the 'item' clause should be substituted by the reserved word all.

The use clause is valid for the design unit immediately following it and for all secondary design units assigned to this design unit (if it is a primary design unit).

Examples

library IEEE;
use IEEE.Std_Logic_1164.all;
library IEEE;
use IEEE.Std_Logic_1164.Std_ulogic;
use IEEE.Std_Logic_1164.Rising_edge;

In the first example, all declarations specified in the package Std_Logic_1164 (which belongs to the library IEEE) have been made visible.

The second example makes visible the Rising_Edge function, which is declared in the same package. The function uses the type Std_ulogic, therefore declaration of this type is also made visible.

Important Notes

· Using multiple value logic and resolution functions requires using library clause and use clause like in the first example.

Variable Assignment

Formal Definition

A variable assignment statement replaces the current value of a variable with a new value specified by an expression.

Simplified Syntax

variable_name := expression ;

Description

The variable assignment statement modifies the value of the variable. The new value of the variable is obtained by assigning an expression to this variable. In order to distinguish variable assignment from signal assignment, the variable assignment symbol is different (:=).

The expression assigned to a variable must give results of the same type as the variable. The target at the left-hand side of the assignment can be either a name of a variable or anaggregate.

In the first case, the target can be in the form of simple name, selected name, indexed name or slice name (Example 1).

In case of aggregate as the target of the assignment, the type of the aggregate must be determinable from the context, including the fact that the type must be of the composite type. Each element of the aggregate must be in the form of the locally static name, which represents variable (Example 2).

The element association of aggregate, similarly to names, may have forms that are more complex: selected name, indexed name or slice name (Example 3).

Examples

Example 1

variable X, Y : REAL;
variable A, B : BIT_VECTOR (0 to 7);
type BIT_RECORD is record
  bitfield : BIT;
  intfield : Integer;
end record;
variable C, D : BIT_RECORD;
X := 1000.0;
A := B;
A := "11111111";
A (3 to 6) := ('1','1','1','1');
A (0 to 5) := B (2 to 7);
A (7) := '0';
B (0) := A (6);
C.bitfield := '1';
D.intfield := C.intfield;

The above examples of variable assignments are grouped in the following way: after the declarations the first group is a group of assignments with simple names as targets, then slice names, indexed names and finally selected names.

Example 2

variable E : BIT;
variable I : INTEGER;
(E, I) := C;

The aggregate used above as a target for a variable assignment could be used for the variable C declared in such a way as in the Example 1. E will be assigned the value of C.bitfield and I - C.intfield.

Example 3

type BIT_VECTOR_RECORD is record
  a: BIT_VECTOR(0 to 7);
  b: Integer;
end record;
variable G, H : BIT_VECTOR_RECORD;
(C.bitfield, C.intfield) := D; -- aggregate with selected name
(G.a(0 to 7), K) := H; -- aggregate with sliced name
(G.a(0), K) := D; -- aggregate with indexed name

Aggregates can use different forms of names.

Important Notes

· Variable assignment can be labeled.

· Variable assignment takes effect immediately.

· Variable assignment can not be specified with a delay.

Variable Declaration

Formal Definition

Variable is an object with a single current value.

Simplified Syntax

variable variable_name : type;

variable variable_name : type := initial_value;

Description

Variables are objects which store information local to processes and subprograms (procedures and functions) in which they are defined. Their values can be changed during simulation through the variable assignment statements.

A variable declaration includes one or more identifiers, a subtype indication and an optional globally static expression defining the initial value for the variable(s). The identifiers specify names for the variables, with one identifier per each variable. The variable can be declared to be of any type or subtype available, either constrained or unconstrained (Example 1).

The initial value of a variable can be assigned by a globally static expression. The expression must reference a value of the same type as the variable itself. If the variable is declared to be of a composite type other than a string, Bit_Vector or Std_Logic_Vector, then an aggregate must be used (see Example 2).

If the initial value of a variable is not specified, then it is implicitly set as the left bound of the type used. For example for a scalar named T, the default initial value will be T'LEFT. For a composite type, the initial value will be the aggregate consisting of the set of the default values of all the scalar elements. The default initial value for a variable of the access type isnull.

Variables declared in processes are initialized with their default values, given either explicitly or implicitly, at the start of the simulation. Variables declared in subprograms are initialized each time the subprogram is called.

The scope of variables is limited to the process or subprogram they are defined in. The only exception to this rule is a shared variable, which may be shared by multiple processes.

Variables can be also declared outside of a procedure or process to be shared between many processes. Shared variables may be declared within an architecture, block, generate statement or package. Declaration of a shared variable must be preceded by the shared keyword (Example 3).

Although the Language Reference Manual allows several processes to access a single shared variable it does not define what happens when two or more conflicting processes try to access the same variable at the same time. Such a situation may lead to unpredictable results and therefore should be avoided.

Examples

Example 1

type Mem is array (Natural range <>, Natural range <>) of Std_Logic;
variable Delay1, Delay2 : Time;
variable RAM1: Mem (0 to 1023, 0 to 8);

The type Mem is specified as an unconstrained memory (the limit depends on the implementation of the Natural subtype). The variable RAM1, specified in the third line, is based on the Mem type and is defined as a subtype constrained to a 1 KB memory.

Both Delay1 and Delay2 variables are of the Time type and are declared in the second line.

Example 2

type Mem is array (Natural range <>, Natural range <>) of Std_Logic;
variable TempCond : Boolean := true;
variable RAM2: Mem (0 to 7, 0 to 7):=
  (('0', '0', '0', '0', '0', '0', '0', '0'),
  ('0', '0', '0', '0', '0', '0', '0', '0'),
  ('0', '0', '0', '0', '0', '0', '0', '0'),
  ('0', '0', '0', '0', '0', '0', '0', '0'),
  ('0', '0', '0', '0', '0', '0', '0', '0'),
  ('0', '0', '0', '0', '0', '0', '0', '0'),
  ('0', '0', '0', '0', '0', '0', '0', '0'),
  ('0', '0', '0', '0', '0', '0', '0', '0'));

Both variables are initialized according to the types used. Note the aggregate has been used for initializing RAM2, which is an 88 bit memory.

Example 3

shared variable FreeAccess : Boolean := true;

The shared variable FreeAccess statement is used to determine whether a shared resource can be accessed at any particular time. However, in real applications a signal declaration would better serve for this purpose because using signals makes the specification more deterministic.

Important Notes

· Unlike signals, variables have neither history nor future, because according to its definition, each variable has only current value. No checking for the last event, time elapsed since the last event, previous value, etc. can be performed on variables.

· The non-shared variables are limited to subprograms and processes only.

· If a value of a variable is read before it is assigned in a clocked process (i.e. where operations are performed when an edge of clock signal is detected) then a register will be synthesized for this variable. A similar situation inside a combinatorial process may lead to generation of a latch.

· Variables declared in a subprogram are synthesized as combinatorial logic.

· During simulation variables consume a lot less (even an order of magnitude) memory space than signals. Therefore, it is highly recommended to use them for storage elements (such as memories) instead of signals.

· Shared variables may cause a system to be non-deterministic and therefore they should be avoided.

Vector

Description

Vector is another name for a one-dimensional array. It is used in particular for the arrays with elements of logical types: bit and std_logic (bit_vector and std_logic_vector, respectively).

Examples

signal DataBus : Bit_Vector(7 downto 0);
  . . .
DataBus <= "11000011";

Important Notes

  • Vectors of logical values are not directly transferable to integer values. Neither Standard package nor Std_Logic_1164 package define any conversion functions from logical vector to an integer or vice-versa. Most synthesis tools, however, support such functions (although these functions are tool-specific).
  • No arithmetic functions are allowed on logical vectors.

Vital

Formal Definition

VITAL (VHDL Initiative Towards ASIC Libraries) is an initiative, which objective is to accelerate the development of sign-off quality ASIC macro-cell simulation libraries written in VHDL by leveraging existing methodologies of model development.

Complete description: IEEE Standard 1076.4.

Description

VITAL, which is now standardized by IEEE, was created by an industry-based, informal consortium in order to accelerate the availability of ASIC (Application Specific Integrated Circuits) libraries for use in industrial VHDL simulators. As a result of the effort a new modeling specification has been created.

VITAL contains four main elements:

  • Model Development Specification document, which defines how ASIC libraries should be specified in VITAL-compliant VHDL in order to be simulated in VHDL simulators.
  • VHDL package Vital_Timing, defining standard types and procedures that support development of macro-cell timing models. The package contains routines for delay selections, timing violations checking and reporting and glitch detection.
  • VHDL package Vital_Primitives, defining commonly used combinatorial primitives provided both as functions and concurrent procedures and supporting either behavioral or structural modeling styles, e.g. VitalAND, VitalOR, VitalMux4, etc. The procedure versions of the primitives support separate pin-to-pin delay path and GlitchOnEvent glitch detection. Additionally, general purpose Truth Tables and State Tables are specified which are very useful in defining state machines and registers.
  • VITAL SDF map - specification that defines the mapping (translation) of Standard Delay Files (SDF), used for support timing parameters of real macro-cells, to VHDL generic values.

MODELING SPECIFICATION

The modeling specification of VITAL defines several rules for VHDL files to be VITAL-compliant. This covers in particular:

  • Naming conventions for timing parameters and internal signals, including prefixes for timing parameters, which must be used in the generics specifications (Example 1);
  • How to use the types defined in the Vital_Timing package for specifications of timing parameters;
  • Methodology of coding styles;
  • Two levels of compliance: level 0 for complex models described at higher level, and level 1, which additionally permits model acceleration.

A VITAL-compliant specification consists of an entity with generics defining the timing parameters of the ports (Example 1) and an architecture that can be written in one of two coding styles: either pin-to-pin delay style or distributed delay style.

PIN-TO-PIN DELAY MODELING STYLE

An architecture that follows this style contains two main parts (Example 2):

  • A block called Wire_Delay, which defines input path delays between input ports and internal signals. This block calls the concurrent procedure VitalPropagateWireDelay.
  • A process called VitalBehavior. This process may contain declarations of local aliases, constants and variables. It has a very rigid structure and is divided into three parts:
    • Timing Checks - does calls to procedure VitalTimingCheck which is defined in the package Vital_Timing.
    • Functionality - makes one or more calls to subprograms contained in the Vital_Primitives package and assignments to internal temporal variables. No wait statements, signal assignments or control structures are allowed here.
    • Path Delay - contains a call to VitalPropagateDelay for each output signal.

DISTRIBUTED DELAY MODELING STYLE

In this style the specification (ASIC cell) is composed of structural portions (VITAL primitives), each of which has its own delay. The output is an artifact of the structure, events and actual delays. All the functionality is contained in one block, called Vital_Netlist and this block may contain only calls to primitives defined in the Vital_Primitives package.

Examples

Example 1

library IEEE;
use IEEE.Std_Logic_1164.all;
library VITAL;
use VITAL.Vital_Timing.all;
use VITAL.Vital_Timing;
use VITAL.Vital_Primitives.all;
use VITAL.Vital_Primitives;
entity Counter is
  generic(tpd_ClkOut1 : DelayType01 := (10 ns, 10 ns);
  . . .);
  port (Reset : in Std_Logic := 'U';
    Clk : in Std_logic := 'U';
    CntOut : out Std_logic_Vector(3 downto 0));
end Counter;

This entity is a part of a VITAL-compliant specification of a four-bit synchronous counter with reset. Note that two libraries and three packages are used. In particular, multiple value logic types, defined in Std_Logic_1164, are standard logical types for VITAL.

The example given here specifies the propagation delay between the Clk input and the output number 1. The VITAL prefix tpd determines the timing parameter. The type used is specified in the Vital_Tming package.

Example 2

architecture PinToPin of Counter is
-- declarations of internal signals
begin
-- Input path delay
  Wire_Delay: block
  begin
  -- calls to the VitalPropagateWireDelay procedure
  Vital_Timing.VitalPropagateWireDelay (. . .);
  . . .
end block;
-- Behavior section
VitalBehavior: process(. . .)
  -- declarations
begin
  -- Timing Check
  Vital_Timing.VitalTimingCheck (. . .);
  -- Functionality
  Vital_Primitives.VitalStateTable (. . .);
  -- Path Delay
  Vital_Timing.VitalPropagatePathDelay (. . .);
  Vital_Timing.VitalPropagatePathDelay (. . .);
end process VitalBehavior;
end PinToPin;

The above listed architecture PinToPin is a template of a pin-to-pin modeling style. All its procedure calls should be specified with appropriate parameters.

Example 3

architecture DistrDelay of Counter is
  -- internal signals declarations
begin
-- Input path delay
Vital_Netlist: block
  -- internal declarations of the block
  begin
  -- calls to VITAL primitives, for example
  Vital_Primitives.VitalAND2(. . .);
  Vital_Primitives.VitalBuf(. . .);
  Vital_Primitives.VitalStateTable(. . .);
  end block;
end DistrDelay;

The above listed Architecture DistrDelay is a template of a distributed delay modeling style. All its procedure calls should be specified with appropriate parameters.