vivado常用IP调用配置——FIFO

FIFO-IP核介绍

  • FIFO(First In First Out, 即先入先出),是一种数据缓冲器,用来实现数据先入先出的读写方式。FIFO存储器主要是作为缓存,应用在同步时钟系统核异步时钟系统中,在很多设计中都会用到,如:多比特数据做跨时钟域处理、前后带宽不同步等都用到了FIFO
  • 根据读写时钟可以分为:同步FIFO(SCFIFO)、异步FIFO(DCFIFO)
    在这里插入图片描述

SCFIFO-IP核的配置和验证

  1. 现在IP-Catalog中找到FIFO-IP核
    在这里插入图片描述

  2. Basic
    总线类型就选默认的在这里插入图片描述

  3. Native Ports
    在这里插入图片描述

  4. Status Flags
    在这里插入图片描述
    补充一下快要空满标志信号,高有效。如果满深度为256,那么当写到255的时候,Almost Full Flag信号被拉高。Almost Empty Flag则是数据还有一个时信号被拉高。下面的Programmable Flags可以规定数据深度为多少的时候信号被拉高。
    若FIFO满,再继续向FIFO里面写数据,则会导致现在的数据覆盖以前的数据,所以当full信号被拉高时,应停止写数据。
    若FIFO空,再及速度数据,则会读出以前写入的数据。

在这里插入图片描述

  1. Data Counts
    添加一个数据个数计数器
    在这里插入图片描述

  2. Summary
    这里可以看到一些总体的配置信息
    在这里插入图片描述

ok 那就那就开始验证吧
想来一个顶层模块把IP核添加进去,IP核的实例化模板可以打开默认路径FIFO_IP.ip_user_files\ip\scfifo_8x256里面的.veo文件

module fifo(
	input	wire				sys_clk		,
	input	wire				sys_rst_n	,
	input	wire	[7:0]		din			,
	input	wire				wr_en		,
	input	wire				rd_en		,
	
	output	wire	[7:0]		dout		,
	output	wire				full		,
	output	wire				empty		,
	output	wire	[7:0]		data_count
    );
    
    scfifo_8x256 scfifo_8_256_inst (
			  .clk			(sys_clk),      // input wire clk
			  .din			(din),      	// input wire [7 : 0] din
			  .wr_en		(wr_en),  		// input wire wr_en
			  .rd_en		(rd_en),  		// input wire rd_en
			  
			  .dout			(dout),    		// output wire [7 : 0] dout
			  .full			(full),    		// output wire full
			  .empty		(empty),  		// output wire empty
			  .data_count	(data_count)  	// output wire [7 : 0] data_count
		);
		
endmodule

然后是测试模块

