基于FPGA的異步FIFO設計

今天要介紹的異步FIFO,可以有不同的讀寫時鐘,即不同的時鐘域。由于異步FIFO沒有外部地址端口,因此內部采用讀寫指針并順序讀寫,即先寫進FIFO的數據先讀取(簡稱先進先出)。這里的讀寫指針是異步的,處理不同的時鐘域,而異步FIFO的空滿標志位是根據讀寫指針的情況得到的。為了得到正確的空滿標志位,需要對讀寫指針進行同步。一般情況下,如果一個時鐘域的信號直接給另一個時鐘域采集,可能會產生亞穩態,亞穩態的產生對設計而言是致命的。為了減少不同時鐘域間的亞穩態問題,我們先對它進行兩拍寄存同步,如圖1所示。當然,對異步信號的寄存越多,產生亞穩態的概率就越小,但延時越多。不過一般情況下,寄存兩拍就夠了。為了繼續減少亞穩態產生的概率,在對異步信號同步之前,將其轉換為格雷碼,使其每個狀態只有一個位在變化。例如,假設N位二進制變量產生的亞穩態概率為a,那么二進制轉換成格雷碼后其產生的亞穩態概率則為a/N。

對異步信號進行同步.jpg

圖1 ?對異步信號用兩級寄存器同步

????根據上述原理,設計了異步FIFO的架構,如圖2所示。

異步FIFO設計框架.jpg

圖2 ?異步FIFO設計架構

????根據異步FIFO的設計架構,歸納以下設計步驟:

????寫時鐘域:

????(1)根據寫使能wr_en和寫滿標志位wr_full產生二進制寫指針

????(2)根據二進制寫指針產生雙端口RAM的寫地址

????(3)由二進制寫指針轉換成格雷碼寫指針

????(4)對格雷碼讀指針在寫時鐘域中進行兩級同步得同步后格雷碼讀指針

????(5)同步后格雷碼讀指針轉化成同步后二進制讀指針

????(6)步驟(3)與步驟(4)比較得寫滿標志位wr_full

????(7)步驟(1)與步驟(5)相減得指示寫FIFO的數據量

????讀時鐘域:

????(8)根據讀使能rd_en和讀空標志位rd_empty產生二進制讀指針

????(9)根據二進制讀指針產生雙端口RAM的讀地址

????(10)由二進制讀指針轉換成格雷碼讀指針

????(11)對格雷碼寫指針在讀時鐘域中進行兩級同步得同步后格雷碼寫指針

????(12)同步后格雷碼寫指針轉化成同步后二進制寫指針

????(13)步驟(10)與步驟(11)比較得讀空標志位rd_empty

????(14)步驟(8)與步驟(12)相減得指示讀FIFO的數據量

????Verilog HDL設計電路,如下所示:

