通用 AXIS 异步 FIFO

module axis_async_fifo #(
parameter integer DATA_WIDTH = 8,
parameter integer USER_WIDTH = 1,
parameter integer FIFO_DEPTH = 1024,
parameter HAS_LAST = 1'b1,
parameter HAS_USER = 1'b0,
parameter FIFO_MEMORY_TYPE = "auto"
)(
input wire s_clk_i, // 写侧时钟
input wire s_rst_n_i, // 写侧同步低有效复位
input wire [DATA_WIDTH-1:0] s_data_i, // 写侧数据
input wire s_valid_i, // 写侧有效
output wire s_ready_o, // 写侧ready
input wire s_last_i, // 写侧last
input wire [USER_WIDTH-1:0] s_user_i, // 写侧user

input wire m_clk_i, // 读侧时钟
input wire m_rst_n_i, // 读侧同步低有效复位
output wire [DATA_WIDTH-1:0] m_data_o, // 读侧数据
output wire m_valid_o, // 读侧有效
input wire m_ready_i, // 读侧ready
output wire m_last_o, // 读侧last
output wire [USER_WIDTH-1:0] m_user_o, // 读侧user

output wire full_o, // FIFO满
output wire empty_o // FIFO空
);

localparam integer LAST_WIDTH = HAS_LAST ? 1 : 0;
localparam integer USER_W = HAS_USER ? USER_WIDTH : 0;
localparam integer FIFO_WIDTH = DATA_WIDTH + LAST_WIDTH + USER_W;
localparam integer CNT_WIDTH = $clog2(FIFO_DEPTH) + 1;

wire [FIFO_WIDTH-1:0] fifo_din_w; // FIFO写数据
wire [FIFO_WIDTH-1:0] fifo_dout_w; // FIFO读数据
wire wr_en_w; // 写使能
wire rd_en_w; // 读使能
wire full_w; // 满
wire empty_w; // 空

generate
if (HAS_LAST && HAS_USER) begin : gen_last_user
assign fifo_din_w = {s_user_i, s_last_i, s_data_i};
assign m_user_o = fifo_dout_w[DATA_WIDTH+1 +: USER_WIDTH];
assign m_last_o = fifo_dout_w[DATA_WIDTH];
assign m_data_o = fifo_dout_w[DATA_WIDTH-1:0];
end
else if (HAS_LAST) begin : gen_last_only
assign fifo_din_w = {s_last_i, s_data_i};
assign m_user_o = {USER_WIDTH{1'b0}};
assign m_last_o = fifo_dout_w[DATA_WIDTH];
assign m_data_o = fifo_dout_w[DATA_WIDTH-1:0];
end
else if (HAS_USER) begin : gen_user_only
assign fifo_din_w = {s_user_i, s_data_i};
assign m_user_o = fifo_dout_w[DATA_WIDTH +: USER_WIDTH];
assign m_last_o = 1'b0;
assign m_data_o = fifo_dout_w[DATA_WIDTH-1:0];
end
else begin : gen_data_only
assign fifo_din_w = s_data_i;
assign m_user_o = {USER_WIDTH{1'b0}};
assign m_last_o = 1'b0;
assign m_data_o = fifo_dout_w[DATA_WIDTH-1:0];
end
endgenerate

assign s_ready_o = ~full_w;
assign wr_en_w = s_valid_i && s_ready_o;

assign m_valid_o = ~empty_w;
assign rd_en_w = m_valid_o && m_ready_i;

assign full_o = full_w;
assign empty_o = empty_w;

xpm_fifo_async #(
.CDC_SYNC_STAGES (2),
.DOUT_RESET_VALUE ("0"),
.ECC_MODE ("no_ecc"),
.FIFO_MEMORY_TYPE (FIFO_MEMORY_TYPE),
.FIFO_READ_LATENCY (0),
.FIFO_WRITE_DEPTH (FIFO_DEPTH),
.FULL_RESET_VALUE (0),
.PROG_EMPTY_THRESH (10),
.PROG_FULL_THRESH (FIFO_DEPTH-10),
.RD_DATA_COUNT_WIDTH (CNT_WIDTH),
.READ_DATA_WIDTH (FIFO_WIDTH),
.READ_MODE ("fwft"),
.RELATED_CLOCKS (0),
.SIM_ASSERT_CHK (0),
.USE_ADV_FEATURES ("0000"),
.WAKEUP_TIME (0),
.WRITE_DATA_WIDTH (FIFO_WIDTH),
.WR_DATA_COUNT_WIDTH (CNT_WIDTH)
) u_xpm_fifo_async (
.rst (~s_rst_n_i),

.wr_clk (s_clk_i),
.wr_en (wr_en_w),
.din (fifo_din_w),
.full (full_w),

.rd_clk (m_clk_i),
.rd_en (rd_en_w),
.dout (fifo_dout_w),
.empty (empty_w),

.overflow (),
.underflow (),
.prog_full (),
.prog_empty (),
.wr_data_count (),
.rd_data_count (),
.wr_rst_busy (),
.rd_rst_busy (),
.almost_full (),
.almost_empty (),
.data_valid (),
.injectdbiterr (1'b0),
.injectsbiterr (1'b0),
.sleep (1'b0),
.sbiterr (),
.dbiterr ()
);

endmodule

posted @ 2026-06-16 13:23  Oppenic  阅读(5)  评论(0)    收藏  举报