# Introduction to Custom OFDM

This example shows the design and verification of a transmitter and receiver for a custom OFDM communication system that is suitable for HDL code generation.

This example uses the resource grid from the Create Custom OFDM Resource Grid example and implements designs for a two-board point-to-point environment. The transmitter and receiver designs both have a MATLAB reference and a Simulink model. The MATLAB reference explores the design space and provides test vectors. The simulink model simulates the fixed-point and latency behavior and generates HDL code.

A block diagram of the transmitter design is shown.

A block diagram of the receiver design is shown.

This example is part of a related set of examples for custom OFDM communication systems. For more information see Custom OFDM Reference Applications Overview.

### Resource Grid Definition

The first stage of designing a custom OFDM communication system is to define the structure and contents of the resource grid. The resource grid is defined as a 2-D matrix in the frequency domain with number of subcarriers (`Nsc`

) rows and number of OFDM symbols (`NofdmSyms`

) columns. OFDM modulation converts this resource grid from the frequency domain to the time domain. The FFT size (`Nfft`

), subcarrier spacing (`scs`

), and the length of the cyclic-prefix (`Ncp`

) determine the symbol bandwidth and duration. The `Nfft`

and `Ncp`

values are in samples, and the `scs`

in kHz. For more information on OFDM see OFDM Modulation Using MATLAB.

The OFDM resource grid is populated by modulated symbols of a specified signal type on each resource element. A resource element is one subcarrier in one OFDM symbol. This allows for the design of custom communication systems where many different signal types are combined to satisfy the system requirements. This example includes the following three signal types. Any resource element without a specified signal type is filled with a null.

Synchronization Sequence - The synchronization sequence is created using a maximal length PN sequence that has good auto-correlation properties. It is placed in the first OFDM symbol of the resource grid to allow the receiver to perform synchronization before data reception.

Reference Symbols - The reference symbols are transmitted interspersed with the data symbols to allow the receiver to estimate and equalize the channel.

Data Symbols - The data symbols carry the information in the resource grid.

This code defines the OFDM resource grid. The example defines the overall grid structure, and then the indices for each signal type in the resource grid. Additionally, the synchronization sequence is generated from a maximal-length PN sequence.

