(9)FIFO ip使用

一、FIFO简介

 

 二、FIFO ip使用

使用方案:

 操作:

在IP Catalog中找到这个

 配置fifo:

 生成ip:

 

项目生成bit流后的仿真结果:

 可以看到,写数据是写一段,然后全0,再写一段;读数据是先为254,再读一段,再置254,由下图可以更详细的看出FIFO读写的过程

 也可以看到,将空信号比空信号提前一个时钟拉高,将满信号比满信号提前一个时钟拉高

 

 


附:工程设计

设计架构:

 ip_fifo

module ip_fifo(
    input sys_clk,sys_rst_n
    );

wire    almost_empty   ;
wire    almost_full    ;
wire    fifo_wr_en     ;
wire  [7:0]  fifo_wr_data   ;
wire fifo_rd_en  ;
wire [7:0] dout;
wire full;
wire empty;
wire [7:0] rd_data_count;
wire [7:0] wr_data_count;

fifo_wr fifo_wr_u(
   .clk          (sys_clk)       ,         
   .rst_n        (sys_rst_n)       ,         
   .almost_empty (almost_empty)       ,
   .almost_full  (almost_full)       ,    
   .fifo_wr_en   (fifo_wr_en)       ,  
   .fifo_wr_data (fifo_wr_data)
);

fifo_rd fifo_rd_u(
   .clk          (sys_clk)       ,         
   .rst_n        (sys_rst_n)       ,         
   .almost_empty (almost_empty)       ,
   .almost_full  (almost_full)       ,    
   .fifo_rd_en   (fifo_rd_en)       
);

fifo_generator_0 fifo_generator_0_u (
  .wr_clk(sys_clk),                // input wire wr_clk
  .rd_clk(sys_clk),                // input wire rd_clk
  .din(fifo_wr_data),                      // input wire [7 : 0] din
  .wr_en(fifo_wr_en),                  // input wire wr_en
  .rd_en(fifo_rd_en),                  // input wire rd_en
  .dout(dout),                    // output wire [7 : 0] dout
  .full(full),                    // output wire full
  .almost_full(almost_full),      // output wire almost_full
  .empty(empty),                  // output wire empty
  .almost_empty(almost_empty),    // output wire almost_empty
  .rd_data_count(rd_data_count),  // output wire [7 : 0] rd_data_count
  .wr_data_count(wr_data_count)  // output wire [7 : 0] wr_data_count
);

ila_0 your_instance_name (
    .clk(sys_clk), // input wire clk
    .probe0(fifo_wr_en), // input wire [0:0]  probe0  
    .probe1(fifo_rd_en), // input wire [0:0]  probe1 
    .probe2(full), // input wire [0:0]  probe2 
    .probe3(empty), // input wire [0:0]  probe3 
    .probe4(fifo_wr_data), // input wire [7:0]  probe4 
    .probe5(dout), // input wire [7:0]  probe5 
    .probe6(rd_data_count), // input wire [7:0]  probe6 
    .probe7(wr_data_count), // input wire [7:0]  probe7 
    .probe8(almost_full), // input wire [0:0]  probe8 
    .probe9(almost_empty) // input wire [0:0]  probe9
);

endmodule

fifo_wr

`timescale 1ns / 1ps

module fifo_wr(
    input                       clk,
    input                       rst_n,
   //这里的两个信号都是快读空和快写满
    input                       almost_empty,
    input                       almost_full,
    
    output      reg             fifo_wr_en,
    output      reg  [7:0]      fifo_wr_data
    );
    
//抓取almost_empty信号的上升沿(异步时钟必须抓取其上升沿)
reg almost_empty_d0,almost_empty_d1;
wire syn;

assign syn = (!almost_empty_d1) &&  (almost_empty_d0);

always @(posedge clk or negedge rst_n)
    if(!rst_n) begin
        almost_empty_d0 <= 0;
        almost_empty_d1 <= 0;
    end
    else begin
        almost_empty_d0 <= almost_empty;
        almost_empty_d1 <= almost_empty_d0;
    end

//-----------------------------------------------//
reg [1:0] state;
reg [3:0] dly_cnt;
 always @(posedge clk or negedge rst_n)
    if(!rst_n) begin
        fifo_wr_en <= 0;
        fifo_wr_data <= 8'd0;
        state <= 2'b00;
        dly_cnt <= 4'b0;
    end
    else begin
        case(state) 
            2'b00:begin
                    if(syn)
                        state <= 2'b01;
                    else
                        state <= state;
                   end
             2'b01:begin
                    if(dly_cnt == 4'd10) begin
                        dly_cnt <= 4'd0;
                        state <= 2'b10;
                        fifo_wr_en <= 1;
                    end
                    else
                        dly_cnt <= dly_cnt + 1;
                    end
              2'b10:begin
                    if(almost_full) begin       //这里almost_full因为是在本时钟域下,因此可以直接使用
                        fifo_wr_en <= 0;
                        fifo_wr_data <= 8'd0;
                        state <= 2'b00; 
                    end
                    else begin
                        fifo_wr_en <= 1;   
                        fifo_wr_data <= fifo_wr_data + 1; 
                        end
                    end     
               default:
                      state <= 2'b00;
               endcase
            end
 
endmodule

fifo_rd

`timescale 1ns / 1ps

module fifo_rd(
    input                       clk,
    input                       rst_n,
    
    //这里的两个信号都是快读空和快写满
    input                       almost_empty,
    input                       almost_full,
    
    output      reg             fifo_rd_en,
    input        [7:0]      fifo_rd_data
    );
    
//抓取写满的标志位
reg almost_full_d0,almost_full_d1;
wire syn;

assign syn = (!almost_full_d1) &&  (almost_full_d0);

always @(posedge clk or negedge rst_n)
    if(!rst_n) begin
        almost_full_d0 <= 0;
        almost_full_d1 <= 0;
    end
    else begin
        almost_full_d0 <= almost_full;
        almost_full_d1 <= almost_full_d0;
    end

//-----------------------------------------------//
reg [1:0] state;
reg [3:0] dly_cnt;
 always @(posedge clk or negedge rst_n)
    if(!rst_n) begin
        fifo_rd_en <= 0;
        state <= 2'b00;
        dly_cnt <= 4'b0;
    end
    else begin
        case(state) 
            2'b00:begin
                    if(syn)
                        state <= 2'b01;
                    else
                        state <= state;
                   end
             2'b01:begin
                    if(dly_cnt == 4'd10) begin
                        dly_cnt <= 4'd0;
                        state <= 2'b10;
                    end
                    else
                        dly_cnt <= dly_cnt + 1;
                    end
              2'b10:begin
                    if(almost_empty) begin       //这里almost_full因为是在本时钟域下,因此可以直接使用
                        fifo_rd_en <= 0;
                        state <= 2'b00; 
                    end
                    else begin
                        fifo_rd_en <= 1;    
                        end
                    end     
               default:
                      state <= 2'b00;
               endcase
            end
    
endmodule

 

特别注意:

syn判定上升沿是两个判定条件相与,第一次写代码写成或了,结果耽误了很多调试时间

 

posted @ 2024-05-15 01:44  xuxuxu69  阅读(18)  评论(0编辑  收藏  举报