5G NR同步(3)——NR下行同步MATLAB仿真

__kindeditor_temp_url__写在前面:

  • 代码下载地址(matlab官方提供的代码,下面的代码有个人在学习过程中的注释,可以参考):
  • 在阅读本文前,推荐大家阅读我写的前几篇文章,或者参考其它关于同步的文献,尤其是刚接触同步。
  • 文章用matlab形式为大家展现5G NR下行同步,比C语言理解起来更方便。
  • 文章中插入的链接有的是国外的一些网站,建议大家使用***,***。
  • 文章比较长,大家仔细研究每一个过程,会收获很多!

文章主要分为两大部分讲解:

1. 整体流程讲解:

构建包含同步信号SSB突发集波形,将波形通过具有 AWGN 的衰落信道,然后盲同步到接收到的波形以解码主信息块 (MIB)。

2. 部分子函数讲解:

主要讲解代码中和协议相关的部分(选取重要部分讲解)


一:5G NR同步流程仿真

仿真主要流程图:

  • Burst generation:创建配置一个SSB突发集结构,以及创建一个OFDM时频资源网格。
  • Beam sweep:SS 突发的 OFDM 资源网格被波束成形到一组物理传输天线上,突发中的每个 SS/PBCH 块具有不同的波束成形矢量。
  • Propagation channel:传输的波形采用TDL传播通道模型(这里不想看没问题,不影响对整个同步流程的理解)。
  • AWGN:附加高斯白噪声应用于接收天线侧。
  • Receiver:接收各种同步和解调过程应用于的波形,以建立小区标识并解码主信息块(MIB)

接收端详细处理流程:

  • PSS search:主同步信号检测(自相关检测)。通过忙检测,即产生的模拟信号和接收的信号做自相关运算,由于M序列具有良好的自相关特性,可以通过检测峰值的大小确定出接收的M序列,进而可以确定出OFDM符号的起始位置,实现OFDM符号的时间同步和SSB块同步,解码出
  • OFDM demodulation:检测解调OFDM信号,得到OFDM信号的资源网格。
  • SSS search:辐同步信号检测(自相关检测),与PSS信号检测类似,通过忙检测,可以确定 ,此时可以获取小区ID( )。
  • PBCH DM-RS search:DM-RS有四个频域偏移,频偏的计算公式为: ,UE可以确定出SSB块的指示编号,即在信号生成一节中介绍的iSSB。当 时,可以得到完整iSSB的2 bit信息和半帧信息,实现半帧同步,但不能确定出无线帧的第一个半帧还是第二个半帧,也不可以确定出系统帧号;对于 ,可以得出iSSB的最低3个bit位,但半帧同步、无线帧的起始位置和系统帧号都不能确定。
  • channel estimation/noise estimation:信道估计和噪声估计,前面的文档没有整理关于信道估计的内容,可以参考下面的文档。



  • PBCH extraction:Extract physical broadcast channel (PBCH) symbols from a received grid and associated channel estimates in preparation for decoding a beamformed PBCH. 在接收的符号中提取PBCH。大家可以参考下面的文章(matlab 官方推出的 5G 工具,我们在代码块中会用到很多函数,用到哪个直接查阅也可以)。

  • PBCH equalization:信道均衡。为了提高衰落信道中的通信系统的传输性能而采取的一种抗衰落措施。它主要是为了消除或者是减弱宽带通信时的多径时延带来的码间串扰(ISI)问题(参考上面文章中的MMSE —— 一种作为均衡器的后处理算法)。
  • PBCH demod:解调PBCH。UE通过检测出DM-RS,进行信道估计,解码出PBCH。
  • BCH demod:获取MIB信息。(BCH——下行传输信道,PBCH——下行物理信道,对于协议栈的角度,PBCH位于物理层,BCH位于物理层和MAC层之间。这里做算法分析不需要过于纠结PBCH/BCH)
  • MIB:包含的信息:
    MIB主要包括系统帧号、半帧信息、iSSB的3个最高bit位(对于 )、SSB的子载波偏移 。对于 ,此时UE已经获得完整系统帧号,实现帧同步;对于 ,此时UE获得半帧信息和完整的系统帧号,实现了帧同步;对于 ,UE获得了完整的iSSB、半帧信息和完整的系统帧号,实现了半帧同步以及帧同步。根据确定出的 ,UE可以确定子载波0,即point A的位置,实现频率同步。另外, MIB中 还包括用于SIB1(System Information Block Type1)以及Msg2、Msg4传输的子载波间隔,6GHz以下使用15 kHz或30 kHz、6 GHz以上使用60 kHz或120 kHz) 。DM-RS Type A位置、pdcch-configSIB1(决定CORESET的RB数和OFDM符号数)、小区禁止指示、同频小区选择允许标志等信息,这些信息用于SIB1的接收。如果小区禁止指示是“是”,则UE不能驻留在该小区,否则UE可以驻留在该小区。(一定要看前面的几篇文章,不然初学者肯定不知道这些都是什么)

