This tutorial shows the steps in a digital design project using Xilinx Vivado design suite and
Digilent Basys 3 FPGA board. You will learn how to use Vivado tools to create a design and
implement it on the Basys3's FPGA. This is a starter project with very little hands-on work, but it
is a good reference if you ever forget how to start and complete a lab project.
Logic gates are the foundation of all computer systems. They allow for the application of logical
processing to be mapped onto physical circuits. In this lab project you will design and implement
a digital system that uses three basic logic gates: the AND gate, the OR gate, and the NOT
gate. The logic schematic of the digital system is given below.
Background
AND Gate
The truth table for a 2-input AND gate is:
A
B
Out
0
0
0
0
1
0
1
0
0
1
1
1
And is denoted by the following schematic symbol:
The verilog keyword is: &
OR Gate
The truth table for a 2 input OR gate is:
A
B
Out
0
0
0
0
1
1
1
0
1
1
1
1
And is denoted by the following schematic symbol:
The verilog keyword is: |
NOT Gate
The truth table for a 1-input NOT gate is:
A
Out
0
1
1
0
And is denoted by the following schematic symbol:
The verilog keyword is: ~
Creating a Vivado Project
Start Vivado and create a new project.
Follow the wizard. Browse and select a folder in which your project will be created.
Give a name to your project, for example `Project1`.
Check "Create project subdirectory."
For Project Type, select "`RTL Project.`"
You do not need to add any sources at this time.
You do not need to add any constraints at this time.
Search for part "xc7a35ticpg236-1L."
Now click 'Finish'
Your screen should look like this:
Creating a Design Source File
Now we will add our first SystemVerilog source file
Right click on "`Add Sources`" on the left side window.
Check "`Add` or create design sources", then "Next."
Click "`+`" on the left hand menu, and select "`Create` file." In the dialog box enter the name of the file, to make it easier, give it the name "top.sv" This will be our 'top'-level 'verilog' file.
Select 'System Verilog' from the 'File type' Menu. The "System" Verilog extension lets us use modern Verilog features. We will discuss this more later in the class. If you forget to do this, you can modify the File type later through the 'properties' menu.
Click "`Finish`."
It should look something like this:
If you get a "`Define Module`" prompt, just click "`OK`".
File "`top.sv`" is now in `Design Sources` under the `Project Manager Window`.
This `code` has two inputs (a and b) and three outputs (`myAND`, `myOR`, and `myNOT`). The `assign` statements tell the `FPGA` how to map the output signals given the input signals. In this `case`, we are using boolean logic operations (`&`, `|`, and `~`) to compute the `logical and, or,` and `not` of the input signals.
When you are done it should look something like this:
Save the file (`Ctrl^S`)
Creating a Constraints File
Now we will add our first constraints source file. This tells Vivado how the inputs and outputs of
the verilog code map to the real inputs and outputs of the Basys3 board.
Verilog Signal
Basys switch/LED
a
sw
b
sw
myAND
led
myNOT
led
myOR
led
Click on "Add Sources."
Select "Add or create constraints"
Click `+` on the left hand menu, and select "Create file." In the dialog box enter the name of the file, to make it easier, give it a name "constraints.xdc"
Click "Finish"
File "constraints.xdc" is now in Constraints -> constrs_1 under the `Project Manager Window`.
This tells Vivado which physical pins (or `PACKAGE_PIN`) you want your verilog signals to map to. A complete listing of what each pin does will be provided for you.
Save the file (`Ctrl^S`)
Later in the semester, we will make use of the `"Basys3_Master.xdc"` constraints file uploaded
on the website. It can be found under the `Downloads` quick link.
Create Simulation File (AKA a ‘testbench’)
We are now going to run a simulation to ensure that our verilog code is correct.
Right click "Add Sources."
Select "Add or create simulation sources" hit `Next`.
Click `+` on the left hand menu, and select "Create file." In the dialog box enter the name of the file, to make it easier give it a name "top_tb.sv". Select "System Verilog" from the "File Type" drop-down menu. This will be our "top" level testbench. The "tb" is shorthand for "test bench".
Click "`Finish`."
Again, if you get a Module popup, just click `OK`.
File "top_tb.sv" is in Simulation Sources -> sim_1.
Note that "top.sv" is also in Simulation Sources -> sim_1. This is normal.
Double click on "top_tb.sv".
Enter the following Verilog statements into top_tb.sv:
(please copy + paste this code, don't try to rewrite it)
`timescale1ns/1ps//specify how detailed of a simulation we want to runmoduletestbench();logica,b;//logic (or 'reg') for module inputswiremyand,myor,mynot;//wires for module outputs//// connect our module for testing// This is sometimes called a DUT - Device Under Test//toptop0(.a(a),.b(b),.myAND(myand),.myOR(myor),.myNOT(mynot));initialbegin//print out these signals whenever anything changes$monitor("a:%h b:%h myand:%h myor:%h mynot:%h",a,b,myand,myor,mynot);#100// a 100 nanosecond delaya=0;b=0;//set inputs a and b to logical 0#100// a 100 nanosecond delay// check if any of our outputs are incorrect.// if so, fail the simulation with an error messageassert(myand==0)else$fatal(1,"myand");assert(myor==0)else$fatal(1,"myor");assert(mynot==1)else$fatal(1,"mynot");#100// a 100 nanosecond delaya=0;b=1;// now set a=0, b=1, and repeat the test#100// a 100 nanosecond delayassert(myand==0)else$fatal(1,"myand");assert(myor==1)else$fatal(1,"myor");assert(mynot==1)else$fatal(1,"mynot");#100a=1;b=0;//continue testing input combinations#100assert(myand==0)else$fatal(1,"myand");assert(myor==1)else$fatal(1,"myor");assert(mynot==0)else$fatal(1,"mynot");#100a=1;b=1;//last input combination#100assert(myand==1)else$fatal(1,"myand");assert(myor==1)else$fatal(1,"myor");assert(mynot==0)else$fatal(1,"mynot");#100// now we've tested all possible input combinations to// ensure correct output for each$display("@@@Passed");$finish;endendmodule
Save the file (`Ctrl^S`)
Project Checkpoint
Now we should have all of our source files. Your setup should look like the following:
Running a Simulation
Now we are going to run our simulation, and use the testbench to drive inputs and observe the
outputs of our verilog module.
On the left hand menu select "SIMULATION" -> "Run Simulation", then "Run Behavioral Simulation."
This will take a few seconds
When it is finished, you should get a window that looks something like this in the bottom window. Note the `@@@Passed`. This means our simulation, well, passed.
Now let's try to understand why it passed. For that, we need to look at the "Wave Window". Vivado automatically created one for you (circled below). Click on it.
It should look something like this:
- Now click on the ![Vivado Zoom Out Button](/projects/assets/VV_Tutorial/vivado_zoom_out_button.png) button:
- Now your wave window should display the entire waveform. Waveforms allow us to observe how signals change through time. Time moves from left to right, it starts at `0ns` (nanoseconds), and moves to `900ns`.
- The simulator looks for an initial block to run the simulations.
initialbegin
- It starts at `0ns`, but everything is red. Red lines means that the simulation doesn't know the value for a signal. Before `100ns`, we haven't assigned `a` or `b` to anything, so the simulation doesn't have a value for them. Because the simulation doesn't know the value for the inputs, it can't figure out the value for the outputs `myAND, myOR,` and `myNOT`.
- At `100ns`, everything changes to green. This is because we used
#100// a 100 nanosecond delaya=0;b=0;//set inputs a and b to logical 0
in our simulation file. We told the simulation to set a and b to 0, so now it knows their
values. Once the simulation knew the value for a and b, it could calculate the value for
myAND, because we told it
assignmyAND=a&b;
in our source file.
- FPGAs require a small amount of time to update an output signal given changes in the input. Therefore, we need another `#100` delay before the updates in `a` and `b` show up in the outputs.
- At `200ns`, we test the values of `myAND, myOR,` and `myNOT` to make sure they are correct. Assert statements test a boolean equation `(myand == 0)` and does nothing if it is `true`. If it is `false`, it will terminate the simulation and report an error (`$fatal(1, "myand")`).
- This process repeats for every possible combination of `a` and `b`.
- Waveform simulations are a great way to visualize and understand what is happening when problems arise. We will use them frequently in this class. The autograder uses a command-line version of these same simulations for its tests.
Hardware Synthesis
- Now that we're (mostly) sure our logic is correct, we can move on to "Synthesis". Synthesis is roughly equivalent to "Compiling" for FPGAs.
- On the left hand menu select "`SYNTHESIS`" -> "Run Synthesis." If prompted where to launch runs, select "Launch runs on local host'. This tells Vivado to run synthesis on your local machine.
- Even for simple designs, synthesis takes a surprisingly long time, usually 1-2 minutes. For large industrial designs, it can take days. This process translates our verilog code into `LUTs`, or "Look-Up Tables". It can also translate our code into basic logic gates. We'll discuss this later in class.
- After the Synthesis is complete, select "Run Implementation". This is also called "`Auto Place and Route`". This process decides which locations within the `FPGA` to use for each `LUT`, and how best to connect then.
- After the Implementation is complete, select "Generate Bitstream". This generates a configuration file that is read by the `FPGA` when it boots up to decide how to configure itself.
- After the Generate Bitstream is complete, select "Open Hardware Manager".
Programming the FPGA
This process will (finally) program the FPGA.
- If you haven't already, make sure your Basys3 board is connected.
- On the right-hand side, select "Programming and Debug" -> "Open Hardware Manager" -> "Open Target" -> "Autoconnect"
- This should automatically detect the Basys
- Now select "Programming and Debug" -> "Open Hardware Manager" -> "Program Device" -> 'xc7a35t_0'. (Your device might be named differently)
- You will need to select your 'bitstream' file. Xilinx did not make this easy. The bitstream is located at './project_0.runs/impl_1/top.bit' within your project. See the example below:
- With the bitstream selected, hit "program". This should only take a few seconds.
Testing your FPGA
You should now be able to test your FPGA. When you flip the right-most switches, the
corresponding LEDs should also toggle.