FPGARelated.com
Forums

Meta-stable problem with MAX-II ?

Started by Unknown October 25, 2006
I'm trying to snag a 90nS pulse with a 16MHz clock.  On paper, it
should work just fine: 62.5 < 90.

What I see is that if the leading edge of the pulse is co-incident with
the leading edge of the clock, the pulse is not clocked in.  (Which I
think it should be; at least on the next clock edge.)

To make it more "interesting", it will then miss the next few pulses;
mayby 10 or so.

After that, it will go back to normal operation, clocking in the pulses
as intended.

Anyone else seen something like this?  Any pointers as to what to look
for?

Regards,
GH

Metastability is often blamed for things that have nothing to do with
metastability.
I am not an expert on Altera parts, but I understand metastability
problems. It seems unbelievable to me that a Max-II flip-flop can
misbehave for dozens of nanoseconds.
Look somewhere else!
Peter Alfke, Xilinx Applications.

On Oct 25, 8:49 am, ghel...@lycos.com wrote:
> I'm trying to snag a 90nS pulse with a 16MHz clock. On paper, it > should work just fine: 62.5 < 90. > > What I see is that if the leading edge of the pulse is co-incident with > the leading edge of the clock, the pulse is not clocked in. (Which I > think it should be; at least on the next clock edge.) > > To make it more "interesting", it will then miss the next few pulses; > mayby 10 or so. > > After that, it will go back to normal operation, clocking in the pulses > as intended. > > Anyone else seen something like this? Any pointers as to what to look > for? > > Regards, > GH
ghelbig@lycos.com wrote:
> I'm trying to snag a 90nS pulse with a 16MHz clock. On paper, it > should work just fine: 62.5 < 90. > > What I see is that if the leading edge of the pulse is co-incident with > the leading edge of the clock, the pulse is not clocked in. (Which I > think it should be; at least on the next clock edge.) > > To make it more "interesting", it will then miss the next few pulses; > mayby 10 or so. > > After that, it will go back to normal operation, clocking in the pulses > as intended. > > Anyone else seen something like this? Any pointers as to what to look > for? >
I suspect that there is something else that you're not quite telling us and that the problem is that the setup time is being violated on some 'other' logic that is causing the pulses to be missed. In other words, if the 90ns pulse signal is 'D' and the output that gets 'missed' is 'Q', then does 'D' feed into ANY logic other than that for 'Q'? Like a state machine perhaps? If so, then whatever that other path(s) is is probably getting whacked out because of the setup time violation. To check this look at your fitted design in the Quartus Technology Map viewer and verify that 'D' is only an input to the flip flop that compute 'Q'. KJ
ghelbig@lycos.com wrote:

> I'm trying to snag a 90nS pulse with a 16MHz clock. On paper, it > should work just fine: 62.5 < 90. > > What I see is that if the leading edge of the pulse is co-incident with > the leading edge of the clock, the pulse is not clocked in. (Which I > think it should be; at least on the next clock edge.) > > To make it more "interesting", it will then miss the next few pulses; > mayby 10 or so. > > After that, it will go back to normal operation, clocking in the pulses > as intended. > > Anyone else seen something like this? Any pointers as to what to look > for?
Can you post a sample design? Nowadays FFs, even when they go metastable, will only get into that state for a very brief time. Assuming the incoming pulse is asynchronous to your system clock, I'd say something like this should do the trick: entity snagpulse is port ( clk : in std_logic; rst : in std_logic; pulsein : in std_logic; snagged : out std_logic ); end snagpulse; architecture justtoillustrate of snagpulse is signal FF1, FF2, FF3; begin -- Sync the incoming pulse to the system clock process(clk) begin if rising_edge(clk) then FF1 <= pulsein; end if; end process; -- Time-shift the synchronized pulse and check if we see a rising edge process(clk, rst) begin if rst = '1' then FF2 <= '0'; FF3 <= '0'; elsif rising_edge(clk) then FF2 <= FF1; FF3 <= FF2; if FF2 = '1' and FF3 = '0' then snagged <= '1'; end if; end if; end process; end justtoillustrate; Best regards, Ben
Ben Twijnstra wrote:

Hmmm... Seem to have forgotten the bits where snagged is set to '0' again -
I'll trust everyone's intelligence to add the appropriate two statements.

Best regards,
Ben

While I am playing Altera support ;-)
Since there inevitably will be either 1 or 2 (never more) rising clock
edges during the pulse, just put a 2-input AND gate in front of the
D-input, and feed it with the pulse, and on its other input with the
inverted Q.
That means, once set, the flip-flop will inevitably be reset on the
next clock edge.
Peter Alfke

On Oct 25, 11:45 am, Ben Twijnstra <btwijns...@gmail.com> wrote:
> Ben Twijnstra wrote:Hmmm... Seem to have forgotten the bits where snagged is set to '0' again - > I'll trust everyone's intelligence to add the appropriate two statements. > > Best regards, > Ben
Peter Alfke schrieb:

