Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
[ vhdl_course_notes ] [ questions ] VHDL COURSE NOTES 1 1.1 1.2 1.3 1.4 1.5 1.6 1.7 1.8 1.9 Application and Language Introduction What you will learn in this Lesson What is VHDL Application Areas Limitation of VHDL Levels of Abstraction Behavioral Versus RTL Exercise 1: Application of VHDL Exercise 2: Application of VHDL Exercise 3: VHDL for Synthesis
1.10 Main Language Concepts 1.11Entity 1.12Architecture 1.13 Representing Hierarchy 1.14 Local Declarations 1.15 Configurations 1.16 Exercise 4: Numbers of Architectures 1.17 Exercise 5: Local Signal Declarations
1.18 Exercise 6: Entities and Components 1.19 Processes and Types 1.20 Packages 1.21 Compilation and Libraries 1.22 The complete Picture 1.23 Exercise 7: Sequential Statement 1.24Exercise 8: VHDL Design Units 1.25 Exercise 9: Name of Directory 2 2.1 2.2 2.3 2.4 2.5 2.6 2.7 2.8 2.9 Signals and Data Types What You Will Learn in This Lesson The Concept of a Type Exercise 1: Declaration of types Standard Data Types Signals And Drivers Arrays Exercise 2: Array Assignments Concatenation and Aggregates Exercise 3: Statements Independent of Width
2.10 Type definition 2.11 Multi Valued Logic 2.12 Standard Logic 2.13 Exercise 4: Use of Standard Logic 2.14 Using Standard Logic
2.15Exercise 5: Which lines are legal VHDL 3 3.1 3.2 3.3 3.4 3.5 3.6 3.7 3.8 4 4.1 4.2 4.3 4.4 4.5 4.6 4.7 4.8 4.9 VHDL Operators What You Will Learn in This Lesson Logical Operators Exercise 1: Logical Operators Relational Operators Exercise 2: Relational Operators Arithmetic Operators Exercise 3: Arithmetic Operator Exercise 4: which code is Legal Concurrent and Sequential Statements What You Will Learn in this Lesson Concurrent Assignment Statements The Process Process Execution Complete Sensitivity List Exercise 1: Statement Execution Exercise 2: Signal Update in a Process Exercise 3: Sensitivity List The If Statement
4.10 The Case Statement 4.11 The For Loop 4.12 Exercise 4: If Statement Execution
4.13 Exercise 5: Case Statement Rule 4.14 Exercise 6: Where Can They Be Used 4.15 Exercise 7: For Loop Example 5 5.1 5.2 5.3 5.4 5.5 5.6 5.7 5.8 5.9 Sequential Statements What You Will Learn in this Lesson Concurrent Versus Sequential Signal Assignment in a Process Exercise 1: Signal Update in a Process Multiple Process Calls(1) Multiple Process Calls(2) The Simulation Cycle Exercise 2: How Many Delta Cycles The Behavior of a Process
5.10 The Wait Statement 5.11 Exercise 4: Wait Statements 5.12 Variables 5.13 Variable Usage Model 5.14 Parity Generator Example 5.15Exercise 5: Variables versus Signals 6 6.1 6.2 6.3 Synthesis Issues What You will Learn in This Lesson Specifying Registers in VHDL Detecting a Rising Clock
Clock Process Rules Exercise 1: Incomplete Assignments Exercise 2: Incomplete Assignments Controlling Transparent Latches Definition of RTL Exercise 3: Partitioning Between Processes
6.10Exercise 4: Find the Latches 6.11 Finite State Machines 6.12 State Machine Code 6.13 Operation on Vectors 6.14 Overloading 6.15 Exercise 5: Operator Overloading (1) 6.16 Exercise 6: Operator Overloading (2) 6.17 Exercise 7: Operator Overloading (3) 6.18 Exercise 8: Operator Overloading (4) 6.19 Vector Arithmetic Packages 6.20 Synthesis of Operators 6.21 Resource Sharing 7 7.1 7.2 7.3 7.4 Overview of Synthesis for Xilinx Devices Introduction What we will cover Terminology PLD Synthesis Issues
Xilinx Device Architectures FPGA Technologies CPLD Technologies Where PLD Specific Issues Occur How the PLD Specific Issues Are Handled
7.10 Exercise 1: Inference 7.11 Exercise 2: Instantiation 8 8.1 8.2 8.3 8.4 8.5 8.6 8.7 8.8 8.9 Coding Styles Coding Styles Introduction Using Modules LogiBOX Facility Synthesis of Arithmetic Operators Exercise 1: LogiBox Exercise 2: Manual Resource Sharing Encoding for State Machines Use of One-Hot State Machines Safe State Machines
8.10 Exercise 3: Safe state machine 8.11 I/O Features 8.12 I/O Definitions 8.13 Using 3-state and Bidirectional I/O 8.14 Utilizing Registered I/Os 8.15Exercise 5: IOB Definition
8.16 Special Routing Requirements 8.17Exercise 6: Clock Buffer 8.18 Internal 3-state signals 8.19 Exercise 7: 3-state Inference 9 9.1 9.2 9.3 9.4 9.5 9.6 9.7 9.8 9.9 Design Flow and Control Introduction Generic Design Flow-Specification Generic Design Flow-Simulation and Synthesis Generic Design Flow-Implementation Exercise 1 RTL Simulation Simulation Support from Xilinx Synthesis Gate Level Simulation
9.10 Implementation 9.11 Exercise2: 9.12 Back Annotation 9.13 Exercise 3: 9.14 Post Layout Verification 9.15 Exercise 4: 9.16 Programming 9.17 Summary 10 Issues in Using VHDL for Programmable Logic Design
10.1 10.2 Why Use VHDL 10.3 Advantages of Simulation 10.4 Medium Term Advantages of Using VHDL 10.5 The Issues to watch for 10.6 Quality of Result Issues 10.7 Data path Issues 10.8 Issues to watch: Conclusions 10.9 Fitting VHDL into Your Design Flow 10.10 10.11 10.12 11 Examples 11.1Example for if statement 11.1.1 N-bit Comparator 11.1.2 Shift Register (shift_reg) 11.2Example for Array 11.2.1 Static Random Access Memory (SRAM) 11.2.2 Read Only Memory (ROM) Use for a Complete Design Board Level Simulation Conclusions
This Diagram shows the complete electronic design Process, from the requirements for the system, through hardware and software partitioning, down to the specification and implementation of the hardware and software parts of the completed system.
HARDWARE IMPLEMENTATION:
In the early 1990s, VHDL was being used primarily for complex ASIC design, using synthesis tools to automatically create and optimize the implementation. Then the use of VHDL with
Modeling Specifications: There is also an increase in the use of VHDL for modeling specifications, both of hardware part of the system, and the complete system itself.
Levels of Abstraction
Layout Level: The lowest level of abstraction is the layout level. This specifies information about the actual layout of the design on silicon, and may also specify detail timing information and analog effects.
Logic Level: Above the layout level is the logic level, where we interconnect logic gates and registers. Layout information is ignored, and the design contains information about the function, architecture, technology and detailed timing.
Register Transfer Level: At the Register Transfer Level we Use VHDL in a strict style that defines every register in the design, and the logic between them. The design still contains architecture information but not the details of the details of the technology. Absolute timing delays are not specified.
Behavioral: Above the RTL, we have the behavioral level. This level uses VHDL to describe the function of a design, without specifying the architecture of registers. Behavioral code can contain as much timing information as the designer requires representing his function.
At RTL style the designer has control over the architecture of the registers in his design.
A- Only ASIC and programmable logic design. B- Only specifying the hardware part of the system. C- Only specifying the system before it is partitioning into hardware and software. D- All stages mentioned in choices A, B, and C.
A- The code must be written in a behavioral style. B- The code must be written in an RTL style C- The code must be written at gate level. D- VHDL for synthesis can be written in any style.
1.11Entity
We will start to look at some VHDL syntax, starting with the main building block of any VHDL design, the entity.
The entity in VHDL describes the interface to a hierarchical block, without defining its behavior. The entity is equivalent to a symbol in schematic based design. Lets look at the syntax for this example of a HALF ADDER. The syntax for an entity starts with the keyword entity, followed by the name of the entity, and the keyword is. The inputs and outputs are contained within the port statement: This lists the direction, and states that each signal is a single bit. Finally we have the keyword end , end the name of the entity, followed by a semi-colon.
1.12Architecture
Now we will take a look at how the behavior of an entity is described, using an architecture.
Here we have the architecture of our entity HALFADD that we saw previously. The syntax begins with the keyword architecture, followed by a user defined name of architecture itself, which is BEHAVE in this example. We then have the keywords is, and begin. After the beginning of the architecture, we have the statements defining the actual behavior. In this case, we have two signal assignments: the result of A xor B is assigned to the output SUM and the result of A and B is being assigned to the output CARRY.
And finally it is important to note that an entity can have more than one architecture. One usual application of this is when a design is described at several levels of abstraction: there may be behavioral, RTL and gate level descriptions of the same design.
entity FULADD is port (A, B, CIN : in bit; SUM, CARRY : out bit) ; End FULLADD;
The code is shown here for the entity of FULLADD. As you can see, all of the five ports are declared as single bits, in the same style as we saw for the HALF ADDER
Here we can see the architecture of FULLADD. Start by looking at the three lines of code between the begin and the end statements. Each of these statements creates an instance of another entity, similar to placing down a symbol in a schematic capture package.
Looking at the syntax, we have the instance name (u1), and following the colon we have the name of the entity we are making an instance of. Then we have the key words port map, and then a list of the signals within FULLADD that are connected to the ports of our design HALFADD
Entity HALFADD is Port (A, B: in bit ; SUM, CARRY : out bit); End HALFADD;
Component Declarations
Component declarations
Begin u1: HALFADD port map (A, B, I1, I2); u2: HALFADD port map (I1, CIN, SUM, I3); u3: ORGATE port map (I3, I2, CARRY); end STRUCT;
Before we can make an instance of an entity such as HALFADD it is necessary to declare the interface to the entity locally in the FULLADD architecture. This is done with what is called a component declaration.
Component HALFADD port (A, B : in bit: SUM, CARRY : out bit); End component;
The component declaration has the same style of syntax as the entity. In 99% of situations, you will want your component to have the same name and the same port list, as your entity. There is no getting around this: the component declaration must be present.
entity HALFADD is port (A, B : in bit; SUM, CARRY : out bit) End HALFADD;
Entity FULLADD is
Port (A, B, CIN : in bit; SUM, CARRY : out bit); End FULLADD;
Architecture STRUCT of FULLADD is Signal I1, I2, I3 : bit; Component HALFADD Port (A, B : in bit; SUM, CARRY : out bit; End component; Component ORGATE Port (A, B : in bit; Z : out bit; End component;
Begin u1 :HALFADD port map (A, B, I1, I2); u2 :HALFADD port map (I1, CIN, SUM, I3);
end STRUCT;
The complete code for the FULLADD design is shown here. In an architecture, note that we declare the local signals and component before the begin, and the description of the designs function is between the begin and end.
1.15 Configurations
The next VHDL object we will look at, is called configuration. Consider that a full design hierarchy consists of entities, each of which can have multiple architectures.
The configuration is like a parts list, specifying which architecture is to be used for each entity in the design.
entity A B C D
arch Y X X Y
You are not required to give this parts list information for all of your design hierarchy. If no configuration information is specified for an entity, then the last architecture that was compiled by the simulator is the one that is used during the simulation. It is common for complete design to only have on architecture for every entity and not require configuration. Some simulators allow this, while others require at least a Default configuration. Always using a default configuration makes your code more portable.
Default Configuration:
here is the syntax for default configurations. A configuration has its own name, and is associated with the entity of the top level of hierarchy, before the end for and end <name> constructs.
As we have said, we recommend that you always construct at least a default configuration for your design.
In which area of VHDL code must signals be declared which are local to architecture? Please select one of the answers.
A- In the ports list of the architectures entity. B- In an associated configurations. C- In In the architecture, after the begin key word. D- In he architecture, before the begin key word.
A-There are unlikely to be any similarities. B- The entity and component will have the same name, but their port names will be different. C- The entity and component will have the different names, but their port names will be the same. D- The entity and component will have the same name, and their port names will be same.
Process contains sequential statements: The process is a region of VHDL code, inside which statements execute in sequence. A process
exists inside an architecture, and multiple processes interact with each other concurrently.
entity ORGATE is port (A, B: in bit; Z: out bit); End ORGATE; Architecture BEHAVE of ORGATE is Begin OR_FUNC: process (A,B) begin if (A=1 or B=1) then else
Any VHDL model is seen by a simulator as a collection of processes. Each process executes its statements in sequence and the multiple processes are interacting concurrently, as this diagram shows. There can be any number of processes within an architecture.
Type: There are types pre-defined in the language standard, and the user can also define his own type. So far we have seen type bit, which can have the values of 0 and 1.
Examples for pre defined types: real , bit, integer, bit_vector, boolean. Examples for user defined types: States, cpu_instructions, network_packet, My_type.
1.20 Packages
A package contains a collection of definitions that may be referenced by many designs at the same time. Placing definitions that are common between designs in one location helps a design team to work more consistently.
A package is a separate design unit in VHDL. Therefore it exists outside of the design units that we have considered so far, such as entities, architectures and configurations.
A package may contain definitions of constant values, user defined date types, component declarations, and sub programs of VHDL code that are shared between different designs.
The final concepts of the language that we will cover in this introduction section are how VHDL source code is compiled, and how designs are grouped together into a library.
Compilation or Analysis:
When you have written your VHDL code as text in a file, the code is checked for syntax errors, and a library file is created. This process is known by some tools as compilation, and by other tools as analysis. We will use the word compilation in the rest of the tutorial.
Design Units:
The smallest item in VHDL that you can compile is a single design unit.
These are the entity, architecture, configurations and package, which can have a separate part called a package body. These five objects are the only design units defined in the VHDL language.
Compile into a library: When VHDL code is compiled, the resulting binary file is stored in a specific directory on your computers disc. In order to keep references to this file independent of a specific directory path, directories are given a logical name known as library All VHDL simulation and synthesis tools access a file that maps VHDL library names to physical directory pats on your system. VHDL also allows a library called WORK to be defined as the library into which design units are compiled if no library destination is specified.
a complete design hierarchy is defined by multiple entities, which have at least one architecture. Many of these entities and architectures will reference one or more packages of common definitions. The link between each level of hierarchy, and specification of which architecture is to be used, is performed by the configuration.
And finally, the top level of hierarchy is usually used to contain both the design and the stimulus
A-The process, before the begin keyword B- The architecture. C- The process, after the begin keyword. D- The package.
Type concept:
Values allowed in a signal of type bit: 0 , 1. The VHDL language defines that every signal must have a data type associated with it when the signal is declared. The type defines a set of values, and an assignment to that signal must always be of a value defined by that set.
entity FULLADD is port (A, B, CIN : in bit; SUM, CARRY : out bit); end FULLADD; architecture STRUCT of FULLADD is signal N_SUM : bit; -- other declarations begin --code end STRUCT;
A signal is generally declared either in the port section of an entity, or within an explicit signal declaration in an architecture. When a signal is declared in either of these locations, its associated type must be specified: the type is bit in this example.
When we make an assignment to a signal, the types on either side of the signal assignment operator must match up.
SUM <= A xor B; Hence in this example , the result of A xor B must be of type bit for us to be able to assign it to the signal SUM.
A- when the signal is declared. B- When the signal is first used in the code. C- In a package. D- It is not necessary to declare the type of a signal.
Having reviewed the conceps of data type, we will now look at the standard types that predefined within the VHDL language. All of this types are specified as VHDL source code, and the language defines that they should be found in a package called STANDARD.
package STANDARD is type BOOLEAN is ( FALSE, TRUE); type BIT is (0, 1); -------------------------------------
end STANDARD;
Boolean Time:
The type Boolean defines two values: true and false. Boolean type is returned when two values are compared. Time is used to model simulation time, and consists of both a number, and units.
Bit, bit_vector:
Character, string:
As the name implies, type character defines a single character in VHDL, and type string defines an array of characters. Note the same differences with single and double quotes for bit and bit_vector.
Integer, real:
VHDL supports both integer and real data types: an integer must be a whole number, whereas a real can have any number of decimal places. Note the difference in how they are specified: a real must have a decimal point, an integer must not.
A signal is assigned a new value with what is known as a signal assignment, as we have seen in the examples of half adder and full adder.
Signal Driver:
An assignment to a signal defines a driver on that signal. A buffer would not necessarily be used by a synthesis tool, unless the buffer is needed to drive a large load.
Multiple Drivers:
If more than one assignment is made to a signal, then that signal must be declared to be a special kind of type, known as resolved type. A resolved type has a function call associated with it to resolve the final value of the signal. This only used in very special cases in hardware. Normally it is illegal to use it.
2.6 Arrays
An array is a collection of objects, where each one is of the same type. The language defines two types of array: bit vector, and string.
The range of an array is defined when the array is declared. Example: Legal declaration: Signal Z_BUS: bit_vector (3 downto 0); Signal C_BUS: bit_vector (1 to 4);
This example shows two bit_vectors, where each one is four bits wide. The range may be declared using either the to or downto notation. However the appropriate keyword must be chosen.
Illegal declaration: Signal Z_BUS: bit_vector (0 downto 3); Signal C_BUS: bit_vector (3 to 0);
Array Assignments:
Two array objects can be assigned to each other, as long as they are of the same type and same size: Note that assignment is by position, and tot by index number. There is no concept of a most significant bit defined with the language.
Array slices:
A slice of an array may be referenced, including a single element. The direction of the slice (i.e. to or downto) must match the direction in which the array is declared.
Legal: Z_BUS (3 downto 2) <= 00; C_BUS(2 to 4) <= Z_BUS (3 downto 1);
A- By matching their index numbers. B- By matching their position within the array. C- It depends on whether the arrays are defined as to or downto D- It doesnt matter.
Concatenation:
VHDL provides the ability to associate single bits and vectors together, to form array structures. This is known as concatenation, and uses the ampersand (&) operator. The examples here show
that single bits, and bit vectors can be concatenated together to form new vectors.
Aggregates:
Another method of assigning to elements of an array is known as aggregate. An aggregate is contained within round brackets, and assignment to each element are separated by commas (,).
It is possible to specify the element of array to assign by name, as well as by position. This example also shown that, a range of the array can be specified, as long as the same value is being assigned to each element in the range.
others statement:
Aggregates have the ability to use the others statement, which will assign a value to all other elements of the array that have not been specified. Finally, not all synthesis tools support the use of aggregates, so you may be required to use concatenation to perform array manipulation.
Enumerated type:
A user defined type in VHDL is known as an enumerated type. Types are most commonly defined inside a package, architecture or process.
After specifying the type name, we have a list of values that an object of the type can contain, with each value separated by comma (,).
Having defined the type, then we can define signals to be of that type. Here we have declared the signal STATE to be of type MY_STATE. We have toobserve the strict rules when using tis signals: we cannot assign anything to signal state which is not of type MY_STATE.
Most synthesis tools can build logic from a signal which is of an enumerated type. Usually the signal has minimum number of bits required to represent the number of possible values. This example shows how each value is usually encoded in the hardware implementation.
Standard logic type definitions are contained within a package called standard_logic_1164. We will see how to reference this package.
The package of definitions is contained within a library called IEEE. It is necessary to reference both the library and the package, as shown in the diagram. You will use these lines of code before every entity you write that uses Standard Logic.
3 VHDL Operators
3.1 What You Will Learn in This Lesson Main operators:
Having learned about signals and their types, we now introduce the main operators that allow us to perform operations on these signals.
Logical:
We will cover the logical operators, such as and and or.
Relational:
Then we will look at the relational operators that used to compare different values.
Arithmetic:
And finally we will look at the arithmetic operators for performing mathematics.
Example:
End MYDESIGN;
End MYD;
This example shows the simple use of logical operators. Note that the brackets are required, otherwise the not function will only be invert signal B.
3.3 Exercise 1: Logical Operators 3.4 Relational Operators >, >=, <, <=, /=, =
less than
greater than
equal to
not equal to
Return a Boolean:
They each return a Boolean value, and are most often used within a if-then-else statement to control the flow of code depending on different conditions.
The rules for using relational operators are that the operands must be of the same type. For an array, the operands can be of different lengths: the operands are aligned to the left, and compared
to the right.
C- std_ulogic D- Boolean
3.6
Arithmetic Operators
addition
subtraction
multiplication
division
exponential
absolute value
modulus
remainder
The arithmetic operators are listed here. They are pre-defined for types integer, real, (except for modulus and remainder), and type time. As vectors do nt represent a numerical value, the arithmetic operators do can not be used with types bit_vector, std_ulogic_vector, or std_logic_vector.
Generally the operands need to be of the same type. Intis example we are adding two intigers and the result returned is also an integer.
4.1 What You Will Learn in this Lesson 4.2 Concurrent Assignment Statements
Concurrent statements are those which can execute at the same time in parallel. This differs from
The behavior of concurrent statement is independent of the order in which they are written. In this example, we can write either statement first, and the result is the same: the result of A+B is used as an input to the adder that defines Z.
Draw a picture
The easiest way to perceive this is to actually draw a schematic of the operations. Schematics are used to represent hardware, and so they are concurrent in nature. If we draw the two adders here, then we get the same diagram, no matter which adder we draw first.
There are some things that you may have done when writing traditional software, they may not make much sense in describing the hardware. In software, X and Y are register locations: We take the contents of X, add it to Y, and store the result in register X.
As a concurrent statement, the same line of code is describing an adder, with no implied storage registers. Hence we have described feedback around combinational logic. As you can see it is really important to think about the fact that you are describing hardware when you write VHDL.
Having reviewed the concepts behind concurrent and sequential statements, lets go on to look at how these types of statements interact in VHDL, through the VHDL process
Process syntax
Begin
if SEL = 1 then
Z <= A;
as we have said, the process containes sequencial statements. It has an optional label, the key word process, and a sensitivity list. Following the key word begin, we have the sequencial statements, and then we have the sequencial statements, and then we have the key words end process followed by the label name.
Begin
A process does not execute continuously: it is invoked when one of the signals in its sensitivity list changes value, or in VHDL- speak, has an event.
While each process executes its statements in sequence, multiple processes interact with each oter concurrently, as depicted in this diagram. Each process executes when trere is event on one of the signals in its sensitivity list, causing events to occur on signals that is assign to.
--------concurrent statements
A process must be written within an architecture, and VHDL allows any number of processec to be described within the same architecture.
To put the execution of a process in context, we will look at two statements, each statement making an assignment to the same signal. First we will consider the behavior of these as concurrent statements, and then as sequential statements.
Architecture CONCURRENT of MULTIPLE is signal, Z, A, B, C, D: std_logic; begin Z<= A and B; Z<= C and D; End CONCURRENT;
When these two statements are concurrent, they define two drivers on the signal Z, and Z needs to be resolved data type to determine the final value.
process (A, B, C, D)
When these statements are sequential, their behaviour changes. The value that the signal is updated with is the last value assigned to it within the process execution.
MUX example
MUX: process (A, B, SEL) Begin If SEL = 1 then Z <= A; Else Z <= B;
The code describes to one MUX : if there is an event on A, B or SEL then the process is called , and depending on the value, of SEL, either A or B is assigned to Z.
MUX: process (A, B) Begin If SEL = 1 then Z <= A; Else Z <= B; End if; End process MUX;
Let us consider the same piece of code, but without SEL in its sensitivity list.
Z is sometimes delayed
The process is only executed when there is an event on A or B. When there is an event on SEL, any corresponding change of Z lags behind by an event on either A or B. This error can be difficult to debug.
4.6 Exercise 1: Statement Execution 4.7 Exercise 2: Signal Update in a Process 4.8 Exercise 3: Sensitivity List 4.9 The If Statement If-then syntax
If-then-else syntax
if CONDITION then --- sequential statements else -- sequential statements end if;
The if statement tests a condition, and executes a different set of statements depending on the result. The two most basic forms are shown here : the if-then and if-then-else statements.
if-elsif syntax
The if-elsif statement allows a series of condition to be tested, and the first condition that is true will cause the statements that follow to be executed. This cannot happen for more then one branch of the structure: the flow then passes to the end if statement at the bottom.
The order in which the statements are written in the else-if structure is very important. More than one of the condition may be true, and it is the first true condition that causes the following set of statements to be executed.
case OBJECT is When VALUE_1 => -- statements when VALUE_2 => --statements
end case;
The case statement considers all of the possible values that an object can take, and executes a different branch, depending on the current value of the object.
process (A, B, C, X) begin case X is when 0 to 4 => Z <= B; when 5 => Z <= C; when 7 | 9 => Z <= A; when others =>
The case statement has some special syntax to give more control over specifying the possible values. This simple example shows a range 0 to 4, a list of values separated by the pipe | symbol, and the others clause, covering all other possible values of X that have not been specified.
The concept of the for loop is that it will iterate around a loop a fixed number of times, while incrementing a value through a fixed range. In this example we are incrementing the variable I from 0 to 3, and therefore making four passes around the loop.
There is no need to declare the loop (I in this case ) variable in any other part of the code: it is implicitly declared within the loop.
Example
Here is an example using the for loop.
entity EX is port (A: in std_logic_vector (0 to 15); SEL : in integer range 0 to 15; Z : out std_logic); end EX;
architecture RTL of X is begin WHAT: process ( A, SEL) begin for I in 0 to 15 loop if SEL = I then Z <= A(I);
4.12 Exercise 4: If Statement Execution 4.13 Exercise 5: Case Statement Rule 4.14 Exercise 6: Where Can They Be Used 4.15 Exercise 7: For Loop Example
5 Sequential Statements
5.1 What You Will Learn in this Lesson
Our aim during this lesson is to explain further capabilities that a process can offer, we will show how a single process and then a multiple process execute, to build up a picture of a complete simulation in VHDL. Finally we will look at the wait statement and how it is affect the execution of a process.
Process model:
Remember that our model of VHDL simulation consists of multiple processes executing sequentially, and interacting concurrently.
Concurrent in architecture:
and we said that the process is seen a single concurrent statement within the architecture.
It is possible for architecture to contain any number of concurrent statements, and therefore any number of processes.
Then we looked at this similar example, where the two assignments to Z are inside a process, and we said that a process can only define one driver on a signal. The language defines that within a process it is the last assignment made to a signal that takes affect, but only when the process suspends, which in this case is at the bottom of the process.
Different meaning
is not equal to
Hence the same two statements have a very different meaning, depending on whether they are executed inside or outside of a process.
Having reviewed the basic concept of how signals are updated within a process, we will now move on to see how a process can potentially be executed several times before all signals are updated.
Example: process (A, B, M) Begin Y <= A; M<=B; Z < = M; End process Example;
In this example we have a process with an assignment to a signal M, and the value of M is also read within the same process. Let us use this example to see how a process executes in more detail.
Event on B
Lets assume that there has been an event on the signal B, which has just transitioned from 0 to 1. The process is called because B is in its sensitivity list.
The value of M is not updated when the line M< B; is executed, but when the process suspends at he bottom.
Z not updated Hence when the line Z<=M; is executed, the value of M is still 0, and Z is not updated with a 1 when the process suspends.
Now on the second call, the assignment of M to Z will cause Z to be updated with the value of 1 when the process suspends at the bottom.
Z is finally updated
So when the process suspends this time, Z is finally updated with a 1.
Queue mechanism
At a given point of simulation time, there are two queues: one of signals to be updated, and one of processes to be executed.
When a signal is updated at specific point in simulation time, all processes that are sensitive to that signal are placed on a process Execution queue.
Each process executes in turn, and signals that are assigned to in each process are not updated immediately the process suspends, but are placed on the Signal Update queue. When all of the processes have executed, then the signals are updated.
Delta cycle
As a result of the signals being updated, further processes may be placed on the process execution queue. One loop around this sequence is known as a Delta Cycle.
B- At least one Correct. There will be at least one, but any number of delta cycles are possible if processes are sensitive to signals that change values at this same point of simulation time. C- Always more than one Wrong.
D- None
Wrong.
5.9
Infinite loop
A process without a sensitivity list is defined to be an infinite loop, so when execution reaches the bottom, it automatically starts to execute again from the fist line.
process (A, B) begin if (A=1 or B=1) then Z<=1; else Z<=0; end if; end process;
process begin if (A=1 or B=1) then Z<=1; else Z<=0; end if; wait on A, B; end process;
However, for describing combinational logic you are recommended to use the form with the
STIMULUS: process Begin SEL <= 0; BUS _B <=0000; BUS _A <=1111; wait for 10 ns; SEL <=1; Wait for 10 ns; ----------------------end process STIMULUS;
The first one is wait for, which causes the process to re-execute after a specific amount of time has passed, as we discussed earlier. This can be useful in test benches to create stimulus, where signals are required to change value over time.
process begin if (A=1 or B=1) then Z<=1; else Z <=0; end if; wait on A, B; end process;
the wait on statement waits for an event on one or more of the signals in a list before reexecuting.
Q<=D;
End process:
The wait until statement has a condition which returns either true or false. The statement waits for an event on one of the signals in the condition, and if as a result of the event the condition has become true, then the process re-executes.
Wait : forever
STIMULUS: process Begin SEL <= 0; BUS _B <=0000; BUS _A <=1111; wait for 10 ns; SEL <=1; Wait ; end process STIMULUS;
and finally it is possible just to say wait, which suspends a process forever. This can be useful in a test bench to prevent infinite loop feature of processes from causing your stimulus to repeat once complete.
From where in a process does execution commence when a wait statement causes the process to be re-invoked?
D- The line immediately below the wait statement. Correct. After a process suspends, it re executes from the line immediately below.
5.12 Variables
Lets look at a new type of object in VHDL, called the variable.
Process (A, B, C) Variable M, N : integer; Begin M:=A; N:=B; Z<=M+N; M:=C; Y<=M+N; End process;
Assigned immediately
The variable is an object in VHDL that can only be declared and used within a process. A variable is different to a signal in that it is assigned its value immediately, like in traditional software.
To make assignments easy to recognize, it is required to use the := notation, rater than the <= notation used for signal assignments. A variable can only be used within the process that it is declared: this is known as the scope of the variable.
Retains value
A variable retains its value between calls to a process, and so is possible to imply the behavior of a memory element if required. To prevent any problems when describing combinational logic,
always assign a value to your variable before you read its value, as we have done in this example.
And finally, it is possible to freely assign signals to variables, and variables to signals, as we have done in this example. However, note that the rules about matching data types still need to be observed.
Intermediate values
Because a variable is updated immediately, it is commonly used to calculate an intermediate value within a process, which is then used later on in the process execution.
Note the range of the for loop: Alow is the lowest index of array A (0 in this case), and Ahigh is the highest index of A (3 in this case). Hence we will loop once for each element of A, and the code is made independent of the size of A. Ahigh and Alow are known as attributes of A.
Unfold for loop In order to understand how this code works, lets unfold the for loop, substituting the value for I. This results in the sequence of variable assignments shown on the diagram. Next we need to think about the interconnection of xor operators being described.
TMP := 0;
for I in Alow to Ahigh loop TMP:= TMP xor A(I); end loop;
Our first xor operator has inputs A(0) and TMP, which currently has the value of 0. Our second operator has inputs A(1) and TMP: in this case, the value of TMP is that which we calculated on the last line, so from the hardware point of view it is the output of the previous xor function.
The result is a chain of xor gates. When this structure is synthesized, it will not necessarily produce these exact xor gates. However this xor structure is the starting architecture that you give the synthesis tool to optimize from, and this can influence the resulting implementation.
Lets consider the different behavior of variables and signals with an example.
As we have said, a variable is assigned its value immediately. Hence in this example when we execute the line Z<=M+N; then the value of M+N is the value of A+B. The value that signal Z is to be updated with when the process suspends is calculated and stored when the assignment to Z is made. Hence in this example, z will be updated with the value of A+B when the process suspends.
Similar to Y
When we reach the assignment to Y, then M has been updated with the value of C, and so Y will be assigned the result of C+B when the process suspends.
Signal A, B, C, Y, Z : integer; Signal M, N : integer; Begin Process (A, B, C) M:=A; N:=B; Z<=M+N;
Now consider the same example, except that M and N are signals instead of variables. Spend a few moments thinking about how the process will execute if there is an event on A, B, or C and Read the exercise question and select one of the answers.
In the example shown, what are the final values of Y and Z in terms of A, B, and C ?
A- Both Y and Z are C+B. Correct. Both Y and Z are C+B, because M and N are assigned at the end of the first call to the process, and M always gets the value of C. the process is then called again and Y and Z both get C+B.
B- Both Y and Z are A+B. Wrong. Neither Y or Z can be A+B, because M is not updated until the process suspends, and it is always updated with C. C- Y is C+B, Z is A+B. Wrong. Z cannot be A+B, because M is not updated until the process suspends, and it is always updated with C. D- Y is A+B, Z is C+B. Wrong. Y cannot be A+B, because M is not updated until the process suspends, and it is always updated with C.
6 Synthesis Issues
First we will look at ways of describing registers in VHDL, building up a definition of what is a register transfer level style.
-Vector arithmetic
You will recall from the VHDL operators lesson that it is not possible to perform arithmetic on vectors in VHDL by default. However there is a way around this, and the next part of the chapter covers this subject.
-Synthesis of arithmetic operators. Finally we will look at how arithmetic operators can be synthresized in VHDL, and consider the effect this will have on how you should write your code for synthesis.
A Clocked Process
entity FLOP is port (D, CLK: in std_logic; Q : out std_logic); end FLOP;
architecture A of FLOP is begin process begin Wait until CLKevent and CLK=1; Q <=D; end process; end A;
The basic style of describing registers is to have a process which only executes when there is a rising edge of clock. Here, Q is only updated with the value of D on a rising clock, and will not be updated if D changes at any other time. Hence it describes the function of a register in hardware.
Clocked process
This type of process, with a rising edge of clock detection as the first statement, is known a a clocked process. The lines of code within the process only get executed when there is a rising clock edge.
There are many ways to detect a rising edge of clock in VHDL, and some methods are supported by more synthesis tools than the others. Lets look at the different methods, and the issues in choosing which one to use.
These two forms use the wait until statement. They both wait for an event on the clock, however the second form uses the additional CLKevent syntax to double check for the clock event. This version is more commonly supported by synthesis tools, and is therefore recommended.
These two forms use the sensitivity list to detect an event on the clock, followed by an if statement to check the sense of the event. As synthesis tools ignore the functionality implied by process sensitivity list, most tools only support the form with the CLKevent clause.
Function call
The Std_Logic_1164 package, which defines the Std_logic based data types, includes a function
call which checks for a rising edge of clock: the details are shown here. Some synthesis tools are able to detect a rising clock edge using this method.
The if and wait until styles, with the CLKevent syntax, are most commonly accepted by synthesis tools. You are recommended to use these forms of rising edge detection
Lets look at some additional rules regarding the format of code within a clocked process.
The general rule about using the wait statement to detect the clock edge is that it must be first, and only wait statement in the process. All other statements describe combinational logic that has registered outputs.
Th e rule regarding the if form of the clock process is that there should be no other statements outside of the if structure, and that the structure should have no else clause. All code inside the if statement describes combinational logic.
to specify registers with asynchronous resets, then it is necessary to use the code structure shown here. In this case, an event on RST causes the process to execute, and Q to be reset to 0.
Otherwise it is only an event on the clock which can cause Q to be updated with D.
The rule for the asynchronous reset form of the clocked process is similar to that for the if form: No other statements outside of the if structure, and ther should be no else clause after the edge detection.
architecture A of INCOMP_IF is begin process (EN, D) if (EN = 1) then Q <= D; end if; end process; end A;
please read the exercise question and select one of the answers.
QUESTION: Consider the above piece of VHDL code . If the process is called when the value of EN is 0, what do you think happens to the value of Q.
A- Q is assigned the value of D. Wrong. B- Q is assigned 0; Wrong. C- Q is assigned the value of EN Wrong. D- Q retains its existing value Correct. Q retains its existing value, because when the process is called, no assignments are made to change the value of Q.
A- an AND gate wrong. B- A transparent ( i.e. level sensitive) latch Wrong. Correct. A transparent latch is synthesized, as the value of q is the same as D when EN=1, but Q retains its last value when EN=0. C- An edge triggered flip flop Wrong.
Lets consider the implications of what we have seen in these two exercises.
Transparent Latches
The process shown in this example is the same as you have studied in the last exercise, and synthesize into a transparent latch.
The more general description of what we have seen is where a signal is assigned to within some branches of code, but not in others. This is called an incomplete assignment. If this happens within a COMBINATIONAL process, then a transparent latch is build in the synthesized hardware.
The most reliable methode is to makedefault assignments to signals at the very top of a combinational process. These assignments will be overridden by assignments made later in the process, but will ensure that transparent latches are not synthesized.
Hence the way in which the design function is partitioned defines where each register is placed in the design, and how it is clocked and reset.
From this definition, we can see that you control how much logic is placed between registers. I f the synthesis tool cannot achieve your required clock speed, then you may need to re-write the code to place less logic between registers.
To summarize the rules for clocked processes: all combinational logic defined within the process must follow the rising edge of clock detection.
which of these architectures represents the hardware described by VHDL code shown?
A- Answer A No.
B- Answer B No.
C- Answer C Correct. No. all signals which are assigned to within a clocked process have register s on their outputs so we have described two register pipelines, one for X and Y and anoter for Z.
D- Answer D No.
Please read the exercise question and select one of the answers.
Which one of the four sections of code shown here will synthesize transparent latches?
A- Example A Correct. This example synthesizes transparent latches because Z is only assigned when X=0. B- Example B No. because the assignment to Z on the first line ensures that Z is always assigned a value. C- Example C No. because the else clause ensures that there will always be an assignment to Z.
D- Example D No. it is a clock process , which synthesizes edge trigger registers on the signal Z. In this case when X=1, then the value of Z is retained in its synthesized register.
Our example design is part of a controller for a CPU (Central Processing Unit) based system. We will look at the general style of describing a state machine, rather then considering all of the functionality of this example.
FSM architecture
The general architecture of an FSM (Finite State Machine) consists of a combinational block of next state logic, state registers, and combinational output logic as shown here.
In this example, we will assume that the FSM has 4 states. These are described using user defined data type. In this code here we have defined a type called T_STATE which will be used to represent the 4 states named IDLE, RW_CYCLE, INT_CYCLE and DMA_CYCLE.
architecture RTL of FSM is Type T_STATE is (IDLE, RW_CYCLE, INT_CYCLE, DMA_CYCLE); Signal NEXT_STATE, STATE : T_STATE; begin
we then declare the signals STATE and NEXT_STATE as the inputs and outputs of our state vector: as these signals define the state of our FSM, then they are declared to be of type T_STATE.
NS: process (STATE, RW, INT, INT_REQ, DMA_REQ) Begin Case STATE is When IDLE => --- statements When RW_CYCLE => --- statements When INT_CYCLE => --- statements When DMA_CYCLE => --- statements end case; end process NS;
The next state logic is defined within a combinational process which contains a large case statement with a branch for each state of the state machine. The process is sensitive to the control inputs, and to the signal STATE.
NS: process (STATE, RW, INT, INT_REQ, DMA_REQ) Begin Case STATE is When IDLE =>
If ( INT_REQ = 1 ) then NEXT_STATE <= INT_CYCLE; elsif (DMA_REQ = 1 ) then NEXT_STATE <DMA_CYCLE; end if; When RW_CYCLE => --- statements When INT_CYCLE => --- statements When DMA_CYCLE => --- statements end case; end process NS;
Within each branch of the case statement, we have code which assigns to the NEXT_STATE signal to define the state transitions. In this example we will transition from state IDLE if INT_REQ or DMA is a 1.
Registers
REG : process (CLK , RST) Begin if RST = 1 then STATE <= IDLE;
else if CLK event and CLK =1 then STATE <= NEXT_STATE; end if; end process REG; The state vector is defined within a separate clocked process which defines only registers, and no combinational logic. We assign the value of NEXT_STATE to STATE only when there is a rising edge of clock.
Output logic
The output logic may be defined either within the same process as the next state logic, or within a new combinational process. If you wish to describe a Moore state machine where the outputs are only a function of the state vector, then a separate process is recommended.
A vector (such as std_logic_vector), is not considered to represent a number. VHDL considers a vector as just a collection of single bit values which have been associated together for
convenience.
Not OK
As a result of this, by default in the language it is not possible to perform arithmetic operations , such as addition and subtraction, on vectors. Relational operations such as testing for equality,only give a satisfactory result if the vectors are of the same length.
There is a solution
There is a solution to this issue, which is implemented via a capability known as operator overloading.
6.14 Overloading
First we will look at the concept of overloading, and consider a few examples.
The concept of overloading is that VHDL allows multiple functions to be defined with the same name, but different types for their input and output.
This concepts extend to standard operators: for example , it is legal to define multiple functions called +, as long as they have different combinations of data types for their inputs and outputs.
Signal A, B, Z: X; Z <= A + B;
The language defines that a VHDL simulator should be able to call the appropriate function automatically in the context in which it is used.
The package:
Package P_ARITHMETIC is Subtype slv is std_logic_vector; Function + (L:slv; R:slv) return integer; (1) Function + (L:slv; R:slv) return slv; (2) Function + (L:slv; R:integer) return slv; (3) Function + (L:integer; R:slv) return slv; (4) End P_ARITHMETIC;
The exercises use the package P_ARITHMETIC SHOWN HERE.The package contains four functions called +, each with a different combination of data types. We have defined slv as subtype of std_logic_vector, which makes slv effectively an alias for std_logic_vector.
entity:
use work.P_ARITHMETIC.all; entity OVERLOADED is port ( A_BUS, B_BUS: in slv (0 to 3); A_INT, B_INT: in integer; Y_BUS, Z_BUS: out slv (0 to 3); Y_INT, Z_INT: out integer); End OVERLOADED;
The ports of this entity, describes the signals that we will be trying to add together. Each signal is either a vector (signal named _BUS) or an integer (signal named _INT).
Architecture
Y_INT <= A_INT + B_INT; Z_BUS <= A_BUS + B_BUS; Y_BUS <= A_BUS+B_INT; End A;
In the architecture are the lines of VHDL code that we want to implement. In the following exercises, your task is to explain whether each line of VHDL code is legal by default in the language, legal because a function is overloaded, or illegal.
Please read the exercise question and select one of the answers.
A- Overloading of function 1. No function number 1 cannot be overloaded, as the types of its input and output parameters do not match the types of signals in the line of VHDL code we are considering. B- Overloading of function number 4. No function number 4 cannot be overloaded, as the types of its input and output parameters do not match the types of signals in the line of VHDL code we are considering.
Correct . It is legal in the language to add together two integers and return an integer, so no overloaded functions are required.
A- Overloading of function 1. No. function number 1 cannot be overloaded, as the types of its input and output parameters do not match the types of signals in the line of VHDL code we are considering. B- Overloading of function number 2. Correct. It is not legal to add together vectors by default in the language, but function number 2 has parameters with the same type and is overloaded to implement the addition.
No, it is not legal to add together two vectors by default in the language.
D- The line of code is illegal. No, the code is definitely legal when used in this context.
A- Overloading of function 3. Correct. It is not legal to add together vectors by default in the language, but function number 3 has parameters with the same type and is overloaded to implement the addition. B- Overloading of function number 4. No. function number 4 cannot be overloaded, as the types of its input and output parameters do not match the types of signals in the line of VHDL code we are considering. C- The code is legal VHDL without the need for overloading. No, it is not legal to add together a vector and intiger by default in the language.
D- The line of code is illegal. No, the code is definitely legal when used in this context.
A- Overloading of function number 2. No.Function number 2 cannot be overloaded, as the types of its input and output parameters do not match the types of the signals in the line of VHDL code we are considering. B- No. Function number 3 cannot be overloaded, as the types of its input and output parameters do not match the types of the signals in the line of VHDL code we are considering. C- The code is legal VHDL without the need for overloading. No, it is not legal to add together a vector and integer by default in the language.
D- The line of code is illegal. Correct. The code is illegal because you cannot perform addition with a vector by default, and there is no function to overload with the correct combination of data types.
As you can imagine, what is ideally required is a large VHDL package, with overloaded functions for all of the major arithmetic and relational operators, for all combinations of vectors and integers. The good news is that you dont have to write one yourself
Z<= A+B;
Z <= A+B;
When we are dealing with these operators, we find that a small amount of code can easily relate to large amount of silicon area, so it is important to understand how the operators can be synthesized efficiently.
The first issue is whether the operator is build from discrete gates, or if an optimized macro-cell is chosen from your technology library. Some synthesis tools can choose macro-cells automatically, while others require you to make a technology specific instance of a cell within your VHDL code.
Architecture of operator:
With mathematical operators, it is important to consider whether the implementation is optimized for area or speed. Some synthesis tools can only synthesize one architecture, whiles others will allow you to specify what architecture should be used, or even make the choice automatically.
Z<=A+B Generate: ---- Ripple carry adder: SMALL - Carry Lookahead adder: FAST
Sharing of operators:
In some situations operations are not being carried out at he same time, and a single operator can be shared. Again some synthesis tools are able to perform this automatically, while with others it is necessary to write the VHDL code in a different style to share the operator.
Example:
The example code is shown here. This code literally represents two adders, because two + operators have been used. The architecture that this code represents is shown, with two adders, and a multiplexer.
It is possible to implement this function with only one adder. We can multiplex either B or C Onto the single adder, as we have shown in this diagram. Some synthesis tools can perform this automatically while others cannot.
Manual Sharing:
If the synthesis tool cannot perform this optimization, the VHDL code can be re-written to achieve the same result.
the code is shown here, and you can see that an intermediate variable, X , has been defined to represent the output of the MUX, which is then input to a single adder.
In this chapter we will be setting scene and giving a very general overview of some of the issues involved in using VHDL for the design of Xilinx devices.
PLD technologies:
First we will discuss PLD architectures , how they differ from ASICs and how this effects design methodologies. Then we will architectures of two types of Xilinx PLD. These are FPGAs and CPLDs.
Xilinx PLDs:
Then will look at the architectures of the two types of Xilinx PLD. These are FPGAs and
CPLDs.
Xilinx Atchitectures:
Then we will look at how these characteristics impact on the style in which you write your code.
7.3 Terminology
We will start by clarifying some of the terminology that we will be using. Here are the definitions Xilinx uses:
PLDs:
The term PLD (Programmable Logic Device) covers all of the programmable devices that Xilinx offers. The two types of PLD that Xilinx offer are the FPGA (Field Programmable Gate Array), and the CPLD or Complex PLD.
FPGAs, CLDs:
The Xilinx FPGA technologies are SRAM-based, such as the XC4000e. The Xilinx CPLD architecture are EPROM or FLASH technology based, en example of which is the XC9000 series.
Implementation:
The term implementation is used to describe the process of turning the logic design into a physical design i.e. placing and routing the design and downloading into the target device.
First synthesis users designed ASICs (Application Specific Integrated Circuits), where you can
Then it moved into PLD-based technologies. Where, you can re- program the device many times.
From a synthesis perspective, the tool needs to contain specific algorithms to map the logic into the most efficient combination of the large building blocks.
Each building block in a given Xilinx FPGA device is known as Configurable Logic Block (CLB) A CLB is a cell consisting of 8 or more inputs, 3 or more outputs, some combinational logic and
The CPLDs are arranged into a fixed matrix and are connected by programmable switches. These form the required signal nets between CLBs.
The matrix of logic cells is surrounded by IO cells called IOBs (Input Output Blocks). These IO cells have different structure from the CLBs and can be configured to provide different types of IO interface.
CPLD technologies are not based on static RAM building blocks and they dont need to be downloaded with their logical function each time the system is powered up. They have bigger physical size, and accommodate less function. CPLD technologies is mainly useful for smaller applications. CPLDs are based on a different type of building block than used in FPGAs. In a CPLD, each building block is referred to as a Function Block (FB). Each FB is comprised of macro cells, each capable of implementing a combinational or registered function. These function blocks are connected via a switch matrix.
main areas of interest from the coding style and synthesis point of view.
Architecture independence
An important advantage of designing with VHDL is that the description can be independent of architecture, an can be re targeted to a new architecture if required. However the code that is purely generic may not make the most efficient use of architecture specific features.
In fact not all functions can be inferred by a synthesis tool. For instance, some tools do not infer RAM. Hence users are sometimes required to make specific reference to these parts in their code. This is known as instantiation.
the
A- The code cannot be synthesized. No. The code can be synthesized. The synthesis tool simply includes the instantiated function in the generated netlist. B- It will lead to inefficient usage of resources. No. On the contrary, a physical structure will already be defined for the function and it already have been optimized.
will
No. providing the libraries contain definitions of the behaviour of the function then it can be simulated.
Correct. Having instantiated an architecture specific function in your design the synthesis tool will not be able to infer an alternative structure in another architecture.
8 Coding Styles
Now we are going to look at some of the features available in XILINX architectures. We will look at the coding styles which will make best use of these resources.
generic modules and a set of tools for customizing them. This means that you can create your own library of functions that are optimized towards the architecture and technology of your choice. You can instantiate these functions in your code as and when you need them. LogiBLOX also generates simulateable VHDL modules, so you can simulate the function available in your target family series, and create architecture specific, optimized implementation of your chosen functions.
B- Enables you generate your own library modules Yes. You can instantiate these modules in your code
C- Generates code that the synthesis tool can easily synthesize No. LogiBLOX will generate behavioral code of the block that you create and it synthesizes the module on the fly but it does not generate code for synthesis.
D- Checks that the code you have written is efficient No. LogiBLOX will not do this for you. It is agraphical tool that enables you generate
your
B- The method by which the synthesis tool reduces the use of resources. No. this is known as automatic resource sharing.
C- The method by which the synthesis tool reduces the use of resources. No. This is known as automatic resource sharing.
D- A method of creating an arithmetic module. No. Manual resource sharing is a method of specifying how the module is utilized rather than created.
Default encoding
By default in VHDL, an enumerated type is usually encoded as a binary sequence, mapping from the value 0 throug the sequence of values which are listed in the type definition. However in the XILINX synthesis tool, the default encoding is a one-hot style.
DMA_CYCLE
1000
Changing the encoding Within the Xilix tools you can choose between binary or one hot encoding from the user interface or specify a different encoding from from within the VHDL code. En example of the VHDL syntax which can be used to change the encoding is shown here.
Illegal states
This means that one of the possible states of the register is not legal, and the operation of the state machine is not defined if the registers enter this state.
A quick way of doing this is to use the others clause in the case statement and define a legal next state in this clause. From this the Xilinx synthesis tool builds logic that will send the state machine into a known state from any illegal state.
an alternative method is to specify all possible illegal states so that their action can be defined. This can be very tedious process.
Whenever you write VHDL for synthesis, it is essential to think Hardware, You need to be sure that you only code for features that are available.
Please read the exercise question and select one of the answers.
B- One which can never get into an illegal state No. A safe state machine could get into an illegal state.
C- One which will always go to a valid state from an illegal state. Correct. If the state machine gets into an illegal state then goes into a valid state.
We will look at some Xilinx IO Features that available, such as clock buffers and 3-states. We will start by looking at IO cells in Xilinx devices.
IOB configuration
Each IOB controls one package pin and can be configured to provide different types of buffers as input, output or bidirectional pins. In the next section of this chapter we will concentrate on how we can insert the different types of buffer into our design.
If your synthesis tool does not infer IOBs or if you have chosen to instantiate them in your code it is a good idea to treat the IO definition as a separate level of hierarchy. Using this method, the highest level of hierarcy instantiates the core logic as well as each of the IOBs.
In some synthesis tools you can perform a separate step for IO definition. You will be allowed to select buffer types and assign them to ports of the core logic. Alternatively you may be able to make these definitions in a control file.
IO Pin assignment
And finally, lets consider pin assignment. When using the Xilinx tools, the pin assignment is specified within what is called the User Control File (.UCF). See Xilinx tools documentation for more details on how to specify this information.
3-state outputs
Many synthesis tools, including Xilinx tools, have the ability to automatically infr both 3-state output and bi directional IO cells from the equivalent VHDL code.
The appropriate coding style to infer a 3-state function in an IO cell uses statements as shown in this example. I t is the use of the assignment of Z that enables the synthesis tool to infer the 3state buffer.
The code shown here will generate bi-directional IO blocks or cells. Note again the use of the assignment of the Z value.
Registered IO
For Xilinx tools registered IO are automatically implemented using a register in the appropriate IO cell if it is available. But be careful here; make sure that the architecture supports your implied usage of clock enable and resets in IO cell.
if you want to make use of registers within a 3-state or bi-directional IO, then this function from your VHDL code by the Xilix tools.
Pull-ups
Xilinx device families have IO resources which allow pull-up/down resistors to be connected to IO pads: these can be instantiated or specified by a graphical methode.
A- By inference only. No. You can imply IOBs but it is not the only method defining them.
B- By inference or instantiation No. Theses are two methods of IOB definition but there is another technique that you can use.
C- By inference, instantiation or via a tool driven method. That is right. You need to investigate which method fits in best with your design flow.
No. Schematic method is a method of doing this but it is not the only way of doing it.
If your synthesis tool cannot infer the reset network from its connectivity, you can highlight it by instantiating the STARTUP component, whose input is connected to all of the RESET connections of the device, via a net called GSR.
Clock networks
Xilinx synthesis tool, examines the connectivity of design and instantiate global buffers automatically on clock networks. If your synthesis tool does not do this then you need to instantiate a global buffer cell to drive the clock net.
Unless you require the use of a specific global buffer, it is the best to use the generic BUFG global routing resource. The place and route tools can substitute this buffer for the best available resources. Use of any other buffering schemes means the tool is not free to make the best choice.
Portability issues
Keep in mind that many Xilinx architectures have global buffers which are available only in that architecture, so using the BUFG allows for an easier transition between families. Also the number of clock buffers available varies, so check on how many you need and how many you
implying.
A- By naming the net CLOCK. No. This is not sufficient to indicate to the synthesis tool that it should use a clock buffer to drive the net. B- By instantiating the generic clock buffer Thats right. By instantiating the generic buffer the implementation tools are then free to allocate the best resources for the net.
C- By leave the tool to decide whether one is required No. while some tools do automatically assign clock buffers to signals with a high fanout, this not always the case so you will not be guaranteed a clock buffer.
No You must be able to insert a clock buffer using the synthesis tool but you would be better advised to instantiate a generic clock buffer BUFG instead.
Lets now consider the use of internal 3-state buffers, which can save a great deal of resources within your design. They are very useful for implementing muxes or wired functions. These 3state buffers can be configured in 3-state, wired and, or wired.
3-state inference
This code shows an alternative to the usual if description of a 3 to 1 decoder by using 3-state inference. It will yield an efficient implementation of 3 to 1 mux, utilizing 3 state buffers.
Wired logic
Wired logic can be a good way of reducing the area and complexity of some types of combinational function. Most tools are not capable of inferring wired logic from Boolean operators so you will need to use instantiating to create this structure of logic.
Wide decoders
A common function is that of an address decoder and many Xilix devices have dedicated circuitry around the edge of the device so the input signals can be decoded. These type of Wide Edge Decoders are usually implemented as a service of wired-and cells with a pull-up on the 3state signal.
A- Instantiate the 3-state component. No. This would indeed yield a 3-state component but the question is looking for how would you infer a 3-state component.
B- Use logiBLOX module. No. While it is possible to generate a bussed 3-state buffer symbol using LogiBLOX, this question does not relate to LogiBLOX usage.
C- Use either a sequential or concurrent assignment to Z. That is correct. This implies to the synthesis tool that the inferred component must be able to generate the Z state. D- Use a Synthesis tool specific question. No. using a synthesis tool specific instruction should not be necessary.
9.1 Introduction
In this chapter of the tutorial we are going to take a close look at the design for Xilinx devices. We will start by looking at a generic design flow, in other words the flow that applies to any HDL design.
Then we will look at how design flow maps into the Xilinx tools and technologies.
Specifications
The design flow should always start with a specification, whether it is simply a few algorithms for input to output relationship, or a large document written in English or even VHDL.
Behavioral coding
Sometimes, VHDL design work will start by producing a behavioral VHDL description and then converting each functional block into RTL. This generally done for new development of large designs-100k gates or more.
RTL for programmable logic As we have said, this type of approach is only used for large designs. For the typical programmable logic design, it is not generally necessary to use such a rigorous methodology. Coding directly at the register transfer level is sufficient.
Following the synthesis it is necessary to check that the synthesis tool has generated a logic description that has the same behavior as the RTL. This is done using the same testbench to simulate the gate level netlist as was used to simulate the RTL description, and comparing the simulation results.
Mapping
Mapping is the process of packing the logical description generated by the synthesis tool into the different resources of the device, such as Configurable Logif Blocs (CLBs) or functional Blocks (FBs);
Placement involves allocation of mapped resources into specific locations on the device. Routing is then performed to connect between these building blocks. If timing requirements are supplied to the place and route tools, then the routing will be performed to rty to meet these timing constraints.
Now that we have this physical description of the design, the timing will have been changed slightly. In order to check that this does not change the functionality of the dasign, we must verify that the designs timing is stiil within specification.
Programming
The final step is to program the device with the design files that you have created.
9.5
Exercise 1
What is the advantage of performing syntax checking within the code editor? A- You dont need to compile your code after checking the syntax. No. You still need to compile your code after you have used the syntax checker as part of the
separate simulation and synthesis steps. B- Syntax checking is usually faster than code compilation so errors are found quicker. Correct. It is a quicker way of finding syntax errors in your code, and can be performed within the editor you already working in. C- It will correct your code for you. No it will not correct your code for you, but it will find errors and usually indicate what the problem is. D- You will no longer need to perform simulation. No. Syntax checking will not check the functionality of your design for you, so simulation will still be required.
9.6
RTL Simulation
You may simulate your RTL as you write it on a block by block basis. This will require you to write a test bench for each piece of code.
Code iteration
You may need to iterate around the code entry and simulation loop several times before you satisfied with your code.
9.7
Now we are going to discuss the kinds of VHDL packages and libraries that Xilinx supply with the Xilinx tools to support the VHDL based design flow.
VITAL support
Xilinx provides these gate level libraries that you require for the VHDL simulator. The libraries are written to conform to the industry standard VITAL format. Libraries are supplied for macro functions as well as lower level primitives.
9.8
Synthesis
NCF- Netlist Constraint Files Once synthesis is complete, the synthesis tool will create a netlist and may optionally create a constraint file containing all the timing and constraint information during synthesis. This is known as the Netlist Constraint File, and it is used to pass constraints on to timing driven implementation tools.
NGDBuild
Finally, we take the netlist and constraint outputs from the synthesis tool along with descriptions of the macros referenced in the netlist and use a tool called NGDBuild to create a generic database representing the design entirely from low level Xilinx primitives. This database is known as the NGD Generic Database.
9.9
Following synthesis, you now have a design described in Xilinx primitives which can be simulated within your VHDL simulator.
Re-use testbebch
The same testbench may be used to simulate the gate level description as was used for the RTL. This ensures that no functional errors have been introduced by the synthesis process, and that the style of the RTL code allowed an equivalent gate level design to be created.
NGD2VHDL
Before you can perform this VHDL base gate level simulation, you need to use a netlist translator called NGD2VHDL which translates the NGD file into a VHDL netlist.
9.10 Implementation
So now you are at a point where you are satisfied with the synthesis results and you want to move towards implementing the design. Lets look at the steps involved in the implementation process.
The NGD file is a netlist of Xilinx primitives which at this point coul be mapped to any device family. Because the available resources differ among different Xilinx technologies, the MAP program chooses different implementations, depending upon which device is used.
Mapping
The mapping software distributes the synthesized design across the available technology building blocks, and Generates the Negative Circuit Description (NCD) file. It also generates a Physical Constraints (PCF) file which is used by the next step which is placement and routing (PAR).
9.11 Exercise2:
What is the meaning of the term implementation? A- Simulating the actual FPGA device in its board level environment. No. B- Simulating the gate level description of the design No. C- Synthesizing the design No. D- Translating the logical description of the design into a physical description. Correct.
Physical information
In order to verify the design at this stage we need a description where the physical implementation information is used to more accurately define the timing characteristics of the design. This process is called back annotation.
NGDAnno
Back annotation data is generated by a program called NGDAnno. It extracts timing information from the physical database and generates either an SDF (Standard Delay Format) file or annotates the delays directly on the netlist.
Timing checks
Provided you have set up HDL simulator correctly, you should get warning and error messages whenever you have violations of timing checks such as those for checking setup and hold times.
9.13 Exercise 3:
What is the process of back annotation? A- Distributing implementation delays back into the logical design. Correct. It means that you can run simulations with real delays instead of estimated delays. B- Running a simulation of the logical design that includes the real delays in the description. No. C- Distributing implementation delays back into the RTL design. No D- Checking that the routing is correct. No.
Re-use testbench
So now you are at the stage where you have a VHDL file that has all of the implementation delays included. There are a couple of ways of verifying that functionality is still within
specification.
Re-use testbench
As we have discussed, you could run the simulation with the same testbench as used for the RTL and pre-layout simulations and complete the results.
Timing report
ITA also generates an enumerated report on constraint violations. ITA can be run on unplaced designs, completely placed and routed designs, or designs that are placed and/or routed to any degree of completion.
9.15 Exercise 4:
How is post layout VHDL simulation performed? A- By simulating back-annotated RTL Code. No. Timing information cannot be back annoted onto RTL code, only onto a gate level VHDL netlist. B- By simulating back-annotated gate level code Correct. The simulation database contains the timing information passed back from the layout tool.
C- By simulating XNF netlist No. The XNF netlist is not in VHDL format. D- On a purely gate level simulator. No. You can run post layoput simulations on a VHDL simulator. You do not have to move to a different simulator provided you have the VITAL based VHDL technology libraries available.
9.16 Programming
The final stage in the design fow is to program the target device. At this step, you need to translate the design information into a format suitable for programming.
BitGen program
The BitGen program is used to perform this translation. It takes a fully routed NCD (Circuit Description ) file as its input, and produces a configuration bitsream which is binary file with a .bit extention.
Filename .bit
This .bit file contains all of the configuration information from the NCD file defining the internal logic and interconnections, plus device-specific information from the files associated with the target device.
Download
The binary data in the .bit file can then be downloaded to the device, or it can be passed through a program called PROMGEN which will translate it to the appropriate format for PROM programming.
CPLD programming
The flow for programming a CPLD is very similar to that of programming an FPGA which we have just described. The NGD file is passed to the PLD Fitter Program. This then generates a .JED (JEDEC file ) which can be downloaded directly to the device, or red into the programmer.
10
10.1
Implementation independent
One reason for using VHDL is to have a design description which is independent of its implementation technology.
Vendor independence
VHDL is now supported by all major tools vendors, and so a VHDL description is generally portable between different tools sets, giving greater choice and flexibility.
A VHDL description can be simulated, which is not the case for language such as ABEL and PALASM. There are many advantages which this can bring: lets move on to look at these in more detail.
A VHDL based simulation typically uses the VHDL language to describe the stimulus, as well as the device which is being designed. The code that defines the stimulus is generally called the testbench, and having a portable stimulus description gives greater flexibility.
Testbench advantages
There are many advantages of the testbench. Very complex stimulus can be created, and it allows interaction between the testbench and the device model.
Testbench benefits
Through the testbench, the interaction between devices on the board can be simulated at an early stage in the design cycle, leading a fewer board level iterations, and a reduction in overall development time.
Modeling of a system
Some companies use VHDL to model their system, before they have partitioned it to implementation. This can help to clarify the specification at an early stage, provide a precise definition of the partitioning, and supply stimulus for the more detailed implementation models.
Design re-use
It is well known that 80% of design is re-design. There is the opportunity to make significant productivity increases on future projects through the re-use of VHDL code.
10.4 Medium Term Advantages of Using VHDL Increasing programmable logic densities
In the 1990s the programmable logic devices were available with tens and hundreds of thousand useable gates. The experience of early VHDL users has shown that it is at these design complexities where significant productivity gains can be achieved by using VHDL synthesis.
VHDL is a standard
VHDL is a standard language. An ever increasing number of engineers will have VHDL skills, and other design groups will use VHDL too.
Design re use
It is well known that 80% of the design is re-resign. By investing in a technology and tool independent standard language, there is the opportunity to make significant productivity increases on future projects through the re-use of VHDL code.
Summary
In summary, we have considered the advantages of implementation and tool independence, increased productivity when using synthesis with large designs, the ability to simulate at board and system levels, and a future-proof investment which can facilitate design re-use.
It is necessary to write VHDL for synthesis in a style which describes each register in the design, and the function of the combinational logic between registers. This is known as a Register Transfer Level description (RTL), and is a subset of the complete language definition.
The style which VHDL code is written has a direct influence on the quality of the design resulting from synthesis. VHDL designers therefore need to understand both language syntax and how coding styles affect synthesis results.
These logic cells can be quite large and therefore more difficult for a synthesis tool to optimally place into a design. If the logic cells are not used efficiently, a slower and larger implementation may result. Different tools can give very different results, so evaluate this issues carefully.
Even the most sophisticated synthesis tools are not always able to optimize a design as well as an experienced designer, and you should expect to carry out a smaal amount of manual intervention at times. In spite of this, synthesis can still offer significant productivity benefits for large designs.
Other issues which can occur are associated with data path oriented designs. Lets look at these issues now.
Data path oriented portions of a design contain many regular structures such as arithmetic and comparison elements. Often silicon vendors libraries contain macrocells of these elements which can be build efficiently during device layout.
many primitive gates, or may not choose the most efficient macrocell.
Work arounds
These issues can be worked around by making instances of vendor specific macrocells in the VHDL code. However this makes the code vendor specific and more difficult to write.
When you plan to buy a synthesis tool set then your programmable logic vendor may be able to give good advice about the issues you can expect to face with specific tools.
It is not necessary to base all of a programmable logic design on VHDL. It is plssible to use VHDL on the parts of the design you consider most suitable. In this Scenario you can simulate the synthesized gate level netlist.
10.10
The second method of introducing VHDL is to describe a complete device with the language, and to simulate the VHDL code as well as synthesizing the gate level design.
10.11
Finally, we will look at what is required to perform VHDL simulation at the board level in a design with multiple programmable logic or Application Specific (ASIC) devices.
Alternatively, some of the more powerful work station based simulators can mix non VHDL software and hardware models of standard parts with the VHDL code for the programmable logic and ASIC devices. As you may be aware, these simulators and models can be very expensive.
Potential Benefits
To summarize, VHDL brings the opportunity on complex designs to reduce the number of board
10.12
Conclusions
Finally, lets draw some conclusion from the topics we have covered.
Potential benefits
We have considered the benefits of VHDL in terms of implementation and tool independence, increased productivity when using synthesis with large designs, reduced iterations through board and system simulation. You can purchase a low cost synthesis tool and have one engineer use VHDL for parts of a device. You can invest more in using VHDL with simulation for your designes.
11 Examples
11.1Example for if statement
11.1.1 N-bit Comparator
---------------------------------------------------- n-bit Comparator --- this comparator has two n-bit inputs &
---------------------------------------------------
---------------------------------------------------
entity Comp is
generic(n: natural :=2); port( A: B: less: equal: in std_logic_vector(n-1 downto 0); in std_logic_vector(n-1 downto 0); out std_logic; out std_logic;
---------------------------------------------------
begin
process(A,B) begin if (A<B) then less <= '1'; equal <= '0'; greater <= '0'; elsif (A=B) then less <= '0'; equal <= '1'; greater <= '0'; else less <= '0'; equal <= '0'; greater <= '1'; end if; end process;
end behv;
---------------------------------------------------
-- Component Declaration for the Unit Under Test (UUT) COMPONENT Comp PORT( A : IN std_logic_vector(1 downto 0); B : IN std_logic_vector(1 downto 0); less : OUT std_logic; equal : OUT std_logic; greater : OUT std_logic
); END COMPONENT;
--Outputs SIGNAL less : std_logic; SIGNAL equal : std_logic; SIGNAL greater : std_logic;
BEGIN
-- Instantiate the Unit Under Test (UUT) uut: Comp PORT MAP( A => A, B => B, less => less, equal => equal, greater => greater );
tb : PROCESS BEGIN
-- Wait 100 ns for global reset to finish wait for 100 ns; A<= "01"; B<= "11"; wait for 100 ns; A<= "10"; B<= "00";
END; ------------------------------------------------------------------------------------------------------------
--
SIMULATION
---------------------------------------------------
entity shift_reg is port( I: clock: shift: Q: ); end shift_reg; in std_logic; in std_logic; in std_logic; out std_logic
---------------------------------------------------
begin
-- everything happens upon the clock changing if clock'event and clock='1' then
if shift = '1' then S <= I & S(2 downto 1); end if; end if;
end process;
end behv;
----------------------------------------------------
-- Component Declaration for the Unit Under Test (UUT) COMPONENT shift_reg PORT( I : IN std_logic; clock : IN std_logic; shift : IN std_logic; Q : OUT std_logic ); END COMPONENT;
--Inputs SIGNAL I : std_logic := '0'; SIGNAL clock : std_logic := '0'; SIGNAL shift : std_logic := '0';
BEGIN
-- Instantiate the Unit Under Test (UUT) uut: shift_reg PORT MAP( I => I, clock => clock, shift => shift, Q => Q );
clk_p: PROCESS begin CLOCK <= '0'; wait FOR 10 ns; clock <= '1'; wait for 10 ns; END PROCESS;
tb : PROCESS BEGIN
-- Wait 100 ns for global reset to finish wait for 100 ns;
I<= transport '1'; shift <= '1'; wait for 100 ns; I<= transport '0'; wait for 100 ns; I<= transport '1'; -- Place stimulus here
END;
--------------------------------------------------------------
entity SRAM is generic( width: integer:=4; depth: integer:=4; addr: integer:=2); port( Clock: Enable: Read: Write: Read_Addr: in std_logic; in std_logic; in std_logic; in std_logic; in std_logic_vector(addr-1 downto 0);
--------------------------------------------------------------
type ram_type is array (0 to depth-1) of std_logic_vector(width-1 downto 0); signal tmp_ram: ram_type;
begin
-- Read Functional Section process(Clock, Read) begin if (Clock'event and Clock='1') then if Enable='1' then
if Read='1' then -- buildin function conv_integer change the type -- from std_logic_vector to integer Data_out <= tmp_ram(conv_integer(Read_Addr)); else Data_out <= (Data_out'range => 'Z'); end if; end if; end if; end process;
-- Write Functional Section process(Clock, Write) begin if (Clock'event and Clock='1') then if Enable='1' then if Write='1' then tmp_ram(conv_integer(Write_Addr)) <= Data_in; end if; end if; end if; end process;
--------------------------------------------------------------------- Test Bench for memory module --- use loop statement to test module completely --------------------------------------------------------------------
-- entity declaration
--------------------------------------------------------------------
architecture TB of MEM_TB is
component SRAM is port( Clock: Enable: Read: Write: Read_Addr: Write_Addr: Data_in: Data_out: ); end component; in std_logic; in std_logic; in std_logic; in std_logic; in std_logic_vector(1 downto 0); in std_logic_vector(1 downto 0); in std_logic_vector(3 downto 0); out std_logic_vector(3 downto 0)
signal T_Clock, T_Enable, T_Read, T_Write: std_logic; signal T_Data_in, T_Data_out: std_logic_vector(3 downto 0); signal T_Read_Addr: std_logic_vector(1 downto 0); signal T_Write_Addr: std_logic_vector(1 downto 0);
begin
U_CKT: SRAM port map (T_Clock, T_Enable, T_Read, T_Write, T_Read_Addr, T_Write_Addr, T_Data_in, T_Data_out);
Clk_sig: process begin T_Clock<='1'; wait for 5 ns; T_Clock<='0'; wait for 5 ns; end process; -- clock cycle 10 ns
T_Enable <= '1'; T_Read <= '0'; T_Write <= '0'; T_Write_Addr <= (T_Write_Addr'range => '0'); T_Read_Addr <= (T_Read_Addr'range => '0'); T_Data_in <= (T_Data_in'range => '0'); wait for 20 ns;
T_Write_Addr <= T_Write_Addr + '1'; T_Data_in <= T_Data_in + "10"; T_Write <= '1'; wait for 10 ns; assert (T_Data_out="ZZZZ") report "Something wrong!" severity Error; if (T_Data_out /= "ZZZZ") then err_cnt := err_cnt + 1; end if; end loop;
-- test read for i in 0 to 2 loop T_Read_Addr <= T_Read_Addr + '1'; T_Read <= '1'; wait for 10 ns; assert (conv_integer(T_Data_out)=2*conv_integer(T_Read_Addr)) report "Something wrong!" severity Error; if (conv_integer(T_Data_out)/=2*conv_integer(T_Read_Addr)) then err_cnt := err_cnt + 1; end if; end loop;
-- summary of all the tests if (err_cnt=0) then assert false report "Testbench of ROM completed successfully!" severity note; else assert true report "Something wrong, try again" severity error; end if;
wait;
end process;
end TB;
--------------------------------------------------------------- 32*8 ROM module -- This examples shows how to use two dimensional ARRAY -- ROM model has predefined content for read only purpose --------------------------------------------------------------
Address
--------------------------------------------------------------
constant Content: ROM_Array := ( 0 => "00000001", 1 => "00000010", 2 => "00000011", 3 => "00000100", 4 => "00000101", 5 => "00000110", 6 => "00000111", 7 => "00001000", 8 => "00001001", 9 => "00001010", 10 => "00001011", 11 => "00001100", 12 => "00001101", 13 => "00001110", 14 => "00001111", OTHERS => "11111111" -- Suppose ROM has -- prestored value -- like this table --------------
);
begin process(Clock, Reset, Read, Address) begin if( Reset = '1' ) then Data_out <= "ZZZZZZZZ"; elsif( Clock'event and Clock = '1' ) then if Enable = '1' then if( Read = '1' ) then Data_out <= Content(conv_integer(Address)); else Data_out <= "ZZZZZZZZ"; end if; end if; end if; end process; end Behav;
--------------------------------------------------------------
---------------------------------------------------------------------------------File_name :ROM_TB --DESIGNED BY : A.K.G. --Date: 13-11-2006 -------------------------------------------------------------------------------LIBRARY ieee; USE ieee.std_logic_1164.ALL; USE ieee.std_logic_unsigned.all; USE ieee.numeric_std.ALL;
-- Component Declaration for the Unit Under Test (UUT) COMPONENT ROM PORT( Clock : IN std_logic; Reset : IN std_logic; Enable : IN std_logic; Read : IN std_logic;
Address : IN std_logic_vector(4 downto 0); Data_out : OUT std_logic_vector(7 downto 0) ); END COMPONENT;
--Inputs SIGNAL Clock : std_logic := '0'; SIGNAL Reset : std_logic := '0'; SIGNAL Enable : std_logic := '0'; SIGNAL Read : std_logic := '0'; SIGNAL Address : std_logic_vector(4 downto 0) := (others=>'0');
BEGIN
-- Instantiate the Unit Under Test (UUT) uut: ROM PORT MAP( Clock => Clock, Reset => Reset, Enable => Enable, Read => Read,
clock <='0'; wait for 10 ns; clock <='1'; wait for 10 ns;
end process;
tb : PROCESS BEGIN
-- Wait 100 ns for global reset to finish wait for 100 ns; RESET <='0'; enable<='1';
address<="00001"; wait for 100 ns; address<="00010"; read<='1'; -- Place stimulus here
END;
11.3.1 Hex2led
-- Module Name:
hextoled - Behavioral
-- Uncomment the following lines to use the declarations that are -- provided for instantiating Xilinx primitive components. --library UNISIM; --use UNISIM.VComponents.all;
entity hex2led is Port ( HEX : in std_logic_vector(3 downto 0);--defines the input LED : out std_logic_vector(6 downto 0));
end hex2led;
begin
--HEX-to-seven-segment decoder -- HEX: in STD_LOGIC_VECTOR (3 downto 0); -- LED: out STD_LOGIC_VECTOR (6 downto 0); --- segment encoding --0 ---
-- 5 | | 1 ---- <- 6
-- 4 | | 2 ----3
"0010010" when "0101", --5 "0000010" when "0110", --6 "1111000" when "0111", --7 "0000000" when "1000", --8 "0010000" when "1001", --9 "0001000" when "1010", --A "0000011" when "1011", --b "1000110" when "1100", --C "0100001" when "1101", --d "0000110" when "1110", --E "0001110" when "1111", --F "1000000" when others; --0
end Behavioral;
-- Component Declaration for the Unit Under Test (UUT) COMPONENT hex2led PORT( HEX : IN std_logic_vector(3 downto 0); LED : OUT std_logic_vector(6 downto 0) ); END COMPONENT;
BEGIN
-- Instantiate the Unit Under Test (UUT) uut: hex2led PORT MAP( HEX => HEX, LED => LED );
tb : PROCESS BEGIN
-- Wait 100 ns for global reset to finish wait for 100 ns; Hex<="0001"; wait for 100 ns; Hex<="0010"; wait for 100 ns;
Hex<="0011";
wait for 100 ns; Hex<="0100"; wait for 100 ns; Hex<="0101"; wait for 100 ns; Hex<="1000";
END;
---------------------------------------------------------------------------------library IEEE;
---- Uncomment the following library declaration if instantiating ---- any Xilinx primitives in this code. --library UNISIM; --use UNISIM.VComponents.all; entity mux4 is Port ( sel : in integer range 0 to 3; d0 : in STD_LOGIC; d1 : in STD_LOGIC; d2 : in STD_LOGIC; d3 : in STD_LOGIC; z : out STD_LOGIC); end mux4;
begin output_selection: process (sel, d0, d1, d2, d3) begin case sel is
when 0 => z<= d0; when 1 => z<= d1; when 2 => z<= d2; when 3 => z<= d3; end case; end process output_selection;
-- Component Declaration for the Unit Under Test (UUT) COMPONENT mux4 PORT( sel : IN integer range 0 to 3; d0 : IN std_logic; d1 : IN std_logic; d2 : IN std_logic; d3 : IN std_logic; z : OUT std_logic ); END COMPONENT;
--Inputs SIGNAL d0 : std_logic := '0'; SIGNAL d1 : std_logic := '0'; SIGNAL d2 : std_logic := '0'; SIGNAL d3 : std_logic := '0'; SIGNAL sel : integer range 0 to 3;
BEGIN
-- Instantiate the Unit Under Test (UUT) uut: mux4 PORT MAP( sel => sel, d0 => d0, d1 => d1, d2 => d2, d3 => d3, z => z );
tb : PROCESS BEGIN
-- Wait 100 ns for global reset to finish wait for 100 ns;
d0 <= transport '1'; d1 <= transport '0'; d2 <= transport '1'; d3 <= transport '0'; wait for 100 ns; sel <= transport 0; wait for 100 ns; sel <= transport 1; wait for 100 ns; sel <= transport 2; wait for 100 ns; sel <= transport 3; wait; -- will wait forever END PROCESS;
END; ----------------------------------------------------------------------------------------------------------------------
-- Example of doing multiplication showing -- (1) how to use variable with in process -- (2) how to use for loop statement -- (3) algorithm of multiplication ---------------------------------------------------------
-- two 4-bit inputs and one 8-bit outputs entity multip is port( num1, num2: product: ); end multip; in std_logic_vector(1 downto 0); out std_logic_vector(3 downto 0)
variable num1_reg: std_logic_vector(2 downto 0); variable product_reg: std_logic_vector(5 downto 0);
begin
for i in 1 to 3 loop if product_reg(0)='1' then product_reg(5 downto 3) := product_reg(5 downto 3) + num1_reg(2 downto 0); end if; product_reg(5 downto 0) := '0' & product_reg(5 downto 1); end loop;
-- assign the result of computation back to output signal product <= product_reg(3 downto 0);
end process;
end behv;
----------------------------------------------------------------------------------------------------------------------
architecture TB of multip_tb is
component multip is port( num1, num2: in std_logic_vector(1 downto 0); product: ); end component; out std_logic_vector(3 downto 0)
signal T_num1, T_num2: std_logic_vector(1 downto 0); signal T_product: std_logic_vector(3 downto 0);
begin
process begin
wait for 100 ns; T_num1 <= "11"; T_num2 <= "01"; wait for 100 ns; T_num1 <= "11"; T_num2 <= "11"; wait;
end process;
end TB;
GO TO TOP
Sponsored by