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...

Saturday, 29 December 2012

Floating Point Type

Formal Definition

Floating point type provides an approximation of the real number value.

Simplified Syntax

type type_name is real_number_left_bound downto real_number_right_bound;

type type_name is real_number_left_bound to real_number_right_bound;

Description

A floating point type is a numeric type consisting of real numbers which values are constrained by a specified range.

There exists only one predefined floating point type: REAL. The range of the values for the type REAL are implementation-dependent, but it is required by the standard that it covers the values from -1.0E38 to +1.0E38.

A user-defined floating point type can be constructed on the basis of the predefined REAL type by constraining its range (example 1). The bounds of the range of a user-defined floating point type should be in the form of locally static expression. The expression is classified as a locally static if it is possible to determine its value without running the code. The value of an expression used as a range for a floating point type must also be of floating point type, not necessarily the same for both bounds (example 2). Negative bounds are allowed.

All floating point types (including user-defined) have the same set of arithmetic operators, namely: addition, subtraction, multiplication, division, absolute function and exponentiation.

Examples

Example 1

type Voltage_Level is range -5.5 to +5.5;
type Int_64K is range - 65536.00 to 65535.00;

Example 2

type APPROX_VALUES_DOWNTO is range (2.0**(N+1)) - 1.0 downto 0.0;
type APPROX_VALUES_TO is range 0.0 to (2.0**(N+1)) - 1.0;

Important Notes

· In order to add, subtract, multiply or divide integer object to/from a real object, type conversion of the integer object is needed. The only exception from this rule is multiplication and division of universal integer and universal real.

· The floating point types are not synthesizeable by any of the existing tools. Their use is thus very limited.

Function

Complete Definition:

A function call is a subprogram of the form of an expression that returns a value.

Simplified Syntax

function function_name (parameters) return type;

function function_name (parameters) return type is

declarations

begin

     sequential statements

end function function_name;

Description

The function is a subprogram that either defines an algorithm for computing values or describes a behavior. The important feature of functions is that they are used as expressions that return values of specified type. This is the main difference from another type of subprograms: procedures, which are used as statements.

The result returned by a function can be of either scalar or complex type.

Functions can be either pure (which is default) or impure. Pure functions always return the same value for the same set of actual parameters. Impure functions may return different values for the same set of parameters. Additionally, an impure function may have „side effects”, like updating objects outside of their scope, which is not allowed for pure functions.

The function definition consists of two parts:

· function declaration, which consists of name, parameter list and type of the values returned by the function;

· function body, which contains local declarations of nested subprograms, types, constants, variables, files, aliases, attributes and groups, as well as sequence of statements specifying the algorithm performed by the function.

The function declaration is optional and function body, which contains a copy of it, is sufficient for correct specification. However, if a function declaration exists, the function bodydeclaration must appear in the given scope.

FUNCTION DECLARATION

The function declaration can be preceded by an optional reserved word pure or impure, denoting the character of the function. If the reserved word is omitted it is assumed by default that the function is pure.

The function name, which appears after the reserved word function, can be either an identifier or an operator symbol (if the function specifies the operator). Specification of new functions for existing operators is allowed in VHDL and is called operator overloading. See respective topic for details.

The parameters of the function are by definition inputs and therefore they do not need to have the mode (direction) explicitly specified. Only constants, signals and files can be function parameters. The object class is specified by a reserved word (constant, signal or file, respectively) preceding the parameter's name. If no reserved word is used, it is assumed by default that the parameter is a constant.

In case of signal parameters the attributes of the signal are passed into the function, except for 'STABLE, 'QUIET, 'TRANSACTION and 'DELAYED, which may not be accessed within the function.

If a file parameter is used, it is necessary to specify the type of the data appearing in the opened file.

Example 1 contains several examples of function declarations.

FUNCTION BODY

Function body contains a sequence of statements that specify the algorithm to be realized within the function. When the function is called, the sequence of statements is executed.

A function body consists of two parts: declarations and sequential statements. At the end of the function body, the reserved word end can be followed by an optional reserved wordfunction and the function name. Examples 2 through 4 illustrate the function bodies.

