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 3

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

powered by: WebSVN 2.1.0

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