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

Subversion Repositories g729a_codec

[/] [g729a_codec/] [trunk/] [VHDL/] [G729A_asip_pipe_a_2w.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) 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 pipeline-A (dedicated) decoder 
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_IDEC_2W_PKG.all;
39
use WORK.G729A_ASIP_OP_PKG.all;
40
 
41
entity G729A_ASIP_PIPE_A_DEC_2W is
42
  port(
43
    INSTR_i : in DEC_INSTR_T;
44
 
45
    FWDE_o : out std_logic;
46
    SEL_o :  out std_logic_vector(7-1 downto 0)
47
  );
48
end G729A_ASIP_PIPE_A_DEC_2W;
49
 
50
architecture ARC of G729A_ASIP_PIPE_A_DEC_2W is
51
 
52
begin
53
 
54
  -- Note:
55
  -- forward-enable flags account for ld/stpp instructions in
56
  -- order to correctly handle rA register incrementation
57
  -- (that is performed by logic inside pipe-A).
58
 
59
  -- Result forward-enable flag
60
 
61
  FWDE_o <= '1' when (
62
    INSTR_i.IMNMC = IM_ADD or
63
    INSTR_i.IMNMC = IM_ADDI or
64
    INSTR_i.IMNMC = IM_SUB or
65
    INSTR_i.IMNMC = IM_SUBI or
66
    INSTR_i.IMNMC = IM_MUL or
67
    INSTR_i.IMNMC = IM_MULI or
68
    INSTR_i.IMNMC = IM_MOVI or
69
    INSTR_i.IMNMC = IM_LMAC or
70
    INSTR_i.IMNMC = IM_LMACI or
71
    INSTR_i.IMNMC = IM_LMSU or
72
    INSTR_i.IMNMC = IM_LMSUI or
73
    INSTR_i.IMNMC = IM_LD
74
  ) else '0';
75
 
76
  -- pipe-A operation selector
77
 
78
  process(INSTR_i)
79
  begin
80
    case INSTR_i.IMNMC is
81
      when IM_ADD|IM_ADDI => SEL_o <= "0000001";
82
      when IM_SUB|IM_SUBI => SEL_o <= "0000010";
83
      when IM_MUL|IM_MULI => SEL_o <= "0000100";
84
      when IM_MOVI => SEL_o <= "0001000";
85
      when IM_LMAC|IM_LMACI => SEL_o <= "0010000";
86
      when IM_LMSU|IM_LMSUI => SEL_o <= "0100000";
87
      when others => SEL_o <= "1000000"; -- ld/ldpp
88
    end case;
89
  end process;
90
 
91
end ARC;
92
 
93
---------------------------------------------------------------
94
-- A-pipeline 
95
---------------------------------------------------------------
96
 
97
library IEEE;
98
use IEEE.std_logic_1164.all;
99
use IEEE.numeric_std.all;
100
 
101
library WORK;
102
use WORK.G729A_ASIP_PKG.all;
103
use WORK.G729A_ASIP_BASIC_PKG.all;
104
use WORK.G729A_ASIP_ARITH_PKG.all;
105
use WORK.G729A_ASIP_OP_PKG.all;
106
 
107
entity G729A_ASIP_PIPE_A_2W is
108
  port(
109
    CLK_i : in std_logic;
110
    SEL_i :  in std_logic_vector(7-1 downto 0);
111
    OPA_i : in SDWORD_T;
112
    OPB_i : in SDWORD_T;
113
    ACC_i : in LDWORD_T;
114
    LDAT_i : in std_logic_vector(SDLEN-1 downto 0);
115
 
116
    RES_1C_o : out SDWORD_T; --  port #0 1-cycle result
117
    RES_o : out LDWORD_T; -- port #0 result
118
    ACC_o : out LDWORD_T; -- updated accumulator
119
    OVF_o : out std_logic -- port #0 overflow flag
120
  );
121
end G729A_ASIP_PIPE_A_2W;
122
 
123
architecture ARC of G729A_ASIP_PIPE_A_2W is
124
 
125
  constant MUL_OVFVAL : LDWORD_T := hex_to_signed("40000000",LDLEN);
126
  constant ZERO16 : SDWORD_T := (others => '0');
127
 
128
  constant OP_ADD : natural := 0;
129
  constant OP_SUB : natural := 1;
130
  constant OP_MUL : natural := 2;
131
  constant OP_MOV : natural := 3;
132
  constant OP_LMAC : natural := 4;
