You are on page 1of 20

SMR: 2065

Advanced Training Course on FPGA Design and VHDL for Hardware


Simulation and Synthesis
26 October 2009 - 20 November 2009
Trieste - Italy
___________________________________________________________________

VHDL
Syntax Templates
and
Synthesis Constructs

Prepared and Edited by:


ICTP Multidisciplinary Laboratory
MLAB

ICTP Multidisciplinary Laboratory, MLAB, Trieste, Italy

1/19

TableofContents

SyntaxTemplates

SynthesisConstructs

I. Module Structure
A. Library
B. Entity
C. Architecture
D. Component
II. Data Objects
A. Signal
B. Constant
C. Variable
III. Concurrent Statements
A. Boolean Equations
B. when-else Cond. Signal Assignment
C. with-select-when Cond. Signal Assignment
IV. Sequential Statements
A. Process
B. if-then-else Conditional Statement
C. case-when Conditional Statement

2
2
3
4
5
5
6
7
7
7
8
8
9

D. for-loop Statement

E. while-loop Statement

V.

DataTypes

VI.

ConversionFunctions

VII.

Operators

I.

Accumulator

12

II.

Adder

12

III.

SimpleComparator

12

IV.

Up/DownCounter

13

V.

BinarytoGreyConverter

13

VI.

LinearFeedbackShiftRegister 14

VII.

3to8Decoder

14

VIII.

8to3Encoder

15

IX.

DTypeFlipFlop

15

X.

DebouncingCircuit

16

XI.

4to1Multiplexer

16

XII.

PISOShiftRegister

17

XIII.

SIPOShiftRegister

17

XIV.

TriStateBuffer(2Examples) 17

XV.

FiniteStateMachine

10
11
11

28

SyntaxTemplates
I.ModuleStructure
A. Library
Library: A collection of VHDL design units, typically used to hold reusable components and type declarations.
Package: A design unit often used to gather related component, type, constant, and subprogram declarations. Packages are compiled to
libraries.
Syntax:
library <library_name>;
use <library_name>.<package_name>.[all|<part>];

Example:
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;

B. Entity
Entity: An abstraction of a system, board, chip, component, or logic gate. An entity, or design entity, is defined by an entity declaration and
architecture body.
Entity Declaration: A design unit that defines a design entitys interface.
Mode: Associated with ports declared in an entity declaration. A mode defines the direction of signal communication for an entity, and whether
a signal is readable, writable, or both.
In: used for signals (ports) that are inputs-only to an entity.
Out: used for signals that are outputs-only and for which the values are not required internal to an entity.
Buffer: used for signals that are outputs, but for which the values are required internal to the given entity.
Inout: used for signals that are truly bidirectional.

Syntax:

Example:

entity <entity_name> is
port (
<port_name> : <mode> <type>;
<other ports>
);
end <entity_name>;

entity or_entity is
port(
input_1: in std_logic;
input_2: in std_logic;
output: out std_logic
);
end or_entity;

C. Architecture
Architecture Body: A design unit that describes the behavior or structure of a design entity. An entity declaration is paired with an architecture
body to form a complete design entity.
Syntax:

Example:

architecture <arch_name> of <entity_name> is

architecture or_entity_arch of or_entity is

{
|
|
|
|

<type-declaration>
<signal-declaration>
<constant-declaration>
<component-declaration>
}

begin
{ <process statement>
| <concurrent signal assignment statement>
| <component instantiation statement>
| }
end <arch_name>;

signal inp1: std_logic;

begin
inp1 <= input_1;
output <= inp1 or input_2;
end or_entity_arch;

D. Component
Component: A design entity instantiated in another design entity. Components are used to create hierarchy and are essentials in structural
descriptions of a design entity.
Component Declaration: A template that defines the interface of a component. At the time of synthesis, a component must be bound to a specific
entity declaration and architecture body pair.
Syntax:

Example:

component <component_name> is
port (
-- port declarations as done
in entity declarations
);
end component;

component or_entity is
port(
input_1: in std_logic;
input_2: in std_logic;
output: out std_logic
);
end component;

Component Instantiation:
Syntax:

Example:

<component_identifier>: <component_name>
port map(

or_ent_1: or_entity
port map(
input_1 => input_1_sig,
input_2 => input_2_sig,
output => output_sig);

<port_name> => <assigned_signal>,


<other ports>
);

II.DataObjects
A.

Signal

Signals are the most commonly used data object in synthesis designs. Signals have projected output waveforms. They are typically used to store
internal values or to connect components.
Signal Declaration:
Syntax:

Examples:

signal <signal_name> : <type>;

signal port_i : std_logic;


signal bus_signal: std_logic_vector(15 downto 0);
signal count: integer range 0 to 31;

Signal Assignments are scheduled, not immediate; they update projected output waveforms.
Syntax:

Example:

