- •About This Manual
- •Additional Resources
- •Manual Contents
- •Conventions
- •Typographical
- •Online Document
- •Using Foundation Express with VHDL
- •Hardware Description Languages
- •Typical Uses for HDLs
- •Advantages of HDLs
- •About VHDL
- •Foundation Express Design Process
- •Using Foundation Express to Compile a VHDL Design
- •Design Methodology
- •Design Descriptions
- •Entities
- •Entity Generic Specifications
- •Entity Port Specifications
- •Architecture
- •Declarations
- •Components
- •Concurrent Statements
- •Constant Declarations
- •Processes
- •Signal Declarations
- •Subprograms
- •Type Declarations
- •Examples of Architectures for NAND2 Entity
- •Configurations
- •Packages
- •Using a Package
- •Package Structure
- •Package Declarations
- •Package Body
- •Resolution Functions
- •Data Types
- •Type Overview
- •Enumeration Types
- •Enumeration Overloading
- •Enumeration Encoding
- •Enumeration Encoding Values
- •Integer Types
- •Array Types
- •Constrained Array
- •Unconstrained Array
- •Array Attributes
- •Record Types
- •Record Aggregates
- •Predefined VHDL Data Types
- •Data Type BOOLEAN
- •Data Type BIT
- •Data Type CHARACTER
- •Data Type INTEGER
- •Data Type NATURAL
- •Data Type POSITIVE
- •Data Type STRING
- •Data Type BIT_VECTOR
- •Unsupported Data Types
- •Physical Types
- •Floating-Point Types
- •Access Types
- •File Types
- •Express Data Types
- •Subtypes
- •Expressions
- •Overview
- •Operators
- •Logical Operators
- •Relational Operators
- •Adding Operators
- •Unary (Signed) Operators
- •Multiplying Operators
- •Miscellaneous Arithmetic Operators
- •Operands
- •Operand Bit-Width
- •Computable Operands
- •Aggregates
- •Attributes
- •Expressions
- •Function Calls
- •Identifiers
- •Indexed Names
- •Literals
- •Numeric Literals
- •Character Literals
- •Enumeration Literals
- •String Literals
- •Qualified Expressions
- •Records and Fields
- •Slice Names
- •Limitations on Null Slices
- •Limitations on Noncomputable Slices
- •Type Conversions
- •Sequential Statements
- •Assignment Statements and Targets
- •Simple Name Targets
- •Indexed Name Targets
- •Slice Targets
- •Field Targets
- •Aggregate Targets
- •Variable Assignment Statements
- •Signal Assignment Statements
- •Variable Assignment
- •Signal Assignment
- •if Statements
- •Evaluating Conditions
- •Using the if Statement to Infer Registers and Latches
- •case Statements
- •Using Different Expression Types
- •Invalid case Statements
- •loop Statements
- •Basic loop Statement
- •while...loop Statements
- •for...loop Statements
- •Steps in the Execution of a for...loop Statement
- •for...loop Statements and Arrays
- •next Statements
- •exit Statements
- •Subprograms
- •Subprogram Always a Combinatorial Circuit
- •Subprogram Declaration and Body
- •Subprogram Calls
- •Procedure Calls
- •Function Calls
- •return Statements
- •Procedures and Functions as Design Components
- •Example with Component Implication Directives
- •Example without Component Implication Directives
- •wait Statements
- •Inferring Synchronous Logic
- •Combinatorial Versus Sequential Processes
- •null Statements
- •Concurrent Statements
- •Overview
- •process Statements
- •Combinatorial Process Example
- •Sequential Process Example
- •Driving Signals
- •block Statements
- •Nested Blocks
- •Guarded Blocks
- •Concurrent Versions of Sequential Statements
- •Concurrent Procedure Calls
- •Concurrent Signal Assignments
- •Simple Concurrent Signal Assignments
- •Conditional Signal Assignments
- •Selected Signal Assignments
- •Component Instantiation Statements
- •Direct Instantiation
- •generate Statements
- •for...generate Statements
- •Steps in the Execution of a for...generate Statement
- •Common Usage of a for...generate Statement
- •if...generate Statements
- •Register and Three-State Inference
- •Register Inference
- •The Inference Report
- •Latch Inference Warnings
- •Controlling Register Inference
- •Inferring Latches
- •Inferring Set/Reset (SR) Latches
- •Inferring D Latches
- •Inferring Master-Slave Latches
- •Inferring Flip-Flops
- •Inferring D Flip-Flops
- •Inferring JK Flip-Flops
- •Inferring Toggle Flip-Flops
- •Getting the Best Results
- •Understanding Limitations of Register Inference
- •Three-State Inference
- •Reporting Three-State Inference
- •Controlling Three-State Inference
- •Inferring Three-State Drivers
- •Inferring a Simple Three-State Driver
- •Three-State Driver with Registered Enable
- •Three-State Driver Without Registered Enable
- •Writing Circuit Descriptions
- •How Statements Are Mapped to Logic
- •Design Structure
- •Adding Structure
- •Using Variables and Signals
- •Using Parentheses
- •Using Design Knowledge
- •Optimizing Arithmetic Expressions
- •Arranging Expression Trees for Minimum Delay
- •Sharing Common Subexpressions
- •Changing an Operator Bit-Width
- •Using State Information
- •Propagating Constants
- •Sharing Complex Operators
- •Asynchronous Designs
- •Don’t Care Inference
- •Using Don’t Care Default Values
- •Differences Between Simulation and Synthesis
- •Synthesis Issues
- •Feedback Paths and Latches
- •Fully Specified Variables
- •Asynchronous Behavior
- •Understanding Superset Issues and Error Checking
- •Foundation Express Directives
- •Notation for Foundation Express Directives
- •Foundation Express Directives
- •Translation Stop and Start Pragma Directives
- •synthesis_off and synthesis_on Directives
- •Resolution Function Directives
- •Component Implication Directives
- •Foundation Express Packages
- •std_logic_1164 Package
- •std_logic_arith Package
- •Using the Package
- •Modifying the Package
- •Data Types
- •UNSIGNED
- •SIGNED
- •Conversion Functions
- •Arithmetic Functions
- •Example 10-1: Binary Arithmetic Functions
- •Example 10-2: Unary Arithmetic Functions
- •Comparison Functions
- •Example 10-3: Ordering Functions
- •Example 10-4: Equality Functions
- •Shift Functions
- •ENUM_ENCODING Attribute
- •pragma built_in
- •Type Conversion
- •numeric_std Package
- •Understanding the Limitations of numeric_std package
- •Using the Package
- •Data Types
- •Conversion Functions
- •Resize Function
- •Arithmetic Functions
- •Comparison Functions
- •Defining Logical Operators Functions
- •Shift Functions
- •Rotate Functions
- •Shift and Rotate Operators
- •std_logic_misc Package
- •ATTRIBUTES Package
- •VHDL Constructs
- •VHDL Construct Support
- •Design Units
- •Data Types
- •Declarations
- •Specifications
- •Names
- •Identifiers and Extended Identifiers
- •Specifics of Identifiers
- •Specifics of Extended Identifiers
- •Operators
- •Shift and Rotate Operators
- •xnor Operator
- •Operands and Expressions
- •Sequential Statements
- •Concurrent Statements
- •Predefined Language Environment
- •VHDL Reserved Words
- •Examples
- •Moore Machine
- •Mealy Machine
- •Read-Only Memory
- •Waveform Generator
- •Smart Waveform Generator
- •Definable-Width Adder-Subtracter
- •Count Zeros—Combinatorial Version
- •Count Zeros—Sequential Version
- •Soft Drink Machine—State Machine Version
- •Soft Drink Machine—Count Nickels Version
- •Carry-Lookahead Adder
- •Carry Value Computations
- •Implementation
- •Serial-to-Parallel Converter—Counting Bits
- •Input Format
- •Implementation Details
- •Serial-to-Parallel Converter—Shifting Bits
- •Programmable Logic Arrays
Examples
Waveform Generator Schematic
Figure A-8 Waveform Generator Schematic
When the counter STEP reaches the end of the ROM, STEP stops, generates the last value, then waits until a reset. To make the sequence automatically repeat, remove the following statement.
STEP <= ROM_RANGE’high; -- Hold at last value
Use the following statement instead (commented out in the previous example).
STEP <= ROM_RANGE’low; -- Continuous wave
Smart Waveform Generator
The smart waveform generator in the following figure is an extension of the waveform generator in the figure “Waveform Example.” But
VHDL Reference Guide |
A-27 |
VHDL Reference Guide
this smart waveform generator is capable of holding the waveform at any time step for several clock cycles.
Figure A-9 Waveform for Smart Waveform Generator
The implementation of the smart waveform generator is shown in the following example. It is similar to the waveform generator in the
“Mealy Machine Schematic” figure in the Mealy Machine section, but has two additions. A new ROM, D_ROM, has been added to hold the length of each time step. A value of 1 specifies that the corresponding time step should be one clock cycle long; a value of 80 specifies that the time step should be 80 clock cycles long. The second addition to the previous waveform generator is a delay counter that counts the clock cycles between time steps.
In the architecture of the following example, a selected signal assignment determines the value of the NEXT_STEP counter.
package ROMS is
-- a 4x13 ROM called W_ROM containing the waveform constant W_ROM_WIDTH: INTEGER := 4;
subtype W_ROM_WORD is BIT_VECTOR (1 to W_ROM_WIDTH); subtype W_ROM_RANGE is INTEGER range 0 to 12;
type W_ROM_TABLE is array (0 to 12) of W_ROM_WORD; constant W_ROM: W_ROM_TABLE := W_ROM_TABLE’(
”1100”, -- time step 0 ”1100”, -- time step 1 ”0100”, -- time step 2
A-28 |
Xilinx Development System |
Examples
”0000”, |
-- time step 3 |
”0110”, |
-- time step 4 |
”0101”, |
-- time step 5 |
”0111”, |
-- time step 6 |
”1100”, |
-- time step 7 |
”0100”, |
-- time step 8 |
”0000”, |
-- time step 9 |
”0110”, |
-- time step 10 |
”0101”, |
-- time step 11 |
”0111”); |
-- time step 12 |
-- a |
7x13 ROM called D_ROM containing the delays |
|
subtype D_ROM_WORD is INTEGER range 0 to 100; |
||
subtype D_ROM_RANGE is INTEGER range 0 to 12; |
||
type |
D_ROM_TABLE is array (0 to 12) of D_ROM_WORD; |
|
constant D_ROM: D_ROM_TABLE := D_ROM_TABLE’( |
||
|
1,80,5,1,1,1,1,20,5,1,1,1,1); |
|
end ROMS; |
|
|
use work.ROMS.all; |
|
|
entity |
WAVEFORM is |
-- Smart Waveform Generator |
port(CLOCK: in BIT; |
|
|
|
RESET: in BOOLEAN; |
|
|
WAVES: out W_ROM_WORD); |
|
end WAVEFORM; |
|
|
architecture BEHAVIOR of WAVEFORM is signal STEP, NEXT_STEP: W_ROM_RANGE; signal DELAY: D_ROM_WORD;
begin
-- Determine the value of the next time step NEXT_STEP <= W_ROM_RANGE’high when
STEP = W_ROM_RANGE’high
else
STEP + 1;
-- Keep track of which time step we are in TIMESTEP_COUNTER: process
begin
wait until CLOCK’event and CLOCK = ’1’;
if RESET then |
|
-- |
Detect reset |
STEP <= 0; |
|
-- |
Restart waveform |
elsif DELAY = 1 then |
|
|
|
STEP <= NEXT_STEP; |
-- |
Continue stepping |
|
else |
|
|
|
null; |
-- Wait for |
DELAY to count down; |
|
VHDL Reference Guide |
A-29 |
VHDL Reference Guide
end if; |
-- do nothing |
here |
end process TIMESTEP_COUNTER; |
|
|
-- Count the delay between time |
steps |
|
DELAY_COUNTER: process |
|
|
begin |
|
|
wait until CLOCK’event and CLOCK = ’1’;
if RESET then |
-- Detect reset |
DELAY <= D_ROM(0); |
-- Restart |
elsif DELAY = 1 then |
-- Have we counted down? |
DELAY <= D_ROM(NEXT_STEP); -- Next delay value |
|
else
DELAY <= DELAY - 1; -- decrement DELAY counter
end if; |
|
|
|
end |
process DELAY_COUNTER; |
|
|
WAVES |
<= W_ROM(STEP); |
-- |
Output waveform value |
end BEHAVIOR;
Figure A-10 Smart Waveform Generator Schematic
Definable-Width Adder-Subtracter
VHDL lets you create functions for use with array operands of any size. This example shows an adder-subtracter circuit that, when called, is adjusted to fit the size of its operands.
The following example shows an adder-subtracter defined for two unconstrained arrays of bits (type BIT_VECTOR) in a package named
A-30 |
Xilinx Development System |
Examples
MATH. When an unconstrained array type is used for an argument to a subprogram, the actual constraints of the array are taken from the actual parameter values in a subprogram call.
package MATH is
function ADD_SUB(L, R: BIT_VECTOR; ADD: BOOLEAN) return BIT_VECTOR;
-- Add or subtract two BIT_VECTORs of equal length end MATH;
package body MATH is
function ADD_SUB(L, R: BIT_VECTOR; ADD: BOOLEAN) return BIT_VECTOR is
variable CARRY: BIT; variable A, B, SUM:
BIT_VECTOR(L’length-1 downto 0);
begin
if ADD then
-- Prepare for an ”add” operation A := L;
B := R; CARRY := ’0’;
else
-- Prepare for a ”subtract” operation A := L;
B := not R; CARRY := ’1’;
end if;
-- Create a ripple carry chain; sum up bits for i in 0 to A’left loop
SUM(i) := A(i) xor B(i) xor CARRY; CARRY := (A(i) and B(i)) or
(A(i) and CARRY) or (CARRY and B(i));
end loop;
return SUM; -- Result end;
end MATH;
Within the function ADD_SUB, two temporary variables, A and B, are declared. These variables are declared to be the same length as L (and necessarily, R) but have their index constraints normalized to
L’length-1 downto 0. After the arguments are normalized, you can create a ripple carry adder by using a for loop.
VHDL Reference Guide |
A-31 |
