PCI Target Termination Examples for pci_mt32 and pci_t32 MegaCore Functions
This document describes how to generate various target terminations when using Altera’s pci_t32 and pci_mt32 MegaCore® functions, and assumes that the user is familiar with the PCI specifications as well as the functionality of the Altera® PCI MegaCore functions.
Under most conditions, the target is able to source or sink the data requested by the master until the master terminates the transaction. But when the target is unable to complete the request, it may use the stopn signal to initiate termination of the transaction. How the target combines stopn with other signals will indicate to the master information about the condition which lead to the termination.
There are three types of target initiated termination:
The following sections describe each of the target termination types in more detail.
Download the files used in this example:
Target Abort
Target abort refers to an abnormal termination because either the local logic detected a fatal error, or the target will never be able to complete the request. An abnormal termination may cause a fatal error for the application that originally requested the transaction. A target abort allows the transaction to complete gracefully, thus preserving normal operation for other agents. A target device issues an abort by deasserting devseln and trdyn and asserting stopn..
The user logic can request a target abort by asserting the signal lt_abortn. If unused, the signal lt_abortn should be tied high as shown below:
wire lt_abortn = 1’b1;
The local-side device can request a retry because, for example, the device cannot meet the initial latency requirement or because the local resource cannot transfer data at this time. A target device signals a retry by asserting devseln and stopn, while deasserting trdyn before the first data phase. The local-side device can request a retry as long as it did not supply or request at least one data phase in a burst transaction. In a write transaction, the local-side device may request a retry by asserting lt_discn as long as it did not assert the lt_rdyn signal to indicate it is ready for a data transfer. If lt_rdyn is asserted, it can result in the PCI MegaCore function asserting the trdyn signal on the PCI bus. Therefore, asserting lt_discn forces a disconnect instead of a retry. In a read transaction, the local-side device can request a retry as long as data has not been transferred to the PCI MegaCore function.
The following example shows the sample logic required for generating a PCI retry
always @ (posedge clk or negedge rstn)
if (!rstn) begin
lt_rdyn <= 1'b1;
lt_discn <= 1'b1;
end else begin
lt_rdyn <= ! USER_READY ;
lt_discn <= !(cycle_start & !USER_READY);
end
USER_READY is an active high user signal that indicates if the user application is ready to accept a PCI access. The above example assumes that USER_READY is generated elsewhere in the user logic. USER_READY is typically a function of the signals bar_hit[5:0], l_cmdo[3:0], lt_framen and l_adro[31:0].
The signal cycle_start is a signal generated in the user logic to indicate the start of a target transaction. This signal can be generated by detecting a falling edge of the signal lt_framen.
A PCI target can signal a disconnect by asserting stopn and devseln after at least one data phase is complete. There are two types of disconnects: Disconnect with data and disconnect without data.
Disconnect with data may be signaled on any data phase by asserting trdyn and stopn together. This termination is used when the target is only willing to complete the current data phase and no more.
Disconnect without data may be signaled on any subsequent data phase (meaning data was transferred on the previous data phase) by deasserting trdyn and asserting stopn.
lt_rdyn and lt_discn control the PCI MegaCore function’s generation of a target disconnect. In addition, the state of irdyn controls whether there is a disconnect with data or disconnect without data.
Since disconnect with data or disconnect without data transactions depend upon the sate of the irdyn signal, you must design your logic to disconnect after the specified number of DWORDs are transferred on the PCI bus. You can use lt_dxfrn to check the number of DWORDS transferred on the local side and use lt_tsr[10] to check the number of DWORDS transferred on the PCI bus.
The following examples show how to generate a target disconnect for different transfer lengths. The final example is a generic example and can generate a disconnect for any transfer length.
Example 1: Disconnect after 1st data transfer
In this example, the user application is always ready and cannot accept burst transfers, so it terminates the transfer after the first data transfer.
always @ (posedge clk or negedge rstn)
if (!rstn) begin
lt_rdyn <= 1'b1;
lt_discn <= 1'b1;
end else begin
lt_rdyn <= lt_framen;
lt_discn <= lt_rdyn;
end
Example 2: Disconnect after 2 transfers
The following example shows how to generate a target disconnect after 2 transfers. For PCI writes, the user application can detect a successful PCI transfer one cycle after it occurs. So lt_discn in this case is generated combinatorially by looking at the signal lt_dxfrn, indicating that the first transfer has taken place and the second transfer is in progress on the PCI bus. For reads, lt_discn is generated by looking at a registered version of lt_dxfrn. This signal is called assert_disc. This condition indicates that the first transfer has taken place on the local side. The combinatorial gating of lt_dxfrn with assert_disc, allows lt_discn to be asserted when the second transfer is occurring on the local side.
The signal targ_wr_rdn indicates the direction of transfer and can be generated by looking at l_cmd[0] .
reg targ_wr_rdn; // write = 1 and read = 0
always @ (posedge clk)
targ_wr_rdn <= l_cmdo[0];
// Signal indicating when lt_discn should be asserted.
reg assert_disc;
always @ (posedge clk or negedge rstn)
if (!rstn)
assert_disc <= 1’b0;
else if (!lt_framen )
assert_disc <= targ_wr_rdn | (!targ_wr_rdn & !lt_dxfrn);
else // lt_framen = >
assert_disc <= 1’b0;
wire lt_discn = ! (assert_disc & !lt_dxfrn);
Example 3: Generic Disconnect Example
The following example shows lt_discn generation for different transfer lengths. The assumption here is that the user logic knows at the beginning of the transfer how many transfers it can accept and provides this information in the parameter CAN_ACCEPT. The signal assert_disc indicates when lt_discn should be asserted. This signal is generated based on the value of CAN_ACCEPT and the number of transfers that have taken place on the local side. In order to keep track of the number of words transferred on the local side, a counter is required and is implemented by the signal xfr_cnt.
// The parameter indicates how many transfers the design can accept and must be greater than 0
parameter [7:0] CAN_ACCEPT = 4;
always @ (posedge clk or negedge rstn)
if (!rstn)
xfr_cntr <= 8'b0;
else if (cycle_start)
xfr_cntr <= 8'b0;
else if (!lt_dxfrn)
xfr_cntr <= xfr_cntr + 1'b1;
// This signal indicates that the value of CAN_ACCEPT is either 1
reg transfer_1_dword;
// This signal indicates timing for when lt_discn should be asserted and is generated
// based on the value of xfr_cntr and CAN_ACCEPT
reg assert_disc;
always @ (posedge clk or negedge rstn)
if (!rstn) begin
lt_rdyn <= 1'b1;
assert_disc <= 1'b0;
transfer_1_dword <= 1'b0;
end else begin
transfer_1_dword <= ( (CAN_ACCEPT == 8'h1) );
lt_rdyn <= lt_framen ;
if (!lt_framen) begin
if (CAN_ACCEPT == 8'h1)
assert_disc <= !lt_rdyn;
else if (CAN_ACCEPT == 8'h2)
assert_disc <= targ_wr_rdn | (!targ_wr_rdn & !lt_dxfrn);
else
assert_disc <= assert_disc | (!lt_dxfrn &
((targ_wr_rdn & (xfr_cntr == CAN_ACCEPT -3)) |
(!targ_wr_rdn & (xfr_cntr == CAN_ACCEPT -2))));
end else
assert_disc <= 1'b0;
end
wire lt_discn = !(assert_disc & (!lt_dxfrn | transfer_1_dword));
For more information about using these examples in your project, visit the related links.
|