Máquina de estados finitos en Verilog

1

Así que estoy tratando de hacer un FSM básico en verilog para encender 3 LED diferentes. He visto ejemplos y el trabajo de otras personas, pero no puedo entender por qué el mío no funciona. Tal vez alguien pueda ayudarme a detectar un error en mi código que no puedo ver.

module blink( input rst, output reg [2:0] leds, output LED);

OSCH #("2.08") osc_int (                    //"2.03" specifies the operating frequency, 2.03 MHz. Other clock frequencies can be found in the MachX02's documentation
        .STDBY(1'b0),                           //Specifies active state
        .OSC(clk),                              //Outputs clock signal to 'clk' net
        .SEDSTDBY());       
wire clk_slow;              //this will be the slower clock wire

reg [21:0] cnt;                     //these two lines use the fast clock to increment a 21 bit register
always @(posedge clk) cnt <= cnt+1;

assign clk_slow = cnt[21];      //this is high whenever the 21st bit of the fast clock register is true, thus slowing the clock to about 1 Hz
assign LED = clk_slow ;         //status LED so I know my clock is working


reg [1:0] state;            
reg [1:0] state_n;

    parameter S0 = 2'b00;           //state paramenters
    parameter S1 = 2'b01;
    parameter S2 = 2'b10;

always @ (posedge clk_slow or posedge rst)  //state changer
begin
    if(!rst)
        state <= S0;
    else
        state <= state_n;

end

always @ (*)        //changes next state
begin
    case(state)
        S0: state_n = S1;
        S1: state_n = S2;
        S2: state_n = S0;
        default state_n = S0;
    endcase
end

always @ (*)        //decides what leds to light based on state
begin
    if (state == S0)
        leds = 3'b001;
    else if(state == S1)
        leds = 3'b010;
    else if(state == S2)
        leds = 3'b100;
end


endmodule

No estoy muy seguro de por qué no funciona. El LED de estado que he conectado está parpadeando a 1 Hz, lo cual es correcto. Mis otros 3 LED parecen estar atascados en el estado 0 ... o algo así. Cuando presiono el botón de reinicio, a veces cambia mi LED al estado 1, pero creo que tiene que ver con la superposición del reloj. Cualquier ayuda es apreciada.

Estoy usando un FPGA de Lattice Diamond para programar esto. Estoy usando el reloj incorporado para generar el reloj inicial, y estoy usando los LED de a bordo. Mi botón de reinicio es externo y activo bajo.

    
pregunta Gigaxalus

2 respuestas

3
always @ (posedge clk_slow or posedge rst)  //state changer
begin
    if(!rst)
        state <= S0;
    else
        state <= state_n;

end

Si desea un restablecimiento activo-bajo asíncrono, este bloque siempre debe ser sensible a negedge rst en lugar de posedge rst .

Si desea un restablecimiento activo-alto, entonces la condición en su declaración if debe ser rst en lugar de !rst .

Editar

Otros problemas menores que veo en el código (que no deberían hacer que su sistema no funcione):

  • Su comentario dice que cnt es un registro de 21 bits, pero el código real lo convierte en un registro de 22 bits. Esto debería hacer que los LED parpadeen la mitad de la velocidad que esperaba.

  • No hay lógica de reinicio para cnt . Esto hará que el código sea difícil de simular (porque cnt se quedará atascado en el estado 'x').

respondido por el The Photon
0

La mejor práctica es no usar clk_slow como el reloj de la máquina de estado. Use clk para su máquina de estado y haga de clk_slow una especie de bandera.

always @ (posedge clk or posedge rst)
begin
    if(!rst)
        state <= S0;
    else if (clk_slow)
        state <= state_n;
end

(Normalmente no trabajo en Verilog, por favor verifique la sintaxis)

    
respondido por el mng

Lea otras preguntas en las etiquetas