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
Simulation
Running on hardware.
Adding a counter

The Basics

  1. Create a folder on your desktop for the files for this lab.
  2. Start Quartus and select "Create a New Project (New Project Wizard)"
  3. On the next page ("Directory, Name, Top-Level Entity [page 1 of 5]") choose the directory you just created and a name for the project and hit "Next >"
  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. Important - this is different than what we did for schematic entry. 
    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 compilation; you'll learn about this in class (the 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 "lab3.v".  Note that the file name and module name should be the same as the top level entity (the name you chose previously).  As with programs in "C," there are no rules about indenting - but be neat and be consistent.
    module lab3(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]);
    
    endmodule
  10. Create another file and call it "hadd.v".  This file is shown below.  It implements a half adder.
    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.
    
    endmodule
  11. Go to Processing →Start →Analysis and Synthesis (or type ctrl-k).  After  a little wait you should get an error announcing success.
  12. Note (in the flow summary) 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.

Simulation

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.
  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 →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].  Are the results as expected?

Running on Hardware

  1. Go to "Assignment→Import Assignments..." and choose the E15DE2_IO.qsf file.  This should automatically assign the proper pins.
  2. Compile your code, then program the device.  Verify that it works as expected.

Making a More Complex Circuit.

  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.
    
    endmodule
  2. Change the code in "lab3.v" to look like the following
    module lab3(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
    
    endmodule
  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.

The return of the counter

  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 "lab3.v" file to look like the one below:
    module lab3(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
    
    endmodule
  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