一个异步FIFO的设计示例

合集下载

quartus 异步fifo用法 -回复

quartus 异步fifo用法 -回复

quartus 异步fifo用法-回复quartus异步FIFO用法引言:在数字电路设计中,FIFO(First In First Out)是一种常见的数据存储器,它允许数据以先进先出的顺序进出。

在使用Quartus进行FPGA设计时,异步FIFO是一种非常有用的工具,它可以帮助我们处理不同速度的数据流,并实现数据的缓冲和流量控制。

本文将介绍Quartus异步FIFO的基本概念和使用方法,并给出一些实例。

第一部分:Quartus异步FIFO概述1.1 什么是异步FIFO?异步FIFO是一种数据存储器,在其中数据可以以不同速度进入和退出。

与同步FIFO不同,异步FIFO的读写时钟可以是不同的,这使得它可以处理速度不匹配的数据流。

Quartus提供了异步FIFO的库函数和IP核,使得它可以在FPGA设计中方便地使用。

1.2 Quartus异步FIFO的特点Quartus异步FIFO具有以下特点:- 可以使用不同的时钟频率进行读写操作。

- 可以配置不同的缓冲深度来满足特定的设计需求。

- 可以实现流量控制和数据的重排序。

- 可以支持并行读写和读写使能信号。

- 可以适应不同的数据宽度和时钟域要求。

第二部分:Quartus异步FIFO的使用方法2.1 创建异步FIFO在Quartus中创建异步FIFO的方式有两种:使用库函数和使用IP核。

使用库函数创建异步FIFO的步骤如下:- 首先,在Quartus中打开设计工程,并创建一个新的源文件。

- 然后,将异步FIFO的库函数导入到源文件中,以便在设计中调用它。

- 接着,实例化异步FIFO,并通过参数配置其属性,例如宽度,深度,时钟域等。

- 最后,将异步FIFO连接到其他逻辑模块,完成设计。

使用IP核创建异步FIFO的步骤如下:- 首先,在Quartus中打开设计工程,并创建一个新的IP核。

- 然后,在IP核的界面中选择合适的FIFO类型和配置参数。

- 接着,将异步FIFO实例化到设计中,将其连接到其他逻辑模块。

一种读写深度可配置的异步FIFO设计

一种读写深度可配置的异步FIFO设计

引 言
随着设计复杂度 的不断 提高 , 现 代 电子信 息设计 中,
单 一 时 钟 驱 动 已无 法 满 足 设 计 与 应 用 的 需 求 。 基 于 多 时 钟 驱 动 的设 计 已经 越 来 越 普 遍 , 在异 步 时钟域 的设计 中,
Байду номын сангаас
模 块 和读 地址 逻 辑 模 块 是 两 个 相 互 独 立 的 时 钟 域模 块 。 F I F O的空/ 满状态 的 判断 是 F I FO 设 计 中 的 一 个 关 键部分 , 主要 通 过对 读 / 写地 址 的 比较 来 实 现 。鉴 于 读 / 写
状态标 志 的产 生 , 同 时 通
F I F O 的存 储 资 源 没 有 使 用 , 造 成 硬件 资 源 的 浪 费 。
针对这一现状, 本 文 提 出 一 种 读 写 深 度 可 配 置 的 FI F O 设 计 。通 过 对 寄 存 器 的配 置 , 来设定产生有效 F I F O
地 址 的控 制 逻 辑 分 别 工 作 在 各 自 的 时 钟 域 下 , 进 行 比 较
时, 通常将二进制码 的地址 转换 为格雷 码 的编码 方式 , 传 输 到 异 步 时 钟 域 再 进 行 比较 , 以使 亚 稳 态 的 产 生 处 于 可 以
跨 时钟 域 数 据 信 号 传 输 是 必 须 考 虑 的 一 个 问题 。控 制 信 号一般使用握手协议来 实现异步传输 , 对 于 异 步 时 钟 域 大
态时就开始读操作 , 防 止 写 满 后 禁 止 写 操 作 再
图 1 通用异步 F l F O原 理 结构 图
进 行 读 取 造 成 数 据 的 丢失 。
敬请登录网站在线投稿

异步FIFO的实现

异步FIFO的实现

异步FIFO的实现2012-05-01 01:41:47| 分类:实例分享| 标签:异步fifo 格雷码跨时钟域 function 函数|字号大中小订阅以下是一个异步FIFO的实现代码,实现的是一个FWFT的异步FIFO功能,与Xilinx CORE Generator生成FIFO功能、时序一模一样。

其中,simple_dual_port_ram 是一个Xilinx的简单双端口RAM,可以很简单的移植到其他厂商的FPGA中。

在产生空满信号的判断时,需要将读操作侧的地址传递到写操作侧,将写操作地址传递读操作侧,为了减少读写地址的位翻转率,从而减少亚稳态的发生,在将地址跨越时钟域之前首先转换成格雷码,跨越时钟域并正常采样以后再恢复成二进制的地址。

由于模块中多次使用到将格雷码转换成二进制码以及将二进制码转换成格雷码,所以将格雷码与二进制码的转换使用了两个函数(function)来实现,方便在代码中不同处调用。

跨越时钟域时,为了隔断亚稳态的传递,首先要用两级寄存器对另一时钟域产生的地址打两拍,这样子即使有亚稳态发生,也能被阻隔在两级寄存器中。

尽管打两拍能阻断亚稳态的传递,但是不能避免跨时钟域时采样错误的发生,使用格雷码的作用是使得错误仅发生在其中一个位上。

代码中RAM输入和输出都没有使用到寄存器,读者可以根据自己的需要定制满足自己要求的FIFO,在写操作侧或读操作侧加寄存器。

代码中数据的位宽和地址的位宽,亦可以根据读者的需要修改。

尽管本文提供了异步FIFO的完整实现代码,博主还是建议各位读者在使用FIFO 时尽量多用CORE Generator生成的FIFO,那样会更加可靠稳定,使用起来也更方便。

