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

Subversion Repositories openfpu64

[/] [openfpu64/] [trunk/] [fpu_mul_single.vhd] - Rev 6

Go to most recent revision | Compare with Previous | Blame | View Log

-------------------------------------------------------------------------------
-- Project    : openFPU64 Multiplier Component
-------------------------------------------------------------------------------
-- File       : fpu_mul.vhd
-- Author     : Peter Huewe  <peterhuewe@gmx.de>
-- Created    : 2010-04-19
-- Last update: 2010-04-19
-- Standard   : VHDL'87
-- Status     : ALPHA! - Bugs exists!
-------------------------------------------------------------------------------
-- Description: double precision floating point multiplier component
--                     for openFPU64, includes rounding and normalization
--              Uses only one embedded 18x18 multiplier
-- Note       : Last few bits are wrong, perhaps related to stickybit /rounding
--                      issues
-------------------------------------------------------------------------------
-- Copyright (c) 2010 
-------------------------------------------------------------------------------
-- License: gplv3, see licence.txt
-------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.helpers.all;
use work.fpu_package.all;
-------------------------------------------------------------------------------
 
entity fpu_mul is
  port (
    clk, reset_n           : in  std_logic;  -- reset = standard active low
    cs                     : in  std_logic;  --  mode: 0 = add , 1= sub
    sign_a, sign_b         : in  std_logic;  -- sign bits
    exponent_a, exponent_b : in  std_logic_vector (11 downto 0);  -- exponents of the operands
    mantissa_a, mantissa_b : in  std_logic_vector (57 downto 0);  -- mantissa of operands
    --enable       : in  std_logic;       -- enable this submodule
    sign_res               : out std_logic;
    exponent_res           : out std_logic_vector(11 downto 0);
    mantissa_res           : out std_logic_vector (57 downto 0);
    rounding_needed        : out std_logic;
    -- result                 : out std_logic_vector (63 downto 0);
    -- ready        : out std_logic;       -- entspricht waitrequest_n
    valid                  : out std_logic
    );
 
end fpu_mul;
 
-------------------------------------------------------------------------------
 
architecture rtl of fpu_mul is
 
  -----------------------------------------------------------------------------
  -- Internal signal declarations
  -----------------------------------------------------------------------------
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
  --signal mul_a, mul_b         : std_logic_vector(53 downto 0);  -- inputs for multiplier
--signal mul_result: std_logic_vector(57 downto 0);  -- result of multiplier
  signal add_result, add_op_a : unsigned (39 downto 0);
  signal add_op_b             : unsigned (35 downto 0);
  signal mul_result           : unsigned(35 downto 0);
  signal mul_op_a, mul_op_b   : unsigned(17 downto 0);
  type t_state is (s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s12a, s12b,s12c,s12d);  -- possible states
  signal state                : t_state;  -- current state
 
  signal exponent_out : std_logic_vector(11 downto 0);
  signal tmp_result   : std_logic_vector (57 downto 0);
 
 
  alias a : std_logic_vector(17 downto 0) is mantissa_a(56 downto 39);
  alias b : std_logic_vector(17 downto 0) is mantissa_a(38 downto 21);
  alias c : std_logic_vector(17 downto 0) is mantissa_a(20 downto 3);
  alias d : std_logic_vector(17 downto 0) is mantissa_b(56 downto 39);
  alias e : std_logic_vector(17 downto 0) is mantissa_b(38 downto 21);
  alias f : std_logic_vector(17 downto 0) is mantissa_b(20 downto 3);
 
 
  signal a_is_normal, b_is_normal : std_logic;
  signal sticky_bit               : std_logic;
  signal sticky_bit_enabled       : std_logic;
