[verilog n00b] Maquinas de estado

490 views
Skip to first unread message

Carlos

unread,
Sep 30, 2016, 5:10:31 AM9/30/16
to FPGA-WARS: explorando el lado libre
Que tal, ¿como están?

Estuve tratando de implementar una maquina de estados de lo más simple. Cuenta con 4 estados (estado0, estado1, estado2, estado3), cada flanco de subida del reloj (clk_pres que es el clock que sale del prescaler) pasa al estado siguiente (Y), o al menos es lo que pretendo que haga xD.
Dependiendo de cada estado se prenderán y apagaran los LEDs de la iCEStick, si el estado presente (y) es estado0 todos los LEDs deben estar apagados, en el estado1 el led1 se prende y los demás se apagan, etc.
Este es el código del modulo principal:

module stateMachine (clk,led0,led1,led2);

input clk;
output reg led0, led1, led2;

// Parametro para el prescaler
parameter N = 22;

// Reloj de salida del prescaler
wire clk_pres;

// Instancia del prescaler de N bits
prescaler #(.N(N))
    pres1 (
        .clk_in(clk),
        .clk_out(clk_pres)
    );

// registros de 3 bits que almacenan el estado actual y estado siguiente
reg [2:0] y, Y;

// Estados, codecs implementados con one-hot
parameter estado0 = 3'b000,
            estado1 = 3'b001,
            estado2 = 3'b010,
            estado3 = 3'b100;

// Secuencia de estados
always @(y) begin
    case(y)
        estado0: Y <= estado1;
        estado1: Y <= estado2;
        estado2: Y <= estado3;
        estado3: Y <= estado0;
        default: Y <= 3'bxxx;
    endcase
end

// Cambio de estado actual a siguiente estado
always @(posedge clk_pres) begin
    y <= Y;
end

// Salidas dependientes del estado presente
always @(y) begin
    {led2, led1, led0} <= y;
end

endmodule


Este es mi test bench, solo simulo el clk, ya que no tengo entradas en la maquina de estados (aca N = 2 para obtener más fácil el clk_pres):

