library ieee; use ieee.std_logic_1164.all; --use ieee.std_logic_arith.all; --use ieee.std_logic_unsigned.all; package mypackage is constant p: natural := 4; constant B: natural := 10; constant B_div_2: natural := 5; constant NDIGITS :natural := p+1; constant MDIGITS :natural := p+1; subtype digit is natural range 0 to B-1; type digit_vector is array (integer range <>) of digit; type mybit_vector is array (integer range <>) of std_logic; --function to_integer (x: digit_vector) return natural; --function to_digit_vector (int_x: natural; n: natural) return digit_vector; end mypackage; --------------------------------------------------------- -- Basic base B multiplier (unsigned operands) ---------------------------------------------------------- library IEEE; use IEEE.std_logic_1164.all; use IEEE.std_logic_arith.all; use IEEE.std_logic_unsigned.all; use work.mypackage.all; entity basic_base_B_mult is port ( X: in digit_vector(NDIGITS-1 downto 0); Y: in digit_vector(MDIGITS-1 downto 0); P: out digit_vector(NDIGITS+MDIGITS-1 downto 0) ); end basic_base_B_mult; architecture simple_arch of basic_base_B_mult is component mult_by_1_digit is port ( A: in digit_vector(MDIGITS-1 downto 0); BB: in digit_vector(MDIGITS-1 downto 0); x_i : in digit; P: out digit_vector(MDIGITS downto 0) ); end component; type conections is array (0 to NDIGITS) of digit_vector(MDIGITS downto 0); Signal wires: conections; begin wires(0) <= (others => 0); iterac: for I in 0 to NDIGITS-1 generate mult: mult_by_1_digit port map (A => wires(i)(MDIGITS downto 1), BB => Y, x_i => X(i), P => wires(i+1) ); p(i) <= wires(i+1)(0); end generate; p(MDIGITS+NDIGITS-1 downto NDIGITS) <= wires(NDIGITS)(MDIGITS downto 1); end simple_arch; ---------------------------------------------------- -- Mult_by_1_digit: Caclutate P <= A + (x_i*B) -- where x_i is a digit; A and B are digit vectors ---------------------------------------------------- library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_ARITH.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; use work.mypackage.all; entity mult_by_1_digit is Port ( A: in digit_vector(MDIGITS-1 downto 0); BB: in digit_vector(MDIGITS-1 downto 0); x_i : in digit; P: out digit_vector(MDIGITS downto 0) ); end mult_by_1_digit; architecture Behavioral of mult_by_1_digit is begin process(BB,A, x_i) variable carry: digit_vector(MDIGITS downto 0); begin carry(0) := 0; for i in 0 to MDIGITS-1 loop P(i) <= (BB(i) * X_i + A(i) + carry(i)) mod B; carry(i+1) := (BB(i) * X_i + A(i) + carry(i)) / B; end loop; P(MDIGITS) <= carry(MDIGITS); end process; end Behavioral; library ieee; use ieee.std_logic_1164.all; --use ieee.std_logic_arith.all; --use ieee.std_logic_unsigned.all; use work.mypackage.all; entity multiplication is port ( s1, s2: in digit_vector(0 downto -p); sign1, sign2: in std_logic; e1, e2: in integer; s: out digit_vector(1 downto -2*p); sign: out std_logic; e: out integer ); end multiplication; architecture circuit of multiplication is component basic_base_B_mult port ( X: in digit_vector(NDIGITS-1 downto 0); Y: in digit_vector(MDIGITS-1 downto 0); P: out digit_vector(NDIGITS+MDIGITS-1 downto 0) ); end component; signal int_s1, int_s2: digit_vector(p downto 0); signal unaligned_result: digit_vector(2*p+1 downto 0); begin to_integer: for i in 0 to p generate int_s1(i) <= s1(i-p); int_s2(i) <= s2(i-p); end generate; multiplier: basic_base_B_mult port map (int_s1, int_s2, unaligned_result); alignment: for i in 1 downto -2*p generate s(i) <= unaligned_result(i+2*p); end generate; sign <= sign1 xor sign2; e <= e1 + e2; end circuit; library ieee; use ieee.std_logic_1164.all; --use ieee.std_logic_arith.all; --use ieee.std_logic_unsigned.all; use work.mypackage.all; entity guard_digits is port ( s: in digit_vector(1 downto -2*p); product: out digit_vector(1 downto -(p+2)) ); end guard_digits; architecture behavior of guard_digits is begin process(s) variable acc_or: digit; begin acc_or := 0; for i in -(p+2) downto -2*p loop if (s(i) > 0) or (acc_or > 0) then acc_or := 1; end if; end loop; product <= s(1 downto -(p+1))&acc_or; end process; end behavior; library ieee; use ieee.std_logic_1164.all; --use ieee.std_logic_arith.all; --use ieee.std_logic_unsigned.all; use work.mypackage.all; entity test_guard_digits is end test_guard_digits; architecture test of test_guard_digits is component guard_digits port ( s: in digit_vector(1 downto -2*p); product: out digit_vector(1 downto -(p+2)) ); end component; signal s: digit_vector(1 downto -2*p); signal product: digit_vector(1 downto -(p+2)); begin device_under_test: guard_digits port map (s, product); --s <= (4, 5, 6, 3, 4, 6, 0, 0, 0, 4), (7, 5, 4, 3, 4, 6, 0, 0, 0, 0) after 10 ns, --(4, 9, 9, 3, 4, 6, 1, 1, 0, 0) after 20 ns; end test; library ieee; use ieee.std_logic_1164.all; --use ieee.std_logic_arith.all; --use ieee.std_logic_unsigned.all; use work.mypackage.all; entity test_multiplication is end test_multiplication; architecture test of test_multiplication is component multiplication port ( s1, s2: in digit_vector(0 downto -p); sign1, sign2: in std_logic; e1, e2: in integer; s: out digit_vector(1 downto -2*p); sign: out std_logic; e: out integer ); end component; signal s1, s2: digit_vector(0 downto -p); signal sign1, sign2, sign: std_logic; signal e1, e2, e: integer; signal result: digit_vector(1 downto -2*p); begin device_under_test: multiplication port map (s1, s2, sign1, sign2, e1, e2, result, sign, e); --s1 <= (3, 4, 3), (9, 4, 3) after 10 ns, (4, 7, 6) after 20 ns; --s2 <= (2, 5, 4), (8, 6, 2) after 10 ns, (2, 1, 0) after 20 ns; sign1 <= '0'; sign2 <= '0'; e1 <= 3, 3 after 10 ns, 2 after 20 ns; e2 <= -1, 2 after 10 ns, 3 after 20 ns; end test; library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; use ieee.std_logic_unsigned.all; use work.mypackage.all; entity normalization is port ( e: in natural; product: in digit_vector(1 downto -(p+2)); new_s: out digit_vector(0 downto -(p+3)); new_e: out natural ); end normalization; architecture rtl of normalization is signal product_div_B: digit_vector(0 downto -(p+3)); begin divide_by_B: for i in -(p+3) to 0 generate product_div_B(i) <= product(i+1); end generate; new_s <= product(0 downto -(p+2))&0 when product(1) = 0 else product_div_B; new_e <= e when product(1) = 0 else e+1; end rtl; library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; use ieee.std_logic_unsigned.all; use work.mypackage.all; entity rounding is port ( s: in digit_vector(0 downto -(p+3)); e: in natural; new_s: out digit_vector(0 downto -p); new_e: out natural ); end rounding; architecture behavior of rounding is begin process(s) variable carry: digit_vector(1 downto -p); variable sum: digit_vector(0 downto -p); begin if s(-(p+1)) < B_div_2 then new_s <= s(0 downto -p); new_e <= e; elsif (s(-(p+1)) > B_div_2) or (s(-(p+2)) > 0) or (s(-p) mod 2 = 1) then --plus ulp carry(-p) := 1; for i in -p to 0 loop if s(i) + carry(i) > B-1 then carry(i+1) := 1; else carry(i+1) := 0; end if; sum(i) := (carry(i) + s(i)) mod B; end loop; ------ if carry(1) = 1 then new_s(0) <= 1; for i in -1 downto -p loop new_s(i) <= 0; end loop; new_e <= e+1; else new_s <= sum; new_e <= e; end if; else new_s <= s(0 downto -p); new_e <= e; end if; end process; end behavior; library ieee; use ieee.std_logic_1164.all; --use ieee.std_logic_arith.all; --use ieee.std_logic_unsigned.all; use work.mypackage.all; entity fp_multiplier is port ( sign1, sign2: in std_logic; e1, e2: in integer; s1, s2: in digit_vector(0 downto -p); sign: out std_logic; e: out natural; s: out digit_vector(0 downto -p) ); end fp_multiplier; architecture circuit of fp_multiplier is component multiplication port ( s1, s2: in digit_vector(0 downto -p); sign1, sign2: in std_logic; e1, e2: in integer; s: out digit_vector(1 downto -2*p); sign: out std_logic; e: out integer ); end component; component guard_digits port ( s: in digit_vector(1 downto -2*p); product: out digit_vector(1 downto -(p+2)) ); end component; component normalization port ( e: in natural; product: in digit_vector(1 downto -(p+2)); new_s: out digit_vector(0 downto -(p+3)); new_e: out natural ); end component; component rounding port ( s: in digit_vector(0 downto -(p+3)); e: in natural; new_s: out digit_vector(0 downto -p); new_e: out natural ); end component; signal e_m, e_n: natural; signal s_m: digit_vector(1 downto -2*p); signal s_g: digit_vector(1 downto -(p+2)); signal s_n: digit_vector(0 downto -(p+3)); begin multiplication_component: multiplication port map (s1, s2, sign1, sign2, e1, e2, s_m, sign, e_m); guard_digits_component: guard_digits port map (s_m, s_g); normalization_component: normalization port map (e_m, s_g, s_n, e_n); rounding_component: rounding port map (s_n, e_n, s, e); end circuit; library ieee; use ieee.std_logic_1164.all; --use ieee.std_logic_arith.all; --use ieee.std_logic_unsigned.all; use work.mypackage.all; entity test_fp_multiplier is end test_fp_multiplier; architecture test of test_fp_multiplier is component fp_multiplier port ( sign1, sign2: in std_logic; e1, e2: in integer; s1, s2: in digit_vector(0 downto -p); sign: out std_logic; e: out natural; s: out digit_vector(0 downto -p) ); end component; signal s1, s2, s: digit_vector(0 downto -p); signal sign1, sign2, sign: std_logic; signal e1, e2, e: integer; begin device_under_test: fp_multiplier port map (sign1, sign2, e1, e2, s1, s2, sign, e, s); s1 <= (3, 4, 3, 8, 2), (9, 4, 3, 0, 0) after 10 ns, (4, 7, 6, 1, 9) after 20 ns; s2 <= (2, 5, 4, 7, 1), (8, 6, 2, 0, 0) after 10 ns, (2, 1, 0, 0, 0) after 20 ns; sign1 <= '0', '1' after 10 ns, '0' after 30 ns; sign2 <= '0', '1' after 20 ns; e1 <= 3, 3 after 10 ns, 2 after 20 ns; e2 <= -1, 2 after 10 ns, 3 after 20 ns; end test;