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

Subversion Repositories yac

[/] [yac/] [trunk/] [rtl/] [vhdl/] [cordic_iterative_int.vhd] - Blame information for rev 2

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

Line No. Rev Author Line
1 2 feddischso
----------------------------------------------------------------------------
2
----                                                                    ----
3
----  File           : cordic_iterative_int.vhd                         ----
4
----  Project        : YAC (Yet Another CORDIC Core)                    ----
5
----  Creation       : Feb. 2014                                        ----
6
----  Limitations    :                                                  ----
7
----  Synthesizer    :                                                  ----
8
----  Target         :                                                  ----
9
----                                                                    ----
10
----  Author(s):     : Christian Haettich                               ----
11
----  Email          : feddischson@opencores.org                        ----
12
----                                                                    ----
13
----                                                                    ----
14
-----                                                                  -----
15
----                                                                    ----
16
----  Description                                                       ----
17
----        VHDL implementation of YAC                                  ----
18
----                                                                    ----
19
----                                                                    ----
20
----                                                                    ----
21
-----                                                                  -----
22
----                                                                    ----
23
----  TODO                                                              ----
24
----        Some documentation and function description                 ----
25
----        Optimization                                                ----
26
----                                                                    ----
27
----                                                                    ----
28
----                                                                    ----
29
----------------------------------------------------------------------------
30
----                                                                    ----
31
----                  Copyright Notice                                  ----
32
----                                                                    ----
33
---- This file is part of YAC - Yet Another CORDIC Core                 ----
34
---- Copyright (c) 2014, Author(s), All rights reserved.                ----
35
----                                                                    ----
36
---- YAC is free software; you can redistribute it and/or               ----
37
---- modify it under the terms of the GNU Lesser General Public         ----
38
---- License as published by the Free Software Foundation; either       ----
39
---- version 3.0 of the License, or (at your option) any later version. ----
40
----                                                                    ----
41
---- YAC is distributed in the hope that it will be useful,             ----
42
---- but WITHOUT ANY WARRANTY; without even the implied warranty of     ----
43
---- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU  ----
44
---- Lesser General Public License for more details.                    ----
45
----                                                                    ----
46
---- You should have received a copy of the GNU Lesser General Public   ----
47
---- License along with this library. If not, download it from          ----
48
---- http://www.gnu.org/licenses/lgpl                                   ----
49
----                                                                    ----
50
----------------------------------------------------------------------------
51
 
52
 
53
 
54
library ieee;
55
library std;
56
use std.textio.all;
57
use ieee.std_logic_1164.ALL;
58
use ieee.numeric_std.ALL;
59
use ieee.std_logic_textio.all; -- I/O for logic types
60
use work.cordic_pkg.ALL;
61
use ieee.math_real.ALL;
62
 
63
entity cordic_iterative_int is
64
generic(
65
   XY_WIDTH    : natural := 12;
66
   A_WIDTH     : natural := 12;
67
   GUARD_BITS  : natural :=  2;
68
   RM_GAIN     : natural :=  4
69
       );
70
port(
71
   clk, rst  : in  std_logic;
72
   en        : in  std_logic;
73
   start     : in  std_logic;
74
   done      : out std_logic;
75
   mode_i    : in  std_logic_vector( 4-1 downto 0 );
76
   x_i       : in  std_logic_vector( XY_WIDTH-1  downto 0 );
77
   y_i       : in  std_logic_vector( XY_WIDTH-1  downto 0 );
78
   a_i       : in  std_logic_vector( A_WIDTH+2-1 downto 0 );
79
   x_o       : out std_logic_vector( XY_WIDTH+GUARD_BITS-1  downto 0 );
80
   y_o       : out std_logic_vector( XY_WIDTH+GUARD_BITS-1  downto 0 );
81
   a_o       : out std_logic_vector( A_WIDTH+2-1 downto 0 )
82
    );
83
end entity cordic_iterative_int;
84
 
