FIFO FWFT Adapter(First Word Fall Through) 预读FIFO适配器

预读fifo

修改了一下1:
增加了暂停预读信号stop。
修改2:
考虑一种情况,在没有预取的情况下,若fifo剩余的数据长度比预取流水线长度小,且在预取完成的前后一段时间内都没有读请求,empty流水线内会产生一段"气泡"。
此时若有新的数据写入fifo,预取流水线不会对这些“气泡”进行填充,如果能即时的填充这些气泡,应该能提高读请求的连续性。
修改3:
读请求是关键路径,会造成很大的延迟。增加了两种模式:1、超预取模式,2、普通预取模式

`timescale 1ns / 1ps
/*========================================FILE_HEADER=====================================
# Author          : WYM
# Create Time     : 2023-07-31 15:32
# Last modified   : 2023-07-31 15:32
# Filename        : fwft_adapt.sv
# Synthesizable   :  Vivado 2022.2
# FPGA Chip Model :  XC7A100T-2
# Description     : fwft_adapt.sv
#
#
=========================================FILE_HEADER====================================*/
module fwft_adapter
#(
    parameter DATA_WIDTH = 8,
    parameter PRE_DEPTH = 1,
    parameter FETCH_MODE = "normal"
)
(
    input rclk,
    input rst,
    
    input rden,
    output empty,
    output [DATA_WIDTH - 1 : 0]dout,

    input fifo_empty,
    output fifo_rden,
    input [DATA_WIDTH - 1 : 0]fifo_din
);

    reg [PRE_DEPTH : 0]pre_reg_ld = 0;
    reg [DATA_WIDTH - 1 : 0]pre_dout[PRE_DEPTH - 1 : 0];

    assign fifo_rden = ~fifo_empty & (|(~pre_reg_ld) | rden);

generate
    genvar i;

    if(FETCH_MODE == "super")begin
        wire [PRE_DEPTH : 0]pre_reg_ld_stop;
        // pre register load sig
        assign pre_reg_ld_stop[PRE_DEPTH] = ~rden & pre_reg_ld[PRE_DEPTH]; 
        always@(posedge rclk)
            if(rst)
                pre_reg_ld[0] <= 'd0;
            else if(~pre_reg_ld_stop[0])
                pre_reg_ld[0] <= fifo_rden;

        for(i = 0;i <PRE_DEPTH;i=i+1)
        begin
            assign pre_reg_ld_stop[i] = (fifo_empty | pre_reg_ld[i]) & pre_reg_ld_stop[i+1];
            always@(posedge rclk)
                if(rst)
                    pre_reg_ld[i+1] <= 'd0;
                else if(~pre_reg_ld_stop[i+1])
                    pre_reg_ld[i+1] <= pre_reg_ld[i];
        end

        // pre register data sig
        always@(posedge rclk)
            if(pre_reg_ld[0] & ~pre_reg_ld_stop[1])
                pre_dout[0] <= fifo_din;

        for(i = 0;i <PRE_DEPTH - 1;i=i+1)
        begin
            always@(posedge rclk)
                if(pre_reg_ld[i+1] & ~pre_reg_ld_stop[i+2])
                    pre_dout[i+1] <= pre_dout[i];
        end
end
else if(FETCH_MODE == "normal")begin
        wire pre_reg_ld_stop;
        // pre register load sig
        assign pre_reg_ld_stop = ~rden & pre_reg_ld[PRE_DEPTH]; 
        always@(posedge rclk)
            if(rst)
                pre_reg_ld[0] <= 'd0;
            else if(~pre_reg_ld_stop)
                pre_reg_ld[0] <= fifo_rden;

        for(i = 0;i <PRE_DEPTH;i=i+1)
        begin
            always@(posedge rclk)
                if(rst)
                    pre_reg_ld[i+1] <= 'd0;
                else if(~pre_reg_ld_stop)
                    pre_reg_ld[i+1] <= pre_reg_ld[i];
        end

        // pre register data sig
        always@(posedge rclk)
            if(pre_reg_ld[0] & ~pre_reg_ld_stop)
                pre_dout[0] <= fifo_din;

        for(i = 0;i <PRE_DEPTH - 1;i=i+1)
        begin
            always@(posedge rclk)
                if(pre_reg_ld[i+1] & ~pre_reg_ld_stop)
                    pre_dout[i+1] <= pre_dout[i];
        end
    end
endgenerate

    assign empty = ~pre_reg_ld[PRE_DEPTH];
    assign dout = pre_dout[PRE_DEPTH-1];
    

endmodule

posted @ 2023-08-01 11:26  已经吃不动了  阅读(235)  评论(1编辑  收藏  举报