Running the AD9361 at 122.88 Msps

The Analog Devices AD9361 is an RFIC that is used in several popular SDRs, such as the USRP B2xx series and E3xx series, the BladeRF 2.0 micro, the ADALM Pluto, the ANTSDR, and in many other products (some of these use the AD9363 or the AD9364, which are similar chips in the same family). This RFIC has a nominal maximum sample rate of 61.44 Msps, and an analog bandwidth of 56 MHz.

A few days ago, Nuand has published a new software version that allows running the BladeRF 2.0 at 122.88 Msps. This has attracted some interest in Twitter, specially regarding questions about how they manage to achieve this and how good the performance is. One of the changes that Nuand has done to support the 122.88 Msps mode is an 8-bit wire protocol for the USB 3.0 interface. This is required to be able to pass 122.88 Msps through the USB. This change affects the FPGA gateware and host drivers. The other change involves manually setting some registers of the AD9361 in the host drivers in order to bypass a half-band filter, effectively doubling the output sample rate. In this post I will give a short review of the AD9361 register settings that enable the 122.88 Msps mode.

Before beginning, a word of caution: Analog Devices has a document which specifies the maximum rates along the data path of the AD9361. This includes the image shown below. The maximum output sample rate is 61.44 Msps. They state “please do not exceed below specified rates for the blocks shown”. In principle, running the device above these limits could not only cause a degradation in signal quality, but potentially permanent damage. On the other hand, Nuand mentions: “As is typical with overclocks, please bear in mind system stability may be affected. In our testing, we found the system to be quite stable.”

Maximum AD9361 RX data path rates (source)

So, kids, don’t try this at home. If you test any of this, you’re doing so under your own responsibility.

In the 2023.02 bladeRF release, the code to set the AD9361 registers can be found in the bladerf_set_rational_sample_rate() function. The way this works is that first the AD9361 is configured for half of the desired frequency (for instance, for 61.44 Msps if we want to achieve 122.88 Msps). This is done using the regular code in the ADI no-OS AD9361 drivers, which among other things determines and sets the required configuration for the decimation stages in the RX chain. Afterwards, a few registers are set to some hardcoded values.

