OpenCores
URL https://opencores.org/ocsvn/neorv32/neorv32/trunk

Subversion Repositories neorv32

[/] [neorv32/] [trunk/] [rtl/] [core/] [neorv32_cpu_cp_muldiv.vhd] - Diff between revs 6 and 12

Go to most recent revision | Show entire file | Details | Blame | View Log

Rev 6 Rev 12
Line 58... Line 58...
  );
  );
end neorv32_cpu_cp_muldiv;
end neorv32_cpu_cp_muldiv;
 
 
architecture neorv32_cpu_cp_muldiv_rtl of neorv32_cpu_cp_muldiv is
architecture neorv32_cpu_cp_muldiv_rtl of neorv32_cpu_cp_muldiv is
 
 
  -- constants --
  -- configuration - still experimental --
  constant all_zero_c : std_ulogic_vector(data_width_c-1 downto 0) := (others => '0');
  constant FAST_MUL_EN : boolean := false; -- use DSPs for faster multiplication
 
 
  -- controller --
  -- controller --
  type state_t is (IDLE, DECODE, INIT_OPX, INIT_OPY, PROCESSING, FINALIZE, COMPLETED);
  type state_t is (IDLE, DECODE, INIT_OPX, INIT_OPY, PROCESSING, FINALIZE, COMPLETED);
  signal state         : state_t;
  signal state         : state_t;
  signal cnt           : std_ulogic_vector(4 downto 0);
  signal cnt           : std_ulogic_vector(4 downto 0);
Line 84... Line 84...
  signal div_sign_comp    : std_ulogic_vector(data_width_c-1 downto 0);
  signal div_sign_comp    : std_ulogic_vector(data_width_c-1 downto 0);
  signal div_res          : std_ulogic_vector(data_width_c-1 downto 0);
  signal div_res          : std_ulogic_vector(data_width_c-1 downto 0);
 
 
  -- multiplier core --
  -- multiplier core --
  signal mul_product    : std_ulogic_vector(63 downto 0);
  signal mul_product    : std_ulogic_vector(63 downto 0);
  signal mul_do_add     : std_ulogic_vector(32 downto 0);
  signal mul_do_add     : std_ulogic_vector(data_width_c downto 0);
  signal mul_sign_cycle : std_ulogic;
  signal mul_sign_cycle : std_ulogic;
  signal mul_p_sext     : std_ulogic;
  signal mul_p_sext     : std_ulogic;
 
  signal mul_op_x       : std_ulogic_vector(32 downto 0);
 
  signal mul_op_y       : std_ulogic_vector(32 downto 0);
 
  signal mul_buf_ff0    : std_ulogic_vector(65 downto 0);
 
  signal mul_buf_ff1    : std_ulogic_vector(65 downto 0);
 
 
begin
begin
 
 
  -- Co-Processor Controller ----------------------------------------------------------------
  -- Co-Processor Controller ----------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