<signal_name> <= <expression>;

std_logic_signal_1 <= not std_logic_signal_2;


std_logic_signal <= signal_a and signal_b;
large_vector(15 downto 5) <= small_vector(10 downto 0);

B.

Constant

Constants are used to hold a static value; they are typically used to improve the readability and maintenance of code. Some common uses include
making understandable names for states in a state machine and setting maximum values for ranges of integers.

Constant Declaration:
Syntax:

Examples:

constant <constant-name> : <type> := <initial-val>;

constant state_1 : std_logic_vector := "01";


constant state_2 : std_logic_vector := "10";
constant addr_max: integer := 1024;

C. Variable
Variables can be used in processes and subprograms, that is, in sequential areas only. The scope of a variable is the process or subprogram.
Variables are most commonly used as the indices of loops o for the calculation of intermediate values, or immediate assignment. To use
the value of a variable outside of the process or subprogram in which it was declared, the value of the variable must be assigned to a
signal.
Variable Declaration:
Syntax:

Examples:

variable <variable_name> : <type>;

variable count_v: integer range 0 to 15;


variable data_v: std_logic_vector(7 downto 0);
variable condition_v: boolean;

Variable Assignments are immediate, not scheduled.


Syntax:

Example:

<variable_name> := <expression>

boolean_v := true;
temp_v(3 downto 0) := sl_vector_signal(7 downto 4);

III.ConcurrentStatements
A. Boolean Equations (the basis of most of VHDL codes is the logical interactions between signals).
Syntax:

Example:

[not] <identifier> [
[and | or | nor | nand | xor | xnor | ]
[ <identifier> ]
];

X <= not signal_1;


Y <= signal_1 and signal_2;
Z <= (not signal_1) and
(signal_2 xor (signal_3 or not signal_4))

B. when-else Conditional Signal Assignment


Syntax:

Example:

{ <expression> when <condition> else }


<expression>;

X <= 1 when
Y <= signal_1
signal_2
signal_3
signal_4

b = c else 0;
when state = idle else
when state = state_1 else
when state = state_2 else
when others;

C. with-select-when Conditional Signal Assignment


Syntax:

Example:

with <choice_expression> select

with state select

<identifier> <= { <expression> when <choice(s)> },


<expression> when <choice(s)>;

X <= 00 when st0;


11 when st1 | st2;
sig_vector when others;

IV.SequentialStatements
A. Process
Processes are essentials in behavioral descriptions of a design entity. They facilitate clock-edge specification as well as synchronization among
signal assignments. Processes are most commonly used when a signal assignment is dependent on changes in another. The dependency therein
should be reflected in the process sensitivity list.
Syntax:

Example:

[<process_name>:] process (<sensitive list>)

output_process: process(flag_signal)

{ <type-declaration>
| <constant-declaration>
| <variable-declaration>
| }
begin
{ <statement(s)> }
end process;

begin
if flag_signal = '1' then
output_vector <= "010";
else
output_vector <= "101";
end if;
end process;

NOTE: Its advisable to put all the signals used in the process into the sensitivity list.

B. if-then-else Conditional Statement


Syntax:

Example:

if <condition> then <statement(s)>


{ elsif <condition> then <statement(s)> }
[ else <statement(s)> ]
end if;

if cond_v_1 = '1' then


out_vector <= "001";
elsif cond_v_2 = '1' then
out_vector <= "110";
else
out_vector <= "000";
end if;

C. case-when Conditional Statement


Syntax:

Example:

case <expression> is
{ when <choice(s)> => <assignments>; }
when <choice(s)> => <assignments>;
end case;

case state is
when 00" => integer_signal <= 1;
when "11" => integer_signal <= 2;
when others => integer_signal <= 0;
end case;

D. for-loop Statement
Syntax:

Example:

[<loop_lavel>:]
for <identifier> in <discrete_range> loop
<statement(s)>;
end loop [<loop_lavel>];

for_loop_1:
for i in 3 downto 0 loop
if reset(i) = '1' then
out_vector(i) <= 0;
end if;
end loop for_loop_1;

E. while-loop Statement
Syntax:

Example:

[<loop_lavel>:]
while <condition> loop
<statement(s)>;
end loop [<loop_lavel>];

while_loop_1:
while (count > 0) loop
count := count - 1;
result <= result + data_in;
end loop while_loop_1;

V.DataTypes
A. Enumeration Types
Values are user-defined; commonly used to define states for a state machine.

Syntax:

Examples:

type <type_name> is ( <values> );

type state_type is (st0, st1, st2);

B. std_logic & std_logic_vector


The std_logic data type is the most frequently used type in VHDL. It is part of the std_logic_1164 package in the IEEE library and is used to represents regular two-value
logical values (as '0' and '1') as well as other common logic values like high impedance ('Z').
Further to this data type is the std_logic_vector, which represents busses in VHDL. This data type acts like an array of std_logic 'bits' in order represent such a collection

