精品国产人成在线_亚洲高清无码在线观看_国产在线视频国产永久2021_国产AV综合第一页一个的一区免费影院黑人_最近中文字幕MV高清在线视频

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

基于FPGA的異步FIFO設計架構

SwM2_ChinaAET ? 來源:未知 ? 作者:李倩 ? 2018-09-25 14:34 ? 次閱讀

今天要介紹的異步FIFO,可以有不同的讀寫時鐘,即不同的時鐘域。由于異步FIFO沒有外部地址端口,因此內部采用讀寫指針并順序讀寫,即先寫進FIFO的數據先讀取(簡稱先進先出)。這里的讀寫指針是異步的,處理不同的時鐘域,而異步FIFO的空滿標志位是根據讀寫指針的情況得到的。

為了得到正確的空滿標志位,需要對讀寫指針進行同步。一般情況下,如果一個時鐘域的信號直接給另一個時鐘域采集,可能會產生亞穩態,亞穩態的產生對設計而言是致命的。為了減少不同時鐘域間的亞穩態問題,我們先對它進行兩拍寄存同步,如圖1所示。

當然,對異步信號的寄存越多,產生亞穩態的概率就越小,但延時越多。不過一般情況下,寄存兩拍就夠了。為了繼續減少亞穩態產生的概率,在對異步信號同步之前,將其轉換為格雷碼,使其每個狀態只有一個位在變化。例如,假設N位二進制變量產生的亞穩態概率為a,那么二進制轉換成格雷碼后其產生的亞穩態概率則為a/N。

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

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

圖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設計電路,如下所示:

**------------------------------文件信息--------------------------------

** 文件名: 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的讀寫

//******************************************************************

// 寫RAM

always @(posedge wr_clk)

begin

if((wr_en & ~wr_full) == 1‘b1)

mem[wr_addr] 《= wr_data;

end

// 讀RAM

assign 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)

begin

if(wr_rst_n == 1’b0)

wr_bin_ptr 《= {(C_FIFO_DEPTH_WIDTH+1){1‘b0}};

else

wr_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)

begin

if(wr_rst_n == 1’b0)

begin

wr_full 《= 1‘b0;

wr_cnt 《= {(C_FIFO_DEPTH_WIDTH+1){1’b0}};

end

else

begin

wr_full 《= wr_full_w;

wr_cnt 《= wr_cnt_w;

end

end

//******************************************************************

// 二進制讀指針的產生

//******************************************************************

assign next_rd_bin_ptr = rd_bin_ptr + (rd_en & ~rd_empty);

always @(posedge rd_clk or negedge rd_rst_n)

begin

if(rd_rst_n == 1‘b0)

rd_bin_ptr 《= {(C_FIFO_DEPTH_WIDTH+1){1’b0}};

else

rd_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)

begin

if(rd_rst_n == 1‘b0)

begin

rd_empty 《= 1’b0;

rd_cnt 《= {(C_FIFO_DEPTH_WIDTH+1){1‘b0}};

end

else

begin

rd_empty 《= rd_empty_w;

rd_cnt 《= rd_cnt_w;

end

end

endmodule

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

**------------------------------文件信息--------------------------------

** 文件名: 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)

begin

if(rst_n == 1’b0)

{dout,data_r} 《= {(2*C_DATA_WIDTH){1‘b0}};

else

{dout,data_r} 《= {data_r,din};

end

endmodule

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

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 寄存器
    +關注

    關注

    31

    文章

    5321

    瀏覽量

    120017
  • fifo
    +關注

    關注

    3

    文章

    387

    瀏覽量

    43555

原文標題:【原創博文】基于FPGA的異步FIFO設計

