ENUNCIADO

En el año 2718, la humanidad ha sido capaz de explorar numerosos sistemas planetarios lejanos sin haber encontrado vida inteligente1. Los científicos deciden dejar dispositivos en los planetas visitados que den pistas de la localización de la Tierra a otros viajeros interestelares. Para que el visitante tenga constancia de que el objeto que ve es producto de vida inteligente y no del azar, se decide que debe llevar un contador que cuente según el inicio de la sucesión de Fibonacci, en la que cada término resulta ser la suma de los dos anteriores:

0, 1, 1, 2, 3, 5, 8, 13, y vuelta a empezar.

Nuestro cometido es diseñar tal contador. Después de mucho recapacitar, se decide que se va a realizar el dispositivo como un contador de cuatro bits de cuenta arbitraria. Sin embargo, nos encontramos con el problema de que hay un número que se repite (el 1). Se decide solucionarlo usando para el primer 1 otro número no usado (el 9) e intentar corregir esa salida con lógica combinacional añadida al final. De este modo, la cuenta que se debe generar es:

0, 9, 1, 2, 3, 5, 8, 13, y vuelta a empezar.

Veamos los pasos que hay que dar, recordando el ejemplo visto en teoría:
  1. Debemos construir el diagrama de transición de estados, haciendo que los estados no usados decaigan a cualquiera de los otros. De una elección acertada de estos decaimientos puede depender lo simple o complicado que resulte el circuito final y, dada la gran cantidad de planetas con posibilidad de vida, unos céntimos de ahorro puede suponer un gran pellizco al final. Este es el diagrama del ejemplo que veíamos en teoría:
    Diagrama de transición de ejemplo
  2. Con ayuda de la tabla de transiciones del biestable JK,
    Tabla de transiciones de JK
    se debe escribir la tabla de transiciones. En el ejemplo de la teoría, era:

    Tabla de transiciones
  3. Toca ahora escribir las jotas y las kas de los biestables en función de las variables binarias que determinan el estado. Estas variables son, en este ejercicio, las salidas de los biestables: Q3Q2Q1Q0. Nos podemos auxiliar de mapas de Karnaugh. Como muestra, parte del ejemplo visto en teoría:
    Ejemplo de Karnaugh para J y K
  4. Una vez deducidas las ecuaciones de excitación de las jotas y las kas de cada biestable, se puede construir el circuito. En el ejemplo de teoría, este es el circuito resultante:
    Contador de cuenta arbitraria
  5. Probad con Verilog el circuito que habéis obtenido. En caso de que no realice la cuenta: 0, 9, 1, 2, 3, 5, 8, 13, 0, ..., revisad los cálculos.
  6. Diseñad el circuito combinacional que cambie el 9 por un 1, dejando el resto de valores que importan como está. Si no sois capaces de diseñarlo sobre la marcha, construid la tabla de verdad y aplicad de nuevo los mapas de Karnaugh.
  7. Probad el diseño final y, de funcionar, disfrutad de vuestra obra: un flamante señalador de vida inteligente para extraterrestres2, marca ACME®.
_____________________________
1 Esto supuso un duro revés para el proyecto encargado de la búsqueda de vida inteligente, al cual se dedicaron no pocos fondos. Para evitar la tragedia política, se votó y se aprobó, por ley, que se había demostrado que no había vida inteligente en el Universo. No se sabe bien si a propósito o no, no se hizo salvedad respecto al planeta Tierra...

2 En el año 3141 parece que el dispositivo tuvo éxito pues se recibió por radio cuántica un mensaje de respuesta. La celebración fue grandiosa, aun sin haber sido capaz de descifrar el mensaje. Por supuesto que se revocó la ley que afirmaba que no había vida inteligente en el Universo y se levantaron múltiples estatuas. El mensaje se vio que estaba compuesto por dos partes claramente diferenciadas. Lo que parecía un saluda y una segunda parte algo más extensa que podría ser un manual técnico avanzado con los descubrimientos científicos de la civilización alienígena.
   Al final, después de mucho esfuerzo, se logró descifrar el mensaje corto. Venía a decir: "Vayan ya dejando de abandonar chismes electrónicos. Nos estamos gastando un pastón limpiando los planetas por donde van pasando". La traducción de la segunda parte se abandonó al descubrir, justo al principio, las palabras: "En la oscuridad sonaba un teléfono, un sonido débil"...


COMENTARIOS

La primera solución y, de momento, la única, es la presentada por Cunart (2010). Merece la pena que la echéis un vistazo por lo bien documentada que está.