代码://********************************************************************************************************** ******// Copyright(c) 2012, Technology Endless - Creative Boundless , All right reserved// Filename : asynfifo.v// Author : lucien// Email : intellectuallib@// Date : Apr 22th, 2012// Version : 1.0// Company :// Description : asynchronous FIFO(first in first out)// Modification History// Date By Revision Change Description// ---------------------------------------------------------------------------------------// 2012/04/22 Lucien 1.0 Original//********************************************************************************************************** ******`timescale 1ns/1psmodule asynfifo(rst ,wr_clk ,wr_en ,din ,full ,rd_clk ,rd_en ,dout ,empty);input wire rst ;//reset signalinput wire wr_clk ;//clock of read clock fieldinput wire wr_en ;//write enableinput wire [7:0] din ;output wire full ;input wire rd_clk ;//clock of write clock fieldinput wire rd_en ;output wire [7:0] dout ;output wire empty ;/********************************************************************************************************** ****//********************************************************************************************************** ****\* define internal signals * \********************************************************************************************************** ****/reg [7:0] waddr; //write address in write clock fieldreg [7:0] raddr; //read address in read clock fieldwire [7:0] waddr_gray_wclk; //the gray code of write address in write clock fieldwire [7:0] raddr_gray_rclk; //the gray code of read address in read clock fieldreg [7:0] waddr_gray_rclk_0; //the dealyed gray codes of write address in read clock field reg [7:0] waddr_gray_rclk_1;reg [7:0] raddr_gray_wclk_0; //the dealyed gray codes of read address in write clock field reg [7:0] raddr_gray_wclk_1;wire [7:0] waddr_rclk; //write address in read clock fieldwire [7:0] raddr_wclk; //read address in write clock fieldreg [8:0] count_wclk; //the data counter in write clock fieldreg [8:0] count_rclk; //the data counter in read clock fieldfunction [7:0] binary_to_gray;input [7:0] binary_code ;beginbinary_to_gray[0]=binary_code[0]^binary_code[1];binary_to_gray[1]=binary_code[1]^binary_code[2];binary_to_gray[2]=binary_code[2]^binary_code[3];binary_to_gray[3]=binary_code[3]^binary_code[4];binary_to_gray[4]=binary_code[4]^binary_code[5];binary_to_gray[5]=binary_code[5]^binary_code[6];binary_to_gray[6]=binary_code[6]^binary_code[7];binary_to_gray[7]=binary_code[7];endendfunctionfunction [7:0] gray_to_binary;input [7:0] gray_code ;begingray_to_binary[7]=waddr_gray_rclk_1[7];gray_to_binary[6]=waddr_gray_rclk_1[6]^gray_to_binary[7];gray_to_binary[5]=waddr_gray_rclk_1[5]^gray_to_binary[6];gray_to_binary[4]=waddr_gray_rclk_1[4]^gray_to_binary[5];gray_to_binary[3]=waddr_gray_rclk_1[3]^gray_to_binary[4];gray_to_binary[2]=waddr_gray_rclk_1[2]^gray_to_binary[3];gray_to_binary[1]=waddr_gray_rclk_1[1]^gray_to_binary[2];gray_to_binary[0]=waddr_gray_rclk_1[0]^gray_to_binary[1]; endendfunctionsimple_dual_port_ram U_simple_dual_port_ram(.clka (wr_clk ),.wea (wr_en ),.addra (waddr ),.dina (din ),.clkb (rd_clk ),.addrb (raddr ),.doutb (dout ));assign empty = (count_rclk[8:0] == 9'h0);assign full = (count_rclk[8:0] == 9'h100);assign waddr_gray_wclk = binary_to_gray(waddr);assign raddr_gray_rclk = binary_to_gray(raddr);assign waddr_rclk = gray_to_binary(waddr_gray_rclk_1);assign raddr_wclk = gray_to_binary(raddr_gray_wclk_1);always@(posedge wr_clk or posedge rst)beginif(rst == 1'b1)waddr <= 8'h0;elseif(wr_en==1'b1)waddr <= waddr + 8'h1;elsewaddr <= waddr;endalways@(posedge rd_clk or posedge rst)beginif(rst == 1'b1)raddr <= 8'h0;elseif(wr_en==1'b1)raddr <= raddr + 8'h1;elseraddr <= raddr;endalways@(posedge wr_clk or posedge rst)beginif(rst == 1'b1)beginraddr_gray_wclk_0<=8'b0;raddr_gray_wclk_1<=8'b0;endelsebeginraddr_gray_wclk_0<=raddr_gray_rclk;raddr_gray_wclk_1<=raddr_gray_wclk_0;endendalways@(posedge rd_clk or posedge rst)beginif(rst == 1'b1)beginwaddr_gray_rclk_0<=8'b0;waddr_gray_rclk_1<=8'b0;endelsebeginwaddr_gray_rclk_0<=waddr_gray_wclk;waddr_gray_rclk_1<=waddr_gray_rclk_0;endendalways@(posedge wr_clk or posedge rst)beginif(rst == 1'b1)count_wclk <= 9'h0;elseif(waddr < raddr_wclk)count_wclk <= waddr + 9'h100 - raddr_wclk;else if((count_wclk > 9'h0) && (waddr == raddr_wclk)) count_wclk <= 9'h100;elsecount_wclk <= waddr - raddr_wclk;endalways@(posedge rd_clk or posedge rst)beginif(rst == 1'b1)count_rclk <= 9'h0;elseif(waddr_rclk < raddr)count_rclk <= waddr_rclk + 9'h100 - raddr;else if((count_rclk > 9'h0) && (waddr_rclk == raddr)) count_rclk <= 9'h100;elsecount_rclk <= waddr_rclk - raddr;endendmodule。

异步FIFO的设计分析及详细代码

异步FIFO的设计分析及详细代码

异步FIFO的设计分析及详细代码本文首先对异步FIFO设计的重点难点进行分析,最后给出详细代码。

一、F1FO简单讲解FIFO的本质是RAM,先进先出重要参数:fif。

深度(简单来说就是需要存多少个数据)fif。

