0

組み合わせロジックで 32 ビット浮動小数点乗算器を作成しようとしています。テストベンチをシミュレートしようとする場合を除いて、私が知る限り、そうしました。コードを入力してシミュレートすると、すべての値で U が得られます。コードを取り出してシミュレートすると、入力ベクトルが得られます。仮数部をまだ完全に正規化していないことはわかっています。なぜなのか全く理解できません。すべてが完全にコンパイルされます。私が抱えている唯一の問題は、テストベンチをシミュレートするときに値を取得することです...すべてがすべて正しく呼び出されています。どんな助けでも大歓迎です。

テストベンチが機能することに注意してください。正しい値を返す他の VHDL でシミュレートしました。

乗数のコードは次のとおりです。

library IEEE                   ;
use IEeE.std_logic_1164.all    ;
use ieee.std_logic_arith.all   ;
use ieee.numeric_std.all       ;
Use Ieee.std_logic_unsigned.all; 

entity FP_MULTIPLIER is
    port( A_VAL, B_VAL : in std_logic_vector (31 downto 0);
            F_VAL : out std_logic_vector (31 downto 0));
end FP_MULTIPLIER;--

architecture Behavioral of FP_MULTIPLIER is
signal exponant : std_logic_vector (8 downto 0);
signal holder : std_logic_vector (47 downto 0);
signal PPA1 : std_logic_vector (47 downto 0);
signal PPA2 : std_logic_vector (47 downto 0);
signal PPA3 : std_logic_vector (47 downto 0);
signal PPA4 : std_logic_vector (47 downto 0);
signal PPA5 : std_logic_vector (47 downto 0);
signal PPA6 : std_logic_vector (47 downto 0);
signal PPA7 : std_logic_vector (47 downto 0);
signal PPA8 : std_logic_vector (47 downto 0);
signal PPA9 : std_logic_vector (47 downto 0);
signal AD1  : std_logic_vector (47 downto 0);
signal AD2  : std_logic_vector (47 downto 0);
signal AD3  : std_logic_vector (47 downto 0);
signal almost:std_logic_vector (23 downto 0);
signal F0:std_logic_vector (47 downto 0);
signal F1:std_logic_vector (47 downto 0);
constant ZERO : std_logic_vector := "000000000000000000000000000000000000000000000000";     --zero vektir for imputs

type temp_MP is array (6 downto 1) of std_logic_vector (47 downto 0);
signal MP :temp_MP;
type temp_PPA is array (23 downto 0) of std_logic_vector (47 downto 0);                         --creates 24 vectir array of 49 length
signal temp :temp_PPA := (others => (others => '0'));
begin

exponant(8) <= A_VAL(31) xor B_VAL(31);                                                         --gets sign bit
exponant (7 downto 0) <= ((A_VAL (30 downto 23) + B_VAL (30 downto 23)) - 127 );                --gets exponant

partial : for I in 0 to 23 generate
    temp(I) (23+I downto I) <= '1'& A_VAL(22 downto 0) WHEN B_VAL(I)='1' ELSE                   --fills vector array and shifts it properly
                                    (others => '0');
end generate partial;


RRU1 : entity work.RRU7_3 port map (temp(0),temp(1),temp(2),temp(3),temp(4),temp(5),temp(6),PPA1,PPA2,PPA3);
RRU2 : entity work.RRU7_3 port map (temp(7),temp(8),temp(9),temp(10),temp(11),temp(12),temp(13),PPA4,PPA5,PPA6);
RRU3 : entity work.RRU7_3 port map (temp(14),temp(15),temp(16),temp(17),temp(18),temp(19),temp(20),PPA7,PPA8,PPA9);
RRU4 : entity work.RRU7_3 port map (temp(21),temp(22),temp(23),ZERO,PPA7,PPA8,PPA9,MP(1),MP(2),MP(3));
RRU5 : entity work.RRU7_3 port map (PPA1,PPA2,PPA3,PPA4,PPA5,PPA6,ZERO,MP(4),MP(5),MP(6));
RRU6 : entity work.RRU7_3 port map (MP(1),MP(2),MP(3),MP(4),MP(5),MP(6),ZERO,AD1,AD2,AD3);
RRU32: entity work.RRU3_2 port map (AD1,AD2,AD3,F1,F0);

holder <= F1+ F0;    --implement with CSA?

almost <=   holder(46 downto 22) WHEN holder(47)='1' ELSE  --fix for rounding and radix point
                holder(45 downto 21);

F_VAL <= exponant & almost;

end Behavioral;

私のテストベンチのコードは次のとおりです。

library IEEE;
use IEEE.STD_LOGIC_1164.all;
use STD.TEXTIO.all;
use IEEE.STD_LOGIC_TEXTIO.all;

entity ATB_FPM is
end entity ATB_FPM;