> While I am playing Altera support ;-)
so it looks! BTW, there is an "A" in your name too ;) uups in mine too Antti
Thanks for the inputs so far!  Here's the code that's giving me greif:

architecture inside of stepmachine is

  type   pulsestate is (IDLE, PAUSE, OUT1, OUT2, OUT3);
  signal currentstate, nextstate : pulsestate;

  signal stretched : std_logic;

begin

  process(CLOCK, RESET)
  begin
    if(RESET = '1') then
      currentstate <= IDLE;
    elsif(CLOCK'event and CLOCK = '1') then
      currentstate <= nextstate;
    end if;
  end process;

  process(currentstate, pulse)
  begin

    case currentstate is

      when IDLE =>
        stretched <= '0';
        if (pulse = '1') then
          nextstate <= PAUSE;
        end if;

      when PAUSE =>
        stretched <= '0';
        nextstate <= OUT1;

      when OUT1 =>
        stretched <= '1';
        nextstate <= OUT2;

      when OUT2 =>
        stretched <= '1';
        nextstate <= OUT3;

      when OUT3 =>
        stretched <= '1';
        nextstate <= IDLE;

      when others =>
        stretched <= '0';
        nextstate <= IDLE;
        
    end case;
  end process;

Xntti, Mr Xlfke,

> While I am playing Altera support ;-)
You've got a definite knack for it - maybe you should apply for a job in Altera apps - I think they would be most happy to receive you ;-)
> Since there inevitably will be either 1 or 2 (never more) rising clock > edges during the pulse, just put a 2-input AND gate in front of the > D-input, and feed it with the pulse, and on its other input with the > inverted Q. > That means, once set, the flip-flop will inevitably be reset on the > next clock edge.
Well, what I've written pretty much does this (once you've added the "else snagged <= '0';" in the appropriate spot), except that it's one FF level deeper in order to really really really get around metastability, setup&hold violations etc. FF2 is the value of FF3's D input and FF3 is, well, FF3's Q output. This should result in an equation saying something like snagged.D = FF2 & !FF3; snagged.CLK = CLK; or so. Best regards, Ben
Assuming that "CLOCK" is your 16 MHz clock, and "pulse" is
your 90nS pulse, then it is no surprise at all that this design
is failing. The problem is you don't have a synchronizer on the
signal "pulse". Depending on how pulsestate is encoded,
multiple flipflops could change in this piece of code at the
indicated line

> when IDLE => > stretched <= '0'; > if (pulse = '1') then > nextstate <= PAUSE; <<<<<<<<<<< here's where crap happens > end if;
You must synchronize "pulse" before you use it in a state machine to affect state changes. Your problem is almost certainly not metastability (it is a race condition between multiple conditional paths), but the solution is the same as if it was a metastability issue. Add something that looks like this: signal pulse_sync_1 : std_logic; signal pulse_sync_2 : std_logic; process(CLOCK, RESET) begin if(RESET = '1') then pulse_sync_1 <= '0'; pulse_sync_2 <= '0'; elsif(CLOCK'event and CLOCK = '1') then pulse_sync_1 <= pulse; pulse_sync_2 <= pulse_sync_1; end if; end process; and use pulse_sync_2 rather than pulse in your state machine. This will add 2 cycles of latency, but it will solve your problem. To learn more about metastability and synchronizers, start reading here: http://www.fpga-faq.org/FAQ_Pages/0017_Tell_me_about_metastables.htm and look at the section "Multi-Stage Synchronizer" at: http://www.interfacebus.com/Design_MetaStable.html ( the dual FF circuit matches my code example above) Philip Freidin On 25 Oct 2006 15:02:09 -0700, ghelbig@lycos.com wrote:
>Thanks for the inputs so far! Here's the code that's giving me greif: > >architecture inside of stepmachine is > > type pulsestate is (IDLE, PAUSE, OUT1, OUT2, OUT3); > signal currentstate, nextstate : pulsestate; > > signal stretched : std_logic; > >begin > > process(CLOCK, RESET) > begin > if(RESET = '1') then > currentstate <= IDLE; > elsif(CLOCK'event and CLOCK = '1') then > currentstate <= nextstate; > end if; > end process; > > process(currentstate, pulse) > begin > > case currentstate is > > when IDLE => > stretched <= '0'; > if (pulse = '1') then > nextstate <= PAUSE; > end if; > > when PAUSE => > stretched <= '0'; > nextstate <= OUT1; > > when OUT1 => > stretched <= '1'; > nextstate <= OUT2; > > when OUT2 => > stretched <= '1'; > nextstate <= OUT3; > > when OUT3 => > stretched <= '1'; > nextstate <= IDLE; > > when others => > stretched <= '0'; > nextstate <= IDLE; > > end case; > end process;
=================== Philip Freidin philip.freidin@fpga-faq.org Host for WWW.FPGA-FAQ.ORG