位宽(每个数据的位宽)FIFO有同步和异步两种,同步即读写时钟相同,异步即读写时钟不相同同步F1FO用的少,可以作为数据缓存异步FIFO可以解决跨时钟域的问题,在应用时需根据实际情况考虑好fifo 深度即可本次要设计一个异步FIFO,深度为8,位宽也是&代码是学习Simu1ation andSynthesis Techniquesfor AsynchronousFIFODesignC1iffordE.Cu mmings,SunburstDesign,InC.这篇文章的,百度搜搜很容易找到,虽然是英文的但是写的酸值得研究。

下面我会对设计的要点进行分析,也是对自己学习过程的一个总结,希望能和大家交流共同进步。

二、设计要点解析1、读空值号如何产生?写满信号如何产生?读空信号:复位的时候,读指针和写指针相等,读空信号有效(这里所说的指针其实就是读地址、写地址)当读指针赶上写指针的时候,写指针等于读指针意味着最后一个数据被读完,此时读空信号有效写满信号:当写指针比读指针多一圈时,写指针等于读指针意味着写满了,此时写满信号有效我们会发现读空的条件是写指针等于读指针,写满的条件也是写指针等于读指针,到底如何区分呢?解决方法:将指针的位宽多定义一位举个例子说明:假设要设计深度为8的异步FIFO,此时定义读写指针只需要3位(2-3二8)就够用了,但是我们在设计时将指针的位宽设计成4位,最高位的作用就是区分是读空还是写满,具体理论1如下当最高位相同,其余位相同认为是读空当最高位不同,其余位相同认为是写满注意:理论1试用的是二进制数之间的空满比较判断。

但是这篇文章中确不是这样比较的,而是用的理论2,这里我解释一下由于文章在设计中判断是读指针是否等于写指针的时候,用的是读写指针的格雷码形式(为什么用格雷码后面解释),此时若用上面的理论1就会出问题,因为格雷码是镜像对称的,若只根据最高位是否相同来区分是读空还是写满是有问题的,详情我会慢慢说,请看图1绿色框起来的是0-15的格雷码,用红线将格雷码分为上下两部分通过观察格雷码相邻位每次只有1位发生变化,且上下两部分,除了最高位相反,其余位全都关于红线镜像对称,7—>8,格雷码从0100->1100,只有最高位发生变化其余位相同6->9,格雷码从0101->1101,只有最高位发生变化其余位相同以此类推,为什么要说镜像对称呢?试想如果读指针指向8,写指针指向7,我们可以知道此时此刻并不是读空状态也不是写满状态但是如果在此刻套用理论1来判断,看会出现什么情况,我们来套一下7的格雷码与8的格雷码的最高位不同,其余位相同,所以判断出为写满。

异步FIFO的VHDL设计

异步FIFO的VHDL设计

异步FIFO的VHDL设计下面是一个异步FIFO的VHDL设计示例:```vhdllibrary ieee;use ieee.std_logic_1164.all;entity AsyncFIFO isgenericDATA_WIDTH : natural := 8; -- 数据宽度FIFO_DEPTH : natural := 16 -- FIFO深度portclk : in std_logic; -- 时钟信号rst : in std_logic; -- 复位信号read_en : in std_logic; -- 读使能write_en : in std_logic; -- 写使能read_data : out std_logic_vector(DATA_WIDTH-1 downto 0); -- 读数据write_data : in std_logic_vector(DATA_WIDTH-1 downto 0); -- 写数据full : out std_logic; -- FIFO满标志empty : out std_logic -- FIFO空标志end AsyncFIFO;architecture Behavioral of AsyncFIFO istype buffer_array is array (FIFO_DEPTH-1 downto 0) ofstd_logic_vector(DATA_WIDTH-1 downto 0);signal buffer : buffer_array; -- 数据缓冲区signal wr_ptr : natural range 0 to FIFO_DEPTH-1; -- 写指针signal rd_ptr : natural range 0 to FIFO_DEPTH-1; -- 读指针signal count : natural range 0 to FIFO_DEPTH-1; -- 缓冲区中数据个数beginprocess (clk)beginif rising_edge(clk) thenif rst = '1' thenwr_ptr <= 0;rd_ptr <= 0;count <= 0;elseif write_en = '1' and full = '0' then -- 写使能且FIFO非满buffer(wr_ptr) <= write_data;wr_ptr <= wr_ptr + 1;count <= count + 1;end if;if read_en = '1' and empty = '0' then -- 读使能且FIFO非空read_data <= buffer(rd_ptr);rd_ptr <= rd_ptr + 1;count <= count - 1;end if;end if;end if;end process;full <= '1' when count = FIFO_DEPTH-1 else '0';empty <= '1' when count = 0 else '0';end Behavioral;```在上面的代码中,`DATA_WIDTH`和`FIFO_DEPTH`是异步FIFO的泛型参数,可以根据实际需求进行配置。

一种高可靠性高速可编程异步FIFO的设计

一种高可靠性高速可编程异步FIFO的设计

0引言在现代的大规模ASIC 设计中,常常涉及多时钟系统控制方式,这样就会产生不同时钟域数据传输的问题。

比较好的解决方案就是使用异步FIFO(First In First Out)来实现不同时钟域数据传输的缓冲[1-2]。

这是因为,异步FIFO 只按指针的递增顺序写入数据,并以同样的顺序读出数据,不需要外部读写地址线,使用起来非常简单,这样既可以使相异时钟域数据传输的时序要求变得宽松,也提高了它们之间的传输效率。

因此,异步FIFO 在网络通信和数字信息处理等领域都有着广泛的应用[3-6]。

而高性能异步FIFO 的研究也就成为了大规模集成电路设计领域的研究热点之一,并取得了很多研究成果[7-10]。

例如,文献[7]中,采取了比较同步指针的方法来降低亚稳态出现的可能,这样做确实保证了比较时两个指针都是同步的,但是在进行大容量FIFO 设计时,读、写指针的位数很多,同步模块会使用大量的寄存器,这样会大大增加设计成本,降低工作效率。

而且该论文提到的设计方案在进行空满判断时,增加了一个地址位来标识读写指针的相对位置,这样做不仅占用了过多的逻辑资源,还降低了FIFO 控制系统的可移植性。

文献[8]中提到了一种通过判断格雷码前两位来划分存储区间,进而判断空满的方法,但是由于这种判断区间的划分方式是通过硬件的形式实现的,可编程性不好。

