Máquina de Estados

Máquina de Estados

Uno de los aspectos más destacados y frecuentes en los diseños Verilog, es la realización de máquinas de estados. En esta sección, se propone un método para la estructuración de una máquina de estados, empleando tres procesos.

  • Asignación asíncrona del siguiente estado, partiendo de de las entradas al diseño y del estado en el que se encuentre.
  • Asignación síncrona, donde el flanco de reloj hace que el estado actual sea el que se ha estado preparando.
  • Asignación de las salidas.
maquinas de estado

Máquina de Estados

A continuación en el siguiente ejemplo se modela un semáforo en Verilog, mediante una máquina de estados:

module semaforo (clk, rst, color);
 input clk;
 input rst;
 output [1:0] color;

 reg [1:0] state, nextState;
 reg [8:0] cnt;

 // Asignación asíncrona del siguiente estado
 always @(state, cnt)
  case(state)
   0: // Color Rojo
    if (cnt == 100) nextState = 1;
    else nextState = 0;
   1: // Color Ambar
    if (cnt == 120) nextState = 2;
    else nextState = 1;
   2: // Color Verde
    if (cnt == 200) nextState = 0;
    else nextState = 2;
   default: nextState = 0;
  endcase

 // Asignación síncrona: Actualización del estado
 always @(posedge clk or negedge rst)
  if(rst == 0) state = 0;
  else state = nextState;

 // Asignación de las salidas
 always @(state)
  if(state == 0) color = 2'b00; // Color Rojo
  else if(state == 1) color = 2'b01; // Color Ámbar
  else color = 2'b10; // Color Verde

 // Contador
 always @(posedge clk or negedge rst)
  if(rst == 0) cnt = 0;
  else cnt = cnt + 1;
endmodule

En este ejemplo direccionamos una señal de reloj para prender automáticamente tres LEDs de diferentes colores (verde, ámbar, rojo) asignando un contador que dure determinado tiempo para prender cada uno de los LEDs.

Práctica de Contador Ascendente

Con displays de 7 Segmentos

Práctica Contador:

Esta práctica consiste en crear un contador ascendente de un segundo (1 Hz) utilizando una señal de reloj para hacer el cambio de estados (clk) y mostrándolo en los diplays de 7 segmentos.

La programación se muestra a continuación:

module Contador (clock_50mhz, clock_1hz, segmentos, comun,estado);

 input clock_50mhz; //entrada de oscilación del cristal externo
 output reg clock_1hz; //clock 1 segundo

 output reg [6:0] segmentos = 7'h3F; //apagar segmentos
 output reg comun = 0; //encender display1
 output reg [3:0] estado = 0; //estado inicial para conectar 2 LEDs, 00, 01, 10, 11, 00 y se repite

 reg [25:0] cuenta_para_1hz = 0; //inicialización de la variable que servirá para generar la salida de 1hz

  parameter [6:0] cero   = ~7'h3F;
  parameter [6:0] uno    = ~7'h06;
  parameter [6:0] dos    = ~7'h5B;
  parameter [6:0] tres   = ~7'h4F;
  parameter [6:0] cuatro = ~7'h66;
  parameter [6:0] cinco  = ~7'h6D;
  parameter [6:0] seis   = ~7'h7D;
  parameter [6:0] siete  = ~7'h07;
  parameter [6:0] ocho   = ~7'h7F;
  parameter [6:0] nueve  = ~7'h6F;
  parameter [6:0] ha     = ~7'h77;
  parameter [6:0] hb     = ~7'h7C;
  parameter [6:0] hc     = ~7'h39;
  parameter [6:0] hd     = ~7'h5E;
  parameter [6:0] he     = ~7'h79;
  parameter [6:0] hf     = ~7'h71; 

 always @(posedge clock_50mhz)
  begin
    cuenta_para_1hz = cuenta_para_1hz + 1;
     if(cuenta_para_1hz == 25_000_000)
     begin
       clock_1hz = ~clock_1hz; //genera la señal de oscilación, esta señal empezó en 0, valor inicial
       cuenta_para_1hz = 0; // reset a el contador
     end
  end

 always @(posedge clock_1hz)
  begin
    case(estado)
      0: estado <= 1;
      1: estado <= 2;
      2: estado <= 3;
      3: estado <= 4;
      4: estado <= 5;
      5: estado <= 6;
      6: estado <= 7;
      7: estado <= 8;
      8: estado <= 9;
      9: estado <= 10;
     10: estado <= 11;
     11: estado <= 12;
     12: estado <= 13;
     13: estado <= 14;
     14: estado <= 15;
     15: estado <= 0;
    endcase
  end

 always @(estado)
  begin
    case(estado)
      0: segmentos = cero;
      1: segmentos = uno;
      2: segmentos = dos;
      3: segmentos = tres;
      4: segmentos = cuatro;
      5: segmentos = cinco;
      6: segmentos = seis;
      7: segmentos = siete;
      8: segmentos = ocho;
      9: segmentos = nueve;
     10: segmentos = ha;
     11: segmentos = hb;
     12: segmentos = hc;
     13: segmentos = hd;
     14: segmentos = he;
     15: segmentos = hf;
    endcase
  end
