# What options do I have when synthesising control registers?

When your design includes control registers that are set/read on a dedicated clock domain (SPI or I2C etc), how do you usually deal with those?

For instance:

• Do you keep them on their own clock domain and false_path them to wherever they go, not worrying too much about metastability?

• Or maybe take loads of care to make sure there are meta-stable flops on each domain crossing, pushing up area in the case of large reg-maps? And if they span out into multiple clock domains, well, you just hang multiple synchronisers off the control line?

Any other suggestions I'm missing?

You have to pay attention EVERY time you cross clock domains. For each signal, you need to analyze it to see if special logic is required or not. If you don't then you will eventually get burned, and probably burned badly. It's possible that much of your logic doesn't need special synchronization, but you can't just assume that nothing is needed.

One thing that is super important, but often overlooked by even experts, is that you cannot just double-register (or double clock) busses (std_logic_vector in VHDL). Doing so would eliminate metastability issues, but not data errors due to skew between bits in the bus. Special logic is required for these cases.

The only case where "not worry too much about metastability" is an option is with quasi-static signals — signals that do not change when they are being actively used. Configuration settings that are applied once before starting to use the primary logic function and then left alone usually meet this description. This is a risky design practice. If you do it long enough, you'll eventually get burned, but maybe that's a risk you're willing to take. Also consider that any intentional cross-domain paths you add will make it more difficult to identify unintentional paths if you run an automated cross-domain path checker.

If that scares you away from unsynchronized use of the register data, you may want to consider:

• If most uses of the register bits are on a single, higher speed clock, you can implement the I2C/SPI interface in the fast clock domain. Immediately synchronize the low-speed inputs to the fast clock.

• Add the synchronization logic to the register read/write interface rather than downstream of the individual register bits. For multiple destination clocks, you can implement a one-to-many repeater. I'm not sure how well this approach meshes with the I2C/SPI protocols.

• You may call the practice risky, but in many cases it would seem nicer than the alternative. For example, in the ST32LF151 series, changing one of the alarm registers on the real-time clock requires disabling the alarm, waiting a synchronization delay, then setting it, and then re-enabling it. It would seem easier from both a hardware and software standpoint to say that one can change the alarm setting at any time, but one should disable the interrupt first, and after setting the alarm one must clear the alarm flag, read the time, and ensure the alarm time hasn't yet arrived. Aug 15, 2012 at 20:49
• Designing an RTC alarm in such fashion as to avoid any possibility of missed or spurious events when the alarm is changed would be difficult without making the alarm-setting synchronous, but simply saying "spurious or missed events may occur--deal with it" would seem easier from both a hardware and software perspective. I wonder why there aren't many timers with compare registers that can be written at arbitrary times, but which can work properly when the the timer's clock and CPU clock are asynchronous. If one is willing to ignore spurious events when writing, it would seem simple. Aug 15, 2012 at 20:54

Get your I2C and SPI signals into your main clock domain in a very controlled way, worrying all the while about metastability. Nail it down: constrain the tools so that your metastability resolution flipflops don't get placed on opposite sides of the chip, and don't get replicated (it's usually this that gets you when crossing clock domains, rather than metastability as such)

Once you've done that, your control and status registers can exist in your main clock domain and you need worry no more!