44_ZYNQ7020开发板Vivado配置FIFO并用Vivao自带逻辑分析仪分析

摘要:FIFO是FPGA应用当中非常重要的模块,广泛应用于数据的缓存跨时钟域数据处理。学好FIFO是FPGA的关键,灵活运用好FIFO是一个FPGA工程师必备的技能。
赛灵思提供的FIFO IP核进行读写测试。

一、实验原理
FIFO:First in,First out代表先进的数据先出,后进的数据后出。
需要在Xilinx提供的FIFO的IP核实例化一个FIFO,根据读写时序写入和读取FIFO中存储的数据。
结构
FIFO分为读和写两部分,另外就算是状态信号,空和满信号,同时还有数据的数量状态信号,没有地址线,不能随机地址读取数据。
在这里插入图片描述
初始状态下,读写地址都为0,向FIFO中写入一个数据后,写地址加1,从FIFO中读出一个数据后,读地址加1.此时FIFO的状态为空,因为写了一个数据,又读了一个数据。

根据读写时钟,可以分为同步FIFO(读写时钟相同)和异步FIFO(读写时钟不同)。
读时钟75Mhz写时钟100Mhz。采用Vivado集成的逻辑分析仪ila,从中观察FIFO读写时序和从FIFO中读取数据。
二、创建fifo_test工程,然后添加FIFO IP核。
在这里插入图片描述
在弹出的窗口中设置Component Name为fifo_ip,设置FIFO Implementation为Independent Clocks Block RAM
在这里插入图片描述
切换到Native Ports栏目下,选择数据位宽16FIFO深512,Read Mode有两种,一个Standard FIFO,也就是平时常见的FIFO,数据滞后读信号一个周期,还有一种方式是First Word Fall Through,数据预取模式,简称FWFT模式。也就是FIFO会预先取出一个数据,当读信号有效时,相应的数据也有效。

在这里插入图片描述
在Data Counts栏下,使能Write Data Count和Read Data Count,这样就可以通过两个值来看FIFO内部的数据多少。
在这里插入图片描述
点击OK,Generate生成FIFO IP核。
在这里插入图片描述
FIFO的端口定义与时序
在这里插入图片描述

标准FIFO写时序

在这里插入图片描述
FIFO的数据写入和读出都是按时钟的上升沿操作的,当wr_en信号为高时写入FIFO数据,当almost_full信号有效时,表示FIFO只能再写入一个数据,一旦写入一个数据,full信号就会拉高,如果在full的情况下wr_en任然有效,也就是继续向FIFO写数据,则FIFO的overflow就会有效,表示溢出。

标准读时序

在这里插入图片描述
当rd_en信号为高时读FIFO,数据在下一个周期有效,valid为数据有效信号,almost_empty表示还有一个数据读,当再读一个数据,empty信号有效,如果继续读,则underflow有效,表示下溢,此时读出的数据无效。

FWFT FIFO读时序
在这里插入图片描述
而从FWFT模式读数据时序图可以看出,rd_en信号有效时,有效数据D0已经在数据线上准备好有效了,不会再延后一个周期。这就是标准FIFO的不同之处。
在这里插入图片描述
三、FIFO的测试代码
按照异步FIFO进行设计,用PLL产生两路时钟,分别100M hz和75Mhz,用于写时钟和读时钟,也就是写时钟频率高于读时钟频率。
fifo_test.v