/*******************************版權申明********************************
**?????????????????????電子技術應用網站,?CrazyBird
**?????http://www.chinaaet.com,?http://blog.chinaaet.com/crazybird
**
**------------------------------文件信息--------------------------------
**?文件名:??????????asyn_fifo.v
**?創建者:??????????CrazyBird
**?創建日期:????????2016-1-16
**?版本號:???????????v1.0
**?功能描述:????????異步FIFO,用于處理不同的時鐘域
**???????????????????
***********************************************************************/
//?synopsys?translate_off
`timescale?1?ns?/?1?ps
//?synopsys?translate_on
module?asyn_fifo(wr_rst_n,wr_clk,wr_en,wr_data,wr_full,wr_cnt,rd_rst_n,rd_clk,rd_en,rd_data,rd_empty,rd_cnt);//******************************************************************//??參數定義//******************************************************************parameter???C_DATA_WIDTH?=?8;parameter???C_FIFO_DEPTH_WIDTH?=?4;//******************************************************************//??端口定義//******************************************************************input???????????????????????????????????wr_rst_n;input???????????????????????????????????wr_clk;input???????????????????????????????????wr_en;input???????[C_DATA_WIDTH-1:0]??????????wr_data;output?reg??????????????????????????????wr_full;output?reg??[C_FIFO_DEPTH_WIDTH:0]??????wr_cnt;input???????????????????????????????????rd_rst_n;input???????????????????????????????????rd_clk;input???????????????????????????????????rd_en;output??????[C_DATA_WIDTH-1:0]??????????rd_data;output?reg??????????????????????????????rd_empty;output?reg??[C_FIFO_DEPTH_WIDTH:0]??????rd_cnt;//******************************************************************//??內部變量定義//******************************************************************reg?????[C_DATA_WIDTH-1:0]??????mem?????[0:(1?<<?C_FIFO_DEPTH_WIDTH)-1];wire????[C_FIFO_DEPTH_WIDTH-1:0]????????wr_addr;wire????[C_FIFO_DEPTH_WIDTH-1:0]????????rd_addr;wire????[C_FIFO_DEPTH_WIDTH:0]??????????next_wr_bin_ptr;wire????[C_FIFO_DEPTH_WIDTH:0]??????????next_rd_bin_ptr;reg?????[C_FIFO_DEPTH_WIDTH:0]??????????wr_bin_ptr;reg?????[C_FIFO_DEPTH_WIDTH:0]??????????rd_bin_ptr;wire????[C_FIFO_DEPTH_WIDTH:0]??????????next_wr_gray_ptr;wire????[C_FIFO_DEPTH_WIDTH:0]??????????next_rd_gray_ptr;wire????[C_FIFO_DEPTH_WIDTH:0]??????????syn_wr_bin_ptr_rd_clk;wire????[C_FIFO_DEPTH_WIDTH:0]??????????syn_rd_bin_ptr_wr_clk;wire????[C_FIFO_DEPTH_WIDTH:0]??????????syn_wr_gray_ptr_rd_clk;wire????[C_FIFO_DEPTH_WIDTH:0]??????????syn_rd_gray_ptr_wr_clk;wire????[C_FIFO_DEPTH_WIDTH:0]??????????wr_cnt_w;wire????[C_FIFO_DEPTH_WIDTH:0]??????????rd_cnt_w;wire????????????????????????????????????wr_full_w;wire????????????????????????????????????rd_empty_w;//******************************************************************//??雙端口RAM的讀寫//******************************************************************//??寫RAMalways?@(posedge?wr_clk)beginif((wr_en?&?~wr_full)?==?1'b1)mem[wr_addr]?<=?wr_data;end//??讀RAMassign?rd_data?=?mem[rd_addr];//******************************************************************//??二進制寫指針的產生//******************************************************************assign?next_wr_bin_ptr?=?wr_bin_ptr?+?(wr_en?&?~wr_full);always?@(posedge?wr_clk?or?negedge?wr_rst_n)beginif(wr_rst_n?==?1'b0)wr_bin_ptr?<=?{(C_FIFO_DEPTH_WIDTH+1){1'b0}};elsewr_bin_ptr?<=?next_wr_bin_ptr;end//******************************************************************//??RAM寫地址的產生//******************************************************************assign?wr_addr?=?wr_bin_ptr[C_FIFO_DEPTH_WIDTH-1:0];//******************************************************************//??二進制寫指針轉換成格雷碼寫指針//******************************************************************bin2gray?#(.C_DATA_WIDTH(C_FIFO_DEPTH_WIDTH+1))u_bin2gray_wr?(.bin????(???next_wr_bin_ptr?????),.gray???(???next_wr_gray_ptr????));//******************************************************************//??對格雷碼讀指針在寫時鐘域中進行兩級同步//******************************************************************double_syn_ff?#(.C_DATA_WIDTH(C_FIFO_DEPTH_WIDTH+1))u_double_syn_ff_wr?(.rst_n??(???wr_rst_n????????????????),.clk????(???wr_clk??????????????????),.din????(???next_rd_gray_ptr?????????),.dout???(???syn_rd_gray_ptr_wr_clk???));//******************************************************************//??同步后的格雷碼讀指針轉換成同步后的二進制讀指針//******************************************************************gray2bin?#(.C_DATA_WIDTH(C_FIFO_DEPTH_WIDTH+1))u_gray2bin_wr?(.gray???(???syn_rd_gray_ptr_wr_clk??),.bin????(???syn_rd_bin_ptr_wr_clk???));//******************************************************************//??FIFO寫滿標志位的產生和寫FIFO數據量的計數//******************************************************************assign?wr_full_w?=?(next_wr_gray_ptr?==?({~syn_rd_gray_ptr_wr_clk[C_FIFO_DEPTH_WIDTH:C_FIFO_DEPTH_WIDTH-1],syn_rd_gray_ptr_wr_clk[C_FIFO_DEPTH_WIDTH-2:0]}));assign?wr_cnt_w??=?next_wr_bin_ptr?-?syn_rd_bin_ptr_wr_clk;always?@(posedge?wr_clk?or?negedge?wr_rst_n)beginif(wr_rst_n?==?1'b0)beginwr_full?<=?1'b0;wr_cnt??<=?{(C_FIFO_DEPTH_WIDTH+1){1'b0}};endelsebeginwr_full?<=?wr_full_w;wr_cnt??<=?wr_cnt_w;endend//******************************************************************//??二進制讀指針的產生//******************************************************************assign?next_rd_bin_ptr?=?rd_bin_ptr?+?(rd_en?&?~rd_empty);always?@(posedge?rd_clk?or?negedge?rd_rst_n)beginif(rd_rst_n?==?1'b0)rd_bin_ptr?<=?{(C_FIFO_DEPTH_WIDTH+1){1'b0}};elserd_bin_ptr?<=?next_rd_bin_ptr;end//******************************************************************//??RAM讀地址的產生//******************************************************************assign?rd_addr?=?rd_bin_ptr[C_FIFO_DEPTH_WIDTH-1:0];//******************************************************************//??二進制讀指針轉換成格雷碼讀指針//******************************************************************bin2gray?#(.C_DATA_WIDTH(C_FIFO_DEPTH_WIDTH+1))u_bin2gray_rd?(.bin????(???next_rd_bin_ptr?????),.gray???(???next_rd_gray_ptr????));//******************************************************************//??對格雷碼寫指針在讀時鐘域中進行兩級同步//******************************************************************double_syn_ff?#(.C_DATA_WIDTH(C_FIFO_DEPTH_WIDTH+1))u_double_syn_ff_rd?(.rst_n??(???rd_rst_n????????????????),.clk????(???rd_clk??????????????????),.din????(???next_wr_gray_ptr????????),.dout???(???syn_wr_gray_ptr_rd_clk??));//******************************************************************//??同步后的格雷碼寫指針轉換成同步后的二進制寫指針//******************************************************************gray2bin?#(.C_DATA_WIDTH(C_FIFO_DEPTH_WIDTH+1))u_gray2bin_rd?(.gray???(???syn_wr_gray_ptr_rd_clk??),.bin????(???syn_wr_bin_ptr_rd_clk???));//******************************************************************//??FIFO讀空標志位的產生和讀FIFO數據量的計數//******************************************************************assign?rd_empty_w?=?(next_rd_gray_ptr?==?syn_wr_gray_ptr_rd_clk);assign?rd_cnt_w???=?syn_wr_bin_ptr_rd_clk?-?next_rd_bin_ptr;always?@(posedge?rd_clk?or?negedge?rd_rst_n)beginif(rd_rst_n?==?1'b0)beginrd_empty?<=?1'b0;rd_cnt???<=?{(C_FIFO_DEPTH_WIDTH+1){1'b0}};endelsebeginrd_empty?<=?rd_empty_w;rd_cnt???<=?rd_cnt_w;endendendmodule

????其中,模塊gray2bin是格雷碼轉二進制碼,模塊bin2gray是二進制碼轉格雷碼,詳情見上一篇博客,地址:http://blog.chinaaet.com/crazybird/p/5100000866?。模塊double_syn_ff是兩級寄存器,用于同步信號,對應的Verilog HDL實現如下所示:

/*******************************版權申明********************************
**?????????????????????電子技術應用網站,?CrazyBird
**?????http://www.chinaaet.com,?http://blog.chinaaet.com/crazybird
**
**------------------------------文件信息--------------------------------
**?文件名:??????????double_syn_ff.v
**?創建者:??????????CrazyBird
**?創建日期:????????2016-1-16
**?版本號:???????????v1.0
**?功能描述:????????對輸入信號進行兩級同步后輸出
**???????????????????
***********************************************************************/
//?synopsys?translate_off
`timescale?1?ns?/?1?ps
//?synopsys?translate_on
module?double_syn_ff(rst_n,clk,din,dout);//******************************************************************//??參數定義//******************************************************************parameter???C_DATA_WIDTH?=?8;//******************************************************************//??端口定義//******************************************************************input???????????????????????????????rst_n;input???????????????????????????????clk;input???????[C_DATA_WIDTH-1:0]??????din;output?reg??[C_DATA_WIDTH-1:0]??????dout;//******************************************************************//??內部變量定義//******************************************************************reg?????????[C_DATA_WIDTH-1:0]??????data_r;//******************************************************************//??對輸入信號進行兩級同步后輸出//******************************************************************always?@(posedge?clk?or?negedge?rst_n)beginif(rst_n?==?1'b0){dout,data_r}?<=?{(2*C_DATA_WIDTH){1'b0}};else{dout,data_r}?<=?{data_r,din};endendmodule

