Welcome to IDI Electronica!!!



Welcome!!! IDI Electronica is a blog for my personal projects and articles to help electronics enthusiasts like me.

Bienvenidos!!! IDI Electronica es un blog con mis proyectos personales y artículos con el fin de ayudar a entusiastas de la electrónica como yo.

Monday, March 21, 2016

Divisor de Frecuencia por Número Impar con Ciclo de Trabajo de 50%

1. INTRODUCCION

En uno de mis artículos expliqué cómo dividir la frequencia de una señal de reloj para crear señales de reloj con frecuencias menores.  El concepto es muy simple, esperamos que cierto número de ciclos del reloj pasen y cambiamos nuestra señal de salida de 0 a 1, o de 1 a 0.  Por ejemplo,  la figura 1 describe el diagrama de tiempo de un divisor de frecuencia por 12.  Por cada 6 ciclos del reloj de entrada, el valor de la señal de salida cambia.


Fig 1. Diagrama de tiempo de divisor de frecuencia por 12


Si observamos el diagrama de tiempo, notamos que el contador de ciclos usa el borde de subida del reloj como referencia (instante en que el reloj cambia de 0 a 1).  Debido a ésto, el circuito es fácil de diseñar si la frecuencia es dividida por un número par.  Sin embargo, el circuito se vuelve más complicado si queremos dividir la frecuencia por un número impar.  Si observamos la figura 2, un divisor de reloj impar necesita usar el borde de subida y el de bajada del reloj.  Por lo tanto, un simple contador de bordes de subida no sirve en estos casos.


Fig 2. Diagrama de tiempo de divisor de frecuencia por 5


2. DESCRIPCION DEL CIRCUITO

Para dividir la frecuencia de un reloj digital por un número impar, necesitamos crear otras señales e implementar lógica secuencial y combinacional.

La forma más sencilla de entender cómo funciona el circuito es observando el diagrama de tiempo en la figura 3 y siguiendo las instrucciones que escribí a continuación:

- Nuestro circuito divide la frecuencia de un reloj por el número impar N.  En este ejemplo, N=5.

- La señal clk_in es nuestro reloj de entrada con frecuencia 500MHz y con ciclos de 2ns.

- El bus de señales Count es un contador de ciclos de entrada clk_in y reinicia a 0 cuando el contador llega a N-1. Para nuestro ejemplo, N-1 = 4, o sea 0100 en binario.

- La señal A es igual a 1 sólo cuando el valor en el contador Count es 0001.  Sino, es 0.

- La señal B es igual a 1 sólo cuando el valor en el contador Count es (N+1)/2.  Para nuestro ejemplo, (5+1)/2 = 3, o 0011 en binario.

- La señal Tff_A es un biestable T (T flip flop) activado por el borde de caída de la señal A.

- La señal Tff_B es un biestable T (T flip flop) activado por el borde de caída del reloj y sólamente cuando la señal B es 1.

- La señal clk_out es nuestro reloj de salida.  Para producir esta señal, usamos una puerta XOR entre las señales Tff_A y Tff_B.  La señal clk_out es alta cuando Tff_A y Tff_B son diferentes (10,01) y baja cuando ambas señas son iguales (11, 00). En nuestro ejemplo creamos una señal con frecuencia de 100MHz y ciclos de 10ns.


Fig 3. Diagrama de tiempo mostrando las señales usadas en divisor frecuencia por 5


Para una explicación más técnica de lo que hice en este circuito, les recomiendo que lean la hoja de aplicación AND8001-D publicada por ON Semiconductors.


3.  Implementación en Verilog

Para crear el circuito descrito en la sección anterior, debemos utilizar lógica secuencial (biestables, registros, etc) y lógica combinacional (puertas lógicas).

A continuación les dejo el código para el divisor de frecuencia por 5, el cual también se encuentra disponible en mi repositorio de Github  https://github.com/sphanlung/FPGA/blob/master/clk_div_odd.v 



module clk_div_odd(
input clk_in,
output  clk_out
    );

reg  [3:0] count = 4'b0;        //4-bit counter
reg    A1 = 0;
reg       B1 = 0;
reg     Tff_A = 0;
reg   Tff_B = 0;
wire   clock_out;
wire   wTff_A;
wire   wTff_B;

//Connects registers to wires for combinational logic
assign   wTff_A  = Tff_A;
assign   wTff_B  = Tff_B;

assign   clk_out = wTff_B ^ wTff_A; //XOR gate 

//Counter for division by N
always@(posedge clk_in)
begin
if(count == 4'b0100) //Count to N-1 (4) 
begin // Example: Use 4 to divide by 5        
    count <= 4'b0000;
end
else
begin
count <= count + 1;
end
end

//Set A to high for one clock cycle when counter is 0
always@(posedge clk_in)
begin
if(count == 4'b0000)
A1 <= 1;
else
A1 <= 0;
end

//Sets B to high for one clock cycle when counter is (N+1)/2
always@(posedge clk_in)
begin
if(count == 4'b0011) //Use (N+1)/2
B1 <= 1; //Ex: (5+1)/2 = 3
else
B1 <= 0;
end

//T flip flop toggles 
always@(negedge A1) // Toggle signal Tff_A 
begin  //whenever A1 goes from 1 to 0
Tff_A <= ~Tff_A;
end

always@(negedge clk_in)
begin
if(B1) // Toggle signal Tff_B whenever   
   begin //B1 is 1
Tff_B <= ~Tff_B;
end
end

endmodule




Fig 4. Diagrama de RTL generado por Xilinx ISE

No comments:

Post a Comment