olo_ft_fifo_async¶
Status Information¶
VHDL Source: olo_ft_fifo_async
Description¶
This component implements an ECC-protected asynchronous FIFO with TMR-hardened clock domain crossings. The data is protected by a SECDED (Single Error Correction, Double Error Detection) Hamming code and the Gray-pointer and reset crossings are single-SEU immune. The interface and behavior match olo_base_fifo_async.
The ECC is transparent to the user: data is automatically encoded on write and decoded/corrected on read. Error status flags indicate whether a single-bit error was corrected or a double-bit error was detected.
Generics¶
| Name | Type | Default | Description |
|---|---|---|---|
| Width_g | positive | - | Number of data bits per FIFO entry. The internal FIFO is wider to accommodate ECC parity bits. |
| Depth_g | positive | - | Number of entries (must be a power of two) |
| AlmFullOn_g | boolean | false | Enable almost-full flag |
| AlmFullLevel_g | natural | 0 | Almost-full threshold level |
| AlmEmptyOn_g | boolean | false | Enable almost-empty flag |
| AlmEmptyLevel_g | natural | 0 | Almost-empty threshold level |
| RamStyle_g | string | "auto" | Controls the RAM implementation resource |
| RamBehavior_g | string | "RBW" | Controls the RAM behavior. "RBW" or "WBR" |
| ReadyRstState_g | std_logic | '1' | Value of In_Ready during reset |
| Optimization_g | string | "SPEED" | "SPEED" or "LATENCY" |
| SyncStages_g | positive | 2 | Number of synchronizer stages per TMR chain in the pointer crossings (range 2..4) |
Interfaces¶
Input (In_Clk domain)¶
| Name | In/Out | Length | Default | Description |
|---|---|---|---|---|
| In_Clk | in | 1 | - | Input clock |
| In_Rst | in | 1 | - | Input reset (high-active, synchronous to In_Clk). Resets both sides of the FIFO through the internal reset crossing. |
| In_RstOut | out | 1 | N/A | Synchronized input-side reset output |
| In_Data | in | Width_g | - | Input data |
| In_Valid | in | 1 | '1' | Input valid (AXI-S handshaking) |
| In_Ready | out | 1 | N/A | Input ready (AXI-S handshaking) |
| In_Full | out | 1 | N/A | FIFO full (input side) |
| In_Empty | out | 1 | N/A | FIFO empty (input side) |
| In_AlmFull | out | 1 | N/A | Almost full (input side) |
| In_AlmEmpty | out | 1 | N/A | Almost empty (input side) |
| In_Level | out | ceil(log2(Depth_g+1)) | N/A | Fill level (input side) |
Output (Out_Clk domain)¶
| Name | In/Out | Length | Default | Description |
|---|---|---|---|---|
| Out_Clk | in | 1 | - | Output clock |
| Out_Rst | in | 1 | - | Output reset (high-active, synchronous to Out_Clk). Resets both sides of the FIFO through the internal reset crossing. |
| Out_RstOut | out | 1 | N/A | Synchronized output-side reset output |
| Out_Data | out | Width_g | N/A | Output data (corrected if a single-bit error was detected) |
| Out_Valid | out | 1 | N/A | Output valid (AXI-S handshaking) |
| Out_Ready | in | 1 | '1' | Output ready (AXI-S handshaking) |
| Out_EccSec | out | 1 | N/A | Single error corrected flag. Time-aligned with Out_Data. |
| Out_EccDed | out | 1 | N/A | Double error detected flag. Read data is unreliable. Time-aligned with Out_Data. |
| Out_Full | out | 1 | N/A | FIFO full (output side) |
| Out_Empty | out | 1 | N/A | FIFO empty (output side) |
| Out_AlmFull | out | 1 | N/A | Almost full (output side) |
| Out_AlmEmpty | out | 1 | N/A | Almost empty (output side) |
| Out_Level | out | ceil(log2(Depth_g+1)) | N/A | Fill level (output side) |
Error Injection (optional, In_Clk domain)¶
These ports drive the internal olo_ft_ecc_encode instance. Leave them unconnected for normal operation; see Open Logic Fault-Tolerance Principles - Error Injection for the latched-strobe semantics shared across the ft area.
| Name | In/Out | Length | Default | Description |
|---|---|---|---|---|
| In_ErrInj_BitFlip | in | eccCodewordWidth(Width_g) | all 0 | Codeword-wide flip pattern. Each '1' bit XORs (flips) the corresponding bit of the stored codeword. Popcount 1 = SEC-correctable, popcount 2 = DED-detectable. |
| In_ErrInj_Valid | in | 1 | '0' | Strobe that latches In_ErrInj_BitFlip into the encoder's pending-injection register. The latched pattern is applied to the next accepted input beat. |
Detailed Description¶
Architecture¶

