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

Subversion Repositories neorv32

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

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

Rev 4 Rev 6
Line 1... Line 1...
-- #################################################################################################
-- #################################################################################################
-- # << NEORV32 - CPU Co-Processor: MULDIV unit >>                                                 #
-- # << NEORV32 - CPU Co-Processor: MULDIV unit >>                                                 #
-- # ********************************************************************************************* #
-- # ********************************************************************************************* #
-- # 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+8 cycles latency               #
-- # Multiplier core (signed/unsigned) uses serial algorithm. -> 32+4 cycles latency               #
-- # Divider core (unsigned) uses serial algorithm. -> 32+8 cycles latency                         #
-- # Divider core (unsigned) uses serial algorithm. -> 32+6 cycles latency                         #
-- # ********************************************************************************************* #
-- # ********************************************************************************************* #
-- # BSD 3-Clause License                                                                          #
-- # BSD 3-Clause License                                                                          #
-- #                                                                                               #
-- #                                                                                               #
-- # Copyright (c) 2020, Stephan Nolting. All rights reserved.                                     #
-- # Copyright (c) 2020, Stephan Nolting. All rights reserved.                                     #
-- #                                                                                               #
-- #                                                                                               #
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 --
 
  constant all_zero_c : std_ulogic_vector(data_width_c-1 downto 0) := (others => '0');
 
 
  -- 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);
  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 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 div_res_corr  : std_ulogic;
  signal div_res_corr  : 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);
Line 99... Line 103...
      opy          <= (others => '0');
      opy          <= (others => '0');
      cnt          <= (others => '0');
      cnt          <= (others => '0');
      start        <= '0';
      start        <= '0';
      valid_o      <= '0';
      valid_o      <= '0';
      div_res_corr <= '0';
      div_res_corr <= '0';
 
      opy_is_zero  <= '0';
    elsif rising_edge(clk_i) then
    elsif rising_edge(clk_i) then
      -- defaults --
      -- defaults --
      start   <= '0';
      start   <= '0';
      valid_o <= '0';
      valid_o <= '0';
 
 
Line 116... Line 121...
            state <= DECODE;
            state <= DECODE;
          end if;
          end if;
 
 
        when DECODE =>
        when DECODE =>
          cnt <= "11111";
          cnt <= "11111";
          if (cp_op = cp_op_div_c) or (cp_op = cp_op_rem_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?
 
            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?
 
            opy_is_zero <= '1';
 
          else
 
            opy_is_zero <= '0';
 
          end if;
          if (operation = '1') then -- division
          if (operation = '1') then -- division
            state <= INIT_OPX;
            state <= INIT_OPX;
          else -- multiplication
          else -- multiplication
            start <= '1';
            start <= '1';
            state <= PROCESSING;
            state <= PROCESSING;
Line 173... Line 186...
  -- -------------------------------------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  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 (start = '1') then -- start new multiplication
      if (start = '1') then -- start new multiplication
        mul_product(63 downto 32) <= (others => (opy(opy'left) and opy_is_signed)); -- sign extension
        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;
Line 187... Line 200...
  -- 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
    if (mul_product(0) = '1') then
      if (mul_sign_cycle = '1') then -- for signed operation only: take care of negative weighted MSB
      if (mul_sign_cycle = '1') then -- for signed operation only: take care of negative weighted MSB
        mul_do_add <= std_ulogic_vector(unsigned(mul_p_sext & mul_product(63 downto 32)) - unsigned((opx(opy'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
        mul_do_add <= std_ulogic_vector(unsigned(mul_p_sext & mul_product(63 downto 32)) + unsigned((opx(opy'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
      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;
Line 230... Line 243...
                      opy when (state = INIT_OPY) else
                      opy when (state = INIT_OPY) else
                      quotient when ((cp_op = cp_op_div_c) or (cp_op = cp_op_divu_c)) else remainder;
                      quotient when ((cp_op = cp_op_div_c) or (cp_op = cp_op_divu_c)) else remainder;
  div_sign_comp <= std_ulogic_vector(0 - unsigned(div_sign_comp_in));
  div_sign_comp <= std_ulogic_vector(0 - unsigned(div_sign_comp_in));
 
 
  -- result sign correction --
  -- result sign correction --
  div_res <= div_sign_comp when (div_res_corr = '1') 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(clk_i)
  begin
  begin
    if rising_edge(clk_i) then
    if rising_edge(clk_i) then
 
      res_o <= (others => '0'); -- default
      case cp_op is
      case cp_op 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 =>
          res_o <= div_res;
          res_o <= div_res;
        when cp_op_divu_c =>
        when cp_op_divu_c =>
          res_o <= quotient;
          res_o <= quotient;
        when cp_op_rem_c =>
        when cp_op_rem_c =>
 
          if (opy_is_zero = '0') then
          res_o <= div_res;
          res_o <= div_res;
 
          else
 
            res_o <= opx;
 
          end if;
        when cp_op_remu_c =>
        when cp_op_remu_c =>
          res_o <= remainder;
          res_o <= remainder;
        when others => -- undefined
        when others => -- undefined
          res_o <= (others => '0');
          res_o <= (others => '0');
      end case;
      end case;

powered by: WebSVN 2.1.0

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