Below are my requirements for clock gating assertion :
refclk toggles when both req and ack are asserted. I want to check for the refclk to be
gated or 0 during the other 3 situations,
ie ref = 0 and ack = 0;
ref = 0 and ack = 1;
ref = 1 and ack = 0;
I have another clock in my test bench to time this assertion, ie sclk. But my assertion
gets triggered @ every posedge of sclk and hence it fails until req and ack becomes zero.
In reply to foxtrot:
Your requirements are ambiguous.
Can you create a table or a better description of the requirements?
For example,
If ref = 0 and ack = 0 then …
// or is it “if($fell(ref) and ack”, or is it "if($fell(ack) …
…If(…) then …
…
You need to clarify the antecedents. It is OK (or even better) to have multiple small assertions.
With *!refclk throughout (!refClkReq && !refClkAck) [1:$];
are you trying to say
@(posedge sclk) $fell(req) |-> !refclk throughout (!Req ##[*1:$] !Ack);
Thethroughout operator specifies that a signal (expression) must hold throughout a sequence.
*( b throughout R ) is equivalent to ( b [0:$] intersect R )
For example, in the following handshake example, a req is honored with an acknowledge within the next 4 cycles. The ack is then followed at a later time by a done control signal. However, there is one additional requirement that throughout the time between the ack and done an enable signal must be asserted to drive a tri-state bus. That assertion can be expressed as follows. Figure 2.4.6 demonstrates a timing diagram that satisfies an assertion of this property.
Let me simplify and ignore other scenarios. I want the assertion to check for refclk to be gated when req and ack both are zero. Not at any edge, I want it to be level-triggered.
Btw, the assertion I posted earlier will not be useful in my case as it will get triggered at every posedge of sclk and I will see failures throughout my simulation. So, please suggest a better method.
In reply to foxtrot:
Below is my approach. Note my use of a delayed sysclk to be used in the concurrent assertion.
/* @(posedge sclk) $fell(req) |-> !refclk throughout (!Req ##[*1:$] !Ack);
I want the assertion to check for refclk to be gated when req and ack both are zero.
Not at any edge, I want it to be level-triggered.
req ack gate ref_clk
0 0 0 0
0 1 1 ==clk
1 0 1 == clk
1 1 1 == clk
*/
module top;
`include "uvm_macros.svh"
import uvm_pkg::*;
logic req, ack, ref_clk, gate, sysclk=0, sysclk1;
// gate is the enable for the ref_clk to equal the sysclk
// sysclk is the system clock
// sysclk1 is a delayed sysclk by 1ns; it is used for the conccurrent assertion
// I delayed by 1ns to evaluate the signals after they settled from the gating.
initial forever #10 sysclk = !sysclk;
assign #1 sysclk1= sysclk;
always_comb begin // Operation of the ref_clk per the design
if(req==0 && ack==0) ref_clk=0;
else ref_clk = sysclk;
end
always_comb begin
if(req==0 && ack==0) gate=0; // logic for the gate, used in the verification
else gate = 1'b1;
end
always_comb begin // check on the gate
p_ref: assert final (gate==(req || ack));
end
// concurrent assertions on the ref clk
ap_ref_clk1: assert property(@ (sysclk1) gate |-> ref_clk==sysclk);
ap_ref_clk1b: assert property(@ (sysclk1) (req || ack) |-> ref_clk==sysclk);
ap_ref_clk0: assert property(@ (sysclk1) !gate |-> ref_clk==0);
initial begin
repeat (200) begin
@(posedge sysclk);
if (!randomize(req, ack) with {
req dist {1'b1 := 1, 1'b0 := 1};
ack dist {1'b1 := 1, 1'b0 := 2};
})
`uvm_error("MYERR", "This is a randomize error");
end
$finish;
end
endmodule