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 :INTEGER := p+1; constant PDIGITS :INTEGER := p+3; 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; --------------------------------------------------------------- -- RESTORING base-B Divisor -- -- --------------------------------------------------------------- library IEEE; use IEEE.std_logic_1164.all; use work.mypackage.all; entity modif_div_rest_baseB is port ( A: in digit_vector(NDIGITS-1 downto 0); BB: in digit_vector(NDIGITS-1 downto 0); Q: out digit_vector(PDIGITS-1 downto 0); R: out digit_vector(NDIGITS-1 downto 0) ); end modif_div_rest_baseB; architecture div_arch of modif_div_rest_baseB is component rest_baseB_step is port ( a_by_B: in digit_vector(NDIGITS downto 0); BB: in digit_vector(NDIGITS-1 downto 0); q: out digit; r: out digit_vector(NDIGITS-1 downto 0) ); end component; type connections_in is array (0 to PDIGITS-1) of digit_vector(NDIGITS downto 0); type connections_out is array (0 to PDIGITS-1) of digit_vector(NDIGITS-1 downto 0); Signal wires_in: connections_in; Signal wires_out: connections_out; begin wires_in(0) <= 0&A; divisor: for i in 0 to PDIGITS-1 generate rest_step: rest_baseB_step port map (a_by_B => wires_in(i), BB => BB, q => Q(PDIGITS-i-1), r => wires_out(i)); end generate; wire_connections: for i in 1 to PDIGITS-1 generate wires_in(i) <= wires_out(i-1)&0; end generate; R <= wires_out(PDIGITS-1); end div_arch; --------------------------------------------------------------- -- RESTORING base-B Division step -- -- --------------------------------------------------------------- library IEEE; use work.mypackage.all; entity rest_baseB_step is port ( a_by_B: in digit_vector(NDIGITS downto 0); BB: in digit_vector(NDIGITS-1 downto 0); q: out digit; r: out digit_vector(NDIGITS-1 downto 0) ); end rest_baseB_step; architecture behavioural of rest_baseB_step is component look_up_table is port ( at: in digit_vector(2 downto 0); bt: in digit_vector(1 downto 0); qt: out digit; qt_1: out digit ); end component; component base_b_mult is port ( a: in digit; BB: in digit_vector(NDIGITS-1 downto 0); m: out digit_vector(NDIGITS downto 0) ); end component; component base_b_adder is port ( a: in digit_vector(NDIGITS-1 downto 0); BB: in digit_vector(NDIGITS-1 downto 0); s: out digit_vector(NDIGITS downto 0) ); end component; component base_b_subt is port ( a: in digit_vector(NDIGITS downto 0); BB: in digit_vector(NDIGITS downto 0); s: out digit_vector(NDIGITS downto 0); sign: out bit ); end component; signal at: digit_vector(2 downto 0); signal bt: digit_vector(1 downto 0); signal qt,qt_1: digit; signal q_x_b, a_x_BASE, remainder, rem_plus_b: digit_vector(NDIGITS downto 0); signal sign: bit; begin at <= a_by_B(NDIGITS downto NDIGITS-2); bt <= BB(NDIGITS-1 downto NDIGITS-2); a_x_BASE <= a_by_B; LookUpTable: look_up_table port map (at => at, bt => bt, qt => qt, qt_1 => qt_1); mult: base_b_mult port map (a => qt, BB => BB, m => q_x_b); subtrator: base_b_subt port map (a => a_x_BASE, BB => q_x_b, s => remainder, sign => sign); adder: base_b_adder port map (a => remainder(NDIGITS-1 downto 0), BB => BB, s => rem_plus_b); multiplexers: process (sign,qt_1, qt, rem_plus_b,remainder) begin if sign = '1' then q <= qt_1; r <= rem_plus_b(NDIGITS-1 downto 0); else q <= qt; r <= remainder(NDIGITS-1 downto 0); end if; end process; end behavioural; --------------------------------------------------------------- -- RESTORING base-B Division step: base B adder -- -- --------------------------------------------------------------- library IEEE; use work.mypackage.all; entity base_B_adder is port ( a: in digit_vector(NDIGITS-1 downto 0); BB: in digit_vector(NDIGITS-1 downto 0); s: out digit_vector(NDIGITS downto 0) ); end base_B_adder; architecture behavior of base_B_adder is begin process(BB,A) variable carry: digit_vector(NDIGITS downto 0); begin carry(0) := 0; for i in 0 to NDIGITS-1 loop s(i) <= (BB(i) + A(i) + carry(i)) mod B; carry(i+1) := (BB(i) + A(i) + carry(i)) / B; end loop; s(NDIGITS) <= carry(NDIGITS); end process; end behavior; --------------------------------------------------------------- -- RESTORING base-B Division step: base B multiplier -- -- --------------------------------------------------------------- library IEEE; use work.mypackage.all; entity base_B_mult is port ( a: in digit; BB: in digit_vector(NDIGITS-1 downto 0); m: out digit_vector(NDIGITS downto 0) ); end base_B_mult; architecture behavior of base_B_mult is begin process(BB,A) variable carry: digit_vector(NDIGITS downto 0); begin carry(0) := 0; for i in 0 to NDIGITS-1 loop m(i) <= (BB(i) * A + carry(i)) mod B; carry(i+1) := ( BB(i) * A + carry(i) ) / B; end loop; m(NDIGITS) <= carry(NDIGITS); end process; end behavior; --------------------------------------------------------------- -- RESTORING base-B Division step: base B subtractor -- -- --------------------------------------------------------------- library IEEE; use work.mypackage.all; entity base_B_subt is port ( a: in digit_vector(NDIGITS downto 0); BB: in digit_vector(NDIGITS downto 0); s: out digit_vector(NDIGITS downto 0); sign: out bit ); end base_B_subt; architecture behavior of base_B_subt is begin process(BB,a) variable borrow: digit_vector(NDIGITS+1 downto 0); begin borrow(0) := 0; for i in 0 to NDIGITS loop s(i) <= (A(i) - BB(i) - borrow(i)) mod B; --borrow(i+1) <= (A(i) - BB(i) - borrow(i)) / B; if (A(i) - BB(i) - borrow(i)) < 0 then borrow(i+1) := 1; else borrow(i+1) := 0; end if; end loop; if borrow(NDIGITS+1) = 0 then sign <= '0'; else sign <= '1'; end if; end process; end behavior; --------------------------------------------------------------- -- RESTORING base-B Division step: Look Up Table -- -- --------------------------------------------------------------- library IEEE; use work.mypackage.all; entity look_up_table is port ( at: in digit_vector(2 downto 0); bt: in digit_vector(1 downto 0); qt: out digit; qt_1: out digit ); end look_up_table; architecture behavior of look_up_table is begin process(at,bt) variable at_i,bt_i,qt_i: integer ; begin qt <= 0; qt_1 <= 0; at_i := at(2) *B*B + at(1)*B + at(0); bt_i := bt(1) *B + bt(0); if bt_i > 0 then qt_i := at_i / bt_i; if qt_i < B and qt_i > 0 then qt <= qt_i; qt_1 <= qt_i - 1; elsif qt_i = B then qt <= B - 1; qt_1 <= B - 1; end if; 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 division is port ( s1, s2: in digit_vector(0 downto -p); sign1, sign2: in std_logic; e1, e2: in integer; s: out digit_vector(0 downto -(p+3)); sign: out std_logic; e: out integer ); end division; architecture circuit of division is component modif_div_rest_baseB port ( A: in digit_vector(NDIGITS-1 downto 0); BB: in digit_vector(NDIGITS-1 downto 0); Q: out digit_vector(PDIGITS-1 downto 0); R: out digit_vector(NDIGITS-1 downto 0) ); end component; signal int_s1, int_s2, int_remainder: digit_vector(p downto 0); signal unaligned_quotient: digit_vector(p+2 downto 0); begin int_s1(0) <= s1(-p); int_s2(0) <= s2(-p); to_integers: for i in 1 to p generate int_s1(i) <= s1(i-p); int_s2(i) <= s2(i-p); end generate; --int_s1(p+1) <= 0; int_s2(p+1) <= s2(0); divider: modif_div_rest_baseB port map (int_s1, int_s2, unaligned_quotient, int_remainder); alignment: for i in 0 downto -(p+2) generate s(i) <= unaligned_quotient(i+p+2); end generate; process(int_remainder) variable acc_or: digit; begin acc_or := 0; for i in p downto 0 loop if (int_remainder(i) > 0) or (acc_or > 0) then acc_or := 1; end if; end loop; if acc_or > 0 then s(-(p+3)) <= 1; else s(-(p+3)) <= 0; end if; end process; 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 test_division is end test_division; architecture test of test_division is component division port ( s1, s2: in digit_vector(0 downto -p); sign1, sign2: in std_logic; e1, e2: in integer; s: out digit_vector(0 downto -(p+3)); 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 s: digit_vector(0 downto -(p+3)); begin device_under_test: division port map (s1, s2, sign1, sign2, e1, e2, s, sign, e); s1 <= (3, 4, 3, 7, 5), (2, 5, 4, 9, 1) after 10 ns, (1, 0, 0, 9, 9) after 20 ns; s2 <= (2, 5, 4, 9, 1), (3, 4, 3, 7, 5) after 10 ns, (1, 0, 0, 0, 0) after 40 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; s: in digit_vector(0 downto -(p+3)); new_s: out digit_vector(0 downto -(p+3)); new_e: out natural ); end normalization; architecture rtl of normalization is signal quotient_by_B: digit_vector(0 downto -(p+3)); begin multiply_by_B: for i in -(p+2) to 0 generate quotient_by_B(i) <= s(i-1); end generate; quotient_by_B(-(p+3)) <= 0; new_s <= quotient_by_B when s(0) = 0 else s; new_e <= e-1 when s(0) = 0 else e; 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; ------ new_s <= sum; new_e <= e; 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_divider 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_divider; architecture circuit of fp_divider is component division port ( s1, s2: in digit_vector(0 downto -p); sign1, sign2: in std_logic; e1, e2: in integer; s: out digit_vector(0 downto -(p+3)); sign: out std_logic; e: out integer ); end component; component normalization port ( e: in natural; s: in digit_vector(0 downto -(p+3)); 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_d, e_n: natural; signal s_d, s_n: digit_vector(0 downto -(p+3)); begin divider_component: division port map (s1, s2, sign1, sign2, e1, e2, s_d, sign, e_d); normalization_component: normalization port map (e_d, s_d, 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_divider is end test_fp_divider; architecture test of test_fp_divider is component fp_divider 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_divider port map (sign1, sign2, e1, e2, s1, s2, sign, e, s); s1 <= (3, 4, 3, 7, 5), (2, 5, 4, 9, 1) after 10 ns, (1, 0, 0, 9, 9) after 20 ns, (1, 0, 0, 0, 0) after 50 ns, (9, 9, 9, 9, 9) after 60 ns; s2 <= (2, 5, 4, 9, 1), (3, 4, 3, 7, 5) after 10 ns, (1, 0, 0, 0, 0) after 40 ns, (9, 9, 9, 9, 9) after 50 ns, (1, 0, 0, 0, 0) after 60 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;