• No results found

VHDL Reference Manual

N/A
N/A
Protected

Academic year: 2021

Share "VHDL Reference Manual"

Copied!
144
0
0

Loading.... (view fulltext now)

Full text

(1)

VHDL Reference

Manual

(2)

Design Automation assumes no liability for errors, or for any incidental,

consequential, indirect or special damages, including, without limitation, loss of use, loss or alteration of data, delays, or lost profits or savings, arising from the use of this document or the product which it accompanies.

No part of this document may be reproduced or transmitted in any form or by any means, electronic or mechanical, for any purpose without written permission from Data I/O.

Synario Design Automation

10525 Willows Road N.E., P.O. Box 97046 Redmond, Washington 98073-9746 USA Corporate Switchboard: (206) 881-6444

Sales: 1-888-SYNARIO or [email protected]

Technical Support: 1-800-789-6507 or [email protected] World Wide Web: www.synario.com

Acknowledgments:

Synario, Synario ECS, ABEL, and Synario Design Automation are either trademarks or registered trademarks of Data I/O Corporation in the United States and/or other countries. Other trademarks are the property of their respective owners. Copyright© 1993-1997 Synario Design Automation, a division of Data I/O Corporation. All rights reserved.

Copyright

1993-1997 Synario Design Automation, a division of Data I/O

Corporation.

All rights reserved.

Portions copyright:

Microsoft

Corporation. All rights reserved;

Model Technology. All rights reserved;

(3)

Table of Contents

1. Introduction ... 1-1

2. Language Structure ... 2-1

Structure of a VHDL Design Description...2-2 Library Units...2-3 Package ...2-3 Entity ...2-4 Architecture...2-5 Configuration...2-5 Statements ...2-6 Declaration Statements...2-6 Concurrent and Sequential Statements ...2-6 Data Objects...2-8 Variables...2-8 Constants...2-9 Signals ...2-9 Data Types... 2-11 Numeric Types... 2-12 Other Types... 2-13 Enumerated Types... 2-13 The Std_ulogic and Std_logic Data Types ... 2-14 User Defined Types and Subtypes ... 2-14 Types and Logic Synthesis... 2-15 Type Conversions ... 2-15 Operators... 2-16 Logical Operators ... 2-16 Relational Operators ... 2-16 Arithmetic Operators ... 2-17 Overloading Operators ... 2-17 VHDL Attributes ... 2-17

3. How to Write Synthesizable VHDL... 3-1

(4)

Describing Combinational Logic...3-2 Constants and Types ...3-3 Logical Operators ...3-3 Relational Operators ...3-5 Arithmetic Operators ...3-6 Shift Operators ...3-8 Describing Conditional Logic ...3-8 Concurrent Statement: Conditional Signal Assignment...3-9 Concurrent Statement: Selected Signal Assignment...3-9 If Statement...3-9 Case Statement ... 3-10 Describing Replicated Logic ... 3-11 Functions and Procedures... 3-11 Loop Statements ... 3-12 Generate Statements... 3-13 Describing Sequential Logic ... 3-15 Conditional Specification ... 3-15 Wait Statement... 3-18 Latches ... 3-19 Flip-flops... 3-19 Gated Clocks and Clock Enable... 3-21 Synchronous Set/Reset ... 3-22 Asynchronous Set/Reset... 3-22 Asynchronous Reset/Preset... 3-23 Describing Finite State Machines ... 3-24 Template State Machine... 3-25 Feedback Mechanisms... 3-26 Types of State Machines... 3-28 Moore Machine... 3-28 Mealy Machine ... 3-30 Avoiding Unwanted Latches ... 3-31

4. How to Control the Implementation of VHDL... 4-1

Using Enumerated Types...4-1 A Review of Enumerated Types ...4-1 Synthesis of Enumerated Types ...4-2 Enum_encoding attribute ...4-2 “One hot” Enumeration ...4-4 Don’t-cares and Enumerated Types ...4-4 Describing Output Enables...4-5 Using Std_logic to Describe Output Enables ...4-5 Controlling Output Inversion...4-6
(5)

Selecting a Base Data Type ... 4-10 Using the Integer Type ... 4-10 Using Bit and Bit_vector Types... 4-11 Using Std_ulogic and Std_ulogic_vector Types... 4-11 Using Std_logic and Std_logic_vector Types ... 4-11 Using IEEE 1076.3 Unsigned/Signed Types ... 4-12 Synthesis of Don't Cares ... 4-13 Using Device Fitting Attributes ... 4-13 Pinnum Attribute... 4-14 Property Attribute ... 4-15 Macrocell Attribute ... 4-16 Critical Attribute... 4-17 Enum_encoding Attribute ... 4-18

5. VHDL Datapath Synthesis ... 5-1

How Inferencing Works ...5-2 Controlling Datapath Inferencing...5-2 Limitations of Inferencing Support...5-3 Examples of How to Infer Datapath Macrofunctions...5-4 Inferencing Details ...5-7 Instantiation Details ...5-9

6. How to Manage VHDL Design Hierarchies... 6-1

Managing Large Designs ...6-1 Hierarchy ...6-1 Components ...6-2 Components And Synthesis ...6-3 Configurations ...6-4 Blocks...6-5 Using Packages ...6-5 Package Visibility Rules...6-6 Design Libraries ...6-6 Using Packages For Common Declarations ...6-7 Using Design Libraries ...6-8 Library Search Paths...6-8 The Work Library...6-8 The Dataio and Generics Libraries ...6-9 Using Schematics With VHDL ...6-9 Using A Top-Level Schematic With VHDL ...6-9 Using Lower-Level Schematics With VHDL ... 6-10 Using Generic Symbols With VHDL ... 6-10
(6)

Reserved Words ...A-1 VHDL Syntax Basics...A-2 Declarations ...A-2 Names ...A-2 Sequential Statements...A-3 Subprograms...A-4 Concurrent Statements ...A-5 Library Units...A-7 Attributes...A-8

B. Limitations ...B-1

Constraints and Unsupported Constructs ...B-1 Unsupported Constructs ...B-1 Constrained Constructs ...B-1 Ignored Constructs ...B-2

C. VHDL for the ABEL-HDL Designer ...C-1

Design I/O ...C-1 Describing Design I/O in ABEL-HDL ...C-1 Describing Design I/O in VHDL...C-1 Pin and Node Numbers...C-2 Describing Pin Numbers in ABEL-HDL...C-2 Describing Pin and Node Numbers in VHDL ...C-2 Combinational Logic ...C-3 Describing Combinational Logic in ABEL-HDL ...C-3 Describing Combinational Logic in VHDL...C-4 Registers...C-4 Describing Registers in ABEL-HDL ...C-4 Describing Registers in VHDL ...C-4 Avoiding Unwanted Latches ...C-7 State Machines ...C-9 Describing State Machines in ABEL-HDL ...C-9 Describing State Machines in VHDL...C-9 A Standard ABEL-HDL Design in VHDL ...C-11 Design I/O ...C-12 Combinational Logic ...C-12 Registered Logic...C-12

