Verilog学习笔记简单功能实现(八)...............异步FIFO
基本原理:
1.读写指针的工作原理
写指针:总是指向下一个将要被写入的单元,复位时,指向第1个单元(编号为0)。
读指针:总是指向当前要被读出的数据,复位时,指向第1个单元(编号为0).
2.FIFO的“空”/“满”检测
FIFO设计的关键:产生可靠的FIFO读写指针和生成FIFO“空”/“满”状态标志。
当读写指针相等时,表明FIFO为空,这种情况发生在复位操作时,或者当读指针读出FIFO中最后一个字后,追赶上了写指针时,如下图所示:

当读写指针再次相等时,表明FIFO为满,这种情况发生在,当写指针转了一圈,折回来(wrapped around)又追上了读指针,如下图:

为了区分到底是满状态还是空状态,可以采用以下方法:
方法1:在指针中添加一个额外的位(extra bit),当写指针增加并越过最后一个FIFO地址时,就将写指针这个未用的MSB加1,其它位回零。对读指针也进行同样的操作。此时,对于深度为2n的FIFO,需要的读/写指针位宽为(n+1)位,如对于深度为8的FIFO,需要采用4bit的计数器,0000~1000、1001~1111,MSB作为折回标志位,而低3位作为地址指针。
- 如果两个指针的MSB不同,说明写指针比读指针多折回了一次;如r_addr=0000,而w_addr = 1000,为满。
- 如果两个指针的MSB相同,则说明两个指针折回的次数相等。其余位相等,说明FIFO为空;
3. 二进制FIFO指针的考虑
将一个二进制的计数值从一个时钟域同步到另一个时钟域的时候很容易出现问题,因为采用二进制计数器时所有位都可能同时变化,在同一个时钟沿同步多个信号的变化会产生亚稳态问题。而使用格雷码只有一位变化,因此在两个时钟域间同步多个位不会产生问题。所以需要一个二进制到gray码的转换电路,将地址值转换为相应的gray码,然后将该gray码同步到另一个时钟域进行对比,作为空满状态的检测。
使用gray码解决了一个问题,但同时也带来另一个问题,即在格雷码域如何判断空与满。
对于“空”的判断依然依据二者完全相等(包括MSB);
而对于“满”的判断,如下图,由于gray码除了MSB外,具有镜像对称的特点,当读指针指向7,写指针指向8时,除了MSB,其余位皆相同,不能说它为满。因此不能单纯的只检测最高位了,在gray码上判断为满必须同时满足以下3条:
- wptr和同步过来的rptr的MSB不相等,因为wptr必须比rptr多折回一次。
- wptr与rptr的次高位不相等,如上图位置7和位置15,转化为二进制对应的是0111和1111,MSB不同说明多折回一次,111相同代表同一位置。
- 剩下的其余位完全相等。

5.总体实现

