同步FIFO设计实现(8/7)

1.    同步FIFO的写时钟和读时钟为同一个时钟,FIFO内部所有逻辑都是同步逻辑,常常用于交互数据缓冲。
2.    典型同步FIFO有三部分组成: (1) FIFO写控制逻辑; (2)FIFO读控制逻辑;(3)FIFO 存储实体(如Memory、Reg)。

 

3.    FIFO写控制逻辑主要功能:产生FIFO写地址、写有效信号,同时产生FIFO写满、写错等状态信号;
4.    FIFO读控制逻辑主要功能:产生FIFO读地址、读有效信号,同时产生FIFO读空、读错等状态信号。

FIFO基本概念: 

•    FIFO:先进先出(First-in-first-out)
•    FIFO的深度(如下), 同一块数据内存的大小
•    FIFO的宽度
•    写指针:Write-pointer
•    读指针:Read-pointer
•    写数据端口
•    读数据端口
•    FIFO空、FIFO满
•    同步FIFO/异步FIFO
•    同步:数据写入FIFO的时钟和数据读出FIFO的时钟是同步的(synchronous)

•    异步:数据写入FIFO的时钟和数据读出FIFO的时钟是异步的(asynchronous)

一般FIFO使用循环指针(计数溢出自动归零)。一般可以称写指针为头head,读指针为尾tail。初始化时,读写指针指向同一数据地址。
下图可见,FIFO初始化时,WP和RP指针指向同一数据单元。WP指向下一个将要写入的数据单元,RP指向将要读出的数据单元 

使用fifo_counter记录FIFO RAM中的数据个数: 

1.    等于0时,给出empty信号
2.    等于BUF_LENGTH时,给出full信号

fifo_counter:

1.    写而未满时增加1
2.    读而未空时减1
3.    同时发生读写操作时,fifo_counter不变

读写指针宽度

1.    与地址宽度相当
2.    地址增加而溢出后,自动变成0
3.    循环指针(此处地址变化:0-7-0-7-0)

代码实现 

RTL

`define BUF_WIDTH 4 //地址宽度为3+1
`define BUF_SIZE  8 //数据个数,FIFO深度

module fifo_counter(clk,rst_n,buf_in,buf_out,wr_en,rd_en,buf_empty,buf_full,fifo_cnt);
	input clk,rst_n;
	input wr_en,rd_en;
	input [7:0] buf_in; //data input to be pushed to buffer
	output reg [7:0] buf_out; //port to output the data using pop
	output wire buf_empty,buf_full; //buffer empty and full indication
	output reg [`BUF_WIDTH-1:0] fifo_cnt; //number of data pushed in to buffer
	//当写入数据个数为8时,FIFO为满
	reg [`BUF_WIDTH-2:0] rd_ptr,wr_ptr;
	//数据指针3位宽度,0-7索引,8个数据深度,循环指针0-7-0-7
	reg [7:0] buf_mem [0:`BUF_SIZE-1];
	//判断空满
	assign buf_empty=(fifo_cnt==0);
	assign buf_full=(fifo_cnt==`BUF_SIZE);
	
	always@(posedge clk or negedge rst_n)begin
		if(!rst_n)
		  fifo_cnt<=0;
		else if((!buf_full&&wr_en)&&(!buf_empty&&rd_en))//同时读写,counter不变
		  fifo_cnt<=fifo_cnt;
		else if(!buf_full&&wr_en) //写数据
		  fifo_cnt<=fifo_cnt+1;
		else if(!buf_empty&&rd_en) //读数据
		  fifo_cnt<=fifo_cnt-1;
		else
		  fifo_cnt<=fifo_cnt;
		end
	
	always@(posedge clk or negedge rst_n)begin //读数据
		if(!rst_n)
		  buf_out<=0;
		else if(rd_en&&!buf_empty)
		  buf_out<=buf_mem[rd_ptr];
		end
		
	always@(posedge clk )begin  //写数据
	    if(wr_en&&!buf_full)
		  buf_mem[wr_ptr]<=buf_in;
		end
		
	always@(posedge clk or negedge rst_n) begin
		if(!rst_n) begin
		  rd_ptr<=0;
		  wr_ptr<=0;
		end
		else begin
		  if(!buf_empty&&rd_en)
			rd_ptr<=rd_ptr+1;
		  if(!buf_full&&wr_en)
		    wr_ptr<=wr_ptr+1;
		end
		end
endmodule

TB: 

//fifi.v TB
`define BUF_WINTH 4 //地址宽度位3+1
`define BUF_SIZE  8 //数据个数,FIFO深度

module tb_fifo_counter;
	reg clk,rst_n;
	reg wr_en,rd_en;
	reg [7:0] buf_in; //data input to be pushed to buffer
	wire reg [7:0] buf_out; //port to output the data using pop
	wire buf_empty,buf_full; //buffer empty and full indication
	wire [`BUF_WIDTH-1:0] fifo_cnt; //number of data pushed in to buffer
	//当写入数据个数为8时,FIFO为满

	fifo_counter init(clk,rst_n,buf_in,buf_out,wr_en,rd_en,buf_empty,buf_full,fifo_cnt);
	
	always begin
	#10 clk=~clk;
	end
	
	reg[7:0] tempdata;
	initial begin
	clk=0;
	rst_n=0;
	wr_en=0;
	rd_en=0;
	buf_in=0;
	#15;
	rst_n=1;
	push(1);
	
	fork
	push(2);
	pop(tempdata);
	join
	
	push(10);
	push(20);
	push(30);
	push(40);
	push(50);
	push(60);
	pop(tempdata);
	push(70);
	push(80);
	push(90);
	push(100);
	push(110);
	pop(tempdata);
	push(120);
	push(130);
	push(140);
	push(150);
	pop(tempdata);
	pop(tempdata);
	pop(tempdata);
	pop(tempdata);
	pop(tempdata);
	pop(tempdata);
	push(160);
	pop(tempdata);
	pop(tempdata);
	pop(tempdata);
	pop(tempdata);
	pop(tempdata);
	pop(tempdata);
	pop(tempdata);
	pop(tempdata);
	pop(tempdata);
	push(170);
	pop(tempdata);
	end
	
	task push(input [7:0] data);
		if(buf_full)
		$display("---cannot push %d:buffer full", data);
		else begin
		$display("push",,data);
		buf_in =data;
		wr_en=1;
		@(posedge clk);
		#5 wr_en=0;
		end
	endtask
	
	task pop(output[7:0] data);
		if(buf_empty)
		$display("---cannot pop %d:buffer empty", data);
		else begin
		rd_en=1;
		@(posedge clk);
		#3 rd_en=0;
		data=buf_out;
		$display("poped",,data);
		end
	endtask
endmodule

波形

 

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

创芯人

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值