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

Subversion Repositories core_arm

[/] [core_arm/] [trunk/] [vhdl/] [sparc/] [mul.vhd] - Blame information for rev 5

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

Line No. Rev Author Line
1 2 tarookumic
 
2
 
3
 
4
 
5
----------------------------------------------------------------------------
6
--  This file is a part of the LEON VHDL model
7
--  Copyright (C) 1999  European Space Agency (ESA)
8
--
9
--  This library is free software; you can redistribute it and/or
10
--  modify it under the terms of the GNU Lesser General Public
11
--  License as published by the Free Software Foundation; either
12
--  version 2 of the License, or (at your option) any later version.
13
--
14
--  See the file COPYING.LGPL for the full details of the license.
15
 
16
 
17
-----------------------------------------------------------------------------
18
-- Entity:      mul
19
-- File:        mul.vhd
20
-- Author:      Jiri Gaisler - Gaisler Research
21
-- Description: This unit implemets integer multiply and optionally the
22
--              UMUL/SMUL/UMAC/SMAC instructions.
23
------------------------------------------------------------------------------
24
 
25
library IEEE;
26
use IEEE.std_logic_1164.all;
27
use IEEE.std_logic_unsigned."+";
28
use work.leon_target.all;
29
use work.leon_config.all;
30
use work.leon_iface.all;
31
use work.tech_map.all;
32
 
33
entity mul is
34
port (
35
    rst     : in  std_logic;
36
    clk     : in  clk_type;
37
    holdn   : in  std_logic;
38
    muli    : in  mul_in_type;
39
    mulo    : out mul_out_type
40
);
41
end;
42
 
43
architecture rtl of mul is
44
 
45
type mul_regtype is record
46
  acc    : std_logic_vector(63 downto 0);
47
  state  : std_logic_vector(1 downto 0);
48
  start  : std_logic;
49
  ready  : std_logic;
50
end record;
51
 
52
type mac_regtype is record
53
  mac    : std_logic;
54
  signed : std_logic;
55
end record;
56
 
57
signal rm, rmin : mul_regtype;
58
signal mm, mmin : mac_regtype;
59
signal ma, mb : std_logic_vector(32 downto 0);
60
signal prod : std_logic_vector(65 downto 0);
61
signal mreg : std_logic_vector(49 downto 0);
62
 
63
begin
64
 
65
  mulcomb : process(rst, rm, muli, mreg, prod, mm)
66
  variable mop1, mop2 : std_logic_vector(32 downto 0);
67
  variable acc, acc1, acc2 : std_logic_vector(48 downto 0);
68
  variable zero : std_logic;
69
  variable v : mul_regtype;
70
  variable w : mac_regtype;
71
  constant CZero: std_logic_vector(47 downto 0) := "000000000000000000000000000000000000000000000000";
72
  begin
73
 
74
    v := rm; w := mm; v.start := muli.start; v.ready := '0';
75
    mop1 := muli.op1; mop2 := muli.op2;
76
    acc1 := (others => '0'); acc2 := (others => '0');
77
    w.mac := muli.mac; w.signed := muli.signed; zero := '0';
78
 
79
-- select input 2 to accumulator
80
    case MULTIPLIER is
81
    when m16x16 =>
82
      acc2(32 downto 0) := mreg(32 downto 0);
83
    when m32x8  =>
84
      acc2(40 downto 0) := mreg(40 downto 0);
85
    when m32x16 =>
86
      acc2(48 downto 0) := mreg(48 downto 0);
87
    when others => null;
88
    end case;
89
 
90
-- state machine + inputs to multiplier and accumulator input 1
91
    case rm.state is
92
    when "00" =>
93
      case MULTIPLIER is
94
      when m16x16 =>
95
        mop1(16 downto 0) := '0' & muli.op1(15 downto 0);
96
        mop2(16 downto 0) := '0' & muli.op2(15 downto 0);
