Programmable Devices
CPLDs, FPGAs, SoC FPGAs, Configuration, and Transceivers
Announcements
FPGA community forums and blogs on community.intel.com are migrating to the new Altera Community and are read-only. For urgent support needs during this transition, please visit the FPGA Design Resources page or contact an Altera Authorized Distributor.
21615 Discussions

processes: while loop does not work, for loop does work. Why?

Altera_Forum
Honored Contributor II
2,403 Views

I want to write this code for a basic synchronous counter more efficiently... 

 

u_count: process(rst_i, clk_i) -- generated on rising edge 

variable i: integer :=1; 

begin  

if rst_i = '1' then 

c <= "00000000000000000"; 

elsif (clk_i ='0' and clk_i'event) then 

c(0) <= c(0) xor cyi; 

c(1) <= c(1) xor t(0); -- t(n) terms are propagate terms defined earlier as dataflow statements. 

c(2) <= c(2) xor t(1); 

.. 

c(16) <= c(16) xor t(15); 

end if; 

end process; 

 

This code below for a loop counter works (good to know) 

 

u_count: process(rst_i, clk_i) -- generated on rising edge 

variable i: integer range 1 to 16; 

begin  

if rst_i = '1' then 

c <= "00000000000000000"; 

elsif (clk_i ='0' and clk_i'event) then 

c(0) <= c(0) xor cyi; 

for i in 1 to 16 loop 

c(i) <= c(i) xor t(i-1);  

end loop; 

end if; 

end process; 

--------------------------------------------------------------------- 

And this code below with the most basic while loop does not 

Error (10536): loop must terminate within 10,000 iterations 

 

u_count: process(rst_i, clk_i) -- generated on rising edge 

variable i: integer :=1; 

begin  

if rst_i = '1' then 

c <= "00000000000000000"; 

elsif (clk_i ='0' and clk_i'event) then 

c(0) <= c(0) xor cyi; 

while (i <= 16) loop 

c(i) <= c(i) xor t(i-1);  

i:=i+1; -- how can i get past 16 to 10,000?  

end loop; 

end if; 

end process; 

 

Lots of people get this error, but they don't present a simple, bullet-proof example that does not have some other quirk that obfuscates this issue, so I never could find an explanation for the error. 

 

Thanks.
0 Kudos
12 Replies
Altera_Forum
Honored Contributor II
1,342 Views

Have you tried having it exit at 9,999?, eg what it suggests here: 

http://quartushelp.altera.com/13.0/mergedprojects/msgs/msgs/evrfx_vhdl_loop_does_not_term.htm
0 Kudos
Altera_Forum
Honored Contributor II
1,342 Views

To write efficient code for a synchronous counter, just type 

c <= c +1; 

If you want to write low level code for some reason, e.g. as an exercise, you are restricted to synthesizable VHDL constructs. 

 

You probably have noticed that not all legal VHDL constructs are synthesizable. They can be however used in testbenches. 

 

Because iterations are enrolled to parallel hardware, it's essential that the number of iterations is constant and can be determined at "compile" time. The while statement in your example has a constant number of iterations, but other possible while statements don't. For this reason, synthesis tools don't support it. 

 

For Quartus, the supported VHDL constructs are listed in the online help. The selection is mostly identical to IEEE 1076.6, ieee standard for vhdl register transfer level (rtl) synthesis

 

P.S.: Regarding "efficient code". Even if your code is synthesizable, there's a certain risk that it's not recognized as arithmetic operation and thus won't utilize the fast carry chain. In this case, the resulting hardware will be considerably less efficient, slower and consuming more logic cells than that generated by the simple c <= c +1.
0 Kudos
Altera_Forum
Honored Contributor II
1,342 Views

Jderrick 

If the variable i goes beyond 16, such that I need a huge inexplicable exit condition, then neither I nor the compiler knows what's going on and I'm going to get some abomination logic that swallows my whole CPLD :) 

 

FvM 

I'm looking to understand how the compiler works. I will not use WHILE but I still don't understand why the variable i would exceed 16. The compiler should so a simple ascii text expansion to yield the ascending terms of the counter before it analyzes and elaborates. WHILE fails and FOR works. 

 

My simple example demonstrates a compiler flaw and the rule with Altera is "do not use WHILE inside a process".  

 

It is interesting that "c=c+1" defaultas to a synchronous counter and that is, tentatively, the way to go. I like to write code that 

a) Will result in synthesizable logic that I intend. The less freedom I give the compiler the better. Easier to debug and do timing analysis. 

b) That is understandable to others since I don't work alone. The simplicity and elegant of "c=c+1" also hides the subtlety that might be missed. I would not it in a comment.  

 