%% Define OFDM Constants % Define OFDM Resource Grid Nfft = 256; % FFT size in samples Ncp = 64; % Cyclic-prefix length in samples Nsym = Nfft+Ncp; % Time domain OFDM symbol length in samples scs = 30; % Subcarrier spacing in kHz Nsc = 228; % Number of active subcarriers in the resource grid NofdmSyms = 240; % Number of OFDM symbols in the resource grid Nguard = (Nfft/2) - (Nsc/2); % Number of guard subcarriers in the resource grid ofdmSampleRate = scs*1e3*Nfft; % Time domain sample rate in Hz % Define OFDM Grid Signals % Synchronization Sequence % Generate constant synchonization sequence from maximum length sequence syncSeqGen = comm.PNSequence("Polynomial",[7 6 0],"InitialConditions",[1 1 0 1 1 0 1],"SamplesPerFrame",127); syncSeq = syncSeqGen(); gridOffset = floor((Nsc-length(syncSeq))/2); ssIdx = (1:length(syncSeq)).'+gridOffset; % Reference Symbols refSymSpacing = 4; refOFDMIdx = 2:refSymSpacing:NofdmSyms; refSCIdx = repmat((1:Nsc).',length(refOFDMIdx),1); refIdx = [refSCIdx reshape(repmat(refOFDMIdx,Nsc,1),[],1)]; refIdx = sub2ind([Nsc,NofdmSyms],refIdx(:,1),refIdx(:,2)); % Data Symbols dataOFDMIdx = setdiff(2:NofdmSyms,refOFDMIdx); dataSCIdx = repmat((1:Nsc).',length(dataOFDMIdx),1); dataIdx = [dataSCIdx reshape(repmat(dataOFDMIdx,Nsc,1),[],1)]; dataIdx = sub2ind([Nsc,NofdmSyms],dataIdx(:,1),dataIdx(:,2)); dataSymsPerFrame = length(dataOFDMIdx)*Nsc; bitsPerFrame = dataSymsPerFrame * 2;

### OFDM Transmitter MATLAB Reference

The OFDM transmitter performs two operations to generate OFDM frames. Each frame is one repetition of the resource grid. The frames are sent back-to-back to create a continuous transmission.

Resource grid construction - Creates an empty resource grid from the grid structure for each frame. Then, generates contents for each signal type and allocates them to the specified resource element. The synchronization sequence PN-sequence data is BPSK modulated. The reference symbols are generated using a gold sequence and QPSK modulated. The data payload for the frame is indexed from the transmitted bits and QPSK modulated. Symbol modulation uses the

`qammod`

function to map bits onto the constellation symbols.OFDM modulation - Converts the resource grid into a time domain waveform to transmit using the

`ofdmmod`

function. The resource grid is centered in the FFT by adding guard bands using the`nullIndices`

parameter. Windowing is performed on the transition between OFDM symbols to suppress the sidelobes of the transmitted waveform.

This code implements the OFDM transmitter. The code is a behavioral reference for the Simulink model.

%% OFDM Transmitter MATLAB numTxFrames = 1; % Generate data bits for all transmit frames txBits = randi([0 1],bitsPerFrame*numTxFrames,1); txGridML = zeros(Nsc,NofdmSyms*numTxFrames); for ii = 1:numTxFrames % Construct resource grid txFrameML = zeros(Nsc,NofdmSyms); % Synchronization Sequence - BPSK modulate, add to grid syncSyms = qammod(syncSeq,2); txFrameML(ssIdx,1) = syncSyms; % Reference Symbols - Generate sequence, QPSK modulate, add to grid goldSeq = comm.GoldSequence("FirstPolynomial",[31 3 0],"FirstInitialConditions",[zeros(30,1); 1], ... "SecondPolynomial",[31 3 2 1 0],"SecondInitialConditions",arrayfun(@(x) str2double(x),dec2bin(100,31)), ... "Shift",1600,SamplesPerFrame=length(refIdx)*2); refBits = goldSeq(); refSyms = qammod(refBits,4,[2 3 0 1],UnitAveragePower=1,InputType="bit"); txFrameML(refIdx) = refSyms; % Data Symbols - Extract payload for current frame, QPSK modulate, add to grid txFramePayload = txBits((ii-1)*bitsPerFrame + (1:bitsPerFrame)); dataSyms = qammod(txFramePayload,4,[2 3 0 1],UnitAveragePower=1,InputType="bit"); txFrameML(dataIdx) = dataSyms; txGridML(:,(ii-1)*NofdmSyms + (1:NofdmSyms)) = txFrameML; end % OFDM Modulate firstSC = Nguard + 1; nullIndices = [1:(firstSC-1) (firstSC+Nsc):Nfft].'; ofdmModML = ofdmmod(txGridML,Nfft,Ncp,nullIndices); % OFDM Symbol Windowing transmittedSyms = length(ofdmModML)/Nsym; unwindowed = reshape(ofdmModML,[],transmittedSyms); windowCoeffs = flipud(0.5*(1-sin(pi*(windowLength+1-2*(1:windowLength).')/(2*windowLength)))); windowedSuffixes = [zeros(windowLength,1), repmat(windowCoeffs, [1 transmittedSyms-1]) .* unwindowed(Ncp + (1:windowLength),1:end-1)]; windowedPrefixes = repmat(flipud(windowCoeffs), [1 transmittedSyms]) .* unwindowed(1:windowLength,:); txWaveformML = unwindowed; txWaveformML(1:windowLength,:) = windowedPrefixes + windowedSuffixes; txWaveformML = txWaveformML(:) * modScalingFactor; txWaveformMax = max(abs([real(txWaveformML(:)); imag(txWaveformML(:))])); if any(txWaveformMax >= 0.95) warning("Transmitted MATLAB waveform maximum value of " + num2str(txWaveformMax) + " exceeds expected maximum of 0.95, this can cause the fixed point implementation to overflow. Adjust the modScalingFactor."); end

### OFDM Transmitter Simulink

