You are on page 1of 30

Distinguish between Analog and Digital circuits.

Explain the forward and reverse biasing of diode with proper circuit
diagrams.

Explain the working principal of BJT with proper diagram.

Compare between Analog and Digital circuits.

Draw and illustrate the VI characteristics of diode.

What is transistor? Draw its symbols and give types.

Conversions: -

a. Convert 2526.12 octal number in to its equivalent Hex number.


b. Convert 1101 Binary Number into Gray Code

A=(1010)2, and B=(0101)2 ; Evaluate Y1=A+B, Y2=A-B, and Y3=B-A.

Conversions: -

a. Convert 56.43 decimal number in to its equivalent binary number.


b. Convert 49D hex number in to its equivalent octal number.

Evaluate the sum of the BCD numbers (A & B) given below: -

a. A=0111 0101 and B=0011 0101


b. A=0100 0011 and B=0011 0101

A=(0010)2, and B=(1101)2 Evaluate Y1=A-B using 2’s complement.

Convert the given number in decimal, octal, hexadecimal, Excess-3, Gray code
(1011 0101)2

List and draw the symbols of the different logic gates used in digital electronics
(Any five).
For the logic expression,
𝒀 = 𝑨𝑩 ̅ +𝑨 ̅𝑩
a) Obtain the truth table.
b) Realize this operation using basic and universal gates.

The logic equation is

F (A, B, C, D) = Σm (4,6,10,11,12,14,15)

a. Make a truth table.


b. Simplify using K-map.

Design “F” using NAND gates only.

Design the NAND gate and NOR gate using minimum basic gates. Write their
respective truth tables.

Convert the following boolean expression into the standard SOP form
̅𝑪 + 𝑨
𝒇 = 𝑨𝑩 ̅𝑩 ̅𝑫
̅ _𝑨𝑩𝑪

Design XOR gate using Basic gates. Write their respective truth tables.

Simplify the logic equation given below using Quine-McCluskey method.

Y (A, B, C, D) = Σm (0,1,3,7,8,9,11,15)

Design and implement using basic gates:


• 2-bit comparator

Design and implement using basic gates:


• Half subtractor

Design 32:1 multiplexer using 16:1 and 2:1 multiplexers.

Design and implement using basic gates:


• Full adder

Design and implement using basic gates:


• 4:1 multiplexer

Design and implement using basic gates:


• 2:4 Decoder
Design and implement using basic gates:
• 4:2 Encoder

Design and implement using basic gates:


• Half Adder

Realize SR flip-flop using NAND gate and explain its operation.

Convert the JK flip-flop to SR flip-flop and explain its conversion table and
find logic equation using K-map.

Design 4-bit ripple counter using JK flipflop. And draw the output waveform.

What is flipflop? List its types and draw the symbols of the same.
Convert the JK flip-flop to D flip-flop and explain its conversion table and find
logic equation using K-map.

Draw and explain SISO, SIPO shift registers.

Compare combinational vs sequential circuits.

Explain the operation of Master-slave JK flipflop with neat circuit diagram.

Develop VHDL code for implementation of OR, AND, NOT, logic gates.

-- VHDL Code for AND gate

-- Header file declaration

library IEEE;
use IEEE.std_logic_1164.all;

-- Entity declaration

entity andGate is

port(A : in std_logic; -- AND gate input


B : in std_logic; -- AND gate input
Y : out std_logic); -- AND gate output

end andGate;

-- Dataflow Modelling Style


-- Architecture definition
architecture andLogic of andGate is

begin

Y <= A AND B;

end andLogic;
**************************************************************

-- VHDL Code for OR gate

-- Header file declaration

library IEEE;
use IEEE.std_logic_1164.all;

-- Entity declaration

entity orGate is

port(A : in std_logic; -- OR gate input


B : in std_logic; -- OR gate input
Y : out std_logic); -- OR gate output

end orGate;

-- Dataflow Modelling Style


-- Architecture definition

architecture orLogic of orGate is

begin

Y <= A OR B;

end orLogic;

library IEEE;

use IEEE.std_logic_1164.all;

entity NOT2 is

port (A : in std_logic;

B : out std_logic);
end NOT2;