? ?由于字數的限制,異步FIFO的功能驗證放在下一篇博文中吧!!!

轉載:http://blog.chinaaet.com/crazybird/p/5100000872

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/284283.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/284283.shtml
英文地址,請注明出處:http://en.pswp.cn/news/284283.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

顧小清:教育信息化進入數字化轉型重要時期

身處技術加快更新、新概念頻出的時代&#xff0c;教育信息化的發展更需要堅守以人為本的初心&#xff0c;在熱點炒作的雜音中保持理智&#xff0c;避免盲目&#xff0c;抓住符合教育規律、滿足教育需求、安全有效的準繩&#xff0c;理性推進和落實。 技術在不斷發展&#xff0c…

EJB

Enterprise JavaBean,企業級javabean,是J2EE的一部分&#xff0c;定義了一個用于 開發基于組件的企業多重應用程序的標準。其特點包括網絡服務支持和核心開發工具(SDK)。 是Java的核心代碼&#xff0c;分別是會話Bean&#xff08;Session Bean&#xff09;&#xff0c;實體Be…

java 連接redis 以及基本操作

一、首先下載安裝redis 二、項目搭建 1.搭建一個maven 工程 2. 在pom.xml文件的dependencies節點下增加如下內容&#xff1a; <!-- resis --><dependency><groupId>org.redisson</groupId><artifactId>redisson</artifactId><version&…

