Carrier Setup and CCID Sequencing - 2.0 English

RFSoC DFE PRACH LogiCORE IP Product Guide (PG391)

Document ID
PG391
Release Date
2024-05-30
Version
2.0 English

The API provides functions to dynamically add, update, and remove component carriers, and to manage the CCID sequence. These are described below.

Updates to the RACH channels and component carrier configuration are typically performed using immediate triggers or single-shot triggers. Single-shot should be used to give precise control of the RACH-UPDATE timing. When using a single shot trigger for RACH UPDATE, it must be triggered by the TUSER bus on band 0. However, this is not recommended if more than one band is configured.

Synchronization of the radio frame timing is typically performed using continuous triggers based on a bit of the TUSER bus. A FrameInit trigger is provided for each band, allowing the framing on each band to be aligned independently. This allows the frame to be aligned precisely to a particular sample.

The DFE PRACH core uses two triggers to align the update with the frame boundary. Once the core has been activated, the register interface is used to load a new configuration into the register map. The new configuration must be loaded across all bands. Any channels that are not changing must be reloaded with the same configuration as they are already running.

Once the configuration is fully loaded, the RACH_UPDATE trigger must be fired. The trigger can either be immediate or triggered off of a TUSER bit of band 0 with a single-shot trigger. Triggering the RACH update will enable the new configuration internally, but it will not be adopted until the FRAME_INIT trigger.

To adopt the new configuration, the FRAME_INIT trigger should be fired (using TUSER bit). The FRAME_INIT trigger marks the last bit of the radio frame and is necessary to align the internal scheduling. It must be aligned on the clock cycle preceding the first cycle of the CCID sequence of its band, as shown in the following figure.

