VHDL Presentation
VHDL Presentation
VHDL Presentation
P L A N O F
T H E T A L K
Module I Introduction to VHDL Module II Modeling Digital Systems Module III Basic Language Concepts Module IV Modeling Delays Module V Dataflow Style of Modeling Module VI Behavioral Style of Modeling Module VII Structural Style of Modeling Module VIII Subprograms Module IX Advanced Concepts Module X Orcad Simulation
Module I
Introduction to VHDL
What is VHDL?
VHSIC Very High Speed Integrated Circuit
H Hardware
D Description L Language
Interoperability: models at multiple levels of abstraction Technology independence: portable model Design re-use and rapid prototyping
The word 'hardware', is used in a wide variety of contexts which range from complete systems like personal computers on one side to the small logical gates on their internal integrated circuits on the other side. This is why different descriptions exist for the hardware functionality. Complex systems are often described by the behavior that is observable from the outside. Abstract behavioral models are used in this case that hide all the implementation details. The description of a basic logic gate, on the other hand, may consist of only one Boolean equation, which is a very short and precise description.
H I S T O R Y
O F
V H D L
Designed by IBM, Texas Instruments, & Intermetrics as part of the DoD funded VHSIC program. Standardized by IEEE in 1987: IEEE 1076-1987 Enhanced version of the language defined in 1993: IEEE 1076-1993 Additional standardized packages provide definitions of data types & expressions of timing data IEEE 1164 (data types) IEEE 1076.3 (numeric) IEEE 1076.4 (timing)
Design Simulation
verify system/subsystem/chip performance prior to design implementation
Design Synthesis
automated generation of a hardware design
Module II
Modeling Digital Systems
Systems Hierarchy
Abstraction
Abstraction is hiding of details Differentiation between essential and nonessential information Creation of abstraction levels On every abstraction level only the essential information is considered, nonessential information is left out Equability of the abstraction All information of a model on one abstraction level contains the same degree of abstraction
Design is represented as a net list with logic gates (AND, OR, NOT, ...) and storage elements Design is divided into combinational logic and storage elements Synthesizable Description
Different cells of the target technology are placed on the chip Connections are routed. After the layout has been verified, the circuit is ready for the production process
Computation of events takes place at specific points in time Need to wait for an event (in this case the clock) Timing is an attribute of both synchronous and asynchronous systems
Example
Asynchronous communication No global clock Still need to wait for events on specific signals
Hardware description languages must provide constructs for naturally describing these attributes of a specific design
simulators use such descriptions for mimicking the physical system synthesis compilers use such descriptions for synthesizing manufacturable hardware specifications that conform to this description
Module III
Basic Language Concepts
Design Units
Primary design units Entity Configuration Package Declaration These are not dependent on other design units
What aspects of a digital system do we want to describe? Interface: how do we connect to it Function: what does it do?
The interface is a collection of ports Ports have a type Ports have a mode
Port Modes
Indicates the driver direction
Types of modes:
IN OUT INOUT BUFFER
Mode in
Mode out
Mode inout
Mode buffer
Bottom Line
Implementation of the design Always connected with a specific entity One entity can have several architectures Entity ports are available as signals within the architecture Contains concurrent statements
Identifiers
There are two kinds of identifiers in VHDL: 1. Basic Identifiers 2. Extended Identifiers
Basic/Normal Identifiers
Extended Identifiers
These have a specific meaning in the language, and therefore, cannot be used as basic identifiers
Data Objects
A data object, holds a value or a sequence of values of a certain specified type. Every data object, belongs to one of the following four classes : 1. 2. 3. 4. Constants Variables Signals File
Constants
An object of a constant class, can hold a single value of a given type. This value is assigned to the constant before simulation starts, and the value cannot be changed during the course of the simulation. For a constant declared within a subprogram, the value is assigned to the constant every time the subprogram is called.
Deferred Constants
Example
constant NO_OF_INPUTS : INTEGER;
The value of the constant has not been specified in this case. Such a constant is called a DEFERRED CONSTANT, and it can appear only
Variables
An object of variable class can hold a single value of a given type. However, in this case, different values can be assigned to the variable at different times, using a variable assignment operator := It can optionally be assigned initial values (done only once prior to simulation). variable symbol: type [:= initial_value]; If no initial value is specified for a variable object, a default value is used as an initial value. The default value is TLEFT, where T is the object type, and LEFT is a predefined attribute of a type, that gives the leftmost value in the set of values belonging to type T.
Variables Cont..
Signals
An object belonging to the signal class, holds a list of values, which includes the current value of the signal, and a set of possible future values, that are to appear on the signal. Future values can be assigned to the signal using a signal assignment statement.
Examples:
File
An object belonging to the file class, contains a sequence of values. Values can be read or written to the file using read procedures and write procedures respectively.
Data Types
Every data object in VHDl, can hold a value, that belongs to a set of values. This set of values is specified by using a TYPE DECLARATION. A TYPE is a name, that has associated with it, a set of values and a set of operations. Certain types, and operations that can be performed on these objects are predefined in the language. The declarations for the predefined types of the language are contained in package STANDARD. The language also provides facility to define user customized data types, and the operations that can be performed on those data typed objects, as and when needed. The data types can be classified as: 1. Scalar Types 2. Composite Types 3. Access Types 4. File Types 5. Incomplete Types
SCALAR TYPES
Scalar types represents a single numeric value, or an enumeration value. Values belonging to these types, appear in sequential order. Every value has a position number associated with it. This number is the position of the value in the ordered list of values belonging to that type. The scalar types can broadly be classified under the following four categories: 1. 2. 3. 4. Enumeration Type Integer Type Physical Type Real (Floating Point) Type
Enumeration Types
An enumeration type declaration, defines two categories: 1. User Defined Enumeration Types 2. Predefined Enumeration Types User defined data types are frequently used to enhance readability when dealing with so called state machines, i.e. modules that behave differently, depending on the state of internal storage elements.
Instead of fixed bit patterns, the symbolic names of the data type values are used which will be mapped to a bit level representation automatically during synthesis. These enhances readability in the code.
1. 2. 3. 4. 5. 6. 7.
CHARACTER Type
It constitutes the 191 characters of the IS eight-bit coded character set. These values are called character literals, and are always written between two single quotes ( ).
Examples
A - 3 variable VAL: character :=$;
SEVERITY_LEVEL Type
It has the values:
NOTE, WARNING, ERROR and FAILURE. It is typically used in assertion statements.
Std_ulogic Type
It is recommended to use the multi-valued logic system from the IEEE instead of the standard 'bit' data type. The new type is called 'std_ulogic' and is defined in the package 'std_logic_1164' which is placed in the library IEEE (i.e. it is included by the following statement: 'use IEEE.std_logic_1164.all'
Floating point literals are values of a floating point type. Example : 16.26, 0.6, 0.002 These differ from integer literals by the presence of the dot (.) character. Thus, 0 is an integer literal, while 0.0 is a floating point literal. These can also be expressed in an exponential form. Example : 62.3E-2 (E represents power of 10, and value must be an integer) It provides at least six decimal digits of precision.
Array Types
Arrays are a collection of a number of values of a single data type. type ADDRESS_WORD is array (0 to 63) of BIT;
Elements of an array can be accessed by specifying the index values into the array. E.g. signal ADDRESS_BUS : ADDRESS_WORD; ADDRESS_BUS(26) refers to the 27th element of ADDRESS_BUS array object.
An object X(5,2) declared of multi type, refers to the value of the element at the 2nd column and 5th row of 2-d object. Also, it can be in the form of array of an array. The index set can be of any type.
Unconstrained Array
The array types can be unconstrained also. In this case, the number of elements in the array is not specified in the type declaration, instead, an object declaration for an object of that type declares the number of elements of the array. The <> symbol is called BOX. type STACK_TYPE is array (INTEGER range <>) of ADDRESS_WORD; subtype STACK is STACK_TYPE (0 to 63); subtype STACK_ONE is STACK_TYPE (0 to 5); There are two predefined one-dimensional unconstrained array types in the language: 1. STRING (array of characters) (string literals are enclosed within double quotes) 2. BIT_VECTOR (array of bits)
variable MESSAGE : STRING (1 to 17) := Hello, VHDL world; VHDL does not allows a type, that is an unconstrained array of an unconstrained array.
Examples
signal RASTER_LINE : STD_LOGIC_VECTOR (0 to 8);
Assignment to an Array
The language allows an array object to be assigned to another array object of the same type using a signal assignment statement. The assignment can be made to an entire array, or to an element of an array, or to a slice of an array. Examples variable OP_CODES : BIT_VECTOR (1 to 5); OP_CODES := 01001; -- A string literal is assigned OP_CODES := (0,1,0,0,1); -- Positional association is used OP_CODES := (2=>1,5=>1,others =>0); -- Named Association OP_CODES := (others => 0); OP_CODES(4) := 1; -- Assign to an element of an array DECODER_VALUE := DECODER; -- An entire array is assigned ADDRESS_BUS(1 to 3) <= XFF; -- Assign to a slice of an array An AGGREGATE is a set of comma separated elements, enclosed within parenthesis.
Record Types
It represents a collection of values, that may belong to different types. An object of a record type is composed of elements of same or different types. Three choices exist for value assignments: Assign one record to another (' STUDENT_2 <= STUDENT_1 '). This does not allow to set individual values, however. Aggregates are commonly used for this purpose, i.e. the different element values are grouped together (e.g. ' TODAY <= (26, JUL, 1988) '). The single elements are addressed via RECORD.ELEMENT constructs
Access Types
Values belonging to an access type are pointers to a dynamically allocated object of some other type. These are similar to pointers in Pascal and C languages. type PTR is access MODULE; type FIFO is array (0 to 63, 0 to 7) of bit; type FIFO_PTR is access FIFO; PTR is an access type, whose values are addresses, that points to objects of type MODULE. Only variables can be an access type; that is, it is not permissible for a signal to be utilized as an access type. Every access type may also have the value null, which means that, it does not point to any object, i.e. null is the default value unless otherwise specified)
Incomplete Types
It is possible to have an access type, that points to an object, which has elements, that are also access types. This can lead to mutually dependent or recursive access types. Since a type must be declared before it is used, this can be done using the incomplete types. type type_name; Once an incomplete type has been declared, the type_name can now be used in any mutually dependent or recursive access type. However, a corresponding full type declaration, must follow later. type COMP; type COMP_PTR is access COMP; Full Type Declarations: type COMP is record COMP_NAME : STRING(1 to 10); end record;
File Types
Objects of file types, represent files in the host environment. They provide a mechanism, by which, a VHDL design, communicates with the host environment. type file-type-name is file of type_name; The type name is the type of values contained in the file.
Attributes
Data can be obtained about VHDL objects such as types, arrays and signals. object attribute Example: consider the implementation of a signal
What types of information about this signal are useful? Occurrence of an event Elapsed time since last event Previous value, i.e., prior to the last event
Classes of Attributes
Value attributes Returns a constant value Function attributes Invokes a function that returns a value Signal attributes Creates a new signal Type Attributes Supports queries about the type of VHDL objects Range attributes Returns a range
Value Attributes
clk_process: process begin wait until (clkevent and clk = 1); if reset = 1 then state <= statetypeleft; Returns a constant value else state <= next_state; type statetype is (state0, state1, state2 state3); end if; end process clk_process; state_typeleft = state0 state_typeright = state3
Function Attributes
Use of attributes invokes a function call which returns a value
type mem_array is array(0 to 7) of bit_vector(31 downto 0) mem_arrayleft = 0 mem_arrayright = 7 mem_arraylength = 8 (value kind attribute)
Range Attributes
Signal Attributes
Creates a new implicit signal
Aliases
Type Conversions
Since VHDL is a strongly typed language one cannot assign a value of one data type to a signal of a different data type. In general, it is preferred to the same data types for the signals in a design, such as std_logic (instead of a mix of std_logic and bit types). Sometimes one cannot avoid using different types. To allow assigning data between objects of different types, one needs to convert one type to the other. Fortunately there are functions available in several packages in the ieee library, such as the std_logic_1164 and the std_logic_arith packages. As an example, the std_logic_1164 package allows the following conversions:
Type Conversions
The IEEE std_logic_unsigned and the IEEE std_logic_arith packages allow additional conversions such as from an integer to std_logic_vector and vice versa. The expression A and B which is of the type bit_vector has to be converted to the type std_logic_vector to be of the same type as the output signal out4. type_name (expression);
In order for the conversion to be legal, the expression must return a type that can be converted into the type type_name. Here are the conditions that must be fulfilled for the conversion to be possible 1. Type conversions between integer types or between similar array types are possible 2. Conversion between array types is possible if they have the same length and if they have identical element types or convertible element types. 3. Enumerated types cannot be converted.
Operators
P R E C E D E N C E
Operators in the same category, have the same precedence, and evaluation is done from left to right. Parenthesis may be used to override the left to right evaluation.
Logical Operators
The logic operators (and, or, nand, nor, xor and xnor) are defined for the bit, Boolean, std_logic and std_ulogic types and their vectors. They are used to define Boolean logic expression or to perform bit-per-bit operations on arrays of bits. They give a result of the same type as the operand (Bit or Boolean). These operators can be applied to signals, variables and constants. Notice that the nand and nor operators are not associative. One should use parentheses in a sequence of nand or nor operators to prevent a syntax error:
X nand Y nand Z will give a syntax error and should be written as (X nand Y) nand Z
Relational Operators
The relational operators test the relative values of two scalar types and give as result a Boolean output of TRUE or FALSE.
For discrete array types, the comparison is done on an element-per-element basis, starting from the left towards the right.
Examples
Shift Operators
These operators perform a bit-wise shift or rotate operation on a one-dimensional array of elements of the type bit (or std_logic) or Boolean.
Example
The operand is on the left of the operator and the number (integer) of shifts is on the right side of the operator. As an example, variable NUM1:bit_vector := 10010110; NUM1 srl 2; will result in the number 00100101. When a negative integer is given, the opposite action occurs, i.e. a shift to the left will be a shift to the right. As an example NUM1 srl 2 would be equivalent to NUM1 sll 2 and give the result 01011000.
Addition Operators
The addition operators are used to perform arithmetic operation (addition and subtraction) on operands of any numeric type. The concatenation (&) operator is used to concatenate two vectors together to make a longer one. In order to use these operators one has to specify the ieee.std_logic_unsigned.all or std_logic_arith package in addition to the ieee.std_logic_1164 package.
Example
An example of concatenation is the grouping of signals into a single bus [4]. signal MYBUS :std_logic_vector (15 downto 0); signal STATUS :std_logic_vector (2 downto 0); signal RW, CS1, CS2 :std_logic; signal MDATA :std_logic_vector ( 0 to 9); MYBUS <= STATUS & RW & CS1 & SC2 & MDATA; MYARRAY (15 downto 0) <= 1111_1111 & MDATA (2 to 9); NEWWORD <= VHDL & 93;
Unary Operators
The unary operators + and - are used to specify the sign of a numeric type.
Multiplying Operators
The multiplying operators are used to perform mathematical functions on numeric types (integer or floating point).
Multiplication Operator
The multiplication operator is also defined when one of the operands is a physical type and the other an integer or real type. The remainder (rem) and modulus (mod) are defined as follows:
The result of the rem operator has the sign of its first operand while the result of the mod operators has the sign of the second operand.
Miscellaneous Operators
These are the absolute value and exponentiation operators that can be applied to numeric types. The logical negation (not) results in the inverse polarity but the same type.
Module IV
Modelling Delays
Summary
Primary unit of abstraction is a design entity Design units include Primary design units entity, configuration, package declaration Secondary design units architecture, package body Concurrent signal assignment statements Simple, selected, conditional Can be coalesced to form models of combinational circuits
Module V
Dataflow Style of Modelling
Design Description
A design is described using one or more concurrent statements in an architecture body (all statements within an architecture are executed concurrently) The execution of a concurrent statement is based on events on signals in its input list, i.e. ,at the same time. The order of concurrent statement within an architecture body is not important. Each concurrent statement will synthesize to a block of logic. The following concurrent statements are available in VHDL: Concurrent Signal Assignment Statement Concurrent Procedure Call Statement Concurrent Assertion Statement Component Instantiation Statement Generate Statement Process Statement Block Statement
Implementation of Signals
Driver is set of future signal values: current signal value is provided by the transaction at the head of the list We can specify multiple waveform elements in a single assignment statement by specifying multiple future values for a signal
Multiple waveform elements can be specified in a single signal assignment statement Describe the signal transitions at future point in time Each transition is specified as a waveform element
Implementation of Signals
The basic structure of a signal assignment statement signal <= (value expression after time expression) RHS is referred to as a waveform element Every signal has associated with it a driver
Holds the current and future values of the signal a projected waveform Signal assignment statements modify the driver of a signal Value of a signal is the value at the head of the driver
Shared Signals
Resolved Signals
Physical operation If any of the control signals activate the switch, the output signal is pulled low
VHDL model If any of the drivers attempt to drive the signal low (value at the head of the driver), the resolution functions returns a value of 0 Resolution function is invoked when any driver attempts to drive the output signal
Pair wise resolution of signal values from multiple drivers Resolution operation must be associative
Example
Multiple components driving a shared error signal Signal value is the logical OR of the driver values
A Complete Example
Use of unconstrained arrays This is why the resolution function must be associative!
Unaffected Value
It is possible to assign a value of UNAFFECTED to a signal in a concurrent signal assignment statement. Such an assignment causes no change to the driver for the target signal; i.e. the target driver retains its previous/old value.
BLOCK Statement
It can be used for three major purposes: 1. To disable signal drivers by using guards. 2. To limit the scope of declarations, including signal declarations. 3. To represent a portion of the design (modularity) Syntax: Block_label:block [(guard_expression)][is] [block_header] [block declarations] begin concurrent statements end block [Block_label];
The block_header if present, describes the interface of the block statement to its environment. Any declarations appearing within the block are visible only within the block.
An assertion statement is a concurrent statement, by virtue of its place of appearance within the model. If it appears inside a process, it is a sequential assertion statement, and if it appears outside a process, it is a concurrent assertion statement. Whenever an event occurs on a signal in the boolean expression of the assertion statement, the statement is executed.
Example entity sr is port (s,r:in std_lgic;q,notq:out std_logic); end sr; architecture sr_assert of sr is begin assert not (s=0 and r=0); report Not valid inputs severity error; end sr_assert;
Module VI
Behavioral Style of Modelling
PROCESS Statement
It is a concurrent statement, which contains sequential statements, that describe the functionality of a portion of an entity in sequential terms. Syntax [process label]: process [(sensitivity list)][is] [process item declarations] begin sequential statements; end process [process label]; A set of signals to which, the process is sensitive, is defined by the SENSITIVITY LIST, i.e.; each time an event occurs on any of the signals in the sensitivity list, the sequential statements within the process are executed in a sequential order. The process then suspends after executing the last sequential statement, and waits for another event to occur on a signal in the sensitivity list.
WAIT Statement
A process may be suspended by means of a sensitivity list, i.e.; when a process has a sensitivity list, it always suspends after executing the last sequential statement in the process. WAIT Statement provides an ALTERNATE way to suspend the execution of a process. There are three basic forms of wait statement: 1. wait on sensitivity list; 2. wait until boolean_expression; 3. wait for time_expression; Wait on sensitivity list until boolean_expression for time_expression; [ label: ] wait [ sensitivity clause ] [ condition clause ] ;
wait for 10 ns; -- timeout clause, specific time delay. wait until clk='1'; -- condition clause, Boolean condition wait until A>B and S1 or S2; -- condition clause, Boolean condition wait on sig1, sig2; -- sensitivity clause, any event on any
IF Statement
It selects a sequence of statements for execution, based on the value of a condition. The condition can be any expression, that evaluates to a Boolean value.
IF Statement Cont..
It is executed by checking each condition sequentially, until the first true condition is found; then the set of sequential statements associated with this condition is executed. The if statement can have zero or more elsif clauses, and an optional else clause.
CASE Statement
It selects one of the branches for execution based on the value of the expression. Choices may be expressed as: a) single values b) Range of values c) Using others clause
All possible values of the expression must be covered in the case statement exactly once. The others clause can be used as a choice to cover the catch all values, and, if present, must be the last branch in the case statement.
NULL Statement
It is a sequential statement, that does not cause any action to take place. Execution continues with the next statement. It is useful in an if statement or in a case statement, where, for certain conditions, it may be useful or necessary to explicitly specify that no action is to be performed.
Example: process begin If STROBE =0 then MARK_DET <= BKDET after 5ns; else null; end if; wait o STROBE,BKDET;
LOOP Statement
It is used to iterate through a set of sequential statements. [loop label:] iteration scheme loop sequential statements end loop [loop label]; There are three types of iteration schemes: 1. FOR Iteration Scheme 2. WHILE Iteration Scheme 3. No Iteration Scheme All kind of schemes may have exit and next statements. Loops operate in the usual way, i.e. they are used to execute the same some VHDL code a couple of times. Loop labels may be used to enhance readability, especially when loops are nested or the code block executed within the loop is rather long. The loop variable is the only object in VHDL which is implicitly defined. The loop variable can not be declared externally and is only visible within the loop.
No Iteration Scheme
In this, all statements in the loop body are repeatedly executed, until some other action causes the loop to exit. This can be achieved by using an exit statement, a next statement, or a return statement.
SUM:=1;J:=0; L2: loop J:=J+2; SUM:=SUM*10; exit when SUM > 100; end loop L2;
EXIT Statement
It is a sequential statement, that can be used only inside a loop. It causes execution to jump out of the innermost loop, or the loop whose label is specified. If no loop label is specified, the innermost loop is exited. If the when clause is used, the specified loop is exited only if, the given condition is true; otherwise, execution continues with the next statement. [ label: ] exit [ label2 ] [ when condition ] ; loop wait on A,B; exit when A=B; end loop;
NEXT Statement
It is a sequential statement, that can be used only inside a loop. It results in skipping the remaining statements in the current iteration of the specified loop; execution resumes with the first statement in the next iteration of this loop, if one exists. If n loop label is specified, the innermost loop is assumed.
[ label: ] next [ label2 ] [ when condition ] ; next; next outer_loop; next when A>B; next this_loop when C=D or done; -- done is a Boolean variable
Assertion Statement
These are useful in modeling constraints of an entity.
Report Statement
It can be used to display a message. It is similar to the assertion statement, but without the assertion check. When a report statement is executed, it causes the specified string to be printed and the severity level to be reported to the simulator for proper action.
Return Statement
Causes the subprogram, that contains the return statement to terminate.
Multiple Processes
Since a process statement is a concurrent statement, it is possible to have more than one process within an architecture body. Processes within an architecture body communicate with each other using signals that are visible to all the processes. Variables declared within a process, cannot be used to pass information between processes, because their scope is limited to be within a process. Shared variables, however, could be used.
Module VII
Structural Style of Modelling
THE COMPONENT INSTANTIATION STATEMENT IS THE PRIMARY MECHANISM USED FOR DESCRIBING SUCH A MODEL OF AN ENTITY.
The component instantiation statements are concurrent statements, and their order of appearance in the architecture body is therefore not important. A component can, in general, be instantiated any number of times. However, each instantiation must have a unique component label. A purely structural architecture does not describe any functionality and contains just a list of components, their instantiation and the definition of their interconnections.
Component Declaration
A component instantiated in a structural description must first be declared using a component declaration, in the declaration part of the architecture body. A component declaration declares the name and the interface of a component. The interface specifies the mode and the type of ports. component component_name [is] [port (list of interface ports);] end component [component_name]; The component_name may or may not refer to the name of an entity already existing in a library. If it does not, it must be explicitly bound to an entity; otherwise, the model cannot be simulated. The binding information can be specified using a configuration.
Component Instantiation
A component instantiation statement defines a subcomponent of the entity in which it appears. It associates the signals in the entity with the ports of that subcomponent. component_label : component_name [port map (association_list)]; The component_label can be any legal identifier, and can be considered as the name of the instance. The component_name must be the name of the component declared earlier using a component declaration. The association list, associates signals in the entity, called ACTUALS, with the ports of a component, called FORMALS. An actual may be a signal or an expression or it can be the keyword open, to indicate a port that is not connected. There are two ways to perform the association of formals with the actuals: 1. Positional Association 2. Named Association
Positional Association
In positional association, the association list is of the form:
Actual1, actual2, actual3,,actualn Each actual in the component instantiation is mapped by position with each port in the component declaration. That is, the first port in the component declaration corresponds to the first actual in the component instantiation, the second with the second, and so on. The ordering of actuals is therefore important. If a port in a component instantiation is not connected to any signal, the keyword open can be used to signify that the port is not connected.
N3:NAND2 port map (S1, open, S3); The second input port of the NAND2 component is not connected to any signal. An input port may be left openonly if its declaration specifies an initial value.
Named Association
In named association, the ordering of the association is not important, since, the mapping between the actuals and the formals is explicitly specified. The port names from the component declaration, also called "formals", are associated with an arrow ' => ' with the signals of the entity ("actuals"). entity FULLADDER is port (A,B, CARRY_IN: in bit; SUM, CARRY: out bit); end FULLADDER; architecture STRUCT of FULLADDER is component HALFADDER port (A, B : in bit; SUM, CARRY : out bit); end component; ... signal W_SUM, W_CARRY1, W_CARRY2 : bit;
Modeling Structure
Structured Modeling
State Machines
Basic components Combinational component: output function and next state function Sequential component Natural process-based implementation
Generics
library IEEE; use IEEE.std_logic_1164.all; entity xor2 is generic (gate_delay : Time:= 2 ns); port(In1, In2 : in std_logic; z : out std_logic); end entity xor2; architecture behavioral of xor2 is begin z <= (In1 xor In2) after gate_delay; end architecture behavioral;
architecture Generics in isgeneric_delay of Hierarchical Models half_adder component xor2 generic (gate_delay: Time); port (a, b : in std_logic; c : out std_logic); end component; component and2 generic (gate_delay: Time); port (a, b : in std_logic; c : out std_logic); end component; begin EX1: xor2 generic map (gate_delay => 6 ns) port map(a => a, b => b, c => sum); A1: and2 generic map (gate_delay => 3 ns) port map(a=> a, b=> b, c=> carry); end architecture generic_delay; Parameter values are passed through the hierarchy
Generics: Properties
Generics are constant objects and can only be read The values of generics must be known at compile time They are a part of the interface specification but do not have a physical interpretation Use of generics is not limited to delay like parameters and are in fact a very powerful structuring mechanism
Example: Using the Generic Narchitecture structural of full_adder is component generic_or Gate Input OR generic (n: positive);
port (in1 : in std_logic_vector ((n-1) downto 0); z : out std_logic); end component; ... ... -- remainder of the declarative region from earlier example ... begin H1: half_adder port map (a => In1, b => In2, sum=>s1, carry=>s3); H2:half_adder port map (a => s1, b => c_in, sum =>sum, carry => s2); O1: generic_or generic map (n => 2) port map (a => s2, b => s3, c => c_out); end structural; Full adder model can be modified to use the generic OR gate model via the generic map () construct Analogy with macros
Instantiating interconnected components Declare local signals used for the interconnect
Configurations
A design entity can have multiple alternative architectures A configuration specifies the architecture that is to be used to implement a design entity
Component Binding
We are concerned with configuring the architecture and not the entity Enhances sharing of designs: simply change the configuration
Configuration Specification
Configuration Specification
Short form where applicable for all: half_adder use entity WORK.half_adder (behavioral); Not constrained by the name space Delayed binding when a specification is not present Will be available at a later step Analogous to unresolved symbol references during compilation of traditional programs
Configuration Declaration
Written as a separate design unit Can be written to span a design hierarchy Use of the for all clause
Essentials of Functions
function rising_edge (signal clock: std_logic) return boolean is ---declarative region: declare variables local to the function -begin -- body -return (expression) end rising_edge; Formal parameters and mode Default mode is of type in Functions cannot modify parameters Pure functions vs. impure functions Latter occur because of visibility into signals that are not parameters Function variables initialized on each call
Placement of Functions
Function: Example
Function: Example
function to_bitvector (svalue : std_logic_vector) return bit_vector is variable outvalue : bit_vector (svaluelength-1 downto 0); begin for i in svaluerange loop -- scan all elements of the array case svalue (i) is when 0 => outvalue (i) := 0; when 1 => outvalue (i) := 1; when others => outvalue (i) := 0; end case; end loop; return outvalue; end to_bitvector
A common use of functions: type conversion Use of attributes for flexible function definitions Data size is determined at the time of the call Browse the vendor supplied packages for many examples
Essentials of Procedures
procedure read_v1d (variable f: in text; v :out std_logic_vector) --declarative region: declare variables local to the procedure -begin -- body -end read_v1d;
Parameters may be of mode in (read only) and out (write only) Default class of input parameters is constant Default class of output parameters is variable Variables declared within procedure are initialized on each call
Procedures: Placement
Placement of Procedures
Variables cannot be passed into a concurrent procedure call Explicit vs. positional association of formal and actual parameters
Subprogram Overloading
Hardware components differ in number of inputs and the type of input signals Model each component by a distinct procedure Procedure naming becomes tedious
Subprogram Overloading
Consider the following procedures for the previous components dff_bit (clk, d, q, qbar) asynch_dff_bit (clk, d,q,qbar,reset,clear) dff_std (clk,d,q,qbar) asynch_dff_std (clk, d,q,qbar,reset,clear) All of the previous components can use the same name subprogram overloading The proper procedure can be determined based on the arguments of the call Example function * (arg1, arg2: std_logic_vector) return std_logic_vector; function + (arg1, arg2 :signed) return signed; -- the following function is from std_logic_arith.vhd
Subprogram Overloading
VHDL is a strongly typed language Overloading is a convenient means for handling user defined types We need a structuring mechanism to keep track of our overloaded implementations
Essentials of Packages
Package Declaration Declaration of the functions, procedures, and types that are available in the package Serves as a package interface Only declared contents are visible for external use Note the behavior of the use clause Package body Implementation of the functions and procedures declared in the package header Instantiation of constants provided in the package header
Packages are typically compiled into libraries New types must have associated definitions for operations such as logical operations (e.g., and, or) and arithmetic operations (e.g., +, *) Examine the package std_logic_1164 stored in library IEEE
Essentials of Libraries
Design units are analyzed (compiled) and placed in libraries Logical library names map to physical directories Libraries STD and WORK are implicitly declared
Libraries
Packages
Packages are repositories for type definitions, procedures, and Functions