本设计为了满足一款国产FPGA 的芯片设计需求,在保证高可靠性的前提下,进一步增强了异步FIFO 的可编程性,提出了一种基于格雷码的、可以对近空满示警阈值进行编程的异步FIFO ,并且结合异步指针比较的方法提出了一种新的空满判断标准,进而提高了电路的工作速度和效率,∗基金项目:辽宁省教育厅研究生教育教学改革联合培养项目(辽教函[2017]24号)一种高可靠性高速可编程异步FIFO 的设计∗牛博,赵宏亮(辽宁大学物理学院,辽宁沈阳110036)摘要:基于一款国产FPGA 芯片的研发,提出了一种具有高可靠性、高速及可编程性的异步FIFO 电路结构。

异步FIFO的设计文档

异步FIFO的设计文档

异步FIFO的设计版本v1.02011-05-06异步FIFO的设计一.功能描述本设计用16*8 RAM实现一个异步FIFO,具体功能定义如下:1. 异步复位。

2. FIFO不为满时,当写使能有效时,在写时钟的上升沿向FIFO中写入数据。

3. FIFO不为空时,当读使能有效时,在读时钟的上升沿从FIFO中读出数据。

4. 当FIFO写满的时候,产生满信号;当FIFO读空的时候,产生空信号。

5. FIFO一旦空或者满时候,复位FIFO;二.输入输出信号描述信号名输入/输出目标/源功能描述Rclk Input Pin 读时钟频率,10M ,占空比1:1。

Wclk Input Pin 写时钟,频率10M ,占空比1:1。

data_in[7:0] Input Pin 8位的输入数据rd_en Input Pin 读使能,高电平有效,在FIFO非空时,CLK上升沿读入数据;wr_en Input Pin 写使能,高电平有效,在FIFO非满时,CLK上升沿写入数据;Rst Input Pin 异步清零,低电平有效,低电平时读地址,写地址,计数器都清零。

三顶层划分图1 系统框图顶层模块说明:1.RAM :存储器模块,用于存放及输出数据;2.Waddr_Reg : 保存访问RAM的写地址;3.Raddr_Reg : 保存访问RAM的写地址;4.Wbin_addr : 计算RAM下一个写地址;5.Rbin_addr : 计算RAM下一个读地址;6.Gwaddr_reg : 将写地址的二进制编码转换成格雷码,并保存;7.Graddr_reg : 将读地址的二进制编码转换成格雷码,并保存;8.Syn_Rfield : 将写地址同步到读时钟域,并产生空标志;9.Syn_Wfield : 将读地址同步到写时钟域,并产生满标志;10、Reset_Unit : 复位信号产生单元设计思想说明:1、由于实现的异步FIFO,分别用不同的读、写时钟产生读写地址,因此FIFO 的判空和判满是本设计中的一个难点。

高速异步FIFO的设计和实现

高速异步FIFO的设计和实现

万方数据路中,这一信号最终会朝着0和1两个稳态转换,变成稳定的信号。

这一变换所需的时间取决于寄存器的结构和参数,通常在一个时钟周期内可以完成这一从亚稳态到稳态的转换。

所以,在设计中普遍采用两级寄存器串接的同步器来对信号进行同步,如图1所示。

图1解决亚稳态的同步器电路2.2毛刺单根信号的同步采用图1所示的同步电路即可消除亚稳态问题。

然而,对多位总线信号的同步,除了亚稳态外,还有一个重要的问题就是毛刺现象。

如果需要同步的总线的多位同时发生变化,由于在实际电路中各位的延时不可能完全一致,因此中间就可能会产生毛刺现象。

而用另一个频率相位完全不同的时钟采样的时候就有可能采样到毛刺信号,造成错误的同步。

例如,FIFO的读写指针是一个二进制计数器,当它从l计数到2时,位0从1变成0,位l从0变成1。

如果位0从1变成0的延时比位1从0变1要大,就会在1和2中间多出一个毛刺3,而如果直接用图l的同步电路同步,就有可能错误地在另一个时钟域得到一个3的结果。

对于FIFO的设计来说,这样的同步错误是致命的,会造成空满判断的失误。

解决这一问题就是需要采用无毛刺的电路结构,无毛刺电路要求信号同步前必须被寄存器锁存,并且每次只有一位发生变化。

例如,文献[2]中设计的FIFO就采用格雷码来避免这一问题。

3高速异步FIFO结构3.1基本结构本文设计的高速异步FIFO结构如图2所示,主要包括数据通路reg—file和控制模块fifo—eft两个部分。

reg—file模块是FIFO的存储器部分;fifo_eft模块负责FIFO的读写控制,如读写指针的产生和空满信号的产生。

图2高速异步FWO结构框图本设计的外部端口如表l所示。

3.2reg__file模块设计FIFO的存储器部分可以采用双端口SRAM或者用DFF寄存器搭建存储部分。

由于本设计为32×32的FIFC,存储器容量不大,采用双端口SRAM由于powerring等因素,面积会比用寄存器搭建要大,速度也不容易达86到500MHz的高速。

异步FIFO设计

异步FIFO设计

异步FIFO设计
摘要:本文介绍如何应用美国QUICKLOGIC 公司的QUICKRAM 器件设
计高速、高可靠异步FIFO(Asynchronous FIFO)。

异步FIFO 广泛地用于计算机网络工业中进行非同步数据传送,这里的非同步指按一种速率发送而按另一速率接收。

因此异步FIFO 有两个不同的时钟,
一个为读同步时钟,一个为写同步时钟。

当数据从一个时钟驱动的模块进入另一个时钟驱动的模块时,一个需仔细
解决的问题就出现了。

例如当写时钟比读时钟快时,未读走数据有可能被新数
据覆盖,因而导致数据丢失。

为了解决这个问题,就必须增加一些控制信号和
状态信号,控制信号如pusb、pop,状态信号如empty,almostempty,full,almost- full。

功能描述
典型的异步FIFO(AsynFIFO)都是由异步双端口RAM 和控制逻辑构成,控制逻辑包含读指针和写指针。

