1

I have this FSM that controls different events in a game I'm building (in Quartus Prime Lite Edition 17.0). When I try to compile it, I get this error:

Error (10166): SystemVerilog RTL Coding error at GameFSM.sv(40): always_comb construct does not infer purely combinational logic.

I have all the outputs assigned as default values, so no latches should be inferred I believe (I don't totally understand how it works).

//Game FSM, controls the game events

module GameFSM (
    input logic clk, resetN, NPCCollisions, Dead_NPCs, start_game, pause_game, continue_game, delay_indicator,
    
    output logic Message_main_menu,
    output logic Message_pause,
    output logic Message_win,
    output logic Message_lose,
    output logic Display_Main_Menu,
    output logic MainMenu_Music,
    output logic BackGround_Music, 
    output logic Paused,
    output logic Win_Music,
    output logic Lose_Music
   );

enum logic [2:0] {main_Menu, three_hearts, two_hearts, one_heart, delay_state, pause, win, lose} prState, nxtState;

logic [1:0] return_state;
    
always @(posedge clk or negedge resetN)
  begin
       
    if ( !resetN ) begin // Asynchronic reset
        prState <= main_Menu;
    end
        
    else    begin   // Synchronic logic FSM
        prState <= nxtState;
    end
        
end // always

always_comb // Update next state and outputs
    begin
        nxtState = prState; // default values 
        Message_main_menu = 1'b0;
        Message_pause = 1'b0;
        Message_win = 1'b0;
        Message_lose = 1'b0;
        MainMenu_Music = 1'b0;
        BackGround_Music = 1'b0;
        Paused = 1'b0;
        Win_Music = 1'b0;
        Lose_Music = 1'b0;
        Display_Main_Menu = 1'b0;
            
        case (prState)
                
            main_Menu: begin
                Message_main_menu = 1'b1;
                MainMenu_Music = 1'b1;
                Display_Main_Menu = 1'b1;
                if(start_game)
                    nxtState = three_hearts; 
            end
            
            three_hearts: begin
                BackGround_Music = 1'b1;
                return_state = 2'h3;
                if(NPCCollisions) //Corony hits an npc while he has 3 hearts left
                    nxtState = delay_state;
                else if(Dead_NPCs) //all npc's are dead
                    nxtState = win;
                else if(pause_game)
                    nxtState = pause;
            end
            
            two_hearts: begin
                BackGround_Music = 1'b1;
                return_state = 2'h2;
                if(NPCCollisions) //Corony hits an npc while he has 2 hearts left
                    nxtState = delay_state;
                else if(Dead_NPCs) //all npc's are dead
                    nxtState = win;
                else if(pause_game)
                    nxtState = pause; 
            end
            
            one_heart: begin
                BackGround_Music = 1'b1;
                return_state = 2'h1;
                if(NPCCollisions) //Corony lost all his hearts
                    nxtState = lose;
                else if(Dead_NPCs) //all npc's are dead
                    nxtState = win;
                else if(pause_game)
                    nxtState = pause;
            end
            
            delay_state: begin
                if(delay_indicator) begin
                    if(return_state == 2'h3)
                        nxtState = two_hearts;
                    else if(return_state == 2'h2)
                        nxtState = one_heart;
                end
            end
            
            pause: begin
                Paused = 1'b1;
                Message_pause = 1'b1;
                if(continue_game) begin
                    if(return_state == 2'h3)
                        nxtState = three_hearts;
                    else if(return_state == 2'h2)
                        nxtState = two_hearts;
                    else
                        nxtState = one_heart;
                end
            end
            
            win: begin
                Win_Music = 1'b1;
                Message_win = 1'b1;
            end
                        
            lose: begin
                Lose_Music = 1'b1;
                Message_lose = 1'b1;
                end 
                
            
                
            endcase
    end // always comb
    
endmodule

return_state is used so I can know which state delivered me to the pause state, so when I want to leave the pause state, I'd know where I should return to.

1 Answer 1

2

The problem is that you read and assign to the counter signal in side the always_comb block:

                counter = counter - 1;

This can create a combinational feedback loop.

Similarly for:

                counter = DELAY_TIME;

Perhaps you should use sequential logic for counter: always @(posedge clk ...)

Another problem signal might be return_state. I'm not sure why my simulator doesn't complain about this one. I think return_state should be assigned in its own sequential logic block as well.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.