2017-02-01 5 views
0

私は、vhdlにブース修正乗数を実装しました。私はVivadoと合成する必要がありますが、このエラーのためには不可能です: "複雑な割り当てはサポートされていません"。 これは、エラーの原因となるシフターコードです:ビバード合成:複雑な代入はサポートされていません

entity shift_register is 
generic (
N : integer := 6; 
M : integer := 6 
); 
port (
en_s   : in std_logic; 
cod_result  : in std_logic_vector (N+M-1 downto 0); 
position  : in integer; 
shift_result : out std_logic_vector(N+M-1 downto 0) 
);  
end shift_register; 

architecture shift_arch of shift_register is 
begin 
process(en_s) 

variable shift_aux : std_logic_vector(N+M-1 downto 0); 
variable i : integer := 0; --solo per comodità 
begin 
    if(en_s'event and en_s ='1') then 
     i := position; 
     shift_aux := (others => '0'); 
     shift_aux(N+M-1 downto i) := cod_result(N+M-1-i downto 0); --ERROR!! 
     shift_result <= shift_aux ; 
    end if; 
end process; 
end shift_arch; 

ブース乗算器は任意のオペレータの次元で動作します。だから私はこの一般的なコードを特定のものに変更することはできません。 私を助けてください!ありがとうございます

答えて

0

実行時のさまざまな値を使用して範囲を作成しようとしていますが、これは合成ツールではサポートされていません。 N,Mおよび1はすべて合成時に既知であるため、cod_result(N+M-1 downto 0);がサポートされます。

乗算器を実装しようとしている場合、x <= a * bを使用して最適な結果を得て、合成ツールで最適な方法を選択するようにします。あなたのデバイスの乗数よりも広いオペランドがある場合、ドキュメントを見て、通常はある種のパイプライン処理を含む最適なルートを判断する必要があります。

実行時の変数シフトが必要な場合は、「バレルシフタ」を探します。既存の回答があります(例:this one)。

+0

私はなぜ動作しないのか分かりますが、私の仕事はx <= a * bを使うことができないようにブース乗数を実装することです。とにかくお返事 –

+0

@DarioFigliuzziので、あなたの実際の質問は "私はどのようにバレルシフタを実装しますか?"です。そうである場合、これに関する既存の質問があります。 –

+0

私はこの問題を回避する方法についてもっと考えていました。代わりの方法 –

1

索引付けを静的合成にする方法があります。

最初に、ループに基づいて、の範囲内の値を持つ必要があります。そうしないと、ヌルスライス(IEEE Std 1076-2008 8.5スライス名)になります。実体宣言で示すことができる

:変更内容

library ieee; 
use ieee.std_logic_1164.all; 

entity shift_register is 
    generic (
     N: integer := 6; 
     M: integer := 6 
    ); 
    port (
     en_s:   in std_logic; 
     cod_result: in std_logic_vector (N + M - 1 downto 0); 
     position:  in integer range 0 to N + M - 1 ; -- range ADDED 
     shift_result: out std_logic_vector(N + M - 1 downto 0) 
    );  
end entity shift_register; 

positionのポート宣言の範囲の制約を追加することです。この考え方は、デフォルト値が整数であることができるシミュレーションをサポートすることです。integer'leftです。 shift_registerをシミュレートすると、shift_auxのインデックス範囲の最初の値がposition(実際のドライバ)に指定されていないと、en_sの立ち上がりエッジでエラーが発生します。

合成の観点から、無制限の整数では、正と負の両方の整数値を考慮する必要があります。 forループは正の整数値のみを使用しています。

同じプロセスで、変数iの宣言で行うことができます

 variable i:   integer range 0 to N + M - 1 := 0; -- range ADDED 

我々はのためのループを見てすぐに合成の問題に対処するために。

ザイリンクスサポートの問題AR# 52302は、インデックスに動的値を使用している問題を示しています。

architecture shift_loop of shift_register is 

begin 

    process (en_s) 
     variable shift_aux: std_logic_vector(N + M - 1 downto 0); 
    -- variable i:   integer range 0 to N + M - 1 := 0; -- range ADDED 
    begin 
     if en_s'event and en_s = '1' then 
      -- i := position; 
      shift_aux := (others => '0'); 
      for i in 0 to N + M - 1 loop 
      -- shift_aux(N + M - 1 downto i) := cod_result(N + M - 1 - i downto 0); 
       if i = position then 
        shift_aux(N + M - 1 downto i) 
         := cod_result(N + M - 1 - i downto 0); 
       end if; 
      end loop; 
      shift_result <= shift_aux; 
     end if; 
    end process; 

end architecture shift_loop; 

iループは、それがインデックスの計算に使用することができる合成に展開される静的な値となった場合:

溶液はないループのもの修正することです。

これはN + M入力マルチプレクサを示しています。ここで、各入力はi = positionのときに選択されています。

NとMの大きな値に関連する変数の数が非常に多くの合成作業を必要とするか、単に失敗することが予想されるかもしれませんが、このコンストラクトは最適化によって実際にバレルシフタに縮小できます。

合成が成功すると、割り当ての各出力要素が、パトリックの barrel shifterと一致する別のマルチプレクサに折りたたまれます。

NとMの値が十分大きいと、バレルシフタのマルチプレクサレイヤ数の深さを整数の距離範囲のバイナリ表現のビット数に基づいて定義できます。

positionに宣言された整数型またはサブタイプが必要か、またはN + Mのlog2値を見つける必要があります。静的にしか使用されないので、log2値を使用できます。 (XSTはlog2(x)をサポートします。ここで、xは静的値を決定するためのRealです。関数はIEEEパッケージmath_realにあります)。これにより、バイナリの長さはpositionになります。 (シフト距離、マルチプレクサのレベル数を記述するために必要なビット数)。左のオペランドが2であるとiの値はループ文で見つかった一連の文で定数として扱われている場合

architecture barrel_shifter of shift_register is 
begin 
    process (en_s) 
     use ieee.math_real.all; -- log2 [real return real] 
     use ieee.numeric_std.all; -- to_unsigned, unsigned 
     constant DISTLEN: natural := integer(log2(real(N + M))); -- binary lengh 
     type muxv is array (0 to DISTLEN - 1) of 
         unsigned (N + M - 1 downto 0); 
     variable shft_aux:  muxv; 
     variable distance:  unsigned (DISTLEN - 1 downto 0); 
    begin 
     if en_s'event and en_s = '1' then 
      distance := to_unsigned(position, DISTLEN); -- position in binary 
      shft_aux := (others => (others =>'0')); 
      for i in 0 to DISTLEN - 1 loop 
       if i = 0 then 
        if distance(i) = '1' then 
         shft_aux(i) := SHIFT_LEFT(unsigned(cod_result), 2 ** i); 
        else 
         shft_aux(i) := unsigned(cod_result); 
        end if; 
       else 
        if distance(i) = '1' then 
         shft_aux(i) := SHIFT_LEFT(shft_aux(i - 1), 2 ** i); 
        else 
         shft_aux(i) := shft_aux(i - 1); 
        end if; 
       end if; 
      end loop; 
      shift_result <= std_logic_vector(shft_aux(DISTLEN - 1)); 
     end if; 
    end process; 
end architecture barrel_shifter; 

XSTも**をサポートしています。

これは、変数の代わりに、またはループステートメントの代わりにgenerateステートメントに構造的に、またはサブプログラムとして実装することができます。

この2つのアーキテクチャの基本的な考え方は、あなたのものから派生したものを合成することです。

最初の上に第二のアーキテクチャの利点は、これらのアーキテクチャのいずれも元にテストベンチを欠いて検証されたN + M.

のより大きな値に対して最適化中に合成努力の量の減少です。彼らは分析して精緻化しています。単純なケーステストベンチ書き込み

library ieee; 
use ieee.std_logic_1164.all; 
use ieee.numeric_std.all; 

entity shift_register_tb is 
end entity; 

architecture foo of shift_register_tb is 
    constant N:  integer := 6; 
    constant M:  integer := 6; 
    signal clk:  std_logic := '0'; 
    signal din:  std_logic_vector (N + M - 1 downto 0) 
           := (0 => '1', others => '0'); 
    signal dout:  std_logic_vector (N + M - 1 downto 0); 
    signal dist:  integer := 0; 
begin 
DUT: 
    entity work.shift_register 
     generic map (
      N => N, 
      M => M 
     ) 
     port map (
      en_s => clk, 
      cod_result => din, 
      position => dist, 
      shift_result => dout 
     ); 
CLOCK: 
    process 
    begin 
     wait for 10 ns; 
     clk <= not clk; 
     if now > (N + M + 2) * 20 ns then 
      wait; 
     end if; 
    end process; 
STIMULI: 
    process 
    begin 
     for i in 1 to N + M loop 
      wait for 20 ns; 
      dist <= i; 
      din <= std_logic_vector(SHIFT_LEFT(unsigned(din),1)); 
     end loop; 
     wait; 
    end process; 
end architecture; 

そしてシミュレートはpositionの範囲とループ反復の回数だけ乗算なく被乗数のビット数をカバーするために必要であることがわかります。フルバレルシフターは必要ありません。

これは、shift_registerアーキテクチャで簡単に修正することができ、shift_loopアーキテクチャをより魅力的にするという副作用があります。乗算器のビット長(おそらくM)に基づいて合成する方が簡単ですN + M)。

