SystemVerilog basics: parallel blocks fork-join, join_any, join_none (2)

Related Reading

SystemVerilog基础icon-default.png?t=N7T8https://blog.csdn.net/weixin_45791458/category_12517449.html


        In the first section, we discussed the fork-join block and the fork-join_any block in the parallel block and understood their differences. This article will continue to discuss the use of the fork-join_none block.

        The fork-join_none parallel block has the same statement parallelism properties as the ordinary fork_join parallel block, that is, the statements in the block are executed at the same simulation time, but it has a feature that does not hinder the execution of the parent thread at all. The following is the SystemVerilog standard explain.

         The general idea is that fork-join_none will not hinder the execution of the parent thread, which means that the parent thread can then execute other statements, but the standard still provides a certain degree of certainty. As the last sentence above says, fork The statements in the -join_none block will not be executed until the parent process encounters a blocking statement or the schedule ends.

        How to explain the above blocking statement? Does it mean blocking assignment<=? Actually no, the blocking statement here actually refers to a statement with procedural statement pre-timing control, that is, there is #, @ or wait before the statement. We will not discuss hereprocess statement pre-timing control related content, which can be found in previous articles (it is important to note that the timing here Controls include #0). Verilog Basics: Delay Model_verilog Delay Module-CSDN BlogThe article has been viewed and read 501 times, liked 13 times, and collected 34 times. Verilog basics column. _verilog delay modulehttps://blog.csdn.net/weixin_45791458/article/details/132579787?spm=1001.2014.3001.5502        Let’s take a look at a few An example to deepen our understanding of the fork-join_none block.

例1
`timescale 1ns/1ns 
module test();
initial begin
    $display("Out of fork join_none1");
    $display("Out of fork join_none2");
    fork
        $display("In fork join_none1");
        $display("In fork join_none2");
    join_none
    $display("Out of fork join_none3");
    $display("Out of fork join_none4");
end
endmodule

输出:
Out of fork join_none1
Out of fork join_none2
Out of fork join_none3
Out of fork join_none4
In fork join_none1
In fork join_none2

        The results of Example 1 show that the statements in the fork-join_none parallel block are executed at the end, because when the control flow executes to the fork-join_none parallel block, the fork-join_none parallel block will be skipped and the subsequent statements will be viewed. , until encountering a blocking statement or the end of the begin-end block (end of schedule), in Example 1 the end of the begin-end block ( Scheduling ends), the statements in the fork-join_none parallel block will be executed.

        Example 2 below shows another situation where a blocking statement is encountered.

例2
`timescale 1ns/1ns 
module test();
initial begin
    $display("Out of fork join_none1");
    $display("Out of fork join_none2");
    fork
        $display("In fork join_none1");
        $display("In fork join_none2");
    join_none
    $display("Out of fork join_none3");
    #1 $display("Out of fork join_none4");
end
endmodule

输出:
Out of fork join_none1
Out of fork join_none2
Out of fork join_none3
In fork join_none1
In fork join_none2
Out of fork join_none4

        When the control flow executes to #1 $display("Out of fork join_none4");thisblocking statement, the control flow will Go to execution of the statements in the fork-join_none parallel block. So the results show that the statements in the fork-join_none parallel block are executed at the end of the 0ns simulation time.

        Now a question arises, what happens when the parent thread of the fork-join_none parallel block is fork-join? Let's look at an example of this.

例3
`timescale 1ns/1ns 
module test();
initial fork
    $display("Out of fork join_none1");
    $display("Out of fork join_none2");
    fork
        $display("In fork join_none1");
        $display("In fork join_none2");
    join_none
    $display("Out of fork join_none3");
    #1 $display("Out of fork join_none4");
join
endmodule

         Why does Example 3 not directly give output? Because it does not have a definite output. The execution order of statements in the fork-join block is uncertain, so multiple situations may occur.

1. If the fork-join_none parallel block is scheduled after #1 $display("Out of fork join_none4");, the statements in the fork-join_none parallel block will not be executed until the end of the fork-end block scheduling, reflected in the output for

Out of fork join_none1 //前三个输出顺序是不定的
Out of fork join_none2
Out of fork join_none3
In fork join_none1     //这两个输出顺序是不定的
In fork join_none2    
Out of fork join_none4 //这个输出一定在最后(但它在fork-join_none并行块前调度)

2. If the fork-join_none parallel block is scheduled before #1 $display("Out of fork join_none4");, the statements in the fork-join_none parallel block will wait until #1 $display("Out of fork join_none4"); It will be executed when it is scheduled, and the reflected output is

Out of fork join_none1 //这五个个输出的顺序是不定的
Out of fork join_none2
Out of fork join_none3
In fork join_none1     
In fork join_none2    
Out of fork join_none4 //这个输出一定在最后(但它在fork-join_none并行块后调度)

       The output results of several common emulators are given below.

对于Mentor Modelsim SE,输出结果为
Out of fork join_none1
Out of fork join_none2
In fork join_none1
In fork join_none2
Out of fork join_none3
Out of fork join_none4
 
对于Aldec Riviera Pro,输出结果为
Out of fork join_none1
Out of fork join_none2
In fork join_none1
In fork join_none2
Out of fork join_none3
Out of fork join_none4
 
对于Cadence Xcelium,输出结果为
Out of fork join_none1
Out of fork join_none2
In fork join_none1
In fork join_none2
Out of fork join_none3
Out of fork join_none4
 
对于Mentor Questa,输出结果为
Out of fork join_none1
Out of fork join_none2
In fork join_none1
In fork join_none2
Out of fork join_none3
Out of fork join_none4
 
对于Synopsys VCS,输出结果为
Out of fork join_none1
Out of fork join_none2
Out of fork join_none3
In fork join_none1
In fork join_none2
Out of fork join_none4

        From the output results, it can be seen that Synopsys VCS seems to adopt the processing method of case 1, while other simulators use the processing method of case 2. This warns us not to write such confusing and uncertain code.

        ​ ​ ​ A slightly more complex example is shown below as a question. If you understand the above content, you should be able to predict its output.

例4
`timescale 1ns/1ns 
module test();
initial begin
    for (int j=0; j<3; j++) begin 
        fork
            $display(j);
        join_none
    end
end
endmodule

        Because the fork-join_none parallel block needs to wait for the parent thread's scheduling to end before executing, it does not directly display the output during iteration, but waits for the end of the for loop to encounter the end of the begin-end block (the end of scheduling).

        The output result is three 3's.

Guess you like

Origin blog.csdn.net/weixin_45791458/article/details/135036768