verilog同步和异步FIFO,可直接仿真和综合
Verilog笔记.5.同步、异步

Verilog笔记.5.同步、异步在数字电路中经常有同步synchronism、异步asynchronism的概念。
异步指输⼊信号和时钟⽆关;同步指输⼊信号和时钟信号有关,实际上就是输⼊信号和时钟信号进⾏了与运算或者与⾮运算。
实际开发中,经常有同步清零、异步清零、同步复位、异步复位等概念,下⾯就给与相关代码演⽰。
简单的异步复位1always @ (posedge clk or negedge rst_n)2if(!rst_n) b <= 1'b0;3else b <= a;简单的同步复位1always @ (posedge clk)2if(!rst_n) b <= 1'b0;3else b <= a;PS:同步复位信号RST必须⾄少长于⼀个时钟周期CLK,否则,这个复位信号引起的变化是不会被检测到的!异步复位、同步释放1always @ (posedge clk)2 rst_nr <= rst_n; //现将异步复位信号⽤同步时钟打⼀拍34always @ (posedge clk or negedge rst_nr)5if(!rst_nr) b <= 1'b0;6else b <= a;78always @ (posedge clk or negedge rst_nr)9if(!rst_nr) c <= 1'b0;10else c <= b;同步复位和异步复位的区别就在于前者的复何信号不能出现在always语句的敏感信号表中,⽆论是同步复位还是异步复位,always语句的结构都是if(Reset)...else... ,否则,综合⼯具将不能正确的综合所有always语句中的赋值最好采⽤⾮阻塞赋值语,否则,可能会导致仿真与综合的不⼀致”。
verilog语言的综合与不可综合

Verilog的综合与不可综合综合说明编的代码可以对应出具体的电路,不可综合说明没有对应的电路结构。
不可综合的代码编译通过,只能看到输出,不能实现电路,就是不能用来制作具体的芯片。
一、基本Verilog中的变量有线网类型和寄存器类型。
线网型变量综合成wire,而寄存器可能综合成WIRE,锁存器和触发器。
二:verilog语句结构到门级的映射1、连续性赋值:assign连续性赋值语句逻辑结构上就是将等式右边的驱动左边的结点。
因些连续性赋值的目标结点总是综合成由组合逻辑驱动的结点。
Assign语句中的延时综合时都将忽视。
2、过程性赋值:过程性赋值只出现在always语句中。
阻塞赋值和非阻塞赋值就该赋值本身是没有区别的,只是对后面的语句有不同的影响。
建议设计组合逻辑电路时用阻塞赋值,设计时序电路时用非阻塞赋值。
过程性赋值的赋值对象有可能综合成wire,latch,和flip-flop,取决于具体状况。
如,时钟控制下的非阻塞赋值综合成flip-flop。
过程性赋值语句中的任何延时在综合时都将忽略。
建议同一个变量单一地使用阻塞或者非阻塞赋值。
3、逻辑操作符:逻辑操作符对应于硬件中已有的逻辑门4、算术操作符:Verilog中将reg视为无符号数,而integer视为有符号数。
因此,进行有符号操作时使用integer,使用无符号操作时使用reg。
5、进位:通常会将进行运算操作的结果比原操作数扩展一位,用来存放进位或者借位。
如:Wire [3:0] A,B;Wire [4:0] C;Assign C=A+B;C的最高位用来存放进位。
6、关系运算符:关系运算符:<,>,<=,>=和算术操作符一样,可以进行有符号和无符号运算,取决于数据类型是reg,net还是integer。
7、相等运算符:==,!=注意:===和!==是不可综合的。
可以进行有符号或无符号操作,取决于数据类型8、移位运算符:左移,右移,右边操作数可以是常数或者是变量,二者综合出来的结果不同。
异步FIFO的Verilog HDL设计

