Electronics Adventures: Hardware Description
Guide to VHDL for Digital Systems' Design.
VHDL
Very high-speed integrated circuit Hardware Description Language is a used to describe programmable digital Systems On Chip.
I created this guide out of interest, to act as a cheat-sheet for my personal use.
There were many high quality guides for Verilog, but not so many for VHDL.
Overview
VHDL is neither case sensitive nor sensitive to spaces.
It is a reasonable practice to adhere to consistent syntactic styling.
Hardware Description is largely concurrent instead of largely procedural.
Schematic capture is not a recommended method for digital design.
Operators
Operator groups follow precedence: exponential, logical, multiplication, addition, unary, shift, relational. There is no precedence within operator groups. A good practice will be to strongly type the description and rely as little on the precedence order.
**
Exponential.ABS
Absolute value.AND
Logical AND.OR
Logical OR.NOT
Logical NOT.NAND
Logical Not of AND.NOR
Logical Not of OR.XOR
Logical eXclusive OR.XNOR
Logical eXclusive Not of OR.*
Multiplication./
Division.MOD
Modulus.REM
Remainder.+
Addition. Unary Identity.-
Subtraction. Unary Negation.&
Concatenation (of bits).SLL
Shift Left Logically.SRL
Shift Right Logically.SRA
Shift Right Arithmetically.SLA
Shift Left Arithmetically.ROL
ROtate Left.ROR
ROtate Right.=
Equality./=
Inequality.<
Less than.<=
Less than or equal to.>
Greater than.>=
Greater than or equal to.--
Single line comments. No method for block comments.
Use ‘single’ quotes for single bit value; “double quotes” for bit sequence.
Library
Use standard libraries for cross compiler compatibility.
1
2
3
4
5
6
7
8
9
LIBRARY name_of_library;
USE name_of_library.module.all;
-- example
LIBRARY ieee;
USE ieee.numeric_std.all;
USE ieee.numeric_bit.all;
USE ieee.std_logic_1164.all;
Entity
Entity is model interface.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
ENTITY name_of_entity IS
PORT (
name_of_first_port, name_of_second_port: IN data_type;
name_of_third_port: OUT data_type;
name_of_fourth_port: INOUT data_type;
-- decare more ports
);
GENERIC (
name_of_generic: data_type := value;
-- declare more generics
);
CONSTANT: name_of_constant: data_type := value;
END name_of_entity;
Architecture
Architecture is model behavior.
Implementation can follow data-flow model (or functional model), behavioural model, structural model or a combination of one or more of the three. Functional model uses more of concurrent, conditional and selective signal assignments. Behavioural model uses more of process statements. Hierarchical design and reuse of design units follow the structural model.
1
2
3
4
5
6
7
8
9
ARCHITECTURE behavior OF name_of_entity IS
SIGNAL name_of_signal: data_type; -- optional local declaration
COMPONENT name_of_component IS
-- define ports
END
BEGIN
-- architecture behavior
END behavior;
Signals are like wires inside the model. Delay cannot be synthesized, but they can be assigned to signals for simulation. Variables are much more abstract.
1
2
3
4
5
6
7
8
9
10
-- inertial delay
output <= input_after_processing AFTER few ns; -- replace "few" with a number
-- transport delay
output <= TRANSPORT input_after_processing AFTER few ns; -- replace "few" with a number
-- delays are used only for simulation purpose
-- transport delay assumes that the signal needs some time to transmit
-- inertial delay assumes the time to process the input
Process
Basic functional units.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
PROCESS (first_variable_to_watch, second_variable_to_watch)
VARIABLE name_of_local_variable : data_type;
BEGIN
-- process behavior
END PROCESS;
-- process can be named with an optional label as well
label : PROCESS (first_variable_to_watch, second_variable_to_watch) IS
-- variables_to_watch form the sensitivity list
VARIABLE name_of_local_variable : data_type;
BEGIN
-- process behavior
END PROCESS label;
When-Else
1
2
3
4
name_of_target_signal <= value_or_source_signal WHEN first_expression ELSE
another_value_or_source_signal WHEN second_expression ELSE
default_value_or_source_signal;
With-Select-When
1
2
3
4
5
6
7
8
9
WITH expression_to_evaluate SELECT
name_of_target_signal <= value_or_source_signal WHEN value_of_evaluated_expression,
another_value_or_source_signal WHEN another_value_of_evaluated_expression,
yet_another_value_or_source_signal WHEN OTHERS;
-- there can be multiple values of evaluated expression in a single WHEN statement
-- multiple values need to be listed using '|' separator
-- value_or_source_signal WHEN first_value | second_value | third_value,
Case-When
1
2
3
4
5
6
7
8
9
PROCESS (variable_to_watch)
BEGIN
CASE variable_to_watch IS
WHEN value => ; -- do something
WHEN another_value => ; -- do something else
WHEN OTHERS => ; -- do everything else
END CASE;
END PROCESS;
If-Then-Else
1
2
3
4
5
6
7
8
IF (condition) THEN
; -- statements
ELSIF (condition) THEN
; -- statements
ELSE
; -- statements
END IF;
For
1
2
3
4
5
6
7
8
9
10
11
12
13
14
FOR loopvar IN start TO finish LOOP
-- loop statements
END LOOP;
FOR loopvar IN start DOWNTO finish LOOP
-- loop statements
IF (condition) THEN
NEXT;
ELSE
EXIT;
END IF;
-- more loop statements
END LOOP;
Functions
Reusable behaviours.
1
2
3
4
5
6
7
8
9
10
FUNCTION name_of_function (first_parameter, second_parameter : data_type) RETURN data_type IS
variables: data_type
BEGIN
-- do something
END;
-- some standard functions
rising_edge()
falling_edge()
Packages
Packages disseminate reusable behaviours.
1
2
3
4
5
6
7
8
PACKAGE name_of_package IS
-- header which maybe function declaration
END PACKAGE;
PACKAGE BODY name_of_package IS
-- body which maybe function definition
END PACKAGE BODY;
Procedures
Procedures can use directional parameters.
1
2
3
4
5
PROCEDURE name_of_procedure (parameters : IN data_type; parameters : OUT data_type) IS
BEGIN
-- do something
END PROCEDURE;
Assertion
1
2
3
ASSERT value <= max_value
REPORT "assertion failed";
Data Types
Derived or User-Defined data types can be derived from Native or Standard data types or other derived data types.
‘Single’ quote can be used to access the properties of data.
1
2
3
4
5
6
7
8
-- length property
unsigned_data <= to_unsigned(value, unsigned_data'LENGTH);
-- range property
FOR i IN test_data'RANGE LOOP
; -- do something
END LOOP;
Native or Standard Data Types
BIT
‘0’ or ‘1’. UseSTD_LOGIC
instead.BIT_VECTOR
UseSTD_LOGIC_VECTOR
instead.BOOLEAN
INTEGER
NATURAL
Greater than equal to zero.POSITIVE
Greater than zero.
REAL
TIME
CHARACTER
STRING
Common Derived Data Types
Use ieee.std_logic_1164
for common derived data types.
STD_LOGIC
9 values.0
Low.1
High.L
Weak low.H
Weak high.U
Uninitialized.X
High (forced) unknown.Z
High impedance. Tri-state.W
Weak unknown.-
Do not care.
SIGNED
UNSIGNED
STD_LOGIC_VECTOR
A bundle ofSTD_LOGIC
data.
Type Conversion
Use ieee.numeric_std
for type conversions.
Use of alternatives such as ieee.std_logic_arith
are discouraged as it is not as strongly evaluating as the former: extensive overloading of operators that may lead to incorrect operations without any warning.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
-- integer to signed
signed_data <= TO_SIGNED(integer_data, signed_data'LENGTH);
-- integer to unsigned
unsigned_data <= TO_UNSIGNED(integer_data, unsigned_data'LENGTH);
-- integer to std_logic_vector
-- convert to signed or unsigned before converting to std_logic_vector
std_logic_vector_data <= STD_LOGIC_VECTOR(TO_SIGNED(integer_data, std_logic_vector_data'LENGTH));
-- conversion does not change the sign of data
-- replace TO_SIGNED with TO_UNSIGNED for positive only conversion
-- std_logic_vector to signed
integer_data <= SIGNED(std_logic_vector_data)
-- std_logic_vector to unsigned
integer_data <= UNSIGNED(std_logic_vector_data)
-- std_logic_vector to integer
-- convert to signed or unsigned before converting to integer
integer_data <= TO_INTEGER(SIGNED(std_logic_vector_data));
-- conversion does not change the sign of data
-- replace SIGNED with UNSIGNED for positive only conversion
-- signed to integer
integer_data <= TO_INTEGER(signed_data);
-- signed to unsigned
unsigned_data <= UNSIGNED(signed_data);
-- signed to std_logic_vector
std_logic_vector_data <= STD_LOGIC_VECTOR(signed_data);
-- unsigned to integer
integer_data <= TO_INTEGER(unsigned_data);
-- unsigned to signed
unsigned_data <= SIGNED(unsigned_data);
-- unsigned to std_logic_vector
std_logic_vector_data <= STD_LOGIC_VECTOR(unsigned_data);
User-Defined Types
1
2
3
4
5
6
7
TYPE name_of_type IS ; -- define the type
-- example
TYPE ram IS ARRAY (0 to memory_size) OF STD_LOGIC_VECTOR (data_size downto 0);
-- replace "memory_size" by number of registers
-- replace "data_size" by number of flip-flops in each register
Enumerated Type
1
2
3
-- enumerated type has similar declaration to user-defined types
TYPE state_type IS (ST0, ST1, ST2, ST3);
Notes
GHDL and other tools can be used to simulate designs on a general purpose computer but it is better to use an actual programmable chip set. Moreover, the chip set associated softwares are often shipped with common digital blocks that can be imported for higher level design.
Verilog
Verilog is case sensitive and similarly typed as C. There are greater number of resources available for Verilog HDL including quick references and guide.
References
Not exhaustive.
- Hamblen, Hall, Furman. Rapid Prototyping of Digital Systems. SOPC Edition. Springer.
Verilog is a great alternative and commonly used.
- Palnitkar. Verilog HDL: A Guide to Digital Design and Synthesis. Pearson.