MATLAB仿真主程序:

在介绍之前,写几点我个人对于学习这部分的建议:

  • 移动通信系统这块一定要比较了解,大家可以参考中移写的这本书,虽然是4G的,但是还是很适合入门。
  • 一定要先把同步的原理看懂,多看几篇,尽量扣的细一些,可以参考我前面总结的几篇文章,关于5G NR的。
  • 代码中有些看不懂的部分可以使用matlab进行单步调试,通过数据和我们所学的原理进行比对,这样理解起来可能会比较快。
  • 当看完原理以后,大家可以采用分块学习,如下面的代码就是分解为13个小部分,大家可以参照下面的分块,一部分一部分的深入。
  • 大家也可以参考一下面的文章(NR Cell Search and MIB and SIB1 Recovery)

  1. SSB突发集配置
(1)SSB突发集结构
burst.BlockPattern = 'Case B';%选择模式B传输
burst.SSBPeriodicity = 20;%SSB实际发送周期可以为5ms、10ms或20ms,但不能大于20ms
burst.NFrame = 4;%5G NR的系统帧号(无线帧号){0-1023},默认为0。
burst.SSBTransmitted = [1 1 1 1 1 1 1 1];%SSB突发集中SSB最大的个数,上文提到的   ,此处SSB突发集中的个数为8。
burst.NCellID = 102;%小区ID,设置为102


(2) SSB突发集子载波配置(38.104)
gnb.SubcarrierSpacing = 30;%子载波间隔30KHz,我上传的代码这里写成15KHz,修改一下。
gnb.NRB = 24;%在传输带宽为10MHz时,可以传输24个RB,一个RB为12个子载波,其余带宽作为保护间隔。我上传的代码这里写成52,修改一下。
gnb.CyclicPrefix = 'Normal';%设置OFDM循环前缀的长度,15KHz为标准长度
carrierInfo = hOFDMInfo(gnb);%涉及到子程序的调用,与子载波相关的配置信息。
burst.SampleRate = carrierInfo.SamplingRate;%采样率 15.36M,这里其实如果各种琢磨,会比较难理解。根据上面的参数举例,10M/30KHz=333.33,所以采用512点FFT,采样率512×30KHz=15.36M。涉及到OFDM的相关知识,在下面放一个链接,讲解原理。
K = carrierInfo.NSubcarriers;%子载波数目=NRB * 12
burst.FrequencyPointA = -K/2 * gnb.SubcarrierSpacing * 1e3;%5G NR新定义的频域参考点。


注解:

①关于循环前缀的相关定义(gnb.CyclicPrefix = 'Normal';):


②采样率问题:


③RB(NRB)、PointA相关讲解以及NRB个数的定义

case B子载波间隔为30KHz,在10MHz的传输带宽情况下可以传输24RB。

(3)***B突发集中MIB相关内容
burst.DMRSTypeAPosition = 2;%标准中定义的dmrs-TypeA-Position,DM-RS第一个符号的位置(下行同步机制中有讲解DM-RS在一个SSB中的位置)
burst.PDCCHConfigSIB1 = 17;%参考38.213 - section13 - UE procedure for monitoring Type0-PDCCH CSS sets
burst.CellBarred = 0;%广播MIB的两种方式
burst.IntraFreqReselection = 0;%内部频率选择问题
burst.SubcarrierSpacingCommon = carrierInfo.SubcarrierSpacing;%子载波间隔
burst.DisplayBurst = true;%显示SSB


注解:

①关于DM-RS补充内容


②pdcch-ConfigSIB1补充(关于CORESET上文中未讲解,也可以找一本5G书籍看一看)


③CellBarred and IntraFreqReselection 相关




2. 信道配置(TDL信道+AWGN)

(1)配置发送和接收天线数

ntxants = 8; nrxants = 2;

(2)信道配置
velocity = 30.0;
fc = 4e9;
c = physconst('lightspeed');
fd = (velocity*1000/3600)/c*fc;%最大多普勒频移
channel = nrTDLChannel;%matlab输入 help nrTDLChannel 查看使用方法
channel.Seed = 24;
channel.DelayProfile = 'TDL-C';
channel.DelaySpread = 300e-9;
channel.MaximumDopplerShift = fd;
channel.MIMOCorrelation = 'Medium';
channel.Polarization = 'Cross-Polar';
channel.NumTransmitAntennas = ntxants;
channel.NumReceiveAntennas = nrxants;
以上均为配置TDL信道操作,不懂的函数直接在matlab中help即可。

(3)配置信噪比

SNRdB = 10;


3. SSB生成

(1)打印出所有SSB配置信息

disp(burst);

(2)创建并显示SSB(转换的过程)
burstInfo = hSSBurstInfo(burst); disp(burstInfo);

(3)创建SSB的资源网格
[~,burstGrid] = hSSBurst(burst);
注:hSSBurst函数用于创建SSB的资源网格


4. 波束扫描

目的:OFDM资源网格被波束成形到一组物理传输天线上,SSB中的每个SS/PBCH块具有不同的波束成形向量,然后对波束成形的 OFDM 资源网格进行 OFDM 调制以给出时域波形。

(1)配置波束赋形的权重(简单的基于FFT的波束赋形和波束赋形权重)

W = fft(eye(ntxants)) / sqrt(ntxants);

(2)把每个SSB的OFDM符号映射到波束
beamformedGrid = zeros([size(burstGrid) ntxants]);
blockSubcarriers = burstInfo.OccupiedSubcarriers;
for ssb = 1:length(burstInfo.SSBIndex)
    blockSymbols = burstInfo.OccupiedSymbols(ssb,:);
    block = burstGrid(blockSubcarriers,blockSymbols);
    Wssb = W(mod(ssb-1,ntxants)+1,:);
    beamformedBlock = reshape(block(:) * Wssb,[size(block) ntxants]);
    beamformedGrid(blockSubcarriers,blockSymbols,:) = beamformedBlock;
end

上面对应每个SSB的时频资源映射到子载波的过程,如下所示(将下图的时频资源一一映射):

(3)OFDM调制
beamformedGrid = beamformedGrid(:,1:max(burstInfo.OccupiedSymbols(:))+1,:);
ofdmConfig.SubcarrierSpacing = burstInfo.SubcarrierSpacing;%子载波间隔
ofdmConfig.NRB = burstInfo.NRB;%RB个数
ofdmConfig.CyclicPrefix = burstInfo.CyclicPrefix;%循环前缀的长度
ofdmConfig.Windowing = 0;
[burstWaveform,ofdmInfo] = hOFDMModulate(ofdmConfig,beamformedGrid);%进行OFDM调制


5. 传输信道

发送的波形通过 TDL 传播信道模型,从而产生用于配置数量的天线的接收波形。

rxWaveform = channel(burstWaveform); % rxWaveform = burstWaveform;


6. 加入高斯白噪声
rng('default');%产生伪随机数 % rxWaveform = awgn(rxWaveform,SNRdB,-10*log10(double(ofdmInfo.Nfft)));

下面开始正式开始介绍接收端流程,在讲解之前先附上两张图(SSB的帧结构&参考信号的具***置),这张图在我前面总结的文章也出现过。



