Electronic – How are blocking statements synthesised? – Verilog

verilog

I understand that with the following Verilog code

always @(posedge i_clock)
begin
    r_Test_1 <= 1'b1;
    r_Test_2 <= r_Test_1;
    r_Test_3 <= r_Test_2;
end

It uses non-blocking statements all in parallel and I understand that when this is synthesised, it's basically 3 registers in series and it takes 3 clock cycles for 1'b1 to reach r_Test_3.

But what about this,

always @(posedge i_clock)
begin
    r_Test_1 = 1'b1;
    r_Test_2 = r_Test_1;
    r_Test_3 = r_Test_2;
end

This uses blocking statements and so, all of this code should be performed in series. How exactly will this be synthesised? I mean will it be the exact same? I'm confused.

Best Answer

What makes VHDL and verilog somewhat confusing is that they were originaly designed to describe hardware for simulation and later re-used to describe hardware for synthisis.

I understand that with the following Verilog code

(snip code example using blocking assignments)

It uses non-blocking statements all in parallel and I understand that when this is synthesised, it's basically 3 registers in series and it takes 3 clock cycles for 1'b1 to reach r_Test_3.

Careful.

Remember the initial state of registers is undefined. As a result unless you have specified the initial state of the registers* it is very likely your synthisizer will optimise this to all your signals having a constant value of 1.

Lets for now pretend that you did set the initial state of the registers to zero and you just haven't included that in your example. In that case as you say there will be three registers set one after another on the first three clock edges.

But what about this,

(snip code example using blocking assignments)

This uses blocking statements and so, all of this code should be performed in series. How exactly will this be synthesised? I mean will it be the exact same? I'm confused.

As photon says that code is equivilent to.

always @(posedge i_clock)
begin
    r_Test_1 = 1'b1;
    r_Test_2 = 1'b1;
    r_Test_3 = 1'b1;
end

But none of that really answers your real question which boils down to.

How are blocking statements in sequential always blocks synthesised?

How a blocking statement in a sequential always block behaves and hence how it is synthisized depends on where you read it. There are three cases.

  • Same always block, read after write.
  • Same always block, read before write (or without a write on this invocation of the block).
  • Different always block.

In the first case, there is no need for a register (though one may be generated initially and then removed for having zero fanout). The signal just feeds through combinatorially.

In the second case the value needs to be stored from one clock cycle to the next, hence a register is needed.

Note that in some cases flow control may mean that a read is sometimes after a write and sometimes not, in that case the synthisis tool will need to generate a mux to either read from the register or directly from the logic as appropriate, just as it needs to generate muxes when a value is written on multiple different paths.

In the third case the behaviour is not well-defined. In simulation the results will depend on what order the always blocks are evaluated in. In synthisis the tool will probablly spit out a warning and do something, but what it does may not be what you wanted.

Hence you should avoid the third case, if you use blocking assignments in sequential always blocks you should only read the results of those assignments from within the same always block. Signals passing between different always blocks (or going out to the outside world) should always use nonblocking assignments.

* Unfortunately the ability to specify the initial state of registers is something that varies between tools (and versions of tools), some allow use of "initial" blocks for this purpose, some require tool-specific techniques, some don't support it at all.