module sim_fifo( );

	reg					sys_clk		;
	reg					sys_rst_n	;
	reg		[7:0]		din			;
	reg					wr_en		;
	reg					rd_en		;
	
	wire	[7:0]		dout		;
	wire				full		;
	wire				empty		;
	wire	[7:0]		data_count	;
	
	
	reg		[1:0]		cnt			;	// 计数器时间间隔


	fifo fifo_inst (
			.sys_clk	(sys_clk),
			.sys_rst_n	(sys_rst_n),
			.din		(din),
			.wr_en		(wr_en),
			.rd_en		(rd_en),
			
			.dout		(dout),
			.full		(full),
			.empty		(empty),
			.data_count	(data_count)
			
		);
	
	// 50MHz
	parameter	clk_period_50M	=	20;
	always # (clk_period_50M / 2)	sys_clk	=	~sys_clk;
	
	initial	begin
		sys_clk		=	0;
		sys_rst_n	=	0;
		#20
		sys_rst_n	=	1;
		
	end
	
	// cnt:计数器变量的赋值
	always @ (posedge sys_clk or negedge sys_rst_n)
		if (!sys_rst_n)
			cnt	<=	2'd0;
		else	if (cnt == 2'd3)
			cnt	<=	2'd0;
		else
			cnt	<=	cnt + 1'b1;
	
	// wr_en:写请求信号的赋值
	always @ (posedge sys_clk or negedge sys_rst_n)
		if (!sys_rst_n)
			wr_en	<=	1'b1;
		else	if ((cnt == 2'd0) && (rd_en == 1'b0))
			wr_en	<=	1'b1;
		else
			wr_en	<=	1'b0;
	
	// din:写数据
	always @ (posedge sys_clk or negedge sys_rst_n)
		if (!sys_rst_n)
			din	<=	8'd0;
		else if ((din == 8'd255) && (wr_en == 1'b1))
			din	<=	8'd0;
		else	if (wr_en == 1'b1)
			din	<=	din + 1'b1;
		else
			din	<=	din;
	
	// rd_en:读请求信号的赋值
	always @ (posedge sys_clk or negedge sys_rst_n)
		if (!sys_rst_n)
			rd_en	<=	1'b0;
		else	if (full == 1'b1)		// FIFO写满后开始读取
			rd_en	<=	1'b1;
		else	if (empty == 1'b1)		// FIFO取空后停止读
			rd_en	<=	1'b0;
				
endmodule

波形如下
Native Ports配置界面的两个读模式,波形出来的差距从读-写、写-读的结交位置可以看出,可以试一下
在这里插入图片描述
写满之后开始读
在这里插入图片描述
读空之后又开始写
在这里插入图片描述

DCFIFO-IP核的配置和验证

  1. 选中IP核
    在这里插入图片描述

  2. Basic
    在这里插入图片描述

  3. Native Ports
    在这里插入图片描述

  4. Status Flags
    在这里插入图片描述

  5. Data Counts
    在这里插入图片描述

  6. Summary
    在这里插入图片描述

开始仿真
顶层模块实例化FIFO-IP

module fifo_dcfifo(
	input	wire			wr_clk			,
	input	wire	 		wr_en			,
	input	wire	[7:0]	wr_data			,
	input	wire			rd_clk			,
	input	wire			rd_en			,
	
	output	wire	[15:0]	rd_data			,
	output	wire			full			,
	output	wire			empty			,
	output	wire	[6:0]	rd_data_count	,
	output	wire	[7:0]	wr_data_count
    );

	dcfifo_8x256_to_16x128 dcfifo_8x256_to_16x128_inst (
		  .wr_clk		(wr_clk),		// input wire wr_clk
		  .rd_clk		(rd_clk),		// input wire rd_clk
		  .din			(wr_data),		// input wire [7 : 0] din
		  .wr_en		(wr_en),		// input wire wr_en
		  .rd_en		(rd_en),		// input wire rd_en
		  
		  .dout			(rd_data),		// output wire [15 : 0] dout
		  .full			(full),			// output wire full
		  .empty		(empty),	 	// output wire empty
		  .rd_data_count(rd_data_count), // output wire [6 : 0] rd_data_count
		  .wr_data_count(wr_data_count)  // output wire [7 : 0] wr_data_count
		);

endmodule

测试模块

module sim_fifo_dcfifo ();
    reg				wr_clk	;
    reg				wr_en	;
    reg		[7:0]	wr_data	;
    reg				rd_clk	;
    reg				rd_en	;
    
    wire	[15:0]	rd_data	;
    wire			full	;
    wire			empty	;
    wire	[6:0]	rd_data_count	;
    wire	[7:0]	wr_data_count	;
	
	
	reg				sys_rst_n	;
	reg		[1:0]	cnt			;		// 控制写时间间隔	
	reg				wr_full_reg0;		// 用于同步写满标志信号
	reg				wr_full_reg1;
	
	// 写时钟:50MHz
	parameter	clk_period_50M	=	20;
	always # (clk_period_50M / 2)	wr_clk	=	~wr_clk;
	
	// 读时钟:25MHz
	parameter	clk_period_25M	=	40;
	always # (clk_period_25M / 2)	rd_clk	=	~rd_clk;

	initial	begin
		wr_clk		=	0;
		rd_clk		=	0;
		sys_rst_n	=	0;
		#20
		sys_rst_n	=	1;
		
	end
	
	
// cnt:计数器	
	always @ (posedge wr_clk or negedge sys_rst_n)
		if (!sys_rst_n)
			cnt	<=	2'd0;
		else	if (cnt == 2'd3)
			cnt	<=	2'd0;
		else
			cnt	<=	cnt + 1'b1;

// wr_en:写请求信号
	always @ (posedge wr_clk or negedge sys_rst_n)
		if (!sys_rst_n)
			wr_en	<=	1'b0;
		else	if ((cnt == 2'd0) && (wr_en == 1'b0))
			wr_en	<=	1'b1;
		else
			wr_en	<=	1'b0;

// wr_data:写数据赋值
	always @ (posedge wr_clk or negedge sys_rst_n)
		if (!sys_rst_n)
			wr_data	<=	8'd0;
		else	if ((wr_data == 8'd255) && (wr_en == 1'b1))
			wr_data	<=	8'd0;
		else	if (wr_en == 1'b1)
			wr_data	<=	wr_data + 1'b1;
		else
			wr_data	<=	wr_data;
			
// 时钟同步处理
	always @ (posedge rd_clk or negedge sys_rst_n)
		if (!sys_rst_n)
			begin
				wr_full_reg0	<=	1'b0;
				wr_full_reg1	<=	1'b0;
			end
		else			// 相当于多打一拍,就让写时钟同步到读时钟下
			begin
				wr_full_reg0	<=	full;
				wr_full_reg1	<=	wr_full_reg0;
			end
			
// rd_en:写请求信号
	always @ (posedge rd_clk or negedge sys_rst_n)
		if (!sys_rst_n)
			rd_en	<=	1'b0;
		else	if (wr_full_reg1 == 1'b1)	// 此时数据已经写满
			rd_en	<=	1'b1;
		else	if (empty == 1'b1)			// 此时数据已经读空
			rd_en	<=	1'b0;

	fifo_dcfifo fifo_dcfifo_inst (
		  .wr_clk		(wr_clk),		// input wire wr_clk
		  .rd_clk		(rd_clk),		// input wire rd_clk
		  .wr_data		(wr_data),		// input wire [7 : 0] din
		  .wr_en		(wr_en),		// input wire wr_en
		  .rd_en		(rd_en),		// input wire rd_en
		  
		  .rd_data		(rd_data),		// output wire [15 : 0] dout
		  .full			(full),			// output wire full
		  .empty		(empty),	 	// output wire empty
		  .rd_data_count(rd_data_count), // output wire [6 : 0] rd_data_count
		  .wr_data_count(wr_data_count)  // output wire [7 : 0] wr_data_count
		);
		
endmodule

波形:
在这里插入图片描述
在这里插入图片描述

  • 19
    点赞
  • 83
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值