Professional Documents
Culture Documents
Explain the forward and reverse biasing of diode with proper circuit
diagrams.
Conversions: -
Conversions: -
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.
F (A, B, C, D) = Σm (4,6,10,11,12,14,15)
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.
Y (A, B, C, D) = Σm (0,1,3,7,8,9,11,15)
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.
Develop VHDL code for implementation of OR, AND, NOT, logic gates.
library IEEE;
use IEEE.std_logic_1164.all;
-- Entity declaration
entity andGate is
end andGate;
begin
Y <= A AND B;
end andLogic;
**************************************************************
library IEEE;
use IEEE.std_logic_1164.all;
-- Entity declaration
entity orGate is
end orGate;
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;
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;
begin
process (A)
begin
if A='0' then
B <= '1';
end if;
end process;
end behav;
******************************************************
• 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:
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;
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;
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”
begin
Y <= A OR B;
end orLogic;
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;
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”
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;
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”
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;
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”
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;
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”.
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;
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”
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;
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;
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”.
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.
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
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.
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;
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.
If we wanted to make the code more concise, we could directly return the result of
the addition operation.
1 return a
+ b;
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.
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.
2 --
variable
declaration
3 begin
4 --
Function
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 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.
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.
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
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;
8 pulse
<= not pulse;
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.
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
6 -- The
code
defining
the
behaviour
of
functions
and
procedures
7 -- is
contained
in the
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.
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>);
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.
In the package declaration, we simply declare the prototype for both of the
subprograms in the example.
1 package example_package is
2 -- In the
package
declaration
we only
declare
prototypes
3 function addition (a
: integer, b
: integer) return integer;
5 signal pulse_length
: in time);
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;
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;
19 pulse
<= not pulse;
21
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;
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
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
<=
a +
b;
9 end procedure delayed_addition;
hide answer
When do we need to include a separate package body in the code for package?