architecture data_flow of NOT2 is

begin

B <= NOT A;

end data_flow;

library IEEE;

use IEEE.std_logic_1164.all;

entity NOT2 is

port (A : in std_logic;

B : out std_logic);

end NOT2;

architecture behav of NOT2 is

begin

process (A)

begin

if A='0' then

B <= '1';

else B <= '0';

end if;

end process;

end behav;

******************************************************

How arrays are written in VHDL?


What is an array
In any software programming language, when we need to deal with a collection of elements
of the same type we can take advantage of the dedicated data structures provided by the
language. In VHDL such kind of structure is defined “array“.
We can collect any data type object in an array type, many of the predefined VHDL data types
are defined as an array of a basic data type.
An example is:

type string is array (positive range <>) of character;


type bit_vector is array (natural range <>) of bit;

Figure 1 – example of VHDL array definition and addressing

VHDL array declaration


The VHDL Arrays can be may both one-dimensional (with one index) or
multidimensional (with two or more indices).
When we declare an array, we can decide if the array is

• Constrained
• Urnconstrained

In the constrained array, he bounds for an index are established when the
array type is defined
In the unconstrained array, the bounds are established subsequently during
the declaration of the variable or signal.
The BNF for declaring an array type is:

array_type_definition ::= unconstrained_array_definition | constrained_array_definition


unconstrained_array_definition ::=
array ( index_subtype_definition { , index_subtype_definition } ) of
element_subtype_indication
constrained_array_definition ::=
array index_constraint of element_subtype_indication
index_subtype_definition ::= type_mark range <>
index_constraint ::= ( discrete_range { , discrete_range } )
discrete_range ::= discrete_subtype_indication | range
subtype_declaration ::= subtype identifier is subtype_indication ;
subtype_indication ::= [ resolution_function_name ] type_mark [ constraint ]
type_mark ::= type_name | subtype_name
constraint ::= range_constraint | index_constraint

the subtype allows the values taken on by an object to be restricted or


constrained subset of some base type.
Some examples of constrained array type declarations:

type t_vector is array (integer range <>) of real;


type t_word is array (31 downto 0) of bit;
type t_memory is array (address) of word;
type t_transform is array (1 to 4, 1 to 4) of real;
type string is array (positive range <>) of character;
type bit_vector is array (natural range <>) of bit;
signal mystring : string(1 to 255);
variable mybitvector : bit_vector(15 downto 0);

Accessing to the array object


An element of an array object can be referred to by indexing the name of the object.
Figure 1 reports an example of the signal vector and matrix addressing, here below
the VHDL code for matrix and vector definition and addressing.

type t_matrix is array (0 to 3, 0 to 7) of integer; -- matrix 4 x 8


type t_vector is array (0 to 3) of integer; -- vector 4 element
signal matrix : t_matrix;
signal vector : t_vector;
matrix(0,2) <= 5;
vector(1) <= 42;

Implementing a MUX using an array in VHDL


In this post, we describe the VHDL implementation of a MUX using the CASE-WHEN
statement. Another compact and elegant way for describing a MUX architecture in
VHDL is to use the array approach. In the VHDL code below is reported the VHDL
code of the implementation of an 8-way MUX. We defined an array of the same type
of data of the MUX then the array is referenced using the MUX selector. In a single
VHDL line, we can implement an N-way MUX.

library ieee ;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity array_mux8 is
port(
d0 : in std_logic_vector(1 downto 0);
d1 : in std_logic_vector(1 downto 0);
d2 : in std_logic_vector(1 downto 0);
d3 : in std_logic_vector(1 downto 0);
d4 : in std_logic_vector(1 downto 0);
d5 : in std_logic_vector(1 downto 0);
d6 : in std_logic_vector(1 downto 0);
d7 : in std_logic_vector(1 downto 0);
s : in std_logic_vector(2 downto 0);
m : out std_logic_vector(1 downto 0));
end array_mux8;
architecture rtl of array_mux8 is
type t_array_mux is array (0 to 7) of std_logic_vector(1 downto 0);
signal array_mux : t_array_mux;
begin
array_mux(0) <= d0;
array_mux(1) <= d1;
array_mux(2) <= d2;
array_mux(3) <= d3;
array_mux(4) <= d4;
array_mux(5) <= d5;
array_mux(6) <= d6;
array_mux(7) <= d7;
m <= array_mux(to_integer(unsigned(s)));
end rtl;

