【问题标题】:Function clogb2() generated by vivado can't synthesize with loop limit errorvivado 生成的函数 clogb2() 无法合成循环限制错误
【发布时间】:2017-06-23 08:47:27
【问题描述】:

我正在尝试使用 vivado 设计一个 AXI_master 外设。我在vivado菜单中使用了axi外设生成器,修改了生成的vhdl代码。

在 vhdl 代码中有一个函数 clogb2 用以下代码声明:

function clogb2 (bit_depth : integer) return integer is
    variable depth  : integer := bit_depth;
    variable count  : integer := 1;
begin
  for clogb2 in 1 to bit_depth loop  -- Works for up to 32 bit integers
    if (bit_depth <= 2) then
      count := 1;
    else
      if(depth <= 1) then
          count := count;
        else
          depth := depth / 2;
        count := count + 1;
        end if;
    end if;
  end loop;
  return(count);
end;

这在模拟(GHDL)中有效,但在综合中失败并出现错误:

[Synth 8-403] 循环限制 (65538) 超出

我尝试使用以下 tcl 命令增加 vivado 中的循环限制:

set_param synth.elaboration.rodinMoreOptions "rt::set_parameter max_loop_limit <X>"

正如here 所解释的那样,但是 vivado 以无限时间合成并且永远不会完成。 你知道如何解决这个问题吗?

【问题讨论】:

    标签: vhdl vivado


    【解决方案1】:

    您也可以尝试不同的路径。虽然逻辑中不支持浮点(虽然支持正在增加),但它允许用于内部计算等。 (至少由 Xilinx 和 Altera/Intel 提供)。

    试试这个:

    use ieee.math_real.all;
    
    function ceillog2(input : positive) return natural is
    begin
        return integer(ceil(log2(real(input))));
    end function;
    

    【讨论】:

      【解决方案2】:

      尝试限制输入的范围,例如:

      function clogb2 (bit_depth : integer range 1 to 32) return integer is
      

      此外,如果 Vivado 生成的代码无法编译,您应该在 Xilinx 论坛上报告这是一个错误。

      【讨论】:

        【解决方案3】:

        最后我找到了一个解决方案,通过用大案例重写函数来工作:

        function clogb2 (bit_depth : integer) return integer is
         begin
             case bit_depth is
                 when 0 to 2             => return( 1);
                 when (2** 1)+1 to 2** 2 => return( 2);
                 when (2** 2)+1 to 2** 3 => return( 3);
                 when (2** 3)+1 to 2** 4 => return( 4);
                 when (2** 4)+1 to 2** 5 => return( 5);
                 when (2** 5)+1 to 2** 6 => return( 6);
                 when (2** 6)+1 to 2** 7 => return( 7);
                 when (2** 7)+1 to 2** 8 => return( 8);
                 when (2** 8)+1 to 2** 9 => return( 9);
                 when (2** 9)+1 to 2**10 => return(10);
                 when (2**10)+1 to 2**11 => return(11);
                 when (2**11)+1 to 2**12 => return(12);
                 when (2**12)+1 to 2**13 => return(13);
                 when (2**13)+1 to 2**14 => return(14);
                 when (2**14)+1 to 2**15 => return(15);
                 when (2**15)+1 to 2**16 => return(16);
                 when (2**16)+1 to 2**17 => return(17);
                 when (2**17)+1 to 2**18 => return(18);
                 when (2**18)+1 to 2**19 => return(19);
                 when (2**19)+1 to 2**20 => return(20);
                 when (2**20)+1 to 2**21 => return(21);
                 when (2**21)+1 to 2**22 => return(22);
                 when (2**22)+1 to 2**23 => return(23);
                 when (2**23)+1 to 2**24 => return(24);
                 when (2**24)+1 to 2**25 => return(25);
                 when (2**25)+1 to 2**26 => return(26);
                 when (2**26)+1 to 2**27 => return(27);
                 when (2**27)+1 to 2**28 => return(28);
                 when (2**28)+1 to 2**29 => return(29);
                 when (2**29)+1 to 2**30 => return(30);
                 when (2**30)+1 to (2**31)-1 => return(31);
                 when others => return(0);
             end case;
         end;
        

        使用这种奇怪的代码结构,可以在综合和模拟中使用。

        【讨论】:

        • 您看过其他答案吗?这根本不是一个优雅的解决方案。
        【解决方案4】:

        这个递归版本综合了:

        function clogb2 (bit_depth : integer) return integer is 
          begin
            if bit_depth <= 1 then
              return 0;
            else
              return clogb2(bit_depth / 2) + 1;
            end if;
          end function clogb2;
        

        你可以用它来标注其他东西,例如

        entity counter is
          generic (max_count : POSITIVE);
          port (clock, reset : in  std_logic;
                Q            : out std_logic_vector(clogb2(max_count) downto 0)  
               );
        end;
        

        或者您可以将其用作组合逻辑:

        process (I)
        begin
          O <= clogb2(I);
        end process;
        

        顺便说一句:您最好使用整数子类型作为输入:

        function clogb2 (bit_depth : positive) return integer is 
        --                               ^
        --                               |
        

        【讨论】:

        • 但是你喜欢这个答案吗? clog2bee.vhdl:20:9:@0ms:(report note): clogb2 (112000) = 16。这个特定的值需要 17 的二进制长度来描述。函数调用也应该有一个正范围。负整数或零值永远不会达到 bit_depth = 1。根据工具的不同,会有递归限制,它只会循环,否则你会用完调用堆栈。
        • @user1155120 我确实喜欢这个答案:112000 的 log2 在整数数学中是 16。原始函数确实使用了正输入 - 我更改了接口和函数名称以匹配问题。
        • 2 ** 16 是 65536。保持值 112000 的上限(如在接受的答案的 ceillog2 中)是 2 ** 17 (131072),其中 11200 介于两者之间。您的函数提供了一个底值。在你的辩护中,这个问题可能已经显示出函数调用的用途。
        • 具有未指定初始值的整数类型将默认为整数'LEFT,它是一个负数。仅使用允许负值的参数类型标记将正子类型显示为实际使用是不够的。我个人发现自旋循环执行递归调用的模拟器在道德上令人反感,但在标准下并未定义为错误或错误。
        猜你喜欢
        • 2012-06-18
        • 2018-11-09
        • 2015-07-01
        • 2018-09-09
        • 2016-05-27
        • 2014-11-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多