| Contents | Index |
| On this page… |
|---|
Communications System Toolbox software implements a variety of communications-related tasks. Many of the functions in the toolbox perform computations associated with a particular component of a communication system, such as a demodulator or equalizer. Other functions are designed for visualization or analysis.
While the later chapters of this document discuss various features in more depth, this section builds an example step-by-step to give you a first look at the Communications System Toolbox software. This section also shows how Communications System Toolbox functionalities build upon the computational and visualization tools in the underlying MATLAB environment.
This first example addresses the following problem:
Problem Process a binary data stream using a communication system that consists of a baseband modulator, channel, and demodulator. Compute the system's bit error rate (BER). Also, display the transmitted and received signals in a scatter plot. |
The following table indicates the key tasks in solving the problem, along with relevant Communications System Toolbox functions. The solution arbitrarily chooses baseband 16-QAM (quadrature amplitude modulation) as the modulation scheme and AWGN (additive white Gaussian noise) as the channel model.
| Task | Function or Method |
|---|---|
| Generate a random binary data stream | randi |
| Modulate using 16-QAM | modulate method on modem.qammod object |
| Add white Gaussian noise | awgn |
| Create a scatter plot | scatterplot |
| Demodulate using 16-QAM | modulate method on modem.qamdemod object |
| Compute the system's BER | biterr |
The discussion below describes each step in more detail, introducing MATLAB code along the way. To view all the code in one editor window, enter the following in the MATLAB Command Window.
edit commdoc_mod
1. Generate a Random Binary Data Stream. The conventional format for representing a signal in MATLAB is a vector or matrix. This example uses the randi function to create a column vector that lists the successive values of a binary data stream. The length of the binary data stream (that is, the number of rows in the column vector) is arbitrarily set to 30,000.
Note The sampling times associated with the bits do not appear explicitly, and MATLAB has no inherent notion of time. For the purpose of this example, knowing only the values in the data stream is enough to solve the problem. |
The code below also creates a stem plot of a portion of the data stream, showing the binary values. Your plot might look different because the example uses random numbers. Notice the use of the colon (:) operator in MATLAB to select a portion of the vector. For more information about this syntax, see The Colon Operator in the MATLAB documentation set.
%% Setup % Define parameters. M = 16; % Size of signal constellation k = log2(M); % Number of bits per symbol n = 3e4; % Number of bits to process nsamp = 1; % Oversampling rate hMod = comm.RectangularQAMModulator(M); % Create a 16-QAM modulator %% Signal Source % Create a binary data stream as a column vector. x = randi([0 1],n,1); % Random binary data stream % Plot first 40 bits in a stem plot. stem(x(1:40),'filled'); title('Random Bits'); xlabel('Bit Index'); ylabel('Binary Value');

2. Prepare to Modulate. The modem.qammod object implements an M-ary QAM modulator, M being 16 in this example. It is configured to receive integers between 0 and 15 rather than 4-tuples of bits. Therefore, you must preprocess the binary data stream x before using the modulate method of the object. In particular, you arrange each 4-tuple of values from x across a row of a matrix, using the reshape function in MATLAB, and then apply the bi2de function to convert each 4-tuple to a corresponding integer. (The .' characters after the reshape command form the unconjugated array transpose operator in MATLAB. For more information about this and the similar ' operator, see Reshaping a Matrix in the MATLAB documentation set.)
%% Bit-to-Symbol Mapping % Convert the bits in x into k-bit symbols. hBitToInt = comm.BitToInteger(k); xsym = step(hBitToInt,x); %% Stem Plot of Symbols % Plot first 10 symbols in a stem plot. figure; % Create new figure window. stem(xsym(1:10)); title('Random Symbols'); xlabel('Symbol Index'); ylabel('Integer Value');

