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

Subversion Repositories g729a_codec

[/] [g729a_codec/] [trunk/] [VHDL/] [G729A_asip_mulu_pipeb.vhd] - Blame information for rev 2

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

Line No. Rev Author Line
1 2 madsilicon
-----------------------------------------------------------------
2
--                                                             --
3
-----------------------------------------------------------------
4
--                                                             --
5
-- Copyright (C) 2013 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
-- G.729A ASIP Two-cycle multiply unit
30
---------------------------------------------------------------
31
 
32
library IEEE;
33
use IEEE.std_logic_1164.all;
34
use IEEE.numeric_std.all;
35
 
36
library WORK;
37
use WORK.G729A_ASIP_PKG.all;
38
use WORK.G729A_ASIP_BASIC_PKG.all;
39
use WORK.G729A_ASIP_ARITH_PKG.all;
40
use WORK.G729A_ASIP_OP_PKG.all;
41
 
42
entity G729A_ASIP_MULU_PIPEB is
43
  port(
44
    CLK_i : in std_logic;
45
    CTRL_i : in MUL_CTRL;
46
    OPA_i : in LDWORD_T;
47
    OPB_i : in LDWORD_T;
48
 
49
    RES_o : out LDWORD_T;
50
    OVF_o : out std_logic
51
  );
52
end G729A_ASIP_MULU_PIPEB;
53
 
54
architecture ARC of G729A_ASIP_MULU_PIPEB is
55
 
56
  constant ZERO32 : LDWORD_T := hex_to_signed("00000000",LDLEN);
57
 
58
  component G729A_ASIP_ADDER is
59
    generic(
60
      WIDTH : integer := 16
61
    );
62
    port(
63
      OPA_i : in signed(WIDTH-1 downto 0);
64
      OPB_i : in signed(WIDTH-1 downto 0);
65
      CI_i : in std_logic;
66
 
67
      SUM_o : out signed(WIDTH-1 downto 0)
68
    );
69
  end component;
70
 
71
  component G729A_ASIP_ADDER_F is
72
    generic(
73
      LEN1 : integer := 16;
74
      LEN2 : integer := 16
75
    );
76
    port(
77
      OPA_i : in signed(LEN1+LEN2-1 downto 0);
78
      OPB_i : in signed(LEN1+LEN2-1 downto 0);
79
      CI_i : in std_logic;
80
 
81
      SUM_o : out signed(LEN1+LEN2-1 downto 0)
82
    );
83
  end component;
84
 
85
  -- check for overflow in addition/subtraction
86
  function overflow(
87
    SA : std_logic;
88
    SGNA : std_logic;
89
    SGNB : std_logic;
90
    SGNR : std_logic
91
  ) return std_logic is
92
  variable OVF : std_logic;
93
  begin
94
    -- overflow flag
95
    if(SA = '0') then
96
      -- addition
97
      if(SGNR = '1') then
98
        OVF := not(SGNA or SGNB);
99
      else
100
        OVF := (SGNA and SGNB);
101
      end if;
102
    else
103
      -- subtraction
104
      if(SGNR = '1') then
105
        OVF := (not(SGNA) and SGNB);
106
      else
107
        OVF := (SGNA and not(SGNB));
108
      end if;
109
    end if;
110
    return(OVF);
111
  end function;
112
 
113
  function "not"(S : signed) return signed is
114
    variable NOTS : signed(S'high downto S'low);
115
  begin
116
    for k in S'low to S'high loop
117
      NOTS(k) := not(S(k));
118
    end loop;
119
    return(NOTS);
120
  end function;
121
 
122
  signal PROD1,PROD2 : LDWORD_T;
123
  signal MULA_RES : LDWORD_T;
124
  signal MULA_RES_q : LDWORD_T;
125
  signal MULA_OVF : std_logic;
126
  signal MULA_OVF_q : std_logic;
127
  signal LMUL_PROD_q : LDWORD_T;
128
  signal LMUL_RES : LDWORD_T;
129
  signal LMUL_OVF : std_logic;
130
  signal MULR_PROD_q,MULR_SUM1,MULR_SUM2 : LDWORD_T;
131
  signal MULR_RES : LDWORD_T;
132
  signal MULR_OVF : std_logic;
133
  signal M3216_PRODHI,M3216_PRODLO2 : LDWORD_T;
134
  signal M3216_PRODLO1 : SDWORD_T;
135
  signal M3216_PRODHI_q,M3216_PRODLO_q : LDWORD_T;
136
  signal M3216_MUL_OVFHI,M3216_MUL_OVFLO : std_logic;
137
  signal M3216_MUL_OVF_q : std_logic;
138
  signal M3216_SUM,M3216_RES : LDWORD_T;
