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

Subversion Repositories yac

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

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
%prod( sqrt( 1-2.^(-2 .* [ 1 : 100000 ] ) ) )
72
 
73
 
74
signs = get_rm_gain_shifts( K0, 30 );
75
print_rm_gain_code( fid, signs, K0, 1, 1, 0 );
76
 
77
signs = get_rm_gain_shifts( K1, 30 );
78
print_rm_gain_code( fid, signs, K1, 1, 1, 1 );
79
 
80
signs = get_rm_gain_shifts( K0, 30 );
81
print_rm_gain_code( fid, signs, K0, 1, 0, 0 );
82
 
83
signs = get_rm_gain_shifts( K1, 30 );
84
print_rm_gain_code( fid, signs, K1, 1, 0, 1 );
85
 
86
MAX_A_WIDTH = 32;
87
print_angular_lut( fid, MAX_A_WIDTH );
88
 
89
 
90
fclose( fid );
91
 
92
end
93
 
94
 
95
 
96
 
97
function print_angular_lut( fid, MAX_A_WIDTH )
98
 
99
 
100
    values = round( atan( 2.^-[0:MAX_A_WIDTH] ) / pi * 2^(MAX_A_WIDTH-1)  );
101
 
102
 
103
    fprintf( fid,  '-- Auto-generated function \n' );
104
    fprintf( fid,  '-- by matlab (see c_octave/cordic_iterative_code.m)\n'         );
105
    fprintf( fid,  'function angular_lut( n : integer; mode : std_logic_vector; ANG_WIDTH : natural ) return signed is\n'    );
106
    fprintf( fid,  '   variable result : signed( ANG_WIDTH-1 downto 0 );\n'   );
107
    fprintf( fid,  '   variable temp : signed( MAX_A_WIDTH-1 downto 0 );\n' );
108
    fprintf( fid,  '      begin\n' );
109
    fprintf( fid,  '      if mode = VAL_MODE_CIR then\n' );
110
    fprintf( fid,  '         case n is\n' );
111
    for x = 0 : 10
112
    val     = floor( atan( 2^-x ) * 2^(MAX_A_WIDTH+2-1) );
113
    fprintf( fid,  '            when %d => temp := "', x );
114
    fprintf( fid,  '%c',           dec2bin( val, MAX_A_WIDTH+2 ) );
115
    fprintf( fid,  '"; \t-- %d\n', val );
116
    end
117
    fprintf( fid,  '            when others => temp := to_signed( 2**(MAX_A_WIDTH-1-n), MAX_A_WIDTH );\n' );
118
    fprintf( fid,  '         end case;\n' );
119
    fprintf( fid,  '      elsif mode = VAL_MODE_HYP then\n' );
120
    fprintf( fid,  '         case n is\n' );
121
    for x = 1 : 10
122
    val = floor( atanh( 2^-x ) * 2^(MAX_A_WIDTH+2-1)  );
123
    fprintf( fid,  '            when %d => temp := "', x );
124
    fprintf( fid,  '%c', dec2bin( val, MAX_A_WIDTH+2 ) );
125
    fprintf( fid,  '"; \t-- %d\n', val);
126
    end
127
    fprintf( fid,  '            when others => temp := to_signed( 2**(MAX_A_WIDTH-1-n), MAX_A_WIDTH );\n' );
128
    fprintf( fid,  '         end case;\n' );
129
    fprintf( fid,  '      elsif mode = VAL_MODE_LIN then\n' );
130
    fprintf( fid,  '         temp := ( others => ''0'' );\n' );
131
    fprintf( fid,  '         temp( temp''high-1-n downto 0  ) := ( others => ''1'' );\n' );
132
    fprintf( fid,  '      end if;\n' );
133
    fprintf( fid,  '   result := temp( temp''high downto temp''high-result''length+1 );\n' );
134
    fprintf( fid,  '   return result;\n' );
135
    fprintf( fid,  'end function angular_lut;\n' );
136
end
137
 
138
 
139
function print_rm_gain_code( fid, signs, value, force_pos_err, c_or_vhdl, plus_one )
140
 
141
 
