1. Functions
A function accepts a number of arguments and returns a result.
Each of the arguments and the result in a function definition or
function call have a predetermined type.
When a function is called, the actual parameters in the function call
are substituted for the formal parameters
When a function is called from within an architecture, a value of
the type return-type is returned in place of the function call
A function may define its own local types, constants, variables and
nested functions and procedures
The keywords begin and end enclose a series of “sequential
statements” that are executed when the function is called
1
2. A simple example
entity Inhibit is -- a.k.a. “but-not” as in “X but not Y”
port (X,Y: in BIT;
Z: out BIT);
end Inhibit; -- end of entity declaration
architecture Inhibit_arch of Inhibit is
begin
Z <= ‘1’ when X=‘1’ and Y=‘0’ else ‘0’;
end Inhibit_arch -- end of architecture declaration
2
3. But-not gate using a function
architecture Inhibit_archf of Inhibit is
function ButNot (A,B: bit) return bit is
begin
if B = ‘0’ then return A;
else return ‘0’;
end if;
end ButNot;
begin
Z <= ButNot(X,Y);
end Inhibit_archf
3
4. Libraries
A VHDL library is a place where the compiler stores information about a
particular design project, including intermediate files that are used in the
analysis, simulation and synthesis of the design.
Library location is implementation-dependent
For a given VHDL design, the compiler automatically creates and uses a
library named “work”.
When compiler analyzes each file in the design, it puts the results there.
A complete VHDL design usually has multiple files, each containing
different design units including entities and architectures.
Not all the information needed in a design may be in the “work” library.
4
5. Libraries
A designer may rely on common definitions or functional modules
across a family of different projects.
Even small projects may use a standard library such as the one
containing IEEE standard definitions
The designer can specify the name of such a library using a
library clause at the beginning of the design file.
For example one can specify the IEEE library as
library IEEE;
Specifying a library name in a design gives it access to any
previously analyzed entities and architectures stored in the library,
but does not give access to type definitions and the like. This is
the function of “packages” and “use clauses”
5
6. Library statement in VHDL
library ieee;
-- needed if you want to use the ieee library
library unisim;
-- will see this in Xilinx-generated files
library work;
-- implicitly included in every VHDL file
6
7. What’s in a package?
A package is a file containing definitions of
“objects” that can be used in other programs
Is an ADA concept
Like the entity-architecture pair, the package is another
precursor to the OOP idea!
“object” here means signals, types, constants,
functions, procedures, components declarations, etc.
NOT objects as in OOP.
The kind of objects are signal, type,
constant, function, procedure, and
component declarations
7
8. Packages
Signals that are defined in a package are “global” signals,
available to any VHDL entity that uses the package
Types and constants defined in a package are known in any
file that uses the package
Likewise functions and procedures defined in a package can
be called in files that use the package and components can be
“instantiated” in architectures that use the package.
To use a package you say “use” … for example:
use ieee.std_logic_1164.all; -- use all
definitions in pkg
use ieee.std_logic_1164.std_ulogic -- use
just def std_ulogic type
8
9. Packages
A design can use a package by including a use clause at the
beginning of the design file
To use all the definitions in the IEEE standard 1164 package one
would write
use ieee.std_logic_1164.all;
Here “ieee” is the name of the library which has previously been
given in the library clause
Within the library , the file named “std_logic_1164” contains
the desired definitions and the suffix “all” tells the compiler to use
all of the definitions in this file
Package is not limited to standard bodies, anyone can write a
package using the proper syntax
9
10. VHDL Design Styles
VHDL Design
Styles
dataflow structural behavioral
Concurrent Components and Sequential statements
statements interconnects • Registers
• State machines
• Test benches
Subset most suitable for synthesis 10
11. VHDL Example
Entity declaration for the 2 to 1 MUX
ENTITY mux2_1 IS
PORT (in0, in1, sel: IN STD_LOGIC;
yout: OUT STD_LOGIC);
END mux2_1;
11
12. VHDL Example
Logic circuit for a 2-1 MUX device
Helpful for understanding architecture
in1
sel
yout
in0
12
13. Behavioral architecture for the 2 to 1 MUX
ARCHITECTURE a1 OF mux2_1 IS
P1: PROCESS (sel, in0, in1)
BEGIN
IF (sel = ‘0’) THEN
yout <= in0;
ELSE
yout <= in1;
END IF;
END P1;
END a1;
in1
sel
yout
in0
13
14. Structural architecture for the 2 to 1 MUX
ARCHITECTURE a2 OF mux2_1 IS
SIGNAL sel_not, in0_and, in1_and: STD_LOGIC;
COMPONENT OR_GATE PORT(x,y: IN STD_LOGIC; z: OUT STD_LOGIC);
COMPONENT AND_GATE PORT (x,y: IN STD_LOGIC; z: OUT STD_LOGIC);
COMPONENT INV_GATE PORT (x: IN STD_LOGIC; z: OUT STD_LOGIC);
BEGIN
U1: AND_GATE PORT MAP (in0, sel_not, in0_and);
U2: AND_GATE PORT MAP (in1, sel, in1_and);
U3: INV_GATE PORT MAP (sel, sel_not);
U4: OR_GATE PORT MAP (in0_and, in1_and, yout);
END a2;
in1 In1_and
sel
yout
in0 In0_and
sel_not
14
15. Dataflow architecture for the 2 to 1 MUX
ARCHITECTURE a3 OF mux2_1 IS
BEGIN
yout <= ((in0 AND NOT(sel)) OR (in1 AND sel));
END a3;
In1
sel
yout
In0
15
16. Half Adder Circuit
Looking at the truth table for a half adder, it is easy
to visualize the circuit
AB CS A
S
B
C
16
17. Full Adder Circuit
The circuit at right shows a half adder
full adder constructed from
two half adders.
XOR generates the sum
output
AND generates the carry
output half adder
[ ]
C = ( A ⋅ B + A ⋅ B ) ⋅ C ′ + ( A ⋅ B ) = ( A ⋅ B ⋅ C ′) + ( A ⋅ B ⋅ C ′) + ( A ⋅ B )
= ( A ⋅ C ′) + ( B ⋅ C ′) + ( A ⋅ B )
S = A ⊕ B ⊕ C′
17
18. -- Dataflow model for a full adder circuit
-- Library Statement declares the ieee synthesis library
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
-- Entity declaration
ENTITY fulladder IS
PORT(Ain, Bin, Cin: IN STD_LOGIC;
Cout, Sout: OUT STD_LOGIC);
END fulladder;
-- Architecture defines the function
-- In this case the function is defined using Boolean
equations
ARCHITECTURE dataflow OF fulladder IS
BEGIN
-- Concurrent Signal Assignment Statements
Sout <= Ain XOR Bin XOR Cin;
Cout <= (Ain AND Bin) OR (Ain AND Cin) OR (Bin AND Cin);
END dataflow;
19. -- Structural architecture is defined by a circuit
ARCHITECTURE structural OF fulladder IS
COMPONENT AND2
PORT( A, B: IN STD_LOGIC; F: OUT STD_LOGIC);
END COMPONENT;
COMPONENT OR3
PORT( A, B, C: IN STD_LOGIC; F: OUT STD_LOGIC);
END COMPONENT;
COMPONENT XOR2
PORT( A, B: IN STD_LOGIC; F: OUT STD_LOGIC);
END COMPONENT;
SIGNAL AXB, AB, BC, AC: STD_LOGIC;
BEGIN
F1: XOR2 port map (Ain, Bin, AXB); --Port Map Statements
F2: XOR2 port map (AXB, Cin, Sout);
F3: AND2 port map (Ain, Bin, AB);
F4: AND2 port map (Bin, Cin, BC);
F5: AND2 port map (Ain, Cin, AC);
F6: OR3 port map (AB, BC, AC, Cout);
END structural;
20. Binary Addition: 4-Bit Numbers
The following example illustrates the addition of two
4-bit numbers A(A3A2A1A0) and B(B3B2B1B0):
20
21. Binary Addition: 4-Bit Numbers
The addition can be split-up in bit
slices
Each slice performs the addition of
the bits Ai, Bi and the Carry-in bit Ci
Ci <= carry-out bit of the previous slice
Each slice is simply a full adder
21
22. 4-Bit Binary Adder
Circuit for a 4-bit parallel binary adder constructed
from full adder building blocks
22
23. LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
-- VHDL model of a 4-bit adder using four full adders
ENTITY four_bit_adder_st IS
PORT (A, B : IN STD_LOGIC_VECTOR(3 downto 0);
SUM : OUT STD_LOGIC_VECTOR(3 downto 0);
CIN : IN STD_LOGIC;
COUT : OUT STD_LOGIC);
END four_bit_adder_st;
Cin
Cout
Internal Signals
24. -- The architecture is a structural one.
ARCHITECTURE structural OF four_bit_adder_st IS
-- First all the components are declared. The full adder
-- is declared only once, even though it will be used 4
times.
COMPONENT fulladder
PORT(Ain, Bin, Cin: IN STD_LOGIC;
Cout, Sout: OUT STD_LOGIC);
END COMPONENT;
-- The full adders are connected by carry signals. These
-- must be declared also.
SIGNAL C : STD_LOGIC_VECTOR(1 to 3);
-- Port map statements are used to define full adder
-- instances and how they are connected.
BEGIN
F1: fulladder port map (A(0),B(0),CIN,C(1),SUM(0));
F2: fulladder port map (A(1),B(1),C(1),C(2),SUM(1));
F3: fulladder port map (A(2),B(2),C(2),C(3),SUM(2));
F4: fulladder port map (A(3),B(3),C(3),COUT,SUM(3));
END structural;
25. -- The architecture in this case is a dataflow one
ARCHITECTURE dataflow OF four_bit_add_df IS
-- Again there will be internal carry signals that are not
-- inputs or outputs. These must be declared as signals.
SIGNAL C : STD_LOGIC_VECTOR(1 to 3);
-- Concurrent signal assignments can be used to describe
-- each of the 4 outputs and the carry signals.
BEGIN
SUM(0) <= A(0) XOR B(0) XOR Cin;
C(1) <= (A(0) AND B(0)) OR (A(0) AND Cin) OR (B(0) AND Cin);
SUM(1) <= A(1) XOR B(1) XOR C(1);
C(2) <= (A(1) AND B(1)) OR (A(1) AND C(1)) OR (B(1) AND C(1));
SUM(2) <= A(2) XOR B(2) XOR C(2);
C(3) <= (A(2) AND B(2)) OR (A(2) AND C(2)) OR (B(2) AND C(2));
SUM(3) <= A(3) XOR B(3) XOR C(3);
COUT <= (A(3) AND B(3)) OR (A(3) AND C(3)) OR (B(3) AND C(3));
END dataflow;
26. D latch with an async clear and level sensitivity
library IEEE;
use IEEE.Std_logic_1164.all;
entity latch_wc is
port (CLK, D, CLR: in Std_logic;
Q: out Std_logic);
end latch_wc; CLR
Architecture design of latch_wc is
begin
process (CLK, D, CLR)
begin
if CLR = '1' then -- CLR active High
Q <= '0';
elsif CLK = '1' then -- CLK active High
Q <= D; -- note that Q is not assigned
a value for CLK = '0'
end if;
end process;
end design;
26
27. D latch with asynch clear and rising-edge triggered
library IEEE;
use IEEE.Std_logic_1164.all;
entity dff_wac is
port (CLK, D, CLR: in Std_logic;
Q: out Std_logic);
CLR
end dff_wac;
Architecture design of dff_wac is
begin
process (CLK, D, CLR)
begin
if CLR = '1' then -- asynchronous CLR active High
Q <= '0';
elsif (CLK'event and CLK='1') then
Q <= D; -- CLK rising edge, CLK'event and
CLK = '1' can be replaced by the
"function" rising_edge (CLK)
end if;
end process;
end design; 27
28. T f-f with an asynch clear and rising edge triggered
library IEEE;
use IEEE.Std_logic_1164.all;
entity t_ff is
port (T, CLK, CLR: in std_logic;
Q: buffer std_logic);
end t_ff; CLR
architecture design of t_ff is
begin
process (CLK, CLR, T)
begin
if (CLR = '1') then
Q <= '0';
elsif rising_edge (CLK) then
case T is
when '0' => Q <= Q;
when '1' => Q <= not Q;
when others => Q <= '0';
end case;
end if;
28
end process;
29. JK f-f with an asynch reset and rising edge triggered
library IEEE;
use IEEE.Std_logic_1164.all;
entity JK_FF is
port (clock, J, K, reset: in std_logic; reset
Q, Qbar: out std_logic);
end JK_FF;
architecture behv of JK_FF is
signal state: std_logic; -- define the useful
signals here
signal input: std_logic_vector(1 downto 0);
29
30. JK f-f with an asynch reset and rising edge triggered
begin
input <= J & K; -- combine inputs into 2-bit vector
p: process(clock, reset) is
begin
if (reset='1') then
state <= '0';
elsif (rising_edge(clock)) then
case (input) is -- compare to the truth table
when "11" => state <= not state;
when "10" => state <= '1';
when "01" => state <= '0';
when others => null;
end case;
end if;
end process;
-- concurrent statements
Q <= state;
Qbar <= not state;
end behv; reset
30
31. JK f/f with enable using if-then-else structure
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity JK_FF_VHDL is
port( J,K: in std_logic;
Reset: in std_logic;
Clock_enable: in std_logic;
Clock: in std_logic;
Output: out std_logic);
end JK_FF_VHDL;
31
32. JK f/f with enable using if-then-else structure
architecture Behavioral of JK_FF_VHDL is
signal temp: std_logic;
begin
process (Clock)
begin
if Clock'event and Clock='1' then
if Reset='1' then temp <= '0';
elsif Clock_enable ='1' then
if (J='0' and K='0') then temp <= temp;
elsif (J='0' and K='1') then temp <= '0';
elsif (J='1' and K='0') then temp <= '1';
elsif (J='1' and K='1') then temp <= not
(temp);
end if;
end if;
end if;
end process;
Output <= temp;
end Behavioral;
32