verilog question, break while loop to avoid combinational feedback during synthesis

Hello, I am puzzled by a statement in a book I am reading:

To avoid combinational feedback during synthesis, a while loop must be broken with an @(posedge/negedge clock) statement, such as this

while (!done) begin @(posedge clk); counter = counter + 1; end

I searched combinational feedback, I found it usually happens when a code only has 'if' branch (missing the else branch) and unexpected behavior could happen if the condition is always false. Does it apply here that maybe done is always false?

How does '@(posedge clk);' avoid this combinational feedback?

Fei

Reply to
Fei Liu
Loading thread data ...

Not for the first time, a book that contains a statement that is so misleading that it could reasonably be described as "wrong".

Consider what would happen if you did not have the clock event:

while (!done) begin counter = counter + 1; end

Now, let's imagine a simulator entering this loop when "done" is false. It'll increment "counter" IN ZERO SIMULATED TIME, then loop back and - surprise, surprise - "done" will still be false. And so on. And the zero-time loop will prevent the simulator from ever making forward progress through simulated time. A synthesis tool might perhaps create a combinational feedback loop as its best effort, but it really makes no sense either for simulation or synthesis, and is a sure way to get a simulator to lock-up.

Insert a clock delay in the loop, as your example shows, and you start to get sensible behaviour. Test "done", find it's false. Wait until the NEXT clock, increment the counter and test "done" again. By that time, there has been plenty of opportunity for other parts of the design or testbench to modify the value of "done" so that the loop can exit. Keep looping, testing "done" on each clock edge, until eventually you discover "done" is true and your loop exits.

Note that this form of "implied state machine" coding is not universally supported by synthesis tools, and is harder to reason about than the traditional clocked coding style in which a clocked process (always block) has exactly one @(posedge clock) at its head. Implied state machines are also very troublesome to reset. I mightily dislike them, even though they can be shorter and superficially simpler for some kinds of sequential design.

(Disclaimer: In the above paragraph, I'm talking about DESIGN for synthesis. In a testbench, a completely different set of concerns and compromises apply.)

--
Jonathan Bromley, Consultant

DOULOS - Developing Design Know-how
VHDL * Verilog * SystemC * e * Perl * Tcl/Tk * Project Services

Doulos Ltd., 22 Market Place, Ringwood, BH24 1AW, UK
jonathan.bromley@MYCOMPANY.com
http://www.MYCOMPANY.com

The contents of this message may contain personal views which 
are not the views of Doulos Ltd., unless specifically stated.
Reply to
Jonathan Bromley

Thanks for your explanation, now it makes sense to me. My brain is still wired to think only in software sense. Another thing that I don't understand is the disable command. In the following code example, the 'disable count;' statement does not break the loop (or maybe it's reentered right away?)

Does always code_block causes code_block executed indefinitely even when code_block is disabled? always and disable seem to contradict with each other.

module mytest;

// wire x, y, c, d, b; reg clock; integer counter; wire [3:0] a = 4'b0101;

assign b = c & d; assign d = x | y;

initial begin counter = 1'b0; clock = 1'b0; forever #10 clock=~clock; end

always @(posedge clock) begin: count counter = counter + 1; if(counter == 1000) disable count; end

initial begin $monitor("counter = %d", counter); end endmodule

Reply to
Fei Liu

A simulator is a piece of software. I was talking about the behaviour of simulation's software execution.

Synthesis promises to build hardware that matches the code's simulation behaviour (within certain limits), or else give an error to say that it can't do that.

[...]

The effect of "disable code_block" is to abandon execution of code_block. This is equivalent to transferring control (jumping) to the "end" keyword that closes code_block.

"always", like EVERY control construct in Verilog, controls exactly one procedural statement; in your case, that one statement is a "begin...end" block, with an @(posedge clock) delay prefix. When the disable kills your begin...end block, the block terminates - the "always" then causes it to execute again, but as usual the @(posedge clock) prefix delays its execution until the next clock. The counter will then increment from 1000 to 1001, and the if() test will fail, so your if()...disable has in fact had no effect whatever.

If you want to disable a loop, you must disable a code block that encloses the entire loop. Here are the standard ways to implement C's "continue" and "break" in Verilog:

initial begin : outer_block forever begin : inner_block ... ... if (...) disable inner_block; // continue ... if (...) disable outer_block; // break ... end // inner_block end // outer_block

Note that "forever" is simply "while (1)".

This kind of code, using initial/forever/disable, is unlikely to be synthesisable.

--
Jonathan Bromley, Consultant

DOULOS - Developing Design Know-how
VHDL * Verilog * SystemC * e * Perl * Tcl/Tk * Project Services

Doulos Ltd., 22 Market Place, Ringwood, BH24 1AW, UK
jonathan.bromley@MYCOMPANY.com
http://www.MYCOMPANY.com

The contents of this message may contain personal views which 
are not the views of Doulos Ltd., unless specifically stated.
Reply to
Jonathan Bromley

Thanks for the "continue" and "break" comments. I was looking for these features in Verilog (for simulation), but noticing them to be absent from the LRM, assumed there was no equivalent to the C constructs. I worked around this using the loop condition, but disable seems to be exacly what I was after. The only hitch appears to be that the block must be named.

Regards, Gabor

Reply to
Gabor

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.