2

I have a problem in synthesis with my VHDL code : I am trying to get the logarithm value of an input signal S_ink:

My code :

entity ....
....

architecture rtl of myEntity is
attribute syn_looplimit : integer;
attribute syn_looplimit of loopabc : label is 16384;

logcalc:process(I_clk)
  variable temp : integer;
  variable log  : integer;
  begin

    if(I_clk'event and I_clk='1') then
      if (IN_rst='0') then
        S_klog<=0;
        temp:=0; 
        log:=0;
      else 
        temp := S_ink+1;               --S_ink is an input of my entity (integer)
        log:=0;
        loopabc:while (temp/=0) loop
          temp:=temp/2;
          log :=log+1;
        end loop loopabc;
        S_klog<=3*log;
      end if;
    end if;
end process;

It works very well in simulation but doesn't synthesize. The error message is : "While loop is not terminating. You can set the maximum of loop iterations with the syn_looplimit attribute"

However, this code synthesize (but that is not what I want)

entity ....
....

architecture rtl of myEntity is
attribute syn_looplimit : integer;
attribute syn_looplimit of loopabc : label is 16384;

logcalc:process(I_clk)
  variable temp : integer;
  variable log  : integer;
  begin

    if(I_clk'event and I_clk='1') then
      if (IN_rst='0') then
        S_klog<=0;
        temp:=0; 
        log:=0;
      else
        temp := 3000;       -- a random constant value
        log:=0;
        loopabc:while (temp/=0) loop
          temp:=temp/2;
          log :=log+1;
        end loop loopabc;
        S_klog<=3*log;
      end if;
    end if;
end process;
Forge
  • 6,538
  • 6
  • 44
  • 64
lctdim
  • 57
  • 6

2 Answers2

2

When the synthesis tool translates the design, it will make a circuit with a topology that does not depend on the data values, but where the wires carries the data values. The circuit must have a fixed calculation latency between each level of flip-flops, so timing analysis can determine if the amount of logic between flip-flops can fit for the specified frequency. In this process any loops are unrolled, and you can think of this as converting the loop to a long sequence of ordinary (non-loop) statements. To do this unrolling, the synthesis tool must be able to determine the number of iterations in the loops, so it can repeated the loop body this number of times when doing loop unrolling.

In the first code example the number of iterations in the loop depends on the S_ink value, so the synthesis tool can't unroll the loop to a fixed circuit, since the circuit depends on the data value.

In the second code example the synthesis tool can determine the number of iterations in the loop, thus do the unrolling to a fixed circuit.

One way to address this is make the algorithm with a fixed number of iteration, where this number of iterations can handle the worst case input data, and where any superfluous iteration on other input data will not change the result.

Morten Zilmer
  • 15,586
  • 3
  • 30
  • 49
  • Thank you for your response. The problem is S_ink is an integer between 1 and 16384 .... so my "fixed number of iteration loop" would be too long. The number of iterations is unknown by the synthesis tool but the syn_looplimit attribute should resolve this problem ? – lctdim Mar 17 '16 at 08:41
  • @ Dimitri Lecomte If the maximum value of S_ink is 16384, the maximum number of iterations of your loop is 14 (or 15?). Always loop that number of times, but only execute `log := log + 1;` if `temp` greater than zero. – Matthew Taylor Mar 17 '16 at 08:47
  • @Morten Zilmer Ironically, implement the same algorithm using a recursive function and it synthesises just fine. – Matthew Taylor Mar 17 '16 at 08:47
  • Thank you for your response. You are right the maximum value is 14. I will post the correct answer but I still don't understand why the syn_looplimit doesn't work in my first example. With this property, the synthesis tool know the maximum number of iterations ... – lctdim Mar 17 '16 at 08:54
  • @DimitriLecomte: I assume you use Lattice, since I could not find attribute `syn_looplimit` defined for Altera nor Xilinx. In the example Lattice gives the number of loops is still a constant, thus not data dependent, so it appears that `syn_looplimit` is only a hint to the tool. So even when applying `syn_looplimit` the tool can't determine the number of iterations when unrolling the loop. – Morten Zilmer Mar 17 '16 at 12:59
  • @MatthewTaylor: I have not looked at the recursive solution, but maybe the tool is able to determine a non-data dependent stop condition when doing recursion, but not for iteration. Interesting. – Morten Zilmer Mar 17 '16 at 13:01
  • @MortenZilmer I am using synplify for Microsemi and there is a syn_looplimit. It works when the loop condition is a constant but doesn't when the condition in the loop is a signal (an input of the "entity") – lctdim Apr 23 '16 at 08:10
  • @DimitriLecomte: That is as expected in my answer. The synthesis tool can only unroll the loop to hardware if it know the number of iterations at synthesis time, and for this the number of iterations must be a constant, not a run time value (signal value). – Morten Zilmer Apr 23 '16 at 09:13
1

Solution :

process(I_clk)
  variable temp : integer;
  variable log  : integer;
  begin

    if(I_clk'event and I_clk='1') then
      if (IN_rst='0') then
        S_klog<=0;
        temp:=0; 
        log:=0;
      else 
        temp := S_ink+1;
        log:=0;
        for I in 1 to 14 loop
          temp := temp/2;
          if (temp /=0) then
            log :=log+1;
          end if;
        end loop;
        S_klog<=3*log;                           -- 3*log because of my application
      end if;
end if;
end process;
lctdim
  • 57
  • 6
  • I would recommend using a `for` loop rather than a `while` loop in synthesisable code., ie `for I in 1 to maxloop loop` or something like that. It is more likely to synthesise on any old synthesiser, I would have thought. Anyway, you have effectively coded your own `for` loop manually using a `while` loop. – Matthew Taylor Mar 17 '16 at 10:39
  • While loop changed. Thank you – lctdim Mar 17 '16 at 11:01