随 着 I 计 规 模 的不 断 扩 大 , 多 元 件 集 成 在 同 一 裸 片 C设 更 上 , 裸片尺寸越来越大 , 使 同步化设 计越 来越 困难 。一些新 的 方法 , 如整体异步局部同步( A S 结 构正在替代通 常的 同步 G L) 方法 J这样一个系统中就往往含 有多个时 钟 , , 不可避 免地要
维普资讯
旦丝堕窒 旦
文章编号 : 7 —14 (0 8 0 0 6 0 1 1 0 1 20 )3— 0 8— 2 6
仪 器仪表 用户
异步 F F 的 Vei gHD IO r o L设 计 l
蔡 发 志 ,苏 进 ,叶 兵
( 合肥 工业 大学 理学 院 , 肥 2 0 0 合 3 0 9)
通过 了验 证 。 关键 词 :亚稳 态 ;异步 时钟 域 ;同步 ; 雷 码 格
2 异 步设 计所产 生的 问题
2 1 亚 稳 态 .
中图分类号 : N 3 文献标识码 : T 42 B
Th eL ed sg fay c r n u I wi v rl h o
c m mu iat ewe feen lc oman gi C e in,Ths o nc e b t endi r tco kd isdi t I d sg al i t ss m a e n a alss a d rs rhf ra y c r n u F me he i k sa n y i n e eac o s n h o o s FIO m— or y,u ig gry c e oner a d dvdig t e d e s p c no sn a od p it s n ii n h a drs s a e it s m equ d a t odit g ih b t e ul n m py.Th e in i o a r nst si us ewe n fla d e n t e d sg s ba e n h ero HDL an u ge, d h e ut f s d o te v i g l l g a an te r s l o mo lsm s de i smuai n PGA eria i ot diae t e g e il i lt on a d F v ic t f on b h i c t hed sin i fasbe. n s Ke y wors: m ea t ly; a y c r o s lck do is; s n hr— d tsabl i t s n hon u co man y c o nz ie;Gry c e a od
verilog之可综合与不可综合

verilog之可综合与不可综合可综合的意思是说所编写的代码可以对应成详细的,不行综合就是所写代码没有对应的电路结构,例如行为级语法就是一种不行综合的代码,通常用于写测试文件。
建立可综合模型时,需注重以下几点:不用法initial不用法10之类的延时语句不用法循环次数不确定的循环语句,如forever,while等不用法用户自定义原语(UDP元件)尽量用法同步方式设计电路用always块来描述组合规律时,应列出全部输入信号作为敏感信号列表,即always@(*)全部的内部寄存器都应当能够被复位,在用法实现设计时,尽量用法器件的全局复位端作为系统的总复位对时序规律描述和建模,尽量用法非堵塞赋值的方式,对组合规律描述和建模,虽然堵塞和非堵塞赋值的方式都可以,但在同一过程快中最好不要同时用法堵塞赋值和非堵塞赋值。
我个人比较推举用堵塞赋值的方式描述组合规律不能在多个always块中对同一个变量举行赋值。
对同一个对象不能既用法非堵塞赋值,又用法堵塞赋值假如不决定让变量生成锁存器,那么必需在用法if语句或case语句时补全全部条件不行综合语句:initial 初始化语句,只能在testbench中用法,不行综合event event在同步testbench时更实用,不能综合real 不支持real数据类型的综合time 不支持time数据类型的综合assign 和 deassign 不支持对reg数据类型赋值的综合,但支持wire类型赋值的综合以开始的延时语句不能被综合verilog是一种硬件描述语言,我们在写verilog 代码时,首先要有所要写的module在硬件上如何实现的概念,而不是去想编译器如何说明这个module。
比如在打算是否用法 reg 定义时,要问问自己物理上是不是真正存在这个 register, 假如是,它的clock 是什么? D 端是什么?Q 端是什么?有没有清零和置位?同步还是异步?再比如上面研究的三态输出问题,首先想到的应当是在 register 的输出后面加一个三态门,而不是如何才干让编译器知道要“赋值”给一个信号为三态。
verilog基本电路设计(包括:时钟域同步、无缝切换、异步fifo、去抖滤波))

