Clock oscillator for testbench

https://www.sunburst-design.com/papers/CummingsSNUG2006Boston_SystemVerilog_Events.pdf
I was reading this paper and trying to understand the where put clock oscillator in module and program block and use why initial forever block and I pretty much convice about above things but my question comes when :

`define CLK_PERIOD 10
`timescale 1ns/1ps
module clock_oscillator();
  bit clk;
    begin 
      clk <= 0;
      forever 
        #(`CLK_PERIOD/2) clk = ~clk;
    end
  endmodule

This is recommended but this will also result in same thing
why this is not used

`define CLK_PERIOD 10
`timescale 1ns/1ps
module clock_oscillator();
  bit clk;
    begin 
      clk <= 0;
      forever 
        #(`CLK_PERIOD/2) clk <= ~clk;
    end
  endmodule

And when generating using always with NBA why blocking assignment is not used?

always
#5 clk = ~clk;

why not this way?

Please format your code making your code easier for others to read. I have done that for you.

Nonblocking assignments are used to prevent race conditions between synchronous logic blocks. NBAs have higher overhead compared to regular blocking assignments, so they should only be used when absolutely necessary.

The clock signal is not in a race with any other process so regular blocking assignment should be used.

The reason initial/forever is used instead of always is when there are multiple clocks, as it’s easier to introduce a skew.

initial begin
   clk1 = 1;
   #2 forever #5 clk1 = ! clk1;
end
initial begin
   clk2 = 0;
   #4 forever #5 clk2 = ! clk2;
end

Hi Dave,
Although this is one of the things that one learns as an intern/fresher, I was never clear with the reason of using one over the other.

Nonblocking assignments are used when a signal is driven as well as read at the same instant (which is generally a clock tick). This prevents race conditions as the process reading the value would use sampled value and the signal would be updated with the new value( based on RHS ) in NBA region.

I am not clear on the above quote.

Although the clock is being driven (after CLK_PERIOD/2 delay) as well as read by DUT and Tb components ( via @(posedge clk) ), we want the newly assigned value to result in an event ( thereby unblocking @( … ) in DUT & Tb )
Is this also a valid reason for using blocking assignments to drive the clock ?

There’s no race condition with the process driving clk because the assignment that sets clk from 0 to 1 must precede any other process resuming from waiting for an @(posedge clk). This is because the posedge hasn’t occurred yet, so the waiting processes can’t come before the clock driving process.

Races occur when multiple processes wait for an @(posedge clk), and the order in which they resume is unpredictable.