This shows you the differences between two versions of the page.
Both sides previous revision Previous revision Next revision | Previous revision | ||
labs:stopwatch [2019/10/18 15:59] nelson [Exercise 1: Modulus Counter] |
labs:stopwatch [2020/05/18 11:18] (current) nelson [Personal Exploration] |
||
---|---|---|---|
Line 25: | Line 25: | ||
===== Exercise 1: Modulus Counter ===== | ===== Exercise 1: Modulus Counter ===== | ||
- | At the heart of your stopwatch will be a counter module for each of the eight digits. The counter should be a modulus counter, meaning it counts up to some predetermine value, then rolls over to 0 and continues counting. | + | At the heart of your stopwatch will be a counter module for each of the eight digits. The counter should be a modulus counter, meaning it counts up to some predetermined value, then rolls over to 0 and continues counting. |
- | You will use a SystemVerilog ''parameter'', ''MOD_VALUE'' to indicate the modulus value. The counter should reach ''(MOD_VALUE-1)'' and then roll over to 0. This approach will allow us to use this module for digits that count 0-9, as well as digits that count 0-5. Consult the //Parameterization in Dataflow SystemVerilog// section in the textbook for an example on adding parameters to your SystemVerilog modules. | + | You will use a SystemVerilog parameter, ''MOD_VALUE'' to indicate the modulus value. The counter should reach ''(MOD_VALUE-1)'' and then roll over to 0. This approach will allow us to use this module for digits that count 0-9, as well as digits that count 0-5. Consult the //Parameterization in Dataflow SystemVerilog// section in the textbook (Chapter 14) for an example on adding parameters to your SystemVerilog modules. |
Line 39: | Line 39: | ||
| reset | Input | 1 | Reset | | | reset | Input | 1 | Reset | | ||
| increment | Input | 1 | When high, increment the counter value on the next clock edge. | | | increment | Input | 1 | When high, increment the counter value on the next clock edge. | | ||
- | | rolling_over | Output | 1 | High when the counter is about to roll-over (increment is high and counter is at the maximum value). NOW, re-read the previous sentence carefully - it is NOT asserted just when | + | | rolling_over | Output | 1 | High when the counter is about to roll-over (increment is high __and__ counter is at the maximum value). NOW, re-read the previous sentence carefully - it is NOT asserted just when the counter is at the maximum value. Do you see the difference? | |
- | the counter is at the maximum value). | | + | |
| count | Output | 4 | The counter value | | | count | Output | 4 | The counter value | | ||
Line 47: | Line 46: | ||
* Create a Vivado project. | * Create a Vivado project. | ||
* Write the SystemVerilog for the ''mod_counter'' module. | * Write the SystemVerilog for the ''mod_counter'' module. | ||
- | * Create a tcl simulation script, and verify that your counter is working. Make sure your simulation is thorough; for example, check that the counter only counts when ''increment'' is high, and that the ''rolling_over'' output is high only in the appropriate condition. | + | * NOTE: the vast majority (>90%?) of students write the logic for their ''rolling_over'' wrong the first time. Why? Go re-read the description for this signal above a third time. Exactly what is the logic condition for this signal? Does it involve the 'clk' signal and a register or is it purely combinational logic? If you put the code to generate this signal this inside an ''always_ff'' block will it generate a register or will it generate combinational logic? What is it that you really want? |
+ | * Create a tcl simulation script, and verify that your counter is working. Make sure your simulation is thorough; for example, check that the counter only counts when ''increment'' is high, and that the ''rolling_over'' output is high only in the appropriate condition. Also, don't forget to do the Tcl file in this general order: a) set up the clocking, b) reset the design and simulate a few cycles, and then c) exercise the rest of your counter functionality. | ||
- | <color #ed1c24>Include you Tcl simulation script in your lab report.</color> | + | <color #ed1c24>Include your Tcl simulation script in your lab report.</color> |
**Pass-Off:** Show the TA your simulation and explain how you tested the correctness of your module. | **Pass-Off:** Show the TA your simulation and explain how you tested the correctness of your module. | ||
Line 56: | Line 56: | ||
===== Exercise 2: Stopwatch Module ===== | ===== Exercise 2: Stopwatch Module ===== | ||
- | In this exercise you will create the stopwatch module which will consist of eight instances of your ''mod_counter'' module. Each of these instances will be responsible for generating the value for one digit of the display. | + | In this exercise you will create the stopwatch module which will consist of eight instances of your ''mod_counter'' module . Each of these instances will be responsible for generating the value for one digit of the display. In addition, you will create one counter which will serve as a timer module to time the refreshing of your 7-segment display. The figure below shows the overall outline of your ''stopwatch'' module. |
- | Each ''rolling_over'' output is fed into the ''increment'' signal for the next most significant digit, as shown below. A counter is added to the module that rolls over every 0.0001s. When this counter rolls over, it should generate a **single cycle pulse** that is input to the ''increment'' signal for the least significant digit. | + | ===The ''mod_counter'' Modules== |
- | + | Your stopwatch will contain eight copies of your ''mod_counter''. Each counter's ''rolling_over'' output is fed into the ''increment'' signal for the next most significant digit, as shown below. You will need to declare those intermediate signals as local signals in your SystemVerilog code. | |
- | The 0.0001s counter should increment every cycle that the ''run'' input is high, and reset to 0 if the ''reset'' input is high. | + | |
Make sure you set the roll-over parameter for each of your ''mod_counter'' instances. The most significant two digits represent minutes, and the next two digits represent seconds; both should roll over at 59. The lower four digits represent fractions of a second, and should behave accordingly. | Make sure you set the roll-over parameter for each of your ''mod_counter'' instances. The most significant two digits represent minutes, and the next two digits represent seconds; both should roll over at 59. The lower four digits represent fractions of a second, and should behave accordingly. | ||
- | <color #ed1c24>Given that the system clock is 100MHz, what value does your counter need to count to in order to roll over every 0.0001s?</color> | + | ===The 0.0001s ''timer'' Module== |
+ | Note the module in the upper left - this is a counter that rolls over every 0.0001s. When this counter rolls over, it should generate a **single cycle pulse** on its output. That pulse then is the input to the ''increment'' signal for the least significant digit of the 8 digits. This 0.0001s counter should increment every cycle that the ''run'' input is high, and reset to 0 if the ''reset'' input is high (where reset takes precedence). | ||
+ | |||
+ | <color #ed1c24>Given that the system clock is 100MHz, what value does your counter need to count to in order to roll over every 0.0001s?</color> | ||
+ | |||
+ | To answer this question you should a) compute how long (in seconds) one clock period is for a 100MHz clock. Then calculate how many of those will fit into a 0.0001s interval. That is the maximum count value for this counter. Also, once you compute this you should then be able to calculate how many bits wide the counter should be. Remember: you can only count from 0-15 using 4-bits, to count from 0-1023 takes 10 bits, to count from 0-2047 takes 11 bits, and so on. Once you know the maximum count value and the number of bits for the counter, you can design it. | ||
+ | |||
+ | You have two ways to design this timer, you can choose which to use. | ||
+ | - The first way is to simply design this counter very similarly to how you designed the ''mod_counter'' module. In fact, you could largely just copy the code and change the number of bits in the counter. | ||
+ | - The second way is to modify your ''mod_counter'' module to be parameterized for width and then just instance another copy of it. Note that it already is parameterized with a ''MOD_VALUE'' parameter for its maximum count. If you simply add a **second parameter** to parameterize number of bits for the counter signal you can then just instance another copy of your ''mod_counter'' design for this ''timer'' module. | ||
+ | * The textbook example on parameterization shows how to parameterize signal widths. | ||
+ | * To add a second parameter in the module definition, you just separate it from the first using a comma like this: ''#(parameter PARAM1 = val1, PARAM2 = val2)''. | ||
+ | * Then, when you instance it, you add a second value inside the parens like this: ''mod_counter #(10, 495) TIMER (clk, run, ...)''. | ||
+ | |||
+ | {{ :labs:stopwatch:stopwatch.png?400 |}} | ||
+ | |||
+ | ===The Stopwatch Design== | ||
+ | Now that you have all the blocks designed, create a ''stopwatch'' module and instance all of the needed modules inside it. | ||
+ | |||
+ | Some things to remember: | ||
+ | - You will need to declare local signals for those wires in the diagram below that are not input or output signals. | ||
+ | - Note that the your ''timer'' module output ('count') is not tied to anything. You will still need to declare a local signal for it to wire up to the ''timer'' module, but that signal will not connect to anything else in your ''stopwatch'' module. | ||
^ Module Name = stopwatch ^^^^ | ^ Module Name = stopwatch ^^^^ | ||
Line 79: | Line 99: | ||
| digit6 | Output | 4 | The value of the minutes digit | | | digit6 | Output | 4 | The value of the minutes digit | | ||
| digit7 | Output | 4 | The value of the tens of minutes digit | | | digit7 | Output | 4 | The value of the tens of minutes digit | | ||
- | |||
- | |||
- | {{ :labs:stopwatch:stopwatch.png?400 |}} | ||
Create a tcl simulation script to simulate the behavior of your ''stopwatch'' module. You will likely need to simulate for several milliseconds to check that the lower digits are functioning correctly. It will take too long to simulate the upper digits, so you will have to wait until next exercise to test it on the board. In your simulation, make sure to check that: | Create a tcl simulation script to simulate the behavior of your ''stopwatch'' module. You will likely need to simulate for several milliseconds to check that the lower digits are functioning correctly. It will take too long to simulate the upper digits, so you will have to wait until next exercise to test it on the board. In your simulation, make sure to check that: | ||
Line 88: | Line 105: | ||
* The stopwatch only runs when the ''run'' input is high. | * The stopwatch only runs when the ''run'' input is high. | ||
* The digits roll over correctly. | * The digits roll over correctly. | ||
+ | * The rest works after it has counted for some time. | ||
<color #ed1c24>Include your Tcl simulation script in your lab report.</color> | <color #ed1c24>Include your Tcl simulation script in your lab report.</color> | ||
Line 96: | Line 114: | ||
In this exercise you will create the top-level module and test your stopwatch on the board. | In this exercise you will create the top-level module and test your stopwatch on the board. | ||
- | Create the top-level module as follows, and be sure to include an appropriate constraints file: | + | Create the top-level module as follows: |
^ Module Name = stopwatch_top ^^^^ | ^ Module Name = stopwatch_top ^^^^ | ||
Line 108: | Line 126: | ||
Your top module should: | Your top module should: | ||
* Instantiate both your ''stopwatch'' module, as well as a [[resources:seven_seg|SevenSegmentControl]] module. | * Instantiate both your ''stopwatch'' module, as well as a [[resources:seven_seg|SevenSegmentControl]] module. | ||
- | * Concatenate your digit values output from the ''stopwatch'' module and provide them to the ''dataIn'' input of the ''SevenSegmentControl''. | + | * Connect your digit values output from the ''stopwatch'' module to the ''dataIn'' input of the ''SevenSegmentControl''. |
* Turn on the appropriate decimal point. | * Turn on the appropriate decimal point. | ||
+ | * **Note:** The CPU_RESETN button is active-low. This means it behaves differently than the other buttons you have used: it is a ''0'' when pressed and a ''1'' otherwise. You will need to invert the signal when connecting it to your ''stopwatch'' and ''SevenSegmentControl'' modules. | ||
+ | Be sure to include an appropriate constraints file: | ||
+ | * **Note:** For this lab, and all subsequent labs that use the ''clk'' pin, you should also uncomment two lines near the top that refer to the clock. One connects the clock, the line after it tells informs Vivado that the clock runs at 100MHz. | ||
- | **Pass-off:** Show the TAs your stopwatch working on the board. | + | ===== Final Passoff===== |
+ | Show the TAs your stopwatch working on the board. | ||
- | <color red>Submit your SystemVerilog modules using the code submission on Learning Suite.</color> (Make sure your SystemVerilog conforms to the lab SystemVerilog coding standards). | + | =====Final Questions===== |
+ | <color red>Submit your SystemVerilog modules as part of the lab report on Learning Suite. (Make sure your SystemVerilog conforms to the lab SystemVerilog coding standards). </color> | ||
+ | <color red>How many hours did you spend on this lab?</color> | ||
+ | |||
+ | <color red>Describe any problems or challenges you had with the lab. </color> | ||
+ | |||
+ | /* | ||
=====Personal Exploration===== | =====Personal Exploration===== | ||
Here are some ideas for personal exploration in this laboratory: | Here are some ideas for personal exploration in this laboratory: | ||
* Use additional switches to make your stopwatch run faster or slower than real-time. | * Use additional switches to make your stopwatch run faster or slower than real-time. | ||
- | * In the first exercise, is the ''rolling_over'' output a mealy or moore-type output? Would the stopwatch work if the other type were used? What might be the advantages/disadvantages? | ||
* Modify your design to work as a countdown timer when sw1 is high, and a count-up timer when sw0 is low. | * Modify your design to work as a countdown timer when sw1 is high, and a count-up timer when sw0 is low. | ||
+ | |||
+ | <color red>Describe your personal exploration.</color> | ||
+ | */ |