Applying delay to logic in interface using heirarchy reference does not work

Hi guys, I am trying to understand on why applying delay to a logic in interface using hierarchical reference from top level does not seems to work. Searched online but could not able to find any material regarding this. Do you guys has any idea about this ?

Thank you


interface A;
 logic C;
 logic D;
endinterface

interface B;
 logic X;
endinterface


module tb;
 logic clk;
 A a1;
 B b1;

 initial clk=0;
 always #10 clk= ~clk;
 assign b1.X=clk;

 assign a1.C=b1.X; //working
 assign #1ps a1.D=b1.X; //not working

 //i tried to assign b1.X to a logic and then assign the delayed logic to a1.D and this method works
 logic temp;
 assign #1ps temp=b1.X;
 assign a1.D=temp;

endmodule


In reply to moganesh:

You need to explain what “working” and “not working” means.

In reply to dave_59:

Apologies for not describing the working/not working term


 assign a1.C=b1.X; //working
 assign #1ps a1.D=b1.X; //not working

working : a1.C value is same as b1.X
not working : here the value a1.D is “X”.

Once the delay is applied, the value become “X”.

In reply to moganesh:
But you never make an assignment to any variable except clk=0. So all variables remain ‘X’.

In reply to dave_59:

In reply to dave_59:

I am assigning clk to b1.X


assign b1.X=clk;

The output of a1.C value is same as clk


assign a1.C=b1.X

In reply to moganesh:

Sorry, I did not see that initially.

There are number of problems with your code. Aside from the typo when instantiating the two interfaces (missing ()'s), you did not specify a timescale, yet you have used a #10 delay for the clk with no time units, and then #1ps delay in the assign statement. That really should be an error, but most tools will be a default timescale of 1ns/1ns. Then #1ps becomes #0. If on the other hand the default timescale is smaller than 1ps, the continuous assignment statement has an inertial delay model and will not make an assignment if the RHS is changing faster than the delay on the LHS.

You should always specify a default timeunit and time precision and explicitly provide time units to all delays.

In reply to dave_59:
Thank you for the info Dave.
To be honest, I simplify the code for ease of understanding and there are typos’ and missing info here. Sorry for that.
In the actual top module, the timescale is defined as :

 timeunit 1fs
 timeprecision 1fs

As for the interface block, the timescale is not defined.

In the code below, the delay is not defined as #1ps. It is defined as #5000.

 assign #1ps a1.D=b1.X; 

And clk is not generated like that, it is actually from dut which is a basically a clock output with period 625ps.

I have revised and add the missing info.



interface A;
 logic C;
 logic D;
endinterface
 
interface B;
 logic X;
endinterface
 
 
module tb;
 timeunit 1fs;
 timeprecision 1fs;

 logic clk;
 A a1();
 B b1();
 
 dut d1(
   .....
   .out(b1.X), //output is clk with period 625ps
   .....
 );
 
 assign a1.C=b1.X; // once assign the a1.C has the value of b1.X which is dut.out: clk with period 625ps
 assign #5000 a1.D=b1.X; // The idea is to delay b1.X by 5ps and assign to to a1.D // but the a1.D has "X" value.
 
 //workaround: Delayed b1.X by 5ps and assigned to a temp logic, assign back the temp logic to a1.D  and this able accomplish the earlier idea

 logic temp;
 assign #5000 temp=b1.X; //here the temp value is delayed 5ps of the dut.out
 assign a1.D=temp; // the a1.D value is same as temp value
 
endmodule


In reply to moganesh:

It would help if you could provide a complete example of your problem. Perhaps you are mixing up a1 and b1.
Here is the complete example that works for me:

interface A;
 logic C;
 logic D;
endinterface
 
interface B;
 logic X;
endinterface
module dut(output logic clk);
   timeunit 1fs;
   timeprecision 1fs;
   initial clk=0;
   always #(625ps/2) clk++;
endmodule // dut

module tb;
   timeunit 1fs;
   timeprecision 1fs;
   
   logic clk;
   dut d(.clk);
 A a1();
 B b1();
 
 initial begin
    $printtimescale;
    $timeformat(-12,3,"ps",5);
    $monitor("%t a1.C: %b a1.D: %b",$time,a1.C,a1.D);
    #100ns $finish;
    end
 always #10ns clk= ~clk;
 assign b1.X=clk;
 
 assign a1.C=b1.X; //working
 assign #1ps a1.D=b1.X; //not working -- works for me
 
 //i tried to assign b1.X to a logic and then assign the delayed logic to a1.D and this method works
// logic temp;
// assign #1ps temp=b1.X;
// assign a1.D=temp;
 
endmodule

In reply to dave_59:

Thank you Dave for your time.
This is most of it. Except that I included the dut from earlier post and tie the interface logics’ to it for testing purpose.
Included the simulation result.


module clk_gen(output logic clk, clk1);
   timeunit 1fs;
   timeprecision 1fs;
   initial clk=0;
   initial clk1=1;
   always #(625ps/2) clk++;
   always #(625ps/2) clk1++;

endmodule // clk_gen

module fxhnd_tb;

  timeprecision 1fs;
  timeunit 1fs;
  `define NUM_SERDES 2

  import uvm_pkg::*;
  import fxhnd_tb_test_lib_pkg::*; 

  initial begin
   	if ($value$plusargs("CTS_TDAT_DEL=%s", cts_tdat_del))
		convert_str_to_time(cts_tdat_del,CTS_TDAT_DEL);
  	else 	CTS_TDAT_DEL=0;
      	if ($test$plusargs("DDLL_EN"))
		ddll_vif.ddll_en=1;
  end
	
  task convert_str_to_time(input string value, output time tValue);
         int value_size;
	value_size=value.len();

	case({value[value_size-2],value[value_size-1]})
	"ps": begin
		tValue=value.atoi() * 1ps;
		end
	"ns": begin
		tValue=value.atoi() * 1ns;
		end
	"us": begin
		tValue=value.atoi() * 1us;
		end

	endcase
  endtask

ddll_if ddll_vif();

for (genvar i=0; i<`NUM_SERDES; i=i+1) begin :serdes 

 datapath_if dpath_vif();
 clk_gen dut2(.clk(ddll_vif.tclk[i]),
              .clk1(ddll_vif.rclk[i])); 

 assign #(CTS_TDAT_DEL) dpath_vif.tclk = ddll_vif.tclk_o[i];
 assign dpath_vif.rclk = ddll_vif.rclk_o[i];