IMPURE FUNCTIONS

If a function is explicitly specified as an impure (which is denoted with the reserved word impure, preceding the function declaration) it may return different results in different calls even with the same parameters. See Example 5.

Examples

Example 1

type Int_Data is file of NATURAL;
function Func_1 (A,B,X: REAL) return REAL;
function "*" (a,b: Integer_new) return Integer_new;
function Add_Signals (signal In1,In2: REAL) return REAL;
function End_Of_File (file File_name: Int_Data) return BOOLEAN;

The first function above is called Func_1, it has three parameters A, B and X, all of REAL type and returns a value also of REAL type.

· The second function defines a new algorithm for executing multiplication. Note that the operator is enclosed in double quotes and plays the role of the function name.

· The third function is based on signals as input parameters, which is denoted by the reserved word signal preceding the parameters.

· The fourth function declaration is a part of the function checking for end of file, consisting of natural numbers. Note that the parameter list uses the Boolean type declaration.

Example 2

function Transcod_1(Value: in bit_vector(0 to 7)) return bit_vector is
begin
   case Value is
     when "00000000" => return "01010101";
     when "01010101" => return "00000000";
     when others => return "11111111";
   end case;
end Transcod_1;

The case statement has been used to realize the function algorithm. The formal parameter appearing in the declaration part is the Value constant, which is a parameter of the Bit_vector type. This function returns a value of the same type.

Example 3

function Func_3 (constant A,B,X: real) return real is
begin
   return A*X**2+B;
end Func_3;

The formal parameters: A, B and X are constants of the real type. The value returned by this function is a result of calculating the A*X**2+B expression and it is also of the real type.

Example 4

function Func_4 (constant A,B,Step,LeftB,RightB: in real) return real is
variable counter, max, temp: real;
begin
counter:= LeftB;
max:=Func_3(A,B, counter);
L1:
     while counter <= RightB loop
temp:=Func_1(A,B, counter);
         if temp > max then
max:=temp;
         end if;
counter := counter + Step;
     end loop L1;
   return max;
end Func_4;

The fourth example is much more complicated. It calculates the maximum value of the Func_1 function.

All the formal parameters are constants of the real type. When the function is called, the A and B values appearing in the function are passed, Step is a determinant of calculation correctness. The LeftB and RightB values define the range in which we search for the maximum value of the function.

Inside the function body are contained definitions of variables counter, max and temp. They are used in the simple algorithm, which calculates all the function values in a given range and storing the maximum value returned by the function.

Example 5

variable number: Integer := 0;
impure function Func_5 (A: Integer) return Integer is
variable counter: Integer;
begin
counter := A * number;
number := number + 1;
   return counter;
end Func_5;

Func_ 5 is an impure function; its formal parameter A and returned value are constants of the integer type. When the function is invoked, output value depends on the variablenumber declared outside the function.

The number variable is additionally updated after each function call (it increases its value by 1). This variable affects the value calculated by the function, that is why the out function value is different for the same actual parameter value.

Important Notes

· Functions can be called recursively.

· Function body may not contain a wait statement or a signal assignment.

· Subprograms (functions and procedures) can be nested.

Generate Statement

Formal Definition

A mechanism for iterative or conditional elaboration of a portion of a description.

Simplified Syntax

label : for parameter in range generate

[ { declarations }

begin ]

{ concurrent_statements }

end generate [ label ] ;

label : if condition generate

[ { declarations }

begin ]

{ concurrent_statements }

end generate [ label ] ;

Description

The generate statement simplifies description of regular design structures. Usually it is used to specify a group of identical components using just one component specification and repeating it using the generate mechanism.

A generate statement consists of three main parts:

· generation scheme (either for scheme or if scheme);

· declarative part (local declarations of subprograms, types, signals, constants, components, attributes, configurations, files and groups);

· concurrent statements.

The generation scheme specifies how the concurrent structure statement should be generated. There are two generation schemes available: for scheme and if scheme.

The for generation scheme is used to describe regular structures in the design. In such a case, the generation parameter and its scope of values are generated in similar way as in the sequential loop statement. Example 1 illustrates this concept with N-bit binary counter created by the generate statement that instantiates N D-type flip-flops (Figure 1).

