A Fairly Small VHDL Guide: Petter K Allstr Om Petter - Kallstrom@liu - Se
A Fairly Small VHDL Guide: Petter K Allstr Om Petter - Kallstrom@liu - Se
Petter Källström
[email protected]
Version: 2.1
Abstract
This VHDL guide is aimed to show you some common constructions in VHDL, together with their
hardware structure. It also tells the difference between concurrent and sequential VHDL code. The
emphasize is on RTL level (synthesizable code), but some high level VHDL code are also presented.
Contents
1 Introduction 1 4.3 Test Operations . . . . . . . . . . . . . . . . . . 9
1.1 A Simple Example . . . . . . . . . . . . . . . . 2 4.4 Vectors and Indexing . . . . . . . . . . . . . . . 10
1.2 RTL vs Behavioral VHDL . . . . . . . . . . . . 2 4.4.1 Vector Indexing . . . . . . . . . . . . . . 10
1.2.1 RTL VHDL . . . . . . . . . . . . . . . . 2 4.4.2 Vector concatenation . . . . . . . . . . . 10
1.2.2 Behavioral VHDL . . . . . . . . . . . . 2 4.4.3 Aggregation: Generating Vectors (the
1.3 Concurrent vs Sequential Syntax . . . . . . . . 2 “(others=>’0’)” syntax) . . . . . . . . 10
1.3.1 Concurrent VHDL . . . . . . . . . . . . 3 4.4.4 Shifting . . . . . . . . . . . . . . . . . . 11
1.3.2 Sequential VHDL . . . . . . . . . . . . . 3 4.5 Assignment . . . . . . . . . . . . . . . . . . . . 11
This document is a brief VHDL summary, intended as a help during the labs, rather than a read-through
document. For an introduction to VHDL, consider taking for instance Alteras 90 minutes online class in
basic VHDL[1].
1 Introduction
Very high speed integrated circuit (VHSIC) Hardware Description Language (VHDL) was initially aimed as
a way to describe good models of how digital circuits behaved. Soon, VHDL started to be used to describe
how circuits could be built.[citation needed]
1
A Fairly Small VHDL Guide
1.1 A Simple Example
The structure of a VHDL file is depicted in Code 1.
• library ⇒ Gives you access to the library ieee, which contains
all standard functions defined in VHDL.
• use ieee.std logic 1164.all; ⇒ Lets you simpler access mem-
bers from the package ieee.std logic 1164, e.g. std logic.
• Comments starts with “--” on a line.
• entity ename is {defs} end entity; ⇒ Defines the “public
interface” of the module ename. library ieee;
use ieee.std_logic_1164.all;
• port({pins}); ⇒ If the module is a chip, {pins} is the pins.
• std logic ⇒ “The” data type for digital logic. Mostly ’0’ or ’1’. -- this is a comment
• architecture aname of ename is {decl} begin {body} end entity and_dff is
architecture ⇒ Defines the “engine” of module ename. {decl} port(clk : in std_logic;
a,b : in std_logic;
contains all declaration of internal signals in the module. {body} y : out std_logic);
contains the actual logic definition. aname is the name of the end entity;
“engine”. “RTL” stands for “Register Transfer Level”.
• signal foo : std logic; ⇒ Declares an internal signal named architecture rtl of and_dff is
signal foo : std_logic;
foo of type std logic.
begin
• process(clk) begin {body} end process; ⇒ Defines a sequen- process(clk) begin
tial block that is “executed” on all events of the signal clk. if rising_edge(clk) then
• if rising edge(clk) then {stats} end if; ⇒ The code “{stats}” foo <= a and b;
end if;
will be “executed” only on positive clock flanks. Hence each
end process;
assignment here acts as a D-type flip flop (DFF, or “D-vippa” y <= foo;
in Swedish). end architecture;
• foo <= a and b; ⇒ Implement the logic AND gate, and assign
the result to (the input of) a DFF.
• y <= foo; ⇒ Y is continuously assigned the value of signal foo. Code 1: A simple VHDL example.
E.g., directly connected to foo.
2
A Fairly Small VHDL Guide
By default, the code in the architecture is concurrent, which means all statements are executed in parallel,
all the time (and hence, it does not matter in which order you write them). You can have processes, and
within those, the code is sequential.
(a) (b)
The signals are updated when the execution comes to the end of the process. Hence, the order of signal
assignments does not matter, just like in the concurrent case. Version (a) and (b) in Code 4 gives the
behavior depicted in (c).
Code 4: Two ways of writing the same thing. Note that c is “AND:ed” with the old version of (a OR b).
1
There are dirty ways to generate registers or flip flops in concurrent VHDL, but we don’t teach dirty codes.
3
A Fairly Small VHDL Guide
2 Data Types
There are some data types in VHDL that is good to know about.
106 = "000011110100001001000000"
= b"0000 1111 0100 0010 0100 0000”
= X"0F4240” (hexadecimal)
The packages ieee.std logic signed andieee.std logic unsigned contains arithmetic operations on
those.
4
A Fairly Small VHDL Guide
2.2 High Level Data Types
There are also some more data types, e.g.
• integer – an integer, signed 32 bit value.
• unsigned – an integer, unsigned 32 bit value.
• boolean – a boolean, can be true or false.
Those can be used for synthesis, but we recommend they are not.
There are more attributes as well, for instance all signals have the attribute ’event (see Section 3.6,
“Process Definitions”).
res <= ieee.std logic signed."+"(a,b); Without “use ieee.std logic signed."+";”
res <= a + b; With “use ieee.std logic signed."+";”
You can find a good list of the standard packages, and what they contains on the web page [2], and in
App A.
5
A Fairly Small VHDL Guide
3.2 Entity Definitions
The syntax for the entity definition is
entity my_add is
generic(N : integer := 16);
port(a,b : in std_logic_vector(N-1 downto 0);
res : out std_logic_vector(N downto 0));
end entity;
Here, the owner (if this is a sub module) can decide how wide the buses should be (by changing N ). By
default, the input buses are 16 bits, and the result is 17 bits.
In simulations, you can have, e.g. generic(delay : time := 10ns);, if you want to model different
delays in the design.
6
A Fairly Small VHDL Guide
3.4 Signal Declarations
Signals are declared before the begin in the architecture. The syntax is
7
A Fairly Small VHDL Guide
8
A Fairly Small VHDL Guide
4 Basic VHDL
What is stated here holds in both concurrent and sequential VHDL.
Some interesting functions from ieee.std logic misc, operating on std logic vectors.
• fun MUX2x1(in0,in1,sel) ⇒ A multiplexer, that works on std logic.
• {X} REDUCE(slv) ⇒ An N input {X} gate, fed with a vector of size N . {X} is AND, NAND, OR, NOR,
XOR or XNOR.
E.g. XNOR REDUCE(x(2 to 4)) corresponds to “not (x(2) xor x(3) xor x(4));”.
It is not possible to mix boolean and std logic (unless you define those operators yourself).
9
A Fairly Small VHDL Guide
4.4 Vectors and Indexing
VHDL have great support for vectors, e.g. std logic vector.
We use the signals in Table 2 to exemplify the operations.
Signal Type Content
x,y std logic ’x’, ’y’
an std logic vector(n-1 downto 0) "an−1 . . . a0 "
bn std logic vector(n-1 downto 0) "bn−1 . . . b0 "
cn std logic vector(n-1 downto 0) "cn−1 . . . c0 "
Examples
a4 std logic vector(3 downto 0) "a3 a2 a1 a0 "
b5 std logic vector(4 downto 0) "b4 b3 b2 b1 b0 "
10
A Fairly Small VHDL Guide
When not assigning, the index of the result is increasing, so the lowest index is to the left.
Some examples are shown in Table 5.
Expression Result Aggregation Index
(5=>’1’, 4=>’0’) "01" 4 to 5
(4=>’0’, 1 to 3=>’1’, 0=>’Z’) "Z1110" 0 to 4
(4=>’0’, 1 to 2=>’1’, 0=>’Z’) Error: index 3 is missing in range 0 to 4.
a5 <= (3=>’1’, others=>’0’) a5 = "01000" 4 downto 0
a5 <= (5=>’1’, 4 downto 1=>’0’) a5 = "10000" 5 downto 1
a5 <= ""&(5=>’1’, 4 downto 1=>’0’) a5 = "00001" 1 to 5
a5 <= (5=>’1’, others=>’0’) Error: index 5 is outside range 4 downto 0.
b5 = (b5’range => ’1’) test if all elements in b5 is one.
Aggregation is most often used for resets, something like “my signal <= (others => ’0’);”, which
fills my signal with zeros.
4.4.4 Shifting
There are six built in shift operators, listed in Table 6. Unfortunately, those are only defined for the type
bit vector, and not for any vector type.
If you want to perform a shift operations on std logic vectors, the simplest way is often to write it in
normal VHDL. Then you have also full control of what is shifted in. Examples are given in Table 7.
Since the shift operators exist at all, you can define them also for the std logic vector, as illustrated in
Code 8.
The packages ieee.std logic signed and ieee.std logic unsigned provides some shift functions,
listed in Table 8, where slvβ is a std logic vector treated as an unsigned number in all four cases.
4.5 Assignment
Assignments are done using the <= operator for signals, and the := operator for variables. The assignment
do not return a value. If a value is expected from the formula, the “≤” operator is used instead. Some
examples are given in Table 9.
The signal/variable to the left of the assignment must have the same data type as the value to the right.
In cases of vectors, the direction should also match.
11
A Fairly Small VHDL Guide
Code 8: Define the “sll” operator for the std logic vector.
Table 8: Shift functions for the std logic vector data type.
Operation Description
a <= b; signal a is assigned the content of b.
a := b; variable a is assigned the content of b.
a <= b <= c; b is compared with c, the result (boolean) is assigned to a.
a(2) <= b; Element 2 from signal a is assigned the content of b.
The assignment operator cannot be overloaded (you can for instance not define the assignment operator
that assigns an integer to a std logic vector).
5 Concurrent Constructions
Concurrent VHDL statements are “executed” continuously, and corresponds to combinational logic.
{res} <= {val1} when {cond1} else {val2} when {cond2} else ... else {valN };
Code 9: When-else: A multiplexer net, in VHDL and as a schematic (before and after optimization).
12
A Fairly Small VHDL Guide
5.2 With-Select: One Hugh Multiplexer
The syntax for the With-Select statement is
with {expr} select {res} <= {val1} when {choice1}, {val2} when {choice2}, ... {valN } when others;
architecture architecture
component and_dff is component my_add is
port(clk : in std_logic; generic(N : integer := 16);
a,b : in std_logic; port(a,b : in unsigned(N-1 downto 0);
y : out std_logic); res : out unsigned(N downto 0));
end component; end component;
begin begin
inst1 : and_dff inst1 : my_add
port map(clk => iclk, a=>ia, b=>ib, y=>iy); generic map(N => 12)
inst2 : and_dff port map(a=>ia, b=>ib, res=>ires);
port map(iclk, ia, ib, iy); inst2 : my_add
end architecture; generic map(12)
port map(ia,ib,ires);
end architecture;
(a) (b)
The => i* signals are local signals, that are connected to the port on the instantiated module. An error
will occure, since the signals iy and ires are written to from both instances inst1 and inst2. The “=>”
operator connects the pin with the local signal, independen of the direction of the pin.
In some cases the component declaration is unnecessary.
13
A Fairly Small VHDL Guide
6 Sequential Constructions
Sequential VHDL statements are “executed” sequential, when something happens on a signal in the sensi-
tivity list in a process, or when a function is called.
In concurrent constructions, a signal that is assigned should always be assigned some value.
In sequential VHDL, a signal does not have to be assigned, and will then keep it’s value (by pulling the
en signal to the DFF/reg low).
if {cond1} then {stats1} elsif {cond2} then {stats2} elsif ...else {statsN } end if;
case {expr} is when {choice1} => {stats1} when {choice2} => ... when others => {statsN } end case;
case sel is
when "101" => A <= db;
when others => B <= db;
end case;
14
A Fairly Small VHDL Guide
6.3 For Loop: Simplifies Some Tasks
The for loop have the syntax:
{lname} : for {id} in {range} loop {stats} end loop;
• {lname} : ⇒ Optional name for the loop.
• {id} ⇒ An integer, that will step through the range.
• {range} ⇒ A range, like “5 to 9” or “a’range”.
• {stats} ⇒ The statements that should be performed.
Code 14 illustrates the use of a for loop, where the operator “mod” is used in a “safe” way (i.e. not
resulting in arithmetic hardware).
Variables can be used as indexing variables (e.g. i in Code 15), or writing a temporary wire (e.g. tmp).
How variables are treated in processes:
• A variable is local within a process or function.
• A variable is assigned a value using the “:=” operator.
• An assignment of run time data to a variable corresponds to writing to a wire.
• If a variable is assigned several times in the same clock cycle, that corresponds to writing to several
wires (as illustrated in Code 15).
• From a programming perspective, the variable value is updated immediately.
• If a variable is not assigned a value, it should keep it’s previous value. Hence you can use it as a DFF,
but you should avoid it.
15
A Fairly Small VHDL Guide
7 Pipelining
Pipelining is used to speed up logics. A logic gate always contains a small delay (e.g. 3 ns). Lets say we
have the combinational net depicted in Fig. 1, which have the following propagation characteristics:
Shortest delay for any signal path 5 ns
Longest delay for any signal path 15 ns
The effect is that the longest delay in the system (from input or register to register or output) is now
only 6.4 ns. Hence we can clock the system in at most 6.41 ns ≈ 156 MHz.
One important change: The output is not available at once. The different stages of the pipeline processes
data that is a number of clock cycles late, as depicted in Table 10.
Clock cycle net1 net 2 net 3 Output
1 1 (old) (old) (old)
2 2 1 (old) (old)
3 3 2 1 (old)
4 4 3 2 1
5 5 4 3 2
Table 10: The data sets processed by the different nets from Fig. 3.
This is the main idea with pipelining. Split the design into several stages, with one clock cycle delay per
stage. If you need to feed data backwards, it’s more tricky. The pitfall: Watch out so you don’t mix data
from different time sets, that belongs in different pipeline stages.
References
[1] http://www.altera.com/customertraining/webex/VHDL/player.html
[2] http://www.csee.umbc.edu/portal/help/VHDL/stdpkg.html
16
A Fairly Small VHDL Guide
Appendix A Misc Package Declarations
This appendix aims to give a quick-and-sloppy overview of the ieee packages. They are explained more in
details in [2].
Some packages are developed by IEEE (who defined the language), and some are developed (and owned)
by Synopsys.
Notations in this appendix:
• sl ⇒ std_logic. • SI ⇒ S or int or a combina- • <=
⇒ the six comparison op-
>6=
• slv ⇒ std_logic_vector. tion, except (int,int). erators <, <=, =, /=, >=, >.
• int ⇒ integer. • UN ⇒ U or nat or a combina- • aox ⇒ the operators and,
• nat ⇒ natural (≥ 0). tion, except (nat,nat). nand, or, nor, xor and xnor.
• S ⇒ signed. • US ⇒ U or S.
• U ⇒ unsigned.
By default (without any library or use statement), VHDL defines basic types (bit, bit vector, integer,
natural, boolean, string, real, time) and some operations on those.
Warning: There are two packages called ieee.std logic arith. One from IEEE, and one from Syn-
opsys. A computer can have any of them installed, which reduces the portability of the code. Avoid those.
17
A Fairly Small VHDL Guide
A.3 ieee.std logic arith (IEEE)
Never use this package, since your system might instead have the Synopsys package, see below.
Contains own definitions of the types SIGNED and UNSIGNED, and a huge set of operators on those and on
int.
Types
• SIGNED,UNSIGNED ⇒ same def as slv, but own types.
Functions/operators
All those functions, involving S will return S, the rest will return U. All functions also exist in a version
returning slv. The comparison functions only returns boolean.
• (no logical operators are defined)
• "+", - ⇒ all combinations of S, U, int and sl. No combinations of only int and sl are available.
• +U, +S, -S.
• abs(S).
• "*" ⇒ all combinations of S and U.
• " >6
<=
= " ⇒ comparison operators for S, U, int and any combination of them. Returns only boolean.
• SHL(...,U) ⇒ shift S or U left a number of steps.
• SHR(...,U) ⇒ shift S or U right a number of steps.
• CONV INTEGER(...) ⇒ convert int, U, S or sl to int.
• CONV UNSIGNED(..., int), CONV SIGNED(..., int) ⇒ convert int, U, S or sl to U or S.
• CONV STD LOGIC VECTOR(..., int) ⇒ convert int, U, S or sl to U or slv.
• UNSIGNED(...), SIGNED(...), STD LOGIC VECTOR(...) ⇒ convert between S, U and slv.
• EXT(slv,int), SXT(slv,int) ⇒ zero resp. sign extend slv.
Arithmetic operations on slv, that treat those as unsigned and signed values respectively.
Functions/operators
• slv+slv, slv+int, int+slv,slv+sl,sl+slv. • slv*slv.
• + slv (unary operator). • slv >6
<= <= <=
= slv, slv >6= int, int >6= slv.
• - slv (only in signed). • SHL(slv,slv).
• ABS(slv) (only in signed). • SHR(slv,slv).
• slv-slv, slv-int, int-slv,slv-sl,sl-slv. • CONV_INTEGER(slv).
18