97
        if MULPIPE and (rm.ready = '1' ) then
98
          acc1(32 downto 0) := rm.acc(48 downto 16);
99
        else acc1(32 downto 0) := '0' & rm.acc(63 downto 32); end if;
100
      when m32x8 =>
101
        mop1 := muli.op1;
102
        mop2(8 downto 0) := '0' & muli.op2(7 downto 0);
103
        acc1(40 downto 0) := '0' & rm.acc(63 downto 24);
104
      when m32x16 =>
105
        mop1 := muli.op1;
106
        mop2(16 downto 0) := '0' & muli.op2(15 downto 0);
107
        acc1(48 downto 0) := '0' & rm.acc(63 downto 16);
108
      when others => null;
109
      end case;
110
      if (rm.start = '1') then v.state := "01"; end if;
111
    when "01" =>
112
      case MULTIPLIER is
113
      when m16x16 =>
114
        mop1(16 downto 0) := muli.op1(32 downto 16);
115
        mop2(16 downto 0) := '0' & muli.op2(15 downto 0);
116
        if MULPIPE then acc1(32 downto 0) := '0' & rm.acc(63 downto 32); end if;
117
        v.state := "10";
118
      when m32x8 =>
119
        mop1 := muli.op1; mop2(8 downto 0) := '0' & muli.op2(15 downto 8);
120
        v.state := "10";
121
      when m32x16 =>
122
        mop1 := muli.op1; mop2(16 downto 0) := muli.op2(32 downto 16);
123
        v.state := "00";
124
      when others => null;
125
      end case;
126
    when "10" =>
127
      case MULTIPLIER is
128
      when m16x16 =>
129
        mop1(16 downto 0) := '0' & muli.op1(15 downto 0);
130
        mop2(16 downto 0) := muli.op2(32 downto 16);
131
        if MULPIPE then acc1 := (others => '0'); acc2 := (others => '0');
132
        else acc1(32 downto 0) := rm.acc(48 downto 16); end if;
133
        v.state := "11";
134
      when m32x8 =>
135
        mop1 := muli.op1; mop2(8 downto 0) := '0' & muli.op2(23 downto 16);
136
        acc1(40 downto 0) := rm.acc(48 downto 8);
137
        v.state := "11";
138
      when others => null;
139
      end case;
140
    when others =>
141
      case MULTIPLIER is
142
      when m16x16 =>
143
        mop1(16 downto 0) := muli.op1(32 downto 16);
144
        mop2(16 downto 0) := muli.op2(32 downto 16);
145
        if MULPIPE then acc1(32 downto 0) := rm.acc(48 downto 16);
146
        else acc1(32 downto 0) := rm.acc(48 downto 16); end if;
147
        v.state := "00";
148
      when m32x8 =>
149
        mop1 := muli.op1; mop2(8 downto 0) := muli.op2(32 downto 24);
150
        acc1(40 downto 0) := rm.acc(56 downto 16);
151
        v.state := "00";
152
      when others => null;
153
      end case;
154
    end case;
155
 
156
-- optional UMAC/SMAC support
157
 
158
    if MACEN then
159
      if ((muli.mac and muli.signed) = '1') then
160
        mop1(16) := muli.op1(15); mop2(16) := muli.op2(15);
161
      end if;
162
      if mm.mac = '1' then
163
         acc1(32 downto 0) := muli.y(0) & muli.asr18;
164
         if mm.signed = '1' then acc2(39 downto 32) := (others => mreg(31));
165
         else acc2(39 downto 32) := (others => '0'); end if;
166
      end if;
167
       acc1(39 downto 33) := muli.y(7 downto 1);
168
    end if;
169
 
170
 
171
-- accumulator for iterative multiplication (and MAC)
172
-- pragma translate_off
173
    if not (is_x(acc1 & acc2)) then
174
-- pragma translate_on
175
    case MULTIPLIER is
176
    when m16x16 =>