WinForm(一):開始一個WinForm程序

WinForm程序只能運行在Windows上&#xff0c;即使是基于.NET5&#xff0c;6&#xff0c;7也一樣。因為WinForm的UI層對接的底層API是基于Windows的。用VisualStudio創建一個WinForm應用很簡單&#xff0c;建議使用非.NET Framework版&#xff0c;因為.NET Framework微軟漸漸不支…

【ArcGIS微課1000例】0050:Geodatabase屬性域操作全解

文章目錄 1. 屬性域的創建2. 屬性域的查看3. 屬性域的刪除與修改4. 屬性域的關聯地理數據庫按照面向對象的模型存儲地理信息,也可以將其非空間信息保存在表中。對于要素和表可以設置一些規則進行限制,對屬性的約束稱為屬性域。 屬性域是描述字段合法值的規則,是一種增強數據…

ctype.h

isalpha&#xff1a;int isalpha(char ch);檢查ch是否是字母.是字母返回非0&#xff0c;否則返回0。iscntrl&#xff1a; int iscntrl(int ch); 檢查ch是否控制字符(其ASCII碼在0和0x1F之間,數值為 0-31).是返回非0,否則返回 0.isdigit&#xff1a;int isdigit(char ch);檢查ch…

『JavaScript』核心

為什么80%的碼農都做不了架構師&#xff1f;>>> 弱類型語言 JavaScript是一種弱類型的語言。變量可以根據所賦的值改變類型。原始類型之間也可以進行類型轉換。其弱類型的物質為其帶來了極大的靈活性。 注意&#xff1a;原始類型使用值傳遞&#xff0c;復合類型使用…

優酷VIP會員周卡只需7.5元,看《沉香如屑》用優酷視頻

由楊紫、成毅主演的《沉香如屑》已上線7天。站內熱度值已經破萬&#xff0c;也拿下了4次日冠的好成績。追優酷視頻最新熱劇不能沒有優酷VIP會員啊&#xff0c;優酷的會員&#xff0c;價格算是最便宜的了&#xff0c;下面是幻海優品優酷VIP會員特價充值的價格。優酷VIP會員特價充…

Solr6.1.0Windows安裝步驟

一、 環境 solr 6.1.0 下載地址 http://archive.apache.org/dist/lucene/solr/6.1.0/ jdk 1.8 tomcat8 二、 安裝solr到tomcat 1.解壓solr&#xff0c;把 solr-6.1.0\solr-6.1.0\server 下的solr-webapp 文件夾拷貝到tomcat 的webapps下&#xff0c;重命名為solr&#xff1b;…

