Response handling between UVM Driver and Sequencer for Pipelined Protocols
In the pipelined protocols, the handling of responses requires a different approach as compared to other non-pipelined protocols. In other protocols, the Driver and Sequencer synchronisation can be implemented in a simpler way, where the Driver gets the transaction item from the Sequencer, drives it on the interface and then sends the response back to the Sequencer just after calling the item done and before getting the new transaction item again from the Sequencer. However, the same method of sending a response cannot be used while dealing with the protocols where the response is pipelined.
In the case of a pipelined response, the Driver cannot send the response to the Sequencer at the time when no response has been driven on the bus by the Slave. If the driver waits for sampling the response at the right clock cycle before sending it to the Sequencer, then it will get the next packet from the Sequencer with some delay. When the driver is waiting for the response, and it has not fetched the new transaction packet from the Sequencer, it has to drive Idle transfers on the interface. If we want the scenario of continuous back-to-back transactions on the interface without Idle transfers in between, it cannot be achieved in this case.
Let us take the example of AHB protocol. According to AHB, a simple transfer proceeds with the following steps:
1. The master drives the address and control signals onto the bus after the rising edge of HCLK.
2. The slave then samples the address and control information on the next rising edge of HCLK.
3. After the slave has sampled the address and control, it can start to drive the appropriate HREADY response. This response is sampled by the master on the third rising edge of HCLK.
To get the continuous back-to-back transactions (shown in Figure 2), the driver needs to respond immediately (this response would be a dummy response just to get the next packet from the Sequencer) or call the item done without sending any response so that the next burst can be started without an Idle transfer. But, till that time response or read data is not sampled by the Driver as it is available after two clock cycles or at the third posedge. Therefore, we will not be able to use the response / read data in the Sequence if required.
Figure 2: AHB back-to-back write and read transfers without Idle
To meet the requirements of synchronizing Sequencer and Driver with no Idle transfers in between the bursts, along with sampling the correct response/read data, we can use the methods as suggested in the UVM User’s Guide for the pipelined protocols operating on several transactions at the same time. One of these methods is using “rsp_port” (shown in Figure 3), which is an inbuilt analysis port of uvm_driver and is used to send the response back to the Sequencer.
Figure 3: Response handling for pipelined protocols using “rsp_port”
The code snippets below show the cases of response handling between Driver and Sequencer without using “rsp_port”:
A). Putting response after collecting the response / read data from bus - Able to collect and send the correct response / read data, but not able to generate back-to-back transfers without Idle
seq_item_port.get_next_item(req); // Get the transaction packet from Sequencer
…..
….. // Drive transaction on the interface and sample response / read data
…..
seq_item_port.item_done(rsp); // Send the response packet to Sequencer
B). Putting a response immediately without waiting for the response / read data on the bus, or not put response. Back-to-back transfers are possible without Idle, but are not able to collect and send a correct response/read data
seq_item_port.get_next_item(req); // Get the transaction packet from Sequencer
Recommended by LinkedIn
seq_item_port.item_done(rsp); // Send the response packet to Sequencer
…..
….. // Drive transaction on the interface and sample response / read data
…..
or
seq_item_port.get_next_item(req); // Get the transaction packet from Sequencer
seq_item_port.item_done(); // Do not send any response to Sequencer
…..
….. // Drive transaction on the interface and sample response / read data
…..
The code snippet below shows the response handling between Driver and Sequencer using “rsp_port”:
C). Using “rsp_port” to put response after collecting the response from bus - Able to collect and send the correct response / read data along with the back-to-back transfers without Idle -
seq_item_port.get_next_item(req); // Get the transaction packet from Sequencer
seq_item_port.item_done(rsp); // Send the dummy response packet to Sequencer
…..
….. // Drive transaction on the interface and sample response / read data
…..
rsp_port.write(rsp); // Sending the response sampled from the bus to the Sequencer in parallel
Summary: By using “rsp_port”, we can complete the Driver and Sequencer synchronization with collecting and sending the right response and reading data and can also achieve the requirement of continuous back-to-back transfers in case of pipelined protocols.