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… .
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