UPGRADE YOUR BROWSER

We have detected your current browser version is not the latest one. Xilinx.com uses the latest web technologies to bring you the best online experience possible. Please upgrade to a Xilinx.com supported browser:Chrome, Firefox, Internet Explorer 11, Safari. Thank you!

cancel
Showing results for 
Search instead for 
Did you mean: 
Highlighted
Scholar mistercoffee
Scholar
10,551 Views
Registered: ‎04-04-2014

FSM not inferred - does it matter?

Ok,

 

For a while I have contemplated the best way to do an FSM. I have read comments on the forum, I have read the guide in the synthesis notes, and in the end I used a variation which I thought was the best all round. However, the synthesis tool (Vivado 2014.2) doesn't infer an FSM from my code.

 

The recommend way, in the synthesis guide for Vivado, is a single clocked process like the following.

 

type STATE_T is (S01, S02, S03);
signal cs: STATE_T := S01;

state_machine: process (clk) is
begin
   if rising_edge clk then
   	if rst = ‘1’ then
   		cs <= S01;
   	else
   		case cs is

   		when S01 =>
          	if input_1 = ‘0’ then
	      		cs <= S02;
	      		output_1 <= ‘0’;
	      		output_2 <= ‘0’;
	      		output_3 <= ‘1’;
          	else
               		cs <= S01
	      		output_1 <= ‘0’;
	      		output_2 <= ‘0’;
	      		output_3 <= ‘0;
		end if;

   		when S02 =>
          	if input_2 = ‘1’ then
	      		cs <= S03;
	      		output_1 <= ‘1’;
	      		output_2 <= ‘1’;
	      		output_3 <= ‘1’;
          	else
               		cs <= S01
	      		output_1 <= ‘0’;
	      		output_2 <= ‘0’;
	      		output_3 <= ‘0’;
		end if;

   		when S03 =>
         	if input_3 = ‘1’ then
	      		cs <= S01;
	      		output_1 <= ‘0’;
	      		output_2 <= ‘0’;
	      		output_3 <= ‘0’;
          	else
               		cs <= S03
	      		output_1 <= ‘1’;
	      		output_2 <= ‘1;
	      		output_3 <= ‘1’;
		end if;

   		when others =>
         		cs <= S01;
			output_1 <= ‘0’;
			output_2 <= ‘0’;
			output_3 <= ‘0’;
   		end case;
	end if;
end if;

end process;

So, the advantages here are:

1. Outputs are clocked.

2. It's easier to read as everything is in one process.

3. Outputs updated one cycle after the inputs change (not two as sometimes when using two processes and a next state variable).

 

There is one disadvantages I don't like:

- You have to specify the set of outputs in more than one place. For example here there are four places where we go to state S01 next and in each place we specify the state of the 3 outputs. This, in my opinion, could lead to mistakes. If you want to change the value of an output for a particular state (you are debugging and find you need to set it differently than you thought for a particular state) you have to go to each place you assign it and you could miss one out.

 

Having a separate clocked process for outputs, with a case statement based n the current state, solves this dilemma but loses you the advantages of a single clocked process listed above

 

My solution was to do as follows:

 

type STATE_T is (S01, S02, S03);
signal cs: STATE_T := S01;

state_machine_2: process (clk) is
   variable cs_var: STATE_T := S01;
begin
   if rising_edge clk then
   	if rst = ‘1’ then
   		cs <= S01;
   	else
   		case cs is

   		when S01 =>
          	if input_1 = ‘0’ then
	      		cs_var <= S02;
	      		output_1 <= ‘0’;
	      		output_2 <= ‘0’;
	      		output_3 <= ‘1’;
          	else
               		cs_var<= S01
	      		output_1 <= ‘0’;
	      		output_2 <= ‘0’;
	      		output_3 <= ‘0;
		end if;

   		when S02 =>
          	if input_2 = ‘1’ then
	      		cs_var <= S03;
	      		output_1 <= ‘1’;
	      		output_2 <= ‘1’;
	      		output_3 <= ‘1’;
          	else
               		cs_var <= S01
	      		output_1 <= ‘0’;
	      		output_2 <= ‘0’;
	      		output_3 <= ‘0’;
		end if;

   		when S03 =>
         	if input_3 = ‘1’ then
	      		cs_var <= S01;
	      		output_1 <= ‘0’;
	      		output_2 <= ‘0’;
	      		output_3 <= ‘0’;
          	else
               		cs_var <= S03
	      		output_1 <= ‘1’;
	      		output_2 <= ‘1;
	      		output_3 <= ‘1’;
		end if;

   		when others =>
         		cs_var <= S01;
			output_1 <= ‘0’;
			output_2 <= ‘0’;
			output_3 <= ‘0’;
   		end case;

   		case cs_var is

   		when S01 =>
	      		output_1 <= ‘0’;
	      		output_2 <= ‘0’;
	      		output_3 <= ‘0;

   		when S02 =>
	      		output_1 <= ‘0’;
	      		output_2 <= ‘0’;
	      		output_3 <= ‘1’;

   		when S03 =>
	      		output_1 <= ‘1’;
	      		output_2 <= ‘1;
	      		output_3 <= ‘1’;

   		when others =>
			output_1 <= ‘0’;
			output_2 <= ‘0’;
			output_3 <= ‘0’;
   		end case;

		cs <= cs_var;

	end if;

