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

Subversion Repositories rv01_riscv_core

[/] [rv01_riscv_core/] [trunk/] [VHDL/] [RV01_mulu.vhd] - Blame information for rev 2

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 madsilicon
-----------------------------------------------------------------
2
--                                                             --
3
-----------------------------------------------------------------
4
--                                                             --
5
-- Copyright (C) 2015 Stefano Tonello                          --
6
--                                                             --
7
-- This source file may be used and distributed without        --
8
-- restriction provided that this copyright statement is not   --
9
-- removed from the file and that any derivative work contains --
10
-- the original copyright notice and the associated disclaimer.--
11
--                                                             --
12
-- THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY         --
13
-- EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED   --
14
-- TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS   --
15
-- FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR      --
16
-- OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,         --
17
-- INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES    --
18
-- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE   --
19
-- GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR        --
20
-- BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF  --
21
-- LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT  --
22
-- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT  --
23
-- OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE         --
24
-- POSSIBILITY OF SUCH DAMAGE.                                 --
25
--                                                             --
26
-----------------------------------------------------------------
27
 
28
---------------------------------------------------------------
29
-- RV01 4:2 compressor
30
---------------------------------------------------------------
31
 
32
library IEEE;
33
use IEEE.std_logic_1164.all;
34
use IEEE.numeric_std.all;
35
 
36
entity RV01_COMP42 is
37
  port(
38
    A_i : in std_logic_vector(4-1 downto 0);
39
    CI_i : in std_logic;
40
 
41
    S_o : out std_logic;
42
    C_o : out std_logic;
43
    CO_o : out std_logic
44
  );
45
end RV01_COMP42;
46
 
47
architecture ARC of RV01_COMP42 is
48
 
49
  signal X01,X23,X03 : std_logic;
50
 
51
begin
52
 
53
  X01 <= A_i(0) xor A_i(1);
54
  X23 <= A_i(2) xor A_i(3);
55
  X03 <= X01 xor X23;
56
  S_o <= X03 xor CI_i;
57
  C_o <= CI_i when (X03 = '1') else A_i(3);
58
  CO_o <= A_i(2) when (X01 = '1') else A_i(0);
59
 
60
end ARC;
61
 
62
---------------------------------------------------------------
63
-- RV01 multiplier (signed/unsigned/mix-signed)
64
---------------------------------------------------------------
65
 
66
library IEEE;
67
use IEEE.std_logic_1164.all;
68
use IEEE.numeric_std.all;
69
 
70
library WORK;
71
use WORK.RV01_CONSTS_PKG.all;
72
use WORK.RV01_TYPES_PKG.all;
73
use WORK.RV01_FUNCS_PKG.all;
74
use WORK.RV01_ARITH_PKG.all;
75
 
76
entity RV01_MULTIPLIER is
77
  generic(
78
    LEN : natural := 32
79
  );
80
  port(
81
    CLK_i : in std_logic;
82
    MD_i : in signed(LEN-1 downto 0);
83
    MR_i : in signed(LEN-1 downto 0);
84
    OP_i : in std_logic_vector(2-1 downto 0);
85
 
86
    PROD_o : out signed(LEN*2-1 downto 0)
87
  );
88
end RV01_MULTIPLIER;
89
 
90
architecture ARC of RV01_MULTIPLIER is
91
 
92
  constant LEN32 : natural := (LEN/2)*3;
93
  subtype ROW_T is std_logic_vector(LEN32-1 downto 0);
94
  subtype COL_T is std_logic_vector(4-1 downto 0);
95
  type ROW_MTRX_T is array(4-1 downto 0) of ROW_T;
96
  type COL_MTRX_T is array(LEN32-1 downto 0) of COL_T;
97
 
98
  component RV01_COMP42 is
99
    port(
100
      A_i : in std_logic_vector(4-1 downto 0);
101
      CI_i : in std_logic;
102
 
103
      S_o : out std_logic;
104
      C_o : out std_logic;
105
      CO_o : out std_logic
106
    );
107
  end component;
108
 
109
  component RV01_ADDER_F is
110
    generic(
111
      LEN1 : integer := 16;
112
      LEN2 : integer := 16
113
    );
114
    port(
115
      OPA_i : in signed(LEN1+LEN2-1 downto 0);
116
      OPB_i : in signed(LEN1+LEN2-1 downto 0);
117
      CI_i : in std_logic;
118
 
119
      SUM_o : out signed(LEN1+LEN2-1 downto 0)
120
    );
