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

Subversion Repositories mips_enhanced

[/] [mips_enhanced/] [trunk/] [grlib-gpl-1.0.19-b3188/] [lib/] [gaisler/] [arith/] [mul32.vhd] - Blame information for rev 2

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 dimamali
------------------------------------------------------------------------------
2
--  This file is a part of the GRLIB VHDL IP LIBRARY
3
--  Copyright (C) 2003, Gaisler Research
4
--
5
--  This program is free software; you can redistribute it and/or modify
6
--  it under the terms of the GNU General Public License as published by
7
--  the Free Software Foundation; either version 2 of the License, or
8
--  (at your option) any later version.
9
--
10
--  This program is distributed in the hope that it will be useful,
11
--  but WITHOUT ANY WARRANTY; without even the implied warranty of
12
--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
--  GNU General Public License for more details.
14
--
15
--  You should have received a copy of the GNU General Public License
16
--  along with this program; if not, write to the Free Software
17
--  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
18
-----------------------------------------------------------------------------
19
-- Entity:      mul
20
-- File:        mul.vhd
21
-- Author:      Jiri Gaisler - Gaisler Research
22
-- Description: This unit implements signed/unsigned 32-bit multiply module, 
23
--              producing a 64-bit result.
24
------------------------------------------------------------------------------
25
 
26
library ieee;
27
use ieee.std_logic_1164.all;
28
library grlib;
29
use grlib.stdlib.all;
30
use grlib.multlib.all;
31
library gaisler;
32
use gaisler.arith.all;
33
 
34
entity mul32 is
35
generic (
36
    infer   : integer range 0 to 1 := 1;
37
    multype : integer range 0 to 3 := 0;
38
    pipe    : integer range 0 to 1 := 0;
39
    mac     : integer range 0 to 1 := 0
40
);
41
port (
42
    rst     : in  std_ulogic;
43
    clk     : in  std_ulogic;
44
    holdn   : in  std_ulogic;
45
    muli    : in  mul32_in_type;
46
    mulo    : out mul32_out_type
47
);
48
end;
49
 
50
architecture rtl of mul32 is
51
 
52
--attribute sync_set_reset : string;
53
--attribute sync_set_reset of rst : signal is "true";
54
 
55
constant m16x16 : integer := 0;
56
constant m32x8  : integer := 1;
57
constant m32x16 : integer := 2;
58
constant m32x32 : integer := 3;
59
constant MULTIPLIER : integer := multype;
60
constant MULPIPE : boolean := ((multype = 0) or (multype = 3)) and (pipe = 1);
61
constant MACEN  : boolean := (multype = 0) and (mac = 1);
62
 
63
type mul_regtype is record
64
  acc    : std_logic_vector(63 downto 0);
65
  state  : std_logic_vector(1 downto 0);
66
  start  : std_logic;
67
  ready  : std_logic;
68
  nready : std_logic;
69
end record;
70
 
71
type mac_regtype is record
72
  mmac, xmac    : std_logic;
73
  msigned, xsigned : std_logic;
74
end record;
75
 
76
signal rm, rmin : mul_regtype;
77
signal mm, mmin : mac_regtype;
78
signal ma, mb : std_logic_vector(32 downto 0);
79
signal prod : std_logic_vector(65 downto 0);
80
signal mreg : std_logic_vector(49 downto 0);
81
 
82
begin
83
 
84
  mulcomb : process(rst, rm, muli, mreg, prod, mm)
85
  variable mop1, mop2 : std_logic_vector(32 downto 0);
86
  variable acc, acc1, acc2 : std_logic_vector(48 downto 0);
87
  variable zero, rsigned, rmac : std_logic;
88
  variable v : mul_regtype;
89
  variable w : mac_regtype;
90
  constant CZero: std_logic_vector(47 downto 0) := "000000000000000000000000000000000000000000000000";
91
  begin
92
 
93
    v := rm; w := mm; v.start := muli.start; v.ready := '0'; v.nready := '0';
94
    mop1 := muli.op1; mop2 := muli.op2;
95
    acc1 := (others => '0'); acc2 := (others => '0'); zero := '0';
96
    w.mmac := muli.mac; w.xmac := mm.mmac;
97
    w.msigned := muli.signed; w.xsigned := mm.msigned;
98
 
99
    if MULPIPE then rsigned := mm.xsigned; rmac := mm.xmac;
100
    else rsigned := mm.msigned; rmac := mm.mmac; end if;
101
 
102
-- select input 2 to accumulator
103
    case MULTIPLIER is
104
    when m16x16 =>
105
      acc2(32 downto 0) := mreg(32 downto 0);
106
    when m32x8  =>
107
      acc2(40 downto 0) := mreg(40 downto 0);
108
    when m32x16 =>
109
      acc2(48 downto 0) := mreg(48 downto 0);
