Quick Quartus: Verilog

Please contact me if you find any errors or other problems (e.g., something is unclearly stated) in this web page

This document presents a (very) quick introduction to the use of Quartus to design a system using verilog.

The Basics
Running on hardware.
Adding a counter

The Basics

  1. Create a folder on your desktop for the files for this lab.
  2. Start Quartus (There should be an icon on the desktop, if not go to (Start Menu→All Programs→Altera...→Quartus...→Quartus II 13.0.1 (64 bit)) and select "Create a New Project (New Project Wizard)". It may take some time to open.
  3. On the next page ("Directory, Name, Top-Level Entity [page 1 of 5]") choose the directory you just created and name the project "lab0" and hit "Next >". It is a good idea to have the name of the project the same as that of the top level entity, which you will create below).
  4. Hit "Next >" (from "Add Files [page 2 of 5]").
  5. On the next page ("Family and Device Settings [page 3 of 5]"):
    1. choose Family: "Cyclone II"
    2. choose Available Devices: "EP2C35F672C6" (the number on the large chip on the DE2 Altera board).  Note, these are not alphabetical, so you need to scroll through the choices.
    3. hit "Next >"
  6. On the next page ("EDA Tool Settings [page 4 of 5]"), under "Tool Type→Simulation" pick "ModelSim-Altera" for the "Tool name" and "Verilog HDL" for format.  Then hit "Next >".  (Note: this is only necessary for projects that you will be simulating; if you don't expect to simulate, you don't need to do this.  Also, if you only want to simulate, you can use ModelSim without doing a full compilationas we did in class (that process is much faster).).
  7. Hit "Finish" ("Summary [page 5 of 5]")
  8. From the Quartus main menu choose "File→New→Design Files→Verilog HDL File" then "OK"
  9. Enter the text below into the file and save in a file "lab0.v".  Note that the file name and module name should be the same as the top level entity (the name you chose previously).  There are no rules about indenting - but be neat and be consistent.
    module lab0(SW,LEDG);
    input [1:0]SW;   // add SW[0] and SW[1] are inputs
    output [1:0]LEDG;  // LED's are outputs 
    // instantiate a half adder.  The inputs are SW[0] and SW[1],
    // the outputs are LEDG[0] (sum) and LEDG[1] (carry).
    	hadd myHalfAdder(SW[0],SW[1],LEDG[1], LEDG[0]);
  10. Create another file and call it "hadd.v" (module name is the same as file name).  This file is shown below.  It implements a half adder. Note this file is used by the previous file.
    module hadd(a,b,cout,s);
    input a, b;     	// Inputs to be added together
    output cout, s;	        // Output, carry (cout) and sum (s)
    assign {cout,s} = a+b;  // add a and b and put result in cout and s.
  11. Go to Processing →Start →Analysis and Synthesis (or type ctrl-k).  After  a little wait you should get an message announcing success.
  12. Note (in the flow summary - this is available in the "Table of Contents" page of the project window) how many logic elements were used.
  13. To see the resulting circuit go to Tools →Netlist Viewers →Technology Map Viewer (post-mapping).  Double click the half-adder to expand it, then double click on each logic cell to expand.  To see the individual lines right-click in the window and select "Viewer Options →Customize View"  and deselect "group all related nodes."  You should get the expected half adder circuit.


Note: Before simulation you must perform Analysis and Synthesis.

  1. Go to File →New →Verification/Debugging Files→University Program VWF  (VWF = vector waveform file).
  2. When the "Simulation Waveform Editor" window appears click Edit →Insert → Node or Bus.
  3. When the "Insert Node or Bus" window  appears, click on Node Finder...
  4. When the "Node Finder" window appears, click on List
  5. Select LEDG[0], LEDG[1], SW[0] and SW[1] and hit the ">" button to move them to selected nodes.  Hit OK.
  6. Hit OK to close "Insert Node or Bus".
  7. You should get a window like the one below.  It shows the inputs as 0, and the outputs as undefined (since we have not run the simulation).
  8. We first define the inputs.  Select SW[0] on the left side of the page and then choose "Overwrite clock" () from the menu above the timing diagram.  Choose a 10 ns period and 50% duty cycle clock.  Hit OK.
  9. Now do the same for SW[1] but make it a 20 ns period (half as fast as before).
  10. This leaves a lot of oscillations of the inputs, so go to Edit →End Time and set the end time to 80 ns.
  11. Go to Simulation →Options and choose "Quartus II Simulator" and then "Okay". You will get a warning about using the simulator, just close it.
  12. Go to Simulation →Run Functional Simulation.  The output should look like below.  Recall that we are adding SW[0] and SW[1], and the sum is LEDG[0] and carry is LEDG[1]. Again, this takes some time.Are the results as expected?

Running on Hardware

