====== Lab 6 - Fun With Registers ======
=== Prof Brent Nelson ===
In this lab you will do some experimentation with flip flops to learn how they operate. You will create a single-bit loadable register, a 4-bit loadable register, and a counter.
===== Learning Outcomes =====
* Create a sequential circuit using FDCE flip-flop primitives
* Learn how to organize multiple flip-flops into a register
* Create a clearable, incrementable 4-bit counter
===== Preliminary =====
The Artix-7 FPGA we are using has built-in flip-flops that you can use to make sequential circuits. You will use FDCE flip-flop primitives to construct a few simple register-type circuits. The FDCE flip-flop is available to you without any extra work required on your part, you merely need to instance it into your design the same way you instance your own modules into your designs. Read the following pdf file to learn about the FDCE module, its ports, and how to instance the module in your SystemVerilog.
{{ :tutorials:fdce.pdf |}}
The SystemVerilog example below demonstrates how to instance a single FDCE flip-flop into a design:
FDCE my_ff (.Q(ff_output), .C(CLK), .CE(1'b1), .CLR(1'b0), .D(ff_input));
The example shown above assigns a constant zero to the CLR input and a constant one to the clock_enable since we will not use those functions. As a result, what you are getting is basically a flip flop with a D input, a clock input (C), and a Q output. NOTE: this is a rising edge triggered flip flop.
===== Exercises =====
==== Exercise #1 - 1-Bit Register ====
For this exercise you will create a 1-bit register. It is exactly the circuit in Figure 16.4 in the textbook. Begin this exercise by creating a new Vivado project and an empty SystemVerilog module with the following name and ports.
^ Module Name: funRegister ^^^^
^ Port Name ^ Direction ^ Width ^ Function ^
| CLK | Input | 1 | Clock input |
| DIN | Input | 1 | Data to be loaded into register |
| LOAD | Input | 1 | Control signal to cause register to load |
| Q | Output | 1 | Register output |
| NXT | Output | 1 | The input to the register (we want to monitor it as an output of this module.) |
Note that in Figure 16.4 there is an unlabelled signal --- it is the
output of the MUX (which is also the input to the flip flop). Label it in your textbook with the name
NXT. It is
the NXT signal in the table above. It is the value the
flip flop will load on the next edge of the CLK signal (and thus the
name NXT). We want to see it in our design and so we are bringing it out of the module as an ouput
so we can watch it.
Then, instance one FDCE flip-flop as shown above. Then, add either a single dataflow statement or an always_comb block to implement the MUX logic. You should now have logic which implements the MUX and have the MUX wired to the ports on the FDCE. This is called a "loadable register". On each rising edge of CLK, If LOAD is high, then the flip flop will load what is on its DIN input. On the other hand, if LOAD is low, then the flip flop will load its old value.
SANITY CHECK: your code should have approximately 5 lines. If it has a lot more you are likely on the wrong track...
After creating your register, simulate your register with a TCL script. The following
set of TCL commands demonstrates a simple test for your register file. You can use this script and add to or modify it to test your register as you like.
Make sure that your TCL file includes a ''run 100ns'' at the beginning. For the first 100ns, the FDCE primitive resets itself. During this time it won't operate at all, so wait for this time to be over.
restart
# run for 100ns so the FDCE can properly reset
run 100 ns
# set inputs low
add_force LOAD 0
add_force DIN 0
# add oscillating clock input with 10ns period
add_force CLK {0 0} {1 5ns} -repeat_every 10ns
# run 3 cycles before loading anything
run 30 ns
# load a 0
add_force LOAD 1
run 20ns
add_force LOAD 0
# change DIN and run some time
# notice that the register doesn't
# load this new value because
# the load signal is low
add_force DIN 1
run 20ns
# now let's load the register
add_force LOAD 1
run 10ns
add_force LOAD 0
add_force DIN 0
run 10ns
# now we will apply various
# data input values and watch
# the register load them
# on succeeding clock edges
add_force DIN 1
run 10ns
add_force LOAD 1
run 10ns
add_force DIN 0
run 10ns
run 10ns
run 10ns
add_force DIN 1
run 10ns
run 10ns
add_force DIN 0
**Exercise 1 Pass-off:** No need to pass off this. Just make sure it works in simulation before you proceed.\\ \\
==== Exercise #2 - 4-bit Register ====
In this exercise, you will modify your register to be 4 bits wide as shown in Figure 16.5
of the textbook. To do this the changes to your code are minimal: (a)
make the DIN, NXT, and Q signals 4 bits wide in your module definition and (b) instance a total of 4 FDCE flip flops and wire them up like the one in Exercise #1. If you have used a ?: operator or an if-then-else statement to describe your MUX you probably shouldn't even have to change the MUX code.
After creating your register, simulate it by modifying your original TCL script. The only changes that you should have to make are to change the 1 and 0 values you drive into DIN to be more interesting numbers between 0000 and 1111.
Provide a copy of your TCL script you used to simulate the 4-bit register.
**Exercise 2 Pass-off:** Show a TA your code for your 4-bit register
and your simulation waveform. Show that your register loads 4-bit
values from DIN when LOAD=1 and keeps its old value otherwise. Also
show that the NXT signal does indeed reflect what the output of the
MUX value should be. \\ \\
==== Exercise #3 ====
We are now going to modify your 4-bit register to create a counter and use the counter to blink some lights.
In addition to making registers to hold values, another good use of registers is to create counters. Figure 16.7 from the textbook shows such a counter. It can be cleared and it can be incremented under control of the signals CLR and INC.
^ Module Name: funRegister ^^^^
^ Port Name ^ Direction ^ Width ^ Function ^
| CLK | Input | 1 | Clock input |
| CLR | Input | 1 | Clear control signal |
| INC | Input | 1 | Increment control signal |
| Q | Output | 4 | 4 bits of counter's register |
| NXT | Output | 4 | the register's 4 input bits |
Modify your design (erase the old stuff you don't need and add the new stuff):
* Change your module definition to reflect the signals in the table above.
* Create combinational logic using either a ?: dataflow assignment or an always_comb if statement to implement the MUX of Figure 16.7 in the textbook.
* Wire the MUX up to the register's input and output wires.
Modify your TCL script from above to exercise the counter. First, clear the counter and then increment for a few cycles. Then, clear it again and then increment it 20 or so cycles. Raise and lower INC as you do this to observe that it only counts on rising clock edges where INC is true. Finally, increment it enough times so that it then rolls back over to 0.
Provide a copy of your TCL script you used to simulate the counter.
**Exercise 3 Pass-off:** Show a TA your code for your 4-bit counter
and your simulation waveform. Show that your counter works as
desired. Also show that the value of NXT is what you would expect.\\ \\
==== Exercise #4: Synthesize, Implement, and Test in Hardware ====
You are now ready to test your counter in hardware.
First, we need to create an XDC file for your design to declare the
pin numbers for each top-level port of the design. Below are the pins
you should tie up and what to tie them to:
^ Port Name ^ Direction ^ Width ^ Function ^
| CLK | Input | 1 | Tie to the center button (btnc) |
| CLR | Input | 1 | Tie to switch 0 |
| INC | Input | 1 | Tie to switch 1 |
| Q | Output | 4 | Tie to led3-led0 |
| NXT | Output | 4 | Tie to led11-led8 |
**Note**: Your constraints file will instruct Vivado to connect the ''CLK'' to a button; however, Vivado knows that this is not a true clock pin and will report an error. In order to ignore this, you will need to add the following line to your constraints file, which you can add immediately after the constraint that connects ''CLK'' to the button:
''set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets CLK_IBUF];''
Even with this inserted you will get a Critical Warning, which you can ignore (at least it is now a warning and not an error).
Perform the steps of Synthesis, Implementation, and Bitstream
Generation. Download your design and demonstrate that it is working
properly. When you turn on CLR you should immediately see that NXT is
0. When you then push the CLK button the flip flop will actually load
that value and will become a 0 and you will see that on the LEDs.
Then, when you then deassert CLR and assert INC you should see that NXT
becomes Q+1. When you then push the CLK button you should see the
counter increment and then immediately NXT will become the new value
of 1 plus the new Q value.
NOTE: This is the only lab where we will tie the CLK input to a button.
In all later labs it will be tied to a 100MHz input to the FPGA.
You may notice that, in actuality, your counter may increment more than once when you
push the CLK button. Why? It is because we have tied the CLK input to a button.
In the real-world buttons and switches
don't transition cleanly from open to closed or from closed to open.
As they are opening or closing they may "bounce", meaning they may
open and close rapidly in succession. Thus, when you push your CLK
button the circuit might actually get multiple clock edges like this:
0-1-0-1-0-1-0. In that case your circuit would see 3 rising clock
edges and your counter would increment by 3. At other times it might
just go 0-1-0 and your counter will increment by 1. Experiment with it
to see just how "bouncy" the button is on the board you are using. It
might be pretty bad or it might hardly ever bounce. In a later lab we
will design a circuit to clean up the button output by ignoring the
bouncing. But, for now we have to live with it.
AWESOME! You have designed your first sequential circuit.
===== Final Pass Off =====
Pass off your laboratory by demonstrating the following to the TA:
* Pass off Exercise 4 by showing it working on the board
How many hours did you work on the lab?
Provide any suggestions for improving this lab in the future.
Submit your final SystemVerilog modules using the code submission on Learning Suite. (Make sure your SystemVerilog conforms to the lab SystemVerilog coding standards).
===== Personal Exploration =====
Choose one of the following for personal exploration in this laboratory:
* Make your counter wider and wire up to additional LEDs.
* Wire in a copy of your 7-segment decoder from last week and have the 4-bit counter value displayed on the 7-segment display. By the way, this is way cooler than just making your counter wider... :-)
Describe your personal exploration activities.
/*
===== Lab Report =====
* **Header**
* Class
* Lab
* Name
* Section
* **Preliminary**
* Q waveform
* **Exercise 1**
* Simulation screenshot
* 4-bit register Verilog
* **Exercise 2**
* TCL script
* Register file Verilog
* **Exercise 3**
* Top-level Verilog
* **Exercise 4**
* Synthesis warnings
* Number of LUTs and FFs
* Personal exploration description
* Hours spent on lab
* Feedback
*/
----
[[labs:ta:registerfile|TA Notes and Feedback]]