VHDL syn_looplimit 和综合

VHDL syn_looplimit and synthesis

我在使用 VHDL 代码进行综合时遇到问题:我正在尝试获取输入信号的对数值 S_ink:

我的代码:

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;

它在模拟中工作得很好,但不能综合。 错误信息是:"While loop is not terminating. You can set the maximum of loop iterations with the syn_looplimit attribute"

然而,这段代码综合了(但这不是我想要的)

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;

当综合工具翻译设计时,它会制作一个电路,其拓扑结构不依赖于数据值,但电线承载数据值。该电路必须在每一级触发器之间具有固定的计算延迟,因此时序分析可以确定触发器之间的逻辑数量是否适合指定频率。在此过程中,任何循环都会展开,您可以将此视为将循环转换为一长串普通(非循环)语句。要进行此展开,综合工具必须能够确定循环中的迭代次数,以便在进行循环展开时可以将循环体重复此次数。

在第一个代码示例中,循环中的迭代次数取决于 S_ink 值,因此综合工具无法将循环展开为固定电路,因为电路取决于数据值.

在第二个代码示例中,综合工具可以确定循环中的迭代次数,从而展开到固定电路。

解决此问题的一种方法是使算法具有固定的迭代次数,其中该迭代次数可以处理最坏情况的输入数据,并且对其他输入数据的任何多余迭代都不会改变结果。

解决方案:

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;