Verilog学习笔记简单功能实现(八)...............同步FIFO

Part 1,功能定义:

用16*8 RAM实现一个同步先进先出(FIFO)队列设计。由写使能端控制该数据流的写入FIFO,并由读使能控制FIFO中数据的读出。写入和读出的操作(高电平有效)由时钟的上升沿触发。当FIFO的数据满和空的时候分别设置相应的高电平加以指示。FIFO是英文First In First Out 的缩写,是一种先进先出的数据缓存器,它与普通存储器的区别是没有外部读写地址线,这样使用起来非常简单,但缺点就是只能顺序写入数据,顺序的读出数据,其数据地址由内部读写指针自动加1完成,不能像普通存储器那样可以由地址线决定读取或写入某个指定的地址。

所谓同步FIFO是指读时钟和写时钟采用同一个时钟。同时,异步FIFO就是指读写时钟不一致。

Part 2.顶层信号定义: 


信号名称


I/O


功能描述


源/目标


备注


Rst


In


全局复位(低有效)


管脚


Clk


In


全局时钟


管脚


频率10Mhz;占空比:50%


W_en


In


高有效写使能


管脚


R_en


In


高有效读使能


管脚


Data_in[7:0]


In


数据输入端


管脚


Data_out[7:0]


Out


数据输出端


管脚


Empty


Out


空指示信号


管脚


为高时表示fifo空


Full


Out


满指示信号


管脚


为高时表示fifo满

Part 3.顶层模块即划分: 

该同步fifo可划分为如下四个模块,如图所示:

①存储器模块(RAM)    ——用于存放及输出数据;

②读地址模块(r_addr)  ——用于读地址的产生;

③写地址模块(w_addr)——用于写地址的产生

④标志模块(flag_gen) ---- 用于产生FIFO当前空满状态。

Part 4.RAM块: 

RAM块的源码

本设计中采用16*8的双扣RAM,以循环读写的方式实现。

根据r_addr模块产生的读地址在,读使能(ren==1)时,将r_addr[4:0]地址中的对应单元的数据在时钟上升沿到来时,读出到data_out[7:0]中;

根据w_addr模块产生的写地址,在写实能(wen==1)时,在时钟沿的上升沿到来时,将data_in[7:0]中的数据写入到w_addr[4:0]地址对应的单元。

 1 //16*8 RAM define (七个端口)
 2 module RAM(clk,ren,wen,r_addr,w_addr,data_in,data_out);
 3   input clk,ren,wen;
 4   input [4:0]r_addr,w_addr;
 5   input [7:0]data_in;
 6   output [7:0]data_out;
 7   reg [7:0]data_out;
 8   reg [7:0]fifo[15:0];
 9   always @(posedge clk)
10   begin
11   if(ren==1)
12   begin data_out<=fifo[r_addr]; end
13   end
14   always @(posedge clk)
15   begin
16   if(wen==1)
17   begin fifo[w_addr]<=data_in; end
18   end
19 endmodule

Part 5.r_addr产生块:

该模块用于产生FIFO读数据时所用的地址。由于16个RAM单元可以用4位地址线寻址。本模块用5位计数器(rd_addr[4:0])实现读地址的产生。

在复位时(rst=0),读地址值为0。

如果FIFO未空(~empty)且有读使能(r_en)有效,则r_addr[4:0]加1;否则不变。

 1 //read address genaration
 2 module r_addr_gen(clk,rst,ren,r_addr,empty);
 3   input clk,rst,ren,empty;
 4   output [4:0]r_addr;
 5   reg [4:0]r_addr;
 6   always @(posedge clk)                //negedge rst can be here to make it asynchronous
 7   begin
 8   if (!rst) begin r_addr<=5‘b00000; end
 9     else if(ren==1&&empty==0) begin r_addr<=r_addr+1;end
10       else begin r_addr<=5‘b00000;  end
11   end
12 endmodule

Part 6.w_addr产生块:

该模块用于产生FIFO写数据时所用的地址。由于16个RAM单元可以用4位地址线寻址。

在复位时(rst=0),写地址值为0。

如果FIFO未满(~full)且有写使能(w_en)有效,则w_addr[4:0]加1;否则不变。

 

 1 //write address genaration
 2 module w_addr_gen(clk,rst,wen,w_addr,full);
 3   input clk,rst,wen,full;
 4   output [4:0]w_addr;
 5   reg [4:0]w_addr;
 6   always @(posedge clk)                //negedge rst can be here to make it asynchronous
 7   begin
 8   if (!rst) begin w_addr<=5‘b00000; end
 9     else if(wen==1&&full==0) begin w_addr<=w_addr+1;end
10       else begin w_addr<=5‘b00000;  end
11   end
12 endmodule

Part 7.空满标志产生块: 

flag_gen模块产生FIFO空满标志。本模块设计并不用读写地址判定FIFO是否空满。设计一个计数器,该计数器(pt_cnt)用于指示当前周期中FIFO中数据的个数。由于FIFO中最多只有16个数据,因此采用5位计数器来指示FIFO中数据个数。具体计算如下:

1)复位的时候,count=0;

2)如果w_en和r_en同时有效的时候,count不加也不减;表示同时对FIFO进行读写操作的时候,FIFO中的数据个数不变。

3)如果w_en有效且full=0,则count+1;表示写操作且FIFO未满时候,FIFO中的数据个数增加了1;

