| Products & Services | Solutions | Academia | Support | User Community | Company |
| Download Product Updates | | | Get Pricing | | | Trial Software |
| Documentation → Communications Toolbox |
| Contents | Index |
| Learn more about Communications Toolbox |
| On this page… |
|---|
Equalizing Using a Training Sequence |
This section describes how to equalize a signal by using the equalize function to apply an adaptive equalizer object to the signal. The equalize function also updates the equalizer. This section assumes that you have already created an adaptive equalizer object, as described in Specifying an Adaptive Equalizer.
For examples that complement those in this section, see the Adaptive Equalization Simulation demo (part I and part II).
In typical applications, an equalizer begins by using a known sequence of transmitted symbols when adapting the equalizer weights. The known sequence, called a training sequence, enables the equalizer to gather information about the channel characteristics. After the equalizer finishes processing the training sequence, it adapts the equalizer weights in decision-directed mode using a detected version of the output signal. To use a training sequence when invoking the equalize function, include the symbols of the training sequence as an input vector.
Note As an exception, CMA equalizers do not use a training sequence. If an equalizer object is based on CMA, you should not include a training sequence as an input vector. |
The following code illustrates how to use equalize with a training sequence. The training sequence in this case is just the beginning of the transmitted message.
% Set up parameters and signals.
M = 4; % Alphabet size for modulation
msg = randint(1500,1,M); % Random message
modmsg = pskmod(msg,M); % Modulate using QPSK.
trainlen = 500; % Length of training sequence
chan = [.986; .845; .237; .123+.31i]; % Channel coefficients
filtmsg = filter(chan,1,modmsg); % Introduce channel distortion.
% Equalize the received signal.
eq1 = lineareq(8, lms(0.01)); % Create an equalizer object.
eq1.SigConst = pskmod([0:M-1],M); % Set signal constellation.
[symbolest,yd] = equalize(eq1,filtmsg,modmsg(1:trainlen)); % Equalize.
% Plot signals.
h = scatterplot(filtmsg,1,trainlen,'bx'); hold on;
scatterplot(symbolest,1,trainlen,'g.',h);
scatterplot(eq1.SigConst,1,0,'k*',h);
legend('Filtered signal','Equalized signal',...
'Ideal signal constellation');
hold off;
% Compute error rates with and without equalization.
demodmsg_noeq = pskdemod(filtmsg,M); % Demodulate unequalized signal.
demodmsg = pskdemod(yd,M); % Demodulate detected signal from equalizer.
[nnoeq,rnoeq] = symerr(demodmsg_noeq(trainlen+1:end),...
msg(trainlen+1:end));
[neq,req] = symerr(demodmsg(trainlen+1:end),...
msg(trainlen+1:end));
disp('Symbol error rates with and without equalizer:')
disp([req rnoeq])The example goes on to determine how many errors occur in trying to recover the modulated message with and without the equalizer. The symbol error rates, below, show that the equalizer improves the performance significantly.
Symbol error rates with and without equalizer:
0 0.3410
The example also creates a scatter plot that shows the signal before and after equalization, as well as the signal constellation for QPSK modulation. Notice on the plot that the points of the equalized signal are clustered more closely around the points of the signal constellation.

