Sunteți pe pagina 1din 8

IEEE-754 Multiplicator în virgulă mobilă

Shyam Shankar H R
EE15B127

septembrie 16, 2017

Enunțarea problemei
Întrebarea nr.: 18. Pentru a implementa multiplicarea în virgulă mobilă cu format de precizie unic IEEE.

Procedură
1. Obținerea semnului produsului.

2. Adunarea exponenților și scăderea părtinirii (=127).

3. Înmulțirea mantisei cu MSB 1 concatenat.

4. Plasarea punctului binar în rezultat și verificarea cerinței de normalizare.

5. Normalizarea mantisei și creșterea exponenților dacă este necesar.

6. Rotunjirea mantisei la 23 de biți.

7. Verificarea pentru subrevărsare/preaplin.

Codul verilog scris este aproape în întregime structural.

Implementare (la nivel de modul)


0.1 Identificarea bitului de semn
Pentru a găsi bitul de semn al produsului, pur și simplu XOR biții de semn ai multiplicatorului și multiplicatorului. Bitul semnului 1 implică -ve și
0 implică +ve.

Codul Verilog:
modul sign_bit( semnal fir ieșire, cablu intrare[31:0] ini, cablu intrare [31:0] in2);
xor(semn,ini[31],in2[31]); Modul final

0.2 Adăugarea exponenților și scăderea părtinirii


Avem nevoie de un adder pe 8 biți și un subtractor pe 9 biți (pentru a include transportul de adăugare, în minuend). Aici, am făcut un modul
adder complet și am implementat algoritmul ripple carry pentru a-l face adder pe 8 biți. Aici adderul de transport ondulat este suficient,
deoarece complexitatea generală a codului va fi determinată de partea de multiplicare mantissa (24bit x 24bit).

1
Codul Verilog:
Am bit modulul Full Adder full_adder (suma firului de ieșire, cout de sârmă de ieșire, fir de intrare ini, fir de intrare în2, cin de sârmă de intrare);
tempi de sârmă;
temp de sârmă2;
temp de sârmă3;
xor(sum,ini,in2,cin);
și(tempi,ini,in2); și(temp2,ini,cin); și(temp3,în2,cin);
sau(cout,templ,temp2,temp3); Modul final

Modul adder Ripple-carry pe 8 biți ripple_8( cablu de ieșire[7:0] sumă, cout de sârmă de ieșire,
cablu [7:0] ini, cablu [7:0]
intrare in2, cablu cin
intrare )
;
sârmă cl,c2,c3,c4,c5,c6,c7;
full_adder FAl(sum[0],cl,inl[0],in2[0],cin); full_adder FA2(sumă[l],c2,inl[l],in2[l],cl); full_adder FA3(sumă[2],c3,inl[2],în2[2],c2); full_adder
FA4(sumă[3],c4,inl[3],în2[3] ,c3); full_adder FA5(sumă[4],c5,inl[4],în2[4],c4); full_adder FA6(sumă[5],c6,inl[5],în2[5],c5); full_adder
FA7(sumă[6],c7,inl[6],în2[6],c6); full_adder FA8(sumă[7],cout,inl[7],în2[7],c7); Modul final

După adăugarea exponenților, trebuie să scădem părtinirea, care este 127. Folosind faptul că subtrahendul este întotdeauna o constantă
(001111111), putem face două subtractoare complete specializate (unde subtrahend este fixat la 0 și, respectiv, la 1).

Subtractor complet cu subtrahend = 1 Subtractor complet cu subtrahend = 0


Aceste circuite logice sunt obținute din tabele simple de adevăr, care nu sunt prezentate aici.

