Bootstrap

FPGA FIFO IP核(4)-异步时钟FIFO

配置异步FIFO IP核

  • 新建文件夹,新建工程(略)
  • 配置FIFO IP核

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

调用代码

module fifo(
	input	wire			wrclk	,
	input	wire	[7:0]	pi_data	,//输入顶层模块的数据         wrclk
	input	wire			pi_flag ,//写请求                    wrclk

	input	wire			rdclk	,
	input	wire			rdreq	,//读请求                    rdclk     

	output	wire			wrempty ,//写端口空标志,高电平有效   wrclk
	output	wire			wrfull  ,//写端口满标志,高电平有效   wrclk
	output  wire	[7:0]	wrusedw ,//写端口中的数据个数         wrclk

	output	wire	[15:0]  po_data ,//读出的数据                rdclk
	output  wire			rdempty ,//读端口空标志,高电平有效   rdclk
	output	wire			rdfull  ,//读端口满标志,高电平有效   rdclk
	output  wire    [6:0]   rdusedw ,//读端口中存在的数据个数     rdclk

dcfifo_256x8to128x16	dcfifo_256x8to128x16_inst
(
	//input
	.data	(pi_data),
	.rdclk	(rdclk  ),
	.rdreq	(rdreq  ),
	.wrclk  (wrclk  ),
	.wrreq  (wrreq  ),
	//output
	.q      (po_data),
	.rdempty(rdempty),
	.rdfull (rdfull ),
	.rdusedw(rdusedw),
	.wrempty(wrempty),
	.wrfull (wrfull ),
	.wrusedw(wrusedw),
);
endmodule
	
  • 分析综合后的RTL视图
    在这里插入图片描述

仿真代码

'timescale 1ns/1ns
module	tb_fifo();
//定义端口,连接
reg				wrclk	 	;
reg		[7:0]	pi_data 	;
reg				pi_flag  	;
reg				rdclk    	;
reg				rdreq	 	;
reg				sys_rst_n	;
reg		[1:0]	cnt_baud 	;
reg				wrfull_reg0 ;
reg				wrfull_reg1 ;

wire			wrempty		;
wire			wrfull		;
wire	[7:0]	wrusedw		;
wire	[15:0]  po_data		;
wire			rdempty		;
wire			rdfull		;
wire	[6:0]   rdusedw		;

//时钟,复位初始化
initial	begin
	wrclk		=	1'b1;
	rdclk		=	1'b1;
	sys_rst_n	<=	1'b0;
	#100;
	sys_rst_n	<=	1'b1;
end

//写时钟wrclk:50Mhz   周期20ns,每10ns电平翻转一次
always	#10		wrclk	=	~wrclk;

//读时钟rdclk:25Mhz   周期40ns,每20ns电平翻转一次
always	#20		rdclk	=	~rdclk;

//计数器cnt_baud:从0到3计数   产生输入数据间的间隔
always@(posedge	wrclk or negedge sys_rst_n)    //写时钟高电平,复位时钟低电平
	if(sys_rst_n == 1'b0)
		cnt_baud <= 2'b0;
	else	if(&cnt_baud == 1'b1) //位与
		cnt_baud <= 2'b0;
	else
	    cnt_baud <= cnt_baud +1'b1;

//输入数据有效标志信号,写请求信号:pi_flag
always@(posedge	wrclk or negedge sys_rst_n)    //写时钟高电平,复位时钟低电平
	if(sys_rst_n == 1'b0)
		pi_flag <= 1'b0
	else	if((cnt_baud == 2'd0)  &&  (rdreq == 1'b0)) //每4个时钟周期且没有读信号时产生一个数据有效标志信号
		pi_flag <= 1'b1;
	else
		pi_flag <= 1'b0;

//写入FIFO的数据:pi_data   0~255的依次循环
always@(posedge	wrclk or negedge sys_rst_n)    //写时钟高电平,复位时钟低电平
	if(sys_rst_n == 1'b0)
		pi_data <= 8'b0;
	else	if((pi_data == 8'd255) && (pi_flag ==1'b1))
		pi_data <= 8'b0;
	else	if(pi_flag == 1'b1)
		pi_data <= pi_data +1'b1;

//将写满标志信号wrfull在rdclk时钟下 延迟两拍
always@(posedge	rdclk or negedge sys_rst_n)    //读时钟高电平,复位时钟低电平
	if(sys_rst_n == 1'b0)
		begin
			wrfull_rag0 <= 1'b0;
			wrfull_reg1 <= 1'b0;
		end
	else
		begin
			wrfull_reg0 <= wrfull;
			wrfull_reg1 <= wrfull_reg0;
		end
	
//读请求信号同步与rdclk时钟
always@(posedge	rdclk or negedge sys_rst_n)    //读时钟高电平,复位时钟低电平
	if(sys_rst_n = 1'b0)
		rdreq <= 1'b0;
	else	if(wrfull_reg1 == 1'b1)
		rdreq <= 1'b1;
	else	if(rdempty == 1'b1)
		rdreq <= 1'b0;

//例化
fifo fifo_inst(
	//写
	.wrclk	 (wrclk  ), 
	.pi_data (pi_data),
	.pi_flag (pi_flag),
	//读
	.rdclk   (rdclk  ),
	.rdreq   (rdreq  ),
	//写
	.wrempty (wrempty),
	.wrfull	 (wrfull ),
	.wrusedw (wrusedw),
	//读
	.po_data (po_data).rdempty (rdempty),
	.rdfull  (rdfull ),
	.rdusedw (reusedw)
	);
	endmodule

仿真结果

  • 整体结果
    1、pi_data与po_data交替出现
    2、pi_flag信号与pi_data一一对应
    3、读请求信号rdreq为高时po_data输出
    在这里插入图片描述
  • wrfull与rdfull信号
    pi_data为11111111(255)时且pi_flag为高时,wrfull(写满信号)拉高,一段时间后,rdfull(读端口满信号)拉高:FIFO的存储空间已满。两个信号同步的时钟分别是wrclk和rdclk。
    在这里插入图片描述
    在这里插入图片描述
  • wrusedw和rdusedw信号
    wrusedw信号计数到1111_1111(255),rdusedw计数到1111_111(127),从8位256个数据变成16位128个数据。之后都变为0,即数据存满,计数器溢出。
    在这里插入图片描述
    在这里插入图片描述
  • rdempty和wrempty信号
    16位数据全部读出后,rdempty信号立即拉高,即数据全部读完,因为同步时钟的不同,一段时间后,wrempty信号也被拉高。
    在这里插入图片描述

小结

逻辑思维拷打!

;