Normal synchronous FIFO mode 和 Show-ahead synchronous FIFO mode

FIFO是先进先出,可以用fifo来处理跨时钟域的数据传输问题,用到的地方特别多,一定要搞会。

在学习调用fifo的IP核中发现有normal synchronous FIFO mode 和 Show-ahead synchronous FIFO mode这两种模式,就研究一下。

研究 IP 核最方便的方式就是用 modesim 仿真一下,这样关系就会很明了。

下面的两幅图是我用 Time_Gen 软件自己总结画的,并不是 modesim 的仿真图。

假定存入fifo的第一个数是01,第二个数是02,第三个数是03,以此类推。。。

clk是读时钟,rd是读使能,q是fifo的数据输出端

normal mode,只有在读使能信号有效的时候,才会在读时钟上升沿来的时候输出第一个数01。

Show-ahead 模式的输出要比 normal 模式的输出早一拍,意思是只要FIFO中有数据,他就会把第一个数据输出,

当第一个读使能信号来的时候,则会在读时钟上升沿的时候输出第二个数据02。

 

Normal mode                                                     Show-ahead mode

既然二者的区别是数据输出相差一拍,因此在设计 fifo 的时候就要根据不同的模式进行设计

下面举个例子,该代码实现了100Mhz 与 80Mhz 不同时钟域的数据传输问题

因为不同时钟域的频率不同,在进行数据传输的时候如果不进行处理必然会有数据丢失

FIFO 可以缓存数据,因此我们可以先把数据放在 fifo 里,再进行传输

当fifo中的数据 resudw>=某个数的时候,就不允许往 fifo 中写入数据,当 FIFO 空的时候也不允许再读数据。

module fifo(             rst_n ,
            clk_in ,    //100Mhz ,fifo写时钟
            data_in ,   //输入的数据
            data_in_vld,//输入数据有效指示信号

            clk_out  , //80Mhz ,fifo读时钟
            data_out , //输出的数据
            data_out_vld,//输出数据有效指示信号
            b_rdy       //当为高,表示可以接收从fifo中读的数据,反之则不行

                            );

input rst_n ,clk_in,clk_out,b_rdy;
input [15:0] data_in ;
input  data_in_vld ;
output[15:0] data_out    ;
output[15:0] data_out_vld;
reg wr_ff0;
wire wr_ff1;
wire[15:0] q;
reg[7:0] data_out;
reg data_out_vld;
reg rd_ff0;
wire   rdempty ;
wire   wrfull ;
wire[5:0]   wrusedw;//调用IP核生成位宽为16 位,深度为64的FIFO, Show-ahead模式
 my_fifo  u1_fifo(
                  .data (data_in),
                  .rdclk(clk_out),
                  .rdreq(rd_ff0),
                  .wrclk(clk_in),
                  .wrreq(wr_ff1),
                  .q    (q),
                  .rdempty(rdempty),
                  .wrfull (wrfull ),
                  .wrusedw(wrusedw)
                );
//----------------------------------------------------------------------
//写满保护
                always  @(*)begin
                    if(wrusedw>=61) begin
                        wr_ff0<=0;
                    end
                    else
                        wr_ff0<=1;
                end
               assign wr_ff1 = (data_in_vld && wr_ff0)?1‘b1:1‘b0;

//rd_ff0
always  @(*)begin
    if(b_rdy==1&&rdempty==0 )begin
        rd_ff0<=1;
    end
    else
        rd_ff0<=0;
end
//------------------------------------------------------------- //如果是Show-ahead 模式入,此时data_out与data_out_vld是对齐的//如果是normal 模式,则需要将rd_ff0在多打一拍,然后将rd_ff1值给data_out_vld才能对齐
always  @(posedge clk_out or negedge rst_n)begin
    if(rst_n==1‘b0)begin
        data_out<=0;
    end
    else begin
        data_out<=q;
    end
end

always  @(posedge clk_out or negedge rst_n)begin
    if(rst_n==1‘b0)begin
        data_out_vld<=0;
    end
    else begin
        data_out_vld<=rd_ff0;
    end
end
endmodule

文章出处:http://www.cnblogs.com/aslmer/p/5872412.html

时间: 2024-10-21 05:01:28

Normal synchronous FIFO mode 和 Show-ahead synchronous FIFO mode的相关文章

[转]Normal synchronous FIFO mode 和 Show-ahead synchronous FIFO mode

FIFO是先进先出,可以用fifo来处理跨时钟域的数据传输问题,用到的地方特别多,一定要搞会. 在学习调用fifo的IP核中发现有normal synchronous FIFO mode 和 Show-ahead synchronous FIFO mode这两种模式,就研究一下. 研究 IP 核最方便的方式就是用 modesim 仿真一下,这样关系就会很明了. 下面的两幅图是我用 Time_Gen 软件自己总结画的,并不是 modesim 的仿真图. 假定存入fifo的第一个数是01,第二个数是

