Trilha 18 · Lógica e teoria da computação

Circuitos lógicos

Portas lógicas se combinam em circuitos que calculam. O somador completo (full adder) é o bloco básico de toda aritmética binária: três bits entram (A, B, carry), dois saem (soma e carry out). Bilhões desses circuitos formam a ULA do seu processador.

① Intuição

Somando 1 + 1 em hardware

Quando você soma dois números no computador, a CPU executa adição bit a bit. O bit menos significativo é somado primeiro; se produz carry (vai-um), ele alimenta a próxima posição. Esse encadeamento é um somador ripple-carry.

Um half adder soma 2 bits e produz soma + carry. Um full adder soma 3 bits (dois operandos + carry de entrada) — é o que permite encadear N full adders para somar números de N bits.

Por que XOR para a soma? 0+0=0, 0+1=1, 1+0=1, 1+1=0 (com carry). A tabela de soma é idêntica à tabela do XOR. O carry é o AND: só é 1 quando ambos são 1. Dois transistores de silício implementam uma porção da aritmética do seu processador.
② Visualização interativa

Full adder interativo

Clique em A, B e Cin para alternar os valores. Os fios verdes carregam 1; cinzas, 0. Veja como o carry se propaga pelo circuito.

A=1B=1Cin=1HA 1S1 = A ⊕ BC1 = A ∧ BXOR · ANDS1=0C1=1HA 2Sum = S1⊕CinC2 = S1∧CinXOR · ANDSum=1C2=0ORC1 | C2Cout=1
1 + 1 + 1 = 3 = 11 (binário)  ·  Sum = 1   Cout = 1
③ Explicação técnica

Half adder e Full adder

// Half Adder: soma 2 bits (sem carry de entrada)
S = A XOR B     // bit de soma
C = A AND B     // carry out

// Full Adder: soma 3 bits (A, B, carry de entrada Cin)
// Construído com 2 Half Adders + 1 OR
S1  = A   XOR B    // HA1: XOR
C1  = A   AND B    // HA1: AND
Sum = S1  XOR Cin  // HA2: XOR — bit de resultado
C2  = S1  AND Cin  // HA2: AND
Cout = C1 OR  C2   // carry final

// Encadeando Full Adders: somador ripple-carry de N bits
// FA[0].Cin = 0, FA[i].Cin = FA[i-1].Cout
// Desvantagem: carry se propaga em série → lento para N grande
// Solução: carry-lookahead adder (calcula todos os carries em paralelo)

Descrevendo hardware em Verilog

// Verilog: descrever hardware em código
// (sintetiza direto para portas lógicas em FPGA/ASIC)

module full_adder(
    input  a, b, cin,
    output sum, cout
);
    wire s1, c1, c2;

    xor (s1,  a,  b);    // HA1
    and (c1,  a,  b);
    xor (sum, s1, cin);  // HA2
    and (c2,  s1, cin);
    or  (cout, c1, c2);  // OR final
endmodule

// Ripple-carry adder de 4 bits usando o módulo acima:
module adder4(
    input  [3:0] a, b,
    output [3:0] sum,
    output       cout
);
    wire [3:0] c;
    full_adder fa0 (.a(a[0]), .b(b[0]), .cin(1'b0),  .sum(sum[0]), .cout(c[0]));
    full_adder fa1 (.a(a[1]), .b(b[1]), .cin(c[0]),   .sum(sum[1]), .cout(c[1]));
    full_adder fa2 (.a(a[2]), .b(b[2]), .cin(c[1]),   .sum(sum[2]), .cout(c[2]));
    full_adder fa3 (.a(a[3]), .b(b[3]), .cin(c[2]),   .sum(sum[3]), .cout(cout));
endmodule
Carry-lookahead: no ripple-carry, o carry do bit N precisa esperar o carry do bit N-1, que espera N-2, etc. Para um somador de 64 bits isso seria lento demais. O carry-lookahead calcula todos os carries em paralelo usando apenas dois níveis de lógica. Processadores modernos usam variantes (carry-select, prefix adder) para atingir frequências de GHz.
④ Projeto para programar

Simulador de circuitos

Mini projeto: simule o full adder em Python. Represente cada fio como uma variável booleana. Implemente as funções half_adder(a, b) e full_adder(a, b, cin) usando apenas AND, OR, XOR (ou &, |, ^). Gere e imprima a tabela-verdade completa.

Projeto principal: construa um simulador de circuitos genérico. Represente um circuito como um grafo de portas e fios. Leia a topologia de um arquivo JSON e avalie a saída para qualquer entrada. Teste com: half adder, full adder, multiplexador 2:1, e decodificador 2-para-4.

Desafio extra: implemente o algoritmo de síntese de circuitos: dada uma tabela-verdade de N entradas, gere a expressão SOP mínima (via Quine-McCluskey ou K-map) e depois converta para um circuito de portas NAND apenas (usando De Morgan). Verifique que a saída é equivalente à tabela original.

⑤ Exercícios rápidos

Teste sua intuição

Quais duas portas formam o half adder (soma de 2 bits)?
Por que precisamos do full adder (não apenas do half adder) para somar números de N bits?
Por que o somador ripple-carry fica lento para N grande?
⑥ Aplicações no mundo real

Onde você encontra isso

🖥️

ULA — Unidade Lógica e Aritmética

A ULA do processador é uma coleção de circuitos combinacionais: somadores, subtratores (complemento de 2), shifters, comparadores. Uma ULA de 64 bits moderna usa prefix adders (Kogge-Stone, Han-Carlson) para completar a adição em O(log N) níveis de lógica, atingindo frequências acima de 3 GHz.

🔢

Ponto flutuante — IEEE 754

Somar dois floats exige alinhar os expoentes, somar as mantissas (com um circuito somador), normalizar e arredondar o resultado. A FPU (Floating Point Unit) tem somadores dedicados separados da ALU inteira. O padrão IEEE 754 define exatamente quais bits entram e saem — o mesmo circuito implementado em todo processador moderno.

🧮

FPGA — somadores sintetizados

Ao sintetizar um projeto Verilog/VHDL para FPGA, a ferramenta reconhece automaticamente padrões de somador e os mapeia para blocos DSP dedicados no chip (muito mais eficientes que portas LUT individuais). Os mesmos full adders que você viu aqui aparecem no relatório de síntese como "DSP48" no Xilinx ou "DSP Blocks" no Intel Altera.

← Anterior: Álgebra booleana Próxima: Máquinas de estado →