end

 initial begin
    $timeformat(-9, 2, "ns", 12);
    $monitor("%t serdes[0].dpath_vif.tclk:%b ; serdes[1].dpath_vif.tclk:%b  ",$time,serdes[0].dpath_vif.tclk, serdes[1].dpath_vif.tclk ); //added this
    run_test();
  end

endmodule

interface ddll_if;
 logic [`NUM_SERDES-1:0]  tclk_o;
 logic [`NUM_SERDES-1:0]  rclk_o;
 logic [`NUM_SERDES-1:0] tclk;
 logic [`NUM_SERDES-1:0] rclk;
 logic dll_out=1; //this is assigned from some other block at fxhnd_tb. right now, set this to 1 for testing purpose. 
 bit ddll_en=0;

 always_comb begin
  if(ddll_en)begin	
	for(int i=0; i<`NUM_SERDES;i++) begin
		tclk_o[i]=dll_out;
		rclk_o[i]=dll_out;
	end
  end else begin
	tclk_o=tclk;
	rclk_o=rclk;
  end
 end

endinterface

interface datapath_if;  
 import uvm_pkg::*;
 `include "uvm_macros.svh"

 logic rclk;
 logic tclk;

 //there are some other codes here but nothing is using tclk,rclk

endinterface


Simulation result:

Output from Console:

145625.00ps serdes[0].dpath_vif.tclk:0 ; serdes[1].dpath_vif.tclk:0
145937.50ps serdes[0].dpath_vif.tclk:1 ; serdes[1].dpath_vif.tclk:1
146250.00ps serdes[0].dpath_vif.tclk:0 ; serdes[1].dpath_vif.tclk:0
146562.50ps serdes[0].dpath_vif.tclk:1 ; serdes[1].dpath_vif.tclk:1
146875.00ps serdes[0].dpath_vif.tclk:0 ; serdes[1].dpath_vif.tclk:0
147187.50ps serdes[0].dpath_vif.tclk:1 ; serdes[1].dpath_vif.tclk:1
147500.00ps serdes[0].dpath_vif.tclk:0 ; serdes[1].dpath_vif.tclk:0
147812.50ps serdes[0].dpath_vif.tclk:1 ; serdes[1].dpath_vif.tclk:1
148125.00ps serdes[0].dpath_vif.tclk:0 ; serdes[1].dpath_vif.tclk:0
148437.50ps serdes[0].dpath_vif.tclk:1 ; serdes[1].dpath_vif.tclk:1
148750.00ps serdes[0].dpath_vif.tclk:0 ; serdes[1].dpath_vif.tclk:0
149062.50ps serdes[0].dpath_vif.tclk:1 ; serdes[1].dpath_vif.tclk:1
149375.00ps serdes[0].dpath_vif.tclk:0 ; serdes[1].dpath_vif.tclk:0
149687.50ps serdes[0].dpath_vif.tclk:1 ; serdes[1].dpath_vif.tclk:1

Simulation result after reset back to time 0

103125.00ps serdes[0].dpath_vif.tclk:0 ; serdes[1].dpath_vif.tclk:0
103437.50ps serdes[0].dpath_vif.tclk:1 ; serdes[1].dpath_vif.tclk:1
103750.00ps serdes[0].dpath_vif.tclk:0 ; serdes[1].dpath_vif.tclk:0
104062.50ps serdes[0].dpath_vif.tclk:1 ; serdes[1].dpath_vif.tclk:1
104375.00ps serdes[0].dpath_vif.tclk:0 ; serdes[1].dpath_vif.tclk:0
104687.50ps serdes[0].dpath_vif.tclk:1 ; serdes[1].dpath_vif.tclk:1
105000.00ps serdes[0].dpath_vif.tclk:0 ; serdes[1].dpath_vif.tclk:0
105312.50ps serdes[0].dpath_vif.tclk:1 ; serdes[1].dpath_vif.tclk:1
105625.00ps serdes[0].dpath_vif.tclk:0 ; serdes[1].dpath_vif.tclk:0
105937.50ps serdes[0].dpath_vif.tclk:1 ; serdes[1].dpath_vif.tclk:1
106250.00ps serdes[0].dpath_vif.tclk:0 ; serdes[1].dpath_vif.tclk:0