comm.EVM

Measure error vector magnitude

Description

The comm.EVM (error vector magnitude) System object™ measures the modulator or demodulator performance of an impaired signal.

To measure error vector magnitude:

  1. Define and set up your EVM object. See Construction.

  2. Call step to measure the modulator or demodulator performance according to the properties of comm.EVM. The behavior of step is specific to each object in the toolbox.

Note

Starting in R2016b, instead of using the step method to perform the operation defined by the System object, you can call the object with arguments, as if it were a function. For example, y = step(obj,x) and y = obj(x) perform equivalent operations.

Construction

EVM = comm.EVM creates an error vector magnitude object, EVM. This object measures the amount of impairment in a modulated signal.

EVM = comm.EVM(Name,Value) creates an EVM object with each specified property set to the specified value. You can specify additional name-value pair arguments in any order as (Name1,Value1,...,NameN,ValueN).

Example: EVM = comm.EVM('ReferenceSignalSource','Estimated from reference constellation') creates an object, EVM, that measures the RMS EVM of a received signal by using a reference constellation.

Properties

Normalization

Normalization method

Normalization method used in EVM calculation, specified as one of the following: 'Average reference signal power' (default), 'Average constellation power', or 'Peak constellation power'.

AverageConstellationPower

Average constellation power

Average constellation power, specified in watts as a positive real scalar. This property is available when Normalization is 'Average constellation power'. The default is 1.

PeakConstellationPower

Peak constellation power

Peak constellation power, specified in watts as a positive real scalar. This property is available when Normalization is 'Peak constellation power'. The default is 1.

ReferenceSignalSource

Reference signal source

Reference signal source, specified as either 'Input port' (default) or 'Estimated from reference constellation'. To provide an explicit reference signal against which the input signal is measured, set this property to 'Input port'. To measure the EVM of the input signal against a reference constellation, set this property to 'Estimated from reference constellation'.

ReferenceConstellation

Reference constellation

Reference constellation, specified as a vector. This property is available when the ReferenceSignalSource property is 'Estimated from reference constellation'.

The default is [0.7071 - 0.7071i; -0.7071 - 0.7071i; -0.7071 + 0.7071i; 0.7071 + 0.7071i], which corresponds to a standard QPSK constellation. You can derive constellation points by using modulation functions or objects. For example, to derive the reference constellation for a 16-QAM signal, you can use qammod(0:15,16).

MeasurementIntervalSource

Measurement interval source

Measurement interval source, specified as one of the following: 'Input length' (default), 'Entire history', 'Custom', or 'Custom with periodic reset'. This property affects the RMS and maximum EVM outputs only.

  • To calculate EVM using only the current samples, set this property to 'Input length'.

  • To calculate EVM for all samples, set this property to 'Entire history'.

  • To calculate EVM over an interval you specify and to use a sliding window, set this property to 'Custom'.

  • To calculate EVM over an interval you specify and to reset the object each time the measurement interval is filled, set this property to 'Custom with periodic reset'.

MeasurementInterval

Measurement interval

Measurement interval over which the EVM is calculated, specified in samples as a real positive integer. This property is available when MeasurementIntervalSource is 'Custom' or 'Custom with periodic reset'. The default is 100.

AveragingDimensions

Averaging dimensions

Averaging dimensions, specified as a positive integer or row vector of positive integers. This property determines the dimensions over which the averaging is performed. For example, to average across the rows, set this property to 2. The default is 1.

The object supports variable-size inputs over the dimensions in which the averaging takes place. However, the input size for the nonaveraged dimensions must remain constant between step calls. For example, if the input has size [4 3 2] and Averaging dimensions is [1 3], the output size is [1 3 1], and the second dimension must remain fixed at 3.

MaximumEVMOutputPort

Maximum EVM measurement output port

Maximum EVM measurement output port, specified as a logical scalar. To create an output port for maximum EVM measurements, set this property to true. The default is false.

XPercentileEVMOutputPort

X-percentile EVM measurement output port

X-percentile EVM measurement output port, specified as a logical scalar. To create an output port for X-percentile EVM measurements, set this property to true. The X-percentile EVM measurements persist until you reset the object. These measurements are calculated by using all of the input frames since the last reset. The default is false.

