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)
- 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
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';):
case B子载波间隔为30KHz,在10MHz的传输带宽情况下可以传输24RB。
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 相关
(1)配置发送和接收天线数
ntxants = 8; nrxants = 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;
(3)配置信噪比
SNRdB = 10;
(1)打印出所有SSB配置信息
disp(burst);
burstInfo = hSSBurstInfo(burst); disp(burstInfo);
[~,burstGrid] = hSSBurst(burst);
目的:OFDM资源网格被波束成形到一组物理传输天线上,SSB中的每个SS/PBCH块具有不同的波束成形向量,然后对波束成形的 OFDM 资源网格进行 OFDM 调制以给出时域波形。
(1)配置波束赋形的权重(简单的基于FFT的波束赋形和波束赋形权重)
W = fft(eye(ntxants)) / sqrt(ntxants);
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
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调制
发送的波形通过 TDL 传播信道模型,从而产生用于配置数量的天线的接收波形。
rxWaveform = channel(burstWaveform); % rxWaveform = burstWaveform;
rng('default');%产生伪随机数 % rxWaveform = awgn(rxWaveform,SNRdB,-10*log10(double(ofdmInfo.Nfft)));
下面开始正式开始介绍接收端流程,在讲解之前先附上两张图(SSB的帧结构&参考信号的具***置),这张图在我前面总结的文章也出现过。
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信号。
% 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 。
% 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)]);
%% 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;
% 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') '%']);
24bit来自高层广播信道(BCCH-BCH),包括23bit的MIB,在38.311中定义。(详细内容参考前面的文章(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)]);
%% 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方式进行同步信号的收发)
% Generate the CP and frame numerology for the 1ms subframe function info = nrNumerology(info,deltaf,slotduration)
% 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)等)