Here is a rule in SystemVerilog (SV) LRM that specifies how non-blocking statements in a begin-end block are executed. Consider the example shown below.
logic [3:0] y;
always @(posedge clock) begin
if (reset) begin
y <= 4'd0;
end else begin
y <= 4'd1; // line A
y <= 4'd2; // line B
y <= 4'd3; // line C
end
end
It would appear that there are three conflicting assignments to ‘y’ on lines A, B and C. The SV LRM clearly defines the effect of these three assignments, with the “source order” rule: The last assignment on line C will override the earlier ones, and hence ‘y’ will be assigned the value 4’d3.
From the SV LRM:
Statements within a begin-end block shall be executed in the order in which they appear in that begin-end block.
This applies to both blocking and non-blocking assignments in a sequential block. The following example shows how this rule is useful to initialize variables.
logic error;
always @(posedge clock) begin
if (reset) begin
state <= RX;
error <= 1'b0; // clear at reset
end else begin
error <= 1'b0; // clear error at the beginning of cycle
case (state)
RX: begin
if (rx_error) begin
error <= 1'b1; // set error
end else begin
// RX logic code
state <= TX;
end
end
TX: begin
if (tx_error) begin
error <= 1'b1; // set error
end else begin
// Rx logic code
state <= RX;
end
end
endcase
end
end