I am trying to write an assertion that should make sure that the clock is stable (frequency is constant) for 1us before a signal is asserted.
I have another faster reference clock which can be used to write the assertion. Is there any way to write the assertion when the expected clock period is not known?
import uvm_pkg::*; `include "uvm_macros.svh"
module top;
bit clk, a, go;
event e, e0, e1;
initial forever #5 clk=!clk;
/* I am trying to write an assertion that should make sure that the clock is stable
(frequency is constant) for 1us before a signal is asserted.
I have another faster reference clock that can be used to write the assertion.
Is there any way to write the assertion when the expected clock period is not known? */
let T=100ns; // or 1us
task automatic t_count();
int count;
fork
fork1: begin
-> e0;
forever begin
@(posedge clk) count += 1'b1;
end
//disable fork2;
end
fork2: begin
#T;
disable fork1;
-> e1;
end
fork3: begin
@(posedge a); // "a" signal is asserted.
disable fork1;
disable fork2;
end
join_any
$display("%t count= %d ", $realtime, count);
a_t_count: assert (count >9 && count < 11) else -> e;
endtask
always @(go) t_count();
initial begin
#35 go <= 1'b1;
#20 a <= 1'b1;
end
endmodule
In reply to Ankit Bhange:
A small variation to my model, plus an SVA assertion. Adjust the time when a==1.
import uvm_pkg::*; `include "uvm_macros.svh"
module top;
bit clk, a;
event e, e0, e1;
initial begin
#39;
forever #5 clk=!clk;
end
/* When clock starts running, signal A should be low for at least 1us.*/
let T=1000ns; // at 10ns/cycle then 100 clocks
task automatic t_count();
int count;
fork
fork1: begin
-> e0;
forever begin
@(posedge clk) count += 1'b1;
end
//disable fork2;
end
/* fork2: begin
#T;
disable fork1;
-> e1;
end */
fork3: begin
@(posedge a); // "a" signal is asserted.
disable fork1;
// disable fork2;
end
join_any
$display("%t count= %d ", $realtime, count);
a_t_count: assert (count >= 100) else -> e; // error
endtask
initial begin
a_aIS0: assert(a==1'b0); // "a" starts at 0
t_count();
end
property p_100before_a;
int v_count=0;
@(posedge clk) first_match((a==1'b0, v_count+=1'b1) [*1:$] ##1 $rose(a))
##0 v_count >=100;
endproperty
initial ap_100before_a: assert property(@ (posedge clk) p_100before_a );
initial begin
#1399 a <= 1'b1;
end
endmodule
logic CLK; //expected frequency is 100Mhz
logic stable_CLK;
realtime period;
realtime current_time;
task freq_monitor();
@(posedge CLK) current_time = $realtime;
@(posedge CLK) period = $realtime - current_time;
endtask
//reset period after waiting for 10 times CLK period after the last negedge of CLK
task reset_period;
fork begin
fork
begin
@(negedge CLK);
@(posedge CLK);
end
begin
#100ns; //10*period for 100MHz
period = 0;
end
join_any
disable fork;
end
join
endtask
initial forever freq_monitor();
initial forever reset_period();
//10000 because the ref_clk is 2GHz
assign stable_CLK = period <= 10000*1.01 && period >= 10000*0.99 ? 1 : 0;
property sig1_high_for_1us_before_sig2 (logic sig1, sig2);
disable iff (!rstb)
$rose(|sig1) && !sig2 |-> !sig2[*2000];
endproperty //sig1_stable_for_1us_before_sig2
//ref_clk is 2GHz
CLK_stable_for_1us_before_A: assert property (@(posedge ref_clk) sig1_high_for_1us_before_sig2 (stable_CLK , A));