Decision-directed mode means the equalizer uses a detected version of its output signal when adapting the weights. Adaptive equalizers typically start with a training sequence (as mentioned in Equalizing Using a Training Sequence) and switch to decision-directed mode after exhausting all symbols in the training sequence. CMA equalizers are an exception, using neither training mode nor decision-directed mode. For non-CMA equalizers, the equalize function operates in decision-directed mode when one of these conditions is true:
The syntax does not include a training sequence.
The equalizer has exhausted all symbols in the training sequence and still has more input symbols to process.
The example in Equalizing Using a Training Sequence uses training mode when processing the first trainlen symbols of the input signal, and decision-directed mode thereafter. The example below discusses another scenario.
If you invoke equalize multiple times with the same equalizer object to equalize a series of signal vectors, you might use a training sequence the first time you call the function and omit the training sequence in subsequent calls. Each iteration of the equalize function after the first one operates completely in decision-directed mode. However, because the ResetBeforeFiltering property of the equalizer object is set to 0, the equalize function uses the existing state information in the equalizer object when starting each iteration's equalization operation. As a result, the training affects all equalization operations, not just the first.
The code below illustrates this approach. Notice that the first call to equalize uses a training sequence as an input argument, and the second call to equalize omits a training sequence.
M = 4; % Alphabet size for modulation msg = randint(1500,1,M); % Random message modmsg = pskmod(msg,M); % Modulate using QPSK. trainlen = 500; % Length of training sequence chan = [.986; .845; .237; .123+.31i]; % Channel coefficients filtmsg = filter(chan,1,modmsg); % Introduce channel distortion. % Set up equalizer. eqlms = lineareq(8, lms(0.01)); % Create an equalizer object. eqlms.SigConst = pskmod([0:M-1],M); % Set signal constellation. % Maintain continuity between calls to equalize. eqlms.ResetBeforeFiltering = 0; % Equalize the received signal, in pieces. % 1. Process the training sequence. s1 = equalize(eqlms,filtmsg(1:trainlen),modmsg(1:trainlen)); % 2. Process some of the data in decision-directed mode. s2 = equalize(eqlms,filtmsg(trainlen+1:800)); % 3. Process the rest of the data in decision-directed mode. s3 = equalize(eqlms,filtmsg(801:end)); s = [s1; s2; s3]; % Full output of equalizer
For proper equalization using adaptive algorithms other than CMA, you should set the reference tap so that it exceeds the delay, in symbols, between the transmitter's modulator output and the equalizer input. When this condition is satisfied, the total delay between the modulator output and the equalizer output is equal to
(RefTap-1)/nSampPerSym
symbols. Because the channel delay is typically unknown, a common practice is to set the reference tap to the center tap in a linear equalizer, or the center tap of the forward filter in a decision-feedback equalizer.
For CMA equalizers, the expression above does not apply because a CMA equalizer has no reference tap. If you need to know the delay, you can find it empirically after the equalizer weights have converged. Use the xcorr function to examine cross-correlations of the modulator output and the equalizer output.
Here are some typical ways to take a delay of D into account by padding or truncating data:
Pad your original data with D extra symbols at the end. Before comparing the original data with the received data, omit the first D symbols of the received data. In this approach, all the original data (not including the padding) is accounted for in the received data.
Before comparing the original data with the received data, omit the last D symbols of the original data and the first D symbols of the received data. In this approach, some of the original symbols are not accounted for in the received data.
The example below illustrates the latter approach. For an example that illustrates both approaches in the context of interleavers, see Delays of Convolutional Interleavers.
M = 2; % Use BPSK modulation for this example. msg = randint(1000,1,M); % Random data modmsg = pskmod(msg,M); % Modulate. trainlen = 100; % Length of training sequence trainsig = modmsg(1:trainlen); % Training sequence % Define an equalizer and equalize the received signal. eqlin = lineareq(3,normlms(.0005,.0001),pskmod(0:M-1,M)); eqlin.RefTap = 2; % Set reference tap of equalizer. [eqsig,detsym] = equalize(eqlin,modmsg,trainsig); % Equalize. detmsg = pskdemod(detsym,M); % Demodulate the detected signal. % Compensate for delay introduced by RefTap. D = (eqlin.RefTap -1)/eqlin.nSampPerSym; trunc_detmsg = detmsg(D+1:end); % Omit first D symbols of equalized data. trunc_msg = msg(1:end-D); % Omit last D symbols. % Compute bit error rate, ignoring training sequence. [numerrs,ber] = biterr(trunc_msg(trainlen+1:end),... trunc_detmsg(trainlen+1:end))
The output is below.
numerrs =
0
ber =
0
If your data is partitioned into a series of vectors (that you process within a loop, for example), you can invoke the equalize function multiple times, saving the equalizer's internal state information for use in a subsequent invocation. In particular, the final values of the WeightInputs and Weights properties in one equalization operation should be the initial values in the next equalization operation. This section gives an example, followed by more general procedures for equalizing within a loop.
The example below illustrates how to use equalize within a loop, varying the equalizer between iterations. Because the example is long, this discussion presents it in these steps:
If you want to equalize iteratively while potentially changing equalizers between iterations, see Changing the Equalizer Between Iterations for help generalizing from this example to other cases.
Initializing Variables. The beginning of the example defines parameters and creates three equalizer objects:
An RLS equalizer object.
An LMS equalizer object.
A variable, eq_current, that points to the equalizer object to use in the current iteration of the loop. Initially, this points to the RLS equalizer object. After the second iteration of the loop, eq_current is redefined to point to the LMS equalizer object.
% Set up parameters. M = 16; % Alphabet size for modulation sigconst = qammod(0:M-1,M); % Signal constellation for 16-QAM chan = [1 0.45 0.3+0.2i]; % Channel coefficients % Set up equalizers. eqrls = lineareq(6, rls(0.99,0.1)); % Create an RLS equalizer object. eqrls.SigConst = sigconst; % Set signal constellation. eqrls.ResetBeforeFiltering = 0; % Maintain continuity between iterations. eqlms = lineareq(6, lms(0.003)); % Create an LMS equalizer object. eqlms.SigConst = sigconst; % Set signal constellation. eqlms.ResetBeforeFiltering = 0; % Maintain continuity between iterations. eq_current = eqrls; % Point to RLS for first iteration.
Simulating the System Using a Loop. The next portion of the example is a loop that
Generates a signal to transmit and selects a portion to use as a training sequence in the first iteration of the loop
Introduces channel distortion
Equalizes the distorted signal using the chosen equalizer for this iteration, retaining the final state and weights for later use
Plots the distorted and equalized signals, for comparison
Switches to an LMS equalizer between the second and third iterations
% Main loop
for jj = 1:4
msg = randi([0 M-1],500,1); % Random message
modmsg = qammod(msg,M); % Modulate using 16-QAM.
% Set up training sequence for first iteration.
if jj == 1
ltr = 200; trainsig = modmsg(1:ltr);
else
% Use decision-directed mode after first iteration.
ltr = 0; trainsig = [];
end
% Introduce channel distortion.
filtmsg = filter(chan,1,modmsg);
% Equalize the received signal.
s = equalize(eq_current,filtmsg,trainsig);
% Plot signals.
h = scatterplot(filtmsg(ltr+1:end),1,0,'bx'); hold on;
scatterplot(s(ltr+1:end),1,0,'g.',h);
scatterplot(sigconst,1,0,'k*',h);
legend('Received signal','Equalized signal','Signal constellation');
title(['Iteration #' num2str(jj) ' (' eq_current.AlgType ')']);
hold off;
% Switch from RLS to LMS after second iteration.
if jj == 2
eqlms.WeightInputs = eq_current.WeightInputs; % Copy final inputs.
eqlms.Weights = eq_current.Weights; % Copy final weights.
eq_current = eqlms; % Make eq_current point to eqlms.
end
endThe example produces one scatter plot for each iteration, indicating the iteration number and the adaptive algorithm in the title. A sample plot is below. Your plot might look different because this example uses random numbers.

