web-dev-qa-db-ja.com

VHDL:整数ジェネリックの長さを使用して選択行の数を決定します

私は再利用可能なバレルシフターを作成しようとしています。ビットの入力配列を取り、それらを特定の数の位置にシフトします(別の入力によって決定されます)。モジュールをパラメーター化して、どのnでも機能するようにします。

必要な選択行の数は、n->つまり、以下のコードのSHIFT_CNT = log2(NUMBITS-1)+1によって決まります。 std_logic_vectorまたはstd_logic以外のポートを使用することは、私の組織(および私は全体的に考えると)では不適切なフォームと見なされるため、選択行の数にstd_logic_vectorを使用しました。入力ジェネリックに基づいてstd_logic_vectorの長さを調整する必要があります。 2番目のジェネリックを使用せずにこれを行う方法はありますか?私は this の投稿を見てきましたが、ジェネリックを扱いません。 This postは、ジェネリックを完全に削除するか、ログ値をジェネリックとして使用します。これは、将来のユーザーにとって直感的ではありません(INPUTが2の累乗でない場合、問題が発生する可能性があります) )。

以下のSHIFT_CNTの宣言は間違いなく間違っています。 2番目のジェネリックを使用せずにエンティティ宣言で長さを自動的に生成する方法はありますか?

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;
11
NickD

数学ライブラリを使用して、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))));

これらの関数を使用してパラメーターを計算する場合、あなたのコードは合成可能(私がやった)

エンティティで使用したくない場合は、ライブラリで宣言するか、これらの関数でジェネリックを宣言できます。

18
Khanh N. Dang

次のように、ライブラリに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)

これはやや醜いソリューションですが、リソースを使用しません(関数は純粋で、すべての入力はコンパイル時に既知であるため)。

私は通常これを行いますが、あなたが言及しているようにログ値をジェネリックとして指定することを好むかもしれません。

7
pc3e

2つの代替アプローチ:

あなたはそれを逆に作業し、genericshift_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                 
        );  

ツールがそれを理解できるようにします。

4
Martin Thompson

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;
0
Ben Parkes

カーンが述べた方法を使用していたときに、丸めエラーが発生しました。そこで、丸め誤差の影響を受けず、原則として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;
0
Karsten Becker