121
  end component;
122
 
123
  signal MDU,MRU,CF,CF_q : unsigned(LEN-1 downto 0);
124
  signal PRODU : unsigned(LEN*2 downto 0);
125
  signal PRODU0,PRODU0_q : unsigned(LEN-1 downto 0);
126
  signal PRODU1,PRODU1_q : unsigned(LEN-1 downto 0);
127
  signal PRODU2,PRODU2_q : unsigned(LEN-1 downto 0);
128
  signal PRODU3,PRODU3_q : unsigned(LEN-1 downto 0);
129
  signal CM : COL_MTRX_T;
130
  signal C,S,CY : std_logic_vector(LEN32 downto 0);
131
  signal PROD : signed(LEN*2-1 downto 0);
132
  signal PROD_CHK : unsigned(LEN*2-1 downto 0);
133
  signal ZERO : std_logic := '0';
134
 
135
  -- Prevent merging of pipeline registers into
136
  -- DSP block
137
  attribute KEEP : string;
138
  attribute KEEP of PRODU0_q  : signal is "true";
139
  attribute KEEP of PRODU1_q  : signal is "true";
140
  attribute KEEP of PRODU2_q  : signal is "true";
141
  attribute KEEP of PRODU3_q  : signal is "true";
142
 
143
begin
144
 
145
  -- convert multiplicand to unsigned
146
  MDU <= to_unsigned(MD_i);
147
 
148
  -- convert multiplier to unsigned
149
  MRU <= to_unsigned(MR_i);
150
 
151
  -- calculate partial products (each one is LEN bits long)
152
  PRODU0 <= MDU(LEN/2-1 downto 0) * MRU(LEN/2-1 downto 0);
153
  PRODU1 <= MDU(LEN-1 downto LEN/2) * MRU(LEN/2-1 downto 0);
154
  PRODU2 <= MDU(LEN/2-1 downto 0) * MRU(LEN-1 downto LEN/2);
155
  PRODU3 <= MDU(LEN-1 downto LEN/2) * MRU(LEN-1 downto LEN/2);
156
 
157
  -- pipeline registers
158
  process(CLK_i)
159
  begin