-----------------------------------------------------------------------------
-- Component declarations
-----------------------------------------------------------------------------
begin
----------------------------------------------------------------
  -- Component instantiations
  -----------------------------------------------------------------------------
 
  -- purpose: calculates the result of a multiplication
  -- type   : combinational
  -- inputs : sign_a, sign_b, exponent_a, exponent_b, mantissa_a, mantissa_b
  -- outputs: result
 
  add_result  <= add_op_a + add_op_b;
  mul_result  <= unsigned(mul_op_a) * unsigned(mul_op_b);
  a_is_normal <= '0'                when unsigned(exponent_a(10 downto 0)) = ALL_ZEROS else '1';
  b_is_normal <= '0'                when unsigned(exponent_b(10 downto 0)) = ALL_ZEROS else '1';
  sticky_bit  <= sticky_bit_enabled when add_result(18 downto 0) /= ZEROS(18 downto 0) else '0';
 
  state_trans : process (clk, reset_n, cs)
    variable tmp : unsigned(57 downto 0);
  begin  -- process state_trans
    rounding_needed <= '1';
    if reset_n = '0' or cs = '0' then
      state              <= s1;
      sign_res           <= '0';
      valid              <= '0';
      sticky_bit_enabled <= '0';
      --     result       <= (others => '0');
      exponent_res       <= (others => '0');
      mantissa_res       <= (others => '0');
      -- tmp          := (others => '0');
      tmp_result         <= (others => '0');
    elsif rising_edge(clk) then
      sign_res           <= sign_a xor sign_b;
      valid              <= '0';
      --    result       <= (others => '0');
      exponent_res       <= exponent_out;
      mantissa_res       <= (others => '0');
      mantissa_res       <= tmp_result;
      tmp_result         <= tmp_result;
      add_op_a           <= (others => '0');
      add_op_b           <= (others => '0');
      mul_op_a           <= (others => '0');
      mul_op_b           <= (others => '0');
      sticky_bit_enabled <= sticky_bit_enabled;
 
      case state is
        when s1 =>
          add_op_a              <= (others => '0');
          add_op_b              <= (others => '0');
          add_op_a(10 downto 0) <= unsigned(exponent_a(10 downto 0));
          add_op_b(10 downto 0) <= unsigned(exponent_b(10 downto 0));
 
          mul_op_a <= unsigned(c);
          mul_op_b <= unsigned(f);
          state    <= s2;
        when s2 =>
          --assert false report "Test" & to_string(std_logic_vector(add_result(13 downto 0))) severity warning;
          add_op_a (11 downto 0)  <= add_result(11 downto 0);
          add_op_b (11 downto 0)  <= DOUBLE_BIAS_2COMPLEMENT(11 downto 0);
          tmp_result(35 downto 0) <= std_logic_vector(mul_result);
 
          mul_op_a <= unsigned(b);
          mul_op_b <= unsigned(f);
 
 
          state <= s3;
        when s3 =>
          --  assert false report "Test" & to_string(std_logic_vector(add_result(13 downto 0))) severity warning;
          --  assert false report "ea" & to_string(exponent_a) & "eb" & to_string(exponent_b) &"xx"& to_string(std_logic_vector(DOUBLE_BIAS_2COMPLEMENT)) severity warning;
          -- if either the result is a subnormal/zero or both operands are zero
          -- set exponent to zero
          if (add_result(12) = '1' and (a_is_normal = '0' or b_is_normal = '0'))
            or (a_is_normal = '0' and b_is_normal = '0')
          then
            exponent_out <= (others => '0');
          else
            exponent_out <= std_logic_vector(add_result(11 downto 0));
          end if;
          sticky_bit_enabled <= '1';    -- since we start adding up values,
                                        -- sticky bit has to be calculated
          assert sticky_bit = '0' report "sticky3"&to_string(std_logic_vector(add_result))severity note;
 
          if unsigned(tmp_result(18 downto 0)) = (ZEROS(18 downto 0))then
            add_op_a <= unsigned(tmp_result(57 downto 19))&'0';
 
          else
            add_op_a <= unsigned(tmp_result(57 downto 18));
          end if;
 
          add_op_b <= mul_result;
 
          mul_op_a <= unsigned(c);
          mul_op_b <= unsigned(e);
 
          state <= s4;
        when s4 =>
          assert sticky_bit = '0' report "sticky4"&to_string(std_logic_vector(add_result))severity note;
          add_op_a <= add_result;
          add_op_b <= mul_result;
 
          mul_op_a <= unsigned(a);
          mul_op_b <= unsigned(f);
 
          state <= s5;
        when s5 =>
          assert sticky_bit = '0' report "sticky5"&to_string(std_logic_vector(add_result))severity note;
          add_op_a <= "00"&x"0000"& add_result(39 downto 19)&sticky_bit;
          add_op_b <= mul_result;
 
          mul_op_a <= unsigned(b);
          mul_op_b <= unsigned(e);
 
          state <= s6;
        when s6 =>
          assert sticky_bit = '0' report "sticky6"&to_string(std_logic_vector(add_result))severity note;
          add_op_a <= add_result;
          add_op_b <= mul_result;
 
          mul_op_a <= unsigned(c);
          mul_op_b <= unsigned(d);
 
 
 
          state <= s7;
        when s7 =>
          assert sticky_bit = '0' report "sticky7"&to_string(std_logic_vector(add_result))severity note;
          add_op_a <= add_result;
          add_op_b <= mul_result;
          mul_op_a <= unsigned(a);
          mul_op_b <= unsigned(e);
 
          state <= s8;
        when s8 =>
          assert sticky_bit = '0' report "sticky8"&to_string(std_logic_vector(add_result))severity note;
          add_op_a <= "00"&x"0000"& add_result(39 downto 18);--&sticky_bit;
          add_op_b <= mul_result;
 
          mul_op_a <= unsigned(b);
          mul_op_b <= unsigned(d);
 
 
          state <= s9;
        when s9 =>
          assert sticky_bit = '0' report "sticky9"&to_string(std_logic_vector(add_result))severity note;
          add_op_a                <= add_result;
          add_op_b                <= mul_result;
          mul_op_a                <= unsigned(a);
          mul_op_b                <= unsigned(d);
          tmp_result              <= (others => '0');
          assert false report "bla" & to_string(std_logic_vector(add_result)) severity warning;
          assert false report "bla" & to_string(std_logic_vector(add_result(39 downto 30))) severity warning;
          tmp_result (4 downto 0) <= std_logic_vector(add_result(39 downto 36))&sticky_bit;  --
          -- driving me crazy!
 
          state <= s10;
        when s10 =>
          assert sticky_bit = '0' report "sticky10"&to_string(std_logic_vector(add_result))severity note;
          assert false report "bla1" & to_string(std_logic_vector(add_result)) severity warning;
          add_op_a <= "00"&x"0000"& add_result(39 downto 18);
          add_op_b <= mul_result;
 
          tmp_result(22 downto 5) <= std_logic_vector(add_result(17 downto 0));
 
 
          state <= s11;
        when s11 =>
          assert false report "bla2" & to_string(std_logic_vector(add_result)) severity warning;
          tmp_result (57 downto 23) <= std_logic_vector(add_result(34 downto 0));
          state                     <= s12b;
          if add_result (33) = '1' then
            state <= s12a;
          end if;
          --     VALID                     <= '1';
 
        when s12a=>
          assert false report "shift"&to_string(tmp_result) severity note;
          assert false report "ungleich" severity note;
          tmp_result(57 downto 1) <= '0'&tmp_result(57 downto 2);
          tmp_result(0)           <= tmp_result(1) or tmp_result(0);
          exponent_out            <= std_logic_vector(unsigned(exponent_out)+"1");
          state                   <= s12b;
 
        when s12b=>
          assert false report "vorrund"&to_string(tmp_result) severity note;
          case tmp_result(3 downto 0) is
            when "0101" => tmp_result(3) <= '1';
            when "0110" => tmp_result(3) <= '1';
            when "0111" => tmp_result(3) <= '1';
 
            when "1100" => tmp_result(57 downto 3) <= std_logic_vector(unsigned(tmp_result(57 downto 3))+"1");
            when "1101" => tmp_result(57 downto 3) <= std_logic_vector(unsigned(tmp_result(57 downto 3))+"1");
            when "1110" => tmp_result(57 downto 3) <= std_logic_vector(unsigned(tmp_result(57 downto 3))+"1");
            when "1111" => tmp_result(57 downto 3) <= std_logic_vector(unsigned(tmp_result (57 downto 3))+"1");
 
 
            when others => null;        -- others remain unchanged
          end case; 
 
		  state <= s12c;
        when s12c=>
                  state <= s12;
                  if tmp_result(56) ='1' then
                    state <= s12d;
 
                  end if;
 
        when s12d=>
          assert false report "ungleich" severity note;
          tmp_result(57 downto 1) <= '0'&tmp_result(57 downto 2);
          tmp_result(0)           <= tmp_result(1) or tmp_result(0);
          exponent_out            <= std_logic_vector(unsigned(exponent_out)+"1");
          state                   <= s12;
 
 
        when s12 =>
          assert false report "ttt"&to_string(tmp_result) severity note;
          state <= s12;
          valid <= '1';
 
        when others => null;
      end case;
    end if;
 
  end process state_trans;
 
end rtl;
 
-------------------------------------------------------------------------------
 

Go to most recent revision | Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

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