Develop VHDL code for implementation of basic and


universal logic gates.
VHDL OR Gate:

Now that we know the Truth Table, let's start scripting the VHDL code for OR
Gate. To understand the general structure of the VHDL code, please refer to the
first tutorial.

Library IEEE;
use IEEE.std_logic_1164.all;
entity OR_gate is
port(A : in std_logic;
B : in std_logic;
Y : out std_logic);
end OR_gate;
architecture orLogic of OR_gate is
begin
Y <= A OR B;
end orLogic;

First the Libraries are imported.

library IEEE;
use IEEE.std_logic_1164.all;
Since A and B are the inputs, variables A and B are mapped to “in std_logic”.
Here “in” refers to the input and std_logic refers to the standard
signal/waveform. Similarly Y is mapped to “out std_logic” which refers to the
output. Finally, the entity declaration is terminated by “end OR_gate”.

entity OR_gate is
port(A: in std_logic;
B: in std_logic;
Y: out std_logic);
end OR_gate;

Once the entity is declared, the next step is to define the architecture of the
entity (OR_gate). The architecture name is given as “orLogic”. The architecture
of the entity (OR_gate) is defined by “architecture orLogic of OR_gate is”. Now
that we know Y is the output, we know that output is nothing but the OR
operation of the two inputs A and B. So, Y is mapped to A OR B (Y<=A OR B).
The Boolean operator ‘OR’ is used to perform the OR operation between A and
B. The architecture is terminated by “end orLogic”

architecture orLogic of OR_gate is

begin
Y <= A OR B;
end orLogic;

VHDL Code for AND Gate:

library IEEE;
use IEEE.std_logic_1164.all;
entity andd_Gaate is
port(A: in std_logic;
B: in std_logic;
Y: out std_logic);
end andd_Gaate;
architecture andLogic of andd_Gaate is
begin
Y <= A AND B;
end andLogic;

First the libraries are imported.


library IEEE;
use IEEE.std_logic_1164.all;

The entity is decalred as andd_Gaate and A,B are decalred as inputs , Y


is decalred as Output.

entity andd_Gaate is
port(A: in std_logic;
B: in std_logic;
Y: out std_logic);
end and_gate;

Once the entity is declared, the next step is to define the architecture of the
entity (andd_Gaate). The architecture name is given as “andLogic”. The
architecture of the entity(and_gate) is defined by
“architecture andLogic of andd_Gaate is”. Now that we know Y is the output, we
know that output is nothing but the AND operation of the two inputs A and B.
So, Y is mapped to A AND B(Y<=A AND B). The Boolean operator ‘AND’ is used
to perform the AND operation between A and B. The architecture is terminated
by “end andLogic”

architecture andLogic of andd_Gate is


begin
Y <= A AND B;
end andLogic;

VHDL Code for NOT Gate:

library IEEE;
use IEEE.std_logic_1164.all;
entity not_gate is
port(A : in std_logic;
Y : out std_logic);
end not_gate;
architecture notLogic of not_gate is
begin
Y <= not(A) ;
end notLogic;
First, the libraries are imported.

library IEEE;
use IEEE.std_logic_1164.all;

The entity is declared as not_gate and A is declared as input, Y is declared as


Output.

entity not_gate is
port(A: in std_logic;
Y: out std_logic);
end not_gate;

Once the entity is declared, the next step is to define the architecture of the
entity (not_gate). The architecture name is given as “andLogic”. The architecture
of the entity(not_gate) is defined by “architecture notLogic of not_gate is”. Now
that we know Y is the output, we know that output is nothing but the NOT
operation of the input A. So, Y is mapped to NOT(A) (Y<=NOT(A)). The Boolean
operator ‘NOT’ is used to perform the NOT operation for A. The architecture is
terminated by “end notLogic”

VHDL Code for NOR Gate:

Since, the NOR gate is the complement of the OR Gate, the outputs of the OR
gates are inverted. The VHDL code is given below.

