Measure error vector magnitude
comm.EVM (error vector magnitude) System object™ measures
the modulator or demodulator performance of an impaired signal.
To measure error vector magnitude:
Starting in R2016b, instead of using the
to perform the operation defined by the System object, you can
call the object with arguments, as if it were a function. For example,
= step(obj,x) and
y = obj(x) perform
EVM = comm.EVM creates an error vector
EVM. This object measures the
amount of impairment in a modulated signal.
EVM = comm.EVM( creates
EVM object with each specified property set
to the specified value. You can specify additional name-value pair
arguments in any order as (
EVM = comm.EVM('ReferenceSignalSource','Estimated
from reference constellation') creates an object,
that measures the RMS EVM of a received signal by using a reference
Normalization method used in EVM calculation, specified as one
of the following:
Average constellation power
Average constellation power, specified in watts as a positive
real scalar. This property is available when
Peak constellation power
Peak constellation power, specified in watts as a positive real
scalar. This property is available when
Reference signal source
Reference signal source, specified as either
Reference constellation, specified as a vector. This property
is available when the
The default is
Measurement interval source
Measurement interval source, specified as one of the following:
Measurement interval over which the EVM is calculated, specified
in samples as a real positive integer. This property is available
Averaging dimensions over which to average the EVM measurements, specified as an integer or
row vector of integers with element values in the range [1, 3]. For example,
to average across the rows, set this property to
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 calls of the object. For example, if the input has size
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
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
X-percentile value below which X%
of the EVM measurements fall, specified as a real scalar from
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
|step||Measure error vector magnitude|
Measure EVM of Noisy 16-QAM Modulated Signal
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
Estimate Received EVM
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
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
Measure EVM Using Reference Constellation
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 EVM Using Custom Measurement Interval
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,
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')
Measure EVM Across Different Dimensions
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
Plot Time-Varying EVM for OFDM Signal
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 = timescope('YLabel','EVM (%)','YLimits',[0 40], ... 'SampleRate',1000,'TimeSpanSource','Property','TimeSpan',1.2, ... 'ShowGrid',true);
Create an EVM object. To generate a time-varying estimate of the EVM, set the
AveragingDimensions property to
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)
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 Method||Algorithm|
Ik is the in-phase measurement of the kth symbol in the burst
Qk is the quadrature phase measurement of the kth symbol in the burst
N is the input vector length
Pavg is the average constellation power
Pmax is the peak constellation power
Ik and Qk represent ideal (reference) values. and represent measured (received) symbols.
The max EVM is the maximum EVM value in a frame or 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.
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.
C/C++ Code Generation
Generate C and C++ code using MATLAB® Coder™.
Usage notes and limitations:
See System Objects in MATLAB Code Generation (MATLAB Coder).