In this series:

OFDM reference design: Moving into cognitive mode – Part 1

In part 1 of this blog series, we listed the registers that can be used to change the LMS6002D PLL’s transmit and receive frequency to 433 MHz. The Nutaq software includes functions that configure the registers automatically.

The following Command Line Interpreter (CLI) function configures the LMS6002D PLL frequency:


PLL frequency configuration can also be performed with the following C code functions:

fmc_radio_lime_calculate(); then fmc_radio_lime_setpllparam_send();

These functions, however, require an external computer to be connected to the PicoSDR via an Ethernet or PCIe connection. So, for a cognitive application based on energy detection, feedback from the mean noise power calculator would need to be sent to the external computer if a switch in frequency is required, which adds latency to the algorithm. In many cognitive radio applications, latency must be managed carefully as the radio needs to be opportunistic. So, depending on the number of frequencies that need to be scanned and the silence period of the primary users (PUs), latency can be crucial to the correct operation of your cognitive radio.

Configuring the PLLs directly from the FPGA is the most efficient way to minimize latency. This can be easily done by using Nutaq’s Model-based Design Kit (MBDK). The following blocks can be used to send SPI commands to the LMS6002D chips:

An interesting fact: In MIMO mode where you have two FGPA mezzanine card (FMC) radios (or two LMS6002D chips) to configure, you can control both in parallel at the same time, thanks to the parallel architecture.
The blocks have four ports (2 inputs, 2 outputs):

lime_data: The 16-bit SPI data to send to the LMS6002D chip
lime_data_start: The lime_data valid signal.  A “1” means that lime_data will be sent to the LMS6002D chip.
fpga_ext_control: The output port indicating if control from the FPGA is enabled. A “1” indicates that the FMC radio is controlled by the FPGA.
lime_data_busy: The output port indicating if the LMS6002D is busy processing an SPI command. A “1” indicates that the chip is busy.

Let’s take a look at how to send an SPI command to the chip. From the LMS6002D Programming and Calibration Guide, page 2:

Basically, this figure tells us that lime_data, a 16-bit sample, is the concatenation of 1:

[address]:[value]. The ‘1’ bit on the front tells the chip that it’s an SPI write operation. Recalling the registers and values that need to be configured, let’s see the actual 16-bit samples that need to be sent to the LMS6002D chips:

Register Name

Register Address (TX, RX)

Register value (TX, RX)

lime_data(TX, RX)


0x15, 0x25

0xFD, 0xFD

0x95FD, 0xA5FD


0x10, 0x20

0x70, 0x70

0x9070, 0xA070

NINT[0] & NFRAC[22:16]

0x11, 0x21

0xC2, 0xC2

0x91C2, 0xA1C2


0x12, 0x22

0xAA, 0xAA

0x92AA, 0xA2AA


0x13, 0x23

0xAA, 0xAA

0x93AA, 0xA3AA

XX & VCOCAP[5:0]

0x19, 0x29

0xA4, 0xA4

0x99A4, 0xA9A4

Now, for the FPGA algorithm, let’s take a look at the mean noise power calculator:

This is roughly the same algorithm used for the mean received power calculator in the AGC algorithm. This time, however, once we have finished decoding a packet (when Pkt_Done is true), we store the current value of the mean received power calculator for threshold comparison (since the packet was received and detected some hundreds of clock cycles before, the mean received power calculator is receiving only noise until the next packet arrival).

Using this stored value, let’s take a look at the algorithm that verifies if the noise is higher than the fixed threshold and reconfigures the RX and TX frequency as required.

noise_ave_pow is compared to Cognitive_thresh (which can be any value fixed by the user via a custom register). If noise_ave_pow is higher than the user fixed threshold, Counter is flipped from “0” to “1” or “1” to “0”, and Mux changes its input vector accordingly. ROM_453_mhz and ROM_433_mhz are ROMs that have the 12 lime_data values required for configuring the RX and TX frequencies in the LMS6002D chips (see the above table for the ROM_433_mhz values). Once a packet is done decoding, we reconfigure the RX and TX frequencies at either 453 MHz or 433 MHz for the next packet to come, depending on the noise_ave_pow value. The first value of the selected ROM is sent and, on the falling edge of the lime_data_busy signal, we increment the read address of the selected ROM and send the next value. This process is repeated 12 times. It may seem like a lot of SPI write operations but in the end, the complete process only takes about 40 µs to execute, which is must faster than reconfiguring the radios dynamically from an external computer.

In this blog series, we presented a simple cognitive algorithm based on energy detection. It should be clear by now how to use Nutaq’s MBDK to reconfigure the Radio420X’s LMS6002D chips directly from the FPGA. This algorithm is the one used in the cognitive OFDM video. As a side note, by using multiple ROMs, it would be very simple to extrapolate this example for use in a frequency hopping application as well.


An OFDM reference design built to support cognitive radio