そして、それはあなたを与えるだろう:

library ieee; 
use ieee.std_logic_1164.all; 

entity shift_register is 
    generic (
     N: integer := 6; 
     M: integer := 6 
    ); 
    port (
     en_s:   in std_logic; 
     cod_result: in std_logic_vector (N + M - 1 downto 0); 
     position:  in integer range 0 to M - 1 ; -- range ADDED 
     shift_result: out std_logic_vector(N + M - 1 downto 0) 
    );  
end entity shift_register; 

architecture shift_loop of shift_register is 
begin 
    process (en_s) 
     variable shift_aux: std_logic_vector(N + M - 1 downto 0); 
    -- variable i:   integer range 0 to M - 1 := 0; -- range ADDED 
    begin 
     if en_s'event and en_s = '1' then 
      -- i := position; 
      shift_aux := (others => '0'); 
      for i in 0 to M - 1 loop 
      -- shift_aux(N + M - 1 downto i) := cod_result(N + M - 1 - i downto 0); 
       if i = position then -- This creates an N + M - 1 input MUX 
        shift_aux(N + M - 1 downto i) 
         := cod_result(N + M - 1 - i downto 0); 
       end if; 
      end loop; -- The loop is unrolled in synthesis, i is CONSTANT 
      shift_result <= shift_aux; 
     end if; 
    end process;  
end architecture shift_loop; 

は、テストベンチを変更:

STIMULI: 
    process 
    begin 
     for i in 1 to M loop -- WAS N + M loop 
      wait for 20 ns; 
      dist <= i; 
      din <= std_logic_vector(SHIFT_LEFT(unsigned(din),1)); 
     end loop; 
     wait; 
    end process; 

はシフトを示す結果になりますが(Mによって指定された)乗数値の範囲を超えている。

shift_register_tb_1.png

ここでは、道徳的なものは完全ではありませんバレルシフタは、乗算器の範囲で動作し、製品の範囲では動作しません。

コードの最後のビットは合成適格でなければなりません。

関連する問題