160
    if(CLK_i = '1' and CLK_i'event) then
161
      PRODU0_q <= PRODU0;
162
      PRODU1_q <= PRODU1;
163
      PRODU2_q <= PRODU2;
164
      PRODU3_q <= PRODU3;
165
    end if;
166
  end process;
167
 
168
  -- Partial products and correction factor must be summed up
169
  -- in the following fashion (each digit is a byte):
170
  --
171
  --     0000 +
172
  --   1111   +
173
  --   2222   +
174
  -- 3333     +
175
  -- FFFF
176
  -- --------
177
  -- PPPPPPPP
178
 
179
  -- The LS LEN/2 bits of the result are available without any
180
  -- summation (they're provided by PRODU0 LS LEN/2 bits).
181
  -- The remaining LEN*3/2 bits of the results require the
182
  -- summation of up to 5 terms, which can be reduced to 4 by
183
  -- merging PRODU3 and PRODU0, which don't have overlapping
184
  -- bits.
185
  -- Summation of the 4 terms of above is performed using a
186
  -- 4:2 compressor array followed by a carry propagate adder.
187
 
188
  process(PRODU0_q,PRODU1_q,PRODU2_q,PRODU3_q,CF_q)
189
    variable RM : ROW_MTRX_T;
190
    constant ZERO : std_logic_vector(LEN/2-1 downto 0) := (others => '0');
191
    variable TMP_R : ROW_T;
192
    variable TMP_C : COL_T;
193
  begin
194
 
195
    RM(0) := ZERO & to_std_logic_vector(PRODU1_q);
196
    RM(1) := ZERO & to_std_logic_vector(PRODU2_q);
197
    RM(2) := to_std_logic_vector(PRODU3_q) &
198
      to_std_logic_vector(PRODU0_q(LEN-1 downto LEN/2));
199
    RM(3) := to_std_logic_vector(CF_q) & ZERO;
200
 
201
    -- transpose RM to generate CM
202
 
203
    for k in 0 to LEN32-1 loop
204
      TMP_R := RM(0);
205
      TMP_C(0) := TMP_R(k);
206
      TMP_R := RM(1);
207
      TMP_C(1) := TMP_R(k);
208
      TMP_R := RM(2);
209
      TMP_C(2) := TMP_R(k);
210
      TMP_R := RM(3);
211
      TMP_C(3) := TMP_R(k);
212
      CM(k) <= TMP_C;
213
    end loop;
214
 
215
  end process;
216
 
217
  -- tree-adder (composed of 4:2 compressors)
218
 
219
  S(LEN32) <= '0';
220
  C(0) <= '0';
221
  CY(0) <= '0';
222
 
223
  G0: for k in 0 to LEN32-1 generate
224
 
225
  UCOMP: RV01_COMP42
226
    port map(
227
      A_i => CM(k),
228
      CI_i => CY(k),
229
 
230
      S_o => S(k),
231
      C_o => C(k+1),
232
      CO_o => CY(k+1)
233
    );
234
 
235
  end generate;
236
 
237
  --PRODU(LEN/2-1 downto 0) <= PRODU0(LEN/2-1 downto 0);
238
 
239
  -- carry-propagate adder
240
  --PRODU(LEN*2 downto LEN/2) <= to_unsigned(S) + to_unsigned(C);
241
 
242
  PROD(LEN/2-1 downto 0) <= to_signed(PRODU0_q(LEN/2-1 downto 0));
243
 
244
  U_ADDF : RV01_ADDER_F
245
    generic map(
246
      LEN1 => LEN32/2,
247
      LEN2 => LEN32/2
248
    )
249
    port map(
250
      OPA_i => to_signed(S(LEN32-1 downto 0)),
251
      OPB_i => to_signed(C(LEN32-1 downto 0)),
252
      CI_i => ZERO,
253
      SUM_o => PROD(LEN*2-1 downto LEN/2)
254
    );
255
 
256
  -- select correcting factor for signed and mixed-sign 
257
  -- multiplication
258
 
259
  process(OP_i,MDU,MRU)
260
    variable SD,SR : std_logic;
261
    variable NMDU,NMRU : unsigned(LEN-1 downto 0);
262
  begin
263
    -- multiplicand  sign
264
    SD := MDU(LEN-1);
265
 
266
    -- multiplier sign
267
    SR := MRU(LEN-1);
268
 
269
    -- get MDU 2's complement
270
    NMDU := not(MDU)+1;
271
 
272
    -- get MRU 2's complement
273
    NMRU := not(MRU)+1;
274
 
275
    if(OP_i = "00") then
276
      -- signed x signed
277
      if(SD = '1' and SR = '1') then
278
        CF <= NMDU + NMRU;
279
      elsif(SD = '1') then
280
        CF <= NMRU;
281
      elsif(SR = '1') then
282
        CF <= NMDU;
283
      else
284
        CF <= to_unsigned(0,LEN);
285
      end if;
286
    elsif(OP_i = "01") then
287
      -- signed x unsigned
288
      if(SD = '1') then
289
        CF <= NMRU;
290
      else
291
        CF <= to_unsigned(0,LEN);
292
      end if;
293
    else
294
      -- unsigned x unsigned
295
      CF <= to_unsigned(0,LEN);
296
    end if;
297
  end process;
298
 
299
  -- pipeline registers
300
  process(CLK_i)
301
  begin
302
    if(CLK_i = '1' and CLK_i'event) then
303
      CF_q <= CF;
304
    end if;
305
  end process;
306
 
307
  -- output
308
  --PROD_o <= to_signed(PRODU(LEN*2-1 downto 0));
309
  PROD_o <= PROD;
310
 
311
  -- synthesis translate_off
312
 
313
  PROD_CHK <=
314
   --((X"0000" & PRODU0_q) + (X"00" & PRODU1_q & X"00")) +
315
   --((X"00" & PRODU2_q & X"00") + (PRODU3_q & X"0000")) +
316
   --(CF_q & X"0000"); 
317
   (to_unsigned(0,LEN) & PRODU0_q) +
318
   (to_unsigned(0,LEN/2) & PRODU1_q & to_unsigned(0,LEN/2)) +
319
   (to_unsigned(0,LEN/2) & PRODU2_q & to_unsigned(0,LEN/2)) +
320
   (PRODU3_q & to_unsigned(0,LEN)) +
321
   (CF_q & to_unsigned(0,LEN));
322
 
323
  -- synthesis translate_on
324
 
325
end ARC;
326
 
327
---------------------------------------------------------------
328
-- RV01 Two-cycle multiply unit
329
---------------------------------------------------------------
330
 
331
library IEEE;
332
use IEEE.std_logic_1164.all;
333
use IEEE.numeric_std.all;
334
 
335
library WORK;
336
use WORK.RV01_CONSTS_PKG.all;
337
use WORK.RV01_TYPES_PKG.all;
338
use WORK.RV01_ARITH_PKG.all;
339
use WORK.RV01_OP_PKG.all;
340
 
341
entity RV01_MULU is
342
  port(
343
    CLK_i : in std_logic;
344
    CTRL_i : in MUL_CTRL;
345
    OPA_i : in SDWORD_T;
346
    OPB_i : in SDWORD_T;
347
 
348
    RES_o : out SDWORD_T
349
  );
350
end RV01_MULU;
351
 
352
architecture ARC of RV01_MULU is
353
 
354
  constant ZERO32 : SDWORD_T := (others => '0');
355
 
356
  component RV01_ADDER is
357
    generic(
358
      WIDTH : integer := 16
359
    );
360
    port(
361
      OPA_i : in signed(WIDTH-1 downto 0);
362
      OPB_i : in signed(WIDTH-1 downto 0);
363
      CI_i : in std_logic;
364
 
365
      SUM_o : out signed(WIDTH-1 downto 0)
366
    );
367
  end component;
368
 
369
  component RV01_ADDER_F is
370
    generic(
371
      LEN1 : integer := 16;
372
      LEN2 : integer := 16
373
    );
374
    port(
375
      OPA_i : in signed(LEN1+LEN2-1 downto 0);
376
      OPB_i : in signed(LEN1+LEN2-1 downto 0);
377
      CI_i : in std_logic;
378
 
379
      SUM_o : out signed(LEN1+LEN2-1 downto 0)
380
    );
381
  end component;
382
 
383
  component RV01_MULTIPLIER is
384
    generic(
385
      LEN : natural := 32
386
    );
387
    port(
388
      CLK_i : in std_logic;
389
      MD_i : in signed(LEN-1 downto 0);
390
      MR_i : in signed(LEN-1 downto 0);
391
      OP_i : in std_logic_vector(2-1 downto 0);
392
 
393
      PROD_o : out signed(LEN*2-1 downto 0)
394
    );
395
  end component;
396
 
397
  signal CTRL_q : MUL_CTRL;
398
  signal PROD : signed(LDLEN-1 downto 0);
399
  signal OP : std_logic_vector(2-1 downto 0);
400
  signal RES : signed(SDLEN-1 downto 0);
401
 
402
begin
403
 
404
  ------------------------------------
405
  -- Notes
406
  ------------------------------------
407
 
408
  -- This units performs three types of multiplication:
409
  -- 1) MUL/MULH signed(OPA_i)   * signed(OPB_i)
410
  -- 2) MULHU    unsigned(OPA_i) * unsigned(OPB_i) 
411
  -- 3) MULHSU   signed(OPA_i)   * unsigned(OPB_i)