D. ABEL-HDL Language Reference ...D-1

Dot extensions... D-2

Index

(7)

1.

Introduction

This manual discusses VHDL and the Synario Programmable IC Solution. This manual is intended to supplement the material presented in the Programmable IC Entry manual.

The following topics are discussed in this manual: • VHDL Language Structure

• How to write Synthesizable VHDL

• How to control the implementation of a VHDL Design • VHDL Datapath Synthesis

• How to Manage VHDL Design Hierarchies • VHDL Quick Reference

• Limitations (Constraints and unsupported Constructs) • VHDL for ABEL-HDL users

(8)
(9)

2.

Language Structure

VHDL is a hardware description language (HDL) that contains the features of conventional programming languages such as Pascal or C, logic description languages such as ABEL-HDL, and netlist languages such as EDIF. VHDL also includes design management features, and features that allow precise modeling of events that occur over time. This chapter introduces a subset of the VHDL language that allows you to begin creating synthesizable designs, and is not intended to

describe the full language. For further information on VHDL, consult a standard VHDL reference book. A number of these books are listed at the end of this chapter.

The VHDL Synthesizer supports most of the VHDL language, as

described in IEEE Standard 1076-1993. The meaning of some sections of the language, however, is unclear in the context of logic synthesis. Examples of this are found in the standard package textio. The file I/O operations supported by textio are useful for simulation purposes but are not currently synthesizable.

• For sample syntax and a list of VHDL statements supported by the VHDL Synthesizer, see Appendix A, “Quick Reference.”

• For a list of exceptions and constraints on the VHDL Synthesizer's support of VHDL, see Appendix B, “Limitations.”

This chapter shows you the structure of a VHDL design, and then describes the primary building blocks of VHDL used to describe typical circuits for synthesis:

• Library (Design) Units • Statements

• Objects • Types • Operators • Attributes

In addition, the three primary methods of VHDL design are discussed: • Dataflow VHDL

• Behavioral VHDL • Structural VHDL

(10)

Structure of a VHDL Design Description

The basic organization of a VHDL design description is shown in Figure 2-1. The sample file shown includes an entity-architecture pair and a package.

Figure 2-1: The Structure of a VHDL Design Description PREP Benchmark Circuit #1: Data Path

---- Copyright 1993, Data I/O Corporation.

---- Copyright 1993, Metamor, Inc.

--package typedef is

subtype byte is bit_vector (7 downto 0); end; use work.typedef.all; entity data_path is port (clk,rst,s_1 : in boolean; s0, s1 : in bit; d0, d1, d2, d3 : in byte; q : out byte); end data_path;

architecture behavior of data_path is signal reg,shft : byte;

signal sel: bit_vector(1 downto 0); begin

process (clk,rst) begin

if rst then -- async reset reg <= x"00";

shft <= x"00";

elsif clk and clk'event then -- define a clock sel <= s0 & s1;

case sel is -- mux function when b"00" => reg <= d0; when b"10" => reg <= d1; when b"01" => reg <= d2; when b"11" => reg <= d3; end case;

if s_1 then -- conditional shift shft <= shft(6 downto 0) & shft (7); else shft <= reg; end if; end if; end process; q <= shft; end behavior; Comments Package Use Clause Entity Sequential Statements Process Statements Architecture

(11)

Library Units

Library units (also known as design units) are the main components of a VHDL description. They consist of the following kinds of declarations: • Package (optional)

• Entity • Architecture

• Configuration (optional)

A design may include any number of package, entity, architecture, and configuration declarations. The relationship of the four types of design units is illustrated in Figure 2-2. Note that only the entity and

architecture design units are required; the package and configuration design units are optional.

Figure 2-2: Relationship of VHDL design units

Package

A package is an optional library unit used for making shared

definitions. An example of something that might be shared is a type definition, as shown in Figure 2-1. When you make definitions in a package, you must use the library and use statements to make the package available to other parts of the VHDL design.

package example_arithmetic is type small_int is range 0 to 7; end example_arithmetic;

(12)

Entity

Entities contain the input and output definitions of the design. In VHDL designs that contain a hierarchy of lower-level circuits, the entity functions very much like a block symbol on a schematic. An entity usually has one or more ports, which are analogous to the pins on a schematic symbol. All information must flow into and out of the entity through the ports, as shown:

library my_lib;

use my_lib.example_arithmetic.all; entity ent is

port (a0,a1,b0,b1 : in small_int; c0,c1 : out small_int); end ent;

Note that this example references the package defined in the previous section to gain access to the type small_int. Each port has a mode that defines a direction: in, out, inout, or buffer.

Modes in, out, and inout all have the obvious meanings. Ports declared to be of type out may not be read. Therefore, the assignment:

c1 <= c0;

would be illegal since c0 is declared to be an out port. Mode buffer is equivalent to mode out except that the value of the port may be read within the entity.

In addition to ports, entities may also contain generics. Generics are similar to ports, except that they pass static information. You can use generics to create two or more instances of an entity where the instances behave in different ways. A common use of generics is in gate-level modeling, where generics pass delay values into the model, as shown:

library my_lib;

use my_lib.example_arithmetic.all; entity ent is

generic (t_rise, t_fall : time := 5 ns);

port (a0,a1,b0,b1 : in small_int; c0,c1 : out small_int); end ent;

The preceding example specifies a rise and fall delay using the pre-defined type time, and gives the delays a default value of 5 ns. Note that if you use generics when writing code for synthesis, all generic parameters must be given default values.

(13)

Architecture

The architecture is the actual description of the design. If you think of an entity as a functional block symbol on a schematic, then an architecture describes what's inside the block. An architecture can contain both concurrent and sequential statements, which are

described below. Note that VHDL allows you to have more than one architecture for the same entity. For example, you might have an architecture for synthesis and a gate-level (netlist) architecture. If you have more than one architecture for an entity, use configuration declarations to determine which architecture to use for synthesis or simulation.

An architecture consists of two pieces: the architecture declaration section and the architecture body. Consider the following example: architecture behavioral of ent is

signal c_internal: small_int; begin

c_internal <= a0 + b0; c0 <= c_internal;

c1 <= c_internal + a1 + b1; end behavioral;

The declaration section of the architecture is the area between the keyword architecture and the keyword begin. Here you may declare objects that are local to the architecture. After the declaration section comes the architecture body, which is where you specify the behavior of the architecture.

Configuration

Configuration declarations may be used to associate particular design entities to component instances (unique references to lower-level components) in a hierarchical design, or to associate a particular architecture to an entity. As their name implies, configuration declarations are used to provide configuration management and project organization for a large design.

(14)

Statements

There are three basic kinds of statements in VHDL: • Declaration Statements

• Concurrent Statements • Sequential Statements

Declaration Statements

Declaration statements are used to define constants (such as literal numbers or strings), types (such as records and arrays), objects (such as signals, variables and components), and subprograms (such as functions and procedures) that will be used in the design. Declarations can be made in many different locations within a VHDL design,

depending on the desired scope of the item being declared.

Concurrent and Sequential Statements

