Interview Question · Concept
Choosing a State Encoding
The Question
The interviewer asks
Binary, one-hot or Gray: how do you choose a state encoding, and how do you check the tool used it?
You have two and a half minutes. Speak or type, then press Get Feedback under your answer. No credits needed.
Speech-to-text runs in your browser. Chrome and Edge may send audio to their own speech service.
You can edit your answer before you send it. Feedback uses AI and checks your answer only against our written answer. No credits are used and your answer is not saved.
Reveal the Model Answer
Binary uses the fewest flops, about log2 of the state count, but needs decoding. One-hot uses one flop per state, so testing a state reads one bit. Gray changes one bit per step, which suits machines that move in a fixed sequence. The real answer comes from measuring, because it depends on the machine and the tool. Check the flop count in the report: synthesis tools may re-encode your FSM.
- Climb the pattern
Each expected bit moves the machine one state to the right: 1, then 0, then 1 reaches S101.
Follow the calls, values and waits
- data sampled bit: S0 → S1
- data sampled bit: S1 → S10
- data sampled bit: S10 → S101
- A match keeps its last 1
From S101 a 1 completes 1011 and raises match. The stream now ends in "11", and its longest tail that starts 1011 is "1", so the next state is S1.
Follow the calls, values and waits
- data sampled bit: S101 → S1
- A miss keeps what it can
From S101 a 0 makes "1010". Its tail "10" still starts 1011, so the next state is S10. From S10 a 0 makes "100", and no tail starts 1011: back to S0.
Follow the calls, values and waits
- data sampled bit: S101 → S10
Read the diagram as text
- S0: seen nothing; stays on 0
- S1: seen "1"; stays on 1
- S10: seen "10"
- S101: seen "101"; a 1 now completes 1011
- S0 → S1: 1
- S1 → S10: 0
- S10 → S101: 1
- S10 → S0: 0
- S101 → S1: 1: match
- S101 → S10: 0
From lesson R3.4: a machine with four states. Binary codes it in 2 flops; one-hot uses 4, one per state.
| Encoding | Flops | Cells | Levels |
|---|---|---|---|
| Binary, encoding kept | 3 | 13 | 2 |
| One-hot (full-vector compares), encoding kept | 5 | 27 | 5 |
| Binary written, no keep attribute | 5 | 11 | 2 |
Measured on the pinned Yosys flow by the runs in this tree. In the last row the tool re-encoded the machine: read the flop count to see what it built.
A five-state sequencer, binary, encoding kept, with a default arm.
module seq5 (input logic clk, rst_n, start, last, output logic load, run, done);
typedef enum logic [2:0] {IDLE, LOAD, RUN, DRAIN, DONE} state_e; // binary 0 to 4
(* fsm_encoding = "none" *) state_e st_q;
state_e st_d;
always_ff @(posedge clk or negedge rst_n)
if (!rst_n) st_q <= IDLE;
else st_q <= st_d;
always_comb begin
st_d = st_q; // stay, unless an arm moves
case (st_q)
IDLE: if (start) st_d = LOAD;
LOAD: st_d = RUN;
RUN: if (last) st_d = DRAIN;
DRAIN: st_d = DONE;
DONE: st_d = IDLE;
default: st_d = IDLE; // any unnamed code: back to IDLE
endcase
end
assign load = (st_q == LOAD);
assign run = (st_q == RUN);
assign done = (st_q == DONE);
endmodule
Self-Check
Tick each key point you covered in your answer.
What Interviewers Listen For (Junior)
A good junior answer gives the flop count for each encoding. It says what one-hot makes cheap.
What Interviewers Listen For (Senior)
A good senior answer measures the options on the real flow and reads the flop count to see what the tool did. It keeps a chosen encoding when safety needs it.
Cross-Questions
Where the interviewer goes next. Open a node to practise that follow-up.
WhyWhat IfCompareScale It
- Choosing a State Encoding
-
WhyWhy One-Hot Decoding Is CheapL1 JuniorL2 Mid-Level
Why can one-hot be fast, when the full-compare version above was not? Read this version.
systemverilog module seq5 (input logic clk, rst_n, start, last, output logic load, run, done); localparam int IDLE = 0, LOAD = 1, RUN = 2, DRAIN = 3, DONE = 4; // bit positions (* fsm_encoding = "none" *) logic [4:0] st_q; logic [4:0] st_d; always_ff @(posedge clk or negedge rst_n) if (!rst_n) st_q <= 5'b00001; else st_q <= st_d; always_comb begin st_d = '0; // each arm sets one bit unique case (1'b1) // reverse case: each arm tests one state bit st_q[IDLE]: if (start) st_d[LOAD] = 1'b1; else st_d[IDLE] = 1'b1; st_q[LOAD]: st_d[RUN] = 1'b1; st_q[RUN]: if (last) st_d[DRAIN] = 1'b1; else st_d[RUN] = 1'b1; st_q[DRAIN]: st_d[DONE] = 1'b1; st_q[DONE]: st_d[IDLE] = 1'b1; default: st_d[IDLE] = 1'b1; endcase end assign load = st_q[LOAD]; assign run = st_q[RUN]; assign done = st_q[DONE]; endmodule module tb; logic clk = 0, rst_n = 1, start = 0, last = 0, load, run, done; seq5 dut (.*); always #5 clk = ~clk; initial begin #1 rst_n = 0; #1 rst_n = 1; start = 1; @(posedge clk); #1 start = 0; @(posedge clk); #1 $display("two edges after start: load=%b run=%b", load, run); last = 1; @(posedge clk); #1 last = 0; @(posedge clk); #1 $display("two edges after last: done=%b", done); $finish; end endmodule2:30You have two and a half minutes. Speak or type, then press Get Feedback under your answer. No credits needed.
Speech-to-text runs in your browser. Chrome and Edge may send audio to their own speech service.
You can edit your answer before you send it. Feedback uses AI and checks your answer only against our written answer. No credits are used and your answer is not saved.
Reveal the Model Answer
Each arm tests one state bit, not the whole 5-bit vector. So "am I in RUN?" is one wire, and each next-state bit is a small OR of a few terms. On this flow it is 13 cells and 3 levels, against 27 and 5 for full-vector compares. The coding has to use the one-hot property for the encoding to save logic.
RUNIcarus Verilog · in your browserExpected:two edges after start: load=0 run=1two edges after last: done=1Self-Check
Tick each key point you covered in your answer.
Misconception
"Writing
enumvalues as one-hot is enough to get one-hot logic."A
caseon the whole vector still compares all bits, as the full-compare version shows. Testing single bits is what makes it cheap.Source Measured: this run and the root twin, Yosys 0.70+290 (OSS CAD Suite 2026-11-02), slang front end, synth -flatten with ABC, ltp -noff
-
What IfWhen the Synthesizer Re-Encodes Your FSML2 Mid-LevelL3 Senior
What if the tool does not keep your encoding? How would you notice, and when does it matter?
2:30You have two and a half minutes. Speak or type, then press Get Feedback under your answer. No credits needed.
Speech-to-text runs in your browser. Chrome and Edge may send audio to their own speech service.
You can edit your answer before you send it. Feedback uses AI and checks your answer only against our written answer. No credits are used and your answer is not saved.
Reveal the Model Answer
Look at the flop count and the FSM section of the synthesis log. Here the binary machine came out with 5 flops: Yosys re-encoded it one-hot. That is often fine for speed. It matters when other logic reads the state code or the code crosses a clock domain. It also matters when recovery logic depends on it.
module seq5 (input logic clk, rst_n, start, last, output logic load, run, done); typedef enum logic [2:0] {IDLE, LOAD, RUN, DRAIN, DONE} state_e; // binary 0 to 4 state_e st_q; state_e st_d; always_ff @(posedge clk or negedge rst_n) if (!rst_n) st_q <= IDLE; else st_q <= st_d; always_comb begin st_d = st_q; // stay, unless an arm moves case (st_q) IDLE: if (start) st_d = LOAD; LOAD: st_d = RUN; RUN: if (last) st_d = DRAIN; DRAIN: st_d = DONE; DONE: st_d = IDLE; default: st_d = IDLE; // any unnamed code: back to IDLE endcase end assign load = (st_q == LOAD); assign run = (st_q == RUN); assign done = (st_q == DONE); endmoduleSelf-Check
Tick each key point you covered in your answer.
Missed Corner
"Re-encoding cannot change behaviour."
It keeps behaviour only for the reachable states. Codes the machine never reaches from reset, and the arms for them, can disappear.
Source Yosys 0.70+290 command help,
help fsm_recodeandhelp fsm_detect; lesson R3.2 measured netlists -
What IfA State Code That Crosses a Clock DomainL3 Senior
What if the state register is read in another clock domain, and the tool re-encodes it?
2:30You have two and a half minutes. Speak or type, then press Get Feedback under your answer. No credits needed.
Speech-to-text runs in your browser. Chrome and Edge may send audio to their own speech service.
You can edit your answer before you send it. Feedback uses AI and checks your answer only against our written answer. No credits are used and your answer is not saved.
Reveal the Model Answer
Then the reader may see a code that changes several bits at once, so it can sample a mix of two states. First, do not cross the state register at all. Cross a one-bit status through a synchronizer, or use a handshake. If you must keep the code, tell the tool not to re-encode it, and check the log after every run.
Self-Check
Tick each key point you covered in your answer.
Missed Corner
"Gray-code the states and the crossing is safe."
Only if every transition changes one bit and the tool keeps the code. A branching or re-encoded machine can change several bits at once.
Source Mehta, ASIC/SoC Functional Design Verification (2018) ch. 8.3.4 Multi-bit synchronization
-
CompareGray-Coded States vs One-HotL2 Mid-Level
Compare a Gray-coded state register with one-hot. When would you pick Gray?
2:30You have two and a half minutes. Speak or type, then press Get Feedback under your answer. No credits needed.
Speech-to-text runs in your browser. Chrome and Edge may send audio to their own speech service.
You can edit your answer before you send it. Feedback uses AI and checks your answer only against our written answer. No credits are used and your answer is not saved.
Reveal the Model Answer
Pick Gray when the machine walks a fixed loop, like a counter, and you want one bit to change per step. Each step then toggles one flop instead of two. It also matters if the state is read in another clock domain, because a Gray step is never a torn value. One-hot is usually better for speed in a branching machine.
Self-Check
Tick each key point you covered in your answer.
Misconception
"You can safely synchronize a binary state register into another domain."
Several bits can change in one step. The receiver can then catch a mix of old and new bits, which is a state that never existed.
Source Mehta, ASIC/SoC Functional Design Verification (2018) ch. 8.3.4 Multi-bit synchronization
-
Scale ItSplitting a Very Large FSML3 Senior
Scale it up: a protocol controller has grown to 60 states and misses timing. What do you do?
2:30You have two and a half minutes. Speak or type, then press Get Feedback under your answer. No credits needed.
Speech-to-text runs in your browser. Chrome and Edge may send audio to their own speech service.
You can edit your answer before you send it. Feedback uses AI and checks your answer only against our written answer. No credits are used and your answer is not saved.
Reveal the Model Answer
First look for hidden counters: chains of states that only count cycles. Replace them with one counter and one waiting state. Then split the rest into a main machine and small sub-machines that talk through start and done signals. Each piece gets fewer states, smaller next-state logic, and its own tests.
Self-Check
Tick each key point you covered in your answer.
What Interviewers Listen For (Senior)
A good senior answer looks for structure before it tunes encodings. It keeps each split machine testable on its own.
Wrong Altitude
"Try one-hot, then binary, and keep whichever passes."
Encoding tweaks shave a level or two. A 60-state machine usually hides a counter or two machines, and fixing that removes the problem.
What People Get Wrong
Common wrong answers and why they fail. Run It shows the wrong belief failing on a real simulator.
Misconception
"One-hot always gives less logic and fewer levels."
A hand-written one-hot machine that compares the whole state vector is the worst here: 27 cells and 5 levels, against 13 and 2 for binary.
Run It
The sequencer one-hot with full-vector compares, then binary; both with the encoding kept.
module seq5 (input logic clk, rst_n, start, last, output logic load, run, done);
typedef enum logic [4:0] {IDLE = 5'b00001, LOAD = 5'b00010, RUN = 5'b00100, DRAIN = 5'b01000, DONE = 5'b10000} state_e;
(* fsm_encoding = "none" *) state_e st_q;
state_e st_d;
always_ff @(posedge clk or negedge rst_n)
if (!rst_n) st_q <= IDLE;
else st_q <= st_d;
always_comb begin
st_d = st_q; // stay, unless an arm moves
case (st_q)
IDLE: if (start) st_d = LOAD;
LOAD: st_d = RUN;
RUN: if (last) st_d = DRAIN;
DRAIN: st_d = DONE;
DONE: st_d = IDLE;
default: st_d = IDLE; // any unnamed code: back to IDLE
endcase
end
assign load = (st_q == LOAD);
assign run = (st_q == RUN);
assign done = (st_q == DONE);
endmodule
See the Fix
module seq5 (input logic clk, rst_n, start, last, output logic load, run, done);
typedef enum logic [2:0] {IDLE, LOAD, RUN, DRAIN, DONE} state_e; // binary 0 to 4
(* fsm_encoding = "none" *) state_e st_q;
state_e st_d;
always_ff @(posedge clk or negedge rst_n)
if (!rst_n) st_q <= IDLE;
else st_q <= st_d;
always_comb begin
st_d = st_q; // stay, unless an arm moves
case (st_q)
IDLE: if (start) st_d = LOAD;
LOAD: st_d = RUN;
RUN: if (last) st_d = DRAIN;
DRAIN: st_d = DONE;
DONE: st_d = IDLE;
default: st_d = IDLE; // any unnamed code: back to IDLE
endcase
end
assign load = (st_q == LOAD);
assign run = (st_q == RUN);
assign done = (st_q == DONE);
endmodule
Tool as Truth
"The netlist uses the encoding I wrote in the enum."
Yosys re-encodes a detected FSM one-hot unless the state register has fsm_encoding = "none". Without it, this binary machine came out with 5 flops.
Source Measured: the sequencer without the attribute: 5 flops, 11 cells, Yosys 0.70+290 (OSS CAD Suite 2026-11-02), slang front end, synth -flatten with ABC, ltp -noff
Half-Truth
"Gray encoding saves power in every FSM."
Gray keeps one bit changing only along a fixed sequence of states. A machine that jumps between states loses that, and may need more logic.
Source Mehta, ASIC/SoC Functional Design Verification (2018) ch. 8.3.4 Multi-bit synchronization (one bit per Gray step)