FPGA-基本IP核的应用-FIFO(同步)

基本概念

FIFO的英文全称为First In First Out,即先进先出。FPGA使用的FIFO一般指的是对数据的存储具有先进先出的特性的一个缓存器,常被用于数据的缓存或者高速异步数据的交互,也即所谓的跨时钟域信号传递(发送和接收不是同一个时钟)。

它与FPGA内部的RAM和ROM的区别是没有外部读写地址线,采取顺序写入数据,顺序读出数据的方式,使用起来简单方便,由此带来的缺点就是不能像RAM和ROM那样可以由地址线决定读取或写入某个指定的地址

 

创建IP

先做同步时钟(单时钟FIFO)情况下

 设置FIFO的位宽,即传输数据的位宽,深度为传输128字节的数据,选择单时钟FIFO

 设置引脚

full为数据满时的标志信号,empty为空数据标志信号,usedw[]为剩余的可用数据量;

almost empty/almost full 将满/将空 标志信号,当剩余数据量将满/将空时,对应信号拉高;

Asynchronous clear 异步清零;

Synchronous clear同步清零;

一般使用异步清零。

选择读请求信号的类型,此处选择正常模式的FIFO,即数据在读请求发出后有效;

选择存储的数据类型,此处以自动Auto为例。

 不需要用更多空间换取最大的性能,但需要电能保护。

 仍然生成.v文件

 再创建一个前写模式s_fifo_ah.v,存储数据256字节,选择另一种模式,在读请求之前数据有效,生成.v文件。

 

打开生成的inst文件

 

将其复制到test_ip文件里,并修改端口连接信息 

测试代码

顶层test_ip.v

module test_ip (
    input          rst_n,
    input          clk,

    input  [7:0]       no_data   ,
    input              no_rdreq  ,
    input              no_wrreq  ,            
    output [7:0]       no_q      ,  

    input  [7:0]       ah_data   ,
    input              ah_rdreq  ,
    input              ah_wrreq  ,
    output [7:0]       ah_q           

);

      wire              no_empty ;
      wire              no_full  ;
      wire    [6:0]     no_usedw ;

	  wire              ah_empty ; 
      wire              ah_full  ;  
	  wire    [7:0]     ah_usedw ; 


s_fifo	s_fifo_inst (
	.aclr  ( ~rst_n   ),
	.clock ( clk      ),
	.data  ( no_data  ),
	.rdreq ( no_rdreq ),
	.wrreq ( no_wrreq ),
	.empty ( no_empty ),
	.full  ( no_full  ),
	.q     ( no_q     ),
	.usedw ( no_usedw )
	);

s_fifo_ah	s_fifo_ah_inst (
	.aclr  ( ~rst_n   ),
	.clock ( clk      ),
	.data  ( ah_data  ),
	.rdreq ( ah_rdreq ),
	.wrreq ( ah_wrreq ),
	.empty ( ah_empty ),
	.full  ( ah_full  ),
	.q     ( ah_q     ),
	.usedw ( ah_usedw )
	);

endmodule

测试文件

`timescale 1ns/1ps
module test_tb();
    reg               rst_n       ; 
    reg               clk         ; 

    reg   [7:0]       no_data     ;  
    reg               no_rdreq    ; 
    reg               no_wrreq    ;
    wire  [7:0]       no_q        ;

    reg   [7:0]       ah_data     ;  
    reg               ah_rdreq    ; 
    reg               ah_wrreq    ; 
    wire  [7:0]       ah_q        ;    

  
    parameter CYCLE = 20;

test_ip u_test_ip (
	.rst_n    ( rst_n   ),
	.clk      ( clk     ),
	.no_data  (no_data  ),
    .no_rdreq (no_rdreq ),
    .no_wrreq (no_wrreq ),
    .no_q     (no_q     ),

    .ah_data  (ah_data  ),
    .ah_rdreq (ah_rdreq ),
    .ah_wrreq (ah_wrreq ),
    .ah_q     (ah_q     )

);

	integer i ;

initial begin
	clk = 1'b1;
	rst_n = 1'b1;
	#(2*CYCLE);
	#5;

	rst_n = 1'b0;
    no_data  = 0 ;//复位给定信号初值
    no_rdreq = 0 ;
    no_wrreq = 0 ;

    ah_data  = 0 ;
    ah_rdreq = 0 ;
    ah_wrreq = 0 ;


	#(5*CYCLE);
	rst_n = 1'b1;//复位释放
	#(CYCLE*10);//延迟10个时钟是为了打开时钟锁得到稳定的时钟信号

//写数据
    for(i=0;i<32;i=i+1) begin
        no_wrreq = 1'b1    ;
	    no_data = i + 1   ;//data给1到64

		ah_wrreq = 1'b1   ;
        ah_data  = i + 1  ;
	    #(CYCLE)     ;//保证一个时钟周期写写完一个数据
end 
    no_wrreq = 1'b0    ;//写完数据拉低
	ah_wrreq = 1'b0    ;
    #(5*CYCLE)   ;

//读数据
    for (i=0;i<16;i=i+1) begin
		no_rdreq = 1'b1    ;
        ah_rdreq = 1'b1    ;//写数据读地址
        #(CYCLE*2)     ;//保证一个是时钟周期读完一个数据
	end   //这个for循环,内部三行代码,在时钟上升沿到来时且读请求拉高时读一个数据,持续两个时钟周期读2个数据,相当于执行依次循环读2个数据,for循环要经历16次,所以循环内读了32个数据
	    no_rdreq = 1'b0    ; 
        ah_rdreq = 1'b0    ;    //读完数据拉低
	#(20*CYCLE)   ;
	
	$stop;
end

always #(CYCLE/2)  clk = ~clk ;//50M
endmodule

test.do文件(修改自己的对应文件路径)

vlib work
vmap work work

#编译testbench文件
vlog     test_tb.v
#编译   设计文件
vlog     ../ip/s_fifo.v
vlog     ../ip/s_fifo_ah.v
vlog     ../rtl/test_ip.v

vlog     altera_mf.v


#指定仿真顶层
vsim -novopt work.test_tb
#添加信号到波形窗
add wave -position insertpoint sim:/test_tb//*

run -all

另外,由于正常模式和前写模式fifo生成的ip文件里没有用到eccstatus端口,需要注释掉

 仿真分析

全局:

先分析正常模式下,

上图定位出可以看出,写写请求拉高时有了第一个数据,而当在下一个始终上升沿时,此时已经有了数据,空数据标志拉低(它是在数据写入的同时拉低,表明可能是组合逻辑),可用数据量为1,q端无变化。

 然后观察读数据波形:

当读请求拉高时,在下一个时钟上升沿读出数据1,之前写入了32个数据,读出1个数后,剩余可用数据量为31个

 到最后读完时,输出32个数据,剩余可用数据为0,与此同时空信号标志拉高,数据读完后读请求拉低。

 然后分析前写模式:

对比两种模式下,正常模式是在读请求拉高后才有数据,而前写模式fifo在读请求拉高之前就已经输出了一个数据,并知道拉高之后再输出第二个数据。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值