85
 
86
architecture BEHAVIORAL of cordic_iterative_int is
87
 
88
   -- log2( max-iteration )
89
   constant L2_MAX_I    : natural := 8;
90
 
91
   constant MAX_A_WIDTH : natural := 34;
92
 
93
   -- Internal angle width
94
   constant A_WIDTH_I : natural := A_WIDTH+2;
95
 
96
 
97
   constant SQRT2_REAL  : real    := 1.4142135623730951454746218587388284504413604;
98
   constant PI_REAL     : real    := 3.1415926535897931159979634685441851615905762;
99
   constant PI          : integer := natural( PI_REAL    * real( 2**( A_WIDTH-1 ) ) + 0.5 );
100
   constant PI_H        : integer := natural( PI_REAL    * real( 2**( A_WIDTH-2 ) ) + 0.5 );
101
   constant SQRT2       : integer := natural( SQRT2_REAL * real( 2**( XY_WIDTH-1 ) ) + 0.5 );
102
   constant XY_MAX      : integer := natural( 2**( XY_WIDTH-1)-1);
103
 
104
 
105
   constant XY_WIDTH_G : natural := XY_WIDTH + GUARD_BITS;
106
 
107
 
108
 
109
   type state_st is( ST_IDLE, ST_INIT, ST_ROTATE, ST_RM_GAIN, ST_DONE );
110
   type state_t is record
111
      st       : state_st;
