Basics of VHDL
Table of Contents
Introduction to VHDL
Basic Language Concepts
Language Reference
Basics Elements
Data Types and Declarations
Structural Syntax
Module Structure
Declarations
Create Architecture
Create Behavioral
Test Bench
UCF
VHDL Resources
VHDL is an acronym
for VHSIC Hardware Description Language (VHSIC is an acronym for
Very High Speed Integrated Circuits). With HDL we can describe and
model a system in several levels of abstraction, making management
relatively clear and easy. In these systems, we can model combinational
and sequential architectures/behaviors. VHDL was originally developed
by the United States Department of Defense in order to document
application specific integrated circuits (ASICs)
to silicon chip manufactures.
In VHDL, we can describe five different primary constructs called
design units. The design units are: entity declaration, architecture
body, configuration declaration, package declaration, and package
body. In this class, we will only use entity declaration, architecture
body, and package declaration.
An entity declaration is model of one or more particular architectures;
where we define inputs, input/output, and output data flow. Architecture
body can contain either a specific architecture description of a
single or multiple combinational or sequential components. Package
declaration summarizes type, subtype, and sub-entities to be used
across design spaces.
In the architecture body we can describe two models behavioral and
structural. Structural modeling is a set of interconnected components
relating to a combinational circuit in a concurrent structure. The
data flow of the interconnected signals is significant, so independent
signals must be declared first. The expression representing these
statements is on the right-hand-side of the assignment operator
and the left-hand-side of the statement is known as a target signal.
In contrast, behavioral modeling is set of sequential statements
executed in specified order; these sequential statements are described
in a process statement. A process statement is a concurrent statement
that appears within an architecture body. Each process statement
requires a sensitivity list, where independent must be checked before
evaluating target signals. A process statement executes it contents
in the ordered sequence continuously, which is why a process statement
is a concurrent statement because multiple processes can be executing
at the same time. It is possible to mix the modeling styles, just
remember what you are trying to represent.
When a model is described, it can be testing using a test bench
simulation. The simulation is used in advanced timing and result
analysis. The simulation can be halted by using assert or wait statement
indicating an error or successful test run.
The tool-chain to compile the HDL onto the fabric happens in several
steps. These steps are logical synthesis, translation, technology
mapping, and placement and routing. Logical synthesis is the process
of abstracting the HDL in terms of logical gates; an example is
Berkeley's ABC.
The logical synthesis process uses algorithms and data structures
to reduce and optimize the logical gates for several design strategies,
including area and delay. When the logical synthesis process is
complete, the data is sent to translation. The translation is the
first step in the implementation process, where all inputs, outputs,
and design constraints are put into a logical structure to be used
for the target fabric; translation then sends the data to technology
mapping. Technology mapping takes the logical structure and creates
lower-level primitives for placement and routing; and example is
VPR.
Placement and routing then takes the primitives and places these
on the specific fabric with all logical structure and interconnect.
Signals are similar to variables and constants and can be
assigned and read values, however a signal cannot be read and written
at the same time because these relate to physical wires. Signals
can be many types and the convention for synthesis is standard logic
or standard logic vector, which is essentially a bit or group of
bits. Signals of type standard logic can take the values 0, 1, or
Z (high-impedance).
Signals are similar to variables and constants and can be
assigned and read values, however a signal cannot be read and written
at the same time because these relate to physical wires. Signals
can be many types and the convention for synthesis is standard logic
or standard logic vector, which is essentially a bit or group of
bits. Signals of type standard logic can take the values 0, 1, or
Z (high-impedance).
signal A_signal : std_logic;
signal B_signal : std_logic_vector (15 downto 0);
constant C_constant : std_logic := '1';
constant D_constant : std_logic_vector(7 downto 0) := "01101011";
constant E_constant : std_logic_vector(7 downto 0) := x"F2";
constant F_constant : std_logic_vector(7 downto 0) := conv_std_logic_vector(3, 8);
An entity describes the interface to a design describing
the inputs and outputs of the hardware module. Below is an example
of a single bit full adder interface.
entity full_adder is
port(
Carry_in : in std_logic;
A : in std_logic;
B : in std_logic;
Sum : out std_logic;
Carry_out : out std_logic
);
end full_adder;
A module is complete description either structurally or behaviorally
of hardware design.
-----------------------------------------
architecture Combinational of full_adder is
begin
Sum <= A XOR B XOR Carry_in;
Carry_out <= (A AND B) OR (A OR Carry_in) OR (B AND Carry_in);
end Combinational;
-----------------------------------------
-----------------------------------------
architecture Behavioral of full_adder is
signal sum_signal : std_logic_vector(1 downto 0);
begin
Addition : process( A, B, Carry_in)
begin
sum_signal <= A + B + Carry_in;
end process : Addition;
Sum <= sum_signal(0);
Carry_out <= sum_signal(1);
end Behavioral;
-----------------------------------------
As seen in the code above, a process describes a sequence
of statements which are repeatedly executed only when a input changes
on its sensitivity list. So if A was left out of the sensitivity
list in the process above, only changes to B or Carry_in would force
a re-execution of the sequential statements in the process. Processes
are generally used in describing a behavior and concurrent statement
are used in describing structures. Processes are useful for conditional
code, such as,case switch statements and if else trees.
To use a previous made module, you must declare it as a component
similarly to declaring a function call. Declaring the component
will allow the use of this module in the code body.
component full_adder is
port(
Carry_in : in std_logic;
A : in std_logic;
B : in std_logic;
Sum : out std_logic;
Carry_out : out std_logic
);
end component;
To use a component in a hardware design after it has been declared
you must port map it to existing signals or input/output ports.
A module which only contains port maps is considered a structural
hardware design.
Unique_name : full_adder
port map(
Carry_in => carryin_signal,
A => a_signal,
B => b_signal,
Sum => sum_signal,
Carry_out => carryout_signal
);
When making modules, sometime it is useful to make them of variable
bitwidth. To dynamically change a module for that particular use,
we would want to use a generic. The generic below changes the width
of the calculation based on the value used in the component port
mapping.
entity subtractor is
generic( WIDTH : Integer := 16);
port(
A : in std_logic_vector(WIDTH-1 downto 0);
B : in std_logic_vector(WIDTH-1 downto 0);
Difference : out std_logic_vector(WIDTH-1 downto 0);
Borrow : out std_logic
);
end subtractor;
architecture Behavioral of subtractor is
signal difference_signal : std_logic_vector(WIDTH downto 0);
begin
subtraction : process( A, B )
begin
difference_signal <= A - B;
end process;
Difference <= difference_signal(WIDTH-1 downto 0);
Borrow <= difference_signal(WIDTH);
end Behavioral;
I. Basics Elements
A. Operators
1. Logical Operators
not complement, not logic, or Boolean
[name] <= not( [name] );
and logical and, operates on logical array or
Boolean
[name] <= [name] and [name];
or logical or, operates on logical array or Boolean
[name] <= [name] or [name];
nand logical complement of and, operates on logical
array or Boolean
[name] <= [name] nand [name];
nor logical complement of or, operates on logical
array or Boolean
[name] <= [name] nor [name];
xor logical exclusive or, operates on logical
array or Boolean
[name] <= [name] xor [name];
xnor logical complement of exclusive or, operates
on logical array or Boolean
[name] <= [name] xnor [name];
2. Relational Operators
= test for equality, result is Boolean
/= test for inequality, result is Boolean
< test for less than, result is Boolean
<= test for less than or equal, result is Boolean
> test for greater than, result is Boolean
>= test for greater than or equal, result is
Boolean
3. Shift Operators
sll shift left logical
[name] <= [name] sll [integer to shift by]
srl shift right logical
[name] <= [name] srl [integer to shift by]
sla shift left arithmetic
[name] <= [name] sla [integer to shift by]
sra shift right arithmetic
[name] <= [name] sra [integer to shift by]
rol rotate left
[name] <= [name] rol [integer to shift by]
ror rotate right
[name] <= [name] ror [integer to shift by]
4. Adding Operators
+ addition
[name] <= [name] + [name];
- subtraction
[name] <= [name] - [name];
& concatenation
[name] <= [name] & [name];
5. Multiply Operators
* multiplication
[name] <= [name] * [name];
/ division
[name] <= [name] / [name];
mod modulo
[name] <= [name] mod [name];
rem remainder
[name] <= [name] rem [name];
6. Miscellaneous Operators
** exponentiation
[name] <= [name] ** [name of power];
abs absolute value
[name] <= abs( [name] );
B. Conditional Statements
1. If-Then-Else Statements
if [condition] then
elsif [condition] then
else
end if;
2. Case Statements
case [expression] is
when [choice] => [statement];
...
when [choice] => [statement];
when others => [statement];
end case;
II. Data Types and Declarations
A. Signal
1. Single Signal
signal [name] : std_logic;
2. Ranged
signal [name] : std_logic_vector( [range] );
B. Convert Integer to Ranged Signal
[name] <= conv_std_logic_vector( [integer], [no. of bits
for vector] );
C. Set Target
[name] <= [name];
D. Constants
constant name : [single or ranged] := [initial value];
E. Enumerations
type enum_type is ( [name 1], [name 2], [name 3], ... ,
[name 4] );
F. Arrays and Vectors
type [name] is array ( [max value] downto [min value] )
of [single or ranged];
G. Subtypes: used to restrict range/values a type can have.
subtype [subtype name] is [ranged] range [max value] to
[min value];
III. Structural Syntax
A. Signal Assignments
1. General
[signal name] <= [expression];
2. Set Ranged to a Single Bit Value
[signal name] <= (others => '[1,0]');
B. Process
[process name] : process( [sensitive signals] )
Begin
[statements];
end process [process name];
C. Signal Assign Statement
[target out signal] <= [signal choice or value] when [condition]
else [signal choice];
D. Signal Select Statement
with [expression] select [target] <=
[out signal value] when [component name],
...,
[out signal value] when [component name],
[out signal value] when others;
E. Generate Statement
[generate name] : for [variable] in [min value] to [max
value] generate
[array name] : [component name]
generic map (
[generic name] => [constant, value, or variables],
...
[generic name] => [constant, value, or variables],
)
port map (
[port name] => [single or ranged with variables],
...
[port name] => [single or ranged with variables]
);
end generate [generate name];
F. Component Instantiation
[component identifier] : [component name]
generic map (
[generic name] => [assigned generic],
...
[generic name] => [assigned generic],
[generic name] => [assigned generic]
)
port map (
[port name] => [assigned signal],
...
[port name] => [assigned signal],
[port name] => [assigned signal]
);
IV. Module Structure
A. Library
library [library name];
B. Use of Library
use [library name].[package].[all or parts];
C. Entity
entity [entity name] is
generic (
[name] : [data type] := [default value],
...
[name] : [data type] := [default value]
);
port (
[port name] : [direction] [single or ranged type];
...
[port name] : [direction] [single or ranged type];
[port name] : [direction] [single or ranged type]
);
end [entity name];
D. Architecture
architecture [entity architecture ] of [entity name] is
begin
[combinational];
end architecture;
V. Declarations
A. Component
component [component name] is
generic (
[name] : [type] := [default value],
...
[name] : [type] := [default value]
);
port (
[port name] : [direction] [single or ranged type];
...
[port name] : [direction] [single or ranged type]
);
end component;
VI. Create Architecture
entity [entity name] is
generic (
[name] : [data type] := [default value],
...
[name] : [data type] := [default value]
);
port (
[port name] : [direction] [single or ranged type];
...
[port name] : [direction] [single or ranged type];
[port name] : [direction] [single or ranged type]
);
end [entity name];
architecture [architecture name] of [entity name] is
[internal signals]
begin
[expression logic]
[signals to outputs]
end [architecture name];
VII. Create Behavioral
entity [entity name] is
generic (
[name] : [data type] := [default value],
...
[name] : [data type] := [default value]
);
port (
[port name] : [direction] [single or ranged type];
...
[port name] : [direction] [single or ranged type];
[port name] : [direction] [single or ranged type]
);
end [entity name];
architecture behavioral of [entity name] is
[internal signals]
begin
[processes]
[signals to outputs]
end behavioral;
VIII. Test Bench
A. Syntax for test bench only!
1. Loop statement
loop
[statement];
end loop;
2. For statement
for [variable] in [min integer] to [max integer] loop
[statement];
end loop;
3. While statement
while [condition] loop
[statement];
end loop;
4. Assertion Statement
assert [condition] "[report string]" severity [error,
failure, note, warning];
5. Report Statement
report "[string]" severity [error, failure, note, warning];
B. Structure
[libraries]
entity [testing name] is
end [testing name];
architecture [test bench name] of [testing name] is
[component declaration to test]
[input and output signals for verification]
[clock signal]
[clock constant period]
begin
[component port mapping]
[clock process]
[assign component with signals]
[Process]
[assign inputs]
[wait for clock period]
[assert if wrong]
...
[assign inputs]
[wait for clock period]
[assert if wrong]
[assert complete is all tests are valid]
[Indefinite wait statement]
[end process]
end [test bench name];
IX. UCF
#[comment]
NET "[clock name]" LOC=[PIN/PORT];
NET "[clock name]" TNM_NET = LOC= "[clock name]";
TIMESPEC "TS_[clock name]" = PERIOD "[clock name]" [time frame]
[metric prefix]hz HIGH 50%;
NET [signal name] LOC=[PIN/PORT];
NET [signal name]<[bit]> LOC=[PIN/PORT];
Comprehensive Source
http://www.csee.umbc.edu/portal/help/VHDL/
Semantics and Language explanation
http://www.cs.umbc.edu/portal/help/VHDL/summary.html
Slides on the basics
http://users.ece.gatech.edu/~sudha/book/starters-guide/
VHDL by example
http://esd.cs.ucr.edu/labs/tutorial/#gates
|