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... Thanx for any help Carlo --------------------------------------- Posted through http://www.FPGARelated.com
FSM single process...BIG question
Started by ●December 2, 2010
Reply by ●December 2, 20102010-12-02
On 12/2/2010 6:43 AM, carlob wrote:> I've a problem to efficiently unregister output from FSM written in a > single process style...> I've read something about using variables...but I don't understand exactly > how...please show me an example...For such a simple case, you could more quickly rewrite the code. If you are interested in using vhdl variables, and have some spare time, here is how I do it: begin -- process template if reset = '1' then -- Assumes synched trailing edge reset init_regs; -- reg_v := init_c; No port init required elsif rising_edge(clock) then update_regs; -- reg_v := f(in, var) -- no port update need here end if; -- update_ports; -- out_port <= reg_v; -- sync outputs -- out_port <= f(in, var) -- asych out end process sync_template; -- will infer port wires ok rst or clk end architecture synth; Details here: http://mysite.ncnetwork.net/reszotzl/sync_template.vhd http://mysite.ncnetwork.net/reszotzl Good luck -- Mike Treseler
Reply by ●December 2, 20102010-12-02
On Dec 2, 9:43=A0am, "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 =3D '1') then > next_state <=3D START; > if (pluto =3D '1') then > outp <=3D '0'; > else > outp <=3D '1'; > end if; > end if; > > outp is registered...if I want to avoid that register I should (in anothe=r> process) duplicate a lot of logic: > > if (state =3D IDLE) then > if (pippo =3D '1' and pluto =3D '1') then > outp <=3D '0' > elsif (pippo =3D '1' and pluto =3D '0') then > outp <=3D '1'; > else outp <=3D '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 exactl=y> 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 =3D '1') then next_state <=3D START; if (pluto =3D '1') then outp <=3D '0'; else outp <=3D '1'; end if; end if; ... end process StateLogicPrc; StateRegPrc: process (rst, clk) begin if (rst =3D '1') then CurState <=3D StartingState; elsif (rising_edge(clk)) then CurState <=3D 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
Reply by ●December 2, 20102010-12-02
On Dec 2, 1:46=A0pm, Mike Treseler <mtrese...@gmail.com> wrote:> On 12/2/2010 6:43 AM, carlob wrote: > > > I've a problem to efficiently unregister output from FSM written in a > > single process style... > > I've read something about using variables...but I don't understand exac=tly> > how...please show me an example... > > For such a simple case, you could more quickly rewrite the code. > > If you are interested in using vhdl variables, and have some spare time, > here is how I do it: > > =A0 =A0 begin =A0-- process template > =A0 =A0 =A0 =A0if reset =3D '1' then =A0 =A0 -- Assumes synched trailing =edge reset> =A0 =A0 =A0 =A0 =A0 init_regs; =A0 =A0 =A0 =A0 =A0 -- reg_v :=3D init_c; =No port init required> =A0 =A0 =A0 =A0elsif rising_edge(clock) then > =A0 =A0 =A0 =A0 =A0 update_regs; =A0 =A0 =A0 =A0 -- reg_v :=3D f(in, var) > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0-- no port=update need here> =A0 =A0 =A0 =A0end if; =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 -- > =A0 =A0 =A0 =A0update_ports; =A0 =A0 =A0 =A0 =A0 -- out_port <=3D reg_v; ==A0 =A0 -- sync outputs> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0-- out_por=t <=3D f(in, var) -- asych out> =A0 =A0 end process sync_template; -- will infer port wires ok rst or clk > end architecture synth; > > Details here:http://mysite.ncnetwork.net/reszotzl/sync_template.vhdhttp:/=/mysite.ncnetwork.net/reszotzl> > Good luck > =A0 =A0 =A0-- Mike TreselerNote that while out_port <=3D f(in, var), located after the clk/rst end if statement, will produce combinatorial logic from in to out_port (or out_sig), the simulation and synthesis will mismatch slightly. Outport will only be updated on any event of clk or rst (i.e. both edges of both) in simulation, but continously in hardware (i.e. any edge of in). Whether this makes a difference is dependent upon what is reading the out_port. This can be avoided by adding any "in" signals used as such to the process sensitivity list. If pluto is an input to the process, then the only way to do it and retain the sim/hw matching behavior for all cases is to use a separate combinatorial process. I generally do not like combinatorial paths from in to out within a state machine, and will seek to implement it in a register if at all possible. Combinatorial processes, especially ones as complex as state machines with nested case & if statements, are prone to create latches. Avoid the combinatorial process, and avoid the possibility of a latch. If you cannot avoid the combinatorial process, then at least add default assignments for all output signals in the very beginning of the process, before any conditional statements are executed. This is much easier to write, and to review/audit, than the old addage to include an else for every if, etc. Andy
Reply by ●December 2, 20102010-12-02
On Dec 2, 2:16=A0pm, rickman <gnu...@gmail.com> wrote:> On Dec 2, 9:43=A0am, "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 =3D '1') then > > next_state <=3D START; > > if (pluto =3D '1') then > > outp <=3D '0'; > > else > > outp <=3D '1'; > > end if; > > end if; > > > outp is registered...if I want to avoid that register I should (in anot=her> > process) duplicate a lot of logic: > > > if (state =3D IDLE) then > > if (pippo =3D '1' and pluto =3D '1') then > > outp <=3D '0' > > elsif (pippo =3D '1' and pluto =3D '0') then > > outp <=3D '1'; > > else outp <=3D '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 exac=tly> > how...please show me an example... > > You might find it easier to separate the state machine from the state > register. =A0Then 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. =A0The > 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. =A0The clocked > process just defines the CurState register in terms of the NxtState > signal. =A0The clocked process is idiot simple and so does not duplicate > the code that you are worried about. > > StateLogicPrc: process (CurState, pippo, pluto,...) begin > =A0 -- if (rising_edge(clk)) then =A0-- remove this sequential stuff from > the process > =A0 -- so you are just left with the logic... > =A0 case CurState is > =A0 =A0 when IDLE: > =A0 =A0 =A0 if (pippo =3D '1') then > =A0 =A0 =A0 =A0 next_state <=3D START; > =A0 =A0 =A0 =A0 if (pluto =3D '1') then > =A0 =A0 =A0 =A0 =A0 outp <=3D '0'; > =A0 =A0 =A0 =A0 else > =A0 =A0 =A0 =A0 =A0 outp <=3D '1'; > =A0 =A0 =A0 =A0 end if; > =A0 =A0 =A0 end if; > ... > end process StateLogicPrc; > > StateRegPrc: process (rst, clk) begin > =A0 if (rst =3D '1') then > =A0 =A0 CurState <=3D StartingState; > =A0 elsif (rising_edge(clk)) then > =A0 =A0 CurState <=3D next_state; > =A0 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. =A0Now 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. Andy
Reply by ●December 2, 20102010-12-02
Carlo, You may already know this, but... Your combinatorial process is not equivalent to the clocked process. An unassigned signal is not driven to 'Z'; it creates a latch. Read below for more information. If this was just an unfortunate choice of "for example" please disregard. Andy
Reply by ●December 2, 20102010-12-02
>Carlo, > >You may already know this, but... > >Your combinatorial process is not equivalent to the clocked process. >An unassigned signal is not driven to 'Z'; it creates a latch. Read >below for more information. > >If this was just an unfortunate choice of "for example" please >disregard. > >Andy >Hi, first of all...thanx for your help.... The question is...basically in a case like that is better to use 2 process method...is it right?? I'm studing vhdl by myself and on every textbook I've found around the best way to code FSM is 2 process... I started writing my code (in 2 process style)...but, taking a look at code written by others I see very often only 1 process...crazy... I tried to implement some part in 1 process style because it seems to me more "simple"..cleaner...but the output is registered and doesn't fit well with rest of the code (other FSM)... I've started to ask me if there is a method to implement in a 1 process unregistered output FSM... I've tried something like this: variable v_tx_data : std_logic_vector(7 downto 0); begin if (reset='1') then act_txd_state <= TXD_IDLE; v_tx_data := (others => '0'); elsif (clk'event and clk ='1') then case act_txd_state is when TXD_IDLE => if (txValid = '1') then if (dataIn = "00000000") then v_tx_data := "01000000"; else v_tx_data := "11000000"; end if; act_txd_state <= TXD_ACTIVE; end if; when TXD_ACTIVE => if (txReady = '1') then act_txd_state <= TXD_END; end if; when TXD_END => v_tx_data := dataIn; if (txValid = '0') then act_txd_state <= TXD_IDLE; end if; end case; end if; tx_data <= v_tx_data; Obviously v_tx_data is a FF...and the output is registered....I don't find any way to unregister output in a process like that... Any hint?? Mike in you example output is registered or not?? eventually...how can I apply your 1 process example to the above code??? Yes code is very simple...I've already coded a version with 2 process and 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 choose if un/register output??? Thanx Carlo --------------------------------------- Posted through http://www.FPGARelated.com
Reply by ●December 3, 20102010-12-03
> Yes code is very simple...I've already coded a version with 2 process and > 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 choose > 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 = active then sig_a <= '0'; elsif rising_edge(clk) sig_a <= input_a; end if; end process; comb_out <= (sig_a xor input_a) when fsm_state=idle else '0';
Reply by ●December 3, 20102010-12-03
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';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
Reply by ●December 3, 20102010-12-03
> >> Yes code is very simple...I've already coded a version with 2 processand>> 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 andchoose>> 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 = active then > sig_a <= '0'; >elsif rising_edge(clk) > sig_a <= input_a; >end if; >end process; > >comb_out <= (sig_a xor input_a) when fsm_state=idle else '0'; > >Hi, that's only because that is a simple fsm inside a project...and 1 clock latency on that signal doesn't fit with other modules.... Yes...I agree with you...I tend to use registers when possible...using 2 process style (till now) you have to take care of registering output therefore is up to you to decide... Thanx Carlo --------------------------------------- Posted through http://www.FPGARelated.com