412
 
413
  -- -n is rapresented in 2's complement as 2^32-n
414
  -- So, -n*m => (2^32-n)*m = 2^32*m - n*m => CF = -2^32*m
415
  -- So, -n*-m => (2^32-n)*(2^32-n) = 2^64 - 2^32*(m+n) + n*m => CF = 2^32*(m+n)
416
 
417
  process(CTRL_i)
418
  begin
419
    case CTRL_i is
420
      when MC_MULH => OP <= "00"; -- "01";
421
      when MC_MULHSU => OP <= "01"; --"10";
422
      when others => OP <= "10"; --"00";
423
    end case;
424
  end process;
425
 
426
  U_MUL : RV01_MULTIPLIER
427
    generic map(
428
      LEN => SDLEN
429
    )
430
    port map(
431
      CLK_i => CLK_i,
432
      MD_i => OPA_i,
433
      MR_i => OPB_i,
434
      OP_i => OP,
435
 
436
      PROD_o => PROD
437
    );
438
 
439
  -- pipeline registers
440
  process(CLK_i)
441
  begin
442
    if(CLK_i = '1' and CLK_i'event) then
443
      CTRL_q <= CTRL_i;
444
    end if;
445
  end process;
446
 
447
  RES <= PROD(SDLEN-1 downto 0) when (CTRL_q = MC_MUL)
448
    else PROD(LDLEN-1 downto SDLEN);
449
 
450
  RES_o <= RES;
451
 
452
end ARC;

powered by: WebSVN 2.1.0

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