University of Bridgeport

Computer Science and Engineering Department

 

 

 

 

VHDL Design tutorial

using

Mentor Graphics

And ModelSim System

 

Introduction

This tutorial will give you a short introduction to Mentor-Graphics ModelSim system and guide you through the creation and verification of an up/down 8 bit counter. The tutorial assumes that you are already familiar with IEEE - 1076 standard VHDL syntax.

Mentor Graphics is the software package you will use to create and verify your VHDL based design. The ModelSim compiler is close to 100% IEEE-1076 compliant - which means that your code can contain the most advanced VHDL directives without the fear of being kicked out in compile time, or worse, getting unpredictable hardware. The Mentor-Graphics package is a state of the art CAD tool being used by top rated chip design companies for chip fabrication. The package is comprised out of many (more the a hundred) different applications which enable the engineer to create a fully operational fabricated product out of scratch.

Introduction to applications

In this tutorial, you will use only one product out of the Mentor-Graphics package.

ModelSim

The ModelSim package is a self contained Integrated Design Environment tool. The ModelSim system contains a context sensitive VHDL editor, library manager, compiler, simulator, and post processing tools, that will enable you to create compile and functionally simulate a VHDL design. You will do all your work in the IDE.

Introduction to the Design

The design you will work on in this tutorial is an automatic up/down 8 bit counter. The counter has a reset input, a clock input, and an 8 bit count output. After power-up, we give a reset (level sensitive - active @ high) which causes the counter to reset to “00000000”. For each positive going clock transition the counter advances by one. When the counter reaches “11111111” it reverses its direction automatically and on the next positive going clock transition it will decrease its count. When it reaches “00000000” the opposite happens, and the counter changes automatically to the increase mode, starting to count upwards. A suggested block diagram of the counter follows:

 












The block diagram

latch8 unit description

This is a positive edge triggered 8 bit latch. it has an asynchronous level sensitive reset (active @ high).

incdec unit description

This block receives an 8 bit byte and a control bit. When the ud control  input is ‘0’ the nextval  output will be the decremented outval input (nextval=outval-1). When the ud control  input is ‘1’ the nextval  output will be the incremented outval input (nextval=outval+1).

uddet unit description

This block receives an 8 bit byte and outputs a control bit. When the outval input is “00000000”  the ud output will be set to ‘1’. When the outval input is “11111111”  the ud output will be set to ‘0’. In all the other outval combinations, ud will preserve its state.

Starting a new design

2.        Log into a Mentor-capable machine and start an Xwindows session.

3.        Open a terminal window.

4.        Change directory to mentor_work : cd mentor_work

5.        Start ModelSim by typing vsim in the terminal.

6.        Click on “Create a Project”

7.        In the dialog box, click on browse, then in the file dialog box, click OK. This will fill your new projects home with the current directory.

8.        In the “New Project’s Name” type UD. Click OK.

9.        Click “NO” when asked to create a HDL source file.

The system will create a work library for your project.

10.    Click on Done.

11.    Click File > New > New_Source

12.    In the filename dialog box, enter latch8.vhd, then click OK.

13.    Click on Yes when asked to edit the source.

A new VHDL editor window opens up for the latch8 module.

Creating the latch8 entity

1.      Type in the following code:

LIBRARY ieee;

USE ieee.std_logic_1164.all;

USE ieee.std_logic_unsigned.all;

ENTITY latch8 IS PORT (

                 reset , clk:IN std_logic;

                 nextval:IN std_logic_vector(7 DOWNTO 0);

                 outval:INOUT std_logic_vector(7 DOWNTO 0));

END;

 

ARCHITECTURE latchbhv OF latch8 IS

BEGIN

        PROCESS(reset,clk)

        BEGIN

                IF (reset = '1') THEN

                        outval <= "00000000";

                ELSIF (clk'EVENT) THEN

                        outval <= nextval;

                ELSE

                        outval <= outval;

                END IF;

        END PROCESS;

END latch8;

 

 

This is the Entity declaration and architecture of our latch8 device. Try to follow the code and understand how it works.

2.        Click on File > Save, then File > Close

Compiling latch8

VHDL is a highly structural language. In order to manage large projects, the language was defined around the notion of libraries. Every library is a level of abstraction for a specific kind of code. You can see that the first 3 lines in our latch8 are exposing and using the IEEE standard logic libraries. As Libraries are an abstract object, it is essential for us to instruct the compiler to look for them in its physical file domain. Every VHDL compiler designer solves this problem in a different way. Mentor-Graphics are using a physical-logical mapping scheme. When the compiler finds a call to a library it checks out a special file (by the name of UD.mpf) in the users project directory (in our case the mentor_work/UD directory), if it doesn’t find it, it uses a default file in the Mentor-Graphics file system. The quickhdl.ini file contains lines in the form: ieee = /home/lib/ieee.lib which map the logical library name into a physical path in the file system. A special case is the work library. The compiler treats the work library as the current working area in which all the design hierarchy entities reside. When a component is being instantiated in a design, the work library will be advised first, then other user libraries (like std, ieee etc.). Whenever the compiler compiles an entity, it will place the compiled object with all it’s relevant architectures under the current work library. The default project file maps the work library to ./work meaning the work subdirectory under the current project directory. It is clear that a correct setup of the work library is crucial for the correct generation of a hierarchical design tree.

1.      Click on Design > Compile

2.      Select the latch8.vhd and click Compile

You’ll see some messages scrolling down the ModeSim transcript window. If you see only black # lines, then your compilation was successful and you are all set to continue to the simulation stage. If you see any red lines, then your code has errors and needs to be corrected.

3.      Read the error explanation, then Double Click on the first ERROR line you see.

An editor window will open up with the offending line highlighted in bright orange.

4.      Change the highlighted label from latch8 to latchbhv.

5.      Click on the Diskette Icon to save the correction to the file.

6.      Try to compile the part again by clicking the Compile in the Compile dialog box.

Hopefully there are no more errors. If there are, continue correcting them (if you need help in VHDL, there are two very comprehensive books inside The Mentor help system: "Mentor Graphics Introduction to VHDL" and "Mentor Graphics VHDL User's and Reference Manual").

Simulating the latch8 entity

Assuming you've succeeded in compiling successfully the above entity, you now have to verify the functionality of it.

1.        Click on Design > Load_Design

The simulator will be invoked, and it will display the entities and architectures available for simulation in the work library. Since we have only one Entity and only one architecture we don't have any other options when loading this entity.

2.        Select the latch8 entity, then click Load.

ModelSim will load the libraries into the simulator environment. You can see the actual load by looking at the purple “Loading” lines in the transcript window.

 

3.        open up a signals and wave windows:

       click on [ModeSim]View > Signals

       click on [Signals]View >Wave > Signals in design

We now have a Wave display that includes all the signals in the design (in a larger design you should consider displaying only part of the signals).

The last requirement before the actual simulation is creating a stimulus:

5.        In the ModelSim transcript window type in the following stimulus:

force -freeze /reset 0 0, 1 10, 0 20

force -freeze -repeat 100 /clk 0 0, 1 50

force -freeze /nextval 16#AA 30

 

We have defined a stimulus for our latch. Each line describes a single signal in the design. The signal stimulus command is force. You should look at the command’s syntax in the ModelSim simulator user’s manual. In general, it accepts data pairs. Each pair is comprised out of a logic level and the time (from the beginning of the simulation - in simulation units) for it to be set. The -freeze switch instructs the simulator to continue driving the signal with the last value even after the setup time, without it the simulator clears the driver from the signal (read about the methods of driving a SIGNAL in VHDL) following the last time mentioned in the force command. The -repeat n switch is causing the simulator to repeat the force command every n time units where n is the number appearing following the switch. the simulator is ready to execute.

6.        Click on the run icon  a few times.

Watch the wave display as simulation progresses, does the results comply with the source requirements for a positive edge triggered latch?

Lets test a few more values for the nextval signal to check out its stability over the falling edge:

7.        Highlight the nextval signal in the signals window.

8.        Click on [signals] Edit > Force

9.        In the dialog box, Change the value to 16#55

10.    Click on the run icon a few more times.

11.    Repeat items 8-10 with a value of 16#FF. Put in Delay values of 20 and 70 nanoseconds. This will introduce the new nextval before the rising and falling edge respectively.

Does the design behave correctly? (look at the falling edge !!!). If you think that the design is not correct, go back to the VHDL editor window (don't close the simulator), apply the corrections, click on compile. After a successful compilation, get back to the simulator, restart the design, load the stimulus and again simulate your design. Continue that cycle until you are satisfied with the simulation results.

12.    Click on Design > End Simulation.

creating the Inc/Dec module

1.      Create a new VHDL source with the name incdec.vhd (the same way as you did in latch8 design).

2.      type in the following code:

LIBRARY ieee;

USE ieee.std_logic_1164.all;

USE ieee.std_logic_unsigned.all;

 

ENTITY incdec IS PORT (

                        ud:IN std_logic;

                        outval:IN std_logic_vector(7 DOWNTO 0);

                        nextval:OUT std_logic_vector(7 DOWNTO 0));

END;

 

ARCHITECTURE incdecbhv OF incdec IS

 

BEGIN

        PROCESS(ud,outval)

        VARIABLE x : std_logic_vector(7 DOWNTO 0);

        BEGIN

                x := outval;

                FOR i in 0 to 7 LOOP

                        IF outval(i) = NOT(ud) THEN

                                x(i) := ud;

                        ELSE x(i) := NOT(ud);

                        END IF;

                END LOOP;

                nextval <= x;

        END PROCESS;

END incdecbhv;

 

The above code is a behavioral description of the increase/decrease module. Try to follow the code and understand how it works.

3.      Compile the code and correct any errors (if any) that occurred during the compilation.

4.      Start the simulator on the incdec entity.

5.      Initialize the following stimulus:

force -freeze /ud 0 0, 1 100, 0 200

force -freeze /outval 16#AA 50, 16#55 150

 

6.      Open a Signals and a Wave window in the simulator.

7.      Run a few simulation cycles and observe the results. Is that what we expected?

It looks as if our incdec module only inverts the bits. To debug our module we need to step through the FOR loop and see exactly what happens.

8.      Restart the design in the simulator: [ModelSim] Run > Restart > Restart

9.      Initialize the stimulus in the simulator.

10.  open a Source window by: [ModelSim]View > Source...

11.  open a Variable window by: [ModelSim]View > Variables...

12.  create a break-point in the line x := outval; by clicking on the line-number of that line in the Source window (a red dot should appear beside the line number).

13.  click on Run, so a single iteration of the FOR loop will be executed

(we do that in order to bring outval into its initialized status)

14.  click on the Step icon  while observing the red arrow in the Source window, the outval value in the Signals window, and the x and i values in the Variables window.

During the first iteration, everything works fine, x's LSB is being inverted by evaluating the ELSE clause. On the second iteration, the LSB+1 bit is being inverted by evaluating the IF=true clause. Now we have the correct answer (outval-1), but if you’ll keep pressing Step you'll see that instead of exiting the loop now, we continue to run and invert all the bits. So we need to EXIT the loop after the IF=true clause is evaluated.

15.  get back to the VHDL Editor, correct the code, compile it, restart the design in the simulator, and simulate it. Does it work as expected?

Creating the Up/Down detector

1.      open a new VHDL Source Editor window under the name uddet.vhd and type the following code:

LIBRARY ieee;

USE ieee.std_logic_1164.all;

USE ieee.std_logic_unsigned.all;

 

ENTITY uddet IS PORT (

                        outval:IN std_logic_vector(7 DOWNTO 0);

                        ud:INOUT std_logic);

END;

 

ARCHITECTURE uddetdf OF uddet IS

 

BEGIN

        ud <= '0' WHEN outval = "11111111" else ud;

        ud <= '1' WHEN outval = "00000000" else ud;

END uddetdf;

 

The above code is a dataflow description of the up/down detector . Try to follow the code and understand how it works.

2.      compile the Entity.

3.      invoke the simulator on the uddet Entity.

4.      open the Signals and Wave windows.

5.      Initialize a stimulus with the following command:

force -freeze /outval 16#FF 50, 16#55 100, 16#00 150

 

6.      run a few simulation cycles. Are the results satisfactory? What is wrong? (Hint - The two WHEN directives are evaluated concurrently).

7.      correct the design and rerun the simulation until you are getting satisfactory results.

The Wrapper Entity

1.    open a VHDL Editor window under the name uddet.vhd and type the following:

LIBRARY ieee;

USE ieee.std_logic_1164.all;

USE ieee.std_logic_unsigned.all;

USE work.all;

 

ENTITY udcount IS PORT (

                        clk,reset:IN std_logic;

                        num:OUT std_logic_vector(7 DOWNTO 0));

END;

 

ARCHITECTURE udcstruc OF udcount IS

 

SIGNAL outval , nextval : std_logic_vector(7 DOWNTO 0);

SIGNAL ud : std_logic;

 

COMPONENT latch8

        PORT (clk,reset : IN std_logic;

         nextval : IN std_logic_vector(7 DOWNTO 0);

                        outval : OUT std_logic_vector(7 DOWNTO 0));

END COMPONENT;

 

COMPONENT incdec

        PORT (outval : IN std_logic_vector(7 DOWNTO 0);

                        ud : IN std_logic;

                        nextval : OUT std_logic_vector(7 DOWNTO 0));

END COMPONENT;

 

COMPONENT uddet

        PORT (outval : INOUT std_logic_vector(7 DOWNTO 0);

                        ud : INOUT std_logic);

END COMPONENT;

BEGIN

   p1: latch8 PORT MAP (reset , clk , nextval , outval);

   p2: incdec PORT MAP (outval , ud , nextval);

   p3: uddet  PORT MAP (outval , ud);

   num <= outval;

END udcstruc;

 

The above code is a structural description of the wrapper entity (the entity that connects all the blocks together). Try to follow the code and understand how it works.

2.    compile, debug and simulate a design. Execute the design cycle on the above code so it will compile and simulate correctly. Create a stimulus and apply the correct forces (reset the counter then apply a continuous clock) to the inputs.

3.    Simulate a full cycle (i.e. running the counter from 00000000 to 11111111 and back to 00000000). You can set the default run length to be longer so it will require less clicks on the Run button by:

       Options > Simulation

       in the Default Run box enter a 1000

       click OK

Now every Run push, will execute 1000 simulator units instead of 100.