同步fifo设计

这篇文章主要介绍一下同步fifo用verilog实现。首先介绍一下fifo的相关知识。

fifo是 first input first output 的缩写,即先进先出队列,fifo一般用作不同时钟域的缓冲器。fifo根据读和写的时钟是否为同一时钟分为同步fifo和异步fifo。异步fifo相比同步fifo来说,设计更加复杂一点。本文中先讲同步fifo的一种设计方法。下图是同步fifo的结构图:


设计fifo的时候一般需要考虑的有两点:

1.fifo的大小

 fifo的大小指就是双端口ram的大小,这个可以根据设计需要来设置。

2.fifo空满状态的判断

 fifo空满状态的判断通常有两种方法。

  a、fifo中的ram一般是双端口ram,所以有独立的读写地址。因此可以一种是设置读,写指针,写指针指向下一个要写入数据的地址,读指针指向下一个要读的地址,最后通过比较读指针和写指针的大小来确定空满状态。

 b、设置一个计数器,当写使能有效的时候计数器加一;当读使能有效的时候,计数器减一,将计数器与ram的size进行比较来判断fifo的空满状态。这种方法设计比较简单,但是需要的额外的计数器,就会产生额外的资源,而且当fifo比较大时,会降低fifo最终可以达到的速度。

下面的设计是将fifo当做一个整体来进行设计,输入输出端口有clk,rst,data_in,data_out,wr_en,rd_en,empty,full,利用verilog进行设计,代码如下:

module fifo(clk,rst,wr_en,rd_en,data_in,data_out,empty,full);
input clk,rst;
input wr_en,rd_en;
input  [7:0]data_in;//输入数据
output [7:0]data_out;//输出数据
output empty,full;//空满标志

wire    empty,full;
reg    [7:0]data_out;  

reg    [7:0] ram[15:0];//dual port RAM
reg    [3:0] wr_ptr,rd_ptr;//写和读指针
reg    [3:0] counter;//用来判断空满

always@(posedge clk)
begin
 if(!rst)
 begin
  counter=0;
  data_out=0;
  wr_ptr=0;
  rd_ptr=0;
 end
 else
 begin
  case({wr_en,rd_en})
   2'b00: counter=counter;
   2'b01: 
          begin
		   data_out=ram[rd_ptr];//先进先出,因此读的话依旧按照次序来
		   counter=counter-1;
		   rd_ptr=(rd_ptr==15)?0:rd_ptr+1;
		  end
   2'b10:
          begin
		   ram[wr_ptr]=data_in;//写操作
		   counter=counter+1;
		   wr_ptr=(wr_ptr==15)?0:wr_ptr+1;
		  end
   2'b11:
         begin
		  ram[wr_ptr]=data_in;//读写同时进行,此时counter不增加
		  data_out=ram[rd_ptr];
		  wr_ptr=(wr_ptr==15)?0:wr_ptr+1;
		  rd_ptr=(rd_ptr==15)?0:rd_ptr+1;
		 end 
  endcase
 end
end

assign empty=(counter==0)?1:0;
assign full =(counter==15)?1:0;


endmodule


在modelsim中进行仿真,测试代码如下:

`timescale 1ns/1ns
`define half_cycle 10
module fifoTB;
wire empty,full;
wire [7:0]data_out;

reg clk,rst;
reg wr_en,rd_en;
reg [7:0] data_in;

always #(`half_cycle) clk=~clk;
initial
begin
clk=0;
data_in=0;
rst=1;
#10 rst=0;
#10 rst=1;
wr_en=1;rd_en=0;
#60
wr_en=0;rd_en=1;
#60 
wr_en=1;rd_en=0;
#320 wr_en=0;rd_en=1;
#320 wr_en=1;rd_en=0;
#60 $stop;

end

always@(posedge clk)
begin
data_in=data_in+1;
end

 fifo m(clk,rst,wr_en,rd_en,data_in,data_out,empty,full);

endmodule


得到的仿真图如下:



  • 23
    点赞
  • 165
    收藏
    觉得还不错? 一键收藏
  • 11
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值