.. _ch:stopwatch: Stopwatch ========= This lab implements a stopwatch which displays the elapsed time since we activated a switch button. We'll split the task of designing our stopwatch into three steps. First, in :numref:`ch:stopwatch_counters` we'll design a modulo-k counter which produces a tick every :math:`k` cycles of an input clock signal. Second, in :numref:`ch:stopwatch_clock_signals` we'll implement our own clock signals which have frequencies of interest to us. Third, in :numref:`ch:stopwatch_elapsed_time` we'll use our custom clock signals and count the number of elapsed time units which the final stopwatch displays. .. _ch:stopwatch_counters: Counters -------- Our stopwatch will show typical time units since the last reset, i.e., tenths of a second, seconds, tens of seconds, minutes and tens of minutes. The clock signals available in the MAX 10 FPGA have much higher frequencies. This means that we require a way to generate clock signals with (much) lower frequencies from the provides ones. .. figure:: /chapters/data_stopwatch/clocks_4.svg :name: fig:stopwatch_clocks Illustration of different clock signals. Clock signal clk0 has the highest frequency and a total of 12 cycles of clk0 are illustrated. Four additional clock signals with lower frequencies w.r.t. to clk0's frequency are shown: clk1 (half), clk2 (third), clk3 (fourth) and clk4 (eighth). :numref:`fig:stopwatch_clocks` illustrates the challenge. Here, clk0 has the highest frequency and we are interested in deriving new clock signals from clk0. For example, we could be interested in generating the signal clk3 which has a four times lower frequency than clk0. Putting some numbers behind this, assume that clk0 has a frequency of 100MHz. This means that we have :math:`100 \cdot 10^6` cycles per second as input. Now, we'd like to generate the 25MHz signal clk3 which therefore has :math:`25 \cdot 10^6` cycles per second. How can we design a circuit which takes clk0 as input and outputs clk3? The conceptual answer to this is a rather simple one: We simply count the number of elapsed cycles of the higher-frequency clock and generate our new clock signal based on that counter. .. figure:: /chapters/data_stopwatch/ctr3.svg :name: fig:stopwatch_counter_3 Illustration of an input clock signal clk0 which is used as input for the modulo-2 counter ctr3. The counter outputs the visualized rollover signal which can be used to generate the clock signal clk3. :numref:`fig:stopwatch_counter_3` illustrates the counter-based generation of the clock signal clk3 from signal clk0. The used counter ctr3 is an instantiation of a modulo-k counter where :math:`k=2` for ctr3. Our targeted modulo-k counter counts from 0 to :math:`k-1`. When the counter has the value :math:`k-1` in a clock cycle, it will have the value 0 in the next clock cycle. As shown in :numref:`fig:stopwatch_counter_3` ctr3 has the initial value 0 during the first clock cycle of clk0 with id 0. Then, in the second clock cycle of clk0 with id 1, the value of ctr3 is 1. This means that ctr3 now has the value :math:`k-1`. Thus, in the next clock cycle of clk0 which has id 2, the value of ctr3 is 0. Similarly, ctr3 has the value zero in clk0's clock cycles with ids 4, 6, 8 and 10. .. figure:: /chapters/data_stopwatch/ctr4.svg :name: fig:stopwatch_counter_4 Illustration of an input clock signal clk0 which is used as input for the modulo-4 counter ctr4. The counter outputs the visualized rollover signal which can be used to generate the clock signal clk4. Another modulo-k counter with :math:`k=4` is illustrated in :numref:`fig:stopwatch_counter_4`. Here, ctr4 counts from 0 to 3. Respectively, ctr4's value is 0 in clk0's clock cycles with ids 0, 4 and 8. .. literalinclude:: data_stopwatch/counter_mod_k_count.sv :linenos: :language: systemverilog :caption: Implementation of the module ``counter_mod_k_count``. :name: lst:counter_mod_k_count An implementation of a SystemVerilog module which implements a modulo-k counter is given :numref:`lst:counter_mod_k_count`. We see that the module modifies the counter's value ``m_count`` only on a rising edge of the input clock signal ``i_clk`` or the reset signal ``i_reset`` (line 18 - 35). If the reset signal is high, the counter's value ``m_count`` is set to zero (lines 20 - 23). Additionally, if the reset signal is low, ``m_count`` is also set to zero if the counters value is :math:`k-1` (lines 26-29). Lastly, if neither of the previous cases occurred, the counter is simply incremented (lines 30-33). The output of the counter is its value (line 38). In this part of the lab, we'll implement and test a slightly different module. Instead of outputting the value of the counter, we output a 1-bit rollover signal. We set this rollover signal to high in the clock cycle of the input clock after a rollover ocurred, i.e., the counter's value changed from :math:`k-1` to :math:`0`. In all other cases the rollover signal is low. The illustrated signals of ctr3 in :numref:`fig:stopwatch_counter_3` and ctr4 in :numref:`fig:stopwatch_counter_4` show the rollover. A template of the targeted module ``counter_mod_k_ro`` is given in :numref:`lst:counter_mod_k_ro`. To simplify your initial efforts, a :download:`code frame <data_stopwatch/stopwatch.tar.xz>` for the stopwatch is provided as starting point. .. literalinclude:: data_stopwatch/counter_mod_k_ro.sv :linenos: :language: systemverilog :caption: Template of the module ``counter_mod_k_ro``. :name: lst:counter_mod_k_ro .. admonition:: Tasks #. Finish the implementation of the module ``counter_mod_k_ro`` and the testbench ``counter_mod_k_ro_tb`` in the stopwatch code frame. Use :math:`k=4` in the testbench and check the output of the counter for at least ten clock cycles. #. Generate a waveform plot illustrating the behavior of ``counter_mod_k_ro`` with :math:`k=4` in the first ten clock cycles of the input clock ``i_clk``. The plot shall show all inputs, i.e., ``i_clk``, ``i_reset``, ``i_k``, the value of the counter, i.e., ``m_count``, and the output ``o_roll_over``. .. _ch:stopwatch_clock_signals: Clock Signals ------------- .. raw:: html <video width="100%" controls> <source src="../_static/clocks_de10_lite.mp4" type="video/mp4"> </video> In this task we use our modulo-k counter with rollover output to derive custom clock signals. For this, we'll write a SystemVerilog module which takes a rollover signal as an input and outputs a clock signal. Specifically, on each rising edge of the rollover signal our clock changes its state. We see in :numref:`fig:stopwatch_counter_3` that we may obtain the clock signal clk3 from ct3's rollover output. Here, the state of clk3 changes for the first time from high to low when clk0 transitions from cycle 1 to cycle 2. This coincides with the first shown rising edge of ctr3's rollover signal. Since a full clock cycle implies two state changes, the resulting clock signal of ctr3 has a four times lower frequency when compared to clk0. The clock clk4 in :numref:`fig:stopwatch_counter_3` is derived analogously from the rollover output signal of ctr4. .. literalinclude:: data_stopwatch/clock.sv :linenos: :language: systemverilog :caption: Template of the module ``clock``. :name: lst:clock A template for the clock is given in :numref:`lst:clock`. The module shall only change its state on a rising edge of input ``i_roll_over`` or ``i_reset``. If ``i_reset`` is high, the clock should set its state ``m_clk`` to high. Otherwise it should simply change its state, i.e., if ``m_clk`` is high it should change to low and if ``m_clk`` is low it should change to high. Once our custom clock is implemented and tested, we can combine it with the modulo-k counter given through the module ``counter_mod_k_ro``. Combined both modules allow us to lower frequency of the clock signal ``MAX10_CLK1_50`` which can be accessed in the MAX 10 FPGA. In the last part of this task, we'll generate a 10Hz clock signal, an 1Hz signal and an 0.1Hz one from ``MAX10_CLK1_50``. We'll display the 10Hz clock signal using ``LEDR5``, the 1Hz signal using ``LEDR6``, and the 0.1Hz one using ``LEDR7``. The signal of the first switch button ``SW0`` will drive the reset signal of all modules (reset on low). An exemplary video of the targeted functionality is shown at the top of this task. .. hint:: Base all your custom clocks on the MAX10_CLK1_50 clock signal. In other words: Do not chain your clocks! .. admonition:: Tasks #. Finish the implementation of the module ``clock`` and the testbench ``clock_tb`` in the stopwatch code frame. #. Generate a waveform plot illustrating the behavior of the module ``clock``. Manually provide the rollover signal when generating the plot and show three full cycles of the clock. The plot shall show all inputs, i.e., ``i_roll_over``, ``i_reset`` and the output ``o_clk``. #. Look up the frequency of the clock signal ``MAX10_CLK1_50`` in the `DE10-Lite User Manual <https://www.terasic.com.tw/cgi-bin/page/archive_download.pl?Language=English&No=1021&FID=a13a2782811152b477e60203d34b1baa>`__. #. Derive appropriate values for :math:`k` such that you can use ``MAX10_CLK1_50`` as clock input for your modulo-k counter ``counter_mod_k_ro`` followed by the clock module ``clock`` to generate clock signals with 10Hz, 1Hz and 0.1Hz. #. Finish the top-level module ``clocks_de10_lite`` of the stopwatch code frame. Use the smallest possible values for the parameter ``N`` in the instantiations of the module ``counter_mod_k_ro``. #. Program the FPGA of a DE10-Lite board. Explain and illustrate your programmed FPGA to the teaching personnel. In your submission include a scan of this week's tailored coversheet which represents the deliverable of this subtask. .. _ch:stopwatch_elapsed_time: Elapsed Time ------------ .. raw:: html <video width="100%" controls> <source src="../_static/stopwatch_de10_lite.mp4" type="video/mp4"> </video> This final part of the lab combines the pieces of :numref:`ch:stopwatch_counters` and :numref:`ch:stopwatch_clock_signals` into an actual stopwatch. For this we write the top-level module ``stopwatch_de10_lite``. The short video above shows the deployed stopwatch. The stopwatch uses switch button ``SW0`` as input. If ``SW0`` is high the watch runs and measures the elapsed time, if it is low the stopwatch holds and resets to zero. The outputs of the stopwatch are as follows: * ``LEDR5`` displays the 10Hz clock signal which drives a tenth of a second counter * ``HEX0`` displays the output of the tenth of a second counter * ``LEDR6`` displays the 1Hz clock signal which drives a seconds counter * ``HEX1`` displays the output of the seconds counter. Further, ``HEX1`` has an always-on decimal dot. Check the DE10-Lite User Manual on how to activate the dot. * ``LEDR7`` displays the 0.1Hz clock signal which drives a tens of seconds counter * ``HEX2`` displays the output of the tens of seconds counter * ``HEX3`` displays a blinking dash which separates the displays showing seconds from the ones showing minutes * ``LEDR8`` displays the 1/60Hz clock signal which drives a minutes counter * ``HEX4`` displays the output of the minutes counter * ``LEDR9`` displays the 1/600Hz clock signal which drives a tens of minutes counter * ``HEX5`` displays the output of the tens of minutes counter In general, one of the time-showing HEX displays can be programmed by combining four modules: #. A modulo-k counter which generates a suitable rollover signal from ``MAX10_CLK1_50``. In :numref:`ch:stopwatch_clock_signals` we already derived proper values for :math:`k` for the seconds-related parts. Respective values of :math:`k` for minutes and tens of minutes still have to be derived. #. A clock which takes the rollover output of the modulo-k counter as input and generates a respective clock signal. #. Another modulo-k counter which has the generated clock signal as input and outputs the counter's value. *Hint*: For this counter :math:`k` is either 6 or 10. #. A decoder which wires the output bits of the second counter to the respective HEX display. .. admonition:: Tasks #. Implement the top-level module ``stopwatch_de10_lite`` in the file ``stopwatch_de10_lite.sv``. As in :numref:`ch:stopwatch_clock_signals` use minimal values for the parameter ``N`` in all instantiations of the counters ``counter_mod_k_count`` and ``counter_mod_k_ro``. #. Program the FPGA of a DE10-Lite board. Explain and illustrate your programmed FPGA to the teaching personnel. In your submission include a scan of this week's tailored coversheet which represents the deliverable of this subtask.