110
    when others => null;
111
    end case;
112
 
113
-- state machine + inputs to multiplier and accumulator input 1
114
    case rm.state is
115
    when "00" =>
116
      case MULTIPLIER is
117
      when m16x16 =>
118
        mop1(16 downto 0) := '0' & muli.op1(15 downto 0);
119
        mop2(16 downto 0) := '0' & muli.op2(15 downto 0);
120
        if MULPIPE and (rm.ready = '1' ) then
121
          acc1(32 downto 0) := rm.acc(48 downto 16);
122
        else acc1(32 downto 0) := '0' & rm.acc(63 downto 32); end if;
123
      when m32x8 =>
124
        mop1 := muli.op1;
125
        mop2(8 downto 0) := '0' & muli.op2(7 downto 0);
126
        acc1(40 downto 0) := '0' & rm.acc(63 downto 24);
127
      when m32x16 =>
128
        mop1 := muli.op1;
129
        mop2(16 downto 0) := '0' & muli.op2(15 downto 0);
130
        acc1(48 downto 0) := '0' & rm.acc(63 downto 16);
131
      when others => null;
132
      end case;
133
      if (rm.start = '1') then v.state := "01"; end if;
134
    when "01" =>
135
      case MULTIPLIER is
136
      when m16x16 =>
137
        mop1(16 downto 0) := muli.op1(32 downto 16);
138
        mop2(16 downto 0) := '0' & muli.op2(15 downto 0);
139
        if MULPIPE then acc1(32 downto 0) := '0' & rm.acc(63 downto 32); end if;
140
        v.state := "10";
141
      when m32x8 =>
142
        mop1 := muli.op1; mop2(8 downto 0) := '0' & muli.op2(15 downto 8);
143
        v.state := "10";
144
      when m32x16 =>
145
        mop1 := muli.op1; mop2(16 downto 0) := muli.op2(32 downto 16);
146
        v.state := "00";
147
      when others => null;
148
      end case;
149
    when "10" =>
150
      case MULTIPLIER is
151
      when m16x16 =>
152
        mop1(16 downto 0) := '0' & muli.op1(15 downto 0);
153
        mop2(16 downto 0) := muli.op2(32 downto 16);
154
        if MULPIPE then acc1 := (others => '0'); acc2 := (others => '0');
155
        else acc1(32 downto 0) := rm.acc(48 downto 16); end if;
156
        v.state := "11";
157
      when m32x8 =>
158
        mop1 := muli.op1; mop2(8 downto 0) := '0' & muli.op2(23 downto 16);
159
        acc1(40 downto 0) := rm.acc(48 downto 8);
160
        v.state := "11";
161
      when others => null;
162
      end case;
163
    when others =>
164
      case MULTIPLIER is
165
      when m16x16 =>
166
        mop1(16 downto 0) := muli.op1(32 downto 16);
167
        mop2(16 downto 0) := muli.op2(32 downto 16);
168
        if MULPIPE then acc1(32 downto 0) := rm.acc(48 downto 16);
169
        else acc1(32 downto 0) := rm.acc(48 downto 16); end if;
170
        v.state := "00";
171
      when m32x8 =>
172
        mop1 := muli.op1; mop2(8 downto 0) := muli.op2(32 downto 24);
173
        acc1(40 downto 0) := rm.acc(56 downto 16);
174
        v.state := "00";
175
      when others => null;
176
      end case;
177
    end case;
178
 
179
-- optional UMAC/SMAC support
180
 
181
    if MACEN then
182
      if ((muli.mac and muli.signed) = '1') then
183
        mop1(16) := muli.op1(15); mop2(16) := muli.op2(15);
184
      end if;
185
      if rmac = '1' then
186
         acc1(32 downto 0) := muli.acc(32 downto 0);--muli.y(0) & muli.asr18;
187
         if rsigned = '1' then acc2(39 downto 32) := (others => mreg(31));
188
         else acc2(39 downto 32) := (others => '0'); end if;
189
      end if;
190
       acc1(39 downto 33) := muli.acc(39 downto 33);--muli.y(7 downto 1);
191
    end if;
192
 
193
 
194
-- accumulator for iterative multiplication (and MAC)
195
-- pragma translate_off
196
    if not (is_x(acc1 & acc2)) then
197
-- pragma translate_on
198
    case MULTIPLIER is
199
    when m16x16 =>
200
      if MACEN then
201
        acc(39 downto 0) := acc1(39 downto 0) + acc2(39 downto 0);
202
      else
203
        acc(32 downto 0) := acc1(32 downto 0) + acc2(32 downto 0);
204
      end if;
205
    when m32x8 =>
206
      acc(40 downto 0) := acc1(40 downto 0) + acc2(40 downto 0);
207
    when m32x16 =>
