【问题标题】:VHDL: use the length of an integer generic to determine number of select linesVHDL:使用整数泛型的长度来确定选择行的数量
【发布时间】:2012-09-26 19:57:24
【问题描述】:

我正在尝试创建一个可重复使用的桶形移位器;它需要一个输入位数组并将它们移动一定数量的位置(由另一个输入确定)。我想对模块进行参数化,使其适用于任何n

所需的选择行数由n 确定--> 即SHIFT_CNT = log2(NUMBITS-1)+1 在下面的代码中。在我的组织中(我认为总体而言),拥有不是std_logic_vectorstd_logic 的端口被认为是一种糟糕的形式,因此我使用std_logic_vector 来表示选择行的数量。我需要根据输入通用调整std_logic_vector 的长度。有没有办法在不使用第二个泛型的情况下做到这一点?我看过this 的帖子,但它不涉及泛型。 This 帖子完全消除了泛型或使用日志值作为泛型,这对未来的用户来说不是那么直观(如果INPUT 不是二的幂,可能会导致问题)。

下面SHIFT_CNT的声明肯定是不正确的;有没有办法在不使用第二个泛型的情况下自动生成实体声明中的长度?

entity BarrelShifter is

generic ( NUMBITS : integer :=8);                                                   
Port    ( INPUT     : in   std_logic_vector (NUMBITS-1 downto 0);                
          OUTPUT    : out  std_logic_vector (NUMBITS-1 downto 0);                
          SHIFT_CNT : in   std_logic_vector ((NUMBITS-1)'length downto 0)                 
        );                                                               
end BarrelShifter;

【问题讨论】:

    标签: generics vhdl


    【解决方案1】:

    您可以使用数学库计算log2和ceil的对数结果来声明SHIFT_CNT的大小。

    use IEEE.math_real.all;
    

    或特定功能

    use IEEE.math_real."ceil";
    use IEEE.math_real."log2";
    

    例如你想计算值 a 的 clog2

    result := integer(ceil(log2(real(a))));
    

    如果你只是使用这些函数来计算参数,你的代码是synthesizable (我做到了)

    如果您不想在实体中使用它,您可以在库中声明它们或使用这些函数进行泛型。

    【讨论】:

    • 谢谢Khanh;我这样做是为了权宜之计,而 ceil 和 log2 函数总是给我额外的一点。无论如何它都会被剪掉,但我希望有一些更紧凑的东西,不需要库或额外的 FPGA 资源。
    • 这意味着你想要 log2 的地板以获得更小的位。例如,log 2 的结果是 1.34,ceil 是 2,floor 是 1。我认为这个必需的库是标准的(IEEE 标准),并不关心它。另一种方法是使用 2 参数来声明。在顶部文件中,您可以使用此功能。
    • @user1723509,以这种方式或the other 回答中描述的方式使用库,根本不应该使用任何额外的 FPGA 资源,因为函数的输出可以在编译/综合时解决。
    • 由于舍入问题,这可能会产生意想不到的结果,尤其是与地板一起使用时...
    • result := integer(ceil(log2(real(a) + real(1)))); 防止舍入错误,例如当 a = 8 时。
    【解决方案2】:

    您可以在库中创建 log2 函数,如下所示:

       function f_log2 (x : positive) return natural is
          variable i : natural;
       begin
          i := 0;  
          while (2**i < x) and i < 31 loop
             i := i + 1;
          end loop;
          return i;
       end function;
    

    如果库被导入,您可以像这样指定端口:

    shift_cnt : in std_logic_vector(f_log2(NUMBITS)-1 downto 0)
    

    这是一个有点丑陋的解决方案,但它不使用任何资源(因为函数是纯函数并且所有输入在编译时都是已知的)。

    我通常这样做,但您可能更喜欢将日志值指定为您提到的通用值。

    【讨论】:

    • 这是我的担忧之一——我不想编写一个需要 FPGA 资源来计算的函数。如果可能的话,我仍然想要完全独立的东西(而不是编写一个库,然后记住将它包含在我需要的任何地方)
    • 我明白你为什么想要这样(我也想要,因为这是一个常见的问题!)但我很确定没有更优雅的方法可以做到这一点。在我的公司,我们有一个库,其中包含我们在所有源文件中导入的通用函数。
    【解决方案3】:

    两种替代方法:

    你可以倒过来把 generic 设为 shift_bits - 然后计算输入和输出向量的宽度:

    generic ( shift_bits: integer :=3);                                                   
    Port    ( INPUT     : in   std_logic_vector ((2**shift_bits)-1 downto 0);                
              OUTPUT    : out  std_logic_vector ((2**shift_bits)-1 downto 0);                
              SHIFT_CNT : in   std_logic_vector (shift_bits-1 downto 0)                 
            ); 
    

    或将计数视为一个数字:

    generic ( NUMBITS : integer :=8);                                                   
    Port    ( INPUT     : in   std_logic_vector (NUMBITS-1 downto 0);                
              OUTPUT    : out  std_logic_vector (NUMBITS-1 downto 0);                
              SHIFT_CNT : in   integer range 0 to numbits-1                 
            );  
    

    并让工具为您解决问题。

    【讨论】:

    • 我认为如果 BITWIDTH 不是 2 次方,第一种声明不合适,第二种方式更好。我做了一些带有整数/自然类型输入/输出的模块,但我的同事不接受。那么这有什么问题吗?合成后得到fix-sized吗?
    【解决方案4】:

    我在使用Khan提到的方法时,遇到了舍入错误。所以我写了我自己的版本,它不受舍入错误的影响,原则上可以处理超过 32 位。您可以将 L 的类型替换为具有逻辑左移运算符的任何类型。

    大多数情况下,您希望使用 log2ceil,它是存储给定数字所需的位数,而 log2floor 可以更多地描述为最高位集。

    在大多数情况下,这些函数很适合合成,因为它们用于生成常量。因此没有为它们推断硬件。

    function log2ceil (L: POSITIVE) return NATURAL is
        variable i, bitCount : natural;
    begin
        i := L-1;
        bitCount:=0;
        while (i > 0) loop
            bitCount := bitCount + 1;
            i:=srlInteger(i,1);
        end loop;
        return bitCount;
    end log2ceil;
    
    function log2floor (L: POSITIVE) return NATURAL is
        variable i, bitCount : natural;
    begin
        i := L;
        bitCount:=0;
        while (i > 1) loop
            bitCount := bitCount + 1;
            i:=srlInteger(i,1);
        end loop;
        return bitCount;
    end log2floor;
    
    function srlInteger(arg: integer; s:natural) return integer is
    begin
        return to_integer(SHIFT_RIGHT(to_UNSIGNED(ARG,32), s));
    end srlInteger;
    

    【讨论】:

      【解决方案5】:

      您可以不将 NUMBITS 值输入为 8,而是将其输入为 2 (log2(8)),然后按以下方式重新键入以解决问题,您的泛型不会那么干净,但它是可扩展的.

      entity BarrelShifter is
      
      generic ( NUMBITS : integer :=2);                                                   
      Port    ( INPUT     : in   std_logic_vector (((2**Nbits)-1) downto 0);                
                OUTPUT    : out  std_logic_vector (((2**Nbits)-1) downto 0);                
                SHIFT_CNT : in   std_logic_vector ((NUMBITS-1) downto 0)                 
              );                                                               
      end BarrelShifter;
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2023-04-09
        • 2020-10-15
        • 1970-01-01
        • 1970-01-01
        • 2019-08-26
        • 1970-01-01
        • 2018-04-05
        相关资源
        最近更新 更多