【问题标题】:VHDL syn_looplimit and synthesisVHDL syn_looplimit 和综合
【发布时间】:2016-03-17 06:58:44
【问题描述】:

我的 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;

它在模拟中效果很好,但不能合成。 错误消息是:“虽然循环没有终止。您可以使用 syn_looplimit 属性设置循环迭代的最大值”

但是,这段代码合成(但这不是我想要的)

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;

【问题讨论】:

    标签: vhdl synthesis


    【解决方案1】:

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

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

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

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

    【讨论】:

    • 感谢您的回复。问题是 S_ink 是 1 到 16384 之间的整数 .... 所以我的“固定迭代循环数”会太长。合成工具不知道迭代次数,但是 syn_looplimit 属性应该可以解决这个问题?
    • @Dimitri Lecomte 如果 S_ink 的最大值为 16384,则循环的最大迭代次数为 14(或 15?)。始终循环该次数,但仅在 temp 大于零时执行 log := log + 1;
    • @Morten Zilmer 具有讽刺意味的是,使用递归函数实现相同的算法并且它合成得很好。
    • 感谢您的回复。没错,最大值是 14。我会发布正确的答案,但我仍然不明白为什么 syn_looplimit 在我的第一个示例中不起作用。有了这个属性,综合工具就知道最大迭代次数...
    • @DimitriLecomte:我假设您使用 Lattice,因为我找不到为 Altera 或 Xilinx 定义的属性 syn_looplimit。在示例中,Lattice 给出的循环数仍然是一个常数,因此不依赖于数据,因此syn_looplimit 似乎只是对该工具的一个提示。因此,即使在应用syn_looplimit 时,该工具也无法确定展开循环时的迭代次数。
    【解决方案2】:

    解决方案:

    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;
    

    【讨论】:

    • 我建议在可综合代码中使用for 循环而不是while 循环。例如for I in 1 to maxloop loop 或类似的东西。我想,它更有可能在任何旧的合成器上进行合成。无论如何,您已经使用while 循环手动有效地编写了自己的for 循环。
    • 当循环改变时。谢谢
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多