STD_LOGIC
STD_LOGIC_VECTOR

-- 'U','X','0','1','Z','W','L','H','-'
-- Natural Range of STD_LOGIC

C. boolean
BOOLEAN

-- True or False

D. bit & bit_vector


BIT
BIT_VECTOR

-- '0','1
-- Array of bits

E. ranged types
There are a couple of ways to represent numbers in VHDL. One is to use the binary/hexadecimal representation afforded by the std_logic_vector or bit_vector. While this is
useful when representing physical signals, integers are easier to use. As such an integer type and two subtypes have been defined in VHDL, but they are not implemented in
wires. They are translated to busses. Thus, to limit the physical wires that are implemented by the design, and hence make the implementation of the design more efficient, its
advisable to limit integers to specified ranges.

INTEGER
NATURAL
POSITIVE

-- 32 or 64 bits
-- Integers >= 0
-- Integers > 0

VIConversionFunctions
The VHDL language allows the usage of conversion functions. These conversion functions are generally used to convert from one type to another.
There are multiple conversion functions provided in different libraries. This is why it is important to reference the correct library in which the
conversion function is available.

VIIOperatorsDefinedintheVHDLLanguage
+
*
/
Mod
**

Addition
Subtraction
Multiplication
Divide
Modulus
Power Operator (i.e. 2**8 returns 256)

The following operators either concatenate several bits into a bus or replicate a bit or combination of bits multiple
times.

a & b & c

Concatenate a, b and c into a bus

The following logical operators are used in conditional TRUE/FALSE statements such as an if statement in order to
specify the condition for the operation.
NOT
AND (NAND)
OR (NOR)
XOR (XNOR)
=
/=
<
<=
>
>=

Not True
Both Inputs True
Either Input True
Only one Input True
Inputs Equal
Inputs Not Equal
Less-than
Less-than or Equal
Greater-than
Greater-than or Equal

SynthesisConstructs
Accumulator with synchronous Reset and Chip Enable
process (<clock>, <reset>)
begin
if <clock>='1' and <clock>'event then
if <reset>='1' then
<accumulate_out> <= (others => '0');
elsif <clock_enable>='1' then
<accumulate_out> <= <accumulate_out> + <accumulate_in>;
end if;
end if;
end process;

Adder with Carry Out


<temp_value> <= <input1> + <input2>;
<output_sum> <= <temp_value>((<adder_width>-1) downto 0);
<carry_out> <= <temp_value>(<adder_width>);

