SV之fork语句

目录

 

fork join

fork join_any

 fork join_none

wait fork

disable fork

always_combo

always_latch 

always_ff 


fork join

 fork...join内部的线程都会并行执行,直至处理完内部所有线程后才会结束块语句。

fork join 例子:

module fork_join;
 
  initial begin
    $display("-----------------------------------------------------------------");
    fork
      //-------------------
      //Process-1
      //-------------------
      begin
        $display($time,"\tProcess-1 Started");
        #5;
        $display($time,"\tProcess-1 Finished");
      end
 
      //-------------------
      //Process-2
      //-------------------
      begin
        $display($time,"\tProcess-2 Started");
        #20;
        $display($time,"\tProcess-2 Finished");
      end
    join
 
    $display($time,"\tOutside Fork-Join");
    $display("-----------------------------------------------------------------");
    $finish;
  end
endmodule

Process-1和Process-2将会同时开始运行,Process-1在5ns完成,Process-2在20ns完成.运行结果如下:

SV之fork语句_第1张图片

fork join_any

 fork...join_any语句块会阻塞statement-3的执行,直至fork..join_any语句块中的任意一个线程执行完(如上图中的proceess-2)后才能开始执行statement-3。

fork join any 例子:

module fork_join;
  initial begin
    $display("-----------------------------------------------------------------");
    fork
      //Process-1
      begin
        $display($time,"\tProcess-1 Started");
        #5;
        $display($time,"\tProcess-1 Finished");
      end
 
      //Process-2
      begin
        $display($time,"\tProcess-2 Started");
        #20;
        $display($time,"\tProcess-2 Finished");
      end
    join_any
 
    $display($time,"\tOutside Fork-Join");
    $display("-----------------------------------------------------------------");
  end
endmodule

 Process-1和Process-2将会同时开始运行,Process-1在5ns完成,Process-2在20ns完成.在执行fork..join_any语句块的同时,语句块后的$display语句也在执行。运行结果如下:

SV之fork语句_第2张图片

 fork join_none

 fork...join_none语句块不会阻塞statement-3的执行,即在执行fork...join_none语句块的同时也在执行statement-3.

 fork join none 例子:

module fork_join_none;
  initial begin
    $display("-----------------------------------------------------------------");
 
    fork
      //Process-1
      begin
        $display($time,"\tProcess-1 Started");
        #5;
        $display($time,"\tProcess-1 Finished");
      end
      //Process-2
      begin
        $display($time,"\tProcess-2 Startedt");
        #20;
        $display($time,"\tProcess-2 Finished");
      end
    join_none
  
    $display($time,"\tOutside Fork-Join_none");
    $display("-----------------------------------------------------------------");
  end
endmodule

在执行fork块语句的同时,语句块后面的$display语句也在执行,运行结果如下:

SV之fork语句_第3张图片

wait fork

 直至处理完fork块中的线程,程序才会往下执行,也就是将程序阻塞在fork块这里,直到fork块执行完。例子如下:

module wait_fork;
 
  initial begin
    $display("-----------------------------------------------------------------");
 
 
    fork
      //Process-1
      begin
        $display($time,"\tProcess-1 Started");
        #5;
        $display($time,"\tProcess-1 Finished");
      end
 
      //Process-2
      begin
        $display($time,"\tProcess-2 Started");
        #20;
        $display($time,"\tProcess-2 Finished");
      end
    join_any
 
   $display("-----------------------------------------------------------------");
$finish; //ends the simulation
  
  end
endmodule

上面的例子在5ns执行完process-1后,fork块将不会阻塞,在执行fork块内的process-2的同时,开始执行块后的$display语句,当遇到$finish时会结束程序的执行,导致 process-2被迫中途停止执行。运行结果如下:

SV之fork语句_第4张图片

解决上述问题的办法就是在fork块语句后添加wait fork语句,它会等待fork语句块内的所有线程执行完毕后,才会继续往下执行。修改后的代码如下:

module wait_fork;
 
  initial begin
    $display("-----------------------------------------------------------------");
 
    fork
      //Process-1
      begin
        $display($time,"\tProcess-1 Started");
        #5;
        $display($time,"\tProcess-1 Finished");
      end
 
      //Process-2
      begin
        $display($time,"\tProcess-2 Started");
        #20;
        $display($time,"\tProcess-2 Finished");
      end
    join_any
    wait fork; //waiting for the completion of active fork threads
     
    $display("-----------------------------------------------------------------");
    $finish; //ends the simulation
  end