当FIFO 中有数据而非空时,POP 信号(同步于读时钟)用于控制数据的读出,所读数据来自读指针所指的(AUAL PORT RAM)中的存储单元,并且读指针加一。

当读指针赶上写指针时,FIFO 为空并且用empty 信号(同步于读时钟)来指示这种情况。

当FIFO 中有空间而非满时,PUSH 信号(同步于写时钟)用于控制数据的写入,所写数据写入写指针所指的双端口RAM 中的存储单元,并且写指针加一。

当写指针赶上读指针时,FIFO 为满足并且用full 信号(同步于写时钟)来指示这种情况。

当FIFO 中只剩不足三个数据时,almost-empty 有效(同步于读时钟)。

类似。

4.异步FIFO的设计

4.异步FIFO的设计

利用异步FIFO在跨时钟域中降低亚稳态发生概率在数字电路设计中,时钟是整个电路最重要、最特殊的信号,系统内大部分器件的操作都是在时钟的跳变沿上进行,如果时序不满足要求,就可能造成逻辑状态出错甚至整个系统设计的失败。

随着SOC技术的不断发展,数字系统设计的复杂度也在日益增加,经常需要跨时钟域的数据传输,通信技术等异步设计才能实现特定的功能需求。

本文设计的异步FIFO就是为了解决将数据从一个时钟域同步的读/写到另一个时钟域,并且能很好的避免亚稳态的发生。

1.异步系统任意的两个系统如果满足以下条件之一,如图1-2所示,就可称其为异步的:(1)工作在不同的时钟频率上;(2)工作在相同频率上,但相位不同图1-2 异步系统时钟当两个不同时钟域的系统进行数据传输,由于接口处是异步的,就可能会违反建立时间和保持时间规则导致亚稳态以及不可靠的数据传输,因此处理起来较同步逻辑复杂困难。

在同步系统中,输入信号必须总是满足寄存器时序要求,所以亚稳态不会发生。

亚稳态问题通常发生在当一个信号在无关的线路中或异步时钟域中传输。

在所有的异步系统中,亚稳态是不可避免的。

1.1亚稳态所有的数字器件寄存器都定义了一个信号时序要求,满足了这个要求寄存器才可以正确地在输入端获取(capture)数据在输出端产生数据。

为了确保数据的可靠与正确性,在数据传输过程中必须满足寄存器的建立时间和保持时间,如图1-1,即输入数据在时钟沿之前必须稳定一段时间(寄存器建立时间Tsu)并且在时钟沿之后稳定一段时间(寄存器保持时间Th),然后寄存器输出经过一个特定的时钟到输出延时(clock to output ,Tco)后有效。

图1-1 建立时间与保持时间如果一个数据信号在翻转中违反了一个寄存器的建立和保持时间的要求,寄存器的输出可能就会出现亚稳态。

在亚稳态中,寄存器的输出值在高和低之间徘徊一段时间,这就意味着输出翻转到一个确定的高或低的延时会超过固定的时钟到输出延时。

一个异步FIFO的设计示例

一个异步FIFO的设计示例

一、异步FIFO 技术规范1. 总体描述1.1. 功能定义异步FIFO ( First In First Out)指的是在两个相互独立的时钟域下, 数据从一个时钟域写入FIFO 而另一个时钟域又从这个FIFO 中将数据读出。

本设计用8*256的RAM 实现异步FIFO 。

具体功能:1. 写使能有效,且FIFO 不为满时,在写时钟的上升沿向FIFO 中写入数据。

2. 读使能有效,且FIFO 不为空时,在读时钟的上升沿从FIFO 中读出数据。

3. 当FIFO 写满时产生满信号,当FIFO 读空时产生空信号。

1.2. 应用范围异步FIFO 是用来作为缓冲的存储器, 它能对数据进行快速、顺序的存储和发送, 主要用来解决不同速率器件间的速率匹配问题。

2. 引脚描述8*256异步FIFO rst r_clkr_en data_in[7:0]full empty w_clkw_endata_out[7:0]图12.1. 引脚功能描述 信号名输入/输出 功能描述r_clk输入 读数据时钟信号 w_clk 输入 写数据时钟信号data_in[7:0] 输入8位的输入数据r_en 输入读使能,高电平有效,在FIFO非空时,clk上升沿读入数据;w_en 输入写使能,高电平有效,在FIFO非满时,clk上升沿写入数据;rst 输入异步清零,低电平有效,低电平时读地址,写地址,计数器都清零。

empty 输出空信号,高电平有效,当FIFO读空时其值为1full 输出满信号,高电平有效,当FIFO写满时其值为1 data_out[7:0] 输出8位的输出数据2.2.引脚时序描述当写满时full由低变高,当读空时empty由低变高。

只要不为满full就为低,不为空empty就为低。

3.顶层模块划分。

任意深度的异步FIFO设计

任意深度的异步FIFO设计
1 1 Gr y码 存 储 器 及 其 缺 陷 . a
在异 步 FF IO存 储 器 中 , 写指 针要 被 同步 到对方 的时钟 域 以产 生 空/ 读/ 满信 号 . 由于 二进 制 数 据 每 次
翻转 的不确定性及亚稳态的影响 , 不能将多位二进制数据直接同步到另一时钟域 中. 最常见的方法是先将 数据转化成 Ga 码再同步. r y Ga 码是一种错误最小化编码 , r y ]其缺点是 G a 码指针只能用于实现大小为 2的幂次的 FF r y IO存储
mo tFI s FO s d sg e t a o e,t i e u r s t e d ph o mo y i wa e i n d wi Gr y c d h h s r q ie h e t fme r s 2 Ge e al n rl y,t e h
Ke o d : I O ;me a tb l y y c r n z ;G a o e yw r s F F tsa i t ;s n h o ie i ry c d
随着集成 电路设计规模 的不断扩大 , 使裸片尺寸越来越大 , 这容易造成时钟偏差. 一些新 的方法 , 如整
体异步局部同步( A S 结构正在替代通 常的同步方法 _ , G L) 1 它不需要整体采用单一时钟 , j 因而避免 了时钟
Ab ta t As n h o o s F F s a g n r lwa o c mmu i ae b t e i ee t co k d ma n . As s c : y c rn u I O i e ea r y t o n c t ewe n d f r n l c o i s f
企 肥 学 院 学 报 ( 然科学版) 自
2 1 年 8月 第 2 卷 第 3期 01 1

