# OFDM Demodulator

Demodulate time-domain OFDM samples and return subcarriers for custom communication protocols

*Since R2019b*

**Libraries:**

Wireless HDL Toolbox /
Modulation

## Description

The OFDM Demodulator block demodulates time-domain orthogonal frequency division multiplexing (OFDM) samples and outputs subcarriers based on the OFDM parameters. The block supports 5G new radio (NR) standard, long term evolution (LTE) [1], wireless local area network (WLAN 802.11a/g/n/ac) [2], WiMAX, digital video broadcast (DVB), and digital audio broadcast (DAB) standards.

The block accepts input data along with a valid control signal and these OFDM parameters:
FFT length, CP length, and the number of right and left guard subcarriers. The block outputs
demodulated data along with valid and ready controls signals. The block enables the **ready** output port only when these OFDM parameters are provided to the
block through input ports. The block samples the corresponding OFDM parameters only when the
**ready** port is `1`

(high) and the first
**valid** port of each OFDM symbol is `1`

(high).

The block supports scalar and vector inputs. You can use a vector input to increase the data throughput and achieve a giga-sample-per-second (GSPS) throughput. The block provides an interface and architecture suitable for HDL code generation and hardware deployment.

## Examples

## Ports

### Input

**data** — Input data

scalar | column vector

Input data, specified as a scalar or column vector of real or complex values. The vector size must be a power of 2, in the range from 1 to 64, and less than or equal to the FFT length.

The software supports `double`

and
`single`

data types for simulation, but not for HDL code generation.

**Data Types: **`single`

| `double`

| `int8`

| `int16`

| `int32`

| `signed fixed point`

**Complex Number Support: **Yes

**valid** — Indicates valid input data

scalar

Indicates valid input data, specified as a scalar.

This port is a control signal that indicates when the sample from the
**data** input port is valid. When this value is
`1`

, the block captures the values on the **data**
input port. When this value is `0`

, the block ignores the values on
the **data** input port.

**Data Types: **`Boolean`

**FFTLen** — Length of FFT

scalar

Length of the FFT, specified as a scalar. The FFT length must be power of 2 and in
the range from 8 to 65,536. This value must be less than or equal to the
**Maximum FFT length** parameter value.

To support the minimum FFT length of 8, the **FFTLen** data type
must be `fixdt(0,k,0)`

, where *k* is greater than or
equal to 4.

#### Dependencies

To enable this port, set the **OFDM parameters source**
parameter to `Input port`

.

**Data Types: **`single`

| `double`

| `uint8`

| `uint16`

| `uint32`

| `unsigned fixed point`

**CPLen** — Length of cyclic prefix

scalar

Length of the cyclic prefix, specified as a scalar in the range from 0 to
**FFTLen**.

To support the minimum FFT length of 8, the **CPLen** data type
must be `fixdt(0,k,0)`

, where *k* is greater than or
equal to 4.

#### Dependencies

To enable this port, set the **OFDM parameters source**
parameter to `Input port`

.

**Data Types: **`single`

| `double`

| `uint8`

| `uint16`

| `uint32`

| `unsigned fixed point`

**numLgSc** — Number of left guard carriers of OFDM symbol

scalar

Number of left guard carriers of OFDM symbol, specified as a scalar in the range
from 0 to (**FFTLen**/2) – 1.

To support the minimum FFT length of 8, the **numLgSc** data type
must be `fixdt(0,k,0)`

, where *k* is greater than or
equal to 2.

#### Dependencies

To enable this port, set the **OFDM parameters source**
parameter to `Input port`

.

**Data Types: **`single`

| `double`

| `uint8`

| `uint16`

| `uint32`

| `unsigned fixed point`

**numRgSc** — Number of right guard carriers of OFDM symbol

scalar

Number of right guard carriers of OFDM symbol, specified as a scalar in the range
from 0 to (**FFTLen**/2) – 1.

To support the minimum FFT length of 8, the **numRgSc** data type
must be `fixdt(0,k,0)`

, where *k* is greater than or
equal to 2.

