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

Subversion Repositories yac

[/] [yac/] [trunk/] [c_octave/] [cordic_iterative_code.m] - Blame information for rev 4

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

Line No. Rev Author Line
1 2 feddischso
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2
%%%%                                                                    %%%%
3
%%%%  File           : cordic_iterative_code.m                          %%%%
4
%%%%  Project        : YAC (Yet Another CORDIC Core)                    %%%%
5
%%%%  Creation       : Feb. 2014                                        %%%%
6
%%%%  Limitations    :                                                  %%%%
7
%%%%  Platform       : Linux, Mac, Windows                              %%%%
8
%%%%  Target         : Octave, Matlab                                   %%%%
9
%%%%                                                                    %%%%
10
%%%%  Author(s):     : Christian Haettich                               %%%%
11
%%%%  Email          : feddischson@opencores.org                        %%%%
12
%%%%                                                                    %%%%
13
%%%%                                                                    %%%%
14
%%%%%                                                                  %%%%%
15
%%%%                                                                    %%%%
16
%%%%  Description                                                       %%%%
17
%%%%   Script to create VHDL and C code.                                %%%%
18
%%%%   Two functionalities are created:                                 %%%%
19
%%%%                                                                    %%%%
20
%%%%         - A division by a fixed value                              %%%%
21
%%%%           (to remove the cordic gain)                              %%%%
22
%%%%                                                                    %%%%
23
%%%%         - Atan/Atanh/Linear lookup table                           %%%%
24
%%%%%                                                                  %%%%%
25
%%%%                                                                    %%%%
26
%%%%  TODO                                                              %%%%
27
%%%%        Some documentation and function description                 %%%%
28
%%%%                                                                    %%%%
29
%%%%                                                                    %%%%
30
%%%%                                                                    %%%%
31
%%%%                                                                    %%%%
32
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
33
%%%%                                                                    %%%%
34
%%%%                  Copyright Notice                                  %%%%
35
%%%%                                                                    %%%%
36
%%%% This file is part of YAC - Yet Another CORDIC Core                 %%%%
37
%%%% Copyright (c) 2014, Author(s), All rights reserved.                %%%%
38
%%%%                                                                    %%%%
39
%%%% YAC is free software; you can redistribute it and/or               %%%%
40
%%%% modify it under the terms of the GNU Lesser General Public         %%%%
41
%%%% License as published by the Free Software Foundation; either       %%%%
42
%%%% version 3.0 of the License, or (at your option) any later version. %%%%
43
%%%%                                                                    %%%%
44
%%%% YAC is distributed in the hope that it will be useful,             %%%%
45
%%%% but WITHOUT ANY WARRANTY; without even the implied warranty of     %%%%
46
%%%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU  %%%%
47
%%%% Lesser General Public License for more details.                    %%%%
48
%%%%                                                                    %%%%
49
%%%% You should have received a copy of the GNU Lesser General Public   %%%%
50
%%%% License along with this library. If not, download it from          %%%%
51
%%%% http://www.gnu.org/licenses/lgpl                                   %%%%
52
%%%%                                                                    %%%%
53
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
54
 
55
 
56
 
57
 
58
 
59
 
60
function cordic_iterative_code( outfile )
61
 
62
if ~exist( 'outfile', 'var' )
63
   outfile = 'autogen_code.txt';
64
end
65
 
66
fid = fopen( outfile, 'w' );
67
 
68
% TODO: calculate these values
69
K0 = 0.607252935009;
70
K1 = 0.207497067763;
71 3 feddischso
<<<<<<< HEAD
72 4 feddischso
<<<<<<< HEAD
73 2 feddischso
%prod( sqrt( 1-2.^(-2 .* [ 1 : 100000 ] ) ) )
74
 
75 3 feddischso
=======
76
>>>>>>> initial commit
77 4 feddischso
=======
78
%prod( sqrt( 1-2.^(-2 .* [ 1 : 100000 ] ) ) )
79 2 feddischso
 
80 4 feddischso
>>>>>>> Updated C and RTL model as well as the documentation
81
 
82 2 feddischso
signs = get_rm_gain_shifts( K0, 30 );
83
print_rm_gain_code( fid, signs, K0, 1, 1, 0 );
84
 