endmodule

Una vez compilado nuestro programa procedemos a declarar nuestros pines de salida a cualquier display de 7 segmentos de nuestro FPGA, como lo muestra la siguiente imagen:

vv

Asignación de Pines a un Display de 7 Segmentos

uu

Clk

Señal de Reloj (Clk)

PIN_17

Ya asignados los pines de salida y el Clk de nuestro FPGA, compilaremos y cargaremos nuestro programa con el programador USB Blaster, si siguieron correctamente los pasos anteriores se demostrará en físico un contador ascendente del 0 al 9 con una señal de reloj de un segundo (1 Hz).

Maquina de Estados

Imagen Representativa

 

Contadores y Clocks

Diseño de Contadores y Clocks

Clk

Clock

El diseño de contadores y clocks (señales de reloj) regulan la lógica de las señales para que los sistemas secuenciales puedan correr a una velocidad óptima.

Para la generación de estímulos se utilizan los procesos initial y always. La elección de éstos viene determinada por las características de las señales a generar. Dependiendo de la naturaleza de la señal, éstas se pueden generar de forma síncrona o asíncrona.

La generación asíncrona se basa en el uso de retardos para activar y desactivar señales, mientras que la generación síncrona se basa en el uso de eventos, disparados por flancos para activar y desactivar señales. En este caso todas las señales que se activen de forma síncrona se harán con un retardo.

Señal de Reset Síncrona

initial
  begin
    rst = 1'b0;
    repeat(2)
      @(posedge clk) #1;
    rst = 1'b1;
      @(posedge clk) #1;
    rst = 1'b0;
  end
Diagrama Clock FPGA

Diagrama Clock FPGA

Fuentes de Oscilación  (Clocks)

Clock Multiplicación / Divición

Clock Multiplicación / Divición

Fuente de Oscilación (Hz)

Fuente de Oscilación (Hz)

Fuente de oscilación del FPGA

Fuente de oscilación del FPGA

Pin_17

En verilog podemos sintetizar relojes mediante contadores síncronos.

Diseño de un Oscilador de 1Hz.

Practica Clocks:

Esta practica consiste en generar un oscilador entre estados altos y bajos a 1Hz en un LED. El diseño de este oscilador se muestra en el siguiente diagrama:

Diseño de un Oscilador de 1Hz

Diseño de un Oscilador de 1Hz

  • C_50Mhz: Entrada externa de oscilación.
  • C_1Hz: Oscilación de salida.
  • [24:0] Cuenta -Variable del divisor.

Los periodos que tendrá una señal a una frecuencia de 50 Mhz en 1 segundo son 50,000,000 en 0.5 segundos son 25,000,000 a 0.001 segundos son 50,000. De esta manera se hace el divisor de frecuencia.

Código en Verilog