I'll play around with the explicit code I have and c=c+1 and see what happens. 

 

Will I get a synchonous counter from c=c+1 with another compiler? (assume and try!). 

 

Thanks.
0 Kudos
Altera_Forum
Honored Contributor II
1,342 Views

c<=c+1; will always give you a synchronous counter, if it's in a synchronous process. Otheriwse you just get a logic loop (that the synthesisor wont like very much). 

 

It really is not a compiler error. While loops do not convert well to hardware. And in your example, i has a range -2^31 to 2^31-1, so the compiler doesnt know what could happen to i. According to your code you never set it to 0 again, so technically it only ever adds 1 on the first clock edge and then never again, whereas the for loop resets i every time it enters the loop. 

 

AFAIK, the compilers do not do behavioural analysis, hence why it doesnt know i never goes past 16. It just converts it to a netlist using specific templates. If you had set the size of i as : 

 

variable i : integer range 1 to 16; 

 

It may have had an easier time.
0 Kudos
Altera_Forum
Honored Contributor II
1,342 Views

Tricky, 

 

Thanks for the suggestion. I had in fact also tried "variable i : integer range 1 to 16;" and got the same bad result. That means it is not a problem of undefined range in the compiler. 

 

I think you are saying the WHILE is evaluated as if it were logic but in my view it is shorthand for a text expansion prior to any evaluation of logic and consideration of clock edges. 

 

I'm still convinced the compiler is not being faithful to VHDL. One of my VHDL books (old but good) is by Kevin Skahill from Cypress Semi and he has a handy example in chapter 4.5.1. Cypress' compiler obviously handles WHILE back in 1996. It would be nice if Altera wrote an app note on this.
0 Kudos
Altera_Forum
Honored Contributor II
1,342 Views

Why not post that example? Afaik, it is able to process it if you put an exit staement in the code. Also, a point to note, you did not post your whole code (just a snippet). Why not post the real code.  

 

The Altera VHDL compiler is actually one of the better VHDL synthesisors out there.  

 

The VHDL compiler HAS to convert to logic in Quartus. it has specific templates to follow and is actually pretty good at converting to logic. Post this example your on about, and we'll see if it really is a logic example.
0 Kudos
Altera_Forum
Honored Contributor II
1,342 Views

I think anyone could in a minute implement a while loop in a process and not be able to compile it, so posting my whole design obscures the issue, as it definitely does in all other related forum threads I've seen. 

 

I respect Altera's compiler overall but WHILE fails and FOR works. That's all designer's need to know.
0 Kudos
Altera_Forum
Honored Contributor II
1,342 Views

The while loop could be used to wait on a signal: 

 

process(clk) begin if rising_edge(clk) then while some_input = 0 loop --do something end loop; end if; end process;  

 

THis is completly unsuitable for synthesis as it does not map to any real logic circuit. Its not an argument of While vs for - you can also write code that wont synthesis a for loop.
0 Kudos
Altera_Forum
Honored Contributor II
1,342 Views

I found that Quartus does synthesize the while iteration. The problem is a missing i:=1; before the while statement.

0 Kudos
Altera_Forum
Honored Contributor II
1,342 Views

 

--- Quote Start ---  

I found that Quartus does synthesize the while iteration. The problem is a missing i:=1; before the while statement. 

--- Quote End ---  

 

 

so the variable cannot be initialized in the declaration as I did it "variable i: integer :=1;" 

 

We should be able to do that so the compiler does have a problem. Simple solution though. Thank you!
0 Kudos
Altera_Forum
Honored Contributor II
1,342 Views

The initializing statement sets the value only once. But it must be set every time.

0 Kudos
Altera_Forum
Honored Contributor II
1,342 Views

As far as I know, it is almost always discouraged to write a while loop, if it is possible to make it a for loop, in any language. 

This is because it is easy to make a mistake with a while loop, so that it never ends, software nor hardware will like this. 

Ofcourse you could also write a neverending forloop, but a forloop always has at least some exit statement. 

So wether it compiles or not, if you can write it as a for loop, just do.
0 Kudos
Reply