• Keine Ergebnisse gefunden

4 Implementierung in VHDL

4.9 Simulation

Zur rein logischen Verifikation des VHDL-Quellcodes wird der Simulator ModelSim XE Starter der Fa.

Mentor Graphics verwendet. Die Umrechnung zwischen Dezimalzahlen und 32-Bit-Gleitkommazahlen erfolgt über ein Java-Applet unter der URL http://www.h-schmidt.net/FloatApplet/IEEE754de.html. Die Stimulidaten stehen in einer do-Datei, die für die Bilder 4.10 bzw. 4.11 wie folgt lautet:

# Kommandodatei für Bild 4.10; Berechnung von exp(4.85) restart -f

radix hex

force reset 0 0, 1 70ns

force start_cordic 0 0, 1 175ns, 0 320ns force clk 0 0, 1 50ns -repeat 100ns force op_code x"03"

force xfp x"3F800000"

force yfp x"00000000"

force zfp x"409B3333"

run 3.6us

# Kommandodatei für Bild 4.11; Berechnung von cos(3.5) und sin(3.5) sowie ln(112.26) restart -f

radix hex

force reset 0 0, 1 70ns

force start_cordic 0 0, 1 175ns, 0 320ns, 1 3.56us, 0 3.72us force clk 0 0, 1 50ns -repeat 100ns

force op_code x"01" 0, x"04" 3.57us

force xfp x"3F800000" 0, x"42E0851F" 3.53us force yfp x"00000000" 0, x"42E0851F" 3.53us force zfp x"40600000" 0, x"00000000" 3.53us run 7.2us

In der Kommandodatei für Bild 4.10 werden XFP auf 1.0d, YFP auf 0.0 und ZFP auf 4.85d gesetzt.

Mittels OP_CODE = X“03“ wird folglich die Exponentialfunktion berechnet. Das Ergebnis steht im Register QXFP_OUT und entspricht umgewandelt folgendem dezimalem Wert (zum Vergleich ist der mit einem Taschenrechner ermittelte Wert ebenfalls angegeben):

QXFP_OUT[31:0] = 42FF7B0Fh 127.74035d

exp(4.85) = 127.7403898… (Taschenrechner)

In Bild 4.11 sind zwei CORDIC-Berechnungen zu sehen, zunächst für OP_CODE = X“01“ (cos- und sin-Funktion) und anschließend für OP_CODE = X“04“ (ln-Funktion). Das Argument für die cos- und sin-Funktion ist 3.5d, der Numerus für die ln-Funktion ist 112.26. Mit diesen Eingabedaten erhält man folgende Ergebnisse:

1. CORDIC-Berechnung: QXFP_OUT[31:0] = BF6FBBA0h -0.9364567d

cos(3.5) = -0.936456687… (Taschenrechner)

QYZFP_OUT[31:0] = BEB399D8h -0.3507831d

sin(3.5) = -0.350783227… (Taschenrechner)

2. CORDIC-Berechnung: QYZFP_OUT[31:0] = 409710EFh 4.720817d

ln(112.26) = 4.72081760… (Taschenrechner) In Tabelle 4.8 sind für jeden OP-Code einige Testdaten mit den zugehörigen Ergebnissen sowie einem Vergleich zur jeweils exakten Lösung zusammengefasst. Man erkennt, dass die 24 CORDIC-Iterationen auf ein etwa 6 Stellen genaues Ergebnis führen.

Bild 4.10: Berechnung von exp(4.85)

OP_CODE z bzw. r XFP YFP ZFP QXFP_OUT dezimal Taschenrechner QYZFP_OUT dezimal Taschenrechner 01 0.000 3F800000 00000000 00000000 3F7FFFFF 0.99999994 1.000000000 B3800000 -5.9604645E-8 0.000000000 01 0.080 3F800000 00000000 3DA3D70A 3F7F2E65 0.9968017 0.996801706 3DA3AA47 0.07991462 0.079914693 01 0.670 3F800000 00000000 3F2B851F 3F48A888 0.7838216 0.783821665 3F1EF8F0 0.620986 0.620985987 01 1.520 3F800000 00000000 3FC28F5C 3D4FF906 0.050774597 0.050774484 3F7FAB77 0.9987101 0.998710143 01 2.270 3F800000 00000000 401147AE BF24C385 -0.6436084 -0.643608418 3F43EE4C 0.7653549 0.765354952 01 3.055 3F800000 00000000 4043851F BF7F0A72 -0.99625313 -0.996253198 3DB11EC4 0.08648446 0.086484478 01 4.937 3F800000 00000000 409DFBE7 3E641281 0.22272684 0.222727169 BF7991CB -0.9748809 -0.974880817 01 5.377 3F800000 00000000 40AC1062 3F1DE384 0.61675286 0.616752990 BF49831C -0.7871568 -0.787156749 01 5.900 3F800000 00000000 40BCCCCD 3F6D6F3A 0.92747843 0.927478430 BEBF6CC1 -0.3738766 -0.373876664 01 6.180 3F800000 00000000 40C5C28F 3F7EA36B 0.99468106 0.994681117 BDD2F2FE -0.10300253 -0.103002298 03 0.000 3F800000 00000000 00000000 3F800001 1.0000001 1.000000000 00000000 - - 03 0.430 3F800000 00000000 3EDC28F6 3FC4C4D9 1.5372573 1.537257523 00000000 - - 03 1.550 3F800000 00000000 3FC66666 4096C45E 4.7114706 4.711470182 00000000 - - 03 3.905 3F800000 00000000 4079EB85 424699AF 49.65008 49.65007991 00000000 - - 03 8.330 3F800000 00000000 410547AE 45819356 4146.417 4146.417552 00000000 - - 03 15.950 3F800000 00000000 417F3333 4B00FA79 8452729.0 8452729.796 00000000 - - 03 -0.005 3F800000 00000000 BBA3D70A 3F7EB925 0.9950126 0.995012479 00000000 - - 03 -0.520 3F800000 00000000 BF051EB8 3F183280 0.59452057 0.594520547 00000000 - - 03 -1.107 3F800000 00000000 BF8DB22D 3EA93DBA 0.33054906 0.330549122 00000000 - - 03 -8.336 3F800000 00000000 C1056042 397B5FD3 2.3972923E-4 2.39729345E-4 00000000 - - 04 0.00005 3851B717 3851B717 00000000 00000000 - - C11E74AE -9.903486 -9.903487552 04 0.008 3C03126F 3C03126F 00000000 00000000 - - C09A818A -4.828313 -4.828313737 04 1.825 3FE9999A 3FE9999A 00000000 00000000 - - 3F1A011F 0.6015796 0.601579987 04 2.71828 402DF84D 402DF84D 00000000 00000000 - - 3F7FFFF3 0.9999992 0.999999327 04 22.6 41B4CCCD 41B4CCCD 00000000 00000000 - - 40478C7D 3.1179497 3.117949906 04 500.8 43FA6666 43FA6666 00000000 00000000 - - 40C6EB29 6.216206 6.216206819 04 4200.5 45834400 45834400 00000000 00000000 - - 41057CC1 8.3429575 8.342958844 04 22000 46ABE000 46ABE000 00000000 00000000 - - 411FFB12 9.998796 9.998797732 04 522560 48FF2800 48FF2800 00000000 00000000 - - 4152A9F5 13.166493 13.16649508 04 1.52E+6 49B98C00 49B98C00 00000000 00000000 - - 4163BF5C 14.234219 14.23422089 05 0.00005 3851B717 3851B717 00000000 3BE7B469 0.007071067 0.007071067 00000000 - - 05 0.008 3C03126F 3C03126F 00000000 3DB72DBE 0.089442715 0.089442719 00000000 - - 05 1.825 3FE9999A 3FE9999A 00000000 3FACEB21 1.3509256 1.350925608 00000000 - - 05 2.71828 402DF84D 402DF84D 00000000 3FD30947 1.6487206 1.648720716 00000000 - - 05 22.6 41B4CCCD 41B4CCCD 00000000 40982052 4.7539454 4.753945729 00000000 - - 05 500.8 43FA6666 43FA6666 00000000 41B3074A 22.37856 22.37856116 00000000 - - 05 4200.5 45834400 45834400 00000000 42819F5D 64.81126 64.81126445 00000000 - - 05 22000 46ABE000 46ABE000 00000000 431452EF 148.32396 148.3239697 00000000 - - 05 522560 48FF2800 48FF2800 00000000 4434B884 722.88306 722.8831164 00000000 - - 05 1.52E+6 49B98C00 49B98C00 00000000 449A1C3F 1232.8827 1232.882800 00000000 - -

