Divisor de frecuencia de números impares

Nota importante: no me estás ayudando a hacer mi tarea. Esto es para un concurso para estudiantes de ingeniería, que te anima a "usar tu red" ;)

Tengo este patrón para un divisor de frecuencia que divide el reloj por 5. Se supone que tiene un problema importante, pero parece que no puedo descifrar exactamente cuál es.

ingrese la descripción de la imagen aquí

Las opciones que tengo para solucionar este problema son:

  • X==(000|001|100), Y==(001)
  • X==(000|001|010|011), Y==(010|011)
  • X==(001|010|011), Y==(000)
  • ¡Tanto a) como c) son correctos!

Me tomé el tiempo de mapear las señales en el diseño original y en la opción número 3, ya que pensé que esa era la respuesta.

http://imgur.com/dD30q

He movido el reloj medio ciclo de reloj, ¡ups! Aunque no debería cambiar nada. El resto se hace a mano.

¿Alguien aquí tiene alguna buena sugerencia?

Respuestas (3)

Se supone que tiene un gran problema.

El único problema posible que salta a la vista es la prevención de fallas. Su salida es una señal de reloj, por lo que sería muy sensible a los bordes adicionales. Pero es una salida combinacional, por lo que puede ser propenso a fallas.

Solo como ejemplo, supongamos que tiene esta implementación ingenua de un generador de acarreo completo (al menos 2 entradas de 3 son verdaderas), a saber

Y = ABC + AB(!C) + A(!B)C + (!A)BC

Si sus señales ABC cambian de 111 a 011, existe la posibilidad, dependiendo de los retrasos de propagación, de que la salida Y, que debería ser un 1 todo el tiempo, le dé un breve error de 0. Lo que sucede básicamente es que la salida la veracidad tiene que pasar de un término a otro: ABC -> (!A)BC en este caso. Si el término (!A)BC tiene un retraso de propagación más largo que el término ABC para la transición 1 -> 0 en A, entonces ambos términos ABC y (!A)BC pueden ser 0 por un corto período de tiempo, y se obtiene un 0 como salida.

Una implementación adecuada es aquella en la que un solo cambio de bit de entrada no produce fallas en la salida: el nivel de la salida es compartido por dos términos a medida que transiciona. En el caso de un generador full-carry, esto funciona:

Y = AB + BC + CA

En su caso, hay dos posibles causas de fallas.

Una es que X y Z cambian casi al mismo tiempo, pero en su caso, de acuerdo con sus diagramas de tiempo, esto no debería suceder.

La otra es que la lógica combinacional que produce X es propensa a fallas. No sabemos cómo se implementa, por lo que es difícil de decir.

La solución más simple en cualquier caso es colocar un flip-flop en la salida, con la misma entrada de reloj que los otros flip-flops. Los flip-flops modernos tienen especificaciones de muestra/retención tales que cualquier retraso de propagación >= 0 y < (período de reloj - tiempo de configuración) producirá salidas estables y sin fallas, por lo que, a menos que su período de reloj sea realmente rápido, cualquier falla en la entrada de el flip-flop se asentará al comienzo de su ventana de tiempo de configuración en el siguiente borde del reloj.

Si no puede tolerar la demora de poner un flip-flop en la salida, debe garantizar que toda la lógica combinacional que produce directamente la salida esté libre de fallas.

Me había perdido que era una salida de reloj. Es casi seguro que los fallos son el "problema principal". Estaba pensando que una de las respuestas tenía una solución lógica más óptima (menos puertas).

Sugeriría comenzar con un contador de dividir por cinco, uno de cuyos bits es alto para dos cuentas y bajo para tres. Por ejemplo:

Q0 := !Q1 & !Q2;
Q1 := Q0;
Q2 := Q1;

Este contador seguirá la secuencia: 000 001 011 110 100 (un valor de 101 alcanzará un estado válido después de dos relojes; 010 o 111 alcanzará un estado válido después de un reloj). Cualquier parte de él puede usarse como una salida de dos puntos calientes.

Tome la salida de este contador e introdúzcalo en un pestillo que se activa con el borde opuesto del reloj. El "O" de esta salida de contador con la primera produciría la forma de onda deseada.

No hay necesidad de hacerlo tan complejo. Lo he hecho para dividir por 3, puede generalizarlo o codificarlo para dividir por 5 simplemente cambiando el valor de c1 y los elementos de sensibilidad. A continuación se muestra el código:

module clk ();
reg clk,clkout;
initial clk =0;
initial clkout = 0;
int c1,c2,c3;
always #5 clk = ~clk;
always@(posedge clk or negedge clk)
begin
c1 <= c1 +1;

if (c1 == 5)
begin
c1 <= 0;
end

//
end

always@(posedge clk or negedge clk)
begin
if(c1==0 || c1 == 3)
begin
clkout = ~clkout;
end
end


endmodule
Debe formatear su código, esto es muy difícil de leer
Seleccione el texto y presione el {}botón de código en la barra de herramientas del editor. Tenga en cuenta que parece haber proporcionado un programa para algo sin decir qué es ese algo. También tenga en cuenta que la pregunta es sobre lógica, no sobre programación. Finalmente, vea que el OP aceptó una respuesta hace siete años.
@DHANESH: nidhin ha agregado las etiquetas de código, pero debe sangrar el código correctamente y explicar cómo responde esto a la pregunta.