文章出處:【微信號:ChinaAET,微信公眾號:電子技術應用ChinaAET】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    基于FPGA異步FIFO的實現

    大家好,又到了每日學習的時間了,今天我們來聊一聊基于FPGA異步FIFO的實現。 一、FIFO簡介 FIFO是英文First In Fir
    的頭像 發表于 06-21 11:15 ?6478次閱讀
    基于<b class='flag-5'>FPGA</b>的<b class='flag-5'>異步</b><b class='flag-5'>FIFO</b>的實現

    基于FPGA器件實現異步FIFO讀寫系統的設計

    異步 FIFO 讀寫分別采用相互異步的不同時鐘。在現代集成電路芯片中,隨著設計規模的不斷擴大,一個系統中往往含有數個時鐘,多時鐘域帶來的一個問題就是,如何設計異步時鐘之間的接口電路。
    發表于 07-16 17:41 ?1214次閱讀
    基于<b class='flag-5'>FPGA</b>器件實現<b class='flag-5'>異步</b><b class='flag-5'>FIFO</b>讀寫系統的設計

    怎么解決異步FIFO設計的難點?

    FIFO的基本結構和工作原理異步FIFO設計中的問題與解決辦法FPGA內部軟異步FIFO設計
    發表于 04-08 07:07

    異步FIFO結構及FPGA設計

    首先介紹異步FIFO 的概念、應用及其結構,然后分析實現異步FIFO的難點問題及其解決辦法; 在傳統設計的基礎上提出一種新穎的電路結構并對其進行綜合仿真和
    發表于 04-16 09:25 ?46次下載

    高速異步FIFO的設計與實現

    本文主要研究了用FPGA 芯片內部的EBRSRAM 來實現異步FIFO 設計方案,重點闡述了異步FIFO 的標志信號——空/滿狀態的設計思路
    發表于 01-13 17:11 ?40次下載

    Camera Link接口的異步FIFO設計與實現

    介紹了異步FIFO在Camera Link接口中的應用,將Camera Link接口中的幀有效信號FVAL和行有效信號LVAL引入到異步FIFO的設計中。分析了
    發表于 07-28 16:08 ?32次下載

    異步FIFO結構及FPGA設計

    摘要:首先介紹異步FIFO的概念、應用及其結構,然后分析實現異步FIFO的難點問題及其解決辦法;在傳統設計的基礎上提出一種新穎的電路結構并對其進行
    發表于 06-20 12:46 ?3852次閱讀
    <b class='flag-5'>異步</b><b class='flag-5'>FIFO</b>結構及<b class='flag-5'>FPGA</b>設計

    異步FIFOFPGA與DSP通信中的運用

    文中給出了異步FIFO的實現代碼和FPGA與DSP的硬件連接電路。經驗證,利用異步FIFO的方法,在FP
    發表于 12-12 14:28 ?51次下載
    <b class='flag-5'>異步</b><b class='flag-5'>FIFO</b>在<b class='flag-5'>FPGA</b>與DSP通信中的運用

    異步FIFO結構及FPGA設計

    異步FIFO結構及FPGA設計,解決亞穩態的問題
    發表于 11-10 15:21 ?4次下載

    異步FIFOFPGA與DSP通信中的運用

    異步FIFOFPGA與DSP通信中的運用
    發表于 05-19 11:17 ?0次下載

    基于異步FIFOFPGA與DSP通信中的運用

    基于異步FIFOFPGA與DSP通信中的運用
    發表于 10-19 10:30 ?10次下載
    基于<b class='flag-5'>異步</b><b class='flag-5'>FIFO</b>在<b class='flag-5'>FPGA</b>與DSP通信中的運用

    異步FIFOFPGA與DSP通信中的應用解析

    摘要 利用異步FIFO實現FPGA與DSP進行數據通信的方案。FPGA在寫時鐘的控制下將數據寫入FIFO,再與DSP進行握手后,DSP通過E
    發表于 10-30 11:48 ?2次下載
    <b class='flag-5'>異步</b><b class='flag-5'>FIFO</b>在<b class='flag-5'>FPGA</b>與DSP通信中的應用解析

    基于FPGA異步FIFO設計方法詳解

    在現代電路設計中,一個系統往往包含了多個時鐘,如何在異步時鐘間傳遞數據成為一個很重要的問題,而使用異步FIFO可以有效地解決這個問題。異步FIFO
    發表于 07-17 08:33 ?8327次閱讀
    基于<b class='flag-5'>FPGA</b>的<b class='flag-5'>異步</b><b class='flag-5'>FIFO</b>設計方法詳解

    Xilinx異步FIFO的大坑

    FIFOFPGA處理跨時鐘和數據緩存的必要IP,可以這么說,只要是任意一個成熟的FPGA涉及,一定會涉及到FIFO。但是我在使用異步
    發表于 03-12 06:01 ?12次下載
    Xilinx<b class='flag-5'>異步</b><b class='flag-5'>FIFO</b>的大坑

    同步FIFO異步FIFO的區別 同步FIFO異步FIFO各在什么情況下應用

    同步FIFO異步FIFO的區別 同步FIFO異步FIFO各在什么情況下應用? 1. 同步
    的頭像 發表于 10-18 15:23 ?1640次閱讀