Puntos de conocimiento FPGA --- diseño de circuito de división de frecuencia arbitraria

Antes de aprender, ¿comprende qué es el ciclo de trabajo?
Ciclo de trabajo: para una secuencia de pulso ideal (como una onda cuadrada), la relación entre la duración del pulso positivo y el período en el pulso se denomina ciclo de trabajo de la onda cuadrada.

Incluso división de frecuencia

La multiplicación y división de números pares debe ser la división familiar y el contador de división más simple, que se puede realizar directamente con el contador. Por ejemplo, si la frecuencia se divide entre N múltiplos y números pares, el reloj puede activar el contador para dividirlo. Cuando el contador cuenta de 0 a N / 2-1, el reloj de salida se invierte y el contador se reinicia. El siguiente reloj es de Empiece a contar desde cero. En este ciclo, se puede lograr cualquier división de frecuencia uniforme

División de frecuencia impar

La multiplicación y división de números impares a menudo se preguntan en los foros. De hecho, hay dos métodos de implementación para la multiplicación y división de números impares:
primero, se puede lograr mediante un contador. Por ejemplo, dividir por tres, activar el contador por el borde ascendente del reloj que se dividirá. Contando módulo tres, cuando el contador cuenta hasta el valor adyacente, se invierte dos veces. Por ejemplo, cuando el contador cuenta hasta 1, el reloj de salida se invierte, y cuando el contador llega a 2 se invierte nuevamente. Es decir, el valor de recuento se invierte dos veces en el 1 y 2 adyacentes. La relación de trabajo de la frecuencia de tres vías realizada de esta manera es 1/3 o 2/3. Si desea lograr un reloj de tres frecuencias con un ciclo de trabajo del 50% , puede activar el conteo por el borde descendente del reloj que se dividirá, y contar de tres en tres de la misma manera que el borde ascendente, y luego el reloj de tres frecuencias y el borde ascendente generado por el borde descendente El reloj generado realiza la operación de fase OR para obtener un reloj de tres frecuencias con un ciclo de trabajo del 50%. Este método puede lograr cualquier división de frecuencia impar.
El método clasificado como general es: para la realización de la división de frecuencia N veces impar con un ciclo de trabajo del 50%, el disparo del flanco ascendente se realiza para la cuenta del módulo N, la cuenta se selecciona a un cierto valor y el reloj de salida se invierte, y luego el (N- 1) / 2 se invierte nuevamente para obtener un reloj de frecuencia n con número impar que no sea del 50% con un ciclo de trabajo. Al mismo tiempo, se realiza el conteo del módulo N activado por el flanco negativo. Cuando el valor es el mismo que el valor seleccionado del cambio de reloj de salida activado por el flanco ascendente, se realiza el cambio del reloj de salida. Cuando también se pasa (N-1) / 2, el reloj de salida vuelve a girar para generar una cuenta Un reloj dividido de n números impares con una proporción vacía distinta del 50%. Dos relojes divididos por n con un ciclo de trabajo distinto del 50% se aplican mediante OR para obtener un reloj dividido n de números impares con un ciclo de trabajo del 50%.
Otro método: para dividir el reloj entre múltiplos impares entre n, primero divida entre n / 2 (con decimales, que es igual a (n-1) /2+0.5), y luego divida entre dos. Obtenga una división de frecuencia impar con un ciclo de trabajo del 50%.

Frecuencia fraccional

Primero, déjame hablar sobre cómo dividir por n + 0.5, lo que requiere operación en el reloj de entrada. Idea básica de diseño: para la división de frecuencia de n + 0.5, primero cuente módulo n. Cuando el conteo llega a n-1, el reloj de salida se asigna a '1', y cuando vuelve al conteo 0, se asigna a 0. Por lo tanto, puede Se sabe que cuando el valor de conteo es n-1, el reloj de salida es 1. Por lo tanto, siempre que el valor de conteo n-1 se mantenga durante la mitad del ciclo del reloj de entrada, se realiza el reloj de división de frecuencia n + 0.5, así que mantenga n-1 como la mitad Un ciclo de reloj es una dificultad. Se puede encontrar que debido a que el contador cuenta por el borde ascendente del reloj, el reloj de activación de conteo se puede voltear cuando el conteo es n-1, entonces el borde descendente del reloj se convierte en un borde ascendente. Es decir, cuando el valor de recuento es n-1, el flanco descendente del reloj se convierte en el flanco ascendente, y el valor de recuento n-1 solo se mantiene durante medio ciclo de reloj. Debido a que el reloj cambia el flanco descendente al flanco ascendente, el valor de recuento se convierte en 0. Por lo tanto, cada vez que se genera un período de reloj dividido n + 0.5, el reloj de activación debe invertirse una vez. La idea de diseño es la siguiente:
Inserte la descripción de la imagen aquí
Lo siguiente es cualquier código de división de frecuencia de entero positivo:

