Traditional FPGA textbooks instruct the student or professional in the design of pure Moore machines and pure Mealy machines. With the help of recursive FSM registers, a single state of a state machine can iterate through the processing of bits or bytes. Here’s an example. When a module input indicates that the next FIFO byte is ready for enqueue or dequeue, the state machine of this module can combinatorially enqueue or dequeue the FIFO on a clock edge by a direct input to output assignment within the state. Additionally, upon each iteration, the bit or byte being indexed can be processed as input or output. The FSM designs I recently published on GitHub make use of this technique; a technique that I have not seen elsewhere, but was effective coding. For the example in VHDL, quoted from the fpga-serial-acl-tester-1 project, in the source file pmod_acl2_stand_spi_solo.vhdl:

when ST_DRV_READ_ACT0_DATA =>
	-- Receive the eight bytes of measurement data from the SPI
	-- bus operation, and output the bytes one-at-a-time in a streaming
	-- pattern.
	o_tx_len              <= std_logic_vector(
	    to_unsigned(c_tx_ax_readlm_length, o_tx_len'length));
	o_rx_len              <= std_logic_vector(
	    to_unsigned(c_rx_ax_readlm_length, o_rx_len'length));
	o_rx_dequeue          <= i_rx_avail;
	o_rd_data_stream      <= i_rx_data;
	o_rd_data_byte_valid  <= i_rx_valid;
	o_rd_data_group_valid <= '1';
	s_byte_index_val      <= (s_byte_index_aux - 1) when (i_rx_valid = '1')
	                         else s_byte_index_aux;

	if ((i_rx_valid = '1') and (s_byte_index_aux <= 1)) then
		s_acl2_drv_nx_state <= ST_DRV_READ_WAIT6;
	else
		s_acl2_drv_nx_state <= ST_DRV_READ_ACT0_DATA;
	end if;

Here the inputs i_rx_avail, i_rx_data, and i_rx_valid, are passed directly to output signals. When in this state, the RX Available signal is passed immediately to the RX Dequeue input of the SPI bus driver; whereas the RX Data and RX Valid signals are passed directly as outputs from this Accelerometer application driver module to be captured by the downstream module. Note also that the recursive register s_byte_index is decremented on and only on the clock edge of the pulse received on signal i_rx_valid. When RX Valid is received for the last byte, the state sets the Next State to move the machine on to a waiting state instead of continuing in this state.

The use of the VHDL 2008 Sequential Conditional Signal Assignment,

s_byte_index_val <= (s_byte_index_aux - 1) when (i_rx_valid = '1')
                    else s_byte_index_aux;

gives the appearance that the machine is still Moore with some “transparent” signal assignments. The statement in this form separates the recursive signal next value from the if-else branches that select the next state machine state.

The traditional way to code this state would cause a mix of Moore and Mealy coding style as the assignment to the recursive register s_byte_index would depend upon its current value and the module input i_rx_valid, in the same if-else structure that selects the Next State. Here’s the example:

when ST_DRV_READ_ACT0_DATA =>
	-- Receive the eight bytes of measurement data from the SPI
	-- bus operation, and output the bytes one-at-a-time in a streaming
	-- pattern.
	o_tx_len              <= std_logic_vector(
	    to_unsigned(c_tx_ax_readlm_length, o_tx_len'length));
	o_rx_len              <= std_logic_vector(
	    to_unsigned(c_rx_ax_readlm_length, o_rx_len'length));
	o_rx_dequeue          <= i_rx_avail;
	o_rd_data_stream      <= i_rx_data;
	o_rd_data_byte_valid  <= i_rx_valid;
	o_rd_data_group_valid <= '1';

	if (i_rx_valid = '1') then
		s_byte_index_val <= (s_byte_index_aux - 1);
		if (s_byte_index_aux <= 1)) then
			s_acl2_drv_nx_state <= ST_DRV_READ_WAIT6;
		else
			s_acl2_drv_nx_state <= ST_DRV_READ_ACT0_DATA;
		end if;
	else
		s_byte_index_val    <= s_byte_index_aux;
		s_acl2_drv_nx_state <= ST_DRV_READ_ACT0_DATA;
	end if;

This latter form is supported as VHDL-2002 instead of VHDL-2008 synthesis and simulation. I do have a hypothesis however that the VHDL-2008 coding form mentioned first, when synthesized with Xilinx Vivado, creates additional logic in the combinatorial logic part of the FSM, with a benefit of higher slack in the synthesis timing of the FSM. Email or LinkedIn comments are welcome!

One additional note. It should always be possible to break-up the above state of the state machine into multiple states to keep the FSM implementation a pure Moore machine. The above style was invented as a coding experiment based upon FSM diagram suggestions of recursive assignment usages from the FSM textbook cited in the project’s Info document.