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

Subversion Repositories plasma

[/] [plasma/] [tags/] [V2_1/] [vhdl/] [mult.vhd] - Blame information for rev 47

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

powered by: WebSVN 2.1.0

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