module Cloks (C_50Mhz,C_1Hz);
 input C_50Mhz;         //Clock de entrada del FPGA de entrada (Pin 17).
 output reg C_1Hz = 1;  //Señal de salida (<em>Se debe asignar un estado lógico</em>).

 reg[24:0] contador = 0; //Variable Contador equivale a 25 millones de estados. 

 always @(posedge C_50Mhz)
  begin
   contador = contador + 1; //0.5 segundos LED encendido
   if(contador == 25_000_000)
    begin
      contador = 0;
      C_1Hz = ~C_1Hz; //0.5 segundos LED apagado
    end
  end
endmodule

Se debe de asignar un estado lógico inicial a la salida C_1Hz ya que de esta manera  asignamos el estado de el led al poner nosotros “1” declaramos que el LED inicializara encendido, o viveversa si declaramos un “0”, de cualquiera de las dos formas es aseptable.

El bloque always que presente un posedge, únicamente se «ejecutara» cuando ocurra el flanco positivo.Si presenta un negedge, únicamente se «ejecutara» cuando ocurra el flanco negativo.

negedge

Negedge

posedge

Posedge

Cuando un bloque always es usado para sintetizar lógica secuencial, no se recomienda mezclar con otro tipo de flancos o entradas.

Descargar el código a la FPGA, asignar la señal C_50Mhz a la entrada PIN_17 y la salida C_1Hz a un led (cualquiera).

Asinacion de Pines S3A2

Asignación de Pines

Probaremos nuestro programa en físico mostrando la oscilación en un LED en estados altos y bajos a 1 Hz de frecuencia.

Imagen Representativa On

Imagen Representativa On

Imagen Representativa Off

Imagen Representativa Off

 

 

Estructura Case

Estructura Case

La sentencia case evalúa una expresión y en función de su valor ejecutará la sentencia o grupo de sentencias agrupadas en el primer caso que coincida. Si existen varias sentencias se deben agrupar en un bloque begin-end. Si no se cubren todos los posibles valores se debe hacer uso del caso por defecto, denominado default, el cual se ejecutará cuando ninguno de los casos anteriores se cumplan. La sintaxis de esta estructura es la siguiente:

case (expresion)
 caso 1:
  begin
   Sentencias 1;
  end
 caso 2:
  begin
   Sentencias 2;
  end
 .....
 default:
  begin
   Sentencias D;
  end
endcase

Consideraciones

  • Esta estructura permite clasificar las acciones que se realizaran a partir de una variable digital.
  • Toda estructura Case deberá de estar contenida en un bloque always @ (Array).
  • Begin y end solo son necesarios en caso de realizar mas de una instrucción.
  • Todas las combinatorias de las entradas deberán ser evaluadas en el bloque case.

Ejemplo:

En este ejemplo se explicara el funcionamiento de la estructura case (casos).

Teniendo en cuenta 4 entradas y asignándole a una salida el valor de una de las entradas dependiendo la elección entre los cases en binario.

zz

Ejemplo S2L1

Código en Verilog:

module casos (A,B,C,D,S,Y);

     input A, B, C, D;
     input [1:0] S;
     output reg Y;

always @ (A, B, C, D, S)
    begin
        case (S)
            0: Y = A;
            1: Y = B;
            2: Y = C;
            3: Y = D;
        endcase
    end
end module

“Esta es la forma de declarar una variable con un tamaño superior a un bit:”

   input [1:0] S;

En este ejemplo tenemos dos interruptores S0 y S1 dependiendo el valor en binario que estos dos formen (00b = 0, 01b = 1, 10b = 2, 11b = 3) asignara a la salida Y el valor de la entrada correspondiente a la misma (10b = 2 = C).

Practica Decodificador de BCD a 7 Segmentos

Con Interruptores

Practica DecoderBS

Xx

Decodificador BCD a 7 Segmentos

Desarrollaremos una aplicación en Verilog que permita hacer una decodificación de BCD a 7 segmentos. Utilizaremos 4 Switches, ya que sus estados son del 0 al 15 (4 bits = 16 estados) cada estado en binario asignará a la salida que enciendan diferentes LEDs dentro del 7 Segmentos asciendo un decodificador BCD a Decimal.

Código en Verilog con Compuertas Lógicas:

module DecoderBS (A,B,C,D,a,b,c,d,e,f,g,com,test);
 input A; //43
 input B; //48
 input C; //40
 input D; //45

 output a; //93
 output b; //92
 output c; //87
 output d; //86
 output e; //55
 output f; //58
 output g; //79
 output com; //94
 output test;

 assign a = !( (~B & ~D) | (~A & C) | (~A & B & D) | (B & C) | (A & ~D) | (A & ~B & ~C));
 assign b = !( (A & ~C & D) | (~B) | (~A & ~C & ~D) | (~A & C & D));
 assign c = !( (~C & D) | (~A & B) | (A & ~B) | (~A & ~C) | (~A & D));
 assign d = !( (B & ~C & D) | (~B & C & D) | (B & C & ~D) | (A & ~C & ~D) | (~A & ~B & ~D));
 assign e = !( (~B & ~D) | (C & ~D) | (A & C) | (A & B));
 assign f = !( (~C & ~D) | (B & ~D) | (~A & B & ~C) | (A & ~B) | (A & C));
 assign g = !( (~A & C) | (~A & B) | (B & D) | (C & ~D) | (A & ~B & ~C));
 assign com = 0;
 assign test = 0;
endmodule

Código Verilog con Case

module DecoderBS (Z, SEG, com);
 input [3:0] Z;
 output com;
 output reg [6:0] SEG;

 parameter [6:0] cero   = 7'b0000001;
 parameter [6:0] uno    = 7'b1001111;
 parameter [6:0] dos    = 7'b0010010;
 parameter [6:0] tres   = 7'b0000110;
 parameter [6:0] cuatro = 7'b1001100;
 parameter [6:0] cinco  = 7'b0100100;
 parameter [6:0] seis   = 7'b0100000;
 parameter [6:0] siete  = 7'b0001111;
 parameter [6:0] ocho   = 7'b0000000;
 parameter [6:0] nueve  = 7'b0000100;
 parameter [6:0] A      = 7'b0001000;
 parameter [6:0] B      = 7'b1100000;
 parameter [6:0] C      = 7'b0110001;
 parameter [6:0] D      = 7'b1000010;
 parameter [6:0] E      = 7'b0110000;
 parameter [6:0] F      = 7'b0111000;
 parameter [6:0] guion  = 7'b1111110;

always @ (Z)
 begin
  case(Z)
    15: SEG = cero;
    14: SEG = uno;
    13: SEG = dos;
    12: SEG = tres;
    11: SEG = cuatro;
    10: SEG = cinco;
     9: SEG = seis;
     8: SEG = siete;
     7: SEG = ocho;
     6: SEG = nueve;
     5: SEG = A;
     4: SEG = B;
     3: SEG = C;
     2: SEG = D;
     1: SEG = E;
     0: SEG = F;
     default: SEG = guion;
  endcase
 end
 assign com = 0;
endmodule

 Después de escribir el código lo compilaremos y nos aseguramos de haber cumplido los pasos de los anteriores tutoriales, lo siguiente será asignar los pines de entrada y salida de nuestro FPGA.

vv

LEDs y Comunes del los 7 Segmentos

Nota: Los Display de 7 segmentos del FPGA se activan con Pull-Down.

uu

 

ll

Asignación de Pines

Ya asignados los pines de entrada y salida compilaremos nuestro proyecto e instalaremos el dispositivo “USB Blaster” para hacer la interconección y programar el FPGA, seleccionamos el archivo .sof  del proyecto y daremos “Start”.

Nota: “Si es la primera vez que usas Quartus II y USB Blaster, es explicado más a detalle en el tutorial anterior”.

Probaremos nuestro programa en físico con los display de 7 segmentos como salida en codificación decimal y los switches como entrada en codificación binaria.

FPGA

Imagen Representativa (b1000 = 8)

 

Introducción a Verilog

Introducción a Verilog

Descripción de Software

Introducción a Verilog es un lenguaje de descripción de hardware (HDL), es ideal para la programación sencilla de FPGA’s Altera, este lenguaje soporta el diseño, prueba e implementación de circuitos analógicos, digitales y de señal mixta a diferentes niveles de abstracción.