The OFDM transmitter algorithm is implemented in Simulink for HDL code generation. The algorithm is converted into a fixed-point streaming design with control signals. The top level of the model is shown.

The `OFDM Transmitter`

subsystem consists of three stages:

The

`Grid Structure`

subsystem creates the streaming control signals that construct the resource grid. The`isSyncSeq`

,`isRef`

and`isData`

ports specify when symbols for the synchronization sequence, reference or data signals are added to the streaming resource grid, respectively. Inside the`Grid Structure`

subsystem the`Frame Counter`

serializes the resource grid first in the subcarrier dimension, and then along the OFDM symbols and outputs the current subcarrier number and symbol number. The`Frame Counter`

also generates the valid signal required to pace the samples through the system. The`frameStart`

signal indicates the beginning of each frame. The`Frame Counter`

is paused when the`enable`

input port is zero. This signal controls the duty cycle of the transmitted signal. The`Frame Counter Subsystem`

drives the`Resource Element Type`

subsystem which implements logic to determine which resource grid element is placed in the resource grid.The

`Grid Contents`

subsystem creates the symbols for each resource grid element. Each subsystem uses the control signals from the`Grid Structure`

to generate the next symbol for the streaming resource grid. The subsystems are delay balanced and the signal types are multiplexed together to form the input to the OFDM modulator. For the synchronization sequence, a counter increments through a lookup table containing the bit sequence and a BPSK modulator converts the bits to symbols. For the reference symbols, a gold sequence generator block creates the bit sequence and a QPSK modulator converts the bits to symbols. For the data, a FIFO stores the transmit payload bits. This FIFO is loaded from outside the transmitter using a streaming interface with backpressure provided by the ready signal. The interface expects two bits per clock as a vector, this provides enough data to the QPSK modulator to meet throughput. The ready signal goes low when a full frame of data bits is stored. At the beginning of each frame if the ready signal is high then no data will be transmitted for the entire frame, and nulls will be inserted on the data resource elements. When the subsequent frame starts, if the ready is now low, data will be transmitted. By providing enough data to the input, continuous data transmission can be achieved.The

`OFDM Modulator`

block creates the time-domain transmitter waveform. It is parameterized by the resource grid definition and performs all stages of OFDM modulation and inter-symbol windowing. The OFDM modulator fixed-point wordlength grows by log2 of`Nfft`

between the input and the output. The output from the OFDM modulator is multiplied by a scaling factor and the reciprocal of the FFT size in the`OFDM Mod Scaling`

subsystem. The scaling factor is empirically selected through simulation so the final output is approximately within the range +/-0.8. this is a trade-off between using the full dynamic range of the fixed-point data types while leaving overhead for downstream processing when integrated into a target device.

When converting from frame-based MATLAB code to a streaming Simulink model, the pacing of data with control signals must be considered. This example uses a single Simulink rate to implement the whole algorithm - this rate represents the clock in the generated HDL code. The output from the transmitter will feed the digital-to-analog converter (DAC) when deployed on the target board, and the same clock may drive both components. Therefore, the transmitter must be capable of producing a valid output sample every clock cycle, after an initial latency. This constraint defines the valid behavior through the model.

The output `txValid`

signal from the transmitter is the output from the OFDM modulator. The OFDM modulator block is designed to meet this requirement with a constant valid output, if the input data is correctly paced. OFDM modulation increases the length of the output relative to the input by adding guard subcarriers and the cyclic-prefix to the signal. For an input length of `Nsc`

, the output length is `Nsc + Ncp + Nguard * 2`

. In a streaming design this means the output takes more cycles than the input. Therefore, a gap of `Ncp + Nguard * 2`

must be left between each input to allow for the OFDM modulator to finish outputting the previous OFDM symbol. If the input data stalls, the output valid will fall and the DAC will not receive data. Conversely, if the input data is provided too fast then the OFDM modulator will drop the data. Both of these outcomes result in data loss from the transmitter. The data pacing is handled by the `Frame Counter`

valid output, the valid is high for `Nsc`

cycles and then goes low for `Nsym`

- `Nsc`

cycles. This duty cycle ensures that the output from the transmitter will stay high. A timing diagram of the input and output from the OFDM modulator, with the corresponding valid signals, is shown.

