vhdl lab tutorial

24
Basic vhdl by Qassem Alweh

Upload: qassem-alweh

Post on 31-Oct-2014

152 views

Category:

Documents


0 download

DESCRIPTION

basic vhdl synthesis tutorial using ghdl on a linux ubuntu system.

TRANSCRIPT

Page 1: vhdl lab tutorial

Basic vhdl

by Qassem Alweh

Page 2: vhdl lab tutorial

Introduction

What is VHDL?

1. VHDL stands for ( very high speed integrated circuit hardware description language)

2. as a HDL ( hardware description language) VHDL is used for formal description and design of digital logic, it describes the circuit's operation, its design and organization, and simulates the design to test and verify its operation.

Page 3: vhdl lab tutorial

Getting started with vhdl

For the purpose of our lab we will be using the vhdl compiler (ghdl)

First we will simulate (or execute) a simple hello world program for the sake of demonstration.

Second we will move on to simulate a 1 bit adder And finally you will simulate and submit a 4 bit adder

for grading

Page 4: vhdl lab tutorial

Hello world

Start by creating a new directory under the home folder and name it project1

Page 5: vhdl lab tutorial

Hello world

In the project1 directory add a text file Open the text file with gedit and paste in the source code for the hello world program Click on the edit menu and hit preferences a window will appear highlight the plugins tab and select both external tools and python console Finally rename the file to hello and change the extension to .vhdl

Page 6: vhdl lab tutorial

Hello world

Page 7: vhdl lab tutorial

Hello world

Clicking on the dash home search for the terminal (or the cmd from the start menu on windows)

Now change the directory to simplify things a notch by typing the command (in our case only) cd /home/ubuntu/project1

Page 8: vhdl lab tutorial

Hello world

A vhdl program is run in three steps

1. by analyzing (or checking the codes for errors)

2. by elaborating (or creating an executable file)

3. and finally by simulating (or compiling the executable file)

Page 9: vhdl lab tutorial

Hello world

To analyze the code type the command

ghdl -a hello.vhdl To elaborate the program type the command

ghdl -e hello_world And to run the executable file (or simulate)

type the command

ghdl -r hello_world If everything was correct the phrase hello

benedict college should be printed in the terminal

Page 10: vhdl lab tutorial

Hello world

Page 11: vhdl lab tutorial

One bit adder

Although it is possible to write and compile general programs as in the hello world example, it is generally used for hardware design that why we will take a look at a one bit adder

The procedures for simulating a one bit adder is different in the sense that the source code is of no use without a way to test it

To test our one bit adder we integrate a testbench into our design

A testbench will check exhaustively all inputs

Page 12: vhdl lab tutorial

One bit adder

As with the hello world example we will start by creating a new directory and naming it project2

Next create two text documents one for the source code and another for the testbench

Paste, rename to src and testbench, and change the file extension to .vhdl

Page 13: vhdl lab tutorial

One bit adder

Page 14: vhdl lab tutorial

One bit adder

Page 15: vhdl lab tutorial

One bit adder

As always after staring the terminal change the directory using the cd command

Now analyze both commands respectively

1. ghdl -a src.vhdl

2. ghdl -a testbench.vhdl Next elaborate the testbench using the

command

ghdl -e TEST_ADD

Page 16: vhdl lab tutorial

One bit adder

And finally compile the testbench

ghdl -r TEST_ADD You may wish to create a .vcd file to view the

wave using gtkwave

ghdl -r TEST_ADD --vcd=adder.vcd If compiled correctly you should end up with

vcd file in the project2 directory which can be viewed with gtkwave

Page 17: vhdl lab tutorial

One bit adder

Page 18: vhdl lab tutorial

One bit adder

Page 19: vhdl lab tutorial

Four bit adder

Now its your turn using the provided source code and testbench design and simulate a four bit adder

Along with the adder run the results in the gtkwave wave utility

Finally submit your work for grading along with a step by step explanation for how your work was conducted

Page 20: vhdl lab tutorial

