# ofdmdemod

Demodulate time-domain signal using orthogonal frequency division multiplexing (OFDM)

## Syntax

## Description

performs OFDM demodulation on the input time domain signal specified in
`outSym`

= ofdmdemod(`ofdmSig`

,`nfft`

,`cplen`

)`ofdmSig`

, using an FFT size specified by
`nfft`

and cyclic prefix length specified by
`cplen`

. For information, see OFDM Demodulation.

removes null subcarriers from the locations specified in
`outSym`

= ofdmdemod(`ofdmSig`

,`nfft`

,`cplen`

,`symOffset`

,`nullidx`

)`nullidx`

. For this syntax, the symbol sampling offset is
applied to each OFDM symbol and the number of rows in the output is
`nfft`

–
`length(`

, which accounts for the
removal of null subcarriers. Use null subcarriers to account for guard bands and DC
subcarriers. For information, see Subcarrier Allocation and Guard Bands.`nullidx`

)

`[`

returns pilot subcarriers for the pilot indices specified in
`outSym`

,`pilots`

] = ofdmdemod(`ofdmSig`

,`nfft`

,`cplen`

,`symOffset`

,`nullidx`

,`pilotidx`

)`pilotidx`

. For this syntax, the symbol sampling offset is
applied to each OFDM symbol and number of rows in the output is
`nfft`

–
`length(`

–
`nullidx`

)`length(`

, which accounts for
the removal of null and pilot subcarriers. The function assumes that pilot
subcarrier locations are the same across each OFDM symbol and transmit
antenna.`pilotidx`

)

## Examples

### OFDM Demodulation with Different CP Lengths

OFDM-demodulate a signal with different CP lengths for different symbols.

Initialize input parameters defining locations for null and pilot subcarriers. Generate random data and perform OFDM modulation.

nfft = 64; cplen = [16 32]; nSym = 2; dataIn = complex(randn(nfft,nSym),randn(nfft,nSym)); y1 = ofdmmod(dataIn,nfft,cplen);

Demodulate the OFDM symbols. Compare the results to the original input data. The difference between the signals is negligible.

x1 = ofdmdemod(y1,nfft,cplen); max(x1-dataIn)

ans =1×2 complex10^{-15}× 0.2220 - 0.7772i 0.2498 - 0.8882i

### OFDM Mod-Demod SISO Link

Apply OFDM multiplexing to a 16-QAM signal filtered by a SISO link with Rayleigh fading.

Initialize simulation variables, and create Rayleigh fading channel and constellation diagram objects.

s1 = RandStream('mt19937ar','Seed',12345); nFFT = 64; cpLen = 16; nullIdx = [1:6 33 64-4:64].'; numTones = nFFT-length(nullIdx); k = 4; % bits per symbol M = 2^k; constSym = qammod((0:M-1),M,'UnitAveragePower',true); % reference constellation symbols maxDopp = 1; pathDelays = [0 4e-3 8e-3]; pathGains = [0 -2 -3]; sRate = 1000; sampIdx = round(pathDelays/(1/sRate)) + 1; chan = comm.RayleighChannel('PathGainsOutputPort',true, ... 'MaximumDopplerShift',maxDopp, ... 'PathDelays',pathDelays, ... 'AveragePathGains',pathGains, ... 'SampleRate',sRate, ... 'RandomStream','mt19937ar with seed'); cdScope = comm.ConstellationDiagram('ShowReferenceConstellation',true, ... 'ReferenceConstellation',constSym);

Generate signal data and apply 16-QAM modulation.

```
data = randi(s1,[0 M-1],numTones,1);
modOut = qammod(data,M,'UnitAveragePower',true);
```

Apply OFDM modulation and pass the signal through the channel.

y = ofdmmod(modOut,nFFT,cpLen,nullIdx); [fadSig,pg] = chan(y);

Determine symbol sampling offset.

symOffset = min(max(sampIdx),cpLen)

symOffset = 9

OFDM demodulate the received signal with a time shift. Display the constellation diagram before equalization.

x = ofdmdemod(fadSig,nFFT,cpLen,symOffset,nullIdx); cdScope(x);

Convert the vector of path gains, `pg`

, to scalar tap gains that correspond to data subcarriers, `h_datasubcarr`

. Use the `h_datasubcarr`

tap gains for equalization during signal recovery.

