04-24-2016 10:27 AM
I have a large FSM, with 113 states. So encoding really does matter, only one_hot gives good timing.
After fixing the 'next state signal initialization' issue (see posting) the FSM is inferred, but not re-encoded. I see in the log
INFO: [Synth 8-5534] Detected attribute (* fsm_encoding = "one_hot" *) [...] INFO: [Synth 8-802] inferred FSM for state register 'R_STATE_reg' in module 'pdp11_sequencer' ..... --------------------------------------------------------------------------------- Finished RTL Optimization Phase 2 : ...
but no message like
INFO: [Synth 8-3354] encoded FSM with state register '...' using encoding '...'
I've tried with attribute in the code, and with fsm_extract = 'one_hot' synthesis settings.
The state register has 7 bits (needed to encode 113 states). The properties of the state flop indicate funny enough
FSM_ENCODING = 'one_hot'
see attached screen shot.But this is clearly not correct, there are 7 and not 113 state regs. And the logic depth of the next state logic is as deep as the abyss.
A screen shot of the message summary and the full synthesis log are also attached.
Side note: this code was happily synthesized by ISE for years resulting in an one_hot encoded FSM.
What can prevent the one_hot encoding of an inferred FSM ?
Any hint/help very welcome, with best regards, Walter
P.S.: Using Vivado 2016., but 2015.4 shows same behaviour.
05-04-2016 12:54 PM
Check your syntax, I believe the correct syntax is "one-hot" and not "one_hot" as you have entered.
You can set an attribute to almost any value (as your log file noted), but generally only recognized with correct syntax and if invalid there is usually no error message.
Setting to an invalid value results in the default of encoded being used.
05-04-2016 04:55 PM
I have definitely seen it work with one_hot (underscore and lowercase); pasting an xdc snippet I just used below in 2015.4:
set_property fsm_encoding one_hot [get_cells *curr_st* -filter "is_sequential==TRUE"]
"curr_st" is my state register; the *wildcards* are there to match it after synthesis prepends cell names with "FSM_one_hot_" and the is_sequential attribute is there to make sure it only applies to flops in my FSM, not any combo logic that may inherit "curr_st" in part of its name.
Not sure what's preventing one_hot encoding of your FSM, unless it's the size, or if the fsm_extraction setting didn't stick.
Mine went through fine with 10 states represented by 10 flops. You can see the state remapping in the impl_synth/runme.log file. (Sadly, I haven't found more user-friendly ways to get info like report_fsm.)
05-04-2016 10:07 PM
05-05-2016 08:52 AM
My initial reply was a bit hasty; upon closer reading, it looks like you did everything right.
FWIW, it was easy to extend my trivial 10-state FSM to 113 states, encoded as one_hot, and confirm that the synthesized result contained 113 state registers.
On caveat though, is that the FSM extraction/optimization takes place during synthesis, meaning that if you look at the RTL schematic and netlist pane viewer after elaboration, you will only see 7 flip-flops for the state register. After synthesis, I see the change from 7 to 113 in mine.
However, I also observed something odd in the final result: My curr_st reg declaration used an enumerated type with 113 states defined externally in a package. That way, I could output a copy of the state register values to a top-level port, and leave the entity declaration of that port generic enough allow adjustment of bit width based on the chosen encoding:
package types is
type t_state is (s0, s1, s2, s3, s4, s5, s6, s7, s8, s9,
s10, s11, s12, s13, s14, s15, s16, s17, s18, s19,
s20, s21, s22, s23, s24, s25, s26, s27, s28, s29,
s30, s31, s32, s33, s34, s35, s36, s37, s38, s39,
s40, s41, s42, s43, s44, s45, s46, s47, s48, s49,
s50, s51, s52, s53, s54, s55, s56, s57, s58, s59,
s60, s61, s62, s63, s64, s65, s66, s67, s68, s69,
s70, s71, s72, s73, s74, s75, s76, s77, s78, s79,
s80, s81, s82, s83, s84, s85, s86, s87, s88, s89,
s90, s91, s92, s93, s94, s95, s96, s97, s98, s99,
s100, s101, s102, s103, s104, s105, s106, s107, s108, s109,
s110, s111, s112);
end package types;
entity state_mach is port (
rst : in std_logic;
clk : in std_logic;
run : in std_logic;
odd : in std_logic;
err : out std_logic;
smon : out t_state); -- intended as arbitrary, generically adjustable width, for state register monitor
end entity state_mach;
The end result though, is that despite having 113 state registers for the 1-hot FSM, Vivado generates logic to re-encode those 113 bits into a 7-bit vector, and generates a 7-bit output port for smon.
It's sort of a chicken/egg problem about picking port widths in the entity first, or recognizing the FSM and choosing an encoding first to drive the port width. I'm not sure if VHDL has a rule for that, or if the result is tool-dependent, but I found it to be an interesting choice (generating all that logic to re-encode outputs as 7-bit).
Sorry to wander a little bit off topic, but I thought this might be of interest to Xilinx. :)
05-22-2016 05:46 AM
05-22-2016 06:19 AM
was traveling, so sorry for the delay in answering your request.
The source is attached as ready to use vivado 2016.1 project in example_project.tar.
Just untar and
vivado -mode gui project_mflow/project_mflow.xpr
Use -fsm-extraction one_hot. The FSM is recognized, but not re-encoded.
The synthesis log from vivado is attached too as vivado_syn.txt.
The same source synthesizes well under ISE since many revisions and gives a one_hot encodes FSM. The xst log for SIE 14.7 is attached as ise_xst.txt.
And two notes:
05-26-2016 11:56 AM
after some more systematic testing I localized the culprit !
At the very end of the admittedly very large and complex state machine is a 'state number generator' which generates a state number based on the current state. It is implmented in a very straight forward way in proc_snum like
proc_snum : process (R_STATE) variable isnum : slv8 := (others=>'0'); begin isnum := (others=>'0'); case R_STATE is when s_idle => isnum := x"00"; when s_cp_regread => isnum := x"01"; when s_cp_rps => isnum := x"02"; ..... when others => isnum := x"ff"; end case; DM_STAT_SE.snum <= isnum; end process proc_snum;
This construct prevents that the FSM is re-encoded as 'one_hot'.
I have added 3 ready to use vivado 2016.1 projects
Bottom line is that even though that one_hot encoding was explicitely requested via
attribute fsm_encoding : string;
attribute fsm_encoding of R_STATE : signal is "one_hot";
the synthesis under some circumstances decides to go for some form of binary encoding.
With best regards, Walter
05-28-2016 01:34 PM
I've tried to create a reproducer for this problem, but that failed, in an interesting way.
I've created a FSM with 120 states and enough transitions that they all are reached.
And I've added the 'state number generator' logic, which caused the problems, as
proc_snum : process (R_STATE) variable isnum : slv7 := (others=>'0'); begin isnum := (others=>'0'); case R_STATE is when s_000 => isnum := slv(to_unsigned( 0,7)); when s_001 => isnum := slv(to_unsigned( 1,7)); ... snip when s_118 => isnum := slv(to_unsigned(118,7)); when s_119 => isnum := slv(to_unsigned(119,7)); when others => isnum := "1111111"; end case; SNUM <= isnum; end process proc_snum;
A ready to use vivado 2016.1 project with the sources is attached as example_reproducer.tar.
The surprise is that this code happily synthesizes and gives a one_hot encoded FSM, the log file has
INFO: [Synth 8-802] inferred FSM for state register 'R_STATE_reg' in module ...
INFO: [Synth 8-3354] encoded FSM with state register 'R_STATE_reg'
using encoding 'one-hot' in ...
So the construct used in proc_snum, which decodes all states and generates the binary number, is not the only reason why the code send with example_orig.tar doesn't produce a properly encode FSM. There must be another factor involved.
Any help or hint to resolve this is highly welcome.
With best regards, Walter
05-29-2016 01:56 AM
"Sorry to wander a little bit off topic, but I thought this might be of interest to Xilinx. :)"
Turned out that exactly such a 'state number generator' is causing the observed problem. See here and here in this thread. The issue raised in this thread is that vivado recognizes a FSM, and than refuses to re-encode it, even though one_hot is requested via fsm_extraction and as signal attribute. This without any INFO or WARNING. That should definitely not happen and imho should be corrected in vivado.
So I started to look for other ways to express it an tried
I posted the surprising outcome is a separate thread.