architecture ATB_FPM of ATB_FPM is

component FP_MULTIPLIER is
  port (
    A_VAL : in  STD_LOGIC_VECTOR ( 31 downto 0 );
    B_VAL : in  STD_LOGIC_VECTOR ( 31 downto 0 );
    F_VAL : out STD_LOGIC_VECTOR ( 31 downto 0 )
  );
end component FP_MULTIPLIER;

type F_VALS_ARRAY is array ( 0 to 15 ) of STD_LOGIC_VECTOR ( 31 downto 0 );
constant A_VALS : F_VALS_ARRAY := (
  X"3F800000", X"3F800000", X"3FA33333", X"38D1B717",
  X"41160000", X"41020831", X"43000000", X"40300000",
  X"47129320", X"41B80A3D", X"42C80000", X"46EC8E00",
  X"49791900", X"45800000", X"46733D52", X"390164EF"
);
constant B_VALS : F_VALS_ARRAY := (
  X"40000000", X"449F6000", X"42C80000", X"3951B717",
  X"460CAF00", X"42F61EB8", X"43800000", X"46210100",
  X"47000600", X"3B8B4396", X"43480000", X"4641BC00",
  X"3C4A42AF", X"46000000", X"44FC8666", X"3959945B"
);

signal X_A_VAL : STD_LOGIC_VECTOR ( 31 downto 0 );
signal X_B_VAL : STD_LOGIC_VECTOR ( 31 downto 0 );
signal X_F_VAL : STD_LOGIC_VECTOR ( 31 downto 0 );

begin
UUT: FP_MULTIPLIER
  port map (
    A_VAL => X_A_VAL,
    B_VAL => X_B_VAL,
    F_VAL => X_F_VAL
  );

process
variable DLAY : TIME;
constant T50N : TIME := 50 ns;
file OUT_FILE : TEXT open WRITE_MODE is "results.txt";
variable BUF  : LINE;
constant SP2  : STRING( 1 to 2 ) := "  ";
constant SP4  : STRING( 1 to 4 ) := "    ";
constant HDR  : STRING( 1 to 38 ) := "  A_VAL     B_VAL       F_VAL     TIME";
variable LNO  : INTEGER := 1;
begin
   for I in 0 to 15 loop
     if LNO = 1 then
       LNO := LNO + 1;
       write ( BUF, HDR );
       writeline ( OUT_FILE, BUF );
     elsif LNO = 25 then
       LNO := 1;
     else
       LNO := LNO + 1;
     end if;
     X_A_VAL <= A_VALS(I) ;    X_B_VAL <= B_VALS(I);
     wait for 50 ns;
     DLAY := T50N - X_F_VAL'LAST_EVENT; 
   hwrite ( BUF, X_A_VAL );  write ( BUF, SP2 );
   hwrite ( BUF, X_B_VAL );  write ( BUF, SP4 );
   hwrite ( BUF, X_F_VAL );  write ( BUF, SP4 );
   write  ( BUF, DLAY    );
   writeline ( OUT_FILE, BUF );
   end loop;
end process;

end architecture ATB_FPM;

多くの要望により、これが私の RRU7to3 です。

library IEEE;
use IEEE.STD_LOGIC_1164.all;

entity RRU7_3 is
  port (
    A_VEC  : in  STD_LOGIC_VECTOR ( 47 downto 0 );
    B_VEC  : in  STD_LOGIC_VECTOR ( 47 downto 0 );
    C_VEC  : in  STD_LOGIC_VECTOR ( 47 downto 0 );
    D_VEC  : in  STD_LOGIC_VECTOR ( 47 downto 0 );
    E_VEC  : in  STD_LOGIC_VECTOR ( 47 downto 0 );
    F_VEC  : in  STD_LOGIC_VECTOR ( 47 downto 0 );
    G_VEC  : in  STD_LOGIC_VECTOR ( 47 downto 0 );
    F2_VEC : out STD_LOGIC_VECTOR ( 47 downto 0 );
    F1_VEC : out STD_LOGIC_VECTOR ( 47 downto 0 );
    F0_VEC : out STD_LOGIC_VECTOR ( 47 downto 0 )
  );
end entity RRU7_3;

architecture WASTEFUL of RRU7_3 is

component WTA7_3 is
  port (
    A  : in  STD_LOGIC;
    B  : in  STD_LOGIC;
    C  : in  STD_LOGIC;
    D  : in  STD_LOGIC;
    E  : in  STD_LOGIC;
    F  : in  STD_LOGIC;
    G  : in  STD_LOGIC;
    F0 : out STD_LOGIC;
    F1 : out STD_LOGIC;
    F2 : out STD_LOGIC
  );
end component WTA7_3;