hImp = complex(zeros(nFFT,1)); hImp(sampIdx) = mean(pg,1); hall = fftshift(fft(hImp)); dataIdx = setdiff((1:nFFT)',nullIdx); h_datasubcarr = hall(dataIdx);

Equalize the signal. Display the constellation diagram after equalization.

eqSig = x ./ h_datasubcarr; cdScope(eqSig);

Demodulate the 16-QAM symbols to recover the signal. Compute the symbol error rate.

rxSym = qamdemod(eqSig,M,'UnitAveragePower',true); numErr = symerr(data,rxSym); disp(['Number of symbol errors: ' num2str(numErr) ' out of ' num2str(length(data)) ' symbols.'])

Number of symbol errors: 2 out of 52 symbols.

### OFDM Demodulation with Null and Pilot Packing

OFDM-demodulate data input that includes null and pilot packing.

Initialize input parameters, defining locations for null and pilot subcarriers. Generate random data and perform OFDM modulation.

nfft = 64; cplen = 16; nSym = 10; nullIdx = [1:6 33 64-4:64]'; pilotIdx = [12 26 40 54]'; numDataCarrs = nfft-length(nullIdx)-length(pilotIdx); dataIn = complex(randn(numDataCarrs,nSym),randn(numDataCarrs,nSym)); pilots = repmat(pskmod((0:3).',4),1,nSym); y2 = ofdmmod(dataIn,nfft,cplen,nullIdx,pilotIdx,pilots);

Demodulate the OFDM symbols. Compare the results to the original input data to show that there is negligible difference between the demodulated signal and the original data and pilot signals.

symOffset = cplen; [x2,rxPilots] = ofdmdemod(y2,nfft,cplen,symOffset,nullIdx,pilotIdx); max(x2-dataIn)

ans =1×10 complex10^{-15}× 0.6661 - 0.2220i -0.5308 + 0.0555i 0.8882 - 0.1110i 0.2498 + 0.4441i 0.4441 + 0.4441i 0.2220 - 0.5829i 0.4441 - 0.4441i -0.6661 - 0.0555i -0.2220 + 0.4441i 0.4441 - 0.2220i

max(rxPilots-pilots)

ans =1×10 complex10^{-15}× -0.0057 - 0.3331i -0.2220 - 0.1388i -0.2326 - 0.4441i -0.2220 - 0.2890i -0.0522 - 0.4441i -0.1167 + 0.4441i 0.2718 + 0.2220i 0.2163 - 0.3331i -0.4441 - 0.1225i 0.4441 - 0.0971i

## Input Arguments

`ofdmSig`

— Modulated OFDM symbols

2-D array of complex symbols

Modulated OFDM symbols, specified as a 2-D array of complex symbols.

**Data Types: **`double`

| `single`

**Complex Number Support: **Yes

`nfft`

— FFT length

integer greater than or equal to 8

FFT length, specified as an integer greater than or equal to 8.
`nfft`

is equivalent to the number of subcarriers
used in the demodulation process.

**Data Types: **`double`

`cplen`

— Cyclic prefix length

scalar | row vector of length
*N*_{Sym}

Cyclic prefix length, specified as a scalar or as a row vector of length
*N*_{Sym}.

When you specify

`cplen`

as a scalar, the cyclic prefix length is the same for all symbols through all antennas.When you specify

`cplen`

as a row vector of length*N*_{Sym}, the cyclic prefix length can vary across symbols but remains the same length through all antennas.

**Data Types: **`double`

`symOffset`

— Symbol sampling offset

`cplen`

(default) | scalar | row vector

Symbol sampling offset, specified as values from 0 to
`cplen`

.

If you do not specify

`symOffset`

, the default value is an offset equal to`cplen`

.If you specify

`symOffset`

as a scalar, the same offset is used for all symbols.If you specify

`symOffset`

as a row vector, the offset value can be different for each symbol.

For information, see Windowing and Symbol Offset.

**Data Types: **`double`

`nullidx`

— Indices of null subcarrier locations

column vector

Indices of null subcarrier locations, specified as a column vector with
element values from 1 to `nfft`

. If you specify
`nullidx`

, the number of rows in
`outSym`

is
`(`

.
For information, see Subcarrier Allocation and Guard Bands.`nfft`

-length(`nullidx`

))

**Data Types: **`double`

`pilotidx`

— Indices of pilot subcarrier locations

column vector

Indices of pilot subcarrier locations, specified as a column vector with
element values from 1 to `nfft`

. If you specify
`pilotidx`

, the number of rows in
`outSym`

is
`(`

.For
information, see Subcarrier Allocation and Guard Bands.`nfft`

-length(`nullidx`

)-length(`pilotidx`

))

**Data Types: **`double`

## Output Arguments

`outSym`

— Output demodulated symbols

3-D array

Output demodulated symbols, returned as an
*N*_{D}-by-*N*_{Sym}-by-*N*_{R}
array of symbols. *N*_{D} must equal
`nfft`

–
`length(`

–
`nullidx`

)`length(`

.
`pilotidx`

)*N*_{Sym} is the number of OFDM
symbols per antenna. *N*_{R} is the
number of receive antennas. For information, see OFDM Demodulation.

`pilots`

— Pilot subcarriers

3-D array

Pilot subcarriers, returned as an
*N*_{Pilot}-by-*N*_{Sym}-by-*N*_{R}
array of symbols. *N*_{Pilot} must
equal the length of `pilotidx`