library IEEE;
use IEEE.std_logic_1164.all;
entity nor_gate is
port(A: in std_logic;
B: in std_logic;
Y: out std_logic);
end nor_gate;
architecture norLogic of nor_gate is
begin
Y <= not(A OR B);
end norLogic;

First, the libraries are imported.


library IEEE;
use IEEE.std_logic_1164.all;

The entity is declared as nor_gate and A, B are declared as inputs, Y


is declared as Output.

entity nor_gate is
port(A: in std_logic;
B: in std_logic;
Y: out std_logic);
end nor_gate;

Once the entity is declared, the next step is to define the architecture of the
entity (nor_gate). The architecture name is given as “norLogic”. The architecture
of the entity(nor_gate) is defined by “architecture norLogic of nor_gate is”. Now
that we know Y is the output, we know that output is nothing but the
complement of OR operation of the two inputs A and B. So Y is mapped to
NOT(A OR B) (Y<=NOT (A AND B)). The Boolean operator ‘OR’ is used to
perform the OR operation between A and B. For complementing the OR
operation NOT operator is used. The architecture is terminated
by “end norLogic”

VHDL Code for NAND Gate:

The output of the NAND Gate is nothing but the compelemnt of the AND Gate.

library IEEE;
use IEEE.std_logic_1164.all;
entity nand_gate is
port(A: in std_logic;
B: in std_logic;
Y: out std_logic);
end nand_gate;
architecture nandLogic of nand_gate is
begin
Y <= not (A and B);
end nandLogic;

First, the libraries are imported.


library IEEE;
use IEEE.std_logic_1164.all;

The entity is declared as nand_gate and A,B are declared as input, Y


is declared as Output.

entity nand_gate is
port(A: in std_logic;
B: in std_logic;
Y: out std_logic);
end nand_gate;

Once the entity is declared, the next step is to define the architecture of the
entity (nand_gate). The architecture name is given as “nandLogic”. The
architecture of the entity(nand_gate) is defined by
“architecture nandLogic of nand_gate is”. Now that we know Y is the output, we
know that output is nothing but the complement of AND operation of the two
inputs A and B. So, Y is mapped to NOT(A AND B) (Y<=NOT (A AND B)). The
Boolean operator ‘AND’ is used to perform the AND operation between A and
B. For complementing the AND operation NOT operator is used. The
architecture is terminated by “end nandLogic”.

architecture nandLogic of nand_gate is


begin
Y <= not (A and B);
end nandLogic;

VHDL Code for XOR:

library IEEE;
use IEEE.std_logic_1164.all;
entity xor_gate is
port(A: in std_logic;
B: in std_logic;
Y: out std_logic);
end xor_gate;
architecture xorLogic of xor_gate is
begin
Y <= A xor B;
end xorLogic;

First, the libraries are imported.

library IEEE;
use IEEE.std_logic_1164.all;

The entity is declared as xor_gate and A,B are declared as input, Y is declared as
Output.

entity xor_gate is
port(A: in std_logic;
B: in std_logic;
Y: out std_logic);
end xor_gate;

Once the entity is declared, the next step is to define the architecture of the
entity (xor_gate). The architecture name is given as “xorLogic”. The architecture
of the entity(xor_gate) is defined by “architecture xorLogic of xor_gate is”. Now
that we know Y is the output, we know that output is nothing but the XOR
operation of the two inputs A and B. So, Y is mapped to A XOR B(Y<=A XOR B).
The Boolean operator ‘XOR’ is used to perform the OR operation between A
and B. The architecture is terminated by “end xorLogic”

architecture xorLogic of xor_gate is


begin
Y <= A XOR B;
end xorLogic;

VHDL Code for XNOR Gate:

The output of the XNOR Gate is nothing but the complement of the XOR Gate.

library IEEE;
use IEEE.std_logic_1164.all;
entity xnor_gate is
port(A : in std_logic;
B : in std_logic;
Y : out std_logic);
end xnor_gate;
architecture xnorLogic of xnor_gate i
begin
Y <= not(A xor B);
end xnorLogic;

First, the libraries are imported.

library IEEE;
use IEEE.std_logic_1164.all;

The entity is declared as xnor_gate and A,B are declared as inputs , Y


