⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fpu_lth.vhd

📁 ARM7的源代码
💻 VHD
📖 第 1 页 / 共 3 页
字号:
type fpu_result_type is record          -- roundnorm <-> out  frac : std_logic_vector(51 downto 0);  exp  : std_logic_vector(10 downto 0);  sign : std_logic;  cc   : std_logic_vector(1 downto 0);  exc  : std_logic_vector(5 downto 0);end record;--------------------------------------------------------------------------------- Declaration of input and output signal from the different pipeline-- registers.-------------------------------------------------------------------------------signal de, de_in : op_decode_stage_type;signal pren, pren_in : prenorm_stage_type;signal as, as_in : addsub_stage_type;signal posn, posn_in : postnorm_stage_type;signal rnd, rnd_in : roundnorm_stage_type;signal rnd_out : fpu_result_type;--------------------------------------------------------------------------------- Type and signals used by generate busy process. In the fututure this process-- might be integrated into the pipeline but for now a seperat process is used.-------------------------------------------------------------------------------type fpu_state is (start, get_operand, pre_norm, add_sub, post_norm,                   rnd_norm, hold_val);signal state, next_state : fpu_state;signal result_ready : std_logic;begin  -- rtl  de_in.opcode <= FpInst;  --------------------------------------------------------------------------------- Opcode decode and unpacking stage-------------------------------------------------------------------------------  decode_stage: process (de, fprf_dout1, fprf_dout2)    variable single : std_logic;    variable exp1 : std_logic_vector(10 downto 0);    variable exp2 : std_logic_vector(10 downto 0);    variable frac1 : std_logic_vector(51 downto 0);    variable frac2 : std_logic_vector(51 downto 0);    variable frac1_zero : std_logic;    variable frac2_zero : std_logic;    variable exp1_max : std_logic;    variable exp2_max : std_logic;    variable exp1_min : std_logic;    variable exp2_min : std_logic;  begin    -- Get sign bit for op1    pren_in.sign1 <= fprf_dout1(63);    -- Unpack exponent and fraction depending on the precision mode. Note that    -- if single precision is used som bit filling must be done for the    -- exponent and fraction since double precision is used internally.    if de.opcode(1 downto 0) = "01" then -- If single precision      single := '1';      exp1 := "000" & fprf_dout1(62 downto 55);      frac1 := "0" & zero(27 downto 0) & fprf_dout1(54 downto 32);      exp2 := "000" & fprf_dout2(62 downto 55);      frac2 := "0" & zero(27 downto 0) & fprf_dout2(54 downto 32);    else      -- If double precision      single := '0';      exp1 := fprf_dout1(62 downto 52);      frac1 := fprf_dout1(51 downto 0);      exp2 := fprf_dout2(62 downto 52);      frac2 := fprf_dout2(51 downto 0);          end if;    -- Check if fracions zero    if frac1 = zero(51 downto 0) then      frac1_zero := '1';    else      frac1_zero := '0';    end if;    if frac2 = zero(51 downto 0) then      frac2_zero := '1';    else      frac2_zero := '0';    end if;    -- Check if exp is max or min    if (exp1(7 downto 0) = "11111111") and       ((single = '1') or (exp1(10 downto 8) = "111")) then      exp1_max := '1';      exp1_min := '0';    elsif exp1 = "00000000000" then      exp1_max := '0';      exp1_min := '1';    else      exp1_max := '0';      exp1_min := '0';    end if;    if (exp2(7 downto 0) = "11111111") and       ((single = '1') or (exp2(10 downto 8) = "111")) then      exp2_max := '1';      exp2_min := '0';    elsif exp2 = "00000000000" then      exp2_max := '0';      exp2_min := '1';    else      exp2_max := '0';      exp2_min := '0';    end if;    -- Detect special numbers    pren_in.op1_denorm <= exp1_min;    pren_in.op2_denorm <= exp2_min;    pren_in.op1_inf <= exp1_max and frac1_zero;    pren_in.op2_inf <= exp2_max and frac2_zero;    pren_in.op1_SNaN <= exp1_max and (not frac1_zero) and                        not (frac1(51) or (frac1(22) and single));    pren_in.op2_SNaN <= exp2_max and (not frac2_zero) and                        not (frac2(51) or (frac2(22) and single));    pren_in.op1_NaN <= exp1_max and (not frac1_zero) and                       (frac1(51) or (frac1(22) and single));    pren_in.op2_NaN <= exp2_max and (not frac2_zero) and                       (frac2(51) or (frac2(22) and single));        -- Decode instruction. If operation is sub or cmp then negate op2 sign.    -- Unimplemented opcodes will result in addition.    case de.opcode(8 downto 0) is      when FSUBS | FSUBD =>     pren_in.sign2 <= not fprf_dout2(63);                                pren_in.comp <= '0';                                pren_in.gen_ex <= '0';      when FCMPS | FCMPD =>     pren_in.sign2 <= not fprf_dout2(63);                                pren_in.comp <= '1';                                pren_in.gen_ex <= '0';      when FCMPES | FCMPED =>   pren_in.sign2 <= not fprf_dout2(63);                                pren_in.comp <= '1';                                pren_in.gen_ex <= '1';      when others =>            pren_in.sign2 <= fprf_dout2(63);                                pren_in.comp <= '0';                                pren_in.gen_ex <= '0';    end case;    pren_in.single <= single;    pren_in.frac1 <= frac1;    pren_in.exp1 <= exp1;    pren_in.frac2 <= frac2;    pren_in.exp2 <= exp2;  end process decode_stage;--------------------------------------------------------------------------------- Prenorm stage-------------------------------------------------------------------------------  prenorm_stage: process (pren)    variable switch_ops : std_logic;    variable sign_diff : std_logic_vector(11 downto 0);    variable abs_diff : std_logic_vector(11 downto 0);    variable all_zero : std_logic_vector(11 downto 0);    variable shift_amount : std_logic_vector(5 downto 0);    variable adj_op : std_logic_vector(54 downto 0);    variable shifted_op : std_logic_vector(54 downto 0);    variable sticky_bit : std_logic;  begin    all_zero := (others => '0');        -- Calculate differens-- pragma translate_off    if not is_x(pren.exp1 & pren.exp2) then-- pragma translate_on      sign_diff := ("0" & pren.exp1) - ("0" & pren.exp2);-- pragma translate_off    end if;-- pragma translate_on    switch_ops := sign_diff(11);        -- Switch needed    -- If negative get absolute value    if sign_diff(11) = '1' then-- pragma translate_off      if not is_x(all_zero & sign_diff) then-- pragma translate_on        abs_diff := all_zero - sign_diff;-- pragma translate_off      end if;-- pragma translate_on    else      abs_diff := sign_diff(11 downto 0);    end if;    -- Not needed to shift more then the length of the fraction-- pragma translate_off    if not is_x(abs_diff) then-- pragma translate_on      if abs_diff > 52 then        shift_amount := "110100";      else        shift_amount := abs_diff(5 downto 0);      end if;-- pragma translate_off    end if;-- pragma translate_on        -- Do switch of operands if needed. Then retrieve the hidden bit for the    -- larger operand and append overflow, guard, round and sticky bit. For the    -- smaller operand retrive hidden bit and append guard and round bit.     if switch_ops = '1' then      if (pren.single='1') then   -- single precision        as_in.a <=zero(29 downto 0) & (not pren.op2_denorm) & pren.frac2(22 downto 0) & "000";        adj_op := zero(28 downto 0) & (not pren.op1_denorm) & pren.frac1(22 downto 0) & "00";      else        as_in.a <= "0" & (not pren.op2_denorm) & pren.frac2 & "000";        adj_op := (not pren.op1_denorm) & pren.frac1 & "00";      end if;      as_in.exp <= pren.exp2;      as_in.sign_a <= pren.sign2;      as_in.sign_b <= pren.sign1;    else      if (pren.single='1') then   -- single precision        as_in.a <=zero(29 downto 0) & (not pren.op1_denorm) & pren.frac1(22 downto 0) & "000";        adj_op := zero(28 downto 0) & (not pren.op2_denorm) & pren.frac2(22 downto 0) & "00";      else        as_in.a <= "0" & (not pren.op1_denorm) & pren.frac1 & "000";        adj_op := (not pren.op2_denorm) & pren.frac2 & "00";      end if;      as_in.exp <= pren.exp1;      as_in.sign_a <= pren.sign1;      as_in.sign_b <= pren.sign2;    end if;        -- Shift smaller operand right and get sticky bit.    right_shifter_sticky(adj_op,shift_amount,shifted_op,sticky_bit);    -- Add overflow and sticky bit for shifted smaller operand.    as_in.b <= "0" & shifted_op & sticky_bit;        as_in.swaped <= switch_ops;    as_in.op1_inf <= pren.op1_inf;    as_in.op2_inf <= pren.op2_inf;    as_in.op1_NaN <= pren.op1_NaN;    as_in.op2_NaN <= pren.op2_Nan;    as_in.op1_SNaN <= pren.op1_SNaN;    as_in.op2_SNaN <= pren.op2_SNaN;    as_in.single <= pren.single;    as_in.comp <= pren_in.comp;    as_in.gen_ex <= pren_in.gen_ex;  end process prenorm_stage;--------------------------------------------------------------------------------- Add/Sub stage-------------------------------------------------------------------------------  addsub_stage: process (as)    variable signs : std_logic_vector(1 downto 0);    variable result : std_logic_vector(56 downto 0);    variable temp : std_logic_vector(56 downto 0);    variable neg_value : std_logic;    variable all_zero : std_logic_vector(56 downto 0);    variable unordered : std_logic;    variable zero_fraction : std_logic;    variable cc_bit0 : std_logic;    variable cc_bit1 : std_logic;    variable SNaN : std_logic;    variable NaN : std_logic;    variable inf : std_logic;  begin    all_zero := (others => '0');        signs := as.sign_a & as.sign_b;    -- Perform operation based on the sign of the operands    case signs is      when "00" => -- pragma translate_off		if not is_x(as.a & as.b) then-- pragma translate_on		   result := as.a + as.b;-- pragma translate_off		end if;-- pragma translate_on                   posn_in.sign <= '0';                   neg_value := '0';      when "01" =>-- pragma translate_off		if not is_x(as.a & as.b) then-- pragma translate_on                   result := as.a - as.b;-- pragma translate_off		end if;-- pragma translate_on                   posn_in.sign <= result(56);                   neg_value := result(56);       when "10" =>-- pragma translate_off		if not is_x(as.a & as.b) then-- pragma translate_on                   result := as.a - as.b;-- pragma translate_off		end if;-- pragma translate_on                   posn_in.sign <= not result(56);                   neg_value := result(56);      when "11" =>-- pragma translate_off		if not is_x(as.a & as.b) then-- pragma translate_on                   result := as.a + as.b;-- pragma translate_off		end if;-- pragma translate_on                   posn_in.sign <= '1';                   neg_value := '0';      when others => null;    end case;    -- If result is negative set fraction = -result else set fraction = result-- pragma translate_off    if not is_x(all_zero & result) then-- pragma translate_on      temp := all_zero - result;-- pragma translate_off    end if;-- pragma translate_on    if neg_value = '1' then      posn_in.frac <= temp(56 downto 0);    else      posn_in.frac <= result(56 downto 0);    end if;    -- Check if result is zero    if result = all_zero then      zero_fraction := '1';      posn_in.exp <= "00000000000";    else      zero_fraction := '0';      posn_in.exp <= as.exp;    end if;    -- Check if unordered operands i.e. any operand is some sort of NaN    unordered := as.op1_NaN or as.op2_NaN or as.op1_SNaN or as.op2_SNaN;    -- Check if result should be a SNaN.    SNaN := as.op1_SNaN or as.op2_SNaN or (unordered and as.gen_ex);    -- Check if result should be a NaN i.e. unordered opearands that don't    -- result in a SNaN or two inf values with different signs.    NaN := (unordered and (not SNaN)) or           (as.op1_inf and as.op2_inf and (signs(1) xor signs(0)));        -- Check if result should be inf.    inf := (as.op1_inf or as.op2_inf) and (not NaN) and (not SNaN);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -