Laboratorul 07 - Sumatorul Carry-Lookahead

Obiective

Scopul acestui laborator este proiectarea unui sumator Carry-lookahead, care are performanțe mai bune decât sumatorul Ripple-Carry studiat în laboratorul trecut.

1. Recapitulare

a. Sumatoare multi-bit

În viața reală noi lucrăm cu numere reprezentabile pe mai mulți biți. Totuși, sumatoarele de tip Half-Adder și Full-Adder pot aduna cel mult un bit. Pentru depășirea acestei limitări, laboratorul trecut am implementat un circuit capabil să facă suma numerelor reprezentate pe mai mulți biți.

Sumatorul Ripple-Carry

Cel mai simplu circuit este sumatorul ripple-carry care folosind N sumatoare full-adder poate însuma numere pe N biți.

 Ripple-carry pe 4 biți

Conectarea lor, prezentată în figura de mai sus, este una foarte simplă: ieșirea Cout a modulului de rang i va fi conectată la intrarea Cin a modulului de rang i+1.

Limitări

Implementarea acestuia este facilă, însă performanța este scăzută. De ce? Deoarece transportul de intrare pentru fiecare sumator complet este dependent de semnalul carry-out din full-adder-ul anterior. Prin structura sa internă: modulul de rang i trebuie să aştepte modulul de rang i-1 sa îşi termine execuția pentru a afla cât este Cin_i.

Îmbunătățiri

Cum putem implementa un circuit mai rapid? Eliminând dependența între rang-uri în ceea ce privește bitul de carry. Pentru început aflăm expresia în logică booleană pornind de la tabelul de adevăr al bitului de carry C1.

A0 B0 C0 C1
0 0 0 0
0 0 1 0
0 1 0 0
0 1 1 1
1 0 0 0
1 0 1 1
1 1 0 1
1 1 1 1

Scriem expresia logică corespunzătoare liniilor din tabel pentru care C1 are valoarea 1:

  • C1 = A0 * B0 * C0 + A0 * B0 * ~C0 + ~A0 * B0 * C0 + A0 * ~B0 * C0
  • C1 = A0 * B0 * (C0 + ~C0) + C0 * (~A0 * B0 + A0 * ~B0)
  • C1 = A0 * B0 + C0 * (A0 ⊕ B0)

Dacă generalizăm formula:

  • Ci+1 = Ai * Bi + Ci * (Ai ⊕ Bi)

Prin urmare, pentru fiecare modul de full-adder, am putea calcula bitul carry de intrare cu cost constant egal cu 1, fără să mai așteptăm propagarea acestuia prin toate celelalte full-adder-e de rang mai mic.

  • Cout = Generează_biții_carry? SAU Propagă_bitul_de_carry_de_la_rangul_inferior_dacă_nu_e_generat?

2. Prezentare generală

Pentru a reduce timpul necesar unui calcul, proiectanții folosesc sumatorul carry-lookahead.

 Sumator Carry-lookahead pe 4 biti

În sumatorul cu transport anticipat, fiecare adunare pe bit elimină dependenţa de semnalul carry-out anterior şi impune în schimb utilizarea valorilor celor doi operanzi de intrare. El functioneaza prin generarea a două noi semnale (P si G) pentru fiecare rang binar în funcție de starea intrărilor.

  • G - reprezintă un semnal de generare a unui bit de carry.
  • P - reprezintă un semnal de propagare a unui bit de carry.

Deci pentru suma a două numere A și B, dacă bitul n din A, împreună cu bitul n din B generează un semnal G, înseamnă că acești biți generează un bit de carry, iar în cazul unui semnal P, bitul de carry de la n-1 (dacă există) este propagat de către biții n pe poziția n+1.

Pornind de la un sumator ripple-carry, pentru fiecare full-adder (i), semnalul carry-out, c(i+1), este setat la 1 dacă una dintre următoarele condiții este adevărată:

  • Ai = 1 AND Bi = 1

sau

  • (Ai = 1 OR Bi = 1) AND ci = 1

am observat că putem calcula semnalul carry-out folosind doar semnalele rangului curent:

  • ci+1 = Ai & Bi | ci & (Ai | Bi) (1)

Pentru un sumator carry-lookahead definim Gi(Ai, Bi) ca fiind predicatul logic care este adevărat atunci când Ai * Bi generează carry (primul caz)

  • Gi(Ai, Bi) = Ai & Bi

Si Pi(Ai, Bi) ca fiind predicatul logic care este adevărat atunci cand Ai + Bi propagă carry (al doilea caz)

  • Pi(Ai, Bi) = Ai | Bi

Implementarea bitului de propagare cu XOR

Implementarea bitului de propagare cu XOR

Uneori (dar nu și în laboratorul de față) se folosește și o altă definiție a propagării. Exprimarea lui Pi = Ai + Bi va propaga carry-ul (dacă numai unul dintre Ai și Bi este 1), dar va propaga și atunci când sumatorul generează carry (Ai și Bi sunt ambele 1). Rezultatul final este corect oricum, însă preferăm să nu propagăm atunci când generăm carry. Astfel, putem folosi operatorul XOR, pentru a propaga carry-ul atunci când numai unul dintre biții Ai și Bi este 1, dar nu ambii:

  • P'i(Ai, Bi) = Ai ⊕ Bi