133
  constant OP_LMSU : natural := 5;
134
  constant OP_LOAD : natural := 6;
135
 
136
  component G729A_ASIP_ADDER is
137
    generic(
138
      WIDTH : integer := 16
139
    );
140
    port(
141
      OPA_i : in signed(WIDTH-1 downto 0);
142
      OPB_i : in signed(WIDTH-1 downto 0);
143
      CI_i : in std_logic;
144
 
145
      SUM_o : out signed(WIDTH-1 downto 0)
146
    );
147
  end component;
148
 
149
  component G729A_ASIP_ADDER_F is
150
    generic(
151
      LEN1 : integer := 16;
152
      LEN2 : integer := 16
153
    );
154
    port(
155
      OPA_i : in signed(LEN1+LEN2-1 downto 0);
156
      OPB_i : in signed(LEN1+LEN2-1 downto 0);
157
      CI_i : in std_logic;
158
 
159
      SUM_o : out signed(LEN1+LEN2-1 downto 0)
160
    );
161
  end component;
162
 
163
  -- check for overflow in addition/subtraction
164
  function overflow(
165
    SA : std_logic;
166
    SGNA : std_logic;
167
    SGNB : std_logic;
168
    SGNR : std_logic
169
  ) return std_logic is
170
  variable OVF : std_logic;
171
  begin
172
    -- overflow flag
173
    if(SA = '0') then
174
      -- addition
175
      if(SGNR = '1') then
176
        OVF := not(SGNA or SGNB);
177
      else
178
        OVF := (SGNA and SGNB);
179
      end if;
180
    else
181
      -- subtraction
182
      if(SGNR = '1') then
183
        OVF := (not(SGNA) and SGNB);
184
      else
185
        OVF := (SGNA and not(SGNB));
186
      end if;
187
    end if;
188
    return(OVF);
189
  end function;
190
 
191
  function to_unsigned(S : signed) return unsigned is
192
    variable U : unsigned(S'HIGH downto S'LOW);
193
  begin
194
    for i in S'HIGH downto S'LOW loop
195
      U(i) := S(i);
196
    end loop;
197
    return(U);
198
  end function;
199
 
200
  function to_signed(U : unsigned) return signed is
201
    variable S : signed(U'HIGH downto U'LOW);
202
  begin
203
    for i in U'HIGH downto U'LOW loop
204
      S(i) := U(i);
205
    end loop;
206
    return(S);
207
  end function;
208
 
209
  signal ZERO : std_logic := '0';
210
  signal ONE : std_logic := '1';
211
  signal OPA_SGN,OPB_SGN : std_logic;
212
  signal OPB_N : SDWORD_T;
213
  signal ADD_RES : SDWORD_T;
214
  signal ADD_RES_SGN,ADD_OVF : std_logic;
215
  signal SUB_RES : SDWORD_T;
216
  signal SUB_RES_SGN,SUB_OVF : std_logic;
217
  signal PROD : LDWORD_T;
218
  signal MUL_RES : SDWORD_T;
219
  signal MUL_RES_SGN,MUL_OVF : std_logic;
220
  signal OPA_ZERO,OPB_ZERO : std_logic;
221
  signal RES_1C,RES_1C_q,RES_1C_NOVF : SDWORD_T;
222
  signal OVF_1C,OVF_1C_q : std_logic;
223
  signal SEL_q : std_logic_vector(7-1 downto 0);
224
  signal MAC_MUL_OVF,MAC_ADD_OVF1,MAC_ADD_OVF2 : std_logic;
225
  signal MAC_MUL_OVF_q : std_logic;
226
  signal MAC_PROD,MAC_PROD_OVF : LDWORD_T;
227
  signal MAC_PROD_q : LDWORD_T;
228
  signal MAC_SUM1,MAC_SUM2 : LDWORD_T;
229
  signal MAC_RES : LDWORD_T;
230
  signal MAC_SA,MAC_SA_q,MAC_OVF : std_logic;
231
  signal MAC_PROD_SGN,MAC_PROD_SGN_q : std_logic;
232
 
233
begin
234
 
235
  ------------------------------------
236
  -- Notes
237
  ------------------------------------
238
 
239
  -- This pipeline executes only the following high-frequency
240
  -- instructions:
241
  -- add/addi,
242
  -- sub/subi,
243
  -- mul/muli,
244
  -- lmac/lmaci/lmsu/lmsui and
245
  -- movi.
