Hi
I’m very appreciated for helps if you can give some tips on this case.
there are two clocks ,clka(~100M),clkb (~10M), and two ‘x’ and ‘z’ signals.
defualt is:
clka toggle.
clkb not toggle
‘x’ is low
‘z’ is low
I need to implment a checker to check follow condition.
in clka toggle phase, set ‘x’ to high, then clkb should be toggled in 100T (unit is clka period) when ‘x’ is high
and ‘z’ should have raise a ack pulse (0-1-0) in clkb toggle phase.
then set set ‘x’ to low
then clkb should stop toggling in 100T (unit is clka period) when ‘x’ is low
and ‘z’ should have raise a similar pulse (0-1-0) in clkb toggle phase.
In reply to guorke:
Your requirements are ambiguous and hard to follow.
I suggest that you clarifyyour requirements wth waveforms and a start of a SystemVerilog template. for example,
// this is not an assrsionb just my noted
// in struggling to understand the requirements
module top;
timeunit 1ns/100ps;
`include "uvm_macros.svh"
import uvm_pkg::*;
bit clka, clkb, x, z;
default clocking @(posedge clka);
endclocking
initial forever #10 clk=!clk;
initial begin
$timeformat(-9, 1, "ns", 8);
$display("%t", $realtime);
end
/* I need to implment a checker to check follow condition.
in clka toggle phase, set 'x' to high, then clkb should be toggled in 100T (unit is clka period) when 'x' is high
and 'z' should have raise a ack pulse (0-1-0) in clkb toggle phase. */
always @(@(clka) begin
realtime v;
bit ten_ps;
x<=1'b1;
v=$realtime;
@(clkb) $realtime -v==10ps;
assert(z==0);
ap: assert property(@(clkb) ack ##1 !ack);
#100000;
/* then set set 'x' to low
then clkb should stop toggling in 100T (unit is clka period) when 'x' is low
and 'z' should have raise a similar pulse (0-1-0) in clkb toggle phase. */
x<=1'b0;
v=$realtime;
// clkb should stop toggling in 100T (unit is clka period) when 'x' is low
fork
begin #10ps; ten_ps=1; end// need to define the units
@(clkb);
join_any
assert(ten_ps);
end
In reply to guorke:
The key to defining a verification assertion (not necessarily with SVA) is to first define the 4 zones or envelopes of examinations http://systemverilog.us/vf/eobeoff.png
*From $rose(x) to ##0 x[100]
The endpoint of this sequence is identified with event e_on
*From $fell(x) to x[100]
The endpoint of this sequence is identified with event e_off
The clkb_region between e_on and e_off to check for clk_b
the envelope between e_on and fell(x) to check for a z
the envelope between fell(x) and e_off to check for a z
// The variables
bit clka, clkb, x, z; // clka(~100M),clkb (~10M)
event e_on, e_off;
logic clkb_region;
// The definition of e_on and e_off
// For this I used an assertion with sequence_match_items calling a function
unction set_event(bit on_off);
if(on_off) -> e_on;
else -> e_off;
endfunction
// Region definition
ap_x_100Tregion: assert property(
@(posedge clka)
$rose(x) |-> !clkb && $past(!clkb) ##0 x[*100] ##0(1, set_event(1'b1))
##[1:$] $fell(x) ##0 x[*100] ##0(1, set_event(1'b0)));
// The clkb_region
always @(e_on) clkb_region <= 1'b1;
always @(e_off) clkb_region <= 1'b0;
// The check clkb region for activity of the clkb
let half_p=55ns; // maybe 1 or 2 ns more for sync? FIX the number needed
always_ff @(e_on) begin
clkb_activity_check();
end
task automatic clkb_activity_check();
bit no_clkb;
fork
begin #half_p; no_clkb=1'b1; end
begin @clkb; no_clkb=1'b0; end // this should come first
join_any
assert(no_clkb==1'b0);
if(clkb_region) clkb_activity_check();
endtask
// The checks for z within their zones
// Check for Z at start of 100T
always @(e_on) begin
bit no_z;
fork
begin @(posedge z) no_z=1'b0; end
begin @(negedge x) no_z=1'b1; end
join_any
assert(no_z==1'b0);
end
// Check for Z at end of 100T
// Need to check if more than one, give it some thoughts
always @(neg_edge(x)) begin
bit no_z;
fork
begin @(z) no_z=1'b0; end
begin @(e_off) no_z=1'b1; end
join_any
assert(no_z==1'b0);
end
The complete untested code. I would like to see your final tested solution and your testbench.
module top;
timeunit 1ns/10ps;
`include "uvm_macros.svh"
import uvm_pkg::*;
bit clka, clkb, x, z; // clka(~100M),clkb (~10M)
event e_on, e_off;
default clocking @(posedge clka);
endclocking
initial forever #10 clka=!clka;
logic clkb_region;
// Ser clkb region envelope
always @(e_on) clkb_region <= 1'b1;
always @(e_off) clkb_region <= 1'b0;
function set_event(bit on_off);
if(on_off) -> e_on;
else -> e_off;
endfunction
// Region definition
ap_x_100Tregion: assert property(
@(posedge clka)
$rose(x) |-> !clkb && $past(!clkb) ##0 x[*100] ##0(1, set_event(1'b1))
##[1:$] $fell(x) ##0 x[*100] ##0(1, set_event(1'b0)));
// check clkb region for activity
let half_p=55ns; // maybe 1 or 2 ns more for sync?
always_ff @(e_on) begin
clkb_activity_check();
end
task automatic clkb_activity_check();
bit no_clkb;
fork
begin #half_p; no_clkb=1'b1; end
begin @clkb; no_clkb=1'b0; end
join_any
assert(no_clkb==1'b0);
if(clkb_region) clkb_activity_check();
endtask
// Check for Z at start of 100T
always @(e_on) begin
bit no_z;
fork
begin @(posedge z) no_z=1'b0; end
begin @(negedge x) no_z=1'b1; end
join_any
assert(no_z==1'b0);
end
// Check for Z at end of 100T
always @(neg_edge(x)) begin
bit no_z;
fork
begin @(z) no_z=1'b0; end
begin @(e_off) no_z=1'b1; end
join_any
assert(no_z==1'b0);
end
endmodule