我试图用组合逻辑制作一个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,以反映为便于阅读而建议的更改(测试并编译仍然很好,根本没有值。)
以下是模拟图片:
答案 0 :(得分:1)
这个实现不是为了易于理解而编写的,并且有许多可能的改进。
但我怀疑最重要的一点是:据我所知,你只是在名为“temp”的数组中分配每个部分产品的一部分,而剩下的每个部分产品都是“UUUU”。我们只保证RRU单元“工作”,无法告知他们是否将这些“UUU”输入值解析为输出中的“UUU”;它们似乎很可能。建议您为每个“temp”值的ALL分配定义的值。这可能足以解决困难,但除非您使用缺失的信息更新问题,否则只能告诉您。
进一步改进:
partial_products
而不是temp
?sign
而不是temp_man(8)
? Ditto指数,而a_mantissa
代替'1'& A_VAL(22 downto 0)
numeric_std
而不是std_logic_arith和std_logic_unsigned(这可能相互矛盾)。然后将未签名的数量(如部分产品)声明为“unsigned”而不是slv。ZERO
(!)的值,否则请将其声明为常量而不是信号((others => '0')
表单会保存对所有这些数字的计数!)。holder
的{{1}}的两个切片大小不同。如果你说,在这种情况下“一切都完美编译”,请提交针对您正在使用的工具的错误报告,并在此处发布其名称和版本,以便我们可以避免使用它。答案 1 :(得分:0)
您的测试平台应至少驱动FB_MULTIPIER组件的输入(a.k.a 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
答案 2 :(得分: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;