module div_clk(
	input	clk,
	input	rst_n,
	output	o_clk
);

	parameter	WIDTH = 3;
	parameter	N	  = 6;
	
	reg [WIDTH-1:0]	cnt_p;
	reg				clk_p;
	reg				clk_n;
	
	assign	o_clk = (N==1)?clk : (N[0])?(clk_p | clk_n) : clk_p;//其中N==1是判断不分频,N[0]是判断是奇数还是偶数,若为1则是奇数分频,若是偶数则是偶数分频。
	
	always @(posedge clk or negedge rst_n) begin
		if(!rst_n)
			cnt_p <= {
    
    WIDTH{
    
    1'b0}};
		else if(cnt_p == (N-1))
			cnt_p <= {
    
    WIDTH{
    
    1'b0}};
		else
			cnt_p <= cnt_p + 1'b1;
	end
	
	always @(posedge clk or negedge rst_n) begin
		if(rst_n == 1'b0)
			clk_p <= 1;//此处设置为0也是可以的,这个没有硬性的要求,不管是取0还是取1结果都是正确的。
		else if(cnt_p < (N>>1))/*N整体向右移动一位,最高位补零,其实就是N/2,不过在计算奇数的时候有很明显的优越性*/
			clk_p <= 1;
		else
			clk_p <= 0;
	end
	
	always @(negedge clk or negedge rst_n) begin
		if(rst_n == 1'b0)
			clk_n <= 1;
		else 
			clk_n <= clk_n;
	end

endmodule

La siguiente es la división impar, par y decimal de un fragmento de código

module divf #
(    parameter Div_num = 12 ,    // 分频数
     parameter state=0        //半分频为0,奇数分频为1,偶数分频为2
)
(
input                 clr,
input                 clk,
output                Div_clk
);
reg [24:0]  count;

case(state)
1:   begin  //ji_shu
          reg         pos_clk;
          reg         neg_clk;

          always@(posedge clk or negedge clr)
          if(!clr)                     count<=0;
          else if(count==0 & pos_clk)  count<=Div_num/2-1;
          else if(count==0)            count<=Div_num/2;
          else                         count<=count-1;

          always@(posedge clk or negedge clr)
          if(!clr)                     pos_clk<=0;
          else if(count==0)            pos_clk<=~pos_clk;
          else                         pos_clk<=pos_clk;

          always@(negedge clk or negedge clr)
          if(!clr)                     neg_clk<=0;
          else                         neg_clk<=pos_clk;

          assign Div_clk = pos_clk & neg_clk;
     end

2:   begin  //ou_shu
          reg          Div_clk1;

          always@(posedge clk or negedge clr)
          if(!clr)                     count<=0;
          else if(count==0)            count<=Div_num/2-1;
          else                         count<=count-1;

          always@(posedge clk or negedge clr)
          if(!clr)                     Div_clk1<=0;
          else if(count==0)            Div_clk1<=~Div_clk1;

          assign Div_clk = Div_clk1;
     end


0:   begin   //ban_fen_pin
          reg         count_div;
          reg         count_div2;
          wire        clk_half;

          assign  clk_half = clk^count_div2;
          always@(posedge clk_half or negedge clr)   //模Div_num 计数
          if(!clr)                       count<=0;
          else if(count== Div_num-1)      count<=0;
          else                         count<=count+1;

          always@(posedge clk_half or negedge clr)   //模Div_num 计数
          if(!clr)                       count_div<=0;
          else if(count== Div_num-1)      count_div<=1;
          else                         count_div<=0;

          always@(posedge count_div or negedge clr)   //对count_div二分频
          if(!clr)                       count_div2<=0;
          else                         count_div2<=~count_div2;

          assign Div_clk = count_div;
     end
endcase

endmodule

Supongo que te gusta

Origin blog.csdn.net/gemengxia/article/details/108483696
Recomendado
Clasificación