Circuitos Aritméticos Somadores20Aritm%e9ticos.pdfINF 01058 – Circuitos Digitais – Circuitos...
Transcript of Circuitos Aritméticos Somadores20Aritm%e9ticos.pdfINF 01058 – Circuitos Digitais – Circuitos...
Circuitos Aritméticos Somadores
Por Bruno Silva Guedes1 - 159033
1. Introdução
Circuitos aritméticos somadores são circuitos combinacionais básicos, cujo
desenvolvimento ocorre desde os primórdios da informática. Neste trabalho, são analisados o
funcionamento e o princípio de cinco circuitos básicos, desde os mais simples até os mais
elaborados.
Primeiramente, serão apresentados os elementos básicos presentes nestes circuitos
(baseando-se em portas lógicas), como o full adder. Depois, um estudo detalhado será feito
dos somadores Ripple Carry Adder (simples, envolve apenas uma soma simples como a que
executamos com papel e caneta), o Carry Select Adder e o Carry Skip Adder, somadores mais
elaborados que partem do princípio de dividir um problema para resolvê-lo mais rapidamente,
e por fim o Parallel Prefix Adder e o Carry Look-Ahead, mais complexos, envolvendo conceitos
de propagação e geração de carry, que também serão abordados.
2. Elementos básicos
Iniciaremos a construção de circuitos aritméticos somadores com base nas portas
lógicas básicas: AND, OR e NOT (representadas pelos símbolos da Figura 2.1). Vale ressaltar
que todos os somadores aqui descritos são somadores de parcelas de 16 bits, ou seja, somam
números em base 2 com 16 algarismos (que podem ser 0 ou 1) cada. O princípio de uma soma
binária é exatamente o mesmo de uma soma decimal, como exemplificado na Figura 2.2.
1 1 1 0 1 1 1 0 + 1 0 1 1
1 1 0 0 1
Fig. 2.1 – (a) Porta AND de duas entradas, (b) porta OR de duas entradas e (c) porta NOT (inversora). A função AND possui saída 1 quando ambas as entradas possuem valor 1, caso contrário valor 0. A função OR possui saída 1 quando ao menos uma das entradas possui valor 1, caso contrário valor 0. Já a função NOT inverte o sinal de entrada, retornando 1 para uma entrada 0, e retornando 0 quando entra 1.
Fig. 2.2 – Aqui temos a soma de 14 com 11 (representação decimal). Note que uma soma de um dígito 0 com um dígito 1 é sempre 1, e uma soma de dois dígitos 1 é 0 (com um “vai-um” para o bit seguinte). O “vai-um” é geralmente chamado de carry out, enquanto que o “vem-um” (o bit que está “chegando” para ser somado no próximo dígito) é o carry in.
Vamos considerar a soma de um único par de bits (como na coluna da direita na
figura 2.2). Temos quatro situações de soma, dependendo do primeiro bit e do segundo bit.
Quando tivermos ambos os bits em 0, a soma será 0. Quando tivermos apenas um bit em 0, e
o outro em 1, a soma será 1. E quando tivermos ambos os bits em 1, teremos a soma deles
igual a 0 e um carry out igual a 1. As quatro situações estão representadas na Figura 2.3.
Seria conveniente encontrar funções lógicas que, a partir das entradas A e B,
derivassem as saídas Soma e Cout, que nos interessam. A saída Cout é claramente a função AND
1 Graduando em Engenharia de Computação
Universidade Federal do Rio Grande do Sul E-mail: [email protected]
INF 01058 – Circuitos Digitais – Circuitos Aritméticos Somadores
2 | P á g i n a
das entradas a e b (ela só vale 1 quando ambas as entradas são 1). Já a Soma é a função XOR
das entradas (a⊕b ⇔ (¬a.b)+(a.¬b)) (esta dedução pode ser obtida via mapa de Karnaugh, e
não será demonstrada aqui).
Assim, definimos o Half Adder,
conforme a figura 2.4.
Seria mais interessante ainda incluir
o carry in na soma das parcelas, ou seja,
somar três valores de entrada e gerar a saída
e o correspondente carry out. Isto seria útil
para a soma das duas colunas da esquerda na soma da Figura 2.2, por exemplo, já que elas
envolvem três valores significativos para a
soma daquela coluna. Considerando uma
soma envolvendo mais um bit de carry in
como parcela, teremos uma nova tabela
verdade, como a da Figura 2.5(a), para o que
chamaremos de Full Adder (somador
completo).
Resolvendo mais uma vez, para os valores de saída, via mapa de Karnaugh, as
funções de S e Cout, teremos:
S = a ⊕ b ⊕ Cin (1)
Cout = a.b + a.Cin + b.Cin (2)
As implementações de (1) e (2) podem ser visualizadas na Figura 2.5(b).
a b Cin S Cout 0 0 0 0 0 0 0 1 1 0 0 1 0 1 0 0 1 1 0 1 1 0 0 1 0 1 0 1 0 1 1 1 0 0 1 1 1 1 1 1
(a)
(b)
Fig. 2.5 – (a) Tabela verdade do Full Adder. A saída é um XOR das três entradas, enquanto o carry out é a soma dos produtos das entradas, duas a duas. (b) Full Adder em esquema de portas lógicas. Uma porta OR de três entradas é utilizada no cálculo do Cout.
O Full Adder será representado daqui em diante pelo símbolo da Figura 2.6.
Fig. 2.6 – Símbolo do Full Adder (bloco que executa as mesmas funções).
a b Soma Cout 0 0 0 0 0 1 1 0 1 0 1 0 1 1 0 1
Fig. 2.3 – Chamando a primeira parcela de a e a segunda parcela de b, temos a soma e o carry-out conforme disposto acima.
Fig. 2.4 – Half Adder (meio somador). Soma dois bits e gera o carry desta soma.
INF 01058 – Circuitos Digitais – Circuitos Aritméticos Somadores
3 | P á g i n a
3. Ripple Carry Adder
O Ripple Carry Adder (RCA) é o somador de n-bits mais básico que existe. Ele consiste
numa concatenação de diversos full adders como o da Figura 2.5(b). Em termos de espaço de
componentes, o RCA é o mais robusto em termos de uso de portas lógicas, pois executa a
soma com o menor número de portas possíveis (melhor que isso, só se um full adder fosse
reaproveitado para fazer as somas dos vários dígitos).
Funcionamento. O RCA calcula, bit a bit, com os respectivos carries in, cada bit da
saída, individualmente. Caso tenhamos uma soma de 64 bits, teremos 64 bits concatenados
somando trios de bits (as duas entradas mais o Cin). Infelizmente, esse processo não pode ser
paralelo, já que um Ci, por exemplo, precisa aguardar a geração do seu valor pelos i-1 bits
anteriores. Assim, nunca os bits de saída serão gerados ao mesmo tempo: o bit 0 de saída é
gerado primeiro, logo após o bit 1, e assim por diante, devido aos atrasos naturais que existem
nas portas lógicas.
Um somador RCA de 16 bits está mostrado na Figura 3.1.
Fig. 3.1 – Somador Ripple Carry Adder de 16 bits.
A dependência dos full adders no RCA é claramente vista na Figura 3.2, onde fica
melhor esclarecido o fato de que um full adder precisa esperar o sinal de carry out do full
adder anterior estabilizar.
Fig. 3.2 – Esquemático do Somador Ripple Carry Adder (no esquema soma apenas quatro bits. Considere FA como um full adder.
INF 01058 – Circuitos Digitais – Circuitos Aritméticos Somadores
4 | P á g i n a
4. Carry Select Adder
O Carry Select Adder (CSA) tenta resolver o problema de tempo do Ripple Carry
Adder. O tempo de execução de uma soma em um CSA pode ser até cinco vezes menor que no
seu antecessor, dependendo do número de bits e da divisão realizada. O princípio do CSA é
simples: dividir a soma em somas menores, que podem ser realizadas paralelamente e depois
unidas.
Funcionamento. A idéia do CSA é muito boa, porém, temos alguns problemas de
implementação. Vamos, por exemplo, dividir uma soma de 16 bits em 4 somas de quatro bits.
Infelizmente, a única informação que temos na soma inicial é o carry in apenas do bit 0, ou
seja, apenas uma destas 4 somas parciais terá seu carry correto. O problema é resolvido
fazendo duas somas para cada etapa, uma considerando que irá chegar um bit 0 da soma
parcial anterior, e uma soma considerando que chegará um bit 1 da soma anterior.
Outro problema surge agora: como saber qual das duas somas que fizemos na
mesma etapa é a correta? Neste caso, precisamos esperar pelo carry out da soma anterior,
porém, já teremos a soma parcial seguinte pronta, para as duas possibilidades de carry in.
Basta avaliar qual carry é o correto e então utilizar a soma parcial correta para a soma geral.
Para fazer essa avaliação, basta utilizar um multiplexador 2-para-1 como o da Figura
4.1, um componente que escolhe, de duas entradas, uma delas para conduzi-la à saída,
dependendo de um sinal de controle. No nosso CSA, teremos as duas somas, uma com Cin igual
a 0 e outra com Cin igual a 1 como entradas deste multiplexador, e o sinal de controle será o
Cout da soma parcial anterior, para averiguar qual das somas parciais é a correta.
Sinal de Controle
a b S
0 0 0 0
0 0 1 0
0 1 0 1
0 1 1 1
1 0 0 0
1 0 1 1
1 1 0 0
1 1 1 1
(a)
(b)
(c)
Fig. 4.1 – (a) Tabela verdade, (b) esquema de portas lógicas e (c) símbolo de um multiplexador 2-para-1.
Para realizar as somas parciais é necessário escolher um método de soma. Neste CSA,
serão usados Ripple Carry Adders que somam 4 bits, como o esquematizado pela Figura 3.2. A
soma de 16 bits será dividida em 4 somas de 4 bits, então. Para a primeira soma parcial, não
será necessário calcular duas vezes com carries in diferentes, já que o Cin já é definido. Para
cada uma das três somas parciais seguintes, teremos que usar dois ripples de 4 bits por etapa,
e um multiplexador para escolher qual das saídas é válida. Assim, o total de componentes que
serão usados no CSA consiste em 7 Ripple Carry Adders de 4 bits, 3 multiplexadores 2-para-1
de 4 bits (para conduzir um conjunto de valores, no caso, quatro), 3 multiplexadores 2-para-1
de 1 bit (para conduzir o carry out válido adiante). O esquemático para este CSA descrito acima
está na Figura 4.2.
INF 01058 – Circuitos Digitais – Circuitos Aritméticos Somadores
5 | P á g i n a
Fig. 4.2 – Esquemático do Somador Carry Select Adder.
Um somador CSA de 16 bits, dividido em 4 etapas de 4 bits, é mostrado na Figura 4.3.
Fig. 4.3 – Somador Carry Select Adder de 16 bits.
INF 01058 – Circuitos Digitais – Circuitos Aritméticos Somadores
6 | P á g i n a
5. Carry Skip Adder
O Carry Skip Adder usa uma abordagem semelhante à do Carry Select Adder: ele
procura dividir o problema em partes menores para juntar o resultado depois. A diferença
básica entre os dois, no entanto, reside no fato de o Carry Skip Adder não precisar de
multiplexadores na sua implementação, pois ele tenta “prever” o carry que chegará em cada
soma parcial do circuito.
Funcionamento. Neste exemplo de Carry Skip Adder de 16 bits, dividiremos a soma
em 4 somas menores de 4 bits. O que o Carry Skip Adder irá procurar são padrões que
garantem a geração de um carry out de valor 1 para a soma parcial seguinte. Caso haja um
jeito fácil de garantir a existência desse Cout em 1, poderemos economizar tempo em relação
ao atraso que a saída estará estabilizada e correta.
Na soma de dois números de 4 bits cada, sempre analisamos parcela por parcela.
Dizemos que um carry out foi gerado nessa soma caso tenhamos uma das duas situações: ou
os bits das casas mais significativas destes números são 1 (ambos), ou então um deles apenas
está em 1, porém recebeu na sua soma um carry in de valor 1. Esse carry in é o carry out do bit
imediatamente anterior, no qual faremos uma análise similar. Analisando recursivamente,
chegamos à seguinte conclusão: todos os pares, bit-a-bit, têm que possuir ao menos um bit 1
para transmitir um valor 1 de carry out no agrupamento todo. Além disso, é necessário que um
carry out no valor 1 chegue à este agrupamento (este sinal que será “propagado” pelos bits em
forma de carry).
Para fazer esta análise, utilizamos um circuito de detect como o da Figura 5.1(a). A
relação “ter que possuir ao menos um bit em 1” é dada pela porta OR.
(a)
(b)
Fig. 5.1 – (a) Circuito Detect, e (b) seu símbolo. Temos uma porta AND com seis entradas analisando a condição de propagação bit a bit (uma das entradas está fixada em valor lógico 1, já que uma porta de 5 entradas AND seria suficiente para este caso).
Este circuito apresenta alguns problemas de implementação que só serão resolvidos
nos dois somadores seguintes. Primeiro, nem sempre o detect detecta que realmente houve
um carry out igual a 1. Isso ocorre porque, por exemplo, poderíamos ter, na Figura 5.1(a), as
entradas i3 e j3 em 1, e todas as outras em 0 (incluindo Cin), que mesmo assim teríamos um
carry out gerado por esse trecho do circuito. Para estes casos, circuitos mais complexos
precisam ser elaborados para satisfazer casos distintos.
Pela análise feita no parágrafo acima, nota-se que não podemos garantir com certeza
que o carry out gerado pelo circuito de detect está correto. Assim, temos que fazer
INF 01058 – Circuitos Digitais – Circuitos Aritméticos Somadores
7 | P á g i n a
“manualmente” uma geração do carry out através de Full Adders, por exemplo. E isso é o que
de fato será feito: usaremos Ripple Carry Adders de 4 bits para gerar as saídas e também os
carries out. O detect será usado apenas quando o carry out é detectado por ele: neste caso,
ótimo, teremos o carry correto rapidamente e a soma pode prosseguir; caso contrário, temos
que esperar a geração do carry correto pelo circuito de Ripple como o da Figura 3.2. O carry
definitivo da soma parcial pode, então, ser obtido através de um simples OR entre os dois
carries gerados por processos diferentes.
A título de ilustração, fiz uma simulação de todos os casos possíveis de somas de dois
números de 4 bits. Como temos 16 parcelas possíveis para cada número, temos um total de
256 somas possíveis. Como temos duas possibilidades de carry in, temos então um total de
512 entradas possíveis em um circuito detect. Destas 512 entradas, pode-se mostrar que 287
entradas apresentarão carry out da soma com valor 1, ou seja, aproximadamente 56%. Porém,
um circuito detect já não detecta entradas com Cin igual a 0, logo já perdemos quase metade
dos casos. Conforme explicado anteriormente, o detect não encontra todos os casos de Cout
igual a 1. Na verdade, um detect realmente detecta apenas 81 saídas de Cout igual a 1 para
somas de 4 bits, ou seja, apenas pouco mais de 28% dos casos de Cout igual a 1.
O esquemático de um somador Carry Skip Adder está na figura 5.2, e sua
implementação na Figura 5.3.
Fig. 5.2 – Esquemático do Somador Carry Skip Adder.
Fig. 5.3 – Implementação de um Carry Skip Adder.
INF 01058 – Circuitos Digitais – Circuitos Aritméticos Somadores
8 | P á g i n a
6. Parallel Prefix Adder
O Parallel Prefix Adder (PPA) busca incrementar a implementação do Carry Skip
Adder em relação a “prever” os carries gerados por um par de bits anteriores que foi
propagado por uma cadeia de bits. Se houver uma maneira de saber qual é exatamente o carry
in de cada soma por dígito, então bastaria somar cada dígito da saída num simples full adder,
paralelamente, com um excelente ganho de tempo (claro, se a identificação dos carries in
corretos seja rápida). O PPA trabalha com os conceitos de Generate e Propagate, que serão
definidos como se segue:
Definição 6.1. (Carry Generate). Dizemos que um sinal de carry generate Gi (ou
simplesmente generate), é de valor lógico 1 se e somente se os i-ésimos bits das parcelas da
soma ai e bi possuem valor lógico 1 (em outras palavras, eles geram um carry out igual a 1
independentemente dos dígitos anteriores). Podemos simplesmente escrever Gi = ai . bi.
Definição 6.2. (Carry Propagate). Dizemos que um sinal de carry propagate Pi (ou
simplesmente propagate), é de valor lógico 1 se e somente se ao menos um bit das parcelas da
soma ai e bi possuem valor lógico 1 (em outras palavras, se um carry in igual a 1 é somado com
ai e bi, então esse carry in será propagado para o carry out desta soma). Podemos
simplesmente escrever Pi = ai + bi.
Note que, pela definição, Gi e Pi são sinais estritamente relacionados com os
correspondentes bits ai e bi das parcelas. Basta agora construir, com estes sinais Gi e Pi, alguma
maneira que faça valer a pena o seu uso para reduzir o tempo de uma soma.
Funcionamento. O PPA e o Carry Look-Ahead adotam a abordagem de analisar a
geração e a propagação de carries ao longo da soma. Ambos criam, para os n bits que cada
parcela possuem, os n sinais correspondentes de G e P. Estes sinais podem ser facilmente
obtidos por meio das fórmulas apresentadas nas Definições 6.1 e 6.2. De fato, criaremos um
símbolo gen_prop como o da Figura 6.1(a) que receberá 4 bits de cada vez das entradas e
gerará os 4 sinais de generate e propagate correspondentes, pelas definições 6.1 e 6.2. A
implementação para este bloco está na Figura 6.1(b).
(a)
(b)
Fig. 6.1 – (a) Símbolo do circuito gen_prop, e (b) a operação que ele executa. Neste artigo usaremos gen_prop que trabalha de quatro em quatro bits, pois este circuito será reaproveitado no Carry Look-Ahead.
O cérebro de um somador que utiliza os conceitos de propagate e generate está no
modo como ele interpreta estes sinais. No caso do PPA, teremos uma rede de unidades
INF 01058 – Circuitos Digitais – Circuitos Aritméticos Somadores
9 | P á g i n a
auxiliares, que serão definidas a seguir, que identificará todos os carries in em relação ao bit
inicial necessários para efetuar a soma. Depois, bastará somar cada par de bits ai e bi com seu
respectivo carry in, realizando todas estas somas paralelamente.
O “cérebro” do PPA é uma unidade que recebe todos os sinais de generate e
propagate obtidos por gen_prop. Como saída, ele retorna todos os n carries out exatos. No
nosso caso, um PPA de 16 bits, teremos 16 carries como saída desta unidade. Note que temos
17 carries out ao total, 16 que serão usados na soma e mais o carry out do bloco inteiro. Além
disso, o primeiro carry é o Cin do bloco inteiro, que pode vir de um somador anterior, por
exemplo.
Na implementação deste PPA, usaremos uma unidade chamada de pg_ball. Esta
unidade deverá receber como entradas um par de sinais P e G referentes a dois índices da
soma, ou seja, teremos 4 entradas: Gi, Pi, Gj e Pj. A idéia é que essa unidade detecte qual será o
sinal de generate e de propagate relacionado ao intervalo [i,j]. Para a nossa aplicação,
queremos saber todos os carries out gerados desde o início de nossa soma, ou seja, queremos
saber o Cout do bit 1 em relação ao bit 0, o Cout do bit 2 em relação ao bit 0, e assim por diante,
até o carry out do bit 15 em relação ao bit 0, que é o Cout da soma total.
Iremos considerar a notação da Figura 6.2 para montar nosso “cérebro”, e também
iremos fazer algumas definições. Vamos definir agora um G1,0 como um generate do
agrupamento correspondido pelos dois bits menos significativos das parcelas. Define-se que
G1,0 = G1 + P1 .G0. Isto faz sentido, já que o grupo só irá gerar um carry out igual a 1 caso os bits
de índice 1 gerem o Cout ou os bits de índice 1 propaguem um Cout igual a 1 vindo dos bits de
índice 0. Define-se também o P1,0 do
agrupamento, que é a capacidade de
propagação deste. Intuitivamente, um
agrupamento propaga um carry igual a 1
caso todos os pares de bits tenham essa
capacidade. Assim, definimos P1,0 = P0.P1.
Precisamos de um Pn,0 e um
Gn,0, ou seja, o caso geral, para que possamos calcular rapidamente todos os carries out da
soma. Vamos iniciar calculando alguns casos particulares para partir para o caso geral.
Iniciaremos com C1. Podemos dizer que teremos C1 igual a 1 caso tenhamos um Cout
gerado por a0 e b0 ou então caso exista um C0 = 1 que foi propagado por a0 e b0. Disto podemos
escrever:
C1 = a0.b0 + (a0 + b0).C0 (3)
Porém, G0 = a0.b0, e P0 = a0 + b0, então, substituindo em (3) temos:
C1 = G0 + P0.C0 (4)
A fórmula (4) seria um modo de escrever o generate e o propagate do bit 1 em
relação ao zero. Agora, vamos escrever uma fórmula para o G e o P do bit 2 em relação ao bit
0:
C2 = a1.b1 + (a1 + b1).C1 + (a0 + b0).(a1 + b1).C0 (5)
Fig. 6.2 – Notação para montagem do PPA. Note que são gerados dezesseis carries out. O décimo sétimo é o Cin.
INF 01058 – Circuitos Digitais – Circuitos Aritméticos Somadores
10 | P á g i n a
Porém, pelas definições 6.1 e 6.2, G1 = a1.b1, P1 = a1+b1, P0 = a0+b0. Assim,
substituindo em (5):
C2 = G1 + P1. C1 + PO. P1. C0. (6)
Substituindo (4) em (6), e com alguma manipulação algébrica:
C2 = G1 + P1.G0 + P1.P0.C0 (7)
Ainda, pelas definições de G1,0 e P1,0, podemos alterar (7):
C2 = G1,0 + P1,0.C0 (8)
A fórmula (8) vale apenas para o C2, porém por demonstrações similares ela pode ser
mostrada para qualquer Ci. Ela diz que podemos escrever o carry out de um par de bits
analisando o generate e o propagate de um grupo de bits anteriores, e também o Cin do grupo
todo, que é o C0. Podemos generalizar um Cn com a seguinte fórmula,
Cn = Gn-1,0 + Pn-1,0.C0 (9)
para qualquer � � � (Considerando G0,0 = G0 e P0,0 = P0).
Falta deduzir quem são os Gn,0 e os Pn,0 para � � �. Como já dito anteriormente,
consideramos Gn,0 e Pn,0 a capacidade de geração e propagação, respectivamente, do
agrupamento de bits da soma desde o bit de índice 0 até o bit de índice n. Podemos dizer, por
uma definição similar a que fizemos para G1,0 e P1,0 que, para dois pares de bits consecutivos
de índices i (o menor) e j (o maior) que Gj,i e Pj,i são tais que (note que (10) e (11) satisfazem os
casos da primeira definição):
Gj,i = Gj + Pj.Gi (10) Pj,i = Pj.Pi (11)
As fórmulas (10) e (11) valem apenas para bits consecutivos (É fácil mostrar que se
utilizarmos elas para bits não consecutivos podemos ter casos não abrangidos). Precisamos
estendê-la para o caso em que i = 0 e j é um n qualquer, não necessariamente 1. Iremos
demonstrar, como exemplo, o caso n = 3. A demonstração para um n qualquer requer indução
e é muito extensa. Para n = 3, temos:
G3,0 = G3 + P3.G2 + P3.P2.G1 + P3.P2.P1.G0 (12) P3,0 = P3.P2. P1.P0 (13)
As formulas (12) e (13) são intuitivas. Um grupo propaga apenas um carry gerado
dentro dele, na condição que todos os bits a seguir propaguem este carry. Para (13), um grupo
propaga apenas se todos os bits propagam.
Por (10) e (11), tomando j = 3 e i = 2, e substituindo em (12) e (13), temos:
G3,0 = G3,2 + P3.P2.G1 + P3.P2.P1.G0 (14) P3,0 = P3,2. P1.P0 (15)
Colocando em evidência P3.P2 em (15), obtém-se:
INF 01058 – Circuitos Digitais – Circuitos Aritméticos Somadores
11 | P á g i n a
G3,0 = G3,2 + P3.P2.(G1 + P1.G0) (16)
Por (10) e (11), tomando j = 1 e i = 0, e substituindo em (16) e (15), e tomando o fato
que P3,2 = P3.P2 vindo de (11) temos:
G3,0 = G3,2 + P3,2.G1,0 (17) P3,0 = P3,2.P1,0 (18)
Apesar de termos demonstrado apenas para um caso, este resultado é válido
sempre: é possível expressar um Gn,0 e um Pn,0 para qualquer � � � da seguinte forma:
Gn,0 = Gn,n-1 + Pn,n-1.Gn-2,0 ou Gn,0 = Gn + Pn.Gn-1,0 (19) Pn,0 = Pn,n-1.Pn-2,0 ou Pn,0 = Pn.Pn-1,0 (20)
Por exemplo, podemos escrever G8,0 como:
G8,0 = G8 + P8.(G7,6 + P7,6.(G5,4 + P5,4.(G3,2 + P3,2.G1,0))) (21)
As fórmulas (10) e (11) são
tão importantes que formam um
operador no PPA. Cada “bolinha” da
Figura 6.4(b) é um circuito que realiza
as fórmulas (10) e (11). Este circuito
está mostrado na Figura 6.6(a), e seu
símbolo na Figura 6.6(b). Note que várias destas “bolinhas” são usadas na implementação do
esquema da Figura 6.4(a), mostrada na Figura 6.5: as duas representações são equivalentes
(ambas possuem as mesmas 22 “bolinhas”).
É interessante ponderar que possuímos diversas maneiras de escrever uma fórmula
como (17) e (21) para determinar Gn,0 e Pn,0 para qualquer � � �. Por exemplo, (21) poderia ser
reescrita como:
G8,0 = G8 + P8.((G7,6 + P7,6.G5,4) + P7,6.P5,4.(G3,2 + P3,2.G1,0)) (22)
Isso mostra que há várias maneiras de escrever fórmulas para Gn,0 e Pn,0 para
qualquer � � �� A fórmula (22), por exemplo, determina G8,0 na chamada árvore de Brent-
Kung, que implementa o circuito da Figura 6.4(b).
Um projeto de um PPA precisa analisar estas diversas maneiras de construir as
árvores geradoras, já que algumas possuem bom desempenho de tempo, outras ocupam
menos espaço, e também há aquelas que são muito ruins em ambos.
Para este artigo, tomei uma análise de baixo desempenho, apesar de ser boa em
termos de espaço e ser bem ilustrativa quanto à concatenação dos propagates e dos
generates. Esta árvore pode ser visualizada na Figura 6.4(a), seu símbolo na Figura 6.4(b). Esta
árvore retorna todos os Gn,0 e Pn,0 em 7 estágios de tempo, o que é considerado de baixo
desempenho (há árvores que executam estes cálculos em até 4 unidades de tempo).
Observe que o modo para obtermos G8,0 em (21), mostrado na Figura 6.3, é utilizado
pela árvore da Figura 6.4(a) para obter qualquer Gn,0. Esta árvore é basicamente recursiva, e
utiliza como regra de sua montagem a própria dedução de Gn,0 e Pn,0
Fig. 6.3 – Escrevendo G8,0 com o auxílio de (19) .
INF 01058 – Circuitos Digitais – Circuitos Aritméticos Somadores
12 | P á g i n a
(a)
(b)
Fig. 6.4 – (a) Árvore geradora dos generates e propagates em relação ao bit 0, e (b) seu símbolo.
Fig. 6.5 – “Cérebro” do somador Parallel Prefix Adder. Cada célula pg_ball é uma das células pretas que aparecem no esquema deste circuito na Figura 6.4(a), e estão implementadas na Figura 6.6(a).
(a)
(b)
Fig. 6.6 – (a) Implementação de pg_ball, e (b) seu símbolo, usado no circuito da Figura 6.5.
INF 01058 – Circuitos Digitais – Circuitos Aritméticos Somadores
13 | P á g i n a
Falta apenas mais uma parte para concluir o PPA, e é a mais simples: utilizar estes
carries gerados no passo anterior e somá-los aos bits de entrada. Para isto, podemos utilizar
vários full adders trabalhando em paralelo, já que não haverá dependência de carries entre os
bits. Assim, temos, na Figura 6.7(a), um circuito que faz essa soma de 4 em 4, e seu símbolo.
(a)
(b)
Fig. 6.7 – (a) Implementação do circuito out_generate, e (b) o seu símbolo. Os carries out gerados pelos full adders deste circuito são ignorados, já que apenas precisamos dos bits de saída que são retornados imediatamente (agora já possuímos os carries in corretos). Já o carry out da soma toda será o C16 gerado pelo bloco ppa, o nosso “cérebro” da Figura 6.5. Ele não precisa ser calculado novamente.
A implementação final do PPA está exibida na Figura 6.8.
Fig. 6.8 – Somador Parallel Prefix Adder de 16 bits.
INF 01058 – Circuitos Digitais – Circuitos Aritméticos Somadores
14 | P á g i n a
7. Carry Look-Ahead Adder
Continuando com o aperfeiçoamento dos somadores, é chegada a hora de corrigir
alguns problemas de implementação do Parallel Prefix Adder. Infelizmente, dependendo da
árvore utilizada pelo bloco da Figura 6.5 no somador anterior, o tempo de geração dos carries
corretos pode não ser muito superior aos três primeiros somadores deste artigo, e
dependendo do caso, este tempo pode até ser pior. Não queremos isso, além do mais, o
Parallel Prefix Adder utiliza uma larga quantidade de componentes eletrônicos.
O Carry Look-Ahead Adder (ou apenas CLA) continua utilizando o mesmo princípio do
somador Parallel Prefix Adder. Inclusive, os blocos das Figuras 6.1 e 6.6 são reaproveitados
aqui. O que muda é o cérebro do somador. Basicamente, evolui-se de um cérebro de um
anfíbio para um cérebro de um primata com os avanços que o CLA faz sobre seu antecessor!
Funcionamento. Para a construção do CLA, dividiremos o problema em 4
problemas menores, como foi feito no Carry Select Adder e no Carry Skip Adder. Chamaremos
de Look Ahead Unit uma unidade que, trabalhando de 4 em 4 bits: (1) recebe um carry in e
dois números de 4 bits de comprimento; (2) gera os sinais de generate e propagate relativos às
entradas (com o circuito da Figura 6.1(a)); (3) produz, com estes sinais, através de um novo
circuito (nosso novo cérebro), o conjunto de carries out, e também um Group Generate (GG) e
um Group Propagate (GP), algo similar com o que tínhamos nas árvores do Parallel Prefix
Adder, quando gerávamos sinais relativos a um intervalo de bits; (4) Por fim, a Look Ahead Unit
fará, como no circuito da Figura 6.7(a), a soma dos pares de bits com os carries in
correspondentes, para então liberar a soma destas duas parcelas de 4 bits.
Cada Look Ahead Unit dá a soma de grupos de 4 bits. O carry in da primeira soma é
fornecido (seria o carry que vem de algum circuito anterior). Porém, os carries das somas
seguintes precisam ser determinados ainda. Para isso, coloca-se mais um dos nossos
“cérebros”, que trabalha com grupos de 4 bits, para receber os 4 GGs e os 4 GPs gerados
anteriormente e retornar 4 valores de carry in. Os três primeiros entrarão para formar a soma
do segundo, terceiro e quarto Look Ahead Unit. O quarto e último é o carry out da soma
completa.
Falta definir o cérebro do CLA. Queremos algo mais rápido, e que se possível, ocupe
menos espaço eletrônico do que a unidade do Parallel Prefix Adder. Queremos que nosso
bloco Look Ahead, como será chamado, gere os 4 carries in correspondentes as variáveis de
entrada e que gere os sinais GG e GP.
Pelas definições de generate e propagate, podemos dizer sempre que:
Cn = Gn-1 + Pn-1.Cn-1 (23)
Logo, temos:
C1 = G0 + P0.C0 (24) C2 = G1 + P1.C1 (25) C3 = G2 + P2.C2 (26) C4 = G3 + P3.C3 (27)
Substituindo (24) em (25), temos uma expressão para C2 dependente apenas dos
sinais de entrada:
INF 01058 – Circuitos Digitais – Circuitos Aritméticos Somadores
15 | P á g i n a
C2 = G1 + P1.G0 + P1.P0.C0 (28)
Substituindo (28) em (26), idem ao procedimento acima:
C3 = G2 + P2.G1 + P2.P1.G0 + P2.P1.P0.C0 (29)
Finalmente, substituindo (29) em (27), temos a expressão para C4:
C4 = G3 + P3.G2 + P3.P2.G1 + P3.P2.P1.G0 + P3.P2.P1.P0.C0 (30)
Faltam apenas expressões para o GG e o GP. O Group Propagate é o mais intuitivo: se
todos os pares de bits propagam um carry igual a 1, então o grupo todo propaga. Logo:
GP = P3.P2.P1.P0 (31)
Um grupo pode gerar um sinal, por exemplo, quando seu par de bits mais
significativos gera um sinal. Porém, um grupo também gera um sinal caso o segundo par de
bits mais significativos gera um sinal e o mais significativo apenas propaga, e assim por diante.
Assim, o sinal de Group Generate é tal que:
GG = G3 + P3.G2 + P3.P2.G1 + P3.P2.P1.G0 (32)
Desse modo o cérebro do CLA, o Bloco Look Ahead, pode ser montado utilizando-se
as fórmulas (24), (28), (29), (30), (31) e (32). Este bloco está implementado na Figura 7.1. Seu
símbolo está exposto na Figura 7.2.
(a)
(b)
Fig. 7.1 – (a) Bloco Look Ahead, e (b) seu símbolo.
Agora, com o Bloco Look Ahead construído, podemos montar a Look Ahead Unit. Ela
é composta pelos blocos das Figuras 6.1, 6.7 e 7.1, e está construído na Figura 7.2(a).
INF 01058 – Circuitos Digitais – Circuitos Aritméticos Somadores
16 | P á g i n a
(a)
(b)
Fig. 7.2 – (a) Montagem da Carry Look Ahead Unit. Ela por si só é um somador de 4 bits, bastando apenas acrescentar uma saída para representar seu carry out. (b) Símbolo da unidade.
Para obter um CLA de 16 bits, basta usar quatro unidades como a da Figura 7.2
trabalhando em paralelo para gerar os pedaços da saída. Os carries in destas unidades serão
enviados por um bloco um grau acima na hierarquia do somador. Este bloco pode ser um
bloco Look Ahead como o da Figura 7.1, recebendo, como sinais de generate e propagate
aqueles gerados por cada uma das Look Ahead Units. O carry out da soma será o C4 gerado por
este último bloco.
A implementação do CLA de 16 bits está na Figura 7.3.
Fig. 7.3 – Carry Look Ahead de 16 bits.
INF 01058 – Circuitos Digitais – Circuitos Aritméticos Somadores
17 | P á g i n a
8. Conclusões
Apesar de não ter sido feita aqui uma análise minuciosa de relação espaço/tempo
para cada um dos cinco somadores aqui descritos, é possível ter uma idéia do desempenho de
cada um deles através de suas características.
O Ripple Carry Adder, descrito na Seção 3, é o que pode ser implementado no menor
espaço. Utilizando apenas full adders, é o que utiliza menos portas lógicas em sua construção.
Porém, é o que apresenta pior desempenho em relação ao tempo, já que cada bit da soma
depende do carry gerado no bit anterior.
O Carry Select Adder, descrito na Seção 4, possui uma boa relação espaço/tempo,
tendendo para o espaço. Ocupa em média o dobro de espaço utilizado por um Ripple Carry
Adder, porém, pode apresentar desempenho em relação ao tempo três vezes melhor do que o
anterior, ou mais ainda, caso venhamos a tratar com somas de 32 ou 64 bits, por exemplo.
Basta fazer uma relação boa em relação a quantas partes será dividida a soma.
O Carry Skip Adder, descrito na Seção 5, ocupa menos espaço em circuito do que o
Carry Select Adder, porém seu desempenho se aproxima mais do Ripple Carry Adder do que do
Carry Select Adder. Isto não o torna uma boa opção de aplicação, já que temos que esperar
pelo carry gerado pela soma parcial caso o circuito de detecção não detecte um carry out igual
a 1 existente.
O Parallel Prefix Adder, descrito na Seção 6, ocupa bastante espaço em se tratando
de componentes eletrônicos, e é bem “flexível”: vários estudos e propostas de mudanças
podem ser feitas em relação às árvores de geração dos carries, de modo que a relação
espaço/tempo para este somador oscila dentro de uma certa faixa. Ele possui conceitos
também que são base também para o Carry Look Ahead Adder.
O Carry Look Ahead Adder, descrito na Seção 7, possui uma boa relação
espaço/tempo, tendendo para o tempo. Como hoje em dia a maioria dos componentes
eletrônicos podem ser medidos em escala micrométrica, este é geralmente o somador
escolhido para a maioria das aplicações, por ser extremamente rápido, ignorando-se o espaço
que ele ocupa. O Carry Look Ahead Adder procura por padrões de propagação e geração de
carry nas parcelas da soma, podendo na maioria dos casos antecipar os valores de carry out bit
a bit e realizar a soma mais rapidamente.
9. Referências
Carry Look-Ahead Adder. Wikipedia. Disponível em:
< http://en.wikipedia.org/wiki/Carry_look-ahead_adder>. Acesso em 11 de maio de 2008.
Todos os circuitos aqui representados foram montados com a ajuda do software
Max+Plus II version 10.2 07/10/2002, de propriedade de Altera Corporation. A versão gratuita
está disponível no website <www.altera.com>.