A simple request/grant arbiter interface. All signals synchronous to clk, async active-low rst_n.
interface arb_if (input bit clk, input bit rst_n);
logic req; // requester asserts, holds until granted
logic gnt; // arbiter grants for exactly one cycle
logic [31:0] addr; // valid with req
logic busy; // arbiter cannot grant while high
logic err; // error pulse
logic [1:0] state; // 0=IDLE 1=ARB 2=GRANT 3=ERR
endinterface
I need to write one single assertion that covers both requirements-
Req1 - Every req gets a gnt within 1 to 5 cycles.
Req2 -gnt must never assert while busy is high. So if busy is high when req arrives, gnt shouldnt be asserted until busy drops.
Is this required ? It’s possible that req is asserted more than once ( 1st assertion → deasserted → 2nd assertion ) before the 1st gnt is asserted within 5 clocks of the 1st req
If the intention is to have a unique grant for each request, I believe Ben has a separate thread discussing this.
Keeping them as three separate assertions is usually easier to debug: each failure points to a specific requirement.
It’s easy to combine Req1 and Req2 into one assertion by and’ing the properties together. The third is a little harder because you’d have to create a local variable counter.
property Req1;
req |-> req until_with gnt;
endproperty
property Req2;
!(gnt && busy);
endproperty
property Req3;
int n;
($rose(req) && !busy, n = 0) |=>
((busy || !gnt && n< 4), n = n + (!busy && !gnt))[*0:$]
##1 (gnt && !busy && n <= 4) ##1 !gnt;
endproperty
assert property ( @(posedge clk) Req1 and Req2 and Req3; );