.. _hdl:


Firmware
============
SPEC7 Golden Architecture

This design  was build to provide PCIe enumeration within 100ms


.. image:: media/spec7_golden.png



SPEC7 Reference design with XDMA for Remote Upgrade

This design was built on SPEC7 Reference Design with addititonal BAR 4 for PCIe to upload new firmware to PS-DDR via 
AXI DMA and PCIe core with addon Virtual UART provided through AXI Uartlite Core to direct PS to load firmware in
PL



.. image:: media/spec7_ref_dma.png



---------------------------------------------------------
To add two Tandem and Reference design in one BOOT.bin
-------------------------------------------------------

1. Script Build.sh  in ``sw/scripts/boot`` intiates build for FSBL and Uboot
   It also creates ``spec7.bif`` file which consists of path for all output obtained i.e bitstream, elf files located in ``output`` directory

.. code-block:: 
   
   ./Build.sh  --t <specify Tandem Design>  --r <reference design> --o <offset>

2. The above step will create BOOT.bin in output directory which can be flashed directly to  flash memory

.. code-block::

   program_flash -f BOOT.bin -fsbl </path/to/fsbl>/zynq_fsbl.elf  -flash_type qspi-x8-dual_parallel  -blank_check -url tcp:localhost:3121

3. To automate loading of second design, it's possible in two ways

Create environment variable in U-boot in Runtime 
++++++++++++++++++++++++++++++++++++++++++++++++++++
.. code-block::
    
   SPEC7> sf probe 0 0 0
   SPEC7> sf erase 0x2000000 0x1000000

   SPEC7> sf write ${loadbit_addr} 0x2000000 ${filesize}

   SPEC7> fpga loadb 0 ${loadbit_addr} ${filesize}
  

The above commands are for test, where 0x2000000 specifies the offset defined in BOOT.bin



Automatic gateware update from QSPI
++++++++++++++++++++++++++++++++++++

In order to allow for automatic loading of the gateware from QSPI using the UBoot, first we define the following environment variables:

.. code-block::

   SPEC7> setenv bootdelay "0"
   SPEC7> setenv gateware_size 0x1000000
   SPEC7> setenv qspi_gateware_offset 0x2000000


The meaning for each of these variables are:
- ``bootdelay``: this contains the maximum value of the countdown that UBoot perform before executing the `bootcmd`. By setting it to zero, we save a precious time at startup.
- ``gateware_size``: we define this auxiliary variable that specify the size of the slot containing the gateware that we want to move from QSPI to DDR. We set the value to 16 MiB, i.e. the full size of the slot.
- ``qspi_gateware_offset``: we define this auxiliary variable containing the QSPI offset of the slot containing the gateware we want to load. In this case, we are pointing to the Slot 2, but we can easily modify the slot to be used by editing this variable.

Now, we create the boot command to read the gateware from the desired QSPI slot to DDR, then from DDR to FPGA, and finally go back to the U-boot prompt:

.. code-block::

   SPEC7> editenv bootcmd_gateware
   edit: sf probe 0 0 0 && sf read ${loadbit_addr} ${qspi_gateware_offset} ${gateware_size} && fpga loadb 0 ${loadbit_addr} 0x1

**Note**: because we are using bitstream in `bit` format, the `fpga loadb` command doesn't require the exact size of the bitstream, just a non zero value, as the size is already encoded in the bitstream header.

In order to boot execute this command at start-up, we must assign the `bootcmd` variable and save the environment:

.. code-block::

   SPEC7> setenv bootcmd "run bootcmd_gateware"
   SPEC7> saveenv


Adding the above environment during building U-boot using ``make menuconfig`` or adding in ``config``

.. code-block::

        #define CONFIG_EXTRA_ENV_SETTINGS \
              "bootdelay = 0"\
              "gateware_size =0x1000000" \
              "qspi_gateware_offse= 0x2000000" \
              " bootcmd_gateware = sf probe 0 0 0 && sf read ${loadbit_addr} ${qspi_gateware_offset} ${gateware_size} && fpga loadb 0 ${loadbit_addr} 0x1" \
              "bootcmd = run bootcmd_gateware"
 