N_bit_counter

Fig. 1. The N-bit binary counter counting forward.

It is quite common that regular structures contain some irregularities. In such cases, the if scheme is very useful. Example 2 describes the synchronuous decimal counter that consists of JK flip-flops and NAND gates (Fig. 2). In that structure there are some irregularities related to the connection of the next level of flip-flops.

8421_BCD_counter

Fig. 2. The 8421 BCD counter counting forward.

A generate statement may contain any concurrent statement: process statement, block statement, concurrent assertion statement, concurrent procedure call statement, component instantiation statement, concurrent signal assignment statement, and another generate statement. The latter mechanism allows nesting the regular design structures and forming multidimensional arrays of components.

Examples

Example 1

entity D_FF is
port (D,CLK_S : in BIT;
      Q : out BIT := '0';
      NQ : out BIT := '1' );
end entity D_FF;
architecture A_RS_FF of D_FF is
begin
BIN_P_RS_FF: process(CLK_S)
begin
if CLK_S = '1' and CLK_S'Event
then Q <= D;
          NQ <= not D;
end if;
end process;
end architecture A_RS_FF;
entity COUNTER_BIN_N is
generic (N : Integer := 4);
port (Q : out Bit_Vector (0 to N-1);
      IN_1 : in Bit );
end entity COUNTER_BIN_N;
architecture BEH of COUNTER_BIN_N is
component D_FF
port(D, CLK_S : in BIT; Q, NQ : out BIT);
end component D_FF;
signal S : BIT_VECTOR(0 to N);
begin
S(0) <= IN_1;
G_1 : for I in 0 to N-1 generate
D_Flip_Flop :
D_FF port map
(S(I+1), S(I), Q(I), S(I+1));
         end generate;
end architecture BEH;

First, a specification of a D flip-flop is given which will be used by the component declaration. The generate statement here is used to define a counter of arbitrary length, determined only by its generic parameter (set here to 4).

Example 2

-- the 8421 BCD counter
entity COUNTER_BCD is
port (IN_1 : in Bit; Q:out Bit_Vector(0 to 3));
end entity COUNTER_BCD;
architecture STRUCT of COUNTER_BCD is
component D_FF
port (J, K, CLK_S : in BIT; Q: out BIT);
end component D_FF;
component NAND_GATE
port (IN1, IN2 : in Bit; OUT1 : out Bit);
end component NAND_GATE;
signal S: Bit_vector(0 to 2);
signal L: Bit_vector(0 to 1);
begin
D_FF_0 : D_FF port map ('1','1',IN_1, S(0));
Gen_1 : for I in 1 to 3 generate
Gen_2 : if I = 1 or I = 2 generate
D_FF_I : D_FF port map (S(I-1),S(I-1), IN_1, L(I-1));
NAND_I : NAND_GATE port map (S(I-1),L(I-1), S(I));
Q(I) <= L(I-1);
        end generate;
Gen_3 : if I = 3 generate
D_FF_3 : D_FF port map (S(I-1),S(I-1), IN_1, Q(I) );
          end generate;
   end generate;
Q(0) <= S(0);
end STRUCT;

Nested generate statements have been used here in order to shorten the description. The outmost generate statement specifies the complete counter, which component parts are generated by the inner statements depending on the index of the component (flip-flop) inside the counter.

Important Notes

· Each generate statement must have a label.

· If the generate statement does not contain any local declarations then the reserved word begin need not to be used.

· Generate statements can be nested.

Generic

Formal Definition

An interface constant declared in the block header of a block statement, a component declaration, or an entity declaration. Generics provide a channel for static information to be communicated to a block from its environment. Unlike constants, however, the value of a generic can be supplied externally, either in a component instantiation statement or in a configuration specification.

Simplified Syntax

generic ( generic_interface_list ) ;

Description

Generics support static information to blocks in a similar way as constants, but unlike the constants the values of generics can be supplied externally. Similar to ports, they can be declared in entities and component declarations, and always before ports.