Presenta el autor, en realidad, dos soluciones, una primera, que usa:
En total, el equivalente a 47 puertas, según las condiciones del ejercicio. Reproducimos el ejercicio, citando en cursiva, las palabras de su autor.

Comenzamos dibujando el diagrama de transicción de estados buscando que haya la mínima variación de bits entre los estados que no pertenecen a la serie y los que sí. El diagrama que he elegido en este caso es el siguiente:
Diagrama de estados 1
A partir del diagrama se hace la tabla de transiciones y se escriben las J y K de los biestables en función de las salidas de los mismos Q3, Q2, Q1, Q0:
J3 K3J2 K2J1 K1J0 K0
0000→10011    x 0    x 0    x 1    x
0001→00100    x 0    x 1    x x    1
0010→00110    x 0    x x    0 1    x
0011→01010    x 1    x x    1 x    0
0100→0101 0    x x    0 0    x 1    x
0101→10001    x x    1 0    x x    1
0110→0011 0    x x    1 x    0 0    x
0111→0011 0    x x    1 x    0 x    0
1000→1101x    0 1    x 0    x 1    x
1001→0001x    1 0    x 0    x x    0
1010→0010 x    1 0    x x    0 0    x
1011→1001 x    0 0    x x    1 x    0
1100→1101 x    0 x    0 0    x 1    x
1101→0000x    1 x    1 0    x x    1
1110→1101 x    0 x    0 x    1 1    x
1111→1101 x    0 x    0 x    1 x    0

No dibujo los mapas de Karnaugh en este ejemplo, pongo tan solo los resultados:
J3= Q0Q1Q2+Q0Q1Q3 K3= Q0Q1+Q0Q2
J2= Q0Q1Q3+Q0Q1Q3 K2= Q0Q1+Q1Q3
J1= Q0Q2Q3 K1= Q0Q3+Q2Q3+Q0Q2
J0= Q0+Q1 K0= Q1Q3+Q1Q2= Q1(Q2+Q3)

Algunas se podrían reducir más, pero por estar repetidas en más de una entrada es más rentable así. Una vez que se tienen se puede dibujar el circuito resultante e implementarlo en Verilog.

Para cambiar el 9 por el 1 he utilizado un circuicirto combinacional sencillo consistente en dos puertas AND y una OR:
Combinacional para cambiar 9 por 1

[[Como efecto colateral, el 11 también cambia al 3, lo que no tiene importancia, pues el 11 no se usa en la cuenta]]
QQ3Q2Q1Q0 Q3* Q3*Q2Q1Q0 Q*
00000000000
10001000011
20010000102
30011000113
40100001004
50101001015
60110001106
70111001117
81000110008
91001000011
1010101101010
111011000113
1211001110012
1311011110113
1411101111014
1511111111115
[[Nota del profesor]]


La imagen siguiente es cómo quedaría el diseño del circuito, una maraña de cables:
Maraña de cables :)


Y este es el código presentado para esta primera solución:

/*
Computadores I - GII - USAL

Sesión 10 - Ejercicio 1.

Se nos pide diseñar un circuíto que siga la serie de Fibonacci
usando el menor número de puertas.

En esta solución se incluyen:

5  AND de tres entradas 
8 AND de dos entradas 
1 OR de tres entradas
7 OR de dos entradas 
4 biestables JK 
===========
48 puertas.

Por: cunart - Grupo A2
*/


//Modulo del biestable JK
module JKdown(output reg Q, output wire NQ, input wire J, input wire K,   input wire C);
  not(NQ,Q);

  initial
  begin
    Q=0;
  end    

  always @(posedge C)
    case ({J,K})
      2'b10: Q=1;
      2'b01: Q=0;
      2'b11: Q=~Q;
    endcase
endmodule

