Lección Teach
Lógica digital en la DE1-SoC (2/6): tablas de verdad, SOP/POS, mapas de Karnaugh y multiplexores
El alumnado conecta tablas de verdad, formas booleanas, mapas de Karnaugh y multiplexores, y prueba lógica combinacional minimizada en la DE1-SoC.
Resultados de aprendizaje
Derivar las formas suma de productos (SOP) y producto de sumas (POS) desde una tabla de verdad.
Minimizar una función booleana con un mapa de Karnaugh y leer la expresión simplificada.
Comparar una forma canónica con su forma mínima en hardware real y confirmar que coinciden.
Construir y verificar un multiplexor 4 a 1 que enruta una de cuatro entradas hacia una salida.
Vista previa de la actividad del estudiante
Contenido de la actividad
Solo vista previa. En una sesión de clase, los estudiantes pueden completar respuestas y entregar su trabajo al docente.
De una tabla de verdad a un circuito
8 min
En la Lección 1 conectaste puertas individuales a interruptores. Los diseños reales empiezan un nivel más arriba: decides qué debe hacer un circuito, normalmente mediante una tabla de verdad, y después buscas una red de puertas que produzca ese comportamiento. En esta lección trabajarás una función desde varias formas y luego la harás más pequeña.
La función de los dos primeros ejercicios es F(C,B,A), una función de tres entradas. Conectarás SW[0]=A, SW[1]=B, SW[2]=C, y mostrarás el resultado en LEDR[0]. Esta es su tabla de verdad. Las filas están en orden de conteo binario C B A, desde 000 hasta 111:
Tabla de verdad de F(C,B,A), en orden binario:
- Fila 0: C B A = 0 0 0 -> F=0
- Fila 1: C B A = 0 0 1 -> F=1
- Fila 2: C B A = 0 1 0 -> F=0
- Fila 3: C B A = 0 1 1 -> F=1
- Fila 4: C B A = 1 0 0 -> F=1
- Fila 5: C B A = 1 0 1 -> F=0
- Fila 6: C B A = 1 1 0 -> F=1
- Fila 7: C B A = 1 1 1 -> F=0
F vale 1 en cuatro de las ocho filas y 0 en las otras cuatro. Léelo en la tabla antes de responder. Esa separación organiza toda la lección: las filas donde F=1 dan la suma de productos, y las filas donde F=0 dan el producto de sumas. Mantén esta tabla a la vista: todo lo que sigue vuelve a ella.
Recuerda las convenciones de la placa que usaste en la Lección 1: un interruptor arriba es lógica 1, y LEDR es activo en alto, así que el LED se enciende cuando la salida vale 1. Estos ejercicios son puramente combinacionales: la salida depende solo de la posición actual de los interruptores, por lo que no hace falta declarar reloj.
En cuántas de las ocho filas vale 1 la función F, y cuáles son esas filas?
Suma de productos y mapa de Karnaugh
14 min
Mintérmino. Un *mintérmino* es un único término AND (producto) construido con todas las entradas. Cada entrada aparece una vez, normal o negada, y el término vale 1 en exactamente una fila de la tabla de verdad. Para tres entradas hay ocho mintérminos, uno por fila. La fila 1 es C=0, B=0, A=1, así que su mintérmino es (~C & ~B & A): este producto vale 1 solo cuando C=0, B=0 y A=1, y vale 0 en todas las demás filas.
Suma de productos canónica (SOP). Para construir F, haces OR de los mintérminos de todas las filas donde F=1. Como cada mintérmino vale 1 solo en su propia fila, el OR vale 1 exactamente en las filas de F=1 y 0 en el resto: eso es justo F. Las cuatro filas con F=1 (1, 3, 4, 6) dan:
- Fila 1 C=0,B=0,A=1 -> (~C & ~B & A)
- Fila 3 C=0,B=1,A=1 -> (~C & B & A)
- Fila 4 C=1,B=0,A=0 -> (C & ~B & ~A)
- Fila 6 C=1,B=1,A=0 -> (C & B & ~A)
Por tanto, la SOP canónica es F = (~C & ~B & A) | (~C & B & A) | (C & ~B & ~A) | (C & B & ~A). Es correcta, pero poco eficiente: cuatro términos AND de tres entradas alimentando un OR de cuatro entradas.
Minimizar con un mapa de Karnaugh. Un *mapa de Karnaugh* reorganiza la tabla de verdad para que las celdas vecinas difieran en una sola entrada. Cuando dos 1 adyacentes están juntos, la variable que *cambia* entre ellos no importa para ese par y se puede eliminar, dejando un término más pequeño. Agrupa los cuatro mintérminos donde F=1 en dos pares:
- Agrupa los mintérminos 1 y 3. La fila 1 es C=0, B=0, A=1; la fila 3 es C=0, B=1, A=1. Ambas tienen C=0 y A=1; solo cambia B (0 frente a 1). Como B cambia mientras el término sigue valiendo 1, B se elimina, y el par se reduce a (~C & A).
- Agrupa los mintérminos 4 y 6. La fila 4 es C=1, B=0, A=0; la fila 6 es C=1, B=1, A=0. Ambas tienen C=1 y A=0; de nuevo solo cambia B, así que B se elimina y el par se reduce a (C & ~A).
Haz OR de los dos términos reducidos: F = (~C & A) | (C & ~A). Esa es la definición de XOR entre A y C, así que:
> F = A ^ C
Observa lo que ocurrió: B se eliminó en *ambos* grupos, por lo que B no aparece en la expresión mínima. El mapa te está diciendo algo real sobre la función: F no depende de B. Puedes confirmarlo directamente en la tabla de verdad: busca dos filas que solo cambien en B y comprueba que F conserva el mismo valor.
Mapa de Karnaugh de F. Cada grupo de dos 1 adyacentes elimina la variable que cambia dentro del grupo. Aquí ambos grupos eliminan B, y queda (~C & A) | (C & ~A) = A ^ C. Como B desaparece de todos los grupos, F es independiente de B.
Aplica el mismo método de mintérminos a una función *distinta*. Una función G(C,B,A) vale 1 exactamente en las filas 0, 2, 5, 7 (y 0 en las filas 1, 3, 4, 6). Escribe la suma de productos canónica completa de G: el OR de un mintérmino por cada fila donde G=1. Usa ~ para NOT, & para AND y | para OR.
Aparece B en la expresión mínima F = A ^ C? Explica qué te dice su ausencia sobre la dependencia de F respecto a sus tres entradas. Después busca por tu cuenta dos filas de la tabla que difieran solo en B, y escribe sus números de fila y sus valores de F para comprobarlo.
Constrúyelo: SOP canónica y forma mínima
14 min
Ahora lleva la función a la placa real. Ejecutarás primero la SOP canónica, verificarás las ocho filas y después cambiarás a la forma mínima F = A ^ C para confirmar que produce exactamente las mismas salidas.
El módulo de abajo trae activa la forma mínima y deja la SOP canónica en una línea comentada. En la primera prueba, comenta el assign mínimo y descomenta la línea de la SOP canónica para probar la versión de cuatro términos; después haz lo contrario para la segunda prueba.
// Lección 2 - Ejercicio 1-B: Suma de Productos (SOP)
// F(C,B,A): mintérminos 1,3,4,6. SW[0]=A, SW[1]=B, SW[2]=C. Salida en LEDR[0].
// Reemplaza TODO el contenido de leds_mirror.v con este módulo.
module leds_mirror(SW, LEDR);
input [9:0] SW; // SW[0]=A, SW[1]=B, SW[2]=C
output [9:0] LEDR;
wire A = SW[0];
wire B = SW[1];
wire C = SW[2];
// SOP canónica (un término producto por cada fila F=1). Descomenta para probarla primero:
// assign LEDR[0] = (~C & ~B & A) | (~C & B & A) | (C & ~B & ~A) | (C & B & ~A);
// Forma mínima del mapa de Karnaugh: F = A XOR C
assign LEDR[0] = A ^ C;
assign LEDR[9:1] = 9'b0; // LED sin usar apagados
endmoduleAbre el laboratorio Verilog de la DE1-SoC. El editor muestra el archivo
leds_mirror.v.Selecciona todo el contenido de
leds_mirror.vy reemplázalo por el módulo SOP de arriba. Mantén el módulo con el nombreleds_mirror.En la primera prueba, activa la SOP canónica: comenta la línea
assign LEDR[0] = A ^ C;y quita el//de delante de la línea SOP canónica. Exactamente una de las dos líneasassign LEDR[0]debe quedar descomentada.Pulsa Sintetizar. Si una guía tapa el botón, ciérrala o sáltala primero. Espera a que termine (aprox. 1-3 minutos). Si informa de un error, revisa punto y coma o paréntesis, corrige y vuelve a sintetizar. Continúa solo cuando el estado final diga que terminó con 0 errores.
Pulsa Enviar a la FPGA y espera a que aparezcan la placa y la cámara en directo.
Recorre
SW[2:0](C B A) por las ocho combinaciones000, 001, 010, 011, 100, 101, 110, 111, leyendoLEDR[0]en la cámara cada vez. Registra cada resultado en la tabla. (Cambia tambiénSW[1]=Ben el conteo aunque esperes que no importe.)En la segunda prueba, edita el archivo otra vez: vuelve a comentar la SOP canónica y descomenta
assign LEDR[0] = A ^ C;. Sintetiza y carga de nuevo; después revisa algunas filas, por ejemplo001,100,111, y confirma queLEDR[0]coincide con la versión canónica.
Coloca SW[2:0] = C B A en cada fila y registra el valor de LEDR[0] que lees en la cámara (1 = encendido, 0 = apagado). La columna esperada es la función de la tabla de verdad; tu observación debe coincidir tanto para la SOP canónica como para la versión mínima A^C.
| C = SW2 | B = SW1 | A = SW0 | F = LEDR0 (observado) |
|---|---|---|---|
La SOP canónica de cuatro términos y la forma mínima F = A ^ C produjeron el mismo LEDR[0] en las filas que comprobaste? En una frase, di qué confirma eso sobre las dos expresiónes.
Sube tu evidencia. Captura una imagen de la cámara con la forma mínima F = A ^ C ejecutándose en una fila donde F = 1 (por ejemplo C B A = 100: SW[2] arriba, SW[1] y SW[0] abajo, así que LEDR[0] está encendido) y adjúntala abajo.
> Bonus opcional (no requiere entrega). Quartus informa cuántos elementos lógicos usa un diseño. Si tu sesión muestra ese informe, sintetiza la SOP canónica de cuatro términos y el A ^ C de una sola operación y compara el número de elementos lógicos: la forma mínima debería usar menos. Trátalo como exploración; el informe de recursos no siempre se muestra igual en todas las sesiones, así que no forma parte de la evidencia obligatoria.
La misma función como producto de sumas
14 min
La SOP construyó F desde sus filas con 1. El producto de sumas (POS) construye la misma F desde sus filas con 0.
Maxtérmino. Un *maxtérmino* es un único término OR (suma) que usa todas las entradas, normales o negadas, y vale 0 en exactamente una fila. Es la imagen simétrica del mintérmino. Para la fila 0 (C=0, B=0, A=0), el maxtérmino es (A | B | C): este OR vale 0 solo cuando A, B y C son todos 0, y vale 1 en cualquier otra fila.
Producto de sumas canónico. Haz AND de los maxtérminos de cada fila donde F=0. Cada maxtérmino fuerza la salida a 0 en su propia fila y la deja a 1 en las demás; por tanto, el AND de todos ellos vale 0 exactamente en las filas de F=0, otra vez la misma función F. Las cuatro filas donde F=0 son 0, 2, 5, 7:
- Fila 0 C=0,B=0,A=0 -> (A | B | C)
- Fila 2 C=0,B=1,A=0 -> (A | ~B | C)
- Fila 5 C=1,B=0,A=1 -> (~A | B | ~C)
- Fila 7 C=1,B=1,A=1 -> (~A | ~B | ~C)
En cada maxtérmino, una variable aparece *negada* cuando vale 1 en esa fila F=0, para que el término se haga 0 allí. El módulo de abajo implementa esta POS canónica directamente. Describe exactamente la misma función, así que sus ocho salidas deben coincidir con lo que ya registraste: las filas 0..7 dan 0, 1, 0, 1, 1, 0, 1, 0.
// Lección 2 - Ejercicio 1-C: Producto de Sumas (POS)
// Misma F(C,B,A). Maxtérminos (filas F=0): 0, 2, 5, 7. SW[0]=A, SW[1]=B, SW[2]=C. Salida LEDR[0].
// Salidas esperadas para filas 0..7 (C,B,A = 000..111): 0,1,0,1,1,0,1,0 (igual que la SOP).
module leds_mirror(SW, LEDR);
input [9:0] SW; // SW[0]=A, SW[1]=B, SW[2]=C
output [9:0] LEDR;
wire A = SW[0];
wire B = SW[1];
wire C = SW[2];
// POS canónica: un término suma por cada fila F=0.
// Fila 0 (C=0,B=0,A=0): (A | B | C)
// Fila 2 (C=0,B=1,A=0): (A | ~B | C)
// Fila 5 (C=1,B=0,A=1): (~A | B | ~C)
// Fila 7 (C=1,B=1,A=1): (~A | ~B | ~C)
assign LEDR[0] = (A | B | C) & (A | ~B | C) & (~A | B | ~C) & (~A | ~B | ~C);
assign LEDR[9:1] = 9'b0;
endmoduleEn el laboratorio Verilog de la DE1-SoC, selecciona todo el contenido de
leds_mirror.vy reemplázalo por el módulo POS de arriba. Mantén el nombreleds_mirror.Pulsa Sintetizar y espera a que termine. Corrige cualquier error de sintaxis y vuelve a sintetizar.
Pulsa Enviar a la FPGA y espera a la cámara en directo.
Recorre
SW[2:0](C B A) por las ocho combinaciones000 ... 111, leyendoLEDR[0]cada vez. Confirma que la secuencia de salidas es0, 1, 0, 1, 1, 0, 1, 0, igual que en la SOP.Si alguna fila no coincide con
0, 1, 0, 1, 1, 0, 1, 0, lo más probable es que haya un desliz al colocar interruptores. Revisa cuál interruptor esC, cuálBy cuálA, y vuelve a leer esa fila.
Para esta F concreta, cómo se compara la POS canónica con la SOP canónica en tamaño?
Un multiplexor 4 a 1
12 min
Un multiplexor (MUX) es un selector: enruta una de varias entradas de datos hacia una sola salida, elegida por unas líneas de selección. Un MUX 4 a 1 tiene cuatro entradas de datos y necesita dos líneas de selección, porque dos bits eligen entre 2^2 = 4 entradas. Se comporta como un conmutador giratorio: el valor de selección decide qué línea de datos queda conectada a la salida.
La asignación de pines de este ejercicio, escrita de forma explícita para evitar ambigüedad en el orden de bits, es:
- Entradas de datos: SW[3]=D3, SW[2]=D2, SW[1]=D1, SW[0]=D0
- Líneas de selección: SW[5]=S1, SW[4]=S0
- Salida: LEDR[0] = Y
El valor de selección {S1, S0} elige la línea de datos: 00 -> D0, 01 -> D1, 10 -> D2, 11 -> D3. El módulo usa una instrucción case dentro de always @(*). La rama default no está de adorno: en un bloque combinacional always, si alguna combinación de entrada dejara Y sin asignar, el sintetizador inferiría un latch para "recordar" el valor anterior. Eso convertiría tu lógica combinacional pura en memoria accidental. Asignar Y en todas las ramas, aquí mediante default, garantiza que Y siempre tenga un valor definido y que no se cree ningún latch.
// Lección 2 - Ejercicio 1-D: multiplexor 4 a 1 (estilo case)
// Entradas de datos: SW[3]=D3, SW[2]=D2, SW[1]=D1, SW[0]=D0
// Líneas de selección: SW[5]=S1, SW[4]=S0
// Salida: LEDR[0] = Y
// Para SW[3:0]=1010, Y para S1:S0 = 00,01,10,11 es 0,1,0,1.
module leds_mirror(SW, LEDR);
input [9:0] SW;
output [9:0] LEDR;
wire D0 = SW[0], D1 = SW[1], D2 = SW[2], D3 = SW[3];
wire S0 = SW[4], S1 = SW[5];
reg Y;
always @(*) begin
case ({S1, S0})
2'b00: Y = D0;
2'b01: Y = D1;
2'b10: Y = D2;
2'b11: Y = D3;
default: Y = 1'b0; // default evita inferir un latch
endcase
end
assign LEDR[0] = Y;
assign LEDR[9:1] = 9'b0;
endmoduleEn el laboratorio Verilog de la DE1-SoC, selecciona todo el contenido de
leds_mirror.vy reemplázalo por el módulo del multiplexor. Mantén el nombreleds_mirror.Pulsa Sintetizar y espera a que termine. Corrige cualquier error y vuelve a sintetizar.
Pulsa Enviar a la FPGA y espera a la cámara.
Coloca los cuatro interruptores de datos en el patrón
SW[3:0] = 1010:D3=1(SW[3]arriba),D2=0(SW[2]abajo),D1=1(SW[1]arriba),D0=0(SW[0]abajo).Ahora recorre las líneas de selección
S1:S0 = 00, 01, 10, 11usandoSW[5](S1) ySW[4](S0). Para cada valor, leeLEDR[0](Y) y anótalo en la tabla. Con datos1010, la salida debe seguir la línea seleccionada:0, 1, 0, 1.Como comprobación rápida, elige un valor de selección, cambia el interruptor de datos correspondiente y confirma que
Ysigue solo a esa línea mientras las otras no afectan.
Mantén los datos en SW[3:0] = 1010 (D3 D2 D1 D0 = 1 0 1 0). Para cada valor de selección, coloca SW[5]=S1 y SW[4]=S0, anota qué entrada se selecciona y registra el LEDR[0] observado (Y). Con este patrón, Y esperada es 0, 1, 0, 1.
| S1 = SW5 | S0 = SW4 | Entrada seleccionada (D0..D3) | Y = LEDR0 (observado) |
|---|---|---|---|
Sube tu evidencia. Captura una imagen de la cámara del multiplexor con datos SW[3:0] = 1010 y selección S1:S0 = 01 (SW[4] arriba, SW[5] abajo). Eso selecciona D1 = 1, así que LEDR[0] debe estar encendido. Adjunta la captura abajo.
Imagina que borras la línea default: Y = 1'b0;, de modo que alguna combinación dejara Y sin asignar. Qué pieza de hardware no deseada inferiría el sintetizador, y por qué eso contradice el multiplexor puramente combinacional que querías construir?
Bonus: decodificador decimal de dos dígitos en 7 segmentos
4 min
Este ejercicio es opcional. Si tienes tiempo, es un salto interesante desde un solo LED hasta una salida formateada en los displays de siete segmentos.
Un display de siete segmentos tiene siete barras, etiquetadas a a g, que se encienden en combinaciones para dibujar un dígito. En la DE1-SoC cada display HEX es activo en bajo y el orden de bits es {g, f, e, d, c, b, a}: un segmento se enciende cuando su bit vale 0. Por tanto, el patrón del dígito 0 (segmentos a,b,c,d,e,f encendidos y g apagado) es 7'b1000000: seis 0 para los segmentos encendidos y un 1 para el g apagado.
Nombres de los segmentos y orden de bits activo en bajo {g,f,e,d,c,b,a} en los displays HEX de la DE1-SoC. Un bit 0 enciende su segmento; un 1 lo apaga. El dígito 0 enciende todos los segmentos salvo g, con codificación 7'b1000000.
El diseño siguiente lee SW[3:0] como un valor 0..15, muestra la cifra de unidades en HEX0 y la cifra de decenas (0 o 1) en HEX1. Observa algo que el proyecto inicial no te da automáticamente: para controlar HEX1 debes añadir output [6:0] HEX1 a la lista de puertos del módulo. El leds_mirror inicial solo expone HEX0. El módulo de abajo ya declara HEX0 y HEX1, así que es el ejemplo concreto de ese puerto adicional.
// Lección 2 - Ejercicio 1-E (opcional): decodificador decimal de dos dígitos
// SW[3:0] selecciona un valor 0..15. HEX0 muestra unidades, HEX1 muestra decenas.
// 7 segmentos activo en bajo, orden {g,f,e,d,c,b,a}: un segmento se enciende con 0.
module leds_mirror(SW, HEX0, HEX1);
input [9:0] SW; // SW[3:0] = valor 0..15
output [6:0] HEX0; // unidades
output [6:0] HEX1; // decenas (0 o 1)
wire [4:0] v = {1'b0, SW[3:0]}; // 0..15
function [6:0] seg; // dígito decimal 0..9 -> segmentos activos en bajo
input [3:0] d;
case (d)
4'd0: seg = 7'b1000000; 4'd1: seg = 7'b1111001;
4'd2: seg = 7'b0100100; 4'd3: seg = 7'b0110000;
4'd4: seg = 7'b0011001; 4'd5: seg = 7'b0010010;
4'd6: seg = 7'b0000010; 4'd7: seg = 7'b1111000;
4'd8: seg = 7'b0000000; 4'd9: seg = 7'b0010000;
default: seg = 7'b1111111;
endcase
endfunction
wire [3:0] tens = (v >= 5'd10) ? 4'd1 : 4'd0;
wire [3:0] ones = (v >= 5'd10) ? (v[3:0] - 4'd10) : v[3:0];
assign HEX0 = seg(ones);
assign HEX1 = seg(tens);
endmoduleOpcional. En el laboratorio Verilog de la DE1-SoC, reemplaza todo el contenido de
leds_mirror.vpor el módulo decodificador. Mantén el nombreleds_mirror. Confirma que la lista de puertos dicemodule leds_mirror(SW, HEX0, HEX1);: eloutput [6:0] HEX1añadido permite controlar el display de decenas.Pulsa Sintetizar, corrige cualquier error y vuelve a sintetizar.
Pulsa Enviar a la FPGA y espera a la cámara.
Coloca
SW[3:0]en algunos valores y lee ambos displays:0000debe mostrar0enHEX0y0enHEX1;1001(decimal 9) muestra9y0;1111(decimal 15) muestra5enHEX0y1enHEX1.
Qué cambio en la lista de puertos del módulo fue necesario para que este diseño pudiera encender HEX1, y por qué era necesario?
Qué construiste
4 min
En un párrafo breve, resume lo que hiciste con F(C,B,A): cómo la SOP canónica y la POS salieron de la tabla de verdad, cómo el mapa de Karnaugh redujo F a A ^ C, y qué te dijo la desaparición de B. Menciona que confirmaste en la placa que las formas canónica y mínima daban salidas idénticas.
Para el multiplexor con datos SW[3:0] = 1010, qué secuencia de valores de Y observaste cuando S1:S0 fue 00, 01, 10, 11, y por qué esa secuencia es exactamente los bits de 1010 leídos en ese orden?