### OFDM Receiver MATLAB Reference

The OFDM receiver performs four operations. Firstly, the receiver synchronizes the received waveform. Secondly, the synchronized waveform is OFDM demodulated to recover the resource grid. Thirdly, the grid reference symbols are used to estimate the channel and equalize the grid data symbols. Finally, the equalized symbols are symbol demodulated to recover the received bits.

Synchronization is performed to measure and correct for timing and frequency offsets. Timing offset estimation is achieved by correlation between the received time domain signal and the expected synchronization sequence. A timing correlation threshold is also computed by measuring the power of the signal over the same period as the correlation. This reduces the probability of false detections when the signal power is high. Additionally, a minimum threshold is applied to prevent false detections if the signal power is too low. Frequency offset estimation is achieved by the cyclic-prefix correlation method over one OFDM symbol. When the timing correlation crosses its threshold value a peak finder searches for the local maximum across a window of

`peakWindowLength`

samples to acquire the optimal timing point. The frequency offset measurement at the peak sample is used for the frequency correction. Therefore, the frequency estimation is the result of cyclic-prefix correlation across the symbol containing the synchronization sequence. In addition to the initial timing synchronization, sample slip tracking is performed after the initial synchronization and updates the timing offset each frame. This tracking allows for continuous reception under the effects of sample clock misalignment between the transmitter and the receiver. Frequency offset correction is applied to the time aligned received waveform before OFDM demodulation and is updated once per frame with the estimate from the latest synchronization sequence OFDM symbol. The`freqCorrectionEn`

variable enables the frequency offset correction, it is disabled by default to simplify comparison between the MATLAB reference and the Simulink implementation.OFDM demodulation uses the

`ofdmdemod`

function to convert the time and frequency corrected waveform to the received resource grid. A cyclic-prefix fraction of 0.5 is used to shift the FFT window so that is starts half way through the cyclic-prefix. This avoids the windowed edges of the OFDM symbols, and reduces inter-symbol interference with the non-ideal timing offset recovery.To estimate the channel the reference symbols are extracted from the received grid using frame structure definition. The expected reference symbols are recreated and a least-squares estimate is performed between the received reference symbols and the expected reference symbol. This estimates the channel at the location of each reference symbol. The channel estimates at these points are then interpolated to estimate the channel for all resource elements that contain data symbols. The reference symbol structure in this example fills one entire OFDM symbol, therefore no interpolation is required in frequency. Linear interpolation between the OFDM symbols containing reference symbols is performed between each pair of neighboring columns. The resource grid contains data symbols after the last column of reference symbols in the resource grid. For these OFDM symbols the channel estimate from the last reference symbol is repeated. The channel estimate is then applied to the received data symbols to perform phase-equalization. Magnitude equalization is not performed as the data symbols are QPSK.

Symbol demodulation uses the

`qamdemod`

function to perform hard-decision demodulation and recover the bits from the equalized resource grid.

This code implements the OFDM receiver. The code is a behavioral reference for the Simulink model.

