4

Unlike Xilinx which provides their users with a set of convenient xpm_cdc_* modules, Lattice does not seem to have “the standard” way for clock domain crossing. So I have no choice other than write my own synchronizer.

In the Xilinx's world I'd use the ASYNC_REG and KEEP_HIERARCHY attributes to prevent the synthesizer from making destructive optimizations, and write some set_false_path constraint alongside.

It looks like /* synthesis syn_hier="hard" */ is the same thing as KEEP_HIERARCHY, but, unfortunately, I found no mention of ASYNC_REG in the Lattice docs.

What attribute (or combination of attributes) should I use instead?

Mitu Raj
  • 10,843
  • 6
  • 23
  • 46
firegurafiku
  • 247
  • 1
  • 7
  • You can't just run it through two flip-flop registers? Or is this on a different level than I am used to working with? I don't even know what these xpm_cdc_ modules you that you are referring to when you cross clock domains. – DKNguyen Feb 14 '22 at 21:44
  • What is your signal? Is it serial or parallel? Can’t you just put 1-bit shift registers when you cross domains. Usually you set the depth to 2. That’s what I’ve used and the synthesizer doesn’t touch them. Isn’t ASYNC_REG for simulation anyway? – user110971 Feb 14 '22 at 21:52
  • 1
    @user110971: It's not for simulation only. Citing the [UG912](https://www.xilinx.com/support/documentation/sw_manuals/xilinx2021_1/ug912-vivado-properties.pdf): “With the ASYNC_REG property, the registers are grouped so that they are placed as closely together as possible.” – firegurafiku Feb 14 '22 at 21:58
  • @dknguyen, the 2-DFF thing is fine for passing levels between domains but what about passing 1-CLK pulses into a slower clock domain (e.g. 100 MHz pulse to 6 MHz domain), or passing a 32-bit data bus without misalignment (some bits 1-CLK delayed) or metastability or wasting FIFO RAM on it. I've written my own to do these with full handshaking. Xilinx offer similar stuff, though I've not looked at them in donkey's years. – TonyM Feb 14 '22 at 22:47
  • "*or passing a 32-bit data bus without misalignment (some bits 1-CLK delayed)*" I guess that's a specific scenario I've never needed to do. What would you delay some of the signals in that data bus by one fast clock cycle for? – DKNguyen Feb 14 '22 at 23:04
  • @DKNguyen, that meant *passing a 32-bit data bus without misalignment (where 'misalignment' is some bits getting 1-CLK delayed and skewed from the others)* – TonyM Feb 14 '22 at 23:22
  • @TonyM I don't want to hijack these comments but isn't that one of the things the synthesizer takes care of anyways? Everything is flip-flopped already so doesn't it check the critical path to make sure nothing within the same register is misaligned outside of the clock? – DKNguyen Feb 14 '22 at 23:37
  • 1
    @DKNguyen, you're forgetting that we're talking about domain crossing, not within a single domain... (I agree - go to chat if you're still not getting this, we'll get through it swiftly enough). – TonyM Feb 14 '22 at 23:41
  • @TonyM https://chat.stackexchange.com/rooms/134129/crossing-domains – DKNguyen Feb 14 '22 at 23:42

1 Answers1

2

Write the flop synchronizer for CDC in plain RTL.

In Xilinx, ASYNC_REG attribute makes sure that the flops in the synchronizer chain are packed and placed as close as possible for the best MTBF, by placing most probably into the same slice.

Not familiar with Lattice, so I am not sure whether it has an equivalent attribute as in Xilinx, but would like to throw some light here.

Lattice seems to support SDC constraints. So what you can do is somehow force the synthesiser to place these flops together by enforcing a tight timing requirement between flop datapaths; by using set_max_delay constraint between their Q and D pins, i.e, on their datapath.

For e.g., for a two-flop synchronizer (F1-F2), it looks something like this (syntax may vary across tools):

set_max_delay 2 -from [get_pins {F1/Q}] -to [get_pins {F2/D}]

This is recommended in Xilinx as well, but it recommends its own flavor of SDC (XDC) which supports custom flag -datapath_only to ignore skews while analyzing these timing paths.

For an n-flop synchronizer, you would have to use n-1 constraints like above.

Also I would recommend to use the syn_keep attribute for the registers used in the synchronizer chain to avoid any possible optimizations.

Mitu Raj
  • 10,843
  • 6
  • 23
  • 46