[轉]Autofac 框架初識與應用

一、前言 這上一篇中&#xff0c;主要講述了什么是IoC容器&#xff0c;以及了解到它是DI構造函注入的框架&#xff0c;它管理著依賴項的生命周期以及映射關系&#xff0c;同時也介紹實踐了在ASP.Net Core中,默認提供的內置IoC容器&#xff0c;以及它的實例注冊方式和相應的生命…

【ArcGIS微課1000例】0051:Geodatabase子類型操作全解

子類型是要素類中具有相同屬性的要素的子集&#xff0c;或表中具有相同屬性的對象的子集。可 通過它們對數據進行分類。 子類型是特征類(或對象類)中特征(或對象)的次級分類。例如一個公路線要素類可以根 據其字段類型的值細分為“高速公路”和“普通公路”兩個子類型。 子類…

作為Java程序員應該掌握的10項技能

本文詳細羅列了作為Java程序員應該掌握的10項技能。分享給大家供大家參考。具體如下&#xff1a; 1、語法&#xff1a;必須比較熟悉&#xff0c;在寫代碼的時候IDE的編輯器對某一行報錯應該能夠根據報錯信息知道是什么樣的語法錯誤并且知道任何修正。 2、命令&#xff1a;必須熟…

在Winform程序中設置管理員權限及為用戶組添加寫入權限

在我們一些Winform程序中&#xff0c;往往需要具有一些特殊的權限才能操作系統文件&#xff0c;我們可以設置運行程序具有管理員權限或者設置運行程序的目錄具有寫入的權限&#xff0c;如果是在操作系統里面&#xff0c;我們可以設置運行程序以管理員身份運行&#xff0c;或者設…

數據庫性能系列之索引(上)

前言上一次&#xff0c;我們從優化子查詢的角度&#xff0c;講解了一些簡單的數據庫性能優化方面的知識。通過優化子查詢的順序&#xff0c;包括合理使用IN和EXISTS&#xff0c;可以起到部分查詢的效率提升。但對于其他大多數場景&#xff0c;如單表記錄很大&#xff0c;或多表…

題目1023:EXCEL排序---------Case后面的是count,不是C

#include<stdio.h> #include<algorithm> #include<cstring> using namespace std;struct student {char num[10];char name[10];int grade; }s[100002]; int cmp1(student s1,student s2)//case 1 按照學號遞增 {return strcmp(s1.num,s2.num)<0; } int…

【ArcGIS微課1000例】0052:創建地理數據庫注記(標準注記、要素關聯注記、尺寸注記)

本文講述創建地理數據庫注記(標準注記、要素關聯注記、尺寸注記)的方法。 文章目錄 一、創建標準注記二、創建與要素關聯的注記三、創建尺寸注記一、創建標準注記 標準注記不與地理數據庫中的要素關聯。標準注記的一個例子是,地圖上標記某山脈的文字,沒有特定的要索代表該…

Lambda表達式超詳解

目錄 背景 Lambda表達式的用法 函數式接口 Lambda表達式的基本使用 語法精簡 變量捕獲 匿名內部類 匿名內部類中的變量捕獲 Lambda的變量捕獲 Lambda表達式在類集中的使用 Collection接口 List接口 Map接口 總結 背景 Lambda表達式是Java SE 8中的一個重要的新特性.…

用十條命令在一分鐘內檢查Linux服務器性能

這種干活必須要和大家分享的啊。 如果你的Linux服務器突然負載暴增&#xff0c;告警短信快發爆你的手機&#xff0c;如何在最短時間內找出Linux性能問題所在&#xff1f;來看Netflix性能工程團隊的這篇博文&#xff0c;看它們通過十條命令在一分鐘內對機器性能問題進行診斷。 概…

[javaEE] JDBC快速入門

JDBC&#xff1a;Java Data Base Connectivity java數據庫連接 1.組成JDBC的兩個包&#xff1a;主要是接口 java.sql javax.sql 2.相應JDBC的數據庫實現 在tomcat的目錄下面添加mysql-connector-java-5.0.8-bin.jar這個數據庫驅動包 package com.tsh.web;import java.io.IOExce…