end if;

end process;

So basically I have two case statements within one clocked process. the first statement uses the cs state SIGNAL to choose a next cs_var state VARIABLE based on the current inputs. The second case statement used the cs_var state VARIABLE, that has just been assigned, to set the outputs for that particular state. At the end of it all I assign the state variable to the state signal.

 

By using two case statements I keep the outputs and next state separate, making it easier to read and make changes. You have to use a state variable so that you can assign the next state in the current clock cycle and use it to set the outputs for the next clock cycle.

 

However, the syntehsis tool has not inferred an FSM!

So:

1. Does it matter?

2. Is my approach a good idea?

3. If so can the tool be made to recognise this approach in future releases?

4. Are there any disadvantages to my method? (it may not be new, but I haven't seen it anywhere else...).

 

Thanks

Tags (2)
0 Kudos
13 Replies
Xilinx Employee
Xilinx Employee
10,544 Views
Registered: ‎08-02-2011

Re: FSM not inferred - does it matter?

There is one disadvantages I don't like:
- You have to specify the set of outputs in more than one place. For example here there
are four places where we go to state S01 next and in each place we specify the state of the
3 outputs. This, in my opinion, could lead to mistakes. If you want to change the value of
an output for a particular state (you are debugging and find you need to set it differently
than you thought for a particular state) you have to go to each place you assign it and you
could miss one out.

You can use default assignment to get around this:

http://stackoverflow.com/questions/6001025/implementing-a-fsm-in-vhdl 

www.xilinx.com
0 Kudos
Scholar mistercoffee
Scholar
10,518 Views
Registered: ‎04-04-2014

Re: FSM not inferred - does it matter?


@bwiec wrote:
There is one disadvantages I don't like:
- You have to specify the set of outputs in more than one place. For example here there
are four places where we go to state S01 next and in each place we specify the state of the
3 outputs. This, in my opinion, could lead to mistakes. If you want to change the value of
an output for a particular state (you are debugging and find you need to set it differently
than you thought for a particular state) you have to go to each place you assign it and you
could miss one out.

You can use default assignment to get around this:

http://stackoverflow.com/questions/6001025/implementing-a-fsm-in-vhdl 


I have seen that used and have considere dit. It definitely works in simple cases, and it even in larger machines with more outputs I suspect it would still simplify things somewhat. But you still need to remember to assign the non-default state, potentially in more than one place, so does it really address my issue? I'm not so sure.

 

Also, I like my method because it groups all the output values for a particular state in one place, so it's really clear what that state is doing. In the default assignment method you have to look both at where the next state is assigned (in the case statement) and also right at the top of the case statement (which may not be in view in the code window) to understand what that state is doing with all of the outputs. I'm not sure I am a fan of it for that reason.

 

But thanks for commenting!

 

0 Kudos
Instructor
Instructor
10,481 Views
Registered: ‎08-14-2007

Re: FSM not inferred - does it matter?

In general, the fact that an FSM is inferred only matters if you have trouble meeting timing.  If synthesis doesn't recognise your code as an FSM, you get the equivalent of an FSM with "user" encoding unless synthesis manages to rip out some of your state variable (for example if you already have enough outputs to encode the state, you may lose some or all bits of the state variable due to duplicate register removal).  Either way, the hardware should be logically equivalent.

-- Gabor
0 Kudos
Participant pete_128
Participant
10,459 Views
Registered: ‎04-02-2016

Re: FSM not inferred - does it matter?

Hi,

 

Its odd that you are using non-blocking assignments on the cs_var variable. Did you mean to use := instead? You also set the outputs in the first case statement but wont all those results be discared by the second? The case 01 is seconds case is redundant. Does this code infer an FSM for you? :

 

 

type STATE_T is (S01, S02, S03);
signal cs: STATE_T := S01;

state_machine_2: process (clk) is
   variable cs_var: STATE_T := S01;
begin
   if rising_edge clk then
   	if rst = ‘1’ then
   		cs <= S01;
   	else
   		case cs is

   		when S01 =>
          	if input_1 = ‘0’ then
	      		cs_var := S02;
          	else
               		cs_var := S01;
		end if;

   		when S02 =>
          	if input_2 = ‘1’ then
	      		cs_var := S03;
          	else
               		cs_var := S01;
		end if;

   		when S03 =>
         	if input_3 = ‘1’ then
	      		cs_var := S01;
          	else
               		cs_var := S03;
		end if;

   		when others =>
         		cs_var := S01;
   		end case;

   		case cs_var is

   		when S02 =>
	      		output_1 <= ‘0’;
	      		output_2 <= ‘0’;
	      		output_3 <= ‘1’;

   		when S03 =>
	      		output_1 <= ‘1’;
	      		output_2 <= ‘1;
	      		output_3 <= ‘1’;

   		when others =>
			output_1 <= ‘0’;
			output_2 <= ‘0’;
			output_3 <= ‘0’;
   		end case;

		cs <= cs_var;

	end if;

end if;

end process;

 

0 Kudos
Scholar mistercoffee
Scholar
10,454 Views
Registered: ‎04-04-2014

Re: FSM not inferred - does it matter?

very sorry about that. My dev PC is not my internet PC so I just wrote some code to explain, but I wrote it in a hurry and made a mistake...

 

Your code is what I meant to write! 

 

Thanks

0 Kudos
Scholar mistercoffee
Scholar
10,452 Views
Registered: ‎04-04-2014

Re: FSM not inferred - does it matter?

it now looks much more readable! I should have checked it more thoroughly first..

0 Kudos
Participant pete_128
Participant
10,450 Views
Registered: ‎04-02-2016

Re: FSM not inferred - does it matter?

OK,

 

Did the := make the difference or still no inference?

0 Kudos
Scholar mistercoffee
Scholar
10,441 Views
Registered: ‎04-04-2014

Re: FSM not inferred - does it matter?

No, it didn't. My actual code, which is a different state machine to my example, was correct. I just tried to give a shorter example and made a mistake. 

 

I don't think the tool will let oyu assign a variable with =>, you tend to get an error...

0 Kudos
Instructor
Instructor
10,414 Views
Registered: ‎08-14-2007

Re: FSM not inferred - does it matter?

So that gets to the next question - are you having trouble meeting timing with this code?

If not, I'm not sure why you would care if synthesis recognises it as an FSM.

-- Gabor
0 Kudos
Scholar mistercoffee
Scholar
8,773 Views
Registered: ‎04-04-2014

Re: FSM not inferred - does it matter?

 

@gszakacs wrote:

So that gets to the next question - are you having trouble meeting timing with this code?

If not, I'm not sure why you would care if synthesis recognises it as an FSM.


In this particular instance no I'm not, but I did have a couple of timing problems in the past that were solved by subtly altering an FSM to allow the tool to infer it.

 

Really, I have been looking for a standard approach I can take with all my FSMs that I like and would consider best practise. I wanted to use the recommended method outlined in the synthesis guide for Vivado but there was a couple of things I disliked about it I mentioned above. So I tried to tweak it, only to find the FSM not inferred. I would prefer that not to be the case going forward, If I was to adopt this style for all my code in future...

 

I think I will actually go ahead with my method, and only alter it if I get timing issues. I know it is different from recommended, but I don't think it introduces any problems or has any particular disadvantages (outside of FSM inference). It is a personal preference thing...

 

Thanks

0 Kudos
Scholar mistercoffee
Scholar
8,766 Views
Registered: ‎04-04-2014

Re: FSM not inferred - does it matter?

I also suspect, and you might agree, that the timing issues I saw in the past were avoidable without having to alter the FSM. I know at the time I was migrating to Vivado and there were a few timing problems I had to overcome so it may not be completely due to the FSM. I know at one point I have to unroll a (not very big) for loop as Vivado made a horrible mess of synthesizing it, despite ISE having no problems. The timing for that module improved massively after that.

0 Kudos
Participant pete_128
Participant
8,701 Views
Registered: ‎04-02-2016

Re: FSM not inferred - does it matter?

Well, it matters because a non-semantic change in code shouldnt radically alter the compiled results.

 

TBH though if a feature requires you to code in very specific way then it defeats the purpose of coding in VHDL in the first place.


So to answer the orginal question, since your VHDL is valid synthesisable, "No it does not matter".

0 Kudos
Scholar mistercoffee
Scholar
8,626 Views
Registered: ‎04-04-2014

Re: FSM not inferred - does it matter?


@pete_128 wrote:

Well, it matters because a non-semantic change in code shouldnt radically alter the compiled results.

 

TBH though if a feature requires you to code in very specific way then it defeats the purpose of coding in VHDL in the first place.


So to answer the orginal question, since your VHDL is valid synthesisable, "No it does not matter".


I suppose my worry was that Vivado might have been making a mess of the synthesis because I wasn't conforming to it's coding standards. As I say, I have had it do this with a for loop I had, which was handled perfectly well in ISE, but became a monster once I ported to Vivado. Indeed when I did some digging I found a part of the synthesis guide advising against it. I was wondering if the FSM situation as similar.

 

Thanks

0 Kudos