3. Modulate Using 16-QAM. Having defined xsym as a column vector containing integers between 0 and 15, you can use the modulate method of the modem.qammod object to modulate xsym using the baseband representation. Recall that M is 16, the alphabet size.
%% Modulation y = modulate(modem.qammod(M),xsym); % Modulate using 16-QAM.
The result is a complex column vector whose values are in the 16-point QAM signal constellation. A later step in this example will show what the constellation looks like.
To learn more about modulation functions, see Digital Modulation. Also, note that the modulate method of the modem.qammod object does not apply any pulse shaping. To extend this example to use pulse shaping, see Pulse Shaping Using a Raised Cosine Filter. For an example that uses Gray coding with PSK modulation, see Gray Coded 8-PSK.
4. Add White Gaussian Noise. Applying the awgn function to the modulated signal adds white Gaussian noise to it. The ratio of bit energy to noise power spectral density, Eb/N0, is arbitrarily set at 10 dB.
The expression to convert this value to the corresponding signal-to-noise ratio (SNR) involves k, the number of bits per symbol (which is 4 for 16-QAM), and nsamp, the oversampling factor (which is 1 in this example). The factor k is used to convert Eb/N0 to an equivalent Es/N0, which is the ratio of symbol energy to noise power spectral density. The factor nsamp is used to convert Es/N0 in the symbol rate bandwidth to an SNR in the sampling bandwidth.
Note The definitions of ytx and yrx and the nsamp term in the definition of snr are not significant in this example so far, but will make it easier to extend the example later to use pulse shaping. |
%% Transmitted Signal ytx = y; %% Channel % Send signal over an AWGN channel. EbNo = 10; % In dB snr = EbNo + 10*log10(k) - 10*log10(nsamp); hChan = comm.AWGNChannel('NoiseMethod', 'Signal to noise ratio (SNR)', ... 'SNR',snr); hChan.SignalPower = (ytx' * ytx)/ length(ytx); ynoisy = step(hChan,ytx); %% Received Signal yrx = ynoisy;
To learn more about awgn and other channel functions, see Channel Modeling and RF Impairments.
5. Create a Scatter Plot. Applying the scatterplot function to the transmitted and received signals shows what the signal constellation looks like and how the noise distorts the signal. In the plot, the horizontal axis is the in-phase component of the signal and the vertical axis is the quadrature component. The code below also uses the title, legend, and axis functions in MATLAB to customize the plot.
%% Scatter Plot % Create scatter plot of noisy signal and transmitted % signal on the same axes. h = scatterplot(yrx(1:nsamp*5e3),nsamp,0,'g.'); hold on; scatterplot(ytx(1:5e3),1,0,'k*',h); title('Received Signal'); legend('Received Signal','Signal Constellation'); axis([-5 5 -5 5]); % Set axis ranges. hold off;

To learn more about scatterplot, see Scatter Plots.
6. Demodulate Using 16-QAM. Applying the demodulate method of the modem.qamdemod object to the received signal demodulates it. The result is a column vector containing integers between 0 and 15.
%% Demodulation % Demodulate signal using 16-QAM. zsym = demodulate(modem.qamdemod(M),yrx);
7. Convert the Integer-Valued Signal to a Binary Signal. The previous step produced zsym, a vector of integers. To obtain an equivalent binary signal, use the de2bi function to convert each integer to a corresponding binary 4-tuple along a row of a matrix. Then use the reshape function to arrange all the bits in a single column vector rather than a four-column matrix.
%% Symbol-to-Bit Mapping % Undo the bit-to-symbol mapping performed earlier. hIntToBit = comm.IntegerToBit(k); z = step(hIntToBit,zsym);
8. Compute the System's BER. Applying the biterr function to the original binary vector and to the binary vector from the demodulation step above yields the number of bit errors and the bit error rate.
%% BER Computation % Compare x and z to obtain the number of errors and % the bit error rate. hErrorCalc = comm.ErrorRate; berVec = step(hErrorCalc,x,z); bit_error_rate = berVec(1) number_of_errors = berVec(2)
The statistics appear in the MATLAB Command Window. Your results might vary because the example uses random numbers.
number_of_errors =
71
bit_error_rate =
0.0024
The example in the previous section created a scatter plot from the modulated signal. Although the plot showed the points in the QAM constellation, the plot did not indicate which integers between 0 and 15 the modulator mapped to a given constellation point. This section addresses the following problem:
Problem Plot a 16-QAM signal constellation with annotations that indicate the mapping from integers to constellation points. |
The solution uses the scatterplot function to create the plot and the text function in MATLAB to create the annotations.
To view a completed MATLAB file for this example, enter edit commdoc_const in the MATLAB Command Window.
1. Find All Points in the 16-QAM Signal Constellation. The Constellation property of the modem.qammod object contains all points in the 16-QAM signal constellation.
M = 16; % Number of points in constellation h=modem.qammod(M); % Modulator object mapping=h.SymbolMapping; % Symbol mapping vector pt = h.Constellation; % Vector of all points in constellation
2. Plot the Signal Constellation. The scatterplot function plots the points in pt.
% Plot the constellation.
scatterplot(pt);

3. Annotate the Plot to Indicate the Mapping. To annotate the plot to show the relationship between mapping and pt, use the text function to place a number in the plot beside each constellation point. The coordinates of the annotation are near the real and imaginary parts of the constellation point, but slightly offset to avoid overlap. The text of the annotation comes from the binary representation of mapping. (The dec2bin function in MATLAB produces a string of digit characters, while the de2bi function used in the last section produces a vector of numbers.)
% Include text annotations that number the points. text(real(pt)+0.1,imag(pt),dec2bin(mapping)); axis([-4 4 -4 4]); % Change axis so all labels fit in plot.
Binary-Coded 16-QAM Signal Constellation

In the plot above, notice that 0001 and 0010 correspond to adjacent constellation points on the left side of the diagram. Because these binary representations differ by two bits, the adjacency indicates that the modem.qammod object did not use a Gray-coded signal constellation. (That is, if it were a Gray-coded signal constellation, then the annotations for each pair of adjacent points would differ by one bit.)
By contrast, the constellation below is one example of a Gray-coded 16-QAM signal constellation.
Gray-Coded 16-QAM Signal Constellation

The only difference, compared to the previous example, is that you configure modem.qammod object to use a Gray-coded constellation.
%% Modified Plot, With Gray Coding M = 16; % Number of points in constellation h = modem.qammod('M',M,'SymbolOrder','Gray'); % Modulator object mapping = h.SymbolMapping; % Symbol mapping vector pt = h.Constellation; % Vector of all points in constellation scatterplot(pt); % Plot the constellation. % Include text annotations that number the points. text(real(pt)+0.1,imag(pt),dec2bin(mapping)); axis([-4 4 -4 4]); % Change axis so all labels fit in plot.%% Modified Plot, With Gray Coding M = 16; % Number of points in constellation h = modem.qammod('M',M,'SymbolOrder','Gray'); % Modulator object mapping = h.SymbolMapping; % Symbol mapping vector pt = h.Constellation; % Vector of all points in constellation scatterplot(pt); % Plot the constellation. % Include text annotations that number the points. text(real(pt)+0.1,imag(pt),dec2bin(mapping)); axis([-4 4 -4 4]); % Change axis so all labels fit in plot.
This section further extends the example by addressing the following problem:
Problem Modify the Gray-coded modulation example so that it uses a pair of square root raised cosine filters to perform pulse shaping and matched filtering at the transmitter and receiver, respectively. |
The solution uses the rcosine function to design the square root raised cosine filter and the rcosflt function to filter the signals. Alternatively, you can use the rcosflt function to perform both tasks in one command; see Design Raised Cosine Filters Using MATLAB or the rcosdemo demonstration for more details.
This solution modifies the code from commdoc_gray.m. To view the original code in an editor window, enter the following command in the MATLAB Command Window.
edit commdoc_gray
To view a completed MATLAB file for this example, enter edit commdoc_rrc in the MATLAB Command Window.
1. Define Filter-Related Parameters. In the Setup section of the example, replace the definition of the oversampling rate, nsamp, with the following.
nsamp = 4; % Oversampling rate
Also, define other key parameters related to the filter by inserting the following after the Modulation section of the example and before the Transmitted signal section.
%% Filter Definition % Define filter-related parameters. filtorder = 40; % Filter order delay = filtorder/(nsamp*2); % Group delay (# of input samples) rolloff = 0.25; % Rolloff factor of filter
2. Create a Square Root Raised Cosine Filter. To design the filter and plot its impulse response, insert the following commands after the commands you added in the previous step.
% Create a square root raised cosine filter. rrcfilter = rcosine(1,nsamp,'fir/sqrt',rolloff,delay); % Plot impulse response. figure; impz(rrcfilter,1);

3. Filter the Modulated Signal. To filter the modulated signal, replace the Transmitted Signal section with following.
%% Transmitted Signal % Upsample and apply square root raised cosine filter. ytx = rcosflt(y,1,nsamp,'filter',rrcfilter); % Create eye diagram for part of filtered signal. eyediagram(ytx(1:2000),nsamp*2);
The rcosflt command internally upsamples the modulated signal, y, by a factor of nsamp, pads the upsampled signal with zeros at the end to flush the filter at the end of the filtering operation, and then applies the filter.
The eyediagram command creates an eye diagram for part of the filtered noiseless signal. This diagram illustrates the effect of the pulse shaping. Note that the signal shows significant intersymbol interference (ISI) because the filter is a square root raised cosine filter, not a full raised cosine filter.

To learn more about eyediagram, see Eye Diagram Analysis.
4. Filter the Received Signal. To filter the received signal, replace the Received Signal section with the following.
%% Received Signal % Filter received signal using square root raised cosine filter. yrx = rcosflt(ynoisy,1,nsamp,'Fs/filter',rrcfilter); yrx = downsample(yrx,nsamp); % Downsample. yrx = yrx(2*delay+1:end-2*delay); % Account for delay.
These commands apply the same square root raised cosine filter that the transmitter used earlier, and then downsample the result by a factor of nsamp.
The last command removes the first 2*delay symbols and the last 2*delay symbols in the downsampled signal because they represent the cumulative delay of the two filtering operations. Now yrx, which is the input to the demodulator, and y, which is the output from the modulator, have the same vector size. In the part of the example that computes the bit error rate, it is important to compare two vectors that have the same size.
5. Adjust the Scatter Plot. For variety in this example, make the scatter plot show the received signal before and after the filtering operation. To do this, replace the Scatter Plot section of the example with the following.
%% Scatter Plot
% Create scatter plot of received signal before and
% after filtering.
h = scatterplot(sqrt(nsamp)*ynoisy(1:nsamp*5e3),nsamp,0,'g.');
hold on;
scatterplot(yrx(1:5e3),1,0,'kx',h);
title('Received Signal, Before and After Filtering');
legend('Before Filtering','After Filtering');
axis([-5 5 -5 5]); % Set axis ranges.
Notice that the first scatterplot command scales ynoisy by sqrt(nsamp) when plotting. This is because the filtering operation changes the signal's power.

This section further extends the example by addressing the following problem:
Problem Modify the previous example so that it includes convolutional coding and decoding, given the constraint lengths and generator polynomials of the convolutional code. |
The solution uses the convenc and vitdec functions to perform encoding and decoding, respectively. It also uses the poly2trellis function to define a trellis that represents a convolutional encoder. To learn more about these functions, see Convolutional Codes.
Enter commConvolutionalCodingPunctures at the MATLAB command line to a access a Punctured Convolutional Coding example.
This solution modifies the code from Pulse Shaping Using a Raised Cosine Filter. To view the original code in an editor window, enter the following command in the MATLAB Command Window.
edit commdoc_rrc
To view a completed MATLAB file for this example, enter edit commdoc_code in the MATLAB Command Window.
1. Increase the Number of Symbols. Convolutional coding at this value of EbNo reduces the BER markedly. As a result, accumulating enough errors to compute a reliable BER requires you to process more symbols. In the Setup section, replace the definition of the number of bits, n, with the following.
n = 5e5; % Number of bits to process
Note The larger number of bits in this example causes it to take a noticeably longer time to run compared to the examples in previous sections. |
2. Encode the Binary Data. To encode the binary data before mapping it to integers for modulation, insert the following after the Signal Source section of the example and before the Bit-to-Symbol Mapping section.
%% Encoder % Define a convolutional coding trellis and use it % to encode the binary data. t = poly2trellis([5 4],[23 35 0; 0 5 13]); % Trellis code = convenc(x,t); % Encode. coderate = 2/3;
The poly2trellis command defines the trellis that represents the convolutional code that convenc uses for encoding the binary vector, x. The two input arguments in the poly2trellis command indicate the constraint length and generator polynomials, respectively, of the code. A diagram showing this encoder is in Design a Rate-2/3 Feedforward Encoder Using MATLAB.
3. Apply the Bit-to-Symbol Mapping to the Encoded Signal. The bit-to-symbol mapping must apply to the encoded signal, code, not the original uncoded data. Replace the first definition of xsym (within the Bit-to-Symbol Mapping section) with the following.
% B. Do ordinary binary-to-decimal mapping. xsym = bi2de(reshape(code,k,length(code)/k).','left-msb');
Recall that k is 4, the number of bits per symbol in 16-QAM.
4. Account for Code Rate When Defining SNR. Converting from Eb/N0 to the signal-to-noise ratio requires you to account for the number of information bits per symbol. Previously, each symbol corresponded to k bits. Now, each symbol corresponds to k*coderate information bits. More concretely, three symbols correspond to 12 coded bits in 16-QAM, which correspond to 8 uncoded (information) bits, so the ratio of symbols to information bits is 8/3 = 4*(2/3) = k*coderate.
Therefore, change the definition of snr (within the Channel section) to the following.
snr = EbNo + 10*log10(k*coderate)-10*log10(nsamp);
5. Decode the Convolutional Code. To decode the convolutional code before computing the error rate, insert the following after the entire Symbol-to-Bit Mapping section and just before the BER Computation section.
%% Decoder % Decode the convolutional code. tb = 16; % Traceback length for decoding z = vitdec(z,t,tb,'cont','hard'); % Decode.
The syntax for the vitdec function instructs it to use hard decisions. The 'cont' argument instructs it to use a mode designed for maintaining continuity when you invoke the function repeatedly (as in a loop). Although this example does not use a loop, the 'cont' mode is used for the purpose of illustrating how to compensate for the delay in this decoding operation. The delay is discussed further in More About Delays.
6. Account for Delay When Computing BER. The continuous operation mode of the Viterbi decoder incurs a delay whose duration in bits equals the traceback length, tb, times the number of input streams to the encoder. For this rate 2/3 code, the encoder has two input streams, so the delay is 2*tb bits.
As a result, the first 2*tb bits in the decoded vector, z, are just zeros. When computing the bit error rate, you should ignore the first 2*tb bits in z and the last 2*tb bits in the original vector, x. If you do not compensate for the delay, then the BER computation is meaningless because it compares two vectors that do not truly correspond to each other.
Therefore, replace the BER Computation section with the following.
%% BER Computation % Compare x and z to obtain the number of errors and % the bit error rate. Take the decoding delay into account. decdelay = 2*tb; % Decoder delay, in bits [number_of_errors,bit_error_rate] = ... biterr(x(1:end-decdelay),z(decdelay+1:end))
The decoding operation in this example incurs a delay, which means that the output of the decoder lags the input. Timing information does not appear explicitly in the example, and the duration of the delay depends on the specific operations being performed. Delays occur in various communications-related operations, including convolutional decoding, convolutional interleaving/deinterleaving, equalization, and filtering. To find out the duration of the delay caused by specific functions or operations, refer to the specific documentation for those functions or operations. For example:
The vitdec reference page
![]() | Compute BER for a QAM System with AWGN and Phase Noise Using Simulink | System Objects | ![]() |

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-2012- The MathWorks, Inc. - Site Help - Patents - Trademarks - Privacy Policy - Preventing Piracy - RSS |