cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
zvs
Adventurer
Adventurer
1,474 Views
Registered: ‎04-08-2017

One-hot FSM extraction in Vivado

Jump to solution

Hi, all!

I’d like to ask a question to Xilinx employees, who really know what’s going on inside the Vivado Synthesizer.

In this forum there are many posts regarding FSM handling by the Vivado, but for some reasons Xilinx traditionally keep silence.

 

So, here's the question.

I have an FSM (for convenience file is attached):

library ieee;
use ieee.std_logic_1164.all;


entity tst_fsm is
   port
   (
      clk : in std_logic;
      ctl : in std_logic;
      dmy0, dmy1, dmy2, dmy3 : out std_logic;
      ret : out std_logic
   );
end entity;


architecture tst_fsm_arch of tst_fsm is
   
   type t_st is (ST_S0, ST_S1, ST_S2, ST_S3);
   signal st : t_st := ST_S0;
   
   attribute fsm_encoding : string;
   attribute fsm_encoding of st : signal is "one_hot";
   
   signal dmy0_rg, dmy1_rg, dmy2_rg, dmy3_rg : std_logic := '0';
   signal ret_rg : std_logic := '0';
   
   
begin
   
   process(clk)
   begin
      if rising_edge(clk) then
         
         case st is
            when ST_S0 =>
               if ctl = '1' then
                  st <= ST_S1;
               end if;
               ret_rg <= '0';
            
            when ST_S1 =>
               if ctl = '1' then
                  st <= ST_S2;
               end if;
               ret_rg <= '0';
            
            when ST_S2 =>
               if ctl = '1' then
                  st <= ST_S3;
               end if;
               ret_rg <= '0';
            
            when ST_S3 =>
               if dmy0_rg = '1' then
                  if dmy1_rg = '1' then
                     if dmy2_rg = '1' then
                        if ctl = '1' then
                           st <= ST_S0;
                        end if;
                        dmy3_rg <= not dmy3_rg;
                     end if;
                     dmy2_rg <= not dmy2_rg;
                  end if;
                  dmy1_rg <= not dmy1_rg;
               end if;
               dmy0_rg <= not dmy0_rg;
               ret_rg <= '1';
         end case;
         
      end if;
   end process;
   
   
   dmy0 <= dmy0_rg;
   dmy1 <= dmy1_rg;
   dmy2 <= dmy2_rg;
   dmy3 <= dmy3_rg;
   
   ret <= ret_rg;
   
   
end architecture;

After synthesizing this module as a top, I've got a very strange result (I'm using Vivado 2019.1, xc7k160tffg676-2 device). At the following fig the extracted logic for the ST_S3 state is shown:

1.jpg

As you can see, the resulting schematic has redundant logic. Why??? For the one-hot encoding scheme the red-marked regs shouldn’t be taken into account for the ST_S3 next state logic!!!

Other state regs have the similar problem. This is obviously an incorrect behavior.

 

When I comment out one nested ‘if’ statement in the ST_S3 branch, things go right and the FSM is handled correctly (of course, the resulting code is not one I need), see:

            when ST_S3 =>
               if dmy0_rg = '1' then
                  if dmy1_rg = '1' then
                     --if dmy2_rg = '1' then
                        if ctl = '1' then
                           st <= ST_S0;
                        end if;
                        dmy3_rg <= not dmy3_rg;
                     --end if;
                     dmy2_rg <= not dmy2_rg;
                  end if;
                  dmy1_rg <= not dmy1_rg;
               end if;
               dmy0_rg <= not dmy0_rg;
               ret_rg <= '1';

And here's the extracted schematic for the ST_S3 reg:

2.jpg

All is fine, as you see. There is nothing redundant here, exactly as it should be. Other states are also ok.

So, can you explain this behavior?
I need the Vivado to handle my original FSM exactly in the same way it handles the modified one. Have any suggestions to accomplish this this?

 

By the way, setting the '-fsm_extraction' option in the Synthesis Settings window to 'one_hot', also gives a very strange synthesized schematic. It's treated differently than the RTL 'fsm_encoding' attribute. You can see this for yourself, using attached file.

Can you explain the mentioned strangeness, also?

 


Regards, Victor.

0 Kudos
1 Solution

Accepted Solutions
anusheel
Moderator
Moderator
1,111 Views
Registered: ‎07-21-2014

@zvs 

After analyzing the generated netlist, we found that the generated FSM Mux is not optimal and hence we have filed a CR for this issue to generate an optimal netlist in future releases. 

Thanks
Anusheel 

View solution in original post

0 Kudos
8 Replies
blindobs
Adventurer
Adventurer
1,459 Views
Registered: ‎09-13-2018

hi,

i think that you see correct tool behavior. One-hot state is not only 1 register per bit but synthesis also must place logic to make sure that only one _onehot_*reg is asserted at any given clock time, and ofc that only two bits must change per clock - so synthesis in first case decided that its optimal to use state0 and state1 regs, where in second case dmX_reg suits this purpose better

 

0 Kudos
zvs
Adventurer
Adventurer
1,448 Views
Registered: ‎04-08-2017

