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

Subversion Repositories mlite

[/] [mlite/] [trunk/] [vhdl/] [mult.vhd] - Blame information for rev 90

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

Line No. Rev Author Line
1 2 rhoads
---------------------------------------------------------------------
2
-- TITLE: Multiplication and Division Unit
3
-- AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
4
-- DATE CREATED: 1/31/01
5
-- FILENAME: mult.vhd
6 43 rhoads
-- PROJECT: Plasma CPU core
7 2 rhoads
-- 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.
11 90 rhoads
--    Division takes 32 clock cycles.
12
--    Multiplication normally takes 16 clock cycles.
13
--    if b <= 0xffff then mult in 8 cycles. 
14
--    if b <= 0xff then mult in 4 cycles. 
15 2 rhoads
---------------------------------------------------------------------
16
library ieee;
17
use ieee.std_logic_1164.all;
18 90 rhoads
use ieee.std_logic_unsigned.all;
19 39 rhoads
use work.mlite_pack.all;
20 2 rhoads
 
21
entity mult is
22 47 rhoads
   generic(adder_type : string := "GENERIC");
23 2 rhoads
   port(clk       : in std_logic;
24
        a, b      : in std_logic_vector(31 downto 0);
25
        mult_func : in mult_function_type;
26
        c_mult    : out std_logic_vector(31 downto 0);
27
        pause_out : out std_logic);
28
end; --entity mult
29
 
30
architecture logic of mult is
31
--   type mult_function_type is (
32
--      mult_nothing, mult_read_lo, mult_read_hi, mult_write_lo, 
33
--      mult_write_hi, mult_mult, mult_divide, mult_signed_divide);
34 47 rhoads
   signal do_mult_reg   : std_logic;
35 2 rhoads
   signal do_signed_reg : std_logic;
36
   signal count_reg     : std_logic_vector(5 downto 0);
37
   signal reg_a         : std_logic_vector(31 downto 0);
38
   signal reg_b         : std_logic_vector(63 downto 0);
39
   signal answer_reg    : std_logic_vector(31 downto 0);
40 90 rhoads
   signal aa, bb        : std_logic_vector(33 downto 0);
41
   signal sum           : std_logic_vector(33 downto 0);
42
   signal reg_a_times3  : std_logic_vector(33 downto 0);
43 2 rhoads
begin
44
 
45
--multiplication/division unit
46
mult_proc: process(clk, a, b, mult_func,
47 47 rhoads
                   do_mult_reg, do_signed_reg, count_reg,
48 90 rhoads
                   reg_a, reg_b, answer_reg, sum, reg_a_times3)
49 47 rhoads
   variable do_mult_temp   : std_logic;
50 2 rhoads
   variable do_signed_temp : std_logic;
51
   variable count_temp     : std_logic_vector(5 downto 0);
52
   variable a_temp         : std_logic_vector(31 downto 0);
53
   variable b_temp         : std_logic_vector(63 downto 0);
54
   variable answer_temp    : std_logic_vector(31 downto 0);
55
   variable start          : std_logic;
56
   variable do_write       : std_logic;
57
   variable do_hi          : std_logic;
58 45 rhoads
   variable sign_extend    : std_logic;
59 2 rhoads
 
60
begin
61 47 rhoads
   do_mult_temp   := do_mult_reg;
62 2 rhoads
   do_signed_temp := do_signed_reg;
63
   count_temp     := count_reg;
64
   a_temp         := reg_a;
65
   b_temp         := reg_b;
66
   answer_temp    := answer_reg;
67 47 rhoads
   sign_extend    := do_signed_reg and do_mult_reg;
68 2 rhoads
   start          := '0';
69
   do_write       := '0';
70
   do_hi          := '0';
71
 
72
   case mult_func is
73
   when mult_read_lo =>
74
   when mult_read_hi =>
75
      do_hi := '1';
76
   when mult_write_lo =>
77
      do_write := '1';
78
   when mult_write_hi =>
79
      do_write := '1';
80
      do_hi := '1';
81
   when mult_mult =>
82
      start := '1';
83 47 rhoads
      do_mult_temp := '1';
84 45 rhoads
      do_signed_temp := '0';
85
   when mult_signed_mult =>
86
      start := '1';
87 47 rhoads
      do_mult_temp := '1';
88 45 rhoads
      do_signed_temp := a(31) xor b(31);
89 2 rhoads
   when mult_divide =>
90
      start := '1';
91 47 rhoads
      do_mult_temp := '0';
92 2 rhoads
      do_signed_temp := '0';
93
   when mult_signed_divide =>
94
      start := '1';
95 47 rhoads
      do_mult_temp := '0';
96 23 rhoads
      do_signed_temp := a(31) xor b(31);
97 2 rhoads
   when others =>
98
   end case;
99
 
100
   if start = '1' then
101
      count_temp := "000000";
102
      answer_temp := ZERO;
103 47 rhoads
      if do_mult_temp = '0' then
104 18 rhoads
         b_temp(63) := '0';
105 23 rhoads
         if mult_func /= mult_signed_divide or b(31) = '0' then
106 2 rhoads
            b_temp(62 downto 31) := b;
107
         else
108
            b_temp(62 downto 31) := bv_negate(b);
109 23 rhoads
         end if;
110
         if mult_func /= mult_signed_divide or a(31) = '0' then
111
            a_temp := a;
112
         else
113 2 rhoads
            a_temp := bv_negate(a);
114
         end if;
115
         b_temp(30 downto 0) := ZERO(30 downto 0);
116
      else --multiply
