MSI Mode - 1.0 English

Versal Adaptive SoC Integrated Block for PCI Express LogiCORE IP Product Guide (PG343)

Document ID
PG343
Release Date
2023-11-10
Version
1.0 English

The user application first asserts a value on cfg_interrupt_msi_int, as shown in the previous figure. The core asserts cfg_interrupt_msi_sent to indicate that the interrupt is accepted and the core sends an MSI Memory Write TLP.

Figure 1. MSI Mode

The MSI request is either a 32-bit addressable Memory Write TLP or a 64-bit addressable Memory Write TLP. The address is taken from the Message Address and Message Upper Address fields of the MSI Capability Structure, while the payload is taken from the Message Data field. These values are programmed by system software through configuration writes to the MSI Capability structure. When the core is configured for Multi-Vector MSI, system software can permit Multi-Vector MSI messages by programming a non-zero value to the Multiple Message Enable field.

The type of MSI TLP sent (32-bit addressable or 64-bit addressable) depends on the value of the Upper Address field in the MSI capability structure. By default, MSI messages are sent as 32-bit addressable Memory Write TLPs. MSI messages use 64-bit addressable Memory Write TLPs only if the system software programs a non-zero value into the Upper Address register.

When Multi-Vector MSI messages are enabled, the user application can override one or more of the lower-order bits in the Message Data field of each transmitted MSI TLP to differentiate between the various MSI messages sent upstream. The number of lower-order bits in the Message Data field available to the user application is determined by the lesser of the value of the Multiple Message Capable field, as set in the IP catalog, and the Multiple Message Enable field, as set by system software and available as the cfg_interrupt_msi_mmenable[2:0] core output. The core masks any bits in cfg_interrupt_msi_select which are not configured by system software through Multiple Message Enable.

This pseudo code shows the processing required:

// Value MSI_Vector_Num must be in range: 0 £ MSI_Vector_Num £ (2^cfg_interrupt_mmenable)-1

if (cfg_interrupt_msienable) {       // MSI Enabled
  if (cfg_interrupt_mmenable > 0) {  // Multi-Vector MSI Enabled
    cfg_interrupt_msi_int[MSI_Vector_Num] = 1;
  } else {                           // Single-Vector MSI Enabled
    cfg_interrupt_msi_int[MSI_Vector_Num] = 0;
  }
} else {
  // Legacy Interrupts Enabled
}

For example:

  1. If cfg_interrupt_mmenable[2:0] == 000b, that is, 1 MSI Vector Enabled, cfg_interrupt_msi_int = 01h;
  2. If cfg_interrupt_mmenable[2:0] == 101b, that is, 32 MSI Vectors Enabled, cfg_interrupt_msi_int = {32'b1 << {MSI_Vector#}};

where MSI_Vector# is a 5-bit value and is allowed to be 00000b ≤ MSI_Vector# ≤ 11111b.

If Per-Vector Masking is enabled, first verify that the vector being signaled is not masked in the Mask register. This is done by reading this register on the Configuration interface (the core does not look at the Mask register).