Data Modeling
Introduction
Data models can be created to provide both very high level models at
the specification and documentation level, and low levels models that allow
design and analysis below the gate level.
high level abstraction
low level, detailed modeling
A data TYPE consists of both values and operators. In this section
we consider first how to construct a TYPE, and then how to form the operators
on and between types.
Values
We define the values that objects of a TYPE can take on in
the following ways:
-
primitive scalars
-
physical
-
user defined
We create more complex, composite data structures as combinations of
-
arrays
-
records
-
access types
In addition we have information about the data structures themselves
(as well as objects, and design bodies) stored as
-
predefined attributes
-
user defined attributes
Then we see how to form constant values for these structures, no matter
how complex they become:
-
Strings, bit strings
-
constant arrays
-
aggregated constants
Operators
VHDL provides the tools to assist in the creation of
-
user-defined functions that serve as operations on the types we create,
and to do
-
type conversions between types we have created and previously defined
types.
Some of these tools are:
-
slicing and concatenation
-
operator overloading
Packages are used to
-
encapsulate data abstractions
-
provide information abstraction to the user community (e.g. type declarations>
-
provide shared routines for designers (e.g., operators)
Data Abstraction
Types (a set of values)
Operations
Derived types and operations
Operations between types
Primitive Scalar Data Types
(included in Package STD.STANDARD)
These arise naturally in most problem domains
integer
real
boolean
char
--especially useful in modeling physical systems
time
-- especially useful in modeling digital systems
bit
Especially Useful Derived Data Types
(also in Package STD.STANDARD)
string (array of character)
bit_vector (array of bit)
natural ( subrange of integers)
positive ( subrange of integers )
Packages
-
between design modules
-
between people doing design
Package Declarations
We use Packages to provide definitions to be shared. The Package
Declaration contains
-
type names
-
values
-
operation names
Package Bodies
Hold
-
detailed information which can be used, but need not be seen
-
the procedures themselves which implement the operations on data types
-
any set of operations which assist in doing a particular kind of design.
-
Simplify view by removing extraneous detail
-
Avoid accidental misuse / corruption of data, misuse of data structure
-
Keep people from fixing what ain't broken
Data Abstraction Examples
Useful both in high level description and low level, detailed modelling
High level example:
Package Traffic_Package is
type color is (green, yellow, red, unknown);
function next_color ( x : color )
return color;
end Traffic_Package;
Low level example:
Package Multi_valued_logic is
type MVL is ( '0', '1', 'X', 'Z' );
function "and" ( a, b : MVL) return MVL;
function "or" ( a, b : MVL) return MVL;
function "not" ( a : MVL) return MVL;
function "nand" ( a, b : MVL) return MVL;
function "nor" ( a, b : MVL) return MVL;
function "xor" ( a, b : MVL) return MVL;
type MVL_vector is
array ( integer range <> ) of MVL;
end Multi_valued_logic;
IEEE Standard 1164
Industry standard logic system supporting 3, 4, 9 valued logic systems
PACKAGE std_logic_1164
TYPE std_ulogic IS
( 'U', -- uninitialized
'X', -- forcing unknown
'0', -- forcing 0
'1', -- forcing 1
'Z', -- high impedance
'W', -- weak unknown
'L', -- weak low (0)
'H', -- weak high (1)
'-' -- don't care
);
It also includes declarations for
functions AND, OR, NAND, NOR, XOR, XNOR, NOT for both bit logic, and
vectors
Conversion functions to bit, and subtypes UX01, X01, X01Z
User Defined Functions
Creating functions to work on a particular kind of data object, or
to convert between types of data is so routine that it frequently is not
viewed as part of providing data abstraction.
With some care and planning, in any package of data type declarations
there a well-conceived set of functions will also be declared to provide
the useful operations on objects of that data type. The implementation
of those functions should appear in the corresponding function body.
Classes of Data Types
Enumerated Types
Based on Character
Example:
type Strength_value is
( 'Z', -- resistive,
'C', -- weak,
'D', -- normal (drive),
'$' -- dominant (as in power supply)
);
Note: By using enumeration on subsets of characters it is possible to
print the values of these enumerated objects. For example, from the bidirectional
register example above, bits are :
report s & "values on s1,s0 inputs illegal.";
User-defined Names
type color is (green, yellow, red, unknown);
Note: By using user-defined names (without quotes) we drop the restriction
of one-character values, but we can no longer print them directly.
Ranges of Base Types
Ranges of Integers - for counting and indexing
type byte_range is range 0 to 255;
Ranges of Real - for measuring values within intervals
-
type RV_gen is range -1.0 to 1.0;
Why use subranges of types?
Does much to add precision to a design and improve efficiency of tools
and implementations.
Restricting the range of values for a signal may imply width of bus
or register at implementation
For test generation, it constrains the space of values from which a
test vector must be taken, or of states which may be reached.
Permits early checking of design consistency at the boundaries of values
and arrays.
Provides boundaries for dynamic checking during simulation to help ensure
model correctness.
Subtypes
Permit the definition of types either by constraining
(1) the range of values of the base type, or
(2) by adding an index constraint to a base array type.
Examples of range constrained subtypes:
subtype control_chars is character range NULL to USP ;
subtype address_range is integer range 0 to 4095 ;
subtype signed_byte is integer range -128 to 127 ;
where the user defines enumerated type
type opcodes is ( adds, addu, addl, addm, subs, subu, subl,
subm . . . );
we can create the following subtypes:
subtype addops is opcodes range adds to addm;
subtype subops is opcodes range subs to subm;
Example of index constrained subtypes:
subtype byte_reg is bit_vector (0 to 7);
Physical Data Types
Physical -- measured in terms of defined units
Values are computed using integer values and operating, but meaning
is extended by specifying the unit of measure, as well.
Example from predefined types:
type TIME is range - (2**63 -1) to (2**63 -1)
units fs ;
-- base unit femtosecond
ps = 1000 fs -- picosecond
ns = 1000 ps -- nanosecond
us = 1000 ns -- microsecond
ms = 1000 us -- millisecond
sec = 1000 ms -- second
hr = 60 min -- hour
end units;
Note: All practical implementations of simulators have found it necessary
to provide range - (2**63 -1) to (2**63 -1).
Other physical types frequently defined by users for computing timing
are
Resistance -- base unit ohms
Capacitance -- base unit picofarads (pf)
Length -- base unit microns
Making the Units Correspond
VHDL helps in writing formulas using physical units.
Addition and subtraction must be between operands of the same type,
and the result is of that type. Units will be automatically "converted"
to be the same. (Actually, all computations are performed in the base type.)
Multiplication or division of a physical type by an integer or real
produces a result of the same type.
Division of a physical type by the same physical type results in an
integer value.
Relational operations must be between operands of the same physical
type.
VHDL helps protect against bad formula writing by enforcing the rules.
Example: Trq := Tcq + Tq * (q_cap / pF);
where Trq, Tcq, and Tq are time; q_cap is of physical type capacitance
in pF.
Composing Complex Data Types
Three mechanisms for composition
Array -- indexed, ordered collection of elements of a certain type
Record of -- collection of elements of different types and use
Access -- pointer to elements of a type
Arrays
type carrier is array ( 15 downto 0 ) of MVL ;
-- two dimensional arrays to model memories
type K_word is array ( 0 to 4095 ) of carrier ;
--or
type K_word is array ( 0 to 4095, 15 downto 0 ) of MVL ;
Still better style is
subtype address_range is natural range 0 to 4095;
type mem_words is array ( address_range ) of carrier ;
Steps to forming useful, self-consistent arrays
(e.g. registers, buses, memories)
-
Form types over the indexing range for each dimension.
-
Use these types in the declaration of the array types.
-
Wherever possible use the same underlying constant(s).
Examples:
constant wordwidth : natural := 8;
constant rightbit : natural := wordwidth-1;
constant high_adrs: natural := 2**wordwidth-1;
subtype bits is natural range 0 to rightbit;
subtype addresses is natural range 0 to high_adrs;
type word is array (bits) of MVL;
type memory is array (addresses) of word;
Strings and Bit Vectors
constant Error_Msg : string := "System Fries!!"
Examples of bit strings, in binary, octal, and hex notation.
constant Zeros : bit_vector := B"0000_0000" ;
constant empty: bit_vector := O"052";
constant restart: bit_vector := X"0FC";
Note the leading, B, O, and X. The underscore is legal and purely cosmetic.
Example:
We use '0', '1', 'X', 'Z' in std_logic. Since the base type is
character for this enumerated type, we can now use string notation for
the vector type and write:
constant ZZZs : MVL_vector := "ZZZZ_ZZZZ" ;
These are actually special cases of aggregated constants, discussed later.
Unconstrained Arrays
Lets the size of the array to be left undefined in the model, to be
set to a value established by the environment into which the model is placed.
A different value is possible for each instance of the model.
Form:
type name is array ( type range <> ) of base_type ;
Note: the type of the dimension is named, but the index range and direction
are not.
Example: A general purpose ALU is designed.
In Package std_logic_1164 there is a declaration:
TYPE std_logic_vector is
ARRAY (NATURAL RANGE <>) of std_logic;
This permits us to write the following entity declaration:
ENTITY alu
( left, right : in std_logic_vector;
result : out std_logic_vector;
cy_in : in std_logic;
cy_out : out std_logic;
CTL : in std_logic_vector(0 to 3)
);
is end ALU;
Strings and Bit_vectors are pre-defined, unconstrained arrays.
How are Arrays Constrained?
-
Constant arrays: by the size of the values defined to go into them.
Example: constant Panic : string := "Help!!";
makes Panic a six element string.
By declaring a subtype of the unconstrained type with index constraints.
Example: subtype xregs : bit_vector(0 to WORDLEN-1);
By declaring objects of unconstrained types with the constraints added.
Example: signal AX : bit_vector(0 to WORDLEN-1);
By mapping actual signals with ranges to the formal ports when components
are instantiated, or procedures / functions are called.
Records
Records collect elements of different types or meaning into a single
object. VHDL objects are similar to Pascal and ADA records, and C, C++
structures.
Examples of Record Use
type Operations is
( mov, add, sub, adc, sbb, bra, call ,
inc, dec, push, pop, shf, rot, flag );
type Address_mode is
( reg, direct, indirect, displacement, indexed, immediate );
type xreg is ( ax, bx, cx, dx, sp, bp, si, di );
type Instruction is record
opcode : Operations;
condition : Secondary_ops;
src_mode: Address_mode;
src_reg : xreg;
dst_mode: Address_mode;
dst_reg : reg;
end record;
signal IR : Instruction;
signal program : ARRAY (1 to Pgm_length) OF Instruction;
We can refer to the condition field of the IR register with
IR.condition
The opcode of the i-th instruction of program is
program(i).opcode
Note that we are likely to use case branching with processes which select
using the operations, secondary_ops, and address_mode types.
Low level use: definition of strength logic value
type iVal is record
v : BIT_5;
s : Strength_logic;
end record;
References (to a signal X of type iVal) then appear as
X.v X.s
Access (Pointers)
Predefined Attributes
Certain characteristics of types and objects (besides value) are important
and can be referenced using attribute notation. As an example, for arrays
the range of index values and the ordering (high to low / low to high)
are needed in writing for loops and generate statements.
Attributes with constant values
left, right, low, high,
range, length, reverse_range
type byte_index is range 7 downto 0 ;
There are four attributes: left, right, low, high
The values of those type attributes for this example are:
byte_index'left = 7
byte_index'right = 0
byte_index'low = 0
byte_index'high = 7
Example:
One can get similar information from attributes of array types themselves.
type long_reg is array ( 0 to 63 ) of std_logic_vector ;
The reference long_reg'right has the value 63.
Example: . . . . or from attributes of an object of the array type:
signal accumulator : long_reg ;
Then accumulator'right has the value 63.
This can be especially useful when the object was an unconstrained port
object whose size was inherited from the size of the actual signal to which
it was connected.
Examples using RANGE, REVERSE_RANGE and LENGTH:
for i in long_reg'range . . . -- means 0 to 63
for i in accumulator'reverse_range . . . -- means 63 downto 0
for i in 1 to byte_index'length . . -- means 8 (the # elements)
-- for multi-dimensional arrays, one can select the range,
-- as this example shows:
for i in x'range(1) loop
for j in x'range(2) loop
Note that when an x is an UNCONSTRAINED array, the values for the range
are UNKNOWN until BUILD time.
Generalizing Models
The generality of a model decreases rapidly with the use of hardcoded
values instead of letting the ATTRIBUTES of a few well-chosen TYPE and
OBJECT declarations provide the necessary values wherever they are needed.
Instead of USE
X(7) X(X'left)
for i in 7 downto 0 for i in byte'range
Example from Std_logic package:
FUNCTION "xor" ( l,r : std_ulogic_vector ) RETURN std_ulogic_vector IS
VARIABLE lv : std_ulogic_vector (1 TO l'LENGTH );
VARIABLE rv : std_ulogic_vector (1 TO r'LENGTH);
BEGIN
IF ( l'LENGTH /= r'LENGTH ) THEN
ASSERT FALSE
REPORT "arguments of overloaded 'xor' operator are not of the same length"
SEVERITY FAILURE;
. . . .
Copyright 1998, Ben M. Huey
Copying this document without the permission of the author is prohibited
and a violation of international copyright laws.
Rev. 2/17/98 B. Huey