Delay in FSM using one process

Discussion in 'VHDL' started by maurizio.gencarelli@dsto.defence.gov.au, Jun 27, 2007.

  1. Guest

    I have implemented the attached FSM code using one process. It seems
    to work except that I am getting a 2 cycle clock delay between output
    wr_fifo_en being aserted when frame_mrk goes high. The frame_mrk
    indicates the beginning of signal which should be reflected in ouput
    wr_fifo_data. This results in my fifo write enable, wr_fifo_en being
    two clock cycles too late=> one cycle delay from input change to state
    change, and the other from state change to output change. This
    wouldn't be a problem if the wr_fifo_data output was delayed with
    wr_fifo_en by 2 clock cycles so they line up=>shouldn't wr_fifo_data
    be delayed w.r.t data because it is registered anyway?

    Any ideas what I am doing wrong ?

    library IEEE;
    use IEEE.STD_LOGIC_1164.ALL;
    use IEEE.STD_LOGIC_ARITH.ALL;
    use IEEE.STD_LOGIC_UNSIGNED.ALL;

    ---- Uncomment the following library declaration if instantiating
    ---- any Xilinx primitives in this code.
    --library UNISIM;
    --use UNISIM.VComponents.all;

    entity RX_FIFO_WR_CONTROL is
    Port ( data_clk : in STD_LOGIC;
    data:in STD_LOGIC_VECTOR (3 downto 0);
    frame_mrk : in STD_LOGIC;
    rxdv: in STD_LOGIC;
    fifo_full : in STD_LOGIC;
    frame_good: in STD_LOGIC;
    frame_bad: in STD_LOGIC;
    fifo_wr_data: out STD_LOGIC_VECTOR (4 downto 0);
    wr_fifo_en : out STD_LOGIC;
    rst: in STD_LOGIC;
    prog_full_thresh: out std_logic_VECTOR(10 downto 0));
    end RX_FIFO_WR_CONTROL;

    architecture RTL of RX_FIFO_WR_CONTROL is


    type fifo_cntrl_state is
    (idle,write_fifo,over_flow,wait_end,read_frame_condition,write_frame_status);
    signal state:fifo_cntrl_state;
    signal ovr_flow: std_logic;



    begin

    prog_full_thresh<="11111111110";


    process
    (data_clk,rst,state,frame_mrk,rxdv,fifo_full,frame_good,frame_bad,data)
    begin
    if rst='1' then
    state<=idle;
    ovr_flow<='0';
    wr_fifo_en<='0';
    fifo_wr_data<="00000";

    elsif rising_edge(data_clk) then

    case state is
    when idle =>
    if frame_mrk='1' then
    state<=write_fifo;
    else
    state<=idle;
    end if;

    fifo_wr_data(3 downto 0)<=data;
    fifo_wr_data(4)<='0';
    ovr_flow<='0';
    wr_fifo_en<='0';

    when write_fifo =>

    wr_fifo_en<='1';
    fifo_wr_data(3 downto 0)<=data;
    fifo_wr_data(4)<=frame_mrk;
    ovr_flow<='0';

    if frame_mrk='0' then
    state<= wait_end;
    elsif fifo_full='1' then
    state<= over_flow;
    else
    state<=write_fifo;
    end if;


    when over_flow=>
    state<=wait_end;
    fifo_wr_data(3 downto 0)<=data;
    fifo_wr_data(4)<=frame_mrk;
    ovr_flow<='1';
    wr_fifo_en<='0';
    when wait_end =>
    if rxdv='0' then
    state<=read_frame_condition;
    else
    state<=wait_end;
    end if;

    fifo_wr_data(3 downto 0)<=data;
    fifo_wr_data(4)<=frame_mrk;
    wr_fifo_en<='0';

    when read_frame_condition =>
    state<=write_frame_status;
    wr_fifo_en<='0';
    fifo_wr_data(4)<='0';
    fifo_wr_data(3)<=ovr_flow;
    fifo_wr_data(2)<=frame_good;
    fifo_wr_data(1)<=frame_bad;
    fifo_wr_data(0)<='0';

    when write_frame_status =>
    state<=idle;
    wr_fifo_en<='1';
    ovr_flow<='0';

    when others =>
    state <= idle;
    fifo_wr_data(3 downto 0)<=data;
    fifo_wr_data(4)<='0';
    ovr_flow<='0';
    wr_fifo_en<='0';

    end case;
    end if;
    end process;

    end RTL;
    , Jun 27, 2007
    #1
    1. Advertising

  2. On Tue, 26 Jun 2007 17:49:05 -0700,
    wrote:

    >Any ideas what I am doing wrong ?


    Some ideas, but I don't have the time to work through your FSM
    in detail.

    >use IEEE.STD_LOGIC_ARITH.ALL;
    >use IEEE.STD_LOGIC_UNSIGNED.ALL;


    Oh dear. Please consider migrating to NUMERIC_STD if you
    can possibly manage it. Soon.

    >process
    >(data_clk,rst,state,frame_mrk,rxdv,fifo_full,frame_good,frame_bad,data)


    This is a straightforward clocked process, and should have
    only (data_clk, rst) in its sensitivity list. The other items
    are redundant, and may yield warnings in synthesis.

    >I have implemented the attached FSM code using one process. It seems
    >to work except that I am getting a 2 cycle clock delay between output
    >wr_fifo_en being aserted when frame_mrk goes high. The frame_mrk
    >indicates the beginning of signal which should be reflected in ouput
    >wr_fifo_data. This results in my fifo write enable, wr_fifo_en being
    >two clock cycles too late=> one cycle delay from input change to state
    >change, and the other from state change to output change. This
    >wouldn't be a problem if the wr_fifo_data output was delayed with
    >wr_fifo_en by 2 clock cycles so they line up=>shouldn't wr_fifo_data
    >be delayed w.r.t data because it is registered anyway?


    You are quite right that you get two cycles of delay from
    input change to output change. There MUST be at least one cycle,
    of course, because the state machine is clocked. But you don't
    need the second cycle of delay. Instead, you should write the
    FSM so that (for example) an output that needs to be asserted in
    state S1 should be driven high as a result of the TRANSITION to S1,
    so that it is synchronous with S1 instead of one cycle late.

    There are at least five sensible ways to do this.
    I don't today have the stomach for the usual crusades
    about which is the best, and which should be condemned
    to be shackled to the walls of the dungeons of history
    with the key thrown away.

    Just a thought: Wouldn't it be fun if we could act like
    the mediaeval church, and hold highbrow convocations at
    which we could decide what coding styles were heretical?
    Then we could impose "cruel and unusual" punishments for
    violators, and I could join the RTL Inquisition and go
    around subjecting people to public humiliation in various
    interesting ways... oh yes, of course, we do that already,
    it's called Usenet :)


    (1) Classic 2-process Moore state machine
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    Rewrite the state machine so that it manipulates only the
    state signal. Write a second, combinational process that
    decodes the state signal to create the outputs.

    (2) Outputs as part of the state vector
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    Instead of writing an enumeration type for the state,
    write a bunch of STD_LOGIC_VECTOR constants. Make sure
    that some of the bits of those constants exactly reflect
    the output bits that you want as a function of the state.
    Add further bits to the state vector to ensure that all
    states have different state values (!). Pick off the
    appropriate bits of state vector to provide your outputs.

    (3) Registered-Mealy state machine with lookahead outputs
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    Go back to your existing FSM code, but rewrite it so that
    when you transition to a given state, you also set up the
    outputs as they WILL be in that new state. This is tedious
    to code because it requires you to set up a state's outputs
    on *every* transition into that state, from anywhere in
    the state diagram not forgetting "to-self" transitions,
    but it works well enough.

    (4) Use a variable to hold the state vector
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    Get rid of the state SIGNAL, and redefine it as a VARIABLE
    inside the FSM clocked process. Rewrite the process as
    TWO case statements. The first one performs all the state
    transitions, the second calculates the outputs and drives
    them on to signals.

    process (clk, rst)
    type state_type is (s1, s2, ...);
    variable state: state_type;
    begin
    if rst = '1' then
    state := <idle_state>;
    outputs <= <reset output values>;
    elsif rising_edge(clk) then
    -- step 1: calculate next-state
    case state is
    when s1 =>
    if <input conditions>
    state := <different state>;
    end if;
    ...
    end case;
    -- step 2: use next-state to determine next-outputs
    case state is
    when s1 =>
    outputs <= <appropriate outputs for s1>;
    ...
    end case;
    end if;
    end process;

    (5) Don't use an explicit state machine at all
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    Write code that uses various variables to keep track of the state
    of your system, and to determine appropriate output values.
    Once you've done all that, drive the chosen output values
    on to your output signals. Method (4) is a useful special case of
    this one. See Mike Treseler's website and posts for examples of
    how to work this idea through in practice.
    --
    Jonathan Bromley, Consultant

    DOULOS - Developing Design Know-how
    VHDL * Verilog * SystemC * e * Perl * Tcl/Tk * Project Services

    Doulos Ltd., 22 Market Place, Ringwood, BH24 1AW, UK

    http://www.MYCOMPANY.com

    The contents of this message may contain personal views which
    are not the views of Doulos Ltd., unless specifically stated.
    Jonathan Bromley, Jun 27, 2007
    #2
    1. Advertising

  3. writes:

    > I have implemented the attached FSM code using one process. It seems
    > to work except that I am getting a 2 cycle clock delay between output
    > wr_fifo_en being aserted when frame_mrk goes high. The frame_mrk
    > indicates the beginning of signal which should be reflected in ouput
    > wr_fifo_data. This results in my fifo write enable, wr_fifo_en being
    > two clock cycles too late=> one cycle delay from input change to state
    > change, and the other from state change to output change. This
    > wouldn't be a problem if the wr_fifo_data output was delayed with
    > wr_fifo_en by 2 clock cycles so they line up=>shouldn't wr_fifo_data
    > be delayed w.r.t data because it is registered anyway?
    >
    > Any ideas what I am doing wrong ?
    >
    > library IEEE;
    > use IEEE.STD_LOGIC_1164.ALL;


    OK so far...

    > use IEEE.STD_LOGIC_ARITH.ALL;
    > use IEEE.STD_LOGIC_UNSIGNED.ALL;
    >


    Don't do this. Use ieee.numeric.std instead. There's many a thread
    about it. Is this is template code?

    <<snip>>
    >
    > type fifo_cntrl_state is
    > (idle,write_fifo,over_flow,wait_end,read_frame_condition,write_frame_status);
    > signal state:fifo_cntrl_state;
    > signal ovr_flow: std_logic;
    >
    >
    >
    > begin
    >
    > prog_full_thresh<="11111111110";
    >
    >
    > process
    > (data_clk,rst,state,frame_mrk,rxdv,fifo_full,frame_good,frame_bad,data)


    It's a synchronous process with async reset, so you only need data_clk
    and rst in your sentivity list.

    > begin
    > if rst='1' then
    > state<=idle;
    > ovr_flow<='0';
    > wr_fifo_en<='0';
    > fifo_wr_data<="00000";
    >
    > elsif rising_edge(data_clk) then
    >
    > case state is
    > when idle =>
    > if frame_mrk='1' then
    > state<=write_fifo;


    You need to assert wr_fifo_en here if you want it to be
    active on the next clock cycle after frame_mrk goes high.

    > else


    and move the clearing of wr_fifo_en here from below (otherwise it will
    always be cleared!)

    > state<=idle;
    > end if;
    >
    > fifo_wr_data(3 downto 0)<=data;


    You are writing your data here, so it *will* be updated for the next
    clock cycle.

    > fifo_wr_data(4)<='0';
    > ovr_flow<='0';
    > wr_fifo_en<='0';


    This clearing of wr_fifo_en needs to be moved up.

    <snip>

    Hope this helps!
    Cheers,
    Martin

    --

    TRW Conekt - Consultancy in Engineering, Knowledge and Technology
    http://www.conekt.net/electronics.html
    Martin Thompson, Jun 27, 2007
    #3
    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. Nic

    One Hot FSM stuck !!

    Nic, Feb 26, 2004, in forum: VHDL
    Replies:
    5
    Views:
    1,139
    FGreen
    Mar 2, 2004
  2. mobi999
    Replies:
    0
    Views:
    746
    mobi999
    Jun 9, 2007
  3. Replies:
    6
    Views:
    592
  4. a s
    Replies:
    2
    Views:
    1,184
  5. kassiopea147

    FSM single process...BIG question

    kassiopea147, Dec 2, 2010, in forum: VHDL
    Replies:
    1
    Views:
    840
    jeppe
    Dec 2, 2010
Loading...

Share This Page