FPGARelated.com
Forums

Verilog in Quartus and assignments in blocks

Started by Giorgos Tzampanakis July 14, 2010
I was under the impression that in Verilog nonblocking 
assignments are evaluated in an arbitrary order. However, in 
Quartus, I have noticed that if you use something like this:

always @(posedge clock) begin
    	a <= 1;
    	if (condition) a <= 0;
end

Then, if "condition" is true "a" will always be assigned the 
value 0. Is this the way Verilog is described in the standard 
or is it just an Altera convention?

Which bring us to my next question: Can I block multiple non-
blocking assignments together like so:

always @(posedge clock) begin
    	begin
    	    	a <= 1;
    	    	b <= 2;
    	end
    	
    	begin
    	    	c <= a;
    	    	d <= b;
    	end
end

So that "c" will end up with value 1 and "d" will end up with 
value 2? I know that if I had only "a" and "c" I could use 
blocking assignments, but with two groups of variables it 
wouldn't be possible. So does the above snippet work reliably?
    	
On Jul 15, 2:20=A0am, Giorgos Tzampanakis <g...@hw.ac.uk> wrote:

> So does the above snippet work reliably?
Yes, but not in the way you described :-)
> I was under the impression that in Verilog nonblocking > assignments are evaluated in an arbitrary order.
You're not alone, but it's a delusion.
> However, in > Quartus, I have noticed that if you use something like this: > > always @(posedge clock) begin > =A0 =A0 =A0 =A0 a <=3D 1; > =A0 =A0 =A0 =A0 if (condition) a <=3D 0; > end > > Then, if "condition" is true "a" will always be assigned the > value 0. Is this the way Verilog is described in the standard
Yes. The standard says that if you have multiple nonblocking assignments (NBAs) to a variable, all maturing at the same time, then they will take effect in the same order in which they were executed procedurally. Given that your begin...end is a procedural block, it's clear that the second a<=3D0 will be executed later than the a<=3D1 assignment, and so it will also take effect (update its target variable) later. This is a fine, reasonable and useful coding style: make a default assignment, and then possibly change your mind about it later in the same procedural block.
> Which bring us to my next question: Can I block multiple non- > blocking assignments together like so: > > always @(posedge clock) begin > =A0 =A0 =A0 =A0 begin > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 a <=3D 1; > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 b <=3D 2; > =A0 =A0 =A0 =A0 end > > =A0 =A0 =A0 =A0 begin > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 c <=3D a; > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 d <=3D b; > =A0 =A0 =A0 =A0 end > end > > So that "c" will end up with value 1 and "d" will end up with > value 2?
No. There will be a one-clock delay between the update on a and the update on c, and similarly for d and b. The inner begin...ends are completely irrelevant and superfluous; begin...end is simply bracketing to make a string of procedural statements act syntactically like a single procedural statement. Within the begin...end the statements are executed sequentially, and each begin...end block is executed in sequence as if it were a single more complex procedural statement. Here's what happens: 1.On the first clock edge, all four assignments are executed sequentially as you would expect. However, at the point when c<=3Da is executed, the earlier NBA a<=3D1 has not yet taken effect, so the assignment is effectively c<=3D1'bx (assuming a was initially 1'bx). 2.At the time of that same clock edge, various other code in your design will also execute as the result of @(posedge clock) controls. All these code blocks will execute as far as their next @() or other delay control. 3.When all code that was triggered by the clock has done executing and has stalled at some delay control, Verilog moves on to the NBA region of its scheduling model. The NBAs that were executed in steps 1 and 2 now mature, and drop their assigned values on to their target variables. 4.As a result of those variables being updated, it's quite likely that other always or continuous-assign code may be triggered for execution. But you can be sure that the clocked always blocks are not among them, because (I hope!) none of the NBAs updated the clock. 5.Then everything goes quiet until the next active clock edge, and we're back to step 1 again. The net result of all of this is that when you write a conventional synthesisable clocked always block, you have some guarantees about the behaviour of variables that were written by NBA... - when you READ the value of such a variable, either in a test condition or in an expression on the RHS of some assignment, you are reliably getting the variable's value as it was immediately BEFORE the clock edge; - when you ASSIGN to a variable using NBA, you are not yet updating the variable; rather, you are specifying the value that variable will take immediately AFTER the clock edge. And you can rewrite that specification as often as you please, by making successive NBAs to the same variable.
> I know that if I had only "a" and "c" I could use > blocking assignments, but with two groups of variables it > wouldn't be possible
I really don't know what you mean by that. Standard advice: take a look at Cliff Cummings's well-known paper on blocking and nonblocking assignments (Google for "Cummings coding styles that kill nonblocking"), which is a thorough and generally reliable overview of the situation. But please keep your critical faculties engaged; there are some unjustified "rules" in his paper that simply don't make sense. I and others have ranted at length about that here, many times. -- Jonathan Bromley
Jonathan Bromley <spam@oxfordbromley.plus.com> wrote in
news:9250a4ef-19e7-41af-9e91-4970608bc6bb@j13g2000yqj.googlegro
ups.com: 

> Yes. The standard says that if you have multiple > nonblocking assignments (NBAs) to a variable, all maturing > at the same time, then they will take effect in the same > order in which they were executed procedurally. > > (snip) > > No. There will be a one-clock delay between the update on a > and the update on c, and similarly for d and b. The >
So, if we have assignments to the same variable we are guaranteed that the assignments will take place in the order they are written in the code. But with assignments to different variables the situtation is still unclear. Compare the following two snippets: //Snippet 1 always @(posedge clock) begin a <= 1; if (condition) b <= a; end //Snippet 2 always @(posedge clock) begin a <= 1; b <= a; end if "condition" is true, do they behave exactly the same?
On Thu, 15 Jul 2010 13:59:48 +0000 (UTC), Giorgos Tzampanakis wrote:

>So, if we have assignments to the same variable we are >guaranteed that the assignments will take place in the order >they are written in the code. But with assignments to different >variables the situtation is still unclear.
No, it isn't.
> Compare the following two snippets: > >//Snippet 1 >always @(posedge clock) begin > a <= 1; > if (condition) b <= a; >end > >//Snippet 2 >always @(posedge clock) begin > a <= 1; > b <= a; >end > >if "condition" is true, do they behave exactly the same?
Yes. And in both cases, b<=a will read the OLD value of a (not the new value '1' whose assignment is scheduled for the upcoming NBA region of the scheduler). I can't really understand what would make you think they would be different. -- Jonathan Bromley
On Thu, 15 Jul 2010 13:59:48 +0000 (UTC), Giorgos Tzampanakis wrote:

Sorry about the second response, but I just noticed....

>So, if we have assignments to the same variable we are >guaranteed that the assignments will take place in the order >they are written in the code.
No, that's not the point at all. They will take place ** in the order they were executed **. In other words, scheduled updates go on to a particular timeslot's NBA queue in FIFO order. In a single sequential block, then of course that has the same effect as "the order they are written" (except in loops, which can divert the flow of execution backwards in the code). But in the presence of concurrent assignment to the same variable from multiple blocks, or of intra-assignment delays, the difference is critical. Fortunately for the present discussion, neither of those two situations is suitable for synthesisable design code. -- Jonathan Bromley