# Verilog - Weird blocking/nonblocking problem

In the rst block in the following code I get a strange error whenever I use non-blocking assignment/ The State_SENDSYNC last for two cycles even though it's supposed to only last one cycle. Changing to blocking assignment fixes the problem, but I am baffled as to why. Shouldn't a mux get inferred either way?

always @(posedge clk, posedge rst) begin
if( rst ) begin
currentState <= State_IDLE;
nextState <= State_IDLE;
end else begin
currentState <= nextState;
end
end

always @(posedge clk) begin
nextState = currentState;
case( currentState )
State_IDLE: begin
if( laneOpen ) begin
nextState = State_SENDSYNC;
end
end
State_SENDSYNC: begin
nextState = State_SENDDATA;
end
State_SENDDATA: begin
if( !laneOpen ) begin
nextState = State_IDLE;
end
end
default: begin
nextState = State_IDLE;
end
endcase
end


nextState should be combination logic (i.e. no clock). What it have infers a mux with a 2 stage flip flop. To correct your design remove nextState <= State_IDLE; and replace always @(posedge clk) begin with always @(*) begin

The reason a non-blocking is delaying the state has to do with scheduling. Example:

a = 1;
b = a;
#1; // a is 1 and b is 1 (a is updated before assigning b)
a = 3;
b <= a;
#1; // a is 3 and b is 3 (a is updated before sampling for b)
a <= 4;
b <= a;
#1; // a is 4 and b is 3 (a is NOT updated before sampling for b)
a <= 5;
b = a;
#1; // a is 5 and b is 4 (a is NOT be updated before assigning b)


It is much clearer to have a value driven by no more than one process, which forces the designer to explicitly resolve driver priorities, rather than rely on implicit process scheduling rules. Verilog language guide probably details something like top-down by process order but It's not the kind of thing I would rely on.

You are also mixing blocking and non-blocking assignment to the same reg, which generally means the designer hasn't got a clear idea of the hardware being targeted: either register or combinatorial function.

Combine both always blocks into one always block. Don't mix blocking and non-blocking assignments for one signal. Also the simulator doesn't have a garantued order in which these blocks are executed during a rising edge!