In this blog post, I show how to generate your own bitstream for measuring the latency of the radio card used in the ZeptoSDR and PicoSDR platforms. This is accomplished by using the platforms' record and playback capabilities. The basic concept is simple: Following the reception of a trigger signal, the FPGA activates the transmission of a tone to the digital-analog converter (DAC) of the radio card and, in parallel, the tone is recorded into memory. The tone is moved to a specific RF frequency and is looped to the radio card's receive (RX) antenna port. The RX chain of the radio card moves the tone back to baseband and generates discrete samples, which are sent to the FPGA. In the FPGA, the received samples are jointly recorded into memory with the sent tone. Once a useful amount of data is recorded, the user downloads the memory’s content and plots the recorded signals in MATLAB to evaluate the latency.

To generate the bitstream, we use Nutaq’s Model-Based Design Kit (MBDK). Here's a screen capture of the actual model used for the FPGA bitstream generation:

This model is basically the Radio420X Record & Playback using Gigabit Ethernet demo that is provided with the MBDK software. First, the yellow part is used for tone generation. The I and Q interleaved tone is sent to a multiplexer (MUX) before going to the radio card. The MUX outputs a null signal if the trigger signal is low. When the signal goes to high (the status is changed remotely from a custom register), the tone is sent to the radio card and the pink box for deinterleaving. The output samples are then recorded by the red box on the bottom right. In parallel, the red box also records the digitized samples of the analog-digital converter (ADC) of the same radio card. As a side note, some clock cycles delay are put in front of the red box inputs simply to help distinguish the start of the recording when plotting the data.

This is it for the FPGA-side of things. It’s important to understand that this model is used to simulate and generate the necessary logic to achieve our goal (the bitstream). Once we have that bitstream, the FPGA is configured but we still need to perform the following tasks:

1. Configure the radio card's gains and local oscillators
2. Generate the necessary trigger to start the recording process
3. Configure the DDR3 memory in record mode
4. Extract the recorded samples from the DDR3 memory for MATLAB analysis
5. Perform the MATLAB analysis

So there are still many steps to perform outside of the FPGA, on the host side. However, they are easily done with Nutaq's command-line interface (CLI) tools. Here's the necessary script to accomplish steps 1 to 4: 

Once this is done, the last step is to read the file correctly. For this purpose, Nutaq provides a MATLAB script for reading the recorded binary file. The script is called fpgaacqgetframes (you can type help fpgaacqgetframes at the MATLAB command prompt to learn more about this script).

Here's an example of how to use the script to plot the necessary data:

data = fpgaacqgetframes('radio420m_record_data.bin', 4, 'int16', 20480);
plot(data(1:end,1));
hold on
plot(data(1:end,3),'r');

Using the script in MATLAB, the data variable will contain 4 columns (we recorded 4 signals, two I and Q pairs) with the recorded data. Using the plot command in MATLAB, we get the following graph:

This is the real part of the sent tone (in blue) and the real part of the received tone (in red). If we zoom to the start of the recording, we see an actual lag between the signals, which can be evaluated here in a number of samples:

We can clearly see the exact moment where we raised the trigger signal (raising edge on the blue curve) and the moment we start to receive back the sent samples. One could zoom in further to evaluate the number of samples – it's around 23-24 clock samples. Since the ADCs and the DACs are running at 40.96 MHz (81920000 / 2 set by the fmcradio_pll CLI command), we can calculated that the round trip delay is around 561 to 585 ns.