vivado的FIFO IP核

这是vivado中fifo的界面
在这里插入图片描述
下面依次介绍每个设置:


1.基本设置


在这里插入图片描述
fifo实现的方式有Common Clock同步和Independent Clocks异步两种,每种fifo下有四种存储形式:

Block RAM:使用FPGA内部的RAM
Distributed RAM:分布式RAM,使用内部的LUT和逻辑电路组成的fifo,
                当深度不大于128时可以使用
shift Register:移位寄存器形式,深度不大于32时可以使用
Built-in:内部自带的fifo,深度大于128可以使用

2.本地端口


Read Mode 读模式
    Standard FIFO 标准FIFO (选择这个模式,读出的数据会滞后读使能信号一个时间周期)
    First Word Fall Through 第一个写入数据将被从ram中提前读出到读数据线,
                           第一个数据有效与empty无效同时,即当empty无效时,
                           不必读取,数据线上的数据已经有效,读信号有效后,
                           读数据线将显示下一数据地址(读出的数据与读使能信号同一个时间周期)

Data Port Parameters   数据接口参数
	write width    写宽度
	write depth    写深度
	read width    读宽度
	read depth    读深度
	(后面读的设置通常与写的设置相同)

Initialization 初始化
	Reset Pin    复位引脚
	Enable safety Circuit    启用安全电路  一般都要选上
	Reset Type   复位类型,有两种
	        异步复位和同步复位
    Full Flag Reset Value 复位的值,0为低电平复位,1为高电平复位
    


3.标志位设置


optional flag    选择的标志
    Almost Full Flag    几乎满标志位
    Almost Empty Flag    几乎空标志位
Handshaking Options  握手选项   用于设计什么时候读,什么时候写
    write port handshaking 
    	write acknowledge    写标志位  分为高有效和低有效
    	overflow    溢出标志
    Read port handshaking 
    	valid flag    有效读
    	underflow flag    读空标志
Programmable Flags  自定义标志位     用于自定义什么是否写满和什么时候读空的标准
	programmable full type  

在整个IP文件夹中,.veo文件为模板文件,复制时使用这个

读写FIFO的操作