//Módulo que contiene el contador y la circuitería auxiliar.
module contador (output wire[3:0] Q, input wire C);
  //Cables correspondientes a las salidas negadas de los biestables.
  wire [3:0] nQ;
  //Cables que almacenan la salida temporal del biestable jk3.
  wire Qt, nQt;

  //Cables de entrada a los biestables.
  wire wJ3, wK3, wJ2, wK2, wJ1, wK1, wJ0, wK0;

  //Cables intermedios.
  wire wq0n1q2,  wn0n1n2, wq0n2, wq0n1, wn0n1q3, wq0q1n3, wq1n3, wq0q3;
  wire wn2q3, wq2n3, wq2q3, wn0q3;

  //Puertas correspondientes al contador.
  and q0n1q2 (wq0n1q2, Q[0], nQ[1], Q[2]);
  and n0n1n2 (wn0n1n2, nQ[0], nQ[1], nQ[2]);
  or  J3 (wJ3, wn0n1n2, wq0n1q2);

  and q0n2 (wq0n2, Q[0], nQ[2]); //La salida va a K3 y K1.
  and q0n1 (wq0n1, Q[0], nQ[1]); //La salida va a este y al K2.
  or K3 (wK3, wq0n1, wq0n2);

  and n0n1q3 (wn0n1q3, nQ[0], nQ[1], Qt);
  and q0q1n3 (wq0q1n3, Q[0], Q[1], nQt);
  or J2 (wJ2, wq0q1n3, wn0n1q3);

  and q1n3 (wq1n3, Q[1], nQt);
  or K2 (wK2, wq0n1, wq1n3);

  and J1 (wJ1, Q[0], nQ[2], nQt);

  and q0q3 (wq0q3, Q[0], Qt);
  and n2q3 (wn2q3, nQ[2], Qt); 
  or K1 (wK1, wq0q3, wn2q3, wq0n2);

  or J0 (wJ0, nQ[0], nQ[1]);

  or q2n3 (wq2n3, Q[2], nQt);
  and K0 (wK0, nQ[1], wq2n3);

  JKdown jk0 (Q[0], nQ[0], wJ0, wK0, C);
  JKdown jk1 (Q[1], nQ[1], wJ1, wK1, C);
  JKdown jk2 (Q[2], nQ[2], wJ2, wK2, C);
  JKdown jk3 (Qt, nQt, wJ3, wK3, C);

  //Circuitería que cambia el nueve por el uno.
  and  q2q3 (wq2q3, Q[2], Qt);
  and  n0q3 (wn0q3, nQ[0], Qt);
  or    NQ3 (Q[3], wq2q3, wn0q3);
endmodule


//Módulo para probar el circuito.
module test;
  reg I, C;
  wire [3:0] Q;
  contador counter (Q,C);

  always 
  begin
    #10 C=~C;
  end

  initial
  begin
    $dumpfile("ej1_48.dmp");
    $dumpvars(2, counter, Q);
          
    C=0;
    #500 $finish;
  end
endmodule



La segunda solución presentada no sigue estrictamente el camino esbozado por el enunciado del ejercicio, sino que actúa de manera más inteligente. Al fin y al cabo, si nos atamos desde el principio a un diagrama de transición de estados, podemos estar desaprovechando la oportunidad de elegir otro mejor. Así que, el autor decide dejar flotanto los estados finales de aquellos que no forman parte de la secuencia. Con lo único que hay que tener precaución es con que los estados no usados decaigan siempre a estados del contador, para evitar problemas en la indeterminación en el encendido. ¿Habrá considerado esto el autor? Sigamos, de nuevo, sus comentarios acerca de esta brillante solución:

Para obtener una solución con menor número de puertas, en lugar de comenzar por el diagrama, lo hice por la tabla de transiciones para los valores del ciclo y dejando como x el resto:
J3 K3J2 K2J1 K1J0 K0
0000→10011    x 0    x 0    x 1    x
0001→00100    x 0    x 1    x x    1
0010→00110    x 0    x x    0 1    x
0011→01010    x 1    x x    1 x    0
0100→xxxx x    x x    x x    x x    x
0101→10001    x x    1 0    x x    1
0110→xxxx x    x x    x x    x x    x
0111→xxxx x    x x    x x    x x    x
1000→1101x    0 1    x 0    x 1    x
1001→0001x    1 0    x 0    x x    0
1010→xxxx x    x x    x x    x x    x
1011→xxxx x    x x    x x    x x    x
1100→xxxx x    x x    x x    x x    x
1101→0000x    1 x    1 0    x x    1
1110→xxxx x    x x    x x    x x    x
1111→xxxx x    x x    x x    x x    x


