viernes, 17 de marzo de 2023

120 - Divisor de Frecuencia

 Circuito Divisor de Frecuencia

Fig1. Salida del Divisor
 

Saludos cordiales, en esta entrada, veremos como describir un circuito divisor de frecuencia con dispositivos biestables. Este trabajo complementa el avance académico para la materia de Sistemas Digitales II, siendo requisito que el lector ya tenga conocimientos básicos sobre el diseño de circuitos digitales, lenguaje verilog y dispositivos lógicos programables.

Para elaborar el código  del modulo y llevar a cabo pruebas de funcionamiento, utilizaremos uno de los siguientes programas:

Operación del circuito divisor

Es un circuito que permite incrementar en múltiplos de dos el periodo de una señal del reloj, donde la relación para este incremento en la señal de salida dependerá del numero de biestables conectados en serie.

Por ejemplo si conectamos dos Flip Flop JK en serie, tal como se observa en la imagen, la relación de salida con respecto a la entrada en el divisor sera 1:4.

Fig2. Circuito Divisor 1:4
La salida del circuito divisor sera siempre la salida q del ultimo biestable, como ambas entradas J y K están en nivel logico alto, el primer biestable conmuta su salida con cada flanco del reloj en la entrada clk, mientras que el segundo biestable conmuta únicamente cuando la salida del primero esta en nivel logico alto. Una representación mas clara de esta operación se observa en el siguiente diagrama de tiempos.

Fig3. Diagrama de tiempo, Divisor 1:4
 

Descripción del Circuito Divisor

Si modificamos el circuito anterior adicionando un biestable, como se muestran en la figura 4, la salida de este ahora tendrá una relación 1:8 con respecto a la señal del reloj.

Fig4. Circuito Divisor 1:8  
 
Fig5. Diagrama de tiempos Divisor 1:8

La nivel mas básico para describir en verilog el circuito divisor 1:8 de la figura 4,  es la descripción estructural, donde primero se debe elaborar un modulo descriptivo para el biestable JK, y luego el modulo divisor donde se describen conexiones entre los biestables utilizando instancias. Observe el siguiente ejemplo:

//Modulo descriptivo del Divisor 1:8
module div8(clk, rstn, s);
input clk, rstn;
output s;
wire q0, q1, q2, jk1, jk2;
assign s = q2; //Salida del ultimo FF
assign jk1 = q0;
assign jk2 = q0 & q1;
FFJKC ff0(clk, 1, 1, rstn, q0);
FFJKC ff1(clk, jk1, jk1, rstn, q1);
FFJKC ff2(clk, jk2, jk2, rstn, q2);
endmodule
 
//Modulo descriptivo del Flip Flop JK
module FFJKC(clk, j, k, clrn, q);
input clk, j, k, clrn;
output reg q;
always @(posedge clk or negedge clrn)
 if(clrn == 0) q <= 0;
 else
   case({j,k})
   2'b00 : q <= q;
   2'b01 : q <= 0;
   2'b10 : q <= 1;
   2'b11 : q <= ~q;
   endcase
endmodule

   
 l
Fig6. Salida del Divisor 1:8
 
Otra manera de elaborar en verilog este circuito es mediante una descripción procedural, donde no es necesario conocer la estructura del circuito en si, porque nos bastara saber su comportamiento a nivel funcional. Para este fin lo importante es considerar que un divisor es en esencia un registro contador limitado por cantidad de bits que lo conforman, y donde el bit de mayor peso estará asignado a su salida, el registro se desborda cada vez que llegue al valor limite. 
 
Fig5. Comportamiento del divisor 1:8
El siguiente código corresponde al modulo descriptivo de la funcionalidad que tiene el circuito divisor 1:8
 
module div8(clk, rstn, s);
input clk, rstn;
output s;
reg [2:0] q; //Registro de 3 bit
assign s = q[2]; //Asigna el bit MSB
always @(posedge clk or negedge rstn)
  if(rstn == 0) q <= 0;
  else q <= q + 1; //Incrementa el registro
endmodule