139
  signal M3216_ADD_OVF,M3216_OVF : std_logic;
140
  signal CTRL_q : MUL_CTRL;
141
 
142
begin
143
 
144
  ------------------------------------
145
  -- Notes
146
  ------------------------------------
147
  -- 1) The scalar multiply unit employs a two-stage pipeline:
148
  -- instructions mul, lmul and mula execute in one cycle, while 
149
  -- lmac, lmsu, mulr and m3216 one executes in two cycles.
150
  -- Result and overflow flag from single-cycle instructions are
151
  -- available at the end of first stage for forwarding.
152
 
153
  ------------------------------------
154
  -- 16x16 multipliers
155
  ------------------------------------
156
 
157
  PROD1 <= OPA_i(SDLEN-1 downto 0) * OPB_i(SDLEN-1 downto 0);
158
 
159
  PROD2 <= OPA_i(LDLEN-1 downto SDLEN) * OPB_i(SDLEN-1 downto 0);
160
 
161
  ------------------------------------
162
  -- mula
163
  ------------------------------------
164
 
165
  -- mul-address, is a normal 16x16 multiplication, used
166
  -- for address arithmetic.
167
 
168
  MULA_RES(SDLEN-1 downto 0) <= PROD1(SDLEN-1 downto 0);
169
  MULA_RES(LDLEN-1 downto SDLEN) <= (others => '0');
170
 
171
  MULA_OVF <= '0';
172
 
173
  -- pipe register
174
  process(CLK_i)
175
  begin
