Question about clocking block usage

I have a signal which needs to be driven/sampled from testbench. I have to drive the signal with respect to negedge of clock and sample it w.r.t posedge.

I have written follwoing code which is working fine but i would like to know whether it is a good coding style or not. (I didn’t negedge/posedge together because most of the driver code need to be driven w.r.t negedge)

interface a2b;
wire out;

clocking cb_pos @(posedge clk);
default input #0ns output #0ns;
inout out;
endclocking

clocking cb_neg @(negedge clk);
default input #0ns output #0ns;
inout out;
endclocking

modport tb(clocking cb_pos, clocking cb_neg);
endinterface

It’s OK to have the same signal in two different clocking blocks, but use input to only allow sampling the signal, and output to only allow driving the signal in each respective clocking block.

Also, do not use #0 for input sampling, use #1step or don’t specify a default at all. #1step is the implicit default and gives you the sampled value at the end of the last timestep.

Dave Rich
Mentor Graphics

In reply to ram007:

Use inout.

In reply to dave_59:

Hi Dave ,

I have a Moore FSM :

On detecting Reset High on posedge of clock , the FSM enters RESET state and de-asserts TxReady ( Active High signal ) either combinationally ( +define+B in below code ) OR sequentially ( +define+NBA in below code )

On detecting Reset Low on posedge of clock , the FSM enters TXWAIT state

I want to check inside the Monitor that on Entering RESET state the signal TxReady is low , else an Error would be reported



interface INTF ( input clk , input reset );

logic TxReady , TxValid ;

clocking cb_sample @(posedge clk );
default input #0 ; 
// Added Purposely to Check Updated Value on posedge of clk and Not b4 posedge 
input TxReady ;    // I want a checker on this !!
endclocking
 
modport tb ( clocking cb_sample   ) ;

endinterface

module FSM ( INTF i1 ) ;

parameter RESET = 0 , TXWAIT = 1  , SEND_SYNC = 2 ;

reg [1:0]  ps , ns ;

always @ ( posedge i1.clk )
begin

if ( i1.reset ) 
 begin

   ps <= RESET ;

`ifdef NBA // "NON_BLOCKING_ASSIGNEMNT"

       i1.TxReady <= 0 ;  // De-assert TxReady

`endif

 end
else
 begin
   
  ps <= ns ;

 end

end

// Output TxReady Combinational Logic

`ifdef B // "B"locking assignment to Tx_Ready
always @ ( ps )
begin

case(ps)

RESET:begin

       i1.TxReady = 0 ;  // De-assert TxReady
      
      end

endcase

end
`endif

endmodule



Inside the TOP FILE ::

bit CLK = 0 ;

bit RST = 0 ;

INTF intf ( .clk(CLK) , .reset(RST) ) ;

FSM  fsm ( .i1(intf) ) ;

 typedef enum bit [2:0]  {
                            DEFAULT       = 3'd0 ,
			    RESET_TX      = 3'b001,
                            TX_WAIT       = 3'b010,
			    SEND_SYNC     = 3'b011			    
			    .....
			 }  tx_device_state_e;
 
tx_device_state_e Tx_Dev_State ;

initial
begin

fork

begin

 forever 

  #5 CLK = ~CLK ;

end


begin

#50 ;
$finish();

end


join


end


initial begin

#7 RST = 1 ; 

#10 RST = 0 ; 


end


initial 
begin

forever @ (  intf.cb_sample )
         case ( Tx_Dev_State )
         
         DEFAULT:begin
                    
                     TX_WAIT_FOR_RESET_HIGH(); 
	          
		  end
         
	 RESET_TX:begin
                    
                     TX_WAIT_FOR_RESET_LOW(); 
	          
		  end

          endcase
       
end


task TX_WAIT_FOR_RESET_HIGH();

       $display($time ," XXXXX Inside task XXXX ");

fork 

 begin

  wait( RST == 1 );
  if ( intf.cb_sample.TxReady == 0  )
   begin
       $display(" XXXXX IT WORKS !!! XXXXX ");
   end
 else if ( intf.cb_sample.TxReady == 1  )
   begin        
        $display(" XXXXX ERROR XXXXX "); // An uvm_error would be flashed here 
        Tx_Dev_State =  RESET_TX ;
   end

 end

join 

endtask


Here is the Output I get :: 

 @5 XXXXX Inside task XXXX 
 @15 XXXXX Inside task XXXX 
 XXXXX IT WORKS !!! XXXXX    // Got what I wanted , but is it a Right way to Code ?? 
 @25 XXXXX Inside task XXXX 



LRM 14.4 Says :: Inputs with explicit #0 skew shall be sampled at the same time as their corresponding clocking event, but to avoid races, they are sampled in the Observed region

So in the Observed Region the Value of TxReady would always be Sampled 0
( either due to Blocking Assignment in Active Region OR NBA Region due to +define+NBA )

In reply to dave_59:

It’s OK to have the same signal in two different clocking blocks, but use input to only allow sampling the signal, and output to only allow driving the signal in each respective clocking block.
Also, do not use #0 for input sampling, use #1step or don’t specify a default at all. #1step is the implicit default and gives you the sampled value at the end of the last timestep.
Dave Rich
Mentor Graphics

Hi Dave,
Sorry if this question is too “basic”.
When you refer to “input”/“output”, do you mean the wire name or do you mean the skew sampling spec? I think you mean Example 2 below, please confirm.

Would this mean : Example 1:

interface a2b;
wire out;
 
clocking cb_pos @(posedge clk);
default output #1ns;
inout out;
endclocking
 
clocking cb_neg @(negedge clk);
default input #1ns;
inout out;
endclocking
 
modport tb(clocking cb_pos, clocking cb_neg);
endinterface

or Example 2 :

interface a2b;
wire out;
 
clocking cb_pos @(posedge clk);
default input #1ns output #1ns;
output out;
endclocking
 
clocking cb_neg @(negedge clk);
default input #1ns output #1ns;
input out;
endclocking
 
modport tb(clocking cb_pos, clocking cb_neg);
endinterface

In reply to UVM_learner6:

confirmed.