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; 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; end mypackage; 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 alignment is port ( sign1, sign2, operation: in std_logic; e1, e2: in integer; s1, s2: in digit_vector(0 downto -p); dif: inout natural; sign, new_sign2: out std_logic; e, new_e2: out natural; aligned_s1, aligned_s2: out digit_vector(0 downto -(p+3)) ); end alignment; architecture behavior of alignment is signal actual_sign2: std_logic; signal s, new_s2: digit_vector(0 downto -p); signal shift_length: natural; signal sticky: digit; begin actual_sign2 <= operation xor sign2; process(sign1, actual_sign2, e1, e2, s1, s2, s) begin if e1 < e2 then dif <= e2 - e1; e <= e2; new_e2 <= e1; sign <= actual_sign2; new_sign2 <= sign1; s <= s2; new_s2 <= s1; else dif <= e1 - e2; e <= e1; new_e2 <= e2; sign <= sign1; new_sign2 <= actual_sign2; s <= s1; new_s2 <= s2; end if; aligned_s1(-(p+1)) <= 0; aligned_s1(-(p+2)) <= 0; aligned_s1(-(p+3)) <= 0; for i in 0 downto -p loop aligned_s1(i) <= s(i); end loop; end process; barrel_shifter: process(dif, shift_length, new_s2, sticky) variable a: digit_vector(0 downto -(2*p+3)); variable acc_or: digit; begin for i in -(p+1) downto -(2*p+3) loop a(i) := 0; end loop; for i in 0 downto -p loop a(i) := new_s2(i); end loop; if dif < p+3 then shift_length <= dif; else shift_length <= p+3; end if; if shift_length > 0 then for j in 1 to shift_length loop for i in -(2*p+3) to -1 loop a(i) := a(i+1); end loop; a(0) := 0; end loop; end if; acc_or := 0; for i in -(p+3) downto -(2*p+2) loop if (a(i) > 0) or (acc_or > 0) then acc_or := 1; end if; end loop; sticky <= acc_or; aligned_s2 <= a(0 downto -(p+2))&sticky; end process barrel_shifter; end behavior; library ieee; use ieee.std_logic_1164.all; use work.mypackage.all; entity test_alignment is end test_alignment; architecture test of test_alignment is component alignment port ( sign1, sign2, operation: in std_logic; e1, e2: in integer; s1, s2: in digit_vector(0 downto -p); dif: inout natural; sign, new_sign2: out std_logic; e, new_e2: out natural; aligned_s1, aligned_s2: out digit_vector(0 downto -(p+3)) ); end component; signal sign1, sign2, operation: std_logic; signal e1, e2: integer; signal s1, s2: digit_vector(0 downto -p); signal dif: natural; signal sign, new_sign2: std_logic; signal e, new_e2: natural; signal aligned_s1, aligned_s2: digit_vector(0 downto -(p+3)); begin device_under_test: alignment port map (sign1, sign2, operation, e1, e2, s1, s2, dif, sign, new_sign2, e, new_e2, aligned_s1, aligned_s2); sign1 <= '0'; sign2 <= '0'; operation <= '0', '1' after 30 ns, '0' after 70 ns; e1 <= 3, 3 after 10 ns, 3 after 20 ns, -1 after 30 ns, 3 after 40 ns, 4 after 50 ns; e2 <= -1, 2 after 10 ns, 2 after 20 ns, 3 after 30 ns, 2 after 40 ns, 2 after 50 ns, -4 after 60 ns; s1 <= (3,4,3,7,5), (9,4,3,7,5) after 10 ns, (9,4,3,7,5) after 20 ns, (3,4,5,1,8) after 30 ns, (1,0,0,1,4) after 40 ns, (1,0,7,1,4) after 50 ns; s2 <= (2,5,4,9,1), (8,6,2,4,7) after 10 ns, (5,6,2,4,7) after 20 ns, (7,2,4,7,1) after 30 ns, (9,9,4,9,1) after 40 ns, (7,1,4,0,3) after 50 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 addition is port ( sign, sign2: in std_logic; aligned_s1, aligned_s2: in digit_vector(0 downto -(p+3)); int_operation: inout std_logic; result, alt_result: out digit_vector(1 downto -(p+3)) ); end addition; architecture rtl of addition is signal long_s, long_s2: digit_vector(1 downto -(p+3)); signal inv_s, inv_s2: digit_vector(1 downto -(p+3)); signal carry1: mybit_vector(1 downto -(p+3)); signal carry2: mybit_vector(1 downto -(p+3)); begin int_operation <= sign xor sign2; long_s <= 0&aligned_s1; long_s2 <= 0&aligned_s2; inverters1: for i in -(p+3) to 1 generate inv_s2(i) <= B-1-long_s2(i) when int_operation = '1' else long_s2(i); end generate; inverters2: for i in -(p+3) to 1 generate inv_s(i) <= B-1-long_s(i); end generate; carry1(-(p+3)) <= int_operation; first_adder: for i in -(p+3) to 0 generate carry1(i+1) <= '1' when long_s(i) + inv_s2(i) + conv_integer(carry1(i)) > B-1 else '0'; result(i) <= (long_s(i) + inv_s2(i) + conv_integer(carry1(i))) mod B; end generate; result(1) <= (long_s(1) + inv_s2(1) + conv_integer(carry1(1))) mod B; carry2(-(p+3)) <= '1'; second_adder: for i in -(p+3) to 0 generate carry2(i+1) <= '1' when inv_s(i) + long_s2(i) + conv_integer(carry2(i)) > B-1 else '0'; alt_result(i) <= (inv_s(i) + long_s2(i) + conv_integer(carry2(i))) mod B; end generate; alt_result(1) <= (inv_s(1) + long_s2(1) + conv_integer(carry2(1))) mod B; end rtl; library ieee; use ieee.std_logic_1164.all; use work.mypackage.all; entity test_addition is end test_addition; architecture test of test_addition is component addition port ( sign, sign2: in std_logic; aligned_s1, aligned_s2: in digit_vector(0 downto -(p+3)); int_operation: inout std_logic; result, alt_result: out digit_vector(1 downto -(p+3)) ); end component; signal sign, sign2, int_operation: std_logic; signal aligned_s1, aligned_s2: digit_vector(0 downto -(p+3)); signal result, alt_result: digit_vector(1 downto -(p+3)); begin device_under_test: addition port map (sign, sign2, aligned_s1, aligned_s2, int_operation, result, alt_result); sign <= '0'; sign2 <= '0', '1' after 30 ns; aligned_s1 <= (3,4,3,7,5,0,0,0), (9,4,3,7,5,0,0,0) after 10 ns, (9,4,3,7,5,0,0,0) after 20 ns, (0,0,0,0,3,4,5,1) after 30 ns, (1,0,0,1,4,0,0,0) after 40 ns, (1,0,7,1,4,0,0,0) after 50 ns; aligned_s2 <= (0,0,0,0,2,5,4,1), (0,8,6,2,4,7,0,0) after 10 ns, (0,5,6,2,4,7,0,0) after 20 ns, (7,2,4,7,1,0,0,0) after 30 ns, (0,9,9,4,9,1,0,0) after 40 ns, (0,0,7,1,4,0,3,0) after 50 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 ( sign, operation: in std_logic; e, dif: in natural; result, alt_result: in digit_vector(1 downto -(p+3)); new_sign, zero_flag: out std_logic; new_s: out digit_vector(0 downto -(p+3)); new_e: out natural ); end normalization; architecture behavior of normalization is signal result_div_B, s1, s, s2: digit_vector(0 downto -(p+3)); signal exp1, k, exp2: natural; signal sign1, sign2: std_logic; begin divide_by_B: for i in -(p+3) to 0 generate result_div_B(i) <= result(i+1); end generate; s1 <= result(0 downto -(p+3)) when result(1) = 0 else result_div_B; exp1 <= e when result(1) = 0 else e+1; sign1 <= sign; s <= alt_result(0 downto -(p+3)) when (dif = 0) and (result(1) > 0) else result(0 downto -(p+3)); leading_zeroes: process(s) variable var_k: natural; begin var_k := 0; for i in 0 downto -(p+3) loop if s(i) > 0 then exit; end if; var_k := var_k+1; end loop; if var_k = p+4 then zero_flag <= '1'; else zero_flag <= '0'; end if; k <= var_k; end process leading_zeroes; shift_k: process (s, k) variable a: digit_vector(0 downto -(p+3)); begin a := s; if k > 0 then for i in 1 to k loop for i in 0 downto -(p+2) loop a(i) := a(i-1); end loop; a(-(p+3)) := 0; end loop; end if; s2 <= a; end process shift_k; exp2 <= e - k; sign2 <= not(sign) when (dif = 0) and (result(1) > 0) else sign; new_s <= s1 when operation = '0' else s2; new_e <= exp1 when operation = '0' else exp2; new_sign <= sign1 when operation = '0' else sign2; end behavior; library ieee; use ieee.std_logic_1164.all; use work.mypackage.all; entity test_normalization is end test_normalization; architecture test of test_normalization is component normalization port ( sign, operation: in std_logic; e, dif: in natural; result, alt_result: in digit_vector(1 downto -(p+3)); new_sign, zero_flag: out std_logic; new_s: out digit_vector(0 downto -(p+3)); new_e: out natural ); end component; signal sign, operation: std_logic; signal e, dif: natural; signal result, alt_result: digit_vector(1 downto -(p+3)); signal new_sign, zero_flag: std_logic; signal new_s: digit_vector(0 downto -(p+3)); signal new_e: natural; begin device_under_test: normalization port map (sign, operation, e, dif, result, alt_result, new_sign, zero_flag, new_s, new_e); sign <= '0', '1' after 30 ns, '0' after 40 ns; operation <= '0', '1' after 30 ns; result <= (0,3,4,3,7,7,5,4,1), (1,0,2,9,9,9,7,0,0) after 10 ns, (0,9,9,9,9,9,7,0,0) after 20 ns, (0,7,2,4,6,7,5,4,9) after 30 ns, (0,0,0,0,6,4,9,0,0) after 40 ns, (0,0,9,9,9,9,9,7,0) after 50 ns, (9,9,9,9,9,8,9,9,9) after 60 ns; alt_result <= (9,6,5,6,2,7,5,4,1), (9,1,4,2,4,9,7,0,0) after 10 ns, (9,1,1,2,4,9,7,0,0) after 20 ns, (9,2,7,5,3,2,4,5,1) after 30 ns, (9,9,9,9,3,5,1,0,0) after 40 ns, (9,9,0,0,0,0,0,3,0) after 50 ns, (0,0,0,0,0,0,9,9,9) after 60 ns; e <= 3, 4 after 50 ns; dif <= 4, 1 after 10 ns, 4 after 30 ns, 1 after 40 ns, 2 after 50 ns, 0 after 60 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 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+3)) > 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 work.mypackage.all; entity test_rounding is end test_rounding; architecture test of test_rounding is 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 s: digit_vector(0 downto -(p+3)); signal new_s: digit_vector(0 downto -p); signal e, new_e: natural; begin device_under_test: rounding port map (s, e, new_s, new_e); s <= (9,9,9,9,9,5,0,0), (9,9,9,9,8,5,0,0) after 10 ns, (7,6,5,8,7,4,9,9) after 20 ns, (9,9,9,9,9,4,9,9) after 30 ns, (5,6,7,3,7,5,0,0) after 40 ns, (4,6,7,5,4,5,0,0) after 50 ns; e <= 3; 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 adder_subtractor is port ( sign1, sign2, operation: in std_logic; e1, e2: in integer; s1, s2: in digit_vector(0 downto -p); sign, zero_flag: out std_logic; e: out natural; s: out digit_vector(0 downto -p) ); end adder_subtractor; architecture circuit of adder_subtractor is component alignment port ( sign1, sign2, operation: in std_logic; e1, e2: in integer; s1, s2: in digit_vector(0 downto -p); dif: inout natural; sign, new_sign2: out std_logic; e, new_e2: out natural; aligned_s1, aligned_s2: out digit_vector(0 downto -(p+3)) ); end component; component addition port ( sign, sign2: in std_logic; aligned_s1, aligned_s2: in digit_vector(0 downto -(p+3)); int_operation: inout std_logic; result, alt_result: out digit_vector(1 downto -(p+3)) ); end component; component normalization port ( sign, operation: in std_logic; e, dif: in natural; result, alt_result: in digit_vector(1 downto -(p+3)); new_sign, zero_flag: out std_logic; 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 sign_a, sign2_a, int_operation: std_logic; signal e_a, new_e2, dif, e_n: natural; signal aligned_s1, aligned_s2, s_n: digit_vector(0 downto -(p+3)); signal result, alt_result: digit_vector(1 downto -(p+3)); begin alignment_component: alignment port map (sign1, sign2, operation, e1, e2, s1, s2, dif, sign_a, sign2_a, e_a, new_e2, aligned_s1, aligned_s2); addition_component: addition port map (sign_a, sign2_a, aligned_s1, aligned_s2, int_operation, result, alt_result); normalization_component: normalization port map (sign_a, int_operation, e_a, dif, result, alt_result, sign, zero_flag, 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 work.mypackage.all; entity test_adder_subtractor is end test_adder_subtractor; architecture test of test_adder_subtractor is component adder_subtractor port ( sign1, sign2, operation: in std_logic; e1, e2: in integer; s1, s2: in digit_vector(0 downto -p); sign, zero_flag: out std_logic; e: out natural; s: out digit_vector(0 downto -p) ); end component; signal sign1, sign2, operation: std_logic; signal e1, e2: integer; signal s1, s2: digit_vector(0 downto -p); signal sign, zero_flag: std_logic; signal e: natural; signal s: digit_vector(0 downto -p); begin device_under_test: adder_subtractor port map (sign1, sign2, operation, e1, e2, s1, s2, sign, zero_flag, e, s); sign1 <= '0'; sign2 <= '0'; operation <= '0', '1' after 30 ns, '0' after 70 ns, '1' after 80 ns; e1 <= 3, 3 after 10 ns, 3 after 20 ns, -1 after 30 ns, 3 after 40 ns, 4 after 50 ns; e2 <= -1, 2 after 10 ns, 2 after 20 ns, 3 after 30 ns, 2 after 40 ns, 2 after 50 ns, -4 after 60 ns, 4 after 70 ns; s1 <= (3,4,3,7,5), (9,4,3,7,5) after 10 ns, (9,4,3,7,5) after 20 ns, (3,4,5,1,8) after 30 ns, (1,0,0,1,4) after 40 ns, (1,0,7,1,4) after 50 ns; s2 <= (2,5,4,9,1), (8,6,2,4,7) after 10 ns, (5,6,2,4,7) after 20 ns, (7,2,4,7,1) after 30 ns, (9,9,4,9,1) after 40 ns, (7,1,4,0,3) after 50 ns, (1,0,7,1,4) after 70 ns ; end test;