7. 检测PSS信号
5G NR标准中定义三种PSS信号,在接收端,接受的信号分别与预先定义的三种PSS信号做自相关检测,并提取出峰值信息,得到PSS信号。
pssIndices = nrPSSIndices;%PSS信号的位置    第一个OFDM符号,所在的子载波范围为[57,183]
pssGrid = zeros([240 4]);%用于存放时域4个OFDM符号,频域上4×240个子载波
refGrid = zeros([ofdmInfo.NSubcarriers ofdmInfo.SymbolsPerSlot]);%每个时隙固定14个OFDM符号
k = burstInfo.OccupiedSubcarriers;
l = burstInfo.OccupiedSymbols(1,:);
figure;
hold on;
peak_value = zeros(1,3);
peak_index = zeros(1,3);
for NID2 = [0 1 2]%NID2三种形式
    pssRef = nrPSS(NID2);%help nrPSS 查看功能
    pssGrid(pssIndices) = pssRef;%生成的PSS信号放入pssGrid
    refGrid(k,l) = pssGrid;%放入SSB中PSS对应的位置
    refWaveform = hOFDMModulate(ofdmConfig,refGrid);%做OFDM调制
    refWaveform = refWaveform(refWaveform~=0);   
    corr = zeros(size(rxWaveform));
    for r = 1:size(rxWaveform,2)%做自相关运算
        antcorr = xcorr(rxWaveform(:,r),refWaveform);
        corr(:,r) = antcorr(size(rxWaveform,1):end);
    end
    corr = sum(abs(corr),2);%相加之后得到自相关运算的结果(这里可以了解一下matlab做自相关的原理)
    [peak_value(NID2+1),peak_index(NID2+1)] = max(corr)%找出三个本地的PSS信号分别与接收的信号做自相关的峰值
    plot(corr);
end
% Plot PSS correlations
axis([1 length(rxWaveform(:,1)) 0 max(peak_value)*1.1]);
title('PSS Correlations (time domain)');
ylabel('Magnitude');
xlabel('Sample Index');
% Determine NID2 by finding the strongest correlation
NID2 = find(peak_value==max(peak_value)) - 1;%找出NID2
%至此已经找出NID2。
% Determine timing offset(找出最大值处的peak_index)
offset = peak_index(NID2+1) - 1;
% Plot selected NID2
plot(offset+1,peak_value(NID2+1),'kx','LineWidth',2,'MarkerSize',8);
lgd = legend;
lgd.Interpreter = 'latex';
legends = "$N_{ID}^{(2)}$ = " + num2cell(0:2);
legend([legends "$N_{ID}^{(2)}$ = " + num2str(NID2)]);
% Extract strongest burst
offset = offset - ofdmInfo.SymbolLengths(1);%SymbolLengths=info.CyclicPrefixLengths + info.Nfft
rxGrid = hOFDMDemodulate(ofdmConfig,rxWaveform(1+offset:end,:));
rxGrid = rxGrid(burstInfo.OccupiedSubcarriers,2:5,:);%解调出PSS信号。
仿真图如下所示,仿真结果 ,与预期相符。


8. 检测SSS信号
上面的过程中检测出PSS信号(三次自相关检测即可),SSS信号有336种,可以看出小区ID共有336×3=1008种(实际在标准中设计的时候是先定小区个数的)。
% Extract the received SSS symbols from the SS/PBCH block
sssIndices = nrSSSIndices;%SSS信号在SSB中的索引
sssRx = nrExtractResources(sssIndices,rxGrid);%找出SSS信号  127×2
% Correlate received SSS symbols with each possible SSS sequence(检测SSS信号过程)
sssEst = zeros(1,336);
for NID1 = 0:335
    ncellid = (3*NID1) + NID2;
    sssRef = nrSSS(ncellid);
    sssEst(NID1+1) = sum(abs(mean(sssRx .* conj(sssRef),1)).^2);%在实际通信系统中也是这样检测的,336种NID2
