.. _ch:fpga:

Field Programmable Gate Arrays
==============================
It is time to get to the hardware part in Experimental *Hardware* Projects 📟.
Most hardware we use on day-to-day basis has a fixed design.
This means that the gates and their wiring are hardcoded.
In other words, the design and purpose of such a device stays the same throughout its operating life.
As an example, assume that you bought a processor.
This could be the Broadcom BCM2711 of the Raspberry Pi 4 Model B which we'll use as our development platform in :numref:`ch:aarch64`.
We can use this processor by running our software on it.
Software consist of instructions where the processor performs the corresponding actions.
However, we can not change the design of the processor itself.

In contrast, Field Programmable Gate Arrays (FGPAs) allow us reconfigure or "program" the logic chip itself.
This means that we can decide which logic gates to use and how those should be connected together:
The same manufactured FPGA could, e.g., one day power a highly tailored microprocessor design or operate as a graphics processing unit another day.
In fact, FPGAs are often used as a first platform for protoyping processor designs.
For example, the `RISC-V Exchange <https://riscv.org/exchange/>`_ platform provides designs for entire cores, some of which are available under open source licenses.

In this section we'll use the `DE10-Lite board <https://www.terasic.com.tw/cgi-bin/page/archive.pl?No=1021>`_ which is build around the `Altera MAX 10 FPGA <https://www.intel.com/content/www/us/en/products/details/fpga/max/10.html>`__.
Additional information outside of the class is available through the `FPGAcademy <https://fpgacademy.org/>`_.
We use the `Quartus Prime Lite Edition Design Software <https://www.intel.com/content/www/us/en/software-kit/684215/intel-quartus-prime-lite-edition-design-software-version-21-1-for-linux.html>`_ to program the board.

.. hint::

   Compile all your modules in Icarus Verilog with flags ``-Wall -Winfloop -g2012`` before even approaching the FPGAs.
   Additionally, write testbenches and run simulations before firing up Quartus Prime.

7-Segment Display Decoder
-------------------------
.. figure:: /chapters/data_fpga/decoder_0010.jpg
   :name: fig:decoder_0010
   :width: 100%

   Picture of the finished 7-segment display encoder where only switch button ``SW1`` is active.
   The decoder connects the buttons ``SW3``, ``SW2``, ``SW1`` and ``SW0`` with the display ``HEX0``.
   Thus, ``0010`` is the visualized binary number which corresponds to the shown hex number 2.

Let's start our FPGA journey by designing a decoder which connects some of the board's switch buttons to a hexadecimal display.
For this we'll use the first four switch buttons ``SW3``, ``SW2``, ``SW1`` and ``SW0``.
Each switch button can either be 0 (down) or 1 (up).
We may represent a hexadecimal number alternatively through exactly four binary digits.
Thus, in our design, the configuration of the four switch buttons will encode a single hexadecimal number.

Our hexadecimal displays consists of seven segments.
While the DE10-Lite board has six of these displays, we'll only use the right-most one, i.e., ``HEX0``, in this task.
The segments of the display are active low.
This means you have to set the value 1 for a specific segment to deactivate it.

.. figure:: /chapters/data_fpga/display.svg
   :name: fig:decoder
   :width: 100%

   Illustration of the hexadecimal digits 0-F when shown on a seven-segment display of the DE10-Lite board.
   The numbers give the ids of the segments which are active low.

:numref:`fig:decoder` illustrates all sixteen outputs our decoder might have.
For example, for the hex digit 0 all but segment 6 have to be active.
This means that we have to set all but the seventh bit of ``HEX0`` to 0, i.e., set ``HEX0[6:0]`` to ``7'b100_0000``.
If we'd like to encode the hex digit 1, we'd set all bits to 1 except the second and third bit, i.e., set ``HEX0[6:0]`` to ``7'b111_1001``.
The respective (incomplete) truth table for our decoder is given in :numref:`tab:decoder_truth_table`.

.. _tab:decoder_truth_table:

