An FSM separates current state, next-state calculation and output decoding. Use symbolic state constants and make defaults explicit. A two-process organization keeps the clocked state update distinct from combinational transition logic. The encoded bit pattern is an implementation choice, while the transition specification defines behavior.
Worked example
The machine enters BUSY on start and leaves on done. The combinational default holds the current state; the default case provides a defined recovery destination for an unrecognized state value in RTL simulation.
module controller(input clk,reset,start,done,output busy);
localparam IDLE=1'b0,BUSY=1'b1;
reg state,next_state;
always @* begin
next_state=state;
case(state)
IDLE:if(start) next_state=BUSY;
BUSY:if(done) next_state=IDLE;
default:next_state=IDLE;
endcase
end
always @(posedge clk) if(reset) state<=IDLE;else state<=next_state;
assign busy=(state==BUSY);
endmodule
What to watch for
A default case in RTL does not by itself guarantee fault-tolerant recovery after synthesis. Illegal-state behavior and synthesis optimizations must be reviewed for that requirement.
Try it yourself
Why initialize next_state to state?
Answer: It makes holding the current state the default transition. Explicit branches override it when a transition condition is met.
How to study this topic
Save the example in a .v file and identify its top module before compiling. Separate stimulus and observation from synthesizable RTL. Change one input, width or boundary condition at a time, predict the result, and compare that prediction with simulation. A syntax check does not establish synthesis support or timing closure.
Continue learning
Previous: Counters and shift registers in RTL
Browse the complete Verilog index
Explore related programmes
These recorded programmes are upcoming. This article is general educational content, not a syllabus or course sample.
Verilog