#### Dependencies

To enable this port, set the **OFDM parameters source**
parameter to `Input port`

.

**Data Types: **`single`

| `double`

| `uint8`

| `uint16`

| `uint32`

| `unsigned fixed point`

**CPFraction** — CP Fraction

real positive scalar

CP Fraction, specified as a real positive scalar in the range [0, 1].

To support maximum precision, the **CPFraction** data type must
be `fixdt(0,k,p)`

, where *k* is less than or equal
to 16 and *p* is equal to *k* - 1.

#### Dependencies

To enable this port, select the **Enable CP fraction **
parameter and set the **CP fraction source** parameter to
`Input port`

.

**Data Types: **`single`

| `double`

| `unsigned fixed point`

**reset** — Clear internal states

scalar

Clear internal states, specified as a scalar. When this value is
`1`

(true), the block stops the current calculation and clears all
internal states.

#### Dependencies

To enable this port, select the **Enable reset input port**
parameter.

**Data Types: **`Boolean`

### Output

**data** — Demodulated output data

scalar | column vector

Demodulated output data, returned as a complex-valued scalar or column vector.
Output data type is dependent on the data type of the input **data**
port.

When you set the

**OFDM parameters source**parameter to`Property`

and clear the**Divide butterfly outputs by two**parameter, the output word length increases by log_{2}(**FFT length**) bits.When you set the

**OFDM parameters source**parameter to`Input port`

and clear the**Divide butterfly outputs by two**parameter, the output word length increases by log_{2}(**Maximum FFT length**) bits.

To avoid overflow, select the **Divide butterfly outputs by two**
parameter.

**Data Types: **`single`

| `double`

| `int8`

| `int16`

| `int32`

| `signed fixed point`

**Complex Number Support: **Yes

**valid** — Indicates valid output data

scalar

Indicates valid input data, returned as a scalar.

This port is a control signal that indicates when the **data**
output port is valid. The block sets this value to `1`

when the data
samples are available on the **data** output port. When you select
the **Remove DC subcarrier** parameter, this value is set to
`0`

at the center of the output samples to exclude the DC
carrier.

**Data Types: **`Boolean`

**ready** — Indicates block is ready

scalar

Control signal that indicates when the block is ready for new input data. When
this value is `1`

, the block accepts input data in the next time
step. When this value is `0`

, the block ignores input data in the
next time step.

#### Dependencies

To enable this port, set the **OFDM parameters source**
parameter to `Input port`

.

**Data Types: **`Boolean`

## Parameters

### Main

**OFDM parameters source** — Source of OFDM parameters

`Property`

(default) | `Input port`

You can set OFDM parameters with an input port or by selecting a value for the parameter.

Select `Property`

to enable the **FFT
length**, **Cyclic prefix length**, **Number of
left guard subcarriers**, and **Number of right guard
subcarriers** parameters.

Select `Input port`

to enable the
**FFTLen**, **CPLen**,
**numLgSc**, **numRgSc** input ports and the
**Maximum FFT length** parameter. The **Maximum
FFT length** parameter sets the upper bound of the range of valid values
for the **FFTLen** input port.

**Maximum FFT length** — Maximum length of FFT length

`64`

(default) | power of 2 in range from 8 to 65,536

Specify the maximum length of the FFT.

#### Dependencies

To enable this parameter, set the **OFDM parameters source**
parameter to `Input port`

.

**FFT length** — Length of FFT

`64`

(default) | power of 2 in range from 8 to 65,536

Specify the FFT length. When you set the **OFDM parameters
source** parameter to `Property`

, the block uses
this FFT length value as the maximum FFT length.

#### Dependencies

To enable this parameter, set the **OFDM parameters source**
parameter to `Property`

.

**Cyclic prefix length** — Length of cyclic prefix

`16`

(default) | integer in range from 0 to **FFT length**

Specify the length of the cyclic prefix.

#### Dependencies

To enable this parameter, set the **OFDM parameters source**
parameter to `Property`

.

**Number of left guard subcarriers** — Number of guard band subcarriers in left extreme of OFDM symbol

