Line 71... |
Line 71... |
-- controller --
|
-- controller --
|
type state_t is (IDLE, DECODE, INIT_OPX, INIT_OPY, PROCESSING, FINALIZE, COMPLETED, FAST_MUL);
|
type state_t is (IDLE, DECODE, INIT_OPX, INIT_OPY, PROCESSING, FINALIZE, COMPLETED, FAST_MUL);
|
signal state : state_t;
|
signal state : state_t;
|
signal cnt : std_ulogic_vector(4 downto 0);
|
signal cnt : std_ulogic_vector(4 downto 0);
|
signal cp_op : std_ulogic_vector(2 downto 0); -- operation to execute
|
signal cp_op : std_ulogic_vector(2 downto 0); -- operation to execute
|
|
signal cp_op_ff : std_ulogic_vector(2 downto 0); -- operation that was executed
|
signal start : std_ulogic;
|
signal start : std_ulogic;
|
signal operation : std_ulogic;
|
signal operation : std_ulogic;
|
signal opx, opy : std_ulogic_vector(data_width_c-1 downto 0); -- input operands
|
signal opx, opy : std_ulogic_vector(data_width_c-1 downto 0); -- input operands
|
signal opx_is_signed : std_ulogic;
|
signal opx_is_signed : std_ulogic;
|
signal opy_is_signed : std_ulogic;
|
signal opy_is_signed : std_ulogic;
|
signal opy_is_zero : std_ulogic;
|
signal opy_is_zero : std_ulogic;
|
signal div_res_corr : std_ulogic;
|
signal div_res_corr : std_ulogic;
|
|
signal valid : std_ulogic;
|
|
|
-- divider core --
|
-- divider core --
|
signal remainder : std_ulogic_vector(data_width_c-1 downto 0);
|
signal remainder : std_ulogic_vector(data_width_c-1 downto 0);
|
signal quotient : std_ulogic_vector(data_width_c-1 downto 0);
|
signal quotient : std_ulogic_vector(data_width_c-1 downto 0);
|
signal div_sub : std_ulogic_vector(data_width_c downto 0);
|
signal div_sub : std_ulogic_vector(data_width_c downto 0);
|
Line 109... |
Line 111... |
state <= IDLE;
|
state <= IDLE;
|
opx <= (others => '0');
|
opx <= (others => '0');
|
opy <= (others => '0');
|
opy <= (others => '0');
|
cnt <= (others => '0');
|
cnt <= (others => '0');
|
start <= '0';
|
start <= '0';
|
valid_o <= '0';
|
valid <= '0';
|
div_res_corr <= '0';
|
div_res_corr <= '0';
|
opy_is_zero <= '0';
|
opy_is_zero <= '0';
|
|
cp_op_ff <= (others => '0');
|
elsif rising_edge(clk_i) then
|
elsif rising_edge(clk_i) then
|
-- defaults --
|
-- defaults --
|
start <= '0';
|
start <= '0';
|
valid_o <= '0';
|
valid <= '0';
|
|
cp_op_ff <= cp_op;
|
|
|
-- FSM --
|
-- FSM --
|
case state is
|
case state is
|
when IDLE =>
|
when IDLE =>
|
opx <= rs1_i;
|
opx <= rs1_i;
|
Line 180... |
Line 184... |
|
|
when FINALIZE =>
|
when FINALIZE =>
|
state <= COMPLETED;
|
state <= COMPLETED;
|
|
|
when COMPLETED =>
|
when COMPLETED =>
|
valid_o <= '1';
|
valid <= '1';
|
state <= IDLE;
|
state <= IDLE;
|
end case;
|
end case;
|
end if;
|
end if;
|
end process coprocessor_ctrl;
|
end process coprocessor_ctrl;
|
|
|
Line 284... |
Line 288... |
div_res <= div_sign_comp when (div_res_corr = '1') and (opy_is_zero = '0') else div_sign_comp_in;
|
div_res <= div_sign_comp when (div_res_corr = '1') and (opy_is_zero = '0') else div_sign_comp_in;
|
|
|
|
|
-- Data Output ----------------------------------------------------------------------------
|
-- Data Output ----------------------------------------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
operation_result: process(clk_i)
|
operation_result: process(valid, cp_op_ff, mul_product, div_res, quotient, opy_is_zero, rs1_i, remainder)
|
begin
|
begin
|
if rising_edge(clk_i) then
|
if (valid = '1') then
|
res_o <= (others => '0'); -- default
|
valid_o <= '1';
|
case cp_op is
|
case cp_op_ff is
|
when cp_op_mul_c =>
|
when cp_op_mul_c =>
|
res_o <= mul_product(31 downto 00);
|
res_o <= mul_product(31 downto 00);
|
when cp_op_mulh_c | cp_op_mulhsu_c | cp_op_mulhu_c =>
|
when cp_op_mulh_c | cp_op_mulhsu_c | cp_op_mulhu_c =>
|
res_o <= mul_product(63 downto 32);
|
res_o <= mul_product(63 downto 32);
|
when cp_op_div_c =>
|
when cp_op_div_c =>
|
Line 301... |
Line 305... |
res_o <= quotient;
|
res_o <= quotient;
|
when cp_op_rem_c =>
|
when cp_op_rem_c =>
|
if (opy_is_zero = '0') then
|
if (opy_is_zero = '0') then
|
res_o <= div_res;
|
res_o <= div_res;
|
else
|
else
|
res_o <= opx;
|
res_o <= rs1_i;
|
end if;
|
end if;
|
when cp_op_remu_c =>
|
when others => -- cp_op_remu_c
|
res_o <= remainder;
|
res_o <= remainder;
|
when others => -- undefined
|
|
res_o <= (others => '0');
|
|
end case;
|
end case;
|
|
else
|
|
valid_o <= '0';
|
|
res_o <= (others => '0');
|
end if;
|
end if;
|
end process operation_result;
|
end process operation_result;
|
|
|
|
|
end neorv32_cpu_cp_muldiv_rtl;
|
end neorv32_cpu_cp_muldiv_rtl;
|