End-to-End DVB-S2X Simulation with RF Impairments and Corrections in Wideband Mode
This example shows how to measure the bit error rate (BER) and packet error rate (PER) of a single stream Digital Video Broadcasting Satellite Second Generation extended (DVB-S2X) link that has constant coding and modulation for wideband mode using time slicing. The example describes the symbol timing, frame, and carrier synchronization strategies in detail, emphasizing on how to correct the RF front-end impairments under severe noise conditions. The single stream signal adds RF front-end impairments and then passes the waveform through an additive white Gaussian noise (AWGN) channel.
Introduction
Wideband mode is an optional transmission format in the DVB-S2/S2X standard for high symbol-rate satellite carriers for broadcasting, professional, and interactive services. This format adopts wideband satellite transponder (200–500 MHz) on a single frequency and uses the time slicing concept defined in the DVB-S2/S2X standard (ETSI EN 302 307-2 Annex M) [1].
Multiple services are time sliced at the transmitter in the form of physical layer (PL) frames, which are transmitted serially in time. Each service is provided as an independent input stream to the dvbs2xWaveformGenerator
System object® and the maximum number of streams possible is 8. Each service is identified by a time slicing number (TSN) transmitted as part of the PL header.
In time slicing receiver, the user selects and decodes a specific stream pertaining to the required service. Based on the TSN information in the header, the receiver decodes certain PL frames and discards others. Thus, FEC decoding speed is equivalent to that of a regular DVB-S2 application in the order of 100 or 200 Mbps. This approach significantly reduces the complexity of the receiving device and in turn creates the opportunity for new applications like high speed data links over the Ka band (26–40 GHz). The information about the relevant time slicing number is already known to the receiver.
This example designs the synchronization aspects of a DVB-S2X receiver using a time slicing receiver in wideband mode. The example supports all modulation schemes from QPSK to 256APSK. ETSI EN 302 307-2 Section 6 Table 20a and Table 20c [1] summarizes the Quasi-Error-Free (QEF) performance requirement over an AWGN channel for different modulation schemes and code rates. Very low signal to noise ratio (VL-SNR) physical layer signaling (PLS) codes are not supported.
In the example, 4 services are given as independent input streams to the dvbs2xWaveformGenerator
System object and the receiver recovers input data stream pertaining to service 2 to demonstrate the time slicing feature. This diagram summarizes the example workflow.
Main Processing Loop
The example processes five PL frames of data per service with the set to 15 dB, and then computes the BER and PER of the required service PL frames. Carrier frequency offset, frequency drift, sampling clock offset, and phase noise impairments are applied to the modulated signal, and AWGN is added to the signal.
At the receiver, after matched filtering, perform the timing and carrier recovery operations to recover the transmitted data. To select the PL frames of the required service, the PL header is decoded and depending on the TSN value, appropriate frames are selected for decoding. Along with the TSN, the physical layer transmission parameters, such as the modulation scheme, code rate, and FEC frame type, are recovered from the PL header to enable demodulation and decoding. To regenerate the input bit stream, decode the baseband (BB) header.
Because the DVB-S2X standard supports packetized and continuous modes of transmission, the BB frame can be either a concatenation of user packets or a stream of bits. The BB header is recovered to determine the mode of transmission. If the BB frame is a concatenation of user packets, the packet cyclic redundancy check (CRC) status of each packet is returned along with the decoded bits, and then the PER and BER are measured. If the BB frame is a stream of bits, only the decoded bits are returned, and then BER is measured.
These block diagrams show the synchronization and input bit recovery workflows.
Download DVB-S2X LDPC Parity Matrices Data Set
This example loads a MAT-file with DVB-S2X LDPC parity matrices. If the MAT-file is not available on the MATLAB® path, use these commands to download and unzip the MAT-file.
if ~exist('dvbs2xLDPCParityMatrices.mat','file') if ~exist('s2xLDPCParityMatrices.zip','file') url = 'https://ssd.mathworks.com/supportfiles/spc/satcom/DVB/s2xLDPCParityMatrices.zip'; websave('s2xLDPCParityMatrices.zip',url); unzip('s2xLDPCParityMatrices.zip'); end addpath('s2xLDPCParityMatrices'); end
DVB-S2X Configuration
Specify the cfgDVBS2X
structure to define DVB-S2X transmission configuration parameters. PLSDecimalCode
129 and 131 are not supported because they are used for generating VL-SNR frames. Only the regular frames are supported. Set HasTimeSlicing
to true
to enable time slicing operation.
cfgDVBS2X.StreamFormat = "TS"; cfgDVBS2X.HasTimeSlicing = true; cfgDVBS2X.NumInputStreams = 4; cfgDVBS2X.PLSDecimalCode = 143; % 8PSK 23/36 cfgDVBS2X.DFL = 41128; % Data field length in bits for % code rate 23/36 cfgDVBS2X.PLScramblingIndex = 0; cfgDVBS2X.RolloffFactor = 0.35; cfgDVBS2X.SamplesPerSymbol = 2;
Simulation Parameters
The DVB-S2X standard for a wideband transponder supports channel bandwidths from 200 to 500 MHz. The symbol rate is calculated as B/(1+R), where B is the channel bandwidth, and R is the transmit filter roll-off factor.
This table defines the phase noise mask (dBc/Hz) used to generate the phase noise that is applied to the transmitted signal. These noise masks are taken from ETSI EN 302 307-1 Annex M.3 [2].
The peak Doppler and frequency drift considered are typically expected from a low Earth orbit (LEO) satellite in motion.
simParams.serviceNumber = 2; % time slicing number to be processed simParams.sps = cfgDVBS2X.SamplesPerSymbol; % Samples per symbol simParams.numFrames = 5; % Number of frames to be processed simParams.chanBW = 200e6; % Channel bandwidth in Hertz rolloffFac = cfgDVBS2X.RolloffFactor; simParams.Fsymb = simParams.chanBW/(1 + rolloffFac); % Symbol rate in symbols/sec simParams.cfo = 0.02*simParams.Fsymb; % Carrier frequency offset in Hertz % due to oscillator instabilities simParams.dopplerRate = 3e4; % Doppler rate in Hertz/sec simParams.peakDoppler = 1e6; % Peak Doppler shift in Hertz simParams.sco = 10; % Sampling clock offset in parts % per million simParams.phNoiseLevel = "Level-1"; % Phase noise level simParams.EsNodB = 15 % Energy per symbol to noise ratio
simParams = struct with fields:
serviceNumber: 2
sps: 2
numFrames: 5
chanBW: 200000000
Fsymb: 1.4815e+08
cfo: 2.9630e+06
dopplerRate: 30000
peakDoppler: 1000000
sco: 10
phNoiseLevel: "Level-1"
EsNodB: 15
Generate DVB-S2X Wideband Waveform Distorted with RF Impairments
To create a DVB-S2X waveform, use the HelperDVBS2XWidebandRxInputGenerate
helper function with the simParams
and cfgDVBS2X
structures as inputs. The function returns the transmitted data bits, transmitted, and received waveforms, physical layer configuration parameters as a structure, and a receiver processing structure. The received waveform is impaired with carrier frequency, frequency drift, sampling clock offsets, and phase noise and then passed through an AWGN channel. The receiver processing parameters structure, rxParams
, includes the reference pilot fields, pilot indices, counters, and buffers. Plot the constellation of the received symbols and the spectrum of the transmitted and received waveforms.
[data,txOut,rxIn,phyConfig,rxParams] = HelperDVBS2XWidebandRxInputGenerate(cfgDVBS2X, ... simParams); % Display the physical layer configuration phyConfig
phyConfig = struct with fields:
FECFrame: {'normal' 'normal' 'normal' 'normal'}
ModulationScheme: {'8PSK' '8PSK' '8PSK' '8PSK'}
LDPCCodeIdentifier: {'23/36' '23/36' '23/36' '23/36'}
% Received signal constellation plot rxConst = comm.ConstellationDiagram(Title = "Received data", ... XLimits = [-1 1], YLimits = [-1 1], ... ShowReferenceConstellation = false, ... SamplesPerSymbol = simParams.sps); rxConst(rxIn(1:rxParams.plFrameSize*simParams.sps))
% Transmitted and received signal spectrum visualization Fsamp = simParams.Fsymb*simParams.sps; specAn = spectrumAnalyzer(SampleRate = Fsamp, ... ChannelNames = ["Transmitted waveform" "Received waveform"], ... ShowLegend = true); specAn([txOut,rxIn(1:length(txOut))]);
Configure Receiver Parameters
At the receiver, matched filtering is performed on the received data and is then followed by symbol timing synchronization, frame synchronization and carrier synchronization. The symbol timing estimator is non-data aided. The preferred loop bandwidth for symbol timing compensation depends on the setting.
The frame synchronization uses the PL header and two pilot blocks. plays a crucial role in determining the accuracy of the frame synchronization. The frame synchronization is performed on successive frames for accurate detection.
The coarse frequency error estimation is performed on the PL header. The fine frequency error estimation can estimate carrier frequency offsets up to 3% of the input symbol rate. The fine frequency estimation must process multiple pilot blocks for the residual carrier frequency offset to be reduced to levels acceptable for the phase estimation algorithm. The phase estimation algorithm can handle residual carrier frequency error up to 0.03% of the input symbol rate.
rxParams.symbSyncLoopBW = 1e-4; % Symbol timing synchronizer loop bandwidth % normalized by symbol rate rxParams.numFramesForFineFreqLock = 3; % Number of frames required for fine % frequency estimation % Create coarse frequency synchronization System object by using % HelperDVBS2XWidebandCoarseFrequencySynchronizer helper object freqSync = HelperDVBS2XWidebandCoarseFrequencySynchronizer(SampleRate = simParams.Fsymb); % Create frame synchronization System object by using % HelperDVBS2XWidebandFrameSynchronizer helper object frameSync = HelperDVBS2XWidebandFrameSynchronizer(... PLScramblingIndex = cfgDVBS2X.PLScramblingIndex); % Create symbol timing synchronization System object by using % comm.SymbolSynchronizer object symSync = comm.SymbolSynchronizer(TimingErrorDetector = "Gardner (non-data-aided)", ... NormalizedLoopBandwidth = rxParams.symbSyncLoopBW, DampingFactor = 1/sqrt(2)); % Create matched filter System object by using % comm.RaisedCosineReceiveFilter object decFac = simParams.sps/2; rxFilter = comm.RaisedCosineReceiveFilter( ... RolloffFactor = 0.35, ... InputSamplesPerSymbol = simParams.sps, DecimationFactor = decFac); b = rxFilter.coeffs; rxFilter.Gain = sum(b.Numerator); % Initialize error computing parameters [numFramesLost,pktsErr,bitsErr,pktsRec] = deal(0); % Initialize data indexing variables stIdx = 0; isLastFrame = false; symBuffer = []; plFrameSize = rxParams.plFrameSize; dataSize = rxParams.inputFrameSize; winLen = plFrameSize; rxParams.fineFreqCorrVal = zeros(rxParams.numFramesForFineFreqLock,1); pilotBlkLen = rxParams.pilotBlkLength;
Timing and Carrier Synchronization and Data Recovery
To synchronize the received data, select the appropriate stream (service) and recover the input data, process the distorted DVB-S2X waveform samples one frame at a time by following these steps.
Apply matched filtering, outputting at the rate of two samples per symbol.
Apply symbol timing synchronization using the Gardner timing error detector with an output generated at the symbol rate.
Apply frame synchronization to detect the start of frame.
Estimate and apply coarse frequency offset correction.
Estimate and apply fine frequency offset correction.
Estimate and compensate for residual carrier frequency and phase noise.
Demodulate and decode the PL header.
Select the PL frames corresponding to the required service based on TSN.
Demodulate and decode the PL frames.
Perform CRC check on the BB header, if the check passes, recover the header parameters.
Regenerate the input stream of data or packets from BB frames.
while stIdx < length(rxIn) % Use one DVB-S2X PL frame for each iteration. endIdx = stIdx + plFrameSize*simParams.sps; % In the last iteration, all the remaining samples in the received % waveform are used. isLastFrame = endIdx > length(rxIn); endIdx(isLastFrame) = length(rxIn); rxData = rxIn(stIdx+1:endIdx); % Retrieve the last frame samples. if isLastFrame resSampCnt = plFrameSize*rxParams.sps - length(rxData); % Inadequate number of samples to fill last frame syncIn = [rxData; zeros(resSampCnt,1)]; else syncIn = rxData; end % Perform matched filtering and downsample the signal to 2 samples per % symbol. filtOut = rxFilter(syncIn); % Apply symbol timing synchronization. symSyncOut = symSync(filtOut); % Apply frame synchronization syncIndex = frameSync(symSyncOut); rxParams.syncIndex = [rxParams.syncIndex;syncIndex]; if length(rxParams.syncIndex) > 1 % The PL frame start index lies somewhere in the middle of the data % being processed. From coarse frequency compensation onwards, the % processing happens as a PL frame. A buffer is used to store symbols % required to fill one PL frame. stIdx1 = rxParams.syncIndex(1); endIdx1 = winLen+rxParams.syncIndex(2); cfoIn = symBuffer(stIdx1:endIdx1-1); % Extract the number of pilots based on frame length numPilots = rxParams.possPilotBlks(rxParams.possFrameSizes == length(cfoIn)); % Apply coarse frequency synchronization. [coarseFreqSyncOut,cEstFreq] = freqSync(cfoIn); % Extract the pilot indices and PL scrambled pilots based on number % of pilots pilotInd = rxParams.pilotIndices(1:numPilots(1)); pilotVal = rxParams.pilotValues(1:numPilots(1)); numPilotBlks = numPilots(1)/pilotBlkLen; % Estimate the fine frequency error by using the HelperDVBS2FineFreqEst % helper function. corrVal = HelperDVBS2FineFreqEst(coarseFreqSyncOut(pilotInd),numPilotBlks, ... pilotVal,0,pilotBlkLen,rxParams.NumLags); % Use the correlation values calculated over pilot fields spanning over % multiple frames to calculate the fine frequency error estimate. % The estimation uses a sliding window technique. fineFreqEst = angle(sum([rxParams.fineFreqCorrVal;corrVal]))/(pi*(rxParams.NumLags)); ind = (rxParams.frameCount-2)*plFrameSize:(rxParams.frameCount-1)*plFrameSize-1; phErr = exp(-1j*2*pi*fineFreqEst*ind).'; freqCompOut = coarseFreqSyncOut.*phErr(:); phErrEst = HelperDVBS2PhaseEst(freqCompOut, ... pilotVal,0,pilotInd); phaseCompOut = HelperDVBS2PhaseCompensate(freqCompOut, ... phErrEst,pilotInd,0,2); % Decode the PL header by using the dvbsPLHeaderRecover function phyParams = dvbsPLHeaderRecover(phaseCompOut(1:180),Mode="DVB-S2X wideband"); plsDecCode = phyParams.PLSDecimalCode; timeSliceNum = phyParams.TimeSlicingNumber; % Validate the decoded PL header. if plsDecCode~=cfgDVBS2X.PLSDecimalCode fprintf("%s\n","PL header decoding failed. PLS code is incorrectly decoded") else if timeSliceNum == simParams.serviceNumber % Estimate noise variance by using % HelperDVBS2NoiseVarEstimate helper function. nVar = HelperDVBS2NoiseVarEstimate(phaseCompOut,pilotInd, ... pilotVal,rxParams.normFlag); % Recover the input bit stream by using the % dvbs2xBitRecover function. [decBitsTemp, isFrameLost, pktCRC] = dvbs2xBitRecover(phaseCompOut,nVar,Mode="wideband",... TimeSlicingNumber=timeSliceNum,PLScramblingIndex=cfgDVBS2X.PLScramblingIndex); decBits = decBitsTemp{:}; % Recover the input bit stream by using % HelperDVBS2StreamRecover helper function. if strcmpi(cfgDVBS2X.StreamFormat,"GS") && ~rxParams.UPL if ~isFrameLost && length(decBits) ~= dataSize(timeSliceNum) isFrameLost = true; end else if ~isFrameLost && length(decBits) ~= dataSize(timeSliceNum) isFrameLost = true; pktCRC = zeros(0,1,"logical"); end % Compute the PER for TS or GS packetized mode. % Number of packets in error based on packet CRC status pktsErr = pktsErr + numel(pktCRC{:}) - nnz(pktCRC{:}); % Number of packets recovered from the baseband frame pktsRec = pktsRec + numel(pktCRC{:}); end if ~isFrameLost ts = sprintf("%s","BB header decoding passed."); else ts = sprintf("%s","BB header decoding failed."); end % Compute the number of frames lost. CRC failure of the % baseband header is considered a frame loss. numFramesLost = isFrameLost + numFramesLost; frameIdx = ceil((rxParams.frameCount-1)/cfgDVBS2X.NumInputStreams); fprintf("%s(Number of frames lost = %1d, service %d, frame number = %d)\n",... ts,numFramesLost,timeSliceNum,frameIdx) % Compute the bits in error. if ~isFrameLost dataInd = (frameIdx-1)*dataSize(timeSliceNum)+1:frameIdx*dataSize(timeSliceNum); errs = nnz(data{timeSliceNum}(dataInd) ~= decBits); bitsErr = bitsErr + errs; end end end symBuffer = symBuffer(endIdx1+1-rxParams.syncIndex(2):end); winLen = length(symBuffer); rxParams.fineFreqCorrVal(1:end-1) = rxParams.fineFreqCorrVal(2:end); rxParams.fineFreqCorrVal(end) = corrVal; rxParams.syncIndex = rxParams.syncIndex(end); end symBuffer = [symBuffer;symSyncOut]; %#ok<AGROW> stIdx = endIdx; rxParams.frameCount = rxParams.frameCount + 1; end
BB header decoding passed.(Number of frames lost = 0, service 2, frame number = 1) BB header decoding passed.(Number of frames lost = 0, service 2, frame number = 2) BB header decoding passed.(Number of frames lost = 0, service 2, frame number = 3) BB header decoding passed.(Number of frames lost = 0, service 2, frame number = 4) BB header decoding passed.(Number of frames lost = 0, service 2, frame number = 5)
Visualization and Error Logs
Plot the constellation of the synchronized data and compute the BER and PER.
% Synchronized data constellation plot syncConst = comm.ConstellationDiagram(Title = "Synchronized data", ... XLimits = [-1.7 1.7], YLimits = [-1.7 1.7], ... ShowReferenceConstellation = false); syncConst(phaseCompOut)
% Error metrics display % For GS continuous streams if strcmpi(cfgDVBS2X.StreamFormat,"GS") && ~rxParams.UPL if (simParams.numFrames == numFramesLost) fprintf("All frames are lost. No bits are retrieved from BB frames.") else numFramesRec = simParams.numFrames - numFramesLost; ber = bitsErr/(numFramesRec*dataSize(timeSliceNum)); fprintf("BER : %1.2e\n",ber) end else % For GS and TS packetized streams if pktsRec == 0 fprintf("All frames are lost. No packets are retrieved from BB frames.") else if strcmpi(cfgDVBS2X.StreamFormat,"TS") pktLen = 1504; else pktLen = cfgDVBS2X.UPL; % UP length including sync byte end ber = bitsErr/(pktsRec*pktLen); per = pktsErr/pktsRec; fprintf("PER: %1.2e\n",per) fprintf("BER: %1.2e\n",ber) end end
PER: 0.00e+00
BER: 0.00e+00
Further Exploration
This section explains how to set some of the fields of rxParams
to make the example work for low SNR conditions.
Configure Symbol Timing Synchronization Parameters
Because the operating range of the DVB-S2X standard is very low, you must use small value for rxParams.symbSyncLoopBW
parameter for proper symbol synchronization. If the symbol timing loop does not converge, try decreasing the rxParams.symbSyncLoopBW
parameter. To achieve convergence of the timing loop, the ratio rxParams.symbSyncLoopBW/simParams.sps
must be greater than 1e-5.
Configure Carrier Synchronization Parameters
The HelperDVBS2PhaseEst
helper function can estimate the phase offset accurately only if the residual carrier frequency offset (CFO) is less than 0.0003 times the symbol rate. Use the second output argument cEstFreq
from the step
call of freqSync
and the fine frequency offset error estimate fineFreqEst
to calculate the overall CFO estimated.
% normCFOEst = cEstFreq/simParams.Fsymb + fineFreqEst; % actCFO = (simParams.cfo + simParams.peakDoppler)/simParams.Fsymb; % residualErr = abs(actCFO - normCFOEst);
Increase the rxParams.numFramesForFineFreqLock
value to improve the accuracy of the fine frequency error estimate if residualErr
is not less than the desired result.
Appendix
The example uses these helper functions:
HelperDVBS2XWidebandRxInputGenerate.m: Generate DVB-S2X waveform samples distorted with RF impairments and structure of parameters for receiver processing
HelperDVBS2PhaseNoise.m: Generate phase noise samples for different DVB-S2X phase noise masks and apply it to the input signal
HelperDopplerShift.m: Generate sinusoidal varying Doppler shift and apply it to input signal
HelperDVBS2XWidebandCoarseFrequencySynchronizer.m: Perform coarse frequency offset estimation and correction
HelperDVBS2XWidebandFrameSynchronizer.m: Perform frame synchronization and detect start of frame
HelperDVBS2FineFreqEst.m: Estimate fine frequency offset
HelperDVBS2PhaseEst.m: Estimate carrier phase offset
HelperDVBS2PhaseCompensate.m: Perform carrier phase compensation
HelperDVBS2NoiseVarEstimate.m: Estimate noise variance of received data
Bibliography
ETSI Standard EN 302 307-2 V1.1.1(2015-11). Digital Video Broadcasting (DVB); Second Generation Framing Structure, Channel Coding and Modulation Systems for Broadcasting, Interactive Services, News Gathering and other Broadband Satellite Applications; Part 2: DVB-S2 extensions (DVB-S2X).
ETSI Standard EN 302 307-1 V1.4.1(2014-11). Digital Video Broadcasting (DVB); Second Generation Framing Structure, Channel Coding and Modulation Systems for Broadcasting, Interactive Services, News Gathering and other Broadband Satellite Applications (DVB-S2).
ETSI Standard TR 102 376-1 V1.2.1(2015-11). Digital Video Broadcasting (DVB); Implementation Guidelines for the Second Generation System for Broadcasting, Interactive Services, News Gathering and other Broadband Satellite Applications (DVB-S2).
P. Kim and D. Oh, "Frame detection for DVB-S2 based time slice," The 18th IEEE International Symposium on Consumer Electronics (ISCE 2014), 2014, pp. 1-2, doi: 10.1109/ISCE.2014.6884410.
Casini, E., et al. “DVB-S2 Modem Algorithms Design and Performance over Typical Satellite Channels.” International Journal of Satellite Communications and Networking, vol. 22, no. 3, May 2004, pp. 281–318.
Michael Rice, Digital Communications: A Discrete-Time Approach. New York: Prentice Hall, 2008.