Verilog does have drive strengths and built-in net-resolution functions: if=
one driver is driving a "strong 1" and another driver is driving a "weak 0=
" on the same net at the same time, the net will be resolved to a value of =
1 just the way you would expect. If you start specifying drive strengths y=
our code is generally not synthesizable, but it's OK to do it in testbenche=
s or simulation models, for example to model a pullup resistor on an open-d=
I'm not sure what you mean by "perfectly valid to set a net or a register t=
o multiple values in the code." Are you talking about sequentially in the =
same block of code, or driving your net/register from different blocks of c=
ode? Sequentially is totally OK. Like inside the same initial or always b=
my_reg =3D 0;
my_reg =3D 1;
Driving the same signal from multiple code blocks is usually considered not=
very good coding style and may not be handled by synthesis tools, but Veri=
log allows it.
When the same net is driven to different values at the same simulation time=
and the result depends on which order the code was executed, it's called a=
race condition. I do not recommend spending too much effort learning how =
Verilog simulators decide which to execute first -- better to learn to code=
so that it isn't left to chance, or use tools that find race conditions fo=
r you. The standard gives simulators a lot of leeway there and different s=
imulators will execute in a different order while all being correct.
A common coding style rule in Verilog is: if it's combinatorial, use blocki=
ng assignments. If it's a flip-flop, use non-blocking:
z =3D a & b; // blocking assignment "=3D"
always @(posedge clk)
z <=3D a & b; // non-blocking assignment "=3D>"