Simple Comparator
process(<clock>,<reset>)
begin
if (<reset> = '1') then
<output> <= '0';
elsif (<clock>'event and <clock> ='1') then
if ( <input1> = <input2> ) then
<output> <= '1';
else
<output> <= '0';
end if;
end if;
end process;

"

Up/Down Counter with Load, Chip Enable and asynchronous Reset


process (<clock>, <reset>)
begin
if <reset>='1' then
<count> <= (others => '0');
elsif <clock>='1' and <clock>'event then
if <clock_enable>='1' then
if <load_enable>='1' then
<count> <= <input>;
else
if <count_direction>='1' then
<count> <= <count> + 1;
else
<count> <= <count> - 1;
end if;
end if;
end if;
end if;
end process;

Binary-to-Grey Converter with Chip Enable and asynchronous Reset


<next_binary_count> <= <binary_count> + 1;
process(<clock>,<reset>)
begin
if ( <reset> = '1') then
<binary_count> <= (others => '0');
<gray_count> <= (others =>'0');
elsif ( <clock>'event and <clock> ='1') then
if <clock_enable>='1' then
<binary_count> <= <next_binary_count>;
<gray_count> <= (('0' & next_binary_count(<width-1> downto 1)) xor
<next_binary_count>);
end if;
end if;
end process;

8bit Linear Feedback Shift Register (LFSR)


process(<clock>,<reset>)
begin
if ( <reset> = '1') then
<reg_name> <= (others => '0');
elsif ( <clock>'event and <clock> ='1') then
if <clock_enable>='1' then
<reg_name>(7 downto 1) <= <reg_name>(6 downto 0) ;
<reg_name>(0) <= not(<reg_name>(7) xor <reg_name>(6) xor <reg_name>(4));
end if;
end if;
end process;

3-to-8 Decoder
process(<clock>,<reset>,<input>)
begin
if ( <reset> = '1') then
<output> <= "00000000";
elsif ( <clock>'event and <clock> ='1') then
case <input> is
when "000" => <output> <= "00000001";
when "001" => <output> <= "00000010";
when "010" => <output> <= "00000100";
when "011" => <output> <= "00001000";
when "100" => <output> <= "00010000";
when "101" => <output> <= "00100000";
when "110" => <output> <= "01000000";
when "111" => <output> <= "10000000";
when others => "00000000";
end case;
end if;
end process;

8-to-3 Encoder
process(<clock>,<reset>,<input>)
begin
if ( <reset> = '1') then
<output> <= "000";
elsif ( <clock>'event and <clock> ='1')
case <input> is
when "00000001" => <output>
when "00000010" => <output>
when "00000100" => <output>
when "00001000" => <output>
when "00010000" => <output>
when "00100000" => <output>
when "01000000" => <output>
when "10000000" => <output>
when others
=> <output>
end case;
end if;
end process;

then
<=
<=
<=
<=
<=
<=
<=
<=
<=

"000";
"001";
"010";
"011";
"100";
"101";
"110";
"111";
"000";

D-Flip-Flop with synchronous Reset and Chip Enable


process (<clock>)
begin
if <clock>'event and <clock>='1' then
if <reset>='1' then
<output> <= '0';
elsif <clock_enable> ='1' then
<output> <= <input>;
end if;
end if;
end process;

Debouncing circuit
Provides a one-shot pulse from a non-clock input, with reset
D_IN: in STD_LOGIC;
RESET: in STD_LOGIC;
clock: in STD_LOGIC;
Q_OUT: out STD_LOGIC);
**Insert the following between the 'architecture' and 'begin' keywords**
signal Q1, Q2, Q3 : std_logic;
**Insert the following after the 'begin' keyword**
process(clock, RESET)
begin
if (RESET = '1') then
Q1 <= '0';
Q2 <= '0';
Q3 <= '0';
elsif (<clock>'event and <clock> = '1') then
Q1 <= D_IN;
Q2 <= Q1;
Q3 <= Q2;
end if;
end process;

Q_OUT <= Q1 and Q2 and (not Q3);


4-to-1 Multiplexer
process (<selector>,<input1>,<input2>,<input3>,<input4>)
begin
case <selector> is
when "00" => <output> <= <input1>;
when "01" => <output> <= <input2>;
when "10" => <output> <= <input3>;
when "11" => <output> <= <input4>;
when others => <output> <= <input1>;
end case;
end process;

Parallel In Serial Out Shift Register


process (<clock>,<reset>)
begin
if <load_enable> = '1' then
<reg_name> <= <input>;
elsif <clock>'event and <clock>='1' then
<reg_name> <= reg_name((<width>-2) downto 0) & '0';
end if;
<output> <= <reg_name>(<width> - 1);
end process;

Serial In Parallel Out Shift Register


process (<clock>)
begin
if <clock>'event and <clock>='1' then
<reg_name> <= reg_name((<width>-2) downto 0) & <input>;
end if;
<output> <= <reg_name>;
end process;

Tri-State Buffer (Example 1)


process (<enable>, <input>)
begin
if (<enable>='0') then
<output> <= <input>;
else
<output> <= 'Z';
end if;
end process;

Tri-State Buffer (Example 2)


<output> <= <input> when <enable> ='0' else 'Z';

Finite State Machine


Moore State Machine A state machine in which outputs change synchronously with respect to the clock.
Mealy State Machine A state machine with outputs that may change asynchronously with respect to the clock.
Example using enumerated types:
Insert the following in the architecture before the begin keyword (use descriptive names for the states):
type state_type is (st1_<name_state>, st2_<name_state>, ...);
signal current_state, next_state : state_type;
Declare internal signals for all outputs of the state machine:
signal <output>_i : std_logic;

-- example output signal

Insert the following in the architecture after the begin keyword:


SYNC_PROC: process (CLOCK, RESET)
begin
if (<reset>='1') then
current_state <= st1_<name_state>;
<output> <= '0';
elsif (<clock>'event and <clock> = '1') then
current_state <= next_state;
<output> <= <output>_i;

-- assign other outputs to reset value

-- output signals synchronization


-- assign other outputs to internal signals

end if;
end process;
MEALY State Machine - Outputs based on state and inputs
OUTPUT_DECODE: process (current_state, <input1>, <input2>, ...)
begin
--insert statements to decode internal output signals
--below is simple example
if (current_state = st3_<name> and <input1> = '1') then
<output>_i <= '1';
else
<output>_i <= '0';
end if;
end process;

NEXT_STATE_DECODE: process (state, <input1>, <input2>, ...)


begin
--declare default state for next_state to avoid latches
next_state <= current_state;
-- default is to stay in current state
--insert statements to decode next_state
--below is a simple example
case (state) is
when st1_<name> =>
if <input_1> = '1' then
next_state <= st2_<name>;
end if;
when st2_<name> =>
if <input_2> = '1' then
next_state <= st3_<name>;
end if;
when st3_<name> =>
next_state <= st1_<name>;
when others =>
next_state <= st1_<name>;
end case;
end process;
NOTE: All the input signals should be synchronized

You might also like