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

Subversion Repositories yac

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

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 7 feddischso
 
88 2 feddischso
   -- 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 7 feddischso
 
97 2 feddischso
   constant SQRT2_REAL  : real    := 1.4142135623730951454746218587388284504413604;
98
   constant PI_REAL     : real    := 3.1415926535897931159979634685441851615905762;
99 7 feddischso
   constant PI          : integer := natural( round( PI_REAL    * real( 2**( A_WIDTH-1  ) ) ) );
100
   constant PI_H        : integer := natural( round( PI_REAL    * real( 2**( A_WIDTH-2  ) ) ) );
101
   constant SQRT2       : integer := natural( round( SQRT2_REAL * real( 2**( XY_WIDTH-1 ) ) ) );
102 2 feddischso
   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
      repeate  : std_logic;
126
   end record state_t;
127
   signal state : state_t;
128
 
129
 
130 7 feddischso
 
131 2 feddischso
   ---------------------------------------
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
                           do_shift => '0',
213
                           repeate  => '0'
214
                           );
215 7 feddischso
 
216 2 feddischso
         elsif en = '1' then
217 7 feddischso
 
218 2 feddischso
            if state.st = ST_IDLE and start = '1' then
219
               state.st       <= ST_INIT;
220
               state.mode     <= mode_i;
