Search code examples
verificationsystem-veriloguvm

Output skew when using clocking blocks


I am using a clocking block in my interface for signal aliasing. I want to concatenate some of the bits together to form a bus, and then drive this bus from my driver. So, for example:

interface bus_intf (clk);
    input logic      clk;
          logic[1:0] x_lsb;
          logic[1:0] x_msb;

   clocking driver_bus @(posedge clk)
      default input #1step output #0;
      output x_bus = {x_msb, x_lsb};
   endclocking
endinterface

Now the problem with this is, in one of my assertions, I need to read bus_intf.driver_bus.x_bus. As stated in the SV manual, an output variable from a clocking block should not be read by the testbench, and if it is, then simulator spits out an error (or warning in my case).

So I modified the interface:

interface bus_intf (clk);
    input logic      clk;
          logic[1:0] x_lsb;
          logic[1:0] x_msb;

   clocking driver_bus @(posedge clk)
      default input #1step output #0;
      inout x_bus = {x_msb, x_lsb};
   endclocking
endinterface

The problem now is, in my waveform I see two signals being created - x_bus and x_bus__o. I understand why Questasim did this - it is to separate the inout declaration so I can view both versions. However, the problem now is all my clocking drive is delayed by one clock cycle! so x_bus__o which is connected to the DUT is one clock cycle later than x_bus. This is inspite of me explicitly stating that output skew is #0.

Any idea why this happens? Am I doing something wrong or have I misunderstood?


Solution

  • I've put your code on EDAPlayground and tried it out. It seems to be working as expected. Here's my test harness:

    module top;
      bit clk;
      always #1 clk = ~clk;
    
      bus_intf busif(clk);
    
      initial begin
        @busif.driver_bus;
        $display("time = ", $time);
        busif.driver_bus.x_bus <= 'hf;
    
        repeat (2)
          @(negedge clk);
        $display("time = ", $time);
        busif.driver_bus.x_bus <= 'ha;
    
        #100;
        $finish();
      end
    
      always @(busif.x_lsb)
        $display("time = ", $time, " x_lsb = ", busif.x_lsb);
    
      always @(busif.x_msb)
        $display("time = ", $time, " x_msb = ", busif.x_msb);
    endmodule
    

    The link is here if you want to try it online: http://www.edaplayground.com/x/Utf

    If I drive x_bus at a posedge, then the value will be written immediately, as would be expected due to the #0 output delay. If I drive x_bus at a negedge (or at any other time aside from a posedge), then it will wait until the next posedge to drive the value. I see this behavior regardless of whether x_bus is declared as output or inout.

    Check to see when you are scheduling your writes; this might be the reason you see some delays on your waves.