XPercentileValue

X-percentile value

X-percentile value below which X% of the EVM measurements fall, specified as a real scalar from 0 to 100. This property is available when XPercentileEVMOutputPort is true. The default is 95.

SymbolCountOutputPort

Symbol count output port

Symbol count output port, specified as a logical scalar. To output the number of accumulated symbols used to calculate the X-percentile EVM measurements, set this property to true. This property is available when XPercentileEVMOutputPort is true. The default is false.

Methods

resetReset states of EVM measurement object
stepMeasure error vector magnitude
Common to All System Objects
release

Allow System object property value changes

Examples

collapse all

Create an EVM object. Configure it using name-value pairs to output maximum EVM, 90th percentile EVM, and the symbol count.

evm = comm.EVM('MaximumEVMOutputPort',true,...
    'XPercentileEVMOutputPort',true, 'XPercentileValue',90,...
    'SymbolCountOutputPort',true);

Generate random data symbols. Apply 16-QAM modulation. The modulated signal serves as the reference for the subsequent EVM measurements.

data = randi([0 15],1000,1);
refSym = qammod(data,16,'UnitAveragePower',true);

Pass the modulated signal through an AWGN channel.

rxSym = awgn(refSym,20);

Measure the EVM of the noisy signal.

[rmsEVM,maxEVM,pctEVM,numSym] = evm(refSym,rxSym)
rmsEVM = 9.8775
maxEVM = 26.8385
pctEVM = 14.9750
numSym = 1000

Generate filtered QAM data and pass it through an AWGN channel. Compute the symbol error rate, and estimate the EVM of the received signal.

Create channel and filter System objects™.

M = 16;
refConst = qammod(0:M-1,M);
channel = comm.AWGNChannel('NoiseMethod','Signal to noise ratio (SNR)',...
    'SNR',15,'SignalPower',10);

txfilter = comm.RaisedCosineTransmitFilter('OutputSamplesPerSymbol',4);
rxfilter = comm.RaisedCosineReceiveFilter('InputSamplesPerSymbol',4, ...
    'DecimationFactor',4);

Create an EVM object to output RMS and maximum EVM measurements.

evm = comm.EVM('MaximumEVMOutputPort',true, ...
    'ReferenceSignalSource','Estimated from reference constellation', ...
    'ReferenceConstellation',refConst);

Create an error rate object and account for the signal delay through the transmit and receive filters. For a filter, the group delay is equal to 1/2 of the FilterSpanInSymbols property.

rxd = (txfilter.FilterSpanInSymbols + rxfilter.FilterSpanInSymbols)/2;
errorRate = comm.ErrorRate('ReceiveDelay',rxd);

Perform the following channel operations:

  • Generate random data symbols.

  • Apply 16-QAM modulation.

  • Filter the modulated data through a raised cosine Tx filter.

  • Pass the transmitted signal through an AWGN channel.

  • Filter the received data through a raised cosine Rx filter.

  • Demodulate the filtered data.

txData = randi([0 15],1000,1);
modData = qammod(txData,M);
txSig = txfilter(modData);
rxSig = channel(txSig);
filtSig = rxfilter(rxSig);
rxData = qamdemod(filtSig,M);

Calculate the error statistics and display the symbol error rate.

errStats = errorRate(txData,rxData);
symErrRate = errStats(1)
symErrRate = 0.0222

Measure and display the received RMS EVM and maximum EVM values. Take the filter delay into account by deleting the first rxd+1 symbols. Because there are symbol errors, the EVM may not be totally accurate.

[rmsEVM,maxEVM] = evm(filtSig(rxd+1:end))
rmsEVM = 17.2966
maxEVM = 40.1595

Generate random data symbols, and apply 8-PSK modulation.

d = randi([0 7],2000,1);
txSig = pskmod(d,8,pi/8);

Pass the modulated signal through an AWGN channel.

rxSig = awgn(txSig,30);

Create an EVM object. Measure the RMS EVM using the transmitted signal as the reference.

evm = comm.EVM;
rmsEVM1 = evm(txSig,rxSig);

Release the EVM object. Configure the object to estimate the EVM of the received signal against a reference constellation.

