基于Vivado的FIFO-IP核-强化篇

FIFO-IP核的配置

下面操作是以异步FIFO为例,且读模式为首字先出模式FWFT。

配置界面1

1、模块命名

首先给FIFO模块起名,要做到见名知意。

2、接口类型

接口类型,选择不同的接口类型,那么FIFO的信号线是不同的,也就是说接口类型不同,信号线的功能也不一样,我们的读写操作所使用的信号线不同。我们默认选择Native本地接口。

3、FIFO类型

FIFO类型选取,有同步FIFO和异步FIFO。

Block RAM称为块RAM、嵌入式RAM,它是一个电路,专门用于存储数据的。其电路是在FPGA内部,一块BRAM大小为36Kbit,由两个小的RAM(18Kbit)组成。在FPGA内部资源里有很多BRM资源。它是按块使用的,比如我们位宽是64bit,深度为65536,那么就要消耗64*65535 / (36*1024) ≈ 113.8,需要114个BRAM。那如果消耗了113.1个,那么还是消耗114个BRAM。

总结:(1)FPGA越贵,BRAM资源越多

(2)BRAM的数量,需要根据我们选择芯片信号,去查看手册得知。

(3)每一个BRAM的容量大小为36Kbit,每一块BRAM是由两个小的RAM(18Kbit)组成。

(4)有时候使用存储类的IP核,可能消耗的是BRAM资源,主要看我们选择是BRAM还是DRAM。

(5)消耗BRAM计算公式:位宽*深度 bit / 36Kbit,若存在小数,则结果要+1。

Distributed RAM称为分布式RAM,它消耗的只能是FPGA内部的CLB(可配置逻辑块)中的SLILCM中的LUT(查找表)资源, 可在UG474手册中12页查到。SLILCM的资源要少于SLILCL,在FPGA中比较分散。

FIFO/ROM/RAM-IP核如何选择RAM类型:

BRAM:尽量选择这个,数据量大、较为重要的数据、时钟频率高。是因为它是一个电路专门用于存储数据,适用于时钟频率快的情况。

DRAM:数据量小、不太重要的数据、时钟频率低。是因为它消耗的只能是FPGA内部的CLB(可配置逻辑块)中的SLILCM中的LUT(查找表)资源,而SLILCM的资源在FPGA中比较分散,在读写数据时这个时延相对来说比较大,适用于时钟频率慢的情况。

Bulitin FIFO:在FPGA内部是一个专门的电路,适用于高速的数据缓存的情况。

这里选择异步FIFO的BRAM类型。

配置界面2

1、读模式选择

设置读模式,分别是标准FIFO和首字先出模式。

标准FIFO:读使能rden和读数据之间会有一拍的延迟,也就是1个时钟的潜伏期(1 Clock Latency)

首字先出模式(FWFT) :读使能rden和读数据之间无延迟,也就是0个潜伏期(0 Clock Latency)

2、数据端口的参数

然后再设置读写位宽,以及深度。

异步FIFO可以解决的问题:(1)数据位宽不匹配问题(跨位宽),FIFO作为数据缓存器(同步FIFO也可以),但是需要注意的是读位宽最大只能是写位宽的8倍。(2)跨时域问题

3、输出寄存器

读使能rden和读数据之间的Clock Latency有三种情况:

0拍:FWFT,用在读使能rden和读数据间的时序是对齐的。

1拍:Standard,正常情况下都使用这个。

2拍:Standard + Output Registers,当时钟频率>=200Mhz或者我们的工程所用资源超过了FPGA芯片内部资源的70%,推荐使用2拍延迟

4、复位引脚

FIFO的复位信号rst高电平有效,在复位时rst信号高电平持续时间需要长一些,而且复位结束以后还需要等一会时间。如下图所示:来自PG057手册P128。在这段时间内读写数据都是无效的,也就是说在复位操作这段时间内不可以读写数据。

配置界面3

prog_full和prog_empty可作为反馈机制引脚,控制往FIFO里写数据模块,FIFO快满时不能写,FIFO读空时快点写。

配置界面4

假设写数据位宽位8bit,读数据位宽16bit。

写用量信号wr_data_count:代表FIFO中有多少个8bit数据。

读用量信号rd_data_count:代表FIFO中有多少个16bit数据。

配置界面5

最后检查一下配置是否正确,然后点击OK,即完成FIFO-IP核的配置。

仿真代码

复制代码
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date: 2023/05/17 09:16:36
// Design Name: 
// Module Name: FWFT_FIFO_TB
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////