142
    % Default values for arguments
143
    if ~exist( 'force_pos_err', 'var' )
144
        force_neg_err = 0;
145
    end
146
 
147
    if ~exist( 'c_or_vhdl', 'var' )
148
        c_or_vhdl = 0;
149
    end
150
 
151
    val_str = sprintf( '%4.2f', value );
152
    val_str( val_str == '.' ) = ('_' );
153
 
154
    if c_or_vhdl
155
        fprintf( fid, '/*  Auto-generated procedure to multiply "x" with %f */\n', value );
156
        fprintf( fid, '/* "shifts" defines the number of shifts, which are used */\n' );
157
        fprintf( fid,  'switch( shifts )\n{\n' );
158
    end
159
    i_shift = 1;
160
    for x = 1 : length( signs )
161
        if signs( x ) ~= 0
162
 
163
            tmp     = signs( 1 : x );
164
 
165
 
166
            err = value - sum( tmp .* 2.^-( 1 : length( tmp ) ) );
167
            if force_pos_err
168
                if err < 0
169
 
170
                    if( tmp( end ) == 1 )
171
                        tmp( end+1 ) = -1;
172
                        tmp( end-1 ) = 0;
173
                    else
174
                        tmp( end-1 ) = -1;
175
                        tmp( end   ) =  0;
176
                    end
177
                end
178
                err = value - sum( tmp .* 2.^-( 1 : length( tmp ) ) );
179
            end
180
 
181
            index               = 1 : length( tmp );
182
            index( tmp == 0 )   = [];
183
            tmp( tmp == 0 )     = [];
184
            tmp2                =  cell( size ( tmp ) );
185
            tmp2( tmp ==  1 )   = { '+' };
186
            tmp2( tmp == -1 )   = { '-' };
187
 
188
            if c_or_vhdl
189
 
190
                % C-Code
191
                if plus_one
192
                    fprintf( fid,  '   case %d: x = x ', i_shift );
193
                else
194
                    fprintf( fid,  '   case %d: x = ', i_shift );
195
                end
196
 
197
                for y = 1 : length( tmp2 )
198
                    fprintf( fid,  '%c ( x >> %d ) ', tmp2{ y }, index( y ) );
199
                end
200
                fprintf( fid,  '; break; /* error: %.10f */ \n', err );
201
            else
202
 
203
                % VHDL CODE
204
 
205
                fprintf( fid, '\n\n--\n' );
206
                fprintf( fid, '-- Auto-generated procedure to multiply "a" with %f iteratively\n', value );
207
                fprintf( fid, '-- a_sh is a temporary register to store the shifted value, and \n' );
208
                fprintf( fid, '-- sum is a temporary register to sum up the result\n' );
209
                fprintf( fid, '--\n' );
210
                fprintf( fid, 'procedure mult_%s_%.2d( signal a    : in    signed; \n', val_str, i_shift );
211
                fprintf( fid, '                   signal a_sh : inout signed; \n' );
212
                fprintf( fid, '                   signal sum  : inout signed; \n' );
213
                fprintf( fid, '                          cnt  : in    natural ) is \n' );
214
                fprintf( fid, '   begin\n' );
215
                fprintf( fid, '      case cnt is\n' );
216
 
217
                if plus_one
218
                fprintf( fid, '         when   0 => sum  <= a;\n' );
219
                else
220
                fprintf( fid, '         when   0 => sum  <= to_signed( 0, sum''length );\n' );
221
                end
222
                fprintf( fid, '                     a_sh <= SHIFT_RIGHT( a, %d ); \n', index( 1 ) );
223
                fprintf( fid, '         when   1 => sum  <= sum %c a_sh; \n', tmp2{ 1 } );
224
 
225
                for y = 2 : length( tmp2 )
226
                fprintf( fid, '                 a_sh <= SHIFT_RIGHT( a, %d );\n', index( y ) );
227
                fprintf( fid, '         when %3.d => sum <= sum %c a_sh; \n', y, tmp2{ y } );
228
                end
229
                fprintf( fid, '         when others => sum <= sum;\n' );
230
                fprintf( fid, '     end case;\n' );
