If you use the "bad" example above:
always @(posedge clk or negedge rst)
if(!rst)
q<=0;
if(clk) // WRONG!
q<=d;
...this will happen during simulation:
- clock rising edge -> process becomes executed, the "if(clk)" path of your statement becomes (so far so good)
- reset becomes low -> this is basically a reset falling edge -> process becomes executed, the "if(!rst)" path of your statement becomes executed -> reset (still good), but since the clock is still high, the "if(clk)" path is then also executed, virtually overriding the thing the "if(!rst)" path did!
- clock falling edge -> nothing happens (as expected)
- clock rising edge -> process becomes executed, again both paths become executed, as before - again, the reset has no effect!
- reset becomes high -> nothing happens (as expected)
- clock rising edge -> everything goes as usual
This is a consequence of how these non-blocking assignments ("<=") work in Verliog (it would be the same in VHDL, by the way). The reset still would have some effect
if it happens to arrive when the clock is low, but that might be even worse (it might appear to be non-deterministic).
I assume when both the rising clock edge and the falling reset edge happen at the very same time, then ModelSim might simply execute the block once, again ignoring the reset, as the effects of "q<=0" become overriden by the "q<=d" two lines below.
Now I didn't try what the synthesis tool would do, but I assume it would throw an error, as I don't see how such a construct can be implemented with a logic cell. You definitely won't get the expected result.
Best regards,
GooGooCluster