`6`

(default) | integer in range from 0 to (**FFT length**/2) – 1

Specify the number of left guard subcarriers.

#### Dependencies

To enable this parameter, set the **OFDM parameters source**
parameter to `Property`

.

**Number of right guard subcarriers** — Number of guard band subcarriers in right extreme of OFDM symbol

`5`

(default) | integer in range from 0 to (**FFT length**/2) – 1

Specify the number of right guard subcarriers.

#### Dependencies

To enable this parameter, set the **OFDM parameters source**
parameter to `Property`

.

**Enable CP fraction** — CP fraction enabler

`off`

(default) | `on`

Select this parameter to enable the CP fraction either through
`Property`

or through ```
Input
port
```

.

**CP fraction source** — CP fraction source type

`Property`

(default) | `Input port`

You can set CP fraction with an input port or by selecting a value for the parameter.

Select `Property`

to enable the **CP
fraction** parameter.

Select `Input port`

to enable the
**CPFraction** input port.

#### Dependencies

To enable this parameter, select the **Enable CP fraction**
parameter.

**CP fraction** — Percent of cyclic prefix to remove

`0.55`

(default) | range from 0 to 1

Cyclic prefix fraction, specified as a value from 0 to 1, inclusive. This parameter specifies the percentage of CP samples that the block removes from the start of the OFDM symbol. The block shifts the remaining CP samples to the end of the OFDM symbol.

When this parameter is `0.55`

, the block removes 55% of the CP
from the beginning of the symbol, and shifts 45% to the end of the symbol. When you
set this parameter to `1`

, the block removes 100% of the CP from the
start of the OFDM symbol, and does not shift any samples to the end.

#### Dependencies

To enable this parameter, select the **Enable CP fraction**
parameter and the set the **CP fraction source** parameter to
`Property`

.

**Remove DC subcarrier** — Exclude or include DC subcarrier

`on`

(default) | `off`

When you select this parameter, the block excludes the DC subcarrier in the output
by setting the output valid signal to `0`

for the center of the
output subcarriers.

**Enable reset input port** — Reset signal

`off`

(default) | `on`

Select this parameter to enable the **reset** input port.

### FFT Parameters

**Divide butterfly outputs by two** — Divide FFT butterfly outputs by two

`off`

(default) | `on`

This parameter controls the scaling option of the FFT block inside the OFDM Demodulator block.

