-- MIPS I system -- Copyright 2011-2012 Stefan Schuermans -- Copyleft GNU public license V2 or later -- http://www.gnu.org/copyleft/gpl.html LIBRARY ieee; USE ieee.std_logic_1164.all; USE ieee.numeric_std.all; USE work.mips_types.all; ENTITY e_mips_mul IS PORT ( rst: IN std_logic; clk: IN std_logic; i_a: IN std_logic_vector(31 DOWNTO 0); i_b: IN std_logic_vector(31 DOWNTO 0); i_signed: IN std_logic; i_start: IN std_logic; o_busy: OUT std_logic; o_res: OUT std_logic_vector(63 DOWNTO 0) ); END ENTITY e_mips_mul; ARCHITECTURE a_mips_mul OF e_mips_mul IS TYPE t_state IS (idle, state_1, state_2, state_3, state_4, post); SIGNAL n_state: t_state; SIGNAL r_state: t_state := idle; SIGNAL n_a: unsigned(31 DOWNTO 0); SIGNAL n_b: unsigned(31 DOWNTO 0); SIGNAL n_neg: boolean; SIGNAL n_res: unsigned(63 DOWNTO 0); SIGNAL r_a: unsigned(31 DOWNTO 0) := (OTHERS => '0'); SIGNAL r_b: unsigned(31 DOWNTO 0) := (OTHERS => '0'); SIGNAL r_neg: boolean := false; SIGNAL r_res: unsigned(63 DOWNTO 0) := (OTHERS => '0'); BEGIN p_mul: PROCESS(r_state, r_a, r_b, r_neg, r_res, i_a, i_b, i_signed, i_start) VARIABLE v_a: unsigned(15 DOWNTO 0); VARIABLE v_b: unsigned(15 DOWNTO 0); VARIABLE v_res: unsigned(31 DOWNTO 0); VARIABLE v_add: unsigned(63 DOWNTO 0); VARIABLE v_sum: unsigned(63 DOWNTO 0); BEGIN o_busy <= '0'; n_state <= idle; n_a <= r_a; n_b <= r_b; n_neg <= r_neg; n_res <= r_res; v_a := (OTHERS => '0'); v_b := (OTHERS => '0'); v_add := (OTHERS => '0'); CASE r_state IS WHEN idle => IF i_start = '1' THEN o_busy <= '1'; n_state <= state_1; IF i_signed = '1' THEN IF i_a(31) = '1' THEN n_a <= unsigned(-signed(i_a)); ELSE n_a <= unsigned(i_a); END IF; IF i_b(31) = '1' THEN n_b <= unsigned(-signed(i_b)); ELSE n_b <= unsigned(i_b); END IF; n_neg <= i_a(31) = '1' XOR i_b(31) = '1'; ELSE n_a <= unsigned(i_a); n_b <= unsigned(i_b); n_neg <= false; END IF; END IF; WHEN state_1 => o_busy <= '1'; n_state <= state_2; v_a := r_a(15 DOWNTO 0); v_b := r_b(15 DOWNTO 0); WHEN state_2 => o_busy <= '1'; n_state <= state_3; v_a := r_a(31 DOWNTO 16); v_b := r_b(15 DOWNTO 0); WHEN state_3 => o_busy <= '1'; n_state <= state_4; v_a := r_a(15 DOWNTO 0); v_b := r_b(31 DOWNTO 16); WHEN state_4 => o_busy <= '1'; n_state <= post; v_a := r_a(31 DOWNTO 16); v_b := r_b(31 DOWNTO 16); WHEN OTHERS => NULL; END CASE; v_res := v_a * v_b; CASE r_state IS WHEN state_1 => v_add := X"00000000" & v_res; WHEN state_2 => v_add := X"0000" & v_res & X"0000"; WHEN state_3 => v_add := X"0000" & v_res & X"0000"; WHEN state_4 => v_add := v_res & X"00000000"; WHEN OTHERS => NULL; END CASE; v_sum := r_res + v_add; CASE r_state IS WHEN idle => n_res <= (OTHERS => '0'); WHEN state_1 | state_2 | state_3 | state_4 => n_res <= v_sum; WHEN post => IF r_neg THEN n_res <= unsigned(-signed(r_res)); ELSE n_res <= r_res; END IF; WHEN OTHERS => NULL; END CASE; END PROCESS p_mul; p_sync: PROCESS(rst, clk) BEGIN IF rst = '1' THEN r_state <= idle; r_a <= (OTHERS => '0'); r_b <= (OTHERS => '0'); r_neg <= false; r_res <= (OTHERS => '0'); ELSIF rising_edge(clk) THEN r_state <= n_state; r_a <= n_a; r_b <= n_b; r_neg <= n_neg; r_res <= n_res; END IF; END PROCESS p_sync; o_res <= std_logic_vector(n_res); END ARCHITECTURE a_mips_mul;