is declared as Output.

entity xnor_gate is
port(A: in std_logic;
B: in std_logic;
Y: out std_logic);
end xnor_gate;

Once the entity is declared, the next step is to define the architecture of the
entity (xnor_gate). The architecture name is given as “xnorLogic”. The
architecture of the entity(xnor_gate) is defined by
“architecture xnorLogic of xnor_gate is”. Now that we know Y is the output, we
know that output is nothing but the complement of the XOR operation of the
two inputs A and B. So Y is mapped to NOT(A XOR B) (Y<=NOT (A XOR B)). The
Boolean operator ‘XOR’ is used to perform the AND operation between A and
B. For complementing the XOR operation NOT operator is used. The
architecture is terminated by “end xorLogic”.

architecture xnorLogic of xnor_gate i


begin
Y <= not(A xor B);
end xnorLogic;

Write short note on VHDL operators, functions and procedures.

VHDL Function
We use functions to implement small portions of code which we can reuse
throughout our designs.

In VHDL, a function is a subprogram which takes zero or more input values and
returns a calculated output value.

We can not use any construct which consumes time in a function.

The code snippet below shows the general syntax for a function in VHDL.

1 function <name>
(<arguments>) return <return_type> is

2 --
variable
declaration

3 begin

4 --
Function

5 end function <name>

We must give every function a name, as denoted by the <name> field above. This
name needs to respect the naming conventions which we discussed in a previous
post.

We must include all of the input arguments in the <arguments> field, with each
argument being separated by a comma.

A function can only ever return one value, with the <return_type> field declaring
which data type the returned value has.

We can also declare variables to use in the function. These are often used to store
intermediate values, or to make the code simpler to read.

As functions can not consume time, we can not use wait statements or after
statements inside of them.

VHDL Function Example


To better demonstrate how to use a VHDL function, let's consider a basic example.

For this example, we will write a function which takes 2 integers as arguments and
returns the sum of them.

The code snippet below shows the implementation of this example function in
VHDL.
1 function addition (a
: integer, b
: integer) return integer is

2 variable sum_result
: integer;

3 begin

4 sum_result
:= a + b;

5 return sum_result;

6 end function addition;

The first thing to note here is that the integer type is unbounded in this example.

As a result, the synthesiser will be unable to determine how many bits are needed
to store the value. Therefore, this function would not necessarily be suitable
for synthesizable code.

However, we could easily modify our code so that it no longer has this issue.

The second thing to note is that the code uses a variable to determine the return
value.

We don't need to do this but it is useful as an example of the methodology.

If we wanted to make the code more concise, we could directly return the result of
the addition operation.

The code snippet below shows how we would do this.

1 return a
+ b;

Calling a Function in VHDL


When we want to use a function in another part of our VHDL code, we have to call
it.

The method we use to do this is similar to other programming languages.

However, there are two different ways we can pass arguments to our function when
we call it.

The first method uses positional association. This means we pass parameters to the
function in the same order as we declared them in the function declaration.
The code snippet below shows how we would use positional association to call the
addition example function. In this example, in_a would map to the a parameter and
in_b would map to b.

1 -- Using
positional
association
to call a
function

2 result <=
addition(in_a,
in_b);

The second method we can use to call a function is known as named association.

When using this method, we must explicitly state which arguments maps to which
parameter.

The code snippet below shows how we would use named association to call the
addition example function. Again, in_a would map to the a parameter and in_b
would map to b in this example.

It is also possible to use a mixture of both approaches when calling a function,


although this is not advisable.

1 -- With
named
association

2 result
<=addition(a
=> in_a, b
=> in_b);

Impure Functions
The addition function which we used in our previous example is known as a pure
function. This means the value it returns dependents only on its arguments.

Prior to the VHDL-93 standard, we also had to include the pure keyword in this type
of function declaration. However, this isn't required in all subsequent versions of
VHDL.

In contrast, impure functions return a value which isn't solely dependent on its
arguments. As a result, we could call the function with the same arguments twice
and get different return values.

The syntax for the impure function is almost identical to a normal function in VHDL.
The only difference is the impure keyword at the beginning of the function
declaration, as shown in the VHDL code snippet below.

1 impure function <name>