Codul Verilog:
Subtractor I bit cu subtrahend = 1 modul full_subtractor_subl(
sârmă de ieșire dif, //diferență sârmă de ieșire, //împrumut sârmă de intrare min, minuend
Coș de intrare împrumut în

2
);
Aici, subtrahendul este întotdeauna 1. Îl putem implementa ca: xnor(diff,min,bin);
sau (bout, "min, bin) ;
Modul final

I bit subtractor cu subtrahend = 0 modul full_subtractor_subO( sârmă de ieșire diff, //diferență sârmă de ieșire, //împrumut sârmă de intrare min,
//minuend fir de intrare bin //împrumut în );
Aici, subtrahendul este întotdeauna O. Îl putem implementa ca: xor(diff,min,bin);
și(bout,~min,bin); Modul final

În cele din urmă, facem subtractorul părtinitor (subtractor pe 9 biți) după cum urmează:

Codul Verilog:
Subtractor pe 9 biți
modulul subtractor_9(
cablu ieșire [8:0] dif,
ieșirea firului de ieșire,
cablu intrare [8:0] min,
Coș de intrare
);
sârmă bl,b2,b3,b4,b5,b6,b7,b8;
full_subtractor_subl subl(diff[0],bl,min[0],bin);
full_subtractor_subl sub2(dif[1],b2,min[l],bl);
full_subtractor_subl sub3(dif[2],b3,min[2],b2);
full_subtractor_subl sub4(dif[3],b4,min[3],b3);
full_subtractor_subl sub5(dif[4],b5,min[4],b4);
full_subtractor_subl sub6(dif[5],b6,min[5],b5);
full_subtractor_subl sub7(dif[6],b7,min[6],b6);
full_subtractor_subO sub8(dif[7],b8,min[7],b7); Două dintre cele mai semnificative și subtrahends sunt 0 în 001111111. full_subtractor_subO
sub9(diff[8],bout,min[8],b8);
Modul final

0.3 Înmulțirea mantissei folosind multiplicatorul Carry Save


Trebuie să adăugăm bitul "1" atât la mantissa, cât și să înmulțim numerele de 24 de biți rezultate. Am implementat o rutină de multiplicare
carry save pentru a implementa acest lucru. În înmulțirea cu salvarea transportului, transportul de la fiecare nivel al sumelor parțiale ale
produsului curge la nivelul următor în diagonală. Este ilustrat în figura prezentată (preluată din Computer Organization ediția a 5-a, Carl
Hamacher):

Mai întâi facem un modul pentru celula cu un singur bit:

3
Codul Verilog:
bloc de module(
sârmă de ieșire ppo, //ieșire termen parțial de produs de ieșire sârmă de ieșire, //ieșire efectuați mout de sârmă de ieșire, //multiplicator de ieșire termen
de intrare sârmă de intrare min, //multiplicator de intrare termen de intrare fir de intrare ppi, //termen de intrare parțial de produs fir de intrare q,
//termen multiplicator de intrare sârmă de intrare cin //transport în );
temperatura sârmei;
și(temp,min,q);
full_adder FA(ppo,cout,ppi,temp,cin);
sau(mout,min,l'bO);
Modul final

Apoi, extindem această celulă de biți pentru a implementa un rând de 23 de astfel de celule cu un singur bit:

Codul Verilog:
rândul modulului(
cablu de ieșire[23:0] ppo,
cablu de ieșire[23:0] mout,
suma firului de ieșire,
cablu de intrare[23:0] min,
cablu de intrare [23:0] ppi, fir de intrare q );
sârmă cl,c2,c3,c4,c5,c6,c7,c8,c9,clO;
sârmă CLL,CL2,CL3,CL4,CL5,CL6,CL7,CL8,CL9,C20;
sârmă C21,C22,C23;
bloc bl (sumă,cl,mout[0],min[0],ppi[0],q,l'bO);
IEEE-754 Multiplicator în virgulă mobilă 1
Enunțarea problemei 1
Procedură 1
Implementare (la nivel de modul) 1
0.1 Identificarea bitului de semn 1
Codul Verilog: 1
0.2 Adăugarea exponenților și scăderea părtinirii 1
Codul Verilog: 2
Codul Verilog: 2
Codul Verilog: 3
0.3 Înmulțirea mantissei folosind multiplicatorul Carry Save 3
Codul Verilog: 4
Codul Verilog: 4
Codul Verilog: 5
0.4 Plasarea punctului binar și normalizarea mantisei 5
Codul Verilog: 5
0.5 Modul de verificare și control al debitului/preaplinului pentru operarea altor module 6
Codul Verilog: 6
Banc de încercare 6
Codul Verilog: 6
Intrări și rezultate ale testelor 7
Comandă ieșire promt 8
Referinţe 8

4
blocul B24(PPO[22], PPO [23], Mout[23], Min[23], PPI [23], Q, C23); Modul final

În cele din urmă, extindem rândurile pentru a forma grilele diagonale. Singurele intrări ale acestui modul sunt multiplicatorul și multiplicatorul,
iar ieșirea este produsul final. Avem 24 de rânduri care iau câte un bit din multiplicator. Acesta este modulul de nivel superior al
multiplicatorului de salvare a transportului:

Codul Verilog:
produs modul(
cablu de ieșire[47:0] sumă,
cablu de intrare[23:0] min,
cablu de intrare[23:0]q
);
fir [23:0] tempi,temp2,temp3,temp4,temp5,temp6,temp7,temp8,temp9,templ0; diagonală m
sârmă [23:0] templl,templ2,templ3,templ4,templ5,templ6,templ7,templ8,templ9,temp20;
sârmă [23:0] temp21,temp22,temp23,temp24;
sârmă [23:0] ptempl,ptemp2,ptemp3,ptemp4,ptemp5,ptemp6,ptemp7,ptemp8,ptemp9,ptempl0;
verticală p
sârmă [23:0] ptempll,ptempl2,ptempl3,ptempl4,ptempl5,ptempl6,ptempl7,ptempl8,ptempl9,ptemp20;
sârmă [23:0] ptemp21,ptemp22,ptemp23;
rândul rl (ptempl, tempi, sum[0] , min, 24'h000000, q[0]);
rând r2 (ptemp2, temp2, sumă[l], Tempi ptempl, q[l]);
rând r3 (ptemp3, temp3, sumă[2], temp2, ptemp2, î[2]);
rând r4 (ptemp4, temp4, sumă[3], temp3, ptemp3, î[3]);
rând r5 (ptemp5, temp5, sumă[4], temp4, ptemp4, î[4]);
rând R6 (ptemp6, temp6, sumă[5], temp5, ptemp5, î[5]);
rând r7 (ptemp7, temp7, sumă[6], temp6, ptemp6, î[6]);
rând r8 (ptemp8, temp8, sumă[7], temp7, ptemp7, î[7]);
rând R9 (ptemp9, temp9, sumă[8], temp8, ptemp8, î[8]);
rândul r10(ptemp10, templO, sum[9] , temp9, ptemp9, q[9]);
rândul r11(ptemp11, templl, sum[10] , templO, ptemplO, q[10]);
rândul Rl2(Ptempl2, Templ2, Sum[ll], Templl, Ptempll, Q[ll]);
rândul Rl3(Ptempl3, Templ3, SUM[12], Templ2, Ptempl2, Q[12]);
rândul rl4(ptempl4, templ4, sum[13], templ3, ptempl3, q[13]);
rândul Rl5(Ptempl5, Templ5, Sum[14], Templ4, Ptempl4, Q[14]);
rândul Rl6(Ptempl6, Templ6, Sum[15], Templ5, Ptempl5, Q[15]);
rândul Rl7(Ptempl7, Tempi?, Sum[16], Templ6, Ptempl6, Q[16]);
rândul Rl8(Ptempl8, Templ8, Sum[17], Templ7, Ptempl7, Q[17]);
rândul Rl9(Ptempl9, Templ9, Sum[18], Templ8, Ptempl8, Q[18]);
rândul R20(ptemp20, temp20, sum[19], templ9, ptempl9, q[19]);
rândul R21(PTEMP21, TEMP21, SUM[20], TEMP20, PTEMP20, Q[20]);
rândul R22(Ptemp22, Temp22, Sum[21], Temp21, Ptemp21, Q[21]);
rândul R23(Ptemp23, Temp23, Sum[22], Temp22, Ptemp22, Q[22]);
rândul R24(sumă[47:24], temp24, sumă[23], temp23, ptemp23, q[23]);
Modul final

0.4 Plasarea punctului binar și normalizarea mantisei


Într-un număr în virgulă mobilă IEEE-754 normalizat, va exista un "l" bit la stânga punctului binar. În timp ce înmulțim mantissa (23 de biți
rămași din punctul binar), am ingerat punctul binar. Deci, în rezultat, cei 46 de biți inferiori se află la stânga punctului binar, adică punctul binar
apare între biții 45 și 46 (începând de la bitul Oth la LSB). După plasarea punctului binar, dacă a mai rămas doar un "1" bit din acesta, nu este
nevoie de normalizare. Dar dacă există MSB "1" apare un bit tată din punct binar, trebuie să normalizăm mantissa, adică să-l schimbăm la
dreapta cu unul. În matissa produsului final, există doar 23 de biți, așa că rotunjim rezultatul nostru la 23 de biți (trunchiere simplă). Bitul "I"
rămas din punctul binar este aruncat în produsul mantissa. Aici, facem un modul "normalizare" pentru a efectua aceste operațiuni. De
asemenea, generează un bit de pavilion "norm_flag", pentru a indica faptul că normalizarea se face și trebuie să creștem exponentul cu 1. De
asemenea, în loc să schimbăm dreapta și apoi să renunțăm la termenii în exces, doar tăiem biții, adică captăm din [45:23] dacă nu există
normalizare și din [46:24] dacă există normalizare. În cele din urmă, un multiplexor este utilizat pentru a canaliza mantissa corespunzătoare
(deplasată sau intactă) în funcție de "norm_flag".

Codul Verilog:
normalizarea modulului(
cablu de ieșire[22:0] adj_mantissa, //mantissa ajustată (după extragerea piesei necesare) cablu de ieșire norm_flag, fir de intrare[47:0] prdt
); Returnează norma = 1 dacă trebuie făcută normalizarea.
și(norm_flag,prdt[47],1'bl); sei = 1 dacă cel care conduce este la 47 ... are nevoie de normalizare
Dacă sei = 0, conducând zero nu la 47... nu este nevoie de rezultate de sârmă de normalizare [1:0][22:0];

5
atribuirea rezultatelor[0] = prdt[45:23];
atribuire rezultate[1] = prdt[46:24];
atribuiți adj_mantissa = {rezultate[norm_flag+0]};
Modul final

0.5 Modul de verificare și control al debitului/preaplinului pentru operarea altor module


În acest modul, obținem diferite felii din rezultatul final, invocând modulele necesare în ordine. Exponentul final ar trebui să se situeze între 1 și
254. În timp ce găsiți exponent, dacă părtinirea expl + exp2 dă un împrumut, înseamnă un subflux. Și dacă exponentul final (după normalizare)
este 255 sau mai mare, atunci există o depășire. Aici invocăm modulul de normalizare pentru a verifica dacă exponentul trebuie incrementat
sau nu. Rezultatul final se formează sub formă de felii și se concatenează împreună.

Codul Verilog:
Modul de control pentru acționarea și reglarea modulelor necesare în ordinea controlului modulului (fir de intrare [31: 0] inpl, fir de intrare [31: 0]
inp2, fir de ieșire [31: 0] ieșire, subflux de sârmă de ieșire, depășire a firului de ieșire);
semn de sârmă;
cablu [7:0] expulza;
cablu [7:0] exp2;
cablu [7:0] exp_out;
cablu [7:0] test_exp;
sârmă [22:0] manti;
sârmă [22:0] mant2;
cablu [22:0] mant_out;
sign_bit sign_bitl(semn,inpl,inp2);
sârmă [7:0]tempi;
manechin de sârmă; pentru a conecta porturile COUT neutilizate ale transportului de sârmă Adder;
cablu [8:0] sub_temp;
ripple_8 ripl(tempi,carry,inpl[30:23],inp2[30:23],1'bO);
subtractor_9 subl(sub_temp,underflow,{carry,tempi},1'bO);
dacă există un perform = > underflow
și(preaplin,sub_temp[8],1'bl); dacă exponentul are mai mult de 8 biți: preaplin //luând produsul din mantissa: sârmă [47:0] prdt;
produs pl(prdt,{1'bl,inpl[22:0]},{1'bl,inp2[22:0]});
sârmă norm_flag;
cablu [22:0] adj_mantissa;
normalizați norml(adj_mantissa,norm_flag,prdt);
ripple_8 ripple_norm(test_exp,manechin,sub_temp[7:0],{7'b0,norm_flag},l'b0);
atribuiți [31] = semn;
atribui[30:23] = test_exp;
atribui[22:0] = adj_mantissa;
Modul final

Banc de încercare
Implementăm bancul de testare astfel încât să oferim patru intrări de testare programului, iar rezultatele sunt prezentate mai jos.

Codul Verilog:
"stimul pentru modulul INS/LPS;

6
Reg [31:0] INI;
reg [31:0] în2;
cablu [31:0] prdct;
revărsarea sârmei;
sârmă subterană;
cablu [7:0] test_exp;
sârmă [22:0] mant;
norma de sârmă;
control de control1(
.inpl(ini), .inp2(in2), .out(prdct), .underflow(underflow), .overflow(overflow);
Începutul inițial
$dumpfile("înmulțiți.vcd");
$dumpvars(0,stimul);
INI = 32'B01000010111101011010001010110010;
în2 = 32'b01000011001001100111010110110110;
producti = 0 10001101 00011111111001111001010
#10
INI = 32'bll010110110110100101011101000110;
în2 = 32'b0100101011101010010111000111000110010;
produs2 = 1 11000100 00111101111001001000001
#10
INI = 32'B010001010100100100100011110001010;
în2 = 32'b0100100110100101010001110110001;
#10
INI = 32'bll001001110100101101100001110100;
în2 = 32'bll000011001110110011011010101010100;
#10
$finish; capăt
Începutul inițial
$monitor("Multiplicand = %32b. Multiplicator = %32b. Produs = %32b. Underflow = 7,1b, Overflow = %1b" ,ini,in2,prdct,underflow,overflow) ;
capăt
Modul final

Intrări și rezultate ale testelor


Procesul nr. Multiplicare Multiplicator Produs
1 01000010110111010110001010110010 01000011001001100111010110110110 01000110100011111111001111001010
2 11010110110110100101011101000110 01001010101110100101110001110010 11100010000111101111001001000001
3 01000101010100100100011110001010 01001001101001011010001110110001 01001111100010000000111010010000
4 11001001110100101101100001110100 11000011001110110011011010110100 01001101100110100011000100101010

+1,12462746 x 214.
În proba 2, multiplicatorul este -1,705788373 x 246 , iar multiplicatorul este +1,455946207 x 222. Produsul se obține corect ca -
1.241768056 x 269.
Formele de undă obținute pentru observațiile de mai sus, folosind gtkwave, sunt prezentate mai jos:
În proba 1, multiplicatorul este +1,729574441 x 26 și multiplicatorul este +1,300467252 x 27. Produsul este obținut corect ca

7
Comandă ieșire promt

Referinţe
[1] Hamacher Computer Organization ediția a 5-a.
[2] Proiectarea și arhitectura sistemelor informatice, V.P Heuring.
[3] IEEE 754-2008, Standardul IEEE pentru aritmetica în virgulă mobilă, 2008.
[4] Douglas J. Smith, VHDL & Verilog comparat și contrastat, plus exemplu modelat scris în VHDL, Verilog și C
[5] http://www.ece.umd.edu/class/enee359a/verilog_tutorial.pdf

S-ar putea să vă placă și