Una vez tenemos esta tabla, escribimos los mapas de Karnaugh para cada entrada de los biestables:
J3
Q3Q2
↓Q1Q0
00011110
001 x x x
010 1 x x
110 x x x
100 x x x
J3= Q2 + Q0 Q1
J2
Q3Q2
↓Q1Q0
00011110
000x x 1
010xx0
111 x x x
100x x x
J2= Q0 Q3 + Q0 Q1
J1
Q3Q2
↓Q1Q0
00011110
000xxx
011 0x0
11x xxx
10xxxx
J1= Q0 Q2 Q3
J0
Q3Q2
↓Q1Q0
00011110
001 x x x
01x x x x
11x x x x
101 x x x
J0= 1
K3
Q3Q2
↓Q1Q0
00011110
00xxx0
01x x 1 1
11x x x x
10xxxx
K3= Q0
K2
Q3Q2
↓Q1Q0
00011110
00x x x x
01x 1 1 x
11x x x x
10x x x x
K2= 1
K1
Q3Q2
↓Q1Q0
00011110
00xxxx
01x x x x
111 x x x
100xxx
K1= Q0
K0
Q3Q2
↓Q1Q0
00011110
00x x x x
011 1 1 0
110 x x x
10x x x x
K0= Q2 + Q1 Q3


Con esto podemos completar ahora la tabla de transiciones y el diagrama:
J3 K3J2 K2J1 K1J0 K0
0000→10011    x 0    x 0    x 1    x
0001→00100    x 0    x 1    x x    1
0010→00110    x 0    x x    0 1    x
0011→01010    x 1    x x    1 x    0
0100→1001 1    x x    1 0    x 1    x
0101→10001    x x    1 0    x x    1
0110→1011 1    x x    1 x    0 1    x
0111→1000 1    x x    1 x    1 x    1
1000→1101x    0 1    x 0    x 1    x
1001→0001x    1 0    x 0    x x    0
1010→0011 x    1 0    x x    0 1    x
1011→0101 x    1 1    x x    1 x    0
1100→0001 x    1 x    1 0    x 1    x
1101→0000x    1 x    1 0    x x    1
1110→0001 x    1 x    1 x    1 1    x
1111→0000 x    1 x    1 x    1 x    1

[[De hecho, podríamos completar mucho más la tabla, pues como ya hemos realizado los mapas de Karnaugh, las x ya han quedado completamente determinadas. Nota del profesor]]

[[Actualización 2018: una alumna desconocida descubrió un error en la tabla anterior. Son las celdas en rojo. Muchas gracias por la aportación. Aprovechemos para dar valores a las x en función de lo obtenido en Karnaugh y, de paso, corregirlo:]]

J3 K3J2 K2J1 K1J0 K0Final
0000→????1    0 0    1 0    0 1    11001
0001→????0    1 0    1 1    1 1    10010
0010→????0    0 0    1 0    0 1    00011
0011→????0    1 1    1 1    1 1    00101
0100→???? 1    0 0    1 0    0 1    11001
0101→????1    1 0    1 0    1 1    11000
0110→???? 1    0 0    1 0    0 1    11011
0111→???? 1    1 1    1 0    1 1    11000
1000→????1    0 1    1 0    0 1    01101
1001→????0    1 0    1 0    1 1    00001
1010→???? 0    0 1    1 0    0 1    01111
1011→???? 0    1 1    1 0    1 1    00101
1100→???? 1    0 1    1 0    0 1    11001
1101→????1    1 0    1 0    1 1    10000
1110→???? 1    0 1    1 0    0 1    11011
1111→???? 1    1 1    1 0    1 1    10000
J3=Q2 + Q0 Q1
K3=Q0
J2= Q0 Q3 + Q0 Q1
K2=1
J1=Q0 Q2 Q3
K1=Q0
J0=1
K0=Q2 + Q1 Q3
El diagrama de estados resultante es el siguiente:
Diagrama de estados 2
[[Afortunadamente, como se ve en el diagrama, no se han producido ciclos entre los estados no usados, como explica el autor dos párrafos más adelante. La solución es, por tanto, válida. Nota del profesor.]]

[[Actualización 2018: el diagrama de estados estaba mal por dos motivos:
  1. Se basaba en los datos de una tabla que estaba mal
  2. Ni siquiera estaba correcto considerando los datos de esa tabla (El 0100 estaba repetido. ¿Dónde estaba el 1111?...)
Esperemos que el siguiente sea correcto:

CorrecciOn diagrama de estados
]]

Se podría hacer que del estado 0110 pasara directamente al ciclo, pero esto supondría un aumento de puertas que se utilizarían constantemente mientras que así, aunque se entre al ciclo en dos pasos, es algo que ocurrirá solo puntualmente.

Es importante también fijarse en este punto en que podría haber dos estados fuera del ciclo que formaran otro bucle externo (Ej.: 1011 → 0111 → 1010 → 0110) puesto que no se parte de un diagrama conocido. Se debe por tanto comprobar que todos los estados externos acaben cayendo a uno que pertenezca a la serie de Fibonacci. En ese caso habría que retocar la tabla de forma que no ocurriera, pero en el diagrama de esta solución se ve claro que esto no ocurre.

