Verilog Introduction: Synopsis
Verilog Introduction: Synopsis
Verilog Introduction: Synopsis
Introduction
Synopsis
This lab introduces you to Verilog. The lab consists of four "mini"‐projects that will introduce you to
Verilog syntax, operations, and grammar. Your TA will supplement this handout with a Verilog tutorial.
Your TA will also introduce you to ModelSim to increase your coding efficiency and enhance your ability
to debug.
Each section presents a separate (independent) task. You will also find a few questions at the end of each
task. You should write (or type) your answers to these and turn them in with your lab.
Mini‐“Projects”
Arbitrary clock divider
Objective
The Nexys3 FPGA uses a 100MHz clock. You learned in the detour and number‐lock labs how to use a
clock divider to produce a slower clock by using a clock divider. But our clock divider produces only clocks
with frequencies of 100MHz divided by powers of 2 (50MHz, 25MHz, 12.5MHz, etc.). In this project you
will build a circuit to produce a clock with a specific desired frequency. This will be useful to many term
projects.
Introduction
Remember that you can use a clock divider with the Nexys3 FPGA to generate clocks with slower
frequency. You do this by using a large counter to output DIV_CLK[31:0]. Each successive bit in the
counter divides the frequency by 2 (doubling the period). So,
BOARD_CLK = 100MHz
DIV_CLK[0] = 50MHz
DIV_CLK[1] = 25MHz
DIV_CLK[2] = 12.5MHz
...
DIV_CLK[25] = 1.49Hz
...
But what if you need a clock with 60Hz? Here we need an alternate method.
Notice that a 60Hz clock "toggles" 120 times / second since each clock has an "up"‐part and a "down"‐
part. So if a signal toggles a register at 120Hz the register will output a 60Hz clock. We now have 2 distinct
(but easier) problems to solve:
1. create a signal (let’s call it count PULSE) with 120 pulses per second
2. create a toggle register and input PULSE
1
EE201L ‐ Introduction to Digital Circuits Verilog Introduction
The procedure and code will step you through the process of creating a hierarchical design that
implements these functions. NOTE: you would not normally break Verilog modules into such atomic
functions because it might reduce the tools ability to optimize your code.
Procedure
1. Open the ee201_pulse_atN module in ModelSim.
2. Consider a 4‐bit counter. Remember that the CEO output is high when all four output bits are 1
(i.e. 1111 = F). So if you input a CLK with 100Mhz to the counter the CEO pulses at 100MHz /
16 = 6.25 million times per second. Each pulse is exactly 1‐clock wide since on the next clock the
4‐bit counter rolls over to 0 (1111 -> 0000) and so CEO return to 0.
So a 4‐bit FF rolls over (starts at 0) every 2^4 = 16 clocks. Now suppose you had a circuit that
counted 0, 1, 2 …, 9, 0, 1 ... (counts to 10) with CEO = 1 when COUNT = 9. Then CEO pulses every
100MHz / 10 = 10MHz (pulse width = 1 clock).
Follow this reasoning to complete (TODOs) the ee201_pulse_atN module. This module takes
an input N and produces a pulse after N clocks.
3. Use the ee201_pulse_atN_tb to simulate your design. Count the number of clocks between
pulses (HINT: N has three different values during the simulation).
4. Open the ee201_clk_60Hz module in ModelSim.
5. Complete (TODOs) the module. Several of the comments provide helpful hints.
6. Use the ee201_clk_60Hz_tb to simulate your design.
Questions
1. Using the waveform what are the three different values of N in the ee201_pulse_atN_tb
simulation?
a. The frequency of the clock is 100MHz. What is the frequency of the pulses for each value
of N?
2. Print modules:
a. ee201_pulse_atN.v
b. ee201_clk_60Hz.v
3. Print waveforms from simulations:
a. ee201_pulse_atN_tb.v
b. ee201_clk_60Hz_tb.v
Weighted coin and die simulator
Objective
Randomness is hard to come‐by in digital circuits. Verilog can generate pseudorandom numbers using
$random(). But this code is NOT synthesizable. So you cannot use $random() in circuits destined for
the Nexys3. This project shows how you can use an asynchronous input (not with the clock) ‐‐ a button
2
EE201L ‐ Introduction to Digital Circuits Verilog Introduction
and a fast clock to produce ~almost~ uniform randomness. You will then add some combinational logic
to add "weighting" (like an unfair coin: 25% heads and 75% tails).
Introduction
Imagine a pendulum swinging back and forth. Suppose you have a button that records the position of the
pendulum each time you press it. Suppose the pendulum is swinging back very slowly (1Hz). If you are
watching the pendulum you could hit the button so that it records the position in almost the same spot
(not exactly, but close) ‐‐ remember its going very slow. Notice that the same thing happens if you decide
to regularly press the button every 1 second or so since the pendulum is swinging at about the same
frequency.
Now imagine the pendulum getting faster, 10Hz. And faster, 1000Hz. Now the pendulum is moving so
fast that you cannot press the button at the same position even if you tried. Even if you press the button
as fast as you can the pendulum will make several swings in between each press. The upshot is that
instead of producing a predictable pattern (like in 1Hz) you will get random positions across the swing.
You can use a fast counter to produce a similar effect in digital logic. Suppose you have a 2‐bit counter
(0, 1, 2, 3, 0, 1 ...) connected to the fast 100MHz Nexys3 clock. Every time you press the button it is equally
likely that the counter is 0, or 1, or 2, or 3. So we have produced a uniform 4‐option random variable (a
4‐sided dice ‐‐ a tetrahedron, 1D4). We can also simulate a coin‐flip by using a 1‐bit counter (0, 1, 0, 1)
with 0 = heads and 1 = tails. And if we want to simulate a 6‐sided die then we can use a 3‐bit counter and
clear the counter every time it hits 5 so it rolls back to 0 ‐‐ 0, 1, 2, 3, 4, 5, 0, 1, ...
Now let’s simulate a coin‐flip that was unfair ‐‐ weighted a little in our favor ‐‐ so H = 25% and T = 75%
(instead of 50/50). We can use a 2‐bit counter and "group" possibilities. Remember that our 2‐bit counter
(0, 1, 2, 3, 0 …) has 4 distinct values. By grouping:
if(COUNT=0)
OUTPUT = head
if(COUNT=1 OR COUNT=2 OR COUNT=3)
OUTPUT = tail
so OUTPUT=head only 1/4 of the time (25%) and OUTPUT=tail 3/4 of the time (75%).
The procedure will step you through code that simulates rolling a fair coin and a fair die. You then finish
the project to cheat just a little by adding some unfairness to your coin flip.
Procedure
1. Open the ee201_roller module in ModelSim.
Complete (TODOs) the module.
2. Modify ee201_roller to simulate flipping a fair coin. Complete the TODO in
ee201_roller_tb and simulate.
3
EE201L ‐ Introduction to Digital Circuits Verilog Introduction
Repeat to simulate rolling a fair die.
3. Uncomment (remove the /** and **/) the "Part 2" sections in the ee201_roller module to enable
weighting.
Complete (TODOs) in this section.
4. Simulate with ee201_roller (update the testbench as necessary). Run the simulation for
1000ns = 1us. Record the tally statistics in the ModelSim (vsim) console.
Run the simulation for 9000ns MORE (total: 10us). Record the statistics in the ModelSim (vsim)
console.
Run the simulation for 990ms MORE (total: 1s). Record the statistics in the ModelSim (vsim)
console.
5. Open the top module (ee201_roller_top).
Complete (TODOs) the module.
Create a new project in Xilinx with your Verilog files. Use the same directory so the ModelSim
and Xilinx projects share the same directory.
Configure your device type, set startup clock = JTAG clock, and generate a bitfile.
Use Adept to load the bitfile onto your FPGA. After you reset (BtnC) the device use BtnL to flip
your unfair coin (20/80). Press the button 20 times and record the number of heads and tails.
Questions
1. How did the module output the unfair flip in Part II since it output the fair flip in "Part 1"?
2. Compare the simulated fair coin flip to the instance on your FPGA. (COMPLETE)
Synchronous vs. Asynchronous FF resets
Objective
The lab tries to show through simulation the difference between FFs with asynchronous and synchronous
reset and also with or without a data‐enable.
Introduction
We have provided a project folder, where you can find a project file (.mpf), two Verilog source files (.v),
two script files (.do), and this lab manual. You can invoke this project in ModelSim as follows. Make sure
that the path of target .mpf file is correctly selected.
File > Open > ff_reset_verilog.mpf
The first source file (ff_reset_verilog.v) is the main design file, where different versions of Flip‐
flop outs (represented as Q_*) have been generated for different purposes. These Q_* can be found in
4
EE201L ‐ Introduction to Digital Circuits Verilog Introduction
Table 1. The second source file (ff_reset_verilog_tb.v) is the testbench to test the design file. A
typical testbench file usually generates clock signal, apply stimulus/input vectors, etc.
Q_* How they are generated?
Q_bad_r BAD coding results in treating the RESET as a Data enable
Q_async_r FF with asynchronous reset
Q_sync_r FF with synchronous reset
Q_no_r FF with no reset at all
Q_async_r_de FF with asynchronous reset with Data Enable
Q_sync_r_de FF with synchronous reset with Data Enable
Q_no_r_de FF with Data Enable but no reset at all
Procedure
1. Complete TODOs by setting a default Q value when reset in ff_reset_verilog.v, either
using Notepad++ or ModelSim as editor.
2. In ModelSim, compile the design file and testbench file and make sure your design has no syntax
errors. Errors will be displayed in the transcript window.
3. Run command: do ff_reset_verilog.do in the transcript window in ModelSim, which
invokes another .do file. These two scripts simulate your design for 600ns and display the
waveforms.
Questions
1. Answer questions in ff_reset_verilog.v and discuss with your TA.
Divider RTL design in Verilog
Objective
This module will introduce you to RTL coding style for state machine and datapath coding. It will also
further your understanding of basic Verilog syntax (case, if-else, always, assign, etc.).
Introduction
A zip file is provided containing a ModelSim project, two source files and a test bench file. Please read the
notes at the top of each file to get to know important aspects of the design to note.
1. divider_combined_cu_dpu.v
2. divider_separate_cu_dpu.v
3. divider_tb_str.v
* ee201l_divider_lab.mpf > ModelSim project
A short description of each of the above 3 files follows.
5
EE201L ‐ Introduction to Digital Circuits Verilog Introduction
divider_combined_cu_dpu.v
A Verilog module for a simple divider. It takes two 4‐bit inputs Xin and Yin (dividend and divisor) and
produce 4‐bit Quotient and Remainder, and three state bits, Qi, Qc, and Qd, as outputs. There are inputs
that control the state machine as well (Start, Ack, Clk, Reset, and Done)
module divider (Xin, Yin, Start, Ack, Clk, Reset, Done, Quotient,
Remainder, Qi, Qc, Qd)
Note that the name of the module is divider, and we’re going to use a single test bench to test two
different divider designs divider_combined_cu_dpu.v and divider_separate_cu_dpu.v.
Their functionalities are identical.
There are three states – INITIAL, COMPUTE and DONE_S ‐ in the state machine and they are one‐hot
coded as below.
localparam
INITIAL = 3'b001,
COMPUTE = 3'b010,
DONE_S = 3'b100;
In this file, there is a single always block where you can locate NSL and SM for three states listed above.
divider_separate_cu_dpu.v
Another Verilog module for a simple divider. In this design, there are two separate always blocks, where
one is for CU and the other is for DPU. There are some blank indicated as ‘TODO’ in this file, for students
to complete.
divider_tb_str.v
A test bench file that performs three divider operations. These are 15 ÷ 7, 5 ÷ 8 and 11 ÷ 3. Run ModelSim
simulation and see messages in the transcript panel for results of the above three operations.
Procedure
1. Read file divider_combined_cu_dpu.v and answer to exercise question 7‐a.
2. Open ee201l_divider_lab.mpf and type do divider.do in the transcript panel. See
messages in the transcript panel and check results of three divider operations.
3. Type quit –sim to escape from simulation.
4. Read file divider_separate_cu_dpu.v and fill‐in every TODO blank.
5. In the same project ee201l_divider_lab, type do divider_exercise.do in the transcript panel. See
messages in the transcript panel and compare results of three divider operations with those
obtained from 6‐b.
6. Answer to question 7‐c. If necessary, change the line in divider_combined_cu_dpu.v and
repeat procedure 6‐b again to see the difference (or they could be the same)
Questions
1. Complete a state machine of the divider module based on divider_combined_cu_dpu.v.
6
EE201L ‐ Introduction to Digital Circuits Verilog Introduction
RESET
2. Fill‐in every blank named TODO in divider_separate_cu_dpu.v.
3. In divider_combined_cu_dpu.v, what will happen if line 73
if (!(X < Y))
is changed to
if (X > Y)?
Can we still obtain correct results from the modified divider design? How about three test cases
in our test bench?
7