end
% Plot SSS correlations
figure;
stem(0:335,sssEst,'o');
title('SSS Correlations (frequency domain)');
xlabel('$N_{ID}^{(1)}$','Interpreter','latex');
ylabel('Magnitude');
axis([-1 336 0 max(sssEst)*1.1]);
% Determine NID1 by finding the strongest correlation
NID1 = find(sssEst==max(sssEst)) - 1;
% Plot selected NID1
hold on;
plot(NID1,max(sssEst),'kx','LineWidth',2,'MarkerSize',8);
lgd = legend;
lgd.Interpreter = 'latex';
legend(["correlations" "$N_{ID}^{(1)}$ = " + num2str(NID1)]);
% Form overall cell identity from NID1 and NID2
ncellid = (3*NID1) + NID2;

仿真图:

检测SSS信号后得出ncellid 。



9. 在PBCH信道中提取DM-RS信号
检测DM-RS信号与检测SSS信号类似
% Extract the received PBCH DM-RS symbols from the SS/PBCH block
dmrsIndices = nrPBCHDMRSIndices(ncellid);%根据得到的小区ID来获取dmrsIndices 
%大家在单步调试查看dmrsIndices时,可以看到初始位置243(对应标准中的0+v, 4+v, ...)
[dmrsRx,dmrsRxIndices] = nrExtractResources(dmrsIndices,rxGrid);%提取出DM-RS信号和索引

% Correlate received DM-RS symbols with each possible DM-RS sequence
dmrsEst = zeros(1,8);
for ibar_SSB = 0:7
    dmrsRef = nrPBCHDMRS(ncellid,ibar_SSB);%nrPBCHDMRS生成标准中定义的所有DM-RS信号
    dmrsEst(ibar_SSB+1) = sum(abs(mean(dmrsRx .* conj(dmrsRef),1)).^2);%做相关检测的过程
    
end

% Plot PBCH DM-RS correlations
figure;
stem(0:7,dmrsEst,'o');
title('PBCH DM-RS Correlations (frequency domain)');
xlabel('$\overline{i}_{SSB}$','Interpreter','latex');
xticks(0:7);
ylabel('Magnitude');
axis([-1 8 0 max(dmrsEst)*1.1]);

% Record ibar_SSB for the strongest correlation
ibar_SSB = find(dmrsEst==max(dmrsEst)) - 1;%找出相关值最大的横坐标(索引)

% Plot selected ibar_SSB
hold on;
plot(ibar_SSB,max(dmrsEst),'kx','LineWidth',2,'MarkerSize',8);
lgd = legend;
lgd.Interpreter = 'latex';
legend(["correlations" "$\overline{i}_{SSB}$ = " + num2str(ibar_SSB)]);

仿真图如下:


10. 利用PBCH DM-RS进行信道估计
%% Channel Estimation using PBCH DM-RS
% Now that the PBCH DM-RS sequence is known, a channel estimate for the
% SS/PBCH block can be created by estimating the channel in each PBCH DM-RS
% resource element location and interpolating across the SS/PBCH block. An
% estimate of the additive noise on the PBCH DM-RS is also performed.

% Channel estimation, using linear interpolation of the PBCH DM-RS
dmrsRef = nrPBCHDMRS(ncellid,ibar_SSB);
dmrsSubs = double(nrPBCHDMRSIndices(ncellid,'IndexStyle','subscript'));
hest = zeros([240 4 nrxants 1]);
[l_hest,k_hest] = meshgrid(1:size(hest,2),1:size(hest,1));
dmrsEsts = dmrsRx .* conj(dmrsRef);
for r = 1:nrxants
    f = scatteredInterpolant(dmrsSubs(:,2),dmrsSubs(:,1),dmrsEsts(:,r));
    hest(:,:,r) = f(l_hest,k_hest);
end

% Noise estimation, based on the difference between the PBCH DM-RS in
% symbols 2 and 4 (1-based) of the SS/PBCH block. This technique assumes
% that the channel itself does not change between the two symbols
dmrsEstsSym2 = dmrsEsts(dmrsSubs(:,2)==2,:);
dmrsEstsSym4 = dmrsEsts(dmrsSubs(:,2)==4,:);
dmrsEstsSym2and4 = [dmrsEstsSym2(:) dmrsEstsSym4(:)];
dmrsNoise = mean(dmrsEstsSym2and4,2) - dmrsEstsSym2and4;
nest = var(dmrsNoise(:)) * 2;