When you select this parameter, the FFT implements an overall
1/*N* scale factor by dividing the output of each butterfly
multiplication by two. This adjustment keeps the output of the FFT in the same
amplitude range as its input. If you clear this parameter, the block avoids overflow
by increasing the word length by one bit after each butterfly multiplication.

**Rounding Method** — Rounding mode for internal fixed-point calculations

`Floor`

(default) | `Ceiling`

| `Convergent`

| `Nearest`

| `Round`

| `Zero`

This parameter specifies the type of rounding mode for internal fixed-point
calculations. For more information about rounding modes, see Rounding Modes. When the input is any integer data
type or fixed-point data type, the FFT algorithm uses fixed-point arithmetic for
internal calculations. This parameter does not apply when the input is of data type
`single`

or `double`

. Rounding applies to
twiddle-factor multiplication and scaling operations.

## Algorithms

The OFDM Demodulator block operation sequence is implemented using these blocks: Ready Generator, Cyclic Prefix Remover, Sample Repeater, FFT Shifter, FFT, Down Sampler, and Subcarrier Selector. The parameters shown in this figure configure the behavior of the block.

### Ready Generator

This block enables a **ready** port when you set the
**OFDM parameters source** parameter to ```
Input
port
```

. This **ready** port controls the input
samples based on the maximum FFT length.

The following equations apply.

*N*_{h}=`ceil`

((*N*_{r}+**FFTLen**+**CPLen**)/*vecLen*)*N*_{l}=`ceil`

((*N*_{r}+**Maximum FFT length**+**CPLen**)/*vecLen*) –*N*_{h}

In these equations,

*N*_{h}is the number of high ready clock cycles*N*_{l}is the number of low ready clock cycles*N*_{r}is the number of remaining samples from the previous OFDM symbol. Initially, this value is`0`

. In the subsequent operations, the block calculates*N*_{r}using the equation, (*N*_{r}+**FFTLen**+**CPLen**) - (`floor`

((*N*_{r}+**FFTLen**+**CPLen**) /*vecLen*) x*vecLen*)*vecLen*is the length of the vector

### Cyclic Prefix Remover

This block removes CP samples from an OFDM symbol for extracting constellation symbols.
The block performs CP removal based on these parameters: **CP length**,
**CP fraction** (when enabled), and the **FFT
length**.

This block supports windowed transmission by implementing fractional cyclic prefix removal. Windowing reduces out-of-band emissions. A transmitter performs windowing by overlapping the tail of each OFDM symbol with the head of the next OFDM symbol. A receiver must avoid these overlapped samples in the FFT calculation. Fractional CP solves this problem by removing part of the CP at the start of a symbol and the remainder of the CP at the end of the symbol. Implementing a CP-fraction algorithm also makes this block less sensitive to timing offset.

The block handles the CP in two stages. First, the block calculates the number of CP
samples to remove, *N*_{r}, and removes those samples
from the input samples. In this case, *N*_{r} =
*CP fraction* x *CP length*.

Next, the block calculates the number of samples to shift,
*N*_{s}, and shifts those samples to the end of OFDM
symbol in the time domain. Where, *N*_{s} = *CP
length* – (*CP fraction* x *CP length*).

These two segments together make up the total cyclic prefix length,
*N*_{cp} =
*N*_{s} +
*N*_{r}. The **CP fraction**
parameter controls how many samples the block removes at the beginning of the symbol. The
block shifts the remainder of the cyclic prefix from the start of the symbol to the end of
the symbol. The block quantizes the **CP fraction** parameter as
`fi(0,11,10)`

. To achieve an integer number of samples, the block
calculates *N*_{r} = `floor`

(*N*_{cp} x **CP fraction**).

For example, if the FFT length is 128 and CP length is 10, the block receives 128 samples plus the cyclic prefix size.

### Sample Repeater

This block repeats FFT-length number of samples until it forms the maximum FFT length.
For this operation, the block buffers the input samples first and then repeats the samples
based on the maximum FFT length value. This repetition mechanism helps to avoid scaling at
the FFT block input. This block is optional and available only when you set the
**OFDM parameters source** parameter to ```
Input
port
```

. When you set the **OFDM parameters source** parameter
to `Property`

, the FFT length value provided in the block mask is
set as the maximum FFT length. The block does not need to repeat the samples in this
context.

For example, if the FFT length is 128 and the maximum FFT length is 2048, each OFDM symbol consists of 128 samples. The block converts these 128 samples to 2048 samples by repeating the 128 samples 16 times. After the block generates 2048 data samples, it sends data and valid input signals to the next block.

### Time-Domain FFT Shifter

Conventionally, receivers perform the FFT shift in the frequency domain. However, this method requires memory and introduces latency related to the size of the FFT. Instead, a receiver can execute the same operation in the time domain by using the frequency shifting property of Fourier transforms. Shifting a function in one domain corresponds to a multiplication by a complex exponential function in the other domain. To reduce hardware resources and latency, this block performs the FFT shift by multiplying the time-domain samples by a complex exponential function.

These equations describe an FFT shift. The equation for an *N*-point
FFT is

$$X(k)=F[x(n)]={\displaystyle \sum _{n=0}^{N-1}x(n){e}^{-\frac{j2\pi nk}{N}}}$$

For an FFT shift of *N*/2 carriers in either direction, substitute $$k=k-\frac{N}{2}$$, resulting in

$$X(k-{\scriptscriptstyle \frac{N}{2}})={\displaystyle \sum _{n=0}^{N-1}x(n){e}^{-\frac{j2\pi n(k-{\scriptscriptstyle \frac{N}{2}})}{N}}}$$

This equation simplifies to