177
      if MACEN then
178
        acc(39 downto 0) := acc1(39 downto 0) + acc2(39 downto 0);
179
      else
180
        acc(32 downto 0) := acc1(32 downto 0) + acc2(32 downto 0);
181
      end if;
182
    when m32x8 =>
183
      acc(40 downto 0) := acc1(40 downto 0) + acc2(40 downto 0);
184
    when m32x16 =>
185
      acc(48 downto 0) := acc1(48 downto 0) + acc2(48 downto 0);
186
    when m32x32 =>
187
      v.acc(31 downto 0) := prod(63 downto 32);
188
    when others => null;
189
    end case;
190
-- pragma translate_off
191
    end if;
192
-- pragma translate_on
193
 
194
-- save intermediate result to accumulator
195
    case rm.state is
196
    when "00" =>
197
      case MULTIPLIER is
198
      when m16x16 =>
199
        if MULPIPE and (rm.ready = '1' ) then
200
          v.acc(48 downto 16) := acc(32 downto 0);
201
          if muli.signed = '1' then
202
            v.acc(63 downto 49) := (others => acc(32));
203
          end if;
204
        else
205
          v.acc(63 downto 32) := acc(31 downto 0);
206
        end if;
207
      when m32x8  => v.acc(63 downto 24) := acc(39 downto 0);
208
      when m32x16 => v.acc(63 downto 16) := acc(47 downto 0);
209
      when others => null;
210
      end case;
211
    when "01" =>
212
      case MULTIPLIER is
213
      when m16x16 =>
214
        if MULPIPE then v.acc := (others => '0');
215
        else v.acc := CZero(31 downto 0) & mreg(31 downto 0); end if;
216
      when m32x8 =>
217
        v.acc := CZero(23 downto 0) & mreg(39 downto 0);
218
        if muli.signed = '1' then v.acc(48 downto 40) := (others => acc(40)); end if;
219
      when m32x16 =>
220
        v.acc := CZero(15 downto 0) & mreg(47 downto 0); v.ready := '1';
221
        if muli.signed = '1' then v.acc(63 downto 48) := (others => acc(48)); end if;
222
      when others => null;
223
      end case;
224
    when "10" =>
225
      case MULTIPLIER is
226
      when m16x16 =>
227
        if MULPIPE then
228
          v.acc := CZero(31 downto 0) & mreg(31 downto 0);
229
        else
230
          v.acc(48 downto 16) := acc(32 downto 0);
231
        end if;
232
      when m32x8 => v.acc(48 downto 8) := acc(40 downto 0);
233
        if muli.signed = '1' then v.acc(56 downto 49) := (others => acc(40)); end if;
234
      when others => null;
235
      end case;
236
    when others =>
237
      case MULTIPLIER is
238
      when m16x16 =>
239
        if MULPIPE then
240
          v.acc(48 downto 16) := acc(32 downto 0);
241
        else
242
          v.acc(48 downto 16) := acc(32 downto 0);
243
          if muli.signed = '1' then
244
            v.acc(63 downto 49) := (others => acc(32));
245
          end if;
246
        end if;
247
        v.ready := '1';
248
      when m32x8 => v.acc(56 downto 16) := acc(40 downto 0); v.ready := '1';
249
        if muli.signed = '1' then v.acc(63 downto 57) := (others => acc(40)); end if;
250
      when others => null;
251
      end case;
252
    end case;
253
 
254
-- drive result and condition codes
255
    if (rst = '0') or (muli.flush = '1') then v.state := "00"; v.start := '0'; end if;
256
    rmin <= v; ma <= mop1; mb <= mop2; mmin <= w;
257
    if MULPIPE then mulo.ready <= rm.ready; else mulo.ready <= v.ready; end if;
258
 
259
    case MULTIPLIER is
260
    when m16x16 =>
261
      if rm.acc(31 downto 0) = CZero(31 downto 0) then zero := '1'; end if;
