Forum Discussion

Altera_Forum's avatar
Altera_Forum
Icon for Honored Contributor rankHonored Contributor
10 years ago

Securely start a State-Machine with pulses or edges

Hi there,

this problem occures in my work from time to time:

I want to start a State-Machine (Transition from Idle-State S000 to State S010) either with a single one-clock-pulse or on the edge (rising or falling) of a signal.

But just when I think "Hey, this seems secure!", the state-machine misses the pulse or the edge.

Is there some kind of attribute or something to mark an input or a signal of the component as really really really very important to the compiler?

I currently work on a project which uses mainly a 125MHz-Clock.

some tries here:

(The following codes are inside the idle-state of a state-machine.)

edge detection (with filter) on input start_in:

   
   sig_Start_IN(0)            <= Start_IN;
   sig_Start_IN(1)            <= sig_Start_IN(0);
   sig_Start_IN(2)            <= sig_Start_IN(1);
   sig_Start_IN(3)            <= sig_Start_IN(2);
                        
   if (sig_Start_IN = "0011") then
      current_state             <= S010; 
   elsif (sig_Start_IN = "1111") then
      current_state             <= current_state;   
   elsif (sig_Start_IN = "1100") then
      current_state             <= S000; 
   else
      current_state             <= current_state;   
   end if;

edge detection (without filter) on input start_in:

   
   sig_Start_IN            <= Start_IN;
                        
   if ((sig_Start_IN = '0') AND (Start_IN = '1')) then
      current_state             <= S010; 
   else
      current_state             <= S000;  
   end if;

start by a one-clock-pulse on start_in:

                           
   if (Start_IN = '1') then
      current_state             <= S010; 
   else
      current_state             <= S000;  
   end if;

Is there somewhere a better way defined to securely "see" the pulse ore edge? Why does the process sometimes skip a pulse or an edge?

20 Replies

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    --- Quote Start ---

    This is something I normally don't use

    --- Quote End ---

    For any asynchronous input it is a must.

    --- Quote Start ---

    But I think my filtered edge-detection is somehow similar to that.

    --- Quote End ---

    No it is not unless you use the output of second synchroniser and discard others in the synchroniser chain.

    --- Quote Start ---

    The problem is between two cores inside the FPGA. Both cores are on the same clock and are working on the same edge (falling_edge).

    So I think the signal must already be synchronized.

    --- Quote End ---

    still it does not explain how the start_in comes in.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    I don't know how to explain it more in detail. See attached Picture.

    The Start_IN-signal is set and unset on falling_edge by Core1. It is read by Core2 on falling_edge. Do I have to synchronize an already synchronized signal?

    Besides to "Logic never misses anything.". Currently I have also a state machine which skips sometimes a state although the path it goes has never been programmed.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    start_in goes into core1 then some logic(I presume) then core2. This is not safe. For core1 it is not synchronised by two stage. For core2 it is not either as the chain of two registers should be clean of any logic.

    start_in should go through two registers then be used in any core(core1 or core2)
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    No, Start_IN is generated by core1 (called Start_OUT, obviously an OUTput). Then no logic, directly connected to core2 where it is called Start_IN (an INput).

    Where do you see Start_IN giong into core1? Where do you see "some logic"?
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    --- Quote Start ---

    No, Start_IN is generated by core1 (called Start_OUT, obviously an OUTput). Then no logic, directly connected to core2 where it is called Start_IN (an INput).

    Where do you see Start_IN giong into core1? Where do you see "some logic"?

    --- Quote End ---

    if you are just generating start_in from same one clock then it is ok and there is no need to consider clock crossing. Moreover this is only a register generating a pulse rather than a core (which gives impression of loads of logic). You haven't explained how do you actually generate the pulse and is it based on async reset. If it all synchronous then this pulse will not be missed in a state machine that runs on same clock unless your state machine logic is not right or timing is not right. The best thing is to show the whole code of state machine.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Now it seems that we're slowly on the same level. Right, the Start_IN signal is already from a synchronized core with a synchronous reset, is read in synchronous by the second core (which also has an synchronous reset) and the result is on synchronous outputs. No asynchronous logic in between.

    Well, now the really generalized question is (see initial post) what are the best (securest) ways to detect edges or one-clock-pulses (everything synchronized) to trigger the start of a state-machine.

    This is a general question and not for debugging a special code.

    I will ask, if I can publish my code to you. (Company problem)

    PS: I think there are so much "synchronous" in this post, we can call Guinness. :)

    PPS: To be sure: synchronous :D
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    --- Quote Start ---

    Well, now the really generalized question is (see initial post) what are the best (securest) ways to detect edges or one-clock-pulses (everything synchronized) to trigger the start of a state-machine.

    This is a general question and not for debugging a special code.

    --- Quote End ---

    There is only one way and is surest securest: sample the pulse on the clock edge and use same clock edge as that generated it, though you may take risk and swap edges but there is no need to swap edges unless for some reason you want to overcome timing issues.

    The timing makes sure that there is setup window and hold window of pulse transition relative to clock edge and in effect says I see the pulse.

    If sampling fails and the clock edge did not see the pulse then either timing is not right or else your logic is not right. We trust the technology otherwise we wouldn't be here.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    --- Quote Start ---

    There is only one way and is surest securest: sample the pulse on the clock edge and use same clock edge as that generated it

    --- Quote End ---

    ie.

    
    signal ip_r : std_logic;
    process(clk)
    begin
      if rising_edge(clk) then
        ip_r <= ip;
        if ip_r = '0' and ip = '1' then
          --action on rising edge
        elsif ip_r = '1' and ip = '0' then
          --action on falling edge
      
        end if;
      end if;
    end process;
    

    Assuming there are no timing failures this will ALWAYS work.

    --- Quote Start ---

    If sampling fails and the clock edge did not see the pulse then either timing is not right or else your logic is not right. We trust the technology otherwise we wouldn't be here.

    --- Quote End ---

    Timequest will tell you if theres a timing problem

    A good testbench will tell you if theres a logic problem.

    Fixing either is usually acheived through modifying the code. Fixing timing problems with extra SDC constraints should be the last resort.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    NOW THAT'S AN ANSWER!!!! NICE. THANK YOU!

    Excuse me for being so loud. ;)

    OK, I know this method (see unfiltered edge detection in first post). Well, if this is a method even a guru choses then it will be fine for me, too.

    Timing is no problem in my design. Everything seems to be working really nice (for TimeQuest) and I have a worst-case slack of +0.17 on a source synchronous 125MHz interface.

    Logic also is no problem because I always test my cores in ModelSim before implementing them.

    Well, seems that there are no other ways than those I already know. Thank you.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Modelsim does not test things for you. Modelsim is a tool that runs your testbench. If your test cases are not catching this bug then I can only assume that your test cases are not good enough.

    Try and capture as much info as you can in the run up to the problem, then try and re-create the bug in modelsim. I bet there is some combination of events that you are not covering in the testbench that are occuring as some corner case in the real system.