This section describes two procedures for equalizing within a loop. The first procedure uses the same equalizer in each iteration, and the second is useful if you want to change the equalizer between iterations.
Using the Same Equalizer in Each Iteration. The typical procedure for using equalize within a loop is as follows:
Before the loop starts, create the equalizer object that you want to use in the first iteration of the loop.
Set the equalizer object's ResetBeforeFiltering property to 0 to maintain continuity between successive invocations of equalize.
Inside the loop, invoke equalize using a syntax like one of these:
y = equalize(eqz,x,trainsig); y = equalize(eqz,x);
The equalize function updates the state and weights of the equalizer at the end of the current iteration. In the next iteration, the function continues from where it finished in the previous iteration because ResetBeforeFiltering is set to 0.
This procedure is similar to the one used in Example: Equalizing Multiple Times, Varying the Mode. That example uses equalize multiple times but not within a loop.
Changing the Equalizer Between Iterations. In some applications, you might want to modify the adaptive algorithm between iterations. For example, you might use a CMA equalizer for the first iteration and an LMS or RLS equalizer in subsequent iterations. The procedure below gives one way to accomplish this, roughly following the example in Example: Adaptive Equalization Within a Loop:
Before the loop starts, create the different kinds of equalizer objects that you want to use during various iterations of the loop.
For example, create one CMA equalizer object, eqcma, and one LMS equalizer object, eqlms.
For each equalizer object, set the ResetBeforeFiltering property to 0 to maintain continuity between successive invocations of equalize.
Create a variable eq_current that points to the equalizer object you want to use for the first iteration. Use = to establish the connection so that the two objects get updated together:
eq_current = eqcma; % Point to eqcma.
The purpose of eq_current is to represent the equalizer used in each iteration, where you can switch equalizers from one iteration to the next by using a command like eq_current = eqlms. The example illustrates this approach near the end of its loop.
Inside the loop, perform these steps:
Invoke equalize using a syntax like one of these:
y = equalize(eq_current,x,trainsig); y = equalize(eq_current,x);
Copy the values of the WeightInputs and Weights properties from eq_current to the equalizer object that you want to use for the next iteration. Use dot notation. For example,
eqlms.WeightInputs = eq_current.WeightInputs; eqlms.Weights = eq_current.Weights;
Redefine eq_current to point to the equalizer object that you want to use for the next iteration, using =. Now eq_current is set up for the next iteration, because it represents the new kind of equalizer but retains the old values for the state and weights.
The reason for creating multiple equalizer objects and then copying the state and weights, instead of simply changing the equalizer class or adaptive algorithm in a single equalizer object, is that the class and adaptive algorithm properties of an equalizer object are fixed.
![]() | Specifying an Adaptive Equalizer | Using MLSE Equalizers | ![]() |

Learn how to apply early verification to your development process through these technical resources.
How much time do you spend on testing to ensure implementation meets system-level requirements?
| © 1984-2010- The MathWorks, Inc. - Site Help - Patents - Trademarks - Privacy Policy - Preventing Piracy - RSS |