Source code for hello world -- Hello benedict college program. use std.textio.all; -- Imports the standard textio package. -- Defines a design entity, without any ports. entity hello_world is end hello_world; architecture behaviour of hello_world is begin process variable l : line; begin write (l, String'("Hello benedict college!")); writeline (output, l); wait; end process; end behaviour;

Page 21: vhdl lab tutorial

Source code for one bit adder -- Simulation Tutorial -- 1-bit Adder

-- This is just to make a reference to some common things needed. LIBRARY IEEE; use IEEE.STD_LOGIC_1164.ALL;

-- We declare the 1-bit adder with the inputs and outputs -- shown inside the port(). -- This will add two bits together(x,y), with a carry in(cin) and -- output the sum(sum) and a carry out(cout). entity BIT_ADDER is port( a, b, cin : in STD_LOGIC; sum, cout : out STD_LOGIC ); end BIT_ADDER;

-- This describes the functionality of the 1-BIT adder. architecture BHV of BIT_ADDER is begin -- Calculate the sum of the 1-BIT adder. sum <= (not a and not b and cin) or (not a and b and not cin) or (a and not b and not cin) or (a and b and cin);

-- Calculates the carry out of the 1-BIT adder. cout <= (not a and b and cin) or (a and not b and cin) or (a and b and not cin) or (a and b and cin); end BHV;

Page 22: vhdl lab tutorial

Testbench for one bit adder -- 1-bit Adder Testbench

-- A testbench is used to rigorously tests a design that you have made. -- The output of the testbench should allow the designer to see if -- the design worked. The testbench should also report where the testbench -- failed.

-- This is just to make a reference to some common things needed. LIBRARY IEEE; use IEEE.STD_LOGIC_1164.ALL;

-- Decare a testbench. Notice that the testbench does not have any -- input or output ports. entity TEST_ADD is end TEST_ADD;

-- Describes the functionality of the tesbench. architecture TEST of TEST_ADD is

-- The object that we wish to test is declared as a component of -- the test bench. Its functionality has already been described elsewhere. -- This simply describes what the object's inputs and outputs are, it -- does not actually create the object. component BIT_ADDER port( a, b, cin : in STD_LOGIC; sum, cout : out STD_LOGIC ); end component;

-- Specifies which description of the adder you will use. for U1: BIT_ADDER use entity WORK.BIT_ADDER(BHV);

-- Create a set of signals which will be associated with both the inputs -- and outputs of the component that we wish to test. signal A_s, B_s : STD_LOGIC; signal CIN_s : STD_LOGIC; signal SUM_s : STD_LOGIC; signal COUT_s : STD_LOGIC;

-- This is where the testbench for the BIT_ADDER actually begins. begin

-- Create a 1-bit adder in the testbench. -- The signals specified above are mapped to their appropriate -- roles in the 1-bit adder which we have created. U1: BIT_ADDER port map (A_s, B_s, CIN_s, SUM_s, COUT_s);

-- The process is where the actual testing is done. process begin

-- We are now going to set the inputs of the adder and test -- the outputs to verify the functionality of our 1-bit adder.

-- Case 0 : 0+0 with carry in of 0.

-- Set the signals for the inputs. A_s <= '0'; B_s <= '0'; CIN_s <= '0';

-- Wait a short amount of time and then check to see if the -- outputs are what they should be. If not, then report an error -- so that we will know there is a problem. wait for 10 ns; assert ( SUM_s = '0' ) report "Failed Case 0 - SUM" severity error; assert ( COUT_s = '0' ) report "Failed Case 0 - COUT" severity error; wait for 40 ns;

-- Carry out the same process outlined above for the other 7 cases.

-- Case 1 : 0+0 with carry in of 1. A_s <= '0'; B_s <= '0'; CIN_s <= '1'; wait for 10 ns; assert ( SUM_s = '1' ) report "Failed Case 1 - SUM" severity error; assert ( COUT_s = '0' ) report "Failed Case 1 - COUT" severity error; wait for 40 ns;

-- Case 2 : 0+1 with carry in of 0. A_s <= '0'; B_s <= '1'; CIN_s <= '0'; wait for 10 ns; assert ( SUM_s = '1' ) report "Failed Case 2 - SUM" severity error; assert ( COUT_s = '0' ) report "Failed Case 2 - COUT" severity error; wait for 40 ns;

-- Case 3 : 0+1 with carry in of 1. A_s <= '0'; B_s <= '1'; CIN_s <= '1'; wait for 10 ns; assert ( SUM_s = '0' ) report "Failed Case 3 - SUM" severity error; assert ( COUT_s = '1' ) report "Failed Case 3 - COUT" severity error; wait for 40 ns;

-- Case 4 : 1+0 with carry in of 0. A_s <= '1'; B_s <= '0'; CIN_s <= '0'; wait for 10 ns; assert ( SUM_s = '1' ) report "Failed Case 4 - SUM" severity error; assert ( COUT_s = '0' ) report "Failed Case 4 - COUT" severity error; wait for 40 ns;

-- Case 5 : 1+0 with carry in of 1. A_s <= '1'; B_s <= '0'; CIN_s <= '1'; wait for 10 ns; assert ( SUM_s = '0' ) report "Failed Case 5 - SUM" severity error; assert ( COUT_s = '1' ) report "Failed Case 5 - COUT" severity error; wait for 40 ns;

-- Case 6 : 1+1 with carry in of 0. A_s <= '1'; B_s <= '1'; CIN_s <= '0'; wait for 10 ns; assert ( SUM_s = '0' ) report "Failed Case 6 - SUM" severity error; assert ( COUT_s = '1' ) report "Failed Case 6 - COUT" severity error; wait for 40 ns;

-- Case 7 : 1+1 with carry in of 1. A_s <= '1'; B_s <= '1'; CIN_s <= '1'; wait for 10 ns; assert ( SUM_s = '1' ) report "Failed Case 7 - SUM" severity error; assert ( COUT_s = '1' ) report "Failed Case 7 - COUT" severity error; wait for 40 ns;

end process; END TEST;

Page 23: vhdl lab tutorial

Source code for four bit adder -- 1-bit Adder

-- This is just to make a reference to some common things needed. LIBRARY IEEE; use IEEE.STD_LOGIC_1164.ALL;

-- We declare the 1-bit adder with the inputs and outputs -- shown inside the port(). -- This will add two bits together(x,y), with a carry in(cin) and -- output the sum(sum) and a carry out(cout). entity BIT_ADDER is port( a, b, cin : in STD_LOGIC; sum, cout : out STD_LOGIC ); end BIT_ADDER;

-- This describes the functionality of the 1-BIT adder. architecture BHV of BIT_ADDER is begin

-- Calculate the sum of the 1-BIT adder. sum <= (not a and not b and cin) or (not a and b and not cin) or (a and not b and not cin) or (a and b and cin);

-- Calculates the carry out of the 1-BIT adder. cout <= (not a and b and cin) or (a and not b and cin) or (a and b and not cin) or (a and b and cin); end BHV;

-- Structural description of a 4-bit Adder. This device -- adds two 4-bit numbers together using four 1-bit adders -- described above.

-- This is just to make a reference to some common things needed. LIBRARY IEEE; use IEEE.STD_LOGIC_1164.ALL;

-- This describes the black-box view of the component we are -- designing. The inputs and outputs are again described -- inside port(). It takes two 4-bit values as input (x and y) -- and produces a 4-bit output (ANS) and a carry out bit (Cout).

entity add4 is port( a, b : in STD_LOGIC_VECTOR(3 downto 0); ans : out STD_LOGIC_VECTOR(3 downto 0); cout : out STD_LOGIC ); end add4;

-- Although we have already described the inputs and outputs, -- we must now describe the functionality of the adder (ie: -- how we produced the desired outputs from the given inputs).

architecture STRUCTURE of add4 is

-- We are going to need four 1-bit adders, so include the -- design that we have already done above.

component BIT_ADDER port( a, b, cin : in STD_LOGIC; sum, cout : out STD_LOGIC ); end component;

-- Now create the signals which are going to be necessary -- to pass the outputs of one adder to the inputs of the next -- in the sequence. signal c0, c1, c2, c3 : STD_LOGIC; begin

c0 <= '0'; b_adder0: BIT_ADDER port map (a(0), b(0), c0, ans(0), c1); b_adder1: BIT_ADDER port map (a(1), b(1), c1, ans(1), c2); b_adder2: BIT_ADDER port map (a(2), b(2), c2, ans(2), c3); b_adder3: BIT_ADDER port map (a(3), b(3), c3, ans(3), cout);

END STRUCTURE;

Page 24: vhdl lab tutorial

Testbench for four bit adder -- 1-bit Adder Testbench

-- A testbench is used to rigorously tests a design that you have made. -- The output of the testbench should allow the designer to see if -- the design worked. The testbench should also report where the testbench -- failed.

-- This is just to make a reference to some common things needed.

LIBRARY IEEE; use IEEE.STD_LOGIC_1164.ALL;

-- Decare a testbench. Notice that the testbench does not have any -- input or output ports.

entity TEST_ADD4 is end TEST_ADD4;

-- Describes the functionality of the tesbench.

architecture TEST of TEST_ADD4 is

component add4 port( a, b : in STD_LOGIC_VECTOR(3 downto 0); ans : out STD_LOGIC_VECTOR(3 downto 0); cout: out STD_LOGIC ); end component;

for U1: add4 use entity WORK.ADD4(STRUCTURE); signal a, b : STD_LOGIC_VECTOR(3 downto 0); signal ans : STD_LOGIC_VECTOR(3 downto 0); signal cout : STD_LOGIC;

begin U1: add4 port map (a,b,ans,cout);

process begin

-- Case 1 that we are testing.

a <= "0000"; b <= "0000"; wait for 10 ns; assert ( ANS = "0000" ) report "Failed Case 1 - ANS" severity error; assert ( Cout = '0' ) report "Failed Case 1 - Cout" severity error; wait for 40 ns;

-- Case 2 that we are testing.

a <= "1111"; b <= "1111"; wait for 10 ns; assert ( ANS = "1110" ) report "Failed Case 2 - ANS" severity error; assert ( Cout = '1' ) report "Failed Case 2 - Cout" severity error; wait for 40 ns; end process; END TEST;