Tomando como referencia el código anterior del circuito divisor, y haciendo algunas modificaciones, podemos implementar fácilmente un circuito contador con secuencia truncada para conseguir cualquier frecuencia final de salida.  El siguiente modulo llamado drv_clock permite definir como parámetro la frecuencia del reloj y la frecuencia deseada en la salida.

module drv_clock(clk, rstn, clko);
input clk, rstn; //Entrada de reloj principal
output reg clko; //Salida de reloj
parameter SYSFREQ = 50000000; //Frecuencia principal en Hz
parameter OUTFREQ =  1000000; //Frecuencia de salida en Hz
localparam halfOUTFREQ = (SYSFREQ/OUTFREQ)/2;
localparam WIDTH = $clog2(halfOUTFREQ); //Medio ciclo
reg [WIDTH-1:0] cnt; //Contador para medio ciclo OUTFREQ
always @(posedge clk or negedge rstn) 
if(!rstn)
  begin
  clko <= 0;
  cnt <= 0;
  end
else
  begin
    if(cnt < (halfOUTFREQ-1)) //medio ciclo
    cnt <= cnt + 1'd1;
    else
      begin
      clko = ~clko; //Conmutación de salida
      cnt <= 0;  
      end
  end
endmodule

El modulo previo describe un circuito divisor 1:50, con esto es posible obtener una frecuencia de 1 MHz(OUTFREQ) si la entrada es de 50 MHz(SYSFREQ), los parámetros definidos permiten determinar la capacidad del registro contador durante la sintetización del circuito. para este caso la función verilog $log2 nos devolverá un valor entero de 5, con la que se dimensionara el registro contador


Ensayando el Divisor 
Para mostrar la correcta operacion de nuestro divisor, crearemos un modulo de estimulo que permita obtener pulsos de 1MHz a partir de un reloj de 24 MHz que es el oscilador utilizado por la placa TangNANO.
El modulo de estimulo descrito a continuacion crea una instancia de drv_clock, con la definicion a requerimiento de los parametros SYSFREQ y OUTFREQ.

