newby: eliminating excess flipflops from simple state machine

Discussion in 'VHDL' started by Paul Guy, May 24, 2004.

  1. Paul Guy

    Paul Guy Guest

    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, May 24, 2004
    #1
    1. Advertisements

  2. 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, May 25, 2004
    #2
    1. Advertisements

  3. Paul Guy

    Jim Lewis Guest

    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 mailto:
    SynthWorks Design Inc. http://www.SynthWorks.com
    1-503-590-4787

    Expert VHDL Training for Hardware Design and Verification
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     
    Jim Lewis, May 25, 2004
    #3
  4. Paul Guy

    Paul Guy Guest




    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, May 27, 2004
    #4
    1. Advertisements

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.