4)如果r_en有效且empty=0,则count-1; 表示读操作且FIFO未满时候,FIFO中的数据个数减少了1;

5)如果count=0的时候,表示FIFO空,需要设置empty=1;如果count=16的时候,表示FIFO现在已经满,需要设置full=1。

 1 //empty and full flag gennaration
 2 module flag_gen(clk,rst,ren,wen,empty,full);
 3   input clk,ren,wen,rst;
 4   output empty,full;
 5   reg empty,full;
 6   reg [4:0]count;
 7   parameter max=5‘b01111;
 8
 9   always @(posedge clk)
10   begin
11   if(!rst) begin count<=0;end
12     else case({ren,wen})
13          2‘b00: count<=count;
14          2‘b01: if(count!=max) count<=count+1;
15          2‘b10: if(count!=5‘b0)count<=count-1;
16          2‘b11: count<=count;
17          default:count<=count;
18          endcase
19   end
20
21   always @(count)
22   begin
23   if (count==max) full<=1;
24     else full<=0;
25   end
26
27   always @(count)
28   begin
29   if (count==5‘b0) empty<=1;
30     else empty<=0;
31   end
32 endmodule
时间: 2024-08-27 00:46:42

Verilog学习笔记简单功能实现(八)...............同步FIFO的相关文章

Verilog学习笔记简单功能实现(六)...............计数分频电路

在分频器电路中最重要的概念有两个:1)奇分频/偶分频:2)占空比. A)其中最简单的就是二分频电路,占空比为50%,其Verilog程序为 1 module half_clk(clr,clk_in,clk_out,out2); 2 input clr,clk_in; 3 output clk_out,out2; 4 reg clk_out,out2; 5 6 always @(posedge clk_in) 7 begin 8 if (clr==0) begin clk_out=0; out2=

Verilog学习笔记简单功能实现(四)...............译码器和编码器

这里以简单的3-8译码器和8-3编码器为例: module decoder3_8(a,out); input [2:0]a; output [7:0]out; assign out=1'b1<<a;/*把最低位的1左移in位(根据in口输入的值)并赋予out*/ endmodule 8-3编码器程序: 1)利用for循环 1 module encoder8_3(a,out,none_on); 2 input [7:0]a; 3 output [2:0]out; 4 output none_on

jQuery源码学习笔记五 六 七 八 转

jQuery源码学习笔记五 六 七 八 转 Js代码   <p>在正式深入jQuery的核心功能选择器之前,还有一些方法,基本都是数组方法,用于遴选更具体的需求,如获得某个元素的所有祖选元素啦,等等.接着是其缓存机制data.</p> <pre class="brush:javascript;gutter:false;toolbar:false"> //@author  司徒正美|なさみ|cheng http://www.cnblogs.com/ru

Redis学习笔记(简单了解与运行)

Redis学习笔记(简单了解与运行) 开源的非关系型数据库 是REmote Dictionary Server(远程字典服务器)的缩写,以字典结构存储数据 允许其他应用通过TCP协议读写字典中的内容. Redis支持存储的键值数据类型 字符串类型 散列类型 列表类型 集合类型 有序集合类型 Redis的特性 通过一个列子看出Mysql和Redis的存储区别 例如: (存储一篇文章,文章包括:标题(title),正文(content),阅读量(views),标签(tags)) 需求: 把数据存储在

树莓派学习笔记——GPIO功能学习

树莓派学习笔记——GPIO功能学习

Linux程序设计学习笔记----多线程编程之线程同步之条件变量

转载请注明出处:http://blog.csdn.net/suool/article/details/38582521. 基本概念与原理 互斥锁能够解决资源的互斥访问,但是在某些情况下,互斥并不能解决问题,比如两个线程需 要互斥的处理各自的操作,但是一个线程的操作仅仅存在一种条件成立的情况下执行,一旦错过不可再重现,由于线程间相互争夺cpu资源,因此在条件成立的时候,该线程不一定争夺到cpu而错过,导致永远得不到执行..... 因此需要某个机制来解决此问题,更重要的是,线程仅仅只有一种情况需要执

Dynamic CRM 2013学习笔记(三十八)流程1 - 操作(action)开发与配置详解

CRM 2013 里流程有4个类别:操作(action).业务流程(business process flow).对话(dialog)和工作流(workflow).它们都是从 setting –> Process 进入,然后点击New按钮来创建: 这篇主要介绍操作:什么是操作.什么时候使用操作.如何创建以及如何调用 一.什么是操作 操作是CRM 2013 新增加的一个功能,用来扩展系统的标准功能.业务人员可以用它来实现业务逻辑,然后开发人员可以在系统事件里(比如update,create)来使用

Dynamic CRM 2013学习笔记(二十八)用JS动态设置字段的change事件、必填以及可见

我们知道通过界面设置字段的change事件,是否是必填,是否可见非常容易.但有时我们需要动态地根据某些条件来设置,这时有需要通过js来动态地控制了. 下面分别介绍如何用js来动态设置.   一.动态设置字段的change事件 // form on load event function onLoad() { init();   pageAttr.delivery_from.addOnChange(deliveryFromChange); pageAttr.type.addOnChange(typ

## vue学习笔记--简单父子组件--

## vue学习笔记 ### 组件之间的通讯1. 父组件到子组件```js //father <div> <son msg="父组件的信息写在这"></son> <son title="title"></son> <!--:title--> </div> <script> export default { data(){ return { title: '当传递一个变量过