%% OFDM Receiver MATLAB % Control applying frequency offset correction freqCorrectionEn = 0; % Input Scaling scaledWaveform = 0.875 * rxWaveform; % Timing Synchronization % Correlation ssCorrML = abs(filter(corrWeightsQ,1,scaledWaveform)).^2; % Threshold G = 10^(threshold_dB/10); energyFilt = ones(Nfft,1); energy = filter(energyFilt,1,abs(scaledWaveform).^2); thresholdML = G * energy; thresholdML(thresholdML<hardThreshold) = hardThreshold; % Determine where the threshold is exceeded thresholdExceededML = ssCorrML(ssCorrML > thresholdML); exceeds = ssCorrML > thresholdML; survivors = ssCorrML .* exceeds; exceedingIndices = find(exceeds); if isempty(exceedingIndices) error("No Synchrnonization sequence detected.") end % Frequency Synchronization sDelayed = [zeros(Nfft,1); scaledWaveform(1:end-Nfft)]; cpProduct = scaledWaveform .* conj(sDelayed); cpXCorr = filter(ones(Ncp,1),1,cpProduct); frameStartIndex = []; peakInfoML = []; triggerIndex = exceedingIndices(1); while (triggerIndex + peakWindowLength -1) <= length(survivors) [~,peakSubIndex] = max(survivors(triggerIndex:triggerIndex++peakWindowLength-1)); index = triggerIndex + peakSubIndex - 1; if exceeds(index) peak.Correlation = ssCorrML(index); peak.Energy = energy(index); startIndex = index - (Nsym - 1); if startIndex <= 0 error("Timing offset is before the start of the received waveform."); end frameStartIndex = [frameStartIndex startIndex]; %#ok<AGROW> peak.tOffset = mod(startIndex-1,Nsym*NofdmSyms); peak.fOffset = round(scs * 1e3 * angle(cpXCorr(index)) / (2*pi)); peakInfoML = [peakInfoML peak]; %#ok<AGROW> end % Move the resume index to the start of the next window triggerIndex = index + NofdmSyms * Nsym - floor(peakWindowLength/2); end samplesBetweenSync = diff(frameStartIndex); % Apply frequency offset with tracking if freqCorrectionEn fOffset = complex(zeros(size(scaledWaveform))); prevPhaseAccum = 0; for ii = 1:length(peakInfoML) sIdx = frameStartIndex(ii); if ii == length(peakInfoML) eIdx = length(fOffset); else eIdx = min(sIdx+samplesBetweenSync(ii)-1,length(fOffset)); end t = ((0:eIdx-sIdx) + (ii~=1)).'/ofdmSampleRate; phaseAccum = peakInfoML(ii).fOffset.*t + prevPhaseAccum; fOffset(sIdx:eIdx) = exp(-1i*2*pi*(phaseAccum)); prevPhaseAccum = phaseAccum(end); end frequencyCorrected = scaledWaveform .* fOffset; else frequencyCorrected = scaledWaveform; end % OFDM Demodulate maxNumOFDMSymsRec = floor((length(scaledWaveform)) / Nsym); numOFDMSymsRec = 0; firstSC = Nguard + 1; nullIndices = [1:(firstSC-1) (firstSC+Nsc):Nfft].'; rxGridML = zeros(Nsc,maxNumOFDMSymsRec); for ii = 1:length(peakInfoML) % Calculate the start and end index for this demodulation % One demodulation is performed per synchronization sequence detection to allow % for timing adjustments to be applied. sIdx = frameStartIndex(ii); % Maximum end index is the end of the waveform maxEIdx = floor((length(scaledWaveform) - sIdx + 1) / Nsym) * Nsym + sIdx - 1; if ii == length(peakInfoML) % Last detection so demodulate until the end eIdx = maxEIdx; else % Demodulate until the next detection eIdx = min(round(samplesBetweenSync(ii) / (Nsym * NofdmSyms)) * (Nsym * NofdmSyms) + sIdx - 1,maxEIdx); end ofdmDemodInML = frequencyCorrected(sIdx:eIdx); rxFrameML = ofdmdemod(ofdmDemodInML,Nfft,Ncp,Ncp*0.5,nullIndices); rxGridML(:,numOFDMSymsRec + (1:size(rxFrameML,2))) = rxFrameML; numOFDMSymsRec = numOFDMSymsRec + size(rxFrameML,2); end rxGridML = rxGridML(:,1:numOFDMSymsRec) / demodScalingFactor; rxWaveformMax = max(abs([real(rxGridML(:)); imag(rxGridML(:))])); if any(rxWaveformMax >= 0.95) warning("Received MATLAB grid maximum value of " + num2str(rxWaveformMax) + " exceeds expected maximum of 0.95, this can cause the fixed point implementation to overflow. Adjust the demodScalingFactor."); end numOFDMSymsRec = size(rxGridML,2); numRxFrames = floor(numOFDMSymsRec / NofdmSyms); rxDataSymsEqML_diag = zeros(dataSymsPerFrame*numRxFrames,1); rxBitsML = zeros(bitsPerFrame*numRxFrames,1); for ii = 1:numRxFrames rxFrameML = rxGridML(:,(ii-1)*NofdmSyms + (1:NofdmSyms)); % Channel Estimate rxRefSymsML = rxFrameML(refIdx); % Channel Estimate Generate Reference Symbols goldSeq = comm.GoldSequence("FirstPolynomial",[31 3 0],"FirstInitialConditions",[zeros(30,1); 1], ... "SecondPolynomial",[31 3 2 1 0],"SecondInitialConditions",arrayfun(@(x) str2double(x),dec2bin(100,31)), ... "Shift",1600,SamplesPerFrame=length(refIdx)*2); refBits = goldSeq(); refSyms = qammod(refBits,4,[2 3 0 1],UnitAveragePower=1,InputType="bit"); % Channel Estimate Least Squares hpML = rxRefSymsML(:)./refSyms(:); hpGridML = reshape(hpML,Nsc,[]); % Channel Estimate Time Interpolation hEstML = zeros(Nsc,length(dataOFDMIdx)); hEstPos = 0; for jj = 1:size(hpGridML,2) if jj ~= size(hpGridML,2) prevEst = hpGridML(:,jj); curEst = hpGridML(:,jj+1); estGap = refOFDMIdx(jj+1) - refOFDMIdx(jj); estDelta = (curEst-prevEst) / estGap; hEstML(:,hEstPos+(1:estGap-1)) = prevEst + estDelta * (1:estGap-1); hEstPos = hEstPos+estGap-1; else if jj == 1 % Only one reference OFDM symbol curEst = hpGridML; end hEstML(:,hEstPos + (1:NofdmReplSyms)) = repmat(curEst,1,NofdmReplSyms); end end % Channel Equalize rxDataSymsML = rxFrameML(dataIdx); rxDataSymsEqML = rxDataSymsML .* conj(hEstML(:)); % Store all the received symbols for diagnostics rxDataSymsEqML_diag((ii-1)*dataSymsPerFrame + (1:dataSymsPerFrame)) = rxDataSymsEqML; % QPSK Demod rxFramePayload = qamdemod(rxDataSymsEqML,4,[2 3 0 1],UnitAveragePower=1,OutputType="bit"); rxBitsML((ii-1)*bitsPerFrame + (1:bitsPerFrame)) = rxFramePayload; end