Verilog基本电路设计(包括:时钟域同步、无缝切换、异步FIFO、去抖滤波))Verilog基本电路设计共包括四部分:单bit跨时钟域同步时钟无缝切换异步FIFO去抖滤波Verilog基本电路设计之一: 单bit跨时钟域同步(帖子链接:/thread-605419-1-1.html)看到坛子里不少朋友,对于基本数字电路存在这样那样的疑惑,本人决定开贴,介绍数字电路最常见的模块单元,希望给初学者带来帮助,也欢迎大佬们前来拍砖。
如果想要做数字设计,下面这些电路是一定会碰到的,也是所有大型IP,SOC设计必不可少的基础,主要包括异步信号的同步处理,同步FIFO,异步FIFO,时钟无缝切换,信号滤波debounce等等,后面会根据大家反馈情况再介绍新电路。
首先介绍异步信号的跨时钟域同步问题。
一般分为单bit的控制信号同步,以及多bit的数据信号同步。
多bit的信号同步会使用异步FIFO完成,而单bit的信号同步,又是时钟无缝切换电路以及异步FIFO电路的设计基础,这里先介绍单bit信号同步处理。
clka域下的信号signal_a,向异步的clkb域传递时,会产生亚稳态问题。
所有的亚稳态,归根结底就是setup/hold时间不满足导致。
在同一个时钟域下的信号,综合以及布线工具可以在data路径或者clock路径上插入buffer使得每一个DFF的setup/hold时间都满足;但是当signal_a在clkb域下使用时,由于clka与clkb异步,它们的相位关系不确定,那么在clkb的时钟沿到来时,无法确定signal_a此时是否处于稳定无变化状态,也即setup/hold时间无法确定,从而产生亚稳态。
这种异步信号在前后端流程里面是无法做时序分析的,也就是静态时序分析里常说的false_path。
消除亚稳态,就是采用多级DFF来采样来自另一个时钟域的信号,级数越多,同步过来的信号越稳定。
对于频率很高的设计,建议至少用三级DFF,而两级DFF同步则是所有异步信号处理的最基本要求。
verilog同步和异步FIFO,可直接仿真和综合解读

EDA/SOPC课程设计报告题目:同异步FIFO模块的设计与验证姓名:xxx学号:120260320同组人:xxx指导教师:xxx成绩:目录目录 (II)第1章课程设计的要求 (1)1.1 课程设计的目的 (1)1.2 课程设计的条件 (1)1.3 课程设计的要求 (1)第2章课程设计的内容 (2)2.1 设计思路 (2)2.2 软件流程图 (2)2.3 HDL代码阐述 (2)2.4 ModelSim验证 (2)第3章课程设计的心得 (3)第1章课程设计的要求1.1 课程设计的目的●掌握FIFO设计的基本原理与方法●培养Verilog语言模块化设计的思想意识●完成一个FIFO的设计与验证●掌握较大工程的基本开发技能●培养综合运用Modelsim工具进行硬件开发的能力●培养数字系统设计的基本能力●加强对课堂Verilog语言学习的理解与升华1.2 课程设计的条件●设计条件ISE、Modelsim等开发软件的使用1.3 课程设计的要求●设计要求1 设计同步FIFO并验证(包括仿真验证、FPGA验证)●设计要求2 设计异步FIFO并验证(包括仿真验证、FPGA验证)●设计要求3 采用Design Compiler完成其逻辑综合,评估其面积和时序●设计要求4 完成综合后的SDF反标仿真第2章课程设计的内容2.1 设计思路FIFO(First Input First Output),即先进先出队列。
在计算机中,先入先出队列是一种传统的按序执行方法,先进入的指令先完成并引退,跟着才执行第二条指令(指令就是计算机在响应用户操作的程序代码,对用户而言是透明的)。
如下图所示,当CPU在某一时段来不及响应所有的指令时,指令就会被安排在FIFO队列中,比如0号指令先进入队列,接着是1号指令、2号指令……当CPU完成当前指令以后就会从队列中取出0号指令先行执行,此时1号指令就会接替0号指令的位置,同样,2号指令、3号指令……都会向前挪一个位置,这样解释大家清楚了吧?在设计之初,我们只对FIFO有一个模糊的了解,只知道它是一个先入先出的队列,但是对于它是如何组成和如何工作并不了解,于是我们设计的首要任务就是查阅资料,逐步完善我们对于同步FIFO和异步FIFO的了解。
Verilog语言的可综合性

