Author Topic: Verilog blocking assignments  (Read 1278 times)

0 Members and 1 Guest are viewing this topic.

Offline tchicagoTopic starter

  • Regular Contributor
  • *
  • Posts: 110
  • Country: us
Verilog blocking assignments
« on: December 23, 2020, 02:07:04 am »
Hello, All, I have a kind of a beginner question.

I've implemented several FPGA small projects, but I still don't understand the semantics and the resulting implementations of a blocking assignment.

I.e. I always used the non-blocking assignments in the clocked always blocks, and used the binary logic wire variables, inline logic and if statements inside the always blocks to implement the combinatorial logic.

For example:

   wire pixelStrobe = (columnFrequencyDivider == 8'd0);
...   
   always @(posedge clock)
   begin
      if (hSyncTrigger)
         pixelCounter <= 10'd0;
      else if (pixelStrobe)
         pixelCounter <= pixelCounter + 10'd1;
   end

That approach pretty much satisfied all my hardware that I needed to implement, and I never understood the need for a blocking assignment. The non-blocking assignment gives a clear definition that what is the right side will be assigned after the execution and will be visible in the register in the next clock edge.

Yet I see bunch of examples where people use the blocking assignments inside the always(something) block, and I don't understand what hardware it generates.

For example, if you have regs reg1, reg2, reg3, reg4 then what hardware will this code generate?
always @(posedge clock)
begin
  reg1 = 1;
  reg2 = reg1;
  reg3 = reg2 | reg4 | reg3;
end

Will it force to use some kind of special flip-flops that open up and propagate values straight though the flip-flop while the clock is positive? I know there flip-flop types like in 74xx logic. But that would contradict the posedge statement.

 

Offline ataradov

  • Super Contributor
  • ***
  • Posts: 11260
  • Country: us
    • Personal site
Re: Verilog blocking assignments
« Reply #1 on: December 23, 2020, 02:23:44 am »
For really complex examples, yes, synthesizer may be forced to generate some strange sequential logic, or just give up and produce an error.  Although I don't even know if there are cases like this. I think it may be possible to always transform blocking  form to a non-bloking form.

Blocking vs non-blocking is more of a logical construct. As long as the end result is correct, it doers not matter how it is achieved.

In this case, the construction will just be translated into:
Code: [Select]
  reg1 <= 1;
  reg2 <= 1;
  reg3 <= 1; // (1 | reg4 | reg3)
« Last Edit: December 23, 2020, 02:25:47 am by ataradov »
Alex
 
The following users thanked this post: tchicago

Offline tchicagoTopic starter

  • Regular Contributor
  • *
  • Posts: 110
  • Country: us
Re: Verilog blocking assignments
« Reply #2 on: December 23, 2020, 02:51:52 am »
Thanks! So the blocking assignment is basically puts a burden on the compiler/synthesizer to decipher what I really wanted to do, even if it makes no sense. And if I make a mistake, it may work really hard and actually implement something complicated and unwanted :) So I guess I'll just keep avoiding this stuff.
 

Online SiliconWizard

  • Super Contributor
  • ***
  • Posts: 14476
  • Country: fr
Re: Verilog blocking assignments
« Reply #3 on: December 23, 2020, 06:20:37 pm »
I don't know a lot of Verilog, but aren't blocking assignments more or less equivalent to using variables in VHDL?
If so, then there can be a number of benefits. For instance, factoring expressions instead of having to duplicate code. Of course this is benefical from a designer's POV - there is no benefit from a low-level POV, you can always implement things without them.

Now I may not completely get what blocking assigments really are in Verilog, so if what I said above is not correct, please say so and possibly explain what they are... then I'll have learned something.
 

Offline ataradov

  • Super Contributor
  • ***
  • Posts: 11260
  • Country: us
    • Personal site
Re: Verilog blocking assignments
« Reply #4 on: December 23, 2020, 06:31:34 pm »
Conversely, I don't know any VHDL, so I have no idea how variables behave there.

The difference between them is how they are evaluated. The blocking assignments are evaluated in order, as if all those statements happened to execute in the order they are written. So
Code: [Select]
  reg1 = other_value;
  reg2 = reg1;
would assign other_value to both reg1 and reg2.

Non-blocking assignments are all executed at the same time. This matches more what you would expect from the real hardware if you were to draw the actual schematic.So the code
Code: [Select]
  reg1 <= other_value;
  reg2 <= reg1;
would assign other_value to reg1 and the old value of the reg1 to reg2, since at the time of the left side evaluation other_value is not yet written to the reg1.

It is possible to use both version to describe the same exact logic, but non-blocking follows the actual hardware if you were to build it using discreet logic, so this is why it is recommended to be used for real code. It is just way easier to think about data transfer form register to register on each clock edge.
Alex
 

Offline asmi

  • Super Contributor
  • ***
  • Posts: 2733
  • Country: ca
Re: Verilog blocking assignments
« Reply #5 on: December 23, 2020, 07:06:53 pm »
Blocking assignments create combinatorial logic. They can also create latches in certain situations. As I use SystemVerilog, I tend to isolate combinatorial logic in always_comb block(s), while sequential logic goes into clocked blocks (always_ff blocks). This way synthesizer (or simulator) will issue a warning if a latch is being inferred inside the always_comb block (that expression is a hint to parser that latches are NOT intended, there is always_latch hint for that).

Blocking assignments by themselves are rather useful as they can make code easier to read - and since code is read much more often that it is written, the effort is worth it. Here is the very simple example:
val_a_times_5 <= (val_a << 2) + val_a;
vs
val_a_times_4 = val_a << 2;
<....>
val_a_times_5 <= val_a_times_4 + val_a;

They can also be used as "aliases" for subexpressions, if they are used in multiple expressions - though care needs to be used here because it's easy to introduce a critical path by nesting too much logic for a single clock cycle.

Online SiliconWizard

  • Super Contributor
  • ***
  • Posts: 14476
  • Country: fr
Re: Verilog blocking assignments
« Reply #6 on: December 23, 2020, 07:23:23 pm »
Conversely, I don't know any VHDL, so I have no idea how variables behave there.

The difference between them is how they are evaluated. The blocking assignments are evaluated in order, as if all those statements happened to execute in the order they are written. So
Code: [Select]
  reg1 = other_value;
  reg2 = reg1;
would assign other_value to both reg1 and reg2.

Non-blocking assignments are all executed at the same time. This matches more what you would expect from the real hardware if you were to draw the actual schematic.So the code
Code: [Select]
  reg1 <= other_value;
  reg2 <= reg1;
would assign other_value to reg1 and the old value of the reg1 to reg2, since at the time of the left side evaluation other_value is not yet written to the reg1.

So yes, this looks exactly like VHDL variables.
And as I said, they are mainly a convenience. This allows you to split expressions in a more readable way, and/or factor expressions.

Simple example (VHDL, but that should be exactly the same with Verilog using the right syntax - VHDL variable assignment is ":="):

C := A and B;
F <= C or D;
G <= E xor C;

Not only does it save you from duplicating "A and B" here, but C may actually have a meaning in itself in your design, and if it later changes to another expression, the rest of the code is unchanged. Guess you see the idea.
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf