Quartus ii FIFO ip核的应用与仿真

本文介绍了FIFO的工作原理,包括单时钟和双时钟FIFO,并详细阐述了如何在Quartus II中配置和使用SCFIFO与DCFIFO。通过设置IP Catalog生成VHDL代码,并展示了SCFIFO和DCFIFO的仿真结果,说明了数据写入和读取的过程及信号变化。

原理

FIFO: first in first out
FIFO分为 signal

FIFO
SCFIFO: single clock FIFO
DCFIFO: dual clock FIFO
普通双时钟
混合宽度双时钟

单时钟常被用于片内数据的收发,而双时钟则常用在接收异步数据,因为收发速率不同,可能会产生亚稳态等一系列问题。

单时钟和双时钟FIFO结构如下:
sc_dc

wrreq: 写入使能信号
rdreq:读出使能信号
full: FIFO写满信号
almost_full: 可配置参数,在写入数据>X的时候电平拉高,表示FIFO快写满
empty: FIFO清空信号
almost_empty: 可配置参数,在写入数据<X的时候电平拉高,标志着FIFO中数据快要读取完
usedw: 表示FIFO中有多少个存储的有效信号。

Quartus ii实现

SCFIFO

点击TOOLS打开 IP Catalog 然后找到FIFO,然后对其进行以下配置,其余默认,构建一个能存储256个8位数据的FIFO。
sc_fifo_ip
生成相应的vhdl代码之后搭建testbench如下:

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;


entity fifo_tb is

end entity;


architecture beh of fifo_tb is
component fifo IS									--- 生成的FIFO VHDL代码
	PORT
	(
		clock		: IN STD_LOGIC ;
		data		: IN STD_LOGIC_VECTOR (7 DOWNTO 0);
		rdreq		: IN STD_LOGIC ;
		sclr		: IN STD_LOGIC ;
		wrreq		: IN STD_LOGIC ;
		almost_empty		: OUT STD_LOGIC ;
		almost_full		: OUT STD_LOGIC ;
		empty		: OUT STD_LOGIC ;
		full		: OUT STD_LOGIC ;
		q		: OUT STD_LOGIC_VECTOR (7 DOWNTO 0);
		usedw		: OUT STD_LOGIC_VECTOR (7 DOWNTO 0)
	);
END component;

------------------------signal declaration-------------------
signal	clock				:	std_logic:='1';	
signal	data				:	std_logic_VECTOR (7 DOWNTO 0);	
signal	rdreq				:	std_logic;	
signal	sclr				:	std_logic;	
signal	wrreq				:	std_logic;	
signal	almost_empty	:	std_logic;
signal	almost_full		:	std_logic;
signal	empty				:	std_logic;
signal	full				:	std_logic;
signal	q					:	std_logic_VECTOR (7 DOWNTO 0);
signal   usedw				:  STD_LOGIC_VECTOR (7 DOWNTO 0);



begin

scfifo_com: component fifo							-- component 调用
	PORT map
	(
		clock				=>	clock,	
		data				=>	data,	
		rdreq				=>	rdreq,	
		sclr				=>	sclr,	
		wrreq				=>	wrreq,	
		almost_empty	=>	almost_empty,	
		almost_full		=>	almost_full,	
		empty				=>	empty,	
		full				=>	full,	
		q					=>	q,	
		usedw				=>	usedw	
	);

	
clock<= not clock after 10 ns;
sclr<='0';


process
begin
	data<=X"00";						--- 数据初始化
	rdreq<='0';
	wrreq<='0';
	wait for 201 ns;
	
	for i in 0 to 255 loop				-- 执行写操作,写入256个数据
		wrreq<='1';
		data<= conv_std_logic_vector(i, 8);
		wait for 20 ns;

	end loop;
	
		wrreq<='0';						-- 停止写入
		wait for 200 ns;
		
		
	for i in 0 to 255 loop				-- 执行读操作,读取256个数据
		rdreq<='1';
		wait for 20 ns;
		
	end loop;
	
		rdreq<='0';						-- 停止读操作
		
		wait for 200 ns;
		
		wait;							--仿真结束
	
end process;

end beh;
仿真结果

如下图所示是SCFIFO的写入操作,当时钟上升沿检测到wrreq写入使能信号有效时,立刻写入数据,usedw立刻+1,empty立即拉低。
scfifo_wr
如下图所示是SCFIFO读取的操作,当时钟上升沿检测到rdreq有效时,立即输出数据到q,并且usedw的有效个数立刻改变。
(PS: 因为usedw为8位,范围从0-255,因此当输入256个数据时,usedw会从255跳变到0)
sc_fifo_rd

DCFIFO

调用FIFO ip核,设置参数如下图所示,其余设置默认。产生一个混合位宽的双时钟FIFO。输入16位,输出8位。输出的时候,先输出低八位,再输出高八位。
dcfifo_ip1
dcfifo_ip2

生成相应的vhdl代码之后设置testbench仿真脚本部分如下:

rdclk<= not rdclk after 5 ns;
wrclk<= not wrclk after 10 ns;



process
begin
	data<=X"0000";
	rdreq<='0';
	wrreq<='0';
	wait for 201 ns;
	
	for i in 0 to 255 loop
		wrreq<='1';
		data<= conv_std_logic_vector(i+1024, 16);		--- +1024 是为了观察输出高八位的值
		wait for 20 ns;

	end loop;
	
		wrreq<='0';
		wait for 200 ns;
		
		
	for i in 0 to 255 loop
		rdreq<='1';
		wait for 20 ns;
		
	end loop;
	
		rdreq<='0';
		
		wait for 200 ns;
		
		wait;
	
end process;
仿真结果

写入数据:
当时钟上升沿检测到wrreq有效之后的下一个时钟上升沿才开始写入第一个数据,rdempty也从写入第一个数据之后的下一个时钟上升沿拉低
dcfifo_wr
读取数据:
当时钟上升沿检测到rdreq有效时,立刻输出数据(先输出低八位,再高八位),但是下一个时钟上升沿rdusedw信号改变
dcfifo_rd

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值