QPSK Receiver with SDR Hardware

This example shows how to use SDR hardware with MATLAB® and SDR System objects to implement a QPSK receiver. The receiver addresses practical issues in wireless communications, such as carrier frequency and phase offset, timing offset and frame synchronization. This system receives the signal sent by the QPSK Transmitter with SDR Hardware example. The receiver demodulates the received symbols and prints a simple message to the MATLAB® command line.

Refer to documentation for details on configuring your host computer to work with the SDR Receiver System object.


This example describes the MATLAB implementation of a QPSK receiver with SDR Hardware. There is another implementation of this example that uses Simulink®.


This example has the following motivation:

  • To implement a real QPSK-based transmission-reception environment in MATLAB using SDR System objects.

  • To illustrate the use of key Communications System Toolbox™ System objects for QPSK system design, including coarse and fine carrier frequency compensation, closed-loop timing recovery with bit stuffing and stripping, frame synchronization, carrier phase ambiguity resolution, and message decoding.

In this example, the SDR System object receives data corrupted by the transmission over the air and outputs complex baseband signals that are processed by the QPSK Receiver System object. This example provides a reference design of a practical digital receiver that can cope with wireless channel impairments. The receiver includes FFT-based coarse frequency compensation, PLL-based fine frequency compensation, timing recovery with fixed-rate resampling and bit stuffing/skipping, frame synchronization, and phase ambiguity resolution.


The sdrfqpskreceiver_init.m script initializes the simulation parameters and generates the structure prmQPSKReceiver.

prmQPSKReceiver = sdrfqpskreceiver_init % Receiver parameter structure
compileIt  = false; % true if code is to be compiled for accelerated execution
useCodegen = false; % true to run the latest generated code (mex file) instead of MATLAB code

To transmit successfully, make sure that the specified center frequency of the SDR Receiver is within the acceptable range of your SDR daughterboard.

Also, by using the compileIt and useCodegen flags, it is possible to interact with the code to explore different execution options. Set the MATLAB variable compileIt to true in order to generate C code; this can be accomplished by using the codegen command provided by the MATLAB Coder™ product. The codegen command compiles MATLAB® functions to a C-based static or dynamic library, executable, or MEX file, producing code for accelerated execution. The generated executable runs several times faster than the original MATLAB code. Set useCodegen to true to run the executable generated by codegen instead of the MATLAB code.

Code Architecture

The function runSDRFQPSKReceiver.m implements the QPSK receiver using two System objects, QPSK Receiver and the SDR receiver.

SDR Receiver

This example communicates with the SDR board using the SDR Receiver System object. You can supply the IP address of the SDR board as an argument when constructing the object. The IP address can be any address within the same sub-network as the host computer. This example configures the SDR object to use the default address The parameter structure prmQPSKReceiver sets the CenterFrequency, Gain, and DecimationFactor arguments.

QPSK Receiver

This component regenerates the original transmitted message. It is divided into five subcomponents, modeled using System objects. Each subcomponent is modeled by other subcomponents using System objects.

  1. Automatic Gain Control: Sets its output amplitude to 1/sqrt(Upsampling Factor) (0.5), so that the equivalent gains of the phase and timing error detectors keep constant over time. The AGC is placed before the Raised Cosine Receive Filter so that the signal amplitude can be measured with an oversampling factor of four. This process improves the accuracy of the estimate.

  2. Coarse frequency compensation: Uses nonlinearity and a Fast Fourier Transform (FFT) to roughly estimate the frequency offset and then compensate for it. The object raises the input signal to the power of four to obtain a signal that is not a function of the QPSK modulation. It then performs an FFT on the modulation-independent signal to estimate the tone at four times the frequency offset. After dividing the estimate by four, the Phase/Frequency Offset System object corrects the frequency offset.

  3. Fine frequency compensation: Performs closed-loop scalar processing and compensates for the frequency offset accurately. The Fine Frequency Compensation object implements a phase-locked loop (PLL) to track the residual frequency offset and the phase offset in the input signal. For more information, see Chapter 7 of [ 1 ]. The PLL uses a Direct Digital Synthesizer (DDS) to generate the compensating phase that offsets the residual frequency and phase offsets. The phase offset estimate from DDS is the integral of the phase error output of the Loop Filter. To obtain details of PLL design, refer to Appendix C.2 of [ 1 ].

  4. Timing recovery: Performs timing recovery with closed-loop scalar processing to overcome the effects of delay introduced by the channel. The Timing Recovery object implements a PLL, described in Chapter 8 of [ 1 ], to correct the timing error in the received signal. The NCO Control object implements a decrementing modulo-1 counter described in Chapter 8.4.3 of [ 1 ] to generate the control signal for the Modified Buffer to select the interpolants of the Interpolation Filter. This control signal also enables the Timing Error Detector (TED), that then calculates the timing errors at the correct timing instants. The NCO Control object updates the timing difference for the Interpolation Filter , generating interpolants at optimum sampling instants. The Interpolation Filter is a Farrow parabolic filter with alpha set to 0.5 as described in Chapter 8.4.2 of [ 1 ]. Based on the interpolants, timing errors are generated by a zero-crossing Timing Error Detector as described in Chapter 8.4.1 of [ 1 ]. They are then filtered by a tunable proportional-plus-integral Loop Filter as described in Appendix C.2 of [ 1 ], and fed into the NCO Control for a timing difference update. The Loop Bandwidth (normalized by the sample rate) and Loop Damping Factor are tunable for the Loop Filter. The default normalized loop bandwidth is set to 0.01 and the default damping factor is set to 1 for critical damping. These settings make sure that the PLL quickly locks to the correct timing while introducing little phase noise.

  5. Data decoder: Uses a Barker code to perform frame synchronization, phase ambiguity resolution, and demodulation. Also, the data decoder compares the regenerated message with the transmitted message and calculates the BER.

For more information about the system components, refer to the Simulink example QPSK Receiver with SDR Hardware example using Simulink.

Execution and Results

The code below runs the receiver and returns the BER and the number of lost samples.

if compileIt
    codegen('runSDRFQPSKReceiver', '-args', {coder.Constant(prmQPSKReceiver)});
if useCodegen
   clear runSDRFQPSKReceiver_mex %#ok<UNRCH>
   BER = runSDRFQPSKReceiver_mex(prmQPSKReceiver);
   BER = runSDRFQPSKReceiver(prmQPSKReceiver);

fprintf('Error rate is = %f.\n',BER(1));
fprintf('Number of detected errors = %d.\n',BER(2));
fprintf('Total number of compared samples = %d.\n',BER(3));

When you run the simulation, the received messages are decoded and printed out in the MATLAB command window while the simulation is running. If the received signal is decoded correctly, you should see 'Hello world 0##' messages in the MATLAB command line similar to those shown below.

Hello world 031
Hello world 032
Hello world 033
Hello world 034
Hello world 035
Hello world 036
Hello world 037
Hello world 038
Hello world 039
Hello world 040

When the simulations are run, the received messages are decoded and printed out in the MATLAB command window while the simulation is running. BER information is also shown at the end of the script execution. The calculation of the BER value includes the first received frames, when some of the adaptive components in the QPSK receiver still have not converged. During this period, the BER is quite high. Once the transient period is over, the receiver is able to estimate the transmitted frame and the BER dramatically improves. In this example, to guarantee a reasonable execution time of the system in simulation mode, the simulation duration is fairly short. As such, the overall BER results are significantly affected by the high BER values at the beginning of the simulation. To increase the simulation duration and obtain lower BER values, the SimParams.StopTime variable can be changed within the receiver initialization file.

Also, the gain behavior of different SDR daughter boards varies considerably. Thus, the gain setting in the receiver defined in this example may not be well-suited for your daughter boards. If the message is not properly decoded by the receiver system, you can vary the gain of the source signals in the SDR Receiver System objects by changing the SimParams.RadioGain value in the transmitter initialization file and in the receiver initialization file.

Finally, a large relative frequency offset between the transmit and receive SDR radios can prevent the receiver functions from properly decoding the message. If that happens, the offset can be determined by sending a tone at a known frequency from the transmitter to the receiver, then measuring the offset between the transmitted and received frequency. This value can then be used to compensate the center frequency of the SDR Receiver System object. See the Frequency Offset Calibration with SDR Hardware example.


This example uses the following script and helper functions:


1. Rice, Michael. Digital Communications - A Discrete-Time Approach. 1st ed. New York, NY: Prentice Hall, 2008.

Was this topic helpful?