NR HDL Downlink Receiver MATLAB Reference
This example shows how to model a 5G NR cell search, MIB and SIB1 recovery hardware algorithm in MATLAB® as a step towards developing a Simulink® HDL implementation of a downlink receiver.
This MATLAB code serves as a reference to verify the Simulink models of the hardware implementations in the NR HDL Cell Search, NR HDL MIB Recovery, NR HDL SIB1 Recovery, and NR HDL SIB1 Recovery for FR2 examples.
The NR HDL Downlink Receiver MATLAB Reference example bridges the gap between a mathematical algorithm and its hardware implementation by providing a MATLAB model of the algorithms that are implemented in hardware. The MATLAB reference is created to evaluate hardware-friendly algorithms and generate test vectors for verifying the Simulink fixed-point HDL optimized implementation. This example is one of a related set, for more information see NR HDL Reference Applications Overview.
Downlink Receiver Overview
A block diagram of the Downlink Receiver algorithm is shown. The algorithm detects, demodulates, and decodes 5G NR synchronization signal blocks (SSBs) and recovers SIB1. It is a hardware-friendly version of the corresponding steps in the NR Cell Search and MIB and SIB1 Recovery (5G Toolbox) example. At the top level, the algorithm consists of a Search Controller, an SSB Detector, an SSB Decoder, SIB1 grid demodulator and SIB1 decoder. This example explains each of these blocks in more detail and demonstrates the corresponding MATLAB reference functions, which are used to explore algorithms for hardware implementation and to verify the streaming fixed-point Simulink models. This example focuses on 5G NR frequency range 1 (FR1). See NR HDL SIB1 Recovery for FR2 for an example of how to use the MATLAB reference for FR2 SIB1 Recovery.
Cell search consists of carrier frequency recovery, primary synchronization signal (PSS) search, OFDM demodulation, and secondary synchronization signal (SSS) search. The Search Controller and the SSB Detector work together to perform these processing steps. The SSB Detector performs all of the high-speed signal processing tasks, making it well suited for FPGA or ASIC implementation. The Search Controller coordinates the search and operates at a low rate, making it well suited for software implementation on an embedded processor.
The algorithm starts by using the PSS to search for SSBs with subcarrier spacings of 15 kHz and 30 kHz across a range of coarse frequency offsets. The subcarrier spacing and coarse frequency offset search ranges are configurable. If SSBs are detected, the receiver OFDM demodulates the resource grid of the SSB with the strongest PSS and determines its cell ID using the SSS. The residual fine frequency offset is corrected during the OFDM demodulation phase.
SSB Detector: Searches for and OFDM-demodulates SSBs at a given carrier frequency offset and subcarrier spacing and measures the residual fine carrier frequency offset.
Digital Down Converter (DDC): Performs frequency translation to correct frequency offsets in the received waveform and then decimates the signal from 61.44 Msps to 7.68 Msps.
PSS search: Searches for PSS symbols within the waveform.
OFDM demodulation: OFDM-demodulates an SSB resource grid.
SSS search: Searches for SSS and determines the overall cell ID.
Search Controller: Coordinates the cell search by directing the SSB Detector to search for PSS symbols at different coarse frequency offsets and subcarrier spacings and to demodulate the SSB with the strongest PSS.
In the MATLAB reference, the
nrhdlexamples.cellSearch function implements the cell search algorithm. This function implements the Search Controller shown in the diagram, and calls the
nrhdlexamples.ssbDetect function, which implements the SSB Detector. The NR HDL Cell Search example shows the streaming fixed-point Simulink HDL implementation of the SSB Detector. In the 5G NR MIB Recovery Using Analog Devices AD9361/AD9364 (Communications Toolbox Support Package for Xilinx Zynq-Based Radio) example, the SSB Detector is implemented in programmable logic while the Search Controller is implemented in software on the integrated processing system.
The Search Controller is responsible for coordinating the overall search. The algorithm follows these steps.
For each subcarrier spacing, step through each coarse frequency offset and use the SSB Detector to search for SSBs until one or more is detected. The coarse frequency offset step size is half the subcarrier spacing. When SSBs are detected at a given frequency, record the residual fine carrier frequency offset of the strongest SSB that is returned.
Move to the next coarse frequency step and search for SSBs again. If the search detects SSBs, choose the coarse frequency offset that resulted in the smallest fine frequency offset measurement. Otherwise, pick the last coarse frequency offset.
Compute the total frequency offset by adding the coarse and fine frequency offsets together.
Use the SSB Detector to correct the frequency offset and perform one more search for SSBs.
Pick the SSB with the strongest PSS correlation. Use the SSB Detector in demodulation mode to find and demodulate the SSB and determine its cell ID.
These diagrams show the SSB Detector structure for FR1, and the parameters and data passed to and from the Search Controller. The SSB Detector is subdivided into two functions: SSB Detector DDC (
nrhdlexamples.ssbDetectDDC) and SSB Detection Search and Demod (
nrhdlexamples.ssbDetectSearchDemod). The DDC accepts samples at 61.44 Msps and performs a frequency shift followed by decimation by a factor of 8 using halfband filters. The frequency offset, in Hz, is provided by the search controller and is used by the algorithm to compensate for both coarse and fine frequency offsets.
SSB Detection Search and Demod accepts samples at 7.68 Msps. For 30 kHz subcarrier spacing, it uses the samples at this rate. For 15 kHz subcarrier spacing, it decimates the input by a factor of two, operating at 3.84 Msps. SSB Detection Search and Demod has two modes of operation: search and demodulation.
In search mode, the function searches for SSBs at the specified subcarrier spacing using the PSS, and returns a list of those detected. For each SSB that is found, the function returns these parameters:
NCellID2: Indicates which of the three possible PSS sequences (0,1, or 2) was detected.
timing offset: The timing offset from the start of the waveform to the start of the SSB.
fine frequency offset: The residual fine frequency offset in Hz measured by using the cyclic prefixes of all four OFDM symbols in the SSB.
correlation strength: The measured PSS correlation level.
signal energy: The total energy in the samples in which the PSS was detected.
In demodulation mode, the function attempts to find a specific SSB by using its timing offset and NCellID2. If the function finds the specified PSS, the receiver OFDM demodulates the SSB resource grid and attempts to detect its SSS. In demodulation mode, the function returns these results.
Updated parameters for only the specified SSB if the PSS is found.
The demodulated SSB resource grid if the PSS is found.
The cell ID if the SSS is found.
The OFDM demodulator uses a 256-point FFT to demodulate the SSB resource grid, which contains 240 active subcarriers.
The cell search algorithm uses timing offsets to identify positions within the received waveform and intermediate signals. A timing offset is the number of samples from the start of the waveform to a given position, such as the start of an SSB. Timing offsets are given in samples at 61.44 Msps and wrap around every 20 ms, or 1228800 samples. In 5G NR, receivers can assume that the SS burst periodicity is 20 ms or less for cell search purposes, hence the reason for this choice of timing reference periodicity.
The figure shows two 5G waveforms with different SS burst periodicities (5 ms and 20 ms) and the receiver timing reference. The MATLAB reference can detect SSBs at any position within the received waveform. However, if the waveform is longer than 20 ms, ambiguity in the returned timing offsets exists because the timing reference wraps around every 20 ms. Additionally, the receiver can demodulate only SSBs that begin within the first 20 ms of the waveform.
The diagram shows the structure of the SSB decoder, which is implemented by the
nrhdlexamples.ssbDecode function. The algorithm takes the SSB resource grid from the OFDM demodulation phase of the SSB detector, processes it through PBCH and BCH decoding, and outputs MIB parameters and PBCH timing information.
PBCH decoding takes the demodulated OFDM symbols of the resource grid and processes using these steps:
DMRS Search: Searches for the index used for demodulation reference symbol (DMRS) generation.
Channel Estimation: Calculates an estimate of the channel using the DMRS.
Channel Equalization: Equalizes the received data using the channel estimate.
Symbol Demod: Performs QPSK demodulation to get the PBCH soft bits.
Descramble: Descrambles the soft bits.
BCH Decode then processes the descrambled soft bits to recover the MIB data using these steps:
Rate Recovery: Combines repeated soft bits then performs scaling and quantization.
Polar Decode + CRC: Performs polar decoding to get the message bits and CRC decoding to check for errors.
MIB Message Parse: Interprets the decoded message bits to produce the MIB parameter outputs.
The diagram shows the structure of the SIB1 Demodulator algorithm, which is implemented by the
nrhdlexamples.sib1Demodulate function. The algorithm accepts samples at 61.44 MHz, and uses the results from the previous processing stages to locate and demodulate a grid containing CORESET0 and the scheduled SIB1 transmission. The MIB results are used to calculate the parameters of CORESET0, which includes the frequency offset, number of resource blocks, and the monitoring occasion. The frequency offset is relative to the location of the detected SSB. The first stage of data processing is a DDC which performs a frequency shift to center the SIB1 grid and then downsamples to 30.72 MHz - the maximum bandwidth for CORESET0 in FR1. The next stage is to wait for the CORESET0 monitoring occasion - the algorithm contains a timing reference that is synchronized with the SSB Detector timing references to identify the next occurance of the monitioring occasion. Once the monitoring occasion is reached the received samples are OFDM demodulated to produce a grid CORESET0 resource blocks wide and two slots in duration.
SIB1 decoding is performed on the SIB1 grid output by SIB1 demodulation. SIB1 decoding requires decoding of PDCCH to recover the SI-RNTI encoded DCI message, and decoding PDSCH to recover SIB1 message. The example shows two methods for decoding SIB1, either with or without hardware accelerators. The hardware accelerator version splits the each decoding stage into two steps. First, a setup step to create the input vectors which can be deployed to embedded software. Second, the hardware accelerated portion of the algorithm which can be deployed on an FPGA. Without hardware accelerators each decoding stage is performed by a single step which can be deployed to embedded software. By default,
nrhdlexamples.CORESET0Decode are used. Alternatively,
nrhdlexamples.pdcchDecoding is used. Both methods use the SIB1 grid and the parameters recovered from the previous decoding stages to locate and decode the PDCCH for CORESET0. They return the DCI message which signals the location of the PDSCH resources allocated to SIB1, and returns a flag indicating whether the DCI was found in the first or second slot of the SIB1 grid. The slot carrying PDSCH and PDSCH for SIB1 is selected from the SIB1 grid and
nrhdlexamples.coreset0PhaseAdjustment corrects for the phase offset applied on an OFDM symbol basis by the transmitter, as detailed in TS 38.211 section 5.4. By default,
nrhdlexamples.SIB1Decode are used. Alternatively,
nrhdlexamples.pdschDecoding is used. Both methods use the phase corrected slot grid, the DCI message, and other information from the previous decoding stages to locate and decode the PDSCH resources carrying the SIB1 message. They return the SIB1 message bits and the result of the SIB1 CRC check. A CRC value of 0 indicates successful recovery of the SIB1.
Generate a Test Waveform
This section shows how to use the MATLAB reference functions to search for SSBs in a waveform, demodulate and decode an SSB to recover the MIB, and recover the scheduled SIB1.
nrhdlexamples.generateFR1RxWaveform function to generate a 5G FR1 waveform containing SSB bursts and the corresponding SIB1 transmissions. Change the
simulationCase to explore different parameter sets. The full set of simulation cases is shown.
disp('Test waveform configurations:') disp(nrhdlexamples.generateFR1RxWaveform('list')); rng('default'); simulationCase = "SimCase 1"; [rxWaveform,ssbPattern,minChanBW,Lmax,txMIB,simCase] = nrhdlexamples.generateFR1RxWaveform(simulationCase); disp("Selected Simulation case:" + newline); disp(simCase); FoCoarse = 0; if ssbPattern == "Case A" scsSSB = 15; else scsSSB = 30; end
Test waveform configurations: Simulation Case SSB Pattern Subcarrier Spacing Common PDCCH Config SIB1 SNR dB Strongest SSB index Lmax _______________ ___________ _________________________ _________________ ______ ___________________ ____ "SimCase 1" "Case C" 30 164 50 4 8 "SimCase 2" "Case B" 15 100 6 3 4 "SimCase 3" "Case A" 30 4 20 2 8 "SimCase 4" "Case A" 15 84 7 0 4 Selected Simulation case: Simulation Case SSB Pattern Subcarrier Spacing Common PDCCH Config SIB1 SNR dB Strongest SSB index Lmax _______________ ___________ _________________________ _________________ ______ ___________________ ____ "SimCase 1" "Case C" 30 164 50 4 8
Plot the spectogram of the waveform.
The plot shows a spectogram of the SSBs, CORESET0s, and PDSCH regions carrying SIB1. These regions are generated with different power levels. The amplitude of each resource element is indicated by its color.
figure(1); clf; rxSampleRate = 61.44e6; nfft = rxSampleRate/(scsSSB*1e3); spectrogram(rxWaveform(:,1),ones(nfft,1),0,nfft,'centered',rxSampleRate,'yaxis','MinThreshold',-110); title('Spectrogram of the Received Waveform')
nrhdlexamples.ssbDetect function to find SSBs in the waveform by searching for PSS symbols. This example calls the function with a coarse carrier frequency offset estimate of zero and a subcarrier spacing determined from the SSB pattern of the generated waveform. The function corrects the coarse frequency offset and measures the residual fine frequency offset of each SSB. Frequency offset input and output are given in Hz. The function returns a list of detected PSS symbols as a structure array. Display the structure array contents by converting it to a table.
[pssList,diagnostics] = nrhdlexamples.ssbDetect(rxWaveform,FoCoarse,scsSSB); % Check if any PSS have been detected if isempty(pssList) disp('No PSS found during SSB detection.'); return; end disp('Detected PSS list:') disp(struct2table(pssList));
Detected PSS list: NCellID2 timingOffset pssCorrelation pssEnergy frequencyOffset ________ ____________ ______________ _________ _______________ 0 4416 0.89392 0.89884 58 0 17568 0.71119 0.71414 -4 0 35136 1.7923 1.8012 15 0 48288 1.4106 1.4226 34 0 65856 5.6444 5.671 -62 0 79008 2.2411 2.2541 3 0 96576 1.1308 1.136 15 0 1.0973e+05 0.79504 0.79883 -9
nrhdlexamples.ssbDetect function also returns a structure containing diagnostic signals. Use this output to plot the PSS correlation results. Each peak in the correlator output shown corresponds to an entry in the PSS list.
figure(2); clf; nrhdlexamples.plotUtils.PSSCorrelation(diagnostics,'PSS Correlation');
nrhdlexamples.ssbDetect function to OFDM-demodulate one of the SSBs and attempt SSS detection. For this operation, call the function with an optional 4th argument that specifies the timing offset and NCellID2 of the desired SSB. This example chooses the PSS with the highest correlation metric, however you can choose any of the detected SSBs. Correct the frequency offset by passing in the sum of the coarse and fine frequency offset estimates.
[~,maxCorrIdx] = max(vertcat(pssList.pssCorrelation)); chosenPSS = pssList(maxCorrIdx); disp('Selected PSS:') disp(struct2table(chosenPSS)); FoFine = chosenPSS.frequencyOffset; FoEst = FoCoarse + FoFine; [ssBlockInfo,ssbGrid,diagnostics] = nrhdlexamples.ssbDetect(rxWaveform,FoEst,scsSSB,chosenPSS); % Check SSB successfully demodulated if isempty(ssBlockInfo) disp('Failed to demodulate selected SSB.'); return; end
Selected PSS: NCellID2 timingOffset pssCorrelation pssEnergy frequencyOffset ________ ____________ ______________ _________ _______________ 0 65856 5.6444 5.671 -62
In demodulation mode, the function returns three outputs instead of two. The
ssBlockInfo structure contains further details of the SSB, such as the SSS correlation strength and the overall cell ID. The
ssGrid output is a matrix containing the demodulated OFDM symbols. Display the SSB info to confirm that the cell ID is correctly decoded.
disp('SSB info for demodulated SSB:') disp(ssBlockInfo);
SSB info for demodulated SSB: NCellID2: 0 timingOffset: 65856 pssCorrelation: 5.6444 pssEnergy: 5.6711 NCellID1: 83 sssCorrelation: 5.7213 sssEnergy: 5.7214 NCellID: 249 frequencyOffset: 0
Display the resulting SSB resource grid.
figure(3); clf; imagesc(abs(ssbGrid)); colorbar; axis xy; xlabel('OFDM symbol'); ylabel('Subcarrier'); title('SSB Resource Grid');
diagnostics output includes SSS correlation results for all 336 possible sequences. Plot the SSS correlation results.
figure(4); clf; nrhdlexamples.plotUtils.SSSCorrelation(diagnostics,'SSS Correlation')
Search for Cells
This section shows how to use the
nrhdlexamples.cellSearch function to search for and demodulate SSBs when the frequency offset and subcarrier spacing are not known. As described previously, the
nrhdlexamples.cellSearch function builds on the
nrhdlexamples.ssbDetect function by adding a search controller that looks for SSBs at different subcarrier spacings and frequency offsets.
Apply a frequency offset to test the coarse and fine frequency recovery functionality.
Fo = 10000; t = (0:length(rxWaveform)-1).'/61.44e6; rxWaveform = rxWaveform .* exp(1i*2*pi*Fo*t);
Define the frequency range endpoints and subcarrier spacing search space and call the
nrhdlexamples.cellSearch function. The function displays information on the search progress as it runs. The frequency range endpoints must be multiples of half the maximum subcarrier spacing.
frequencyRange = [-30 30]; subcarrierSpacings = [15 30]; [ssBlockInfo,ssbGrid] = nrhdlexamples.cellSearch(rxWaveform,frequencyRange,subcarrierSpacings,struct(... 'DisplayPlots',false,... 'DisplayCommandWindowOutput',true)); % Check cell search successfully found and demodulated SSB. if isempty(ssBlockInfo) disp('Cell search failed to find or demodulate SSB.'); return; end
Searching for PSS (subcarrierSpacing: 15 kHz, frequencyOffset: -30 kHz) Searching for PSS (subcarrierSpacing: 15 kHz, frequencyOffset: -22.5 kHz) Searching for PSS (subcarrierSpacing: 15 kHz, frequencyOffset: -15 kHz) Searching for PSS (subcarrierSpacing: 15 kHz, frequencyOffset: -7.5 kHz) Searching for PSS (subcarrierSpacing: 15 kHz, frequencyOffset: 0 kHz) Searching for PSS (subcarrierSpacing: 15 kHz, frequencyOffset: 7.5 kHz) Searching for PSS (subcarrierSpacing: 15 kHz, frequencyOffset: 15 kHz) Searching for PSS (subcarrierSpacing: 15 kHz, frequencyOffset: 22.5 kHz) Searching for PSS (subcarrierSpacing: 15 kHz, frequencyOffset: 30 kHz) Searching for PSS (subcarrierSpacing: 30 kHz, frequencyOffset: -30 kHz) Searching for PSS (subcarrierSpacing: 30 kHz, frequencyOffset: -15 kHz) Searching for PSS (subcarrierSpacing: 30 kHz, frequencyOffset: 0 kHz) ... PSS detected. Searching for PSS (subcarrierSpacing: 30 kHz, frequencyOffset: 15 kHz) ... PSS detected. Found PSS with (subcarrierSpacing: 30 kHz, frequencyOffsetEstimate: 9938 Hz) Correcting frequency offset and searching for PSS again. Found the following PSS symbols: NCellID2 timingOffset pssCorrelation pssEnergy frequencyOffset ________ ____________ ______________ _________ _______________ 0 4416 0.89391 0.89885 120 0 17568 0.71119 0.71415 58 0 35136 1.7923 1.8012 77 0 48288 1.4106 1.4226 96 0 65856 5.6444 5.6711 0 0 79008 2.2411 2.2542 65 0 96576 1.1308 1.1361 77 0 1.0973e+05 0.79503 0.79885 53 Strongest PSS: NCellID2: 0 timingOffset: 65856 pssCorrelation: 5.6444 pssEnergy: 5.6711 frequencyOffset: 0 Attempting to reacquire strongest PSS and demodulate the corresponding SS block. NCellID2: 0 timingOffset: 65856 pssCorrelation: 5.6444 pssEnergy: 5.6711 NCellID1: 83 sssCorrelation: 5.7213 sssEnergy: 5.7214 NCellID: 249 frequencyOffset: 9938 subcarrierSpacing: 30 Cell search summary: Subcarrier spacing: 30 kHz Frequency offset: 9938 Hz Timing offset: 65856 NCellID: 249
As shown in the summary, the receiver returned the correct subcarrier spacing of 30 kHz, a cell ID of 249, and the measured frequency offset is close to the expected value of 10 kHz.
nrhdlexamples.ssbDecode function to decode the SSB resource grid and recover the MIB. The
nrhdlexamples.ssbDecode function is based on the BCH decoding stages of the NR Cell Search and MIB and SIB1 Recovery (5G Toolbox) example.
[mibInfo,decodeDiags] = nrhdlexamples.ssbDecode(ssbGrid,ssBlockInfo.NCellID,Lmax); % Check MIB successfully decoded from SSB. if mibInfo.err disp('Failed to decode MIB from SSB.'); return; end
Plot the correlation peaks for the DMRS search. DMRS search is performed to determine ibar_ssb and the SSB index.
figure(5); clf; plot(0:7,decodeDiags.dmrsCorr); title('DMRS Search Correlation'); xlabel('ibar ssb'); ylabel('Correlation strength');
Plot the PBCH QPSK constellation after phase equalization.
figure(6); clf; plot(decodeDiags.qpskSymb,'o'); xlim(max(abs(real(decodeDiags.qpskSymb))).*[-1.1 1.1]); ylim(max(abs(imag(decodeDiags.qpskSymb))).*[-1.1 1.1]); title('PBCH Symbol Constellation'); xlabel('In-phase'); ylabel('Quadrature');
Display the decoded information and compare the transmitted and received MIB structures. These results show that the information was successfully decoded.
disp(['BCH CRC: ' num2str(mibInfo.err) newline]); disp('Decoded information'); disp(mibInfo); disp('Decoded MIB'); disp(mibInfo.mib); disp('Expected MIB'); disp(txMIB);
BCH CRC: 0 Decoded information pbchPayload: 17637376 ssbIndex: 4 hrf: 0 err: 0 mib: [1×1 struct] Decoded MIB NFrame: 0 SubcarrierSpacingCommon: 30 k_SSB: 0 DMRSTypeAPosition: 3 PDCCHConfigSIB1: 164 CellBarred: 0 IntraFreqReselection: 0 Expected MIB NFrame: 0 SubcarrierSpacingCommon: 30 k_SSB: 0 DMRSTypeAPosition: 3 PDCCHConfigSIB1: 164 CellBarred: 0 IntraFreqReselection: 0
Demodulate the SIB1 Grid
nrhdlexamples.sib1Demodulate function determines the location of CORESET0, using information decoded from previous stages, and OFDM demodulates the SIB1 grid. The SIB1 grid contains CORESET0 and the PDSCH resources allocated to the SIB1 message.
ssbFrequencyOffset = ssBlockInfo.frequencyOffset; ssbResults = struct(... 'SubcarrierSpacing', scsSSB, ... 'TimingOffset', ssBlockInfo.timingOffset, ... 'FrequencyOffset', ssbFrequencyOffset); bandCfg = struct( ... 'ssbPattern', ssbPattern, ... 'Lmax', Lmax, ... 'MinChanBW', minChanBW ... ); sib1Grid = nrhdlexamples.sib1Demodulate(rxWaveform,ssbResults,mibInfo,bandCfg);
Plot the OFDM demodulated SIB1 grid.
figure_SIB1grid = figure(7); clf; imagesc(abs(sib1Grid)); colorbar; axis xy; xlabel('OFDM symbol'); ylabel('Subcarrier'); title('SIB1 Grid');
Decode the SIB1 Grid
The SIB1 grid consists of 2 slots. Only one of these slots carries CORESET0 and the PDSCH with SIB1. Depending on useHardwareAccelerators either
nrhdlexamples.pdcchDecoding searches within each of the slots for DCI messages encoded with SI-RNTI. Once decoded, the SI-RNTI encoded DCI message provides information on the location of the SIB1 message within the PDSCH. Depending on useHardwareAccelerators either
nrhdlexamples.pdschDecoding uses the DCI and information from the previous stages to locate and decode the SIB1 message within the PDSCH. If successfully decoded the sib1CRC will be 0, and the SIB1 message bits output.
useHardwareAccelerators = true; if ~useHardwareAccelerators % Decode PDCCH and recover DCI message [dci,dciCRC,NSlot,secondSlotFlag,coresetNRB,muxPattern] = nrhdlexamples.pdcchDecoding(sib1Grid,ssBlockInfo.NCellID,mibInfo.ssbIndex,scsSSB,mibInfo.mib,minChanBW); % Check DCI successfully decoded from PDCCH. if dciCRC disp('Failed to decode DCI from PDCCH.'); return; end % Select slot containing SIB1 message slotGrid = sib1Grid(:,(1:14)+(14*secondSlotFlag)); % Adjust for phase offset applied by transmitter correctedSlotGrid = nrhdlexamples.coreset0PhaseAdjustment(slotGrid,mibInfo.mib,scsSSB,minChanBW,0); % Decode PDSCH and recover SIB1 message bits [sib1bits,sib1CRC] = nrhdlexamples.pdschDecoding(correctedSlotGrid,ssBlockInfo.NCellID,mibInfo.mib,coresetNRB,dci,NSlot,muxPattern); else % Extract the CORESET0 search space candidates from the SIB1 grid to pass to % the CORESET0 decoding hardware accelerator [candData,candNSym,candBaseRBIdx,... searchSpaces,numSlots,coresetDuration,coresetNRB,coresetNSlot,muxPattern] = ... nrhdlexamples.coreset0Extract(sib1Grid,ssBlockInfo.NCellID,mibInfo.ssbIndex,scsSSB,mibInfo.mib,minChanBW); % Run the CORESET0 decoding hardware accelerator [dci,dciCRC,secondSlotFlag] = ... nrhdlexamples.coreset0Decode(candData,candNSym,candBaseRBIdx,searchSpaces,numSlots,coresetDuration,coresetNRB,coresetNSlot,ssBlockInfo.NCellID); % Check DCI successfully decoded from PDCCH. if dciCRC disp('Failed to decode DCI from PDCCH.'); return; end % Select slot containing SIB1 message slotGrid = sib1Grid(:,(1:14)+(14*secondSlotFlag)); % Adjust for phase offset applied by transmitter correctedSlotGrid = nrhdlexamples.coreset0PhaseAdjustment(slotGrid,mibInfo.mib,scsSSB,minChanBW,0); % Extract the SIB1 LDPC codeword from the SIB1 grid to pass to the SIB1 % decoding hardware accelerator [ldpcCW,tbsLength] = nrhdlexamples.sib1Extract(correctedSlotGrid,ssBlockInfo.NCellID,mibInfo.mib,coresetNRB,dci,coresetNSlot+secondSlotFlag,muxPattern); % Run the SIB1 decoding hardware accelerator [sib1Bits,sib1CRC] = nrhdlexamples.sib1Decode(ldpcCW,tbsLength); end % Update SIB1 grid plot to highlight PDCCH and PDSCH areas nrhdlexamples.plotUtils.labelSIB1Plot(figure_SIB1grid.Number,size(sib1Grid),ssBlockInfo.NCellID,mibInfo.ssbIndex,scsSSB,mibInfo.mib,minChanBW,secondSlotFlag,dci); if sib1CRC == 0 disp('SIB1 successfully decoded'); else disp('SIB1 decoding failed'); end
SIB1 successfully decoded