目录
fork join
fork join_any
fork join_none
wait fork
disable fork
always_combo
always_latch
always_ff
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完成.运行结果如下:
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语句也在执行。运行结果如下:
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语句也在执行,运行结果如下:
直至处理完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被迫中途停止执行。运行结果如下:
解决上述问题的办法就是在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
运行结果如下:
终止正在执行的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的执行都被终止。运行结果如下:
用于对组合逻辑建模,块内语句左边的变量不能在其他块中被赋值,例子如下:
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
一不小心搞一个latch出来,always_comb会告诉综合工具,这里需要的是一个组合逻辑电路,从而报错
对组合逻辑的锁存器建模,例子如下:
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
对时序逻辑寄存器建模,块内的变量应该使用非阻塞赋值.例子如下:
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