Line 42... |
Line 42... |
|
|
entity mult is
|
entity mult is
|
generic(adder_type : string := "GENERIC";
|
generic(adder_type : string := "GENERIC";
|
mult_type : string := "GENERIC");
|
mult_type : string := "GENERIC");
|
port(clk : in std_logic;
|
port(clk : in std_logic;
|
|
reset_in : in std_logic;
|
a, b : in std_logic_vector(31 downto 0);
|
a, b : in std_logic_vector(31 downto 0);
|
mult_func : in mult_function_type;
|
mult_func : in mult_function_type;
|
c_mult : out std_logic_vector(31 downto 0);
|
c_mult : out std_logic_vector(31 downto 0);
|
pause_out : out std_logic);
|
pause_out : out std_logic);
|
end; --entity mult
|
end; --entity mult
|
|
|
architecture logic of mult is
|
architecture logic of mult is
|
|
|
-- type mult_function_type is (
|
|
-- mult_nothing, mult_read_lo, mult_read_hi, mult_write_lo,
|
|
-- mult_write_hi, mult_mult, mult_divide, mult_signed_divide);
|
|
signal do_mult_reg : std_logic;
|
signal do_mult_reg : std_logic;
|
signal do_signed_reg : std_logic;
|
signal do_signed_reg : std_logic;
|
signal count_reg : std_logic_vector(5 downto 0);
|
signal count_reg : std_logic_vector(5 downto 0);
|
signal reg_a : std_logic_vector(31 downto 0);
|
signal reg_a : std_logic_vector(31 downto 0);
|
signal reg_b : std_logic_vector(63 downto 0);
|
signal reg_b : std_logic_vector(63 downto 0);
|
signal answer_reg : std_logic_vector(31 downto 0);
|
signal answer_reg : std_logic_vector(31 downto 0);
|
signal aa, bb : std_logic_vector(33 downto 0);
|
signal aa, bb : std_logic_vector(33 downto 0);
|
signal sum : std_logic_vector(33 downto 0);
|
signal sum : std_logic_vector(33 downto 0);
|
signal sum2 : std_logic_vector(67 downto 0);
|
|
signal reg_a_times3 : std_logic_vector(33 downto 0);
|
signal reg_a_times3 : std_logic_vector(33 downto 0);
|
signal sign_extend_sig : std_logic;
|
signal sign_extend_sig : std_logic;
|
|
signal a_neg_sig : std_logic_vector(31 downto 0);
|
|
signal b_neg_sig : std_logic_vector(31 downto 0);
|
|
|
--Used in Xilinx tri-state area optimizated version
|
--Used in Xilinx tri-state area optimizated version
|
signal SUB_Y, A_PROCESSED, B_PROCESSED, A_REG, B_REG : std_logic_vector(31 downto 0);
|
signal a_temp_sig : std_logic_vector(31 downto 0);
|
signal DIV_Y, DIV_Y_IN, DIV_Y_IN_CALC, DIV_Y_IN_INIT, Y_IN, Y_IN2, MULT_Y, Y : std_logic_vector(63 downto 0) := (others => '0');
|
|
signal SAVE_Y, SAVE_DIV_Y, MULT_ND, MULT_RDY, DO_SIGNED, DIV_ND : std_logic;
|
|
signal DIV_COUNT, INVERT_A, INVERT_B, INVERT_Y, DIV_RDY : std_logic;
|
|
signal DIV_COUNTER : std_logic_vector(4 downto 0);
|
|
signal PAUSE_IN, SAVE_PAUSE, PAUSE : std_logic := '0';
|
|
signal MULT_RFD : std_logic;
|
|
signal a_temp_sig, a_neg_sig, b_neg_sig : std_logic_vector(31 downto 0);
|
|
signal b_temp_sig : std_logic_vector(63 downto 0);
|
signal b_temp_sig : std_logic_vector(63 downto 0);
|
signal a_msb, b_msb : std_logic;
|
signal a_msb, b_msb : std_logic;
|
signal answer_temp_sig : std_logic_vector(31 downto 0);
|
signal answer_temp_sig : std_logic_vector(31 downto 0);
|
signal aa_select : std_logic_vector(3 downto 0);
|
signal aa_select : std_logic_vector(3 downto 0);
|
signal bb_select : std_logic_vector(1 downto 0);
|
signal bb_select : std_logic_vector(1 downto 0);
|
Line 114... |
Line 106... |
a_neg_sig <= bv_negate(a);
|
a_neg_sig <= bv_negate(a);
|
b_neg_sig <= bv_negate(b);
|
b_neg_sig <= bv_negate(b);
|
sign_extend_sig <= do_signed_reg and do_mult_reg;
|
sign_extend_sig <= do_signed_reg and do_mult_reg;
|
|
|
-- Result
|
-- Result
|
c_mult <= reg_b(31 downto 0) when mult_func=mult_read_lo else
|
c_mult <= reg_b(31 downto 0) when mult_func = MULT_READ_LO else
|
reg_b(63 downto 32) when mult_func=mult_read_hi else
|
reg_b(63 downto 32) when mult_func = MULT_READ_HI else
|
ZERO;
|
ZERO;
|
|
|
|
|
GENERIC_MULT: if MULT_TYPE="GENERIC" generate
|
GENERIC_MULT: if MULT_TYPE="GENERIC" generate
|
|
|
--multiplication/division unit
|
--multiplication/division unit
|
mult_proc: process(clk, a, b, mult_func,
|
mult_proc: process(clk, reset_in, a, b, mult_func,
|
do_mult_reg, do_signed_reg, count_reg,
|
do_mult_reg, do_signed_reg, count_reg,
|
reg_a, reg_b, answer_reg, sum, reg_a_times3)
|
reg_a, reg_b, answer_reg, sum, reg_a_times3)
|
variable do_mult_temp : std_logic;
|
variable do_mult_temp : std_logic;
|
variable do_signed_temp : std_logic;
|
variable do_signed_temp : std_logic;
|
variable count_temp : std_logic_vector(5 downto 0);
|
variable count_temp : std_logic_vector(5 downto 0);
|
Line 149... |
Line 141... |
start := '0';
|
start := '0';
|
do_write := '0';
|
do_write := '0';
|
do_hi := '0';
|
do_hi := '0';
|
|
|
case mult_func is
|
case mult_func is
|
when mult_read_lo =>
|
when MULT_READ_LO =>
|
when mult_read_hi =>
|
when MULT_READ_HI =>
|
do_hi := '1';
|
do_hi := '1';
|
when mult_write_lo =>
|
when MULT_WRITE_LO =>
|
do_write := '1';
|
do_write := '1';
|
when mult_write_hi =>
|
when MULT_WRITE_HI =>
|
do_write := '1';
|
do_write := '1';
|
do_hi := '1';
|
do_hi := '1';
|
when mult_mult =>
|
when MULT_MULT =>
|
start := '1';
|
start := '1';
|
do_mult_temp := '1';
|
do_mult_temp := '1';
|
do_signed_temp := '0';
|
do_signed_temp := '0';
|
when mult_signed_mult =>
|
when MULT_SIGNED_MULT =>
|
start := '1';
|
start := '1';
|
do_mult_temp := '1';
|
do_mult_temp := '1';
|
do_signed_temp := '1';
|
do_signed_temp := '1';
|
when mult_divide =>
|
when MULT_DIVIDE =>
|
start := '1';
|
start := '1';
|
do_mult_temp := '0';
|
do_mult_temp := '0';
|
do_signed_temp := '0';
|
do_signed_temp := '0';
|
when mult_signed_divide =>
|
when MULT_SIGNED_DIVIDE =>
|
start := '1';
|
start := '1';
|
do_mult_temp := '0';
|
do_mult_temp := '0';
|
do_signed_temp := a(31) xor b(31);
|
do_signed_temp := a(31) xor b(31);
|
when others =>
|
when others =>
|
end case;
|
end case;
|
Line 181... |
Line 173... |
if start = '1' then
|
if start = '1' then
|
count_temp := "000000";
|
count_temp := "000000";
|
answer_temp := ZERO;
|
answer_temp := ZERO;
|
if do_mult_temp = '0' then
|
if do_mult_temp = '0' then
|
b_temp(63) := '0';
|
b_temp(63) := '0';
|
if mult_func /= mult_signed_divide or a(31) = '0' then
|
if mult_func /= MULT_SIGNED_DIVIDE or a(31) = '0' then
|
a_temp := a;
|
a_temp := a;
|
else
|
else
|
a_temp := a_neg_sig;
|
a_temp := a_neg_sig;
|
end if;
|
end if;
|
if mult_func /= mult_signed_divide or b(31) = '0' then
|
if mult_func /= MULT_SIGNED_DIVIDE or b(31) = '0' then
|
b_temp(62 downto 31) := b;
|
b_temp(62 downto 31) := b;
|
else
|
else
|
b_temp(62 downto 31) := b_neg_sig;
|
b_temp(62 downto 31) := b_neg_sig;
|
end if;
|
end if;
|
b_temp(30 downto 0) := ZERO(30 downto 0);
|
b_temp(30 downto 0) := ZERO(30 downto 0);
|
Line 264... |
Line 256... |
end if;
|
end if;
|
count_temp(5) := count_temp(4);
|
count_temp(5) := count_temp(4);
|
end if;
|
end if;
|
end if;
|
end if;
|
|
|
if rising_edge(clk) then
|
if reset_in = '1' then
|
|
do_mult_reg <= '0';
|
|
do_signed_reg <= '0';
|
|
count_reg <= "000000";
|
|
reg_a <= ZERO;
|
|
reg_b <= ZERO & ZERO;
|
|
answer_reg <= ZERO;
|
|
reg_a_times3 <= "00" & ZERO;
|
|
elsif rising_edge(clk) then
|
do_mult_reg <= do_mult_temp;
|
do_mult_reg <= do_mult_temp;
|
do_signed_reg <= do_signed_temp;
|
do_signed_reg <= do_signed_temp;
|
count_reg <= count_temp;
|
count_reg <= count_temp;
|
reg_a <= a_temp;
|
reg_a <= a_temp;
|
reg_b <= b_temp;
|
reg_b <= b_temp;
|
Line 285... |
Line 285... |
pause_out <= '0';
|
pause_out <= '0';
|
end if;
|
end if;
|
|
|
end process;
|
end process;
|
|
|
|
--Only used in Xilinx tri-state area optimizated version
|
|
a_temp_sig <= ZERO;
|
|
b_temp_sig <= ZERO & ZERO;
|
|
a_msb <= '0';
|
|
b_msb <= '0';
|
|
answer_temp_sig <= ZERO;
|
|
aa_select <= "0000";
|
|
bb_select <= "00";
|
|
a_select <= "00000";
|
|
b_select <= ZERO(11 downto 0);
|
|
answer_select <= "000";
|
|
|
end generate;
|
end generate;
|
|
|
|
|
AREA_OPTIMIZED_MULT: if MULT_TYPE="AREA_OPTIMIZED" generate
|
AREA_OPTIMIZED_MULT: if MULT_TYPE="AREA_OPTIMIZED" generate
|
--Xilinx Tristate size optimization by Matthias Gruenewald
|
--Xilinx Tristate size optimization by Matthias Gruenewald
|
Line 317... |
Line 329... |
aa_select <= (others => '0');
|
aa_select <= (others => '0');
|
bb_select <= (others => '0');
|
bb_select <= (others => '0');
|
answer_select <= (others => '0');
|
answer_select <= (others => '0');
|
|
|
case mult_func is
|
case mult_func is
|
when mult_read_lo =>
|
when MULT_READ_LO =>
|
when mult_read_hi =>
|
when MULT_READ_HI =>
|
do_hi := '1';
|
do_hi := '1';
|
when mult_write_lo =>
|
when MULT_WRITE_LO =>
|
do_write := '1';
|
do_write := '1';
|
when mult_write_hi =>
|
when MULT_WRITE_HI =>
|
do_write := '1';
|
do_write := '1';
|
do_hi := '1';
|
do_hi := '1';
|
when mult_mult =>
|
when MULT_MULT =>
|
start := '1';
|
start := '1';
|
do_mult_temp := '1';
|
do_mult_temp := '1';
|
do_signed_temp := '0';
|
do_signed_temp := '0';
|
when mult_signed_mult =>
|
when MULT_SIGNED_MULT =>
|
start := '1';
|
start := '1';
|
do_mult_temp := '1';
|
do_mult_temp := '1';
|
do_signed_temp := '1';
|
do_signed_temp := '1';
|
when mult_divide =>
|
when MULT_DIVIDE =>
|
start := '1';
|
start := '1';
|
do_mult_temp := '0';
|
do_mult_temp := '0';
|
do_signed_temp := '0';
|
do_signed_temp := '0';
|
when mult_signed_divide =>
|
when MULT_SIGNED_DIVIDE =>
|
start := '1';
|
start := '1';
|
do_mult_temp := '0';
|
do_mult_temp := '0';
|
do_signed_temp := a(31) xor b(31);
|
do_signed_temp := a(31) xor b(31);
|
when others =>
|
when others =>
|
end case;
|
end case;
|
Line 350... |
Line 362... |
count_temp := "000000";
|
count_temp := "000000";
|
answer_select(0)<='1';
|
answer_select(0)<='1';
|
--answer_temp := ZERO;
|
--answer_temp := ZERO;
|
if do_mult_temp = '0' then
|
if do_mult_temp = '0' then
|
--b_temp(63) := '0';
|
--b_temp(63) := '0';
|
if mult_func /= mult_signed_divide or a(31) = '0' then
|
if mult_func /= MULT_SIGNED_DIVIDE or a(31) = '0' then
|
a_select(0) <= '1';
|
a_select(0) <= '1';
|
--a_temp := a;
|
--a_temp := a;
|
else
|
else
|
a_select(1) <= '1';
|
a_select(1) <= '1';
|
--a_temp := a_neg;
|
--a_temp := a_neg;
|
end if;
|
end if;
|
if mult_func /= mult_signed_divide or b(31) = '0' then
|
if mult_func /= MULT_SIGNED_DIVIDE or b(31) = '0' then
|
b_select(0) <= '1';
|
b_select(0) <= '1';
|
--b_temp(62 downto 31) := b;
|
--b_temp(62 downto 31) := b;
|
else
|
else
|
b_select(1) <= '1';
|
b_select(1) <= '1';
|
--b_temp(62 downto 31) := b_neg;
|
--b_temp(62 downto 31) := b_neg;
|
Line 459... |
Line 471... |
end if;
|
end if;
|
count_temp(5) := count_temp(4);
|
count_temp(5) := count_temp(4);
|
end if;
|
end if;
|
end if;
|
end if;
|
|
|
if rising_edge(clk) then
|
if reset_in = '1' then
|
|
do_mult_reg <= '0';
|
|
do_signed_reg <= '0';
|
|
count_reg <= "000000";
|
|
reg_a <= ZERO;
|
|
reg_b <= ZERO & ZERO;
|
|
answer_reg <= ZERO;
|
|
reg_a_times3 <= "00" & ZERO;
|
|
elsif rising_edge(clk) then
|
do_mult_reg <= do_mult_temp;
|
do_mult_reg <= do_mult_temp;
|
do_signed_reg <= do_signed_temp;
|
do_signed_reg <= do_signed_temp;
|
count_reg <= count_temp;
|
count_reg <= count_temp;
|
reg_a <= a_temp_sig;
|
reg_a <= a_temp_sig;
|
reg_b <= b_temp_sig;
|
reg_b <= b_temp_sig;
|