# Adding Fractional STO to an OFDM Signal using Frequency Domain Zero Padding

I have an OFDM system. I would like to introduce a fractional delay of (0.25 samples). Therefore:

1. I increase the sampling rate of the OFDM signal by a factor of 4 (via frequency domain zero padding (FDZP)).
2. and then I shift the signal by simply adding 1 zero at the beginning of the signal.
3. and then I downsample the signal by a factor of 4. So that the fractional delay will be (1/4 = 0.25)

However, I have noticed, that by doing this, after equalization and phase correction (due to this introduced timing offset), the EVM performance of high-frequency subcarriers is lower than low-frequency subcarriers, and I don't know the reason (see Figs. 2 & 3 & 4). Even before equalization, I can see that the constellation of high-frequency subcarriers suffers more noise compared with low-frequency subcarriers (see Figs. 5 & 6) To verify my code, at the receiver, I measured STO by observing the phase rotation of the received constellation, I can see that the STO is almost 0.25 samples for all subcarriers (except subcarrier -N/2 which is at the Nyquist frequency). (see Fig. 1).

I cannot understand why the EVM performance is subcarrier dependent. I expected all subcarriers to have the same EVM (should be low) as STO is less than the length of the cyclic prefix. Please help me to identify the problem. I suspect that this is caused by the oversampling method I used which is frequency-domain zero padding (FDZP), but I was told that FDZP does not introduce noise and all subcarriers should be equally effected. I would be very grateful if someone explains why EVM performance is subcarrier dependent. Here is my code, it is very simple

%% OFDM system with channel estimation:
clear all;clc;
%% define parameters
Nsymbol = 3000; %OFDM symbols to be simulated;
Nsc = 128; %length of OFDM symbols;
M = 16; %Constellation Order;
Ncp = 4; %Cyclic Prefix length;
Ncs = 4; %cyclic suffix;
Npilot = 100; %training sequence for equalization
%% data generation
Data=randi ([0 M-1],Nsc,Nsymbol+Npilot);
%% mapping
Tx_QAM=qammod(Data,M,'UnitAveragePower',true);
%% inverse discret Fourier transform (IFFT)
OFDM_Sig_no_cp=ifft(Tx_QAM);
%% Adding Cyclic Prefix & Suffix
OFDM_Sig_with_cp_cs=[OFDM_Sig_no_cp((Nsc-(Ncp)+1):end,:);OFDM_Sig_no_cp;OFDM_Sig_no_cp(1:Ncs,:)];
%% parallel to serail
OFDM_Sig=reshape(OFDM_Sig_with_cp_cs,1,(Nsymbol+Npilot)*(Nsc+Ncp+Ncs));
STO = 0.25;
osf = 4;
% Oversample the signal by a factor of osf by FDZP
L =  length(OFDM_Sig);
OFDM_Sig_f = fft(OFDM_Sig);
OFDM_Sig_f = [OFDM_Sig_f(1:L/2) zeros(1,(osf-1)*L) OFDM_Sig_f(L/2+1:end)];
OFDM_Sig_osf = osf*ifft(OFDM_Sig_f);
% apply STO
OFDM_Sig_osf_STO = circshift(OFDM_Sig_osf,STO*osf);
% downsample the signal
OFDM_Sig_STO = OFDM_Sig_osf_STO(1:osf:end);
%% serial to parallel
Rx_OFDM_Sig = reshape(OFDM_Sig_STO,Nsc+Ncp+Ncs,Nsymbol+Npilot);
Rx_OFDM_cp_removed = Rx_OFDM_Sig(Ncp+1:end,:); % remove cyclic prefix
Rx_OFDM_cs_removed = Rx_OFDM_cp_removed(1:end-Ncs,:); % remove cyclic suffix
%% Discret Fourier transform (FFT)
Rx_QAM = fft(Rx_OFDM_cs_removed);
%% LS channel estimation & Equalization
TxP = Tx_QAM(:,1:Npilot); % trnasmitted pilots
RxP = Rx_QAM(:,1:Npilot); % received pilots
Hpilot_LS = mean(RxP./TxP,2); % LS channel estimation
Rx_QAM = Rx_QAM(:,Npilot+1:end); % remove pilot sequence of the received signal
Tx_QAM = Tx_QAM(:,Npilot+1:end); % remove pilot sequence of the transmitted signal
Rx_QAM_EQ = (Rx_QAM)./repmat(Hpilot_LS,1,Nsymbol);
%% measure STO by estimating phase offset
Phase = mean((angle(Rx_QAM./Tx_QAM)),2);
SC_index = [0:Nsc/2-1 -Nsc/2:1:-1];
Phase2 = (Phase./2/pi*Nsc);
estimated_STO = -1*Phase2./SC_index.'; %this is the STO measured by observing the phase rotation due to STO
figure(1);plot(fftshift(SC_index), fftshift(estimated_STO),'linewidth',3)
grid on
xlabel('subcarrier index')
ylabel('Measured STO by observing phase rotation due to STO')
title('Fig.1')
%% measuring EVM
for cc = 1:Nsc
EVM = lteEVM(Rx_QAM_EQ(cc,:),Tx_QAM(cc,:));
EVM_per_SC_rms(cc) = EVM.RMS;
EVM_per_SC_dB(cc) = 20*log10(EVM_per_SC_rms(cc));
end
figure(2);plot(fftshift(SC_index), fftshift(EVM_per_SC_dB),'linewidth',3)
grid on
xlabel('subcarrier index')
ylabel('EVM (dB)')
title('Fig.2')
% SC0
figure(3);plot(Rx_QAM(1,:),'.')
title('Fig.3 Original Received Constellation of Subcarrier 0 (before Equalization)')
% SC0
figure(4);plot(Rx_QAM(64,:),'.')
title('Fig.4 Original Received Constellation of Subcarrier 63 (before Equalization)')
% SC0
figure(5);plot(Rx_QAM_EQ(1,:),'.')
title('Fig.5 Original Received Constellation of Subcarrier 0 (after Equalization)')
% SC0
figure(6);plot(Rx_QAM_EQ(64,:),'.')
title('Fig.6 Original Received Constellation of Subcarrier 63 (after Equalization)')


