在 SystemVerilog 中,fork
和 join
块用于创建并行进程,disable fork
用来终止这些并行进程。然而,直接使用 disable fork
会杀死当前作用范围内所有的并行进程,影响过于广泛。为了避免这种情况,可以使用以下两种方法来限制 fork
的范围:为 fork
加别名,或使用 guard fork
。
方法一:给 fork
加别名
通过为 fork
块命名,可以在特定情况下使用 disable
语句仅禁用特定的 fork
,而不是所有 fork
。但要注意,某些仿真工具(如 Cadence 编译工具)不支持这种做法。
示例代码:
task A(int max_delay); fork: p1 // 给 fork 块加别名 p1 begin wait (tb_top.valid === 1); $display("@%0t: Detected valid", $realtime); end begin repeat (max_delay) #1ns; $display("@%0t: Time out!", $realtime); end join_any disable p1; // 仅禁用指定的 fork 块 p1 #100ns; endtask
关键点:
- 给
fork
块指定一个别名(如p1
),然后通过disable p1;
禁用这个特定的fork
,而不是所有并行块。 - 该方法在一些工具(如 Synopsys VCS)中有效,但在 Cadence 编译工具中可能不支持。
方法二:使用 guard fork
这种方法通过嵌套一个 fork
块(称为 guard fork
),使得 disable fork
仅影响这个特定的嵌套块。这样可以局限 fork
的影响范围。
task A(int max_delay); fork // 外层 guard fork begin fork // 内层 fork begin wait (tb_top.valid === 1); $display("@%0t: Detected valid", $realtime); end begin repeat (max_delay) #1ns; $display("@%0t: Time out!", $realtime); end join_any disable fork; // 仅禁用内层 fork 块 end join // 外层 guard fork 的结束 #100ns; endtask
关键点:
- 通过嵌套
fork
块的方式,disable fork;
仅作用于内层fork
,而不会影响其他并行进程。 - 这种方法与给
fork
加别名相比,更加通用,并且在不同工具上都能得到支持,避免了工具不兼容的问题。