(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判定上升沿是两个判定条件相与,第一次写代码写成或了,结果耽误了很多调试时间