对于信道估计和噪声估计,涉及的基础知识比较多,大家可以参考以下链接,再来看这部分代码:


11. PBCH解调
% Extract the received PBCH symbols from the SS/PBCH block
[pbchIndices,pbchIndicesInfo] = nrPBCHIndices(ncellid);%根据得到的小区ID来获取dmrsIndices pbchIndices&pbchIndicesInfo
pbchRx = nrExtractResources(pbchIndices,rxGrid);%根据pbchIndices,在接收的时频资源(一堆复数信号)中提取出PBCH信号

% Plot received PBCH constellation before equalization
figure;
plot(pbchRx,'o');
title('Received PBCH constellation');
m = max(abs([real(pbchRx(:)); imag(pbchRx(:))])) * 1.1;%取实部和虚部来画出星座图
axis([-m m -m m]);

% Configure 'v' for PBCH scrambling according to TS 38.211 Section 7.3.3.1
% 'v' is also the 2 LSBs of the SS/PBCH block index for L=4,&nbs***bsp;the 3 LSBs
% for L=8&nbs***bsp;64
%这部分时加扰PBCH加扰操作,解调过程中需要加扰相关信息,把标准中定义放在代码后。
if (burstInfo.L==4)
    v = mod(ibar_SSB,4);
else
    v = ibar_SSB;
end
ssbIndex = v;

