-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathmathpack.vhd
1524 lines (1365 loc) · 48.8 KB
/
mathpack.vhd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
------------------------------------------------------------------------
--
-- This source file may be used and distributed without restriction.
-- No declarations or definitions shall be added to this package.
-- This package cannot be sold or distributed for profit.
--
-- ****************************************************************
-- * *
-- * W A R N I N G *
-- * *
-- * This DRAFT version IS NOT endorsed or approved by IEEE *
-- * *
-- ****************************************************************
--
-- Title: PACKAGE MATH_REAL
--
-- Library: This package shall be compiled into a library
-- symbolically named IEEE.
--
-- Purpose: VHDL declarations for mathematical package MATH_REAL
-- which contains common real constants, common real
-- functions, and real trascendental functions.
--
-- Author: IEEE VHDL Math Package Study Group
--
-- Notes:
-- The package body shall be considered the formal definition of
-- the semantics of this package. Tool developers may choose to implement
-- the package body in the most efficient manner available to them.
--
-- History:
-- Version 0.1 (Strawman) Jose A. Torres 6/22/92
-- Version 0.2 Jose A. Torres 1/15/93
-- Version 0.3 Jose A. Torres 4/13/93
-- Version 0.4 Jose A. Torres 4/19/93
-- Version 0.5 Jose A. Torres 4/20/93 Added RANDOM()
-- Version 0.6 Jose A. Torres 4/23/93 Renamed RANDOM as
-- UNIFORM. Modified
-- rights banner.
-- Version 0.7 Jose A. Torres 5/28/93 Rev up for compatibility
-- with package body.
-------------------------------------------------------------
Library IEEE;
Package MATH_REAL is
--
-- commonly used constants
--
constant MATH_E : real := 2.71828_18284_59045_23536;
-- value of e
constant MATH_1_E: real := 0.36787_94411_71442_32160;
-- value of 1/e
constant MATH_PI : real := 3.14159_26535_89793_23846;
-- value of pi
constant MATH_1_PI : real := 0.31830_98861_83790_67154;
-- value of 1/pi
constant MATH_LOG_OF_2: real := 0.69314_71805_59945_30942;
-- natural log of 2
constant MATH_LOG_OF_10: real := 2.30258_50929_94045_68402;
-- natural log of10
constant MATH_LOG2_OF_E: real := 1.44269_50408_88963_4074;
-- log base 2 of e
constant MATH_LOG10_OF_E: real := 0.43429_44819_03251_82765;
-- log base 10 of e
constant MATH_SQRT2: real := 1.41421_35623_73095_04880;
-- sqrt of 2
constant MATH_SQRT1_2: real := 0.70710_67811_86547_52440;
-- sqrt of 1/2
constant MATH_SQRT_PI: real := 1.77245_38509_05516_02730;
-- sqrt of pi
constant MATH_DEG_TO_RAD: real := 0.01745_32925_19943_29577;
-- conversion factor from degree to radian
constant MATH_RAD_TO_DEG: real := 57.29577_95130_82320_87685;
-- conversion factor from radian to degree
--
-- attribute for functions whose implementation is foreign (C native)
--
--attribute FOREIGN : string; -- predefined attribute in VHDL-1992
--
-- function declarations
--
function SIGN (X: real ) return real;
-- returns 1.0 if X > 0.0; 0.0 if X == 0.0; -1.0 if X < 0.0
function CEIL (X : real ) return real;
-- returns smallest integer value (as real) not less than X
function FLOOR (X : real ) return real;
-- returns largest integer value (as real) not greater than X
function ROUND (X : real ) return real;
-- returns integer FLOOR(X + 0.5) if X > 0;
-- return integer CEIL(X - 0.5) if X < 0
function FMAX (X, Y : real ) return real;
-- returns the algebraically larger of X and Y
function FMIN (X, Y : real ) return real;
-- returns the algebraically smaller of X and Y
procedure UNIFORM (variable Seed1,Seed2:inout integer; variable X:out real);
-- returns a pseudo-random number with uniform distribution in the
-- interval (0.0, 1.0).
-- Before the first call to UNIFORM, the seed values (Seed1, Seed2) must
-- be initialized to values in the range [1, 2147483562] and
-- [1, 2147483398] respectively. The seed values are modified after
-- each call to UNIFORM.
-- This random number generator is portable for 32-bit computers, and
-- it has period ~2.30584*(10**18) for each set of seed values.
--
-- For VHDL-1992, the seeds will be global variables, functions to
-- initialize their values (INIT_SEED) will be provided, and the UNIFORM
-- procedure call will be modified accordingly.
-- function SRAND (seed: in integer ) return integer;
-- --
-- -- sets value of seed for sequence of
-- -- pseudo-random numbers.
-- -- It uses the foreign native C function srand().
-- attribute FOREIGN of SRAND : function is "C_NATIVE";
--
-- function RAND return integer;
-- --
-- -- returns an integer pseudo-random number with uniform distribution.
-- -- It uses the foreign native C function rand().
-- -- Seed for the sequence is initialized with the
-- -- SRAND() function and value of the seed is changed every
-- -- time SRAND() is called, but it is not visible.
-- -- The range of generated values is platform dependent.
-- attribute FOREIGN of RAND : function is "C_NATIVE";
--
-- function GET_RAND_MAX return integer;
-- --
-- -- returns the upper bound of the range of the
-- -- pseudo-random numbers generated by RAND().
-- -- The support for this function is platform dependent, and
-- -- it uses foreign native C functions or constants.
-- -- It may not be available in some platforms.
-- -- Note: the value of (RAND() / GET_RAND_MAX()) is a
-- -- pseudo-random number distributed between 0 & 1.
-- attribute FOREIGN of GET_RAND_MAX : function is "C_NATIVE";
function SQRT (X : real ) return real;
-- returns square root of X; X >= 0
function CBRT (X : real ) return real;
-- returns cube root of X
function "**" (X : integer; Y : real) return real;
-- returns Y power of X ==> X**Y;
-- error if X = 0 and Y <= 0.0
-- error if X < 0 and Y does not have an integer value
function "**" (X : real; Y : real) return real;
-- returns Y power of X ==> X**Y;
-- error if X = 0.0 and Y <= 0.0
-- error if X < 0.0 and Y does not have an integer value
function EXP (X : real ) return real;
-- returns e**X; where e = MATH_E
function LOG (X : real ) return real;
-- returns natural logarithm of X; X > 0
function LOG (BASE: positive; X : real) return real;
-- returns logarithm base BASE of X; X > 0
function SIN (X : real ) return real;
-- returns sin X; X in radians
function COS ( X : real ) return real;
-- returns cos X; X in radians
function TAN (X : real ) return real;
-- returns tan X; X in radians
-- X /= ((2k+1) * PI/2), where k is an integer
function ASIN (X : real ) return real;
-- returns -PI/2 < asin X < PI/2; | X | <= 1
function ACOS (X : real ) return real;
-- returns 0 < acos X < PI; | X | <= 1
function ATAN (X : real) return real;
-- returns -PI/2 < atan X < PI/2
function ATAN2 (X : real; Y : real) return real;
-- returns atan (X/Y); -PI < atan2(X,Y) < PI; Y /= 0.0
function SINH (X : real) return real;
-- hyperbolic sine; returns (e**X - e**(-X))/2
function COSH (X : real) return real;
-- hyperbolic cosine; returns (e**X + e**(-X))/2
function TANH (X : real) return real;
-- hyperbolic tangent; -- returns (e**X - e**(-X))/(e**X + e**(-X))
function ASINH (X : real) return real;
-- returns ln( X + sqrt( X**2 + 1))
function ACOSH (X : real) return real;
-- returns ln( X + sqrt( X**2 - 1)); X >= 1
function ATANH (X : real) return real;
-- returns (ln( (1 + X)/(1 - X)))/2 ; | X | < 1
end MATH_REAL;
---------------------------------------------------------------
--
-- This source file may be used and distributed without restriction.
-- No declarations or definitions shall be included in this package.
-- This package cannot be sold or distributed for profit.
--
-- ****************************************************************
-- * *
-- * W A R N I N G *
-- * *
-- * This DRAFT version IS NOT endorsed or approved by IEEE *
-- * *
-- ****************************************************************
--
-- Title: PACKAGE MATH_COMPLEX
--
-- Purpose: VHDL declarations for mathematical package MATH_COMPLEX
-- which contains common complex constants and basic complex
-- functions and operations.
--
-- Author: IEEE VHDL Math Package Study Group
--
-- Notes:
-- The package body uses package IEEE.MATH_REAL
--
-- The package body shall be considered the formal definition of
-- the semantics of this package. Tool developers may choose to implement
-- the package body in the most efficient manner available to them.
--
-- History:
-- Version 0.1 (Strawman) Jose A. Torres 6/22/92
-- Version 0.2 Jose A. Torres 1/15/93
-- Version 0.3 Jose A. Torres 4/13/93
-- Version 0.4 Jose A. Torres 4/19/93
-- Version 0.5 Jose A. Torres 4/20/93
-- Version 0.6 Jose A. Torres 4/23/93 Added unary minus
-- and CONJ for polar
-- Version 0.7 Jose A. Torres 5/28/93 Rev up for compatibility
-- with package body.
-------------------------------------------------------------
Library IEEE;
Package MATH_COMPLEX is
type COMPLEX is record RE, IM: real; end record;
type COMPLEX_VECTOR is array (integer range <>) of COMPLEX;
type COMPLEX_POLAR is record MAG: real; ARG: real; end record;
constant CBASE_1: complex := COMPLEX'(1.0, 0.0);
constant CBASE_j: complex := COMPLEX'(0.0, 1.0);
constant CZERO: complex := COMPLEX'(0.0, 0.0);
function CABS(Z: in complex ) return real;
-- returns absolute value (magnitude) of Z
function CARG(Z: in complex ) return real;
-- returns argument (angle) in radians of a complex number
function CMPLX(X: in real; Y: in real:= 0.0 ) return complex;
-- returns complex number X + iY
function "-" (Z: in complex ) return complex;
-- unary minus
function "-" (Z: in complex_polar ) return complex_polar;
-- unary minus
function CONJ (Z: in complex) return complex;
-- returns complex conjugate
function CONJ (Z: in complex_polar) return complex_polar;
-- returns complex conjugate
function CSQRT(Z: in complex ) return complex_vector;
-- returns square root of Z; 2 values
function CEXP(Z: in complex ) return complex;
-- returns e**Z
function COMPLEX_TO_POLAR(Z: in complex ) return complex_polar;
-- converts complex to complex_polar
function POLAR_TO_COMPLEX(Z: in complex_polar ) return complex;
-- converts complex_polar to complex
-- arithmetic operators
function "+" ( L: in complex; R: in complex ) return complex;
function "+" ( L: in complex_polar; R: in complex_polar) return complex;
function "+" ( L: in complex_polar; R: in complex ) return complex;
function "+" ( L: in complex; R: in complex_polar) return complex;
function "+" ( L: in real; R: in complex ) return complex;
function "+" ( L: in complex; R: in real ) return complex;
function "+" ( L: in real; R: in complex_polar) return complex;
function "+" ( L: in complex_polar; R: in real) return complex;
function "-" ( L: in complex; R: in complex ) return complex;
function "-" ( L: in complex_polar; R: in complex_polar) return complex;
function "-" ( L: in complex_polar; R: in complex ) return complex;
function "-" ( L: in complex; R: in complex_polar) return complex;
function "-" ( L: in real; R: in complex ) return complex;
function "-" ( L: in complex; R: in real ) return complex;
function "-" ( L: in real; R: in complex_polar) return complex;
function "-" ( L: in complex_polar; R: in real) return complex;
function "*" ( L: in complex; R: in complex ) return complex;
function "*" ( L: in complex_polar; R: in complex_polar) return complex;
function "*" ( L: in complex_polar; R: in complex ) return complex;
function "*" ( L: in complex; R: in complex_polar) return complex;
function "*" ( L: in real; R: in complex ) return complex;
function "*" ( L: in complex; R: in real ) return complex;
function "*" ( L: in real; R: in complex_polar) return complex;
function "*" ( L: in complex_polar; R: in real) return complex;
function "/" ( L: in complex; R: in complex ) return complex;
function "/" ( L: in complex_polar; R: in complex_polar) return complex;
function "/" ( L: in complex_polar; R: in complex ) return complex;
function "/" ( L: in complex; R: in complex_polar) return complex;
function "/" ( L: in real; R: in complex ) return complex;
function "/" ( L: in complex; R: in real ) return complex;
function "/" ( L: in real; R: in complex_polar) return complex;
function "/" ( L: in complex_polar; R: in real) return complex;
end MATH_COMPLEX;
---------------------------------------------------------------
--
-- This source file may be used and distributed without restriction.
-- No declarations or definitions shall be added to this package.
-- This package cannot be sold or distributed for profit.
--
-- ****************************************************************
-- * *
-- * W A R N I N G *
-- * *
-- * This DRAFT version IS NOT endorsed or approved by IEEE *
-- * *
-- ****************************************************************
--
-- Title: PACKAGE BODY MATH_REAL
--
-- Library: This package shall be compiled into a library
-- symbolically named IEEE.
--
-- Purpose: VHDL declarations for mathematical package MATH_REAL
-- which contains common real constants, common real
-- functions, and real trascendental functions.
--
-- Author: IEEE VHDL Math Package Study Group
--
-- Notes:
-- The package body shall be considered the formal definition of
-- the semantics of this package. Tool developers may choose to implement
-- the package body in the most efficient manner available to them.
--
-- Source code and algorithms for this package body comes from the
-- following sources:
-- IEEE VHDL Math Package Study Group participants,
-- U. of Mississippi, Mentor Graphics, Synopsys,
-- Viewlogic/Vantage, Communications of the ACM (June 1988, Vol
-- 31, Number 6, pp. 747, Pierre L'Ecuyer, Efficient and Portable
-- Random Number Generators), Handbook of Mathematical Functions
-- by Milton Abramowitz and Irene A. Stegun (Dover).
--
-- History:
-- Version 0.1 Jose A. Torres 4/23/93 First draft
-- Version 0.2 Jose A. Torres 5/28/93 Fixed potentially illegal code
-------------------------------------------------------------
Library IEEE;
Package body MATH_REAL is
--
-- some constants for use in the package body only
--
constant Q_PI : real := MATH_PI/4.0;
constant HALF_PI : real := MATH_PI/2.0;
constant TWO_PI : real := MATH_PI*2.0;
constant MAX_ITER: integer := 27; -- max precision factor for cordic
--
-- some type declarations for cordic operations
--
constant KC : REAL := 6.0725293500888142e-01; -- constant for cordic
type REAL_VECTOR is array (NATURAL range <>) of REAL;
type NATURAL_VECTOR is array (NATURAL range <>) of NATURAL;
subtype REAL_VECTOR_N is REAL_VECTOR (0 to max_iter);
subtype REAL_ARR_2 is REAL_VECTOR (0 to 1);
subtype REAL_ARR_3 is REAL_VECTOR (0 to 2);
subtype QUADRANT is INTEGER range 0 to 3;
type CORDIC_MODE_TYPE is (ROTATION, VECTORING);
--
-- auxiliary functions for cordic algorithms
--
function POWER_OF_2_SERIES (d : NATURAL_VECTOR; initial_value : REAL;
number_of_values : NATURAL) return REAL_VECTOR is
variable v : REAL_VECTOR (0 to number_of_values);
variable temp : REAL := initial_value;
variable flag : boolean := true;
begin
for i in 0 to number_of_values loop
v(i) := temp;
for p in d'range loop
if i = d(p) then
flag := false;
end if;
end loop;
if flag then
temp := temp/2.0;
end if;
flag := true;
end loop;
return v;
end POWER_OF_2_SERIES;
constant two_at_minus : REAL_VECTOR := POWER_OF_2_SERIES(
NATURAL_VECTOR'(100, 90),1.0,
MAX_ITER);
constant epsilon : REAL_VECTOR_N := (
7.8539816339744827e-01,
4.6364760900080606e-01,
2.4497866312686413e-01,
1.2435499454676144e-01,
6.2418809995957351e-02,
3.1239833430268277e-02,
1.5623728620476830e-02,
7.8123410601011116e-03,
3.9062301319669717e-03,
1.9531225164788189e-03,
9.7656218955931937e-04,
4.8828121119489829e-04,
2.4414062014936175e-04,
1.2207031189367021e-04,
6.1035156174208768e-05,
3.0517578115526093e-05,
1.5258789061315760e-05,
7.6293945311019699e-06,
3.8146972656064960e-06,
1.9073486328101870e-06,
9.5367431640596080e-07,
4.7683715820308876e-07,
2.3841857910155801e-07,
1.1920928955078067e-07,
5.9604644775390553e-08,
2.9802322387695303e-08,
1.4901161193847654e-08,
7.4505805969238281e-09
);
function CORDIC ( x0 : REAL;
y0 : REAL;
z0 : REAL;
n : NATURAL; -- precision factor
CORDIC_MODE : CORDIC_MODE_TYPE -- rotation (z -> 0)
-- or vectoring (y -> 0)
) return REAL_ARR_3 is
variable x : REAL := x0;
variable y : REAL := y0;
variable z : REAL := z0;
variable x_temp : REAL;
begin
if CORDIC_MODE = ROTATION then
for k in 0 to n loop
x_temp := x;
if ( z >= 0.0) then
x := x - y * two_at_minus(k);
y := y + x_temp * two_at_minus(k);
z := z - epsilon(k);
else
x := x + y * two_at_minus(k);
y := y - x_temp * two_at_minus(k);
z := z + epsilon(k);
end if;
end loop;
else
for k in 0 to n loop
x_temp := x;
if ( y < 0.0) then
x := x - y * two_at_minus(k);
y := y + x_temp * two_at_minus(k);
z := z - epsilon(k);
else
x := x + y * two_at_minus(k);
y := y - x_temp * two_at_minus(k);
z := z + epsilon(k);
end if;
end loop;
end if;
return REAL_ARR_3'(x, y, z);
end CORDIC;
--
-- non-trascendental functions
--
function SIGN (X: real ) return real is
-- returns 1.0 if X > 0.0; 0.0 if X == 0.0; -1.0 if X < 0.0
begin
if ( X > 0.0 ) then
return 1.0;
elsif ( X < 0.0 ) then
return -1.0;
else
return 0.0;
end if;
end SIGN;
function CEIL (X : real ) return real is
-- returns smallest integer value (as real) not less than X
-- No conversion to an integer type is expected, so truncate cannot
-- overflow for large arguments.
variable large: real := 1073741824.0;
type long is range -1073741824 to 1073741824;
-- 2**30 is longer than any single-precision mantissa
variable rd: real;
begin
if abs( X) >= large then
return X;
else
rd := real ( long( X));
if X > 0.0 then
if rd >= X then
return rd;
else
return rd + 1.0;
end if;
elsif X = 0.0 then
return 0.0;
else
if rd <= X then
return rd;
else
return rd - 1.0;
end if;
end if;
end if;
end CEIL;
function FLOOR (X : real ) return real is
-- returns largest integer value (as real) not greater than X
-- No conversion to an integer type is expected, so truncate
-- cannot overflow for large arguments.
--
variable large: real := 1073741824.0;
type long is range -1073741824 to 1073741824;
-- 2**30 is longer than any single-precision mantissa
variable rd: real;
begin
if abs( X ) >= large then
return X;
else
rd := real ( long( X));
if X > 0.0 then
if rd <= X then
return rd;
else
return rd - 1.0;
end if;
elsif X = 0.0 then
return 0.0;
else
if rd >= X then
return rd;
else
return rd + 1.0;
end if;
end if;
end if;
end FLOOR;
function ROUND (X : real ) return real is
-- returns integer FLOOR(X + 0.5) if X > 0;
-- return integer CEIL(X - 0.5) if X < 0
begin
if X > 0.0 then
return FLOOR(X + 0.5);
elsif X < 0.0 then
return CEIL( X - 0.5);
else
return 0.0;
end if;
end ROUND;
function FMAX (X, Y : real ) return real is
-- returns the algebraically larger of X and Y
begin
if X > Y then
return X;
else
return Y;
end if;
end FMAX;
function FMIN (X, Y : real ) return real is
-- returns the algebraically smaller of X and Y
begin
if X < Y then
return X;
else
return Y;
end if;
end FMIN;
--
-- Pseudo-random number generators
--
procedure UNIFORM(variable Seed1,Seed2:inout integer;variable X:out real) is
-- returns a pseudo-random number with uniform distribution in the
-- interval (0.0, 1.0).
-- Before the first call to UNIFORM, the seed values (Seed1, Seed2) must
-- be initialized to values in the range [1, 2147483562] and
-- [1, 2147483398] respectively. The seed values are modified after
-- each call to UNIFORM.
-- This random number generator is portable for 32-bit computers, and
-- it has period ~2.30584*(10**18) for each set of seed values.
--
-- For VHDL-1992, the seeds will be global variables, functions to
-- initialize their values (INIT_SEED) will be provided, and the UNIFORM
-- procedure call will be modified accordingly.
variable z, k: integer;
begin
k := Seed1/53668;
Seed1 := 40014 * (Seed1 - k * 53668) - k * 12211;
if Seed1 < 0 then
Seed1 := Seed1 + 2147483563;
end if;
k := Seed2/52774;
Seed2 := 40692 * (Seed2 - k * 52774) - k * 3791;
if Seed2 < 0 then
Seed2 := Seed2 + 2147483399;
end if;
z := Seed1 - Seed2;
if z < 1 then
z := z + 2147483562;
end if;
X := REAL(Z)*4.656613e-10;
end UNIFORM;
function SRAND (seed: in integer ) return integer is
--
-- sets value of seed for sequence of
-- pseudo-random numbers.
-- Returns the value of the seed.
-- It uses the foreign native C function srand().
begin
end SRAND;
function RAND return integer is
--
-- returns an integer pseudo-random number with uniform distribution.
-- It uses the foreign native C function rand().
-- Seed for the sequence is initialized with the
-- SRAND() function and value of the seed is changed every
-- time SRAND() is called, but it is not visible.
-- The range of generated values is platform dependent.
begin
end RAND;
function GET_RAND_MAX return integer is
--
-- returns the upper bound of the range of the
-- pseudo-random numbers generated by RAND().
-- The support for this function is platform dependent, and
-- it uses foreign native C functions or constants.
-- It may not be available in some platforms.
-- Note: the value of (RAND / GET_RAND_MAX) is a
-- pseudo-random number distributed between 0 & 1.
begin
end GET_RAND_MAX;
--
-- trascendental and trigonometric functions
--
function SQRT (X : real ) return real is
-- returns square root of X; X >= 0
--
-- Computes square root using the Newton-Raphson approximation:
-- F(n+1) = 0.5*[F(n) + x/F(n)];
--
constant inival: real := 1.5;
constant eps : real := 0.000001;
constant relative_err : real := eps*X;
variable oldval : real ;
variable newval : real ;
begin
-- check validity of argument
if ( X < 0.0 ) then
assert false report "X < 0 in SQRT(X)"
severity ERROR;
return (0.0);
end if;
-- get the square root for special cases
if X = 0.0 then
return 0.0;
else
if ( X = 1.0 ) then
return 1.0; -- return exact value
end if;
end if;
-- get the square root for general cases
oldval := inival;
newval := (X/oldval + oldval)/2.0;
while ( abs(newval -oldval) > relative_err ) loop
oldval := newval;
newval := (X/oldval + oldval)/2.0;
end loop;
return newval;
end SQRT;
function CBRT (X : real ) return real is
-- returns cube root of X
-- Computes square root using the Newton-Raphson approximation:
-- F(n+1) = (1/3)*[2*F(n) + x/F(n)**2];
--
constant inival: real := 1.5;
constant eps : real := 0.000001;
constant relative_err : real := eps*abs(X);
variable xlocal : real := X;
variable negative : boolean := X < 0.0;
variable oldval : real ;
variable newval : real ;
begin
-- compute root for special cases
if X = 0.0 then
return 0.0;
elsif ( X = 1.0 ) then
return 1.0;
else
if X = -1.0 then
return -1.0;
end if;
end if;
-- compute root for general cases
if negative then
xlocal := -X;
end if;
oldval := inival;
newval := (xlocal/(oldval*oldval) + 2.0*oldval)/3.0;
while ( abs(newval -oldval) > relative_err ) loop
oldval := newval;
newval :=(xlocal/(oldval*oldval) + 2.0*oldval)/3.0;
end loop;
if negative then
newval := -newval;
end if;
return newval;
end CBRT;
function "**" (X : integer; Y : real) return real is
-- returns Y power of X ==> X**Y;
-- error if X = 0 and Y <= 0.0
-- error if X < 0 and Y does not have an integer value
begin
-- check validity of argument
if ( X = 0 ) and ( Y <= 0.0 ) then
assert false report "X = 0 and Y <= 0.0 in X**Y"
severity ERROR;
return (0.0);
end if;
if ( X < 0 ) and ( Y /= REAL(INTEGER(Y)) ) then
assert false report "X < 0 and Y \= integer in X**Y"
severity ERROR;
return (0.0);
end if;
-- compute the result
return EXP (Y * LOG (REAL(X)));
end "**";
function "**" (X : real; Y : real) return real is
-- returns Y power of X ==> X**Y;
-- error if X = 0.0 and Y <= 0.0
-- error if X < 0.0 and Y does not have an integer value
begin
-- check validity of argument
if ( X = 0.0 ) and ( Y <= 0.0 ) then
assert false report "X = 0.0 and Y <= 0.0 in X**Y"
severity ERROR;
return (0.0);
end if;
if ( X < 0.0 ) and ( Y /= REAL(INTEGER(Y)) ) then
assert false report "X < 0.0 and Y \= integer in X**Y"
severity ERROR;
return (0.0);
end if;
-- compute the result
return EXP (Y * LOG (X));
end "**";
function EXP (X : real ) return real is
-- returns e**X; where e = MATH_E
--
-- This function computes the exponential using the following series:
-- exp(x) = 1 + x + x**2/2! + x**3/3! + ... ; x > 0
--
constant eps : real := 0.000001; -- precision criteria
variable reciprocal: boolean := x < 0.0;-- check sign of argument
variable xlocal : real := abs(x); -- use positive value
variable oldval: real ; -- following variables are
variable num: real ; -- used for series evaluation
variable count: integer ;
variable denom: real ;
variable newval: real ;
begin
-- compute value for special cases
if X = 0.0 then
return 1.0;
else
if X = 1.0 then
return MATH_E;
end if;
end if;
-- compute value for general cases
oldval := 1.0;
num := xlocal;
count := 1;
denom := 1.0;
newval:= oldval + num/denom;
while ( abs(newval - oldval) > eps ) loop
oldval := newval;
num := num*xlocal;
count := count +1;
denom := denom*(real(count));
newval := oldval + num/denom;
end loop;
if reciprocal then
newval := 1.0/newval;
end if;
return newval;
end EXP;
function LOG (X : real ) return real is
-- returns natural logarithm of X; X > 0
--
-- This function computes the exponential using the following series:
-- log(x) = 2[ (x-1)/(x+1) + (((x-1)/(x+1))**3)/3.0 + ...] ; x > 0
--
constant eps : real := 0.000001; -- precision criteria
variable xlocal: real ; -- following variables are
variable oldval: real ; -- used to evaluate the series
variable xlocalsqr: real ;
variable factor : real ;
variable count: integer ;
variable newval: real ;
begin
-- check validity of argument
if ( x <= 0.0 ) then
assert false report "X <= 0 in LOG(X)"
severity ERROR;
return(REAL'LOW);
end if;
-- compute value for special cases
if ( X = 1.0 ) then
return 0.0;
else
if ( X = MATH_E ) then
return 1.0;
end if;
end if;
-- compute value for general cases
xlocal := (X - 1.0)/(X + 1.0);
oldval := xlocal;
xlocalsqr := xlocal*xlocal;
factor := xlocal*xlocalsqr;
count := 3;
newval := oldval + (factor/real(count));
while ( abs(newval - oldval) > eps ) loop
oldval := newval;
count := count +2;
factor := factor * xlocalsqr;
newval := oldval + factor/real(count);
end loop;
newval := newval * 2.0;
return newval;
end LOG;
function LOG (BASE: positive; X : real) return real is
-- returns logarithm base BASE of X; X > 0
begin
-- check validity of argument
if ( BASE <= 0 ) or ( x <= 0.0 ) then
assert false report "BASE <= 0 or X <= 0.0 in LOG(BASE, X)"
severity ERROR;
return(REAL'LOW);
end if;
-- compute the value
return ( LOG(X)/LOG(REAL(BASE)));
end LOG;
function SIN (X : real ) return real is
-- returns sin X; X in radians
variable n : INTEGER;
begin
if (x < 1.6 ) and (x > -1.6) then
return CORDIC( KC, 0.0, x, 27, ROTATION)(1);
end if;
n := INTEGER( x / HALF_PI );
case QUADRANT( n mod 4 ) is
when 0 =>
return CORDIC( KC, 0.0, x - REAL(n) * HALF_PI, 27, ROTATION)(1);
when 1 =>
return CORDIC( KC, 0.0, x - REAL(n) * HALF_PI, 27, ROTATION)(0);
when 2 =>
return -CORDIC( KC, 0.0, x - REAL(n) * HALF_PI, 27, ROTATION)(1);
when 3 =>
return -CORDIC( KC, 0.0, x - REAL(n) * HALF_PI, 27, ROTATION)(0);
end case;
end SIN;
function COS (x : REAL) return REAL is
-- returns cos X; X in radians
variable n : INTEGER;
begin
if (x < 1.6 ) and (x > -1.6) then
return CORDIC( KC, 0.0, x, 27, ROTATION)(0);
end if;
n := INTEGER( x / HALF_PI );
case QUADRANT( n mod 4 ) is
when 0 =>
return CORDIC( KC, 0.0, x - REAL(n) * HALF_PI, 27, ROTATION)(0);
when 1 =>
return -CORDIC( KC, 0.0, x - REAL(n) * HALF_PI, 27, ROTATION)(1);
when 2 =>
return -CORDIC( KC, 0.0, x - REAL(n) * HALF_PI, 27, ROTATION)(0);
when 3 =>
return CORDIC( KC, 0.0, x - REAL(n) * HALF_PI, 27, ROTATION)(1);
end case;