(<arguments>) return <return_type> is

2 --
variable
declaration

3 begin

4 --
Function

5 end function <name>;

At first, it may be difficult to see the use for impure functions.

However, one common use is when we require a function which generates random
values to use in test benches.

In order to do this, we typically use an algorithm which requires a seed value. This
initialises the underlying pseudo random algorithm, allowing it to create a sequence
of apparently random numbers.

The sequence of numbers changes if we give the algorithm a different seed.


Therefore, we can set the value of the seed value using either a constant or a
different function to generate different test patterns. We can then use an impure
function to generate the next number in the sequence for the given seed.

The code snippet below shows the VHDL code for an impure function which
generates a random number. The seed1 and seed2 values would be assigned
externally to the function in this example.

The uniform function is an inbuilt VHDL command which returns a random value
between 0 and 1. This function is part of the math_real package in the ieee library.

We call impure functions in the same way as we would call pure functions.

1 impure function random(max


: real) return real is

2 variable result
: real;

3 begin

4 uniform(seed1,
seed2, result);
5 return (result
* max);

6 end function;

VHDL Procedure
Just like functions, we use procedures to implement small sections of code which
we can reuse throughout our code.

In VHDL, a procedure can have any number of inputs and can generate multiple
outputs.

Unlike functions, we can also use constructs which consume time in a procedure.

Although functions and procedures perform similar function, there are some
important differences between the two which effect when we use them.

The first difference is that procedures don't return a value in the same way as a
function. However, we can use them to assign values to one or more output.

The second major difference is that we can use wait statements and after
statements within them. However, the process which calls the procedure can't have
a sensitivity list if we wish to do this.

These two features mean procedures are best used to implement simple tasks which
are repeated several times in our code. A good example of this would be driving the
pins on a known interface, such as I2C or SPI.

When declaring a procedure in VHDL, we need to include a list of inputs, outputs


and bidirectional parameters associated with the procedure. We can include as
many of each of these types as we need within the procedure.

In addition, we can declare these as signals, variables or constants. If this isn't


explicitly defined, all inputs are treated as constants whilst all output and inout
types are treated as variables.

The code snippet below shows the general syntax we use to declare a procedure in
VHDL.

1 procedure <name>
(<io_list>) is

2 --
variable
declarations

3 begin
4 --
Procedure
code

5 end procedure <name>;

VHDL Procedure Example


Let's consider a basic example to better demonstrate how to write a VHDL
procedure. We will use a basic pulse generation function, which inverts a signal for
a given amount of time.

To do this we require one input, which determines how long the pulse is, and an
inout type to generate the pulse on.

The VHDL code below shows the implementation of this example procedure.

1 procedure pulse_generate(

2 signal pulse
: inout std_logic,

3 signal pulse_length
: in time

4 ) is

5 begin

6 pulse
<= not pulse;

7 wait for pulse_length;

8 pulse
<= not pulse;

9 end procedure pulse_generate;

This example shows how the parameter list differs between a function and
procedure in VHDL.

Whilst we only declare the data type in a function, we also declare the direction and
the fact that we expect signals in this procedure.

We can also see that a wait statement in used in this procedure. We use this to hold
the pulse at the desired level.

One final thing to say about this example is that we could use an output instead of
the inout type. However, using the inout type means that we can create negative
pulses. To do this we would drive the pulse signal to 1b before calling the procedure.
Calling a Procedure in VHDL
As with functions, we must call a procedure when we want to use it in another part
of our VHDL code. The method we use to do this is similar to the method used to
call a function.

However, we also need to ensure the arguments match the object type and direction
of the procedure. This means that the types must match, as in a function, as well as
matching signals, variables and constants. If we are passing arguments which are
part of the entity declaration, we must also match the direction (in/out/inout).

Other than this subtlety, we use either named association or positional association.
We must also take care to ensure procedures which contain a wait statement are
only called within a suitable process block.

The code snippet below shows how we would map to the previously defined
pulse_generate procedure.

1 --
Positional
association

2 pulse_generate(pulse_sig,
pulse_time);

4 -- With
named
association

5 pulse_generate(

6 pulse =>
pulse_sig,

7 pulse_length
=>
in_pulse_time

8 );

