@op: sensitivity lists are almost never the answer. They are a legacy burden that are increasingly being marginalized. Synthesis mostly ignores it. For Verilog, synthesis uses it to determine the clock and (optional) async clear for a FF. Fixing sim issues by tweaking the sensitivity list might mean the sim works but the synthesis doesn't.
You should use "@(posedge clk or negedge aclr)", "@(posedge clk)", and "@(*)". In system verilog, you should use always_ff and always_comb. (sometimes you might have a negedge clk, or posedge aclr)
When you have always@(posedge clk) or always_ff, you should mentally think that you are writing logic for the next cycle. For an FSM, this means writing output logic based on transitions.
When you have always@(*) or always_comb, you should mentally think that you are writing logic for the current cycle, or that you are writing the next_value logic for a register and that this next_value logic could be used in the current cycle.
In Verilog/VHDL, a value is retained if nothing in the always block updates it. for always@(*), this means a value not assigned in all code paths infers a latch. always_comb can detect this.