1

This is the code

module aks();

  initial begin
     rad temp ;
     temp = new;
     temp.fork_ll();

   end
endmodule

//This is Class Which is used in above module

class rad;
 task fork_ll();
     fork
          begin:MYLOOP
             $display("%t  %M:I AM HERE ",$time);
             disable SECOND;//I expected it should kill the SECOND BLOCk 
          end:MYLOOP
          begin:SECOND
               $display("%t  %M:STEP 2 ",$time);
               #10us $display("%t  %M:STEP3 ",$time);
          end:SECOND
     join
  endtask
endclass

I Expected the Output As

I AM HERE
STEP 2

But Actually i am getting Output as

0  $unit_0x5d440f27.rad.fork_ll.MYLOOP:I AM HERE 
           0  $unit_0x5d440f27.rad.fork_ll.SECOND:STEP 2 
       10000  $unit_0x5d440f27.rad.fork_ll.SECOND:STEP3 

Why disable SECOND is Not Killed the SECOND block of statement

toolic
  • 57,801
  • 17
  • 75
  • 117
Akshay Patil
  • 143
  • 2
  • 2
  • 10

2 Answers2

2

Execution order can be non-deterministic (within a scheduling region). Every simulator I have every used execute based on execution order and compiling order.

Verilog executes all code procedurally. It appears (mostly) concurrent because the Verilog scheduler multi-threads each procedural block. One procedural process will run at a time and will complete the procedure unless it is suspended with a blocking statement (#, @, wait).

In your case, MYLOOP finished before SECOND could ever start. There is nothing for disable to disable.

Here are some options:

Disable the task itself (SECOND will never start):

task fork_ll();
  fork
    begin : MYLOOP
      $display("%t  %M:I AM HERE ",$time);
      disable fork_ll;
    end
    begin : SECOND
      $display("%t  %M:STEP 2 ",$time);
      #10us $display("%t  %M:STEP3 ",$time);
    end
 join
 endtask

I AM HERE

Momentarily suspend MYLOOP with a #0 (use cautiously, #0 has is own race condition issues):

task fork_ll();
  fork
    begin : MYLOOP
      $display("%t  %M:I AM HERE ",$time);
      #0; // let other procedural blocks start, then continue
      disable SECOND; //
    end
    begin : SECOND
      $display("%t  %M:STEP 2 ",$time);
      #10us $display("%t  %M:STEP3 ",$time);
    end
 join
 endtask

I AM HERE
STEP 2

Use an event trigger:

task fork_ll();
  event e;
  fork
    begin : MYLOOP
      $display("%t  %M:I AM HERE ",$time);
      @(e); // let other procedural blocks start
      disable SECOND; //
    end
    begin : SECOND
      ->e; // unblock FIRST, SECOND is still active
      $display("%t  %M:STEP 2 ",$time);
      // ->e; // event trigger could be here too
      #10us $display("%t  %M:STEP3 ",$time);
    end
 join
 endtask

I AM HERE
STEP 2

Working examples here

Greg
  • 18,111
  • 5
  • 46
  • 68
1

As you can see in IEEE Std 1800-2012 (section 9.6.2 - Disable Statement):

If the block is not currently executing, the disable has no effect.

This code can solve your problem:

task fork_ll();
  fork
    begin
      $display("%t  %M:I AM HERE ",$time);
      #10;
    end
    begin
      $display("%t  %M:STEP 2 ",$time);
      #10us $display("%t  %M:STEP3 ",$time);
    end
 join_any
 disable fork;
 endtask

Another solution:

task fork_ll();
  fork
    begin: FIRST
      $display("%t  %M:I AM HERE ",$time);
      #1 disable SECOND;
    end
    begin: SECOND
      $display("%t  %M:STEP 2 ",$time);
      #10us $display("%t  %M:STEP3 ",$time);
    end
    join_any
 endtask

So, the output will be:

IAM HERE
STEP 2
antuirno
  • 396
  • 3
  • 8
  • Yes, I agree. But, maybe when the first block is executing the statement disable does not see that there is a SECOND block in the scope. If I change the order of the blocks I can remove the delay #1 and the code will work as expected. – antuirno Sep 09 '15 at 16:07