1

Background

I'm new to VHDL and trying to understand how to code a double flip flop to handle metastability associated with a user pressing a button on my fpga board (Cyclone V). I understand the logic behind using a double flip flop to stabilize the data, but unsure how to implement in VHDL.(Sources: related StackOverflow question, eetimes article)

Question

I'm not sure how to code the double flip flop (see my attempt below). Can someone please provide sample code that shows a working double flip flop?

Example code of my attempt at a double flip flop

--input is std_logic;
input <= key(0) -- user pressed key =1, key can be pressed and held

process(input)
   signal inputFF : std_logic;
begin
   if rising_edge(clock) then
      inputFF<= input;
      if input = '1' and inputFF = '1' then
          -- enter if-statement: user pressed the key and the data was 
          -- synchronized by going through a double flip flop?
      end if;
   end if;
end process;

My thoughts: I'm not sure if the if-statement is acting as a double flip flop or not. I pass the input to the inputFF on the rising_edge and then check if the input and inputFF are equal to 1.

bsheps
  • 1,438
  • 1
  • 15
  • 26
  • 1
    Your code only has a single FF. To have a double register, you'll need two signals assigned, one from input, and another from the first FF. Remember the first FF has a chance to be meta-stable, so you're only safe reading the 2nd FF in the chain. – Tricky Oct 15 '18 at 13:34
  • @Tricky Thanks for the reply. This is exactly where I'm lost. You're saying I need to make a second signal (inputFF2). Assign inputFF2 <= inputFF. Then in the if-statement I would only check if inputFF2 = '1'? – bsheps Oct 15 '18 at 13:41

1 Answers1

4

Here's one flip-flip:

process (clock)
begin
   if rising_edge(clock) then
      inputFF <= input;
   end if;
end process;

Here's another:

process (clock)
begin
   if rising_edge(clock) then
      inputFF2 <= inputFF;
   end if;
end process;

Most people would save some lines of code by combining them like this:

process (clock)
begin
   if rising_edge(clock) then
      inputFF  <= input;
      inputFF2 <= inputFF;
   end if;
end process;

The only safe signal to use is inputFF2. So, if you want to delay that further (for example to detect an edge on it) then you'll need more flip-flops.

Matthew Taylor
  • 13,365
  • 3
  • 17
  • 44
  • I didn't think to put the double FF in it's own process. Certainly makes the code more readable. Thanks for the insight! – bsheps Oct 15 '18 at 16:02
  • 1
    I would advise putting the double flip-flop in its own entity, never mind its own process. And I would instantiate that entity at the top level, not inside another block. Anything asynchronous (as this is) should _literally_ keep you awake at night. Imagine a QA auditor auditing your project. If they ask where the clock domain crossings are, you should be able to pull out a list and rely "here, here and here". If instead you reply "Ah...good question. Ummm... I think there may be one 12 levels of hierarchy down inside this block...errr..." then all is lost. – Matthew Taylor Oct 16 '18 at 07:55
  • For Altera FPGAs, you should apply a matching SDC constraint and a `SYNCHRONIZER_IDENTIFICATION` attribute. Using just 2 FFs in a row is not enough to create a good double-FF synchronizer. See the full code of an [Altera / Intel FPGA specific double-FF synchronizer](https://github.com/VLSI-EDA/PoC/blob/master/src/misc/sync/sync_Bits_Altera.vhdl?ts=2) – Paebbels Oct 21 '18 at 22:15
  • @Paebbels That sounds sensible. Another reason for putting the synchroniser in a separate layer of hierarchy was that (the hope that) the layout tool would lay out the flip-flops close together. (Though I'd always check with the layout engineer that the flip-flops were laid out correctly.) – Matthew Taylor Oct 22 '18 at 08:19