>On Dec 3, 4:05=A0am, Thomas Stanka <usenet_nospam_va...@stanka-web.de> >wrote: >> > Yes code is very simple...I've already coded a version with 2 processa=>nd >> > unregistered output...but, to better >> > understand, I would like to discover if it is possible in oneprocess..=>. >> >> > In general..better 1 process and registered outout or 2 process andcho=>ose >> > if un/register output??? >> >> Why do you want to avoid the output register? Is it for latency or >> resource usage? Is there really no other sollution? >> I strongly suggest to register outputs whenever possible. For all >> other cases I tend to use concurrent signal assignments. Of course I >> use also combinatorical process in cases it would simplify concurrent >> statements (which is seldom the case) >> >> process (clk,rst) >> if reset =3D active then >> =A0 sig_a <=3D '0'; >> elsif rising_edge(clk) >> =A0sig_a <=3D input_a; >> end if; >> end process; >> >> comb_out <=3D (sig_a xor input_a) when fsm_state=3Didle else '0'; > >I agree with Thomas; in register-rich environment, use those regs. >Great for portability, modularity, and performance. > >I find the choices of fsm coding styles fascinating. Myself, I use the >dual method (make sure all inputs in sensitivity list of comb. >process!), but I always keep my "control" signals separate from either >of these processes, and try to register those as well. (e.g. in >clocked process, if ((pstate =3D s3) OR (pstate =3D s4) mux_select <=3D >DATA_A; else mux_select <=3D DATA_B;) > >But what's the desire to combine all processes into one? It certainly >is efficient coding; only one clk/reset structure. But I find that >method somewhat confusing to read and understand. In fact, when I have >to understand someone else's consolidated code, I'll rewrite it >stripping out everything but the fsm states. I'd rather read my FSM >flow in one process and my control variables somewhere else, but I >realize some designers feel the opposite way... >John >Hi, I would like to go deep in both methods...I already manage 2 process....now I would like to improve the 1 process knowledge to better fit my style to every situation... My conclusion is...when your output is regstered (probably very good choise) better to use 1 process style...when some/all outputs are unregistered better dive in 2 process style...that give more flexibility even if is more prone to errors (sensitivity list, inferred latch etc..)... Do you agree??? Thanx Carlo --------------------------------------- Posted through http://www.FPGARelated.com
FSM single process...BIG question
Started by ●December 2, 2010
Reply by ●December 3, 20102010-12-03
Reply by ●December 3, 20102010-12-03
Textbooks are seldom about state of the art in anything. Just because they seem to be in unanimous agreement about one coding method does not mean that the state of the art agrees. Two-process FSMs require twice the declarations, require complex sensitivity lists, require additional code to avoid latches, prohibit using variables to keep local data local, thwart simulation optimizations that take advantage of common sensitivity lists, and a host of other problems. There are two different practical issues at play here. One is whether an output is a combinatorial function of just the state, and one is whether the output is a also a combinatorial function of some combinatorial inputs. The former can be mitigated by assigning registered outputs "early" (i.e. when the FSM transitions to the state, not just when the FSM is already in the state), or by assigning outputs from the state variable after the clocked if statement ends. You appear to want the output to be the latter: a combinatorial function of the registered state and of the unregistered inputs. While you can combine both into one process (with the combinatorial input in the sensitivity list) as Mike has suggested, that is asking for trouble, and if you don't correct the sensitivity list, then the simulation and synthesis results will differ slightly, depending on how/when the output is read by other processes/hardware. It is also potentially prone to creating latches, to which a simple clocked process is immune. You really should create this output in a separate process (or concurrent assignment), but there is no need to separate the FSM into two processes. The best way to avoid latches is to avoid combinatorial processes. If you cannot avoid a combinatorial process, keep it as simple as possible (doing only what has to be done combinatorially) and use up front default assignments. I would suggest you look at your design requirements, and decide what must be combinatorial, and what can tolerate a clock delay. Do you need to avoid a clock delay between tx_valid and tx_data? Do you need to avoid a clock delay between data_in and tx_data? Do you need to avoid a clock delay between tx_ready and tx_data? Make sure you really need to avoid that clock delay. "It would be better if..." does not count. A working design that is simple to write, understand and maintain is much better than a design that is none of those but happens to be a clock cycle faster. Find a way to accomplish combinatorially only what needs to be combinatorial. It appears that tx_data is merely a function of tx_valid, tx_ready, and data_in. What exactly do you need an FSM for? You could use an FSM for error handling (what happens if tx_valid goes high, then low, and tx_ready never fired?). But you don't appear to be using it for that (maybe just to simplify the example?). Andy
Reply by ●December 3, 20102010-12-03
On Dec 2, 5:46 pm, Andy <jonesa...@comcast.net> wrote:> On Dec 2, 2:16 pm, rickman <gnu...@gmail.com> wrote: > > > > > On Dec 2, 9:43 am, "carlob" <carlo.beccia@n_o_s_p_a_m.libero.it> > > wrote: > > > > Hi all, > > > I've a problem to efficiently unregister output from FSM written in a > > > single process style... > > > > in FSM synch process (don't pay attention to syntax..): > > > > case IDLE: > > > if (pippo = '1') then > > > next_state <= START; > > > if (pluto = '1') then > > > outp <= '0'; > > > else > > > outp <= '1'; > > > end if; > > > end if; > > > > outp is registered...if I want to avoid that register I should (in another > > > process) duplicate a lot of logic: > > > > if (state = IDLE) then > > > if (pippo = '1' and pluto = '1') then > > > outp <= '0' > > > elsif (pippo = '1' and pluto = '0') then > > > outp <= '1'; > > > else outp <= 'Z' -- for example > > > end if; > > > end if; > > > > Is it possible to unregister output without duplicating that logic (It > > > seems to me very poor coding...)... > > > > I've read something about using variables...but I don't understand exactly > > > how...please show me an example... > > > You might find it easier to separate the state machine from the state > > register. Then you define all your state transitions and outputs in a > > single process just as you have above, but not a clocked process. > > Instead you need two signals, CurState and NxtState. The > > combinatorial process updates NxtState in terms of CurState with > > CurState and all the other input signals in the sensitivity list, just > > as you have it written now with the outputs registered. The clocked > > process just defines the CurState register in terms of the NxtState > > signal. The clocked process is idiot simple and so does not duplicate > > the code that you are worried about. > > > StateLogicPrc: process (CurState, pippo, pluto,...) begin > > -- if (rising_edge(clk)) then -- remove this sequential stuff from > > the process > > -- so you are just left with the logic... > > case CurState is > > when IDLE: > > if (pippo = '1') then > > next_state <= START; > > if (pluto = '1') then > > outp <= '0'; > > else > > outp <= '1'; > > end if; > > end if; > > ... > > end process StateLogicPrc; > > > StateRegPrc: process (rst, clk) begin > > if (rst = '1') then > > CurState <= StartingState; > > elsif (rising_edge(clk)) then > > CurState <= next_state; > > end if; > > end process StateRegPrc; > > > This style was taught in many text books some 10 years ago because > > some felt the tools did a better job with the two processes > > separated. Now the tools are pretty good no matter what and I think > > this is only used when the output signals are not to be registered as > > in your case. > > > Rick- Hide quoted text - > > > - Show quoted text - > > Rick, > > Your example illustrates exactly why combinatorial processes should be > avoided if possible. You have created a latch (or two)... > > I've read your posts long enough to know that you are an experienced, > talented designer, and in any real design, you would have taken care > of it. But not everyone knows that they need to take care of it, or > knows how. > > The best way to avoid a latch is to avoid a combinatorial process. > The 2nd best way is to include in every combinatorial process, a > default assignment for every output, right up front, before any > conditional logic. This is much easier and more fool-proof than simply > adding an else for every if. > > AndyI wasn't going to provide any code to the OP mainly because I didn't have time to worry with it. But I saw that a verbal explanation wasn't very good and I thought I could get away with a quick edit of his code. Obviously I made a mistake, but that doesn't make combinatorial processes bad. You can also create latches in concurrent statements too. Should you avoid using them as well? I remember when I was just learning VHDL there were things about using integers and variables that I just didn't get. I posted that someone should avoid using them. I was chided for that and I have remembered it since. Just because you don't know how to use a feature effectively doesn't mean no one else should. Rick
Reply by ●December 3, 20102010-12-03
On Dec 3, 7:58=A0am, "carlob" <carlo.beccia@n_o_s_p_a_m.n_o_s_p_a_m.libero.it> wrote:> >On Dec 3, 4:05=3DA0am, Thomas Stanka <usenet_nospam_va...@stanka-web.de> > >wrote: > >> > Yes code is very simple...I've already coded a version with 2 proces=s> a=3D > >nd > >> > unregistered output...but, to better > >> > understand, I would like to discover if it is possible in one > process..=3D > >. > > >> > In general..better 1 process and registered outout or 2 process and > cho=3D > >ose > >> > if un/register output??? > > >> Why do you want to avoid the output register? Is it for latency or > >> resource usage? Is there really no other sollution? > >> I strongly suggest to register outputs whenever possible. For all > >> other cases I tend to use concurrent signal assignments. Of course I > >> use also combinatorical process in cases it would simplify concurrent > >> statements (which is seldom the case) > > >> process (clk,rst) > >> if reset =3D3D active then > >> =3DA0 sig_a <=3D3D '0'; > >> elsif rising_edge(clk) > >> =3DA0sig_a <=3D3D input_a; > >> end if; > >> end process; > > >> comb_out <=3D3D (sig_a xor input_a) when fsm_state=3D3Didle else '0'; > > >I agree with Thomas; in register-rich environment, use those regs. > >Great for portability, modularity, and performance. > > >I find the choices of fsm coding styles fascinating. Myself, I use the > >dual method (make sure all inputs in sensitivity list of comb. > >process!), but I always keep my "control" signals separate from either > >of these processes, and try to register those as well. (e.g. in > >clocked process, if ((pstate =3D3D s3) OR (pstate =3D3D s4) mux_select <==3D3D> >DATA_A; else mux_select <=3D3D DATA_B;) > > >But what's the desire to combine all processes into one? It certainly > >is efficient coding; only one clk/reset structure. But I find that > >method somewhat confusing to read and understand. In fact, when I have > >to understand someone else's consolidated code, I'll rewrite it > >stripping out everything but the fsm states. I'd rather read my FSM > >flow in one process and my control variables somewhere else, but I > >realize some designers feel the opposite way... > >John > > Hi, > I would like to go deep in both methods...I already manage 2 process....n=ow> I would like to improve the 1 process knowledge to better fit my style to > every situation... > > My conclusion is...when your output is regstered (probably very good > choise) better to use 1 process style...when some/all outputs are > unregistered better dive in 2 process style...that give more flexibility > even if is more prone to errors (sensitivity list, inferred latch > etc..)... > > Do you agree???I agree that I evaluate every case on its own merits. The other thing you could do is to use one process for the state machine and then use concurrent statements for the outputs. I don't use combinatorial processes very often. There are also times when I use concurrent statements for intermediate logic in the state machine. It all depends on what is more clear and that would be up to you to decide. Rick
Reply by ●December 3, 20102010-12-03
Hi Andy, as you can understand I'm not an expert.....>The former can be mitigated by assigning registered outputs >"early" (i.e. when the FSM transitions to the state, not just when the >FSM is already in the state), or by assigning outputs from the state >variable after the clocked if statement ends. > >pYou appear to want the output to be the latter: a combinatorial >function of the registered state and of the unregistered inputs. >Could you elaborate better on this with an example on my FSM???>Find a way to accomplish combinatorially only what needs to be >combinatorial. It appears that tx_data is merely a function of >tx_valid, tx_ready, and data_in. What exactly do you need an FSM for? >You could use an FSM for error handling (what happens if tx_valid goes >high, then low, and tx_ready never fired?). But you don't appear to be >using it for that (maybe just to simplify the example?). > >AndyUhmm...I've written a fsm manly to describe the interface...the output becomes "01000000"/"11000000" when tx_valid goes high depending on data input...then stay on that value till tx_ready becomes high....at that point (on the next clock cycle) tx_data will be equal to datain till tx_valid goes to '0'...yes..I miss probably some error handling...the code is not completely written... Every signal on output should change when clock raise...and every signal in input should change/be checked according to the same clock front....input/output interfaces are synchronous to the clock... How do you describe all this combinatorially??? More simple ways are welcome....if you/somebody wanna help me... :-)) Thanx Carlo --------------------------------------- Posted through http://www.FPGARelated.com
Reply by ●December 3, 20102010-12-03
Andy I've tried one of your suggestion...tell me if I'm wrong (this is a quick written code...probably there are mistakes...pay attention to principle..)... if (reset='1') then act_txd_state := TXD_IDLE; v_delay := '0'; elsif (clk'event and clk ='1') then v_delay := '0'; case act_txd_state is when TXD_IDLE => if (txValid = '1') then act_txd_state := TXD_ACTIVE; end if; when TXD_ACTIVE => if (txReady = '1') then v_delay := '1'; act_txd_state := TXD_END; end if; when TXD_END => if (txValid = '0') then act_txd_state := TXD_IDLE; end if; end case; end if; if (act_txd_state = TXD_ACTIVE) OR (v_delay = '1')then if (dataIn = "00000000") then tx_data <= "01000000"; else tx_data <= "11000000"; end if; elsif (act_txd_state = TXD_END) then tx_data <= dataIn; else tx_data <= "00000000"; end if; This "should" be equivalent (not tested yet)...I've used v_delay FF to delay 1 clock the output change between ACTIVE and END...I've no more registered output...but I've been forced to add dataIn in the sensitivity list (to avoid latches)... That is change you were talking about?? Thanx Carlo --------------------------------------- Posted through http://www.FPGARelated.com
Reply by ●December 4, 20102010-12-04
On Dec 3, 12:42=A0pm, Andy <jonesa...@comcast.net> wrote:> Textbooks are seldom about state of the art in anything. Just because > they seem to be in unanimous agreement about one coding method does > not mean that the state of the art agrees. Two-process FSMs require > twice the declarations, require complex sensitivity lists, require > additional code to avoid latches, prohibit using variables to keep > local data local, thwart simulation optimizations that take advantage > of common sensitivity lists, and a host of other problems. > > There are two different practical issues at play here. One is whether > an output is a combinatorial function of just the state, and one is > whether the output is a also a combinatorial function of some > combinatorial inputs. > > The former can be mitigated by assigning registered outputs > "early" (i.e. when the FSM transitions to the state, not just when the > FSM is already in the state), or by assigning outputs from the state > variable after the clocked if statement ends. > > You appear to want the output to be the latter: a combinatorial > function of the registered state and of the unregistered inputs. > > While you can combine both into one process (with the combinatorial > input in the sensitivity list) as Mike has suggested, that is asking > for trouble, and if you don't correct the sensitivity list, then the > simulation and synthesis results will differ slightly, depending on > how/when the output is read by other processes/hardware. It is also > potentially prone to creating latches, to which a simple clocked > process is immune. > > You really should create this output in a separate process (or > concurrent assignment), but there is no need to separate the FSM into > two processes. > > The best way to avoid latches is to avoid combinatorial processes. > If you cannot avoid a combinatorial process, keep it as simple as > possible (doing only what has to be done combinatorially) and use up > front default assignments. > > I would suggest you look at your design requirements, and decide what > must be combinatorial, and what can tolerate a clock delay. > > Do you need to avoid =A0a clock delay between tx_valid and tx_data? > Do you need to avoid a clock delay between data_in and tx_data? > Do you need to avoid a clock delay between tx_ready and tx_data? > > Make sure you really need to avoid that clock delay. "It would be > better if..." does not count. A working design that is simple to > write, understand and maintain is much better than a design that is > none of those but happens to be a clock cycle faster. > > Find a way to accomplish combinatorially only what needs to be > combinatorial. It appears that tx_data is merely a function of > tx_valid, tx_ready, and data_in. What exactly do you need an FSM for? > You could use an FSM for error handling (what happens if tx_valid goes > high, then low, and tx_ready never fired?). But you don't appear to be > using it for that (maybe just to simplify the example?). > > AndyGeneral rule of thumb is that for the very best performance, limit combinatorial block of logic to fanin that can be contained in one LUT of target FPGA fabric. The idea is that you can't go much faster than into one LUT-REG combination. For larger fanins, either use pipelining (for instance, one might have to pipeline large N-bit comparators into multiple clocked stages) or designer will have to rely on tool's efforts in keeping source/destination flops close to combinatorial implementation--at which time floorplanning (i.e. grouping) necessities may rear its ugly head. On FSMs, I don't think either one or two processes is "right" or "wrong." Each has its drawbacks. It is up to the hardware designer to adopt a style and routine of coding it right to meet project requirements. Over time, the designer will be able to draw up and debug that style very efficiently because of familiarity. John
Reply by ●December 4, 20102010-12-04
On Dec 3, 4:05=A0am, Thomas Stanka <usenet_nospam_va...@stanka-web.de> wrote:> > Yes code is very simple...I've already coded a version with 2 process a=nd> > unregistered output...but, to better > > understand, I would like to discover if it is possible in one process..=.> > > In general..better 1 process and registered outout or 2 process and cho=ose> > if un/register output??? > > Why do you want to avoid the output register? Is it for latency or > resource usage? Is there really no other sollution? > I strongly suggest to register outputs whenever possible. For all > other cases I tend to use concurrent signal assignments. Of course I > use also combinatorical process in cases it would simplify concurrent > statements (which is seldom the case) > > process (clk,rst) > if reset =3D active then > =A0 sig_a <=3D '0'; > elsif rising_edge(clk) > =A0sig_a <=3D input_a; > end if; > end process; > > comb_out <=3D (sig_a xor input_a) when fsm_state=3Didle else '0';Just to elaborate on Thomas Stanka's post... Say that you've inherited a design that has a large FSM that had a clocked process and the BRAM were from an old technology and interfaced to the FSM with combinatorial inputs. The new device has registered BRAM inputs so you want to get rid of a pipeline delay in the FSM but want to keep the changes to a minimum. I went through the exercise with the example to see how messy it would be. library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity state_test is port ( clk : in std_logic; reset : in std_logic; txValid : in std_logic; txReady : in std_logic; dataIn : in std_logic_vector(7 downto 0); tx_data_out : out std_logic_vector(7 downto 0) ); end state_test; architecture behav of state_test is type state_typ is (TXD_IDLE, TXD_ACTIVE, TXD_END); signal act_txd_state : state_typ :=3D TXD_IDLE; signal tx_data_next, tx_data : std_logic_vector(7 downto 0); begin tx_data_out <=3D tx_data_next; tx_data_next <=3D "00000000" when reset =3D '1' else "01000000" when ((act_txd_state =3D TXD_IDLE) and (txValid =3D '1') and (dataIn =3D "00000000")) else "11000000" when ((act_txd_state =3D TXD_IDLE) and (txValid =3D '1') and (dataIn /=3D "00000000")) else dataIn when ((act_txd_state =3D TXD_END)) else tx_data; sync_proc : process (clk, reset) is begin if (reset =3D '1') then act_txd_state <=3D TXD_IDLE; tx_data <=3D (others =3D> '0'); elsif (clk'event and clk =3D '1') then tx_data <=3D tx_data_next; case act_txd_state is when TXD_IDLE =3D> if (txValid =3D '1') then act_txd_state <=3D TXD_ACTIVE; end if; when TXD_ACTIVE =3D> if (txReady =3D '1') then act_txd_state <=3D TXD_END; end if; when TXD_END =3D> if (txValid =3D '0') then act_txd_state <=3D TXD_IDLE; end if; end case; end if; end process sync_proc; end behav;
Reply by ●December 5, 20102010-12-05
>I went through the exercise with the example to see how messy it would >be. > >library ieee; >use ieee.std_logic_1164.all; >use ieee.numeric_std.all; > >entity state_test is > > port ( > clk : in std_logic; > reset : in std_logic; > txValid : in std_logic; > txReady : in std_logic; > dataIn : in std_logic_vector(7 downto 0); > > tx_data_out : out std_logic_vector(7 downto 0) > ); > >end state_test; > >architecture behav of state_test is > type state_typ is (TXD_IDLE, TXD_ACTIVE, TXD_END); > > signal act_txd_state : state_typ :=3D TXD_IDLE; > signal tx_data_next, tx_data : std_logic_vector(7 downto 0); > >begin > tx_data_out <=3D tx_data_next; > > tx_data_next <=3D > "00000000" when reset =3D >'1' >else > "01000000" when ((act_txd_state =3D TXD_IDLE) and (txValid =3D '1') >and (dataIn =3D "00000000")) else > "11000000" when ((act_txd_state =3D TXD_IDLE) and (txValid =3D '1') >and (dataIn /=3D "00000000")) else > dataIn when ((act_txd_state =3D >TXD_END)) >else > tx_data; > > sync_proc : process (clk, reset) is > begin > if (reset =3D '1') then > act_txd_state <=3D TXD_IDLE; > tx_data <=3D (others =3D> '0'); > elsif (clk'event and clk =3D '1') then > tx_data <=3D tx_data_next; > > case act_txd_state is > > when TXD_IDLE =3D> > if (txValid =3D '1') then > act_txd_state <=3D TXD_ACTIVE; > end if; > > > when TXD_ACTIVE =3D> > if (txReady =3D '1') then > act_txd_state <=3D TXD_END; > end if; > > > when TXD_END =3D> > if (txValid =3D '0') then > act_txd_state <=3D TXD_IDLE; > end if; > end case; > > end if; > end process sync_proc; >end behav; >Yes...indeed that is the only way (or one of few ways) to eliminate the output FF... In some way it is "similar" to what I've written with variables but using concurrent signal assignment....effectively it is not a complete mess... Anyway...probably I was wrong...I don't need to avoid registered output (and a lot of you were right)...in fact I'm always assigning the "output" of a FF...therefore I'm sure that when fsm reach a state the output will change to the value that is required on that state on the same clock front and I don't have to wait for another clock front to have that value on output...am I correct??? I saw it in simulation...looking at the RTL synthesys diagram wasn't clear for me....I have, further, the advantage of registered output.... Probably I will rewrite everything (or the most part) in 1 process style...it seems more clear....I'm evaluating... Thanx Carlo --------------------------------------- Posted through http://www.FPGARelated.com
Reply by ●December 5, 20102010-12-05
>Anyway...probably I was wrong...I don't need to avoid registered output >(and a lot of you were right)...in fact I'm always assigning the "output" >of a FF...therefore I'm sure that when fsm reach a state the output will >change to the value that is required on that state on the same clockfront>and I don't have to wait for another clock front to have that value on >output...This is not completely true...state change immediately if change condition is met...output is still at values on previous state...on the next clock front the output goes to the new state value...this is the effect of the output FF...I'm sorry a misunderstanding.... ..the difference is now clear....I've just simulated the two situations...(1 process, 2 process-no register)...and checked the differences.... Anyway...since all input signals "should be sinchronous" to the raise front of the clock and the produced output MUST be synch I think that the best way to achieve that is registering output and evaluating input on clock raise...my previous implementation was wrong because output is allowed to change asynchronously...I have to correct...and I think that 1 process style fit better the requirements... If in some cases I will need to unreg output I will use concurrent statements outside of the process as pointed out in the discussion... Thanx to everyone who helped me... Carlo --------------------------------------- Posted through http://www.FPGARelated.com