231
                fprintf( fid, 'end procedure mult_%s_%.2d;\n', val_str, i_shift );
232
            end
233
            i_shift = i_shift+1;
234
        end
235
 
236
    end
237
    if c_or_vhdl
238
        fprintf( fid,  '   default: x = x; break;\n}\n' );
239
    end
240
 
241
 
242
    if ~c_or_vhdl
243
        fprintf( fid, '\n\n--\n' );
244
        fprintf( fid, '-- Auto-generated procedure to multiply "a" with %f iteratively\n', value );
245
        fprintf( fid, '-- a_sh is a temporary register to store the shifted value, and \n' );
246
        fprintf( fid, '-- sum is a temporary register to sum up the result\n' );
247
        fprintf( fid, '--\n' );
248
        fprintf( fid, 'procedure mult_%s( signal   a       : in    signed; \n', val_str );
249
        fprintf( fid, '                   signal   a_sh    : inout signed; \n' );
250
        fprintf( fid, '                   signal   sum     : inout signed; \n' );
251
        fprintf( fid, '                            cnt     : in    natural; \n' );
252
        fprintf( fid, '                   constant RM_GAIN : in    natural ) is \n' );
253
        fprintf( fid, '   begin\n' );
254
        fprintf( fid, '      case RM_GAIN is\n' );
255
        for y = 1 : length( tmp2 )
256
        fprintf( fid, '         when %d => mult_%s_%.2d( a, a_sh, sum, cnt  );\n', y, val_str, y );
257
        end
258
        fprintf( fid, '         when others => mult_%s_%.2d( a, a_sh, sum, cnt  );\n', val_str, y );
259
        fprintf( fid, '      end case;\n' );
260
        fprintf( fid, 'end procedure mult_%s;\n', val_str );
261
    end
262
 
263
 
264
end
265
 
266
function signs = get_rm_gain_shifts( value, N_shifts )
267
    %N_steps = 50;
268
    %signs       = zeros( 1, N_steps );
269
    signs       = [  ];
270
    from_p_n = 1;   % comming from pos or neg
271
 
272
    prev_pos_err = inf;
273
    prev_neg_err = inf;
274
    i_shift = 0;
275
    x = 0;
276
 
277
    while i_shift < N_shifts
278
        x = x + 1;
279
        if isempty( signs )
280
            tmp = 0;
281
        else
282
            tmp = sum( signs .* 2.^-( 1 : length( signs ) ) );
283
        end;
284
 
285
        pos_err = value - ( tmp + 2^-x );
286
        neg_err = value - ( tmp - 2^-x );
287
        signs( end+1 ) = 0;
288
        if      from_p_n == 1 && pos_err < 0  ...
289
            ||  from_p_n == 0 && neg_err > 0
290
            prev_pos_err = pos_err;
291
            prev_neg_err = neg_err;
292
            continue
293
        end
294
        i_shift = i_shift+1;
295
 
296
        if from_p_n == 1 && abs( prev_pos_err ) < abs( pos_err )
297
            signs( x-1 ) = 1;
298
            from_p_n = 0;
299
            neg_err2 = value - ( tmp - 2^-x );
300
            if neg_err2 < 0
301
                signs( x ) = -1;
302
            end
303
 
304
        elseif from_p_n == 0 && abs( prev_neg_err ) < abs( neg_err )
305
            signs( x-1 ) = -1;
306
            from_p_n = 1;
307
            pos_err2 = value - ( tmp + 2^-x );
308
            if pos_err2 > 0
309
                signs( x ) =  1;
310
            end
311
 
312
 
313
        elseif from_p_n == 1 && abs( prev_pos_err ) >= abs( pos_err )
314
            signs( x ) = 1;
315
 
316
        elseif from_p_n == 0 && abs( prev_pos_err ) >= abs( pos_err )
317
            signs( x ) = -1;
318
 
319
        end
320
        prev_pos_err = pos_err;
321
        prev_neg_err = neg_err;
322
 
323
    end
324
 
325
end
326
 
327
 
328
 
329
 
330
 

powered by: WebSVN 2.1.0

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