Hi, blindobs.

You are misunderstanding the nature and purpose of the one-hot encoding. The one-hot DO imply to have one dedicated 1-bit reg for every state. And it DO NOT imply to worry about all the bits of the encoded full-length state reg, but only necessary ones.

This is exactly how it would be, if you made a schematic by hand. You would naturally used the one-hot.

You can synthesize that source file in XST, and you'll see all the beauty and power of the one-hot. XST does it correctly.

 

Regards, Victor.

0 Kudos
bitjockey
Adventurer
Adventurer
1,279 Views
Registered: ‎03-21-2011

Could it be that Vivado, unlike Synplify, doesn't give you a choice of unsafe one-hot FSMs and chooses 'safe' for you?  I.e. if it is one-hot, it has to look at ALL states in case it gets into a non-one-hot condition (cosmic ray flips a bit, etc.).   What happens if your one-hot state s[0..3] becomes "1010" by accident?

See https://class.ece.uw.edu/475/peckol/doc/VerilogStateMachines/behaviouralVerilogSM-0.pdf

For all those that say "but why do you want one-hot if you don't want 'safe' behavior?":  The answer could be logic minimization.  Not only do some FSM graphs get very low-logic, the outputs can also often be lower logic than counter or grey coding, particularly if the synth tool isn't good at picking which codes go to which states.  I.e. if a counter based FSM has outputs based on the "0111" and following "1000" state.

Not that many folks care about saving a LUT or two here or there on modern big-chip designs anymore...

Update: looks like ISE also has 'safe' as an option https://www.xilinx.com/support/documentation/sw_manuals/xilinx10/isehelp/pp_db_xst_hdl_synthesis_options.htm , haven't been able to google Vivado though yet...

Update update: It looks https://www.xilinx.com/support/answers/51237.html  like 'safe' FSM is not implemented in Vivado unless you give it a /*synthesis fsm_safe_state = ... */ pragma???  I also wonder if the (*full case*) directive in the case of the FSM would make a difference?

0 Kudos
zvs
Adventurer
Adventurer
1,256 Views
Registered: ‎04-08-2017

Hi, bitjockey.

 

It's certainly not a 'safe' one-hot, because not all the next state logic functions here check every state FF. For example, the logic for the ST_S2 redundantly checks ST_S0 FF only. And the ST_S1 logic has no redundant checkings at all.

Also, the modified example (see the very first post) gives a correct 'unsafe' one-hot without any redundancy, exactly as it should be.

So, the Vivado doesn't choose 'safe' without giving any choice to the user, it merely behaves unexpectedly.

As I found out, the matter is in the depth of the nested if statements. If you have four or more nested "if"s, you'll get a surprise.

 

Also, I'd like to add some words more. Maybe, some folks will find it useful.

When you don't apply any attributes to the 'st' signal in the RTL, but instead choose the '-fsm_extraction' option with the 'one_hot' value assigned in the Synthesis Settings window, you get a completely different result. See:

3.jpg

Here we have the full-length state reg with a common CE line and muxed D inputs. The CE line is driven by the output of a complex logic function. The function has all the signals used in the FSM as inputs. So, every signal has to be routed to every state FF, even though the most of them are not needed for a given FF. D-input muxes are also controversial.

So, for me the conclusion here, is to avoid using the '-fsm_extraction' setting with the 'one_hot' value. It's better to leave 'auto' and control further through the RTL, if needed.

The source code provided is just an example to illustrate the problem.The real-life FSMs have much more states and much more complex state-transitioning logic.

With the correct unsafe one-hot you could easily get a light-weight fast implementation. But, this often is not the case with Vivado. Instead you get a bulky implementation, heavily entangled with unnecessary routing and degraded performance. In such cases the sequential encoding can be a more advantageous choice.


I didn't ever used the Synplify. Maybe it does the job beter.

0 Kudos
anusheel
Moderator
Moderator
1,231 Views
Registered: ‎07-21-2014

@zvs 

We are looking into this issue. I will update the thread soon.

Thanks
Anusheel 

0 Kudos
anusheel
Moderator
Moderator
1,112 Views
Registered: ‎07-21-2014

@zvs 

After analyzing the generated netlist, we found that the generated FSM Mux is not optimal and hence we have filed a CR for this issue to generate an optimal netlist in future releases. 

Thanks
Anusheel 

View solution in original post

0 Kudos
zvs
Adventurer
Adventurer
1,086 Views
Registered: ‎04-08-2017

Hi, @anusheel 

Thanks for the reply.

 

Regards,

Victor.

 

0 Kudos
maps-mpls
Mentor
Mentor
1,046 Views
Registered: ‎06-20-2017

>Update update:...

Just to jump in...check out UG901 for Vivado.   See DocNav or google for the version of this document that matches your install.

In general, safe state machines are going to be discussed by the synthesizer user guide.  In general, the way  synthesizer handles a safe state machine is synthesizer dependent, and is often done via user defined attributes (from our perspective, vendor defined).

safe.PNG

*** Destination: Rapid design and development cycles *** Unappreciated answers get deleted, unappreciative OPs get put on ignored list ***
0 Kudos