一款低功耗异步FIFO的设计与实现

一款低功耗异步FIFO的设计与实现
t r u h d vd d btl e tc n lg . Th s n h o o s FI O o to o is a o t a n v lcr ut u i g h o g iie - i i e h oo y —n e a y c r n u F c n r llgc d p o e i i sn c
i ef ciey rd c st ec n r llgca d d c d ic i 8 p we ;t em e r el e u e3 p we t fe tv l e u e h o to o i n e o ecr ut 0 o r h mo y c l rd c 8 s o r
EEACC: 7 25 0

款 低 功 耗 异 步 F F 的设 计 与 实现 IO
张英武 , 杜 波, 国顺 袁
( 中国科学 院 微 电子研究 所 , 北京 10 2 ) 0 0 9
摘 要: 我们在异步 FF Frt nFrt u) IO( i i t设计 中, sI sO 引入 了门控时钟技术 降低 了控 制电路 和译 码电路 8 的功耗 ; 0/ 9 6 并采用位线分割技术降低 了存储单元 3 %的功耗. 8 利用格雷码作异步 FF IO指针的控制电路 , 能有效消除多时钟域中的亚稳态. 基于 C MC0 6 S . m标准单元库的半定制设计流程对其进行设计和实现 : 使用 Vei g ro 硬件描述语言 , l 利用 Mo e i d lm进行时序和功能仿真、 y oss X: s S n py 完成逻辑综 0卷 第 3期 20 0 7年 6月
电 子 器 件
C iee J umlOfEe t n Deie hns o r lcr vc s o
VO . 0 No 3 13 .

异步FIFO的verilog代码实现(包含将满和将空逻辑)

异步FIFO的verilog代码实现(包含将满和将空逻辑)

异步FIFO的verilog代码实现(包含将满和将空逻辑)异步FIFO的verilog代码实现(包含将满和将空逻辑)代码参考来源:1. Clifford E. Cummings, "Simulation and Synthesis Techniques for Asynchronous FIFO Design".2.⽬录异步FIFO简介使⽤场景:在有⼤量的数据需要进⾏跨时钟域传输,并且对数据传输速度要求⽐较⾼的场合。

⼀个异步 FIFO ⼀般由如下部分组成:1. Memory, 作为数据的存储器;2.写逻辑部分,主要负责产⽣写信号和地址;3.读逻辑部分,主要负责产⽣读信号和地址;4.地址⽐较部分,主要负责产⽣ FIFO 空、满的标志。

跟普通的FIFO相⽐,异步FIFO实际上多了读写地址的跨时钟域同步的逻辑,以及两个时钟域中读写信号的⽐较逻辑。

异步FIFO关键技术1 -- 读写信号跨时钟域同步⾸先,FIFO的关键是需要判断读空和写满,⽽这两个信号的产⽣依赖读地址和写地址。

在异步FIFO中,读和写是分在两个时钟域中的,在写时钟域,需要得到读地址的信息进⽽判断是否写满(写指针是否追上读指针),同理,在读时钟域,也需要写地址的信息。

我们知道跨时钟域的单⽐特数据⼀般可以⽤双寄存器法进⾏同步,但读写地址通常都是多⽐特的信号,此时如何进⾏同步呢?当然,多⽐特的同步肯定可以通过增加握⼿信号来解决,但实际上对于数值上连续的信号,可以采⽤格雷码进⾏多⽐特到单⽐特的传输。

格雷码再次不做介绍,具体原理可以参考:有了格雷码,就可以将读写地址同步到各⾃的时钟域了。

异步FIFO关键技术2 -- 读写地址的⽐较跟普通fifo⼀样,异步fifo也是通过⽐较读写地址是否相同来判断当前fifo是否空满。

区别在于,异步FIFO因为使⽤了格雷码对地址进⾏编码传输。

⽐如读信号通过格雷码编码后同步到写时钟域,此时需要只需要写信号对应的格雷码和读信号格雷码是否相同(有效位相同)。

异步FIFO设计

异步FIFO设计

,异步FIFO设计文档一、概述在大规模ASIC或FPGA设计中,多时钟系统往往是不可避免的,这样就产生了不同时钟域数据传输的问题,其中一个比较好的解决方案就是使用异步FIFO 来作不同时钟域数据传输的缓冲区,这们既可以使相异时钟域数据传输的时序要求变得宽松,也提高了它们之间的传输效率。

此文内容就是阐述异步FIFO的设计。

二、设计原理结构框图Fig. 2.1.1如上图所示的同步模块synchronize to write clk,其作用是把读时钟域的读指针rd_ptr采集到写时钟(wr_clk)域,然后和写指针wr_ptr进行比较从而产生或撤消写满标志位wr_full;类似地,同步模块synchronize to read clk 的作用是把写时钟域的写指针wr_ptr采集到读时钟域,然后和读指针rd_ptr 进行比较从而产生或撤消读空标志位rd_empty。

~另外还有写指针wr_ptr和写满标志位wr_full产生模块,读指针rd_ptr 和读空标志位rd_empty产生模块,以及双端口存储RAM模块。

二进制计数器存在的问题异步FIFO读写指针需要在数学上的操作和比较才能产生准确的空满标志位,但由于读写指针属于不同的时钟域及读写时钟相位关系的不确定性,同步模块采集另一时钟域的指针时,此指针有可能正处在跳变的过程中,如图Fig.2.2.1所示,那么采集到的值很有可能是不期望的值,当然,不期望的错误结果也会随之发生。

Fig. 2.2.1上图中,rd_ptr2sync 3和4以及4和5之间的中间态是由于到各寄存器的时钟rd_clk存在偏差而引起的。

二进制的递增操作,在大多数情况下都会有两位或者两以上的bit位在同一个递增操作内发生变化,但由于实际电路中会存在时钟偏差和不同的路径延时,二进制计数器在自增时会不可避免地产生错误的中间结果,如图Fig.2.2.2。

Fig.2.2.2…上图是Fig.2.2.1的电路原型以及局部波形的放大。

高速异步FIFO毕业设计思路与设计要求

高速异步FIFO毕业设计思路与设计要求

一、原理及系统结构FIFO(First In First Out)是一种特殊的存储器件,它可以实现存储数据的先进先出,因而在接口电路中有着广泛的应用。

在多时钟电路系统中,它可以充当数据缓冲器,从而实现不同电路系统之间的数据交换。

我认为可以把FIFO理解为一块特殊的存储器,只不过它的读写指针严格遵循先进先出的原则,而不是像普通RAM一样可以指向任意存储单元。

在本次课设中所设计FIFO为异步FIFO,其规格为32X8,其大致框图如下各端口说明:输入:data_in:输入8位数据;rd_en: 读使能端,当rd_en=1时,可以读出数据;wr_en: 写使能端,当wr_en=1时,可以写入数据;wclk: 写时钟信号,在时钟的上升沿进行采样;rclk: 读时钟信号,在时钟的上升沿进行采样;rst: 复位信号,当rst=0时,计数器及读写都被清零(即:读写地址指针都指向0)输出:data_out:输出8位数据;full:FIFO状态信号,当full=1时,表明该FIFO存储器已经写满;empty:FIFO状态信号,当empty=1时,表明该FIFO存储器已经读空;halffull:FIFO状态信号,当halffull=1时,表明FIFO存储器已经处于半满状态。

Compare信号:输出FIFO的实时已使用容量。

二、设计思想:在进行异步FIFO设计时,主要有以下几个关键问题:1、如何表示32x8的FIFO存储体;2、如何进行数据的读写;3、如何判断空状态、满状态和半满状态乃至输出实时已使用容量;4、如何避免亚稳态的出现。

三、设计要求1、模块代码实现及仿真、波形分析2、电路综合。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

一、异步FIFO 技术规 1. 总体描述1.1. 功能定义异步FIFO ( First In First Out)指的是在两个相互独立的时钟域下, 数据从一个时钟域写入FIFO 而另一个时钟域又从这个FIFO 中将数据读出。

本设计用8*256的RAM 实现异步FIFO 。

具体功能:1. 写使能有效,且FIFO 不为满时,在写时钟的上升沿向FIFO 中写入数据。

2. 读使能有效,且FIFO 不为空时,在读时钟的上升沿从FIFO 中读出数据。

3. 当FIFO 写满时产生满信号,当FIFO 读空时产生空信号。

1.2. 应用围异步FIFO 是用来作为缓冲的存储器, 它能对数据进行快速、顺序的存储和发送, 主要用来解决不同速率器件间的速率匹配问题。

2. 引脚描述图12.1. 引脚功能描述2.2.引脚时序描述当写满时full由低变高,当读空时empty由低变高。

只要不为满full就为低,不为空empty就为低。

3.顶层模块划分图2顶层模块说明:1.ram_fifo :存储器模块,用于存放及输出数据;2.w_addr_reg : 保存访问RAM的写地址;3.r_addr_reg : 保存访问RAM的读地址;4.w_addr_adder : 计算RAM下一个写地址;5.r_addr_adder: 计算RAM下一个读地址;6.cmp : 将读地址和写地址进行比较产生空满标志。

设计思想说明:FIFO满空的判定:当读地址的值加1之后等于写地址的值时,表明FIFO写满,当写地址的值加一之后等于读地址的值时,表明FIFO读空。

在初始状态时FIFO的读地址在RAM 的中间位置,写地址在RAM的开始位置,所以初始状态FIFO不满也不空。

空满信号的产生由组合电路产生。

4.功能模块描述ram_fifo:RAM存储器。

用8*256双口RAM实现。

4.2.w_addr_reg模块w_addr_reg模块:写地址寄存器。

用来寄存写地址加法器输出的地址。

4.3.r_addr_reg模块r_addr_reg模块:读地址寄存器。

用来寄存读地址加法器输出的地址。

4.4.w_addr_adder模块w_addr_adder模块:写地址加法器。

把写地址寄存器的输出加一,即表示当前写地址的下一地址位。

当w_en为低时停止累加。

4.5.r_addr_adder模块r_addr_adder模块:读地址加法器。

把读地址寄存器的输出加一,即表示当前读地址的下一地址位。

当r_en为低时停止累加。

4.6.cmp模块cmp模块:读地址和写地址进行比较,产生满空标志。

二、异步FIFO总体设计方案1.概述异步FIFO有高速、可靠性好等特点。

由于异步FIFO 在两个不同时钟系统之间能够快速而方便地传输实时数据, 因此在网络接口、图像处理等方面, 异步FIFO 得到了广泛的应用。

异步FIFO 指的是在两个相互独立的时钟域下, 数据从一个时钟域写入FIFO 而另一个时钟域又从这个FIFO 中将数据读出。

异步FIFO 通常被用来将数据从一个时钟域安全地传送到另外一时钟域。

2.功能模块设计2.1.1.ram_fifo模块描述ram_fifo:RAM存储器。

用8*256双口RAM实现。

2.1.2.管脚描述2.1.3.实现说明应使用双口RAM,双地址输入,并且带有读写使能,异步的读写时钟。

RAM宽度为8bit,深度为256个存储单元。

2.2.w_addr_reg模块2.2.1.w_addr_reg模块描述w_addr_reg模块:写地址寄存器。

用来寄存写地址加法器输出的地址。

2.2.2.管脚描述2.2.3.实现说明在时钟的上升沿将8位的输入数据锁存输出。

2.3.r_addr_reg模块2.3.1.r_addr_reg模块描述r_addr_reg模块:读地址寄存器。

用来寄存读地址加法器输出的地址。

2.3.2.管脚描述表42.3.3.实现说明在时钟的上升沿将8位的输入数据所存输出。

2.4.w_addr_adder模块2.4.1.w_addr_adder模块描述w_addr_adder模块:写地址加法器。

把写地址寄存器的输出加一,即表示当前写地址的下一地址位。

当w_en为低时停止累加。

2.4.2.管脚描述2.4.3.实现说明以w_addr为输入,输出为 w_addr+1。

2.5.r_addr_adder模块2.5.1.r_addr_adder模块描述r_addr_adder模块:读地址加法器。

把读地址寄存器的输出加一,即表示当前读地址的下一地址位。

当r_en为低时停止累加。

2.5.2.管脚描述2.5.3.实现说明以r_addr为输入,输出为 r_addr+1。

2.6.cmp模块2.6.1.cmp模块描述cmp模块:读地址和写地址进行比较,产生满空标志。

2.6.2.管脚描述2.6.3.实现说明将w_addr加一与r_addr对比,相等则full为1否则为0;将r_addr加一与w_addr对比,相等则empty为1否则为0;三、异步FIFO验证方案总体验证方案1.1.测试FIFO在正常状态下,是否能写入和读出;full和empty的标志位均为0;1.2.测试FIFO在写满时,full是否能变为高;当满时读出一个数,full能否由高变低。

1.3.测试FIFO在读空时,empty是否能变为高;当空时写入一个数,empty能否由高变低。

1.4.异步复位后,FIFO是否可以正常工作。

另外,在编写激励时,FIFO读空后,则将读使能禁止,FIFO写满后,则将写使能禁止,以保证读出和写入数据的正确性。

四、电路设计源代码及仿真激励(1)异步FIFO源代码:module fifo(data_in,data_out,r_en,w_en,r_clk,w_clk,full,empty,rst);input [7:0]data_in;input r_en;input w_en;input r_clk;input w_clk;input rst;output [7:0]data_out;output empty;output full;wire [7:0]w_addr;wire [7:0]r_addr;wire [7:0]w_addr_nt;wire [7:0]r_addr_nt;ram u1(.data_out(data_out), .data_in(data_in), .w_clk(w_clk),.r_clk(r_clk),.w_en(w_en),.r_en(r_en),.w_addr(w_addr),.r_addr(r_addr));w_addr_reg u2(.w_addr(w_addr),.w_addr_nt(w_addr_nt), .w_clk(w_clk),.rst(rst));r_addr_reg u3(.r_addr(r_addr),.r_addr_nt(r_addr_nt), .r_clk(r_clk),.rst(rst));w_addr_adder u4(.w_en(w_en),.w_addr(w_addr),.w_addr_nt(w_addr_nt) );r_addr_adder u5(.r_en(r_en),.r_addr(r_addr),.r_addr_nt(r_addr_nt));cmp u6(.w_addr(w_addr),.r_addr(r_addr),.full(full),.empty(empty));endmodulemodule ram(data_out,data_in,w_clk,r_clk,w_en,r_en,w_addr,r_addr);input [7:0]data_in;input w_clk;input r_clk;input w_en;input r_en;input [7:0]w_addr;input [7:0]r_addr;output [7:0]data_out;reg [7:0]ram_f[255:0];reg [7:0]data_out;always(posedge r_clk)beginif(!r_en)data_out <= 8'hzz;elsebegindata_out <= ram_f[r_addr];endendalways(posedge w_clk)beginif(!r_en)ram_f[w_addr] <= ram_f[w_addr]; elsebeginram_f[w_addr] <= data_in;endendendmodule//w_addr_regmodule w_addr_reg(w_addr,w_addr_nt,w_clk,rst);input [7:0]w_addr_nt;input w_clk;input rst;output [7:0]w_addr;reg [7:0]w_addr;always(posedge w_clk or negedge rst) beginif(!rst)w_addr <= 8'h1f;elsew_addr <= w_addr_nt;endendmodule//r_addr_regmodule r_addr_reg(r_addr,r_addr_nt,r_clk,rst);input [7:0]r_addr_nt;input r_clk;input rst;output [7:0]r_addr;reg [7:0]r_addr;always(posedge r_clk or negedge rst) beginif(!rst)r_addr <= 8'h00;elser_addr <= r_addr_nt;endendmodule///////////////////////////////////////////////////////////////////// //w_addr_addermodule w_addr_adder(w_en,w_addr,w_addr_nt);input w_en;input [7:0]w_addr;output [7:0]w_addr_nt;assign w_addr_nt = w_en ? (w_addr + 8'h01) : w_addr;endmodule//r_addr_addermodule r_addr_adder(r_en,r_addr,r_addr_nt);input r_en;input [7:0]r_addr;output [7:0]r_addr_nt;assign r_addr_nt = r_en ? (r_addr + 8'h01) : r_addr;endmodule//cmpmodule cmp (w_addr,r_addr,empty,full);input [7:0]w_addr;input [7:0]r_addr;output empty;output full;assign empty = r_addr + 1 == w_addr;assign full = w_addr + 1 == r_addr;endmodule见fifo_tb.v`timescale 1ns/100psmodule fifo_tb;reg [7:0]data_in;reg r_en;reg w_en;reg r_clk;reg w_clk;reg rst;wire [7:0]data_out;wire full;wire empty;reg [7:0]count;fifo u(.data_in(data_in), .data_out(data_out), .r_en(r_en),.r_clk(r_clk),.w_en(w_en),.w_clk(w_clk),.rst(rst),.full(full),.empty(empty));initialbeginr_clk = 0;w_clk = 0;endalwaysbegin#100 r_clk = !r_clk; endalwaysbegin#2if(empty)r_en = 0;elser_en = 1;if(full)w_en = 0;elsew_en = 1;endalwaysbegin#5 if(count)w_clk = !w_clk;elsew_clk = 0;endinitialbeginr_en = 1;w_en = 1;rst = 0;#100rst =1;#100count = 8'hff;repeat(255)begin#10data_in = count; count = count - 1;end#60000//////////////////////////////#100r_en = 1;w_en = 1;count = 8'h04;repeat(4)begin#10data_in = count;count = count - 1 ;end#10000//////////////////////////////////rst = 0;#1000rst = 1;r_en = 1;w_en = 1;#10count = 8'hff;repeat(300)begin.#10data_in = count;count = count - 1;endcount = 8'h00;#60000$stop;endEndmodule.页脚.。

相关文档
最新文档