Concurrent and sequential statements are the fundamental building blocks of a VHDL design description. These statements, which represent the actual logic of a design, include such things as signal assignments, component instantiations, and behavioral descriptions. There are important distinctions to be made between concurrent and sequential statements, as discussed below.

Concurrent Statements

Concurrent statements are evaluated independently of the order in which they appear. A concurrent statement is much like a signal assignment used in a PLD programming language such as ABEL-HDL. Signals pass values between concurrent statements, much as wires connect components on a schematic. The “components” being

connected in a VHDL design might be logical elements that have been described using concurrent signal assignments, or they might be instances of lower-level entities.

Concurrent statements define logic (typically in the form of signal assignments that include combinational logic) that is inherently parallel. With concurrent statements, values are carried on signals, which may be the actual input and output ports of the design (defined in an entity statement) or local signals declared using a signal declaration statement.

(15)

Concurrent statements include the following: • Signal assignments (selected and conditional) • Component instantiations

• Generate statements • Process statements

• Procedure and function calls

The following syntax shows an example of an architecture declaration with concurrent statements. Note that this code fragment also

demonstrates how to include comments in VHDL source code. The double-hyphen character sequence (--) always begins a comment, and the comment continues until the end of the line.

architecture dataflow of my_circuit is signal d,e bit;

begin

-- concurrent statements tied together with signals d <= in3 and in4; -- logic for d

e <= in5 or in6; -- logic for e out1 <= in1 xor d; -- output logic out2 <= in2 xor e; -- output logic end dataflow;

Sequential Statements

Sequential statements differ from concurrent VHDL statements in that they are executed in the order they are written. Sequential statements always appear within a process statement (which, in its entirety, is a concurrent statement) or within a function or procedure.

Sequential statements are similar to statements used in software programming languages such as C or Pascal. The term sequential in VHDL refers to the fact that the statements execute in order, rather than to the type of logic generated. That is, you can use sequential statements to describe either combinational or sequential (registered) logic. With sequential statements, values may be carried using either signals or variables.

Sequential statements include the following types of statements: • Variable declarations

• Signal assignments • Variable assignments

• Procedure and function calls

• If, case, loop, next, exit, return statements • Wait statements

Following is an example of an architecture declaration that includes sequential statements in a process statement:

(16)

architecture behavior of some_thing is begin

process begin

wait until clock;

if (accelerator = '1') then case speed is

when stop => speed <= slow; when slow => speed <= medium; when medium => speed <= fast; when fast => speed <= fast; end case;

end if; end process; end behavior;

Note: Sequential statements do not imply, and are not the same as, sequential logic.

Data Objects

Data objects hold values. Languages such as C and Pascal generally have only one type of data object: the variable. In addition to the variable, VHDL has two other types of data objects: constants and signals. VHDL variables work in much the same way as variables in conventional programming languages. From a hardware designer’s perspective, both signals and variables can be thought of as wires interconnected with various logic gates. The differences among VHDL data objects lay in how they may be used and how much information they contain.

Before they can be used, data objects must be declared with a declaration statement, as explained separately for each of the three data types, below. Note that the VHDL synthesis compiler ignores initial values on both signals and variables, since most types of

hardware currently available do not have a guaranteed power-up state. Therefore, when writing VHDL code, it is best not to use initial values unless you know that you are guaranteed a certain power-up state in your target device.

Variables

Like a variable in C or Pascal, a variable in VHDL carries with it only one piece of information: its current value. Variables are assigned a value using the := operator. Consider the following variable

assignments: first_var := 45;

SECOND_VAR := first_var; second_var := 0;

(17)

In these assignments, the variable named first_var is being assigned an integer value of 45 (For more information on data types, including integer, see the next section). A variable named SECOND_VAR is then assigned to whatever value first_var currently contains, which is 45. SECOND_VAR is then assigned the integer value 0. The variables named second_var and SECOND_VAR are the same, since VHDL is not case-sensitive.

Note: In VHDL, names (or identifiers, as they are more properly referred to) must begin with a letter, and may consist of any number of letters, digits, or underscores, as long as there is not more than one underscore in a row. As noted earlier, no distinction is made between upper- and lower-case characters.

Before they can be used, variables must be declared with a variable declaration statement, as in the following example:

variable first_var : integer;

variable second_var, third_var : integer := 0;

A variable declaration begins with the keyword variable, followed by one or more names, the data type, and optionally, an initial value. Variables may be declared only within processes or functions, two constructs that are explained later in this chapter.

Constants

Constants are much like variables, except, as they name implies, their value can never change. Constants are normally employed to make code easier to read and to modify.

Like variables, constants are declared with a declaration statements. An example of a constant declaration is as follows:

constant one_grand : integer := 1000;

Signals

Signals are declared in much the same manner as variables. Signal declarations may include an initial value, which will be ignored by the synthesis compiler. Examples of signal declarations are as follows: signal first_sig : integer;

signal second_sig, third_sig : integer := 5;

Signal assignments are performed using the <= operator, as in the following examples:

first_sig <= 9;

second_sig <= first_sig;

third_sig <= first_sig after 5 ns;

The first clue as to the fundamental difference between signals and variables is found in the assignment to third_sig. The example

specifies that third_sig will take on the value held by first_sig, but with a delay of 5 nanoseconds. This is in essence propagation delay.

(18)

Like initial values, delays specified using the optional after keyword are ignored by the synthesis compiler, since it has no way of

guaranteeing that a particular delay will occur in the target hardware. Therefore, you will not normally use the after clause when writing code for synthesis. However, it is important to realize that even without an after clause, all signal assignments occur with some infinitesimal delay, known as delta delay. Technically, delta delay is of no measurable unit, but from a hardware design perspective you should think of delta delay as being the smallest time unit you could measure, such as a femtosecond.

The effect of delta delay on the simulation behavior of your code can be profound. Consider the following example. Assume that the signal first_sig is assigned the value 11 at time 100 ns:

first_sig <= 11;

first_sig actually changes to its new value 1 fs after time 100 ns. Now consider the next two assignments executed at time 200 ns:

first_sig <= 25;

first_var := first_sig;

If both of these assignments are executed at time 200 ns, first_var immediately takes on the value 11, and 1 fs later first_sig has the value 25.

(19)

Data Types

VHDL supports a variety of data types. The type of a variable, signal, or constant determines the operators that are predefined for that object as well as the range of values that it can take on.

The predefined VHDL data types include: • numeric (integer or real)

• boolean • character

• time (measured in units from fs to hr) • string (an array of characters)

• bit (can have a value of 0 or 1) • bit_vector (an array of bits)

After the language was defined it was acknowledged that the built-in types were not entirely adequate for modeling the behavior of real hardware. The IEEE standard 1164 was developed to address this shortcoming. This standard defines the types:

• std_ulogic and std_logic (the equivalent of bits but with 9 possible data values instead of two)

• std_ulogic_vector and std_logic_vector (an array of std_ulogic and std_logic, respectively)

