![]() |
|
|
|||||||
![]() |
VHDL - newby: eliminating excess flipflops from simple state machine |
|
|
Thread Tools | Search this Thread |
|
|
#1 |
|
I have been puzzled by the fact that two implementations have such
drastic differences in synthesized circuits. I know that I have failed to cover all the if-then-else possibilities (that's required to generate SOME of the flipflops). I am really at my wit's end trying to get my head around the "why" and the "howto get around it" of the following situation: first program, it is compiled under Lattice & Synplify, and it works just fine, it's a 4 bit counter, described as a finite state machine, using an asynch reset and synchronous preset (the chips we're using do not allow asynch preset). This one synthesizes nicely to 4 flipflops. The 2nd program is the same as the first, except the lines with ##### in them are removed. .................................................. ...................... library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_unsigned.all; use ieee.std_logic_arith.all; entity counter is PORT(clock :IN STD_LOGIC; barreset :IN STD_LOGIC; barpreset :IN STD_LOGIC; q :OUT STD_LOGIC_VECTOR (3 downto 0)); attribute LOC : string; ATTRIBUTE LOC of clock: signal is "P2"; ATTRIBUTE LOC of barreset: signal is "P3"; ATTRIBUTE LOC of barpreset: signal is "P4"; ATTRIBUTE LOC of q: signal is "P27 P26 P25 P24"; end; --this one works architecture howitcounts of counter is TYPE statemachine IS (s0,s1,s2,s3,s4,s5,s6,s7,s8,s9); begin PROCESS (clock,barreset) VARIABLE state: statemachine; begin if (barreset = '0') then state := s0; elsif rising_edge(clock) then if (barpreset = '0') then --######## state := s8; --######## end if; --######## CASE state IS WHEN s0 => state := s1; WHEN s1 => state := s2; WHEN s2 => state := s3; WHEN s3 => state := s4; WHEN s4 => state := s5; WHEN s5 => state := s6; WHEN s6 => state := s7; WHEN s7 => state := s8; WHEN s8 => state := s9; WHEN s9 => state := s0; WHEN OTHERS => state := s0; END CASE; end if; CASE state is WHEN s0 => q <= "0000"; WHEN s1 => q <= "0001"; WHEN s2 => q <= "0010"; WHEN s3 => q <= "0011"; WHEN s4 => q <= "0100"; WHEN s5 => q <= "0101"; WHEN s6 => q <= "0110"; WHEN s7 => q <= "0111"; WHEN s8 => q <= "1000"; WHEN s9 => q <= "1001"; WHEN OTHERS => q <= "0000"; END CASE; END PROCESS; end howitcounts; .................................................. .......... this next program DOES NOT work nicely. It requires about 13 flipflops and thus fails miserably when using a GAL22V10C (10 flipflops). The ONLY diference between the two, is 3 lines removed that control the synchronous preset (I have shown #####'s on the 1st program where that code is). Hopefully your newsreader will preserve tabs.... otherwise this code will be a mess to read. The implementation is rather clunky for a 4 bit counter, because I will use this program as a template for much more complicated state machines. I suspect that the compiler thinks that the circuit will remember the states in one case, and won't remember then in the other case, hence it needs a flipflop for every state. The "prefit equations" suggest that there is a shift register synthesized for the "bad circuit". I am not very comfortable with FSM details, but it would appear that it might be trying to create a "one-hot" implementation. Am I totally misled? Why should there be such a difference in implementation? Would I be better off to break this program up into more processes? Did I screw up in the if-else blocks? Thanks for any help...... -Paul Paul Guy |
|
|
|
|
#2 |
|
Posts: n/a
|
A few comments:
The two USE statements, use ieee.std_logic_unsigned.all; use ieee.std_logic_arith.all; are not needed. The WHEN OTHERS clauses of the two CASE statements are not needed since all possible values of "state" are already covered by the other WHEN clauses. Also, are you trying to preset the state machine to s8 or s9? Charles Bailey |
|
|
|
#3 |
|
Posts: n/a
|
Paul,
It is surprising that you have different synthesis results. Since your "CASE state is" fully covers all possibilities, the lines marked with "--########" have no synthesis semantic. I agree that the second implementation seems to be implemented as one-hot. The synthesis tool probably will not do this by default. I suspect that some how when you were synthesizing the second design that you accidentally selected one-hot. You might check your constraints and try again. If that does not work, try selecting binary/sequentical encoding (not gray) to try to get it closer to what you want. If that does not work, you might try using Synplicity's "syn_encoding" to force the coding to something exactly the values you expect for Q. Alternately, if you want to stop fooling around with synthesis tool switches, use use a counter. I do this for ring counters like you show: architecture howitcounts of counter is signal StateReg : unsigned(3 downto 0) ; begin StateProc : PROCESS (clock,barreset) begin if (barreset = '0') then StateReg <= "0000" ; elsif rising_edge(clock) then If StateReg = 9 then StateReg <= "0000" ; else StateReg <= StateReg + 1 ; end if ; end if ; end process ; Q <= std_logic_vector(StateReg) ; Cheers, Jim P.S. I recommend the use of the package numeric_std rather than std_logic_arith for all new designs. -- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~ Jim Lewis Director of Training private.php?do=newpm&u= SynthWorks Design Inc. http://www.SynthWorks.com 1-503-590-4787 Expert VHDL Training for Hardware Design and Verification ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~ Paul Guy wrote: > I have been puzzled by the fact that two implementations have such > drastic differences in synthesized circuits. I know that I have failed > to cover all the if-then-else possibilities (that's required to > generate SOME of the flipflops). I am really at my wit's end trying to > get my head around the "why" and the "howto get around it" of the > following situation: > > first program, it is compiled under Lattice & Synplify, and it > works just fine, it's a 4 bit counter, described as a finite state > machine, using an asynch reset and synchronous preset (the chips we're > using do not allow asynch preset). This one synthesizes nicely to 4 > flipflops. > The 2nd program is the same as the first, except the lines with > ##### in them are removed. > .................................................. ..................... > library ieee; > use ieee.std_logic_1164.all; > use ieee.std_logic_unsigned.all; > use ieee.std_logic_arith.all; > > entity counter is > PORT(clock :IN STD_LOGIC; > barreset :IN STD_LOGIC; > barpreset :IN STD_LOGIC; > q :OUT STD_LOGIC_VECTOR (3 downto 0)); > > attribute LOC : string; > ATTRIBUTE LOC of clock: signal is "P2"; > ATTRIBUTE LOC of barreset: signal is "P3"; > ATTRIBUTE LOC of barpreset: signal is "P4"; > ATTRIBUTE LOC of q: signal is "P27 P26 P25 P24"; > end; > > > --this one works > > > architecture howitcounts of counter is > TYPE statemachine IS (s0,s1,s2,s3,s4,s5,s6,s7,s8,s9); > begin > PROCESS (clock,barreset) > VARIABLE state: statemachine; > begin > if (barreset = '0') then > state := s0; > elsif rising_edge(clock) then > if (barpreset = '0') then --######## > state := s8; --######## > end if; --######## > CASE state IS > WHEN s0 => state := s1; > WHEN s1 => state := s2; > WHEN s2 => state := s3; > WHEN s3 => state := s4; > WHEN s4 => state := s5; > WHEN s5 => state := s6; > WHEN s6 => state := s7; > WHEN s7 => state := s8; > WHEN s8 => state := s9; > WHEN s9 => state := s0; > WHEN OTHERS => state := s0; > END CASE; > end if; > > CASE state is > WHEN s0 => q <= "0000"; > WHEN s1 => q <= "0001"; > WHEN s2 => q <= "0010"; > WHEN s3 => q <= "0011"; > WHEN s4 => q <= "0100"; > WHEN s5 => q <= "0101"; > WHEN s6 => q <= "0110"; > WHEN s7 => q <= "0111"; > WHEN s8 => q <= "1000"; > WHEN s9 => q <= "1001"; > WHEN OTHERS => q <= "0000"; > END CASE; > END PROCESS; > > end howitcounts; > .................................................. ......... > > this next program DOES NOT work nicely. It requires about 13 flipflops > and thus fails miserably when using a GAL22V10C (10 flipflops). The > ONLY diference between the two, is 3 lines removed that control the > synchronous preset (I have shown #####'s on the 1st program where that > code is). > Hopefully your newsreader will preserve tabs.... otherwise this code > will be a mess to read. > The implementation is rather clunky for a 4 bit counter, because I > will use this program as a template for much more complicated state > machines. > I suspect that the compiler thinks that the circuit will remember > the states in one case, and won't remember then in the other case, > hence it needs a flipflop for every state. The "prefit equations" > suggest that there is a shift register synthesized for the "bad > circuit". I am not very comfortable with FSM details, but it would > appear that it might be trying to create a "one-hot" implementation. > Am I totally misled? Why should there be such a difference in > implementation? Would I be better off to break this program up into > more processes? Did I screw up in the if-else blocks? > Thanks for any help...... > > -Paul Jim Lewis |
|
|
|
#4 |
|
Posts: n/a
|
On Tue, 25 May 2004 10:08:44 -0700, Jim Lewis <>
wrote: >Paul, >It is surprising that you have different synthesis results. >Since your "CASE state is" fully covers all possibilities, >the lines marked with "--########" have no synthesis semantic. > >I agree that the second implementation seems to be implemented as >one-hot. The synthesis tool probably will not do this by >default. I suspect that some how when you were synthesizing >the second design that you accidentally selected one-hot. >You might check your constraints and try again. If that does >not work, try selecting binary/sequentical encoding (not gray) >to try to get it closer to what you want. > >If that does not work, you might try using Synplicity's >"syn_encoding" to force the coding to something exactly the >values you expect for Q. > > >Alternately, if you want to stop fooling around with synthesis >tool switches, use use a counter. I do this for ring >counters like you show: > >architecture howitcounts of counter is > signal StateReg : unsigned(3 downto 0) ; >begin > StateProc : PROCESS (clock,barreset) > begin > if (barreset = '0') then > StateReg <= "0000" ; > elsif rising_edge(clock) then > If StateReg = 9 then > StateReg <= "0000" ; > else > StateReg <= StateReg + 1 ; > end if ; > end if ; > end process ; > > Q <= std_logic_vector(StateReg) ; > > >Cheers, >Jim >P.S. >I recommend the use of the package numeric_std rather >than std_logic_arith for all new designs. I later tried setting a constraint ("syn_encoding") and it yielded more consistent results, but in this case both versions ended up as a one-hot. My guess is that when I use an asynchronous reset, because the state machine definition is bypassed in the "if" statement, the states must be memorized, and that requires all 10 states to require their own registers. You are correct about modelling it as a counter..... it boils down to the minimum 4 registers. The synthesis part of the package must somehow realize that a counter is best done sequentially, and a state machine is best done by one-hot, despite the constraints. The code I finally chose looks remarkably like that you have shown above. Originally this whole query came about as a result of trying to put a 2 decade counter with reset, preset and carryout onto a 10 register GALV2210. I was demonstrating the similiarities between a behavioural representation as a counter (adding the counts), and a state machine. The statemachine failed miserably - it required far too many flipflops. Students are always quite interested in seeing how an instructor "gets off the hook" in such a case. Both them and I did learn something about the trade-offs between sequential and one-hot implementations of state machines. Next year for this course I must invest in chips with higher complexity - more gates and registers! -Thanks for your help...... -Paul Paul Guy |
|