% PBCH equalization and CSI calculation
pbchHest = nrExtractResources(pbchIndices,hest);
[pbchEq,csi] = nrEqualizeMMSE(pbchRx,pbchHest,nest);%这两步和上面相同
Qm = pbchIndicesInfo.G / pbchIndicesInfo.Gd;
csi = repmat(csi.',Qm,1);
csi = reshape(csi,[],1);

% Plot received PBCH constellation after equalization
%显示均衡之后的星座图
figure;
plot(pbchEq,'o');
title('Equalized PBCH constellation');
m = max(abs([real(pbchEq(:)); imag(pbchEq(:))])) * 1.1;
axis([-m m -m m]);

% PBCH demodulation
pbchBits = nrPBCHDecode(pbchEq,ncellid,v,nest);

% Calculate RMS PBCH EVM
pbchRef = nrPBCH(pbchBits<0,ncellid,v);
evm = comm.EVM;
evm_rms = evm(pbchEq,pbchRef);

% Display calculated EVM
disp(['RMS PBCH EVM = ' num2str(evm_rms,'%0.3f') '%']);


均衡前的星座图

均衡


12. 解码BCH

24bit来自高层广播信道(BCCH-BCH),包括23bit的MIB,在38.311中定义。(详细内容参考前面的文章(PBCH传输过程部分))

BCH传播的信息

PBCH传输过程(这里并不涉及具体流程,但有助于理解下面的代码)
%% BCH Decoding
% The BCH bit estimates are weighted with Channel State Information (CSI)
% from the MMSE equalizer then BCH decoding is performed, consisting of
% rate recovery, polar decoding, CRC decoding, descrambling and separating
% the 24 BCH transport block bits from the 8 additional timing-related
% payload bits.

% Apply CSI
pbchBits = pbchBits .* csi;

% Perform BCH decoding including rate recovery, polar decoding and CRC
% decoding. PBCH descrambling and separation of the BCH transport block
% bits 'trblk' from 8 additional payload bits A...A+7 is also performed:
%   A ... A+3: 4 LSBs of System Frame Number
%         A+4: half frame number
% A+5 ... A+7: for L=64, 3 MSBs of the SS/PBCH block index
%              for L=4&nbs***bsp;8, A+5 is the MSB of the subcarrier offset k_SSB
polarListLength = 8;
[~,err,trblk,sfn4lsb,nHalfFrame,msbidxoffset] = ...
    nrBCHDecode(pbchBits,polarListLength,burstInfo.L,ncellid);%可以成功解码BCH

% Use 'msbidxoffset' value to set bits of 'k_SSB'&nbs***bsp;'ssbIndex', depending
% on the number of SS/PBCH blocks in the burst
if (burstInfo.L==64)
    ssbIndex = ssbIndex + (bi2de(msbidxoffset.','left-msb') * 8);
    k_SSB = 0;
else
    k_SSB = msbidxoffset * 16;
end

% Display the BCH CRC
disp(['BCH CRC = ' num2str(err)]);

% Displaying the SSB index
disp(['SSB index = ' num2str(ssbIndex)]);


13. 获取MIB
下部分注释非常详细了,同时参考12节中23bit的MIB信息,在这里所有信息都可以获取。
%% MIB Parsing
% Finally the 24 decoded BCH transport block bits are parsed into a
% structure which represents the MIB message fields. This includes
% reconstituting the 10-bit System Frame Number (SFN) |NFrame| from the 6
% MSBs in the MIB and the 4 LSBs in the PBCH payload bits. It also includes
% incorporating the MSB of the subcarrier offset |k_SSB| from the PBCH
% payload bits in the case of L=4&nbs***bsp;8 SS/PBCH blocks per burst.

% Create set of subcarrier spacings signaled by the 7th bit of the decoded
% MIB, the set is different for FR1 (L=4&nbs***bsp;8) and FR2 (L=64)
if (burstInfo.L==64)
    commonSCSs = [60 120];
else
    commonSCSs = [15 30];
end

% Create a structure of MIB fields from the decoded MIB bits. The BCH
% transport block 'trblk' is the RRC message BCCH-BCH-Message, consisting
% of a leading 0 bit then 23 bits corresponding to the MIB
mib.NFrame = bi2de([trblk(2:7); sfn4lsb] .','left-msb');
mib.SubcarrierSpacingCommon = commonSCSs(trblk(8) + 1);
mib.k_SSB = k_SSB + bi2de(trblk(9:12).','left-msb');
mib.DMRSTypeAPosition = 2 + trblk(13);
mib.PDCCHConfigSIB1 = bi2de(trblk(14:21).','left-msb');
mib.CellBarred = trblk(22);
mib.IntraFreqReselection = trblk(23);

% Display the MIB structure
disp(mib);
以上是全部的主程序。


二:部分demo讲解

因为代码中的注释已经很详细,所以这部分不会展示出所有的代码,只讲解一些协议中定义的一些内容。

1. hSSBurstInfo.m(设定SSB相关的配置信息)

  • 子载波间隔的选取
%根据不同的模式选取不同的子载波间隔
function scs = getSSBSubcarrierSpacing(burst)

    if (strcmpi(burst.BlockPattern,'Case A'))
        scs = 15;
    elseif (any(strcmpi(burst.BlockPattern,{'Case B','Case C'})))
        scs = 30;
    elseif (strcmpi(burst.BlockPattern,'Case D'))
        scs = 120;
    elseif (strcmpi(burst.BlockPattern,'Case E'))
        scs = 240;
    end

end

  • 选取第一个OFDM符号的位置(对于SSB来讲)
function ssbStartSymbols = getStartSymbols(burst)

    % 'alln' gives the overall set of SS block indices 'n' described in 
    % TS 38.213 Section 4.1, from which a subset is used for each Case A-E

    %这里给出的是对应的n的数值,在协议里面最大范围的索引范围是0~18
    alln = [0; 1; 2; 3; 5; 6; 7; 8; 10; 11; 12; 13; 15; 16; 17; 18];
    
    %求解L的长度
    L = length(burst.SSBTransmitted);
    
    %case索引的范围
    cases = {'Case A' 'Case B' 'Case C' 'Case D' 'Case E'};
    %对应SSB索引的计算  A---14n B---28n  协议里面给出索引表格  一一对应
    m = [14 28 14 28 56];    
    i = {[2 8] [4 8 16 20] [2 8] [4 8 16 20] [8 12 16 20 32 36 40 44]};
    % n可选的取值
    nn = [2 1 2 16 8];      
    
    caseIdx = find(strcmpi(burst.BlockPattern,cases));
    if (any(caseIdx==[1 2 3]))
        if (L==4)
            nn = nn(caseIdx);
        elseif (L==8)
            nn = nn(caseIdx) * 2;       %标准中有定义
        else
            error('For %s, the SSBTransmitted bitmap must be of length 4&nbs***bsp;8.',cases{caseIdx});
        end
    else
        if (L==64)
            nn = nn(caseIdx);
        else
            error('For %s, the SSBTransmitted bitmap must be of length 64.',cases{caseIdx});
        end
    end
    
    n = alln(1:nn);         %一个列向量
    ssbStartSymbols = (i{caseIdx} + m(caseIdx)*n).';
    %输出第一个SSB所占用的四个符号的位置
    ssbStartSymbols = ssbStartSymbols(:).';
    
end

上面的两个函数参考下图:


2. hSSBurst.m(产生SSB突发集)

这里不做讲解,注释中的各个参数已经写的很清楚。


3. hOFDMInfo.m(采用MIMO方式进行同步信号的收发)

在一个1ms子帧中加入CP
% Generate the CP and frame numerology for the 1ms subframe
function info = nrNumerology(info,deltaf,slotduration)

这里涉及到蝶形运算级数的选择,多少点FFT对应经过多少级蝶形运算。
% lteOFDMInfo functionality (LTE baseline numerology with any NRB)
function info = lteNumerology(enb)

    % Valid the parameters
    if ~any(strcmpi(enb.CyclicPrefix,{'Extended', 'Normal'}))
        error('The cyclic prefix type must be one Normal&nbs***bsp;Extended');
    end
  
    % Get FFT size (allowing NRB > 110)
    nFFT = power(2,ceil(log2(enb.NRB*12/0.85)));
    nFFT = max(128,nFFT);
    
    info.SamplingRate = nFFT * 15e3;
    info.Nfft = nFFT;

    ecp = strcmpi(enb.CyclicPrefix,'Extended');
     
    % The number of window samples is chosen in accordance with the maximum
    % values implied by TS 36.101, Tables F.5.3-1, and F.5.4-1.
    if (isfield(enb,'Windowing'))
        w = enb.Windowing;
    else
        w = 0;
        if (ecp)
            switch (nFFT)
                case 128
                    w = 4;
                case 256
                    w = 6;
                case 512
                    w = 4;
                case 1024
                    w = 6;
                case 2048
                    w = 8;
            end
        else
            switch (nFFT)
                case 128
                    w = 4;
                case 256
                    w = 6;
                case 512
                    w = 4;
                case 1024
                    w = 6;
                case 2048
                    w = 8;
            end
        end
        if w==0
            % Additional rule for other FFT sizes
            w = max(0,8-2*(11-(log2(nFFT))));  
        end
    end    
    info.Windowing = w;
      
    % CP lengths for 2048 point FFT per LTE slot (6&nbs***bsp;7 symbols)
    if ecp
        cpLengths = [512 512 512 512 512 512];
    else
        cpLengths = [160 144 144 144 144 144 144];
    end
    
    % Scale according to the FFT size and repeat the slots for a LTE subframe
    info.CyclicPrefixLengths = repmat(cpLengths*double(nFFT)/2048,1,2);
    
end


4. hOFDMModulate.m&hOFDMDemodulate.m(调制和解调部分)

这两个部分我是直接用的,没有细看。

上面的3和4不涉及同步的内容,不过能弄明白最好。

以上就是所有的关于下行同步的仿真,



At the end of the article

在后面,我会陆续更新5G NR物理层传输流程相关内容,物理层相关的问题欢迎大家一起讨论!

主要讲解下图中的基带部分(CRC、LDPC、Polar、加扰、调制(BPSK、QPSK、基于FFT/IFFT的nQAM)等)


以上阐述的内容有问题可以评论或私信我,欢迎交流~ 本文原发于5G NR同步(3)——NR下行同步MATLAB仿真 - 知乎 (zhihu.com)
全部评论
想问一下hofdm中的nfft参数是一个Tu内的采样点数吗
点赞 回复 分享
发布于 2022-09-22 19:34 重庆
大佬,代码链接失效了啊能不能再传一次
点赞 回复 分享
发布于 2024-01-11 20:55 重庆

相关推荐

EEbond:看薪水就好了,还用问牛油吗
点赞 评论 收藏
分享
评论
2
10
分享

创作者周榜

更多
牛客网
牛客企业服务