V e r i l o g 语言的可综合性可综合的Verilog HDL 语句都是V e r i l o g H D L 标准( I E E E 1 3 6 4 ) 的一个子集,并且因所用工具不同而异。
在设计中不能采用不可综合的语句( 测试代码除外) 。
下面我们讨论一下大部分综合工具都支持的语句,具体到某种工具的特性还要查看说明文档。
对于数据类型、运算符、赋值语句、基本门级元件等的可综合性问题,因为都有固定的规定,这里就不多讨论了。
组合逻辑和时序逻辑的可综合性: 用a s s i g n 语句对w i r e 型变量进行赋值,综合后的结果是组合逻辑电路。
用a l w a y s @ ( 电平敏感变量表) ,即电平敏感的a l w a y s 块描述的电路综合后的结果是组合逻辑电路或电平敏感的锁存器,此时,a l w a y s 块内赋值语句左边的变量是r e g或i n t e g e r 型,块中要避免组合反馈回路,每次执行a l w a y s 块时,在生成组合逻辑的a l w a y s 块中被赋值的所有信号必须都在敏感电平列表中列出,否则在综合时将会为没有列出的信号隐含的产生一个透明的锁存器,这时综合后的电路已不是纯组合电路了。
用a l w a y s @( p o s e d g e c l o c k ) 或a l w a y s @ ( n e g e d g e c l o c k ) 块描述的电路综合为同步时序逻辑电路,设计同步时序逻辑电路的关键是建立描述该电路状态转移的可综合的有限状态机模型,在V e r i l o g H D L语言中最常用的描述同步时序状态机的结构是a l w a y s 和块内的c a s e . i f 语句,除了紧跟在a l w a y s 后的@( p o s e d g e c l o c k ) , @ ( n e g e d g e c l o c k ) 外,a l w a y s 块中不允许其他的@ ( e v e n t ) 语句,目前大多数综合工具不能综合V e r i l o g H D L描述的异步状态机,所以用V e r i l o g 设计的时序电路应该是同步时序电路。
怎么用Verilog语言描述同步FIFO和异步FIFO