release(evm)
evm.ReferenceSignalSource = 'Estimated from reference constellation';
evm.ReferenceConstellation = pskmod(0:7,8,pi/8);

Measure the RMS EVM using only the received signal as an input. Verify that it matches the result obtained when using a reference signal.

rmsEVM2 = evm(rxSig);
[rmsEVM1 rmsEVM2]
ans = 1×2

    3.1524    3.1524

Measure the EVM of a noisy 8-PSK signal using two types of custom measurement intervals. Display the results.

Set the number of frames, M, and the number of subframes per frame, K.

M = 2;
K = 5;

Set the number of symbols in a subframe. Calculate the corresponding frame length.

sfLen = 100;
frmLen = K*sfLen
frmLen = 500

Create an EVM object. Configure the object to use a custom measurement interval equal to the frame length.

evm1 = comm.EVM('MeasurementIntervalSource','Custom', ...
    'MeasurementInterval',frmLen);

Configure the object to measure EVM using an 8-PSK reference constellation.

evm1.ReferenceSignalSource = 'Estimated from reference constellation';
evm1.ReferenceConstellation = pskmod(0:7,8,pi/8);

Create an EVM object, and configure it use a 500-symbol measurement interval with a periodic reset. Configure the object to measure EVM using an 8-PSK reference constellation.

evm2 = comm.EVM('MeasurementIntervalSource','Custom with periodic reset', ...
    'MeasurementInterval',frmLen);
evm2.ReferenceSignalSource = 'Estimated from reference constellation';
evm2.ReferenceConstellation = pskmod(0:7,8,pi/8);

Initialize the EVM and signal-to-noise arrays.

rmsEVM1 = zeros(K,M);
rmsEVM2 = zeros(K,M);
snrdB = zeros(K,M);

Measure the EVM for a noisy 8-PSK signal using both objects. The SNR increases by 1 dB from subframe to subframe. For evm1, the 500 most recent symbols are used to compute the estimate. In this case, a sliding window is used so that an entire frame of data is always processed. For evm2, the symbols are cleared each time a new frame is encountered.

for m = 1:M
    for k = 1:K
        data = randi([0 7],sfLen,1);
        txSig = pskmod(data,8,pi/8);
        snrdB(k,m) = k+(m-1)*K+7;
        rxSig = awgn(txSig,snrdB(k,m));
        rmsEVM1(k,m) = evm1(rxSig);
        rmsEVM2(k,m) = evm2(rxSig);
    end
end

Display the EVM measured using the two approaches. The windowing used in the first case provides an averaging across the subframes. In the second case, the EVM object resets after the first frame so that the calculated EVM values more accurately reflect the current SNR.

stairs(snrdB(:),[rmsEVM1(:) rmsEVM2(:)])
xlabel('SNR (dB)')
ylabel('EVM (%)')
legend('No Reset','Periodic Reset')

Create OFDM modulator and demodulator objects.

ofdmmod = comm.OFDMModulator('FFTLength',32,'NumSymbols',4);
ofdmdemod = comm.OFDMDemodulator('FFTLength',32,'NumSymbols',4);

Determine the number of subcarriers and symbols in the OFDM signal.

ofdmDims = info(ofdmmod);
numSC = ofdmDims.DataInputSize(1)
numSC = 21
numSym = ofdmDims.DataInputSize(2)
numSym = 4

Generate random symbols and apply QPSK modulation.

msg = randi([0 3],numSC,numSym);
modSig = pskmod(msg,4,pi/4);

OFDM modulate the QPSK signal. Pass the signal through an AWGN channel. Demodulate the noisy signal.

txSig = ofdmmod(modSig);
rxSig = awgn(txSig,10,'measured');
demodSig = ofdmdemod(rxSig);

Create an EVM object, where the result is averaged over the subcarriers. Measure the EVM. There are four entries corresponding to each of the 4 OFDM symbols.

evm = comm.EVM('AveragingDimensions',1);
rmsEVM = evm(demodSig,modSig)
rmsEVM = 1×4

   27.4354   23.6279   22.6772   23.1699

Overwrite the EVM object, where the result is averaged over the OFDM symbols. Measure the EVM. There are 21 entries corresponding to each of the 21 subcarriers.