85
signs = get_rm_gain_shifts( K1, 30 );
86
print_rm_gain_code( fid, signs, K1, 1, 1, 1 );
87
 
88
signs = get_rm_gain_shifts( K0, 30 );
89
print_rm_gain_code( fid, signs, K0, 1, 0, 0 );
90
 
91
signs = get_rm_gain_shifts( K1, 30 );
92
print_rm_gain_code( fid, signs, K1, 1, 0, 1 );
93
 
94
MAX_A_WIDTH = 32;
95 3 feddischso
<<<<<<< HEAD
96 4 feddischso
<<<<<<< HEAD
97 2 feddischso
print_angular_lut( fid, MAX_A_WIDTH );
98 3 feddischso
=======
99
print_angular_lut( fid, MAX_A_WIDTH )
100
>>>>>>> initial commit
101 4 feddischso
=======
102
print_angular_lut( fid, MAX_A_WIDTH );
103
>>>>>>> Updated C and RTL model as well as the documentation
104 2 feddischso
 
105
 
106
fclose( fid );
107
 
108
end
109
 
110
 
111
 
112
 
113
function print_angular_lut( fid, MAX_A_WIDTH )
114
 
115
 
116
    values = round( atan( 2.^-[0:MAX_A_WIDTH] ) / pi * 2^(MAX_A_WIDTH-1)  );
117
 
118
 
119
    fprintf( fid,  '-- Auto-generated function \n' );
120
    fprintf( fid,  '-- by matlab (see c_octave/cordic_iterative_code.m)\n'         );
121
    fprintf( fid,  'function angular_lut( n : integer; mode : std_logic_vector; ANG_WIDTH : natural ) return signed is\n'    );
122
    fprintf( fid,  '   variable result : signed( ANG_WIDTH-1 downto 0 );\n'   );
123
    fprintf( fid,  '   variable temp : signed( MAX_A_WIDTH-1 downto 0 );\n' );
124
    fprintf( fid,  '      begin\n' );
125
    fprintf( fid,  '      if mode = VAL_MODE_CIR then\n' );
126
    fprintf( fid,  '         case n is\n' );
127
    for x = 0 : 10
128
    val     = floor( atan( 2^-x ) * 2^(MAX_A_WIDTH+2-1) );
129
    fprintf( fid,  '            when %d => temp := "', x );
130
    fprintf( fid,  '%c',           dec2bin( val, MAX_A_WIDTH+2 ) );
131
    fprintf( fid,  '"; \t-- %d\n', val );
132
    end
133
    fprintf( fid,  '            when others => temp := to_signed( 2**(MAX_A_WIDTH-1-n), MAX_A_WIDTH );\n' );
134
    fprintf( fid,  '         end case;\n' );
135
    fprintf( fid,  '      elsif mode = VAL_MODE_HYP then\n' );
136
    fprintf( fid,  '         case n is\n' );
137
    for x = 1 : 10
138
    val = floor( atanh( 2^-x ) * 2^(MAX_A_WIDTH+2-1)  );
139
    fprintf( fid,  '            when %d => temp := "', x );
140
    fprintf( fid,  '%c', dec2bin( val, MAX_A_WIDTH+2 ) );
141
    fprintf( fid,  '"; \t-- %d\n', val);
142
    end
143
    fprintf( fid,  '            when others => temp := to_signed( 2**(MAX_A_WIDTH-1-n), MAX_A_WIDTH );\n' );
144
    fprintf( fid,  '         end case;\n' );
145
    fprintf( fid,  '      elsif mode = VAL_MODE_LIN then\n' );
146
    fprintf( fid,  '         temp := ( others => ''0'' );\n' );
147
    fprintf( fid,  '         temp( temp''high-1-n downto 0  ) := ( others => ''1'' );\n' );
148
    fprintf( fid,  '      end if;\n' );
149
    fprintf( fid,  '   result := temp( temp''high downto temp''high-result''length+1 );\n' );
150
    fprintf( fid,  '   return result;\n' );
151
    fprintf( fid,  'end function angular_lut;\n' );
152
end
153
 
154
 
155
function print_rm_gain_code( fid, signs, value, force_pos_err, c_or_vhdl, plus_one )
156
 
157
 
158
    % Default values for arguments
159
    if ~exist( 'force_pos_err', 'var' )
160
        force_neg_err = 0;
161
    end
162
 
163
    if ~exist( 'c_or_vhdl', 'var' )
164
        c_or_vhdl = 0;
165
    end
166
 
167
    val_str = sprintf( '%4.2f', value );
168
    val_str( val_str == '.' ) = ('_' );
169
 
170
    if c_or_vhdl
171
        fprintf( fid, '/*  Auto-generated procedure to multiply "x" with %f */\n', value );
172
        fprintf( fid, '/* "shifts" defines the number of shifts, which are used */\n' );
173
        fprintf( fid,  'switch( shifts )\n{\n' );
174
    end
175
    i_shift = 1;
176
    for x = 1 : length( signs )
177
        if signs( x ) ~= 0
178
 
179
            tmp     = signs( 1 : x );
180
 
181
 
182
            err = value - sum( tmp .* 2.^-( 1 : length( tmp ) ) );
183
            if force_pos_err
184
                if err < 0
185
 
186
                    if( tmp( end ) == 1 )
187
                        tmp( end+1 ) = -1;
188
                        tmp( end-1 ) = 0;
189
                    else
190
                        tmp( end-1 ) = -1;
191
                        tmp( end   ) =  0;
192
                    end
193
                end
194
                err = value - sum( tmp .* 2.^-( 1 : length( tmp ) ) );
195
            end
196
 
197
            index               = 1 : length( tmp );
198
            index( tmp == 0 )   = [];
199
            tmp( tmp == 0 )     = [];
200
            tmp2                =  cell( size ( tmp ) );
201
            tmp2( tmp ==  1 )   = { '+' };
202
            tmp2( tmp == -1 )   = { '-' };
203
 
204
            if c_or_vhdl
205
 
206
                % C-Code
207
                if plus_one
208
                    fprintf( fid,  '   case %d: x = x ', i_shift );
209
                else
210
                    fprintf( fid,  '   case %d: x = ', i_shift );
211
                end
212
 
213
                for y = 1 : length( tmp2 )
214 3 feddischso
<<<<<<< HEAD
215 4 feddischso
<<<<<<< HEAD
216 2 feddischso
                    fprintf( fid,  '%c ( x >> %d ) ', tmp2{ y }, index( y ) );
217 3 feddischso
=======
218
                    fprintf( fid,  '%c ( x >> %d ) ', tmp2{ y }, index( y ) )
219
>>>>>>> initial commit
220 4 feddischso
=======
221
                    fprintf( fid,  '%c ( x >> %d ) ', tmp2{ y }, index( y ) );
222
>>>>>>> Updated C and RTL model as well as the documentation
223 2 feddischso
                end
224
                fprintf( fid,  '; break; /* error: %.10f */ \n', err );
225
            else
226
 
227
                % VHDL CODE
228
 
229
                fprintf( fid, '\n\n--\n' );
230
                fprintf( fid, '-- Auto-generated procedure to multiply "a" with %f iteratively\n', value );
231
                fprintf( fid, '-- a_sh is a temporary register to store the shifted value, and \n' );
232
                fprintf( fid, '-- sum is a temporary register to sum up the result\n' );
233
                fprintf( fid, '--\n' );
234
                fprintf( fid, 'procedure mult_%s_%.2d( signal a    : in    signed; \n', val_str, i_shift );
235
                fprintf( fid, '                   signal a_sh : inout signed; \n' );
236
                fprintf( fid, '                   signal sum  : inout signed; \n' );
237
                fprintf( fid, '                          cnt  : in    natural ) is \n' );
238
                fprintf( fid, '   begin\n' );
239
                fprintf( fid, '      case cnt is\n' );
240
 
241
                if plus_one
242
                fprintf( fid, '         when   0 => sum  <= a;\n' );
243
                else
244
                fprintf( fid, '         when   0 => sum  <= to_signed( 0, sum''length );\n' );
245
                end
246
                fprintf( fid, '                     a_sh <= SHIFT_RIGHT( a, %d ); \n', index( 1 ) );
247
                fprintf( fid, '         when   1 => sum  <= sum %c a_sh; \n', tmp2{ 1 } );
248
 
249
                for y = 2 : length( tmp2 )
250
                fprintf( fid, '                 a_sh <= SHIFT_RIGHT( a, %d );\n', index( y ) );