262
      if MACEN and (mm.mac = '1') then
263
        mulo.result(39 downto 0) <= acc(39 downto 0);
264
        if mm.signed = '1' then
265
          mulo.result(63 downto 40) <= (others => acc(39));
266
        else
267
          mulo.result(63 downto 40) <= (others => '0');
268
        end if;
269
      else
270
        mulo.result(39 downto 0) <= v.acc(39 downto 32) & rm.acc(31 downto 0);
271
        mulo.result(63 downto 40) <= v.acc(63 downto 40);
272
      end if;
273
      mulo.icc <= rm.acc(31) & zero & "00";
274
    when m32x8 =>
275
      if (rm.acc(23 downto 0) = CZero(23 downto 0)) and
276
         (v.acc(31 downto 24) = CZero(7 downto 0))
277
      then zero := '1'; end if;
278
      mulo.result <= v.acc(63 downto 24) & rm.acc(23 downto 0);
279
      mulo.icc <= v.acc(31) & zero & "00";
280
    when m32x16 =>
281
      if (rm.acc(15 downto 0) = CZero(15 downto 0)) and
282
         (v.acc(31 downto 16) = CZero(15 downto 0))
283
      then zero := '1'; end if;
284
      mulo.result <= v.acc(63 downto 16) & rm.acc(15 downto 0);
285
      mulo.icc <= v.acc(31) & zero & "00";
286
    when m32x32 =>
287
      mulo.result <= rm.acc(31 downto 0) & prod(31 downto 0);
288
      mulo.icc <= "0000";       -- icc set in iu.vhd
289
    when others => null;
290
      mulo.result <= (others => '-');
291
      mulo.icc <= (others => '-');
292
    end case;
293
 
294
  end process;
295
 
296
  xm1616 : if MULTIPLIER = m16x16 generate
297
    m0 : hw_smult generic map (17, 17)
298
         port map (clk, holdn, ma(16 downto 0), mb(16 downto 0), prod(33 downto 0));
299
 
300
    reg : process(clk)
301
    begin
302
      if rising_edge(clk) then
303
        if (holdn = '1') then
304
          if MACEN then mm <= mmin; end if;
305
          mreg(33 downto 0) <= prod(33 downto 0);
306
        end if;
307
      end if;
308
    end process;
309
 
310
  end generate;
311
  xm3208 : if MULTIPLIER = m32x8 generate
312
    m0 : hw_smult generic map (33, 9)
313
         port map (clk, holdn, ma(32 downto 0), mb(8 downto 0), prod(41 downto 0));
314
 
315
    reg : process(clk)
316
    begin
317
      if rising_edge(clk) then
318
        if (holdn = '1') then
319
          mreg(41 downto 0) <= prod(41 downto 0);
320
        end if;
321
      end if;
322
    end process;
323
 
324
  end generate;
325
 
326
  xm3216 : if MULTIPLIER = m32x16 generate
327
    m0 : hw_smult generic map (33, 17)
328
         port map (clk, holdn, ma(32 downto 0), mb(16 downto 0), prod(49 downto 0));
329
 
330
    reg : process(clk)
331
    begin
332
      if rising_edge(clk) then
333
        if (holdn = '1') then
334
          mreg(49 downto 0) <= prod(49 downto 0);
335
        end if;
336
      end if;
337
    end process;
338
 
339
  end generate;
340
 
341
  xm3232 : if MULTIPLIER = m32x32 generate
342
    m0 : hw_smult generic map (33, 33)
343
         port map (clk, holdn, ma(32 downto 0), mb(32 downto 0), prod(65 downto 0));
344
  end generate;
345
 
346
 
347
  reg : process(clk)
348
  begin
349
    if rising_edge(clk) then
350
      if (holdn = '1') then rm <= rmin; end if;
351
    end if;
352
  end process;
353
 
354
end;
355
 

powered by: WebSVN 2.1.0

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