Electronic – Are Verilog if blocks executed sequentially or concurrently

hdlsequential-logicverilog

I'm learning Verilog with some background in VHDL and C. I would like to know if Verilog if blocks are executed concurrently or not, and if this is IDE- or vendor-dependent.

For example, are the following always equivalent or never equivalent, or sometimes equivalent, depending on something I'm not aware of?

always @ (posedge clk)
begin
    if (x == 1'b1) begin
        // do something
    end

    // possibly other code

    if (y == 1'b1) begin
        // do something else
    end

    // possibly other code
end

versus

always @ (posedge clk)
begin
    if (y == 1'b1) begin
        // do something else
    end

    // possibly other code

    if (x == 1'b1) begin
        // do something
    end

    // possibly other code
end

The if blocks and the "// possibly other code" chunks of code always execute sequentially, correct? My understanding is that the two blocks above should never be the same in Verilog because the line-by-line sequence is different.

I've read that "statements in procedural blocks are executed sequentially", implying that the code should be synthesized to execute in hardware line-by-line. However it is unclear to me if the blocks themselves are processed sequentially, and simulating with just one behavioral simulator doesn't address the question of how universal Verilog synthesis is supposed to be.

Best Answer

Sequentially. Statements within an always block are evaluated sequentially, doesn't matter if blocking or non blocking assignments are used - nonblocking assignments are simply deferred assignments, a subsequent nonblocking assignment to the same reg in the same always block will override the first. Same goes for if statements, you can define a "default" value with a blocking or nonblocking statement, then override it later in the same always block. Last assignment in the block wins.

Note that when I say "evaluated sequentially", this does not mean the lines are evaluated in hardware one at a time. If there are no data dependencies, they will effectively be evaluated in parallel, and then the ordering will determine the precedence. Each if statement condition gets converted to an enable signal, and this signal can then drive mux selects, enables, etc. The ordering simply determines which enable signal takes precedence.

The code examples that you have are perfectly valid synthesizable code. They may or may not be equivalent depending on how x and y are assigned (for example, if the values are changed with blocking statements in the same always block) or if the same regs are assigned in different sections of the code (the last assignment wins, no matter if blocking or nonblocking assignments are used).

Recently, I have taken to putting my reset code in an if statement at the bottom of sequential always blocks so I can preferentially reset what needs to be reset without extra dependencies on the reset signal (gating) that occur when you put the whole block in an if (rst) else block.