signal ROW2 : STD_LOGIC_VECTOR ( 65 downto 0 );
signal ROW1 : STD_LOGIC_VECTOR ( 65 downto 0 );
signal ROW0 : STD_LOGIC_VECTOR ( 65 downto 0 );

begin

GEN_LABEL: for I in 0 to 47 generate
  WTAUNIT: WTA7_3
    port map (
      A  => A_VEC(I),
      B  => B_VEC(I),
      C  => C_VEC(I),
      D  => D_VEC(I),
      E  => E_VEC(I),
      F  => F_VEC(I),
      G  => G_VEC(I),
      F0 => ROW0(I),
      F1 => ROW1(I+1),
      F2 => ROW2(I+2)
  );
end generate;

  F0_VEC <= ROW0( 47 downto 0 );
  F1_VEC <= ROW1( 47 downto 1 ) & '0';
  F2_VEC <= ROW2( 47 downto 2 ) & "00";

end architecture WASTEFUL;

これがRRU3to2です

library IEEE;
use IEEE.STD_LOGIC_1164.all;

entity RRU3_2 is
  port (
    A_VEC  : in  STD_LOGIC_VECTOR ( 47 downto 0 );
    B_VEC  : in  STD_LOGIC_VECTOR ( 47 downto 0 );
    C_VEC  : in  STD_LOGIC_VECTOR ( 47 downto 0 );
    F1_VEC : out STD_LOGIC_VECTOR ( 47 downto 0 );
    F0_VEC : out STD_LOGIC_VECTOR ( 47 downto 0 )
  );
end entity RRU3_2;

architecture WASTEFUL of RRU3_2 is

component CSADDER is
  generic (
    G_DELAY : TIME := 1 ns
  );
  port (
    A : in  STD_LOGIC;
    B : in  STD_LOGIC;
    C : in  STD_LOGIC;
    F0: out STD_LOGIC;
    F1: out STD_LOGIC
  );
end component CSADDER;

signal ROW1 : STD_LOGIC_VECTOR ( 48 downto 0 );
signal ROW0 : STD_LOGIC_VECTOR ( 48 downto 0 );

begin

GEN_LABEL: for I in 0 to 47 generate
  WTAUNIT: CSADDER
    port map (
      A  => A_VEC(I),
      B  => B_VEC(I),
      C  => C_VEC(I),
      F0 => ROW0(I),
      F1 => ROW1(I+1)
  );
end generate;

  F0_VEC <= ROW0( 47 downto 0 );
  F1_VEC <= ROW1( 47 downto 1 ) & '0';

end architecture WASTEFUL;

また、上記の FP_Multiplier を編集して、読みやすくするために提案された変更を反映させました (テストしてコンパイルしても問題ありませんが、値はありません)。

シミュレーションのイメージは次のとおりです。

シミュレーションは U のみを生成し、実行を拒否します

4

3 に答える 3

1

この実装は簡単に理解できるように書かれておらず、多くの改善点があります。

しかし、最も重要なポイントは次のとおりだと思います。私が見る限り、「temp」と呼ばれる配列内の各部分積の一部のみを割り当て、各部分積の残りは「UUUU」のままにしています。RRU ユニットが「機能する」という保証だけがあり、それらがこれらの「UUU」入力値を出力で「UUU」に解決しているかどうかを知る方法はありません。そうである可能性が高いようです。各「一時」値のすべてに定義済みの値を割り当てることをお勧めします。問題を解決するにはそれで十分かもしれませんが、不足している情報で質問を更新しない限り、あなただけが知ることができます.

さらなる改良:

  1. partial_productsではなく、部分積配列を次のように呼んでみませんtempか?
  2. signの代わりに符号ビットを呼び出してみませんtemp_man(8)か? 同上の指数であり、a_mantissa 代わりに'1'& A_VAL(22 downto 0)
  3. vermaete が言ったようnumeric_stdに、 std_logic_arith と std_logic_unsigned (おそらく互いに矛盾する) の代わりに標準ライブラリを使用してください。次に、符号なしの数量 (部分積など) を slv ではなく「符号なし」として宣言します。
  4. (!)の値を変更するつもりがない限りZERO、signal の代わりに定数として宣言してください (そして、(others => '0')フォームはこれらすべての桁のカウントを節約します!)。
  5. holder割り当て先の 2 つのスライスalmostはサイズが異なることに注意してください。あなたが言うように、この状態で「すべてが完全にコンパイルされる」場合は、使用しているツールに対してバグレポートを提出し、その名前とバージョンをここに投稿して、使用しないようにしてください。
于 2013-03-01T17:57:58.300 に答える
0

ベクトル配列が、彼らが取り組んでいる関数と一致しないという、少し複雑な問題がありました。これを修正し、ベクトルがゼロで「埋められる」場所も取り出します。コードが動作するようになりました。ただし、まだ数値を正規化していないことに注意してください。ただし 、特定のポイントにある程度正確な数値が得られます。

