Loesung des Praktikums Systementwurf - Bjarne Hoesch - Bernhard Schoeffel
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

float_add.vhd 5.8KB

1 year ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. library IEEE;
  2. use IEEE.std_logic_1164.all;
  3. use IEEE.numeric_std.all;
  4. entity float_add is
  5. port(A : in std_logic_vector(31 downto 0);
  6. B : in std_logic_vector(31 downto 0);
  7. clk : in std_logic;
  8. reset : in std_logic;
  9. start : in std_logic;
  10. done : out std_logic;
  11. sum : out std_logic_vector(31 downto 0)
  12. );
  13. end float_add;
  14. architecture mixed of float_add is
  15. type ST is (WAIT_STATE, ALIGN_STATE, ADDITION_STATE, NORMALIZE_STATE, OUTPUT_STATE);
  16. signal state : ST := WAIT_STATE;
  17. ---Internal Signals latched from the inputs
  18. signal A_mantissa, B_mantissa : std_logic_vector (24 downto 0);
  19. signal A_exp, B_exp : std_logic_vector (8 downto 0);
  20. signal A_sgn, B_sgn : std_logic;
  21. --Internal signals for Output
  22. signal sum_exp: std_logic_vector (8 downto 0);
  23. signal sum_mantissa : std_logic_vector (24 downto 0);
  24. signal sum_sgn : std_logic;
  25. begin
  26. Control_Unit : process (clk, reset) is
  27. variable diff : signed(8 downto 0);
  28. begin
  29. if(reset = '1') then
  30. state <= WAIT_STATE; --start in wait state
  31. done <= '0';
  32. elsif rising_edge(clk) then
  33. case state is
  34. when WAIT_STATE =>
  35. if (start = '1') then --wait till start request startes high
  36. A_sgn <= A(31);
  37. A_exp <= '0' & A(30 downto 23); --One bit is added for signed subtraction
  38. A_mantissa <= "01" & A(22 downto 0); --Two bits are added extra, one for leading 1 and other one for storing carry
  39. B_sgn <= B(31);
  40. B_exp <= '0' & B(30 downto 23);
  41. B_mantissa <= "01" & B(22 downto 0);
  42. state <= ALIGN_STATE;
  43. else
  44. state <= WAIT_STATE;
  45. end if;
  46. when ALIGN_STATE => --Compare exponent and align it
  47. --If any num is greater by 2**24, we skip the addition.
  48. if unsigned(A_exp) > unsigned(B_exp) then
  49. --B needs downshifting
  50. diff := signed(A_exp) - signed(B_exp); --Small Alu
  51. if diff > 23 then
  52. sum_mantissa <= A_mantissa; --B insignificant relative to A
  53. sum_exp <= A_exp;
  54. sum_sgn <= A_sgn;
  55. state <= OUTPUT_STATE; --start latch A as output
  56. else
  57. --downshift B to equilabrate B_exp to A_exp
  58. sum_exp <= A_exp;
  59. B_mantissa(24-to_integer(diff) downto 0) <= B_mantissa(24 downto to_integer(diff));
  60. B_mantissa(24 downto 25-to_integer(diff)) <= (others => '0');
  61. state <= ADDITION_STATE;
  62. end if;
  63. elsif unsigned(A_exp) < unsigned(B_exp) then --A_exp < B_exp. A needs downshifting
  64. diff := signed(B_exp) - signed(A_exp); -- Small Alu
  65. if diff > 23 then
  66. sum_mantissa <= B_mantissa; --A insignificant relative to B
  67. sum_sgn <= B_sgn;
  68. sum_exp <= B_exp;
  69. state <= OUTPUT_STATE; --start latch B as output
  70. else
  71. --downshift A to equilabrate A_exp to B_exp
  72. sum_exp <= B_exp;
  73. A_mantissa(24-to_integer(diff) downto 0) <= A_mantissa(24 downto to_integer(diff));
  74. A_mantissa(24 downto 25-to_integer(diff)) <= (others => '0');
  75. state <= ADDITION_STATE;
  76. end if;
  77. else -- Both exponent is equal. No need to mantissa shift
  78. sum_exp <= A_exp;
  79. state <= ADDITION_STATE;
  80. end if;
  81. when ADDITION_STATE => --Mantissa addition
  82. state <= NORMALIZE_STATE;
  83. if (A_sgn xor B_sgn) = '0' then --signs are the same. Just add them
  84. sum_mantissa <= std_logic_vector((unsigned(A_mantissa) + unsigned(B_mantissa))); --Big Alu
  85. sum_sgn <= A_sgn; --both nums have same sign
  86. --Else subtract smaller from larger and use sign of larger
  87. elsif unsigned(A_mantissa) >= unsigned(B_mantissa) then
  88. sum_mantissa <= std_logic_vector((unsigned(A_mantissa) - unsigned(B_mantissa))); --Big Alu
  89. sum_sgn <= A_sgn;
  90. else
  91. sum_mantissa <= std_logic_vector((unsigned(B_mantissa) - unsigned(A_mantissa))); --Big Alu
  92. sum_sgn <= B_sgn;
  93. end if;
  94. when NORMALIZE_STATE => --Normalization.
  95. if unsigned(sum_mantissa) = TO_UNSIGNED(0, 25) then
  96. --The sum is 0
  97. sum_mantissa <= (others => '0');
  98. sum_exp <= (others => '0');
  99. state <= OUTPUT_STATE;
  100. elsif(sum_mantissa(24) = '1') then --If sum overflowed we downshift and are done.
  101. sum_mantissa <= '0' & sum_mantissa(24 downto 1); --shift the 1 down
  102. sum_exp <= std_logic_vector((unsigned(sum_exp)+ 1));
  103. state <= OUTPUT_STATE;
  104. elsif(sum_mantissa(23) = '0') then --in this case we need to upshift
  105. --This iterates the normalization shifts, thus can take many clocks.
  106. sum_mantissa <= sum_mantissa(23 downto 0) & '0';
  107. sum_exp <= std_logic_vector((unsigned(sum_exp)-1));
  108. state<= NORMALIZE_STATE; --keep shifting till leading 1 appears
  109. else
  110. state <= OUTPUT_STATE; --leading 1 already there. Latch output
  111. end if;
  112. when OUTPUT_STATE =>
  113. sum(22 downto 0) <= sum_mantissa(22 downto 0);
  114. sum(30 downto 23) <= sum_exp(7 downto 0);
  115. sum(31) <= sum_sgn;
  116. done <= '1'; -- signal done
  117. if (start = '0') then -- stay in the state till request ends i.e start is low
  118. done <= '0';
  119. state <= WAIT_STATE;
  120. end if;
  121. when others =>
  122. state <= WAIT_STATE; --Just in case.
  123. end case;
  124. end if;
  125. end process;
  126. end mixed;