A general rule for State Machines?

Discussion in 'VHDL' started by Dave Dean, Sep 12, 2006.

  1. Dave Dean

    Dave Dean Guest

    Hi all,
    I've got a question about some alternate ways to implement a state
    machine - in particular, when you may be in a state for several cycles -
    I'll use a deserializer as my example here.

    First, suppose a boring deserializer that needs to grab just one bit:

    entity test is
    port (
    data_in : in std_logic;
    clk : in std_logic
    );
    end test;

    architecture one_bit of test is

    type states is (idle, get_data);
    signal state : states;
    signal data : std_logic;

    begin
    process(clk)
    begin
    if (rising_edge(clk)) then
    case state is
    when idle => if (go='1') then state <= get_data; end if;
    when get_data => data <= data_in;
    state <= idle;
    end case;
    end if;
    end process;
    end one_bit;
    ---------------------------------
    very simple. Now, suppose we need to deserialize TWO bits. Here's two
    different changes to the SM that will do this:

    architecture two_bits1 of test is

    type states is (idle, get_data1, get_data2);
    signal state : states;
    signal data : std_logic_vector(1 downto 0);

    begin
    process(clk)
    begin
    if (rising_edge(clk)) then
    case state is
    when idle => if (go='1') then state <= get_data1; end if;
    when get_data1 => data <= data(0) & data_in;
    state <= get_data2;
    when get_data2 => data <= data(0) & data_in;
    state <= idle;
    end case;
    end if;
    end process;
    end imp;
    --------------------------------------
    architecture two_bits2 of test is

    type states is (idle, get_data);
    signal state : states;
    signal data : std_logic_vector(1 downto 0);
    signal counter : std_logic;

    begin
    process(clk)
    begin
    if (rising_edge(clk)) then
    case state is
    when idle => if (go='1') then
    state <= get_data;
    counter <= '0';
    end if;
    when get_data => data <= data(0) & data_in;
    counter <= counter + 1;
    if (counter='1') then
    state <= idle;
    end if;
    end case;
    end if;
    end process;
    end imp;
    ----------------------------
    In the first example, I added a second "get_data" state to allow me to get 2
    bits. In the second, I added a counter, so I could stay in the one
    "get_data" state for two cycles. In this small example, I'm not sure which
    implementation is better.
    However, when you start getting significantly larger, like this 16-bit
    example:

    architecture 16bits of test is

    type states is (idle, get_data);
    signal state : states;
    signal data : std_logic_vector(15 downto 0);
    signal counter : std_logic_vector(3 downto 0);

    begin
    process(clk)
    begin
    if (rising_edge(clk)) then
    case state is
    when idle => if (go='1') then
    state <= get_data;
    counter <= (others => '0');
    end if;
    when get_data => data <= data(14 downto 0) & data_in;
    counter <= counter + 1;
    if (counter="1111") then
    state <= idle;
    end if;
    end case;
    end if;
    end process;
    end 16bits;
    ----------------------------------
    Here, I think a counter will be better than adding 16 extra states. If you
    use one-hot encoding, you'll be using a lot of extra resources with the
    additional states (right?).

    Anyway, this is a fairly simple example that I hope illustrates the larger
    point. Does anyone have a good rule of thumb of when to use a counter and
    when to add extra states? I suppose it can depend on the particular
    situation (the extra states will usually be faster) but the counter is
    certainly more flexible and elegent.

    Thanks,
    Dave
     
    Dave Dean, Sep 12, 2006
    #1
    1. Advertising

  2. Dave Dean wrote:

    > Anyway, this is a fairly simple example that I hope illustrates the
    > larger
    > point. Does anyone have a good rule of thumb of when to use a
    > counter and
    > when to add extra states?


    My opinion: go for the implementation that shows the least code
    duplication. This makes it more robust against introduction of bugs
    when the implementation is changed. Using a counter certainly would
    have my preference. It just makes the code easier to maintain.

    --
    Paul.
     
    Paul Uiterlinden, Sep 12, 2006
    #2
    1. Advertising

  3. Dave Dean

    Andy Guest

    Anytime I need to delay more than 3 or 4 clocks, I prefer to use a
    counter. Plus, the length of the delay counter can be parameterized.

    case state is
    when start =>
    state := waiting;
    delay_cnt := WAIT_DELAY;
    when waiting =>
    if delay_cnt - 1 < 0 then -- for integer counters only!
    state := go;
    else
    delay_cnt := delay_cnt - 1;
    end if;
    when ...
    end case;

    Andy


    Paul Uiterlinden wrote:
    > Dave Dean wrote:
    >
    > > Anyway, this is a fairly simple example that I hope illustrates the
    > > larger
    > > point. Does anyone have a good rule of thumb of when to use a
    > > counter and
    > > when to add extra states?

    >
    > My opinion: go for the implementation that shows the least code
    > duplication. This makes it more robust against introduction of bugs
    > when the implementation is changed. Using a counter certainly would
    > have my preference. It just makes the code easier to maintain.
    >
    > --
    > Paul.
     
    Andy, Sep 12, 2006
    #3
  4. If there is no demand for hot encoded states due to speed problems, I
    prefer counters, since they can be reused in more than one area of a
    complex state machine. Also a counter realy indicates "wait" where
    states can do anything (using 2 fsm where actions and clocking are
    separated, you will have to check the state transistion part if there
    are really nothing else than transions without conditions.
     
    homoalteraiensis, Sep 14, 2006
    #4
  5. Dave Dean

    Andy Peters Guest

    Paul Uiterlinden wrote:
    > Dave Dean wrote:
    >
    > > Anyway, this is a fairly simple example that I hope illustrates the
    > > larger
    > > point. Does anyone have a good rule of thumb of when to use a
    > > counter and
    > > when to add extra states?

    >
    > My opinion: go for the implementation that shows the least code
    > duplication. This makes it more robust against introduction of bugs
    > when the implementation is changed. Using a counter certainly would
    > have my preference. It just makes the code easier to maintain.


    Agreed. As a bonus, you can generalize the code by using a generic to
    set the number of bits.

    -a
     
    Andy Peters, Sep 18, 2006
    #5
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Sidney Cadot
    Replies:
    0
    Views:
    2,389
    Sidney Cadot
    Apr 18, 2004
  2. Steve

    Generics and state machines

    Steve, May 3, 2004, in forum: VHDL
    Replies:
    7
    Views:
    627
    Andreas Hinze
    May 5, 2004
  3. Clyde R. Shappee

    One-hot Coding of State machines

    Clyde R. Shappee, Jun 2, 2004, in forum: VHDL
    Replies:
    10
    Views:
    6,364
    Wallclimber
    Jun 3, 2004
  4. Replies:
    0
    Views:
    1,397
  5. pek
    Replies:
    12
    Views:
    505
Loading...

Share This Page