`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date: 2020/07/29 18:49:24
// Design Name: 
// Module Name: fifo_test
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////


module fifo_test(
    input clk,
    input rst_n
    );

    reg [15:0] w_data ; //FIFO写数据
    wire wr_en ; //FIFO写使能
    wire rd_en ; //FIFO读使能
    wire [15:0] r_data ; //FIFO读数据
    wire full ; //FIFO满信号
    wire empty ; //FIFO空信号
    wire [8:0] rd_data_count ; //可读数据数量
    wire [8:0] wr_data_count ; //已写入数据数量
    wire clk_100M ; //PLL产生100MHz时钟
    wire clk_75M ; //PLL产生100MHz时钟
    wire locked ; //PLL lock信号,可作为系统复位信号,高电平表示lock住
    wire fifo_rst_n ; //fifo复位信号, 低电平有效
    wire wr_clk ; //写FIFO时钟
    wire rd_clk ; //读FIFO时钟
    reg [7:0] wcnt ; //写FIFO复位后等待计数器
    reg [7:0] rcnt ; //读FIFO复位后等待计数器
    wire valid;      // 指示读数据有效

    reg reset_rd;

    //例化PLL,产生100MHz和75MHz时钟
    clk_wiz_0 fifo_pll
    (
    // Clock out ports
    .clk_out1(clk_100M), // output clk_out1
    .clk_out2(clk_75M), // output clk_out2
    // Status and control signals
    .reset(~rst_n), // input reset
    .locked(locked), // output locked
    // Clock in ports
    .clk_in1(clk) // input clk_in1
    ); 
    assign fifo_rst_n = locked ; //将PLL的LOCK信号赋值给fifo的复位信号
    assign wr_clk = clk_100M ; //100MHz时钟赋值给写时钟
    assign rd_clk = clk_75M ; //75MHz时钟赋值给读时钟
    /* 写FIFO状态机 */
    localparam W_IDLE = 1 ;
    localparam W_FIFO = 2 ;
    reg[2:0] write_state;
    reg[2:0] next_write_state;
    always@(posedge wr_clk or negedge fifo_rst_n) begin
        if(!fifo_rst_n)
            write_state <= W_IDLE;
        else
            write_state <= next_write_state;
    end

    always@(*) begin
        case(write_state)
            W_IDLE: begin
                if(wcnt == 8'd79) //复位后等待一定时间,等待最慢时钟60周期,只针对xilinx来说
                    next_write_state <= W_FIFO;
                else
                    next_write_state <= W_IDLE;
                end
            W_FIFO:
                next_write_state <= W_FIFO; //一直在写FIFO状态
            default: next_write_state <= W_IDLE;
        endcase
    end


    //在IDLE状态下,也就是复位之后,计数器计数
    always@(posedge wr_clk or negedge fifo_rst_n) begin
        if(!fifo_rst_n)
            wcnt <= 8'd0;
        else if (write_state == W_IDLE)
            wcnt <= wcnt + 1'b1 ;
        else
            wcnt <= 8'd0;
    end


    reg [7:0] wr_timer;
    always@(posedge wr_clk or negedge fifo_rst_n) begin
        if(!fifo_rst_n ) 
            wr_timer <= 0;
        else if (next_write_state == W_FIFO) 
            wr_timer <= wr_timer + 1'b1;
        else if (wr_timer == 8'd49) 
            wr_timer <= 8'd0;
    end


    //在写FIFO状态下,如果不满就向FIFO中写数据
    assign wr_en = (write_state == W_FIFO && wr_timer == 8'd49) ? ~full : 1'b0;
    //在写使能有效情况下,写数据值加1
    always@(posedge wr_clk or negedge fifo_rst_n) begin
        if(!fifo_rst_n)
            w_data <= 16'd1;
        else if (wr_en)
            w_data <= w_data + 1'b1;
    end



    /* 读FIFO状态机 */
    localparam R_IDLE = 1 ;
    localparam R_FIFO = 2 ;
    reg[2:0] read_state;
    reg[2:0] next_read_state;
    ///产生FIFO读的数据
    always@(posedge rd_clk or negedge fifo_rst_n) begin
        if(!fifo_rst_n)
            read_state <= R_IDLE;
        else
            read_state <= next_read_state;
    end

    always@(*) begin
        case(read_state)
            R_IDLE: begin
                if (rcnt == 8'd59) //复位后等待一定时间, 等待最慢时钟60周期,只针对xilinx来说
                    next_read_state <= R_FIFO;
                else
                    next_read_state <= R_IDLE;
            end
            R_FIFO:
                next_read_state <= R_FIFO ; //一直在读FIFO状态
            default: next_read_state <= R_IDLE;
    endcase
    end

    //在IDLE状态下,也就是复位之后,计数器计数
    always@(posedge rd_clk or negedge fifo_rst_n) begin
        if(!fifo_rst_n)
            rcnt <= 8'd0;
        else if (write_state == W_IDLE)
            rcnt <= rcnt + 1'b1 ;
        else
            rcnt <= 8'd0;
    end

    reg [7:0] rd_timer;
    always@(posedge rd_clk or negedge fifo_rst_n) begin
        if(!fifo_rst_n ) begin
            rd_timer <= 0;
            reset_rd <= 1;
        end
        else if (next_read_state == R_FIFO) begin
            reset_rd <= 0;
            rd_timer <= rd_timer + 1'b1;
        end
        else if (rd_timer == 8'd99) begin
            reset_rd <= 1;
            rd_timer <= 8'd0;
        end
    end
    //在读FIFO状态下,如果不空就从FIFO中读数据
    assign rd_en = (read_state == R_FIFO && rd_timer == 8'd99 ) ? ~empty : 1'b0;

    wire almost_full, wr_ack, overflow, almost_empty, underflow, wr_rst_busy, rd_rst_busy;

    //实例化FIFO
    fifo_generator_0 fifo_ip_inst 
    (
    .rst (~fifo_rst_n || reset_rd ), // input rst
    .wr_clk (wr_clk ), // input wr_clk
    .rd_clk (rd_clk ), // input rd_clk
    .din (w_data ), // input [15 : 0] din
    .wr_en (wr_en ), // input wr_en
    .rd_en (rd_en ), // input rd_en
    .dout (r_data ), // output [15 : 0] dout
    .full (full ), // output full
    .almost_full(almost_full),      // output wire almost_full
    .wr_ack(wr_ack),                // output wire wr_ack
    .overflow(overflow),            // output wire overflow
    .empty (empty ), // output empty
    .almost_empty(almost_empty),    // output wire almost_empty
    .valid(valid),                  // output wire valid
    .underflow(underflow),          // output wire underflow
    .rd_data_count (rd_data_count), // output [8 : 0] rd_data_count
    .wr_data_count (wr_data_count), // output [8 : 0] wr_data_count
    .wr_rst_busy(wr_rst_busy),      // output wire wr_rst_busy  为0是才能开始读写
    .rd_rst_busy(rd_rst_busy)      // output wire rd_rst_busy
    );

endmodule

标准的读操作
标准的读操作
FWFT的标准的读操作
FWFT的标准的读操作
对于复位来说
在这里插入图片描述

  • 15
    点赞
  • 98
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值