251
                fprintf( fid, '         when %3.d => sum <= sum %c a_sh; \n', y, tmp2{ y } );
252
                end
253
                fprintf( fid, '         when others => sum <= sum;\n' );
254
                fprintf( fid, '     end case;\n' );
255
                fprintf( fid, 'end procedure mult_%s_%.2d;\n', val_str, i_shift );
256
            end
257
            i_shift = i_shift+1;
258
        end
259
 
260
    end
261
    if c_or_vhdl
262
        fprintf( fid,  '   default: x = x; break;\n}\n' );
263
    end
264
 
265
 
266
    if ~c_or_vhdl
267
        fprintf( fid, '\n\n--\n' );
268
        fprintf( fid, '-- Auto-generated procedure to multiply "a" with %f iteratively\n', value );
269
        fprintf( fid, '-- a_sh is a temporary register to store the shifted value, and \n' );
270
        fprintf( fid, '-- sum is a temporary register to sum up the result\n' );
271
        fprintf( fid, '--\n' );
272
        fprintf( fid, 'procedure mult_%s( signal   a       : in    signed; \n', val_str );
273
        fprintf( fid, '                   signal   a_sh    : inout signed; \n' );
274
        fprintf( fid, '                   signal   sum     : inout signed; \n' );
275
        fprintf( fid, '                            cnt     : in    natural; \n' );
276
        fprintf( fid, '                   constant RM_GAIN : in    natural ) is \n' );
277
        fprintf( fid, '   begin\n' );
278
        fprintf( fid, '      case RM_GAIN is\n' );
279
        for y = 1 : length( tmp2 )
280
        fprintf( fid, '         when %d => mult_%s_%.2d( a, a_sh, sum, cnt  );\n', y, val_str, y );
281
        end
282
        fprintf( fid, '         when others => mult_%s_%.2d( a, a_sh, sum, cnt  );\n', val_str, y );
283
        fprintf( fid, '      end case;\n' );
284
        fprintf( fid, 'end procedure mult_%s;\n', val_str );
285
    end
286
 
287
 
288
end
289
 
290
function signs = get_rm_gain_shifts( value, N_shifts )
291
    %N_steps = 50;
292
    %signs       = zeros( 1, N_steps );
293
    signs       = [  ];
294
    from_p_n = 1;   % comming from pos or neg
295
 
296
    prev_pos_err = inf;
297
    prev_neg_err = inf;
298
    i_shift = 0;
299
    x = 0;
300
 
301
    while i_shift < N_shifts
302
        x = x + 1;
303
        if isempty( signs )
304
            tmp = 0;
305
        else
306
            tmp = sum( signs .* 2.^-( 1 : length( signs ) ) );
307
        end;
308
 
309
        pos_err = value - ( tmp + 2^-x );
310
        neg_err = value - ( tmp - 2^-x );
311
        signs( end+1 ) = 0;
312
        if      from_p_n == 1 && pos_err < 0  ...
313
            ||  from_p_n == 0 && neg_err > 0
314
            prev_pos_err = pos_err;
315
            prev_neg_err = neg_err;
316
            continue
317
        end
318
        i_shift = i_shift+1;
319
 
320
        if from_p_n == 1 && abs( prev_pos_err ) < abs( pos_err )
321
            signs( x-1 ) = 1;
322
            from_p_n = 0;
323
            neg_err2 = value - ( tmp - 2^-x );
324
            if neg_err2 < 0
325
                signs( x ) = -1;
326
            end
327
 
328
        elseif from_p_n == 0 && abs( prev_neg_err ) < abs( neg_err )
329
            signs( x-1 ) = -1;
330
            from_p_n = 1;
331
            pos_err2 = value - ( tmp + 2^-x );
332
            if pos_err2 > 0
333
                signs( x ) =  1;
334
            end
335
 
336
 
337
        elseif from_p_n == 1 && abs( prev_pos_err ) >= abs( pos_err )
338
            signs( x ) = 1;
339
 
340
        elseif from_p_n == 0 && abs( prev_pos_err ) >= abs( pos_err )
341
            signs( x ) = -1;
342
 
343
        end
344
        prev_pos_err = pos_err;
345
        prev_neg_err = neg_err;
346
 
347
    end
348
 
349
end
350
 
351
 
352
 
353
 
354
 

powered by: WebSVN 2.1.0

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