做视频网站需要流量,wordpress中文文章排版插件,天津网上办事大厅官网入口,wordpress花瓣模板今天要介绍的异步FIFO#xff0c;可以有不同的读写时钟#xff0c;即不同的时钟域。由于异步FIFO没有外部地址端口#xff0c;因此内部采用读写指针并顺序读写#xff0c;即先写进FIFO的数据先读取#xff08;简称先进先出#xff09;。这里的读写指针是异步的#xff0…今天要介绍的异步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设计电路如下所示 /*******************************版权申明********************************
** 电子技术应用网站, 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) 1b1)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 1b0)wr_bin_ptr {(C_FIFO_DEPTH_WIDTH1){1b0}};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_WIDTH1))u_bin2gray_wr (.bin ( next_wr_bin_ptr ),.gray ( next_wr_gray_ptr ));//******************************************************************// 对格雷码读指针在写时钟域中进行两级同步//******************************************************************double_syn_ff #(.C_DATA_WIDTH(C_FIFO_DEPTH_WIDTH1))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_WIDTH1))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 1b0)beginwr_full 1b0;wr_cnt {(C_FIFO_DEPTH_WIDTH1){1b0}};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 1b0)rd_bin_ptr {(C_FIFO_DEPTH_WIDTH1){1b0}};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_WIDTH1))u_bin2gray_rd (.bin ( next_rd_bin_ptr ),.gray ( next_rd_gray_ptr ));//******************************************************************// 对格雷码写指针在读时钟域中进行两级同步//******************************************************************double_syn_ff #(.C_DATA_WIDTH(C_FIFO_DEPTH_WIDTH1))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_WIDTH1))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 1b0)beginrd_empty 1b0;rd_cnt {(C_FIFO_DEPTH_WIDTH1){1b0}};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 1b0){dout,data_r} {(2*C_DATA_WIDTH){1b0}};else{dout,data_r} {data_r,din};endendmodule 由于字数的限制异步FIFO的功能验证放在下一篇博文中吧 转载http://blog.chinaaet.com/crazybird/p/5100000872