Утверждение Systemverilog для проверки неверного перехода сигнала

Я пытаюсь написать утверждение, которое будет срабатывать, только если сигнал переходит на передний фронт clk. Я написал ниже код, чтобы проверить свои идеи

module test();

bit clk, clkb;
int d;

assign clkb = ~clk;

initial begin
   clk = 0;
   forever #100 clk = ~clk;
end

initial begin
   d = 10;
   #150 d = 20;
end

sva_d_chgd: assert property (@(posedge clk) $stable(d,@(clkb))) 
   else $error($psprintf("err: time = %0d, clk = %b, d = %0d", $time, clk, d));

always @ (d or clk) begin
   $display("time = %0d, clk = %b, d = %0d", $time, clk, d);
   if ($time > 200) $finish;
end
endmodule

Приведенный выше код возвращает следующий вывод в VCS:

time = 0, clk = 0, d = 10
time = 100, clk = 1, d = 10
"test.vs", 18: test.sva_d_chgd: started at 100s failed at 100s
        Offending '$stable(d, @(clkb))'
Error: "test.vs", 18: test.sva_d_chgd: at time 100
err: time = 100, clk = 1, d = 10
time = 150, clk = 1, d = 20
time = 200, clk = 0, d = 20
time = 300, clk = 1, d = 20
$finish called from file "test.vs", line 23.
$finish at simulation time                  300

Почему утверждение сработало в момент времени 100, когда d оставалось стабильным до момента 150?


person user2400361    schedule 04.05.2014    source источник


Ответы (1)


В вашем коде stable проверяет каждую позицию clk, чтобы увидеть, изменилось ли значение "d" между двумя предыдущими краями clkb. Поскольку в самой первой постановке clk не было предыдущего значения края clkb, равного «d», стабильный возвращает «unknown» вместо «true» или «false», что приводит к сбою вашего утверждения.

Я добавил в ваш код сигнал сброса и отключил утверждение до тех пор, пока не будет выполнена первая постановка clk. Я тоже двигался при изменении "d".

module test();

bit clk, clkb, rst;
int d;

assign clkb = ~clk;

initial begin
   clk = 0;
   forever #100 clk = ~clk;
end

initial begin
   rst = 1;
   #150 rst = 0;
end

initial begin
   d = 10;
   #250 d = 20;
end

sva_d_chgd: assert property (@(posedge clk)
                            disable iff (rst)
                            $stable(d,@(clkb))) 
   else $error($psprintf("err: time = %0d, clk = %b, d = %0d", $time, clk, d));

always @ (d or clk) begin
   $display("time = %0d, clk = %b, d = %0d", $time, clk, d);
   if ($time > 400) $finish;
end
endmodule

Вот результат:

# time = 0, clk = 0, d = 10
# time = 100, clk = 1, d = 10
# time = 200, clk = 0, d = 10
# time = 250, clk = 0, d = 20
# time = 300, clk = 1, d = 20
# ** Error: err: time = 300, clk = 1, d = 20
#    Time: 300 ns Started: 300 ns  Scope: test.sva_d_chgd File: assert_test.sv Line: 26
# time = 400, clk = 0, d = 20
# time = 500, clk = 1, d = 20
# ** Note: $finish    : assert_test.sv(30)
#    Time: 500 ns  Iteration: 1  Instance: /test

Это позволяет избежать первого нежелательного отказа вашего утверждения, но я думаю, что способ, которым вы закодировали свое утверждение, на самом деле все еще не улавливает условие, которое вы ищете.

person Ciano    schedule 05.05.2014
comment
Спасибо, что указали на проблему сброса, но почему утверждение все еще срабатывает неправильно? В момент времени 300 d все еще имеет значение 20, так почему сработало утверждение? - person user2400361; 05.05.2014
comment
Вы оцениваете свое утверждение при каждом щелчке по постановке. На 300 нс (posedge clk) d изменилось на 250 нс, что находится между 200 и 300 нс краями clkb, поэтому ваше утверждение оценивается как ложное. Есть смысл? - person Ciano; 05.05.2014
comment
Да. Я ошибался насчет того, как работает $ stable - person user2400361; 06.05.2014