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

Subversion Repositories mlite

[/] [mlite/] [trunk/] [vhdl/] [mult.vhd] - Diff between revs 47 and 90

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

Rev 47 Rev 90
Line 6... Line 6...
-- PROJECT: Plasma CPU core
-- PROJECT: Plasma CPU core
-- COPYRIGHT: Software placed into the public domain by the author.
-- COPYRIGHT: Software placed into the public domain by the author.
--    Software 'as is' without warranty.  Author liable for nothing.
--    Software 'as is' without warranty.  Author liable for nothing.
-- DESCRIPTION:
-- DESCRIPTION:
--    Implements the multiplication and division unit.
--    Implements the multiplication and division unit.
--    Normally takes 32 clock cycles.
--    Division takes 32 clock cycles.
--    if b(31 downto 16) = ZERO(31 downto 16) then mult in 16 cycles. 
--    Multiplication normally takes 16 clock cycles.
--    if b(31 downto 8) = ZERO(31 downto 8) then mult in 8 cycles. 
--    if b <= 0xffff then mult in 8 cycles. 
 
--    if b <= 0xff then mult in 4 cycles. 
---------------------------------------------------------------------
---------------------------------------------------------------------
library ieee;
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_1164.all;
 
use ieee.std_logic_unsigned.all;
use work.mlite_pack.all;
use work.mlite_pack.all;
 
 
entity mult is
entity mult is
   generic(adder_type : string := "GENERIC");
   generic(adder_type : string := "GENERIC");
   port(clk       : in std_logic;
   port(clk       : in std_logic;
Line 33... Line 35...
   signal do_signed_reg : std_logic;
   signal do_signed_reg : std_logic;
   signal count_reg     : std_logic_vector(5 downto 0);
   signal count_reg     : std_logic_vector(5 downto 0);
   signal reg_a         : std_logic_vector(31 downto 0);
   signal reg_a         : std_logic_vector(31 downto 0);
   signal reg_b         : std_logic_vector(63 downto 0);
   signal reg_b         : std_logic_vector(63 downto 0);
   signal answer_reg    : std_logic_vector(31 downto 0);
   signal answer_reg    : std_logic_vector(31 downto 0);
   signal aa, bb        : std_logic_vector(32 downto 0);
   signal aa, bb        : std_logic_vector(33 downto 0);
   signal sum           : std_logic_vector(32 downto 0);
   signal sum           : std_logic_vector(33 downto 0);
 
   signal reg_a_times3  : std_logic_vector(33 downto 0);
begin
begin
 
 
--multiplication/division unit
--multiplication/division unit
mult_proc: process(clk, a, b, mult_func,
mult_proc: process(clk, a, b, mult_func,
                   do_mult_reg, do_signed_reg, count_reg,
                   do_mult_reg, do_signed_reg, count_reg,
                   reg_a, reg_b, answer_reg, sum)
                   reg_a, reg_b, answer_reg, sum, reg_a_times3)
   variable do_mult_temp   : std_logic;
   variable do_mult_temp   : std_logic;
   variable do_signed_temp : std_logic;
   variable do_signed_temp : std_logic;
   variable count_temp     : std_logic_vector(5 downto 0);
   variable count_temp     : std_logic_vector(5 downto 0);
   variable a_temp         : std_logic_vector(31 downto 0);
   variable a_temp         : std_logic_vector(31 downto 0);
   variable b_temp         : std_logic_vector(63 downto 0);
   variable b_temp         : std_logic_vector(63 downto 0);
Line 120... Line 123...
      else
      else
         b_temp(63 downto 32) := a;
         b_temp(63 downto 32) := a;
      end if;
      end if;
   end if;
   end if;
 
 
   if do_mult_reg = '0' then
   if do_mult_reg = '0' then  --division
      bb <= reg_b(32 downto 0);
      aa <= (reg_a(31) and sign_extend) & (reg_a(31) and sign_extend) & reg_a;
   else
      bb <= reg_b(33 downto 0);
      bb <= (reg_b(63) and sign_extend) & reg_b(63 downto 32);
   else                       --multiplication two-bits at a time
 
      case reg_b(1 downto 0) is
 
      when "00" =>
 
         aa <= "00" & ZERO;
 
      when "01" =>
 
         aa <= (reg_a(31) and sign_extend) & (reg_a(31) and sign_extend) & reg_a;
 
      when "10" =>
 
         aa <= (reg_a(31) and sign_extend) & reg_a & '0';
 
      when others =>
 
         aa <= reg_a_times3;
 
      end case;
 
      bb <= (reg_b(63) and sign_extend) & (reg_b(63) and sign_extend) & reg_b(63 downto 32);
   end if;
   end if;
   aa <= (reg_a(31) and sign_extend) & reg_a;
 
 
 
   -- Choose bv_adder or lpm_add_sub
 
--   sum <= bv_adder(aa, bb, do_mult_reg);
 
 
 
   if count_reg(5) = '0' and start = '0' then
   if count_reg(5) = '0' and start = '0' then
      count_temp := bv_inc6(count_reg);
      count_temp := bv_inc6(count_reg);
      if do_mult_reg = '0' then
      if do_mult_reg = '0' then          --division
         answer_temp(31 downto 1) := answer_reg(30 downto 0);
         answer_temp(31 downto 1) := answer_reg(30 downto 0);
         if reg_b(63 downto 32) = ZERO and sum(32) = '0' then
         if reg_b(63 downto 32) = ZERO and sum(32) = '0' then
            a_temp := sum(31 downto 0);  --aa=aa-bb;
            a_temp := sum(31 downto 0);  --aa=aa-bb;
            answer_temp(0) := '1';
            answer_temp(0) := '1';
         else
         else
            answer_temp(0) := '0';
            answer_temp(0) := '0';
         end if;
         end if;
         if count_reg /= "011111" then
         if count_reg /= "011111" then
            b_temp(62 downto 0) := reg_b(63 downto 1);
            b_temp(62 downto 0) := reg_b(63 downto 1);
         else
         else                            --done with divide
            b_temp(63 downto 32) := a_temp;
            b_temp(63 downto 32) := a_temp;
            if do_signed_reg = '0' then
            if do_signed_reg = '0' then
               b_temp(31 downto 0) := answer_temp;
               b_temp(31 downto 0) := answer_temp;
            else
            else
               b_temp(31 downto 0) := bv_negate(answer_temp);
               b_temp(31 downto 0) := bv_negate(answer_temp);
            end if;
            end if;
         end if;
         end if;
      else  -- mult_mode
      else  -- mult_mode
         if reg_b(0) = '1' then
         b_temp(63 downto 30) := sum;
            b_temp(63 downto 31) := sum;
         b_temp(29 downto 0) := reg_b(31 downto 2);
         else
         if count_reg = "001000" and sign_extend = '0' and   --early stop
            b_temp(63 downto 31) := sign_extend & reg_b(63 downto 32);
 
            if reg_b(63 downto 32) = ZERO then
 
               b_temp(63) := '0';
 
            end if;
 
         end if;
 
         b_temp(30 downto 0) := reg_b(31 downto 1);
 
         if count_reg = "010000" and sign_extend = '0' and   --early stop
 
               reg_b(15 downto 0) = ZERO(15 downto 0) then
               reg_b(15 downto 0) = ZERO(15 downto 0) then
            count_temp := "111111";
            count_temp := "111111";
            b_temp(31 downto 0) := reg_b(47 downto 16);
            b_temp(31 downto 0) := reg_b(47 downto 16);
         end if;
         end if;
         if count_reg = "001000" and sign_extend = '0' and   --early stop
         if count_reg = "000100" and sign_extend = '0' and   --early stop
               reg_b(23 downto 0) = ZERO(23 downto 0) then
               reg_b(23 downto 0) = ZERO(23 downto 0) then
            count_temp := "111111";
            count_temp := "111111";
            b_temp(31 downto 0) := reg_b(55 downto 24);
            b_temp(31 downto 0) := reg_b(55 downto 24);
         end if;
         end if;
 
         count_temp(5) := count_temp(4);
      end if;
      end if;
   end if;
   end if;
 
 
   if rising_edge(clk) then
   if rising_edge(clk) then
      do_mult_reg <= do_mult_temp;
      do_mult_reg <= do_mult_temp;
      do_signed_reg <= do_signed_temp;
      do_signed_reg <= do_signed_temp;
      count_reg <= count_temp;
      count_reg <= count_temp;
      reg_a <= a_temp;
      reg_a <= a_temp;
      reg_b <= b_temp;
      reg_b <= b_temp;
      answer_reg <= answer_temp;
      answer_reg <= answer_temp;
 
      if start = '1' then
 
         reg_a_times3 <= ((a(31) and do_signed_temp) & a & '0') +
 
            ((a(31) and do_signed_temp) & (a(31) and do_signed_temp) & a);
 
      end if;
   end if;
   end if;
 
 
   if count_reg(5) = '0' and mult_func/= mult_nothing and start = '0' then
   if count_reg(5) = '0' and mult_func/= mult_nothing and start = '0' then
      pause_out <= '1';
      pause_out <= '1';
   else
   else
Line 201... Line 209...
end process;
end process;
 
 
 
 
   generic_adder:
   generic_adder:
   if adder_type /= "ALTERA" generate
   if adder_type /= "ALTERA" generate
      sum <= bv_adder(aa, bb, do_mult_reg);
      sum <= (aa + bb) when do_mult_reg = '1' else
 
             (aa - bb);
   end generate; --generic_adder
   end generate; --generic_adder
 
 
   --For Altera
   --For Altera
   lpm_adder:
   lpm_adder:
   if adder_type = "ALTERA" generate
   if adder_type = "ALTERA" generate
      lpm_add_sub_component : lpm_add_sub
      lpm_add_sub_component : lpm_add_sub
      GENERIC MAP (
      GENERIC MAP (
         lpm_width => 33,
         lpm_width => 34,
         lpm_direction => "UNUSED",
         lpm_direction => "UNUSED",
         lpm_type => "LPM_ADD_SUB",
         lpm_type => "LPM_ADD_SUB",
         lpm_hint => "ONE_INPUT_IS_CONSTANT=NO"
         lpm_hint => "ONE_INPUT_IS_CONSTANT=NO"
      )
      )
      PORT MAP (
      PORT MAP (

powered by: WebSVN 2.1.0

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