36. Circuitos combinacionales

Un circuito combinacional produce sus salidas únicamente a partir de las entradas presentes. Las puertas lógicas y las funciones booleanas permiten diseñar sumadores, comparadores, multiplexores, decodificadores y bloques básicos de un procesador.

36.1 Introducción

Un circuito digital procesa señales binarias. En un circuito combinacional, cada salida depende exclusivamente de la combinación actual de entradas: no importa qué valores tuvieron antes.

Esta propiedad permite describirlo con funciones booleanas y tablas de verdad. El circuito es la realización física, o una simulación, de una regla lógica ya definida.

36.2 Entradas, salidas y función

Si un circuito tiene n entradas y m salidas, puede verse como una función que recibe n bits y devuelve m bits. Cada salida es una función booleana de las entradas.

Circuito con entradas A, B y salida Y:
Y = A ∧ B.

Para A = 1 y B = 1, Y = 1.
Para cualquier otra combinación, Y = 0.

Una salida puede reutilizarse como entrada de otra puerta dentro del mismo circuito. Mientras no exista memoria ni retroalimentación que conserve estado, el conjunto sigue siendo combinacional.

36.3 Puertas lógicas básicas

Las puertas lógicas implementan operaciones booleanas elementales sobre señales binarias.

PuertaExpresiónSalida verdadera cuando...
NOT¬AA es falsa
ANDA ∧ Bambas entradas son verdaderas
ORA ∨ Bal menos una entrada es verdadera
NAND¬(A ∧ B)no son ambas verdaderas
NOR¬(A ∨ B)ambas entradas son falsas
XORA ⊕ Bexactamente una entrada es verdadera
XNOR¬(A ⊕ B)las entradas son iguales

Una puerta se representa habitualmente con un símbolo gráfico, pero su tabla de verdad y su expresión booleana describen su comportamiento sin depender del dibujo.

36.4 Puertas universales

NAND y NOR son puertas universales: usando solamente una de ellas se puede construir cualquier función booleana. Esto reduce la variedad de componentes necesaria para implementar un diseño.

Con NAND:
¬A = A NAND A.
A ∧ B = ¬(A NAND B).
A ∨ B = (¬A) NAND (¬B).

Las leyes de De Morgan justifican la última igualdad.

En hardware real, la elección de puertas también depende de velocidad, consumo, tecnología de fabricación y restricciones del diseño, no solo de completitud funcional.

36.5 De una tabla de verdad a un circuito

Para implementar una función podemos seguir un proceso sistemático: listar entradas, construir la tabla de verdad, obtener una expresión booleana, simplificarla y conectar puertas que realicen la expresión.

1. Definir entradas y salidas.
2. Especificar cada fila de la tabla de verdad.
3. Construir minterminos de las filas con salida 1.
4. Simplificar con álgebra booleana o un mapa de Karnaugh.
5. Implementar la expresión con puertas.

La simplificación puede disminuir la cantidad de puertas, el retraso de propagación y el consumo de energía. También hace el circuito más fácil de verificar.

36.6 Ejemplo: detector de dos bits iguales

Queremos una salida Y que valga 1 cuando A y B sean iguales. La tabla muestra que Y es verdadera en 00 y 11.

Y = (¬A ∧ ¬B) ∨ (A ∧ B).

Esta función se llama XNOR:
Y = ¬(A ⊕ B).

El circuito puede construirse con dos NOT, dos AND y un OR, o con una única puerta XNOR si está disponible en la tecnología utilizada.

36.7 Simular puertas en JavaScript

const AND = (a, b) => a && b;
const OR = (a, b) => a || b;
const NOT = a => !a;
const XOR = (a, b) => a !== b;
const XNOR = (a, b) => !XOR(a, b);

function bitsIguales(a, b) {
  return XNOR(a, b);
}

console.log(bitsIguales(true, true));   // true
console.log(bitsIguales(true, false));  // false

La simulación trabaja con valores booleanos. Un circuito físico trabaja con niveles eléctricos que representan esos valores y requiere considerar aspectos que el modelo lógico abstracto no muestra.

36.8 Semisumador

Un semisumador suma dos bits A y B. Tiene dos salidas: S, el bit de suma, y C, el acarreo. No recibe un acarreo previo.

ABSuma decimalSC
00000
01110
10110
11201

Las expresiones son S = A ⊕ B y C = A ∧ B. XOR detecta que hay exactamente un bit activo; AND detecta la única combinación que produce acarreo.

36.9 Implementar un semisumador

function semisumador(a, b) {
  return {
    suma: XOR(a, b),
    acarreo: AND(a, b)
  };
}

console.log(semisumador(true, true));
// { suma: false, acarreo: true }

La suma binaria 1 + 1 produce 10: el bit de suma es 0 y el acarreo hacia la posición siguiente es 1.

36.10 Sumador completo

Un sumador completo recibe A, B y un acarreo de entrada Cin. Produce el bit de suma S y un acarreo de salida Cout.

S = A ⊕ B ⊕ Cin.
Cout = (A ∧ B) ∨ (Cin ∧ (A ⊕ B)).

También: Cout = (A ∧ B) ∨ (A ∧ Cin) ∨ (B ∧ Cin).

El acarreo sale activo cuando al menos dos de las tres entradas son activas. Por eso Cout es una función mayoría.

36.11 Tabla de verdad del sumador completo

ABCinSCout
00000
00110
01010
01101
10010
10101
11001
11111

La tabla equivale a sumar tres bits y expresar el resultado con dos bits: Cout es el bit más significativo y S el menos significativo.

36.12 Implementar un sumador completo

function sumadorCompleto(a, b, acarreoEntrada) {
  const sumaParcial = XOR(a, b);
  return {
    suma: XOR(sumaParcial, acarreoEntrada),
    acarreoSalida: OR(AND(a, b), AND(acarreoEntrada, sumaParcial))
  };
}