以上内容参考http://www.cnblogs.com/BitArt/archive/2013/04/10/3010073.html,非原创。
源码在原来的基础上进行改编,如下:
module Asyn_FIFO(data_out, full, empty, data_in, wen, wclk, wrst,ren, rclk, rrst);
parameter datasize = ;
parameter addrsize = ; input [datasize-:]data_in;
input wen,ren,wclk,rclk,wrst,rrst;
output [datasize-:]data_out;
output empty,full; reg empty,full;
wire [datasize-:]data_out; wire [addrsize-:]raddr,waddr; //
wire [addrsize:]rbinnext,wbinnext,rptrnext,wptrnext;
wire empty_val,full_val;
reg [addrsize:]rbin,wbin,rptr,wptr,rptr1,rptr2,wptr1,wptr2;
reg [addrsize-:]memory[:(addrsize<<)-]; //双口RAM
assign data_out=memory[raddr];
always @(posedge wclk)
begin if(wen&&!full) memory[waddr]<=data_in;end //同步wptr指针
always @(posedge rclk or negedge rrst)
begin if(!rrst) {rptr2,rptr1}<=;
else {rptr2,rptr1}<={rptr1,wptr};
end //同步rptr指针
always @(posedge wclk or negedge wrst)
begin if(!wrst) {wptr2,wptr1}<=;
else {wptr2,wptr1}<={wptr1,rptr};
end //产生raddr信号和empty信号
always @(posedge rclk or negedge rrst)
begin if(!rrst) {rbin,rptr}<=;
else {rbin,rptr}<={rbinnext,rptrnext};
end
assign raddr=rbin[addrsize-:];
assign rbinnext=rbin+(ren&&~empty);
assign rptrnext=(rbinnext>>)^rbinnext; //生成raddr
assign empty_val=(rptrnext==rptr2);
always @(posedge rclk or negedge rrst)
begin if(!rrst) empty<=;
else empty<=empty_val;
end //产生waddr信号和full信号
always @(posedge wclk or negedge wrst)
begin if(!wrst) {wbin,wptr}<=;
else {wbin,wptr}<={wbinnext,wptrnext};
end
assign waddr=wbin[addrsize-:];
assign wbinnext=wbin+(wen&&~full);
assign wptrnext=(wbinnext>>)^wbinnext; //生成waddr
assign full_val=(wptrnext=={~wptr2[addrsize:addrsize-],wptr2[addrsize-:]});
always @(posedge wclk or negedge wrst)
begin if(!rrst) full<=;
else full<=full_val;
end
endmodule
Verilog学习笔记简单功能实现(八)...............异步FIFO的更多相关文章
- Verilog学习笔记简单功能实现(八)...............同步FIFO
Part 1,功能定义: 用16*8 RAM实现一个同步先进先出(FIFO)队列设计.由写使能端控制该数据流的写入FIFO,并由读使能控制FIFO中数据的读出.写入和读出的操作(高电平有效)由时钟的上 ...
- Verilog学习笔记简单功能实现(二)...............全加器
先以一位全加器为例:Xi.Yi代表两个加数,Cin是地位进位信号,Cout是向高位的进位信号.列表有: Xi Yi Cin Sum Cout 0 0 0 0 0 0 0 1 1 0 ...
- Verilog学习笔记简单功能实现(六)...............计数分频电路
在分频器电路中最重要的概念有两个:1)奇分频/偶分频:2)占空比. A)其中最简单的就是二分频电路,占空比为50%,其Verilog程序为 module half_clk(clr,clk_in,clk ...
- Verilog学习笔记简单功能实现(五)...............序列检测设计
这里采用夏宇闻教授第十五章的序列检测为例来学习; 从以上的状态转换图可以写出状态机的程序: module seqdet(x,out,clk,rst); input x,clk,rst; output ...
- Verilog学习笔记简单功能实现(三)...............同步有限状态机
在Verilog中可以采用多种方法来描述有限状态机最常见的方法就是用always和case语句.如下图所示的状态转移图就表示了一个简单的有限状态机: 图中:图表示了一个四状态的状态机,输入为A和Res ...
- Verilog学习笔记简单功能实现(一)...............D触发器
module D_flop(data,clk,clr,q,qb); input data,clk,clr; output q,qb; wire a,b,c,d,e,f,ndata,nclk; nand ...
- Verilog学习笔记简单功能实现(四)...............译码器和编码器
这里以简单的3-8译码器和8-3编码器为例: module decoder3_8(a,out); :]a; :]out; 'b1<<a;/*把最低位的1左移in位(根据in口输入的值)并赋 ...
- Verilog学习笔记简单功能实现(七)...............接口设计(并行输入串行输出)
利用状态机实现比较复杂的接口设计: 这是一个将并行数据转换为串行输出的变换器,利用双向总线输出.这是由EEPROM读写器的缩减得到的,首先对I2C总线特征介绍: I2C总线(inter integra ...
- IIC驱动学习笔记,简单的TSC2007的IIC驱动编写,测试
IIC驱动学习笔记,简单的TSC2007的IIC驱动编写,测试 目的不是为了编写TSC2007驱动,是为了学习IIC驱动的编写,读一下TSC2007的ADC数据进行练习,, Linux主机驱动和外设驱 ...
随机推荐
- 如何正确选择UI自动化测试
近年流行一个词-UI,和UI搭边好像都那么高大上,软件测试行业也不例外,比如UI自动化测试. 常见的UI自动化测试程序有哪些呢? l 带UI的Unit Test,比如mock掉底层代码,仅仅测试UI ...
- Android 在线SDK更新 和谐被墙解决
Failed to fetch URL https://dl-ssl.google.com/android/repository/addons_list-2.xml, reason: Connect ...
- cordova platform add specified version
cordova platform add specified version 命令格式 cordova platform add android@4.0 可用的版本 Valid install tar ...
- linux epoll模型使用注意点
1.默认使用的水平触发方式会多次触发回调函数,但是事实上这时并不需要回调,会浪费系统性能,就是在注册
- python入门学习课程推荐
最近在学习自动化,学习过程中,越来越发现coding能力的重要性,不会coding,基本不能开展自动化测试(自动化工具只是辅助). 故:痛定思痛,先花2个星期将python基础知识学习后,再进入自动化 ...
- OpenCascade BRep Format Description
OpenCascade BRep Format Description eryar@163.com 摘要Abstract:本文结合OpenCascade的BRep格式描述文档和源程序,对BRep格式进 ...
- hibernate(二)annotation第一个示例
一.在数据库中创建teacher表(数据库hibernate) create table teache( id int auto_increment primary key, name ), titl ...
- CSS字体
字体系列 [1]5种通用字体系列:拥有相似外观的字体系列 serif字体:字体成比例,且有上下短线,包括Times\Georgia\New century Schoolbook sans-serif字 ...
- PHP的学习--图解PHP引用
在一篇文章中看到关于PHP引用的图解,对于加深对PHP引用的理解很有帮助,在这里备份一下. 如果你对PHP的引用一点也不了解,可以先看我之前的博客:PHP的学习--PHP的引用
- IOS开发初步
由于工程实践项目的原因,得学习下IOS开发,今天才知道苹果09年才出的开发工具和开发包,也就是说,满打满算,现在顶多有5年IOS开发的工作经验.在我国2010年才火起来,因为那时候国内的iphone4 ...