Line 120... Line 124...
          if (ctrl_i(ctrl_cp_use_c) = '1') and (ctrl_i(ctrl_cp_id_msb_c downto ctrl_cp_id_lsb_c) = cp_sel_muldiv_c) then
          if (ctrl_i(ctrl_cp_use_c) = '1') and (ctrl_i(ctrl_cp_id_msb_c downto ctrl_cp_id_lsb_c) = cp_sel_muldiv_c) then
            state <= DECODE;
            state <= DECODE;
          end if;
          end if;
 
 
        when DECODE =>
        when DECODE =>
          cnt <= "11111";
          --
          if (cp_op = cp_op_div_c) then -- result sign compensation for div?
          if (cp_op = cp_op_div_c) then -- result sign compensation for div?
            div_res_corr <= opx(opx'left) xor opy(opy'left);
            div_res_corr <= opx(opx'left) xor opy(opy'left);
          elsif (cp_op = cp_op_rem_c) then -- result sign compensation for rem?
          elsif (cp_op = cp_op_rem_c) then -- result sign compensation for rem?
            div_res_corr <= opx(opx'left);
            div_res_corr <= opx(opx'left);
          else
          else
            div_res_corr <= '0';
            div_res_corr <= '0';
          end if;
          end if;
--        if (cp_op = cp_op_div_c) and (opy = all_zero_c) then -- *divide* by 0?
          --
          if (opy = all_zero_c) then -- *divide* by 0?
          if (or_all_f(opy) = '0') then -- *divide* by 0?
            opy_is_zero <= '1';
            opy_is_zero <= '1';
          else
          else
            opy_is_zero <= '0';
            opy_is_zero <= '0';
          end if;
          end if;
 
          --
          if (operation = '1') then -- division
          if (operation = '1') then -- division
 
            cnt   <= "11111";
            state <= INIT_OPX;
            state <= INIT_OPX;
          else -- multiplication
          else -- multiplication
 
            if (FAST_MUL_EN = false) then
 
              cnt <= "11111";
 
            else
 
              cnt <= "00101"; -- FIXME
 
            end if;
            start <= '1';
            start <= '1';
            state <= PROCESSING;
            state <= PROCESSING;
          end if;
          end if;
 
 
        when INIT_OPX =>
        when INIT_OPX =>
Line 180... Line 191...
 
 
  -- opy (rs2) signed? --
  -- opy (rs2) signed? --
  opy_is_signed <= '1' when (cp_op = cp_op_mulh_c) or (cp_op = cp_op_div_c) or (cp_op = cp_op_rem_c) else '0';
  opy_is_signed <= '1' when (cp_op = cp_op_mulh_c) or (cp_op = cp_op_div_c) or (cp_op = cp_op_rem_c) else '0';
 
 
 
 
  -- Multiplier Core ------------------------------------------------------------------------
  -- Multiplier Core (signed) ---------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  multiplier_core: process(clk_i)
  multiplier_core: process(clk_i)
  begin
  begin
    if rising_edge(clk_i) then
    if rising_edge(clk_i) then
 
      if (FAST_MUL_EN = false) then -- use small iterative computation
      if (start = '1') then -- start new multiplication
      if (start = '1') then -- start new multiplication
        mul_product(63 downto 32) <= (others => '0');
        mul_product(63 downto 32) <= (others => '0');
        mul_product(31 downto 00) <= opy;
        mul_product(31 downto 00) <= opy;
      elsif ((state = PROCESSING) or (state = FINALIZE)) and (operation = '0') then
      elsif ((state = PROCESSING) or (state = FINALIZE)) and (operation = '0') then
        mul_product(63 downto 31) <= mul_do_add(32 downto 0);
        mul_product(63 downto 31) <= mul_do_add(32 downto 0);
        mul_product(30 downto 00) <= mul_product(31 downto 1);
        mul_product(30 downto 00) <= mul_product(31 downto 1);
      end if;
      end if;
 
      else -- use direct approach using (several!) DSP blocks
 
        if (start = '1') then
 
          mul_op_x <= (opx(opx'left) and opx_is_signed) & opx;
 
          mul_op_y <= (opy(opy'left) and opy_is_signed) & opy;
 
        end if;
 
        mul_buf_ff0 <= std_ulogic_vector(signed(mul_op_x) * signed(mul_op_y));
 
        mul_buf_ff1 <= mul_buf_ff0;
 
        mul_product <= mul_buf_ff1(63 downto 0); -- let the register balancing do the magic here
 
      end if;
    end if;
    end if;
  end process multiplier_core;
  end process multiplier_core;
 
 
  -- MUL: do another addition --
  -- MUL: do another addition --
  mul_update: process(mul_product, mul_sign_cycle, mul_p_sext, opx_is_signed, opx)
  mul_update: process(mul_product, mul_sign_cycle, mul_p_sext, opx_is_signed, opx)
  begin
  begin
    if (mul_product(0) = '1') then
    -- current bit of opy to take care of --
      if (mul_sign_cycle = '1') then -- for signed operation only: take care of negative weighted MSB
    if (mul_product(0) = '1') then -- multiply with 1
 
      if (mul_sign_cycle = '1') then -- for signed operations only: take care of negative weighted MSB -> multiply with -1
        mul_do_add <= std_ulogic_vector(unsigned(mul_p_sext & mul_product(63 downto 32)) - unsigned((opx(opx'left) and opx_is_signed) & opx));
        mul_do_add <= std_ulogic_vector(unsigned(mul_p_sext & mul_product(63 downto 32)) - unsigned((opx(opx'left) and opx_is_signed) & opx));
      else
      else -- multiply with +1
        mul_do_add <= std_ulogic_vector(unsigned(mul_p_sext & mul_product(63 downto 32)) + unsigned((opx(opx'left) and opx_is_signed) & opx));
        mul_do_add <= std_ulogic_vector(unsigned(mul_p_sext & mul_product(63 downto 32)) + unsigned((opx(opx'left) and opx_is_signed) & opx));
      end if;
      end if;
    else
    else -- multiply with 0
      mul_do_add <= mul_p_sext & mul_product(63 downto 32);
      mul_do_add <= mul_p_sext & mul_product(63 downto 32);
    end if;
    end if;
  end process mul_update;
  end process mul_update;
 
 
  -- sign control --
  -- sign control --
  mul_sign_cycle <= opy_is_signed when (state = FINALIZE) else '0';
  mul_sign_cycle <= opy_is_signed when (state = FINALIZE) else '0';
  mul_p_sext     <= mul_product(mul_product'left) and opx_is_signed;
  mul_p_sext     <= mul_product(mul_product'left) and opx_is_signed;
 
 
 
 
  -- Divider Core ---------------------------------------------------------------------------
  -- Divider Core (unsigned) ----------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  divider_core: process(clk_i)
  divider_core: process(clk_i)
  begin
  begin
    if rising_edge(clk_i) then
    if rising_edge(clk_i) then
      if (start = '1') then -- start new division
      if (start = '1') then -- start new division

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.