EmbDev.net

Forum: FPGA, VHDL & Verilog Clock domain crossing


von Stefania M. (val_1010)


Rate this post
useful
not useful
Hi! I have a doubt regarding clock domain crossing from a fast clock to 
a slower one. Is it possible to use the two flip flops scheme? If yes, 
would my code be okay?

sinc_in indicates if data in is valid, sinc_out if data out is valid in 
the secod clock domain and clk1 is faster than clk2, so clk2 is the new 
domain.
1
entity clock_sync is
2
3
port(
4
     clk1 : in std_logic;
5
     clk2 : in std_logic;
6
     sync_in : in std_logic;
7
     Data_in : in std_logic_vector(7 downto 0);
8
     data_out : out std_logic_vector(7 downto 0);
9
     sync_out : out std_logic
10
);
11
architecture behavioral of clock_sync is
12
13
constant in: std_logic_vector (7 downto0):=(others=>0);
14
15
type ff is array(0 to 1) of std_logic_vector(7 downto 0);
16
17
signal sig_reg : ff:=(others=>in);
18
signal i: integer:=0;
19
20
begin
21
  process(Clock2)
22
    begin
23
      if rising_edge(Clock2) and sync_in=1 then
24
        if i < 2 then
25
         i<=i+1;
26
         sig_reg(i)<= Data_in;
27
         sync_out<=0;
28
        else data_out<=sig_reg(i-1);
29
             sync_out<=1;
30
        end if;
31
      end if;
32
   end process;
33
end behavioral;

Thank you!!

: Edited by User
von -gb- (Guest)


Rate this post
useful
not useful
Stefania M. wrote:
> if i < 2 then
>          i<=i+1;

Uiuiuiuiui, looks like a programming language ...

Stefania M. wrote:
> type ff is array(0 to 1) of std_logic_vector(7 downto 0);
>
> signal buffer : ff:=(others=>in);

Why not:

signal buffer: std_logic_vector(15 downto 0):=(others => '0');

Stefania M. wrote:
> Is it possible to use the two flip flops scheme? If yes,
> would my code be okay?

if Data_in is set for only one cycle of the fast clock, you can miss it 
with the slow clock. So no, this will not work reliable.

But Lothar has written a component which takes a short puls and converts 
it to an full clock cycle of another clock:
http://www.lothar-miller.de/s9y/archives/19-Kurzer-Spike-in-Puls-umgewandelt.html

Vivado from xilinx also has CDC XPMs which you could use. They are in 
the language templates XPM_CDC.

von Duke Scarring (Guest)


Rate this post
useful
not useful
-gb- wrote:
> buffer
Naming a signal 'buffer' is not the best idea, because it is a reserved 
word in VHDL:
https://www.xilinx.com/support/documentation/sw_manuals/xilinx11/ite_r_vhdl_reserved_words.htm

Duke

von Lothar M. (Company: Titel) (lkmiller) (Moderator)


Rate this post
useful
not useful
Stefania M. wrote:
> sinc_in indicates if data in is valid, sinc_out if data out is valid in
> the secod clock domain and clk1 is faster than clk2, so clk2 is the new
> domain.
Can you sketch this down in a timing diagram?

> Is it possible to use the two flip flops scheme?
Only when the data rate on the fast clock domain is slower than the clk 
on the slow clock domain.

> If yes, would my code be okay?
> if rising_edge(Clock2) and sync_in=1 then
Forget this, because sync_in is asynchronus to clk2 and then the usual 
happens: sync_in acts as an enable for the counter i which consists ofd 
several flipflops.
And so sync_in is routet to each of the flipflops. Finally you will get 
this:
http://www.lothar-miller.de/s9y/archives/64-State-Machine-mit-asynchronem-Eingang.html
Or, lets simply say the counter i is a FSM (as each counter is).
And never ever(!!) use an async input in a FSM

von -gb- (Guest)


Rate this post
useful
not useful
Duke Scarring wrote:
> Naming a signal 'buffer' is not the best idea, because it is a reserved
> word in VHDL:

You are right, sorry ...

von Christophz (Guest)


Rate this post
useful
not useful
Stefania M. wrote:
> Is it possible to use the two flip flops scheme?

Yes. But as Lothar pointed out, Sync_in is asynchronous to Clk2 so you 
have to apply the two flip flops to this signal.

And you have to validate that Sync_in is stable for enough time with 
regard to the slow clock. Either this is true due to your application or 
you make it true with a pulse-stretcher.

> If yes, would my code be okay?

No.

You applied the two flip flops to the parallel data. This can randomly 
fail due to latency differences in the separate parallel paths.
Have a look at the paper "Fourteen ways to fool your synchronizer", you 
hit number 12 on page 6 :-)


Example to do CDR in this case:
You synchronize Sync_in and then use this (let's call it Sync_clk2) 
signal to enable your single output register. Add another flip flop to 
Sync_clk2 to generate Sync_out so it will be high at the same time the 
data is valid at the register output.

von Jan M. (jamo)


Rate this post
useful
not useful
Hey,

the general approach is:

- create a 1-bit(!) toggle event in the fast clock domain (*_event) when 
your data changes
  - make sure that it is stable long enough so that in can be captured 
safely in the slow clock domain
- bring that into the slow clock domain with at least two FFs (*_meta 
and *_rt)
- create another delay FF of *_rt (*_rt_z) and compare that with xor or 
neq
  - if this comparison is true capture your bus from fast into slow 
clock domain

- you need to tell the synthesis tool your (known good) cdc paths (for 
Xilinx Vivado I always use set_max_delay constraints, better then just a 
tig/set_false_path)
- also use async_reg constraint on your *_meta/*_rt FF pairs
- for Altera/Intel they must be similiar constraints available

Good luck!

BR,
Jan :)

: Edited by User
von SparkyT (Guest)


Rate this post
useful
not useful
Hi,
does this technique for domain crossing from slow-to-fast apply when 
both CLK signals come from the same PLL and are in phase?
I have been using the 2 FF synchronization from fast-to-slow, bet never 
the other way around.

Thanks
T

Please log in before posting. Registration is free and takes only a minute.
Existing account
Do you have a Google/GoogleMail account? No registration required!
Log in with Google account
No account? Register here.