I wasn't thinking about the 'initial' value but rather a default value assigned inside the process, just ahead of the case statement, that provided a value for the named signal in every state unless over-ridden in the state. Given, say, 50 output signals from the FSM, it would be silly to define them in each of 100 states yet all signals must be defined in all states, one way or another. Missing one of these signals results in a latch, something to be avoided.
Ah, OK, this distinction between an initializer and a "default" is important.
As for "default" assignments in a combinatorial process to avoid latch inference, exactly what is the default? For example, say you have a four-state machine and you assign to signal foo in two of those states. How do you maintain the signal value in the other two states? This is one reason why I avoid the two-process FSM.
Yes, the single-process FSM has its one clock of latency. But for most cases this latency is easily handled. Yes, there are exceptions.
I do use a clever trick to set the time (in clocks) spent in some states. Remember this is all in a clocked process. I create a signal called duration. Outside of the state machine I have an assignment:
if duration > 0 then
duration <= duration - 1;
end if;
and then in the machine itself I'll have code like:
when STATEX =>
duration <= 50;
foo <= '1';
state <= STATEY;
when STATEY =>
if duration = 0 then
foo <= '0';
state <= STATEZ;
end if;
Perhaps there's a way to do this in a two-process machine but I don't want to think about it.
But whatever works for you.
I didn't know that initializers weren't universal. After all, it is just a configuration bit among millions of other bits configuring the fabric.
It
should be but it isn't.
The asynchronous versus synchronous reset issue has been debated since the first FPGA project. I have used mostly asynchronous but if Xilinx says to use synchronous, that's fine. I have done it wrong for a long time but there's still time to learn to do it right. I guess the asynchronous approach came from the 7474 which has asynchronous set and reset.
The Xilinx reason for the async reset is that it gets put on a slow global net (GSR) and there's no way to ensure that all flip-flops come out of reset at the same time, especially on the larger chips running fast. And since the flip-flops have resets which are configurable as either async or sync with no penalty for the sync reset (my guess is that the sync reset/preset is nothing more than a mux selected by the reset signal that drives the D input) then it works well. If the flip-flops in the fabric don't have a sync reset capability then it must be implemented outside of the flip-flop (in the CLB or wherever).