Values supported by generics declared in an entity can be read either in entity or in architecture associated with the entity. In particular, a generic can be used to specify the size of ports (example 1), the number of subcomponents within a block, the timing characteristics of a block (example 2), physical characteristics of a design, width of vectors inside an architecture, number of loop iterations, etc. In general, generic can be treated inside an architecture in the same way as constant.

Examples

Example 1

entity CPU is
  generic (BusWidth : Integer := 16);
  port(DataBus : inout Std_Logic_Vector(BusWidth-1 downto 0));
. . .

The generic value BusWidth is used here to declare the width of the port DataBus, and can be successively in all declarations of buses inside associated architecture(s). This way the user supplies only one value, which parameterizes complete design.

Example 2

entity Gen_Gates is
generic (Delay : Time := 10 ns);
port (In1, In2 : in Std_Logic;
      Output : out Std_Logic);
end Gen_Gates;
architecture Gates of Gen_Gates is
begin
  . . .
  Output <= In1 or In2 after Delay;
  . . .
end Gates;

The Delay generic value Delay specifies here the delay through a device or part of the device.

Important Notes

· In most synthesis tools only generics of type integer are supported.

Group

Formal Definition

A named collection of named entities. Groups relate different named entities for the purposes not specified by the language. In particular, groups may be decorated with attributes.

Simplified Syntax

group group_template_name is ( entity_class_list ) ;

group group_name : group_template_name ( group_constituent_list );

Description

The user-defined attributes are connected individually with each named entity. That is why each separate named entity can have its own attributes. In case when the user wants to assign information to several related named entities, he/she should define a group consisting of these units, and then specify attributes for the entire group. The set of units with the specified characteristics can be defined by means of group declaration. The group declaration in turn requires group template declaration to be defined earlier.

THE GROUP TEMPLATE DECLARATION

The group template declaration defines pattern of a group connecting named entities with the specified class. The set of possible entity classes contains entity, architecture, configuration, procedure, function, package, type, subtype, constant, signal, variable, component, label, literal, units, group, and file. Each entity class entry defines an entity class that may appear at that particular position in the group type (Example 1).

The box symbol (<>) can be used together with the name of an entity class to allow zero or more units belonging to this group (Example 2). If such a declaration appears on the list, it must be the last one.

THE GROUP DECLARATION

Group declaration connects named entities having the specified characteristics.

The group declaration consists of identifier, group template name and group constituent list. The identifier represents a group, the group template name indicates group's template declaration, and the group constituent indicates the chosen named entities belonging to this group (Example 3).

THE ATTRIBUTES OF GROUPS

The attribute specification of a group is realized in a similar way to other attribute specifications. First, the attribute of a given type is declared and it is specified for the given group in its declaration part which contains declaration of the particular group (Example 4).

Examples

Example 1

group Variable_group is ( variable, variable );

The Variable_group template group declaration creates two variables which serve as a pattern for the variables belonging to this group.

Example 2

group Component_group is ( component <> );

The Component_group pattern declaration creates a group, which consists of a component list of arbitrary length.

Example 3

group Input_pair : Variable_group ( A1, A2 );

The Input_pair group declaration creates a group, which consists of A1 and A2 variables and is based on the Variable_group group template (declared in Example 1).

Example 4

function Compute_Values (A, B:Integer) return BOOLEAN is
variable A1, A2: Integer;
group Variable_group is ( variable, variable );
group Input_pair : Variable_group ( A1, A2 );
attribute Input_name: String;
attribute Input_name of Input_pair : group is "Input variables";
begin
  .......
end function;

The value of the attribute Input_name for the group Input_pair is equal to ”Input variables”.

Important Notes

· Groups can be nested.

Guard

Formal Definition

A Boolean-valued expression associated with a block statement that controls assignments to guarded signals within a block. A guard expression defines an implicit signal GUARD that may be used to control the operation of certain statements within the block.

Simplified Syntax

some_signal_in_a_block <= guarded expression;

Description

The characteristic feature of the block statement is the guard expression. It is a logical expression of the Boolean type, declared implicitly after the reserved word block whenever a guarded expression appears inside the block (Example 1).