112
      mode     : std_logic_vector( mode_i'range );
113
      x        : signed( XY_WIDTH_G     -1 downto 0 );
114
      y        : signed( XY_WIDTH_G     -1 downto 0 );
115
      x_sh     : signed( XY_WIDTH_G     -1 downto 0 );
116
      y_sh     : signed( XY_WIDTH_G     -1 downto 0 );
117
      x_sum    : signed( XY_WIDTH_G     -1 downto 0 );
118
      y_sum    : signed( XY_WIDTH_G     -1 downto 0 );
119
      a        : signed( A_WIDTH_I      -1 downto 0 );
120
      a_tmp    : signed( A_WIDTH_I      -1 downto 0 );
121
      ylst     : signed( XY_WIDTH_G     -1 downto 0 );
122
      alst     : signed( A_WIDTH_I      -1 downto 0 );
123
      i        : signed( L2_MAX_I       -1 downto 0 );
124
      do_shift : std_logic;
125
      done     : std_logic;
126
      repeate  : std_logic;
127
   end record state_t;
128
   signal state : state_t;
129
 
130
 
131
   ---------------------------------------
132
   -- Auto-generated function 
133
   -- by matlab (see c_octave/cordic_iterative_code.m)
134
   function angular_lut( n : integer; mode : std_logic_vector; ANG_WIDTH : natural ) return signed is
135
      variable result : signed( ANG_WIDTH-1 downto 0 );
136
      variable temp : signed( MAX_A_WIDTH-1 downto 0 );
137
         begin
138
         if mode = VAL_MODE_CIR then
139
            case n is
140
               when 0 => temp := "0110010010000111111011010101000100";   -- -1843415740
141
               when 1 => temp := "0011101101011000110011100000101011";  -- -312264661
142
               when 2 => temp := "0001111101011011011101011111100100";  -- 2104350692
143
               when 3 => temp := "0000111111101010110111010100110101";  -- 1068201269
144
               when 4 => temp := "0000011111111101010101101110110111";  -- 536173495
145
               when 5 => temp := "0000001111111111101010101011011101";  -- 268348125
146
               when 6 => temp := "0000000111111111111101010101010110";  -- 134206806
147
               when 7 => temp := "0000000011111111111111101010101010";  -- 67107498
148
               when 8 => temp := "0000000001111111111111111101010101";  -- 33554261
149
               when 9 => temp := "0000000000111111111111111111101010";  -- 16777194
150
               when 10 => temp := "0000000000011111111111111111111101";         -- 8388605
151
               when others => temp := to_signed( 2**(MAX_A_WIDTH-1-n), MAX_A_WIDTH );
152
            end case;
153
         elsif mode = VAL_MODE_HYP then
154
            case n is
155
               when 1 => temp := "0100011001001111101010011110101010";  -- 423536554
156
               when 2 => temp := "0010000010110001010111011111010100";  -- -2100987948
157
               when 3 => temp := "0001000000010101100010010001110010";  -- 1079387250
158
               when 4 => temp := "0000100000000010101011000100010101";  -- 537571605
159
               when 5 => temp := "0000010000000000010101010110001000";  -- 268522888
160
               when 6 => temp := "0000001000000000000010101010101100";  -- 134228652
161
               when 7 => temp := "0000000100000000000000010101010101";  -- 67110229
162
               when 8 => temp := "0000000010000000000000000010101010";  -- 33554602
163
               when 9 => temp := "0000000001000000000000000000010101";  -- 16777237
164
               when 10 => temp := "0000000000100000000000000000000010";         -- 8388610
165
               when others => temp := to_signed( 2**(MAX_A_WIDTH-1-n), MAX_A_WIDTH );
166
            end case;
167
         elsif mode = VAL_MODE_LIN then
168
            temp := ( others => '0' );
169
            temp( temp'high-1-n downto 0  ) := ( others => '1' );
170
         end if;
171
      result := temp( temp'high downto temp'high-result'length+1 );
172
      return result;
173
   end function angular_lut;
174
   ---------------------------------------
175
 
176
 
177
   function repeat_hyperbolic_it( i : integer ) return boolean is
178
      variable res : boolean;
179
   begin
180
      case i is
181
         when 5         => res := true;
182
         when 14        => res := true;
183
         when 41        => res := true;
184
         when 122       => res := true;
185
         when others    => res := false;
186
      end case;
187
      return res;
188
   end;
189
 
190
begin
191
 
192
 
193
   ST : process( clk, rst )
194
      variable sign : std_logic;
195
    begin
196
 
197
      if clk'event and clk = '1' then
198
         if rst = '1' then
199
             state <= (    st       => ST_IDLE,
200
                           x        => ( others => '0' ),
201
                           y        => ( others => '0' ),
202
                           x_sh     => ( others => '0' ),
203
                           y_sh     => ( others => '0' ),
204
                           x_sum    => ( others => '0' ),
205
                           y_sum    => ( others => '0' ),
206
                           a        => ( others => '0' ),
207
                           a_tmp    => ( others => '0' ),
208
                           ylst     => ( others => '0' ),
209
                           alst     => ( others => '0' ),
210
                           mode     => ( others => '0' ),
211
                           i        => ( others => '0' ),
212
                           done     => '0',
213
                           do_shift => '0',
214
                           repeate  => '0'
215
                           );
216
 
217
         elsif en = '1' then
218
 
219
            if state.st = ST_IDLE and start = '1' then
220
               state.st       <= ST_INIT;
221
               state.mode     <= mode_i;
222
               state.x        <= resize( signed( x_i ), state.x'length );
223
               state.y        <= resize( signed( y_i ), state.y'length );
224
               state.a        <= resize( signed( a_i ), state.a'length );
225
               state.i        <= ( others => '0' );
226
 
227
            elsif state.st = ST_INIT then
228
               -- 
229
               -- initialization state
230
               --    -> do initial rotation (alignment)
231
               --    -> check special situations / miss-configurations (TODO)
232
               --
233
 
234
               state.st       <= ST_ROTATE;
235
               state.do_shift <= '1';
236
 
237
 
238
               if state.mode( 1 downto 0 ) = VAL_MODE_HYP then
239
                  -- if we do a hyperbolic rotation, we start with 1
240
                  state.i(0) <= '1';
241
               end if;
242
 
243
 
244
 
245
 
246
               if     state.mode( I_FLAG_VEC_ROT ) = '0'
247
                  and state.mode( 1 downto 0 )   =  VAL_MODE_CIR  then
248
                  -- circular vector mode
249
 
250
                  if state.a < - PI_H then
251
                     -- move from third quadrant to first
252
                     state.a <= state.a + PI;
253
                     state.x <= - state.x;
254
                     state.y <= - state.y;
255
                  elsif state.a > PI_H then
256
                     -- move from second quadrant to fourth
257
                     state.a <= state.a - PI;
258
                     state.x <= - state.x;
259
                     state.y <= - state.y;
260
                  end if;
261
 
262
               elsif   state.mode( I_FLAG_VEC_ROT ) = '1'
263
                   and state.mode( 1 downto 0 )   = VAL_MODE_CIR then
264
                  -- circular rotation mode
265
 
266
                  if state.x = 0 and state.y = 0 then
267
                     -- zero-input
268
                     state.a  <= ( others => '0' );
269
                     state.y  <= ( others => '0' );
270
                     state.st <= ST_DONE;
271
 
272
                  elsif state.x = XY_MAX and state.y = XY_MAX then
273
                     -- all-max 1
274
                     state.a  <= resize( angular_lut( 0, state.mode( 1 downto 0 ), A_WIDTH ), A_WIDTH_I );
275
                     state.x  <= to_signed( SQRT2, state.x'length );
276
                     state.y  <= (others => '0' );
277
                     state.st <= ST_DONE;
278
                  elsif state.x = -XY_MAX and state.y = -XY_MAX then
279
                     -- all-max 2
280
                     state.a  <= resize( angular_lut( 0, state.mode( 1 downto 0 ), A_WIDTH ), A_WIDTH_I ) - PI;
281
                     state.x  <= to_signed( SQRT2, state.x'length );
282
                     state.y  <= (others => '0' );
283
                     state.st <= ST_DONE;
284
                  elsif state.x = XY_MAX and state.y = -XY_MAX then
285
                     -- all-max 3
286
                     state.a  <= resize( -angular_lut( 0, state.mode( 1 downto 0 ), A_WIDTH ), A_WIDTH_I );
287
                     state.x  <= to_signed( SQRT2, state.x'length );
288
                     state.y  <= (others => '0' );
289
                     state.st <= ST_DONE;
290
                  elsif state.x = -XY_MAX and state.y = XY_MAX then
291
                     -- all-max 4
292
                     state.a  <= PI-  resize( angular_lut( 0, state.mode( 1 downto 0 ), A_WIDTH ), A_WIDTH_I );
293
                     state.x  <= to_signed( SQRT2, state.x'length );
294
                     state.y  <= (others => '0' );
295
                     state.st <= ST_DONE;
296
 
297
                  elsif state.x = 0 and state.y > 0 then
298
                     -- fixed rotation of pi/2
299
                     state.a  <= to_signed( PI_H, state.a'length );
300
                     state.x  <= state.y;
301
                     state.y  <= ( others => '0' );
302
                     state.st<= ST_DONE;
303
                  elsif state.x = 0 and state.y < 0 then
304
                     -- fixed rotation of -pi/2
305
                     state.a  <= to_signed( -PI_H, state.a'length );
306
                     state.x  <= -state.y;
307
                     state.y  <= ( others => '0' );
308
                     state.st<= ST_DONE;
309
 
310
                  elsif state.x < 0 and state.y >= 0 then
311
                     -- move from second quadrant to fourth
312
                     state.x <= - state.x;
313
                     state.y <= - state.y;
314
                     state.a <= to_signed(  PI, state.a'length );
315
                  elsif state.x < 0 and state.y < 0 then
316
                     -- move from third quadrant to first
317
                     state.x <= - state.x;
318
                     state.y <= - state.y;
319
                     state.a <= to_signed( -PI, state.a'length );
320
                  else
321
                     state.a <= ( others => '0' );
322
                  end if;
323
               elsif   state.mode( I_FLAG_VEC_ROT ) = '1'
324
                   and state.mode( 1 downto 0 )   = VAL_MODE_LIN then
325
                  -- linear rotation mode
326
                  if state.x < 0 then
327
                     state.x <= - state.x;
328
                     state.y <= - state.y;
329
                  end if;
330
                  state.a <= to_signed( 0, state.a'length );
331
 
332
               end if;
333
 
334
 
335
 
336
 
337
 
338
            --
339
            -- rotation state
340
            --
341
            -- Each rotation takes 
342
            --           two steps: in the first step, the shifting is
343
            --                      done, in the second step, the
344
            --                      shift-result is added/subtracted
345
            -- 
346
            --
347
            --
348
            elsif state.st = ST_ROTATE then
349
 
350
               -- get the sign
351
               if state.mode( I_FLAG_VEC_ROT )  = '0' then
352
                  if state.a < 0 then
353
                     sign := '0';
354
                  else
355
                     sign := '1';
356
                  end if;
357
               else
358
                  if state.y < 0 then
359
                     sign := '1';
360
                  else
361
                     sign := '0';
362
                  end if;
363
               end if;
364
 
365
 
366
 
367
               if state.do_shift = '1' then
368
                  -- get the angle, do the shifting and set the right angle
369
 
370
                  if sign = '1' then
371
 
372
                     -- circular case
373
                     if state.mode( 1 downto 0 ) = VAL_MODE_CIR then
374
 
375
                        state.a_tmp <= resize( - angular_lut( to_integer( state.i ), state.mode( 1 downto 0 ), A_WIDTH), A_WIDTH_I );
376
                        state.y_sh  <= - SHIFT_RIGHT( state.y, to_integer( state.i ) );
377
 
378
                     -- hyperbolic case
379
                     elsif state.mode( 1 downto 0 ) = VAL_MODE_HYP then
380
 
381
                        state.a_tmp <= resize( - angular_lut( to_integer( state.i ), state.mode( 1 downto 0 ), A_WIDTH), A_WIDTH_I );
382
                        state.y_sh  <= SHIFT_RIGHT( state.y, to_integer( state.i ) );
383
 
384
                     -- linear case
385
                     else
386
 
387
                        state.a_tmp <= resize( - angular_lut( to_integer( state.i ), state.mode( 1 downto 0 ), A_WIDTH  ), A_WIDTH_I ) ;
388
                        state.y_sh  <= ( others => '0' );
389
 
390
                     end if;
391
                     state.x_sh <=   SHIFT_RIGHT( state.x, to_integer( state.i ) );
392
 
393
                  else
394
 
395
                     -- circular case
396
                     if state.mode( 1 downto 0 ) = VAL_MODE_CIR then
397
 
398
                        state.a_tmp <= resize( angular_lut( to_integer( state.i ), state.mode( 1 downto 0 ), A_WIDTH ), A_WIDTH_I );
399
                        state.y_sh  <= SHIFT_RIGHT( state.y, to_integer( state.i ) );
400
 
401
                     -- hyperbolic case
402
                     elsif state.mode( 1 downto 0 ) = VAL_MODE_HYP then
403
 
404
                        state.a_tmp <= resize( angular_lut( to_integer( state.i ), state.mode( 1 downto 0 ), A_WIDTH ), A_WIDTH_I );
405
                        state.y_sh  <= - SHIFT_RIGHT( state.y, to_integer( state.i ) );
406
 
407
                     -- linear case
408
                     else
409
 
410
                        state.a_tmp <= resize( angular_lut( to_integer( state.i ), state.mode( 1 downto 0 ), A_WIDTH ), A_WIDTH_I ) ;
411
                        state.y_sh  <= ( others => '0' );
412
 
413
                     end if;
414
                     state.x_sh <= - SHIFT_RIGHT( state.x, to_integer( state.i ) );
415
 
416
                  end if;
417
                  state.do_shift <= '0';
418
 
419
                  -- abort condition
420
                  if(   state.mode( I_FLAG_VEC_ROT ) = '0' and
421
                        state.a = 0 ) then
422
                     state.st <= ST_RM_GAIN;
423
                     state.i  <= ( others => '0' );
424
                  elsif(   state.mode( I_FLAG_VEC_ROT ) = '0' and
425
                        state.a = state.alst ) then
426
                     state.st <= ST_RM_GAIN;
427
                     state.i  <= ( others => '0' );
428
                  elsif(   state.mode( I_FLAG_VEC_ROT ) = '1' and
429
                        state.y = 0 ) then
430
                     state.st <= ST_RM_GAIN;
431
                     state.i  <= ( others => '0' );
432
                  elsif(   state.mode( I_FLAG_VEC_ROT ) = '1' and
433
                        ( state.y = state.ylst ) ) then
434
                     state.st <= ST_RM_GAIN;
435
                     state.i  <= ( others => '0' );
436
                  end if;
437
 
438
                  state.ylst  <= state.y;
439
                  state.alst  <= state.a;
440
 
441
 
442
               else
443
                  state.x <= state.x + state.y_sh;
444
                  state.y <= state.y + state.x_sh;
445
                  state.a <= state.a + state.a_tmp;
446
                  if VAL_MODE_HYP = state.mode( 1 downto 0 )         and
447
                     state.repeate = '0'                             and
448
                     repeat_hyperbolic_it( to_integer( state.i ) )   then
449
                     state.repeate <= '1';
450
                  else
451
                     state.repeate  <= '0';
452
                     state.i        <= state.i+1;
453
                  end if;
454
                  state.do_shift <= '1';
455
               end if;
456
 
457
 
458
 
459
 
460
 
461
            --
462
            -- removal of the cordic gain
463
            --
464
            elsif state.st = ST_RM_GAIN then
465
               -- we need RM_GAIN+1 cycles to 
466
               -- calculate the RM_GAIN steps
467
               if state.i = (RM_GAIN) then
468
                 state.st   <= ST_DONE;
469
                 state.done <= '1';
470
                   state.i <= ( others => '0' );
471
               else
472
                   state.i  <= state.i + 1;
473
               end if;
474
 
475
               if state.mode( 1 downto 0 ) = VAL_MODE_CIR then
476
                  mult_0_61( state.x, state.x_sh, state.x_sum, to_integer( state.i ), RM_GAIN );
477
                  mult_0_61( state.y, state.y_sh, state.y_sum, to_integer( state.i ), RM_GAIN );
478
               elsif state.mode( 1 downto 0 ) = VAL_MODE_HYP then
479
                  mult_0_21( state.x, state.x_sh, state.x_sum, to_integer( state.i ), RM_GAIN );
480
                  mult_0_21( state.y, state.y_sh, state.y_sum, to_integer( state.i ), RM_GAIN );
481
               else
482
                  -- TODO  merge ST_DONE and state.done
483
                  state.done <= '1';
484
                  state.st    <= ST_DONE;
485
                  state.x_sum <= state.x;
486
                  state.y_sum <= state.y;
487
               end if;
488
 
489
 
490
            elsif state.st = ST_DONE then
491
               state.st    <= ST_IDLE;
492
               state.done  <= '0';
493
            end if;
494
            -- end states
495
 
496
 
497
 
498
         end if;
499
         -- end ena
500
 
501
 
502
      end if;
503
      -- end clk
504
 
505
   end process;
506
   done        <=                   state.done   ;
507
   x_o         <= std_logic_vector( state.x_sum );
508
   y_o         <= std_logic_vector( state.y_sum );
509
   a_o         <= std_logic_vector( state.a );
510
 
511
end architecture BEHAVIORAL;
512
 
513
 
514
 

powered by: WebSVN 2.1.0

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