Estoy implementando un contador de segundos en la placa educativa Altera DE-1 alimentado por el antiguo Cyclone 2 FPGA. Mi plan es hacer un 'reductor de reloj' que tome el reloj integrado de 50 MHz y produzca una señal de reloj de 1 Hz (denominada 'pulso'), que luego se usará para impulsar el contador normal. El módulo down clocker es el siguiente:
module downClockerTest(pulse, clk, reset);
output reg pulse;
reg [25:0] count;
input clk, reset;
always @(posedge clk or negedge reset) begin
if(~reset) begin
count <= 26'h0;
pulse <= 1'd0;
end
else if(count == 26'd49999999)
count <= 26'd0;
else begin
count <= count + 26'h1;
pulse <= (count > 26'd24999999);
end
end
endmodule
Observe que el 'pulso' de salida está registrado. Este diseño funciona bien; el contador cuenta como debería. Sin embargo, si trato de eliminar el registro al final intentando impulsar la salida de 'pulso' con una sola declaración de asignación, el contador de segundos parece comenzar a saltar 1 y luego 4 en 1 segundo, lo que indica 5 pos-bordes desde el down-clocker, donde solo debería haber uno.
El down-clocker ligeramente modificado es el siguiente:
module downClockerTest(pulse, clk, reset);
output pulse;
reg [25:0] count;
input clk, reset;
assign pulse = (count > 26'd24999999); // The counter seems to increment by 1 and then 4 in quick succession (1 second).
always @(posedge clk or negedge reset) begin
if(~reset) begin
count <= 26'h0;
end
else if(count == 26'd49999999)
count <= 26'd0;
else begin
count <= count + 26'h1;
end
end
endmodule
El RTL modificado sin el registro es:
¿Por qué el down-clocker solo funciona bien cuando hay un registro al final? ¿El registro está realizando algún tipo de 'antirrebote'? ¿El 'rebote' ocurre también en circuitos de conmutación no mecánicos? ¿Cuál podría ser la posible razón desde un punto de vista electrónico?
Puede ser prudente agregar que el análisis de tiempo de TimeQuest falla en ambos casos con una advertencia crítica: "No se cumplen los requisitos de tiempo". Pero aún así, uno funciona donde otro no.
Supongo que este extraño comportamiento tiene que ver con una condición de carrera causada cuando una secuencia de bits cambia drásticamente sus 1 y 0 después de un incremento. Por ejemplo, 110111 se convierte en 111000 después de incrementarse en 1. Dado que no se sabe cuál de los flip-flops, que almacena las posiciones de bits individuales en la secuencia, actualizará sus valores primero, el número (léase: secuencia de bits) puede fluctuar por un instante antes de alcanzar un valor estable. Puede haber números (secuencias de bits) que, mientras tienden hacia sus valores estables, fluctúan a través del valor que se compara (24999999, en nuestro caso) y hacen que el comparador emita Logic-HI. Un registro al final sin duda resolvería este problema. Sin embargo, todo esto son conjeturas, con bases en poca experimentación. Cualquier opinión sabida será bienvenida.
Cuando utilice la asignación asíncrona para el pulso, verá la influencia de retrasos desiguales en el comparador como fallas en la salida. El registro de la señal de comparación oculta esto, lo que permite que todo se estabilice antes del siguiente borde del reloj. (Esto está garantizado por la herramienta place-route si dice que la ruta cumple con el tiempo).
Si, en el futuro, tiene alguna razón por la que necesita decodificar asíncronamente un conjunto de salidas de contador, y desea que esté libre de fallas , hay una respuesta: use el conteo de código Gray . Los códigos grises garantizan que solo una señal a la vez cambia de estado, por lo que evita la condición de carrera de múltiples rutas que conduce a la falla.
Sí, hay "rebote", pero en este contexto, los llamamos "problemas técnicos". El comparador (count > 26'd24999999)
representa una cantidad bastante grande de lógica combinatoria, y no hay posibilidad de que todas las rutas a través de esta lógica (y la interconexión FPGA asociada) tengan exactamente el mismo retraso. Por lo tanto, la salida pulse
experimentará una o más fallas antes de que se estabilice.
Si está utilizando pulse
directamente como un reloj para otra lógica, esa lógica experimentará flancos de reloj adicionales.
Los comparadores son una lógica relativamente compleja, con largas cadenas de transporte.
Yo recomendaría algo como esto:
module downClockerTest(pulse, clk, reset);
output reg pulse;
reg [24:0] count;
input clk, reset;
always @(posedge clk or negedge reset) begin
if(~reset) begin
count <= 25'h0;
pulse <= 1'd0;
end
else if(count == 25'd24999999) begin
count <= 25'd0;
pulse <= ~pulse;
end
else begin
count <= count + 1;
end
end
endmodule
En lugar de contar hasta 50 000 000 y usar un comparador para establecer el pulse
valor, solo cuento hasta 25 000 000 y alterno pulse
cada vez que llego al conteo completo.
kraken
el fotón