246
  -- Additionally, the pipeline merges load data to 
247
 
248
  -- Instructions add/addi, sub/subi, mul/muli and movi
249
  -- are executed in one cycle (their results being muxed and
250
  -- registed after first cycle), while instructions lmac/lmaci/
251
  -- lmsu/lmsui are executed in two cycles.
252
 
253
  ------------------------------------
254
  -- operands sign
255
  ------------------------------------
256
 
257
  OPA_SGN <= OPA_i(SDLEN-1);
258
 
259
  OPB_SGN <= OPB_i(SDLEN-1);
260
 
261
  ------------------------------------
262
  -- operand zero flags
263
  ------------------------------------
264
 
265
  OPA_ZERO <= '1' when (OPA_i = 0) else '0';
266
 
267
  OPB_ZERO <= '1' when (OPB_i = 0) else '0';
268
 
269
  ------------------------------------
270
  -- addition
271
  ------------------------------------
272
 
273
  -- addition result
274
  --ADD_RES <= OPA_i + OPB_i;
275
 
276
  -- carry-select adder (to improve timing)
277
 
278
  U_ADD : G729A_ASIP_ADDER_F
279
    generic map(
280
      LEN1 => SDLEN/2,
281
      LEN2 => SDLEN/2
282
    )
283
    port map(
284
      OPA_i => OPA_i,
285
      OPB_i => OPB_i,
286
      CI_i => ZERO,
287
      SUM_o => ADD_RES
288
    );
289
 
290
  -- addition result sign
291
  ADD_RES_SGN <= ADD_RES(SDLEN-1);
292
 
293
  -- Addition overflow flag
294
  ADD_OVF <= overflow('0',OPA_SGN,OPB_SGN,ADD_RES_SGN);
295
 
296
  ------------------------------------
297
  -- subtraction
298
  ------------------------------------
299
 
300
  -- addition result
301
  --SUB_RES <= OPA_i - OPB_i;
302
 
303
  OPB_N <= not(OPB_i);
304
 
305
  -- carry-select adder (to improve timing)
306
 
307
  U_SUB : G729A_ASIP_ADDER_F
308
    generic map(
309
      LEN1 => SDLEN/2,
310
      LEN2 => SDLEN/2
311
    )
312
    port map(
313
      OPA_i => OPA_i,
314
      OPB_i => OPB_N,
315
      CI_i => ONE,
316
      SUM_o => SUB_RES
317
    );
318
 
319
  -- subtraction result sign
320
  SUB_RES_SGN <= SUB_RES(SDLEN-1);
321
 
322
  -- subtraction overflow flag
323
  SUB_OVF <= overflow('1',OPA_SGN,OPB_SGN,SUB_RES_SGN);
324
 
325
  ------------------------------------
326
  -- 16x16 multiplication
327
  -- (result is shared by mul,lmac/i
328
  -- and lmsu/i instructions)
329
  ------------------------------------
330
 
331
  PROD <= OPA_i * OPB_i;
332
 
333
  -- multiplication result
334
  process(PROD)
335
    variable TMP : LDWORD_T;
336
  begin
337
    TMP := shift_right(PROD,SDLEN-1);
338
    MUL_RES <= TMP(SDLEN-1 downto 0);
339
  end process;
340
 
341
  -- multiplication result sign
342
  MUL_RES_SGN <= OPA_i(SDLEN-1) xor OPB_i(SDLEN-1) when
343
    (OPA_ZERO = '0' and OPB_ZERO = '0') else '0';
344
 
345
  -- multiplication overflow flag
346
  MUL_OVF <= PROD(LDLEN-1) xor MUL_RES_SGN;
347
 
348
  ------------------------------------
349
  -- port #0 result and overflow flag
350
  -- (1-cycle instructions only)
351
  ------------------------------------
352
 
353
  -- Overflow flag mux
354
 
355
  process(SEL_i,ADD_OVF,ADD_RES_SGN,SUB_OVF,SUB_RES_SGN,MUL_OVF,MUL_RES_SGN)
356
  begin
357
    if(SEL_i(OP_MUL) = '1') then
358
      OVF_1C <= MUL_OVF;
359
    elsif(SEL_i(OP_ADD) = '1') then
360
      OVF_1C <= ADD_OVF;
361
    elsif(SEL_i(OP_SUB) = '1') then
362
      OVF_1C <= SUB_OVF;
363
    else
364
      OVF_1C <= '0';
365
    end if;
