System Verilog学习笔记—fork...join_xxx的三种用法及wait fork和disable fork

目录

0.前言 

1.fork...join

2.fork...join_any

3.fork...join_none 

4.其它线程执行语句

4.1wait fork

4.2 disable fork 


0.前言 

可以用以下图来表示三者的区别:

1.fork...join

fork...join使内部所有线程同时开始运行,直到内部所有线程运行完毕后才跳出fork...join块儿。

 下面我们以代码详细理解:

module test();
    initial begin
        $display("%t:AAAA",$time);//0
        #10 $display("%t:BBBB",$time);//10

        fork//10
            $display("%t:CCCC",$time);10
            #50 $display("%t:DDDD",$time);//10+50=60
            #10 $display("%t:EEEE",$time);//10+10=20
            begin//10,里面的线程顺序执行
                #30 $display("%t:FFFF",$time);//10+30=40
                #10 $display("%t:GGGG",$time);//40+10=50
            end
        join
        $display("%t:HHHH",$time);//60
        #80 $display("%t:IIII",$time);//60+80=140
    end
endmodule

/*仿真结果:
  0:AAAA
 10:BBBB
 10: CCCC
 20: EEEE
 40: FFFF
 50: GGGG
 60: DDDD
 60: HHHH
140: IIII */

2.fork...join_any

 fork...join_any使内部所有线程同时开始运行,只要有一个线程运行结束就跳出 fork...join_any块儿。

需要注意的是,当跳出 fork...join_any块儿后,里面的线程并行的和块儿外的线程运行

module test();
    initial begin
        $display("%t:AAAA",$time);//0
        #10 $display("%t:BBBB",$time);//10

        fork//10
            $display("%t:CCCC",$time);//10,执行完该线程后跳出去
            //后面的线程和块儿后的线程并行执行
            #50 $display("%t:DDDD",$time);//10+50=60
            #10 $display("%t:EEEE",$time);//10+10=20
            begin//10,里面的线程顺序执行
                #30 $display("%t:FFFF",$time);//10+30=40
                #10 $display("%t:GGGG",$time);//40+10=50
            end
        join_any
        $display("%t:HHHH",$time);//10
        #80 $display("%t:IIII",$time);
    end
endmodule

/*仿真结果:
  0:AAAA
 10:BBBB
 10: CCCC
 10: HHHH
 20: EEEE
 40: FFFF
 50: GGGG
 60: DDDD
140: IIII */

3.fork...join_none 

 fork...join_none运行开始后,里面的子线程并行的和块儿外的线程运行

module test();
    initial begin
        $display("%t:AAAA",$time);//0
        #10 $display("%t:BBBB",$time);//10

        fork//10
            $display("%t:CCCC",$time);//10
            #50 $display("%t:DDDD",$time);//10+50=60
            #10 $display("%t:EEEE",$time);//10+10=20
            begin//10,里面的线程顺序执行
                #30 $display("%t:FFFF",$time);//10+30=40
                #10 $display("%t:GGGG",$time);//40+10=50
            end
        join_none
        $display("%t:HHHH",$time);//10
        #20 $display("%t:IIII",$time);/10+20=30
    end
endmodule

/*仿真结果:
  0:AAAA
 10:BBBB
 10: HHHH
 10: CCCC
 20: EEEE
 30: IIII
 40: FFFF
 50: GGGG
 60: DDDD */

4.其它线程执行语句

4.1wait fork

 该语句会等待前面的所有fork语句执行完毕后才会继续执行后面的语句:

module test();
    initial begin
        fork//0
            #10 $display("%t:A",$time);//10
            #20 $display("%t:B",$time);//0+20=20
        join_any

        fork//10
            #5 $display("%t:C",$time);//10+5=15
            #25 $display("%t:D",$time);//10+25=35
        join_none
        wait fork;
        ······
    end
endmodule

/* 仿真结果:
10:A
15:C
20:B
35:D
······ */

4.2 disable fork 

 停止当前fork线程中未被执行的所有子线程,当然如果是fork...join_none后接disable fork,里面的线程会全部被杀掉。

module test();
    initial begin
        fork
            #10 $display("%t:A",$time);
            #20 $display("%t:B",$time);
            #5 $display("%t:C",$time);//5,跳出
        join_any
        disable fork;//杀掉AB,继续执行D
        #10 $display("%t:D",$time);//15
    end
endmodule

### SystemVerilog 中 `fork...join_none` 结合 `disable fork` 的使用 在SystemVerilog中,当使用 `fork...join_none` 创建并发进程时,父线程不会被阻塞,并且可以继续执行其他操作[^4]。为了提前终止由 `fork...join_none` 启动的所有子线程及其自身的执行流程,可以采用 `disable fork` 命令。 #### 使用场景与语法说明 - **作用**:`disable fork` 可用于立即终止当前线程以及所有由此线程启动的子线程,这有助于清理不再需要的任务或响应特定条件下的异常情况[^2]。 - **语法结构**: ```systemverilog fork // 子线程A逻辑... // 子线程B逻辑... // 更多并行任务... join_none // 主线程后续处理... if (some_condition) begin disable fork; end ``` 上述代码展示了如何定义多个并行运行的任务,在满足某个条件下调用 `disable fork` 来停止所有的子线程活动。 #### 实际案例分析 考虑下面的例子,其中包含了两个独立工作的子线程,如果检测到错误信号,则会触发 `disable fork` 终止所有正在运行中的子线程: ```systemverilog module example; initial begin bit error_detected = 0; fork forever @(posedge clk) begin : proc_A $display("Process A is running."); if(/* some condition */) begin error_detected = 1; end end repeat(5) @(posedge clk) begin : proc_B $display("Process B runs %d times.", i++); end join_none while (!error_detected) @ (posedge clk); $display("Error detected! Disabling all processes..."); disable fork; // 当发现错误时禁用所有子线程 end endmodule ``` 在这个例子中,只要任意一个进程中设置了 `error_detected` 标志位为真,就会立刻执行 `disable fork` 并结束所有关联的子线程。
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值