2 * This is a general recreation of the VHDL ieee.math_real package.
\r
6 // Constants for use below and for general reference
\r
7 // TODO: Bring it out to 12 (or more???) places beyond the decimal?
\r
8 localparam MATH_E = 2.7182818284;
\r
9 localparam MATH_1_OVER_E = 0.3678794411;
\r
10 localparam MATH_PI = 3.1415926536;
\r
11 localparam MATH_2_PI = 6.2831853071;
\r
12 localparam MATH_1_OVER_PI = 0.3183098861;
\r
13 localparam MATH_PI_OVER_2 = 1.5707963267;
\r
14 localparam MATH_PI_OVER_3 = 1.0471975511;
\r
15 localparam MATH_PI_OVER_4 = 0.7853981633;
\r
16 localparam MATH_3_PI_OVER_2 = 4.7123889803;
\r
17 localparam MATH_LOG_OF_2 = 0.6931471805;
\r
18 localparam MATH_LOG_OF_10 = 2.3025850929;
\r
19 localparam MATH_LOG2_OF_E = 1.4426950408;
\r
20 localparam MATH_LOG10_OF_E = 0.4342944819;
\r
21 localparam MATH_SQRT_2 = 1.4142135623;
\r
22 localparam MATH_1_OVER_SQRT_2= 0.7071067811;
\r
23 localparam MATH_SQRT_PI = 1.7724538509;
\r
24 localparam MATH_DEG_TO_RAD = 0.0174532925;
\r
25 localparam MATH_RAD_TO_DEG = 57.2957795130;
\r
27 // The number of iterations to do for the Taylor series approximations
\r
28 localparam EXPLOG_ITERATIONS = 19;
\r
29 localparam COS_ITERATIONS = 8;
\r
31 /* Conversion Routines */
\r
33 // Return the sign of a particular number.
\r
34 function real sign ;
\r
37 sign = x < 0.0 ? 1.0 : 0.0 ;
\r
41 // Return the trunc function of a number
\r
42 function real trunc ;
\r
45 trunc = x - mod(x,1.0) ;
\r
49 // Return the ceiling function of a number.
\r
50 function real ceil ;
\r
54 retval = mod(x,1.0) ;
\r
55 if( retval != 0.0 && x > 0.0 ) retval = x+1.0 ;
\r
57 ceil = trunc(retval) ;
\r
61 // Return the floor function of a number
\r
62 function real floor ;
\r
66 retval = mod(x,1.0) ;
\r
67 if( retval != 0.0 && x < 0.0 ) retval = x - 1.0 ;
\r
69 floor = trunc(retval) ;
\r
73 // Return the round function of a number
\r
74 function real round ;
\r
78 retval = x > 0.0 ? x + 0.5 : x - 0.5 ;
\r
79 round = trunc(retval) ;
\r
83 // Return the fractional remainder of (x mod m)
\r
90 if( retval > m ) begin
\r
91 while( retval > m ) begin
\r
92 retval = retval - m ;
\r
96 while( retval < -m ) begin
\r
97 retval = retval + m ;
\r
104 // Return the max between two real numbers
\r
105 function real realmax ;
\r
109 realmax = x > y ? x : y ;
\r
113 // Return the min between two real numbers
\r
114 function real realmin ;
\r
118 realmin = x > y ? y : x ;
\r
122 /* Random Numbers */
\r
124 // Generate Gaussian distributed variables
\r
125 function real gaussian ;
\r
128 real u1, u2, v1, v2, s ;
\r
131 while( s >= 1.0 ) begin
\r
132 // Two random numbers between 0 and 1
\r
133 u1 = $random/4294967296.0 + 0.5 ;
\r
134 u2 = $random/4294967296.0 + 0.5 ;
\r
135 // Adjust to be between -1,1
\r
138 // Polar mag squared
\r
139 s = (v1*v1 + v2*v2) ;
\r
141 gaussian = mean + sqrt((-2.0*log(s))/s) * v1 * sqrt(var) ;
\r
142 // gaussian2 = mean + sqrt(-2*log(s)/s)*v2 * sqrt(var) ;
\r
146 /* Roots and Log Functions */
\r
148 // Return the square root of a number
\r
149 function real sqrt ;
\r
153 sqrt = (x == 0.0) ? 0.0 : powr(x,0.5) ;
\r
157 // Return the cube root of a number
\r
158 function real cbrt ;
\r
162 cbrt = (x == 0.0) ? 0.0 : powr(x,1.0/3.0) ;
\r
166 // Return the absolute value of a real value
\r
167 function real abs ;
\r
170 abs = (x > 0.0) ? x : -x ;
\r
174 // Return a real value raised to an integer power
\r
175 function real pow ;
\r
184 retval = b*retval ;
\r
186 pow = x < 0 ? (1.0/retval) : retval ;
\r
190 // Return a real value raised to a real power
\r
191 function real powr ;
\r
195 powr = exp(x*log(b)) ;
\r
199 // Return the evaluation of e^x where e is the natural logarithm base
\r
200 // NOTE: This is the Taylor series expansion of e^x
\r
201 function real exp ;
\r
211 for( i = 1 ; i < EXPLOG_ITERATIONS ; i = i + 1 ) begin
\r
213 nm1_fact = nm1_fact * i ;
\r
214 retval = retval + powm1/nm1_fact ;
\r
220 // Return the evaluation log(x)
\r
221 function real log ;
\r
232 while( newx > MATH_E ) begin
\r
233 whole = whole + 1.0 ;
\r
234 newx = newx / MATH_E ;
\r
236 xm1oxp1 = (newx-1.0)/(newx+1.0) ;
\r
237 for( i = 0 ; i < EXPLOG_ITERATIONS ; i = i + 1 ) begin
\r
238 retval = retval + pow(xm1oxp1,2*i+1)/(2.0*i+1.0) ;
\r
240 log = whole+2.0*retval ;
\r
244 // Return the evaluation ln(x) (same as log(x))
\r
252 // Return the evaluation log_2(x)
\r
253 function real log2 ;
\r
256 log2 = log(x)/MATH_LOG_OF_2 ;
\r
260 function real log10 ;
\r
263 log10 = log(x)/MATH_LOG_OF_10 ;
\r
267 function real log_base ;
\r
271 log_base = log(x)/log(b) ;
\r
275 /* Trigonometric Functions */
\r
277 // Internal function to reduce a value to be between [-pi:pi]
\r
278 function real reduce ;
\r
283 while( abs(retval) > MATH_PI ) begin
\r
284 retval = retval > MATH_PI ?
\r
285 (retval - MATH_2_PI) :
\r
286 (retval + MATH_2_PI) ;
\r
292 // Return the cos of a number in radians
\r
293 function real cos ;
\r
306 for( i = 1 ; i < COS_ITERATIONS ; i = i + 1 ) begin
\r
307 sign = -2*(i % 2)+1 ;
\r
308 xsqnm1 = xsqnm1*newx*newx ;
\r
309 twonm1fact = twonm1fact * (2.0*i) * (2.0*i-1.0) ;
\r
310 retval = retval + sign*(xsqnm1/twonm1fact) ;
\r
316 // Return the sin of a number in radians
\r
317 function real sin ;
\r
320 sin = cos(x - MATH_PI_OVER_2) ;
\r
324 // Return the tan of a number in radians
\r
325 function real tan ;
\r
328 tan = sin(x) / cos(x) ;
\r
332 // Return the arcsin in radians of a number
\r
333 function real arcsin ;
\r
336 arcsin = 2.0*arctan(x/(1.0+sqrt(1.0-x*x))) ;
\r
340 // Return the arccos in radians of a number
\r
341 function real arccos ;
\r
344 arccos = MATH_PI_OVER_2-arcsin(x) ;
\r
348 // Return the arctan in radians of a number
\r
349 // TODO: Make sure this REALLY does work as it is supposed to!
\r
350 function real arctan ;
\r
360 twoiotwoip1 = 1.0 ;
\r
363 while( newx > 1.0 ) begin
\r
365 newx = newx/(1.0+sqrt(1.0+newx*newx)) ;
\r
368 for( i = 1 ; i < 2*COS_ITERATIONS ; i = i + 1 ) begin
\r
369 y = y*((newx*newx)/(1+newx*newx)) ;
\r
370 twoiotwoip1 = twoiotwoip1 * (2.0*i)/(2.0*i+1.0) ;
\r
371 retval = retval + twoiotwoip1*y ;
\r
373 retval = retval * (newx/(1+newx*newx)) ;
\r
374 retval = retval * mult ;
\r
376 arctan = (x > 0.0) ? retval : -retval ;
\r
380 // Return the arctan in radians of a ratio x/y
\r
381 // TODO: Test to make sure this works as it is supposed to!
\r
382 function real arctan_xy ;
\r
388 if( x < 0.0 ) retval = MATH_PI - arctan(-abs(y)/x) ;
\r
389 else if( x > 0.0 ) retval = arctan(abs(y)/x) ;
\r
390 else if( x == 0.0 ) retval = MATH_PI_OVER_2 ;
\r
391 arctan_xy = (y < 0.0) ? -retval : retval ;
\r
395 /* Hyperbolic Functions */
\r
397 // Return the sinh of a number
\r
398 function real sinh ;
\r
401 sinh = (exp(x) - exp(-x))/2.0 ;
\r
405 // Return the cosh of a number
\r
406 function real cosh ;
\r
409 cosh = (exp(x) + exp(-x))/2.0 ;
\r
413 // Return the tanh of a number
\r
414 function real tanh ;
\r
419 tanh = (e2x+1.0)/(e2x-1.0) ;
\r
423 // Return the arcsinh of a number
\r
424 function real arcsinh ;
\r
427 arcsinh = log(x+sqrt(x*x+1.0)) ;
\r
431 // Return the arccosh of a number
\r
432 function real arccosh ;
\r
435 arccosh = ln(x+sqrt(x*x-1.0)) ;
\r
439 // Return the arctanh of a number
\r
440 function real arctanh ;
\r
443 arctanh = 0.5*ln((1.0+x)/(1.0-x)) ;
\r
448 $display( "cos(MATH_PI_OVER_3): %f", cos(MATH_PI_OVER_3) ) ;
\r
449 $display( "sin(MATH_PI_OVER_3): %f", sin(MATH_PI_OVER_3) ) ;
\r
450 $display( "sign(-10): %f", sign(-10) ) ;
\r
451 $display( "realmax(MATH_PI,MATH_E): %f", realmax(MATH_PI,MATH_E) ) ;
\r
452 $display( "realmin(MATH_PI,MATH_E): %f", realmin(MATH_PI,MATH_E) ) ;
\r
453 $display( "mod(MATH_PI,MATH_E): %f", mod(MATH_PI,MATH_E) ) ;
\r
454 $display( "ceil(-MATH_PI): %f", ceil(-MATH_PI) ) ;
\r
455 $display( "ceil(4.0): %f", ceil(4.0) ) ;
\r
456 $display( "ceil(3.99999999999999): %f", ceil(3.99999999999999) ) ;
\r
457 $display( "pow(MATH_PI,2): %f", pow(MATH_PI,2) ) ;
\r
458 $display( "gaussian(1.0,1.0): %f", gaussian(1.0,1.0) ) ;
\r
459 $display( "round(MATH_PI): %f", round(MATH_PI) ) ;
\r
460 $display( "trunc(-MATH_PI): %f", trunc(-MATH_PI) ) ;
\r
461 $display( "ceil(-MATH_PI): %f", ceil(-MATH_PI) ) ;
\r
462 $display( "floor(MATH_PI): %f", floor(MATH_PI) ) ;
\r
463 $display( "round(e): %f", round(MATH_E)) ;
\r
464 $display( "ceil(-e): %f", ceil(-MATH_E)) ;
\r
465 $display( "exp(MATH_PI): %f", exp(MATH_PI) ) ;
\r
466 $display( "log2(MATH_PI): %f", log2(MATH_PI) ) ;
\r
467 $display( "log_base(pow(2,32),2): %f", log_base(pow(2,32),2) ) ;
\r
468 $display( "ln(0.1): %f", log(0.1) ) ;
\r
469 $display( "cbrt(7): %f", cbrt(7) ) ;
\r
470 $display( "cos(MATH_2_PI): %f", cos(20*MATH_2_PI) ) ;
\r
471 $display( "sin(-MATH_2_PI): %f", sin(-50*MATH_2_PI) ) ;
\r
472 $display( "sinh(MATH_E): %f", sinh(MATH_E) ) ;
\r
473 $display( "cosh(MATH_2_PI): %f", cosh(MATH_2_PI) ) ;
\r
474 $display( "arctan_xy(-4,3): %f", arctan_xy(-4,3) ) ;
\r
475 $display( "arctan(MATH_PI): %f", arctan(MATH_PI) ) ;
\r
476 $display( "arctan(-MATH_E/2): %f", arctan(-MATH_E/2) ) ;
\r
477 $display( "arctan(MATH_PI_OVER_2): %f", arctan(MATH_PI_OVER_2) ) ;
\r
478 $display( "arctan(1/7) = %f", arctan(1.0/7.0) ) ;
\r
479 $display( "arctan(3/79) = %f", arctan(3.0/79.0) ) ;
\r
480 $display( "pi/4 ?= %f", 5*arctan(1.0/7.0)+2*arctan(3.0/79.0) ) ;
\r
481 $display( "arcsin(1.0): %f", arcsin(1.0) ) ;
\r
482 $display( "cos(pi/2): %f", cos(MATH_PI_OVER_2)) ;
\r
483 $display( "arccos(cos(pi/2)): %f", arccos(cos(MATH_PI_OVER_2)) ) ;
\r
484 $display( "cos(0): %f", cos(0) ) ;
\r
485 $display( "cos(MATH_PI_OVER_4): %f", cos(MATH_PI_OVER_4) ) ;
\r
486 $display( "cos(MATH_PI_OVER_2): %f", cos(MATH_PI_OVER_2) ) ;
\r
487 $display( "cos(3*MATH_PI_OVER_4): %f", cos(3*MATH_PI_OVER_4) ) ;
\r
488 $display( "cos(MATH_PI): %f", cos(MATH_PI) ) ;
\r
489 $display( "cos(5*MATH_PI_OVER_4): %f", cos(5*MATH_PI_OVER_4) ) ;
\r
490 $display( "cos(6*MATH_PI_OVER_4): %f", cos(6*MATH_PI_OVER_4) ) ;
\r
491 $display( "cos(7*MATH_PI_OVER_4): %f", cos(7*MATH_PI_OVER_4) ) ;
\r
492 $display( "cos(8*MATH_PI_OVER_4): %f", cos(8*MATH_PI_OVER_4) ) ;
\r