Cross Clock Domains
This is not the place for being an authority on clock domain crossing techniques as a web search will throw up many authoritative and meritorious articles very quickly on the subject. Here are some at the top of the list:
- Some Simple Clock-Domain Crossing Solutions by The ZipCPU
- Introduction to Clock Domain Crossing: Double Flopping by Steve Arar
- Clock Domain Crossing (CDC) Design & Verification Techniques Using SystemVerilog by Clifford E. Cummings
- Understanding Clock Domain Crossing Issues by Saurabh Verma, Ashima S. Dabare
Instead here I'm concerned with making it easy to get familiar with someone else's HDL code, perhaps where there is some doubt over the safety of some of the cross clock domain signals. To do this I wanted a better way to visualise which clock domain each register was in based on the clock name on the clock pin. So I decided to try using a facility in Vivado where gates can be either or both 'highlighted' or 'marked'. Highlighted seemed to give the best results, here are a few to see if you are convinced about this sort of visualisation technique.
- Cross Clock Domains
- Basic Meta-stability
- Acknowledge transfers from faster to slower clock domains
- Tricky Cases
- Solution: TCL Procedure
- Larger Scale Testing
- References
Basic Meta-stability

First register in the old clock domain ensures the indicator signal exiting the source clock domain is glitch free and hence cannot be randomly sampled at the wrong value. Then the usual double retime registers are applied in the destination clock domain.
Acknowledge transfers from faster to slower clock domains

When an indicator is passed from a faster clock domain to a slower one, the value must be held long enough to be sample by the destination clock domain. Once sampled, it can be double retimed (green) and then acknowledged back to the source domain so it can be reset. However the acknowledgement needs to be double retimed before use back in the source clock domain (blue & orange). To make the point about the advantage of colours here I have used two different faster source clock domains for indicator signals to be passed to one slower one, perhaps on a memory bus back to CPU.
Tricky Cases

For transferring a stream of data one usually uses a dual port FIFO, and here we hit a snag. Which colour should we choose for the dual port BlockRAM, write or read clock? We can't, so I chose no colour, but I can colour the clock nets up to the pins. DSP primitives also have clock pins, but are not always used, so get tied low. This can be detected so that they are left without colour when not clocked.
Solution: TCL Procedure
The TCL code continues to evolve but currently stands at the following.
# Remove all highlighted colourings and marks for a blank canvas.
#
proc uncolor_registers {} {
unhighlight_objects -quiet [get_highlighted_objects]
unmark_objects -quiet [get_marked_objects]
}
# Colourise just the currently selected objects, and mark the ASYNC_REG registers.
#
# Returns a list of primitive instance names with multiple clocks that could
# not be highlighted multiple times.
#
proc colour_selected_primitives_by_clock_source {{objs {}}} {
if {[llength $objs] == 0} {
set objs [get_selected_objects]
}
if {[llength $objs] == 0} {
error "No cells selected or passed as a parameter."
}
uncolor_registers
set nextcol 1
set unhighlightable {}
foreach o $objs {
set clks [get_clocks -of_objects $o -quiet]
if {[llength $clks] == 1} {
if {![info exists clksrcarr($clks)]} {
if {$nextcol >= 21} {
error "Run out of colours"
}
# Add a new clock & color
set clksrcarr($clks) $nextcol
puts "Colour Index = $clksrcarr($clks), Clock = $clks"
set clkport [get_port $clks -quiet]
if {[llength $clkport] > 0} {
highlight_objects -color_index $clksrcarr($clks) $clkport
highlight_objects -color_index $clksrcarr($clks) [get_nets -segments [get_property SOURCE_PINS $clks]]
}
# Deal with differential clocks
set clkport [get_ports $clks -quiet]
if {[llength $clkport] > 0} {
set dp [get_property DIFF_PAIR_PORT $clkport -quiet]
if {([llength $dp] > 0) && (![info exists clksrcarr($dp)])} {
# Make the differential clock the same as its pair.
set clksrcarr($dp) $clksrcarr($clks)
puts "Colour Index = $clksrcarr($dp), Clock = $dp (differential clock)"
set diffport [get_port $dp -quiet]
if {[llength $diffport] > 0} {
highlight_objects -color_index $clksrcarr($dp) $diffport
# Need to find a way to grab the net here
highlight_objects -color_index $clksrcarr($clks) [get_nets -segments $diffport]
}
}
}
incr nextcol
if {$nextcol == 2 || $nextcol == 5} {
# Skip these colours (yellow and blue)
incr nextcol
}
}
# Highlight primitives and clock nets
if {([get_property IS_PRIMITIVE $o] == 1) ||
([get_property TYPE $o] == "GLOBAL_CLOCK") ||
([get_property TYPE $o] == "LOCAL_CLOCK") ||
([get_property TYPE $o] == "SIGNAL")} {
highlight_objects -color_index $clksrcarr($clks) $o
}
# Identify synchronising registers
if {[get_property ASYNC_REG $o] == 1} {
# RGB for Black
mark_objects -rgb {0 0 0} $o
}
} else {
# Ignore pins when listing unhighlightable objects
if {[llength [get_pins {vp891_fmc300_i/test_clk/frequency_counter_0/U0/frequency_counter_regs_inst/AR[0]} -quiet]] == 0} {
lappend unhighlightable $o
puts "Unhighlightable $o"
}
}
}
return $unhighlightable
}
A recent addition not shown in the diagrams here has been to add TCL code to mark registers with the ASYNC_REG property with a black diamond, making it easier to spot their omission. An even more recent addition includes managing differential clock pairs, simply giving each half of the pair the same colour index.
Larger Scale Testing

Speed is an issue with this TCL code. Initial attempts to colour a large design were too slow to be practically useful. So I converged on the idea that you would specify a list of cells to be coloured, and if that list is empty, the procedure would try to use any currently selected cells in the Vivado GUI, otherwise give up. A list of primitives that could not be coloured due to having multiple clocks is returned to make the point that they exist in the design.