FPGA中IP核的调用——DCFIFO实验

1、FIFO IP 核简介
FIFO(First In First Out,即先入先出),是一种数据缓冲器,用来实现数据先入先出的读写方式。与 ROM 或 RAM 的按地址读写方式不同, FIFO 的读写遵循“先进先出”的原则,即数据按顺序写入 FIFO,先被写入的数据同样在读取的时候先被读出,所以 FIFO存储器没有地址线。 FIFO 有一个写端口和一个读端口外部无需使用者控制地址,使用方便。
FIFO 存储器主要是作为缓存,应用在同步时钟系统和异步时钟系统中,在很多的设计中都会使用,后面实例中如:多比特数据做跨时钟域的转换、前后带宽不同步等都用到了FIFO。 FIFO 根据读写时钟是否相同,分为 SCFIFO(同步 FIFO)和 DCFIFO(异步FIFO), SCFIFO 的读写为同一时钟,应用在同步时钟系统中; DCFIFO 的读写时钟不同,应用在异步时钟系统中。


2、如何调用FIFO

直接在vivado中,点击左上角IP catalog选项,输入FIFO进行搜索,选择FIFO Generator进入FIFO的配置。

SCFIFO(同步 FIFO)和 DCFIFO(异步FIFO)两者的调用方法基本一致,只是在于是使用“common Clock Block RAM”还是使用“Independent Clock Block RAM”,这里我们以DCFIFO的调用为例。

使用块 RAM 来实现异步 FIFO;其中 Independent Clock 表示是异步FIFO, Block RAM 表示的是块 RAM 资源。

依次进行DCFIFO的各个参数配置,之后再生成产品即可。

3、顶层调用代码编写

在.v文件中调用FIFO模块(FIFO模块可在其.voe文件中找到,直接复制过来)。

`timescale 1ns / 1ps



module IP_DCFIFO1(
 input wire wr_clk,
 input wire rd_clk,
 input wire rst_n,
 input wire [7:0] din,
 input wire wr_en,
 input wire rd_en,
 
 output wire [15:0] dout,
 output wire full,
 output wire empty,
 output [6:0] rd_da_cnt,
 output [7:0] wr_da_cnt
 
    );
    
    
IP_dcfifo_8x256 ip_dcfifo1 (
  .wr_clk(wr_clk),                // input wire wr_clk
  .rd_clk(rd_clk),                // input wire rd_clk
  .din(din),                      // input wire [7 : 0] din
  .wr_en(wr_en),                  // input wire wr_en
  .rd_en(rd_en),                  // input wire rd_en
  .dout(dout),                    // output wire [15 : 0] dout
  .full(full),                    // output wire full
  .empty(empty),                  // output wire empty
  .rd_data_count(rd_da_cnt),  // output wire [6 : 0] rd_data_count
  .wr_data_count(wr_da_cnt)  // output wire [7 : 0] wr_data_count
);
endmodule

4、编写仿真代码

在仿真代码中给各个输入激励。

我们给予了两个异步的时钟信号,写时钟频率为50MHz,读时钟频率为25MHz。

在调用DCFIFO时,我们这里设置的是写入数据为8位宽,读出数据为16位宽,仿真时也这样设计,以便完整地显示出读出数。

下面将演示如何在跨时钟域工程中使用DCFIFO完成数据的写入读出。

`timescale 1ns / 1ps


module IP_DCFIFO_tb(    );
reg wr_clk;   
reg rd_clk;   
reg rst_n;    
reg [7:0] din;      
reg wr_en;    
reg rd_en;
//reg [1:0] cnt_baud; 
reg full_reg0;
reg full_reg1;   
         
wire [15:0] dout;     
wire full;     
wire empty;    
wire [6:0] rd_da_cnt;
wire [7:0] wr_da_cnt;

initial
  begin
  wr_clk <= 1'b1;
  rd_clk <= 1'b1;
  rst_n <= 1'b0;
  #20
  rst_n <= 1'b1;
  #100000
  rst_n <= 1'b0;
  end

always #10 wr_clk = ~wr_clk;
always #20 rd_clk = ~rd_clk;

always @(posedge wr_clk or rst_n)
    if (rst_n == 1'b0)
       din <= 8'd0;
    else if ((din == 8'd255) && (wr_en == 1'd1))
       din <= 8'd0;
    else if (wr_en == 1'd1)
       din <= din + 8'd1;
    else 
       ;

always @(posedge wr_clk or rst_n)
    if (rst_n == 1'b0)
       wr_en <= 1'd0;
   else if ((full == 1'd1) && (rd_en <= 1'd1))
       wr_en <= 1'd0;
    else if((rd_en <= 1'd0)&& (empty <= 1'd1))
       wr_en <= 1'd1;
    else
       ;


//读取数据激励
always @(posedge rd_clk or rst_n)
    if (rst_n == 1'b0)
       begin
       full_reg0 <= 1'd0;
       full_reg1 <= 1'd0;
       end
    else   //rd_clk打两拍,full仍然为高电平再进行读取
       begin
       full_reg0 <= full;
       full_reg1 <= full_reg0;
       end

always @(posedge rd_clk or rst_n)
    if (rst_n == 1'b0)
       rd_en <= 1'd0;
//如果 full 信号有效就立刻读,则不会看到 full 信号拉高,
//所以此处使用 full 在 rd_clk 时钟下打两拍后的信号
   else if (full_reg1 == 1'd1)
       rd_en <= 1'd1;
    else if (empty == 1'b1)
       rd_en <= 1'd0;
    else
       ;


IP_DCFIFO1 ip_dcfifo_tb(
 .wr_clk    (wr_clk   ),
 .rd_clk    (rd_clk   ),
 .rst_n     (rst_n    ),
 .din       (din      ),
 .wr_en     (wr_en    ),
 .rd_en     (rd_en    ),

 .dout      (dout     ),
 .full      (full     ),
 .empty     (empty    ),
 .rd_da_cnt (rd_da_cnt),
 .wr_da_cnt (wr_da_cnt)
    );
endmodule

5、仿真结果

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在异步FIFO IP调用,首先需要进行FIFO IP的参数配置。然后,编写顶层模块的FIFO调用代码。这个代码示例如下: module fifo ( input wire sys_clk, input wire sys_clk2, input wire [7:0 pi_data, input wire rd_req, input wire wr_req, output wire empty, output wire full, output wire [7:0 po_data, output wire [7:0 usedw ); dcfifo_8x256 dcfifo_8x256_inst ( .clock1 (sys_clk), .clock2 (sys_clk2), .data (pi_data), .rdreq (rd_req), .wrreq (wr_req), .empty (empty), .full (full), .q (po_data), .usedw (usedw) ); endmodule 在这个顶层模块的FIFO调用代码,我们使用了异步FIFO IP,其包括两个时钟信号:sys_clk和sys_clk2。同时,还有输入信号,如写请求信号(wr_req)、读请求信号(rd_req)和输入数据信号(pi_data),以及输出信号,如空状态信号(empty)、满状态信号(full)、输出数据信号(po_data)和已使用字节信号(usedw)。通过这个FIFO调用代码,可以实现对异步FIFO IP调用。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [FIFO IP 调用](https://blog.csdn.net/ziyouruf/article/details/123862569)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 50%"] - *2* [FPGAFIFO IP配置与调用](https://blog.csdn.net/m0_72885897/article/details/128649678)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值