366
  end process;
367
 
368
  -- Result mux
369
 
370
  process(SEL_i,ADD_RES,SUB_RES,MUL_RES,OPB_i,OVF_1C,MUL_OVF,
371
    ADD_OVF,SUB_OVF,ADD_RES_SGN,SUB_RES_SGN,MUL_RES_SGN)
372
  begin
373
    if(SEL_i(OP_MUL) = '1') then
374
      if(MUL_OVF = '0') then
375
        RES_1C <= MUL_RES;
376
      elsif(MUL_RES_SGN = '1') then
377
        RES_1C <= MIN_16;
378
      else
379
        RES_1C <= MAX_16;
380
      end if;
381
    elsif(SEL_i(OP_ADD) = '1') then
382
      if(ADD_OVF = '0') then
383
        RES_1C <= ADD_RES;
384
      elsif(ADD_RES_SGN = '1') then
385
        RES_1C <= MIN_16;
386
      else
387
        RES_1C <= MAX_16;
388
      end if;
389
    elsif(SEL_i(OP_SUB) = '1') then
390
      if(SUB_OVF = '0') then
391
        RES_1C <= SUB_RES;
392
      elsif(SUB_RES_SGN = '1') then
393
        RES_1C <= MIN_16;
394
      else
395
        RES_1C <= MAX_16;
396
      end if;
397
    else
398
      RES_1C <= OPB_i;
399
    end if;
400
  end process;
401
 
402
  ------------------------------------
403
  -- pipe stage 1 outputs
404
  ------------------------------------
405
 
406
  RES_1C_o <= RES_1C;
407
 
408
  ------------------------------------
409
  -- pipe register
410
  ------------------------------------
411
 
412
  process(CLK_i)
413
  begin
414
    if(CLK_i = '1' and CLK_i'event) then
415
      SEL_q <= SEL_i;
416
      RES_1C_q <= RES_1C;
417
      OVF_1C_q <= OVF_1C;
418
    end if;
419
  end process;
420
 
421
  ------------------------------------
422
  -- lmac/i and lmsu/i
423
  ------------------------------------
424
 
425
  -- lmac/lmsu result is selected from three different sources:
426
  -- 1) multiplication actual result plus accumulator content, when
427
  -- nor multiplication and neither addition result in overflow.
428
  -- 2) multiplication overflow result (either MAX32 or -MAX32) plus
429
  -- accumulator content, when multiplication results in overflow but
430
  -- addition doesn't. 
431
  -- 3) addition overflow result, when addition results in overflow
432
  -- (multiplication result is do-not-care in this case).
433
 
434
  -- Source #1
435
 
436
  -- subtract/add selector
437
  MAC_SA <= SEL_i(OP_LMSU);
438
 
439
  -- (32-bit) Multiplication overflow flag
440
  MAC_MUL_OVF <= '1' when PROD = MUL_OVFVAL else '0';
441
 
442
  -- shift PROD left by 1 bit, and negate result if operation
443
  -- is of MSU type.
444
 
445
  MAC_PROD <= shift_left(PROD,1) when MAC_SA = '0' else
446
    not(shift_left(PROD,1));
447
 
448
  -- sign of MAC_PROD (before negation)
449
  MAC_PROD_SGN <= PROD(LDLEN-1);
450
 
451
  -- pipe register
452
  process(CLK_i)
453
  begin
