State diagram to Verilog translation - Time & Space Complexity
When we translate a state diagram into Verilog code, we want to know how the time to run the code changes as the number of states grows.
We ask: How does the number of steps the hardware takes grow when we add more states?
Analyze the time complexity of the following Verilog code implementing a state machine.
module fsm(
input clk, reset,
input in,
output reg out
);
typedef enum logic [1:0] {S0, S1, S2, S3} state_t;
state_t state, next_state;
always_ff @(posedge clk or posedge reset) begin
if (reset) state <= S0;
else state <= next_state;
end
always_comb begin
case(state)
S0: next_state = in ? S1 : S0;
S1: next_state = in ? S2 : S0;
S2: next_state = in ? S3 : S0;
S3: next_state = S0;
default: next_state = S0;
endcase
out = (state == S3);
end
endmodule
This code models a simple state machine with 4 states, moving between them based on input.
Look for parts that repeat as input or states grow.
- Primary operation: The state transition logic inside the
always_combblock, which checks current state and input to decide next state. - How many times: This logic runs every clock cycle, once per cycle, but the complexity depends on how many states we have to check.
As the number of states n increases, the hardware must check more cases to decide the next state.
| Number of States (n) | Approx. Operations per Cycle |
|---|---|
| 4 | 4 checks |
| 10 | 10 checks |
| 100 | 100 checks |
Pattern observation: The number of checks grows directly with the number of states.
Time Complexity: O(n)
This means the time to decide the next state grows linearly as the number of states increases.
[X] Wrong: "The state machine runs in constant time no matter how many states it has."
[OK] Correct: Each added state means more conditions to check, so the decision logic grows with the number of states.
Understanding how state machines scale helps you design efficient hardware and explain your design choices clearly in interviews.
"What if we replaced the case statement with a lookup table for next states? How would the time complexity change?"
Practice
Solution
Step 1: Understand the role of state diagrams
State diagrams show states and how the system moves between them, making design clearer.Step 2: Connect to Verilog design
They help plan the Verilog code but do not generate code or replace hardware elements.Final Answer:
To visually represent states and transitions for easier coding -> Option AQuick Check:
State diagram = Visual design aid [OK]
- Thinking state diagrams generate code automatically
- Confusing state diagrams with testing tools
- Believing state diagrams replace clock signals
Solution
Step 1: Recall Verilog enum syntax
In SystemVerilog (modern Verilog), enums are declared with 'typedef enum {states} name;'.Step 2: Check variable declarations
Variables of enum type are declared as 'state_t current_state, next_state;'.Final Answer:
typedef enum {IDLE, READ, WRITE} state_t; state_t current_state, next_state; -> Option CQuick Check:
Enum typedef syntax = typedef enum {IDLE, READ, WRITE} state_t; state_t current_state, next_state; [OK]
- Using 'enum' without typedef
- Incorrect order of keywords
- Missing variable type for state variables
current_state after two clock cycles if the reset is deasserted and start is 1?
typedef enum {IDLE, BUSY, DONE} state_t;
state_t current_state, next_state;
always_ff @(posedge clk or posedge reset) begin
if (reset) current_state <= IDLE;
else current_state <= next_state;
end
always_comb begin
case (current_state)
IDLE: next_state = start ? BUSY : IDLE;
BUSY: next_state = DONE;
DONE: next_state = IDLE;
default: next_state = IDLE;
endcase
endSolution
Step 1: Analyze state transitions per clock
At reset, current_state = IDLE. On first clock, start=1, so next_state = BUSY.Step 2: Follow second clock update
On second clock, current_state = BUSY, so next_state = DONE.Final Answer:
DONE -> Option BQuick Check:
Two clocks after start=1: IDLE -> BUSY -> DONE [OK]
- Assuming immediate state change without clock
- Confusing next_state with current_state
- Ignoring reset effect
typedef enum {S0, S1, S2} state_t;
state_t current_state, next_state;
always_ff @(posedge clk or posedge reset) begin
if (reset)
current_state <= S0;
else
current_state = next_state;
end
always_comb begin
case (current_state)
S0: next_state = S1;
S1: next_state = S2;
S2: next_state = S0;
endcase
endSolution
Step 1: Check assignment types in always_ff block
Inside always_ff, non-blocking assignment '<=' must be used for sequential logic.Step 2: Identify incorrect assignment
Line 'current_state = next_state;' uses blocking '=', which is incorrect here.Final Answer:
Change 'current_state = next_state;' to 'current_state <= next_state;' -> Option DQuick Check:
Sequential logic uses '<=' [OK]
- Using '=' instead of '<=' in sequential blocks
- Forgetting default case (not critical here)
- Misunderstanding sensitivity list for reset
x. State A transitions to B if x=1, else stays in A. State B transitions to C unconditionally. State C transitions back to A if x=0, else stays in C. Which Verilog code snippet correctly implements the next state logic using a case statement?Solution
Step 1: Translate each transition from the diagram
State A: if x=1 go to B else stay A; State B: always go to C; State C: if x=0 go to A else stay C.Step 2: Match transitions to code options
always_comb begin case (current_state) A: next_state = (x == 1) ? B : A; B: next_state = C; C: next_state = (x == 0) ? A : C; default: next_state = A; endcase end matches all conditions exactly with correct ternary expressions and default case.Final Answer:
Option A code snippet -> Option AQuick Check:
Transitions match diagram = always_comb begin case (current_state) A: next_state = (x == 1) ? B : A; B: next_state = C; C: next_state = (x == 0) ? A : C; default: next_state = A; endcase end [OK]
- Swapping conditions for x in transitions
- Missing default case in case statement
- Incorrect unconditional transitions
Ready to prove it?
Pass the test and this pattern moves unknown
