VHDL:使用整数通用的长度来确定选择行的数量

时间:2012-10-05 16:04:26

标签: generics vhdl

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

所需的选择行数由n - >确定。即,下面代码中的SHIFT_CNT = log2(NUMBITS-1)+1。在我的组织中(我认为总体而言)我认为端口不是std_logic_vectorstd_logic,因此我使用了std_logic_vector作为选择的数量线。我需要根据输入泛型来调整std_logic_vector的长度。有没有办法在不使用第二个通用的情况下执行此操作?我发过this帖子,但它并没有处理泛型。 This帖子完全删除了泛型或使用日志值作为通用,这对于未来的用户来说并不直观(如果INPUT不是2的幂,则可能会导致问题)。

以下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;

5 个答案:

答案 0 :(得分:14)

您可以使用数学库来计算logarit结果的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))));

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

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

答案 1 :(得分:7)

您可以在库中创建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)

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

我通常会这样做,但您可能更愿意将日志值指定为您提及的通用值。

答案 2 :(得分:4)

两种替代方法:

你可以向后工作并将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                 
        );  

让工具为您解决。

答案 3 :(得分:0)

当我使用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;

答案 4 :(得分:0)

你可以代替输入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;