.. table:: Truth table of the decoder.

   +------------+-------------+-----------------+
   | Hex Number |    SW[3:0]  |       HEX0[6:0] |
   +============+=============+=================+
   |          0 | ``4'b0000`` | ``7'b100_0000`` |
   +------------+-------------+-----------------+
   |          1 | ``4'b0001`` | ``7'b111_1001`` |
   +------------+-------------+-----------------+
   |          2 | ``4'b0010`` | ``7'b010_0100`` |
   +------------+-------------+-----------------+
   |          3 | ``4'b0011`` | ``7'b011_0000`` |
   +------------+-------------+-----------------+
   |          4 | ``4'b0100`` | ``7'b???_????`` |
   +------------+-------------+-----------------+
   |          5 | ``4'b0101`` | ``7'b???_????`` |
   +------------+-------------+-----------------+
   |          6 | ``4'b0110`` | ``7'b???_????`` |
   +------------+-------------+-----------------+
   |          7 | ``4'b0111`` | ``7'b???_????`` |
   +------------+-------------+-----------------+
   |          8 | ``4'b1000`` | ``7'b???_????`` |
   +------------+-------------+-----------------+
   |          9 | ``4'b1001`` | ``7'b???_????`` |
   +------------+-------------+-----------------+
   |          A | ``4'b1010`` | ``7'b???_????`` |
   +------------+-------------+-----------------+
   |          B | ``4'b1011`` | ``7'b???_????`` |
   +------------+-------------+-----------------+
   |          C | ``4'b1100`` | ``7'b???_????`` |
   +------------+-------------+-----------------+
   |          D | ``4'b1101`` | ``7'b???_????`` |
   +------------+-------------+-----------------+
   |          E | ``4'b1110`` | ``7'b???_????`` |
   +------------+-------------+-----------------+
   |          F | ``4'b1111`` | ``7'b???_????`` |
   +------------+-------------+-----------------+

Once again, to kickstart your work, templates for your modules are provided.
The template for the ``decoder`` module is located in :numref:`lst:decoder`.
This template only provides the decoding cases for the two binary numbers :math:`0000_2` and :math:`0001_2`.
The remaining 14 numbers shown in :numref:`tab:decoder_truth_table` have to be added still.

.. literalinclude:: data_fpga/decoder.sv
    :linenos:
    :language: systemverilog
    :caption: Template for the module ``decoder``.
    :name: lst:decoder

:numref:`lst:decoder_de10_lite` provides a template for the top-level module.
The top-level module simply wraps our decoder.
Most importantly, we name ``decoder_de10_lite``'s input ``SW`` and the output ``HEX0``.
This naming scheme allows Quartus Prime to recognize that the ``SW`` should be the input of the first three switch buttons and ``HEX0`` the first hex display.

.. note::
   
   Additional signal names are available from the `DE10-Lite User Manual <https://fpgacademy.org/Downloads/DE10_Lite_User_Manual.pdf>`_.
   For example, the fifth LED has the name ``LEDR4``.
   We could also use Quartus Prime's pin assignment to assign the boards to our modules' inputs and outputs.
   However, using top-level modules with respective names is less cumbersome in the development phase.

.. literalinclude:: data_fpga/decoder_de10_lite.sv
    :linenos:
    :language: systemverilog
    :caption: Template for the module ``decoder_de10_lite``.
    :name: lst:decoder_de10_lite

.. admonition:: Tasks

   #. Add the missing encodings for the seven-segment display to :numref:`tab:decoder_truth_table`.
   #. Implement the module ``decoder``. Use the template in :numref:`lst:decoder`.
   #. Finish the implementation of the module ``decoder_de10_lite``.
      Use :numref:`lst:decoder_de10_lite`'s template.
   #. Compile your modules in Quartus Prime and program the FPGA of the DE10-Lite board.
   #. Make sure that the board shows the correct hexadecimal numbers in display ``HEX0`` for all combinations of the switch buttons ``SW0``, ``SW1``, ``SW2``, ``SW3``.
      Provide three pictures of the programmed FPGA for the hex numbers 7, A and E.
      One should see the hex display and the switch button configuration in your pictures.
      An example is given in :numref:`fig:decoder_0010`.

.. _ch:tiny_calculator:

Tiny Calculator
---------------
Now that we have a way to display four digit binary numbers, let's up the game a bit.
In this task we'll implement a tiny calculator which takes two four-bit binary numbers :math:`A_{[3:0]}` and :math:`B_{[3:0]}` as inputs.
We use the input from the first four switch buttons in ``SW[3:0]`` for :math:`A_{[3:0]}` and those of the next four in ``SW[7:4]`` for :math:`B_{[3:0]}`.
Our tiny calculator computes the 5-bit result :math:`C_{[4:0]} = A_{3:0} + B_{3:0}`.
We make the user aware of our inputs by displaying :math:`A_{[3:0]}` on display ``HEX0`` and :math:`B_{[3:0]}` on display ``HEX1``.
The result :math:`C_{[4:0]}` has a total of five bits due to the carry out.
Thus, we require two hex numbers for :math:`C_{[4:0]}`:
One for the four bits 3-0 which we display on ``HEX2`` and one for the fourth bit which we display on ``HEX3``.

.. figure:: /chapters/data_fpga/calculator.jpg
   :name: fig:calculator
   :width: 100%

   Picture of the tiny calculator in action.
   In the shown configuration only switch buttons ``SW0``, ``SW1`` and ``SW5`` are active.
   This means that :math:`A_{[3:0]} = 0011_2`, :math:`B_{[3:0]} = 0010_2` and :math:`C_{[4:0]} = 00101_2`.
   We see that the corresponding hexadecimal representations are shown on displays ``HEX0`` - ``HEX3``, i.e., :math:`0011_2 = 3_{16}` on ``HEX0``, :math:`0010_2 = 2_{16}` on ``HEX1`` and :math:`00101_2 = 05_{16}` on ``HEX2`` and ``HEX3``.

A picture of an exemplary setting is provided in :numref:`fig:calculator`.
In the shown case ``SW[3:0] = 4'b0011`` and ``SW[7:4] = 4'b0010``.
The corresponding hexadecimal numbers :math:`3_{16}` and :math:`2_{16}` are shown on ``HEX0`` and ``HEX1``.
Additionally, displays ``HEX2`` and ``HEX3`` show the result :math:`05_{16}`.


.. _tab:tiny_calculator_tb_inputs:

.. table:: Inputs and (incomplete) outputs required for testing your ``tiny_calculator`` module.

   +----------+----------+--------------+--------------+--------------+--------------+
   | SW[3:0]  |  SW[7:4] |    HEX0[6:0] |    HEX1[6:0] |    HEX2[6:0] |    HEX3[6:0] |
   +==========+==========+==============+==============+==============+==============+
   | ``0000`` | ``0000`` | ``100_0000`` | ``100_0000`` | ``100_0000`` | ``100_0000`` |
   +----------+----------+--------------+--------------+--------------+--------------+
   | ``0011`` | ``0010`` | ``???_????`` | ``???_????`` | ``???_????`` | ``???_????`` |
   +----------+----------+--------------+--------------+--------------+--------------+
   | ``0111`` | ``0001`` | ``???_????`` | ``???_????`` | ``???_????`` | ``???_????`` |
   +----------+----------+--------------+--------------+--------------+--------------+
   | ``1000`` | ``1000`` | ``???_????`` | ``???_????`` | ``???_????`` | ``???_????`` |
   +----------+----------+--------------+--------------+--------------+--------------+
   | ``1111`` | ``1111`` | ``???_????`` | ``???_????`` | ``???_????`` | ``???_????`` |
   +----------+----------+--------------+--------------+--------------+--------------+

.. literalinclude:: data_fpga/tiny_calculator.sv
    :linenos:
    :language: systemverilog
    :caption: Template for the module ``tiny_calculator``.
    :name: lst:tiny_calculator

.. admonition:: Tasks

   #. Implement the module ``tiny_calculator``.
      Use the template in :numref:`lst:tiny_calculator` as a basis for your module.
      Use your four-bit ripple carry adder of :numref:`ch:four_bit_ripple_carry_adder` for the addition.

   #. Add the testbench ``tiny_calculator_tb`` for your ``tiny_calculator`` module.
      Check that your calculator produces the correct outputs, i.e., the bits ``HEX0[6:0]``, ``HEX1[6:0]``, ``HEX2[6:0]``, ``HEX3[6:0]`` for all inputs in :numref:`tab:tiny_calculator_tb_inputs`.

   #. Compile your module in Quartus Prime and program the FPGA of the DE10-Lite board.

   #. Make sure that the board's displays show the correct hexadecimal numbers for the configurations in :numref:`tab:tiny_calculator_tb_inputs`.
      Provide a picture for each of the five configurations.