Hardware Design: SIE
Sign in or create your account | Project List | Help
Hardware Design: SIE Git Source Tree
Root/
| 1 | --------------------------------------------------------------------- |
| 2 | -- TITLE: Multiplication and Division Unit |
| 3 | -- AUTHORS: Steve Rhoads (rhoadss@yahoo.com) |
| 4 | -- DATE CREATED: 1/31/01 |
| 5 | -- FILENAME: mult.vhd |
| 6 | -- PROJECT: Plasma CPU core |
| 7 | -- COPYRIGHT: Software placed into the public domain by the author. |
| 8 | -- Software 'as is' without warranty. Author liable for nothing. |
| 9 | -- DESCRIPTION: |
| 10 | -- Implements the multiplication and division unit in 32 clocks. |
| 11 | -- |
| 12 | -- To reduce space, compile your code using the flag "-mno-mul" which |
| 13 | -- will use software base routines in math.c if USE_SW_MULT is defined. |
| 14 | -- Then remove references to the entity mult in mlite_cpu.vhd. |
| 15 | -- |
| 16 | -- MULTIPLICATION |
| 17 | -- long64 answer = 0 |
| 18 | -- for(i = 0; i < 32; ++i) |
| 19 | -- { |
| 20 | -- answer = (answer >> 1) + (((b&1)?a:0) << 31); |
| 21 | -- b = b >> 1; |
| 22 | -- } |
| 23 | -- |
| 24 | -- DIVISION |
| 25 | -- long upper=a, lower=0; |
| 26 | -- a = b << 31; |
| 27 | -- for(i = 0; i < 32; ++i) |
| 28 | -- { |
| 29 | -- lower = lower << 1; |
| 30 | -- if(upper >= a && a && b < 2) |
| 31 | -- { |
| 32 | -- upper = upper - a; |
| 33 | -- lower |= 1; |
| 34 | -- } |
| 35 | -- a = ((b&2) << 30) | (a >> 1); |
| 36 | -- b = b >> 1; |
| 37 | -- } |
| 38 | --------------------------------------------------------------------- |
| 39 | library ieee; |
| 40 | use ieee.std_logic_1164.all; |
| 41 | use ieee.std_logic_unsigned.all; |
| 42 | use IEEE.std_logic_arith.all; |
| 43 | use work.mlite_pack.all; |
| 44 | |
| 45 | entity mult is |
| 46 | generic(mult_type : string := "DEFAULT"); |
| 47 | port(clk : in std_logic; |
| 48 | reset_in : in std_logic; |
| 49 | a, b : in std_logic_vector(31 downto 0); |
| 50 | mult_func : in mult_function_type; |
| 51 | c_mult : out std_logic_vector(31 downto 0); |
| 52 | pause_out : out std_logic); |
| 53 | end; --entity mult |
| 54 | |
| 55 | architecture logic of mult is |
| 56 | |
| 57 | constant MODE_MULT : std_logic := '1'; |
| 58 | constant MODE_DIV : std_logic := '0'; |
| 59 | |
| 60 | signal mode_reg : std_logic; |
| 61 | signal negate_reg : std_logic; |
| 62 | signal sign_reg : std_logic; |
| 63 | signal sign2_reg : std_logic; |
| 64 | signal count_reg : std_logic_vector(5 downto 0); |
| 65 | signal aa_reg : std_logic_vector(31 downto 0); |
| 66 | signal bb_reg : std_logic_vector(31 downto 0); |
| 67 | signal upper_reg : std_logic_vector(31 downto 0); |
| 68 | signal lower_reg : std_logic_vector(31 downto 0); |
| 69 | |
| 70 | signal a_neg : std_logic_vector(31 downto 0); |
| 71 | signal b_neg : std_logic_vector(31 downto 0); |
| 72 | signal sum : std_logic_vector(32 downto 0); |
| 73 | |
| 74 | begin |
| 75 | |
| 76 | -- Result |
| 77 | c_mult <= lower_reg when mult_func = MULT_READ_LO and negate_reg = '0' else |
| 78 | bv_negate(lower_reg) when mult_func = MULT_READ_LO |
| 79 | and negate_reg = '1' else |
| 80 | upper_reg when mult_func = MULT_READ_HI else |
| 81 | ZERO; |
| 82 | pause_out <= '1' when (count_reg /= "000000") and |
| 83 | (mult_func = MULT_READ_LO or mult_func = MULT_READ_HI) else '0'; |
| 84 | |
| 85 | -- ABS and remainder signals |
| 86 | a_neg <= bv_negate(a); |
| 87 | b_neg <= bv_negate(b); |
| 88 | sum <= bv_adder(upper_reg, aa_reg, mode_reg); |
| 89 | |
| 90 | --multiplication/division unit |
| 91 | mult_proc: process(clk, reset_in, a, b, mult_func, |
| 92 | a_neg, b_neg, sum, sign_reg, mode_reg, negate_reg, |
| 93 | count_reg, aa_reg, bb_reg, upper_reg, lower_reg) |
| 94 | variable count : std_logic_vector(2 downto 0); |
| 95 | begin |
| 96 | count := "001"; |
| 97 | if reset_in = '1' then |
| 98 | mode_reg <= '0'; |
| 99 | negate_reg <= '0'; |
| 100 | sign_reg <= '0'; |
| 101 | sign2_reg <= '0'; |
| 102 | count_reg <= "000000"; |
| 103 | aa_reg <= ZERO; |
| 104 | bb_reg <= ZERO; |
| 105 | upper_reg <= ZERO; |
| 106 | lower_reg <= ZERO; |
| 107 | elsif rising_edge(clk) then |
| 108 | case mult_func is |
| 109 | when MULT_WRITE_LO => |
| 110 | lower_reg <= a; |
| 111 | negate_reg <= '0'; |
| 112 | when MULT_WRITE_HI => |
| 113 | upper_reg <= a; |
| 114 | negate_reg <= '0'; |
| 115 | when MULT_MULT => |
| 116 | mode_reg <= MODE_MULT; |
| 117 | aa_reg <= a; |
| 118 | bb_reg <= b; |
| 119 | upper_reg <= ZERO; |
| 120 | count_reg <= "100000"; |
| 121 | negate_reg <= '0'; |
| 122 | sign_reg <= '0'; |
| 123 | sign2_reg <= '0'; |
| 124 | when MULT_SIGNED_MULT => |
| 125 | mode_reg <= MODE_MULT; |
| 126 | if b(31) = '0' then |
| 127 | aa_reg <= a; |
| 128 | bb_reg <= b; |
| 129 | sign_reg <= a(31); |
| 130 | else |
| 131 | aa_reg <= a_neg; |
| 132 | bb_reg <= b_neg; |
| 133 | sign_reg <= a_neg(31); |
| 134 | end if; |
| 135 | sign2_reg <= '0'; |
| 136 | upper_reg <= ZERO; |
| 137 | count_reg <= "100000"; |
| 138 | negate_reg <= '0'; |
| 139 | when MULT_DIVIDE => |
| 140 | mode_reg <= MODE_DIV; |
| 141 | aa_reg <= b(0) & ZERO(30 downto 0); |
| 142 | bb_reg <= b; |
| 143 | upper_reg <= a; |
| 144 | count_reg <= "100000"; |
| 145 | negate_reg <= '0'; |
| 146 | when MULT_SIGNED_DIVIDE => |
| 147 | mode_reg <= MODE_DIV; |
| 148 | if b(31) = '0' then |
| 149 | aa_reg(31) <= b(0); |
| 150 | bb_reg <= b; |
| 151 | else |
| 152 | aa_reg(31) <= b_neg(0); |
| 153 | bb_reg <= b_neg; |
| 154 | end if; |
| 155 | if a(31) = '0' then |
| 156 | upper_reg <= a; |
| 157 | else |
| 158 | upper_reg <= a_neg; |
| 159 | end if; |
| 160 | aa_reg(30 downto 0) <= ZERO(30 downto 0); |
| 161 | count_reg <= "100000"; |
| 162 | negate_reg <= a(31) xor b(31); |
| 163 | when others => |
| 164 | |
| 165 | if count_reg /= "000000" then |
| 166 | if mode_reg = MODE_MULT then |
| 167 | -- Multiplication |
| 168 | if bb_reg(0) = '1' then |
| 169 | upper_reg <= (sign_reg xor sum(32)) & sum(31 downto 1); |
| 170 | lower_reg <= sum(0) & lower_reg(31 downto 1); |
| 171 | sign2_reg <= sign2_reg or sign_reg; |
| 172 | sign_reg <= '0'; |
| 173 | bb_reg <= '0' & bb_reg(31 downto 1); |
| 174 | -- The following six lines are optional for speedup |
| 175 | --elsif bb_reg(3 downto 0) = "0000" and sign2_reg = '0' and |
| 176 | -- count_reg(5 downto 2) /= "0000" then |
| 177 | -- upper_reg <= "0000" & upper_reg(31 downto 4); |
| 178 | -- lower_reg <= upper_reg(3 downto 0) & lower_reg(31 downto 4); |
| 179 | -- count := "100"; |
| 180 | -- bb_reg <= "0000" & bb_reg(31 downto 4); |
| 181 | else |
| 182 | upper_reg <= sign2_reg & upper_reg(31 downto 1); |
| 183 | lower_reg <= upper_reg(0) & lower_reg(31 downto 1); |
| 184 | bb_reg <= '0' & bb_reg(31 downto 1); |
| 185 | end if; |
| 186 | else |
| 187 | -- Division |
| 188 | if sum(32) = '0' and aa_reg /= ZERO and |
| 189 | bb_reg(31 downto 1) = ZERO(31 downto 1) then |
| 190 | upper_reg <= sum(31 downto 0); |
| 191 | lower_reg(0) <= '1'; |
| 192 | else |
| 193 | lower_reg(0) <= '0'; |
| 194 | end if; |
| 195 | aa_reg <= bb_reg(1) & aa_reg(31 downto 1); |
| 196 | lower_reg(31 downto 1) <= lower_reg(30 downto 0); |
| 197 | bb_reg <= '0' & bb_reg(31 downto 1); |
| 198 | end if; |
| 199 | count_reg <= count_reg - count; |
| 200 | end if; --count |
| 201 | |
| 202 | end case; |
| 203 | |
| 204 | end if; |
| 205 | |
| 206 | end process; |
| 207 | |
| 208 | end; --architecture logic |
| 209 |
Branches:
master