176
    if(CLK_i = '1' and CLK_i'event) then
177
      MULA_RES_q <= MULA_RES;
178
      MULA_OVF_q <= MULA_OVF;
179
    end if;
180
  end process;
181
 
182
--  ------------------------------------
183
--  -- L_mac() & L_msu()
184
--  ------------------------------------
185
--
186
--  -- L_mac(L_var3,var1,var2)
187
--  -- L_produit = L_mult(var1,var2);
188
--  -- L_var_out = L_add(L_var3,L_produit);
189
--  --
190
--  -- L_mult(var1,var2)
191
--  -- L_var_out = (WORD_T32)var1 * (WORD_T32)var2;
192
--  -- if (L_var_out != (WORD_T32)0x40000000L)
193
--  --   L_var_out *= 2;
194
--  -- else{
195
--  --   Overflow = 1;
196
--  --   L_var_out = MAX_32;
197
--  -- }
198
--  --
199
--  -- L_add(L_var1,L_var2)
200
--  -- L_var_out = L_var1 + L_var2;
201
--  -- if (((L_var1 ^ L_var2) & MIN_32) == 0)
202
--  --   if ((L_var_out ^ L_var1) & MIN_32){
203
--  --     L_var_out = (L_var1 < 0) ? MIN_32 : MAX_32;
204
--  --     Overflow = 1;
205
--  --   }
206
--
207
--  -- lmac/lmsu result is selected from three different sources:
208
--  -- 1) multiplication actual result plus accumulator content, when
209
--  -- nor multiplication and neither addition result in overflow.
210
--  -- 2) multiplication overflow result (either MAX32 or -MAX32) plus
211
--  -- accumulator content, when multiplication results in overflow but
212
--  -- addition doesn't. 
213
--  -- 3) addition overflow result, when addition results in overflow
214
--  -- (multiplication result is do-not-care in this case).
215
--
216
--  -- Source #1
217
--
218
--  -- subtract/add selector
219
--  MAC_SA <= '1' when CTRL_i = MC_LMSU else '0';
220
--
221
--  -- Multiplication overflow flag
222
--  MAC_MUL_OVF <= '1' when PROD1 = MUL_OVFVAL else '0';
223
--
224
--  -- shift PROD left by 1 bit, and negate result if operation
225
--  -- is of MSU type.
226
--
227
--  MAC_PROD1 <= shift_left(PROD1,1) when MAC_SA = '0' else 
228
--    not(shift_left(PROD1,1));
229
--
230
--  -- pipe register
231
--  process(CLK_i)
232
--  begin
233
--    if(CLK_i = '1' and CLK_i'event) then
234
--      MAC_PROD1_q <= MAC_PROD1;
235
--      MAC_MUL_OVF_q <= MAC_MUL_OVF;
236
--      MAC_SA_q <= MAC_SA;
237
--    end if;
238
--  end process;
239
--
240
--  -- MAC_SUM1 is MAC/MSU result assuming overflow occurs nor in
241
--  -- multiplication and neither in addition/subtraction.
242
--
243
--  U_ADD1 : G729A_ASIP_ADDER -- _F
244
--    generic map(
245
--      --LEN1 => SDLEN,
246
--      --LEN2 => SDLEN
247
--      WIDTH => LDLEN
248
--    )
249
--    port map(
250
--      OPA_i => ACC_i,
251
--      OPB_i => MAC_PROD1_q,
252
--      CI_i => MAC_SA_q,
253
--      SUM_o => MAC_SUM1
254
--    );
255
--
256
--  -- Addition #1 overflow flag
257
--  MAC_ADD_OVF1 <= overflow(
258
--    MAC_SA_q,
259
--    ACC_i(LDLEN-1),
260
--    MAC_PROD1_q(LDLEN-1),
261
--    MAC_SUM1(LDLEN-1)
262
--  );
263
--
264
--  -- Source #2
265
--
266
--  -- MAC_PROD2 is multiplication result assuming this operation
267
--  -- results in overflow (MAX_32 for lmac* and -MAX_32 for lmsu*,
268
--  -- latter value being generated negating MAX_32 and then add 1 
269
--  -- in addition to accumulator).
270
--
271
--  MAC_PROD2 <= MAX_32 when MAC_SA_q = '0' else not(MAX_32);
272
--
273
--  -- MAC_SUM2 is MAC/MSU result when overflow occurs in multiplication, but
274
--  -- not in addition/subtraction
275
--
276
--  U_ADD2 : G729A_ASIP_ADDER
277
--    generic map(
278
--      WIDTH => LDLEN
279
--    )
280
--    port map(
281
--      OPA_i => ACC_i,
282
--      OPB_i => MAC_PROD2,
283
--      CI_i => MAC_SA_q,
284
--      SUM_o => MAC_SUM2
285
--    );
286
--
287
--  -- Addition #2 overflow flag
288
--  MAC_ADD_OVF2 <= overflow(
289
--    MAC_SA_q,
290
--    ACC_i(LDLEN-1),
291
--    MAC_PROD2(LDLEN-1),
292
--    MAC_SUM2(LDLEN-1)
293
--  );
294
--
295
--  -- Final MAC/MSU overflow flag
296
--  MAC_OVF <= MAC_MUL_OVF_q or MAC_ADD_OVF1;
297
--
298
--  -- Select lmac*/lmsu* result
299
--  -- (coded to minimize MAC_SUM1 path delay)
300
--
301
--  process(MAC_OVF,MAC_MUL_OVF_q,ACC_i,MAC_SUM1,MAC_SUM2,MAC_ADD_OVF2)
302
--  begin
303
--    if(MAC_OVF = '0') then
304
--      -- no overflow
305
--      MAC_RES <= MAC_SUM1;
306
--    elsif(MAC_MUL_OVF_q = '1' and MAC_ADD_OVF2 = '0') then
307
--      -- overflow in multiplication, but not in addition
308
--      MAC_RES <= MAC_SUM2;
309
--    elsif(ACC_i(LDLEN-1) = '0') then
310
--      -- positive overflow in addition
311
--      MAC_RES <= MAX_32;   
312
--    else
313
--      -- negative overflow in addition
314
--      MAC_RES <= MIN_32;   
315
--    end if;
316
--  end process;
317
 
318
  ------------------------------------
319
  -- L_mult()
320
  ------------------------------------
321
 
322
  -- pipe register
323
  process(CLK_i)
324
  begin
325
    if(CLK_i = '1' and CLK_i'event) then
326
      LMUL_PROD_q <= PROD1;
327
    end if;
328
  end process;
329
 
330
  process(LMUL_PROD_q)
331
    variable IRES : LDWORD_T;
332
    variable IOVF : std_logic;
333
  begin
334
    L_mult(LMUL_PROD_q,IRES,IOVF);
335
    LMUL_RES <= IRES;
336
    LMUL_OVF <= IOVF;
337
  end process;
338
 
339
  ------------------------------------
340
  -- mult_r()
341
  ------------------------------------
342
 
343
  -- mult_r() is performed in two cycles:
344
  -- cycle #1: a standard mult() is executed, its result being
345
  -- stored in a pipe register
346
  -- cycle #2: pipe register content is added 0x00004000 and
347
  -- result is saturated.
348
 
349
  -- pipe register
350
  process(CLK_i)
351
  begin
352
    if(CLK_i = '1' and CLK_i'event) then
353
      MULR_PROD_q <= PROD1;
354
    end if;
355
  end process;
356
 
357
  MULR_SUM1 <= MULR_PROD_q + hex_to_signed("00004000",LDLEN);
358
 
359
  MULR_SUM2 <= shift_right(MULR_SUM1,SDLEN-1);
360
 
361
  process(MULR_SUM2)
362
    variable IRES : SDWORD_T;
363
    variable IOVF : std_logic;
364
  begin
365
    sature(MULR_SUM2,IRES,IOVF);
366
    MULR_RES(SDLEN-1 downto 0) <= IRES;
367
    MULR_RES(LDLEN-1 downto SDLEN) <= (others => '0');
368
    MULR_OVF <= IOVF;
369
  end process;
370
 
371
  ------------------------------------
372
  -- Mpy_32_16()
373
  ------------------------------------
374
 
375
  -- Mpy_32_16() is performed in two cycles:
376
  -- cycle #1: L_mult(hi,n) and L_mult(mult(lo,n),1) are
377
  -- calculated in parallel, their results being stored in
378
  -- pipe registers.
379
  -- cycle #2: pipe registers are long-added.
380
 
381
  process(PROD2)
382
    variable IRES : LDWORD_T;
383
    variable IOVF : std_logic;
384
  begin
385
    L_mult(PROD2,IRES,IOVF);
386
    M3216_PRODHI <= IRES;
387
    M3216_MUL_OVFHI <= IOVF;
388
  end process;
389
 
390
  process(PROD1)
391
    variable IRES : SDWORD_T;
392
    variable IOVF : std_logic;
393
  begin
394
    mult(PROD1,IRES,IOVF);
395
    M3216_PRODLO1 <= IRES;
396
    M3216_MUL_OVFLO <= IOVF;
397
  end process;
398
 
399
  -- L_mult(mult(lo,n),1) : shift PROD_LO left by 1 bit,
400
  -- and sign-extend result to LDLEN bits.
401
 
402
  M3216_PRODLO2(0) <= '0';
403
  M3216_PRODLO2(SDLEN downto 1) <= M3216_PRODLO1(SDLEN-1 downto 0);
404
  M3216_PRODLO2(LDLEN-1 downto SDLEN+1) <= (others => M3216_PRODLO1(SDLEN-1));
405
 
406
  -- pipe registers
407
  process(CLK_i)
408
  begin
409
    if(CLK_i = '1' and CLK_i'event) then
410
      M3216_PRODLO_q <= M3216_PRODLO2;
411
      M3216_PRODHI_q <= M3216_PRODHI;
412
      M3216_MUL_OVF_q <= (M3216_MUL_OVFHI or M3216_MUL_OVFLO);
413
    end if;
414
  end process;
415
 
416
  M3216_SUM <= (M3216_PRODHI_q + M3216_PRODLO_q);
417
 
418
  process(M3216_SUM,M3216_PRODLO_q,M3216_PRODHI_q)
419
    variable IRES : LDWORD_T;
420
    variable IOVF : std_logic;
421
  begin
422
    L_add_sub(
423
      M3216_SUM,
424
      '1',
425
      M3216_PRODLO_q(LDLEN-1),
426
      M3216_PRODHI_q(LDLEN-1),
427
      IRES,
428
      IOVF
429
    );
430
    M3216_RES <= IRES;
431
    M3216_ADD_OVF <= IOVF;
432
  end process;
433
 
434
  -- Final Mpy_32_16 overflow flag
435
  M3216_OVF <= (M3216_ADD_OVF or M3216_MUL_OVF_q);
436
 
437
  ------------------------------------
438
  -- Result mux
439
  ------------------------------------
440
 
441
  -- pipe register
442
  process(CLK_i)
443
  begin
444
    if(CLK_i = '1' and CLK_i'event) then
445
      CTRL_q <= CTRL_i;
446
    end if;
447
  end process;
448
 
449
  --process(CTRL_q,MAC_RES_q,MAC_OVF_q,MULR_RES,MULR_OVF,LMUL_RES,LMUL_OVF,
450
  --  M3216_RES,M3216_OVF)
451
  process(CTRL_q,MULA_RES_q,MULA_OVF_q,MULR_RES,MULR_OVF,LMUL_RES,LMUL_OVF,
452
    M3216_RES,M3216_OVF)
453
  begin
454
    case CTRL_q is
455
      when MC_MULA =>
456
        RES_o <= MULA_RES_q;
457
        OVF_o <= MULA_OVF_q;
458
      --when MC_LMAC|MC_LMSU =>
459
      --  RES_o <= MAC_RES;
460
      --  OVF_o <= MAC_OVF;
461
      when MC_MULR =>
462
        RES_o <= MULR_RES;
463
        OVF_o <= MULR_OVF;
464
      when MC_LMUL =>
465
        RES_o <= LMUL_RES;
466
        OVF_o <= LMUL_OVF;
467
      when others => -- MC_M3216 =>
468
        RES_o <= M3216_RES;
469
        OVF_o <= M3216_OVF;
470
    end case;
471
  end process;
472
 
473
end ARC;

powered by: WebSVN 2.1.0

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