IP核之初——FIFO添加以太网MAC头部

说白了,IP核就是别人做好了的硬件模块,提供完整的用户接口和说明文档,更复杂的还有示例工程,你只要能用好这个IP核,设计已经完成一半了.说起来容易,从冗长的英文文档和网上各个非标准教程中汲取所需,并灵活运用还是需要下一番功夫的. 我认为其中最重要的几点如下: 1) 提供给IP核正确的时钟和复位条件: 2) 明确各个重要用户接口功能: 3) 掌握所需指令的操作时序: 4) 知道内部寄存器地址及功能和配置方式.顺序: 5) 会从官方示例工程中学会IP核正确使用方式: 今天来讲讲一个最常用的IP核,F

Linux IPC实践(3) --具名FIFO

FIFO具名/命名管道 (匿名)管道应用的一个限制就是只能在具有共同祖先(具有亲缘关系)的进程间通信. 如果我们想在不相关的进程之间交换数据,可以使用FIFO文件来做这项工作,它经常被称为命名管道;命名管道是一种特殊类型的文件. 创建一个命名管道 1)命名管道可以从命令行上创建: $ mkfifo <filename> 2)命名管道在程序里创建: #include <sys/types.h> #include <sys/stat.h> int mkfifo(const

FIFO管道探索历程

刚开始代码的实现如下: void CreateFIFO(){    if((mkfifo(FIFOPATH,O_CREAT|O_EXCL|O_RDWR)<0)&&(errno!=EEXIST))    {        printf(strerror(errno));    }   } int OpenFIFO(){    fd=open(FIFOPATH,O_RDWR|O_NONBLOCK);    return fd;} 觉得非常的不优雅,毕竟需要调用两个函数,而且写函数又有一个

【UNIX网络编程】FIFO

管道作为进程间通信的最古老方式,它的缺点是没有名字,因此只能用在有亲缘关系的父子进程之间.对于无亲缘关系的进程间,无法用管道进行通信.FIFO可以完成无亲缘关系的进程间的通信,FIFO也被称为命名管道.它是一种特殊类型的文件,在文件系统中以文件名的形式存在,但它的行为却和上面提到的管道类似. 创建命名管道有两种方法: 1.在命令行上执行命令:mkfifo filename 来创建FIFO. 2.使用mkfifo函数创建FIFO. #include <sys/stat.h> #include &

[自制简单操作系统] 2、鼠标及键盘中断处理事件[PIC\GDT\IDT\FIFO]

1.大致介绍: >_<" 大致执行顺序是:ipl10.nas->asmhead.nas->bootpack.c PS: 这里bootpack.c要调用graphic.c.dsctbl.c.fifo.c.int.c实现功能,其中有些函数还必须汇编来写,所以单独写一个汇编文件naskfunc.nas,为了方便看全部函数和结构体,所以写一个bootpack.h来写一些结构体和函数声明~ >_<" 下面是编译图解:最终生成的haribote.img可放在软盘

操作系统的页面置换C++算法:OPT FIFO LRU CLOCK 计算缺页率

暴力直接上代码,主要是用了vector来实现,有些方法比较费时,不太好,请各位大神斧正.这是个人的作业,  这是代码下载页http://download.csdn.net/detail/l631068264/7644569   里面还有多级反馈队列进程调度的MFC版 #include <iostream> #include <algorithm> #include <vector> #include <stdio.h> #include <stdlib

Verilog基础知识7(FIFO深度计算)

需求说明:Verilog设计 内容       :第一部分 FIFO深度讨论                   第二部分 FIFO深度计算 来自       :时间的诗 第一部分 FIFO深度讨论 原文:http://comm.chinaaet.com/adi/blogdetail/37555.html 其实很惭愧,在这之前用FIFO都是直接用IP,因为应用场景很简单,因此FIFO深度的选择也比较随意,并没想很多.今天在网上看到一个异步FIFO深度计算的题目,发现对于这块并不熟悉,因此注意了下

第15章 进程间通行 15.5 FIFO

(1)什么是命名管道,未命名管道? 未命名管道:只能在两个相关的进程之间使用,而且这两个相关的进程还要有一个共同的创建了它们的主先进程. 命名管道:FIFO,不相关的进程也能交换数据. (2)FIFO是一种文件类型. 创建FIFO类似于创建文件,且FIFO的路径名存在与文件系统中. (3) 函数mkfifo,mkfifoat创建FIFO,用open打开它(O_NONBLOCK非阻塞标志的影响). 应用程序可以用mknod和mknodat函数创建FIFO. (4)FIFO有两种用途. 1)复制一系