0

Here in this example,a non-blocking assignment propagates to a continuous assignment. Can this cause any execution paradigms.Please elaborate on this piece of code- Possible errors, How can it be removed and good style of coding.

  always @(posedge clk)
        dff1 <= f(x);

    assign fsm_in = f(dff1);
    assign fsm_out = fsm_state;

    always @(fsm_in)
        fsm_state <= g(fsm_in);
chitranna
  • 1,579
  • 6
  • 25
  • 42

3 Answers3

2

First off: Best practice is the have non-blocking assignments for registers and blocking assignment for combination logic. I recommend taking a look at this paper: Nonblocking Assignments in Verilog Synthesis, Coding, Styles That Kill! by Clifford E. Cummings. § 11 covers combination logic. The guidelines of the paper were for IEEE Std 1364-1995 and are still completely applicable today; Verilog and SystemVerilog.

That said, the given code as is will work functionally because you have a simple conditions. It will likely synthesize correctly too (based on Cliff's page).

You could run into problems if you use a poor coding style with a more complex designs. See Cliff's paper for examples. A poor coding style also makes it harder for others to read[1]. Readable code is something you want for your professors and coworkers. An ideal linting tool would flag it as well. It is best to make yourself get into the habit of writing quality code.

1 : See IEEE std 1800-2012 § 34 if you really don't want others reading your code

Greg
  • 18,111
  • 5
  • 46
  • 68
  • I agree that using blocking assignments in combinatorial processes is 'best practice', but this is, of course, just a guideline. you can always code combinatorial logic with NBAs, and VHDL designers do this all the time. Of course, if you start using temporary variables to hold intermediate values, you have to understand what NBAs actually do, and when values update. In VHDL, you use a variable to ensure immediate update; in Verilog, you use a blocking assignment. Verilog 'guidelines' exist because the language is poorly specified - you can ignore them if you understand the language. – EML Aug 16 '13 at 08:01
2

Your code is fine, though I agree with Greg that it's better style to use blocking assignments in the combinatorial process.

On your comments:

In very simplified terms, the scheduler contains 5 queues (SV has 17), but you're only interested in 2 of them: the active event queue, and the nonblocking assignment update queue. In a given simulation cycle, the simulator processes the active event queue, and then the nonblocking update queue. In general, this will create more events, and the simulator cycles around the queues in a pre-determined order until there are no more events at this simulation time. The simulator then moves on to the next time at which an event is scheduled (at the next clock edge, for example).

Assume that 4 things happen 'at once': there is a change in fsm_state, there is a change in f(x), and both your NBA assignments are executed. As far as the simulator is concerned, these 4 statements are executed in the same simulation cycle, but in an undefined order. The definition of 'at once' is rather complex, but assume that they all happen as a result of a clock edge, with no ordering dependencies between the statements. The simulator is usually single-threaded, so it will actually execute the 4 statements at different real times, but it knows that all 4 are expected to happen at the same simulation time.

The changes on fsm_state and f(dff1) are update events, and are added to the scheduler's active event queue.

The RHS of the two NBAs are immediately evaluated, and the LHS updates are added to the nonblocking assignment update queue.

The simulator now sees a queue with 4 events on it. It executes the two active events first, in an undefined order, so fsm_in and fsm_out get their new values. If there are no more active events, it then executes the two non-blocking updates, in an undefined order, so dff1 and fsm_state now get their new values.

In your case, the simulation cycle isn't finished, because the change on fsm_in is also an update event, and this triggers the evaluation/execution of the always block which is sensitive to fsm_in. This is an evaluation event. The sim executes the always block, immediately reads the new value of fsm_in, and adds the update of fsm_state to the NBA assignment update queue. If there are no active events, the assignment is then acted on, and fsm_state gets it's new value.

This goes on until there are no more events in this simulation cycle, and the simulator then advances time, if something is scheduled in the future.

You could get all this from section 5 of the Verilog LRM, but it doesn't make much sense. All the language was grafted on late in the standardisation process and uses (VHDL) terminology that's not used elsewhere in the LRM. It was also all added in such a way as to match the behaviour of Verilog-XL, and specifically to document the non-determinism specific to XL, so don't expect too much from it. NBAs weren't even added to the language till 1992, I think. Don't bother with the SV LRM; there are many more queues, and the common text has changed, just adding another level of confusion.

Cliff Cummings has a simplified description in one of his papers (on non-blocking assignments), but read it with care. I'm pretty sure that the description of the active event queue is incorrect (for RHS evaluation of NBAs). If he was right, it would cause all sorts of problems; he presumably got the description from an early version of the LRM.

Much the best thing to do is to look up any text on VHDL delta cycles. These are easy to understand, and they work, and always have done, and they have crept into Verilog over the years. The details are different, but you don't need to know anything more than you'll find in delta cycles.

EML
  • 9,619
  • 6
  • 46
  • 78
0

I recommend that you ALWAYS use non-blocking for clock driven signals and blocking for combo logic (If it is RTL). I have used many synthesizers and they show errors if you do not use the assignments as I recommended. Also there are other linting tools which also will show errors. And I agree with Greg, that for a better readable code you should follow this guideline.

DOS
  • 499
  • 2
  • 6
  • 9
  • I've never seen a synthesis fail because it didn't understand NBAs, or even heard of it. This is pretty unlikely, given that they work on template recognition, and it would also mean that they couldn't handle a huge amount of VHDL code. – EML Aug 16 '13 at 16:24