Pular para o conteúdo

Hardware e sistemas operacionais · parte 5 de 27

Álgebra booleana e portas lógicas: como a verdade vira circuito

Como postulados booleanos, tabelas-verdade e portas AND, OR, NOT e XOR constroem circuitos lógicos fundamentais para a computação digital.

iniciantePublicada em · 28 min de leitura

Tamanho da fonte:
Largura da coluna:
Tom:
Espaço entre linhas:
Fonte:

Álgebra booleana e portas lógicas: como a verdade vira circuito

Imagine uma escada rolante com dois botões, um em cada extremidade. Ela só anda quando os dois botões estão apertados, porque um segurança exige que ambos sejam pressionados antes de liberar o motor. Essa regra, “só anda se A e B”, é uma lógica, e o motor não sabe nada sobre escadas: ele só recebe um sim ou um não. Quase todo o hardware de um computador é uma coleção enorme dessas regras, e a pergunta desta aula é como elas viram fios e transistores.

A resposta passa por um matemático do século XIX que nunca viu um computador. George Boole tratou a lógica como álgebra, com símbolos que valem verdadeiro ou falso. Um engenheiro americano, Claude Shannon, percebeu em 1937 que as mesmas regras descreviam relés de telefonia. Daí em diante, todo circuito combinacional, aquele cuja saída depende só das entradas naquele instante, é uma função lógica implementada em silício. Circuitos com memória acrescentam estado, e ficam para a fase 2. Esta aula desce desse ponto até o transistor e sobe até o somador e o ladder de um controlador industrial. Pré-requisito: binário, em Bits e binário, e o conceito de complemento de dois em Inteiros, complemento de dois e overflow ajudam, mas não são indispensáveis.

Mapa da aula

A aula começa com as portas como caixas de regra, passa pelas tabelas-verdade e pelas leis que permitem simplificar, mostra por que o NAND basta, desce ao transistor CMOS e termina nos circuitos de prévia da fase 2 e na lógica do software, com flags, máscaras de bits e consultas SQL.

1. Verdadeiro e falso são 1 e 0

Um circuito digital só distingue dois estados elétricos: tensão alta e tensão baixa. Chamamos o alto de 1 e o baixo de 0. Essa escolha é uma convenção, e não uma propriedade da física. Quando dizemos que uma entrada “vale 1”, estamos dizendo que o fio está no nível alto, e a álgebra de Boole trabalha justamente com esses dois valores.

A ideia de Boole, publicada em 1854 no livro An Investigation of the Laws of Thought, foi tratar “e”, “ou” e “não” como operações sobre valores que valem verdadeiro ou falso. Ele não estava pensando em transistores. Há uma nuance histórica que vale guardar: na formulação original de Boole, a soma x + y só correspondia à união quando x e y eram disjuntos, e a forma moderna da álgebra booleana foi consolidada por autores posteriores (fonte: verbete e biografia de George Boole, consultados em 1 de novembro de 2026, ver Fontes).

Shannon fez a conexão em sua tese de mestrado no MIT, concluída em 1937 e publicada em 1938 com o título “A Symbolic Analysis of Relay and Switching Circuits”. A tese mostrou que um relé ligado ou desligado podia ser descrito por uma expressão booleana, e que simplificar a expressão significava simplificar o circuito (fonte: verbete sobre Shannon e espelhos do verbete original, consultados em 1 de novembro de 2026).

2. Para que serve: uma regra por fio

Antes da álgebra, cada máquina de cálculo era um desenho fixo de engrenagens ou de fiação, e mudar a regra exigia reconstruir a máquina. Com a álgebra, a regra passa a ser uma expressão, e a expressão pode ser transformada em circuito, testada e simplificada. Um projetista pode escrever “o alarme toca se a porta está aberta e a chave não está girada”, verificar todas as combinações de entrada antes de soldar qualquer peça, e só então implementar.

A simplificação tem valor prático. Uma expressão menor vira menos portas, menos área no chip, menos energia e, muitas vezes, menos atraso. Os mesmos princípios que cortam uma expressão de cinco termos para três servem para cortar um circuito de milhões de transistores.

3. Exemplos em contextos diferentes

O primeiro contexto é o da chave elétrica. Duas chaves em série só deixam a corrente passar quando as duas estão fechadas. Esse é o comportamento de uma porta E. A figura abaixo mostra o circuito com uma bateria, duas chaves e uma lâmpada.

Circuito de bateria, duas chaves em série e lâmpada: a lâmpada só acende quando as duas chaves estão fechadas, o comportamento de uma porta E
figura 1 · Chaves em série: a lâmpada só acende se as duas estiverem fechadas

Siga o fio da bateria. A corrente sai do polo positivo, atravessa a chave A e a chave B, passa pela lâmpada e volta ao negativo. Se qualquer chave estiver aberta, o caminho se rompe, e a lâmpada apaga. O caminho em série é uma conjunção, um “e” de duas condições. Num circuito em paralelo, as chaves ficam em ramos separados, e basta um ramo fechado para a corrente passar: esse é o “ou”.

O segundo contexto é o da porta lógica como peça de catálogo. Em vez de desenhar chaves, o engenheiro usa o símbolo, que resume a tabela-verdade. A figura mostra as portas E e OU com a entrada A em 1 e B em 0, e a tabela-verdade de cada uma ligada ao circuito.

Duas portas lógicas com entradas A em 1 e B em 0: a porta E sai 0 e a porta OU sai 1, com a tabela-verdade de cada uma ao lado
figura 2 · Portas E e OU com a tabela-verdade ligada à entrada

O terceiro contexto é o da lógica de controle industrial, em que a regra é escrita como uma escada de contatos. Um motor de esteira, por exemplo, liga com um botão e continua ligado depois que o botão é solto, desde que o sinal se mantenha por si mesmo. Esse arranjo se chama selo, e a seção de exemplos resolvidos mostra como ele funciona.

O quarto contexto é o software. Uma permissão de usuário é um bit, e a verificação de permissão é uma operação E sobre bits. A mesma álgebra que move um relé decide se um arquivo pode ser lido. Esse contexto aparece na última seção.

4. Como funciona por dentro: as portas e suas tabelas

Uma porta lógica é um circuito com uma ou mais entradas e uma saída, cuja saída é uma função fixa das entradas. A tabela-verdade lista todas as combinações possíveis e o resultado de cada uma. Com duas entradas há quatro linhas, com três entradas há oito, e em geral com n entradas há 2 elevado a n linhas. Os programas desta aula geram as tabelas por código, para que nenhuma linha seja copiada de memória.

def NOT(a): return 1 - a
def AND(a, b): return a & b
def OR(a, b): return a | b
def XOR(a, b): return a ^ b
def NAND(a, b): return NOT(AND(a, b))
def NOR(a, b): return NOT(OR(a, b))
def XNOR(a, b): return NOT(XOR(a, b))

print(" a b | AND OR XOR NAND NOR XNOR")
for a, b in itertools.product([0, 1], repeat=2):
    print(f" {a} {b} |  {AND(a,b)}  {OR(a,b)}   {XOR(a,b)}    {NAND(a,b)}    {NOR(a,b)}    {XNOR(a,b)}")

Saída real, com Python 3.12.8:

 a b | AND OR XOR NAND NOR XNOR
 0 0 |  0  0   0    1    1    1
 0 1 |  0  1   1    1    0    0
 1 0 |  0  1   1    1    0    0
 1 1 |  1  1   0    0    0    1

Leia a coluna do XOR. Ela vale 1 quando as entradas são diferentes, e é justamente o bit da soma de dois bits sem levar o vai-um. A coluna do XNOR é o inverso: vale 1 quando são iguais, e é a porta que compara dois bits, como faz o comparador de igualdade de um processador.

Um ponto que costuma confundir: NAND é o E seguido de NÃO, e NOR é o OU seguido de NÃO. As duas não são uma forma diferente de E e de OU: são as mesmas operações com a saída invertida. O que as separa é outra propriedade, a universalidade, que a seção 6 mostra. Na prática, em CMOS, a NAND custa menos que um E: quatro transistores contra seis, porque o E precisa de uma NAND e de um inversor.

5. Leis e simplificação

As regras da álgebra booleana permitem reescrever uma expressão sem mudar o que ela faz. Antes das leis, a notação: a’ é NÃO a, ab é a E b, e a + b é a OU b. Três leis resolvem a maior parte dos casos de rotina. A lei de De Morgan diz que a negação de um E é o OU das negações, e que a negação de um OU é o E das negações. A lei da absorção diz que a + ab = a, porque se a é 1 o resultado já é 1, independentemente de b. A lei distributiva diz que a(b + c) = ab + ac, o mesmo raciocínio da álgebra comum.

O programa a seguir verifica essas leis por força bruta, testando todas as combinações possíveis.

import itertools
from functools import reduce

def NOT(a): return 1 - a
def AND(a, b): return a & b
def OR(a, b): return a | b

def AND_n(*xs): return reduce(AND, xs)
def OR_n(*xs): return reduce(OR, xs)

for n in (2, 3):
    casos = list(itertools.product([0, 1], repeat=n))
    nand = all(NOT(AND_n(*x)) == OR_n(*[NOT(v) for v in x]) for x in casos)
    nor = all(NOT(OR_n(*x)) == AND_n(*[NOT(v) for v in x]) for x in casos)
    print(f"n={n}: NAND = OR de negados? {nand}   NOR = AND de negados? {nor}   (combinacoes: {len(casos)})")

absorcao = all(OR(a, AND(a, b)) == a == AND(a, OR(a, b))
               for a, b in itertools.product([0, 1], repeat=2))
distrib = all(AND(a, OR(b, c)) == OR(AND(a, b), AND(a, c))
              for a, b, c in itertools.product([0, 1], repeat=3))
print(f"a + ab = a e a(a+b) = a : {absorcao}")
print(f"a(b+c) = ab + ac          : {distrib}")

Saída real:

n=2: NAND = OR de negados? True   NOR = AND de negados? True   (combinacoes: 4)
n=3: NAND = OR de negados? True   NOR = AND de negados? True   (combinacoes: 8)
a + ab = a e a(a+b) = a : True
a(b+c) = ab + ac          : True

A força bruta é a verificação mais honesta que existe para uma expressão de poucas variáveis, porque não depende de lembrar a lei certa. Com n variáveis ela testa 2 elevado a n casos: 16 casos para n = 4, e cerca de 4,3 bilhões para n = 32. Para um computador, os casos pequenos são instantâneos. O limite está no crescimento, e não no computador: por isso a força bruta serve para conferir uma expressão, e não para simplificá-la. Para simplificar à mão, o mapa de Karnaugh é prático com até quatro a seis variáveis. Acima disso, as ferramentas de síntese usam outros algoritmos, como Quine-McCluskey e Espresso. A razão de simplificar nunca foi a quantidade de casos a testar, e sim o custo do circuito, em portas, área e energia, como a seção 2 mostra.

O mapa de Karnaugh é o método visual de simplificação. Ele dispõe as combinações em uma grade em que apenas uma variável muda entre vizinhos, e os uns que formam retângulos de tamanho 1, 2, 4, 8 ou 16 viram um único termo. O mapa foi publicado por Maurice Karnaugh em 1953, a partir do trabalho de Edward Veitch, de 1952 (fontes: registros bibliográficos do artigo de Karnaugh, consultados em 1 de novembro de 2026). A figura mostra a grade de uma função de quatro variáveis, com os valores da saída, e cada célula com 1 leva o nome do termo que a cobre.

Mapa de Karnaugh de quatro variáveis em que cada célula com 1 leva o nome do termo que a cobre: a'bd, b'c' e cd' cobrem os dez uns
figura 3 · Mapa de Karnaugh de quatro variáveis: três termos cobrem os dez uns

Cada célula é um mintermo: um E que vale 1 numa única combinação das variáveis. O número dela, de 0 a 15, é essa combinação lida em binário. A célula m5, por exemplo, é a combinação 0101, com a=0, b=1, c=0 e d=1. A grade tem a e b nas linhas e c e d nas colunas, com a ordem 00, 01, 11, 10 que faz vizinhos diferirem em um bit só. A cor de cada célula indica o termo que a cobre. O termo a’bd cobre m5 e m7, as duas células da linha ab=01 nas colunas cd=01 e cd=11. O termo cd’ cobre a coluna cd=10 inteira. O termo b’c’ cobre m0, m1, m8 e m9, e aqui está o detalhe que costuma passar despercebido: a linha ab=00 e a linha ab=10 são vizinhas, porque a borda de cima e a de baixo do mapa se encontram. O retângulo do b’c’ dá a volta por essa borda, e por isso ocupa as duas pontas da grade. O programa encontrou seis implicantes primos, que são os maiores retângulos de uns, e uma cobertura mínima com três deles. O resultado, verificado nas 16 combinações, é a’bd + b’c’ + cd’.

Esse é o circuito com menos termos que implementa a mesma função. Os três termos têm sete literais no total (a’ e b e d; b’ e c’; c e d’), e nenhuma cobertura com menos termos existe. Isso não diz qual é o circuito com menos portas: um circuito com XOR, ou que compartilha inversores, pode ter outra contagem, e a aula não os testou. Um leitor atento percebe que a expressão original, com dez mintermos, teria dez termos, e a simplificação corta para três.

6. Detalhes e bordas: o NAND basta

Uma propriedade torna o NAND, e também o NOR, peças especiais. Só com NAND, é possível construir NOT, E, OU e XOR. Isso significa que um fabricante pode produzir um único tipo de porta em larga escala e montar qualquer função a partir dela. O mesmo vale para o NOR.

a forma de soma de produtos

Por que NÃO, E e OU bastam para qualquer função? A resposta é uma receita. Pegue as linhas da tabela-verdade cuja saída vale 1. Cada uma dessas linhas é um mintermo: um E que vale 1 numa única combinação, com cada variável aparecendo sem negação se vale 1 naquela linha e negada se vale 0. Depois, um OU junta todos os mintermos. O resultado é a chamada soma de produtos, e ela sempre funciona, porque cada E vale 1 só na sua linha, e então o OU vale 1 exatamente nas linhas em que a função vale 1.

Um exemplo com três variáveis. Suponha uma função f(a, b, c) que vale 1 nas linhas 011 e 110 da tabela, ou seja, quando a=0, b=1, c=1 e quando a=1, b=1, c=0. A primeira linha vira o E a’bc, e a segunda vira o E abc’. Logo, f = a’bc + abc’. Confira: na combinação 011, o primeiro termo vale 1 e o segundo vale 0, então f vale 1. Nas outras seis combinações, os dois termos valem 0, e f também vale 0.

Qualquer tabela-verdade vira uma soma de produtos, e cada parte dessa soma usa só NÃO, E e OU. O somador da seção 7 é o mesmo tipo de objeto: uma tabela de oito linhas que virou circuito com XOR, E e OU. Falta saber se é preciso mesmo as três operações. Os programas a seguir mostram que o NAND sozinho dá conta delas.

como o NAND constrói cada porta

Os programas a seguir constroem cada porta usando só a porta universal, e conferem o resultado contra a tabela-verdade original.

def nand_not(a): return NAND(a, a)
def nand_and(a, b): return NAND(NAND(a, b), NAND(a, b))
def nand_or(a, b): return NAND(NAND(a, a), NAND(b, b))
def nand_xor(a, b):
    n = NAND(a, b)
    return NAND(NAND(a, n), NAND(b, n))

Saída real:

NAND constroi NOT: True
NAND constroi AND: True
NAND constroi OR: True
NAND constroi XOR: True
NOR constroi NOT: True
NOR constroi OR: True
NOR constroi AND: True

A figura abaixo mostra a construção do NOT, do E e do OU a partir de NAND, com as entradas ligadas entre si onde a porta precisa de uma entrada só.

Portas NAND montando NÃO, E e OU: um NAND com as duas entradas ligadas faz o NÃO, dois NAND em sequência fazem o E, e três NAND fazem o OU
figura 4 · Só portas NAND constroem NÃO, E e OU, com A = 1 e B = 0

Repare no custo. O NOT usa uma porta, o E usa duas, e o OU usa três. Um projeto real raramente faz isso porque cada tipo de porta tem tamanho e velocidade próprios, mas a propriedade é o que permite que a fábrica padronize a célula básica.

Agora o transistor. Num circuito digital moderno, a porta é feita com o padrão CMOS, que usa dois tipos de transistor complementares. O transistor PMOS conduz quando a entrada é 0, e o NMOS conduz quando a entrada é 1. A porta é montada com uma rede de pull-up, feita de PMOS, que liga a saída à alimentação, e uma rede de pull-down, feita de NMOS, que liga a saída ao terra. Se a rede de cima conduz, a saída vai para 1, e se a de baixo conduz, a saída vai para 0. Numa porta bem projetada, em regime estático, exatamente uma das duas redes conduz em cada combinação de entrada. Por isso a saída nunca fica ligada à alimentação e ao terra ao mesmo tempo, nem flutua sem nenhum caminho. Esse é o quadro das chaves ideais, e ele deixa de fora dois efeitos. Quando a entrada muda, as duas redes levam um instante para trocar de estado, e nesse intervalo passa uma corrente breve entre alimentação e terra, a corrente de curto-circuito, que gasta energia a cada transição. Mesmo em repouso, existe uma pequena corrente de fuga pelos transistores. O modelo lógico do programa não enxerga nenhuma das duas.

O programa de verificação modela as duas redes e conta, para cada combinação de entrada, quantas conduzem.

# NAND: PMOS em paralelo (liga se a entrada e 0), NMOS em serie (liga se as duas sao 1)
pullup = lambda x: (x[0]==0) or (x[1]==0)
pulldown = lambda x: (x[0]==1) and (x[1]==1)

Saída real para a porta NAND, e o mesmo modelo para a NOR, com os PMOS em série:

-- porta NAND
   entradas (0, 0): 1 (pull-up liga a saida na alimentacao)
   entradas (0, 1): 1 (pull-up liga a saida na alimentacao)
   entradas (1, 0): 1 (pull-up liga a saida na alimentacao)
   entradas (1, 1): 0 (pull-down liga a saida ao GND)
-- porta NOR
   entradas (0, 0): 1 (pull-up liga a saida na alimentacao)
   entradas (0, 1): 0 (pull-down liga a saida ao GND)
   entradas (1, 0): 0 (pull-down liga a saida ao GND)
   entradas (1, 1): 0 (pull-down liga a saida ao GND)

Em nenhuma linha aparece CURTO nem FLUTUANDO, o que é a propriedade que o modelo queria verificar. A figura seguinte mostra a porta NAND com as entradas em 1 e 1, a configuração em que só a rede de baixo conduz.

Porta NAND em CMOS com as duas entradas em 1: os dois PMOS abertos, os dois NMOS fechados, e a saída ligada ao terra, valendo 0
figura 5 · CMOS de uma porta NAND com A = 1 e B = 1: só a rede de baixo conduz e a saída va

Esta figura é um modelo de chaves, e não uma simulação elétrica. Os PMOS aparecem como chaves que abrem quando a entrada é 1, e os NMOS como chaves que fecham. Cada chave ilustra conduzir ou não conduzir. No transistor real, quem decide isso é a tensão no terminal de porta (gate), e não uma alavanca. As caixas de A e de B mostram o valor de cada entrada, e as etiquetas “porta ligada a A” e “porta ligada a B” dizem qual entrada comanda cada transistor.

Há uma consequência prática. Um transistor não é uma porta ideal: ele leva tempo para carregar e descarregar a capacitância da saída, e por isso cada porta tem um atraso de propagação. A figura abaixo mostra o atraso de um NOT como uma curva em que a saída segue a entrada depois de um intervalo. A entrada sobe em t = 2 e a saída cai em t = 4, e a faixa sombreada marca essas 2 unidades. Os valores do eixo são ilustrativos e não foram medidos.

Curvas de entrada e saída de um NOT: a saída muda alguns instantes depois da entrada, e o intervalo entre as duas mudanças é o atraso de propagação
figura 6 · Atraso de propagação de um NOT (ilustrativo, não medido)

O atraso explica por que o clock tem um período mínimo. Se o caminho mais longo de portas leva mais tempo do que o período do clock, o sinal não se estabiliza a tempo, e o resultado é um valor errado. Essa relação será central na fase 2, em Clock e sincronização, que ainda não foi escrita. Por enquanto, guarde a ideia: portas levam tempo, e o tempo se acumula em cadeia.

7. Portas combinadas: o somador e as peças de prévia

Uma função de vários bits se monta em camadas de portas. O somador completo recebe dois bits e um vai-um de entrada, e produz a soma e um vai-um de saída. A figura mostra a montagem com dois meios somadores e um OU.

Somador completo de um bit montado com portas XOR, E e OU, somando 1 mais 1 mais 0 para dar soma 0 e vai-um 1
figura 7 · Somador completo com A = 1, B = 1 e vai-um de entrada 0: soma 0 e vai-um 1

Siga o circuito com os valores da figura: A e B valem 1, e o vai-um de entrada vale 0. A primeira XOR dá 0, a primeira E dá 1. A segunda XOR, com o parcial 0 e o vai-um 0, dá soma 0. A segunda E dá 0, e o OU junta o 1 da primeira E com esse 0, e o vai-um de saída vale 1. Soma 0 e vai-um 1 é o resultado de 1 + 1 + 0 = 10 em binário.

O programa confere essa montagem contra a soma aritmética nas oito combinações.

def meio_somador(a, b): return XOR(a, b), AND(a, b)
def somador_completo(a, b, cin):
    s1, c1 = meio_somador(a, b)
    s2, c2 = meio_somador(s1, cin)
    return s2, OR(c1, c2)
for a,b,c in itertools.product([0,1],repeat=3):
    s, co = somador_completo(a,b,c)
    assert s + 2*co == a + b + c

Saída real: “somador completo confere com a + b + cin para as 8 combinacoes: True”. O somador de 64 bits, como a nota Como a CPU executa instruções mostra, é esse bloco encadeado 64 vezes, com o vai-um de cada um alimentando o seguinte.

A aula também pede três peças de prévia. O multiplexador 2:1 escolhe uma de duas entradas conforme um seletor, o decodificador 2:4 acende uma de quatro saídas conforme dois bits, e o comparador de dois bits diz se um número é maior que outro. Eles reaparecem na fase 2, e o programa confere os três. Nesta aula, só o multiplexador tem figura: o decodificador e o comparador aparecem apenas no código.

def maior2(a1,a0,b1,b0):
    # A > B: a1 > b1, ou a1 == b1 e a0 > b0
    return OR(AND(a1, NOT(b1)), AND(XNOR(a1,b1), AND(a0, NOT(b0))))
ok = all(maior2(a1,a0,b1,b0) == int((2*a1+a0) > (2*b1+b0))
         for a1,a0,b1,b0 in itertools.product([0,1],repeat=4))

Saída real: “confere com > para os 16 casos: True”, “mux2 com s=0 pega a: 1 | com s=1 pega b: 1”, e “decodificador 2:4 para entrada 10: [0, 0, 1, 0]”. A figura seguinte mostra o multiplexador montado com portas.

Multiplexador 2:1 montado com NÃO, dois E e um OU: o seletor S escolhe entre a entrada 0 e a entrada 1 que chegam ao OU
figura 8 · Multiplexador 2:1 com S = 0: a saída segue a entrada 0

O multiplexador tem a forma de uma chave seletora, e é a peça que alimenta a ULA e os registradores de uma CPU, como a nota de execução mostra. Quando o seletor é 0, o primeiro E deixa passar a entrada 0, e o segundo E fica bloqueado. Quando é 1, acontece o oposto. O OU junta as duas saídas, e só uma delas pode estar ativa de cada vez. A figura tem S = 0, entrada 0 = 1 e entrada 1 = 0, e a conta sai assim: o NÃO inverte S e dá 1, a primeira E recebe 1 e 1 e dá 1, a segunda E recebe S = 0 e dá 0 sem depender da entrada 1, e o OU junta 1 com 0 e dá a saída Y = 1, igual à entrada 0.

8. Lógica de controle: o ladder

O ladder é uma forma de escrever lógica que lembra um diagrama de relés, usada por controladores industriais. Cada degrau tem contatos em série, que representam E, e em paralelo, que representam OU. Um contato normalmente fechado representa NÃO. O degrau termina numa bobina, que é a saída. A figura mostra um degrau de liga e desliga com selo, no instante em que o botão liga é apertado.

Ladder com o botão liga apertado: a bobina K1 energiza pelo ramo do liga, e o contato K1 ainda marca 0 nesse instante
figura 9 · Ladder com selo no instante em que o botão liga é apertado: a bobina energiza

Leia o degrau da esquerda para a direita, da barra L1 até a barra L2. O botão de parar é um contato normalmente fechado, e por isso deixa a corrente passar enquanto não é apertado. O botão de liga e o contato K1 formam um ramo em paralelo, e basta que um dos dois esteja fechado para a corrente chegar à bobina. O ramo de baixo é só uma alternativa ao contato de cima.

A primeira figura mostra o instante em que o botão liga acabou de ser apertado: liga vale 1, e o contato K1 ainda marca 0. A bobina energiza pelo ramo do liga. Quando ela energiza, o contato K1 se fecha, e o sinal se mantém depois que o botão de liga é solto. Esse laço de realimentação é o selo. A segunda figura mostra o instante depois de soltar o botão: liga vale 0, e o contato K1 já vale 1, sustentando a bobina sozinho. É essa segunda figura que prova o selo, porque a bobina continua energizada sem nenhum botão apertado.

Ladder depois de soltar o botão liga: o contato K1 fecha e sustenta a bobina sozinho, que é a prova do selo
figura 10 · Ladder com selo depois de soltar o botão liga: K1 sustenta a bobina

Por que o contato marca 0 na primeira figura, se a vista de portas mostra K1 = 1 no laço de realimentação? A vista de portas mostra o valor que a bobina acabou de produzir. O contato, num controlador, lê o valor guardado na varredura anterior, e por isso ainda marca 0 no instante do aperto. Com a bobina energizada, a varredura seguinte já encontra K1 em 1.

A equação do degrau é a mesma que a álgebra descreve: K1 = (liga OU K1) E NÃO parar. O ladder é uma escrita diferente para a mesma expressão, e a figura mostra as duas vistas.

9. Lógica no software

A álgebra booleana aparece no software em três lugares. O primeiro é a máscara de bits. Um byte com oito bits pode guardar oito flags. A figura mostra um byte de permissões em que o quarto bit é admin e o último é ler.