Definitions for all of the predefined types, with the exception of std_logic and std_logic_vector, are in the file std.vhd, which contains the package standard. The types created by the 1164 standard are defined in the file ieee.vhd. The primary difference between std_ulogic and std_logic is that std_logic is what is referred to as a resolved type. This means that objects of type std_logic can be used for modeling logic with multiple drivers, such as tristate buses or wired logic. Objects of type std_ulogic may have only one driver.

In addition to types, subtypes may be used to define subsets of their base type. For example, a short integer type (one with a specified maximum value) can be defined as a subtype with the statement: subtype short_int is integer range 0 to 255;

VHDL also supports enumerated and user-defined types, which are explained later in this section.

(20)

Numeric Types

The numeric types consist of integer, floating point (real), and physical types. Two encoding schemes are used by the VHDL Synthesizer for numeric types:

• Numeric types and subtypes that contain a negative number in their range definition are encoded as two's complement numbers. • Numeric types and subtypes that contain only positive numbers are

encoded as binary numbers.

The number of wires that are synthesized depends only on the value in the definition that has the largest magnitude. The smallest magnitude is assumed to be zero for numeric types.

Also for synthesis: floating point numbers are constrained to have the same set of possible values as integers, although they can be

represented using floating point format with a positive exponent. Numeric types and subtypes are synthesized as follows:

The declaration: Is synthesized as:

type int0 is range 0 to 100 -- 7 bit binary encoding type int1 is range 10 to 100 -- 7 bit binary encoding type int2 is range -1 to 100 -- 8 bit two's complement type int3 is int2 range 0 to 7 -- 3 bit binary encoding Numeric Operators

If the type of the object to which the result is assigned has more bits than either of the operands, then the result of the numeric operation is automatically sign or zero extended by the VHDL synthesizer.

Sequential encoded types are zero extended, and two's complement numbers are sign extended.

If the type of the object to which the result is assigned has fewer bits than either of the operands, then the result of the numeric operation is truncated. If a numeric operation has a result that is larger than either of the operands then the new size is evaluated before the above rules are applied. For example, if an addition operator "+" generates a carry, the result will be truncated, used, or sign (or zero) extended according to the type of the object to which the result is assigned:

type short is integer 0 to 255;

subtype shorter is short range 0 to 31; subtype shortest is short range 0 to 15; signal op1,op2,res1: shortest;

signal res2: shorter; signal res3: short begin

res1 <= op1 + op2; -- truncate carry res2 <= op1 + op2; -- use carry

res3 <= op1 + op2; -- use carry and zero extend

Note: During simulation, if the result of an arithmetic operation than the size of the specified object, as is the case for signal res1, then the

(21)

The encoding of integers in a binary format means that all ranges are rounded up to the nearest power of two. This means that if shorter had been declared as:

subtype shorter is short range 0 to 16;

then the result would have been the same after synthesis. Objects declared type of type integer without a range constraint will be synthesized into 32 wires.

The are two predefined subtypes of integer. Subtype natural is defined as non-negative integer, while subtype positive is defined as a non-negative and non-zero integer.

Other Types

The types bit, Boolean, character, std_ulogic and std_logic are enumerated types. Enumerated types are discussed in the following subsection. The type bit_vector is an array, as is the type

std_logic_vector.

• Bit , std_logic and std_ulogic types are synthesized to one wire. • Character types are synthesized to seven wires.

• Boolean types are synthesized to one wire.

• Array and record types are composites, and are treated as collections of their elements. Subtypes of composite types are treated as collections of the elements of the subtype only.

Enumerated Types

An enumerated type in VHDL is a special kind of data type that has a symbolic value. A good example of where an enumerated type signal would be used is in a state machine, in which symbolic values are used to represent unique states of the machine:

type machine_state is (Init, Ready, Xmit1, Xmit2, Xmit3, Xmit4); signal present_state, next_state: machine_state;

Many of the common data types used in VHDL, such as bit, Boolean, character, and std_ulogic, are actually enumerated types defined in a library such as std or ieee. Bit, Boolean, and character are all

enumerated types that are predefined in std.vhd.

When synthesized, enumerated types result in a binary encoding, unless the enum_encoding attribute has been used to specify alternate values for each element of the type. In the absence of the enum_encoding attribute, elements in the enumerated type are assigned numeric values from left to right, with the value of the leftmost element being zero.

By default, the number of wires generated to encode an enumerated type will be the smallest possible n, where the number of elements is 2n. (It will, for example, require three wires to represent an

enumerated type with more than four but less than nine different values.)

(22)

The Std_ulogic and Std_logic Data Types

Std_ulogic (which is the base type of the more-commonly used

resolved type std_logic) is a data type defined by IEEE standard 1164, and defined in the file ieee.vhd. Std_ulogic is an enumerated type, and has the following definition (from ieee.vhd):

