In one of my research projects, I need to develop some signal processing logic that runs on the FPGA of the USRP, to meeting some delay and timing requirements. Here is a general overview of the steps to customize the DSP Rx chain of USRP N2x0 devices. Details of my particular customization will be probably discussed in separate posts.
DSP Rx Chain Overview
The spirit of Software Defined Radios is to push as much as of the signal processing to the host PC, enabling easy development and fast prototyping and easy. However, there are certain tasks that are just too timing/performance sensitive to be put on the host PC. Therefore, USRPs has a FPGA on board to perform several pre-processing of the signal samples before they are sent to the host PC.
The above diagram shows the pipeline of the DSP receive chain on the FPGA. The RF signal are sampled and converted by the ADC module, and the raw samples are processed by the Rx Frontend module for scaling and converting the samples to the familiar I/Q values.
Next, the I/Q values (frontend_i, frontend_q) are sent to a dummpy custom module. By default, this Custom module just pipe the I/Q samples directly to the Digital Down Converter (DDC) module to extract the baseband signal.
Then the baseband signals (ddc_out_sample) are passed into the Custom module again, which in turn pass them directly to the VITA49 core, which will frame these samples and send them to host PC.
As we can clear see, the USRP FPGA framework already provides us a nice custom valve where we can perform custom processing either before or after the DDC stage.
Enable Custom Build
By default, the Custom module is disabled. To enable it, we need to make the following changes. Here we use the N200R4 as an example. The steps are the same for other N2x0 devices.
First, clone the USRP FPGA source (if you haven't done so).
$ git clone git@github.com:EttusResearch/fpga.git $ cd fpga/usrp2/top/N2x0/
Next, make a copy the original Makefile.
$ cp Makefile.N200R4 Makefile.N200R4.custom
Then make these changes to Makefile.N200R4.custom.
# use a differnet build directory - BUILD_DIR = $(abspath build$(ISE)-N200R4) + BUILD_DIR = $(abspath build$(ISE)-N200R4-custom) # remove these two lines, as we will set them later - CUSTOM_SRCS = - CUSTOM_DEFS = # include a custom src list file that we will create later, this file sets # the CUSTOM_SRCS variable + include ../../custom/Makefile.srcs # Enable the custom module using verilog macro -"Verilog Macros" "LVDS=1|RX_DSP0_MODULE=custom_dsp_rx" +"Verilog Macros" "LVDS=1|RX_DSP0_MODULE=custom_dsp_rx|RX_DSP1_MODULE=custom_dsp_rx"
Then in fpga/custom/ directory, create a file named Makefile.srcs.
CUSTOM_SRCS = $(abspath $(addprefix $(BASE_DIR)/../custom/, \ custom_dsp_rx.v\ ))
As you continue the development, you'll probably create more Verilog modules. Just add their file names here.
Checkpoint
Now the build system will include the custom_dsp_rx.v file. Before you do any changes to that file, I suggest you compile the whole project for sanity check.
$ cd fpga/top/N2x0/ $ make -f Makefile.N200R4.custom clean bin $ uhd_image_loader --args="type=usrp2" --fpga-path build-custom/u2plus.bin --fw-path path/to/your/firmware
This should succeed and the functionality of the FPAG image should be exactly the same as before since the default Custom module only passes through signals.
Note: to flash the FPGA image, you'll also need a compatible firmware image. So I recommend you to clone the uhd and fpga repos and build them together.