6
\$\begingroup\$

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.

\$\endgroup\$
2
  • \$\begingroup\$ I would not break my head over it as that code should not be used at all. In a posedge clock block you should only use non-blocking assignments. \$\endgroup\$
    – Oldfart
    Oct 8, 2018 at 15:37
  • \$\begingroup\$ I think you may have confused the issue by assigning 1'b1 to the first variable. I don't think that was your intention. \$\endgroup\$
    – dave_59
    Oct 8, 2018 at 16:18

3 Answers 3

10
\$\begingroup\$

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.

\$\endgroup\$
3
\$\begingroup\$

Your second code block is equivalent to

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

It might be synthesized as 3 flip-flops, all with inputs tied to logic high.

Or it might just be synthesized as a single flip-flop, with all other logic that is connected to r_Test_1, r_Test_2, or r_Test_3 actually being connected to the same physical circuit net (assuming fan-out requirements can still be met this way).

That said, I agree with the comment by Oldfart. Stick to non-blocking assignment for synthesizable sequential logic.

\$\endgroup\$
3
  • \$\begingroup\$ Ah alright. So I was right in thinking that it's a bit weird to synthesise that right? \$\endgroup\$ Oct 8, 2018 at 16:04
  • \$\begingroup\$ @AlfroJang80, this example should be easy for a computer to synthesize, but things like this could get confusing for a person to understand how it will synthesize if it gets more complex. Since most Verilog users are more used to seeing non-blocking assignments, it's better to stick to that convention. \$\endgroup\$
    – The Photon
    Oct 8, 2018 at 16:31
  • 1
    \$\begingroup\$ The rule to stick to is that the results of a blocking assignment in a sequential always block should only ever be read in that same always block, reading them from other always blocks leads to ambiguity. \$\endgroup\$ Oct 8, 2018 at 19:30
0
\$\begingroup\$

You first block is equivalent to parallel blocks

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

Which synthesizes into a chain of flops

You second sysnthesizes to

always @(posedge i_clock)  r_Test_3 <= 1'b1;

Which is one flop. This assumes there are no other references to the other variables outside the block.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.