In many cases, the UHD software suite includes parts of software or FPGA which need to work together over, e.g., a network connection or other type of link. To make sure that interfaces are matching, we use compatibility numbers (compat numbers) to indicate versions of various subsystems. This way, checks can be performed a-priori to verify if two separate pieces of software can communicate without error.
There are many subsystems within UHD, including the FPGA codebase, MPM, and various modules within the UHD library itself.
Example: When a USRP X310 is being used with UHD, several compat number checks are being performed under the hood. First, the FPGA has a compat version which is compared with the one that UHD expects. Similarly, the ZPU firmware code also has such a compat number. If any of those numbers mismatch, UHD will refuse to communicate with the X310, and initializing a session is impossible. Only updating the FPGA will fix this issue. If both compat numbers match, then the RFNoC subsystem is accessed. It, also, has a general compat number, and can have another compat number for each RFNoC block. If any of those fail, usage of the X310 is typically also not possible. In that case, the common remedy is to update the FPGA on the device to match the one that UHD expects. Typically, this requires running uhd_images_downloader
to obtain the correct set of images, and then running uhd_image_loader
to copy the FPGA image onto the device. After rebooting the device, all compat numbers will match up and UHD will be able to communicate with the device.
In many cases, the compat number consists of a major part and a minor part. The difference between those numbers is that a major compat number mismatch will always lead to a failure, whereas as minor compat number mismatches only lead to failure when there is potential for UHD to rely on features that aren't yet supported by the device.
Examples:
Compat numbers are typically represented as a tuple $MAJOR.$MINOR
, e.g., 30.1.
The B200-series USRPs have two compat number: One for the FPGA, and one for the FX3 firmware. If UHD fails to communicate with a B200 device because of compat number errors, it is typically sufficient to run uhd_images_downloader
to download the images matching the UHD version. Since neither image is stored on the device persistently, it is not necessary to manually flash the images onto the device.
Like the B200 series, these devices have firmware and FPGA compat numbers. However, the firmware is executed on a softcore within the FPGA, and is thus baked into the FPGA image itself. If there are FPGA/firmware compat errors, the typical remedy is thus to run:
uhd_images_downloader # This will get the correct images uhd_image_loader --args type=x300,addr=192.168.10.1 # This will flash the image
Note to change IP address (or resource) and type of the device accordingly.
The X300, as a generation-3 devices, also runs RFNoC blocks which have their own compat numbers (see RFNoC Components).
See also The Module Peripheral Manager (MPM) Architecture.
All MPM devices have a three-way dependency:
Note that UHD does not directly communicate with the FPGA, unless it's with RFNoC blocks. There is thus no shared compat number between the FPGA and UHD, but RFNoC components will share their own compat numbers (see RFNoC Components).
A guaranteed way to match all compat numbers between an external host, the FPGA and MPM is to run (assuming an N300-series device, replace n3xx with a string that corresponds to your device, or leave it out to download all SD card images):
uhd_images_downloader -t sdimg -t n3xx # This will download a filesystem image
And then to install the new filesystem image onto the device (See the individual device manuals for details, or The Module Peripheral Manager (MPM) Architecture). Since the UHD session will load the filesystem, the compatibility between UHD and MPM is now given. The FPGA images and MPM are both stored on the same filesystem, so these are now also in sync.
Note: MPM has a get_mpm_compat_num()
RPC call, which UHD uses to query its current compat number.
The most common mismatch is that between an RFNoC block on the FPGA, and its UHD block controller. There are two levels of compat numbers:
noc_shell
has its own compat number, which is shared between all blocks and devices (i.e., for any given version of UHD, all RFNoC blocks, regardless on which device, will have the same noc_shell
compat number).For users running default images, the solution to resolving a compat number error is to simply download a matching FPGA image and flash it onto the device, typically by running
uhd_images_downloader uhd_image_loader --args type=$TYPE,addr=$ADDR
For users running their own custom FPGA images, the sequence is a bit more elaborate:
The newly built FPGA image will then work with your version of UHD.
Theoretically, it could be possible that UHD detects the FPGA compat number, and then runs different code based on which version of the FPGA image it detects. However, this is typically not done, for the following reasons:
The software architecture of UHD and RFNoC are such that there is a lot of code that is shared between devices. For example, many RFNoC blocks can easily be ported between devices without any changes to the code. This means that a single compat number per device wouldn't be sufficient.
To keep things compartmentalized, and to avoid the meaning of compat numbers to bleed outside of their modules, there is one compat number for every pair of modules that do not run within the same process, for example:
...and so on. In most cases, updating the FPGA image is the solution to resolving compat number errors.