Now that we have simulated the circuit, we want to actually create the circuit on the DE2 board. Download the E15DE2_IO.qsf file into your working directory. (Note: Right-click on the link and choose "Save Link As..." If you open it and then save it, you will save the file in a format that cannot be properly read. This file has all the information needed to connect the internal circuitry of the FPGA to the hardware on the board.

  1. Go to "Assignment→Import Assignments..." and choose the E15DE2_IO.qsf file.  This should automatically assign the proper pins.
  2. Go to "ProcessingStart Compilation" (or hit the triangular "play" icon at the top of the window).  You will get several warnings - ignore these for now.
  3. Make sure the DE2 board is turned on and connected to the computer through the USB port labeled "Blaster" (there are two USB ports on the DE2 board - choose the one near the power cord). Go to "Tools→Programmer" or choose the "Programmer" icon (). The "Hardware Setup" should show "USB-Blaster". 
  4. Your window should now look something like the one shown below.  If  so, hit "Start".  If the "USB-Blaster" is not listed by the "Hardware Setup" button,  you'll have to start by  setting up the hardware and follow the directions for "JTAG programming"
  5. If no file is listed we have to choose the file to be download.  Click on "Add File..." and and choose the .sof (SRAM Object File) file (this may be in a subdirectory named "output_files."  You'll also have to delete any lines without file.  When the dialog box resembles the one above,  hit "Start".  When finished, close the programmer window (and save the configuration - you'll be able to reuse this configuration later if desired).
  6. Your design is now running, with the inputs connected to SW[0] and SW[1], and the output to LEDG[0] (the sum) and LEDG[1] (the carry).

Making a More Complex Circuit.

Often you will want to create a more complex circuit out of simpler circuits. You will have to do this for the lab. The example below shows how you can use a half-adder, and a full-adder to make a 2 bit adder.

  1. Copy the following into a file called "fadd.v"
    module fadd(a,b,cin,cout,s);  //Implement a full adder.
    input a, b, cin;   	// Inputs to be added together with a carry in
    output cout, s;   	// Output, carry (cout) and sum (s)
    assign {cout,s} = a+b+cin;   // add a and b and put result in c and s.
  2. Change the code in "lab0.v" to look like the following
    module lab0(SW,LEDG);
    input [3:0]SW;  	 // add SW[1:0] and SW[3:2] represent 2 bit numbers
    output [2:0]LEDG;  // LED's are outputs 
    wire cout1;
    // create a two bit adder, a half adder and a full adder
    	hadd myHalfAdder(SW[0], SW[2], cout1, LEDG[0]);			// Add low bits
    	fadd myFullAdder(SW[1], SW[3], cout1, LEDG[2], LEDG[1]);// Add high bits
  3. Make sure you understand the code.
  4. Create another Vector Waveform File, but this time pick LEDG and SW as your variables (this selects all bits).
  5. In the "Simulation Waveform Editor" select "SW" and then choose "Count Value" ().   Select Radix as binary, start value as 1, Increment by 1, count type binary, and count every 10 ns.
  6. Set the end time of the simulation to 200 nS and perform the simulation.
  7. Verify that the result is as expected.  Make sure you can explain these results.

A potential error while simulating

You may get an error window that looks something like the one below:

This occurs if you perform the simulation after importing the pin assignments. The simulator gets confused because you aren't using all of the bits assigned to a variable.  If you only use SW[0:3] the simulator complains because it has SW defined as an 18 bit vector (SW[0:17]) in the pin assignments.  The error you get is the simulator telling you that your vector is not the correct length.  An easy way to fix this is just to change variable names while simulating (e.g., change SW to SWx); just remember to change them back when you want to test on the hardware.  

You can also add the nodes one at a time (instead of as a group) from the node finder (e.g. add SW[0], then SW[1]); you can then group the individual lines from within the simulator.

Another method to get it to work is to remove all the assignment (Assignments→Remove Assignment→Pins) and then do another Analysis and Synthesis.

Using a counter

Instead of using the switches as an input, you can add a counter to generate all possible inputs. At this point you don't have to worry about how the counter works (we'll do that in class very soon).

  1. Now add the file "E15Counter1HzB.v" to your working directory and include it in your project.  There are 3 inputs - a 50 MHz clock, a terminal count and a 4 bit count number.
  2. Change your "lab0.v" file to look like the one below:
    module lab0(CLOCK_50,LEDR,LEDG);
    input  CLOCK_50;   // 50 MHz clock
    output [3:0]LEDR;  // LED's represent numbers being added
    output [2:0]LEDG;  // LED's are outputs 
    wire cout1;
    wire [3:0]Q;
    assign LEDR = Q;
    // Instantiate counter
       E15Counter1HzB myCounter(CLOCK_50, 4'd15, Q);
    // create a two bit adder, a half adder and a full adder
    	hadd myHalfAdder(Q[0], Q[2], cout1, LEDG[0]);			// Add low bits
    	fadd myFullAdder(Q[1], Q[3], cout1, LEDG[2], LEDG[1]);// Add high bits
  3. Compile the file, download to the DE2 board and make sure it operates as expected.
  4. Note (in the flow summary) how many logic elements were used.

Please contact me if you find any errors or other problems (e.g., something is unclearly stated) in this web page