Yosys handles an FSM in three named steps after elaboration. Detection only marks candidates; extraction packs one machine into one cell; recoding reassigns its state codes.
Pass | What it does | What to check |
|---|---|---|
fsm_detect | Marks state-register candidates from the clocked-register plus case pattern | No visible change; unrecognised registers stay plain flops. |
fsm_extract | Packs each detected machine into one | Here: zero |
fsm_recode | Reassigns the state codes inside each | Acts only on |
fsm | The meta pass: optimises and maps | Here: nothing was extracted, so the design stays coarse; the assertions pin the 13-cell mix. |
The script below runs a 4-state machine, written with a 2-bit binary code, through detection, extraction and recoding. Detection does not claim this machine: the script ends with zero $fsm cells, one 2-bit $dffe state register, and twelve combinational coarse cells.
Its assertions pin that exact mix. The honest reading comes first: recognition is pattern-based and never guaranteed, so always assert the $fsm count before relying on recoding.
read_verilog <<EOV
module seq4 (
input wire clk,
input wire go,
output reg ready
);
reg [1:0] state;
reg [1:0] next;
initial state = 2'b00;
always @(posedge clk) state <= next;
always @(*) begin
next = state;
ready = 1'b0;
case (state)
2'b00: begin if (go) next = 2'b01; end
2'b01: begin next = 2'b10; end
2'b10: begin next = 2'b11; end
2'b11: begin ready = 1'b1; if (go) next = 2'b00; end
endcase
end
endmodule
EOV
hierarchy -top seq4
proc
opt
fsm_detect
fsm_extract
fsm_recode
fsm
select -assert-none t:$fsm
select -assert-count 1 t:$dffe
select -assert-count 3 t:$eq
select -assert-count 2 t:$ne
select -assert-count 2 t:$mux
select -assert-count 2 t:$pmux
select -assert-count 1 t:$logic_not
select -assert-count 1 t:$reduce_and
select -assert-count 1 t:$reduce_or
log PASS: 4-state machine keeps a 2-bit coarse state flop and no $fsm cellZero $fsm cells mean the machine was not recognised as a unit. The state stayed in RTL-like form: one 2-bit $dffe plus comparators and multiplexers for the next-state logic.
No generic flops appear because the script never runs techmap or the fine part of synthesis. Coarse cells ($dffe, $eq, $mux) exist only before that lowering, so asserting generic types at this stage finds nothing.
Detection did not claim the machine, so extraction produced no cell and recoding had no target. The state register stayed a plain coarse flop.
It never runs techmap, so lowering to generic flops never happens. The pinned mix is all coarse cells, and asserting a generic type there finds zero.