I have three states in FSM, and in each state different clocks are active. How do I write assertion to detect whether clocks are active are not? Note:- it should not be a temporal check (i.e it should not depend on posedge or negedge of the clock it should purely depend on the state)
In reply to sumanth291092:
- what is your definition of “clocks are active are not?”
Toggling for ever until state changes? - periods of the clock for each of the states?
I would approach this with separate concurrent tasks or fork-join task.
Have to think about it after I know more requirements.
In reply to ben@SystemVerilog.us:
I will give an example, I have two states s0 and s1, and three clocks clk1, clk2, clk3. In s0 state clk1 and clk2 are active, and in s1 state clk3 is active.
I need to fire an assertion when in state s0 if no clk is detected (in this case clk1 and clk2) and when in state s1 if clk33 is not detected.
But there is a catch there is no high lvl clk here controlling the FSM, so I can’t write assert (@posedge clk) or (@negedge clk)
In reply to sumanth291092:
Using the example where we address clk1 by itself.
The concept is to keep track of the clk1 being active or not active, then using an immediate assertion to check that if in ST0, the active1 variable is true.
http://systemverilog.us/vf/alive.sv // code with tb
http://systemverilog.us/vf/alive.png // image of code and simulation
3 parts to this code:
- An initial that fires a task and waits till it’s done
- A task with a fork join to see which forks finish first. If it’s the clock, then active==1, if it’s a #P1 then active1=0. done gets set, the e event is for debug
- The assertion. I used a #10 after the done before checking because of the asynchronous nature of when the state changes state and when I can relably detect if the clk1 is active.
Adjust this as needed. Other immediate assertions can be written based on state=ST1.
/* I have two states s0 and s1, and three clocks clk1, clk2, clk3.
In s0 state clk1 and clk2 are active, and in s1 state clk3 is active.
I need to fire an assertion when in state s0 if no clk is detected
(in this case clk1 and clk2) and when in state s1 if clk33 is not detected. */
module top;
timeunit 1ns; timeprecision 100ps;
// `include "uvm_macros.svh" import uvm_pkg::*;
typedef enum {ST0, ST1} st_t;
bit clk0=0,clk1, clk2, clk3;
bit active1, active2, active3;
st_t state;
bit done, err;
event e;
let P1=7; let P2=8; let P3=10; // periods of the clocks
initial forever #3 clk0 = !clk0; // for test
always_comb if (err) clk1=1'b0;
else if (state==ST0) clk1= clk0;
else clk1=1'b0;
initial forever begin : ALIVE1
t_clk1();
wait (done); //@ (done);
done=0;
end
task automatic t_clk1();
fork
PERIOD1: begin
#P1;
active1=1'b0;
disable CLOCK1; // ADDED
end
CLOCK1: begin
@(clk1);
active1=1'b1;
disable PERIOD1;
end
join_any
done=1; ->e;
endtask
always begin
@(posedge done);
#10 if(state==ST0) am_st0_clk1: assert(active1);
end
always begin // FSM
repeat(3) begin
#100 state= ST0;
#100 state=ST1;
end
end
initial begin
err=0;
#22 err=1; ; // error injection
#44 err=0;
end
endmodule
Ben Cohen
http://www.systemverilog.us/ ben@systemverilog.us
** SVA Handbook 4th Edition, 2016 ISBN 978-1518681448
…
- SVA Package: Dynamic and range delays and repeats SVA: Package for dynamic and range delays and repeats - SystemVerilog - Verification Academy
- Free books: Component Design by Example https://rb.gy/9tcbhl
Real Chip Design and Verification Using Verilog and VHDL($3) https://rb.gy/cwy7nb - Papers:
- Understanding the SVA Engine,
Verification Horizons - SVA Alternative for Complex Assertions
https://verificationacademy.com/news/verification-horizons-march-2018-issue - SVA in a UVM Class-based Environment
https://verificationacademy.com/verification-horizons/february-2013-volume-9-issue-1/SVA-in-a-UVM-Class-based-Environment
Udemy courses by Srinivasan Venkataramanan (http://cvcblr.com/home.html)
https://www.udemy.com/course/sva-basic/
https://www.udemy.com/course/sv-pre-uvm/
In reply to ben@SystemVerilog.us:
To kill any lingering threads on the fork activity tesryou should disable
disable CLOCK1 as shown below.
task automatic t_clk1();
fork
PERIOD1: begin
#P1;
active1=1'b0;
disable CLOCK1;
end
CLOCK1: begin
@(clk1);
active1=1'b1;
disable PERIOD1;
end
join_any
done=1; ->e;
endtask
In reply to ben@SystemVerilog.us:
A quick test on the fork-join_any and disable.
Note without the disable any forked tasks will linger on until completed
module top;
timeunit 1ns; timeprecision 100ps;
bit active1, done;
event e, e2;
initial begin : ALIVE1
$timeformat(-9, 0, " ns", 10);
#10;
$display ("%t t_clk1", $realtime);
t_clk1();
wait (done); //@ (done);
done=0;
#60 ->e2;
t_clk1();
wait (done); //@ (done);
done=0;
#1000 ->e2;
#4000 $finish;
end
task automatic t_clk1();
fork
PERIOD1: begin
#10;
active1=1'b0;
$display ("%t Period1", $realtime);
end
CLOCK1: begin
#100;
active1=1'b1;
$display ("%t CLOCK1 ", $realtime);
end
join_any
done=1; ->e;
disable t_clk1; // <******************* The disable of the fork *******
// Without the disable
/* 10 ns t_clk1
# 20 ns Period1
# 90 ns Period1
# 110 ns CLOCK1
# 180 ns CLOCK1 */
/* with the disable
10 ns t_clk1
# 20 ns Period1
# 90 ns Period1*/
endtask
endmodule