• I didn't read through your entire code processing but where do you do timing offset correction? Phase and Delay are not the same thing: phase is the rotation of the symbols while delay is a time offset; so I am suspecting that you may not have implemented yet an STO correction? (Or you have an issue with your correction approach?) May 10, 2022 at 12:12
• @DanBoschen, applied timing offset (STO = 0.25 samples) is less than the length of cyclic prefix, so it does not cause ISI or ICI. It just causes phase offset (rotation of the received constellation). My problem is that I see some noise (even before correcting the timing offset-induced phase offset) at high-frequency subcarriers as can be seen in Fig.4 compared with low-frequency subcarriers as shown in Fig.3 May 10, 2022 at 12:28
• that is a different phase rotation for every subcarrier (proportional to each subcarrier rather than a constant rotation for each). If you are doing that correction then you are correcting for STO. I suspect the issue may be in doing that- I suggest confirming your correction is a linear phase versus subcarrier index. For a 1/4 sample offset the phase will go linearly from 0 to pi/2 over each of the subcarriers May 10, 2022 at 13:42
• @DanBoschen I have double-checked, yes the phase rotation is linear and proportional to the subcarrier index, May 11, 2022 at 8:46
• It's convolved with a Dirichlet Kernel which is the aliased Sinc function but I don't see how it would treat any of the bins differently. What I am suspicious of if taking the FFT of the time domain sequence with the CP added which has now condensed that whole vector in the time domain into the frequency range given by the original waveform without CP in the frequency range (since there is no change of sampling rate or your used of time for the 1/4 sample delay). Can you try introducing your quarter sample delay using the original (frequency domain) waveform without CP? then add CP to that May 11, 2022 at 13:09