{"id":10178,"date":"2026-09-16T11:25:30","date_gmt":"2026-09-16T11:25:30","guid":{"rendered":"https:\/\/inskill.in\/training\/?p=10178"},"modified":"2026-09-15T11:27:05","modified_gmt":"2026-09-15T11:27:05","slug":"how-to-design-asynchronous-fifo-for-cdc","status":"publish","type":"post","link":"https:\/\/inskill.in\/training\/vlsi\/how-to-design-asynchronous-fifo-for-cdc\/","title":{"rendered":"How to Design an Asynchronous FIFO for CDC Applications"},"content":{"rendered":"\t\t<div data-elementor-type=\"wp-post\" data-elementor-id=\"10178\" class=\"elementor elementor-10178\">\n\t\t\t\t\t\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-2609c33 elementor-section-boxed elementor-section-height-default elementor-section-height-default wpr-particle-no wpr-jarallax-no wpr-parallax-no wpr-sticky-section-no\" data-id=\"2609c33\" data-element_type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-f6128c5\" data-id=\"f6128c5\" data-element_type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t\t\t<div class=\"elementor-element elementor-element-0733bfd elementor-widget elementor-widget-text-editor\" data-id=\"0733bfd\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t<style>\/*! elementor - v3.11.2 - 22-02-2023 *\/\n.elementor-widget-text-editor.elementor-drop-cap-view-stacked .elementor-drop-cap{background-color:#818a91;color:#fff}.elementor-widget-text-editor.elementor-drop-cap-view-framed .elementor-drop-cap{color:#818a91;border:3px solid;background-color:transparent}.elementor-widget-text-editor:not(.elementor-drop-cap-view-default) .elementor-drop-cap{margin-top:8px}.elementor-widget-text-editor:not(.elementor-drop-cap-view-default) .elementor-drop-cap-letter{width:1em;height:1em}.elementor-widget-text-editor .elementor-drop-cap{float:left;text-align:center;line-height:1;font-size:50px}.elementor-widget-text-editor .elementor-drop-cap-letter{display:inline-block}<\/style>\t\t\t\t<p><span style=\"font-weight: 400;\">Modern SoCs, ASICs and FPGA designs commonly contain multiple clock domains. A processor may run at one frequency, a peripheral at another, and a high-speed interface at yet another. When data needs to move between these unrelated clock domains, simply connecting a multi-bit bus from one domain to another can create serious clock domain crossing (CDC) problems.<\/span><\/p><p><span style=\"font-weight: 400;\">An asynchronous FIFO is one of the most widely used solutions for transferring multi-bit data safely between independent clock domains.<\/span><\/p><p><span style=\"font-weight: 400;\">Unlike a synchronous FIFO, an asynchronous FIFO has separate write and read clocks. The write side operates using one clock, while the read side operates using another clock with no fixed phase or frequency relationship.<\/span><\/p><p><span style=\"font-weight: 400;\">The challenging part is not storing the data. The difficult part is safely communicating the read and write positions between the two clock domains.<\/span><\/p><p><span style=\"font-weight: 400;\">This article explains how to design an asynchronous FIFO for CDC applications, including its architecture, binary and Gray-code pointers, two-flop synchronizers, full and empty detection, RTL implementation considerations, and verification strategy.<\/span><\/p><h3><span style=\"font-weight: 400;\">What Is an Asynchronous FIFO?<\/span><\/h3><p><span style=\"font-weight: 400;\">FIFO stands for First-In, First-Out.<\/span><\/p><p><span style=\"font-weight: 400;\">Data written first into the FIFO is read first, preserving the order of transactions.<\/span><\/p><p><span style=\"font-weight: 400;\">In an asynchronous FIFO, the write and read operations use independent clocks:<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0WRITE CLOCK DOMAIN<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0|<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Write Controller<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0|<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0v<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0+&#8212;&#8212;&#8212;&#8211;+<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0| \u00a0 Memory\u00a0 |<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0+&#8212;&#8212;&#8212;&#8211;+<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0|<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0^<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Read Controller<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0|<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0READ CLOCK DOMAIN<\/span><\/p><p>\u00a0<\/p><p><span style=\"font-weight: 400;\">For example:<\/span><\/p><p><span style=\"font-weight: 400;\">write_clk = 100 MHz<\/span><\/p><p><span style=\"font-weight: 400;\">read_clk\u00a0 = 75 MHz<\/span><\/p><p>\u00a0<\/p><p><span style=\"font-weight: 400;\">The clocks may have completely different frequencies and phase relationships.<\/span><\/p><p><span style=\"font-weight: 400;\">This makes the asynchronous FIFO useful when two subsystems cannot operate from the same clock.<\/span><\/p><p><span style=\"font-weight: 400;\">Typical applications include:<\/span><\/p><ul><li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">SoC subsystem communication<\/span><\/li><li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Processor and peripheral interfaces<\/span><\/li><li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Network data paths<\/span><\/li><li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">FPGA multi-clock designs<\/span><\/li><li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">DMA data movement<\/span><\/li><li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Audio and video pipelines<\/span><\/li><li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">High-speed interface buffering<\/span><\/li><li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Rate matching between independent blocks<\/span><\/li><\/ul><p><span style=\"font-weight: 400;\">Inskill&#8217;s CDC material also identifies asynchronous FIFOs as a common solution for multi-bit data transfer between clock domains.<\/span><\/p><h3><span style=\"font-weight: 400;\">Why Is an Asynchronous FIFO Needed for CDC?<\/span><\/h3><p><span style=\"font-weight: 400;\">Consider a simple 8-bit data bus crossing from <\/span><span style=\"font-weight: 400;\">clk_a<\/span><span style=\"font-weight: 400;\"> to <\/span><span style=\"font-weight: 400;\">clk_b<\/span><span style=\"font-weight: 400;\">.<\/span><\/p><p><span style=\"font-weight: 400;\">A beginner might try:<\/span><\/p><p><span style=\"font-weight: 400;\">clk_a domain<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0|<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a08-bit data<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0|<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0v<\/span><\/p><p><span style=\"font-weight: 400;\">clk_b domain<\/span><\/p><p>\u00a0<\/p><p><span style=\"font-weight: 400;\">This is unsafe when the clocks are asynchronous.<\/span><\/p><p><span style=\"font-weight: 400;\">Each bit can potentially be sampled at a different point in time. If the source data changes near the receiving clock edge, the destination may capture an inconsistent combination of bits.<\/span><\/p><p><span style=\"font-weight: 400;\">A two-flop synchronizer is useful for a single-bit control signal, but it is not by itself a safe solution for transferring an arbitrary multi-bit data bus.<\/span><\/p><p><span style=\"font-weight: 400;\">An asynchronous FIFO solves this problem by separating:<\/span><\/p><ul><li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Data storage<\/span><\/li><li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Write control<\/span><\/li><li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Read control<\/span><\/li><li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Pointer synchronization<\/span><\/li><\/ul><p><span style=\"font-weight: 400;\">The data is stored in the FIFO memory, while the information about where the writer and reader are located is transferred safely between clock domains.<\/span><\/p><h3><span style=\"font-weight: 400;\">Basic Architecture of an Asynchronous FIFO<\/span><\/h3><p><span style=\"font-weight: 400;\">A typical asynchronous FIFO contains:<\/span><\/p><ol><li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Dual-clock memory<\/span><\/li><li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Write binary pointer<\/span><\/li><li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Write Gray-code pointer<\/span><\/li><li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Read binary pointer<\/span><\/li><li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Read Gray-code pointer<\/span><\/li><li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Write-pointer synchronizer<\/span><\/li><li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Read-pointer synchronizer<\/span><\/li><li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Full detection logic<\/span><\/li><li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Empty detection logic<\/span><\/li><\/ol><p><span style=\"font-weight: 400;\">The architecture can be represented as:<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0WRITE CLOCK DOMAIN<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0|<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Write Binary Ptr<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0|<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0v<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Gray Conversion<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0|<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0v<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Write Gray Ptr<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0|<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0| CDC<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0v<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0+&#8212;&#8212;&#8212;&#8212;&#8211;+<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0| 2-FF Sync\u00a0 \u00a0 |<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0+&#8212;&#8212;&#8212;&#8212;&#8211;+<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0|<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0v<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0READ CLOCK DOMAIN<\/span><\/p><p><br \/><br \/><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0READ CLOCK DOMAIN<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0|<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Read Binary Ptr<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0|<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0v<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Gray Conversion<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0|<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0v<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Read Gray Ptr<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0|<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0| CDC<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0v<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0+&#8212;&#8212;&#8212;&#8212;&#8211;+<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0| 2-FF Sync\u00a0 \u00a0 |<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0+&#8212;&#8212;&#8212;&#8212;&#8211;+<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0|<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0v<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0WRITE CLOCK DOMAIN<\/span><\/p><p>\u00a0<\/p><p><span style=\"font-weight: 400;\">The important design principle is:<\/span><\/p><p><span style=\"font-weight: 400;\">Binary pointers are used locally for addressing and counting, while Gray-coded pointers are used for clock-domain crossing.<\/span><\/p><h3><span style=\"font-weight: 400;\">Why Are Gray-Code Pointers Used?<\/span><\/h3><p><span style=\"font-weight: 400;\">This is one of the most important concepts in asynchronous FIFO design.<\/span><\/p><p><span style=\"font-weight: 400;\">A binary counter can change multiple bits during a single increment.<\/span><\/p><p><span style=\"font-weight: 400;\">For example:<\/span><\/p><p><span style=\"font-weight: 400;\">0111 \u2192 1000<\/span><\/p><p>\u00a0<\/p><p><span style=\"font-weight: 400;\">Four bits change at the same time.<\/span><\/p><p><span style=\"font-weight: 400;\">If another asynchronous clock samples the counter during this transition, it could observe an unintended combination of bits.<\/span><\/p><p><span style=\"font-weight: 400;\">That can produce an incorrect pointer value.<\/span><\/p><p><span style=\"font-weight: 400;\">Gray code solves this problem because only one bit changes between adjacent Gray-code values.<\/span><\/p><p><span style=\"font-weight: 400;\">For example:<\/span><\/p><p><span style=\"font-weight: 400;\">Binary \u00a0 \u00a0 \u00a0 Gray<\/span><\/p><p><span style=\"font-weight: 400;\">0000 \u00a0 \u00a0 \u00a0 \u00a0 0000<\/span><\/p><p><span style=\"font-weight: 400;\">0001 \u00a0 \u00a0 \u00a0 \u00a0 0001<\/span><\/p><p><span style=\"font-weight: 400;\">0010 \u00a0 \u00a0 \u00a0 \u00a0 0011<\/span><\/p><p><span style=\"font-weight: 400;\">0011 \u00a0 \u00a0 \u00a0 \u00a0 0010<\/span><\/p><p><span style=\"font-weight: 400;\">0100 \u00a0 \u00a0 \u00a0 \u00a0 0110<\/span><\/p><p>\u00a0<\/p><p><span style=\"font-weight: 400;\">Therefore, asynchronous FIFO designs normally convert the local binary pointer to Gray code before sending it to the other clock domain.<\/span><\/p><p><span style=\"font-weight: 400;\">The standard approach is widely used in asynchronous FIFO implementations and CDC methodologies.<\/span><\/p><h3><span style=\"font-weight: 400;\">Binary-to-Gray Conversion<\/span><\/h3><p><span style=\"font-weight: 400;\">The standard conversion from binary to Gray code is:<\/span><\/p><p><span style=\"font-weight: 400;\">gray = binary ^ (binary &gt;&gt; 1);<\/span><\/p><p>\u00a0<\/p><p><span style=\"font-weight: 400;\">For example, in SystemVerilog:<\/span><\/p><p><span style=\"font-weight: 400;\">assign wr_ptr_gray = wr_ptr_bin ^ (wr_ptr_bin &gt;&gt; 1);<\/span><\/p><p><span style=\"font-weight: 400;\">assign rd_ptr_gray = rd_ptr_bin ^ (rd_ptr_bin &gt;&gt; 1);<\/span><\/p><p>\u00a0<\/p><p><span style=\"font-weight: 400;\">The binary pointer remains local to its own clock domain.<\/span><\/p><p><span style=\"font-weight: 400;\">The Gray-coded version is the one that crosses into the other domain.<\/span><\/p><h3><span style=\"font-weight: 400;\">Why Does the FIFO Pointer Need an Extra Bit?<\/span><\/h3><p><span style=\"font-weight: 400;\">An asynchronous FIFO generally uses a pointer that is one bit wider than the memory address.<\/span><\/p><p><span style=\"font-weight: 400;\">For a FIFO with depth 8:<\/span><\/p><p><span style=\"font-weight: 400;\">Address bits = 3<\/span><\/p><p><span style=\"font-weight: 400;\">Pointer bits = 4<\/span><\/p><p>\u00a0<\/p><p><span style=\"font-weight: 400;\">The lower bits identify the memory location.<\/span><\/p><p><span style=\"font-weight: 400;\">The additional bit helps identify whether the write pointer has wrapped around and caught up with the read pointer.<\/span><\/p><p><span style=\"font-weight: 400;\">This distinction is important because:<\/span><\/p><p><span style=\"font-weight: 400;\">write pointer == read pointer<\/span><\/p><p>\u00a0<\/p><p><span style=\"font-weight: 400;\">can mean that the FIFO is empty, but pointer equality can also occur after the writer has wrapped around and filled the FIFO.<\/span><\/p><p><span style=\"font-weight: 400;\">The extra pointer bit helps distinguish these conditions.<\/span><\/p><h3><span style=\"font-weight: 400;\">Two-Flop Synchronization<\/span><\/h3><p><span style=\"font-weight: 400;\">After converting a pointer to Gray code, it still cannot be directly used in the opposite clock domain.<\/span><\/p><p><span style=\"font-weight: 400;\">It must pass through a synchronizer.<\/span><\/p><p><span style=\"font-weight: 400;\">For example:<\/span><\/p><p><span style=\"font-weight: 400;\">Write Gray Pointer<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0|<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0v<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0+&#8212;&#8212;-+<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0| Sync1 |<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0+&#8212;&#8212;-+<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0|<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0v<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0+&#8212;&#8212;-+<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0| Sync2 |<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0+&#8212;&#8212;-+<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0|<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0v<\/span><\/p><p><span style=\"font-weight: 400;\">Read Domain<\/span><\/p><p>\u00a0<\/p><p><span style=\"font-weight: 400;\">A simplified SystemVerilog implementation is:<\/span><\/p><p><span style=\"font-weight: 400;\">always_ff @(posedge rd_clk or negedge rd_rst_n) begin<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0if (!rd_rst_n) begin<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0wr_gray_sync1 &lt;= &#8216;0;<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0wr_gray_sync2 &lt;= &#8216;0;<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0end<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0else begin<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0wr_gray_sync1 &lt;= wr_ptr_gray;<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0wr_gray_sync2 &lt;= wr_gray_sync1;<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0end<\/span><\/p><p><span style=\"font-weight: 400;\">end<\/span><\/p><p>\u00a0<\/p><p><span style=\"font-weight: 400;\">The same approach is used to transfer the read pointer into the write domain.<\/span><\/p><p><span style=\"font-weight: 400;\">The first synchronizer stage may encounter metastability. The second stage provides additional time for that metastability to resolve before the synchronized pointer is used by destination-domain logic.<\/span><\/p><p><span style=\"font-weight: 400;\">Importantly, the synchronizer does not make metastability impossible. It reduces the probability that metastability propagates into functional logic.<\/span><\/p><h3><span style=\"font-weight: 400;\">Write Pointer Logic<\/span><\/h3><p><span style=\"font-weight: 400;\">The write pointer belongs entirely to the write clock domain.<\/span><\/p><p><span style=\"font-weight: 400;\">A typical sequence is:<\/span><\/p><p><span style=\"font-weight: 400;\">write request<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0|<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0v<\/span><\/p><p><span style=\"font-weight: 400;\">FIFO full?<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\/ \u00a0 \u00a0 \\<\/span><\/p><p><span style=\"font-weight: 400;\">YES\u00a0 \u00a0 \u00a0 NO<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0|\u00a0 \u00a0 \u00a0 \u00a0 |<\/span><\/p><p><span style=\"font-weight: 400;\">No write\u00a0 Write data<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0|<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0v<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Increment pointer<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0|<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0v<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Binary \u2192 Gray<\/span><\/p><p>\u00a0<\/p><p><span style=\"font-weight: 400;\">The pointer should advance only when a valid write is accepted.<\/span><\/p><p><span style=\"font-weight: 400;\">Conceptually:<\/span><\/p><p><span style=\"font-weight: 400;\">if (wr_en &amp;&amp; !full)<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0wr_ptr_bin &lt;= wr_ptr_bin + 1&#8217;b1;<\/span><\/p><p>\u00a0<\/p><p><span style=\"font-weight: 400;\">The corresponding Gray pointer is then generated from the next binary pointer.<\/span><\/p><p><span style=\"font-weight: 400;\">The write address is derived from the local binary pointer.<\/span><\/p><h3><span style=\"font-weight: 400;\">Read Pointer Logic<\/span><\/h3><p><span style=\"font-weight: 400;\">The read pointer operates independently using the read clock.<\/span><\/p><p><span style=\"font-weight: 400;\">The basic sequence is:<\/span><\/p><p><span style=\"font-weight: 400;\">read request<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0|<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0v<\/span><\/p><p><span style=\"font-weight: 400;\">FIFO empty?<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\/\u00a0 \u00a0 \u00a0 \\<\/span><\/p><p><span style=\"font-weight: 400;\">YES \u00a0 \u00a0 \u00a0 NO<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0| \u00a0 \u00a0 \u00a0 \u00a0 |<\/span><\/p><p><span style=\"font-weight: 400;\">No read\u00a0 \u00a0 Read data<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0|<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0v<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Increment pointer<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0|<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0v<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Binary \u2192 Gray<\/span><\/p><p>\u00a0<\/p><p><span style=\"font-weight: 400;\">Conceptually:<\/span><\/p><p><span style=\"font-weight: 400;\">if (rd_en &amp;&amp; !empty)<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0rd_ptr_bin &lt;= rd_ptr_bin + 1&#8217;b1;<\/span><\/p><p>\u00a0<\/p><p><span style=\"font-weight: 400;\">The read address comes from the local read pointer.<\/span><\/p><h3><span style=\"font-weight: 400;\">How Is FIFO Empty Detected?<\/span><\/h3><p><span style=\"font-weight: 400;\">The empty condition is generated in the read clock domain.<\/span><\/p><p><span style=\"font-weight: 400;\">Conceptually, the FIFO becomes empty when the next read pointer catches up with the synchronized write pointer.<\/span><\/p><p><span style=\"font-weight: 400;\">A simplified expression is:<\/span><\/p><p><span style=\"font-weight: 400;\">empty = next_read_gray == synchronized_write_gray<\/span><\/p><p>\u00a0<\/p><p><span style=\"font-weight: 400;\">The important point is that the read side does not directly compare its pointer against an asynchronous write pointer.<\/span><\/p><p><span style=\"font-weight: 400;\">It compares against the synchronized Gray-coded write pointer.<\/span><\/p><p><span style=\"font-weight: 400;\">This keeps the comparison within the read clock domain.<\/span><\/p><h3><span style=\"font-weight: 400;\">How Is FIFO Full Detected?<\/span><\/h3><p><span style=\"font-weight: 400;\">Full detection is generated in the write clock domain.<\/span><\/p><p><span style=\"font-weight: 400;\">The write side compares its next Gray-coded pointer against the synchronized read pointer.<\/span><\/p><p><span style=\"font-weight: 400;\">For a conventional power-of-two asynchronous FIFO, the full comparison uses the wrap-around relationship represented by the additional pointer bits.<\/span><\/p><p><span style=\"font-weight: 400;\">Conceptually:<\/span><\/p><p><span style=\"font-weight: 400;\">next_write_pointer<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0|<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0v<\/span><\/p><p><span style=\"font-weight: 400;\">Compare with<\/span><\/p><p><span style=\"font-weight: 400;\">synchronized read pointer<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0|<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0v<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0FULL<\/span><\/p><p>\u00a0<\/p><p><span style=\"font-weight: 400;\">In a common Gray-pointer implementation, the required upper pointer bits are inverted for the full comparison while the remaining bits match. This distinguishes a full FIFO from an empty FIFO after pointer wrap-around.<\/span><\/p><h3><span style=\"font-weight: 400;\">Complete Asynchronous FIFO Data Flow<\/span><\/h3><p><span style=\"font-weight: 400;\">Putting the pieces together:<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0WRITE DOMAIN<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0|<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0wr_en<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0|<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0v<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Full Check<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0|<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0+&#8212;+&#8212;+<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0| \u00a0 \u00a0 \u00a0 |<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Full\u00a0 \u00a0 Not Full<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0| \u00a0 \u00a0 \u00a0 |<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Stop\u00a0 \u00a0 Write<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0|<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0v<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Memory Write<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0|<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Binary Pointer<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0|<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Gray Convert<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0|<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0v<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a02-FF Sync<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0|<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0v<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0READ DOMAIN<\/span><\/p><p><br \/><br \/><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0READ DOMAIN<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0|<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0rd_en<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0|<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0v<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Empty Check<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0|<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0+&#8212;+&#8212;+<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0| \u00a0 \u00a0 \u00a0 |<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Empty \u00a0 Not Empty<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0| \u00a0 \u00a0 \u00a0 |<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Stop \u00a0 \u00a0 Read<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0|<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0v<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Memory Read<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0|<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Binary Pointer<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0|<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Gray Convert<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0|<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0v<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a02-FF Sync<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0|<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0v<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0WRITE DOMAIN<\/span><\/p><p>\u00a0<\/p><p><span style=\"font-weight: 400;\">This architecture allows the two sides to operate independently.<\/span><\/p><h3><span style=\"font-weight: 400;\">Example RTL Structure<\/span><\/h3><p><span style=\"font-weight: 400;\">Instead of placing everything inside one large RTL module, a clean asynchronous FIFO can be divided into logical blocks:<\/span><\/p><p><span style=\"font-weight: 400;\">async_fifo<\/span><\/p><p><span style=\"font-weight: 400;\">\u2502<\/span><\/p><p><span style=\"font-weight: 400;\">\u251c\u2500\u2500 FIFO memory<\/span><\/p><p><span style=\"font-weight: 400;\">\u2502<\/span><\/p><p><span style=\"font-weight: 400;\">\u251c\u2500\u2500 write pointer logic<\/span><\/p><p><span style=\"font-weight: 400;\">\u2502<\/span><\/p><p><span style=\"font-weight: 400;\">\u251c\u2500\u2500 read pointer logic<\/span><\/p><p><span style=\"font-weight: 400;\">\u2502<\/span><\/p><p><span style=\"font-weight: 400;\">\u251c\u2500\u2500 write-to-read synchronizer<\/span><\/p><p><span style=\"font-weight: 400;\">\u2502<\/span><\/p><p><span style=\"font-weight: 400;\">\u251c\u2500\u2500 read-to-write synchronizer<\/span><\/p><p><span style=\"font-weight: 400;\">\u2502<\/span><\/p><p><span style=\"font-weight: 400;\">\u251c\u2500\u2500 full generation<\/span><\/p><p><span style=\"font-weight: 400;\">\u2502<\/span><\/p><p><span style=\"font-weight: 400;\">\u2514\u2500\u2500 empty generation<\/span><\/p><p>\u00a0<\/p><p><span style=\"font-weight: 400;\">This modular structure makes the design easier to review, debug and verify.<\/span><\/p><p><span style=\"font-weight: 400;\">It also makes CDC analysis more straightforward.<\/span><\/p><h3><span style=\"font-weight: 400;\">Why Can&#8217;t We Synchronize the Binary Pointer Directly?<\/span><\/h3><p><span style=\"font-weight: 400;\">This is a common interview question.<\/span><\/p><p><span style=\"font-weight: 400;\">Suppose a binary pointer changes:<\/span><\/p><p><span style=\"font-weight: 400;\">0111 \u2192 1000<\/span><\/p><p>\u00a0<\/p><p><span style=\"font-weight: 400;\">Several bits change simultaneously.<\/span><\/p><p><span style=\"font-weight: 400;\">Because the receiving clock is asynchronous, it may sample the transition at an arbitrary point.<\/span><\/p><p><span style=\"font-weight: 400;\">The resulting value can be invalid.<\/span><\/p><p><span style=\"font-weight: 400;\">With Gray code:<\/span><\/p><p><span style=\"font-weight: 400;\">Gray pointer<\/span><\/p><p><span style=\"font-weight: 400;\">changes by one bit<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u2193<\/span><\/p><p><span style=\"font-weight: 400;\">Only one CDC bit changes<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u2193<\/span><\/p><p><span style=\"font-weight: 400;\">Synchronize Gray pointer<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u2193<\/span><\/p><p><span style=\"font-weight: 400;\">Use synchronized value<\/span><\/p><p>\u00a0<\/p><p><span style=\"font-weight: 400;\">That is why asynchronous FIFO designs normally transfer Gray-coded pointers rather than raw binary pointers.<\/span><\/p><h3><span style=\"font-weight: 400;\">Reset Considerations<\/span><\/h3><p><span style=\"font-weight: 400;\">Reset handling is another important part of asynchronous FIFO design.<\/span><\/p><p><span style=\"font-weight: 400;\">At reset, both pointers are normally initialized to zero:<\/span><\/p><p><span style=\"font-weight: 400;\">write pointer = 0<\/span><\/p><p><span style=\"font-weight: 400;\">read pointer\u00a0 = 0<\/span><\/p><p>\u00a0<\/p><p><span style=\"font-weight: 400;\">This results in the FIFO initially being empty.<\/span><\/p><p><span style=\"font-weight: 400;\">However, reset signals themselves cross clock-domain boundaries in many real designs, so reset assertion and especially reset de-assertion must be designed carefully.<\/span><\/p><p><span style=\"font-weight: 400;\">For independently reset clock domains, engineers need to consider:<\/span><\/p><ul><li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Reset synchronization<\/span><\/li><li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Reset release ordering<\/span><\/li><li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Pointer initialization<\/span><\/li><li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Synchronizer initialization<\/span><\/li><li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Empty\/full flag behavior<\/span><\/li><li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Recovery after reset<\/span><\/li><\/ul><p><span style=\"font-weight: 400;\">A FIFO that works correctly during normal operation can still have a CDC problem if reset behavior is not considered.<\/span><\/p><h3><span style=\"font-weight: 400;\">How to Verify an Asynchronous FIFO<\/span><\/h3><p><span style=\"font-weight: 400;\">Designing the FIFO is only half of the task.<\/span><\/p><p><span style=\"font-weight: 400;\">A proper verification environment should test the FIFO with independent clocks.<\/span><\/p><p><span style=\"font-weight: 400;\">For example:<\/span><\/p><p><span style=\"font-weight: 400;\">write_clk = 10 ns<\/span><\/p><p><span style=\"font-weight: 400;\">read_clk\u00a0 = 14 ns<\/span><\/p><p>\u00a0<\/p><p><span style=\"font-weight: 400;\">The relative phase continuously changes, giving the testbench different sampling relationships.<\/span><\/p><p><span style=\"font-weight: 400;\">Useful verification scenarios include:<\/span><\/p><h5><span style=\"font-weight: 400;\">Basic write and read<\/span><\/h5><p><span style=\"font-weight: 400;\">Write several values and confirm that they are read in exactly the same order.<\/span><\/p><h5><span style=\"font-weight: 400;\">FIFO empty condition<\/span><\/h5><p><span style=\"font-weight: 400;\">Read until the FIFO becomes empty and verify that no additional read is accepted.<\/span><\/p><h5><span style=\"font-weight: 400;\">FIFO full condition<\/span><\/h5><p><span style=\"font-weight: 400;\">Write until the FIFO becomes full and verify that additional writes are blocked.<\/span><\/p><h5><span style=\"font-weight: 400;\">Simultaneous read and write<\/span><\/h5><p><span style=\"font-weight: 400;\">Perform reads and writes at the same time using independent clocks.<\/span><\/p><h5><span style=\"font-weight: 400;\">Different clock frequencies<\/span><\/h5><p><span style=\"font-weight: 400;\">Try several combinations:<\/span><\/p><p><span style=\"font-weight: 400;\">Fast write \/ slow read<\/span><\/p><p><span style=\"font-weight: 400;\">Slow write \/ fast read<\/span><\/p><p><span style=\"font-weight: 400;\">Equal frequency \/ unrelated phase<\/span><\/p><p>\u00a0<\/p><h5><span style=\"font-weight: 400;\">Reset during operation<\/span><\/h5><p><span style=\"font-weight: 400;\">Test reset at different points in the FIFO transaction sequence.<\/span><\/p><h5><span style=\"font-weight: 400;\">Randomized traffic<\/span><\/h5><p><span style=\"font-weight: 400;\">Generate random write\/read operations and compare the FIFO output against a reference queue.<\/span><\/p><p><span style=\"font-weight: 400;\">A self-checking reference model is especially useful because it can verify both data ordering and data integrity. Current asynchronous-FIFO verification examples commonly combine reference models, assertions and randomized traffic.<\/span><\/p><h3><span style=\"font-weight: 400;\">Important Assertions for an Async FIFO<\/span><\/h3><p><span style=\"font-weight: 400;\">SystemVerilog Assertions can help verify important FIFO properties.<\/span><\/p><p><span style=\"font-weight: 400;\">For example, the write pointer should not advance when the FIFO is full:<\/span><\/p><p><span style=\"font-weight: 400;\">full &amp;&amp; wr_en<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0|<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0v<\/span><\/p><p><span style=\"font-weight: 400;\">write pointer must remain unchanged<\/span><\/p><p>\u00a0<\/p><p><span style=\"font-weight: 400;\">Similarly:<\/span><\/p><p><span style=\"font-weight: 400;\">empty &amp;&amp; rd_en<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0|<\/span><\/p><p><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0v<\/span><\/p><p><span style=\"font-weight: 400;\">read pointer must remain unchanged<\/span><\/p><p>\u00a0<\/p><p><span style=\"font-weight: 400;\">Another useful property is checking the Gray-code transition.<\/span><\/p><p><span style=\"font-weight: 400;\">Only one Gray-code bit should change between consecutive pointer values.<\/span><\/p><p><span style=\"font-weight: 400;\">These checks help detect CDC implementation errors early.<\/span><\/p><h3><span style=\"font-weight: 400;\">CDC Tools and Asynchronous FIFO<\/span><\/h3><p><span style=\"font-weight: 400;\">Simulation alone cannot prove that a CDC architecture is safe.<\/span><\/p><p><span style=\"font-weight: 400;\">Static CDC analysis tools can inspect clock crossings and identify issues such as:<\/span><\/p><ul><li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Missing synchronizers<\/span><\/li><li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Unsafe crossings<\/span><\/li><li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Incorrect clock relationships<\/span><\/li><li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Reconvergence<\/span><\/li><li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Synchronizer structures<\/span><\/li><li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Multi-bit CDC problems<\/span><\/li><\/ul><p><span style=\"font-weight: 400;\">Inskill&#8217;s Lint and CDC training specifically includes asynchronous FIFO analysis, binary-to-Gray synchronization, multi-bit crossings and CDC labs.<\/span><\/p><p><span style=\"font-weight: 400;\">For production RTL, the asynchronous FIFO should therefore be checked using both functional verification and dedicated CDC analysis.<\/span><\/p><h3><span style=\"font-weight: 400;\">Where Are Asynchronous FIFOs Used?<\/span><\/h3><p><span style=\"font-weight: 400;\">Asynchronous FIFOs are useful whenever data needs to cross between unrelated clock domains while maintaining ordering and buffering.<\/span><\/p><p><span style=\"font-weight: 400;\">Typical applications include:<\/span><\/p><ul><li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">SoC interconnects<\/span><\/li><li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Processor-to-peripheral communication<\/span><\/li><li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Network interfaces<\/span><\/li><li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">DMA engines<\/span><\/li><li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Video processing<\/span><\/li><li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Audio interfaces<\/span><\/li><li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">FPGA designs<\/span><\/li><li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Multi-clock data pipelines<\/span><\/li><li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">High-speed communication systems<\/span><\/li><\/ul><p><span style=\"font-weight: 400;\">They are especially useful when the producer and consumer operate at different rates.<\/span><\/p><h4><span style=\"font-weight: 400;\">Conclusion<\/span><\/h4><p><span style=\"font-weight: 400;\">Designing an asynchronous FIFO for CDC applications requires more than implementing a memory with read and write pointers.<\/span><\/p><p><span style=\"font-weight: 400;\">The key is safely transferring pointer information between independent clock domains.<\/span><\/p><p><span style=\"font-weight: 400;\">The standard architecture combines:<\/span><\/p><p><span style=\"font-weight: 400;\">Binary pointers \u2192 Gray-code conversion \u2192 clock-domain synchronization \u2192 full\/empty detection<\/span><\/p><p><span style=\"font-weight: 400;\">The write and read sides maintain their own local state, while synchronized Gray-coded pointers provide the information required to determine whether the FIFO is full or empty.<\/span><\/p><p><span style=\"font-weight: 400;\">For beginners, the most important concepts to master are CDC, metastability, Gray code, pointer synchronization, full\/empty detection and reset handling.<\/span><\/p><p><span style=\"font-weight: 400;\">Once these concepts are clear, asynchronous FIFO design becomes much easier to understand and is an excellent practical RTL project for learning real-world CDC design.<\/span><\/p>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t\t\t\t<\/div>\n\t\t","protected":false},"excerpt":{"rendered":"<p>Modern SoCs, ASICs and FPGA designs commonly contain multiple clock domains. A processor may run at one frequency, a peripheral at another, and a high-speed interface at yet another. When data needs to move between these unrelated clock domains, simply connecting a multi-bit bus from one domain to another can create serious clock domain crossing [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[8],"tags":[],"class_list":["post-10178","post","type-post","status-publish","format-standard","hentry","category-vlsi"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v26.7 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>How to Design an Asynchronous FIFO for CDC Applications<\/title>\n<meta name=\"description\" content=\"Learn how to design an asynchronous FIFO for CDC applications using Gray-coded pointers, 2-flop synchronizers, full\/empty logic and Verilog RTL.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/inskill.in\/training\/vlsi\/common-axi-design-mistakes\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"How to Design an Asynchronous FIFO for CDC Applications\" \/>\n<meta property=\"og:description\" content=\"Learn how to design an asynchronous FIFO for CDC applications using Gray-coded pointers, 2-flop synchronizers, full\/empty logic and Verilog RTL.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/inskill.in\/training\/vlsi\/common-axi-design-mistakes\/\" \/>\n<meta property=\"og:site_name\" content=\"Inskill VLSIGURU Elearning Platform\" \/>\n<meta property=\"article:published_time\" content=\"2026-09-16T11:25:30+00:00\" \/>\n<meta name=\"author\" content=\"admin\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"admin\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"10 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/inskill.in\/training\/vlsi\/common-axi-design-mistakes\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/inskill.in\/training\/vlsi\/common-axi-design-mistakes\/\"},\"author\":{\"name\":\"admin\",\"@id\":\"https:\/\/inskill.in\/training\/#\/schema\/person\/9abb65edd31606e6675ad9c153f2d42f\"},\"headline\":\"How to Design an Asynchronous FIFO for CDC Applications\",\"datePublished\":\"2026-09-16T11:25:30+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/inskill.in\/training\/vlsi\/common-axi-design-mistakes\/\"},\"wordCount\":2126,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/inskill.in\/training\/#organization\"},\"articleSection\":[\"VLSI\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/inskill.in\/training\/vlsi\/common-axi-design-mistakes\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/inskill.in\/training\/vlsi\/common-axi-design-mistakes\/\",\"url\":\"https:\/\/inskill.in\/training\/vlsi\/common-axi-design-mistakes\/\",\"name\":\"How to Design an Asynchronous FIFO for CDC Applications\",\"isPartOf\":{\"@id\":\"https:\/\/inskill.in\/training\/#website\"},\"datePublished\":\"2026-09-16T11:25:30+00:00\",\"description\":\"Learn how to design an asynchronous FIFO for CDC applications using Gray-coded pointers, 2-flop synchronizers, full\/empty logic and Verilog RTL.\",\"breadcrumb\":{\"@id\":\"https:\/\/inskill.in\/training\/vlsi\/common-axi-design-mistakes\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/inskill.in\/training\/vlsi\/common-axi-design-mistakes\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/inskill.in\/training\/vlsi\/common-axi-design-mistakes\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/inskill.in\/training\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"How to Design an Asynchronous FIFO for CDC Applications\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/inskill.in\/training\/#website\",\"url\":\"https:\/\/inskill.in\/training\/\",\"name\":\"Inskill VLSIGURU Elearning Platform\",\"description\":\"Best VLSI Training Institute\",\"publisher\":{\"@id\":\"https:\/\/inskill.in\/training\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/inskill.in\/training\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/inskill.in\/training\/#organization\",\"name\":\"Inskill VLSIGURU Elearning Platform\",\"url\":\"https:\/\/inskill.in\/training\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/inskill.in\/training\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/inskill.in\/training\/wp-content\/uploads\/2025\/01\/inskill-2.png\",\"contentUrl\":\"https:\/\/inskill.in\/training\/wp-content\/uploads\/2025\/01\/inskill-2.png\",\"width\":207,\"height\":89,\"caption\":\"Inskill VLSIGURU Elearning Platform\"},\"image\":{\"@id\":\"https:\/\/inskill.in\/training\/#\/schema\/logo\/image\/\"}},{\"@type\":\"Person\",\"@id\":\"https:\/\/inskill.in\/training\/#\/schema\/person\/9abb65edd31606e6675ad9c153f2d42f\",\"name\":\"admin\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/inskill.in\/training\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/ae1b84b5e32e75453917297a43292af55fcc34a59a0d20dc5403287472a37c28?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/ae1b84b5e32e75453917297a43292af55fcc34a59a0d20dc5403287472a37c28?s=96&d=mm&r=g\",\"caption\":\"admin\"},\"sameAs\":[\"https:\/\/inskill.in\/training\"],\"url\":\"https:\/\/inskill.in\/training\/author\/admin\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"How to Design an Asynchronous FIFO for CDC Applications","description":"Learn how to design an asynchronous FIFO for CDC applications using Gray-coded pointers, 2-flop synchronizers, full\/empty logic and Verilog RTL.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/inskill.in\/training\/vlsi\/common-axi-design-mistakes\/","og_locale":"en_US","og_type":"article","og_title":"How to Design an Asynchronous FIFO for CDC Applications","og_description":"Learn how to design an asynchronous FIFO for CDC applications using Gray-coded pointers, 2-flop synchronizers, full\/empty logic and Verilog RTL.","og_url":"https:\/\/inskill.in\/training\/vlsi\/common-axi-design-mistakes\/","og_site_name":"Inskill VLSIGURU Elearning Platform","article_published_time":"2026-09-16T11:25:30+00:00","author":"admin","twitter_card":"summary_large_image","twitter_misc":{"Written by":"admin","Est. reading time":"10 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/inskill.in\/training\/vlsi\/common-axi-design-mistakes\/#article","isPartOf":{"@id":"https:\/\/inskill.in\/training\/vlsi\/common-axi-design-mistakes\/"},"author":{"name":"admin","@id":"https:\/\/inskill.in\/training\/#\/schema\/person\/9abb65edd31606e6675ad9c153f2d42f"},"headline":"How to Design an Asynchronous FIFO for CDC Applications","datePublished":"2026-09-16T11:25:30+00:00","mainEntityOfPage":{"@id":"https:\/\/inskill.in\/training\/vlsi\/common-axi-design-mistakes\/"},"wordCount":2126,"commentCount":0,"publisher":{"@id":"https:\/\/inskill.in\/training\/#organization"},"articleSection":["VLSI"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/inskill.in\/training\/vlsi\/common-axi-design-mistakes\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/inskill.in\/training\/vlsi\/common-axi-design-mistakes\/","url":"https:\/\/inskill.in\/training\/vlsi\/common-axi-design-mistakes\/","name":"How to Design an Asynchronous FIFO for CDC Applications","isPartOf":{"@id":"https:\/\/inskill.in\/training\/#website"},"datePublished":"2026-09-16T11:25:30+00:00","description":"Learn how to design an asynchronous FIFO for CDC applications using Gray-coded pointers, 2-flop synchronizers, full\/empty logic and Verilog RTL.","breadcrumb":{"@id":"https:\/\/inskill.in\/training\/vlsi\/common-axi-design-mistakes\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/inskill.in\/training\/vlsi\/common-axi-design-mistakes\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/inskill.in\/training\/vlsi\/common-axi-design-mistakes\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/inskill.in\/training\/"},{"@type":"ListItem","position":2,"name":"How to Design an Asynchronous FIFO for CDC Applications"}]},{"@type":"WebSite","@id":"https:\/\/inskill.in\/training\/#website","url":"https:\/\/inskill.in\/training\/","name":"Inskill VLSIGURU Elearning Platform","description":"Best VLSI Training Institute","publisher":{"@id":"https:\/\/inskill.in\/training\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/inskill.in\/training\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/inskill.in\/training\/#organization","name":"Inskill VLSIGURU Elearning Platform","url":"https:\/\/inskill.in\/training\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/inskill.in\/training\/#\/schema\/logo\/image\/","url":"https:\/\/inskill.in\/training\/wp-content\/uploads\/2025\/01\/inskill-2.png","contentUrl":"https:\/\/inskill.in\/training\/wp-content\/uploads\/2025\/01\/inskill-2.png","width":207,"height":89,"caption":"Inskill VLSIGURU Elearning Platform"},"image":{"@id":"https:\/\/inskill.in\/training\/#\/schema\/logo\/image\/"}},{"@type":"Person","@id":"https:\/\/inskill.in\/training\/#\/schema\/person\/9abb65edd31606e6675ad9c153f2d42f","name":"admin","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/inskill.in\/training\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/ae1b84b5e32e75453917297a43292af55fcc34a59a0d20dc5403287472a37c28?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/ae1b84b5e32e75453917297a43292af55fcc34a59a0d20dc5403287472a37c28?s=96&d=mm&r=g","caption":"admin"},"sameAs":["https:\/\/inskill.in\/training"],"url":"https:\/\/inskill.in\/training\/author\/admin\/"}]}},"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/inskill.in\/training\/wp-json\/wp\/v2\/posts\/10178","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/inskill.in\/training\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/inskill.in\/training\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/inskill.in\/training\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/inskill.in\/training\/wp-json\/wp\/v2\/comments?post=10178"}],"version-history":[{"count":4,"href":"https:\/\/inskill.in\/training\/wp-json\/wp\/v2\/posts\/10178\/revisions"}],"predecessor-version":[{"id":10184,"href":"https:\/\/inskill.in\/training\/wp-json\/wp\/v2\/posts\/10178\/revisions\/10184"}],"wp:attachment":[{"href":"https:\/\/inskill.in\/training\/wp-json\/wp\/v2\/media?parent=10178"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/inskill.in\/training\/wp-json\/wp\/v2\/categories?post=10178"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/inskill.in\/training\/wp-json\/wp\/v2\/tags?post=10178"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}