$$X(k-\frac{N}{2})={\displaystyle \sum _{n=0}^{N-1}{e}^{j\pi n}x(n){e}^{-\frac{j2\pi nk}{N}}}$$

Since $$\sum _{n=0}^{N-1}x(n){e}^{-\frac{j2\pi nk}{N}}$$ is equivalent to $$F[x(n)]$$, and $${e}^{j\pi}=-1$$, this equation simplifies to

$$X(k-\frac{N}{2})=F[{{\displaystyle (-1)}}^{n}x(n)]$$

The final equation shows that an FFT shift in the time domain simplifies to
multiplication by (–1)^{n}. As a result, the
block implements the FFT shift by multiplying the time-domain samples by either +1 or
–1.

### FFT

This block converts a time-domain signal to a frequency-domain signal based on the maximum FFT length provided for the block. You can provide the FFT length value either through a parameter or through an input port. The output of the FFT shift subsystem is fed to an FFT block. The block calculates the maximum FFT for all the FFT length and CP length values.

The **Divide butterfly outputs by two** parameter sets whether the FFT
implements an overall 1/*N* scale factor by dividing the output of each
butterfly multiplication by two. This adjustment keeps the output of the FFT in the same
amplitude range as its input. When you clear the **Divide butterfly outputs by
two** parameter, the block avoids overflow by increasing the word length by one
bit after each butterfly multiplication.

### Down Sampler

This block down samples maximum-FFT-length number of samples to FFT-length number of
samples. This block is optional and available only when you set the **OFDM
parameters source** parameter to `Input port`

. When you
set the **OFDM parameters source** parameter to
`Property`

, the FFT length value provided in the block mask sets
the maximum FFT length. The block does not need to downsample the samples in this
context.

For example, if the FFT length is 128 and the maximum FFT length is 2048, the input is 2048 samples and must be downsampled with respective to the FFT length of 128. In this case, the block samples 1 sample for every 16 samples.

### Subcarrier Selector

The output subcarriers are categorized into data, DC, and guard subcarriers. Data subcarriers contains useful data. This block selects subcarriers by removing the number of left guard subcarriers and right guard subcarriers provided for the block. The number of guard subcarriers to set varies with standards.

If you select the **Remove DC subcarrier** parameter, the block
excludes the DC subcarrier from output. The block excludes the DC subcarrier by setting the
**valid** port to `0`

(false) for the center cycle of
the output subcarriers.

### Latency

The block captures output data at valid cycles based on the type of input: scalar or vector.

**Scalar Input**

This figure shows a sample output and latency of the OFDM Demodulator
block when you specify a scalar input, set the **OFDM parameters source**
parameter to `Property`

and use default settings for the other
block parameters. In this example, the **FFTLen** parameter is set to
`64`

, **Cyclic prefix length** parameter is set to
`16`

, **Number of left guard subcarriers** parameter
is set to `6`

, and **Number of right guard subcarriers**
parameter is set to `5`

.

In this example, the latency of the block is calculated using this formula:
**Cyclic prefix length** + *FFTLatency* +
**Number of left guard subcarriers** + 12, where
*FFTLatency* is the latency of FFT block for the
specified FFT length, and 12 is the number of pipeline delays.

After calculation, the latency of the block is 207 clock cycles, as shown in the following figure.

This figure shows a sample output and latency of the block when you specify a scalar
input and set the **OFDM parameters source** parameter to
`Input port`

. In this example, the **FFTLen**
port is set to `64`

, **CPLen** port is set to
`16`

, **numLgSc** port is set to `6`

and **numRgSc** port is set to `5`

, and
**Maximum FFT length** parameter is set to
`128`

.

The latency of the block is calculated using the formula **CPLen** +
**FFTLen** + *FFTLatency* +
**numLgSc** x (**Maximum FFT
length**/**FFTLen**) + 25, where *FFTLatency*
is the latency of FFT block for the specified maximum FFT length, and 25 is
the number of pipeline delays.

After calculation, the latency of the block is 424 clock cycles, as shown in this figure.