VHDL Package
A VHDL package provides a convenient way of keeping a number of
related functions, procedures, type definitions, components and constants
grouped together.
This allows us to reuse any of the elements in the package in different VHDL designs.
In this sense, packages can be thought of as being similar to headers in programming
languages like C.

In our previous post on libraries in VHDL, we have already seen examples of


packages being used in our code.

Packages generally consist of two distinct parts - the package declaration and the
package body. However, we don't always need to write a package body.

The code snippet below shows the method for declaring a package in VHDL.

1 package <package_name> is

2 --
This
part is
used to
declare
the
contents
of the
package

3 end package <package_name>;

5 package body <package_name> is

6 -- The
code
defining
the
behaviour
of
functions
and
procedures

7 -- is
contained
in the
package
body

8 end package body <package_body>;

In the initial declaration, we declare the prototypes for the functions and
procedures which we wish to include in our VHDL package.
In these prototypes we simply indicate the types and number of inputs and outputs
our subprograms require.

We write the code which implements the subprograms in the package body using
the syntax we have already discussed.

It is only subprograms which require this separation between declaration and


implementation. As a result, package bodies are not required if no subprograms are
included in the package.

The code snippet below shows the syntax we use to declare procedure and function
prototypes in VHDL.

1 -- Function
prototype
declaration
in a
package

2 function <name>
(<arguments>) return <return_type>;

4 --
Procedure
prototype
declaration
in a
package

5 procedure <name>
(<io_list>);

As we saw in the post on VHDL libraries, we compile packages into libraries. To


include the package in a VHDL design unit, we must include the relevant library and
package.

The code snippet below shows the method we use to include a library and packe in
our VHDL design.

It is also possible to replace the all keyword with the name of the package elements
which we need in the design. However, we rarely see this method used in practise as
it often requires more lines of code.

1 library <library_name>;

2 use <library_name>.<package_name>.all;
Example of a VHDL Package
Let' consider a basic example to better demonstrate how we create a package in
VHDL. We will use this example package as a container for the addition function and
the pulse generator procedure we looked at previously.

As this package contains subprograms, we must create a separate package


declaration and package body.

In the package declaration, we simply declare the prototype for both of the
subprograms in the example.

The code snippet below shows how we do this.

1 package example_package is

2 -- In the
package
declaration
we only
declare
prototypes

3 function addition (a
: integer, b
: integer) return integer;

4 procedure pulse_generate( signal pulse


: inout std_logic,

5 signal pulse_length
: in time);

6 end package example_package;

We then have to create a separate package body which implements our


subprograms. The code snippet below shows how we do this.

1 package body example_package is

2 -- We
write the
code which
implements
the
functions

3 -- and
procedures
in the
package
body

5 function addition (a
: integer, b
: integer) return integer is

6 variable sum_result
: integer;

7 begin

8 sum_result
:= a + b;

9 return sum_result;

10 end function addition;

11

12 procedure pulse_generate(

13 signal pulse
: inout std_logic,

14 signal pulse_length
: in time

15 ) is

16 begin

17 pulse
<= not pulse;

18 wait for pulse_length;

19 pulse
<= not pulse;

20 end procedure pulse_generate;

21

22 end package body example_package;

Exercises
Write a VHDL function which multiplies 2 values together and returns the result.
1 function multiply (a
: integer, b
: integer) return integer is

2 begin

3 return a
* b;

4 end function multiply;


hide answer

What is the difference between a pure function and an impure function

A pure function returns a value which depends only on the value of it’s argument
but an impure function doesn’t.

hide answer

What are the two main differences between functions and procedures in VHDL?

Functions always return a value whereas procedures don’t. Functions can not
consume time whereas procedures can.

hide answer

Write a procedure which adds 2 integers together after 10 ns.

1 procedure delayed_addition(

2 signal a
: in integer,
3 signal b
: in integer,

4 signal c
: out integer

5 ) is

6 begin

7 wait for 10
ns;

8 c
&lt;=
a +
b;
9 end procedure delayed_addition;
hide answer

When do we need to include a separate package body in the code for package?

If the code contains a sub program it must be implemented in a package body.

Write basic terminology of VHDL.

You might also like