### OFDM Receiver Simulink

The OFDM receiver algorithm is implemented in Simulink for HDL code generation. The algorithm is converted into a fixed-point streaming design with control signals. The top level of the model is shown.

The `OFDM Receiver`

subsystem consists of five stages:

The

`Input Scaling`

subsystem scales the input signal by 0.875. This provides a small overhead in the fixed-point scaling for downstream operations, avoiding overflow, without growing the wordlength. The scaled signal is rounded to prevent the introduction of DC error, which can heavily distort an OFDM signal.The

`Synchronization`

subsystem performs the time and frequency synchronization algorithms. The time and frequency estimations are computed in parallel on the input data stream. The timing offset correlation is performed using an FIR filter. The frequency offset estimator performs the cyclic-prefix correlation and converts the result to a phase angle using CORDIC. The`Timing Offset`

and`Frequency Offset`

subsystems have different latencies. Their output signals and the received data must be realigned to allow the corrections to be applied. This is implemented using two stream synchronizer subsystems that use the valid signals and FIFOs to align the data and frequency estimation streams with the slower timing offset stream. The`Frequency Correction`

subsystem corrects the frequency offset using an NCO. The`strobe`

and`tDelta`

output signals indicate the start of an OFDM frame, and the timing offset difference relative to the previous frame respectively. For the initial synchronization`tDelta`

is zero. The`Synchronization`

subsystem provides diagnostic information for the correlation, threshold, timing offset and frequency offset of each peak on the`peakInfo`

port.The

`OFDM Demodulation`

subsystem uses the`OFDM Demodulator`

block to recover the OFDM resource grid from the time and frequency synchronized signal. A state machine applies the timing delta at the start of each frame. If the timing delta is positive (i.e. the timing is delayed from the previous frame) the input valid to the OFDM demodulator goes low to delay the demodulation of the next frame. If the timing delta is positive (i.e. the timing is advanced from the previous frame) then the cyclic-prefix length is shortened to advance the demodulation of the next frame. The OFDM demodulator grows the output wordlength by log2 of`Nfft`

