Line 1... |
Line 1... |
-- #################################################################################################
|
-- #################################################################################################
|
-- # << NEORV32 - CPU Co-Processor: MULDIV unit (RISC-V "M" Extension)>> #
|
-- # << NEORV32 - CPU Co-Processor: Integer Multiplier/Divider Unit (RISC-V "M" Extension)>> #
|
-- # ********************************************************************************************* #
|
-- # ********************************************************************************************* #
|
-- # Multiplier and Divider unit. Implements the RISC-V RV32-M CPU extension. #
|
-- # Multiplier and Divider unit. Implements the RISC-V RV32-M CPU extension. #
|
-- # Multiplier core (signed/unsigned) uses serial algorithm. -> 32+4 cycles latency #
|
-- # Multiplier core (signed/unsigned) uses serial algorithm. -> 32+4 cycles latency #
|
-- # Divider core (unsigned) uses serial algorithm. -> 32+6 cycles latency #
|
-- # Divider core (unsigned) uses serial algorithm. -> 32+6 cycles latency #
|
-- # Multiplications can be mapped to DSP block when FAST_MUL_EN = true. #
|
-- # Multiplications can be mapped to DSP block when FAST_MUL_EN = true. #
|
Line 84... |
Line 84... |
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 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 rs1, 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;
|
signal valid : std_ulogic;
|
Line 119... |
Line 119... |
begin
|
begin
|
if (rstn_i = '0') then
|
if (rstn_i = '0') then
|
state <= IDLE;
|
state <= IDLE;
|
opx <= (others => '0');
|
opx <= (others => '0');
|
opy <= (others => '0');
|
opy <= (others => '0');
|
|
rs1 <= (others => '0');
|
cnt <= (others => '0');
|
cnt <= (others => '0');
|
start <= '0';
|
start <= '0';
|
valid <= '0';
|
valid <= '0';
|
div_res_corr <= '0';
|
div_res_corr <= '0';
|
opy_is_zero <= '0';
|
opy_is_zero <= '0';
|
Line 134... |
Line 135... |
cp_op_ff <= cp_op;
|
cp_op_ff <= cp_op;
|
|
|
-- FSM --
|
-- FSM --
|
case state is
|
case state is
|
when IDLE =>
|
when IDLE =>
|
|
if (start_i = '1') then
|
opx <= rs1_i;
|
opx <= rs1_i;
|
|
rs1 <= rs1_i;
|
opy <= rs2_i;
|
opy <= rs2_i;
|
if (start_i = '1') then
|
|
state <= DECODE;
|
state <= DECODE;
|
end if;
|
end if;
|
|
|
when DECODE =>
|
when DECODE =>
|
--
|
--
|
Line 298... |
Line 300... |
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(valid, cp_op_ff, mul_product, div_res, quotient, opy_is_zero, rs1_i, remainder)
|
operation_result: process(valid, cp_op_ff, mul_product, div_res, quotient, opy_is_zero, rs1, remainder)
|
begin
|
begin
|
if (valid = '1') then
|
if (valid = '1') then
|
case cp_op_ff 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);
|
Line 314... |
Line 316... |
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 <= rs1_i;
|
res_o <= rs1;
|
end if;
|
end if;
|
when others => -- cp_op_remu_c
|
when others => -- cp_op_remu_c
|
res_o <= remainder;
|
res_o <= remainder;
|
end case;
|
end case;
|
else
|
else
|