disable语句不会在fork语句中杀死其他块

时间:2015-09-09 07:15:00

标签: verilog system-verilog

这是代码

module aks();

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

   end
endmodule

//这是在上面的模块中使用的类

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 AM HERE
STEP 2

但实际上我的输出为

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 

为什么禁用SECOND未被杀死的SECOND语句块

2 个答案:

答案 0 :(得分:2)

正如您在IEEE Std 1800-2012中所见(第9.6.2节 - 禁用声明):

  

如果当前没有执行该块,则禁用无效。

此代码可以解决您的问题:

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

另一种解决方案:

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

因此,输出将是:

IAM HERE
STEP 2

答案 1 :(得分:2)

执行顺序可以是非确定性的(在调度区域内)。我每次使用的每个模拟器都根据执行顺序和编译顺序执行。

Verilog在程序上执行所有代码。它(大多数情况下)似乎是并发的,因为Verilog调度程序多线程化每个程序块。一个程序流程将一次运行,并将完成该过程,除非它被阻止声明(#@wait)暂停。

在您的情况下,MYLOOPSECOND开始之前完成。 disable无法禁用。

以下是一些选项:

禁用任务本身(SECOND永远不会启动):

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
  

我在这里

使用MYLOOP暂时暂停#0(谨慎使用,#0有自己的竞争条件问题):

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
  

我在这里   第2步

使用事件触发器:

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
  

我在这里   第2步

工作示例here