Toggle Synchronizer
A dual stage synchronizer cell ensures that the signal remains stable in the sampling clock domain but that is not enough. For example, in the case of a fast source clock to slow destination clock transfer, the signal transition may be lost if the source clock does not hold the signal long enough for the destination clock to sample. On the other hand, if the destination clock is slow, it can sample the signal more than once. Another pitfall is to synchronize both data and strobe (data_valid) signals causing a race condition as the data/strobe signal can change at different times based on PVT. Thus, synchronizers should not be used on individual bits but only on the control (valid or enable) signal.
A more robust and simple synchronization technique to solve these issues is known as toggle synchronizer or a pulse synchronizer. The toggle synchronizer has a signal synchronization stage and a req-ack protocol - i.e. the destination clock domain acks the source clock domain on reception of the signal transition change. The source clock domain signals another change in the strobe (valid) signal only on receiving this ACK. By using the change in signal’s level (transition) rather than level itself to communicate through the synchronizer makes this design robust.
A REQ path logic for the toggle synchronizer is depicted in the figure below - a signal transition in the source clock domain is translated to a signal pulse one cycle wide in the destination clock domain. By mirroring this REQ logic for a transfer from destination clock domain to source clock domain completes the handshaking scheme - a REQ-ACK protocol.
This scheme is elegant because there is no dependency on clock frequency relationships in source/destination domains. One caveat is that the input pulses must have a minimum spacing of atleast two destination synchronizer clock cycles for proper operation. If the input pulses are very close, there is a risk of the output pulse being longer than one clock cycle or not detecting the second transition at all.
This scheme can also be used to self clear interrupts where the CPU’s interrupt service routine writes to a interrupt clear register in the destination clock domain. In such a scenario, only the REQ path logic is necessary.
Sphere: Related ContentMetastability in Design
Clock domain crossings without proper synchronization is a common pitfall in digital design even for experienced engineers. Metastability is seldom understood clearly and one has to tread very carefully while handling blocks with muliple asynchronous clock domains. This post examines metastability behavior and it’s causes, usage of synchronizer cells to avoid metastability.
Metastability is when a flip-flop (FF) operates irregularly due to a data input timing violation i.e. the data switches within setup and hold specification of the FF. This may cause the output of the FF to have an unknown state for only a short duration or for one or more clock cycles. Metastability causes very intermittent and unpredictable behavior making it a very hard to debug problem post-silicon.
Metastability is common in asynchronous clock domain transfers. Two clock domains are considered asynchronous if
- the clocks are from two different sources.
- the clocks are from the same source but have unknown phase relationships.
- the clocks are not multiples of each other.
Metastability Results
Figure below depicts the effects of metastability on a design. The Dataout goes into an unknown metastable state that can cause lockup or malfunctioning of design downstream.
Besides causing malfunction of logic, metastability also causes circuits to consume additional power. A direct path from power to ground may exist if the intermediate voltage levels during metastability partially turns on both P and N transistors.
Metastability Causes
Metastability is affected by
- Setup and Hold window - Larger setup and hold time specification makes metastability more probable.
- Higher clock frequencies (clock edge occurs more often increasing the probability of a clock edge near the data transition)
- Data rise/fall times, load on the FF outputs, datapath delay to the next stage FF - the smaller the number, the better.
Mean Time Between Failures (MTBF)
MTBF is a probabilistic measure of how often malfunctioning can happen in a chip due to metastability. To calculate the MTBF, the data input frequency and clock frequency of each synchronizer is required. MTBF is defined by the equation below
MTBF = 1/(2 * fc * fd * W) where
fc is the clock frequency
fd is the data frequency
W is the width of the metastability window
A reasonable value of MTBF is 10,000 years. This may seem very large but the MTBF of a system is more important and a chip is only one component of the entire system. To calculate the MTBF of a system with n components, the following equation is used
MTBF (system) = 1 / ((1/MTBF1) + (1/MTBF2) + … + (1/MTBFn))
Thus a board with 10 components with MTBF of 1,000 years each would have a MTBF of 100 years. If there are 10 such boards in a system, the MTBF reduces to 10 years!
Synchronizers
Synchronizer cells have back-to-back flops are the easiest way to prevent metastability. The synchronizer cells have FFs that are specially designed to reduce the probablity of metastability.An added advantage of using sync cells instead of two flops is that there is minimal logic between the first and second stage of flops.
Design Guidelines
- Use synchronizer cells in the library to transfer between asynchronous clocks domains. Do NOT use two FFs instead of a synchronizer cell - the synchronizer cells are specifically designed to have lower metastability issues.
- Use synchronizers even with infrequently changing signals. A circuit may function improperly or lock-up if a signal goes metastable. Do not use synchronizers for same clock domain transfers because the MTBF adds up with increase in synchronizer cells.
- Add buffers to the input and output of the synchronizers. This aids in keeping the data rise/fall slopes sharp
- Minimize the number of paths from a synchronizer.
Edge Detector
Let's start with the most fundamental design that is widely used in logic design - the edge detector. The edge detector generates a synchronous one clock cycle pulse upon a change in level (transition) of a signal from high->low or low->high. Edge detectors are used to detect the initial condition and to trigger other logic dependent on this signal - an example would be an active low interrupt where the transition from high to low indicates an interrupt has been asserted.
The edge detect circuit and waves are depicted in the thumbnail below - this detects both rising and falling transitions of the signal.
Edge Detector Circuit
We will now look at the verilog code to implement this logic :
-
always @(posedge CLK or negedge RST_L) begin
-
if (~RST_L) begin
-
IN_D1 <= 1'b0;
-
IN_D2 <= 1'b0;
-
end
-
else begin
-
IN_D1 <= IN;
-
IN_D2 <= IN_D1;
-
end
-
end
-
-
wire OUT = IN_D1 ^ IN_D2; // detects both rising edge and falling edge transitions
-
wire OUT_posedge = IN_D1 & ~IN_D2; // detects rising edge
-
wire OUT_negedge = ~IN_D1 & IN_D2; // detects falling edge
Sphere: Related Content