`timescale 10ns/10ns //tienmpo base 10ns y precisión 1
module dvr_clock_tb;
reg clk, rstn;
wire out;
drv_clock #(.SYSFREQ(24000000), .OUTFREQ(1000000))
          inst0(clk, rstn, out);
initial begin
clk = 0; rstn = 0;
 forever #1 clk = ~clk; //Conmuta cada 10ns
end
initial begin
  #1 rstn = 1; //Desactiva luego de 10ns
end
endmodule

Fig8. Salida Divisor 1:24

Para finalizar solo quiero agradecer tu visita a mi blog, espero que el contenido de esta entrada hubiera sido de ayuda en tu formación educativa, favor cualquier consulta al respecto pueden escribirme a:

pablinzte@gmail.com / pablinza@me.com

Pablo Cesar Zárate.

jueves, 9 de marzo de 2023

107 - Decodificador para 7 Segmentos

 Modulo Decodificador BCDTOSEG

Fig1. Muestra cuatro pantallas de 7 segmentos

Saludos cordiales, en esta entrada, veremos como describir con el lenguaje verilog un modulo decodificador de numero BCD a una pantalla de 7 segmentos, que son muy utilizados en diversas aplicaciones electrónicas,  este trabajo complementa el avance académico para la materia de Sistemas Digitales I, siendo requisito que el lector ya tenga conocimientos sobre el diseño de circuitos combinatorios.

Para elaborar el código  del modulo y llevar a cabo pruebas de funcionamiento, utilizaremos uno de los siguientes programas:

Y si queremos implementar en circuito el modulo decodificador, necesitaremos una tarjeta de ensayos, en mi caso utilizare una FPGA TangNANO

Ahora si, manos a la obra, que llego la hora de comenzar.

Acerca de la Pantalla de 7 Segmentos

La pantalla o display de 7 segmentos, es un dispositivo opto-electrónico que nos permitirá visualizar un valor decimal de 0 a 9, con una distribución de siete diodos LED  que se activaran individualmente para representar un numero decimal.

Fig2. Distribución de los segmentos para representar números

Existen dos tipos de pantallas de 7 segmentos que son: Ánodo Común y Cátodo Común, y se diferencian por la manera de como están conectados los LED's que conforman cada segmento, observe la siguiente figura.

Fig3. Conexión interna de los LED's

La configuración en Cátodo común requiere un voltaje positivo de 5V o 1 logico para activar cada LED. Mientras que en Ánodo común se necesita 0V o 0 logico, debido a que estos LED operan con una corriente de circulación nominal, es necesario utilizar resistencia limitadoras para no exceder la capacidad de corriente maxima y agota la vida útil del dispositivo.

Una ventaja que aun mantiene la demanda de las pantallas de 7 segmentos es su coste y fácil implementación, además de la variedad de presentaciones disponibles con dimensiones que van desde las 6 a 32 pulgadas y  bloques de 1 a 4 dígitos.

Descripción del modulo

Fig4. Esquema del decodificador

Para describir el modulo de un decodificador BCD a 7 segmentos, necesitaremos en primer lugar conocer los segmentos que se activaran en la salida para cada cada numero presente en la entrada, esto es básicamente un circuito combinatorio.  La siguiente tabla nos muestra esta relación de entrada a salida, el numero decimal a mostrar ingresa en su equivalencia binario a las 4 entradas, siendo e3 el bit mas significativo y e0 el de menor peso, entonces la salida deberá activar los LED's o segmentos necesarios para forman el símbolo decimal.

Fig5. Decodificación para pantalla tipo CC
 

En la tabla inferior podrá observar los valores de salida para cada numero binario, considerando ambos tipos de pantalla: Cátodo Común y Ánodo Común.

Fig5. Tabla de salida para pantallas CC y AC

Describiremos de manera funcional un modulo verilog con el nombre bcdtoseg, asumiendo que se utilizara una pantalla del tipo CC. para lo cual utilizamos el editor de texto de los programas de simulación citados previamente.  a continuación se detalla el código del modulo respectivo con sus comentarios.

module bcdtoseg(en, d0,d1,d2,d3, a,b,c,d,e,f,g);
input en; //Habilitador de salida
input d0,d1,d2,d3;  //Entradas de numero binario
output a,b,c,d,e,f,g;//Salidas para los segmentos
wire [3:0] bcd;        //Bus para los datos de entrada
reg [6:0] seg;          //Registro para guardar valor de segmentos
assign bcd = {d3,d2,d1,d0}; //Asignación del numero binario al bus bcd
assign {g,f,e,d,c,b,a} = seg;  //Asignación del registro seg a cada segmento
always @ (en, bcd)              //Lista de eventos
if(en) //Solo si en esta activo
   case(bcd) //Salida gfedcba segun numero bcd
     4'b0000: seg = 7'b0111111; //numero 0
     4'b0001: seg = 7'b0000110; //numero 1
     4'b0010: seg = 7'b1011011; //numero 2
     4'b0011: seg = 7'b1001111; //numero 3
     4'b0100: seg = 7'b1100110; //numero 4
     4'b0101: seg = 7'b1101101; //numero 5
     4'b0110: seg = 7'b1111100; //numero 6
     4'b0111: seg = 7'b0000111; //numero 7
     4'b1000: seg = 7'b1111111; //numero 8
     4'b1001: seg = 7'b1100111; //numero 9
      default: seg = 7'b0000000; //Apaga todos los segmentos
  endcase
endmodule

En caso de utilizar una pantalla del tipo AC, bastaría solo invertir la asignación del registro seg a cada segmento, esto seria así: assign {g,f,e,d,c,b,a} = ~seg; 

Otra manera mas simplificada de describir este decodificador, seria utilizar directamente una bus de entrada para el numero y un bus de salida para los segmentos, tal como ser observa en el siguiente esquema.

Fig6. Decodificador con bus e/s

Entonces considerando el uso de un bus para la entrada y salida, los cambios a nuestro modulo descriptivo quedaran de la siguiente manera.

module bcdtoseg(en, bcd, seg);
input en; //Habilitador de salida
input [3:0] bcd;         //Bus de entrada para el numero binario
output reg [6:0] seg;//Bus de salida para registro de segmentos
always @ (en, bcd) //Lista de eventos
if(en) //Solo si en esta activo
   case(bcd) //Salida gfedcba segun numero bcd
     4'b0000: seg = 7'b0111111; //numero 0
     4'b0001: seg = 7'b0000110; //numero 1
     4'b0010: seg = 7'b1011011; //numero 2
     4'b0011: seg = 7'b1001111; //numero 3
     4'b0100: seg = 7'b1100110; //numero 4
     4'b0101: seg = 7'b1101101; //numero 5
     4'b0110: seg = 7'b1111100; //numero 6
     4'b0111: seg = 7'b0000111; //numero 7
     4'b1000: seg = 7'b1111111; //numero 8
     4'b1001: seg = 7'b1100111; //numero 9
      default: seg = 7'b0000000; //Apaga todos los segmentos
  endcase
endmodule

Prueba de funcionamiento

Para ensayar el funcionamiento de nuestro decodificador, crearemos un modulo de estimulo con la que llevaremos a cabo una simulación. Este modulo llamara mediante una instancia al modulo bcdtoseg, para simplificar un poco consideraremos el decodificador que utiliza un bus para entrada y salida.

 El modulo de estimulo tendrá la siguiente codificación:

module bcdtoseg_tb; //Nombre del modulo de estimulo
reg en; //Registro para estimular la entrada EN
reg [3:0] bcd;//Registro para estimular entrada bcd
wire [6:0] seg; //Bus de salida que muestra los segmentos
bcdtoseg ins0(en,bcd,seg); //crea instancia del modulo bcdtoseg
    initial begin
        #5 en=1;bcd=0; //Habilita e inicia el numero bcd a 0
        #5 bcd=1; //numero bcd a 1
        #5 bcd=2; //numero bcd a 2
        #5 bcd=3;
        #5 bcd=4;
        #5 bcd=5;
        #5 bcd=6;
        #5 bcd=7;
        #5 bcd=8;
        #5 bcd=9; //numero bcd a 9
    end
endmodule

Para efectuar la simulación, utilizare el software ModelSim, donde posterior a la compilación de ambos módulos bcdtoseg y bcdtoseg_tb, se procede a iniciar la simulación adicionando las entradas y salidas que se representaran en un diagrama de tiempo, que nos mostrara el siguiente resultado.

Fig7. Diagrama de tiempos para simulación del decodificador

Este resultado no muestra que el decodificador funciona correctamente, y por lo tanto estará listo para su implementación.

Implementacion del circuito

Ahora como paso final veremos como implementar el decodificador que hemos creado en una FPGA, en mi caso utilizare la placa TangNANO y el software de diseño Gowin EDA, opcionalmente aquí te dejo un pequeño enlace introductorio que nos muestra como crear e implementar un proyecto con esta FPGA.   

<<Introducción a FPGA TangNANO>>

Esta es la lista de los elementos utilizados:

  • Placa FPGA TangNANO y cable USB-C
  • Un HS-3191B, pantalla 7 segmentos tipo AC de 0.39 pulgadas.
  • Una resistencia limitadora, lo recomendable es una por salida.
  • Cuatro pulsadores para establecer los valores en la entrada
  • Protoboard y cables de conexión. 

Con referencia a la hoja de datos de  la placa TangNANO y la pantalla HS-3191B llevo a cabo las siguientes conexiones:

Fig8. Esquema de conexión al FPGA

Debemos tomar en cuenta los siguientes detalles con relación a los pulsadores, ya que esta configuración requiere que las entradas en la FPGA estén con resistencias PULL-DOWN y así mismo el modulo decodificador deberá ajustarse para una pantalla del tipo Ánodo Común.



Fig9. Circuito decodificador en TangNANO

Como resumen de todo lo descrito en la sección, te dejo un vídeo donde se observa la creación e implementación del proyecto con el software GoWin EDA.

 
Haz click <<aquí>> para descargar la carpeta del proyecto

Para finalizar solo quiero agradecer tu visita a mi blog, espero que el contenido de esta entrada hubiera sido de ayuda en tu formación educativa, favor cualquier consulta al respecto pueden escribirme a:

pablinzte@gmail.com / pablinza@me.com

Pablo Cesar Zárate.