El circuito que se utiliza para pasar del 9 al 1 es el mismo que en el apartado anterior, pero en este caso se podría ahorrar una puerta AND, puesto que hemos usado la misma puerta (and n0q3) en la parte anterior:
Combinacional para cambiar 9 por 1

Y este es el código en Verilog:

/* Computadores I - GII - USAL

Sesión 10 - Ejercicio 1.

Se nos pide diseñar un circuíto que siga la serie de Fibonacci
usando el menor número de puertas.

En esta solución se incluyen:

1 AND de tres entradas
5 AND de dos entradas 
4 OR de dos entradas
4 biestables JK
===========
34.5 puertas.

Por: cunart - Grupo A2
*/


//Modulo del biestable JK
module JKdown(output reg Q, output wire NQ, input wire J, input wire K,   input wire C);
  not(NQ,Q);

  initial
  begin
    Q=0;
  end    

  always @(posedge C)
    case ({J,K})
      2'b10: Q=1;
      2'b01: Q=0;
      2'b11: Q=~Q;
    endcase
endmodule


//Módulo que contiene el contador y la circuitería auxiliar.
module contador (output wire [3:0] Q, input wire C);
  //Cables correspondientes a las salidas negadas de los biestables.
  wire [3:0] nQ;
  //Cables que almacenan la salida temporal del biestable jk3.
  wire Qt, nQt;

  //Cables de entrada a los biestables.
  wire wJ3, wJ2, wJ1, wK0;

  //Cables intermedios.
  wire wn0n1, wq0q1, wn0q3, wn3n1, wq2q3;

  //Puertas correspondientes al contador.
  and n0n1 (wn0n1, nQ[0], nQ[1]);
  or J3 (wJ3, wn0n1, Q[2]);

  and q0q1 ( wq0q1, Q[0], Q[1]);
  and n0q3 ( wn0q3, nQ[0], Qt);
  or J2 (wJ2, wq0q1, wn0q3);

  and J1 (wJ1, nQ[2], nQt, Q[0]);

  and n3n1 (wn3n1, nQt, nQ[1]);
  or K0 (wK0, wn3n1, Q[2]);

  JKdown jk1 (Q[0], nQ[0], 1'b1, wK0, C);
  JKdown jk2 (Q[1], nQ[1], wJ1, Q[0], C);
  JKdown jk3 (Q[2], nQ[2], wJ2, 1'b1, C);
  JKdown jk4 (Qt, nQt, wJ3, Q[0], C);

  //Circuitería adicional que cambia el nueve por el uno.
  and  q2q3 (wq2q3, Q[2], Qt);
  or    NQ3 (Q[3], wq2q3, wn0q3);
endmodule


//Módulo para probar el circuíto.
module test;
  reg I, C;
  wire [3:0] Q;
  contador counter (Q,C);

  always 
  begin
    #10 C=~C;
  end

  initial
  begin
    $dumpfile("ej1_34-5.dmp");
    $dumpvars(2, counter, Q);
          
    C=0;
    #500 $finish;
  end
endmodule
La salida vista en el GTKWave es la siguiente:
Salida de GTKWave

El circuito, realizado con el programa KTechLab, donde también se comprueba su funcionamiento, es el siguiente:
Circuito realizado con KTeckLab

A la pregunta que se hace al final, sería un código como el siguiente, útil en caso de que vayamos a útilizar este circuito formando parte de otro mayor y ya tengamos el diseño listo:
module contador (output reg [3:0] Q, input wire C);
  reg [3:0] Qt1; reg [3:0] Qt2;

  initial
  begin
    Q = 13;       
  end

  always @(posedge C)
  begin
    if (Q == 13)
    begin
      Q = 0;     // En estos dos casos, se ignora el reloj.
      #20        // Mejor sería hacer una tabla directa
      Q = 1;     //   basándonos solo en el estado anterior:
      #40        //     0 -> 1 -> 1 -> 2 -> 3 -> ...
      Qt2 = 0;   //   y apañando algo para el 1 repetido
      Qt1 = 1;   // [[Nota del profesor]]
    end
    Q = Qt1 + Qt2;
    Qt2 = Qt1;
    Qt1 = Q;
  end
endmodule

© 2011 Guillermo González Talaván, a excepción de las prácticas presentadas por los alumnos