console.log(sumadorCompleto(true, true, true));
// { suma: true, acarreoSalida: true }

La implementación usa dos semisumadores conceptuales y una OR para combinar los acarreos. Esta composición es una técnica general de diseño de circuitos.

36.13 Sumadores de varios bits

Para sumar números de varios bits se encadenan sumadores completos. El acarreo de salida de una posición se conecta al acarreo de entrada de la siguiente posición más significativa.

Bit 0: suma A0, B0 y Cin.
Su Cout alimenta el bit 1.
El proceso continúa hasta el bit más significativo.

Esta arquitectura se llama sumador con propagación de acarreo.

Es simple, pero el último resultado debe esperar a que se propaguen los acarreos anteriores. Otros diseños calculan o anticipan acarreos para ganar velocidad a cambio de más complejidad.

36.14 Multiplexor

Un multiplexor selecciona una de varias entradas de datos y la envía a una única salida según señales de control. Un multiplexor 2 a 1 tiene entradas D0, D1 y selector S.

Y = (¬S ∧ D0) ∨ (S ∧ D1).

Si S = 0, Y = D0.
Si S = 1, Y = D1.

El multiplexor actúa como un interruptor controlado por lógica. Es un bloque esencial para seleccionar datos, rutas de ejecución y fuentes dentro de un procesador.

36.15 Simular un multiplexor 2 a 1

function multiplexor2(selector, dato0, dato1) {
  return OR(AND(NOT(selector), dato0), AND(selector, dato1));
}

console.log(multiplexor2(false, true, false)); // true: elige dato0
console.log(multiplexor2(true, true, false));  // false: elige dato1

Un multiplexor de 2k entradas requiere k señales de selección. Cada combinación de selectores elige una entrada distinta.

36.16 Decodificador

Un decodificador realiza la operación inversa conceptual de un multiplexor: toma k bits de entrada y activa una de 2k salidas. En un decodificador 2 a 4, exactamente una salida está activa para cada entrada.

Entradas A, B:
D0 = ¬A ∧ ¬B.
D1 = ¬A ∧ B.
D2 = A ∧ ¬B.
D3 = A ∧ B.

Los decodificadores se usan para seleccionar posiciones de memoria, activar dispositivos y convertir códigos binarios en señales individuales.

36.17 Comparador de un bit

Un comparador determina la relación entre dos entradas. Para un bit A y un bit B, podemos producir señales A = B, A > B y A < B.

Igual: A XNOR B.
Mayor: A ∧ ¬B.
Menor: ¬A ∧ B.

Solo una de las tres salidas es verdadera para cada par de entradas.

Los comparadores de varios bits combinan las comparaciones desde los bits más significativos. Son necesarios para ordenamiento, saltos condicionales y verificación de límites.

36.18 Circuitos combinacionales y software

Una función pura de programación se parece a un circuito combinacional: con las mismas entradas devuelve la misma salida y no depende de estado interno mutable ni de efectos externos.

function compararBit(a, b) {
  return {
    igual: XNOR(a, b),
    mayor: AND(a, NOT(b)),
    menor: AND(NOT(a), b)
  };
}

console.log(compararBit(true, false));
// { igual: false, mayor: true, menor: false }

La analogía no elimina diferencias entre software y hardware, pero ayuda a diseñar componentes deterministas, fáciles de probar mediante casos de entrada y salida.

36.19 Retardos y peligros lógicos

En el modelo booleano, las puertas responden instantáneamente. En hardware real, cada puerta tarda un tiempo pequeño en propagar un cambio. Caminos de distinta longitud pueden provocar transiciones momentáneas no deseadas llamadas peligros o glitches.

Modelo lógico: salida = función exacta de las entradas.
Modelo físico: la salida cambia después de retardos finitos.

Un diseño de circuitos debe considerar ambos modelos.

La simplificación algebraica es útil, pero una implementación física puede requerir términos adicionales o sincronización para evitar glitches. Este es un detalle de diseño electrónico, no una contradicción de la función booleana.

36.20 Aplicaciones

  • Unidades aritmético-lógicas de procesadores y microcontroladores.
  • Selección de datos en buses, memoria y periféricos.
  • Codificadores y decodificadores de señales.
  • Control de acceso y lógica de alarmas.
  • Validaciones y transformaciones binarias implementadas en software.

Los circuitos combinacionales son bloques de construcción. Al conectarlos con elementos que guardan estado se obtienen los circuitos secuenciales que veremos en el próximo tema.

36.21 Errores frecuentes

  • Confundir XOR con OR al diseñar el bit de suma.
  • Olvidar el acarreo de entrada al usar un semisumador donde se necesita un sumador completo.
  • Suponer que un circuito combinacional almacena resultados anteriores.
  • Mezclar el orden de las entradas de un decodificador sin documentarlo.
  • Ignorar la diferencia entre el modelo lógico ideal y los retardos físicos.
  • Implementar una expresión sin verificarla contra la tabla de verdad requerida.

36.22 Qué debes recordar y conclusión

  • Un circuito combinacional depende solo de sus entradas actuales.
  • Las puertas lógicas implementan funciones booleanas.
  • NAND y NOR son universales: con una sola de ellas se puede construir cualquier función booleana.
  • Un semisumador suma dos bits; un sumador completo incorpora un acarreo de entrada.
  • Multiplexores seleccionan datos y decodificadores activan una salida según un código.
  • El diseño parte de una especificación, tabla de verdad, simplificación e implementación verificable.

Los circuitos combinacionales calculan funciones sin recordar el pasado. En el próximo tema incorporaremos memoria y tiempo mediante circuitos secuenciales, registros y elementos de almacenamiento.