好奇心旺盛な人のために、ここにやや機能する説明があります

library IEEE                   ;
use IEeE.std_logic_1164.all    ;
use ieee.std_logic_arith.all   ;
use ieee.numeric_std.all       ;
Use Ieee.std_logic_unsigned.all; 

entity FP_MULTIPLIER is
    port( A_VAL, B_VAL : in std_logic_vector (31 downto 0);
            F_VAL : out std_logic_vector (31 downto 0));
end FP_MULTIPLIER;--

architecture Behavioral of FP_MULTIPLIER is
signal exponant : std_logic_vector (8 downto 0);
signal holder : std_logic_vector (47 downto 0);
signal PPA1 : std_logic_vector (47 downto 0);
signal PPA2 : std_logic_vector (47 downto 0);
signal PPA3 : std_logic_vector (47 downto 0);
signal PPA4 : std_logic_vector (47 downto 0);
signal PPA5 : std_logic_vector (47 downto 0);
signal PPA6 : std_logic_vector (47 downto 0);
signal PPA7 : std_logic_vector (47 downto 0);
signal PPA8 : std_logic_vector (47 downto 0);
signal PPA9 : std_logic_vector (47 downto 0);
signal AD1  : std_logic_vector (47 downto 0);
signal AD2  : std_logic_vector (47 downto 0);
signal AD3  : std_logic_vector (47 downto 0);
signal almost:std_logic_vector (23 downto 0);
signal there: std_logic_vector (23 downto 0);
signal F0:std_logic_vector (47 downto 0);
signal F1:std_logic_vector (47 downto 0);
constant ZERO : std_logic_vector := "000000000000000000000000000000000000000000000000";     --zero vektir for imputs

type temp_MP is array (6 downto 1) of std_logic_vector (47 downto 0);
signal MP :temp_MP;
type temp_PPA is array (23 downto 0) of std_logic_vector (47 downto 0);                         --creates 24 vectir array of 49 length
signal temp :temp_PPA := (others => (others => '0'));
begin

exponant(8) <= A_VAL(31) xor B_VAL(31);                                                         --gets sign bit
exponant (7 downto 0) <= ((A_VAL (30 downto 23) + B_VAL (30 downto 23)) - 127 );                --gets exponant

partial : for I in 0 to 23 generate
    temp(I) (23+I downto I) <= '1'& A_VAL(22 downto 0) WHEN B_VAL(I)='1' ELSE                   --fills vector array and shifts it properly
                                    (others => '0');
end generate partial;


RRU1 : entity work.RRU7_3 port map (temp(0),temp(1),temp(2),temp(3),temp(4),temp(5),temp(6),PPA1,PPA2,PPA3);
RRU2 : entity work.RRU7_3 port map (temp(7),temp(8),temp(9),temp(10),temp(11),temp(12),temp(13),PPA4,PPA5,PPA6);
RRU3 : entity work.RRU7_3 port map (temp(14),temp(15),temp(16),temp(17),temp(18),temp(19),temp(20),PPA7,PPA8,PPA9);
RRU4 : entity work.RRU7_3 port map (temp(21),temp(22),temp(23),ZERO,PPA7,PPA8,PPA9,MP(1),MP(2),MP(3));
RRU5 : entity work.RRU7_3 port map (PPA1,PPA2,PPA3,PPA4,PPA5,PPA6,ZERO,MP(4),MP(5),MP(6));
RRU6 : entity work.RRU7_3 port map (MP(1),MP(2),MP(3),MP(4),MP(5),MP(6),ZERO,AD1,AD2,AD3);
RRU32: entity work.RRU3_2 port map (AD1,AD2,AD3,F1,F0);

holder <= F1+ F0;

almost <=   holder(46 downto 23) WHEN holder(47)='1' ELSE
                holder(47 downto 24);

F_VAL <= exponant & almost (22 downto 0);

end Behavioral;
于 2013-03-02T00:41:53.357 に答える
0

テストベンチは、少なくとも FB_MULTIPIER コンポーネント (別名DUT ) の入力を駆動する必要があります。より良いケースでは、DUT の出力も読み取って、期待どおりかどうかをチェックします。

あなたのテストベンチでは、X_A_VAL と X_B_VAL に値を割り当てる場所が見つかりませんでした。std_logic を駆動しない場合、初期化されていない状態 ('U') になります。

そして補足として:

use ieee.std_logic_arith.all   ;
use ieee.numeric_std.all       ;
Use Ieee.std_logic_unsigned.all; 

古いスタイルと新しいスタイルのライブラリが混在しています。詳細については、VHDL FAQを参照してください。しかし、私はあなたがそれをしないことをお勧めします.use ieee.numeric_std.all

于 2013-03-01T08:40:21.453 に答える