module FWFT_FIFO_TB(

    );
	
	
	reg fifo_clk;
	reg [15:0] fifo_wrdata;
	reg fifo_wren;
	reg fifo_rden;
	
	
	
	reg rst_n;
	initial begin 
	
		fifo_clk = 1'b0;
		rst_n = 1'b0;
		#300.1
		rst_n = 1'b1;
	
	end 
	
	always #10 fifo_clk = ~fifo_clk;
	
	
	reg [15:0]work_cnt;
	
	always @ (posedge fifo_clk or negedge rst_n)
	begin 
		if(~rst_n)
			begin 
				work_cnt <= 16'd0;
			end 
		else if(work_cnt == 16'd1000)
			begin 
				work_cnt <= work_cnt;
			end 
		else 
			begin 
				work_cnt <= work_cnt + 1'b1;
			end 
	end 
	
	
	always @ (posedge fifo_clk or negedge rst_n)
	begin 
		if(~rst_n)
			begin 
				fifo_wrdata <= 16'd0;
				fifo_wren <= 1'b0;
			end 
		else if((work_cnt >= 100) && (work_cnt <= 199))//写了100个随机数据
			begin 
				fifo_wrdata <= {$random} %3000;
				fifo_wren <= 1'b1;
			end 
		else 
			begin 
				fifo_wren <= 1'b0;
				fifo_wrdata <= 16'd0;
			end 
	end 
	
	
	always @ (posedge fifo_clk or negedge rst_n)
	begin 
		if(~rst_n)
			begin 
				fifo_rden <= 1'b0;
			end 
		else if((work_cnt >= 200) && (work_cnt <= 299))
			begin 
				fifo_rden <= 1'b1;
			end 
		else 
			begin 
				fifo_rden <= 1'b0;
			end 
	end 
	
	
	
	wire fifo_full;
	wire fifo_empty;
	wire [15:0]fifo_dataout;
	wire [10:0] fifo_data_count;//表示FIFO内部已经存在的数据量
    wire [10:0] wr_data_count;
	
	
	
	
	
	//异步FIFO测试
	FWFT_FIFO FWFT_FIFO (
	  .wr_clk(fifo_clk),                // input wire wr_clk
	  .rd_clk(fifo_clk),                // input wire rd_clk
	  .din(fifo_wrdata),                      // input wire [15 : 0] din
	  .wr_en(fifo_wren),                  // input wire wr_en
	  .rd_en(fifo_rden),                  // input wire rd_en
	  .dout(fifo_dataout),                    // output wire [15 : 0] dout
	  .full(fifo_full),                    // output wire full
	  .empty(fifo_empty),                  // output wire empty
	  .rd_data_count(fifo_data_count),  // output wire [10 : 0] rd_data_count
	  .wr_data_count(wr_data_count)  // output wire [10 : 0] wr_data_count
	);
	
	
	
	
	
	
	
	
	
endmodule

仿真验证

由于使用的首字先出模式,会在写数据时,将第一个数据放在读数据端口上,以此来实现的0拍的延迟。所以才会导致上面这种情况。但是不影响后续读数据时序。

相关推荐
科恒盛远11 小时前
RFSoC XCZU47DR 100G UDP高速数据传输的实现与调试(PCIE908 板卡技术系列三)
fpga开发
小麦嵌入式18 小时前
FPGA入门(十一):受控线性序列机 UART 发送升级
stm32·单片机·嵌入式硬件·mcu·fpga开发·硬件工程
X_xcccc19 小时前
2026硬核拆解:高性能异构计算板卡选型指南
fpga开发
tju新生代魔迷2 天前
Verilog HDL 学习笔记(十)| 第10章 时序和延迟
笔记·学习·fpga开发
aprilaaaaa3 天前
(TC397 学习笔记)二、ICU和TIM的时钟计算
笔记·学习·fpga开发
X_xcccc3 天前
2026高端FPGA开发平台权威评测与选型指南
fpga开发
威嵌神州3 天前
军工加固计算机七大核心特性解析|国产化、宽温、强加固工程实现
嵌入式硬件·计算机网络·fpga开发
FPGA小迷弟3 天前
高云半导体深度解读:国产FPGA车规赛道的领跑者
fpga开发
努力搬砖的小H3 天前
FPGA应用技巧之Block Design基本使用方法
功能测试·fpga开发·zynq·block design
ALINX技术博客3 天前
【黑金云课堂】FPGA技术教程FPGA 基础:HDMI视频输入与环路输出实验
fpga开发·音视频