. However, this full dynamic range is only required when the signal energy is concentrated in a small number of subcarriers. In practice, the system performance can be preserved by applying a scaling factor and reducing the wordlength by square route of the FFT size. The scaling factor is empirically selected through simulation so the final output is approximately within the range +/-0.8.The

`Channel Estimation and Equalization`

subsystem uses a least-squares channel estimator and phase-equalizer to equalize the received data symbols. The resource grid is streamed into the subsystem and the`Grid Structure`

subsystem performs the indexing operations to extract the data and reference streams. The reference streams are used by the`Channel Estimation`

subsystem to approximate the channel. The output from the`Channel Estimation`

subsystem is the channel estimate for each data symbol. The channel is not estimated in locations that do not contain data to be equalized. The estimated channel stream is then aligned with the data symbols and is used for equalization. The stream alignment is performed with a stream synchronizer that waits for data to be ready from both streams before outputting the aligned data. The fixed-point data types for the channel estimator are designed for the output from the OFDM demodulation scaling factor. With this constraint the output channel estimates are the same data type as the input. For the channel equalization the multiplication grows a single integer bit, and maintains the same wordlength by discarding a single fractional bit, to prevent overflow.The

`QPSK Demodulation`

subsystem converts the equalized received data symbols into hard decision bits by slicing the complex signal into real and imaginary parts and comparing to zero. The output stream is a vector of two bits per clock.

### Run OFDM Transmit and Receive

The example includes two scripts to perform the simulation.

The

`runIntroOFDMML`

script defines the OFDM resource grid structure, contents, and the design constants required by the transmitter and receiver. The script runs the transmitter MATLAB reference, distorts the transmit waveform with a wireless channel model, and then receives the distorted signal with the receiver MATLAB reference. By default, the wireless channel is implemented as a rician fading channel. Additionally, AWGN, frequency offset, and sample rate offset impairments can be optionally included. The received bits are verified against the transmitted bits and additional diagnostics are plotted to verify the overall system performance. The`runIntroOFDMML`

script simulation allows for design exploration in MATLAB.The

`runIntroOFDMSL`

script runs the Simulink simulations for the transmitter and receiver, using the resource grid structure, contents, and the design constants from`runIntroOFDMML`

. Signal tap points in the Simulink model are compared with MATLAB to verify the numerical equivalence of the two implementations. The received bits are verified against the transmitted bits.

The diagram shows the full simulation setup performed when both scripts are run back to back.

runIntroOFDMML;

MATLAB received bits match transmitted bits. Synchronization Results ML: Correlation Energy tOffset fOffset ___________ ______ _______ _______ 5.3822 5.4554 32 41

runIntroOFDMSL;

Running introOFDMTransmitter.slx .......... Running introOFDMReceiver.slx .................... Simulink received bits match transmitted bits. Synchronization Results SL: Correlation Energy tOffset fOffset ___________ ______ _______ _______ 5.3824 5.4557 32 41.143

### HDL Code Generation and Implementation Results

To generate the HDL code for this example, you must have the HDL Coder™ product. Use the `makehdl`

and `makehdltb`

commands to generate HDL code and an HDL test bench for the `introOFDMTransmitter/OFDM Transmitter`

and `introOFDMReceiver/OFDM Receiver`

subsystems.

The OFDM Receiver HDL code was generated with an oversample factor of 32 to share DSP resources within the synchronization sequence correlator. The oversample factor is calculated as the target clock rate (245.76e6) / algorithm sample rate (7.68e6).

The resulting HDL code was synthesized for a Xilinx® Zynq® UltraScale+ RFSoC ZCU111 evaluation board. The table shows the post place and route resource utilization results. The design meets timing with a clock frequency of 245.76 MHz.

Resource utilization:

Resource OFDM Transmitter OFDM Receiver _______________ ________________ _____________ Slice Registers 9221 15082 Slice LUTs 4418 9671 RAMB18 4 10 RAMB36 12 1 DSP48 18 65