Tabelle 4.8: Zusammenfassung einiger Testdaten

Anhang

A1 C-Quellcode zur Berechnung von sin() und cos()

// Berechnung von sin und cos

#include <stdio.h>

#include <conio.h>

#include <math.h>

int main (void) {

int n = 1; double g = 1.64676025812, delta = 1;

double tmpx, tmpy, VZ;

double x = 1, y = 0, z = 0.6; // Initialwert für z entspricht phi do

{

if (z < 0) VZ = -1; else VZ = 1;

tmpx = x - VZ*delta*y;

tmpy = y + VZ*delta*x;

x = tmpx; y = tmpy;

z = z - VZ*atan(delta);

delta = delta / 2;

n++;

}

while (n <= 15);

x = x / g; y = y / g;

printf("\n\n x = %1.8lf", x);

printf("\n\n y = %1.8lf\n\n", y);

getch();

return 0;

}

A2 C-Quellcode zur Berechnung von arctan()

// Berechnung von arctan

#include <stdio.h>

#include <conio.h>

#include <math.h>

int main (void) {

int n = 1; double g = 1.64676025812, delta = 1;

double tmpx, tmpy, VZ;

double x = 1.8, y = 0.7, z = 0;

do {

if (y < 0) VZ = 1; else VZ = -1;

tmpx = x - VZ*delta*y;

tmpy = y + VZ*delta*x;

x = tmpx; y = tmpy;

z = z - VZ*atan(delta);

delta = delta / 2;

n++;

}

while (n <= 15);

x = x / g;

printf("\n\n\n x = %1.8lf", x);

printf("\n z = %1.8lf", z);

getch();

return 0;

}

A3 C-Quellcode zur Berechnung von arcsin()

// Berechnung von arcsin

#include <stdio.h>

#include <conio.h>

#include <math.h>

int main (void) {

int n = 1; double g = 1.64676025812, delta = 1;

double tmpx, tmpy, VZ;

double x = 1 / g, y = 0, z = 0, arg = 0.7;

do {

if (arg - y < 0) VZ = -1; else VZ = 1;

tmpx = x - VZ*delta*y;

tmpy = y + VZ*delta*x;

x = tmpx; y = tmpy;

z = z + VZ*atan(delta);

delta = delta / 2;

n++;

}

while (n <= 15);

printf("\n\n\n x = %1.8lf", x);

printf("\n y = %1.8lf", y);

printf("\n\n z = %1.8lf\n\n", z);

getch();

return 0;

}

A4 C-Quellcode zur Berechnung von sinh() und cosh()

// Berechnung von sinh und cosh

// einfache Shiftfolge => Konvergenzkriterium nicht erfüllt

#include <stdio.h>

#include <conio.h>

#include <math.h>

int main (void) {

int n = 1; double g = 0.82978162013, delta = 0.5;

double tmpx, tmpy, VZ;

double x = 1, y = 0, z = 0.8;

do {

if (z < 0) VZ = -1; else VZ = 1;

tmpx = x + VZ*delta*y;

tmpy = y + VZ*delta*x;

x = tmpx; y = tmpy;

z = z - VZ*0.5*log((1+delta)/(1-delta));

delta = delta / 2;

n++;

}

while (n <= 15);

x = x / g; y = y / g;

printf("\n\n x = %1.8lf", x);

printf("\n\n y = %1.8lf\n\n", y);

getch();

return 0;

}

A5 C-Quellcode zur Berechnung von sinh() und cosh()

