We have detected your current browser version is not the latest one. Xilinx.com uses the latest web technologies to bring you the best online experience possible. Please upgrade to a Xilinx.com supported browser:Chrome, Firefox, Internet Explorer 11, Safari. Thank you!

AR# 19727

LogiCORE PCI-X - How do I drive M_DATA_IN and M_CBEA_IN as a completer when issuing a split completion command?


General Description:

How does a user application pass the correct attributes and address information for a split completion command when issuing a split completion?


The user application utilizes the same basic method as described in Chapter 7 of the PCI-X Design Guide. Data passed on M_CBEA_IN and M_DATA_IN varies slightly from a normal initiator transaction like a memory write, due to requirements of the PCI-X specification when a split completion is issued.

Section 2.10.3 of the PCI-X v2.0 specification defines the address of a split completion command to have the following format:

Figure 1 - Split Completion Address Format
Figure 1 - Split Completion Address Format

The attribute phase, section 2.10.4, has the following format:

Figure 2 - Split Completion Attribute Format
Figure 2 - Split Completion Attribute Format

Information must be driven to the core, so that the core will present the correct format of the address and attributes on the bus as shown above. The user application utilizes the M_DATA_IN[31:0] and M_CBEA_IN[3:0] buses to pass the split completion information to the core. The fields are defined in Chapter 7 of the PCI-X Design Guide as follows:

Figure 3 - Attribute and Command Format
Figure 3 - Attribute and Command Format

After you assert M_REQ to start the split completion transaction, the core will assert M_ATTR_VLD, asking you to pass the correct attributes to the core. One major difference between a split completion command and a normal memory command, such as a memory write block, is that the tag value is located in the address phase of a split completion command and not in the attribute phase. The user application must take this into consideration when it passes information to the core.

When M_ATTR_VLD is asserted, the following information must be passed:

Figure 4 - Attribute field descriptions
Figure 4 - Attribute field descriptions

After the attributes are passed, the core will assert M_ADDL_VLD and the data must be presented on M_DATA_IN[31:0] according to the PCI specification requirement for the split completion address as shown in the first figure above. Note that the tag value is passed at this time.

When the core asserts M_ADDL_VLD, the user application does not pass any information on M_CBEA_IN[3:0] since the command was sent previously when M_ATTR_VLD was asserted. These bits should be driven Low.

The rest of the information such as the address and requestor numbers are captured by the user application when the original transaction occurred that the target split.

The following is an example of code needed to handle split completions. This is not a complete design, but only example code to illustrate the basic concepts. This is available only in Verilog, but it can be easily translated to VHDL.

//First, capture the following information on the target transaction being split:

reg [3:0] scmd;

reg [35:0] sattr;

reg [31:0] saddr;

always @(posedge CLK or posedge RST)




scmd <= 4'b0000;

sattr <= 36'h000000000;

saddr <= 32'h00000000;




//Grab address and command



saddr <= S_DATA_OUT;

scmd <= S_CBEA_OUT ;


//Grab attribute



sattr <= {S_CBEA_OUT, S_DATA_OUT};




//For splits completions, you must break this above info down for later use.

//Please note that if you do it this way, you can only service one split completion

//at a time (i.e., you can only split one transaction at a time.)

//If you want to service more, you must create some type of queue to store all of this information.

wire [6:0] low_addr;

wire [2:0] requester_function_num;

wire [4:0] requestor_device_num;

wire [6:0] requestor_bus_num;

wire [4:0] tag;

wire [11:0] byte_count;

assign #DLY low_addr = saddr[6:0];

assign #DLY requester_function_num = sattr[10:8];

assign #DLY requestor_device_num = sattr[15:11];

assign #DLY requestor_bus_num = sattr[23:16];

assign #DLY tag = sattr[28:24];

assign #DLY byte_count = {sattr[35:32],sattr[7:0]};

//Now at some time later you will become the initiator and complete the transaction

//using the above information.

wire [31:0] xfer_addr;

wire [31:0] mdi_temp0;

//Tell the core you want to start a transaction as a Master

assign #DLY M_REQ = some_state_machine_output;

//Create the split completion address value. This is what will appear on

//the bus during the address phase. See the PCI-X spec for more information

//on this format.

assign #DLY xfer_addr = {3'b000,tag,requestor_bus_num,requestor_device_num,


//Send in the attributes for the core. See page 7-3 of the PCI-X core Design Guide

wire attribute_tag;

//Tag value sent in attribute field must be set to zero for split completions.

//is_split would most likely be a state machine output indicating the user app is issuing

//a split completion.

assign #DLY attribute_tag = is_split ? 5'b00000 : normal_tag;

assign #DLY mdi_temp0 = M_ATTR_VLD ? {4'b0000, attribute_tag, 11'b00000000000, byte_count} :


assign #DLY M_DATA_IN = (!M_ATTR_VLD & !M_ADDL_VLD) ? data_to_transfer : mdi_temp0;

//Feed in the split completion command.

assign #DLY M_CBEA_IN = M_ATTR_VLD ? 4'b1100 : 4'b0000;

//Keep in mind the above block of code will become much more complex when you add

//the logic to do other normal master transactions. This will require muxing

//the different types of address fields and attributes. You will probably also

//need to create address counters for your data. But hopefully this will get you

//pointed in the right direction.

AR# 19727
Date Created 09/03/2007
Last Updated 12/15/2012
Status Active
Type General Article