Global training solutions for engineers creating the world's electronics

Unrolling Loops

Quite often, when you're debugging VHDL code, certain pieces of code just do not naturally give up the information you are looking for. This is particularly true of loop statements, whether they be for loops inside a process or generate statements using the for scheme in an architecture.

When generate statements need debugging, they tend to compile OK and then rather annoyingly, cause a FATAL at elaboration time. This is particularly galling, as you can't simulate (because of the FATAL) in order to debug the problem. All you usually get is a somewhat (un)helpful error message concerning port widths or such like. So a plea to compiler/simulator tool suppliers, some kind of elaboration-time debugger (please and thank you)! Until then, you have to manually unwrap the generate and write out the concurrent statements inside the generate wrapper explicitly in order to gain more insight into the problem. (In my experience, you only have to start writing out the first few statements and usually the penny drops.)

But what about for loops in processes? Well, how about this...

One of the golden rules of writing synthesisable code to describe sequential logic runs something like this:

“If it is possible (no matter how convoluted) to read a variable before you write to it during the execution of a clocked process, you WILL get a register element”

For example:

AND_REG: process
  variable V: STD_LOGIC;
  wait until Rising_edge(CLOCK);
  V := '1';
  for I in 0 to 7 loop
    V := V and INPUT(I);
  end loop;
  REG <= V;
end process;

How many register elements? Well, you might think by looking at the for loop,

  for I in 0 to 7 loop
    V := V and INPUT(I);
    -- V is read (and'ed with INPUT(I)) before being written (V := ...)
  end loop;

there would be a register element created from V. But how many? 1? (V is a std_logic) or is it 8? (number of times you read V before writing to it). Ok, lets unroll the loop...

  V := '1';              -- (1)
  -- loop unrolled
  V := V and INPUT(0); -- (2)
  V := V and INPUT(1); -- (3)
  V := V and INPUT(2);
  V := V and INPUT(3);
  V := V and INPUT(4);
  V := V and INPUT(5);
  V := V and INPUT(6);
  V := V and INPUT(7);
  -- to here

In line (1), V is written.

In line (2), we are reading the value of V ('1') which we have just written in line (1) and and'ing it with INPUT(0) to create a new value for V. So in line (1) we wrote to V before we read from it in line (2), whereupon we are writing to it a second time.

In line (3) we are reading this new (second) value of V that we wrote to in line (2) - again, write before read. Notice that V, in fact, is never read before it is written so there is no danger of creating a register element as the golden rule only applies to reading before writing.

So the Tip is “unroll loops for insight into your code”.

Bye for now...



Your e-mail comments are welcome - send email

Copyright 1995-2002 Doulos

Great training!! Excellent Instructor, Excellent facility ...Met all my expectations.
Henry Hastings
Lockheed Martin

View more references