verilog behavior changes with part name in iverilog
As I said in my comment, it looks like a race condition. Changing the name will not cause a race condition; but it could expose one.
Per the IEEE standard, Verilog can have nondeterministic execution within a scheduler event region (Verilog has 4 event regions: Active Events, Inactive Events, NBA Update, Monitored Events).

All versions of the Verilog and SystemVerilog LRMs has an example of a race condition: (IEEE1364-1995 &sect; 5.5, IEEE1364-2001 &sect; 5.5, ..., IEEE IEEE1800-2012 &sect; 4.8, IEEE-800-2017 &sect; 4.8)

assign p = q;
intial begin
  q = 1;
  #1 q = 0;
  $display(p);
end


$display(p) can output 0 or 1 and both are allowed. It is up to the compiler/simulator to decide update p first or display it first. In your case, changing the name seems to make the simulator choose different order of execution. The intention of the nondeterminism is an attempt to reflect the real hardware without talking delays into consideration.

Trying to pick names to get the order you want is not a solution. Any other changes to to the code, a different simulator or version, or ran on a different computer could expose the race condition again. The solution is to add intentional a well placed delay.

I set the timescale as `` timescale 1ns/100ps (the precision smaller) then defined my_not as:

module my_not #(parameter D=0.0)(output out, input in);
  assign #(D) out = ~in;
endmodule


Then changed: my_not q_not(out_bar, out); to my_not #(0.1) q_not(out_bar, out); to add a tiny delay. This creates a timing gap that allows all other evaluations to resolve to a deterministic value regardless of the evaluation order.

You can see my full code and run yourself with different simulations and version here: https://www.edaplayground.com/x/5eAp

I added the display statement in the my_2x1mux_helper definition to get an idea how often evaluations occur (there are noticeable differences between some simulators and versions).

Normal a flop is written as RTL with non-blocking assignment; like below. The non-blocking assignment postpones the update to q which prevents a race condition. With low level gate logic, delays need to be added to prevent zero-time feedback and race conditions.

always @(posedge clk)
  q &lt;= d;


For more detail, I recommend reading http://www.sunburst-design.com/papers/CummingsSNUG2006Boston_SystemVerilog_Events.pdf