怎么⽤Verilog语⾔描述同步FIFO和异步FIFO感谢知乎龚⼤佬打杂⼤佬⽹上⼏个nice的博客(忘了是哪个了。
)前⾔虽然FIFO都有IP可以使⽤,但理解原理还是⾃⼰写⼀个来得透彻。
什么是FIFO?Fist in first out。
先⼊先出的数据缓存器,没有外部读写地址线,可同时读写。
规则:永远不要写⼀个已经写满了的fifo。
永远不要读⼀个读空了的fifo。
FIFO种类?同步FIFO和异步FIFO。
同步FIFO只有⼀个时钟,也就是说写端和读端的时钟是⼀⽑⼀样的。
异步FIFO读端和写端两个时钟则是不⼀样的。
包括同频异相,异频异相。
FIFO⽤途?1. 数据缓冲器。
⽐如你写端burst⼀个数据,没有fifo缓冲的话就炸了。
Fifo会把写端的突发数据吃到肚⼦⾥,读端可以慢慢的⼀个个读出来。
2. 跨时钟域。
异步fifo主要使⽤在不同时钟域的边缘,⽤来同步数据到另⼀个时钟域。
3.ALTERA FIFO IP 的缺点是什么?虽然altera贴⼼的提供了FIFO的IP块,但是对于可移植性与⾃定义位宽深度更好的话,还是⾃⼰写的更佳。
FIFO深度如何计算?(避免溢出)对于异步fifo,如果读时钟⼤于写时钟且每个周期读写,那么⼀定是会读空的,反之⼀定会被写满。
⼀般来说,不会设计这么⽆聊的东西。
假设写端有突发的数据,⽽读端是均匀的读出,怎么保证fifo不溢出呢?异步FIFO快转慢的问题:可能采样踩不到某些值。
同步FIFO:当缓冲器使⽤,可以⽤ram资源搭。
原理图:信号定义:clk:时钟信号rst_n:异步复位信号wr:写请求rd:读请求data:数据输⼊q:数据输出full:满信号,表⽰fifo吃饱了empty:空信号,表⽰fifo肚⼦已经空掉了usedw:表⽰fifo中已有的数据个数仿真:没有usedw款:有usedw款:资源使⽤量:如何设计⼀个异步FIFO?⼀般⽤作跨时钟域,可⽤ram搭。
判断读空与写满,读写指针要跨时钟域,所以采⽤格雷码减少亚稳态。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
EDA/SOPC课程设计报告题目:同异步FIFO模块的设计与验证姓名:xxx学号:120260320同组人:xxx指导教师:xxx成绩:目录目录 (II)第1章课程设计的要求 (1)1.1 课程设计的目的 (1)1.2 课程设计的条件 (1)1.3 课程设计的要求 (1)第2章课程设计的内容 (2)2.1 设计思路 (2)2.2 软件流程图 (3)2.3 HDL代码阐述 (7)2.4 ModelSim验证 (13)第3章课程设计的心得 (21)第1章课程设计的要求1.1 课程设计的目的●掌握FIFO设计的基本原理与方法●培养Verilog语言模块化设计的思想意识●完成一个FIFO的设计与验证●掌握较大工程的基本开发技能●培养综合运用Modelsim工具进行硬件开发的能力●培养数字系统设计的基本能力●加强对课堂Verilog语言学习的理解与升华1.2 课程设计的条件●设计条件ISE、Modelsim等开发软件的使用1.3 课程设计的要求●设计要求1 设计同步FIFO并验证(包括仿真验证、FPGA验证)●设计要求2 设计异步FIFO并验证(包括仿真验证、FPGA验证)●设计要求3 采用Design Compiler完成其逻辑综合,评估其面积和时序●设计要求4 完成综合后的SDF反标仿真第2章课程设计的内容2.1 设计思路FIFO(First Input First Output),即先进先出队列。
在计算机中,先入先出队列是一种传统的按序执行方法,先进入的指令先完成并引退,跟着才执行第二条指令(指令就是计算机在响应用户操作的程序代码,对用户而言是透明的)。
如下图所示,当CPU在某一时段来不及响应所有的指令时,指令就会被安排在FIFO队列中,比如0号指令先进入队列,接着是1号指令、2号指令……当CPU完成当前指令以后就会从队列中取出0号指令先行执行,此时1号指令就会接替0号指令的位置,同样,2号指令、3号指令……都会向前挪一个位置,这样解释大家清楚了吧?在设计之初,我们只对FIFO有一个模糊的了解,只知道它是一个先入先出的队列,但是对于它是如何组成和如何工作并不了解,于是我们设计的首要任务就是查阅资料,逐步完善我们对于同步FIFO和异步FIFO的了解。
在前两天的工作当中,我们查阅了中外各类资料和文献,对FIFO的组成和工作原理有了深入的了解,最终决定以老师给的两篇《Simulation and Synthesis T echniques for Asynchronous FIFO Design》和《Simulation and Synthesis Techniques for Asynchronous FIFO Design with Asynchronous Pointer Comparisons》为学习和参考的重要资料完成本次的课程设计。
在两天的研究中,我们敲定异步FIFO的整体设计原理图如下:在懂得设计模块之后,我们接下来就要逐步编写每个子模块的程序。
并且在写完每个子模块的设计之后,我们为了验证的方便起见,要求验证FIFO在每个时钟沿自动完成数据从0到15的自增一,观察当数据写满深度为15的FIFO之后能否自动产生”写满“信号并且自动开始”读模式“,在读的状态,关键步骤就是验证是否在读空之后不再继续读。
当然,这也是FIFO设计的关键,如何在写满的时候不让外界继续对FIFO继续写入,在读空的时候如何让FIFO不再继续读,在这方面的程序设计中我们走了很多的弯路,最终在两篇重要的论文中找到了解决问题的方式,在写自己代码的时候我们也参考了文章中的代码,感到受益匪浅!2.2 软件流程图一:同步FIFO设计流程图:二:异步FIFO设计流程图1) FIFOMEMORY部分2)sync_r2w 部分3) sync_w2r部分4)wptr_full部分5)rptr_empty部分6) 主模块afifo部分因为这一部分就是将前几部分联系成一个整体,因此无需再画这部分流程图。
2.3 HDL代码阐述1)同步FIFO设计代码:`define DEL 1module synfifo(clock,reset_n,data_in,read_n,write_n,data_out,full,empty);input clock,reset_n,read_n,write_n;input [0:7] data_in;output [0:7] data_out;output full,empty;wire clock,reset_n,read_n,write_n;wire [0:7] data_in;reg [0:7] data_out;wire full,empty;//?reg[7:0] fifo_mem[14:0];reg [3:0] counter;reg[3:0] rd_pointer;reg[3:0] wr_pointer;assign #`DEL full=(counter==15)?1'b1:1'b0;//当计数值为15时代表已经满了assign #`DEL empty=(counter==0)?1'b1:1'b0;//当计数值为0的时候代表空了always @(posedge clock or negedge reset_n)beginif(~reset_n)//复位状态begin#`DEL;rd_pointer<=4'b0;wr_pointer<=4'b0;counter<=4'b0;data_out<=8'b0;endelse if(~read_n)//读信号有效beginif(counter==0)begin$display("\nERROR at time %0t:",$time);$display("\FIFO Underflow\n");$stop;endif(write_n)//只读不写begincounter<=counter-1;enddata_out<=#`DEL fifo_mem[rd_pointer];//数据读出if(rd_pointer==14)rd_pointer<= #`DEL 4'b0;elserd_pointer<=rd_pointer+1;endelse if(~write_n)//写状态有效beginif(counter==15)begin$display("\nERROR at time %0t:",$time);$display("FIFO Overflow\n");$stop;endif(read_n)//只写不读begincounter<=#`DEL counter+1;endfifo_mem[wr_pointer]<=#`DEL data_in;//数据写入if(wr_pointer==14)wr_pointer<=#`DEL 4'b0;elsewr_pointer<=#`DEL wr_pointer+1;endendendmodule2)异步FIFO设计:1、 FIFOmemory部分:module fifomem(rdata,wdata,waddr,raddr,wclken,wfull,wclk,rrst_n,rinc,rempty,rclk);input[7:0]wdata;input[3:0]waddr,raddr;input wclken,wfull,wclk,rrst_n,rinc,rempty,rclk;output[7:0]rdata;reg[7:0]rdata;reg[7:0]mem[0:15];always@(posedge rclk or negedge rrst_n)if(!rrst_n)rdata<=8'b0;else if(rinc&&!rempty)//读有效并且没空rdata<=mem[raddr];//数据读出always@(posedge wclk)if(wclken&&!wfull)//写有效并且没满mem[waddr]<=wdata;endmodule3) sync_r2w部分:module sync_r2w(wq2_rptr,rptr,wq1_rptr,wclk,wrst_n);input[4:0]rptr;input wclk,wrst_n;output [4:0] wq1_rptr,wq2_rptr;reg [4:0] wq1_rptr,wq2_rptr;always@(posedge wclk or negedge wrst_n)//这部分进行写地址到到读地址的同步if(!wrst_n){wq2_rptr,wq1_rptr}<=0;else{wq2_rptr,wq1_rptr}<={wq1_rptr,rptr};endmodule4) sync_w2r部分:module sync_w2r(rq2_wptr,wptr,rq1_wptr,rclk,rrst_n);input[4:0]wptr;input rclk,rrst_n;output [4:0] rq1_wptr,rq2_wptr;reg [4:0] rq1_wptr,rq2_wptr;always@(posedge rclk or negedge rrst_n)//读地址到写地址的同步if(!rrst_n){rq2_wptr,rq1_wptr}<=0;else{rq2_wptr,rq1_wptr}<={rq1_wptr,wptr};Endmodule5) wptr_full部分:module wptr_full(wfull,waddr,wbin,wptr,wq2_rptr,winc,wclk,wrst_n);input wrst_n,wclk,winc;input [4:0]wq2_rptr;output [3:0]waddr;output [4:0]wptr;output wfull;output[4:0]wbin;reg wfull;reg [4:0]wptr;reg[4:0]wbin;wire[4:0]wgraynext,wbinnext;always@(posedge wclk or negedge wrst_n)//转化成格雷码进行比较if(!wrst_n)beginwbin<=5'b0;wptr<=5'b0;endelsebeginwbin<=wbinnext;wptr<=wgraynext;endassign waddr=wbin[3:0];assign wbinnext=wbin+(winc&!wfull);assign wgraynext=(wbinnext>>1)^wbinnext;assign wfull_val = (wgraynext =={!wq2_rptr[4:3],wq2_rptr[2:0]});//如果高两位不同,低3位相同那么写满标志有效always @(posedge wclk or negedge wrst_n)if (!wrst_n)wfull <= 1'b0;elsewfull <= wfull_val;endmodule6) rptr_empty部分:module rptr_empty(rempty,raddr,rbin,rptr,rq2_wptr,rinc,rclk,rrst_n);input rrst_n,rclk,rinc;input [4:0]rq2_wptr;output [3:0]raddr;output [4:0]rptr;output rempty;output[4:0]rbin;reg rempty;reg [4:0]rptr;reg[4:0]rbin;wire[4:0]rgraynext,rbinnext;always@(posedge rclk or negedge rrst_n)if(!rrst_n)beginrbin<=5'b0;rptr<=5'b0;endelsebeginrbin<=rbinnext;rptr<=rgraynext;endassign raddr=rbin[3:0];assign rbinnext=rbin+(rinc&!rempty);assign rgraynext=(rbinnext>>1)^rbinnext;assign rempty_val = (rgraynext == rq2_wptr)?1'b1:1'b0;//均相同时则为空有效always @(posedge rclk or negedge rrst_n)if (!rrst_n)rempty <= 1'b1;elserempty <= rempty_val;endmodule7) afifo部分:module afifo(output [7:0] rdata,output wfull,output rempty,input [7:0] wdata,input winc, wclk, wrst_n,input rinc, rclk, rrst_n);wire [3:0] waddr, raddr;wire [4:0] wptr, rptr, wq2_rptr, rq2_wptr;//每个模块的每个信号都需要例化sync_r2w sync_r2w(.wq2_rptr(wq2_rptr), .rptr(rptr),.wclk(wclk), .wrst_n(wrst_n));sync_w2r sync_w2r(.rq2_wptr(rq2_wptr), .wptr(wptr),.rclk(rclk), .rrst_n(rrst_n));fifomem fifomem(.rdata(rdata), .wdata(wdata),.waddr(waddr), .raddr(raddr),.wclken(winc), .wfull(wfull),.wclk(wclk),.rrst_n(rrst_n),.rinc(rinc),.rempty(rempty),.rclk(rclk));rptr_empty rptr_empty(.rempty(rempty),.raddr(raddr),.rbin(rbin),.rptr(rptr), .rq2_wptr(rq2_wptr),.rinc(rinc), .rclk(rclk),.rrst_n(rrst_n));wptr_full wptr_full(.wfull(wfull), .waddr(waddr),.wbin(wbin),.wptr(wptr), .wq2_rptr(wq2_rptr),.winc(winc), .wclk(wclk),.wrst_n(wrst_n));endmodule2.4 ModelSim验证一、同步FIFO1、HDL验证语言:`define DEL 10module syn_tb;reg clock,reset_n,read_n,write_n;reg [7:0] in_data;wire [7:0] out_data;wire full,empty;integer fifo_count;reg [7:0] exp_data;reg fast_read,fast_write;reg filled_flag;reg cycle_count;synfifosynfifo_tb(.clock(clock),.reset_n(reset_n),.data_in(in_data),.read_n(read_n),.write_n(write_n),.data_out(out_data),.full(full),.empty(empty));initialbeginin_data=0;exp_data=0;fifo_count=0;read_n=1;write_n=1;filled_flag=0;cycle_count=0;clock=1;fast_read=0;fast_write=1;reset_n=1;#20 reset_n=0;#20 reset_n=1;if(empty!==1)begin$display("\nerror at time %0t:",$time);$display("after reset,empty status not asserted\n");$stop;endif(full!==0)begin$display("\nerror at time %0t:",$time);$display("\nerror at time %0t:",$time);$stop;endendalways #100 clock=~clock;always @(posedge clock)beginif(~write_n && read_n)fifo_count=fifo_count+1;else if(write_n && ~read_n)fifo_count=fifo_count-1;endalways @(negedge clock)beginif(~read_n && (out_data!==exp_data))begin$display("\nerror at time %0t:",$time);$display("expected data ut=%h",exp_data);$display("actual data ut=%h\n",out_data);$stop;endif((fast_write&&(cycle_count&1'b1))&&~full)//?beginwrite_n=0;in_data=in_data+1;endelsewrite_n=1;if((fast_read&&(cycle_count&1'b1))&&~empty)//?beginread_n=0;exp_data=exp_data+1;endelseread_n=1;if(full)beginfast_read=1;fast_write=0;filled_flag=1;endif(filled_flag&&empty)begin$display("\nsimulation complete -no errors\n");$finish;endcycle_count=cycle_count+1;endalways@(fifo_count)begin# `DEL;# `DEL;# `DEL;case (fifo_count)0:beginif((empty!==1)||(full!==0))begin$display("\nerror at time %0t:",$time);$display("fifo_count=%h",fifo_count);$display("empty=%h\n",empty);$display("full=%h\n",full);$stop;endif(filled_flag==1)begin$display("\nsimulation complete -no error\n");$finish;endend15:beginif((empty!==0)||(full!==1))begin$display("\nerror at time %0t:",$time);$display("fifo_count=%h",fifo_count);$display("empty=%h\n",empty);$display("full=%h\n",full);$stop;endfilled_flag=1;fast_write=0;fast_read=1;enddefault:beginif((empty!==0)||(full!==0))begin$display("\nerror at time %0t:",$time);$display("fifo_count=%h",fifo_count);$display("empty=%h\n",empty);$display("full=%h\n",full);$stop;endendendcaseendinitial begin$fsdbdumpfile("sfifo.fsdb");$fsdbdumpvars();endendmodule2、仿真波形:3、说明当写FIFO的时候,一个上升的时钟沿一来,并且写信号有效,读信号无效时,数据逐个写入FIFO存储器中。