endmodule

运行结果如下:

SV之fork语句_第5张图片

disable fork

终止正在执行的fork语句块。看下面的例子:

module disable_fork;
 
  initial begin
    $display("-----------------------------------------------------------------");
 
    //fork-1
    fork
      //Process-1
      begin
        $display($time,"\tProcess-1 of fork-1 Started");
        #5;
        $display($time,"\tProcess-1 of fork-1 Finished");
      end
       
      //Process-2
      begin
        $display($time,"\tProcess-2 of fork-1 Started");
        #20;
        $display($time,"\tProcess-2 of fork-1 Finished");
      end
    join_any
 
    //fork-2
    fork
      //Process-1
      begin
        $display($time,"\tProcess-1 of fork-2 Started");
        #5;
        $display($time,"\tProcess-1 of fork-2 Finished");
      end
      //Process-2
      begin
        $display($time,"\tProcess-2 of fork-2 Started");
        #20;
        $display($time,"\tProcess-2 of fork-2 Finished");
      end
    join_none   
 
    disable fork;
     
    $display("-----------------------------------------------------------------");
      $display($time,"\tAfter disable-fork");
    $display("-----------------------------------------------------------------");
  end
endmodule

在执行完fork-1的process-1后开始执行后面的fork-2,由于fork-2为fork...join_none语句,不会发生阻塞,所以会继续执行下面的disable fork语句,在执行此语句后,中断所有的fork块,包括 fork-1的process-2和fork-2的process-1以及process-1的执行都被终止。运行结果如下:

SV之fork语句_第6张图片

always_comb

用于对组合逻辑建模,块内语句左边的变量不能在其他块中被赋值,例子如下:

module always_comb_process();

reg [7:0] sum,a,b;
reg       parity;

initial begin
  $monitor ("@%g a = %h b = %h sum = %h parity = %b", 
   $time, a, b, sum, parity);
  #1 a = 1;
  #1 b = 1;
  #5 a = 10;
  #1 $finish;
end

always_comb
begin : ADDER
  sum = b + a;
  parity = ^sum;
end

endmodule

SV之fork语句_第7张图片

 一不小心搞一个latch出来,always_comb会告诉综合工具,这里需要的是一个组合逻辑电路,从而报错

always_latch 

对组合逻辑的锁存器建模,例子如下:

module always_latch_process();

reg [7:0] sum,a,b;
reg       parity;
reg       enable = 0;

initial begin
  $monitor ("@%g a = %h b = %h sum = %h parity = %b", 
    $time, a, b, sum, parity);
  #2 a = 1;
  #2 b = 1;
  #2 a = 10;
  #2 $finish;
end

always #1 enable = ~enable;

always_latch
begin : ADDER
  if (enable) begin
    sum    <= b + a;
    parity <= ^(b + a);
  end
end

endmodule

SV之fork语句_第8张图片

always_ff 

对时序逻辑寄存器建模,块内的变量应该使用非阻塞赋值.例子如下:

module always_ff_process();

reg [7:0] sum,a,b;
reg       parity;
logic     clk = 0;
reg       rst = 0;

initial begin
  $monitor ("@%g clk = %b rst = %b a = %h b = %h sum = %h parity = %b", 
  $time, clk, rst, a, b, sum, parity);
  #1 rst = 1;
  #5 rst = 0;
  #2 a = 1;
  #2 b = 1;
  #2 a = 10;
  #2 $finish;
end

always #1 clk ++;

// use of iff makes sure that block does not get
// triggered due to posedge of clk when rst == 1
always_ff @(posedge clk iff rst == 0 or posedge rst)//使用iff保证在上升沿rst=1的情况,不会触发
begin : ADDER
  if (rst) begin
    sum    <= 0;
    parity <= 0;
    $display ("Reset is asserted BLOCK 1");
  end else begin
    sum    <= b + a;
    parity <= ^(b + a);
  end
end

// To show how iff affected in earlier code
always_ff @(posedge clk  or posedge rst)
begin
  if (rst) begin
    $display ("Reset is asserted BLOCK 2");
  end 
end

endmodule

SV之fork语句_第9张图片

你可能感兴趣的:(systemverilog)