`timescale 1ns/1ns

module stateMachine_tb;

parameter N = 2;

reg clk = 0;
wire led0, led1, led2;

//-- Instanciar el prescaler de N bits
stateMachine #(.N(N))
stateMachine_DUT
(
    .clk(clk),
    .led0(led0),
    .led1(led1),
    .led2(led2)
);

always #1 clk = ~clk;

//-- Proceso al inicio
initial begin

  //-- Fichero donde almacenar los resultados
  $dumpfile("stateMachine_tb.vcd");
  $dumpvars(0, stateMachine_tb);

  # 99 $display("FIN de la simulacion");
  # 100 $finish;

end
endmodule


Y la salida: El problema es que como se ve no cambia de estado, estuve buscando en varios libros y viendo vídeos y no doy con el error :/. En el GTKWave aparecen los dos módulos, el stateMachine y prescaler, esta es la imagen del stateMachine, que es el "principal".


¿Alguna sugerencia?, seguro se me paso algo re obvio pero no lo puedo ver.

Dejo adjunto el proyecto, solo hay que hacer make all para obtener la simulación (gracias por el makefile Obijuan, lo tome de los tutos :D).

Saludos
-C
stateMachine.zip

Carlos

unread,
Sep 30, 2016, 3:46:37 PM9/30/16
to FPGA-WARS: explorando el lado libre


Que tal, al parecer se solucionó:



Me faltaban varias cosas, por ejemplo los localparam no tenían especificado el vector de 3 bits, y el estado y lo inicialice a 3'b000, después de eso funcionó, supongo que esto lo debí de haber tenido en cuenta en el caso default del case, no he visto que inicialicen los estados en libros/videos, me falta grabarlo en la iCEStick y comprobar que funciona como debería.

Así quedo el stateMachine.v (los otros archivos fuente quedaron igual):

module stateMachine (clk,led0,led1,led2);

input wire clk;

output reg led0, led1, led2;

// Parametro para el prescaler
parameter N = 22;

// Reloj de salida del prescaler
wire clk_pres;

// Instancia del prescaler de N bits
prescaler #(.N(N))
    pres1 (
        .clk_in(clk),
        .clk_out(clk_pres)
    );

// registros de 3 bits que almacenan el estado actual y estado siguiente
reg [2:0] y = 3'b000, Y;


// Estados, codecs implementados con one-hot
localparam [2:0] estado0 = 3'b000,

                estado1 = 3'b001,
                estado2 = 3'b010,
                estado3 = 3'b100;

// Secuencia de estados
always @(y)
begin
    case(y)
        estado0: Y <= estado1;
        estado1: Y <= estado2;
        estado2: Y <= estado3;
        estado3: Y <= estado0;
        default: Y <= 3'bxxx;
    endcase
   
    {led2, led1, led0} = y;
end

// Cambio de estado actual a siguiente estado
always @(posedge clk_pres)
begin
    y <= Y;
end

endmodule

Dejo adjunto los archivos fuente, solo falta hacer make en el directorio para obtener el bin. Bienvenido cualquier feedback :D, queda implementar la maquina de estados con entradas y m'as compleja, esta solo tiene 4 estados y no depende de ninguna entrada.

Saludos
-C
stateMachine.zip

Juan Gonzalez Gomez

unread,
Oct 1, 2016, 4:49:57 AM10/1/16
to FPGA-WARS: explorando el lado libre
Hola Carlos!

No me dió tiempo a responderte. Efectivamente, en simulación los registros tiene por defecto el valor x (desconocido). Es necesario inicializarlos, bien haciendo un reset o bien dándole en el código el valor inicial.

En el circuito combinacional de cambio de estado, always @(y), las asignaciones tiene que ser bloqueantes, porque quieres que se asignen inmediatamente. Como regla general, en circuitos combinaciones usas asignaciones con el símbolo =, y en los circuitos secuenciales <=

Así, debería quedar:

case(y)
        estado0: Y = estado1;
        estado1: Y = estado2;
        estado2: Y = estado3;
        estado3: Y = estado0;
        default: Y = 3'bxxx;
    endcase



Saludos, Obijuan

--
Has recibido este mensaje porque estás suscrito al grupo "FPGA-WARS: explorando el lado libre" de Grupos de Google.
Para anular la suscripción a este grupo y dejar de recibir sus mensajes, envía un correo electrónico a fpga-wars-explorando-el-lado-libre+unsubscribe@googlegroups.com.
Para publicar en este grupo, envía un correo electrónico a fpga-wars-explorando-el-lado-li...@googlegroups.com.
Visita este grupo en https://groups.google.com/group/fpga-wars-explorando-el-lado-libre.
Para ver esta conversación en el sitio web, visita https://groups.google.com/d/msgid/fpga-wars-explorando-el-lado-libre/8a685a3d-deef-4806-afbe-32aa975f7ced%40googlegroups.com.

Para acceder a más opciones, visita https://groups.google.com/d/optout.

Carlos 47

unread,
Oct 2, 2016, 4:43:53 AM10/2/16
to fpga-wars-explora...@googlegroups.com
Hola Obijuan,
Gracias por las correcciones, hice los cambios y funcionan :D, también me di cuenta que en tu tutorial tocas el tema de maquinas de estado pero con otro nombre.
Otra duda no tan relacionada a las maquinas de estado, las iCE40 tienen bloques de RAM, sabes si se pueden usar estos bloques y almacenar información en tiempo de ejecución? o toca implementar memorias con verilog?

Saludos
-C

El 1 de octubre de 2016, 03:49, Juan Gonzalez Gomez<obijua...@gmail.com> escribió:
Hola Carlos!

No me dió tiempo a responderte. Efectivamente, en simulación los registros tiene por defecto el valor x (desconocido). Es necesario inicializarlos, bien haciendo un reset o bien dándole en el código el valor inicial.

En el circuito combinacional de cambio de estado, always @(y), las asignaciones tiene que ser bloqueantes, porque quieres que se asignen inmediatamente. Como regla general, en circuitos combinaciones usas asignaciones con el símbolo =, y en los circuitos secuenciales <=

Así, debería quedar:

case(y)
        estado0: Y = estado1;
        estado1: Y = estado2;
        estado2: Y = estado3;
        estado3: Y = estado0;
        default: Y = 3'bxxx;
    endcase



Saludos, Obijuan
Para publicar en este grupo, envía un correo electrónico a fpga-wars-explorando-el-lado-lib...@googlegroups.com.

--
Has recibido este mensaje porque estás suscrito al grupo "FPGA-WARS: explorando el lado libre" de Grupos de Google.
Para anular la suscripción a este grupo y dejar de recibir sus mensajes, envía un correo electrónico a fpga-wars-explorando-el-lado-libre+unsubscribe@googlegroups.com.
Para publicar en este grupo, envía un correo electrónico a fpga-wars-explorando-el-lado-li...@googlegroups.com.
Visita este grupo en https://groups.google.com/group/fpga-wars-explorando-el-lado-libre.

Obijuan

unread,
Oct 2, 2016, 5:45:23 AM10/2/16
to FPGA-WARS: explorando el lado libre
Hola Carlos!

  Los bloques de RAM por supuesto que se pueden usar!  :-)  Se usan de manera transparente. Es el sintetiazador el que infiere a partir de tu código Verilog que están implementando una memoria (RAM o ROM) y te asigna internamente los bloques BRAM  (Esto es transparente para ti, tú no lo indicas).

Con ellos puedes crear memorias ROM, con datos ya cargados listos para ser leídos. Esto se usa mucho en la implementación de los procesadores. En el tutorial hay varios ejemplos:

https://github.com/Obijuan/open-fpga-verilog-tutorial/wiki/Cap%C3%ADtulo-26%3A-Memoria-ROM

https://github.com/Obijuan/open-fpga-verilog-tutorial/wiki/Cap%C3%ADtulo-27%3A-Memoria-ROM-gen%C3%A9rica

Pero también los puedes usar como memoria RAM estándar, donde puedes leer y/o escribir:

https://github.com/Obijuan/open-fpga-verilog-tutorial/wiki/Cap%C3%ADtulo-28%3A-Memoria-RAM

Saludos, Obijuan
Para publicar en este grupo, envía un correo electrónico a fpga-wars-explorando-el-lado-li...@googlegroups.com.
Visita este grupo en https://groups.google.com/group/fpga-wars-explorando-el-lado-libre.

--
Has recibido este mensaje porque estás suscrito al grupo "FPGA-WARS: explorando el lado libre" de Grupos de Google.
Para anular la suscripción a este grupo y dejar de recibir sus mensajes, envía un correo electrónico a fpga-wars-explorando-el-lado-libre+unsubscribe@googlegroups.com.
Para publicar en este grupo, envía un correo electrónico a fpga-wars-explorando-el-lado-li...@googlegroups.com.
Visita este grupo en https://groups.google.com/group/fpga-wars-explorando-el-lado-libre.
Reply all
Reply to author
Forward
0 new messages