¿Cómo redirijo/regenerar un reloj de entrada a un pin de salida en mi diseño FPGA (Verilog)

Tengo un ADC que requiere que le envíe 20 pulsos de reloj cuando solicito leer datos de su registro interno (después de haberlo activado para leer datos de mi sensor).

Pude simular esto muy bien en ModelSim, pero soy nuevo en Verilog y no me di cuenta de que tendría problemas durante la síntesis al crear el tren de pulsos como este:

reg [4:0] counter = 5'b10100;
parameter counter = 0;

always (posedge clk and negedge clk) 
  begin
   if (counter > 0)
     begin
       counter <= counter - 1;
       serial_out <= ~serial_out; 
     end
  end

Intenté dividir esto en 2 bloques siempre: uno que establece serial_out en 1 en un posedge clk y otro que establece serial_out en 0 durante negedge clk, ambos verificando si el contador es mayor que 0. Esto es problemático porque estoy tratando de conducir contador en dos lugares y obtiene errores que indican "no se puede resolver el controlador constante múltiple para el contador neto ..."

¿Quizás hay una mejor manera de hacer esto?

He visto algunas publicaciones que sugieren duplicar la frecuencia de clk para leer los datos del posedge del reloj. Esto funcionaría, pero necesito mantener el reloj a 30 MHz (no puedo ir a 60 MHz por otras razones).

¿Cómo sugeriría que enrute/reproduzca condicionalmente 20 pulsos de mi reloj de entrada periódico de 30 MHz siempre activo a un pin de salida?

Cualquier ayuda será apreciada.

Gracias, acabo de modificar mi FSM e incorporé un reloj cerrado. La simulación se verifica. Creo que ahora tengo un buen pulso para trabajar cuando hago mi síntesis.

Respuestas (1)

Sugeriría usar un flip flop DDR de salida. La forma en que implemente eso depende de qué FPGA esté usando. Para Xilinx, sería una primitiva ODDR u ODDR2. Para Altera, es ALTDDIO_OUT.

Estoy usando un flip flop D con la salida entrando en una puerta AND usando una declaración de asignación. La simulación se verifica. Me gustaría manejar un pin GPIO directamente con este tren de pulsos (sirve como un reloj en serie). Veo que mencionas usar ALTDDIO_OUT.
El hecho de que la simulación se verifique no significa que funcionará bien en el FPGA, especialmente en términos de IO.
Vale, soy nuevo en esto. ¿Por qué se requiere ALTDDIO_OUT en lugar de tener un flip flop D inferido a través de algunas declaraciones sin bloqueo durante la síntesis? Estoy usando Quartus Prime por cierto.
El ALTDDIO_OUT es una lógica dedicada que cambia entre dos señales cuando cambia el reloj. Podrías hacer lo mismo con los flip flops si estuvieran cronometrados a la doble frecuencia, ya que necesitas reaccionar ante el flanco descendente del reloj, pero la lógica dedicada gana, ya que puedes alimentarla con dos señales triviales (que se transmitirán después de un nivel bajo '1'→ transición alta, y '0'después de una transición alta→baja).
El problema es cómo está diseñado el FPGA. Los pines de salida generalmente se pueden controlar desde la lógica de la estructura o desde un flip flop. El retraso de un flip flop es constante y predecible. El retraso de la lógica de la estructura no es y variará según la lógica, la ubicación y variará de un dispositivo a otro. El problema no es el flip flop, el problema es poner la lógica entre el flip flop y el pin, especialmente si desea mantener una relación de tiempo específica entre ese pin y otros pines que pueden ser controlados directamente por flip flops.
Además, el retraso para los flip flops DDR y los flip flops normales es el mismo, por lo que si genera un reloj invertido con un flip flop DDR, prácticamente se garantiza que tendrá la relación de tiempo adecuada con los datos registrados con el mismo reloj de IOB. chancletas.