SYSTEM VERILOG ASSERTION FOR ROUND ROBIN ARBITER

I want to write round robin assertion for given image. In this when random no of request go high at same time and all grant is low(zero value) then in next clock cycle grant value will be for lowest high bit of req .when random no of req go high and grant signal is not low(non zero) then next grant will come with respective to active requsest signal bit in next clock cycle. On every positive clock request value change and grant also getting change one cycle delay by checking previoust grant . Arbiter is not only in priority it is in Round Robin fashion also. Order of grant value is like 1->2->3->4->1->2->3->4… .

signals
[3:0] req;
[2:0] gnt;


In reply to sumit@2001:
On a checker, one could create a RAM structure addressed by {req[3:0], last_grnt[3:0} and as output grant[3:0]. This ram can be initialized by a program that you write. You can use the $countones to help here. The assertion then becomes a simple lookup.


always @(posedge clk last_grant <= grant; 
ap_grant: assert property (@posedge clk) $changed(req) |-> 
         ram[{$past(req), last_grant}]==grant);  

Below is another option.

EPWave Waveform Viewer // wave
The arbeiter_check generates a bit[3:0] chkr_grant;
The TB does not generate a grant for simplicity


      module arbiter_check(input bit clk, reset_n,
                             input bit [3:0] req,  // request, bit 3 starts as 1st priority,
                             input bit[3:0] grant);
      
        bit[3:0] chkr_grant;  
        bit[1:0] next_grant;
        int pass, fail; 
        let range(val, width) = (val & (2 << width) - 1);
        // Extracts bits width:0 from val[n:0]
        // the solution with a mask is the best, provided that the lower index bound is 0.
        // Example  if ((range(req, next_grant)) != 0) begin : within_the_low_bound
        // if req[3:0]==1011, next_grant==1, the
        // range(4'b1011, 2'b01)== 4'b1011 & (4'b0010 << 1)-1
        //                         4'b1011 &  (4'b0100 -1) == 4'b1011 & 4'b0011) == 4'b0011
        //
      
        // task is called when there is a req
        task automatic do_grant();
          bit found=0;
          bit[3:0] vgrant;
          // maintain next_grant pointer
          if(next_grant==0)
            next_grant <=3;
          else
            next_grant <=next_grant-1;
      
          // CHeck if the req is from next_grant to 0
          if (range(req, next_grant) >0)
          begin : lower_bound
            for (int i = next_grant; i>= 0; i=i-1)
            begin : forlp1
              if(req[i])
              begin
                vgrant[i]=1; $display("vgrant=%b", vgrant);
                found=1;
                chkr_grant <= vgrant;
                next_grant<=i-1;
                break;
              end
            end  : forlp1
      
          end : lower_bound
      
          //else if not found, check rea in range (req[3:next_grant+1],
          else if (!found && range(req, next_grant) >0)
          begin :upper_bound
            for (int i = 3; i>= next_grant; i=i-1)
            begin : forlp2
              if(req[i])
              begin
                vgrant[i]=1;
                found=1;
                chkr_grant <= vgrant;
                next_grant<=i-1;
                break;
              end
            end  : forlp2
      
          end : upper_bound
        endtask
      
        // ----------------------------------------------
        /* Highest priority pointer  */
        always @(posedge clk)
        begin
          if (!reset_n)
            next_grant<=3;
          else  //
            if(req!=0 && grant==0) // there is a req and no grant
              do_grant();
        end
      
        ap_req_grant: assert property(@(posedge clk)
                            req>0 |->  ##1 grant==chkr_grant && $onehot(grant)) 
                            pass=pass+1; else fail=fail+1; 
       endmodule
       
      
       `timescale 1ns / 1ps
      
      module arbiter_check_tb;
          bit clk;
          bit reset_n;
          bit [3:0] req;
          
          // Outputs
          bit [3:0] grant;
          
          // Instantiate the module under test
          arbiter_check dut (
              .clk(clk),
              .reset_n(reset_n),
              .req(req),
              .grant(grant)
          );
          
          // Clock generation
          always #4 clk = !clk;
          
          // Test scenario
          initial begin
              $dumpfile("dump.vcd"); $dumpvars;
              // Initialize inputs
              clk = 0;  @(posedge clk) reset_n = 1;
              req = 4'b1111;
              grant=4'b0000;
              repeat(8) @(posedge clk);
              @(posedge clk) req <= 4'b0110; // Request from priority 2
              #1 grant = 4'b0100;
               @(posedge clk) req = 4'b1111; // Requests from priorities 0 and 2
               #1 grant= 'b0100; 
              #20;
              $finish;
          end
      endmodule

Ben Cohen
Ben@systemverilog.us
Link to the list of papers and books that I wrote, many are now donated.

or Cohen_Links_to_papers_books - Google Docs

Getting started with verification with SystemVerilog