Search code examples
verilogsystem-verilog

Why does this simulate continuous assignment with delay of 2 as if had delay of 3


I have this system verilog code, that does continuous assignment for some simple operations with delays and a simple testbench with clocks.

`timescale 1ns/1ps

module delays(input logic a, b);
   logic bb, n1, n2;
   assign #1ns bb = ~b;
   assign #2ns n1 = bb;
   assign #2ns n2 = a & bb;
endmodule

module tb_delays ();
    reg a, b;

    delays mod(.a(a), .b(b));

    initial begin
        a <= 0;
        b <= 0;
    end

    always #4ns b <= ~b;
    always #2ns a <= ~a;
endmodule

I am running this and getting this result:

scheme1

I am getting the expected delay of 1ns for bb and then expected delay of 2ns for n1, but for some reason n2 changes it's x state to 1 only after 3ns after the value of bb have become known, instead of 2ns.

What's interesting is if I get rid of bb and have 2ns delay, then everything works as expected

module delays(input logic a, b); 
   logic n1, n2; 
   assign #2ns n1 = ~b; 
   assign #2ns n2 = a & (~b); 
endmodule

scheme2

And if I try to keep the same duration for the whole module, then n2 never gets out of the x state.

module delays(input logic a, b); 
   logic n1, n2; 
   assign #3ns n1 = ~b; 
   assign #3ns n2 = a & (~b); 
endmodule

scheme3

All of this behavior seems rather weird to me and I cannot understand if this is actually to be expected or is it a tool bug. But either way I suspect it have something to do with the duration of the clock and that it is close to the duration of the simulation of the module, because if I set the clocks to be slower, then everything starts to work properly.

`timescale 1ns/1ps

module delays(input logic a, b);
   logic bb, n1, n2;
   assign #1ns bb = ~b;
   assign #2ns n1 = bb;
   assign #2ns n2 = a & bb;
endmodule

module tb_delays ();
    reg a, b;

    delays mod(.a(a), .b(b));

    initial begin
        a <= 0;
        b <= 0;
    end

    always #8ns b <= ~b;
    always #4ns a <= ~a;
endmodule

scheme4

My guess is it has something to do with event scheduling, but I am quite unsure of that as I am not experienced in this area and because I don't want to have gaps in my understanding any help is really welcome.


Solution

  • This is known as the inertial delay model—the LHS cannot change faster than the delay on RHS.

    Basically, a continuous assignment can only have one pending scheduled update to the LHS at a time. In certain cases, a new scheduled update cancels the pending update.

    This is defined in section 10.3.3 Continuous assignment delays in the IEEE 1800-2017 SystemVerilog LRM

    There other kinds of delay models to choose from using a variety of different constructs.