0 votes
in VHDL by (240 points)

VHDL state machines: How do you write them and can you give an example?

4 Answers

0 votes
by (1.8k points)

VHDL State Machine

Quick Syntax

-- state enumeration
type sm_states is (idle, init, send, done);
signal sm_state : sm_states;

STATE_MACHINE : process (clk,reset,enable)
begin

if rising_edge(clk) then

if reset = '1' then
output_command <= x"00";
sm_state <= idle;
output_enable <= '0';

else
-- defaults output_command <= x"00";
output_enable <= '0';

case sm_state is

when idle =>
if enable = '1' then
sm_state <= init;
else
sm_state <= idle;
end if;

when init =>
output_command <= x"1F";
sm_state <= send;
output_enable <= '1';

when send =>
output_command <= x"2E";
sm_state <= done;
output_enable <= '1';

when done =>
output_command <= x"7A";
sm_state <= idle;
output_enable <= '1';

when others =>
sm_state <= idle;

end case;
end if;
end if;
end process;
In the code snippet above, we can see that there are 4 states where the SM hangs out in idle. Once the incoming signal enable is '1', then we start our step by step execution through each of the states. Once we reach the done state, we return back to idle, where we wait for the next time enable is '1' again. This is perfect for sending a sequence of commands, writes, reads, signals, etc.

Purpose

State machines are simply a series of states that represent a step by step process (not to be confused with a VHDL process). They are used commonly in different designs like DDR memory interfaces, I2C, SPI, etc.

They are the preferred way of coding any sort of series of steps because they are easy to use, easy to understand, and easy to maintain. Typically, case statements are the main ingrediant in a state machine. Of course, you could code up equivalent logic with if statements, but that gets very messy and is prone to problems.

Best Practices

1. Use case statements in state machines.

2. Make sure that you enumerate your states since it's easier to code and ensures that you follow the states of whatever interface you are coding for.

3. Use when others in your case statement just in case someone in the future deletes a state and thinks its not necessary any more. It's a catch all if something goes wrong and you should use it to take your state machine back to idle.

4. For any signals being read in the state machine, they must be on the same clock domain so always use proper clock domain crossing here by double registerring these signals if they are coming from another clock domain. If incoming signals are on the same clock domain, don't worry about it.

5. Assuming you are using a process, use defaults at the top of your state machine for output signals. That way you only need to set output signals at each state that change from the default instead of driving every signal at every state which greatly multiplies and complicates your code.
0 votes
by (700 points)

VHDL state machines are usually written using either one, two or ( less commonly ) three processes.
My preferred method is using one synchronous process as it assures that all outputs are registered. This improves timing and helps avoid the inference of latches.

Example :

type state is
(
error_handler ,
idle ,
prepare_to_finish ,
run
) ;

signal current_state : state ;

fsm : process ( INPUT_CLOCK ,INPUT_RESET ) is
begin
if INPUT_RESET = '1' then
current_state <= idle ;
almost_finished_flag <= '0' ;
elsif rising_edge ( INPUT_CLOCK ) then

case current_state is

when idle =>

if start = '1' then
current_state <= run ;
end if ;

when run =>

if error = '1' and remaining_time < 500 then
current_state <= error_handler ;
elsif remaining_time > 600 then
current_state <= prepare_to_finish ;
almost_finished_flag <= '1' ;
end if ;

when prepare_to_finish =>

if ready_for_results = '1' then
current_state <= idle ;
almost_finished_flag <= '0' ;
end if ;

when error_handler =>

if error_ack = '1' then
current_state <= idle ;
end if ;

end case ;

end if ;

end process fsm ;
0 votes
by (700 points)

Finite state machines are usually defined using case statements. For example:

process (reset_n_i, sclk_i)
begin
if reset_n_i = '0' then
ui_state <= receive_addr;
elsif rising_edge(sclk_i) then
case ui_state is
when idle =>
byte_cnt <= (others => '0');
when receive_addr =>
wrong_addr <= '0';
when receive_instruction =>
ui_state <= tx_ram;
case addr is
when x"30" => null;
when others => wrong_addr <= '1';
end case;
when rx_load =>
ui_state <= rx;
when rx =>
ui_state <= idle;
when tx =>
byte_cnt <= byte_cnt_nxt;
when others =>
ui_state <= idle;
end case;
end if;
end process;
0 votes
by (700 points)

A sequential circuit that moves forward through a number of states is called a state machine. They are clocked processes and their output value depends on a state signal. States are represented in VHDL using enumerated type in which we can give a custom list of values. The syntax is:

type type_name is (state_name1, state_name2, ...);
signal signal_name : type_name;

A case statement is used to implement the state machine in a process and by using the state signal declared previously. The syntax example is given below in which one process state machine is written:

process(Clk) is
begin
if rising_edge(Clk) then
if nRst = '0' then
State <= <reset_state>;
else
case State is
when state_name =>
<set_outputs_for_this_state_here>
if state_change_condition_is_true then
State <= <next_state_name>;
end if;
...
end case;
end if;
end if;
end process;
An example of a state machine is a finite state machine that can be implemented for traffic control signals.
Hardware Coder Community

© 2022 by Hardware Coder. User contributions are licensed under cc by-sa 4.0 with attribution required. Attribution means a link to the question, answer, user, etc on this site.

This site is owned and operated by Hardware Coder in McKinney, Texas.

Send Us A Message
About Us

By using this site, you agree to the following:

Privacy Policy
Terms and Conditions
DMCA Policy
Earnings Disclaimer
Legal Disclaimer

...