221
               state.x        <= resize( signed( x_i ), state.x'length );
222
               state.y        <= resize( signed( y_i ), state.y'length );
223
               state.a        <= resize( signed( a_i ), state.a'length );
224
               state.i        <= ( others => '0' );
225 7 feddischso
               state.alst     <= ( others => '0' );
226
               state.ylst     <= ( others => '0' );
227 4 feddischso
            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 2 feddischso
               state.st       <= ST_ROTATE;
235
               state.do_shift <= '1';
236
 
237
 
238 7 feddischso
              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
              if state.mode( I_FLAG_VEC_ROT ) = '1' and state.y = 0 then
246
                     -- zero-input
247
                     state.x_sum  <= state.x;
248
                     state.y_sum  <= state.y;
249
                     state.a      <= ( others => '0' );
250
                     state.st     <= ST_DONE;
251
 
252
              elsif state.mode( I_FLAG_VEC_ROT ) = '0' and state.a = 0 then
253
                     -- nothing to do, a is zero
254
                     state.x_sum  <= state.x;
255
                     state.y_sum  <= state.y;
256
                     state.st     <= ST_DONE;
257
 
258
              elsif     state.mode( I_FLAG_VEC_ROT ) = '0'
259 2 feddischso
                  and state.mode( 1 downto 0 )   =  VAL_MODE_CIR  then
260
                  -- circular vector mode
261
 
262
                  if state.a < - PI_H then
263
                     -- move from third quadrant to first
264
                     state.a <= state.a + PI;
265
                     state.x <= - state.x;
266
                     state.y <= - state.y;
267
                  elsif state.a > PI_H then
268
                     -- move from second quadrant to fourth
269
                     state.a <= state.a - PI;
270
                     state.x <= - state.x;
271
                     state.y <= - state.y;
272
                  end if;
273
 
274
               elsif   state.mode( I_FLAG_VEC_ROT ) = '1'
275
                   and state.mode( 1 downto 0 )   = VAL_MODE_CIR then
276
                  -- circular rotation mode
277
 
278 7 feddischso
                  if state.y = 0 then
279 4 feddischso
                     -- zero-input
280 7 feddischso
                     state.x_sum  <= state.x;
281
                     state.y_sum  <= state.y;
282
                     state.a      <= ( others => '0' );
283
                     state.st     <= ST_DONE;
284 4 feddischso
 
285
                  elsif state.x = XY_MAX and state.y = XY_MAX then
286
                     -- all-max 1
287 7 feddischso
                     state.x_sum  <= to_signed( SQRT2, state.x'length );
288
                     state.y_sum  <= (others => '0' );
289
                     state.a      <= resize( angular_lut( 0, state.mode( 1 downto 0 ), A_WIDTH ), A_WIDTH_I );
290
                     state.st     <= ST_DONE;
291 4 feddischso
                  elsif state.x = -XY_MAX and state.y = -XY_MAX then
292
                     -- all-max 2
293 7 feddischso
                     state.x_sum  <= to_signed( SQRT2, state.x'length );
294
                     state.y_sum  <= (others => '0' );
295
                     state.a      <= resize( angular_lut( 0, state.mode( 1 downto 0 ), A_WIDTH ), A_WIDTH_I ) - PI;
296
                     state.st     <= ST_DONE;
297 4 feddischso
                  elsif state.x = XY_MAX and state.y = -XY_MAX then
298
                     -- all-max 3
299 7 feddischso
                     state.x_sum  <= to_signed( SQRT2, state.x'length );
300
                     state.y_sum  <= (others => '0' );
301
                     state.a      <= resize( -angular_lut( 0, state.mode( 1 downto 0 ), A_WIDTH ), A_WIDTH_I );
302
                     state.st     <= ST_DONE;
303 4 feddischso
                  elsif state.x = -XY_MAX and state.y = XY_MAX then
304
                     -- all-max 4
305 7 feddischso
                     state.x_sum  <= to_signed( SQRT2, state.x'length );
306
                     state.y_sum  <= (others => '0' );
307
                     state.a      <= PI-  resize( angular_lut( 0, state.mode( 1 downto 0 ), A_WIDTH ), A_WIDTH_I );
308
                     state.st     <= ST_DONE;
309 4 feddischso
 
310
                  elsif state.x = 0 and state.y > 0 then
311
                     -- fixed rotation of pi/2
312 7 feddischso
                     state.x_sum  <= state.y;
313
                     state.y_sum  <= ( others => '0' );
314
                     state.a      <= to_signed( PI_H, state.a'length );
315
                     state.st     <= ST_DONE;
316 4 feddischso
                  elsif state.x = 0 and state.y < 0 then
317
                     -- fixed rotation of -pi/2
318 7 feddischso
                     state.x_sum  <= -state.y;
319
                     state.y_sum  <= ( others => '0' );
320
                     state.a      <= to_signed( -PI_H, state.a'length );
321
                     state.st     <= ST_DONE;
322 4 feddischso
 
323
                  elsif state.x < 0 and state.y >= 0 then
324
                     -- move from second quadrant to fourth
325 3 feddischso
                     state.x <= - state.x;
326
                     state.y <= - state.y;
327
                     state.a <= to_signed(  PI, state.a'length );
328
                  elsif state.x < 0 and state.y < 0 then
329 4 feddischso
                     -- move from third quadrant to first
330 3 feddischso
                     state.x <= - state.x;
331
                     state.y <= - state.y;
332
                     state.a <= to_signed( -PI, state.a'length );
333
                  else
334
                     state.a <= ( others => '0' );
335
                  end if;
336 4 feddischso
               elsif   state.mode( I_FLAG_VEC_ROT ) = '1'
337 3 feddischso
                   and state.mode( 1 downto 0 )   = VAL_MODE_LIN then
338 4 feddischso
                  -- linear rotation mode
339 7 feddischso
 
340 4 feddischso
                  if state.x < 0 then
341
                     state.x <= - state.x;
342
                     state.y <= - state.y;
343
                  end if;
344
                  state.a <= to_signed( 0, state.a'length );
345 3 feddischso
 
346 2 feddischso
               end if;
347
 
348
 
349
 
350
 
351
 
352
            --
353
            -- rotation state
354
            --
355
            -- Each rotation takes 
356
            --           two steps: in the first step, the shifting is
357
            --                      done, in the second step, the
358
            --                      shift-result is added/subtracted
359
            -- 
360
            --
361
            --
362
            elsif state.st = ST_ROTATE then
363
 
364
               -- get the sign
365
               if state.mode( I_FLAG_VEC_ROT )  = '0' then
366
                  if state.a < 0 then
367
                     sign := '0';
368
                  else
369
                     sign := '1';
370
                  end if;
371
               else
372
                  if state.y < 0 then
373
                     sign := '1';
374
                  else
375
                     sign := '0';
376
                  end if;
377
               end if;
378
 
379
 
380
 
381
               if state.do_shift = '1' then
382 7 feddischso
                  state.do_shift <= '0';
383 2 feddischso
 
384 7 feddischso
                  -- get the angle, do the shifting and set the correct angle
385
 
386 2 feddischso
                  if sign = '1' then
387
 
388
                     -- circular case
389
                     if state.mode( 1 downto 0 ) = VAL_MODE_CIR then
390
 
391
                        state.a_tmp <= resize( - angular_lut( to_integer( state.i ), state.mode( 1 downto 0 ), A_WIDTH), A_WIDTH_I );
392
                        state.y_sh  <= - SHIFT_RIGHT( state.y, to_integer( state.i ) );
393
 
394
                     -- hyperbolic case
395
                     elsif state.mode( 1 downto 0 ) = VAL_MODE_HYP then
396
 
397
                        state.a_tmp <= resize( - angular_lut( to_integer( state.i ), state.mode( 1 downto 0 ), A_WIDTH), A_WIDTH_I );
398
                        state.y_sh  <= SHIFT_RIGHT( state.y, to_integer( state.i ) );
399
 
400
                     -- linear case
401
                     else
402
 
403
                        state.a_tmp <= resize( - angular_lut( to_integer( state.i ), state.mode( 1 downto 0 ), A_WIDTH  ), A_WIDTH_I ) ;
404
                        state.y_sh  <= ( others => '0' );
405
 
406
                     end if;
407
                     state.x_sh <=   SHIFT_RIGHT( state.x, to_integer( state.i ) );
408
 
409
                  else
410
 
411
                     -- circular case
412
                     if state.mode( 1 downto 0 ) = VAL_MODE_CIR then
413
 
414
                        state.a_tmp <= resize( angular_lut( to_integer( state.i ), state.mode( 1 downto 0 ), A_WIDTH ), A_WIDTH_I );
415
                        state.y_sh  <= SHIFT_RIGHT( state.y, to_integer( state.i ) );
416
 
417
                     -- hyperbolic case
418
                     elsif state.mode( 1 downto 0 ) = VAL_MODE_HYP then
419
 
420
                        state.a_tmp <= resize( angular_lut( to_integer( state.i ), state.mode( 1 downto 0 ), A_WIDTH ), A_WIDTH_I );
421
                        state.y_sh  <= - SHIFT_RIGHT( state.y, to_integer( state.i ) );
422
 
423
                     -- linear case
424
                     else
425
 
426
                        state.a_tmp <= resize( angular_lut( to_integer( state.i ), state.mode( 1 downto 0 ), A_WIDTH ), A_WIDTH_I ) ;
427
                        state.y_sh  <= ( others => '0' );
428
 
429
                     end if;
430
                     state.x_sh <= - SHIFT_RIGHT( state.x, to_integer( state.i ) );
431
 
432
                  end if;
433
 
434
                  -- abort condition
435
                  if(   state.mode( I_FLAG_VEC_ROT ) = '0' and
436
                        state.a = 0 ) then
437
                     state.st <= ST_RM_GAIN;
438
                     state.i  <= ( others => '0' );
439
                  elsif(   state.mode( I_FLAG_VEC_ROT ) = '0' and
440
                        state.a = state.alst ) then
441
                     state.st <= ST_RM_GAIN;
442
                     state.i  <= ( others => '0' );
443
                  elsif(   state.mode( I_FLAG_VEC_ROT ) = '1' and
444
                        state.y = 0 ) then
445
                     state.st <= ST_RM_GAIN;
446
                     state.i  <= ( others => '0' );
447
                  elsif(   state.mode( I_FLAG_VEC_ROT ) = '1' and
448
                        ( state.y = state.ylst ) ) then
449
                     state.st <= ST_RM_GAIN;
450
                     state.i  <= ( others => '0' );
451
                  end if;
452
 
453
                  state.ylst  <= state.y;
454
                  state.alst  <= state.a;
455
 
456
 
457
               else
458
                  state.x <= state.x + state.y_sh;
459
                  state.y <= state.y + state.x_sh;
460
                  state.a <= state.a + state.a_tmp;
461
                  if VAL_MODE_HYP = state.mode( 1 downto 0 )         and
462
                     state.repeate = '0'                             and
463
                     repeat_hyperbolic_it( to_integer( state.i ) )   then
464
                     state.repeate <= '1';
465
                  else
466
                     state.repeate  <= '0';
467
                     state.i        <= state.i+1;
468
                  end if;
469
                  state.do_shift <= '1';
470
               end if;
471
 
472
 
473
 
474
 
475 7 feddischso
 
476 2 feddischso
            --
477
            -- removal of the cordic gain
478
            --
479
            elsif state.st = ST_RM_GAIN then
480
               -- we need RM_GAIN+1 cycles to 
481
               -- calculate the RM_GAIN steps
482
               if state.i = (RM_GAIN) then
483
                 state.st   <= ST_DONE;
484
                   state.i <= ( others => '0' );
485
               else
486
                   state.i  <= state.i + 1;
487
               end if;
488
 
489
               if state.mode( 1 downto 0 ) = VAL_MODE_CIR then
490
                  mult_0_61( state.x, state.x_sh, state.x_sum, to_integer( state.i ), RM_GAIN );
491
                  mult_0_61( state.y, state.y_sh, state.y_sum, to_integer( state.i ), RM_GAIN );
492
               elsif state.mode( 1 downto 0 ) = VAL_MODE_HYP then
493
                  mult_0_21( state.x, state.x_sh, state.x_sum, to_integer( state.i ), RM_GAIN );
494
                  mult_0_21( state.y, state.y_sh, state.y_sum, to_integer( state.i ), RM_GAIN );
495
               else
496
                  state.st    <= ST_DONE;
497
                  state.x_sum <= state.x;
498
                  state.y_sum <= state.y;
499
               end if;
500
 
501
 
502
            elsif state.st = ST_DONE then
503
               state.st    <= ST_IDLE;
504
            end if;
505
            -- end states
506
 
507
 
508
 
509
         end if;
510
         -- end ena
511
 
512
 
513
      end if;
514
      -- end clk
515
 
516
   end process;
517 7 feddischso
   done        <= '1' when state.st = ST_DONE else '0';
518 2 feddischso
   x_o         <= std_logic_vector( state.x_sum );
519
   y_o         <= std_logic_vector( state.y_sum );
520
   a_o         <= std_logic_vector( state.a );
521
 
522
end architecture BEHAVIORAL;
523
 
524
 
525
 

powered by: WebSVN 2.1.0

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