FPGA基本IP核之FIFO(异步)

异步FIFO

创建新的异步FIFO IP核,可以看出相比于同步FIFO这里做了写和读两侧并且各自用一个时钟

一般选用二级同步:

然后勾选读和写两侧需要用到的三种信号

选择添加额外的MSB,由于分成两侧时,中间不知道数据是否写满了或者写空了,添加此信号作为保护数据的作用,添加后位宽由7位变成了8位,多出的这一位用来判断是否写满;勾选异步清零。

模式选择正常模式:

生成文件:

代码

顶层文件

这里需要用到两个时钟,写时钟100M,读时钟50M,之前的博客里有关于PLL的讲解。

module test_ip (
    input          rst_n,
    input          clk,  

    input  [7:0]       data   ,
    input              rdreq  ,
    input              wrreq  ,
    output [7:0]       q           

);

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

    wire        c0        ;//25M
    wire        c1        ;//100M  90°
    wire        c2        ;//100M
    wire        c3        ;//25M  25%
    wire        c4        ;//70M
    wire        locked    ;
    wire        inclk     ;

pll pll_inst (
   .areset ( ~rst_n ),//根据cyclone iv手册,pll复位高电平有效,而设计的rst_n为低电平有效
   .inclk0 ( clk    ),
   .c0     ( c0     ),//25M
   .c1     ( c1     ),//100M  90°
   .c2     ( c2     ),//100M
   .c3     ( c3     ),//25M  25%
   .c4     ( c4     ),//70M
   .locked ( locked )
);

wire          wrclk    ;
wire          rdclk    ;

assign  wrclk  = c2  ;//100M
assign  rdclk  = clk ;//50M


a_fifo    a_fifo_inst (
    .aclr           ( ~rst_n   ),
    .data           ( data     ),
    .rdclk          ( rdclk    ),
    .rdreq          ( rdreq    ),
    .wrclk          ( wrclk    ),
    .wrreq          ( wrreq    ),
    .q              ( q        ),
    .rdempty        ( rdempty  ),
    .rdfull         ( rdfull   ),
    .rdusedw        ( rdusedw  ),
    .wrempty        ( wrempty  ),
    .wrfull         ( wrfull   ),
    .wrusedw        ( wrusedw  )
    );

endmodule

测试文件

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

    reg   [7:0]       data     ;  
    reg               rdreq    ; 
    reg               wrreq    ;
    wire  [7:0]       q        ;

    parameter CYCLE = 20;

test_ip u_test_ip (
    .rst_n (rst_n  ),  
    .clk   (clk    ),
    .data  (data   ),  
    .rdreq (rdreq  ),  
    .wrreq (wrreq  ),  
    .q     (q      )         
);

integer  i;

initial begin
    clk = 1'b1;

    rst_n = 1'b1 ;
    #(2*CYCLE);
    rst_n = 1'b0;
    data  = 0;
    rdreq = 0;
    wrreq = 0;

    rst_n = 1'b1;

    #(10*CYCLE);

    //读写

for (i = 0;i<16 ;i=i+1 ) begin//写数据
    wrreq = 1'b1;
    data  = {$random};
    #(CYCLE/2);//这步延时不能省,因为for循环是执行很快的,否则在modelsim中观察不到
end
wrreq = 1'b0;
#40;
for (i = 0;i<16 ;i=i+1 ) begin//读数据
    rdreq = 1'b1;
    #(CYCLE/2);
end
wrreq = 1'b0;
#(CYCLE);

$stop;
end

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

仿真分析

全局:

写数据请求拉高,写入第一个数据36,在下一个写时钟的上升沿对应的读数据空标志信号拉低,在下一个时钟上升沿检测到剩余可用数据量为1。

而读时钟信号在这个上升沿才检测到写请求空信号拉低。

由于在设置里选择的二级同步,从检测到写空信号拉低时,隔了两个读时钟才拉低读数据空信号。

而对于读数据的可用数据量,由于延时,在空信号拉低后的下一个上升沿检测到可用数据量,且为二级同步,在最开始写可用数据量为2的时候被检测,所以读可用数据量分别呈现为2,4,6...

往后分析,for循环16层,刚好写入16哥数据。当读请求拉高时,下一个时钟上升沿读出第一个数据36,后面依次读。

读完返回写侧,刚好是同步的,因为读写时钟是两倍关系,读一个时钟周期刚好可以采到两次

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值