The block accepts input only when the **ready** is
`1`

(high). In this case, the block captures parameters on the first
cycle when the input **valid** port is `1`

(high).

**Vector Input**

This figure shows a sample output and latency of the OFDM Demodulator
block when you specify a two-element column vector input and set the **OFDM
parameters source** parameter to `Property`

and use
default settings for the other block parameters. **FFTLen** is set to
`64`

, **Cyclic prefix length** is set to
`16`

, and **Number of left guard subcarriers** and
**Number of right guard subcarriers** are set to `6`

and `5`

, respectively.

In this example, the latency of the block is calculated using this formula:
`floor`

(**Cyclic prefix
length**/*vecLen*) + *vecFFTLatency* +
`floor`

(**Number of left guard
subcarriers**/*vecLen*) + 12, where
*vecFFTLatency* is the latency of FFT block for the
specified FFT length and vector length, *vecLen* is the length of the
vector, and 12 is the number of pipeline delays.

This calculation shows that the latency of the block is 142 clock cycles, as shown in this figure.

This figure shows a sample output and latency of the block when you specify a
two-element column vector input and set the **OFDM parameters source**
parameter to `Input port`

. For this example,
**FFTLen** is set to `64`

, **CPLen**
is set to `16`

, **numLgSc** is set to
`6`

, **numRgSc** is set to `5`

, and
**Maximum FFT length** is set to `128`

.

In this example, the latency of the block is calculated using this formula:
`floor`

(**CPLen**/*vecLen*) +
**FFTLen**/*vecLen* + *vecFFTLatency*
+ `floor`

(**numLgSc**/*vecLen*) x
(**Maximum FFT length**/**FFTLen**) + 26, where
*vecFFTLatency* is the latency of FFT block for the
specified maximum FFT length and vector length, *vecLen* is the length of
the vector, and 26 is the number of pipeline delays.

After calculation, the latency of the block is 266 clock cycles, as shown in this figure.

The block accepts input only when the **ready** is
`1`

(high). In this case, the block captures parameters on the first
cycle when the input **valid** port is `1`

(high).

### Performance

The performance of the synthesized HDL code varies with your target and synthesis
options. The input data type used in this example for generating HDL code is
`fixdt(1,16,14)`

.

This table shows the resource and performance data synthesis results when using the
block with a scalar or two-element column vector input for default configuration values. The
generated HDL is targeted to the Xilinx^{®}
Zynq^{®}- 7000 ZC706 evaluation board.

Input Data | Slice LUTs | Slice Registers | DSPs | Block RAM | Maximum Frequency in MHz |
---|---|---|---|---|---|

Scalar | 2434 | 4161 | 8 | 1 | 340 |

Vector | 4890 | 7764 | 16 | 0 | 235 |

## References

[1] 3GPP TS 36.211 version 14.2.0
Release 14. "Physical channels and modulation." *LTE - Evolved Universal Terrestrial
Radio Access (E-UTRA)*.

[2] "Wireless LAN Medium Access Control (MAC) and Physical layer (PHY) Specifications." IEEE Std 802.11 – 2012.

[3] Stefania Sesia, Issam Toufik, and
Matthew baker. *LTE - THE UMTS Long Term Evolution from theory to
practice*.

[4] Erik Dahlman, Stefan Parkvall, and
Johan Skold. *4G - LTE/LTE - Advanced for Mobile broadband Second
edition*.

## Extended Capabilities

### C/C++ Code Generation

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

This block supports C/C++ code generation for Simulink^{®} accelerator and rapid accelerator modes and for DPI component generation.

### HDL Code Generation

Generate VHDL, Verilog and SystemVerilog code for FPGA and ASIC designs using HDL Coder™.

HDL Coder™ provides additional configuration options that affect HDL implementation and synthesized logic.

This block does not have any HDL Block Properties.

## Version History

**Introduced in R2019b**

### R2023a: CP fraction as input port

You can now specify the CP fraction through port. To enable this port, select the
**Enable CP fraction** parameter and set the **CP fraction
source** parameter to `Input port`

.

## 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)