Targeting HDL Optimized QPSK Receiver Using Analog Devices AD9361/AD9364
This example shows how to model an HDL-optimized QPSK receiver and prototype it on the FPGA of an SDR platform using the HDL Coder™ workflow advisor. The SDR device in this model is designed to receive indexed 'Hello world' messages and print them to the command window. For a full description of targeting, see Targeting Overview in the documentation.
Refer to the Installation for Hardware-Software Co-Design documentation for details on configuring your host computer to work with the Support Package for Zynq-Based Radio.
- Communications System Toolbox
- HDL Coder
- Communications System Toolbox Support Package for Zynq-Based Radio
The commqpskrxhdl model walks through building a practical HDL-optimized digital receiver, which includes coarse frequency compensation, PLL-based fine frequency compensation, timing recovery, frame synchronization, phase ambiguity resolution, and QPSK demodulation. This example takes the next steps to generate HDL code from this HDL-optimized receiver, and prototype it on the FPGA of the SDR hardware. This includes the generation of an HDL IP core to be implemented on the Zynq programmable logic (PL), which is achieved through the use of the HDL workflow advisor.
Targeting typically involves a pair of models:
- The targeting model, used to generate the HDL code and integrate the user logic into the receive path implemented on the FPGA of the SDR hardware
- The retargeted model, which uses the SDR hardware with the included user logic performing a portion of the baseband processing
Note that there are two methods of running this example, based on the targeting/retargeted pair of models:
Before running the example, ensure you have performed the following steps:
1. Configure your host computer to work with the Support Package for Zynq-Based Radio. See Installation for Hardware-Software Co-Design for help.
- Some additional steps may be required if you want to run two radios from a single host computer. See Setup for Two Radios - One Host for help.
2. Ensure that you have a suitable transmitter. This example is designed to work in conjunction with any of the following possible transmitters:
- The QPSK Transmit Repeat Using Analog Devices AD9361/AD9364 MATLAB® example
- The QPSK Transmitter Using Analog Devices™ AD9361/AD9364 Simulink® example
- The QPSK Transmitter Using Analog Devices AD9361/AD9364 MATLAB example
- The Targeting HDL-Optimized QPSK Transmitter Using Analog Devices AD9361/AD9364 Simulink example
Running the Example: Simulated
To run the example directly, open zynqRadioQPSKRxFPGAAD9361AD9364SL and start the simulation. Note that this simulates the entire baseband design in a similar way to the QPSK Receiver Using Analog Devices AD9361/AD9364 Simulink example i.e. no HDL code is generated, and all of the baseband processing is done in Simulink.
The main benefit of running the example in this way is that you can verify the conversion of your design to fixed point HDL works with real world data. The main disadvantage is that the HDL optimized sections of the model will run significantly slower than their floating point, frame based equivalents. This example uses burst mode to ensure large enough blocks of data are received consecutively to verify the receiver functionality.
Running the Example: Targeted
The zynqRadioQPSKRxFPGAAD9361AD9364SL model can be used to generate a targeted bitstream for the SDR hardware that includes the HDLRx subsystem as a DUT. The DUT is automatically placed in the SDR receiver chain that is implemented on the FPGA.
To generate the new bitstream, perform the following steps:
- Make sure you have added Vivado to the system path. See related workflow setup.
- Right click on the HDLRx subsystem, select Block Parameters (Subsystem), and ensure that the treat as atomic unit checkbox is selected.
- Open the HDL workflow advisor by right-clicking on the HDLRx subsystem and selecting HDL Code -> HDL Workflow Advisor.
- In step 1.1, at Target workflow, select IP Core Generation. At Target platform, select the appropriate option for your radio hardware (e.g. 'ZC706 and FMCOMMS2/3/4', 'Zedboard and FMCOMMS2/3/4' or 'ADI RF SOM'). The Synthesis tool field should automatically set to Xilinx Vivado if you added Vivado to the path. Click Apply, then click Run This Task.
- In step 1.2, ensure that Reference Design is set to Receive path. Set the synthesis frequency to a lower rate (1MHz would be appropriate). Click Apply, then click Run This Task.
- In step 1.3, ensure Processor/FPGA synchronization is set to Free running, and that each port is mapped to the appropriate interface as shown in the figure below.
- The default values for step 2 and step 3 can be used.
- Run the Workflow Advisor to step 4.1. A quick way to run all the preceding steps is to right click on 4.1 Create Project in the workflow window and click Run to selected task.
- In step 4.2, ensure that the Skip This Task checkbox is selected, and then click Run This Task.
- In step 4.3, ensure that the Run build process externally checkbox is selected, then click Run This Task.
If no errors are found, the FPGA programming file generation process starts in an external command shell. You can monitor the implementation progress in the external shell. A message indicating successful completion of file generation is displayed in the shell upon completion.
At this point there are two methods of downloading the generated bitstream to the board. The first method (which requires the Embedded Coder product) is to return to the HDL Workflow Advisor, select Download from the drop-down menu in step 4.4, and click Run This Task. When using this method, note that the bitstream is not persistent across power cycles.
If you want the generated FPGA image to load each time you turn on the board, call the downloadImage method as shown below (assuming the default 'hdl_prj' folder was used in step 1.1). This method does not require Embedded Coder.
>> dev = sdrdev('ADI RF SOM'); >> downloadImage(dev, 'FPGAImage','hdl_prj\vivado_ip_prj\vivado_prj.runs\impl_1\system_wrapper.bit');
The FPGA implementation of the QPSK receiver can be verified using the companion retargeted model zynqRadioQPSKRxFPGAAD9361AD9364RetargetSL, whose receiver structure is shown in the figure below.
This model can be built from the original zynqRadioQPSKRxFPGAAD9361AD9364SL model by making the following modifications:
- Removing the Data Type Conversion block, the Serializer and Deserializer blocks, the HDLRx subsystem and the Complex/Real-Imag conversion blocks. The functionality of these blocks is now implemented on the FPGA.
- Deselecting the Bypass user logic option in the Advanced tab of the Zynq SDR Receiver block.
With the targeted bitstream loaded, simulating the zynqRadioQPSKRxFPGAAD9361AD9364RetargetSL model should produce the expected 'Hello world' messages in the MATLAB command window.
Receiver Design: System Architecture
The structure of the QPSK receiver in zynqRadioQPSKRxFPGAAD9361AD9364SL is shown in the figure below.
The HDL-optimized part of the QPSK receiver is modeled under the subsystem HDLRx, whose contents are shown below. This is the user logic that will be implemented in the receive path on the FPGA fabric.
The IP core generation requires that the input and output interfaces of the HDL subsystem have two 16-bit data signals and a valid signal. These interface signals should be at the highest sample rate of the subsystem.
As the QPSK HDL subsystem performs a downsample by two, the valid and data signals have to be upsampled before being output from the subsystem to ensure the sample rate is equal at the input and output. By modifying the valid signal, every second sample is discarded at the hardware level.
When doing an FPGA only targeting flow, it is important to note that a large amount of internal downsampling may result in timeout issues when communicating with the SDR blocks on the host. The QPSK HDL subsystem attempts to decode symbols and send them back to the host. To ensure the host only attempts to process valid QPSK data, a valid bit is packed into the data stream by the FPGA to host block which packs bit1, bit2, and dValid in the I and Q data outputs. We have deliberately avoided using the dValid directly as the HDL subsystem valid out signal (RxValid_Out). This is because in the absence of valid QPSK data being received, the HDL subsystem would not send any data to the host incurring a timeout when using the SDR receiver block.
Implementation of algorithms with advanced valid modelling may require use of the full HW/SW workflow, where a software model can be configured to receive data at rates lower than the baseband sample rate.
Corresponding to the presence of the FPGA to Host subsystem in HDLRx, the Unpack FPGA Outputs subsystem extracts the three Boolean signals (bit1, bit2, and dValid) from the 16-bit signed complex values. The extracted Boolean signals are then fed to the dataframer subsystem.
List of Example Helper Files
This example uses the following helper files:
- zynqRadioQPSKRxFPGAAD9361AD9364SL_init.m: initialize variables used for running the model.