【原创】Xilinx 同步FIFO IP核时序仿真说明(附testbench代码)

引言

最近在研究硬件tcp/ip协议栈,需要用到同步FIFO缓存电脑发来的以太网数据。以前用的Altera家的芯片,还没仔细研究过Xilinx的同步FIFO IP核的时序,为了避免以后采坑,简单分析一下其操作时序。
软件环境:Vivado 2019.2
仿真环境:Vivado Simulator
官方手册:PG057


一、时序分析

为了验证手册中的时序图,在Vivado中进行了仿真,仿真结果如下: 

 可以看见,在wr_en拉高的同时,往FIFO中写了一个数据 “1” ,但这个 “1” 能否正确地写进FIFO中,则需要看读FIFO的时序图。

上图为读时序的仿真结果,可以看见,读出的第一个数据的确是 “1” (FIFO复位值为32'd85),说明手册中的写时序图是正确的,即在wr_en有效的第一个沿就将数据写入FIFO了。

返回来再继续看上面的读时序仿真图,发现FIFO输出数据是在rd_en拉高的下一个时钟上沿输出到dout上的,说明在rd_en拉高后的下一个读时钟上升沿,输出数据才会有效 
这种读模式称为 Standard FIFO Read Operation ,其时序在手册中如下图所示,可见与仿真结果一致。

手册中还提到了一种称为 First-Word Fall-Through FIFO Read Operation(FWFT) 的读模式,其时序在手册中如下图所示,手册中描述为:“When data is available in theFIFO, the first word falls through the FIFO and appears automatically on the output bus(dout).”。  即当FIFO中有可用数据时,第一个数据将通过FIFO并自动出现在输出总线(dout)上。也就是无论rd_en是否拉高,第一个输出的数据总是有效的,这就使得读 rd_en 和 dout 之间不再相差一个时钟周期,而是拉高rd_en,立即在dout上输出有效数据。

Vivado仿真结果如下,可见在FWFT模式下,的确是rd_en拉高时的第一个输出数据就是有效的数据。


 


二、仿真源码

`timescale 1ns / 1ps



module sfifo_test_tb;

/**************************************************/
// input signals
reg				clk	 ;
reg				rst_n;
reg	[31:0]		din  ;
reg				wr_en;
reg				rd_en;

// output signals
wire	[31:0]	dout    ;
wire			wr_full ;
wire			rd_empty;
/**************************************************/

// reg define
reg	[15:0]		cnt 		;	// 写数据个数计数器
reg	[15:0]		tim_cnt 	;	// 复位延时定时器
reg				start_en 	;	// 读FIFO开始标志
reg				start_cnt_en;	// 写FIFO开始标志
reg	[31:0]		ext_reg     ;	// 连接FIFO dout的外部寄存器



///
//***				Main Code			  	  ***//
//***										  ***//
///


// 初始化
initial	begin
	// initial
	clk = 0;
	rst_n = 1;
	din = 32'd0;
	wr_en = 0;
	rd_en = 0;
	cnt = 16'd0;
	tim_cnt = 16'd0;
	start_cnt_en = 1'b0;
	start_en = 1'b0;
	ext_reg = 32'd0;

	// FIFO复位
	#10 rst_n = 0;
	#20 rst_n = 1;

	// 生成时钟
	forever #5 clk = ~clk;
end


// 复位延时
always @(posedge clk) begin
	tim_cnt <= tim_cnt + 1'b1;
	if( tim_cnt == 16'd20 ) begin
		tim_cnt <= 16'd0;
		start_cnt_en <= 1'b1;
	end
end


// 写FIFO
always @(posedge clk) begin
	if( start_cnt_en == 1'b1 ) begin
		cnt <= cnt + 1'b1;
		din <= din + 1'b1;
		wr_en <= 1'b1;
		if( cnt == 16'd255 ) begin
			cnt <= 16'd0;
			wr_en <= 1'b0;
			start_en <= 1'b1;
		end
	end
end


// 读FIFO
always @(posedge clk) begin
	if( start_en == 1'b1 ) begin
		rd_en <= 1'b1;
		ext_reg <= dout;
	end
end


// 同步FIFO例化
sync_fifo  U_sync_fifo(
  .clk	( clk 		)	,
  .rst	( ~rst_n 	)	,
  .din	( din 		)	,
  .wr_en( wr_en 	)	,
  .rd_en( rd_en 	)	,
  .dout	( dout 		)	,
  .full	( wr_full 	)	,
  .empty( rd_empty 	)
);


endmodule


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值