olo_ft_private_cc_toggle¶
Status Information¶
VHDL Source: olo_ft_private_cc_toggle
Internal building block. This entity is the TMR-hardened pulse crossing instantiated by olo_ft_cc_simple (valid path), olo_ft_cc_status (token feedback path) and olo_ft_cc_handshake (acknowledge path). It is not intended for direct end-user instantiation and is documented here so the instantiating entities can reference its behavior in one place. For pulse crossings in user code, use olo_ft_cc_pulse.
Description¶
The entity transfers single-cycle pulses from one clock domain to another. It works like the pulse crossing of olo_base_cc_pulse: every input pulse toggles a level, the level is synchronized and an edge detector in the output clock domain converts every change of the level back into a single-cycle pulse.
In contrast to olo_base_cc_pulse, the entity does not contain a reset crossing. Both resets must already be crossed (e.g. the RstOut outputs of olo_ft_cc_reset), so both sides are in reset at the same time. This allows the instantiating entities to share one reset crossing for all their paths.
The pulse frequency must be significantly lower than the slower clock frequency. A spacing of 3 + SyncStages_g cycles of the slower clock is sufficient. The entity works for any clock ratio.
Generics¶
| Name | Type | Default | Description |
|---|---|---|---|
| SyncStages_g | positive | 2 | Number of synchronization stages. Range: 2 ... 4 |
Interfaces¶
| Name | In/Out | Length | Default | Description |
|---|---|---|---|---|
| In_Clk | in | 1 | - | Source clock |
| In_Rst | in | 1 | - | Reset (high-active, synchronous to In_Clk), already crossed |
| In_Pulse | in | 1 | - | Input pulse (synchronous to In_Clk) |
| Out_Clk | in | 1 | - | Destination clock |
| Out_Rst | in | 1 | - | Reset (high-active, synchronous to Out_Clk), already crossed |
| Out_Pulse | out | 1 | N/A | Output pulse, exactly one single-cycle pulse per input pulse |
Architecture¶
In_Clk domain : Out_Clk domain
:
In_Pulse --> XOR --> ToggleIn --> olo_ft_cc_bits --> ToggleOut --+-------------> XOR --> Out_Pulse
^ | : (3 chains + | ^
| v : voter) v |
vote <- ToggleLast[A,B,C] : ToggleOutLast[A,B,C] -> vote
- Toggle register (In_Clk): three copies. The next value of every copy is computed from the voted value, so an upset copy is repaired at the next clock edge.
- Synchronizer: olo_ft_cc_bits with three independent synchronizer chains and a majority voter.
- Edge detector (Out_Clk): three copies of the last synchronized toggle value and a voter.
Fault Tolerance¶
A single upset of any flip-flop neither produces a spurious output pulse nor loses or duplicates a pulse:
- Upsets of a toggle register copy or an edge detector copy are masked by the voters and repaired at the next clock edge.
- Upsets inside olo_ft_cc_bits are masked by its voter. The three synchronizer chains may see a toggle one clock cycle apart (sampling uncertainty). Because the toggle is a level and not a pulse, the voted toggle still changes exactly once per input pulse. A single upset during that window can at most delay the change until the last of the three chains sees the toggle, which is within the worst-case latency of a non-hardened synchronizer.
Why Not olo_ft_cc_pulse¶
olo_ft_cc_pulse implements the SR-latch based synchronizer from Li et al. Using it as the building block of the multi-bit crossings would change their behavior compared to the olo_base counterparts:
- It limits the clock ratio (approximately f_out < SyncStages_g x f_in). The feedback paths of olo_ft_cc_status and olo_ft_cc_handshake cross in the opposite direction, so both clocks would have to be within a factor of three of each other. The olo_base crossings work for any clock ratio.
- It supports only 3 or 4 sync stages, while the olo_base crossings support 2 to 4.
- Its output pulse is SyncStages_g - 1 cycles long and would need an additional edge detector.
The toggle-based crossing has none of these restrictions and keeps the timing of the olo_base crossings.