The entity is a peer of olo_base_fifo_async: both instantiate the same private control core (pointer management, Gray coding, level/flag computation), but the fault-tolerant variant supplies hardened building blocks around it:
- olo_ft_ecc_encode (In_Clk domain) encodes each accepted input beat into a SECDED codeword.
- The shared control core plus an olo_base_ram_sdp instance store the codeword. All levels and status flags come from the core.
- Two olo_ft_cc_bits instances cross the Gray-coded write/read pointers between the domains, and one olo_ft_cc_reset instance crosses the resets. All three are TMR-hardened (triplicated synchronizer chains with per-bit majority voters).
- olo_ft_ecc_decode (Out_Clk domain) decodes and corrects each beat and drives Out_EccSec / Out_EccDed time-aligned with Out_Data.
Because encoding happens before, and decoding after, all storage elements, the codeword is protected end-to-end through the FIFO, including the core's internal write-data register.
See olo_base_fifo_async for detailed FIFO behavior.
Combinational ECC Encoder and Decoder¶
Both codecs are instantiated with Pipeline_g = 0. The datapath to and from the internal FIFO is
therefore combinational, and the ft entity behaves exactly like its
olo_base_fifo_async counterpart.
The ECC decode lies between the RAM output and the output ports and is the critical path of the entity. Where it limits the achievable clock frequency, add an olo_base_pl_stage on the output side in the surrounding design. Register Out_Data, Out_EccSec and Out_EccDed in the same stage to keep them aligned.
Clock Domain Crossing in TMR-Based Designs¶
This section documents the interaction between the asynchronous FIFO's internal clock domain
crossing (CDC) mechanism and Triple Module Redundancy (TMR) environments. It is relevant for
designers using this FIFO in radiation-hardened systems where vendor TMR tools (e.g., Synplify's
syn_radhardlevel = "tmr") are applied to the surrounding logic.
What ECC Protects¶
The ECC (SECDED Hamming code) protects the data stored in the block RAM. Data is encoded before writing and decoded/corrected after reading. This addresses the dominant radiation vulnerability: block RAM cells are static storage with large cross-sections and long exposure windows (data persists until the next write, which may be microseconds to mission-lifetime).
What the TMR Crossings Protect¶
The Gray-coded read/write pointers cross clock domains through olo_ft_cc_bits
instances: three independent synchronizer chains per crossing with a per-bit majority voter. A single SEU
on any synchronizer flip-flop is masked by the voter. The reset crossing is hardened the same way through
olo_ft_cc_reset. The manual TMR works regardless of whether vendor TMR is applied
to the rest of the design; the crossing entities carry syn_radhardlevel = "none" on their architectures
so vendor TMR tools do not triplicate the already-triplicated registers.
The remaining control flip-flops (binary pointers, flags and the handshake logic inside the control core)
are not manually triplicated. They should be covered by vendor TMR
(syn_radhardlevel = "tmr") as part of the surrounding radiation-hardened design, like all other
flip-flops. Unlike RAM cells, these flip-flops are refreshed every clock cycle, so a bit flip persists for
at most one clock period, which makes them orders of magnitude less vulnerable than the static RAM cells.
The Sampling Uncertainty + SEU Concern¶
Li, Nelson, and Wirthlin [1] demonstrated that when TMR is applied to signals crossing asynchronous clock domains, a combined failure mode can arise: the three TMR copies may arrive in the receiving domain on different clock cycles due to routing delay differences (signal skew) and the inherent randomness of asynchronous sampling. This is called sampling uncertainty. If this causes a 2-vs-1 disagreement, a single SEU on one of the agreeing copies can flip the majority vote, defeating TMR with a single fault.
Their fault injection experiments showed catastrophic failure rates for naively triplicated pulse-based synchronizers: only 47% of signals arrived correctly in the presence of a sensitive SEU.
Why Per-Bit Voting Is Safe for Gray-Coded FIFO Pointers¶
The Li et al. failure mode applies to transient pulse signals where missing one cycle means losing the information permanently. Gray-coded FIFO pointers are fundamentally different: they are persistent multi-bit level signals with per-bit majority voting. Three properties make them immune to this failure mode:
Property 1: Per-bit voting produces only valid pointer values.
The majority voter operates independently on each bit. At any sampling instant, the Gray code guarantee ensures that at most one bit is transitioning (all other bits are stable and identical across all three TMR copies). Therefore:
- For any stable bit: all three copies agree. A single SEU on one copy is corrected by the voter (2-of-3). This works unconditionally.
- For the one transitioning bit: sampling uncertainty may cause a 2-vs-1 split. A single SEU on the majority side can flip the voted result. But this only affects one bit, and that bit can only resolve to its old or new value. The result is either the current pointer value or the previous pointer value.
Since all other bits are voted correctly, the overall voted pointer is always either Gray(N) or
Gray(N+1), never an invalid value. An invalid pointer would require two simultaneous
SEUs, which is beyond TMR's protection model.
Property 2: Both possible voted values are safe for the FIFO.
The async FIFO is designed to operate with +-1 pointer uncertainty; this is the fundamental
design principle of Gray-coded CDC. The synchronized pointer is always a possibly-stale version
of the actual pointer. Whether the voter outputs Gray(N) or Gray(N+1):
- If the pointer appears more stale (old value): the FIFO flags are more conservative (full asserts earlier, empty de-asserts later). No data corruption; at worst, unnecessary backpressure for one cycle.
- If the pointer appears more fresh (new value): the FIFO flags are less conservative but still correct, since the pointer did reach that value.
Neither outcome causes an overflow, underflow, or read of invalid data.
Property 3: Any voter error self-corrects within one cycle.
The reflected binary Gray code has a second key property beyond single-bit changes: on two consecutive increments, never the same bit changes (the changing-bit pattern follows the ruler sequence: 0, 1, 0, 2, 0, 1, 0, 3, ...). Once a bit transitions, it holds its new value for at least two sender clock periods before it can possibly change again. This means:
- Cycle N: bit K transitions, sampling uncertainty + SEU causes the voter to output the old value
- Cycle N+1: a different bit transitions; bit K is now stable across all three TMR copies
- The voter for bit K now sees three identical inputs: correct output regardless of any SEU
The error is transient and self-heals on the next clock cycle.
No Clock Frequency Constraints¶
The Gray-coded pointer crossing has no constraints on the clock frequency ratio between the write and read clocks. The Gray code single-bit-change property applies at each individual sampling instant, not between consecutive samples. Even if the sender clock is much faster than the receiver clock and the pointer increments multiple times between receiver clock edges:
- At any receiver clock edge, the pointer is either stable or in the middle of a single-bit transition (the previous transitions have already settled)
- The receiver may "skip" intermediate pointer values, but each sample captures a valid Gray code value (or resolves metastability on one bit to an adjacent valid value)
- The only implicit requirement is that routing skew between pointer bits is less than one sender clock period, which is always satisfied in practical designs
Summary¶
| Concern | General TMR CDC [1] | Gray-Coded FIFO Pointers |
|---|---|---|
| Signal type | Transient pulse | Persistent level (multi-bit) |
| Voter granularity | Whole signal | Per-bit independent |
| "Wrong" voted value | Information lost | Previous valid pointer (safe) |
| Self-correction | No, the pulse is gone | Yes, within 1 cycle |
| Invalid output possible? | Yes | No, always Gray(N) or Gray(N+-1) |
| Single SEU consequence | MTTF worse than unmitigated | No functional impact |
| Clock ratio constraint | Yes (pulsewidth dependent) | None |
Recommendations for Radiation-Hardened Designs¶
-
Apply vendor TMR (
syn_radhardlevel = "tmr") to the logic surrounding the FIFO, including the FIFO's internal control logic. TMR covers flip-flops, LUT contents, and routing, which is everything except the block RAM contents (protected by the ECC) and the pointer/reset crossings (protected by their built-in manual TMR). -
Consider the FIFO residency time of your data. The SEU exposure window of a FIFO entry is the time between its write and its read. For long-lived buffer contents, use a scrubbed RAM (olo_ft_ram_sdp_scrub) instead of a FIFO, so single-bit errors cannot accumulate into uncorrectable double-bit errors.
ECC Overhead, Error Injection and Status Flags¶
See the corresponding sections in Open Logic Fault-Tolerance Principles:
- ECC Overhead - internal storage width vs. data width
- Error Injection - semantics of In_ErrInj_BitFlip / In_ErrInj_Valid
- Error Status Flags - meaning of Out_EccSec / Out_EccDed
Constraints¶
See
Open Logic Fault-Tolerance Principles - Constraints That Apply Across the Area
for the constraints that apply across the ft area. No additional olo_ft_fifo_async-specific constraints
apply.
References¶
[1] Y. Li, B. Nelson, and M. Wirthlin, "Synchronization Techniques for Crossing Multiple Clock Domains in FPGA-Based TMR Circuits," IEEE Transactions on Nuclear Science, vol. 57, no. 6, pp. 3506-3514, Dec. 2010. DOI: 10.1109/TNS.2010.2086075
[2] Y. Fan and Z. Deng, "Design and verification for CDC synchronization based on TMR," IEICE Electronics Express, vol. 17, no. 21, pp. 1-6, 2020. DOI: 10.1587/elex.17.20200287