208
      acc(48 downto 0) := acc1(48 downto 0) + acc2(48 downto 0);
209
    when m32x32 =>
210
      v.acc(31 downto 0) := prod(63 downto 32);
211
    when others => null;
212
    end case;
213
-- pragma translate_off
214
    end if;
215
-- pragma translate_on
216
 
217
-- save intermediate result to accumulator
218
    case rm.state is
219
    when "00" =>
220
      case MULTIPLIER is
221
      when m16x16 =>
222
        if MULPIPE and (rm.ready = '1' ) then
223
          v.acc(48 downto 16) := acc(32 downto 0);
224
          if rsigned = '1' then
225
            v.acc(63 downto 49) := (others => acc(32));
226
          end if;
227
        else
228
          v.acc(63 downto 32) := acc(31 downto 0);
229
        end if;
230
      when m32x8  => v.acc(63 downto 24) := acc(39 downto 0);
231
      when m32x16 => v.acc(63 downto 16) := acc(47 downto 0);
232
      when others => null;
233
      end case;
234
    when "01" =>
235
      case MULTIPLIER is
236
      when m16x16 =>
237
        if MULPIPE then v.acc := (others => '0');
238
        else v.acc := CZero(31 downto 0) & mreg(31 downto 0); end if;
239
      when m32x8 =>
240
        v.acc := CZero(23 downto 0) & mreg(39 downto 0);
241
        if muli.signed = '1' then v.acc(48 downto 40) := (others => acc(40)); end if;
242
      when m32x16 =>
243
        v.acc := CZero(15 downto 0) & mreg(47 downto 0); v.ready := '1';
244
        if muli.signed = '1' then v.acc(63 downto 48) := (others => acc(48)); end if;
245
      when others => null;
246
      end case;
247
      v.nready := '1';
248
    when "10" =>
249
      case MULTIPLIER is
250
      when m16x16 =>
251
        if MULPIPE then
252
          v.acc := CZero(31 downto 0) & mreg(31 downto 0);
253
        else
254
          v.acc(48 downto 16) := acc(32 downto 0);
255
        end if;
256
      when m32x8 => v.acc(48 downto 8) := acc(40 downto 0);
257
        if muli.signed = '1' then v.acc(56 downto 49) := (others => acc(40)); end if;
258
      when others => null;
259
      end case;
260
    when others =>
261
      case MULTIPLIER is
262
      when m16x16 =>
263
        if MULPIPE then
264
          v.acc(48 downto 16) := acc(32 downto 0);
265
        else
266
          v.acc(48 downto 16) := acc(32 downto 0);
267
          if rsigned = '1' then
268
            v.acc(63 downto 49) := (others => acc(32));
269
          end if;
270
        end if;
271
        v.ready := '1';
272
      when m32x8 => v.acc(56 downto 16) := acc(40 downto 0); v.ready := '1';
273
        if muli.signed = '1' then v.acc(63 downto 57) := (others => acc(40)); end if;
274
      when others => null;
275
      end case;
276
    end case;
277
 
278
-- drive result and condition codes
279
    if (muli.flush = '1') then v.state := "00"; v.start := '0'; end if;
280
    if (rst = '0') then v.nready := '0'; v.ready := '0'; v.state := "00"; v.start := '0'; end if;
281
    rmin <= v; ma <= mop1; mb <= mop2; mmin <= w;
282
    if MULPIPE then mulo.ready <= rm.ready; mulo.nready <= rm.nready;
283
    else mulo.ready <= v.ready; mulo.nready <= v.nready;   end if;
284
 
285
    case MULTIPLIER is
286
    when m16x16 =>
287
      if rm.acc(31 downto 0) = CZero(31 downto 0) then zero := '1'; end if;
288
      if MACEN and (rmac = '1') then
289
        mulo.result(39 downto 0) <= acc(39 downto 0);
290
        if rsigned = '1' then
291
          mulo.result(63 downto 40) <= (others => acc(39));
292
        else
293
          mulo.result(63 downto 40) <= (others => '0');
294
        end if;
295
      else
296
        mulo.result(39 downto 0) <= v.acc(39 downto 32) & rm.acc(31 downto 0);
297
        mulo.result(63 downto 40) <= v.acc(63 downto 40);
298
      end if;
299
      mulo.icc <= rm.acc(31) & zero & "00";
300
    when m32x8 =>
301
      if (rm.acc(23 downto 0) = CZero(23 downto 0)) and
302
         (v.acc(31 downto 24) = CZero(7 downto 0))
303
      then zero := '1'; end if;
304
      mulo.result <= v.acc(63 downto 24) & rm.acc(23 downto 0);
305
      mulo.icc <= v.acc(31) & zero & "00";
306
    when m32x16 =>
307
      if (rm.acc(15 downto 0) = CZero(15 downto 0)) and