117 23 rhoads
         a_temp := a;
118 7 rhoads
         b_temp := ZERO & b;
119 2 rhoads
      end if;
120
   elsif do_write = '1' then
121
      if do_hi = '0' then
122
         b_temp(31 downto 0) := a;
123
      else
124
         b_temp(63 downto 32) := a;
125
      end if;
126
   end if;
127
 
128 90 rhoads
   if do_mult_reg = '0' then  --division
129
      aa <= (reg_a(31) and sign_extend) & (reg_a(31) and sign_extend) & reg_a;
130
      bb <= reg_b(33 downto 0);
131
   else                       --multiplication two-bits at a time
132
      case reg_b(1 downto 0) is
133
      when "00" =>
134
         aa <= "00" & ZERO;
135
      when "01" =>
136
         aa <= (reg_a(31) and sign_extend) & (reg_a(31) and sign_extend) & reg_a;
137
      when "10" =>
138
         aa <= (reg_a(31) and sign_extend) & reg_a & '0';
139
      when others =>
140
         aa <= reg_a_times3;
141
      end case;
142
      bb <= (reg_b(63) and sign_extend) & (reg_b(63) and sign_extend) & reg_b(63 downto 32);
143 2 rhoads
   end if;
144
 
145
   if count_reg(5) = '0' and start = '0' then
146
      count_temp := bv_inc6(count_reg);
147 90 rhoads
      if do_mult_reg = '0' then          --division
148 2 rhoads
         answer_temp(31 downto 1) := answer_reg(30 downto 0);
149 23 rhoads
         if reg_b(63 downto 32) = ZERO and sum(32) = '0' then
150 2 rhoads
            a_temp := sum(31 downto 0);  --aa=aa-bb;
151
            answer_temp(0) := '1';
152
         else
153
            answer_temp(0) := '0';
154
         end if;
155
         if count_reg /= "011111" then
156
            b_temp(62 downto 0) := reg_b(63 downto 1);
157 90 rhoads
         else                            --done with divide
158 2 rhoads
            b_temp(63 downto 32) := a_temp;
159 23 rhoads
            if do_signed_reg = '0' then
160
               b_temp(31 downto 0) := answer_temp;
161
            else
162
               b_temp(31 downto 0) := bv_negate(answer_temp);
163
            end if;
164 2 rhoads
         end if;
165
      else  -- mult_mode
166 90 rhoads
         b_temp(63 downto 30) := sum;
167
         b_temp(29 downto 0) := reg_b(31 downto 2);
168
         if count_reg = "001000" and sign_extend = '0' and   --early stop
169 7 rhoads
               reg_b(15 downto 0) = ZERO(15 downto 0) then
170 2 rhoads
            count_temp := "111111";
171
            b_temp(31 downto 0) := reg_b(47 downto 16);
172
         end if;
173 90 rhoads
         if count_reg = "000100" and sign_extend = '0' and   --early stop
174 7 rhoads
               reg_b(23 downto 0) = ZERO(23 downto 0) then
175
            count_temp := "111111";
176
            b_temp(31 downto 0) := reg_b(55 downto 24);
177
         end if;
178 90 rhoads
         count_temp(5) := count_temp(4);
179 2 rhoads
      end if;
180
   end if;
181
 
182
   if rising_edge(clk) then
183 47 rhoads
      do_mult_reg <= do_mult_temp;
184 2 rhoads
      do_signed_reg <= do_signed_temp;
185
      count_reg <= count_temp;
186
      reg_a <= a_temp;
187
      reg_b <= b_temp;
188
      answer_reg <= answer_temp;
189 90 rhoads
      if start = '1' then
190
         reg_a_times3 <= ((a(31) and do_signed_temp) & a & '0') +
191
            ((a(31) and do_signed_temp) & (a(31) and do_signed_temp) & a);
192
      end if;
193 2 rhoads
   end if;
194
 
195
   if count_reg(5) = '0' and mult_func/= mult_nothing and start = '0' then
196
      pause_out <= '1';
197
   else
198
      pause_out <= '0';
199
   end if;
200 47 rhoads
   case mult_func is
201
   when mult_read_lo =>
202 2 rhoads
      c_mult <= reg_b(31 downto 0);
203 47 rhoads
   when mult_read_hi =>
204 2 rhoads
      c_mult <= reg_b(63 downto 32);
205 47 rhoads
   when others =>
206 2 rhoads
      c_mult <= ZERO;
207 47 rhoads
   end case;
208 2 rhoads
 
209
end process;
210
 
211 47 rhoads
 
212
   generic_adder:
213
   if adder_type /= "ALTERA" generate
214 90 rhoads
      sum <= (aa + bb) when do_mult_reg = '1' else
215
             (aa - bb);
216 47 rhoads
   end generate; --generic_adder
217
 
218
   --For Altera
219
   lpm_adder:
220
   if adder_type = "ALTERA" generate
221
      lpm_add_sub_component : lpm_add_sub
222
      GENERIC MAP (
223 90 rhoads
         lpm_width => 34,
224 47 rhoads
         lpm_direction => "UNUSED",
225
         lpm_type => "LPM_ADD_SUB",
226
         lpm_hint => "ONE_INPUT_IS_CONSTANT=NO"
227
      )
228
      PORT MAP (
229
         dataa => aa,
230
         add_sub => do_mult_reg,
231
         datab => bb,
232
         result => sum
233
      );
234
   end generate; --lpm_adder
235
 
236 2 rhoads
end; --architecture logic
237
 

powered by: WebSVN 2.1.0

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