/*! \page page_usrp_e320 USRP E320

\tableofcontents

\section e320_feature_list Comparative features list

The E320 is a 2-channel transmitter/receiver based on the AD9361 transceiver IC.
It is a monolithic board with one AD9361 and provides two RF channels.

- TX band: 47 MHz to 6.0 GHz
- RX band: 70 MHz to 6.0 GHz
- 56 MHz of instantaneous bandwidth
- 2 RX DDC chains in FPGA
- 2 TX DUC chain in FPGA

- Hardware Capabilities:
	- Single SFP+ Transceivers (can be used with 1 GigE, 10 GigE, and Aurora)
	- External PPS input
	- External 10 MHz input
	- Internal GPSDO for timing, location, and 10 MHz reference clock + PPS
	- External GPIO Connector with UHD API control
	- External USB Connection for built-in JTAG debugger and serial console
        - Xilinx Zynq SoC with dual-core ARM Cortex A9 (Speedgrade 3) and
          Kintex-7 FPGA (XC7Z045)

- Software Capabilities:
    - Full Linux system running on the ARM core
    - Runs MPM (see also \ref page_mpm)

- FPGA Capabilities:
    - RFNoC capability

\section e320_overview Overview

\subsection e320_zynq The Zynq CPU/FPGA and host operating system

The main CPU of the E320 is a Xilinx Zynq SoC XC7Z045. It
is both a dual-core ARM Cortex A9 CPU and Kintex-7 FPGA on a single die. The
CPU is clocked at 1GHz (speedgrade 3).

The programmable logic (PL, or FPGA) section of the SoC is responsible for
handling all sampling data, the 1/10 GigE network connections, and any other
high-speed utility such as custom RFNoC logic. The processing system (PS, or CPU)
is running a custom-build OpenEmbedded-based Linux operating system. The OS is
responsible for all the device and peripheral management, such as running MPM
(see section \ref page_mpm), configuring the network interfaces, running local
UHD sessions, etc.

It is possible to connect to the host OS either via SSH or serial console (see
sections \ref e320_getting_started_ssh and \ref e320_getting_started_serial,
respectively).

\subsection e320_micro The STM32 microcontroller

The STM32 microcontroller controls various low-level features of the E320 series
motherboard: It controls the power sequencing, reads out fan speeds and some of
the temperature sensors. It is connected to the Zynq via an I2C bus.

It is possible to log into the STM32 using the serial interface
(see \ref e320_getting_started_serial_micro). This will allow certain low-level
controls, such as remote power cycling should the CPU have become unresponsive
for whatever reason.

\subsection e320_sdcard The SD card

The E320 uses a micro SD card as its main storage. The entire root file
system (Linux kernel, libraries) and any user data are stored on this SD card.

The SD card is partitioned into four partitions:

1. Boot partition (contains the bootloader). This partition usually does not
   require any modifications.
2. A data partition, mounted in /data. This is the only partition that is not
   erased during file system updates.
2. Two identical system partitions (root file systems). These contain the
   operating system and the home directory (anything mounted under / that is not
   the data or boot partition). The reason there are two of these is to enable
   remote updates: An update running on one partition can update the other one
   without any effect to the currently running system. Note that the system
   partitions are erased during updates and are thus unsuitable for permanently
   storing information.

Note: It is possible to access the currently inactive root file system by
mounting it. After logging into the device using serial console or SSH (see the
following two sections), run the following commands:

    $ mkdir temp
    $ mount /dev/mmcblk0p3 temp
    $ ls temp # You are now accessing the idle partition:
    bin   data  etc   lib         media  proc  sbin  tmp    usr
    boot  dev   home  lost+found  mnt    run   sys   uboot  var

The device node in the mount command will likely differ, depending on which
partition is currently already mounted.

\section e320_getting_started Getting started

This will run you through the first steps relevant to getting your USRP E320
up and running.
Note: This guide was creating on an Ubuntu machine, and other distributions
or OS's may have different names/methods.

\subsection e320_getting_started_assembling Assembling the E320

Unlike the X300 or N200 series, there is no assembly of required since it is
a monolithic board.

Checklist:
- Connect power and network
- Read security settings
- Connect clocking (if required)

\subsection e320_getting_started_fs_update Updating the file system

Before doing any major work with a newly acquired USRP E320, it is
recommended to update the file system. For the OEM/Board-only version of
E320, the SD card is physically accessible and filesystem update can be
accomplished directly by using Mender or externally by manually writing
an image onto a micro SD card and inserting it. For the
enclosure version of E320, Mender update is required as there is no direct
physical access to the device.  For details on using Mender,
see Section \ref e320_rasm_mender .

Manual updating is simply loading an image on the micro SD card.  The first step
in that process is to obtain an image.

To obtain the default micro SD card image for a specific version of UHD, install
that version of UHD (3.13.0.2 or later) on a host system with Internet access and run:

    $ uhd_images_downloader -t e320 -t sdimg

   The image will be downloaded to
   `<UHD_INSTALL_DIR>/share/uhd/images/usrp_e320_fs.sdimg`,
   where `<UHD_INSTALL_DIR>` is the UHD installation directory.

To load an image onto the micro SD card, connect the card to the host and run:

    $ sudo dd if=<YOUR_IMAGE> of=/dev/<YOUR_SD_CARD> bs=1M

   The `<YOUR_IMAGE>` is the path to the micro SD card image
   (i.e.`<UHD_INSTALL_DIR>/share/uhd/images/usrp_e320_fs.sdimg`).

   The `<YOUR_SD_CARD>` device node depends on your operating system and which
   other devices are plugged in. Typical values are `sdb` or `mmcblk0`.<br>

   CAUTION: The Linux utility `dd` or `bmap` can cause unrecoverable data loss
   if the incorrect disk is selected, or if the parameters are input incorrectly.
   Ensure you have selected the correct input and output parameters for your
   system configuration.

The micro SD card used can be the original SD card shipped with the device or
another one that is at least 16 GB in size.

\subsection e320_getting_started_serial Serial connection

It is possible to gain root access to the device using a serial terminal
emulator. Most Linux, OSX, or other Unix flavours have a tool called 'screen'
which can be used for this purpose, by running the following command:

    $ sudo screen /dev/ttyUSB2 115200

In this command, we prepend 'sudo' to elevate user privileges (by default,
accessing serial ports is not available to regular users), we specify the
device node (in this case, `/dev/ttyUSB2`), and the baud rate (115200).

The exact device node depends on your operating system's driver and other USB
devices that might be already connected. Modern Linux systems offer alternatives
to simply trying device nodes; instead, the OS might have a directory of
symlinks under `/dev/serial/by-id`:

    $ ls /dev/serial/by-id
    /dev/serial/by-id/usb-FTDI_Dual_RS232-HS-if00-port0
    /dev/serial/by-id/usb-FTDI_Dual_RS232-HS-if01-port0
    /dev/serial/by-id/usb-Silicon_Labs_CP2105_Dual_USB_to_UART_Bridge_Controller_007F6A6C-if00-port0
    /dev/serial/by-id/usb-Silicon_Labs_CP2105_Dual_USB_to_UART_Bridge_Controller_007F6A6C-if01-port0

Note: Exact names depend on the host operating system version and may differ.

Every E320 device connected to USB will by default show up as four
different devices. The devices labeled "USB_to_UART_Bridge_Controller" are the
devices that offer a serial prompt. The one with the `if01` suffix connects
to Linux, whereas the one with `if00` suffix connects to the STM32 microcontroller.
If you have multiple E320 devices connected, you may have to try out multiple
devices. In this case, to use this symlink instead of the raw device node
address, modify the command above to:

    $ sudo screen /dev/usb-Silicon_Labs_CP2105_Dual_USB_to_UART_Bridge_Controller_007F6A6C-if01-port0 115200

You should be presented with a shell prompt similar to the following:

    root@ni-e320-311FE00:~#

On this prompt, you can enter any Linux command available. Using the default
configuration, the serial console will also show all kernel log messages (unlike
when using SSH, for example), and give access to the boot loader (U-boot
prompt). This can be used to debug kernel or bootloader issues more efficiently
than when logged in via SSH.

\subsubsection e320_getting_started_serial_micro Connecting to the microcontroller

The STM32 microcontroller (which controls the power sequencing, among other
things) also has a serial console available. To connect to the microcontroller,
use the other UART device. In the example above:

    $ sudo screen /dev/usb-Silicon_Labs_CP2105_Dual_USB_to_UART_Bridge_Controller_007F6CB5-if00-port0 115200

It provides a very simple prompt. The command 'help' will list all available
commands. A direct connection to the microcontroller can be used to hard-reset
the device without physically accessing it (i.e., emulating a power button press)
and other low-level diagnostics.

\subsection e320_getting_started_ssh SSH connection

The USRP E320 devices have two network connections: One SFP port,
and an RJ-45 connector. The latter is by default configured by DHCP; by plugging
it into into 1 Gigabit switch on a DHCP-capable network, it will get assigned
an IP address and thus be accessible via ssh.

In case your network setup does not include a DHCP server, refer to the section
\ref e320_getting_started_serial. A serial login can be used to assign an IP address manually.

After the device obtained an IP address you can log in from a Linux or OSX
machine by typing:

    $ ssh root@ni-e320-311FE00 # Replace with your actual device name!

Depending on your network setup, using a `.local` domain may work:

    $ ssh root@ni-e320-311FE00.local

Of course, you can also connect to the IP address directly if you know it (or
set it manually using the serial console).

Note: The device's hostname is derived from its serial number by default
(`ni-e320-<SERIAL>`). You can change the hostname by modifying the `/etc/hostname`
file and rebooting.

On Microsoft Windows, the connection can be established using a tool such as
Putty, by selecting a username of root without password.

Like with the serial console, you should be presented with a prompt like the
following:

    root@ni-e320-311FE00:~#

\subsection e320_getting_started_connectivity Network Connectivity

The RJ45 port (eth0) comes up with a default configuration of DHCP,
that will request a network address from your DHCP server (if available on your
network).

The SFP+ (sfp0) port is configured with static address 192.168.10.2/24

The configuration for the sfp0 port is stored in /etc/systemd/networkd/sfp0.network.

For configuration please refer to the
<a href=https://www.freedesktop.org/software/systemd/man/systemd.network.html>systemd-networkd manual pages</a>

The factory settings are as follows:

    eth0 (DHCP):

        [Match]
        Name=eth0

        [Network]
        DHCP=v4

        [DHCPv4]
        UseHostname=false

    sfp0 (static):

        [Match]
        Name=sfp0

        [Network]
        Address=192.168.10.2/24

        [Link]
        MTUBytes=8000

Note: Care needs to be taken when editing these files on the device, since
vi / vim sometimes generates undo files (e.g. /etc/systemd/networkd/sfp0.network~),
that systemd-networkd might accidentally pick up.

Note: Temporarily setting the IP addresses via ifconfig etc will only change the
value until the next reboot or reload of the FPGA image.

\subsection e320_getting_started_security Security-related settings

The E320 ships without a root password set. It is possible to ssh into the
device by simply connecting as root, and thus gaining access to all subsystems.
To set a password, run the command

    $ passwd

on the device.

\subsection e320_getting_started_fpga_update Updating the FPGA

Updating the FPGA follows the same procedure as other USRPs. Use the `uhd_image_loader`
command line utility to upload a new FPGA image onto the device. The command can be run
on the host to load the image via RJ-45 network connection or it can be run on the
device.

A common reason to update the FPGA image is in the case of a UHD/FPGA compat
number mismatch (for example, if UHD has been updated, and now expects a newer
version of the FPGA than is on the device). In this case, simply run

    $ uhd_images_downloader

to update the local cache of FPGA images. Then, run

    $ uhd_image_loader --args type=e3xx,addr=ni-e320-311fe00

to update the FPGA using the default settings. Replace ni-e320-311fe00 in the addr with the
correct device address. If a custom FPGA image is targeted for uploading, use the
`--fpga-path` command line argument. Run

    $ uhd_image_loader --help

to see a full list of command line options. Note that updating the FPGA image
will force a reload of the FPGA, which will temporarily take down the SFP
network interfaces (and temporary settings, such as applied via `ifconfig` on
the command line, will be lost).


\section e320_usage Using an E320 USRP from UHD

Like any other USRP, all E320 USRPs are controlled by the UHD software. To
integrate a USRP E320 into your C++ application, you would generate a UHD
device in the same way you would for any other USRP:

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
auto usrp = uhd::usrp::multi_usrp::make("type=e3xx");
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

For a list of which arguments can be passed into make(), see Section
\ref e320_usage_device_args.

\subsection e320_usage_device_args Device arguments

 Key                 | Description                                                                   | Example Value
---------------------|-------------------------------------------------------------------------------|---------------------
 addr                | IPv4 address of primary SFP+ port to connect to.                              | addr=192.168.30.2
 find_all            | When using broadcast, find all devices, even if unreachable via CHDR.         | find_all=1
 master_clock_rate   | Master Clock Rate in Hz. Default is 16 MHz.                                   | master_clock_rate=30.72e6
 serialize_init      | Force serial initialization of daughterboards.                                | serialize_init=1
 skip_dram           | Ignore DRAM FIFO block. Connect TX streamers straight into DUC or radio.      | skip_dram=1
 skip_ddc            | Ignore DDC block. Connect Rx streamers straight into radio.                   | skip_ddc=1
 skip_duc            | Ignore DUC block. Connect Tx streamers or DRAM straight into radio.           | skip_duc=1
 skip_init           | Skip the initialization process for the device.                               | skip_init=1
 ref_clk_freq        | Specify the external reference clock frequency, default is internal (20 MHz). | ref_clk_freq=10e6
 init_cals           | Specify the bitmask for initial calibrations of the RFIC.                     | init_cals=BASIC
 init_cals_timeout   | Timeout for initial calibrations in milliseconds.                             | init_cals_timeout=45000
 discovery_port      | Override default value for MPM discovery port.                                | discovery_port=49700
 rpc_port            | Override default value for MPM RPC port.                                      | rpc_port=49701
 tracking_cals       | Specify the bitmask for tracking calibrations of the RFIC.                    | tracking_cals=ALL

\subsection e320_usage_sensors The sensor API

Like other USRPs, the E320 series has RF and motherboard sensors.
When using uhd::usrp::multi_usrp, the following API calls are relevant to
interact with the sensor API:

- uhd::usrp::multi_usrp::get_mboard_sensor_names()
- uhd::usrp::multi_usrp::get_mboard_sensor()
- uhd::usrp::multi_usrp::get_tx_sensor_names()
- uhd::usrp::multi_usrp::get_rx_sensor_names()
- uhd::usrp::multi_usrp::get_tx_sensor()
- uhd::usrp::multi_usrp::get_rx_sensor()

The following motherboard sensors are always available:
- `temp_internal`: temperature (in C) of Temperature Sensor on board
- `temp_fpga`: temperature (in C) of the FPGA die
- `temp_rf_channelA`: temperature (in C) near power amplifier RF A
- `temp_rf_channelB`: temperature (in C) near power amplifier RF B
- `temp_main_power`: temperature (in C) near power supply
- `gps_locked`: GPS lock
- `gps_time`: GPS time in seconds sin ce the epch
- `gps_tpv`: A TPV report from GPSd serialized as JSON
- `gps_sky`: A SKY report from GPSd serialized as JSON
- `ref_locked`: This will check that all the daughterboards have locked to the
external/internal reference clock.
- `fan`: get fan speed (in rpm)

\section e320_rasm Remote Management

\subsection e320_rasm_mender Mender: Remote update capability

Mender is a third-party software that enables remote updating of the root
file system without physically accessing the device (see also the
[Mender website](https://mender.io)). Mender can be executed locally on the
device, or a Mender server can be set up which can be used to remotely update
an arbitrary number of USRP devices. Mender servers can be self-hosted, or
hosted by Mender (see [mender.io](https://mender.io) for pricing and
availability).

When updating the file system using Mender, the tool will overwrite the root file
system partition that is not currently mounted (note: every SD card comes with
two separate root file system partitions, only one is ever used at a single
time). Any data stored on that partition will be permanently lost. After
updating that partition, it will reboot into the newly updated partition. Only
if the update is confirmed by the user, the update will be made permanent. This
means that if an update fails, the device will be always able to reboot into the
partition from which the update was originally launched (which presumably is in
a working state). Another update can be launched now to correct the previous,
failed update, until it works.
See also Section \ref e320_sdcard.

To initiate an update from the device itself, download a Mender artifact
containing the update itself. These are files with a `.mender` suffix.

Then run mender on the command line:

    $ mender -rootfs /path/to/latest.mender

The artifact can also be stored on a remote server:

    $ mender -rootfs http://server.name/path/to/latest.mender

This procedure will take a while. After mender has logged a successful update,
reboot the device:

    $ reboot

If the reboot worked, and the device seems functional, commit the changes so
the boot loader knows to permanently boot into this partition:

    $ mender -commit

To identify the currently installed Mender artifact from the command line, the
following file can be queried:

    $ cat /etc/mender/artifact_info

If you are running a hosted server, the updates can be initiated from a web
dashboard. From there, you can start the updates without having to log into the
device, and can update groups of USRPs with a few clicks in a web GUI. The
dashboard can also be used to inspect the state of USRPs. This is simple way to
update groups of rack-mounted USRPs with custom file systems.

\subsection e320_rasm_salt Salt: Remote configuration management and execution

Salt (also known as SaltStack, see [Salt Website](https://saltstack.com)) is a
Python-based tool for maintaining fleets of remote devices. It can be used to
manage USRP E320 remotely for all types of settings that are not
controlled by UHD. For example, if an operator would like to reset the root
password on multiple devices, or install custom software, this tool might be a
suitable choice.

Salt is a third-party project with its [own documentation](https://docs.saltstack.com/en/latest/),
which should be consulted for configuring it. However, the Salt minion is
installed by default on every E320 device. To start it, simply log on to the
device and run:

    $ systemctl start salt-minion

To permanently enable it at every boot, run (this won't by itself launch the
salt-minion):

    $ systemctl enable salt-minion

To make use of Salt, both the device needs to be configured (the "minion") and,
typically, a server to act as the Salt master. Refer to the Salt documentation
on how to configure the minion and the master. A typical sequence to get started
will look like this:

1. Install the salt-master package on the server (e.g. by running `apt install salt-master`
   if the server is an Ubuntu system), and make sure the Salt master is running.
2. Add the network address / hostname of that server to the `/etc/salt/minion`
   file on the device by editing the `master:` line.
3. Launch the Salt minion on the USRP by running the command `systemctl start salt-minion`.
4. The minion will try to connect to the master. You need to authorize the
   minion by running `salt-key -a $hostname` where `$hostname` is the name of
   the minion.
5. Once the device is authorized, you can try various commands to see if the
   communication was established:

    $ [sudo] salt '*' test.ping
    ni-n3xx-$serial:
        True
    $ [sudo] salt '*' network.interfaces
    ni-n3xx-$serial:
        ----------
        eth0:
            ----------
            hwaddr:
                02:00:03:11:fe:00
            inet:
                |_
                  ----------
                  address:
                      xx.xx.xx.xx
                  broadcast:
                      xx.xx.xx.xx
                  label:
                      eth0
                  netmask:
                      255.255.254.0
            up:
                True
    # [...]

\section e320_theory_of_ops Theory of Operation

E320 is on the MPM architecture (see also: \ref page_mpm).
Inside the Linux operating system running on the ARM
cores, there is hardware daemon which needs to be active in order for the
device to function as a USRP (it is enabled to run by default).

A large portion of hardware-specific setup is handled by the daemon.

\section e320_software_dev Modifying and compiling UHD and MPM for the E320

E320 devices ship with all relevant software installed on the SD card. Updating
UHD and/or MPM on the SD card is typically easiest done by updating the
filesystem image (see Section \ref e320_rasm_mender). However, it is certainly
possible to compile UHD and MPM by hand, e.g., in order to modify and try out
changes without having to build entire filesystems in between. At Ettus R&D,
this mode of operation is often used for rapid iteration cycles.

\subsection e320_software_dev_mpm_native Compiling MPM natively

In general, compiling natively is not a recommended way of compiling code for
the ARM processors. However, in the case of MPM, the amount of C++ code that
needs to be compiled is very little, and a full compile of MPM will take a few
minutes even on the device. First, you need to get a copy of the MPM source code
onto your device. If you have an internet connection, you can use git to pull
it directly from the Ettus repository (all commands are run on the device
itself, inside the home directory):

    $ git clone https://github.com/EttusResearch/uhd.git

You can also SSHFS it from another computer:

    $ mkdir uhd # Create a new, empty directory called uhd
    $ sshfs user@yourcomputer:src/uhd uhd # This will mount ~/src/uhd from the remote machine to ~/uhd on the device

Now, create a build directory and use the regular cmake/make procedure to kick
off a build. It can be advantageous (especially for slow network connections)
to create the build directory outside of the repository directory:

    $ mkdir build_mpm
    $ cd build_mpm # You are now in /home/root/build_mpm
    $ cmake -DMPM_DEVICE=e320 ../uhd/mpm
    $ make -j2 install # This will take several minutes

Note that this overwrites your system MPM. You can install MPM to another
location by specifying `-DCMAKE_INSTALL_PREFIX`, but make sure to update all of
your paths appropriately.

If you prefer cross-compiling MPM the same way as UHD, refer to the following
sections and adapt the instructions for UHD appropriately.

\subsection e320_software_dev_sdk Obtaining an SDK

The recommended way to develop software for the E320 is to cross-compile. By
running the compiles on a desktop or laptop computer, you will be able to speed
up compile times considerably (compiling UHD natively for the E320 would take
many hours).

SDKs are distributed along with other binaries. They contain a cross-compiler,
a cross-linker, a cross-debugger, and all the libraries available on the device
to mirror its environment.

To unpack the SDK, simply execute it after downloading it:

    $ ./oecore-x86_64-cortexa9hf-neon-toolchain-nodistro.0.sh

This will prompt you for an installation path.  Please ensure you have
sufficient disk space, as each of the SDKs may require several gigabytes of
disk space (depends on the image flavor selected).

This will allow you to compile UHD as well as (depending on the image flavor)
other software.

Please note, that while several toolchains can be installed in parallel, they
have to be installed to different directories.

\subsection e320_software_dev_sdkusage SDK Usage

Having installed the toolchain in the last step,
in order to build software for your device open a new shell and type:

    $ . $SDKPATH/environment-setup-armv7ahf-vfp-neon-oe-linux-gnueabi

This will modify the PATH, CC, CXX etc, environment variables and allow you to compile software for your USRP E320 device.
To verify all went well you can try:

    $ $CC -dumpmachine

which should return 'arm-oe-linux-gnueabi'.

\subsubsection e320_software_dev_uhd  Building UHD

-# Obtain the UHD source code via git or tarball
-# Set up your environment as described in \ref e320_software_dev_sdkusage
-# Type the following in the build directory (assuming a build in host/build):

        $ cmake -DCMAKE_TOOLCHAIN_FILE=../host/cmake/Toolchains/oe-sdk_cross.cmake -DCMAKE_INSTALL_PREFIX=/usr .. # Add any CMake options you desire
        $ make # You can run make -j12 to compile on 12 processes at once

Note: The UHD you are cross-compiling will not run on your host computer (the
one where you're doing the development). Compiling UHD regularly on your host
computer (with MPMD enabled) will allow you to talk to your E320.

\subsubsection e320_software_dev_gr Building GNU Radio

-# Obtain the GNU Radio source code via git or tarball
-# Set up your environment as described in \ref e320_software_dev_sdkusage
-# Use the following commands to create a build directory, configure and compile gnuradio. You only need create the build directory once.

\code{.sh}
$ mkdir build-arm
$ cd build-arm
$ cmake -Wno-dev -DCMAKE_TOOLCHAIN_FILE=../cmake/Toolchains/oe-sdk_cross.cmake \-DCMAKE_INSTALL_PREFIX=/usr -DENABLE_GR_VOCODER=OFF -DENABLE_GR_ATSC=OFF \
-DENABLE_GR_DTV=OFF -DENABLE_DOXYGEN=OFF ../ # Append any CMake options you desire
\endcode

Several GNU Radio components depend on running binaries built for the build
machine during compile. These binaries can be built and used for cross
compiling, but this is an advanced topic.

\section e320_neon E320-specific Features

\subsection e320_panels Front and Rear Panel

Like the USRP X300 and N310 series, E320 has connectors on both the front and back
panel. The back panel holds the power connector, all network connections, USB
connections for serial console (see \ref e320_getting_started_serial), JTAG and
peripherals, and front-panel GPIO.

The front panel is used for all RF connections, SMA connectors for GPS antenna
input, 10 MHz external clock reference.

The connectors are labeled RF A and RF B and are powered by the two channels of
AD9361 RFIC.

\subsection e320_regmap FPGA Register Map

The following tables describe how FPGA registers are mapped into the PS.
This is for reference only, most users will not even have to know about this table.


AXI Slave | Address Range         | UIO Label        | Description
----------|-----------------------|------------------|-----------------------------------
Slave 0   | 4000_0000 - 4000_3fff | -                | Ethernet DMA SFP
Slave 1   | 4000_4000 - 4000_4fff | misc-enet-regs   | Ethernet registers SFP
Slave 2   | 4001_0000 - 4001_3fff | mboard-regs      | Motherboard control
Slave 3   | 4001_4000 - 4001_41ff | dboard-regs      | Daughterboard control


<table>
<caption id="e320_multi_row">E320 Register Map</caption>
<tr><th>AXI Slave              <th>Module                       <th>Address               <th>Name            <th>Read/Write  <th>Description
<tr><td rowspan="1">Slave 0    <td rowspan="1">axi_eth_dma      <td>4000_0000 - 4000_4fff <td>Ethernet DMA    <td>RW          <td>See Linux Driver
<tr><td rowspan="44">Slave 1   <td rowspan="7">e320_mgt_io_core <td>4000_4000             <td>PORT_INFO       <td>RO          <td>SFP port information
<tr>                                                            <td>[31:24]               <td>COMPAT_NUM      <td>RO          <td>-
<tr>                                                            <td>[23:18]               <td>6'h0	      <td>RO          <td>-
<tr>                                                            <td>[17]                  <td>activity	      <td>RO          <td>-
<tr>                                                            <td>[16]                  <td>link_up	      <td>RO          <td>-
<tr>                                                            <td>[15:8]                <td>mgt_protocol    <td>RO          <td>0 - None, 1 - 1G, 2 - XG, 3 - Aurora
<tr>                                                            <td>[7:0]                 <td>PORTNUM         <td>RO          <td>-
<tr>                           <td rowspan="8">e320_mgt_io_core <td>4000_4004             <td>MAC_CTRL_STATUS <td>RW          <td>Control 10gE and Aurora mac
<tr>                                                            <td>[0]                   <td>ctrl_tx_enable (PROTOCOL = "10GbE")<td>RW<td>-
<tr>                                                            <td>[0]                   <td>bist_checker_en (PROTOCOL = "Aurora")<td>RW<td>-
<tr>                                                            <td>[1]                   <td>bist_gen_en    <td>RW           <td>-
<tr>                                                            <td>[2]                   <td>bist_loopback_en<td>RW          <td>-
<tr>                                                            <td>[8:3]                 <td>bist_gen_rate   <td>RW          <td>-
<tr>                                                            <td>[9]                   <td>phy_areset      <td>RW          <td>-
<tr>                                                            <td>[10]                  <td>mac_clear       <td>RW          <td>-
<tr>                           <td>e320_mgt_io_core             <td>4000_4008             <td>PHY_CTRL_STATUS <td>RW          <td>Phy reset control
<tr>                           <td rowspan="3">e320_mgt_io_core <td>4000_400C             <td>MAC_LED_CTL     <td>RW          <td>Used by ethtool to indicate port
<tr>                                                            <td>[1]                   <td>identify_enable <td>RW          <td>-
<tr>                                                            <td>[0]                   <td>identify_value  <td>RW          <td>-
<tr>                           <td rowspan="4">mdio_master      <td>4000_4010             <td>MDIO_DATA       <td>RW          <td>-
<tr>                                                            <td>4000_4014             <td>MDIO_ADDR       <td>RW          <td>-
<tr>                                                            <td>4000_4018             <td>MDIO_OP         <td>RW          <td>-
<tr>                                                            <td>4000_401C             <td>MDIO_CTRL_STATUS<td>RW          <td>-
<tr>                           <td rowspan="4">e320_mgt_io_core <td>4000_4020             <td>AURORA_OVERUNS  <td>RO          <td>-
<tr>                                                            <td>4000_4024             <td>AURORA_CHECKSUM_ERRORS<td>RO    <td>-
<tr>                                                            <td>4000_4028             <td>AURORA_BIST_CHECKER_SAMPS<td>RO <td>-
<tr>                                                            <td>4000_402C             <td>AURORA_BIST_CHECKER_ERRORS<td>RO<td>-
<tr>                           <td rowspan="4">eth_switch       <td>4000_5000             <td>MAC_LSB         <td>RW          <td>Device MAC LSB
<tr>                                                            <td>4000_5004             <td>MAC_MSB         <td>RW          <td>Device MAC MSB
<tr>                                                            <td>4000_6000             <td>IP              <td>RW          <td>Device IP
<tr>                                                            <td>4000_6004             <td>PORT1, PORT0    <td>RW          <td>Device UDP port
<tr>                           <td rowspan="2">eth_dispatch     <td>4000_6008             <td>[1] ndest, [0] bcast<td>RW      <td>Enable Crossover
<tr>                                                            <td>4000_600c             <td>[1] my_icmp_type, [0] my_icmp_code<td>-
<tr>                           <td rowspan="5">eth_switch       <td>4000_6010             <td>BRIDGE_MAC_LSB  <td>            <td>Bridge SFP ports in ARM
<tr>                                                            <td>4000_6014             <td>BRIDGE_MAC_MSB  <td>            <td>-
<tr>                                                            <td>4000_6018             <td>BRIDGE_IP       <td>            <td>-
<tr>                                                            <td>4000_601c             <td>BRIDGE_PORT1, BRIDGE_PORT0<td>  <td>-
<tr>                                                            <td>4000_6020             <td>BRIDGE_EN       <td>            <td>-
<tr>                           <td rowspan="6">chdr_eth_framer  <td>4000_6108 onwards     <td>LOCAL_DST_IP    <td>W           <td>Destination IP, MAC, UDP for Outgoing Packet for 256 SIDs
<tr>                                                            <td>4000_6208 onwards     <td>LOCAL_DST_UDP_MAC_MSB<td>W      <td>Destination MAC for outgoing packets (MSB)
<tr>                                                            <td>4000_6308 onwards     <td>LOCAL_DST_MAC_LSB<td>W          <td>Destination MAC for outgoing packets (LSB)
<tr>                                                            <td>4000_7000 onwards     <td>REMOTE_DST_IP   <td>W           <td>Destination IP, MAC, UDP for Outgoing Packet for 16 local addrs
<tr>                                                            <td>4000_7400 onwards     <td>REMOTE_DST_UDP_MAC_HI<td>W      <td>Destination MAC (MSB)
<tr>                                                            <td>4000_7800 onwards     <td>REMOTE_DST_MAC_LO<td>W          <td>Destination MAC (LSB)

<tr><td rowspan="32">Slave 2   <td rowspan="27">e320_core       <td>4001_0000             <td>COMPAT_NUM      <td>R           <td>FPGA Compat Number
<tr>                                                            <td>[31:16]               <td>Major           <td>RO          <td>-
<tr>                                                            <td>[15:0]                <td>Minor           <td>RO          <td>-
<tr>                                                            <td>4001_0004             <td>DATESTAMP       <td>RO          <td>-
<tr>                                                            <td>4001_0008             <td>GIT_HASH        <td>RO          <td>-
<tr>                                                            <td>4001_000C             <td>SCRATCH         <td>RO          <td>-
<tr>                                                            <td>4001_0010             <td>NUM_CE          <td>RO          <td>Number of Computation Engines (RFNoC Blocks)
<tr>                                                            <td>4001_0014             <td>NUM_IO_CE       <td>RO          <td>Number of fixed IO CEs - Radios + DMA Fifo
<tr>                                                            <td>4001_0018             <td>CLOCK_CTRL      <td>            <td>-
<tr>                                                            <td>[0]                   <td>pps select (internal 10 MHz)<td>RW<td>One-hot encoded pps_select to use the internal PPS from GPSDO
<tr>                                                            <td>[1]                   <td>pps select (external 10 MHz)<td>RW<td>One-hot encoded pps_select to use the external PPS.
<tr>                                                            <td>[2]                   <td>refclk_select (internal/external 10 MHz)<td>RW<td>refclk_select=0 for internal (GPSDO) 10 MHz, refclk_sel=1 for external 10 MHz.
<tr>                                                            <td>4001_001C             <td>XADC_READBACK   <td>RO          <td>-
<tr>                                                            <td>[11:0]                <td>FPGA temperature<td>RO          <td>-
<tr>                                                            <td>4001_0020             <td>BUS_CLK_RATE    <td>RO          <td>-
<tr>                                                            <td>4001_0024             <td>BUS_CLK_COUNT   <td>RO          <td>-
<tr>                                                            <td>4001_0028             <td>SFP_PORT_INFO   <td>RO          <td>Same as port_info register 0x4000_4000
<tr>                                                            <td>4001_002C             <td>FP_GPIO_CTRL    <td>RW          <td>-
<tr>                                                            <td>4001_0030             <td>FP_GPIO_MASTER  <td>RW          <td>-
<tr>                                                            <td>4001_0034             <td>FP_GPIO_RADIO_SRC  <td>RW       <td>-
<tr>                                                            <td>4001_0038             <td>GPS_CTRL        <td>RW          <td>-
<tr>                                                            <td>[0]                   <td>GPS_PWR_EN      <td>RW          <td>Power on GPSDO
<tr>                                                            <td>[1]                   <td>GPS_RST_N       <td>RW          <td>-
<tr>                                                            <td>[2]                   <td>GPS_INITSURV_N  <td>RW          <td>-
<tr>                                                            <td>4001_003C             <td>GPS_STATUS      <td>RO          <td>GPSDO Status
<tr>                                                            <td>[0]                   <td>GPS_LOCK        <td>RO          <td>Returns 1 if GPSDO is locked
<tr>                                                            <td>[1]                   <td>GPS_ALARM       <td>RO          <td>-
<tr>                                                            <td>[2]                   <td>GPS_PHASELOCK   <td>RO          <td>-
<tr>                                                            <td>[3]                   <td>GPS_SURVEY      <td>RO          <td>-
<tr>                                                            <td>[4]                   <td>GPS_WARMUP      <td>RO          <td>-
<tr>                                                            <td>4001_0040             <td>DBOARD_CTRL     <td>RO          <td>-
<tr>                                                            <td>4001_0044             <td>DBOARD_STATUS   <td>RO          <td>-

<tr>                           <td rowspan="5">axi_crossbar     <td>4001_1010             <td>XBAR_VERSION    <td>RO          <td>See crossbar kernel driver
<tr>                                                            <td>4001_1014             <td>XBAR_NUM_PORTS  <td>RO          <td>See crossbar kernel driver
<tr>                                                            <td>4001_1018             <td>LOCAL_ADDR      <td>RW          <td>See crossbar kernel driver
<tr>                                                            <td>4001_1020             <td>remote_offset   <td>WO          <td>XBAR settings reg
<tr>                                                            <td>4001_1420             <td>local_offset    <td>WO          <td>XBAR settings reg

<tr><td rowspan="6">Slave 4                                     <td>4001_4000<td>4001_41FF<td>Daughterboard Registers<td>- <td>Don't exist now. TBD


*/
// vim:ft=doxygen:
