Generar un reloj de 40MHz en un FPGA con un reloj de 100Mhz

1

Estoy tratando de generar un reloj de 40MHz en una clase de lucha de 100Mhz FPGA con Verilog CODE, redirigí el reloj a un pin para verificar los 100Mhz:

assign pin1= clock; //gives me an 100MHz clock
assign pin2= ~clock;  //gives me an 100MHz inverse clock

siempre bloquea

reg clock1;
reg [4:0] prescaler1;

always @(posedge clk) begin
    if(reset==1'b1)begin
        clock1=1'b0;
        prescaler1=2'b0;
    end else begin
        if(prescaler1==2'b01) begin
            clock1=~clock1;
            prescaler1=1'b0;
        end else begin
            prescaler1=prescaler1+1'b1;
            clock1=clock1;
        end
    end
end

me da 50, 25, 16.66, 12.5MHz dependiendo del prescaler configurado en 0, 1, 2, 3

¿Hay un truco para hacerlo?

Es un Zedboard Zynq-7000 Z-7020 XPS te permite asignar 4 relojes de tela PL, pero creo que tienen que ser múltiplos de 33MHz.

¿Cuál es la diferencia de ARM_PLL IO_PLL y DRR_PLL

    
pregunta eactor

4 respuestas

3

El prescaler simple que ha implementado sigue la fórmula $$ fout = fMaster \ div (2 * (1 + prescalerN)) $$ donde fMaster es la entrada del reloj maestro de 100MHz y prescalerN es el valor de recarga del prescaler. No hay un divisor de números enteros de (100MHz / 2) que produzca 40MHz. Esta es una limitación de la implementación del prescaler en la lógica programable de propósito general.

Muchos FPGA incluyen bloques de generación de reloj especializados como PLL (Phase-Locked Loop). Este es un circuito analógico especializado implementado en silicio FPGA, que puede configurarse para funcionar a un reloj interno más rápido que el reloj maestro aplicado. Por lo tanto, el reloj externo de 100MHz puede duplicarse a 200MHz o tal vez hasta 400MHz. El PLL usa un principio de bucle de control similar al que utiliza un amplificador operacional, para lograr generar una frecuencia interna más alta estable, a partir de una referencia externa de frecuencia más baja estable.

Algunos Xilinx FPGA tienen DCM (Digital Clock Manager). Altera llama a este tipo de cosas un "megafunction" si recuerdo correctamente, debería haber un megafunction para PLL. Depende exactamente de qué FPGA está utilizando. Consulte la hoja de datos principal del FPGA.

    
respondido por el MarkU
3

Si no tiene un PLL, necesita un contador de división por 5 (a 20 MHz), una versión del mismo con retardo de 1.5 ciclos (use el borde opuesto del reloj para 0.5 ciclos) y una compuerta XOR (con la versión corregida, una compuerta OR será suficiente ya que ambas señales nunca son '1' al mismo tiempo)

Esto le dará una señal de 40MHz con una proporción constante de espacio de marca del 40% (pero no del 50% ... ¡editado!).

NB: la compuerta OR agregará un poco de inclinación con una división de reloj recta. Si su FPGA cuenta con registros DDR, puede limpiar eso.

process(clk)
variable count : natural range 0 to 4;
begin
  if rising_edge(clk) then
    if count = 4 then
      count  := 0;
      clk_20 <= '1';
    else
      count  := count + 1;
      clk_20 <= '0';
    end if;
    clk_20d1 <= clk_20;   -- delay, thanks to signal assignment semantics
  end if;
end process;

process(clk)
begin
  if falling_edge(clk) then
    clk_20d15 <= clk_20d1; -- +0.5 cycle delay
  end if;
end process;

clk_40 <= clk20 or clk_20d15;

Debería ser sencillo traducirlo en Verilog.

    
respondido por el Brian Drummond
2

Sí, hay un truco para hacer esto. Se llama división fraccional de reloj y a menudo se hace con un preescalador de doble módulo .

Aquí hay una página web que da código de ejemplo en VHDL (perdón, no verilog): fractional-clock-division-dual-modulus

Usando estas técnicas, podrá obtener una señal de 40Mhz de su reloj de 100Mhz, pero tenga en cuenta que el jitter aumentará y puede terminar con una señal que no tiene un ciclo de trabajo del 50%.

Ya que estás trabajando en un FPGA: verifica si tu FPGA contiene un administrador de reloj digital. Estos son bloques de hardware que pueden generar una amplia gama de frecuencias fuera de un reloj existente al multiplicar primero la frecuencia y luego dividirla. Obtendrá un mejor rendimiento de un administrador de reloj digital que un prescaler de doble módulo escrito a mano.

    
respondido por el Nils Pipenbrinck
1

La mejor manera sería un PLL como lo mencionan las otras respuestas: multiplica por 4, luego divide por 10. Puedes hacer x2, / 5 pero eso no te da un ciclo de trabajo del 50% (puede que no sea un problema ).

Pero para agregar a esos, hay una segunda opción si no hay un PLL disponible, que no se recomienda, ya que se basa en la lógica asíncrona. Iría algo como esto:

wire clock2x;
wire clock2xDelay;
assign clock2x = clock100M ^ clock2xDelay;
assign clock2xDelay = ...; //I need to be clock2x delayed by about 5ns

reg [2:0] divider;
always @ (posedge clock2x or posedge reset) begin
  if (reset) begin
    divider <= 3'b0;
  end else if (divider == 3'd4) begin
    divider <= 3'b0;
  end else begin
    divider <= divider + 3'b1
  end
end
assign clock50M = divider[1]; // 40% Duty cycle, 50MHz clock

El código anterior no está completamente completo. Notarás que clock2xDelay no está terminado. Básicamente, aquí es donde debe suceder lo interesante y dependerá de su dispositivo. Básicamente, debe agregar suficiente retraso (mediante el retraso de la cadena de transporte, los retardos de LUT, etc.) para que el XOR produzca un impulso lo suficientemente amplio como para no causar errores mínimos de tiempo de duración del impulso. El sintetizador también necesita que se le diga que no optimice la cadena de retardo.

Este código no se recomienda ya que el retardo asíncrono variará con la temperatura y las características del dispositivo y, como tal, dará como resultado un reloj tembloroso.

    
respondido por el Tom Carpenter

Lea otras preguntas en las etiquetas