454
    if(CLK_i = '1' and CLK_i'event) then
455
      MAC_PROD_q <= MAC_PROD;
456
      MAC_MUL_OVF_q <= MAC_MUL_OVF;
457
      MAC_SA_q <= MAC_SA;
458
      MAC_PROD_SGN_q <= MAC_PROD_SGN;
459
    end if;
460
  end process;
461
 
462
  -- MAC_SUM1 is MAC/MSU result assuming overflow occurs nor in
463
  -- multiplication and neither in addition/subtraction.
464
 
465
  U_ADD1 : G729A_ASIP_ADDER_F
466
    generic map(
467
      LEN1 => SDLEN,
468
      LEN2 => SDLEN
469
    )
470
    port map(
471
      OPA_i => ACC_i,
472
      OPB_i => MAC_PROD_q,
473
      CI_i => MAC_SA_q,
474
      SUM_o => MAC_SUM1
475
    );
476
 
477
  -- Addition #1 overflow flag
478
  MAC_ADD_OVF1 <= overflow(
479
    MAC_SA_q,
480
    ACC_i(LDLEN-1),
481
    MAC_PROD_SGN_q,
482
    MAC_SUM1(LDLEN-1)
483
  );
484
 
485
  -- Source #2
486
 
487
  -- MAC_PROD_OVF is multiplication result assuming this operation
488
  -- results in overflow (MAX_32 for lmac* and -MAX_32 for lmsu*,
489
  -- latter value being generated negating MAX_32 and then add 1 
490
  -- in addition to accumulator).
491
 
492
  MAC_PROD_OVF <= MAX_32 when MAC_SA_q = '0' else not(MAX_32);
493
 
494
  -- MAC_SUM2 is MAC/MSU result when overflow occurs in multiplication, but
495
  -- not in addition/subtraction
496
 
497
  U_ADD2 : G729A_ASIP_ADDER_F
498
    generic map(
499
      LEN1 => SDLEN,
500
      LEN2 => SDLEN
501
    )
502
    port map(
503
      OPA_i => ACC_i,
504
      OPB_i => MAC_PROD_OVF,
505
      CI_i => MAC_SA_q,
506
      SUM_o => MAC_SUM2
507
    );
508
 
509
  -- Addition #2 overflow flag
510
  MAC_ADD_OVF2 <= overflow(
511
    MAC_SA_q,
512
    ACC_i(LDLEN-1),
513
    MAC_PROD_OVF(LDLEN-1),
514
    MAC_SUM2(LDLEN-1)
515
  );
516
 
517
  -- Final MAC/MSU overflow flag
518
  MAC_OVF <= MAC_MUL_OVF_q or MAC_ADD_OVF1;
519
 
520
  -- Select lmac*/lmsu* result
521
 
522
  -- Note: MAC_SUM1 has the longest timing path, in order
523
  -- to improve timing it's removed from this mux and fed
524
  -- directly to the main result mux (see below).
525
 
526
  process(MAC_OVF,MAC_MUL_OVF_q,ACC_i,MAC_SUM1,MAC_SUM2,MAC_ADD_OVF2)
527
  begin
528
    --if(MAC_OVF = '0') then
529
    --  -- no overflow
530
    --  MAC_RES <= MAC_SUM1;
531
    --elsif(MAC_MUL_OVF_q = '1' and MAC_ADD_OVF2 = '0') then
532
    if(MAC_MUL_OVF_q = '1' and MAC_ADD_OVF2 = '0') then
533
      -- overflow in multiplication, but not in addition
534
      MAC_RES <= MAC_SUM2;
535
    elsif(ACC_i(LDLEN-1) = '0') then
536
      -- positive overflow in addition
537
      MAC_RES <= MAX_32;
538
    else
539
      -- negative overflow in addition
540
      MAC_RES <= MIN_32;
541
    end if;
542
  end process;
543
 
544
  ------------------------------------
545
  -- pipe stage 2 outputs
546
  ------------------------------------
547
 
548
  process(SEL_q,MAC_SUM1,MAC_OVF,MAC_RES,LDAT_i,RES_1C_q)
549
  begin
550
    if(MAC_OVF = '0' and (SEL_q(OP_LMAC) = '1' or SEL_q(OP_LMSU) = '1')) then
551
      RES_o(SDLEN-1 downto 0) <= MAC_SUM1(SDLEN-1 downto 0);
552
    elsif(SEL_q(OP_LOAD) = '1') then
553
      RES_o(SDLEN-1 downto 0) <= to_signed(LDAT_i);
554
    elsif((SEL_q(OP_LMAC) = '1' or SEL_q(OP_LMSU) = '1')) then
555
      RES_o(SDLEN-1 downto 0) <= MAC_RES(SDLEN-1 downto 0);
556
    else
557
      RES_o(SDLEN-1 downto 0) <= RES_1C_q;
558
    end if;
559
  end process;
560
 
561
  RES_o(LDLEN-1 downto SDLEN) <= MAC_SUM1(LDLEN-1 downto SDLEN) when
562
    (MAC_OVF = '0') else MAC_RES(LDLEN-1 downto SDLEN);
563
 
564
  OVF_o <= MAC_OVF when (SEL_q(OP_LMAC) = '1' or SEL_q(OP_LMSU) = '1')
565
    else '0' when (SEL_q(OP_LOAD) = '1')
566
    else OVF_1C_q;
567
 
568
  ACC_o <= MAC_RES;
569
 
570
end ARC;

powered by: WebSVN 2.1.0

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