Desi OR(prima variantă) e mai rapid decât XOR(a doua variantă), pentru un sumator carry-lookahead pe mai multe nivele e mai avantajos să folosim P'i(Ai, Bi).

Rescriind ecuația (1) cu Pi si Gi, rezultă:

  • ci+1 = Gi | Pi & ci

Pentru o comparație mai tangibilă a întârzierilor celor 2 sumatoare (ripple-carry și carry-lookahead), puteți folosi aceste 2 simulatoare cu întârziere setabilă pentru porțile folosite (se pot observa întârzieri semnificative ale lui ripple-carry față de carry-lookahead pentru numere reprezentabile pe 32 de biți):

3. Detalii de implementare

Pentru fiecare rang dintr-o secvență binară, sumatorul va determina dacă perechea de biți care trebuie adunată poate genera sau propaga carry. Acest lucru permite circuitului sa “pre-proceseze” cei doi termeni ai adunării pentru a determina transportul înainte de a efectua adunarea propriu-zisă. Apoi, când aceasta are loc, nu va exista nici o întârziere de propagare a carry-ului, ca în cazul unui Ripple Adder. Mai jos aveți un exemplu de calcul al termenilor de propagare și, generare pentru un sumator de 2 biți:

  • c1 = G0 | P0 & c0
  • c2 = G1 | P1 & c1

Înlocuind c1 în expresia lui c2, vom obtine urmatoarele ecuații:

  • c1 = G0 | P0 & c0
  • c2 = G1 | P1 & G0 | P1 & P0 & c0

Similar, putem generaliza pentru un sumator de 4 biți:

  • c3 = G2 | P2 & G1 | P2 & P1 & G0 | P2 & P1 & P0 & c0

ȘI-ul logic (&) are prioritate față de SAU logic (|)!

Putem observa că pentru un sumator carry-lookahead cu 4 biți (cel de mai sus), propagarea semnalului de carry până la ieșirea ultimului nivel de adunare necesită trecerea prin 3 porți logice, pe când un sumator ripple-carry necesită trecerea prin 6 porți.

 Ripple-Carry vs. Carry-Lookahead

TL;DR

- Sumatorul Ripple-Carry calculează valoarea unui bit i din adunare doar după ce au avut loc calculele pentru toți biții de la 0 la i - 1, deci calculul pentru fiecare bit are loc secvențial.

- Sumatorul Carry-Lookahead calculează valoarea unui bit i independent de calculele pentru ceilalti biți (în paralel) folosind formulele:

  • Gi(Ai, Bi) = Ai & Bi
  • Pi(Ai, Bi) = Ai | Bi
  • ci+1 = Gi | Pi & ci

Exerciții

Pentru fiecare dintre exerciții va trebui să faceți atât implementarea cât și simularea cu seturi de date relevante. (minim 3 cazuri de test)

Task 01 (3p) Implementați un sumator carry-lookahead pe 4 biți.

Task 02 (1p) Implementați un scăzător carry-lookahead pe 4 biți, pornind de la punctul precedent.

Task 03 (2p) Implementați un sumator pe 16 de biți folosind modulul carry-lookahead deja implementat și logica sumatorului ripple-carry.

Task 04 (4p) Implementați un sumator/scăzător carry-lookahead pe 4 biti cu ajutorul plăcii de laborator. Interacțiunea cu modulul se va face astfel:

  • Intrări:
    • operandul A → 4 switch-uri
    • operandul B → 4 switch-uri
    • buton1 → buton pentru validarea operanzilor
    • buton2 → buton pentru operația de adunare
    • buton3 → buton pentru operația de scădere
    • buton reset
  • Ieșiri:
    • cele 8 leduri → pentru afisarea progresului (o_r_leds)
    • afisajul cu 7 segmente → pentru afișarea rezultatului (l_r_message)
  • Mod de operare:
    • STATE_INITIAL:
      • se introduc valorile celor doi operanzi folosind switch-urile
      • pe cele 8 leduri se va afișa valoarea PROGRESS_NONE
      • pe afișajul cu 7 segmente se va afișa valoarea unuia dintre operanzi
    • la apăsarea lui buton1:
      • se salvează în memorie valoarea operanzilor
      • se trece în starea STATE_OP_READ
    • STATE_OP_READ:
      • pe cele 8 leduri se va afișa valoarea PROGRESS_BOTH_OPERANDS
      • pe afișajul cu 7 segmente se va afișa mesajul APAS (PRESS_MESSAGE)
    • la apăsarea lui buton2 sau buton3:
      • se trece în starea STATE_RESULT_SELECT
    • STATE_RESULT_SELECT
      • pe cele 8 leduri se va afișa valoarea PROGRESS_RESULT
      • pe afișajul cu 7 segmente se va afișa:
        • mesajul APAS (PRESS_MESSAGE), dacă nu este apăsat nici buton2, nici buton3
        • suma celor doi operanzi din memorie, dacă este apăsat buton2
        • diferența celor doi operanzi din memorie, dacă este apăsat buton3
      • suma și diferența vor fi afișate în zecimal
    • pentru introducerea altor valori pentru operanzi se va apăsa butonul de reset
    • pentru a realiza operațiile veți folosi modulele create la exercițiile anterioare

Puteți porni de la soluția voastră pentru exercițiul 4 de la laboratorul precedent (chiar dacă nu este completă).

Resurse

soc/laboratoare/07.txt · Last modified: 2024/02/29 14:37 (external edit)
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0