Implement FSM in VHDL

It’s just interesting if I implement a finite state machine in VHDL, do I need to indicate which all outputs are in any possible state? Even if I know that some outputs will not change from one state to another, and I know that the order of states will also be in the same order?

For example, in this (forced) example:

entity test is port ( clk : in std_logic; a : in std_logic; b: out std_logic; c: out std_logic; ); end test; architecture Behavioral of test is type executionStage is (s1,s2,s3); signal currentstate, nextstate: executionStage; begin process (clk) begin if(rising_edge(clk)) then currentstate <= nextstate; else currentstate <= currentstate; end if; end process; process(currentstate) begin case currentstate is when s1 => if (a = '1') then b <= '1'; c <= '0'; else b <= '1'; c <= '1'; end if; nextstate <= s2; when s2 => -- b doesnt change state from s1 to here, do I need to define what it is here? if (a = '1') then b <= '1'; c <= '1'; else b <= '1'; c <= '0'; end if; nextstate <= s3; when s3 => if (a = '1') then b <= '0'; c <= '0'; else b <= '1'; c <= '1'; end if; nextstate <= s1; end case; end process; end Behavioral; 

From my understanding, if I do not, then the latches are created?

This is not very similar to this example, but if I have a machine with more than 10 outputs and more than 10 states, then my VHDL files start to look incredibly dirty, and I'm sure it should be a bad practice to copy and paste one and the same thing over and over. Is there a better way to do this?

edit: Can I determine the default state for output? IE set b to be 1 outside of all processes, and then only determine what it is in cases where it is 0? Will this work?

+6
source share
4 answers

Yes, you will trigger latches if you only control signals that must be combinatorial in some branches of the process.

However, you can determine the default state for a signal by simply assigning it a value before the case (but within the same process). For instance:

 process(currentstate, a) begin b <= '1'; c <= '1'; case currentstate is when s1 => if (a = '1') then c <= '0'; end if; nextstate <= s2; when s2 => -- b doesnt change state from s1 to here, do I need to define what it is here? if (a /= '1') then c <= '0'; end if; nextstate <= s3; when s3 => if (a = '1') then b <= '0'; c <= '0'; end if; nextstate <= s1; end case; end process; 
+6
source

Three problems with your example:

The last port in the port list should not have a semicolon:

 port ( clk : in std_logic; a : in std_logic; b: out std_logic; c: out std_logic -- no semicolon here!!! ); 

You should not have an else statement in your registration process. Although this is likely to be adopted with tools, it will confuse your VHDL developers.

 process (clk) begin if(rising_edge(clk)) then currentstate <= nextstate; end if; end process; 

In your combinational logic, the sensitivity list should contain all the signals that you are reading: process(a, currentstate) . In this particular case (again) everything will work well, but you must release the latches or cause other problems if the sensitivity list is incorrect.

Regarding your question:

  • Yes, you need to assign a value (for each state) to each signal in the combinational process.
  • As Tomi mentions, you can easily do this by assigning a default value at the beginning of the process.
  • But you can also write an entire state machine in one synchronous process. Thus, you do not need to assign a value to each signal in each state.
+7
source

Only a note to Philippe’s answer (can’t you comment on it directly?) ..

I prefer to write state machines in two types of processes. This makes it very clear where you expect scheduled triggers and where not. It is also a little more describing hardware - for example, creating a state computer with board level logic, for example. The registered device corresponds to the state process <= next_state, and the case statement maps to the array and / or before the state register.

Having said that, I usually use one process state machine for small simple tasks and move on to two technological machines for larger ones. I even sometimes use the third process to organize government outlets in different groups of tasks, but not often. A really big state machine, as a rule, tells me that architecture needs work.

+3
source
 process (clk) begin if(rising_edge(clk)) then currentstate <= nextstate; end if; end process; 

Hi

the above process is problematic, but not because of the sensitivity list. It is enough to declare clk for a sequential process. Simulation and synthesis tools will not have problems with this. clk is the fastest change / transition signal after everything in your code.

However, you should use asynchronous reset (preferably). Of course, manufacturers now claim that a reset is not even needed for FPGA design; they occur at boot time. Or they offer a synchronous reset.

However, asynchronous reset is valuable for a board-based environment.

In short: add reset to your design and correct its behavior correctly.

Regards, Nikolaos Cavvadius

0
source

Source: https://habr.com/ru/post/888096/


All Articles