One-hot state machine encoding in Verilog conversion

The conversion of my one-hot state machine design surprised me. Instead of expressing the cases as bitfields of all 0s but one 1, the cases are all don’t cares (?) but one 1.

else begin
    casez (io1_trigger_state)
        3'b??1: begin
            if ((io1_trigger_source && io1_gate_source)) begin
                trigger <= 1'b1;
                io1_trigger_state <= 3'b010;
        3'b?1?: begin
            trigger <= 1'b0;
            io1_trigger_state <= 3'b100;
        3'b1??: begin
            if ((!io1_trigger_source)) begin
                io1_trigger_state <= 3'b001;
        default: begin
            io1_trigger_state <= 3'b001;

I realize that the logic for this is simpler but it also can result in less deterministic behavior if an invalid state is somehow reached. Since all invalid states branch to whatever state is the best match instead of to the default state specified, the behavior is unpredictable and my default state clause is useless. I suspect this was a considered MyHDL implementation but I thought I would post it anyway.

Is this the intended behavior?

If you specify either one_hot or one_cold this is what the code makes from it.
Probably almost nobody uses the one_xxx? Or they do not care as much as you do …
I am not a Verilog expert, so I read up on the casez keyword; and I must admit I don’t like this generated result either. Also your default statement never will be triggered, as one of the three previous statements has priority.
I suggest you raise an Issue: Issues · myhdl/myhdl · GitHub

I thought that was the whole idea of one-hot: to eliminate state decode logic.

If your design is incomplete then you are very unlikely to be able to set two bits. Conversely, with no bits set the default state will be selected, and the machine should recover.

If you want the next state fully decoded then perhaps it would be better to use binary encoding, and save register bit or two?

Jan Coombs

Thank you both for your kind comments.

@josyb: I have reverted my designs to binary encoding since the one-hot implementation in unsatisfactory to me. Also, I followed your suggestion and raised an issue.

@JanCoombs: In my problem statement, I said that my default state clause was useless but your answer helped me see that it does offer some help but only for the 000 case. In all other invalid states, the machine will still take one of several paths depending on what bit is errant. For a proper one-hot FSM, every invalid state must be caught by the default case in order to be more deterministic but this may increase the complexity of the decoding logic. With one-hot, you might reduce decoding logic, or in some cases even eliminate it, but not necessarily.

I issued a PR replacing the casez with standard case and no don’t-care bits.