Forum Discussion

Altera_Forum's avatar
Altera_Forum
Icon for Honored Contributor rankHonored Contributor
14 years ago

FSM trouble

I am trying to understand and get working a FSM that is part of a PS/2 mouse lab I am working on. The first always block is not giving me any errors now even though I am not sure that the logic is correct for S3 and S4. The state table says for State: S3, (state priority 1)plugged_in==1 then S0, (state priority 2) ps2_data_en==0 then S4, (state priority 3) S4. State:S4, (state priority 1) plugged_in==1 then S0, (state priority 2) ps2_data_en==0 then S4, (state priority 3) S5. I do not understand how or why state priority 3 gets invoked for S3 and S4. I can see how the priority states 1 and 2 get invoked because plugged_in and ps2_data are there to switch states depending on the value 1 or 0 coming in. How should I deal with state priority 3 then?

There is a 'default:;' waiting to be filled in in the second always block. What should I look at to tell me what I should put in there?

My next question is dealing with the second always block, the state outputs. I was given a table that gave the states S0..S5. The output values are the same for S0..S4 and are as follows: ps2_send_command== 1'b1

ps2_command== 8'hF4

mouse_packet== 1'b0

The output value of S5 is: if(!plugged_in)

mouse_packet=1'b1

I put the output values into the code below just to see what would happen and I received many errors. I am lost as to what to do next. At this point I do not know what else to give as far as data so let me know if there is more that I should post. Thanks

// This FSM resets the PS/2 device and then keeps track of packets, which

// consist of three data bytes. Packets could be from a key board or mouse,

// but this code is needed only for tracking movements of the mouse.

always @(y_Q, was_sent, ps2_data_en, plugged_in, ack_received)

begin: state_table

case (y_Q)

S0: if (was_sent==1'b1)

Y_D=S1;

else

Y_D=S0;

S1: if (ack_received==1'b1)

Y_D= S2;

else

Y_D= S1;

S2: if (ps2_data_en==1'b1)

Y_D= S3;

else

Y_D= S2;

S3: if (plugged_in==1'b1)

Y_D= S0;

else if (ps2_data_en==1'b0)

Y_D= S3;

else Y_D= S4;

S4: if (plugged_in==1'b1)

Y_D= S0;

else if(ps2_data_en==1'b0)

Y_D= S4;

else Y_D= S5;

S5: if (plugged_in==1'b1)

Y_D= S0;

else Y_D= S4;

default: Y_D = 3'bxxx;

endcase

end // state_table

always @(y_Q, ps2_data_en, ps2_command, plugged_in)

begin: state_outputs

case (y_Q)

S0: if (ps2_send_command== 1'b1)

if (ps2_command== 8'hF4)

if (mouse_packet== 1'b0)

S1: if (ps2_send_command== 1'b1)

if (ps2_command== 8'hF4)

if (mouse_packet== 1'b0)

S2: if (ps2_send_command== 1'b1)

if (ps2_command== 8'hF4)

if (mouse_packet== 1'b0)

S3: if (ps2_send_command== 1'b1)

if (ps2_command== 8'hF4)

if (mouse_packet== 1'b0)

S4: if (ps2_send_command== 1'b1)

if (ps2_command== 8'hF4)

if (mouse_packet== 1'b0)

S5: if (!plugged_in)

mouse_packet=1'b1

default:;

endcase

end // state_outputs

4 Replies

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    First you must use clock edge for your state transitions.

    second, your second always is not driving outputs as you want.

    Again it is better to have outputs registered or else you get latches, but anyway you should get the idea from pseudocode below

    
    //pseudocode
    always @(y_Q, plugged_in)
    begin: state_outputs
        
            case (y_Q)   
                 S5:    if (!plugged_in)
                                  mouse_packet=1'b1;
                  default:   
                      ps2_send_command = 1'b1;
                      ps2_command = 8'hF4;
                      mouse_packet = 1'b0;
            
        endcase
    end 
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    here is the working FSM. I like this better as it is easier to see the output states along with the state priority in one shot.

    reg [7:0] Rps2_command;

    reg Rps2_send_command;

    assign ps2_send_command = Rps2_send_command;

    assign ps2_command = Rps2_command;

    /*****************************************************************************

    * Finite State Machine(s) *

    *****************************************************************************/

    // This FSM resets the PS/2 device and then keeps track of packets, which

    // consist of three data bytes. Packets could be from a key board or mouse,

    // but this code is needed only for tracking movements of the mouse.

    always @(y_Q, was_sent, ps2_data_en, plugged_in, ack_received)

    begin: state_table

    case (y_Q)

    S0:

    begin

    Rps2_send_command <= 1'b1;//S0 output values

    Rps2_command <= 8'hF4;

    mouse_packet <= 1'b0;

    if

    (was_sent==1'b1)//state priority 1

    Y_D<=S1;

    else

    Y_D<=S0;//state priority 2

    end

    S1:

    begin

    Rps2_send_command <= 1'b0;//S1 output values

    Rps2_command <= 8'hF4;

    mouse_packet <= 1'b0;

    if

    (ack_received==1'b1)//state priority 1

    Y_D= S2;

    else

    Y_D= S1;//state priority 2

    end

    S2:

    begin

    Rps2_send_command <= 1'b1;//S2 output values

    Rps2_command <= 8'hF4;

    mouse_packet <= 1'b0;

    if

    (ps2_data_en==1'b1)//state priority 1

    Y_D= S3;

    else

    Y_D= S2;//state priority 2

    end

    S3:

    begin

    Rps2_send_command <= 1'b1;//S3 output values

    Rps2_command <= 8'hF4;

    mouse_packet <= 1'b0;

    if

    (plugged_in==1'b1)//state priority 1

    Y_D= S0;

    else if

    (ps2_data_en==1'b0)//state priority 2

    Y_D= S3;

    else

    Y_D= S4;//state priority 3 when plugged_in==0 and ps2_data_en==1

    end

    S4:

    begin

    Rps2_send_command <= 1'b1;//S4 output values

    Rps2_command <= 8'hF4;

    mouse_packet <= 1'b0;

    if

    (plugged_in==1'b1)//state priority 1

    Y_D= S0;

    else if

    (ps2_data_en==1'b0)//state priority 2

    Y_D= S4;

    else

    Y_D= S5;//state priority 3 when plugged_in==0 and ps2_data_en==1

    end

    S5:

    begin

    if

    (!plugged_in)

    mouse_packet=1'b1;//S5 output values

    if (plugged_in==1'b1)//state priority 1

    Y_D= S0;

    else

    Y_D= S4;//state priority 2

    end

    default: Y_D = 3'bxxx;

    endcase

    end // state_table
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Looking back at your output assignments, something can't be right:

    rps2_send_command <= 1'b1

    rps2_command <= 8'hf4;

    in four states and are undefined in s5 i.e. retains its value.

    So you might just set these outside states.