The code that sets the registers is listed below. I have commented it heavily, parsing out the values of each of the register fields and copying the relevant descriptions from the AD9364 register map reference. My comments are written with 3 slashes (///) so that they can be distinguished from the original comments in the bladeRF code.

Even though a couple dozen of registers are set, it is easy to summarize what they do. First, on the RX data path, RHB3 is set to decimate by 2, RHB2 is bypassed, RHB1 is set to decimate by 2 and RFIR is bypassed. This is what causes the sample rate to be twice its usual value. Normally, RHB2 would also be set to decimate by 2 in order to achieve the required RX data rate.

On the TX data path, all the interpolators are bypassed. I don’t understand how this is supposed to work. Usually, the DAC runs at the same frequency as the ADC or at half the frequency of the ADC (the maximum frequency supported by the DAC is lower than the maximum frequency supported by the ADC). In the RX data path the total decimation is 4. If we use no interpolation on the TX path, we would get a too high rate. Note that people have been testing mostly the 122.88 Msps RX, so maybe the TX doesn’t work as intended.

The next registers set a bunch of resistors and capacitors to manual control and set all the resistors to the highest value and the capacitors to the lowest value. I guess that the intention of this is to try to get around the usual limitation of 56 MHz bandwidth in the lowpass filter before the ADC. This seems a rather brute force approach. I wonder if better results could be obtained by tweaking the values.

Finally, the most mysterious part is that the 2 LSBs of the “BIST and Data Port Test Config” register are set to 0b11. According to the register map reference, these must be set to 0b00. I don’t know what is going on here, besides the fact that an undocumented feature is being used. Maybe this is necessary to make the digital interface go above 61.44 Msps.

I’ve done some very simple tests with one of the ADALM Plutos that I’m using to develop Maia SDR. When the Pluto is set up for 61.44 Msps rate, these are the data rates in the RX and TX paths:

# cat rx_path_rates 
BBPLL:983040000 ADC:491520000 R2:245760000 R1:122880000 RF:61440000 RXSAMP:61440000
# cat tx_path_rates 
BBPLL:983040000 DAC:245760000 T2:122880000 T1:61440000 TF:61440000 TXSAMP:61440000

The decimation/interpolation settings are governed by the registers 0x003 and 0x002, whose values are:

# iio_reg ad9361-phy 0x003
# iio_reg ad9361-phy 0x002

/// - Rx Enable = 1
/// - RHB3 Enable and Decimation[1:0] = 1
/// - RHB2 Enable = 1
/// - RHB3 Enable = 1
/// - Rx FIR Enable and Decimation[1:0] = 0

/// - Tx Enable = 1
/// - THB3 Enable and Interpolation[1:0] = 1
/// - THB2 Enable = 1
/// - THB3 Enable = 0
/// - Tx FIR Enable and Interpolation[1:0] = 0

The remaining registers which are modified by the bladeRF 122.88 Msps mode have the following values:

# iio_reg ad9361-phy 0x0c2
# iio_reg ad9361-phy 0x0c3
# iio_reg ad9361-phy 0x0c4
# iio_reg ad9361-phy 0x0c5
# iio_reg ad9361-phy 0x0c6
# iio_reg ad9361-phy 0x0c7
# iio_reg ad9361-phy 0x0c8
# iio_reg ad9361-phy 0x0c9
# iio_reg ad9361-phy 0x1e0
# iio_reg ad9361-phy 0x1e4
# iio_reg ad9361-phy 0x1f2
# iio_reg ad9361-phy 0x1e6
# iio_reg ad9361-phy 0x1e7
# iio_reg ad9361-phy 0x1e8
# iio_reg ad9361-phy 0x1e9
# iio_reg ad9361-phy 0x1ea
# iio_reg ad9361-phy 0x1eb
# iio_reg ad9361-phy 0x1ec
# iio_reg ad9361-phy 0x1ed
# iio_reg ad9361-phy 0x1ee
# iio_reg ad9361-phy 0x1ef
# iio_reg ad9361-phy 0x3f6

Note however that many of these register values do not cause any effect because the BBF override bits are de-asserted. I have checked that setting register 0x1e0 to 0x83 instead of 0x03 in order to enable the RX BBF override causes an increase of approximately 4 dB in the signal level, but the passband shape doesn’t change. Therefore, the “manual” values of these override registers are not exactly the same ones that are being applied normally.

Setting the register 0x003 to 0x54 instead of 0x5c in order to bypass RHB2 seems to work, in the sense that the RX data path rates are computed accordingly.

# cat rx_path_rates
BBPLL:983040000 ADC:491520000 R2:245760000 R1:245760000 RF:122880000 RXSAMP:122880000

When this change is applied, there is definitely a change in the signals in the spectrum shown by Maia SDR. However, it is difficult to tell what is happening, since the Maia SDR FPGA design isn’t prepared to process IQ data at 122.88 Msps. The data path runs on a 62.5 MHz clock, so if the AD9361 supplies samples at 122.88 Msps, the FPGA will drop many samples. Changing from 31 Msps to 62 Msps by bypassing RHB2 appears to work correctly in Maia SDR.

There have been several examples of people on Twitter showing good results running the bladeRF above 61.44 Msps. However, no one has done yet some measurements of the RF performance, including bandpass response, out-of-band rejection, distortion (EVM, for instance) etc. It would be quite interesting to see a study of these parameters.


  1. I don’t understand how the AD9361 provide a bandwidth of 56MHz with 61.44MSPS. Doesn’t this cause aliasing according to Nyquist–Shannon sampling theorem?

    1. It is IQ (complex) sampling, so the Nyquist theorem says that the maximum representable bandwidth is equal to the sample rate (not half the sample rate as in real sampling).

Leave a comment

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.