Los diseñadores de Verilog querían un lenguaje con una sintaxis similar a la del lenguaje de programación C, de tal manera que le resultara familiar a los ingenieros y así fuera rápidamente aceptada. El lenguaje tiene un preprocesador como C, y la mayoría de palabras reservadas de control, como “if”, “while”, “for” etc, son similares. El mecanismo de formateo en las rutinas de impresión y en los operadores del lenguaje (y su precedencia) son también similares.

A diferencia del lenguaje C, Verilog usa Begin/End en lugar de llaves para definir un bloque de código. Por otro lado la definición de constantes en Verilog requiere la longitud de bits con su base. Verilog no tiene estructuras, apuntadores o funciones recursivas. Finalmente el “concepto de tiempo”, muy importante en un HDL, no se encuentra en C.

Estructura Básica

En este tutorial se explicara las características de lenguaje Verilog y hacer funcionar un ejemplo sencillo con un FPGA.

Como vimos en el tutorial anterior se necesita crear un proyecto nuevo, antes de escribir nuestro programa en lenguaje Verilog HDL.

1

ALTERA, FPGA, Cyclone II, EP2C5T144C8

Este FPGA Altera lo puedes encontrar en nuestra pagina oficial https://hetpro-store.com/tarjetas-es/desarrollo/altera-es/tarjeta-fpga-altera-ep2c5t114c8n-con-blaster.html

Ejemplo S1L1

** Este ejemplo fue creado en el tutorial anterior para ver los pasos de inicialización seguir el siguiente enlace **

https://hetpro-store.com/TUTORIALES/como-instalar-quartus-ii-y-crear-un-proyecto-nuevo/

Esta practica consiste en hacer todas las compuertas lógicas básicas en programación Verilog y mostrarlas en físico con el FPGA utilizando Switches y LEDs.

A continuación escribiremos el siguiente programa:

module S1L1
 (
 input A,
 input B,

 output C,
 output D,
 output E,
 output F,
 output G,
 output H,
 );

 assign C = A | B;
 assign D = A & B;
 assign E = A ^ B;
 assign F = A ~^ B;
 assign G = A;
 assign H = !B;
endmodule

Características del Programa

  • Module: El modulo es una unidad de jerarquía, puede ser un módulo fundamental o puede ser una coleccion de elementos, “Tiene que tener el nombre del proyecto”.
  • Input/Output: Declaramos entradas y salidas del modulo dentro de paréntesis.
  • Assign: Describimos su funcionamiento (|=OR, &=AND, ^=XOR, ~^=XNOR, != Negación)

Para compilar el código solo damos click en “Start Compilation” o “Ctl+L”.

A

Compilar

Asignación de pines del FPGA

Si la compilación fue exitosa y la ventana de mensajes no arrojo ningún error se procederá a asignar los pines de entrada y salida de nuestro FPGA,

b

Asignación de Pines

c

Pines del FPGA

De acuerdo con la siguiente gráfica de Switches y LEDs se declaran los pines de acuerdo a su número, de la siguiente manera:

e

Switch

f

Led´s

d

Declaración de Pines

Una vez declarados los pines de entrada y salida, se tiene que compilar nuevamente para asegurar que se declararon correctamente, procedemos a cargar nuestro programa al FPGA por el puerto JTAG con el USB Blaster.

Daremos click en “Tools” y “Programmer”:

h

Programador

Nos arrojara una ventana donde eligiéremos nuestro programador “USB Blaster” Dando click en “Hardware Setup”:

i

Nota: Si no tiene instalado “USB Blaster” en su PC seguir los siguientes pasos, una vez instalado omitir.

Instalar Blaster

Para instalar el programado USB Blaster en su computador siga las siguientes instrucciones:

  • Conecte el USB blaster a su computador y en su FPGA, entre el puerto USB y el puerto JTAG Respectivamente.
  • Precione la tecla “Window” y la tecla Pause/Inter o Breack a la vez.

j

  • Dar click en “Administrador de Dispositivos” e instalar el Driver seleccionado en la ruta C:\altera\13.0sp1\quartus\drivers\usb-blaster en  “Dispositivo Desconocido”.

k

* Una vez instalado el USB Blaster lo seleccionamos en “Hardware Setup” y lo agregamos.

l