Byte de permissões com quatro bits reservados e quatro flags: admin e ler acesos, executar e escrever apagados, lidos com operação E sobre a máscara
figura 11 · Byte de permissões: a máscara 0001 lê só o bit de ler, pelo E

A verificação de permissão é um E com uma máscara. Se a permissão de leitura é 0001, o teste é perm & 0b0001, que dá diferente de zero só quando o bit de leitura está aceso. O programa de teste usa as mesmas operações e confere o resultado.

LER, ESCREVER, EXECUTAR, ADMIN = 1, 2, 4, 8
perm = LER | ESCREVER
print("pode ler?    ", bool(perm & LER))
print("pode admin? ", bool(perm & ADMIN))
perm |= ADMIN
perm &= ~ESCREVER
print(f"depois de +ADMIN -ESCREVER: {perm:04b}")

Saída real:

pode ler?     True
pode admin?  False
depois de +ADMIN -ESCREVER: 1001

O segundo lugar é a consulta SQL, que usa AND e OR sobre condições. Aqui aparece uma regra que confunde muita gente: o banco usa lógica de três valores, porque existe NULL, que significa desconhecido. O programa roda as consultas no SQLite do próprio Python.

cur.execute("CREATE TABLE usuario(nome TEXT, flags INTEGER)")
cur.executemany("INSERT INTO usuario VALUES (?,?)", [("ana", 3), ("bia", 4), ("caio", None)])
print(cur.execute("SELECT NULL AND 0").fetchone()[0])
print(cur.execute("SELECT nome FROM usuario WHERE (flags & 4) = 4").fetchall())

Saída real:

NULL AND 0 = 0
NULL OR 1  = 1
NULL AND 1 = None
WHERE (flags & 4) = 4 : [('bia',)]
WHERE flags & 4 = 0   : [('ana',)]

Repare que “caio”, cujo flag é NULL, não aparece em nenhuma das duas consultas. NULL AND 0 dá 0, porque sabemos que a conjunção é falsa mesmo sem saber o primeiro valor, mas NULL AND 1 dá NULL, porque o resultado depende de algo desconhecido. A cláusula WHERE só aceita linhas em que a condição é verdadeira, e NULL não é verdadeiro, então caio some das duas.

O terceiro lugar é a comparação de regras compostas, como “pode editar se é admin, ou se é dono e não está bloqueado”. Essa frase vira uma expressão booleana, e a expressão pode ser simplificada e testada, como qualquer outra.

10. Erros comuns e boas práticas

O primeiro erro é confundir E e OU ao ler uma frase em português. “Se não é admin ou não é dono” nega a conjunção, e a leitura natural muitas vezes não corresponde à expressão correta. A lei de De Morgan resolve esse caso: a negação de “admin ou dono” é “não admin e não dono”. Escreva a condição com parênteses e verifique cada combinação antes de confiar no resultado.

O segundo erro é achar que o circuito é instantâneo. A expressão está correta, mas o sinal leva tempo para atravessar as portas, e uma leitura feita cedo demais pega um valor intermediário. Esse é o motivo de o clock existir, e a fase 2 volta a esse tema.

O terceiro erro é ignorar o NULL no banco. Uma condição com NOT sobre uma coluna que aceita NULL pode excluir linhas que o leitor esperava incluir. Se a coluna pode ser nula, teste IS NULL explicitamente.

O quarto erro, que todo mundo comete uma vez, é esquecer que o XOR é diferente do OU. Eles concordam em três das quatro combinações, e a diferença aparece exatamente no caso em que as duas entradas são 1. Num somador, o XOR é a soma, e o OU é o vai-um, por isso a diferença importa.

A boa prática é escrever a tabela-verdade antes de implementar, mesmo que ela tenha só quatro linhas. O programa desta aula faz isso por código, o que evita o erro de transcrição.

11. Exercícios

  1. Escreva a tabela-verdade de A XOR B XOR C para as oito combinações. Compare a coluna do resultado com a paridade de bits de A, B e C.
  2. Prove, com uma tabela-verdade de quatro linhas, que a + ab = a. Explique com as suas palavras por que o termo ab não acrescenta nada.
  3. Construa um OU usando só NOR, a partir da figura de NAND como modelo. Quantas portas NOR são necessárias?
  4. Um sistema libera acesso se o usuário for admin, ou se for dono do arquivo e o arquivo não estiver bloqueado. Escreva a expressão, aplique De Morgan para a negação e verifique no código.