.
*N*_{Sym} is the number of OFDM
symbols per antenna. *N*_{R} is the
number of receive antennas. The function assumes that the pilot subcarrier
locations are the same across each OFDM symbol and transmit antenna. Use the
`comm.OFDMDemodulator`

to vary
pilot subcarrier locations across OFDM symbols or antennas.

## More About

### OFDM Demodulation

An OFDM demodulator demultiplexes a multi-subcarrier time-domain signal using orthogonal frequency division modulation.

The OFDM demodulation uses an FFT operation that results in
*N* parallel data streams. An OFDM demodulator consists of a bank of
*N* correlators, with one correlator assigned to each OFDM subcarrier,
followed by a parallel-to-serial conversion.

### Subcarrier Allocation and Guard Bands

Individual OFDM subcarriers are allocated as data, pilot, or null subcarriers.

As shown here, subcarriers are designated as data, DC, pilot, or guard band subcarriers.

Data subcarriers transmit user data.

Pilot subcarriers are used for channel estimation.

Null subcarriers transmit no data. Subcarriers with no data are used to provide a DC null and serve as buffers between OFDM resource blocks.

The null DC subcarrier is the center of the frequency band with an index value of (

`nfft`

/2 + 1) if`nfft`

is even, or ((`nfft`

+ 1) / 2) if`nfft`

is odd.The guard bands provide buffers between consecutive OFDM symbols to protect the integrity of transmitted signals by reducing intersymbol interference.

Null subcarriers enable you to model guard bands and DC subcarrier locations for specific standards, such as the various 802.11 formats, LTE, WiMAX, or for custom allocations. You can allocate the location of nulls by assigning a vector of null subcarrier indices.

Similar to guard bands, guard intervals are used in OFDM to protect the integrity of transmitted signals by reducing intersymbol interference.

Assignment of guard intervals is analogous to the assignment of guard bands. You can model guard intervals to provide temporal separation between OFDM symbols. The guard intervals help preserve intersymbol orthogonality after the signal passes through time-dispersive channels. Guard intervals are created by using cyclic prefixes. Cyclic prefix insertion copies the last part of an OFDM symbol as the first part of the OFDM symbol.

As long as the span of the time dispersion does not exceed the duration of the cyclic prefix, the benefit of cyclic prefix insertion is maintained.

Inserting a cyclic prefix results in a fractional reduction of user data throughput because the cyclic prefix occupies bandwidth that could be used for data transmission.

### Windowing and Symbol Offset

To reduce intersymbol interference (ISI) introduced by signal windowing applied at the transmitter, the function applies a fractional symbol offset before demodulation of each OFDM symbol. Signal windowing is often applied to transmitted OFDM symbols to smooth the discontinuity between consecutive OFDM symbols. Windowing reduces intersymbol out-of-band emissions but increases ISI.

The windowed OFDM symbol consists of the cyclic prefix (CP), ODFM symbol data, plus windowing regions at the beginning and end of the symbol. The leading and trailing windowing shoulders have tails as shown in the figure.

To reduce ISI, you can align signal sample timing by specifying a symbol sampling offset that gets applied before OFDM symbol demodulation.

Specify the symbol sampling offset as a value from 0 to
*L*_{CP}.

When the symbol sampling offset is a scalar from 0 to

*L*_{CP}, the FFT window begins at the*X*+1 sample of the CP length.When the symbol sampling offset is zero, no offset is applied and the FFT window starts at the first sample of the symbol.

When the symbol sampling offset is the cyclic prefix length,

*L*_{CP}, the FFT window begins after the last CP sample. This offset is the default setting if symbol sampling offset is not specified.

## Extended Capabilities

### C/C++ Code Generation

Generate C and C++ code using MATLAB® Coder™.

## Version History

**Introduced in R2018a**

## See Also

### Functions

### Objects

## Open Example

You have a modified version of this example. Do you want to open this example with your edits?

## MATLAB Command

You clicked a link that corresponds to this MATLAB command:

Run the command by entering it in the MATLAB Command Window. Web browsers do not support MATLAB commands.

# Select a Web Site

Choose a web site to get translated content where available and see local events and offers. Based on your location, we recommend that you select: .

You can also select a web site from the following list:

## How to Get Best Site Performance

Select the China site (in Chinese or English) for best site performance. Other MathWorks country sites are not optimized for visits from your location.

### Americas

- América Latina (Español)
- Canada (English)
- United States (English)

### Europe

- Belgium (English)
- Denmark (English)
- Deutschland (Deutsch)
- España (Español)
- Finland (English)
- France (Français)
- Ireland (English)
- Italia (Italiano)
- Luxembourg (English)

- Netherlands (English)
- Norway (English)
- Österreich (Deutsch)
- Portugal (English)
- Sweden (English)
- Switzerland
- United Kingdom (English)