type std_ulogic is ( 'U', -- Uninitialized 'X', -- Forcing Unknown '0', -- Forcing 0 '1', -- Forcing 1 'Z' -- High Impedance 'W' -- Weak Unknown 'L' -- Weak 0 'H' -- Weak 1 '-' -- Don't care );

The std_ulogic (or std_logic) data type is very important for both simulation and synthesis. Std_logic includes values that allow you to accurately simulate such circuit conditions as unknowns and high-impedance states. For synthesis purposes, the high-high-impedance and don't-care values provide a convenient and easily recognizable way to represent three-state enables and don't-care logic. For synthesis, only the values ‘0’, ‘1’, ‘Z’, and ‘-’ have meaning and are supported. The version of std_logic_1164 defined in the file ieee.vhd includes an enum_encoding attribute that results in each object of type std_ulogic or std_logic being synthesized into a single wire.

User Defined Types and Subtypes

In addition to the standard types, you can define your own types which may be scalars, arrays, or records. VHDL also allows subtypes, which are simply a mechanism to define a subset of a type.

The use of types other than bit and bit_vector (or std_logic and std_logic_vector) can make your design much easier to read. It is good VHDL coding practice to put all your type definitions in a package and make the contents of that package visible with a use statement. The following example shows how a subtype of integer is defined in a package and referenced in the rest of the design:

package type_defs is

subtype very_short is integer range 0 to 3; end type_defs;

use work.type_defs.all; -- use clause entity counter is

port (clk: in Boolean; p: inout very_short); end counter;

(23)

process(clk) begin

if clk and clk'event then p <= p + 1;

end if; end process; end behavior;

In this example, type integer was used because the "+" operator is defined for integers but not for bit_vectors.

The most common user-defined types are enumerated types, described in the previous section.

Types and Logic Synthesis

In VHDL, types are used for type checking and for operator overload resolution (a situation in which two or more operators or functions have the same name, but specify different argument types). For logic synthesis, each type declaration also defines the encoding and number of wires to be generated. For subtypes, checking and overloading use the base type of the subtype. Each subtype declaration defines a subset of its base type and can specify the number or wires (directly or indirectly) and possibly the encoding scheme.

During compilation, ports with types that synthesize to multiple wires are renamed by appending _n_, where n is an incremented integer starting from zero.

Type Conversions

Because VHDL is strongly typed, and not all operations are supported for all standard data types, and it is sometimes necessary to convert from one type to another. A good example of this is the previous example, which used an integer data type to describe a counter. What if the design required (for external interface reasons) that all I/O ports be of type std_logic? Since there is no pre-defined + operator for non-numeric types such as std_logic, it is necessary to either overload the + operator (by writing a new + function for std_logic_vector data types) or convert the type from std_logic_vector to integer, and then from integer back to std_logic_vector as shown below:

library ieee;

use ieee.std_logic_1164.all; entity counter is

port (clk: in std_logic;

p: inout std_logic_vector(1 downto 0); end counter;

library dataio;

use dataio.std_logic_ops.all; architecture behavior of counter is begin

(24)

if clk = '1' and clk'event then

p <= To_Vector(2,To_Integer(p) + 1); end if;

end process; end behavior;

The example shown makes use of the package std_logic_ops in the dataio library provided with the VHDL synthesizer. This library includes commonly-used type conversion functions (such as To_Integer and To_Vector).

Operators

VHDL includes the following kinds of operators: • Logical

• Relational • Arithmetic

Logical Operators

Logical operators, when combined with signals and/or variables, are used to create combinational logic. VHDL provides the following logical operators: and or nand nor xor not

These operators are defined for the types bit , std_ulogic (which is the base type of std_logic) and Boolean, and for one-dimensional arrays of these types (for example, an array of type bit_vector or

std_logic_vector).

Relational Operators

Relational operators are used to create equality or magnitude comparison functions. VHDL provides the following relational operators:

= Equal to /= Not equal to > Greater than < Less than

>= Greater than or equal to <= Less than or equal to

The equality operators ( = and /= ) are defined for all VHDL data types. The magnitude operators ( >=, <=, >, < ) are defined for numeric types, enumerated types, and some arrays. The resulting type for all these operators is Boolean.

(25)

Arithmetic Operators

Arithmetic operators are used to create arithmetic functions. VHDL provides the following arithmetic operators:

+ Addition - Subtraction * Multiplication / Division mod Modulus rem Remainder abs Absolute Value ** Exponentiation

These operators are defined for numeric types such as integer and real.

Note: Using arithmetic operators in a design can result in very large amounts of combinational logic being generated.

Overloading Operators

In addition to the predefined operators, VHDL allows you to create new operators, or to overload existing operators to support alternate types of arguments or to give them new meanings. For example, Synario supplies overloaded functions defining the relational operators listed in the previous section for type bit_vector as part of the package

bit_ops contained in the file \synario\lib5\dataio.vhd. Overloaded relational operators for std_logic_vectors are supplied as part of the package std_logic_ops which is found in the same file. Note that these overloaded operators treat bit_vectors and std_logic_vectors as

unsigned quantities.

VHDL Attributes

VHDL has many predefined attributes that allow access to information about types, arrays, and signals. For a complete list of the supported attributes and their definitions, see Appendix A, “Quick Reference.” Examples of attributes used to modify a type are shown below. In this example, the 'high and 'low attributes are used to determine the highest and lowest values of a type:

integer'high -- has a value of 2147483647 integer'low -- has a value of -2147483647

To declare a subtype of type integer, use the 'high and 'low

attributes to determine the resulting new upper and lower bounds of the type :

subtype shorter is integer range 0 to 100; shorter'high -- has a value of 100 shorter'low -- has a value of 0 Attributes can also be combined, as in:

(26)

When used with an array, the 'high attribute has a value of the highest array index:

type my_array is array (0 to 99) of Boolean; variable info : my_array;

info'high -- has a value of 99

There is a set of attributes that gives access to information about signal waveforms. Most of these signal attributes are for simulation, and have no other meaning. There is one signal attribute, however, that is often used to describe clock logic. You can use 'event on signals to specify edge sensitivity, usually in combination with a value test to specify a rising or falling edge:

signal clock : Boolean;

if not clock and clock'event -- falling edge.

Note: An alternative to using the "clock and clock'event" method of specifying a clock edge is to use the rising_edge() function provided with the IEEE 1164 library.

(27)

3.

How to Write

Synthesizable VHDL

The hardware implementation of a design written in VHDL depends on many factors. Coding conventions, fitter technology, and optimization options are all factors. The general nature of a design also has a large impact on its suitability for synthesis to a particular device,

independent of the method used to describe the design.

Not all designs can be synthesized. Many VHDL designs (which are often referred to as models for simulation) are not suitable for synthesis. These include high level performance models;

environmental models (test benches) for stimulus/response; or system models that include a mixture of software, hardware, and physical aspects. For the purposes of logic synthesis, the VHDL synthesizer must assume that the entire VHDL design describes digital logic that is to be implemented in hardware.

Hardware design — and design for synthesis in particular — adds several additional constraints that must be considered above and beyond the requirements for simulation. One example of this is a gated clock . A gated clock may not be an issue for simulation, since values may be written to a computer’s memory without concern for electrical glitches. When designing for synthesis, however, care must be taken to ensure that the circuit described will actually control the clocking of memory elements in a manner appropriate for the target hardware. A simulation model may also describe the timing characteristics of a design. Timing specifications (such as inertial or transport delays) are ignored by the VHDL synthesizer, and the actual timing behavior of the design depends on the architecture and mapping of the target device. For this reason, a VHDL model that depends on the timing for correct operation may not synthesize to the expected result when moved from one target device to another.

Simulation models may describe unbounded conditions (such as loops that have no termination, or integers that have no range) that are impossible represent in hardware. In some cases (such as infinite loops) the synthesis tool will produce an error and exit, while in other cases (such as unbounded integers) the VHDL synthesizer will assume a default representation (for example, 32 bits), which may or may not result in the expected circuit being generated.

(28)

In addition, a VHDL design written for simulation may use enumerated types to represent the encoding of a group of wires, perhaps as part of a symbolic state machine description. A design may also use

enumerated types to represent the electrical characteristics on a signal wire (such as high impedance, resistive, or strong). In this case, the VHDL synthesizer has no way to distinguish the meaning (in terms of how the values should be represented in hardware) of each circuit. Unless you have provided an encoding for these types (using the VHDL synthesis custom attribute enum_encoding described in this

chapter), the VHDL synthesizer must assume a default encoding for all enumerated types.

Optimization Strategies

Most, but not all, PLDs are constructed with an input logic array (the

and array) and output register macrocells that are fed by an or gate. These devices are optimized for wide sum-of-products logic functions. The macrocells in these devices typically include three-state buffers and one or more possible feedback paths back into the array. Most FPGAs, on the other hand, are constructed with smaller basic logic elements (such as 4- or 5-input lookup tables, or multiplexers). The VHDL synthesizer, and other processes invoked by the Project

Navigator, include a number of options (properties) that can be modified to optimize the design for the target device architecture. In most cases, the default property values (which are set depending on the device you have selected) will result in the most efficient

implementation. If you want to experiment with different optimization properties, refer to the on-line help for information about each of the available properties.

Note: An example of modifying VHDL Synthesis and Design Fitting properties can be found in in the Craps Game example, in the tutorials chapter of the VHDL Entry manual.

Describing Combinational Logic

This section describes the relationship between basic VHDL statements and the resulting synthesized combinational logic. Most of the

operators and statements that are used to describe combinational logic are the same as found in any programming language. As in a

programming language, some operations take more time (path delays) to execute in hardware, and some require more space (in this case, device resources) to implement. Some VHDL operations are more expensive to synthesize into logic than others because they require more gates to implement. This section describes the relative costs associated with various combinational operations, and the kind of circuitry you can expect to get out of synthesis.

(29)

Constants and Types

The context in which an operator is used effects the generated

circuitry. Using constant values or simple one-bit data types results in the most compact circuitry, while complex data types (such as arrays) in an expression result in correspondingly more circuitry.

If one operand of a combinational expression is a constant, then less logic is generated. If both operands are constants, the logic can be collapsed during compilation and the cost of the operation is zero gates. Using constants wherever possible means that the design description will not contain unwanted functionality, will synthesize faster and produce a more efficient implementation.

Certain operators in VHDL are restricted to specific types, generally following the programming language conventions which are given in the following subsections. These subsections describe the following kinds of operators:

• Logical Operators • Relational Operators • Arithmetic Operators

Logical Operators

VHDL provides the following logical operators: and or nand nor xor not

These operators are defined for the types bit and Boolean, and for one-dimensional arrays of these types (for example, an array of type

bit_vector). These operators are also defined for the IEEE 1164

std_logic (or std_ulogic), and std_logic_vector data types (if the

ieee library and std_logic_1164 package are included in your design). The generation of logic from language constructs is

reasonably direct, and results in an implementation in gates as shown in the following two examples.

Example 1:

entity logical_ops_1 is

port (a, b, c, d: in bit; m: out bit); end logical_ops_1;

architecture example of logical_ops_1 is signal e: bit;

(30)

m <= (a and b) or e; --concurrent signal assignments e <= c xor d;

end example; Example 2:

entity logical_ops_2 is

port (a, b: in bit_vector (0 to 3); m: out bit_vector (0 to 3)); end logical_ops_2;

architecture example of logical_ops_2 is begin

m <= a and b; end example;

Figure 3-1 shows how these examples are implemented in logic. In the first example, notice that the logic is shown in a multilevel

implementation. In the logic actually generated, the logic for m will be a large sum-of-products function with the exclusive-or function (signal

e) expanded into and/or logic and preserved (in a multilevel logic structure) or flattened into a larger two-level sum-of-products

representation. The actual form of logic generated will depend on the optimization options chosen in the Project Navigator.

The second example shows how bit_vectors are expanded and processed. The and operation is distributed through the bit_vector data for m, as you would expect.

(31)

Relational Operators

VHDL provides relational operators as shown in Table 3-1. Table 3-1: Relational Operators

Operator Description

= Equal

/= Not equal to

> Greater than

< Less than

>= Greater than or equal to <= Less than or equal to

The equality operators ( = and /= ) are defined for all VHDL data types. The magnitude operators ( >=, <=, >, < ) are defined for numeric types, enumerated types, and some arrays. The resulting single-bit type for all these operators is Boolean. In addition to the built-in relational operators, overloaded versions of these operators are supplied in the packages bit_ops and std_logic_ops (found in the file \synario\lib5\dataio.vhd) for bit_vector and std_logic_vector types. The overloaded operators found in these packages treat bit_vectors and std_logic_vectors as unsigned quantities.

The simple comparisons (equal and not equal) are more efficient to implement (in terms of gates or product terms) than the magnitude operators. To illustrate, the first example below uses an equal operator while the second uses a greater-than-or-equal-to operator. As you can see from the schematic of Figure 3-2, the second example uses more than twice as many gates as the first.

Example 1:

entity relational_ops_1 is

port (a, b: in bit_vector (0 to 3); m: out Boolean); end relational_ops_1;

architecture example of relational_ops_1 is begin

m <= a = b; end example; Example 2:

entity relational_ops_2 is

port (a, b: in integer range 0 to 3; m: out Boolean); end relational_ops_2;

architecture example of relational_ops_2 is begin

m <= a >= b; end example;

(32)

Arithmetic Operators

The arithmetic operators in VHDL are defined for numeric types

(integer and real). The operators are listed in Table 3-2. In addition, overloaded versions of the + and - operators are supplied in the packages bit_ops and std_logic_ops for the types bit_vector and std_logic_vector, respectively.

Note: The VHDL synthesizer does not distinguish between integer and real number values. Floating point values are constrained to the same range of values as integers.

Figure 3-2: Relational Operators

Table 3-2: Arithmetic Operators

Operator Description ++ Addition = Subtraction * Multiplication / Division mod Modulus rem Remainder

abs Absolute Value

** Exponentiation

While the addition and subtraction operators (+, -) are somewhat expensive in terms of gates required, the multiplication operators (*,

/, mod, rem) are extremely expensive. The VHDL synthesizer does make special optimizations, however, when the right hand operator is a constant and an even power of 2.

(33)

The absolute (abs) operator is not expensive to implement. The ** operator is only supported when its arguments are constants. The following example illustrates the logic generated for an addition operation:

package example_arithmetic is type small_int is range 0 to 7; end example_arithmetic;

use work.example_arithmetic.all; entity arithmetic is

port (a, b: in small_int; c: out small_int); end arithmetic;

architecture example of arithmetic is begin

c <= a + b; end example;

Figure 3-3 shows the logic generated for this example in schematic form. Again, this logic may be collapsed into a sum-of-products (2-level) form during processing by the VHDL synthesizer and device fitting.

(34)

Shift Operators

The shift operators in VHDL are defined for the types bit and boolean. In addition, the package std_logic_ops found in the file

\synario\lib5\dataio.vhd supplies overloaded operators for type std_logic_vector. The left-hand argument of these operators must be an array type (such as bit_vector or std_logic_vector) and the right-hand argument must be an integer. The return value is always of the same type as the left-hand argument. The operators are listed in

Table 3-3. Table 3-3: Shift Operators

Operator Description

sll Shift Left Logical srl Shift Right Logical sla Shift Left Arithmetic sra Shift Right Arithmetic rol Rotate Left Logical ror Rotate Right Logical

The shift operators are not expensive to implement if the right operand (which must be an integer type) is a constant value. If the right

operand is not a constant (and depends on a signal) then the logic can be quite expensive to implement.

Describing Conditional Logic

Conditional logic is combinational logic that implements a multiplexer-like function.

The two forms of concurrent statements used to describe conditional logic are:

• Conditional signal assignment • Selected signal assignment

There are also two forms of sequential statements for describing conditional logic:

• If statement • Case statement

(35)

Concurrent Statement: Conditional Signal Assignment

The following is an example of a conditional signal assignment: entity control_stmts is

port (a, b, c: in Boolean; m: out Boolean); end control_stmts;

architecture example of control_stmts is begin

m <= b when a else c; end example;

Note: In IEEE standard 1076-1993, the else clause is optional. If you do not provide an elseclause, however, the resulting circuit will probably include a latch, which may not be the desired result.

Concurrent Statement: Selected Signal Assignment

A selected signal assignment uses the with statement, and must include all possible cases. The others case ensures that all cases are covered.

The following is an example of a selected signal assignment: entity control_stmts is

port (sel: bit_vector (0 to 1); a,b,c,d: bit; m: out bit);

end control_stmts;

architecture example of control_stmts is begin

with sel select

m <= c when b"00", m <= d when b"01", m <= a when b"10", m <= b when others; end example;

If Statement

The condition in an if statement must evaluate to true or false (a Boolean type). The following example illustrates the if statement: entity control_stmts is

port (a, b, c: in Boolean; m: out Boolean); end control_stmts;

architecture example of control_stmts is begin process (a, b, c) variable n: Boolean; begin if a then n := b; else n := c; end if; m <= n;

(36)

end process; end example;

Case Statement

Like the with statement, VHDL requires that all the possible conditions be represented in the condition of a case statement. To ensure this, use the others clause at the end of a case statement to cover any unspecified conditions.

Note: Since std_ulogic and std_logic types have nine possible values (instead of two possible values for bit types), you should always include an others clause when using these types.

The following example illustrates the case statement: entity control_stmts is

port (sel: in bit_vector (0 to 1); a,b,c,d: in bit; m: out bit);

end control_stmts;

architecture example of control_stmts is begin process (sel,a,b,c,d) begin case sel is when b"00" => m <= c; when b"01" => m <= d; when b"10" => m <= a; when others => m <= b; end case; end process; end example;

Schematic representations of the if and case logic generated for these two examples are shown in Figure 3-4.

(37)

Describing Replicated Logic

VHDL provides the following subprograms and looping constructs for creating replicated logic:

• Function • Procedure • Loop Statement • Generate Statement

Functions and procedures are collectively referred to as subprograms. Generate is a concurrent loop statement. These constructs are synthesized to produce logic that is replicated once for each subprogram call, or once for each iteration of a loop.

Functions and Procedures

Functions are always terminated by a return statement, which returns a value. A return statement may also be used in a procedure, where it never returns a value.

The following example illustrates the use of a function: entity func is

port (a: in bit_vector (0 to 2); m: out bit_vector (0 to 2)); end func;

architecture example of func is

function simple (w, x, y: bit) return bit is begin return (w and x) or y; end; begin process (a) begin

m(0) <= simple(a(0), a(1), a(2)); m(1) <= simple(a(2), a(0), a(1)); m(2) <= simple(a(1), a(2), a(0)); end process;

(38)

A procedure differs from a function in that there is no return value, and the arguments of the procedure have modes (in, out, or inout): entity proc is

port (a: in bit_vector (0 to 2); m: out bit_vector (0 to 2)); end proc;

architecture example of subprograms is

procedure simple (w, x, y: in bit; z: out bit) is begin z <= (w and x) or y; end; begin process (a) begin

simple(a(0), a(1), a(2), m(0)); simple(a(2), a(0), a(1), m(1)); simple(a(1), a(2), a(0), m(2)); end process;

end example;

For both functions and procedures, the VHDL synthesizer will generate a block of logic for each instance (unique reference to) the function or procedure.

Loop Statements

If possible, loop ranges should be expressed as constants. Otherwise, the logic inside the loop may be replicated for all the possible values of the loop ranges, which can be very expensive in terms of gates. Loop statements may be terminated with an exit statement, and specific iterations of the loop statement may be terminated with the next

statement.

The following example illustrates the use of a loop statement: entity loop_stmt is

port (a: in bit_vector (0 to 3); m: out bit_vector (0 to 3)); end loop_stmt;

architecture example of loop_stmt is begin

process (a)

variable b:bit; begin

b := 1;

for i in 0 to 3 loop -- no need to declare i b := a(3-i) and b;

m(i) <= b; end loop; end process; end example;

(39)

While statements are also supported by the VHDL synthesizer, with the constraint that the loop termination depend only on a value that can be determined at the time of synthesis (for example, a metalogic value. See Appendix B, “Limitations,” for more information about metalogic values).

The following example demonstrates the use of a while loop: entity while_stmt is

port (a: in bit_vector (0 to 3); m: out bit_vector (0 to 3)); end while_stmt;

architecture example of while_stmt is begin process (a) variable b: bit; variable i: integer; begin i := 0; while i < 4 loop b := a(3-i) and b; m(i) <= b; end loop; end process; end example;

Unconstrained loops (such "while true" loops) are not supported in synthesis.

Example schematics for the loop and subprogram are shown in Figure 3-5.

Generate Statements

Generate statements are used to replicate one or more concurrent statement. The generate statement has two forms: for and if.

For Generation Statement

Following is an example of a for generation statement: Gen1: for i in 0 to 3 generate

SM: mod1 port map(A(i),B(i),Y(i)); end generate Gen1;

When processed, this statement expands into four statements as follows:

SM(0): mod1 port map(A(0),B(0),Y(0)); SM(1): mod1 port map(A(1),B(1),Y(1)); SM(2): mod1 port map(A(2),B(2),Y(2)); SM(3): mod1 port map(A(3),B(3),Y(3));

If Generation Statement

The if generation statement is used to describe a conditional selection of concurrent statements:

(40)

Figure 3-5: Loop and Subprogram Statements

Gen2: if test_flag = 1 generate test_pins <= current_state; end generate Gen2;

When an if generation statement is used, the conditional expression (in this case "test_flag = 1") must be a metalogic value (one that does not depend on a signal or variable.) For example, the value of i, used in the previous for generation statement, is a static value and can be used in a nested if generation statement, as follows:

for i in 0 to 3 generate if i /= 2 generate

SM: modl port map A(i),B(i),Y(i); end generate;

(41)

Describing Sequential Logic

This section describes in detail how various kinds of registered sequential circuits can be described using VHDL, and how these descriptions are synthesized into actual circuitry (using latches and flip-flops).

Describing sequential logic in VHDL is very much like programming in a conventional programming language, and less like programming using a traditional PLD programming language. There is no register assignment operator and no special attributes or “dot extensions” for specifying clocks and resets. In VHDL, you must describe the behavior of a sequential logic element such as a latch or flip-flop, as well as specifying the behavior of more complex sequential machines.

The behavior of a sequential logic element (latch or flip-flop) is to save a value of a signal over time. This section shows how such behavior may be described. This description is extended to add the behavior of set and reset (in both their synchronous and asynchronous forms). There are often several ways to describe a particular behavior, and the following examples typically show only two of the many possible styles. There is no “right” style, however. Your choice of style should simply be that which helps you specify the clearest description of your design.

Note: If you deviate from commonly-used VHDL coding conventions (styles) such as those described in this manual, then you may risk creating designs that are not portable to other synthesis tools. There are two commonly-used methods used to describe registered behavior: conditional (if-then) specifications and wait statements.

Conditional Specification

Describing sequential logic with a conditional specification relies on the inherent behavior of a VHDL if statement. The convention used for conditional statements that describe clocking logic is:

process (clk) begin

if clk='1' then y <= a; else

-- default: holds previous value end if;

end process;

This set of statements describes the behavior of a latch; if the clock is high the output (y) gets a new value. If the clock is not high then the output retains its previous value. This is unlike a PLD programming language such as ABEL-HDL, where the else condition results in the signal going to zero. If both conditions had been written as

(42)

process(clk) begin if clk='1' then y <= a; else y <= b; end if; end process;

Note: This example would result in an error during synthesis; because the conditional logic is completely specified using an else statement, the process describes a combinational function. The signals aand b are both inputs to the combinational function, and are therefore required to be in the sensitivity list.

This convention can be summarized: if an if statement is not completely specified, then a flip-flop or latch primitive is implied. Incompletely specified assignments within case statements can also result in latches being generated, but these latches are constructed using combinational feedback rather than latch primitives. If the if

statement is completely specified (using an else clause), a

combinational function is implied. There is no significance to any of the signal names used in these or any other examples. The clock input (in this case clk) can have any name. Implied flip-flops and latches can occur on either signals or variables.

(43)

Alternatively, you can describe a latch as transparent low by inverting the conditional logic:

process(clk) begin if clk='1' then -- hold else y <= a; end if; end process; Or more concisely: process(clk) begin if clk='0' then y <= a; end if; end process;

A rising edge flip-flop is created by making the clock input edge sensitive:

process(clk) begin

if clk'event and clk='1' then y <= a;

end if; end process;

If you are using the IEEE 1164 std_logic (or std_ulogic) data types, you can simplify the description of clock edges (and improve the accuracy of simulations) by using the rising_edge() function:

(44)

process(clk) begin if rising_edge(clk) then y <= a; end if; end process;

In all these cases, the number of registers or the width of the mux are determined by the type of the signal y.

Wait Statement

The second method uses a wait statement within the process: process

wait until expression; .

. .

end process;

This statement suspends evaluation (over time) until an event occurs, and the expression evaluates to true. When a wait statement is used in a process, no process sensitivity list is required (or allowed). A flip-flip may be described as:

process

wait until clk'event and clk='1' y <= a;

end process;

A constraint of the VHDL synthesizer is that wait statements must be located at either the beginning or end of a process, and there may not be more than one wait statement in a process.

Note: Wait statements are not recommended for use in synthesizable designs. If-then conditional statements are a more universally

(45)

Latches

The following three examples each describe a level sensitive latch with an and function connected to its input. In all three of these examples the signal y retains its current value unless the clock input (clk) is

high. Example 1:

This example uses a process statement and conditional (if)

statement. The sensitivity list contains the clock input and two data inputs because when clk is high the output y changes asynchronously with any change in a or b:

process (clk,a,b) begin if clk='1' then y <= a and b; end if; end process; Example 2:

This example uses a procedure statement in combination with a concurrent procedure call. In this example the procedure is called twice to generate two latches from the declared procedure:

architecture dataflow of latch is

procedure my_latch(signal clk,a,b: in Boolean; signal y : out Boolean)

begin if clk='1' then y <= a and b; end if; end; begin

latch_1: my_latch (clock,input1,input2,outputA); label_2: my_latch (clock,input1,input2,outputB); end dataflow;

Example 3:

This example uses a concurrent conditional assignment to describe a latch function for y. Note that y is used as an input to the conditional statement as well as being used as the output:

architecture dataflow of latch is begin

y <= a and b when clk else y; end dataflow;

Flip-flops

The following four examples describe an edge sensitive flip-flop with an AND function connected to its input. In all these cases the signal y

(46)

Example 1:

A process statement for a flip-flop is identical to the first latch example, above, with addition of the 'event attribute to specify an edge. The sensitivity list for the process contains only the clock input, since the output of a flip-flop only changes when the clock transitions from low to high:

process (clk) begin

if clk='1' and clk'event then y <= a and b;

end if;

end process; -- A Process statement : Example 2:

This example shows how to use a wait statement to describe a flip-flop. When a wait statement is used, there is no sensitivity list

associated with the process statement. To accurately describe an edge triggered flip-flop on the output, the wait statement must be the first statement in the process:

process begin

wait until clk'event and clk='1'; -- rising edge y <= a and b;

end process;

Example 3:

This example uses a procedure declaration, and is identical to the second latch example, above. The only difference is the addition of the

'event attribute to define the clock as an edge triggered signal: architecture dataflow of flipflop is

procedure my_ff(signal clk,a,b: Boolean; signal y : out Boolean)

begin

if clk='1' and clk'event then y <= a and b; end if; end; begin ff_1: my_ff (clock,input1,input2,outputA); ff_2: my_ff (clock,input1,input2,outputB); end dataflow; Example 4:

This example shows how to use a concurrent conditional assignment to describe the flip-flop:

architecture concurrent of my_register is begin

y <= a and b when clk='1' and clk'event; end concurrent;

(47)

Note: In examples 1, 3 and 4, above, the clk and clk'event condition expression can be replaced with the IEEE 1164

rising_edge() function, if std_logic (or std_ulogic) is used for the Clk signal. Using rising_edge() can improve the accuracy of

simulations, particularly in cases where you are simulating transitions from uninitialized states.

Note: The concurrent conditional assignment shown in example 4 is allowed in the 1076-1993 VHDL specification, and is not supported in earlier versions of the language.

Gated Clocks and Clock Enable

The examples in this chapter have assumed that the clock is a simple signal. In principle, any complex Boolean expression could be used to specify clocking. The use of a complex clock expression implies a gated clock.

As with any kind of hardware design, there is a risk that gated clocks may cause glitches in the register clock, and hence produce unreliable hardware. You need to be aware of the constraints of the target hardware and, as a general rule, use only simple logic in the wait or

if-then expression.

It is possible to specify a gated clock with a statement such as: if clk='1' and clk1'event and ena then

q <= d; end if;

which implies a logical and in the clock line. If you want to use a clock enable feature in the target device, however, you should use nested if

statements as follows:

if clk='1' and clk1'event then if ena then

q <= d; end if; end if;

This style causes a clock enable feature to be specified in the target architecture if the Generate Clock Enable property of the Synthesize VHDL process is speci

References

Related documents

Most companies recruit for full-time and internship positions, but some indicate Co-Op as a recruiting priority, while not attending Professional Practice

The UNO Assessment Committee is responsible for guiding the process of campus-wide academic assessment of student learning, and to that end it conducts regular reviews of

 Reflections  on  aesthetic

Customer to pay any amount within ten (10) days after the amount is due and payable, b) abuse of the System or the equipment, c) dissolution, termination, discontinuance,

The Department of Health, Physical Education, Recreation and Dance offers a Master of Science in Education in Health and Physical Education and a Master of Science in

• CAIR Research pilot using community based participatory principles to document stories of resilience among urban American Indian elders at the Tucson Indian Center. •

Although total labor earnings increase with the unskilled unions’ bargaining power, we can say nothing when the increase in production is due to stronger skilled unions, since

The unit I teach, the site of this research, involves students exercising self- determination in a collaborative, creative mode; a phenomenon Meill and Littleton (2004:18) describe