Respostas dos exercícios

  1. A saída de A XOR B XOR C vale 1 quando o número de uns nas entradas é ímpar. Para 000 o resultado é 0, para 001, 010 e 100 é 1, para 011, 101 e 110 é 0, e para 111 é 1. Isso é a paridade de bits, usada em detecção simples de erro.
  2. Se a é 0, o termo ab é 0 e a + ab também é 0, igual a a. Se a é 1, a + ab é 1, também igual a a. O termo ab não acrescenta nada porque, quando ele vale 1, a já valia 1, e a soma não muda.
  3. Um NOT é um NOR com as entradas ligadas. Um OU é o NOT de um NOR, e o NOT é outro NOR com as entradas ligadas, então o OU usa duas portas NOR: a primeira calcula NOR(a, b), e a segunda, com as duas entradas ligadas à saída da primeira, inverte o resultado.
  4. A expressão é admin OU (dono E NÃO bloqueado). A negação, pela lei de De Morgan, é NÃO admin E (NÃO dono OU bloqueado). O programa aplica a expressão a todas as combinações e compara com a negação escrita, e as duas precisam bater.

Glossário

Tabela-verdade: lista de todas as combinações de entrada de uma função lógica, com a saída de cada uma.

Porta lógica: circuito com uma ou mais entradas e uma saída, cuja saída é uma função fixa das entradas.

NAND e NOR: portas que são a negação do E e do OU. Cada uma basta sozinha para construir qualquer função lógica.

Mapa de Karnaugh: grade que organiza uma tabela-verdade para simplificar a expressão, agrupando uns vizinhos.

Implicante primo: maior retângulo de uns de um mapa de Karnaugh que não cabe dentro de outro.

Mintermo: um E de literais que vale 1 em exatamente uma combinação das variáveis.

CMOS: tecnologia que usa transistores PMOS e NMOS complementares, com uma rede de pull-up e outra de pull-down.

Atraso de propagação: tempo que uma porta leva para refletir uma mudança na entrada.

Selo: realimentação em que a saída de uma bobina mantém a própria entrada ativa, um tipo simples de memória.

Máscara de bits: número usado com E ou OU para ler ou alterar bits específicos de outro número.

Fontes

Consultadas em 1 de novembro de 2026.

  • Verbete e biografia de George Boole, para a data de 1854, o livro An Investigation of the Laws of Thought e a nuance sobre a soma disjunta. Fonte primária: a obra de Boole, não consultada nesta sessão.
  • Verbete sobre Claude Shannon e espelhos do verbete sobre a tese “A Symbolic Analysis of Relay and Switching Circuits”, para a data de 1937 e a publicação de 1938. As fontes divergem sobre o ano do prêmio associado, e a aula não usa essa data.
  • Registro bibliográfico do artigo de Maurice Karnaugh, “The Map Method for Synthesis of Combinational Logic Circuits”, AIEE Transactions, 1953, e menção ao método de Veitch de 1952. O número da edição varia entre os registros, e a aula cita só o ano.
  • Documentação de Python 3, para unicodedata, bit a bit e o módulo sqlite3, e SQLite para a semântica de NULL na cláusula WHERE. Os resultados foram conferidos pelos programas.

O que não foi confirmado ou medido

Os programas desta aula foram executados, e as saídas são as reais. As portas e as redes CMOS são modelos lógicos de chaves, e não simulações elétricas, então corrente, tensão e consumo não foram medidos. A corrente de curto na transição, a corrente de fuga e a contagem de quatro contra seis transistores vêm de conhecimento geral de CMOS, sem consulta a um livro-texto. A referência sugerida para conferir é Weste e Harris, CMOS VLSI Design. O comportamento de varredura do controlador, em que o contato lê o valor da varredura anterior, também é descrito de forma geral, sem consulta ao manual de um fabricante. O atraso de propagação da figura de atraso é ilustrativo, e nenhum valor de tempo de porta de processo real foi usado. A minimização de Karnaugh foi feita por força bruta sobre implicantes, e a aula não compara com um minimizador comercial. A data exata do artigo de Karnaugh e o número da edição não foram confirmados na fonte primária.

Relacionados

  • Trilha de Hardware
  • CPU
  • Bits e binário
  • Inteiros, complemento de dois e overflow
  • Texto, ASCII, Unicode e UTF-8
  • Ponto flutuante
  • Como a CPU executa instruções

↑ Voltar ao topo

Atalhos de teclado

Abrir busca
/
Alternar tema claro/escuro
t
Aula anterior na série
←
Próxima aula na série
→
Lista de atalhos
?