Damos click en Add File y agregamos el archivo .sof de nuestro programa como lo muestra la siguiente imagen.

.sof  SRAM ObjectFile.
– Modo de programación JTAG (JointTest ActionGroup).

m

n

Una vez cargado y verificando que el archivo .sof se haya cargado y que los pasos anteriores se producieron correctamente damos click en “START” para hacer la comunicación TDI y TDO (Entrada y Salida) y probamos físicamente nuestro programa.

Como Instalar Quartus II y Crear un Proyecto Nuevo

Introducción

En este tutorial se explicara como instalar el programador de FPGA’s y CPLD’s de la familia Altera “Quartus II”.

Los productos de Altera los puedes encontrar en nuestra pagina oficial  https://hetpro-store.com/tarjetas-es/desarrollo/altera-es/

1

Este es un software diseñado por Altera para el análisis y la síntesis de diseños realizados en HDL (Lenguaje de descripción de Hardware).

Quartus II permite al desarrollador o desarrolladora compilar sus diseños, realizar análisis temporales, examinar diagramas RTL y configurar el dispositivo de destino con el programador.

La familia de FPGAs de bajo coste Cyclone, está soportada por esta edición, por lo que los pequeños desarrolladores y desarrolladoras no tendrán problemas por el coste del software.

Instalación

Esta edición permite la compilación y la programación de un número limitado de dispositivos Altera.

Para instalar este software es necesario descargarlo de la siguiente página web:

http://www.altera.com/products/software/quartus-ii/web-edition/qts-we-index.html

Donde aparecerá la siguiente indicación de descarga del software:

2

Descarga del Software

Daremos click en “Download Software Web Edition – Free” para descargar la versión gratuita del software Quartus II  (Esta versión puede ser renovada ilimitadamente sin coste).

3

Ejecutar el Archivo Setup

Una vez descargado el software daremos click a ejecutar el archivo Setup donde iniciara el siguiente programa:

4

Se procede a aceptar la licencia de uso de Software:

5

Después se debe elegir donde se guardaran los documentos en el disco duro:

6

Lo siguiente será asegurarse de instalar el software completo:

7

Después aparecerá donde se guardara el programa y los requisitos que debe tener su PC para la instalación:

8

Listo, al dar siguiente el programa comenzara a instalarse en su PC:

Nota: El programa demorara varios minutos dependiendo la velocidad de su PC debido a que este programa maneja mucha información y es pesado en bits.

9

10

Al finalizar la instalación hay que marcar los iconos que aparecen:

  • Crear un acceso directo en el escritorio (Opcional)
  • Iniciar Quartus II a 64Bits
  • Proporcionar una Retroalimentación

11

Crear un Nuevo Proyecto

Ya instalado el programa Quartus II procedemos a crear un proyecto nuevo para controlar un FPGA  Altera.

Abrir el programa en el escritorio o en la barra de inicio arrojara la siguiente pantalla:

1

Una vez que abierto el programa daremos click en Create a New Project:

2

Se recomienda crear una carpeta de trabajo específica, dentro de la carpeta principal donde se instaló Quartus. Como un ejemplo en este caso el proyecto se llamara S1L1 en una carpeta especifica llamada EJEMPLOS:

3

4

Se debe elegir el FPGA con el cual se desea trabajar, la familia y el número de parte del FPGA (Estas especificaciones vienen grabadas en el FPGA).

5  7

Para finalizar el programa, proporcionara las especificaciones introducidas anteriormente:

8

De esta manera se ha creado un proyecto nuevo llamado “S1L1” en la carpeta “EJEMPLOS” en Altera.

9

Procederemos a crear  la ventana de programación para lenguaje Verilog HDL.

Para esto daremos click en la pestaña superior izquierda de su monitor  “File”, “New” y elegir “Verilog HDL File”, como lo muestra la siguiente imagen.

10 11

Nota: Antes de empezar a programar es importante guardar el archivo en la misma carpeta donde se guardó el proyecto:

12 13

Arquitectura del Software

Ejemplo:

14

Navegador del Proyecto

14-1

Ventana de Código

14-2

Ventana de Mensajes

14-3