Help! Verilog loop! The following signal(s) form a combinatorial loop
Whether you put it the sensitivity list or not, the mode variable depends on the mode variable.  See where I point it out below.

Pretend you are trying to make that hardware.  How do you make that work?  Remember there is not clock here, so you would have to create a combinatorial loop, right?

always @(mux)
begin
    if(mux == 2'b00)
        if(mode == 3'b000)       &lt;----  HERE
            mode = 3'b001;
        else if(mode == 3'b010)  &lt;----- HERE
            mode = 3'b011;
        else mode = 3'b000;
    else if(mux == 2'b01)
        mode = 3'b000;
    else if(mux == 2'b10)
        mode = 3'b010;
    else //if(mux == 2'b11)
        mode = 3'b100;
end


Walk through the design to understand what does this do in the situation where mux is starting at 2'b01 then goes to 2'b00?
When mux = 2'b01, mode = 3'b000.  Then when mux goes to 2'b00, it looks to see that mode is 3'b000, and changes mode to be 3'b001.  Then it immediately sees that mux is 2'b00 and mode is 3'b001 and changes mode to 3'b000, then it sees that mux is 2'b00 and mode is 3'b000 and changes mode to 3'b001.  This is a combinatorial loop.

As an aside, let me explain what the sensitivity list is exactly.  Originally, verilog was designed as a modelling language.  The sensitivity list was a way to tell the simulator dependencies.  This helped to reduce unneeded processing by letting the simulator not look into the code for each always block to determine if it needed to run it.

However, today verilog is mostly used to infer logic, so the sensitivity list is really not as useful as it was.  The synthesis tool will look at the code and determine that you forgot something.  You can't trick it by not putting it in the list.  It is a dependency according to your logic and the synthesis tool will treat it as such.  It probably even helpfully gave you a warning that you forgot it.