In reply to dvuvmsv:
In reply to dvuvmsv:
[b]In reply to dvuvmsv:
Quote:
// How will you make sure , it was equally distributed, each 0.1 seconds
// If you take a window of 1 second, it can be that first 0.5 seconds,
// full traffic was from port1, next 0.3 seconds, full traffic was from
// port2 and remaining 0.2 seconds traffic was from Port3
As you expressed, probabilities need to be measured over several samplings, and the larger the samplings, the better the measurement of the probabilities.
For each port that is enabled to drive the single output port, there is an enable (or grant) for it. Assuming that you want to measure these probabilities increment of T cycles representing 1 second, you could gather those statistics in counters and then compute the ratios of the counts for each of the grants. Thus, you could do something like the following:
int window;
real count0, count1, count2; // for the collection of statistics
let MAXWGT0=3'b101; let MAXWGT1=3'b100; let MAXWGT2=3'b010;
let T = 1000; // 1000 cycles take 1 second
// For greater resolution, use a larger number for T, i.e., more samplings
initial begin : the_init
automatic real sum;
forever begin : the_forever
while (window <= T) begin : the_while
@(posedge clk) if(gnt0) count0 += 1'b1;
if(gnt1) count1 += 1'b1;
if(gnt2) count2 += 1'b1;
window += 1'b1;
end : the_while
// Collected 1000 samplings, now check stats
// resets counts or let count increment for more samplings.
// weights 50 30 20
sum=count0+count1+count2;
a_stat0: assert (count0/sum < 0.505 && count0/sum > 0.495); // 50%
a_stat1: assert (count1/sum < 0.305 && count1/sum > 0.295); // 30%
a_stat2: assert (count2/sum < 0.205 && count2/sum > 0.195); // 20%
window = 0;
// reset the counts if needed
end : the_forever
end : the_init
the complete model I have is below. Note the addition of
if($countones({req0, req1, req2}) ==0) return; // <— NEW
// Weighted Round Robin Arbiter ?
// There are 3 requests and 3 Grants
import uvm_pkg::*; `include "uvm_macros.svh"
module top;
bit clk, req0, req1, req2; //with weights 50, 30, 20
bit gnt0, gnt1, gnt2, max0, max1, max2;
bit[2:0] wgt0, wgt1, wgt2;
int window;
real count0, count1, count2; // for the collection of statistics
let MAXWGT0=3'b101; let MAXWGT1=3'b100; let MAXWGT2=3'b010;
let T = 1000; // 1000 cycles take 1 second
// For greater resolution, use a larger number for T, i.e., more samplings
// Assuming this algorithm
// if($countones({req0, req1, req2}) ==1) then provide grant to requester
// else if(!max0) then grant0 and ++wgt0
// else if(!max1) then grant1 and ++wgt1
// else if(!max2) then grant2 and ++wgt2
// else max1=1, max2=0, max3=0 and grant1
default clocking @(posedge clk); endclocking
initial forever #10 clk=!clk;
// How will you make sure , it was equally distributed, each 0.1 seconds
// If you take a window of 1 second, it can be that first 0.5 seconds,
// full traffic was from port1, next 0.3 seconds, full traffic was from
// port2 and remaining 0.2 seconds traffic was from Port3
initial begin : the_init
automatic real sum;
forever begin : the_forever
while (window <= T) begin : the_while
@(posedge clk) if(gnt0) count0 += 1'b1;
if(gnt1) count1 += 1'b1;
if(gnt2) count2 += 1'b1;
window += 1'b1;
end : the_while
// Collected 1000 samplings, now check stats
// resets counts or let count increment for more samplings.
// weights 50 30 20
sum=count0+count1+count2;
a_stat0: assert (count0/sum < 0.505 && count0/sum > 0.495); // 50%
a_stat1: assert (count1/sum < 0.305 && count1/sum > 0.295); // 30%
a_stat2: assert (count2/sum < 0.205 && count2/sum > 0.195); // 20%
window = 0;
// reset the counts if needed
end : the_forever
end : the_init
task automatic t_reqgrnt();
if($countones({req0, req1, req2}) ==0) return; // <--- NEW
if($countones({req0, req1, req2}) ==1) begin : rq000
// provide grant to requester at next cycle
@ (posedge clk); // at next cycle
// could not use concurrent assertions because
// Concurrent assertions are not allowed in tasks/class methods
ap1_rq0: assert (gnt0 && $past(req0, 1, 1, @ (posedge clk)));
ap1_rq1: assert (gnt1 && $past(req1, 1, 1, @ (posedge clk)));
ap1_rq2: assert (gnt2 && $past(req2, 1, 1, @ (posedge clk)));
end : rq000
//more than one request
else if(req0 && !max0) begin : gnt0_only// grant1 and ++wgt0)
// req0 has higher priority, did not exhaust its percentage
wgt0 <= wgt0 + 1'b1;
if(max0==MAXWGT0) max0 <= 1'b1;
@ (posedge clk); // at next cycle
ap_gnt0_only: assert (gnt0 && !gnt1 && !gnt2);
end : gnt0_only
//
else if(req1 && !max1) begin : gnt1_only// grant1 and ++wgt1)
// req1 has higher priority, did not exhaust its percentage, req1 did
wgt1 <= wgt1 + 1'b1;
if(max1==MAXWGT1) max1 <= 1'b1;
@ (posedge clk); // at next cycle
ap_gnt1_only: assert (gnt1 && !gnt0 && !gnt2);
end : gnt1_only
//
else if(req2 && !max2) begin : gnt2_only// grant2 and ++wgt)
// req1 has higher priority, did not exhaust its percentage, req1 did
wgt2 <= wgt2 + 1'b1;
if(max2==MAXWGT2) max2 <= 1'b1;
@ (posedge clk); // at next cycle
ap_gnt2_only: assert (gnt2 && !gnt0 && !gnt1);
end : gnt2_only
//
else begin : allmaxed // max1=1, max2=0, max3=0 and grant1
// MISSING cases, check the algorithm
wgt0 <= 3'b001; // grant to gnt1
wgt1 <= 3'b000;
wgt2 <= 3'b000;
@ (posedge clk); // at next cycle
ap_gnt0_at_allmax: assert (gnt0 && !gnt1 && !gnt2);
end : allmaxed
endtask : t_reqgrnt
always_ff @(posedge clk) begin // emulate the assertion firing
fork
t_reqgrnt();
join_none
end
initial begin
repeat(200) begin
@(posedge clk);
if (!randomize(req0, req1, req2) with
{req0 dist {1'b1:=1, 1'b0:=1};
req1 dist {1'b1:=1, 1'b0:=1};
req2 dist {1'b1:=1, 1'b0:=1};
}) `uvm_error("MYERR", "This is a randomize error")
end
$finish;
end
endmodule
Ben Cohen
http://www.systemverilog.us/ ben@systemverilog.us
For training, consulting, services: contact Home - My cvcblr
- SVA Alternative for Complex Assertions
Verification Horizons - March 2018 Issue | Verification Academy
- SVA: Package for dynamic and range delays and repeats | Verification Academy
- SVA in a UVM Class-based Environment
SVA in a UVM Class-based Environment | Verification Horizons | Verification Academy