SVA for checking fairness of Round-Robin Arbiter

In reply to hanhha:

This is my solution. Not necessarily the best one. Suggestions for improvements are welcome.

/*
Assume there are 3 requestors namely: A,B and C with reqA, reqB and reqC being the requests
and gntA, gntB and gntC being the grants. 
Assumes the request and grant are on the same cycle
Similar sequence and assertions need to be replicated for each requestor. Can concatenate the requests and grants 
into a bit vector, in order to save some redundant code
*/
   //Denotes there is request and grant for the requestor A. Does not care about other requestors 
   logic                                    requestorA_req_and_gnt;
   //Denotes there is request and grant for requestor A and there is atleast one other requestor active
   logic                                    requestorA_req_and_gnt_with_other_requestors_active;
   //There are requests other than requestor A
   logic                                    other_req_except_requestorA;
   //There are grants other than requestor A
   logic                                    other_gnt_except_requestorA;

   assign other_req_except_requestorA = reqB | reqC; //High when any one of the other requestor's are active
   assign other_gnt_except_requestorA = gntB | gntC;
   assign requestorA_req_and_gnt  = reqA & gntA;
   assign requestorA_req_and_gnt_with_other_requestors_active = reqA && other_req_except_requestorA && gntA;

  //-----------------------------------------------------------------------------------------------------------------------------------------------
  // Covers the case where there is request and grant on one cycle for requestorA, followed by no other requests. And then few cycles later there 
  // are multiple requests(reqA and atleast one other request). In this case, requestorA should NOT be granted again
  //-----------------------------------------------------------------------------------------------------------------------------------------------
  sequence requestorA_req_and_gnt_followed_by_other_req_seq;
     requestorA_req_and_gnt ##0 (!other_req_except_requestorA)[*1:$] ##1 reqA && other_req_except_requestorA;
  endsequence

  //-----------------------------------------------------------------------------------------------------------------------------------------------
  //Covers the case where there are more than one requestor active(reqA and any one of the other requests) followed by cycles of no other request at all
  // and again followed by more than one requestor active. First time during multiple requests, reqA is granted, so, the second time when multiple
  // requests are active, gntA should not be asserted again, and one of the other requests should be granted
  //-----------------------------------------------------------------------------------------------------------------------------------------------
  sequence multiple_requests_with_requestorA_req_and_gnt_followed_by_other_req_seq;
    requestorA_req_and_gnt_with_other_requestors_active ##1 (!other_req_except_requestorA)[*0:$] ##1 reqA && other_req_except_requestorA;
  endsequence
  
  //-----------------------------------------------------------------------------------------------------------------------------------------------
  //Covers the case where there are multiple requestors active in one cycle and next cycle may or may not have reqA, but will have other requests. 
  // If reqA is granted in the previous cycle, it should not be granted again in the next cycle, rather other requestor should be granted
  //-----------------------------------------------------------------------------------------------------------------------------------------------
  sequence back_to_back_multiple_requests_active_with_requestorA_gnted_followed_by_other_req_seq;
    requestorA_req_and_gnt_with_other_requestors_active ##1 other_req_except_requestorA;
  endsequence
  //-----------------------------------------------------------------------------------------------------------------------------------------------
  //Assertion to check if reqA do not hog the round robin arbiter
  //-----------------------------------------------------------------------------------------------------------------------------------------------
  assert_fairness_wrt_requestorA: assert property( @(posedge clk) disable iff(!resetn) 
    (requestorA_req_and_gnt_followed_by_other_req_and_no_bts_seq                                  or
     multiple_requests_with_requestorA_req_and_gnt_followed_by_other_req_and_no_bts_seq           or
     back_to_back_multiple_requests_active_with_requestorA_gnted_followed_by_other_req_and_no_bts_seq
    ) |-> other_gnt_except_requestorA && !gntA
  )
     `uvm_info("ARB_ASSERT",$sformatf("Requestor A was previously granted, and not granted again, round robin scheme followed!"),UVM_LOW) 
  else
     `uvm_error("ARB_ASSERT_ERR",$sformatf("Requestor A was previously granted, and gets granted again, round robin scheme not followed"))