`timescale 1ns / 1ps
//
module fifo_test
	(
		input 		clk,		         //50MHz时钟
		input 		rst_n	             //复位信号,低电平有效	
	);


reg	 [15:0] 		w_data			;	   		//FIFO写数据
wire      			wr_en			;	   		//FIFO写使能
wire      			rd_en			;	   		//FIFO读使能
wire [15:0] 		r_data			;			//FIFO读数据
wire       			full			;  			//FIFO满信号 
wire       			empty			;  			//FIFO空信号 
wire [8:0]  		rd_data_count	;  			//可读数据数量	
wire [8:0]  		wr_data_count	;  			//已写入数据数量
	
wire				clk_100M 		;			//PLL产生100MHz时钟
wire				clk_75M 		;			//PLL产生100MHz时钟
wire				locked 			;			//PLL lock信号,可作为系统复位信号,高电平表示lock住
wire				fifo_rst_n 		;			//fifo复位信号, 低电平有效

wire				wr_clk 			;			//写FIFO时钟
wire				rd_clk 			;			//读FIFO时钟
reg	[7:0]			wcnt 			;			//写FIFO复位后等待计数器
reg	[7:0]			rcnt 			;			//读FIFO复位后等待计数器

//例化PLL,产生100MHz和75MHz时钟
clk_wiz_0 fifo_pll
 (
  // Clock out ports
  .clk_out1(clk_100M),     	 	// output clk_out1
  .clk_out2(clk_75M),    		// output clk_out2
  // Status and control signals
  .reset(~rst_n), 			 	// input reset
  .locked(locked),       		// output locked
  // Clock in ports
  .clk_in1(clk)					// input clk_in1
  );      			

assign fifo_rst_n 	= locked	;	//将PLL的LOCK信号赋值给fifo的复位信号
assign wr_clk 		= clk_100M 	;	//将100MHz时钟赋值给写时钟
assign rd_clk 		= clk_75M 	;	//将75MHz时钟赋值给读时钟


/* 写FIFO状态机 */
localparam      W_IDLE      = 1	;
localparam      W_FIFO     	= 2	; 

reg[2:0]  write_state;
reg[2:0]  next_write_state;

always@(posedge wr_clk or negedge fifo_rst_n)
begin 
	if(!fifo_rst_n)
		write_state <= W_IDLE;
	else
		write_state <= next_write_state;
end

always@(*)
begin
	case(write_state)
		W_IDLE:
			begin
				if(wcnt == 8'd79)               //复位后等待一定时间,safety circuit模式下的最慢时钟60个周期
					next_write_state <= W_FIFO;
				else
					next_write_state <= W_IDLE;
			end
		W_FIFO:
			next_write_state <= W_FIFO;			//一直在写FIFO状态
		default:
			next_write_state <= W_IDLE;
	endcase
end
//在IDLE状态下,也就是复位之后,计数器计数
always@(posedge wr_clk or negedge fifo_rst_n)
begin 
	if(!fifo_rst_n)
		wcnt <= 8'd0;
	else if (write_state == W_IDLE)
		wcnt <= wcnt + 1'b1 ;
	else
		wcnt <= 8'd0;
end
//在写FIFO状态下,如果不满就向FIFO中写数据
assign wr_en = (write_state == W_FIFO) ? ~full : 1'b0; 
//在写使能有效情况下,写数据值加1
always@(posedge wr_clk or negedge fifo_rst_n)
begin
	if(!fifo_rst_n)
		w_data <= 16'd1;
	else if (wr_en)
		w_data <= w_data + 1'b1;
end

/* 读FIFO状态机 */

localparam      R_IDLE      = 1	;
localparam      R_FIFO     	= 2	; 
reg[2:0]  read_state;
reg[2:0]  next_read_state;

///产生FIFO读的数据
always@(posedge rd_clk or negedge fifo_rst_n)
begin
	if(!fifo_rst_n)
		read_state <= R_IDLE;
	else
		read_state <= next_read_state;
end

always@(*)
begin
	case(read_state)
		R_IDLE:
			begin
				if (rcnt == 8'd59)             	//复位后等待一定时间,safety circuit模式下的最慢时钟60个周期
					next_read_state <= R_FIFO;
				else
					next_read_state <= R_IDLE;
			end
		R_FIFO:	
			next_read_state <= R_FIFO ;			//一直在读FIFO状态
		default:
			next_read_state <= R_IDLE;
	endcase
end

//在IDLE状态下,也就是复位之后,计数器计数
always@(posedge rd_clk or negedge fifo_rst_n)
begin 
	if(!fifo_rst_n)
		rcnt <= 8'd0;
	else if (write_state == W_IDLE)
		rcnt <= rcnt + 1'b1 ;
	else
		rcnt <= 8'd0;
end
//在读FIFO状态下,如果不空就从FIFO中读数据
assign rd_en = (read_state == R_FIFO) ? ~empty : 1'b0; 

//-----------------------------------------------------------
//实例化FIFO
fifo_ip fifo_ip_inst 
(
  .rst            (~fifo_rst_n    	),   // input rst
  .wr_clk         (wr_clk          	),   // input wr_clk
  .rd_clk         (rd_clk          	),   // input rd_clk
  .din            (w_data       	),   // input [15 : 0] din
  .wr_en          (wr_en        	),   // input wr_en
  .rd_en          (rd_en        	),   // input rd_en
  .dout           (r_data       	),   // output [15 : 0] dout
  .full           (full         	),   // output full
  .empty          (empty        	),   // output empty
  .rd_data_count  (rd_data_count	),   // output [8 : 0] rd_data_count
  .wr_data_count  (wr_data_count	)    // output [8 : 0] wr_data_count
);

//写通道逻辑分析仪
ila_m0 ila_wfifo (
	.clk		(wr_clk			), 
	.probe0		(w_data			), 	
	.probe1		(wr_en			), 	
	.probe2		(full			), 		
	.probe3		(wr_data_count	)
);
//读通道逻辑分析仪
ila_m0 ila_rfifo (
	.clk		(rd_clk			), 
	.probe0		(r_data			), 	
	.probe1		(rd_en			), 	
	.probe2		(empty			), 		
	.probe3		(rd_data_count	)
);
 	
endmodule

添加PLL、FIFO、ILA的IP核,然后综合布线实例化
添加锁相环倍频分别100Mhz和50Mhz
在这里插入图片描述
FIFO
在这里插入图片描述
ILA逻辑分析仪
在这里插入图片描述
在这里插入图片描述
添加仿真的simulation 文件
vtf_fifo_tv.v

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2019/10/29 09:06:34
// Design Name: 
// Module Name: vtf_fifo_tb
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module vtf_fifo_tb;
// Inputs
reg clk;
reg rst_n;


// Instantiate the Unit Under Test (UUT)
fifo_test uut (
	.clk	(clk), 		
	.rst_n		(rst_n)
);

initial 
begin
	// Initialize Inputs
	clk = 0;
	rst_n = 0;

	// Wait 100 ns for global reset to finish
	#100;
      rst_n = 1;       

 end

然后综合,管脚约束

在这里插入图片描述
然后点击Run Simulation进行在线仿真
在这里插入图片描述
写逻辑
在这里插入图片描述
读逻辑
在这里插入图片描述

点击Gnenerate Bitstream生成bit文件
在这里插入图片描述

  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值