evm = comm.EVM('AveragingDimensions',2);
rmsEVM = evm(demodSig,modSig)
rmsEVM = 21×1

   28.8225
   17.8536
   18.6809
   20.8872
   22.3532
   24.7197
   30.1954
   33.4899
   36.2847
   21.4230
      ⋮

Measure the EVM and average over both the subcarriers and the OFDM symbols.

evm = comm.EVM('AveragingDimensions',[1 2]);
rmsEVM = evm(demodSig,modSig)
rmsEVM = 24.2986

Calculate and plot the EVM of an OFDM signal. The signal consists of two packets separated by an interval.

Create System objects to:

  • OFDM modulate a signal

  • Introduce phase noise

  • Plot time-varying signals

ofdmmod = comm.OFDMModulator('FFTLength',256,'NumSymbols',2);

pnoise = comm.PhaseNoise('Level',-60,'FrequencyOffset',20,'SampleRate',1000);

tscope = dsp.TimeScope('YLabel','EVM (%)','YLimits',[0 40], ...
    'SampleRate',1000,'TimeSpan',1.2, ...
    'ShowGrid',true);

Create an EVM object. To generate a time-varying estimate of the EVM, set the AveragingDimensions property to 2.

evm = comm.EVM('MaximumEVMOutputPort',false, ...
    'ReferenceSignalSource','Input port', ...
    'AveragingDimensions',2);

Determine the input data dimensions of the OFDM modulator.

modDims = info(ofdmmod)
modDims = 

  struct with fields:

    DataInputSize: [245 2]
       OutputSize: [544 1]

Create QPSK-modulated random data for the first packet. Apply OFDM modulation.

data = randi([0 3],modDims.DataInputSize);
qpskSig = pskmod(data,4,pi/4);
txSig1 = ofdmmod(qpskSig);

Create a second data packet.

data = randi([0 3],modDims.DataInputSize);
qpskSig = pskmod(data,4,pi/4);
txSig2 = ofdmmod(qpskSig);

Concatenate the two packets and include an interval in which nothing is transmitted.

txSig = [txSig1; zeros(112,1); txSig2];

Apply I/Q amplitude and phase imbalance to the transmitted signal.

rxSigIQimb = iqimbal(txSig,2,5);

Apply phase noise.

rxSig = pnoise(rxSigIQimb);

Measure the EVM of the received signal, and plot its time-varying EVM.

e = evm(txSig,rxSig);
tscope(e)

Algorithms

Both the EVM block and the EVM object provide three normalization methods. You can normalize measurements according to the average power of the reference signal, average constellation power, or peak constellation power. Different industry standards follow one of these normalization methods.

The block or object calculates the RMS EVM value differently for each normalization method.

EVM Normalization MethodAlgorithm
Reference signal

EVMRMS=1Nk=1N(ek)1Nk=1N(Ik2+Qk2)*100

Average power

EVMRMS(%)=1001Nk=1N(ek)Pavg

Peak power

EVMRMS(%)=1001Nk=1N(ek)Pmax

Where:

  • ek = ek=(IkI˜k)2+(QkQ˜k)2

  • Ik = In-phase measurement of the kth symbol in the burst

  • Qk = Quadrature phase measurement of the kth symbol in the burst

  • N = Input vector length

  • Pavg = The value for Average constellation power

  • Pmax = The value for Peak constellation power

  • Ik and Qk represent ideal (reference) values. I˜k and Q˜k represent measured (received) symbols.

The max EVM is the maximum EVM value in a frame or EVMmax=maxk[1,...,N]{EVMk}, where k is the kth symbol in a burst of length N.

The definition for EVMk varies depending upon which normalization method you select for computing measurements. The block or object supports these algorithms.

EVM NormalizationAlgorithm
Reference signal

EVMk=ek1Nk=1N(Ik2+Qk2)*100

Average power

EVMk=100ekPavg

Peak power

EVMk=100ekPmax

The block or object computes the X-percentile EVM by creating a histogram of all the incoming EVMk values. The output provides the EVM value below which X% of the EVM values fall.

Extended Capabilities

Introduced in R2012a