Overview

Execution block refers to the snippet of code which is altogather treated as a single thread or block which is executed by the simulator. Most of the time a verilog code will have plenty of execution blocks which are first compiled and then executed depending on the rules described in the IEEE Verilog LRM .

Procedural Block

This is the block of code inside which each and every line is treated a sequential command. So in essence, the simulator runs code inside the procedural block in a line by line fashion. Most of the code in verilog is treated as procedural in nature. The exception where they are threated as continous is mentioned in the next section. Some of the more commonly used keywords which act as the scope for procedural code blocks are mentioned below:-

always
forever
initial
begin
end

Continous Block

In this block, every line is treated as a independent and standalone thread. The system/simulator follows the rules of multi-threading and executed these lines of code in such a manner that they mimic parallel code execution.

Continous blocks or parallel execution of code can be achieved by either writing assign keyword in a module or by placing code inside fork-join block.

assign
fork
join

Theory Questions
    The simulator removes the variable once the end is reached. Beyond this, any access to this variable will cease to exist.
    always is a dedicated continous block while forever is a procedural block which is called inside procedural code.
    A therad is any independent call to a procedural code which is supposed to execute parallely with other threads. A good exmple is the fork-join code blocks which are all started parallely. In this case each code block will be considered an independent thread.
    No, the simulator only produces an "illusion" of parallalism, while running all codes sequentially behind the scene. This illusion is possible by the use of verilog scheduling regions .
    You can kill and ongoing thread, by making it a named block and then calling the disable {named_block} to kill it.
    A named block is just like any other executing block, with the added control of being able to kill the block with the uniqe name that was assigned to it.
    RHS is assigned to the LSH right away when the LHS value updates. This basically means that the simualtor will update RHS as many times as required in the time step provided the RHS is changing.
    As soon as the procedural code inside all the blocks/threads have reached their end, the fork comes to an end.
Coding Questions
    module top;
        
        initial
        begin
            $display("Before fork-join");            
            fork
                begin
                    $display("A");
                end
                begin
                    #3 $display("B");
                end
                begin
                    #2 $display("C");
                end
            join
            $display("After fork-join");
        end
    
    endmodule
    
    function integer palindrome_check_4D( integer num );
        if( num < 1000 || num > 9999 )
        begin
           return 0; 
        end
        else
        begin
           return ( (num%1000 == num/1000) && ((num/100)%10 == (num/10)%10) ) && 1; 
        end
    endfunction
    
    module top;
    
        integer i = 0;
    
        initial
        begin
            fork
                begin
                    for ( i = 0; i < 50000; i = i + 1 ) 
                    begin
                        if( palindrome_check_4D(i) )
                        begin
                            break;
                        end    
                    end
                end
            join
            $display("Final Value : %0d", i);
        end
    
    endmodule
    
    module top;
        
        initial
        begin
            fork
                begin : ONE
                    #6 $display("ONE Completed");
                    disable TWO;
                    disable THREE;
                end : ONE
                begin : TWO
                    #2 $display("TWO Completed");
                    disable THREE;
                    disable ONE;
                end : TWO
                begin : THREE
                    #5 $display("THREE Completed");
                    disable TWO;
                    disable ONE;
                end : THREE
            join            
            $display("fork-join Completed");
        end
    
    endmodule