Following a RACH update, the FRAME_INIT triggers for every band must be fired (aligned with that band's frame boundary) to maintain continuity of the configuration for that band. This will not disrupt any already configured captures that have not changed during the Configuration Update.

The following figure shows how the two triggers are used to perform an update to the CC configuration and RACH channel configuration. Note that a RACH_UPDATE is required every time the core has to accept a new configuration. Also, note that each RACH_UPDATE must be followed by a FRAME_INIT on each active band.

Figure 1. Frame Timing and RACH/CC Trigger Update Timing

The RACH_UPDATE and the FRAME_INIT triggers should conform to the following figure regarding their relative timing:

Figure 2. RACH_UPDATE and FRAME_INIT Relative Timing

You can see that in order to perform an update in the next frame, the RACH_UPDATE must arrive no earlier than the FRAME_INIT for the current frame and no later than the last subframe in the current frame. This is to ensure the RACH update is associated with the correct FRAME_INIT and that there is sufficient time to program the PRACH core prior to the FRAME_INIT. The timing of the RACH_UPDATE can be set using a single-shot trigger.

The API provides functions which can allow simultaneous updates to multiple component carriers and RACH channels using a single trigger, and functions that are intended to operate on one carrier at a time. This section will cover the simultaneous functions. The single carrier functions are covered in Making Single Channel Updates.

After the core has been activated, software should assemble the configuration objects that are needed by the API. Two structures are required a component carrier configuration and a RACH channel configuration. An XDfePrach_CCCfg structure is declared to hold the details of the core's component carrier configuration. An XDfePrach_RCCfg structure is also declared to hold the details of the core's RACH channel configuration. These structures can be populated either with the configuration currently in effect or with an empty configuration setup. In both cases, the current state of the core is unaffected and all data processing continues uninterrupted.

The API provides functions which operate on the configuration structures to add, remove, or update component carriers, to enable and disable antennas, and to add, remove or update RACH channels. When all changes to the configuration structures are complete, they are scheduled to be put into effect by a final API call.

The initial component carrier configuration structure is declared and populated with code similar to the following.

/* Declare CC configuration structure */
XDfePrach_CCCfg CCConfig;

/* Retrieve the current CC configuration parameters */
XDfePrach_GetCurrentCCCfg(InstancePtr, &CCConfig);

To start from a blank CC configuration instead of the current configuration, use the function XDfePrach_GetEmptyCCCfg instead of XDfePrach_GetCurrentCCCfg. The arguments and syntax are identical for the two calls. An empty configuration is initialized to 0, and therefore has no active component carriers.

The XDfePrach_CCCfg structure is capable of storing the component carrier configuration for up to three bands. All active bands must be programmed and sent to the core at the same time whenever there is any update to the CC configuration on any band.

To add a component carrier to the configuration, use the XDfePrach_AddCCtoCCCfg function or the XDfePrach_AddCCtoCCCfgMB function. The arguments to both of these functions define the CCID value, the sub-carrier spacing for the CC, and a bitmap representing the position of this component carrier's samples within the CCID sequence. Additionally the XDfePrach_AddCCtoCCCfgMB function has a BandId argument which specifies the band that the CC is being added to. The XDfePrach_AddCCtoCCCfg function operates on band 0 only.

These functions allow the complete CC Sequence structure to be assembled across all three bands prior to sending them over the AXI4 register interface.

To remove a component carrier from the configuration, use XDfePrach_RemoveCCfromCCCfg or XDfePrach_RemoveCCfromCCCfgMB

XDfePrach_CarrierCfg CarrierCfg;
u32 BitSequence;
u32 CCID;
u32 result;

CarrierCfg.SCS = 0; // Spacing = 2^x * 15 kHz, so x=1 -> 15 kHz SCS

BitSequence = 0x5555;        // CC will occupy every other timeslot, starting with the first
CCID = 0;                    // CCID number chosen for the new carrier

/* Add the component carrier to the configuration for band 0 */
result = XDfePrach_AddCCtoCCCfg(InstancePtr, &CCConfig, CCID, BitSequence, &CarrierCfg);

/* Add the same component carrier to the configuration for band 1 */
result = XDfePrach_AddCCtoCCCfgMB(InstancePtr, &CCConfig, CCID, BitSequence, &CarrierCfg, 1);

/* Remove CCID 9 from the configuration for Band 0 */
XDfePrach_RemoveCCfromCCCfgMB(InstancePtr, &CCConfig, 9, 0);

When defining multiple CCs, ensure that the bit sequence values do not overlap. For example, to create one 122.88 MSPS CC and three 30.72 MSPS CCs, a valid set of bit sequences could be:

u32 BitSeq0_122p88 = 0x5555;
u32 BitSeq1_30p72  = 0x0202;
u32 BitSeq2_30p72  = 0x0808;
u32 BitSeq3_30p72  = 0x2020;

assert (BitSeq0_122p88 & BitSeq1_30p72 & BitSeq2_30p72 & BitSeq3_30p72 == 0);
The examples in this section assume a CCID sequence length of 16. For shorter CCID sequences, a smaller bitmap (8-bit, 4-bit etc.) can be used. The pattern specified by the bitmap for each band must match the patterns supplied to the core on s_axis_din0_tid, s_axis_din1_tid, and s_axis_din2_tid. If it does not match, the core records a CC sequence error for the failing band. This condition can be detected using the following code:
XDfePrach_StatusMask status = { 0 };
XDfePrach_GetEventStatus(InstancePtr, &status);
if (status.CCSequenceError[0] != 0 || status.CCSequenceError[1] != 0 || status.CCSequenceError[2] != 0)
  printf("A CC sequence error occured!\n");

The CC parameters for an existing component carrier can be updated within the configuration using XDfePrach_UpdateCCinCCCfg or XDfePrach_UpdateCCinCCCfgMB. It is also possible to retrieve the parameters for an existing component carrier using XDfePrach_GetCarrierCfg or XDfePrach_GetCarrierCfgMB. The following code shows how the these functions can be used.

/* Retrieve the carrier configuration for CCID 3, band 0 or single band configuration*/
XDfePrach_GetCarrierCfg(InstancePtr, &CCConfig, 3, &BitSequence, &CarrierCfg);

/* Update the SCS for CCID 3 */
CarrierCfg.SCS = 2;  // 60 kHz SCS
XDfePrach_UpdateCCinCCCfg(InstancePtr, &CCConfig, 3, &CarrierCfg);

/*Replicate the same Configuration in Band 2*/
XDfePrach_UpdateCCinCCCfgMB(InstancePtr, &CCConfig, 3, &CarrierCfg,2);

The RACH channel configuration contains the settings for all 16 PRACH channels that the core provides. The 16 PRACH resources are shared across all of the active bands. The XDfePrach_RCCfg structure defines the NCO configuration for a RACH channel, the Decimation settings for the RACH channel's DDC, the Component Carrier and band from which the PRACH capture will be taken and the location of the PRACH capture within the Radio Frame.

When using Dynamic modes, some of the values in XDfePrach_RCCfg become redundant because their registers become read only and they are set by the s_axis_sched interface. The redundant fields are ignored and there is no requirement to adjust any function calls.

The initial RACH channel configuration structure is declared and populated with code similar to the following.

/* Declare RACH configuration structure */
XDfePrach_RCCfg RCConfig;

/* Retrieve the current RACH configuration parameters */
XDfePrach_GetCurrentRCCfg(InstancePtr, &RCConfig);

To add a RACH channel to the configuration, use the XDfePrach_AddRCtoRCCfg function for single band and the XDfePrach_AddRCtoRCCfgMB function for multiple bands. These function takes as arguments: the DDC configuration, the NCO configuration, the scheduling information which defines where the capture is located within the radio frame(s), the RCID number of the channel being loaded, the physical channel that the RCID will run on, and the component carrier configuration associated with this XDfePrach_RCCfg. The function also requires an argument which defines which CC the PRACH capture will be taken from. In the XDfePrach_AddRCtoRCCfg function, this is a CCID, which is implicitly taken from Band 0. The CCID must correspond to a CCID which has been enabled in XDfePrach_CCCfg. In XDfePrach_AddRCtoRCCfgMB a BandId argument is included which defines the Band that the CCID belongs to.

The NCO configuration, the DDC configuration, and Scheduling will be discussed in more detail in the NCO Configuration section.

To remove a RACH channel from the configuration, use XDfePrach_RemoveRCfromRCCfg. There is no multiband equivalent of this function.

//assumes XDfePrach_CCCfg structure CCCfg has already been populated.

XDfePrach_DDCCfg DdcCfg = { 0 };
XDfePrach_NCOCfg NcoCfg = { 0 };
XDfePrach_Schedule SchedCfg = { 0 };
u32 CCID;
u32 RCId;
u32 result;

CCID = 0;           // CCID on which to perform RACH extraction
RCId = 1;           // RACH channel identifier (0-15)

/* Set up NcoCfg  */
NcoCfg.Frequency = 32;
NcoCfg.NcoGain   = 1;

/* Set up DdcCfg - default RachGain is 0dB for all stages */
DdcCfg.DecimationRate = 2;  // Rate #2 = 4x decimation
DdcCfg.SCS            = 1;  // SCS #1 = 30 kHz spacing

/* Set up SchedCfg */
SchedCfg.PatternPeriod = 20; // Enable every twentieth frame
SchedCfg.FrameID       =  3; // Start on fourth frame of the period
SchedCfg.SubframeID    =  0; // Start on first subframe
SchedCfg.SlotId        =  0; // Start on first slot
SchedCfg.Duration      = 32; // Number of slots to capture
SchedCfg.Repeats       =  1; // Perform a single capture

/* Add the RACH channel to the configuration */
result = XDfePrach_AddRCtoRCCfg(InstancePtr, &RCConfig, 
           CCID, RCId, RCId, &DdcCfg, &NcoCfg, &SchedCfg, &CCCfg);

/* Remove RCID 4 from the configuration */
XDfePrach_RemoveRCfromRCCfg(InstancePtr, &RCConfig, 4);

The parameters for an existing RACH channel can be updated within the configuration using XDfePrach_UpdateRCinRCCfg and XDfePrach_UpdateRCinRCCfgMB, which have similar syntax to XDfePrach_AddRCtoRCCfg and XDfePrach_AddRCtoRCCfgMB.

When all the require changes have been made and the CC configuration structure and RACH channel configuration structure are both ready to be applied, call the XDfePrach_SetNextCfg function to write the new configuration structures to the core.

/* Apply the changes */
result = XDfePrach_SetNextCfg(InstancePtr, &CCConfig, &RCConfig);

if (result == XST_SUCCESS)
  printf("CC & RACH configurations scheduled for update\n");
else
  printf("Set CC & RACH configuration failed with error code %d!\n", result);

This function will upload all of the register settings associated with XDfePrach_CCCfg and XDfePrach_RCCfg to the core's registers, it will also load the RachUpdate trigger settings (defined in Triggering Configuration Changes) and the FrameInit trigger settings for each band. The new component carrier and RACH channel configurations will replace the existing configurations when the RachUpdate trigger condition occurs.

After this, the new capture configurations will remain dormant until the FrameInit trigger condition occurs for the band they are targeting. Once the FrameInit trigger condition occurs the core can synchronize the CC sequence and initialize the scheduler.