Your cart is currently empty!
Learning Objectives The purpose of this exercise is to apply Verilog in expressing simple circuits, and to learn the importance of simulations and hierarchies when writing Verilog. This exercise is also meant to illustrate the importance of Karnaugh maps in designing circuits, and introduce important devices such as the multiplexer and seven-segment decoder. …
The purpose of this exercise is to apply Verilog in expressing simple circuits, and to learn the importance of simulations and hierarchies when writing Verilog. This exercise is also meant to illustrate the importance of Karnaugh maps in designing circuits, and introduce important devices such as the multiplexer and seven-segment decoder.
This lab also introduces components of the DE1-SoC board and FPGA design in general. We will use switches SW9 0 on the DE1-SoC board as inputs to the circuit, and Light Emitting Diodes (LEDs) and 7-segment displays as output devices.
Note that we may refer to signals as SW9 0, i.e., with the subscripts, but when you write your Verilog, you will need to use SW[0], SW[1], etc.
You can nd many resources about the DE1-SoC board here http://cd-de1-soc.terasic.com/. The User Manual for the DE1-SoC board can be downloaded from here: http://www-ug.eecg.toronto. edu/desl/manuals/DE1-SoC_User_manual.pdf
This lab is worth 4% of your  nal grade, but you will be graded out of 8 marks for this lab, as follows:
For this lab, and all future labs, you will be asked to prepare schematics (which can be drawn by hand on paper, and not necessarily in Quartus), Verilog code and ModelSim simulations for your prelab. The schematics should show the structure of your Verilog code, much like the schematics in Lab 1 showed how your circuit should be built. Figure 2 is an example of how to draw the schematic of a Verilog code.
Your Verilog code will consist of a number of modules and the schematic should show how those modules are wired together, as well as the input and output ports of your circuit, i.e., connections to switches, LEDs, 7-segment hex displays, etc. Think of modules as logic functions consisting of multiple gates, such as the logic functions you wired together in Lab 1. All port names of the modules, wires and I/O ports should be clearly labeled in your schematics.
1
Your Verilog code should be well-commented. For your simulations, you should have a script, or number of scripts, that test important aspects of your design. Print out the waveforms from the simulator and paste them into your lab book (e.g. by taking a screenshot). If the simulation is very long, just print out enough to show that key parts of your circuit are working and as evidence that you have done the simulations. It is not necessary to have pages and pages of waveforms. However, occasionally, you will be asked to demonstrate and explain your entire simulation to the TA in the lab, so be prepared for this.
As an example, if your circuit implements a logic function with three or four inputs, it is reasonable to show waveforms demonstrating the functionality of all possible combinations of input values. However, if your circuit implements a logic function with ten inputs, it would be unreasonable to simulate all 210 possible input values.
Verilog File (.v)
The DE1-SoC board provides 10 toggle switches, called SW9 0, that can be used as inputs to a circuit, and 10 red lights, called LEDR9 0, that can be used to display output values.
A Verilog le for a 2-to-1 multiplexer, named mux.v, has already been provided to you (on Quercus, and in the appendices of this handout). The top module mux has 3 inputs. SW [0] is the input 0 signal, SW [1] is the input 1 signal, and SW [9] is the select signal. The output is displayed on LEDR[0].
module mux(LEDR, SW) ; // module name and p o r t l i s t
The top module, mux, is a very trivial example of a design hierarchy, as it instantiates a single mux2to1 module. In the more general case, any module can instantiate a number of interconnected modules, just like when you wired up a number of chips in Lab 1. However, in any circuit you build, there must be only one top-level module. The .port(connection) notation matches the port name from the mux2to1 module to a connection (e.g., port or internal wire) inside the mux top-level module. Note that multiple modules of the same type can be used to build larger circuits. Each use of a module is called an instance. Every instance has to have a unique name. In our example below we used only one instance of the mux2to1 module, which we named u0.
mux2to1 u0 ( | |||||
. x (SW[ 0 ] ) , // | c o n n e c t | p o r t SW[ 0 ] | t o | p o r t | x |
. y (SW[ 1 ] ) , // | c o n n e c t | p o r t SW[ 1 ] | t o | p o r t | y |
. s (SW[ 9 ] ) , // | c o n n e c t | p o r t SW[ 9 ] | t o | p o r t | s |
.m(LEDR [ 0 ] ) // | c o n n e c t | p o r t LEDR[ 0 ] | t o p o r t m | ||
) ; |
Figure 1 shows the symbol for a 2-to-1 multiplexer. As mentioned in Lab 1, a multiplexer is a device that uses a select signal to select which one of multiple inputs should appear on the output of the device. In Figure 1, input s will control which of the inputs x and y will appear on the output m. If s is 0, x will appear on the output, while if s is 1, y will appear on the output.
Figure 1: Symbol for a 2-to-1 multiplexer
2
The Boolean expression for a 2-to-1 multiplexer is m = xs’+ ys, and one way you can express this in
Verilog is the following:
assign m = x & ~ s j y & s ;
Table 1 shows a mapping of all the bitwise Verilog operators to Boolean symbols.
Table 1: Verilog Operators
Simulation File (.do)
After writing a Verilog code, and to verify the code functionnality properly, we can perform a simulation using a script written in a .do le. This le is also provided to you (on Quercus, and in the appendices of this handout).
Inside the .do le, we start o by creating a working directory called work using the vlib command. We then compile the Verilog le using vlog and load it into the simulation with the vsim command. Lastly, to display all the signals on the waveform viewer, we put f/*g after add wave.
# | S e t | t h e | w o r k i n g | d i r , where a l l | c o m p i l e d | V e r i l o g | g o e s . | |||||||||
vlib | work | |||||||||||||||
# | Compile | a l l | V e r i l o g | modules | i n mux . v | t o | w o r k i n g | d i r ; | ||||||||
# | c o u l d a l s o | have | m u l t i p l e | V e r i l o g | f i l e s . | |||||||||||
# The | t i m e s c a l e | argument | d e f i n e s | d e f a u l t time | u n i t | |||||||||||
# | ( used when | no | u n i t | i s | s p e c i f i e d ) , | w h i l e | t h e | second number | ||||||||
# | d e f i n e s | p r e c i s i o n ( a l l | t i m e s | a r e | rounded | t o t h i s | v a l u e ) | |||||||||
vlog t i m e s c a l e | 1 ns /1 ns | mux . v | ||||||||||||||
# | Load s i m u l a t i o n | u s i n g | mux as | t h e | t o p | l e v e l | s i m u l a t i o n module . | |||||||||
vsim mux | ||||||||||||||||
# Log | a l l | s i g n a l s | and | add | some | s i g n a l s | t o | waveform | window . | |||||||
log f/∗g | ||||||||||||||||
# | add wave f/∗g would add | a l l | i t e m s | i n | t o p | l e v e l s i m u l a t i o n module . | ||||||||||
add wave f/∗g |
Once everything is initiated, we set the input signals to be a 1 or a 0 with the force command. The force command speci es the state of the inputs in the simulation, which mimics setting the inputs using switches in the lab. The run command instructs the simulator to simulate the behavior of the circuit for a speci ed time duration. During this time, the inputs to the circuit are assumed to have the state speci ed by the last force command. If there are inputs whose values have not been speci ed using the force command, their values will be assumed unknown. Depending on the simulator settings, you may see these values appear displayed using special colour in waveforms, and their values labeled as either z or x, instead of 0 or 1. z and x are special symbols used to indicate unknown values.
3
# S e t | i n p u t v a l u e s u s i n g t h e f o r c e  command , | s i g n a l names need | ||||||||
# t o be i n fg b r a c k e t s . | ||||||||||
force | fSW[ 0 ] g | 0 | # | f o r c e | s w i t c h | 0 | (SW[ 0 ] ) | t o | be | 0 |
force | fSW[ 1 ] g | 1 | # | f o r c e | s w i t c h | 1 | (SW[ 1 ] ) | t o | be | 1 |
force | fSW[ 9 ] g | 0 | # | f o c e 3 | s w i t c h | 9 | (SW[ 9 ] ) | t o | be | 0 |
# Run | s i m u l a t i o n | f o r a | few ns . |
run 10 ns
Perform the following steps:
.do le). Look at the generated waveform , which is the simulation output, and verify that the provided test-cases work as expected. (PRELAB).
Start with the code given in Part I and modify the design to make it a 4-to-1 multiplexer. You must use multiple instantiations of the mux2to1 module given to you in Part I. This is known as hierarchical design and is a good practice especially for larger designs where the Verilog code you write can become more di cult to debug. Smaller submodules are generally easier to test thoroughly and debug.
To complete this section, you will need to use the wire declaration to create wires that can be used to connect the multiple blocks together.
wire Connection ; // d e f i n e s a w i r e c a l l e d Connection
The wire created above is called Connection and it can be used to connect the output of a module to the input of another module, the same way you used a physical wire in Lab 1 to connect the output of one gate to the input of another gate. Figure 2 shows a schematic of two modules using the wire Connection. You may also use Connection as input to other logic expressions within the module in which this wire is de ned.
module block1(in1, out1); | module block2(in2, out2); | ||||||||
Connection | |||||||||
SW[0] | in1 | out1 | in2 | out2 | LEDR[5] | ||||
Figure 2: Using the wire Connection to make a connection between two modules
The following Verilog code fragment corresponds to Figure 2. It creates instances of modules block1 and block2, named B1 and B2, respectively. The wire Connection is used to wire the module instances
4
together.
b l o c k 1Â B1 (
. i n 1 (SW[ 0 ] ) ,                  // c o n n e c t                 e x t e r n a l   p o r t SW[ 0 ]  t o p o r t  i n 1     o f         b l o c k 1
. out1 ( Connection )       // c o n n e c t w i r e Connection t o  p o r t o u t 1   o f         b l o c k 1
) ;
b l o c k 2Â B2Â (
. i n 2 ( Connection ) ,         // c o n n e c t w i r e Connection t o  p o r t i n 2 o f b l o c k 2
. out2 (LEDR [ 5 ] )              // c o n n e c t                 e x t e r n a l       p o r t LEDR[ 5 ] t o p o r t o u t 2         o f                                                   b l o c k 2
) ;
Another way to make a connection is to use the assign statement. For example, if we wanted to connect the wire called Connection to LEDR0, we do the following:
assign LEDR [ 0 ] = Connection ; // j o i n s w i r e Connection t o LEDR[ 0 ]
Now construct a module for the 4-to-1 multiplexer shown in Figure 3 with the truth table shown in Table 2 using the wire construct and multiple instances of the mux2to1 module. Note that the truth table in Table 2 is given in a short-hand form. A real truth table would consist of rows enumerating all possible combinations of values of inputs u, v, w, x, in addition to s0 and s1, and show the value (0 or
s1s0Â Â Â m
00Â Â Â Â Â Â u
01Â Â Â Â Â Â v
10Â Â Â Â Â Â w
11Â Â Â Â Â Â x
Figure 3: Symbol for a 4-to-1 multiplexer            Table 2: Truth table for a 4-to-1 multiplexer
Perform the following steps:
5
In this part of the lab, you will design a decoder for the 7-segment HEX display as shown in Figure 4. The output of the HEX display is determined by the value at the input of the decoder as shown in Table 3. We call this a HEX display because it can display all hexadecimal digits.
The 7-segment display uses a common anode. What does common anode mean in terms of lighting up a segment? You should be able to nd the answer online. Section 3.6.2 in the DE1-SoC User manual also tells you what is needed to turn on a segment.
HINT: In order to solve this part you need to rst identify which segment needs to be illuminated for every input and then write a Boolean function for each one of the seven segments of the HEX display so they are turned on when needed. You must use Karnaugh maps to optimize those Boolean expressions before you write the corresponding Verilog code.
c3c2c1c0Â Character
0000Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â 0
0001Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â 1
0010Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â 2
0011Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â 3
0100Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â 4
0101Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â 5
0110Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â 6
0111Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â 7
1000Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â 8
1001Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â 9
1010Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â A
1011Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â b
1100Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â C
1101Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â d
1110Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â E
1111Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â F
Figure 4: HEX decoder                                         Table 3: Desired behaviour of HEX decoder
Debugging Strategy: Before diving into the full Part III implementation, you may nd it helpful to start by creating a very simple Verilog module which turns on segment 0 of the 7-segment display, i.e., pin HEX0 0, based on the input from SW 0.
Perform the following steps:
6
provide input signals for B, then A, then 3, then 1, then 4, and nally 5. You must include your simulation waveforms as part of your prelab. (PRELAB)
output [ 6 : 0 ] HEX0 ;
This way, the names of these outputs match the corresponding names in the DE1-SoC User Manual and the pin assignment DE1 SoC.qsf le.
7