The guard expression implies a signal named 'guard' at the beginning of the block declaration part. This signal can be read as any other signal inside the block statement but no assignment statement cant update it. This signal is visible only within the given block. Whenever a transaction occurs on any of the signals on the right hand side of the guardexpression, the expression is evaluated and the 'guard' signal is immediately updated. The 'guard' signal takes on the TRUE value when the value of the guard expression is true. Otherwise, 'guard' takes on the FALSE value.

The 'guard' signal may also be declared explicitly as a Boolean signal in the block statement. The advantage of this approach is that more complex (than a simple Boolean expression) algorithm to control the guard signal can be used. In particular, a separate process (Example 2) can drive the guard signal.

If there is no guard expression and the guard signal is not declared explicitly, then by default the guard signal is always true.

The guard signal is used to control so called guarded concurrent signal assignment statements contained inside the block. Each such statement contains the reserved word guardplaced after the symbol "<=". They assign a new value to the signal only when the guard signal is true. Otherwise, the signal assignment statement does not change the value of the given signal. In Example 1, the signal OUT_1 will take on the value of not IN_1 only when the value of the expression CLS'EVENT and CLK='1' will be true.

Examples

Example 1

RISING_EDGE : block (CLK'EVENT and CLK='1')
begin
  OUT_1 <= guarded not IN_1 after 5 ns;
  ..................................
end block RISING_EDGE;

The assignment to the signal OUT_1 is guarded, which introduces the implicit GUARD signal into the block.

Example 2

ALU : block
signal GUARD: Boolean := False;
begin
  OUT_1 <= guarded not IN_1 after 5 ns;
  ..............................
  P_1: process
    begin
      GUARD <= True;
      ...............
    end process P_1;
end block ALU;

Signal GUARD is declared explicitly and can be assigned value like any other signal.

Important Notes

  • Guarded blocks are usually not supported for synthesis.

Sunday, 23 December 2012

Identifier

Formal Definition

Names that identify various VHDL named entities.

Syntax:

identifier ::= basic_identifier | extended_identifier

basic_identifier ::= letter { [ underline } letter_or_digit }

letter_or_digit ::= letter | digit

letter ::= upper_case_letter | lower_case_letter

extended_indentifier ::= \graphic_character { graphic_character } \

Description

Identifiers are used both as names for VHDL objects, procedures, functions, processes, design entities, etc., and as reserved words. There are two classes of identifiers: basic identifiers and extended identifiers.

The basic identifiers are used for naming all named entities in VHDL. They can be of any length, provided that the whole identifier is written in one line of code. Reserved words cannot be used as basic identifiers (see reserved words for complete list of reserved words). Underscores are significant characters in an identifier and basic identifiers may contain underscores, but it is not allowed to place an underscore as a first or last character of an identifier. Moreover, two underscores side by side are not allowed as well. Underscores are significant characters in an identifier.

The extended identifiers were included in VHDL '93 in order to make the code more compatible with tools which make use of extended identifiers. The extended identifiers are braced between two backslash characters. They may contain any graphic character (including spaces and non-ASCII characters), as well as reserved words. If a backslash is to be used as one of the graphic characters of an extended literal, it must be doubled. Upper- and lower-case letters are distinguished in extended literals.

Examples

Example 1

-- legal identifiers
Decoder_1       FFT            Sig_N      Not_Ack
\signal\        \C:\\Cads\     \Signal @#\

All above identifiers are legal in VHDL '93. Note that a single backslash inside an extended name is denoted by two backslashes.

Example 2

-- illegal identifiers
_Decoder_1     2FFT       Sig_#N       Not-Ack

No VHDL tool would accept any of the four identifiers above. The errors are as follows: underscore at the beginning of the first identifier, digit at the beginning of the second, special character (#) inside the third and hyphen (special character as well) in the fourth.

Important Notes

· A basic identifier must begin with a letter.

· No spaces are allowed in basic identifiers.

· Basic identifiers are not case sensitive, i.e. upper- and lower-case letters are considered identical.

· Basic identifiers consist of Latin letters (a..z), underscores ( _ ) and digits (0..9). It is not allowed to use any special characters here, including non-Latin (language-specific) letters.