308
         (v.acc(31 downto 16) = CZero(15 downto 0))
309
      then zero := '1'; end if;
310
      mulo.result <= v.acc(63 downto 16) & rm.acc(15 downto 0);
311
      mulo.icc <= v.acc(31) & zero & "00";
312
    when m32x32 =>
313
--      mulo.result <= rm.acc(31 downto 0) & prod(31 downto 0);
314
      mulo.result <= prod(63 downto 0);
315
      mulo.icc(1 downto 0) <= "00";
316
      if prod(31 downto 0) = zero32 then mulo.icc(2) <= '1' ;
317
      else mulo.icc(2) <= '0'; end if;
318
      mulo.icc(3) <= prod(31);
319
    when others => null;
320
      mulo.result <= (others => '-');
321
      mulo.icc <= (others => '-');
322
    end case;
323
 
324
  end process;
325
 
326
  xm1616 : if MULTIPLIER = m16x16 generate
327
    i0 : if (infer = 1) and (pipe = 0) generate
328
      prod(33 downto 0) <= smult (ma(16 downto 0), mb(16 downto 0));
329
    end generate;
330
    i1 : if (infer = 1) and (pipe = 1) generate
331
      reg : process(clk) begin
332
        if rising_edge(clk) then
333
          if (holdn = '1') then
334
            prod(33 downto 0) <= smult (ma(16 downto 0), mb(16 downto 0));
335
          end if;
336
        end if;
337
      end process;
338
    end generate;
339
    i2 : if infer = 0 generate
340
      m0 : mul_17_17
341
         generic map (pipe)
342
         port map (clk, holdn, ma(16 downto 0), mb(16 downto 0), prod(33 downto 0));
343
 
344
    end generate;
345
    reg : process(clk)
346
    begin
347
      if rising_edge(clk) then
348
        if (holdn = '1') then
349
          mm <= mmin;
350
          mreg(33 downto 0) <= prod(33 downto 0);
351
        end if;
352
      end if;
353
    end process;
354
 
355
  end generate;
356
  xm3208 : if MULTIPLIER = m32x8 generate
357
    i0 : if infer = 1 generate
358
      prod(41 downto 0) <= smult (ma(32 downto 0), mb(8 downto 0));
359
    end generate;
360
    i1 : if infer = 0 generate
361
      m0 : mul_33_9
362
         port map (ma(32 downto 0), mb(8 downto 0), prod(41 downto 0));
363
    end generate;
364
 
365
    reg : process(clk)
366
    begin
367
      if rising_edge(clk) then
368
        if (holdn = '1') then
369
          mreg(41 downto 0) <= prod(41 downto 0);
370
        end if;
371
      end if;
372
    end process;
373
 
374
  end generate;
375
 
376
  xm3216 : if MULTIPLIER = m32x16 generate
377
    i1 : if infer = 1 generate
378
      prod(49 downto 0) <= smult (ma(32 downto 0), mb(16 downto 0));
379
    end generate;
380
    i2 : if infer = 0 generate
381
      m0 : mul_33_17
382
         port map (ma(32 downto 0), mb(16 downto 0), prod(49 downto 0));
383
    end generate;
384
 
385
    reg : process(clk)
386
    begin
387
      if rising_edge(clk) then
388
        if (holdn = '1') then
389
          mreg(49 downto 0) <= prod(49 downto 0);
390
        end if;
391
      end if;
392
    end process;
393
 
394
  end generate;
395
 
396
  xm3232 : if MULTIPLIER = m32x32 generate
397
    i1 : if (infer = 1) and (pipe = 1) generate
398
      reg : process(clk) begin
399
        if rising_edge(clk) then
400
          if (holdn = '1') then
401
            prod(65 downto 0) <= smult (ma(32 downto 0), mb(32 downto 0));
402
          end if;
403
        end if;
404
      end process;
405
    end generate;
406
 
407
    i0 : if (infer = 1) and (pipe = 0) generate
408
      prod(65 downto 0) <= smult (ma(32 downto 0), mb(32 downto 0));
409
    end generate;
410
    i2 : if infer = 0 generate
411
      m0 : mul_33_33 generic map (pipe)
412
         port map (clk, holdn, ma(32 downto 0), mb(32 downto 0), prod(65 downto 0));
413
    end generate;
414
  end generate;
415
 
416
 
417
  reg : process(clk)
418
  begin
419
    if rising_edge(clk) then
420
      if (holdn = '1') then rm <= rmin; end if;
421
      if (rst = '0') then -- needed to preserve sync resets in synopsys ...
422
        rm.nready <= '0'; rm.ready <= '0'; rm.state <= "00"; rm.start <= '0';
423
      end if;
424
    end if;
425
  end process;
426
 
427
end;
428
 

powered by: WebSVN 2.1.0

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