// Berechnung von sinh und cosh

// komplexere Shiftfolge => Konvergenzkriterium erfüllt

#include <stdio.h>

#include <conio.h>

#include <math.h>

int main (void) {

int n = 1, k = 4; double g = 0.82815936096, delta = 0.5;

double tmpx, tmpy, VZ;

double x = 1, y = 0, z = 0.01;

do {

if (z < 0) VZ = -1; else VZ = 1;

tmpx = x + VZ*delta*y;

tmpy = y + VZ*delta*x;

x = tmpx; y = tmpy;

z = z - VZ*0.5*log((1+delta)/(1-delta));

if (n == k) {

k = 3*k + 1;

} else {

delta = delta / 2;

n++;

} }

while (n <= 32);

x = x / g; y = y / g;

printf("\n\n x = %1.10lf", x); printf("\n\n y = %1.10lf\n\n", y); getch();

return 0;

}

A6 C-Quellcode zur Berechnung von artanh()

// Berechnung von artanh(); Konvergenzkriterium erfüllt

#include <stdio.h>

#include <conio.h>

#include <math.h>

int main (void) {

int n = 1, k = 4; double g = 0.82815936096, delta = 0.5;

double tmpx, tmpy, VZ;

double x = 3.9, y = 2.5, z = 0;

do {

if (y < 0) VZ = 1; else VZ = -1;

tmpx = x + VZ*delta*y;

tmpy = y + VZ*delta*x;

x = tmpx; y = tmpy;

z = z - VZ*0.5*log((1+delta)/(1-delta));

if (n == k) {

k = 3*k + 1;

} else {

delta = delta / 2;

n++;

} }

while (n <= 15);

x = x / g;

printf("\n\n x = %1.8lf", x); printf("\n\n z = %1.8lf\n\n", z); getch();

A7 C-Quellcode zur Multiplikation im linearen Modus

// Multiplikation im linearen Modus (Rotating)

#include <stdio.h>

#include <conio.h>

#include <math.h>

int main (void) {

int n = 1; double delta = 1, VZ;

double x = 3.5, y = 0, z = 1.9;

do {

if (z < 0) VZ = -1; else VZ = 1;

y = y + VZ*delta*x;

z = z - VZ*delta;

delta = delta / 2;

n++;

}

while (n <= 24);

printf("\n\n y = %1.8lf\n\n", y);

getch();

return 0;

}

A8 C-Quellcode zur Division im linearen Modus

// Division im linearen Modus (Vectoring)

#include <stdio.h>

#include <conio.h>

#include <math.h>

int main (void) {

int n = 1; double delta = 1, VZ;

double x = 4.1, y = -5.8, z = 0;

do {

if (y < 0) VZ = 1; else VZ = -1;

y = y + VZ*delta*x;

z = z - VZ*delta;

delta = delta / 2;

n++;

}

while (n <= 24);

printf("\n\n z = %1.8lf\n\n", z);

getch();

return 0;

}

A9 C-Quellcode zur Berechnung von exp()

// Berechnung von exp() über cosh und sinh

// komplexere Shiftfolge => Konvergenzkriterium für cosh und sinh erfüllt // Berücksichtigung unzulässiger Argumente

#include <stdio.h>

#include <conio.h>

#include <math.h>

int main (void) {

int n = 1, k = 4, m; double g = 0.82815936096, delta = 0.5;

double tmpx, tmpy, VZ;

double z, x = 1, y = 0, arg = -5.7;

double ln_2 = 0.69314718056;

double exp_fkt;

m = (int) (arg / ln_2);

z = arg - m*ln_2;

do {

if (z < 0) VZ = -1; else VZ = 1;

tmpx = x + VZ*delta*y;

tmpy = y + VZ*delta*x;

x = tmpx; y = tmpy;

z = z - VZ*0.5*log((1+delta)/(1-delta));

if (n == k) {

k = 3*k + 1;

} else {

delta = delta / 2;

n++;

} }

while (n <= 32);

x = x / g; y = y / g;

// Berechnung der Exponentialfunktion exp_fkt = pow(2,m)*(x + y);

printf("\n\n exp_fkt = %1.10lf", exp_fkt); getch();

return 0;

}

A10 VHDL-Quellcode für CORDIC-Algorithmus (Stand: 19.06.2008)

-- Top_Level_Modul.vhd library IEEE;

use IEEE.STD_LOGIC_1164.ALL;

use IEEE.STD_LOGIC_ARITH.ALL;

use IEEE.STD_LOGIC_UNSIGNED.ALL;

use work.PACK_CORDIC.ALL;

entity CORDIC_VERSION_1 is

port(CLK,RESET,START_CORDIC: in std_logic;

XFP,YFP,ZFP: in std_logic_vector(31 downto 0);

OP_CODE: in std_logic_vector(7 downto 0);

READY_CORDIC: out std_logic;

XFP_OUT,YZFP_OUT: out std_logic_vector(31 downto 0));

end CORDIC_VERSION_1;

architecture CORDIC_VERSION_1_A of CORDIC_VERSION_1 is -- Komponenten-Deklarationen

component SHFT24LR

port(E: in std_logic_vector(23 downto 0);

COUNT: in std_logic_vector(7 downto 0);

SHIFT_DIRECTION: in std_logic;

OV_BITS: out std_logic_vector(1 downto 0);

A: out std_logic_vector(23 downto 0));

end component SHFT24LR;

component CONV_FP_TC

port(MANTISSE: in std_logic_vector(23 downto 0);

VZ: in std_logic;

OV_BITS: in std_logic_vector(1 downto 0);

S_INT: out std_logic_vector(31 downto 0));

end component CONV_FP_TC;

component COUNT_SH_OP

port(E: in std_logic_vector(32 downto 0);

COUNT: out std_logic_vector(9 downto 0));

end component COUNT_SH_OP;

component SHFT32LR

port(E: in std_logic_vector(32 downto 0);

COUNT: in std_logic_vector(9 downto 0);

A: out std_logic_vector (23 downto 0));

end component SHFT32LR;

component EXTENDING_DOMAIN

port(EXPONENT: in std_logic_vector(7 downto 0);

MANTISSE: in std_logic_vector(23 downto 0);

MANTISSE_SHIFT: in std_logic_vector(23 downto 0);

QUOTIENT: out std_logic_vector(4 downto 0);

REST: out std_logic_vector (23 downto 0));

end component EXTENDING_DOMAIN;

-- Signal-Deklarationen

type ZUSTAENDE is (Z0,Z1,Z2,Z3,Z4,Z5,Z6,Z7,Z8); --Aufzählungstyp

signal ZUSTAND,FOLGE_Z: ZUSTAENDE; --Interprozesskommunikation

signal ManX,ManY,ManZ,ManXshft,ManYshft,ManZshft: std_logic_vector(23 downto 0);

signal ManXout,ManYout,ManZout: std_logic_vector(23 downto 0);

signal XgtY, YgtX,Zgteq127: std_logic;

signal CountX,CountY,CountZ: std_logic_vector(7 downto 0);

signal OV_BITS_X,OV_BITS_Y,OV_BITS_Z: std_logic_vector(1 downto 0);

signal X_INT,Y_INT,Z_INT: std_logic_vector(31 downto 0);

signal QX_INT,QY_INT,QZ_INT: std_logic_vector(31 downto 0);

signal QREF_EXP_XY: std_logic_vector(9 downto 0);

signal QX_MULT,QY_MULT,QE_LN_2: std_logic_vector(32 downto 0);

signal CountX_mult,CountY_mult,CountZ_add: std_logic_vector(9 downto 0);

signal QS: std_logic_vector(4 downto 0);

signal oi,m: integer range -1 to +1;

signal QUOTIENT: std_logic_vector(4 downto 0);

signal QQUOTIENT: std_logic_vector(9 downto 0);

signal REST: std_logic_vector(23 downto 0);

signal FALLUNTERSCHEIDUNG: std_logic_vector(1 downto 0);

signal QXFP_OUT,QYZFP_OUT: std_logic_vector(31 downto 0);

signal QE_MOD_2: std_logic;

begin

-- Kombinatorik

ManX <= '1' & XFP(22 downto 0);

ManY <= '1' & YFP(22 downto 0);

ManZ <= '1' & ZFP(22 downto 0);

XgtY <= '1' when XFP(30 downto 23) > YFP(30 downto 23) else '0';

YgtX <= '1' when YFP(30 downto 23) > XFP(30 downto 23) else '0';

Zgteq127 <= '1' when ZFP(30 downto 23) >= 127 else '0';

CountX <= YFP(30 downto 23) - XFP(30 downto 23) when YgtX = '1' else "00000000";

CountY <= XFP(30 downto 23) - YFP(30 downto 23) when XgtY = '1' else "00000000";

CountZ <= ZFP(30 downto 23) - 127 when Zgteq127 = '1' else (127 - ZFP(30 downto 23));

shftX: SHFT24LR port map (ManX,CountX,'0',OV_BITS_X,ManXshft);

shftY: SHFT24LR port map (ManY,CountY,'0',OV_BITS_Y,ManYshft);

shftZ: SHFT24LR port map (ManZ,CountZ,Zgteq127,OV_BITS_Z,ManZshft);

convx_int: CONV_FP_TC port map(ManXshft,XFP(31),OV_BITS_X,X_INT);

convy_int: CONV_FP_TC port map(ManYshft,YFP(31),OV_BITS_Y,Y_INT);

convz_int: CONV_FP_TC port map(ManZshft,ZFP(31),OV_BITS_Z,Z_INT);

count_sh_op_x: COUNT_SH_OP port map(QX_MULT,CountX_mult);

count_sh_op_y: COUNT_SH_OP port map(QY_MULT,CountY_mult);

count_sh_op_z: COUNT_SH_OP port map(QE_LN_2,CountZ_add);

shftX_out: SHFT32LR port map(QX_MULT,CountX_mult,ManXout);

shftY_out: SHFT32LR port map(QY_MULT,CountY_mult,ManYout);

shftZ_out: SHFT32LR port map(QE_LN_2,CountZ_add,ManZout);

ext_domain: EXTENDING_DOMAIN port map(ZFP(30 downto 23),ManZ,ManZshft,QUOTIENT,REST);

Z_SPEICHER: process(CLK,RESET) begin

if RESET = '0' then ZUSTAND <= Z0;

QS <= "00000";

elsif CLK = '1' and CLK'event then ZUSTAND <= FOLGE_Z;

case ZUSTAND is

when Z0 => QS <= "00000";

when Z3 => QS <= QS + 1;

when others =>

end case;

end if;

end process Z_SPEICHER;

F_BEST: process(START_CORDIC,ZUSTAND,QS) begin

case ZUSTAND is

when Z0 => if START_CORDIC = '1' then FOLGE_Z <= Z1;

else FOLGE_Z <= Z0;

end if;

when Z1 => FOLGE_Z <= Z2;

when Z2 => FOLGE_Z <= Z3;

when Z3 => if QS = "10111" then

FOLGE_Z <= Z4; -- Abbruch des CORDIC-Verfahrens nach 24 Iterationen end if;

when Z4 => FOLGE_Z <= Z5;

when Z5 => FOLGE_Z <= Z6;

when Z6 => FOLGE_Z <= Z7;

when Z7 => FOLGE_Z <= Z8;

when Z8 => FOLGE_Z <= Z0;

end case;

end process F_BEST;

A_BEST: process(ZUSTAND,QS) variable N,I,J: integer;

variable VX_SHIFT,VY_SHIFT: std_logic_vector(31 downto 0);

variable VX_INT,VY_INT,VZ_INT: std_logic_vector(31 downto 0);

variable VREF_EXP_X,VREF_EXP_Y,VREF_EXP_Z: std_logic_vector(9 downto 0);

variable V_ROM_X1_OUT,V_ROM_Y1_OUT: std_logic_vector(31 downto 0);

variable VE_MOD_2: std_logic;

begin

case ZUSTAND is

when Z0 => READY_CORDIC <= '1';

when Z1 => READY_CORDIC <= '0';

QQUOTIENT <= "0000000000"; -- Initialisierung QX_INT <= X_INT;

QY_INT <= Y_INT;

QZ_INT <= Z_INT;

case OP_CODE is

when X"01" => m <= 1;

-- Fallunterscheidung für trigonometrische Funktionen cos und sin -- Argument-Bereich von 0 bis 2pi

if Z_INT <= "00011001001000011111101101010100" then FALLUNTERSCHEIDUNG <= "00";

elsif (Z_INT > "00011001001000011111101101010100" and Z_INT <= "00110010010000111111011010101000") then FALLUNTERSCHEIDUNG <= "01";

QZ_INT <= Z_INT - "00011001001000011111101101010100";

elsif (Z_INT > "00110010010000111111011010101000" and Z_INT <= "01001011011001011111000111111100") then FALLUNTERSCHEIDUNG <= "10";

QZ_INT <= Z_INT - "00110010010000111111011010101000";

else

-- Z_INT liegt zwischen 3pi/2 und 2pi FALLUNTERSCHEIDUNG <= "11";

QZ_INT <= Z_INT - "01001011011001011111000111111100";

end if;

when X"03" => m <= -1;

-- Erweiterung des zulässigen Argument-Bereiches für exp-Funktion if ZFP(31) = '0' then

QQUOTIENT <= "00000" & QUOTIENT;

QZ_INT <= ZFP(31) & "00" & REST & "00000";

else

QQUOTIENT <= ("11111" & not(QUOTIENT)) + 1;

QZ_INT <= (ZFP(31) & "11" & not(REST) & "11111") + 1;

end if;

when X"04" => m <= -1;

QX_INT <= X_INT + X"10000000"; -- Addition von 1d QY_INT <= Y_INT - X"10000000"; -- Subtraktion von 1d

when others => m <= -1;

VE_MOD_2 := E_MOD_2(Bit8Int(XFP(30 downto 23)));

QE_MOD_2 <= VE_MOD_2;

-- falls Exponent ungerade, dann wird Mantisse M geteilt => Bestimmung des Radikanden r -- es wird davon ausgegangen, dass der Radikand positiv ist

if VE_MOD_2 = '1' then

QX_INT <= X_INT(31) & '0' & X_INT(30 downto 1);

QY_INT <= Y_INT(31) & '0' & Y_INT(30 downto 1);

end if;

end case;

when Z2 => -- Bestimmung des Referenzexponenten für X/Y if (XgtY = '0' and YgtX = '0') then

QREF_EXP_XY <= ("00" & XFP(30 downto 23)) - 127;

elsif XgtY = '1' then

QREF_EXP_XY <= ("00" & XFP(30 downto 23)) - 127;

else

QREF_EXP_XY <= ("00" & YFP(30 downto 23)) - 127;

-- Initialisierung von oi und Bestimmung von M für Wurzelberechnung case OP_CODE is

when X"01" => -- zirkularer Modus, Rotating if QZ_INT(31) = '0' then

oi <= 1; -- z0 >= 0 => oi ist positiv else

oi <= -1; -- z0 < 0 => oi ist negativ end if;

when X"03" => -- hyperbolischer Modus, Rotating if QZ_INT(31) = '0' then

oi <= 1; -- z0 >= 0 => oi ist positiv else

oi <= -1; -- z0 < 0 => oi ist negativ end if;

when X"04" => -- hyperbolischer Modus, Vectoring, Berechnung ln if QY_INT(31) = '0' then

oi <= -1; -- y0 >= 0 => oi ist negativ else

oi <= 1; -- y0 < 0 => oi ist positiv end if;

when others => -- hyperbolischer Modus, Vectoring, Berechnung sqrt if QY_INT(31) = '0' then

oi <= -1; -- y0 >= 0 => oi ist negativ else

oi <= 1; -- y0 < 0 => oi ist positiv end if;

QX_INT <= QX_INT + X"04000000"; -- Addition von 0.25d

QY_INT <= QY_INT - X"04000000"; -- Subtraktion von 0.25d end case;

when Z3 => -- Beginn der Iteration if m = 1 then

-- einfache Shiftfolge für zirkularen Modus N:=Bit5Int(QS); -- Rechtsshift um QS Stellen else

-- komplexere Shiftfolge für hyperbolischen Modus if QS < "00100" then

N:=Bit5Int(QS) + 1;

elsif QS < "01110" then N:=Bit5Int(QS);

else

N:=Bit5Int(QS) - 1;

end if;

end if;

for I in 0 to 31 loop if I >= N then

VX_SHIFT(I-N):=QX_INT(I);

VY_SHIFT(I-N):=QY_INT(I);

else

if QX_INT(31) = '0' then

-- Zahl ist positiv => Null einschieben VX_SHIFT(32-N+I):='0';

else

-- Zahl ist negativ => Eins einschieben VX_SHIFT(32-N+I):='1';

end if;

if QY_INT(31) = '0' then

-- Zahl ist positiv => Null einschieben VY_SHIFT(32-N+I):='0';

else

-- Zahl ist negativ => Eins einschieben VY_SHIFT(32-N+I):='1';

end if;

end if;

end loop;

if m = 1 then if oi = 1 then

VX_INT := QX_INT - VY_SHIFT;

VY_INT := QY_INT + VX_SHIFT;

VZ_INT := QZ_INT - ROM_arctan(N);

else

VX_INT := QX_INT + VY_SHIFT; -- oi ist -1 VY_INT := QY_INT - VX_SHIFT;

VZ_INT := QZ_INT + ROM_arctan(N);

end if;

else

if oi = 1 then VX_INT := QX_INT + VY_SHIFT;

VY_INT := QY_INT + VX_SHIFT;

VZ_INT := QZ_INT - ROM_artanh(N-1);

else

VX_INT := QX_INT - VY_SHIFT;

VY_INT := QY_INT - VX_SHIFT;

VZ_INT := QZ_INT + ROM_artanh(N-1);

end if;

end if;

-- Bestimmung von oi case OP_CODE is

when X"01" => if VZ_INT(31) = '0' then

oi <= 1; -- z >= 0 => oi ist positiv else

oi <= -1; -- z < 0 => oi ist negativ end if;

when X"03" => if VZ_INT(31) = '0' then

oi <= 1; -- z >= 0 => oi ist positiv else

oi <= -1; -- z < 0 => oi ist negativ end if;

when others => if VY_INT(31) = '0' then

oi <= -1; -- y >= 0 => oi ist negativ else

oi <= 1; -- y < 0 => oi ist positiv end if;

end case;

QX_INT <= VX_INT(31 downto 0);

QY_INT <= VY_INT(31 downto 0);

QZ_INT <= VZ_INT;

when Z4 => case OP_CODE is

when X"01" => -- Umwandlung des Zweierkomplements in die Vorzeichen-Betrag-Darstellung if QX_INT(31) = '1' then

VX_INT(31 downto 0) := QX_INT(31) & (not(QX_INT(30 downto 0)) + 1);

else

VX_INT(31 downto 0) := QX_INT;

end if;

if QY_INT(31) = '1' then

VY_INT(31 downto 0) := QY_INT(31) & (not(QY_INT(30 downto 0)) + 1);

else

VY_INT(31 downto 0) := QY_INT;

end if;

QX_INT <= VX_INT(31 downto 0); -- unskalierte Vorzeichen-Betrag-Darstellung QY_INT <= VY_INT(31 downto 0); -- unskalierte Vorzeichen-Betrag-Darstellung

--Beginn der seriellen Konstantenmultiplikation

V_ROM_X1_OUT := K1_ROM_X1(Bit6Int(VX_INT(6 downto 1)));

V_ROM_Y1_OUT := K1_ROM_Y1(Bit6Int(VY_INT(6 downto 1)));

QX_MULT <= QX_INT(31) & (("000000" & V_ROM_X1_OUT(31 downto 6)) + K1_ROM_X2(Bit6Int(VX_INT(12 downto 7))));

QY_MULT <= QY_INT(31) & (("000000" & V_ROM_Y1_OUT(31 downto 6)) + K1_ROM_Y2(Bit6Int(VY_INT(12 downto 7))));

when X"03" => --Addition von QX_INT (cosh) und QY_INT (sinh) zur Exponentialfunktion VX_INT(31 downto 0) := QX_INT + QY_INT;

--Umwandlung des Zweierkomplements in die Vorzeichen-Betrag-Darstellung if VX_INT(31) = '1' then

VX_INT(31 downto 0) := VX_INT(31) & (not(VX_INT(30 downto 0)) + 1);

--else

-- VX_INT(31 downto 0) := QX_INT;

end if;

QX_INT <= VX_INT(31 downto 0); -- unskalierte Vorzeichen-Betrag-Darstellung QY_INT <= "00000000000000000000000000000000"; -- löschen

--Beginn der seriellen Konstantenmultiplikation

V_ROM_X1_OUT := K2_ROM_X1(Bit6Int(VX_INT(6 downto 1)));

QX_MULT <= QX_INT(31) & (("000000" & V_ROM_X1_OUT(31 downto 6)) + K2_ROM_X2(Bit6Int(VX_INT(12 downto 7))));

QY_MULT <= "000000000000000000000000000000000";

when X"04" => -- in QZ_INT steht der Areatangens hyperbolicus

QZ_INT <= QZ_INT(30 downto 0) & '0'; -- Linksshift => 2*artanh()

if QREF_EXP_XY(9) = '1' then -- Umwandlung von QREF_EXP_XY in Vorzeichen-Betrag-Darstellung QREF_EXP_XY <= (QREF_EXP_XY(9) & not(QREF_EXP_XY(8 downto 0))) + 1;

end if;

QX_MULT <= "000000000000000000000000000000000";

QY_MULT <= "000000000000000000000000000000000";

when others => -- in QX_INT steht sqrt(r) (unskaliert)

-- Umwandlung des Zweierkomplements in die Vorzeichen-Betrag-Darstellung

if QX_INT(31) = '1' then

VX_INT(31 downto 0) := QX_INT(31) & (not(QX_INT(30 downto 0)) + 1);

else

VX_INT(31 downto 0) := QX_INT;

end if;

--Beginn der seriellen Konstantenmultiplikation

V_ROM_X1_OUT := K2_ROM_X1(Bit6Int(VX_INT(6 downto 1)));

QX_MULT <= QX_INT(31) & (("000000" & V_ROM_X1_OUT(31 downto 6)) + K2_ROM_X2(Bit6Int(VX_INT(12 downto 7))));

QY_MULT <= "000000000000000000000000000000000";

end case;

when Z5 => case OP_CODE is

when X"01" => QX_MULT(31 downto 0) <= ("000000" & QX_MULT(31 downto 6)) + K1_ROM_X2(Bit6Int(QX_INT(18 downto 13)));

QY_MULT(31 downto 0) <= ("000000" & QY_MULT(31 downto 6)) + K1_ROM_Y2(Bit6Int(QY_INT(18 downto 13)));

when X"03" => QX_MULT(31 downto 0) <= ("000000" & QX_MULT(31 downto 6)) + K2_ROM_X2(Bit6Int(QX_INT(18 downto 13)));

when X"04" => if QREF_EXP_XY(9) = '1' then

QE_LN_2 <= ('0' & not(K3_ROM(Bit6Int(QREF_EXP_XY(5 downto 0))))) + 1;

else

QE_LN_2 <= '0' & K3_ROM(Bit6Int(QREF_EXP_XY(5 downto 0)));

end if;

-- Für die Addition von QE_LN_2 werden in QZ_INT drei zusätzliche Overflow-Bits -- eingefügt, wodurch die drei niederwertigsten Addition-Bits verloren gehen;

if QZ_INT(31) = '1' then

QZ_INT <= QZ_INT(31) & "111" & QZ_INT(30 downto 3);

else

QZ_INT <= QZ_INT(31) & "000" & QZ_INT(30 downto 3);

end if;

when others => QX_MULT(31 downto 0) <= ("000000" & QX_MULT(31 downto 6)) + K2_ROM_X2(Bit6Int(QX_INT(18 downto 13)));

-- Anpassung des Referenzexponenten (E mod 2 = 1 => Addition von 1) if QE_MOD_2 = '1' then

QREF_EXP_XY <= QREF_EXP_XY + 1;

end if;

end case;

when Z6 => case OP_CODE is

when X"01" => QX_MULT(31 downto 0) <= ("000000" & QX_MULT(31 downto 6)) + K1_ROM_X2(Bit6Int(QX_INT(24 downto 19)));

QY_MULT(31 downto 0) <= ("000000" & QY_MULT(31 downto 6)) + K1_ROM_Y2(Bit6Int(QY_INT(24 downto 19)));

when X"03" => QX_MULT(31 downto 0) <= ("000000" & QX_MULT(31 downto 6)) + K2_ROM_X2(Bit6Int(QX_INT(24 downto 19)));

when X"04" => -- Addition von QZ_INT und QE_LN_2

QE_LN_2(31 downto 0) <= QZ_INT + QE_LN_2(31 downto 0);

when others => QX_MULT(31 downto 0) <= ("000000" & QX_MULT(31 downto 6)) + K2_ROM_X2(Bit6Int(QX_INT(24 downto 19)));

-- Anpassung des Referenzexponenten (Shiftoperation) if QREF_EXP_XY(9) = '1' then

-- Exponent ist negativ => von links eine '1' nachziehen QREF_EXP_XY <= QREF_EXP_XY(9) & '1' & QREF_EXP_XY(8 downto 1);

else

QREF_EXP_XY <= QREF_EXP_XY(9) & '0' & QREF_EXP_XY(8 downto 1);

end if;

when Z7 => case OP_CODE is

when X"01" => QX_MULT(31 downto 0) <= ("000000" & QX_MULT(31 downto 6)) + K1_ROM_X2(Bit6Int(QX_INT(30 downto 25)));

QY_MULT(31 downto 0) <= ("000000" & QY_MULT(31 downto 6)) + K1_ROM_Y2(Bit6Int(QY_INT(30 downto 25)));

when X"03" => QX_MULT(31 downto 0) <= ("000000" & QX_MULT(31 downto 6)) + K2_ROM_X2(Bit6Int(QX_INT(30 downto 25)));

-- in QX_MULT steht jetzt das skalierte 33-Bit-Ergebnis der CORDIC-Iteration

when X"04" => -- Umwandlung des Zweierkomplements in die Vorzeichen-Betrag-Darstellung if QE_LN_2(31) = '1' then

QE_LN_2 <= (QE_LN_2(31) & '0' & (not(QE_LN_2(30 downto 0)))) + 1;

else

QE_LN_2 <= QE_LN_2(31) & '0' & QE_LN_2(30 downto 0);

end if;

when others => QX_MULT(31 downto 0) <= ("000000" & QX_MULT(31 downto 6)) + K2_ROM_X2(Bit6Int(QX_INT(30 downto 25)));

end case;

when Z8 => -- Umwandlung in das externe 32-Bit-Gleitkommaformat -- Korrektur des Referenzexponenten

VREF_EXP_X := QREF_EXP_XY - CountX_mult + QQUOTIENT + 127;

VREF_EXP_Y := QREF_EXP_XY - CountY_mult + QQUOTIENT + 127;

VREF_EXP_Z := 127 - CountZ_add + 3;

case OP_CODE is

when X"01" => case FALLUNTERSCHEIDUNG is

when "00" => QXFP_OUT <= QX_MULT(32) & VREF_EXP_X(7 downto 0) & ManXout(22 downto 0);

QYZFP_OUT <= QY_MULT(32) & VREF_EXP_Y(7 downto 0) & ManYout(22 downto 0);

when "01" => QXFP_OUT <= not(QY_MULT(32)) & VREF_EXP_Y(7 downto 0) & ManYout(22 downto 0);

QYZFP_OUT <= QX_MULT(32) & VREF_EXP_X(7 downto 0) & ManXout(22 downto 0);

when "10" => QXFP_OUT <= not(QX_MULT(32)) & VREF_EXP_X(7 downto 0) & ManXout(22 downto 0);

QYZFP_OUT <= not(QY_MULT(32)) & VREF_EXP_Y(7 downto 0) & ManYout(22 downto 0);

when "11" => QXFP_OUT <= QY_MULT(32) & VREF_EXP_Y(7 downto 0) & ManYout(22 downto 0);

QYZFP_OUT <= not(QX_MULT(32)) & VREF_EXP_X(7 downto 0) & ManXout(22 downto 0);

when others =>

end case;

when X"03" => QXFP_OUT <= QX_MULT(32) & VREF_EXP_X(7 downto 0) & ManXout(22 downto 0);

QYZFP_OUT <= "00000000000000000000000000000000";

when X"04" => QXFP_OUT <= "00000000000000000000000000000000";

QYZFP_OUT <= QE_LN_2(32) & VREF_EXP_Z(7 downto 0) & ManZout(22 downto 0);

when others => QXFP_OUT <= QX_MULT(32) & VREF_EXP_X(7 downto 0) & ManXout(22 downto 0);

QYZFP_OUT <= "00000000000000000000000000000000";

end case;

when others =>

end case;

end process A_BEST;

XFP_OUT <= QXFP_OUT;

YZFP_OUT <= QYZFP_OUT;

end CORDIC_VERSION_1_A;

-- 24_Bit_Barrelshifter.vhd library IEEE;

use IEEE.STD_LOGIC_1164.ALL;

use IEEE.STD_LOGIC_ARITH.ALL;

use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity SHFT24LR is

port(E: in std_logic_vector(23 downto 0);

COUNT: in std_logic_vector(7 downto 0);

SHIFT_DIRECTION: in std_logic;

OV_BITS: out std_logic_vector(1 downto 0);

A: out std_logic_vector (23 downto 0));

end SHFT24LR;

architecture SHFT24LR_A of SHFT24LR is

signal SELECTOR: std_logic_vector(8 downto 0);

begin

SELECTOR <= SHIFT_DIRECTION & COUNT;

with SELECTOR select

A <= E when "000000000", -- Rechtsshift '0' & E(23 downto 1) when "000000001",

"00" & E(23 downto 2) when "000000010", "000" & E(23 downto 3) when "000000011", "0000" & E(23 downto 4) when "000000100", "00000" & E(23 downto 5) when "000000101", "000000" & E(23 downto 6) when "000000110", "0000000" & E(23 downto 7) when "000000111", "00000000" & E(23 downto 8) when "000001000", "000000000" & E(23 downto 9) when "000001001", "0000000000" & E(23 downto 10) when "000001010", "00000000000" & E(23 downto 11) when "000001011", "000000000000" & E(23 downto 12) when "000001100", "0000000000000" & E(23 downto 13) when "000001101", "00000000000000" & E(23 downto 14) when "000001110", "000000000000000" & E(23 downto 15) when "000001111", "0000000000000000" & E(23 downto 16) when "000010000", "00000000000000000" & E(23 downto 17) when "000010001", "000000000000000000" & E(23 downto 18) when "000010010", "0000000000000000000" & E(23 downto 19) when "000010011", "00000000000000000000" & E(23 downto 20) when "000010100", "000000000000000000000" & E(23 downto 21) when "000010101", "0000000000000000000000" & E(23 downto 22) when "000010110", "00000000000000000000000" & E(23) when "000010111",

E when "100000000", -- Linksshift E(22 downto 0) & '0' when "100000001", -- um eine Stelle E(21 downto 0) & "00" when "100000010", -- um zwei Stellen

"000000000000000000000000" when others;

OV_BITS <= '0' & E(23) when SELECTOR = "100000001" else E(23 downto 22) when SELECTOR = "100000010" else "00";

end SHFT24LR_A;

-- CONV_FP_TC.vhd

-- Konvertierung einer Gleitkommazahl in das interne 32-Bit-Festkommaformat (Zweikomplement-Darstellung) library IEEE;

use IEEE.STD_LOGIC_1164.ALL;

use IEEE.STD_LOGIC_ARITH.ALL;

use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity CONV_FP_TC is

port(MANTISSE: in std_logic_vector(23 downto 0);

VZ: in std_logic;

OV_BITS: in std_logic_vector(1 downto 0);

S_INT: out std_logic_vector(31 downto 0));

end CONV_FP_TC;

architecture CONV_FP_TC_A of CONV_FP_TC is begin

with VZ select

S_INT <= VZ & OV_BITS & MANTISSE(23 downto 0) & "00000" when '0',

(VZ & not(OV_BITS) & not(MANTISSE(23 downto 0)) & "11111") + 1 when '1', "00000000000000000000000000000000" when others;

end CONV_FP_TC_A;

-- EXTENDING_DOMAIN_EXP.vhd

-- Erweiterung des Argumente-Bereichs der exp-Funktion auf +- 16 library IEEE;

use IEEE.STD_LOGIC_1164.ALL;

use IEEE.STD_LOGIC_ARITH.ALL;

use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity EXTENDING_DOMAIN is

port(EXPONENT: in std_logic_vector(7 downto 0);

MANTISSE: in std_logic_vector(23 downto 0);

MANTISSE_SHIFT: in std_logic_vector(23 downto 0);

QUOTIENT: out std_logic_vector(4 downto 0);

REST: out std_logic_vector (23 downto 0));

end EXTENDING_DOMAIN;

architecture EXTENDING_DOMAIN_A of EXTENDING_DOMAIN is

signal Man_1,Man_2,Man_3,Man_4,Man_5: std_logic_vector(24 downto 0);

signal Diff_1,Diff_2,Diff_3,Diff_4,Diff_5: std_logic_vector(24 downto 0);

signal Rest_1,Rest_2,Rest_3,Rest_4,Rest_5: std_logic_vector(23 downto 0);

constant LN_2: std_logic_vector(23 downto 0) := "010110001011100100001100";

begin

Man_1 <= '0' & MANTISSE;

Diff_1 <= Man_1 - (LN_2 & '0');

Rest_1 <= Diff_1(24 downto 1) when Diff_1(24) = '0' else Man_1(24 downto 1);

Man_2 <= Man_1(23 downto 0) & '0' when Diff_1(24) = '1' else Diff_1(23 downto 0) & '0';

Diff_2 <= Man_2 - (LN_2 & '0');

Rest_2 <= Diff_2(24 downto 1) when Diff_2(24) = '0' else Man_2(24 downto 1);

Man_3 <= Man_2(23 downto 0) & '0' when Diff_2(24) = '1' else Diff_2(23 downto 0) & '0';

Diff_3 <= Man_3 - (LN_2 & '0');

Rest_3 <= Diff_3(24 downto 1) when Diff_3(24) = '0' else Man_3(24 downto 1);

Man_4 <= Man_3(23 downto 0) & '0' when Diff_3(24) = '1' else Diff_3(23 downto 0) & '0';

Diff_4 <= Man_4 - (LN_2 & '0');

Rest_4 <= Diff_4(24 downto 1) when Diff_4(24) = '0' else Man_4(24 downto 1);

Man_5 <= Man_4(23 downto 0) & '0' when Diff_4(24) = '1' else Diff_4(23 downto 0) & '0';

Diff_5 <= Man_5 - (LN_2 & '0');

Rest_5 <= Diff_5(24 downto 1) when Diff_5(24) = '0' else Man_5(24 downto 1);

with EXPONENT select

REST <= Rest_1 when "01111110", Rest_2 when "01111111", Rest_3 when "10000000", Rest_4 when "10000001", Rest_5 when "10000010",

--"000000000000000000000000" when others;

MANTISSE_SHIFT when others;

with EXPONENT select

QUOTIENT <= "0000" & (not(Diff_1(24))) when "01111110",

"000" & (not(Diff_1(24) & Diff_2(24))) when "01111111",

"00" & (not(Diff_1(24) & Diff_2(24) & Diff_3(24))) when "10000000",

ÄHNLICHE DOKUMENTE