1
0
mirror of https://github.com/corundum/corundum.git synced 2025-01-16 08:12:53 +08:00
corundum/fpga/common/rtl/rx_fifo.v
Alex Forencich 6b256f82d3 Generate pause frames on TX
Signed-off-by: Alex Forencich <alex@alexforencich.com>
2023-09-10 23:22:50 -07:00

232 lines
7.3 KiB
Verilog

// SPDX-License-Identifier: BSD-2-Clause-Views
/*
* Copyright (c) 2021-2023 The Regents of the University of California
*/
// Language: Verilog 2001
`resetall
`timescale 1ns / 1ps
`default_nettype none
/*
* RX FIFO
*/
module rx_fifo #
(
// FIFO depth in words (each FIFO)
// KEEP_WIDTH words per cycle if KEEP_ENABLE set
// Rounded up to nearest power of 2 cycles
parameter FIFO_DEPTH = 4096,
// Width of FIFO depth status signals
parameter FIFO_DEPTH_WIDTH = $clog2(FIFO_DEPTH)+1,
// Number of AXI stream inputs
parameter PORTS = 4,
// Width of input AXI stream interfaces in bits
parameter S_DATA_WIDTH = 8,
// Propagate tkeep signal
parameter S_KEEP_ENABLE = (S_DATA_WIDTH>8),
// tkeep signal width (words per cycle)
parameter S_KEEP_WIDTH = (S_DATA_WIDTH/8),
// Width of output AXI stream interface in bits
parameter M_DATA_WIDTH = 8*PORTS,
// Propagate tkeep signal
parameter M_KEEP_ENABLE = (M_DATA_WIDTH>8),
// tkeep signal width (words per cycle)
parameter M_KEEP_WIDTH = (M_DATA_WIDTH/8),
// Propagate tid signal
parameter ID_ENABLE = 1,
// input tid signal width
parameter S_ID_WIDTH = 1,
// output tid signal width
parameter M_ID_WIDTH = PORTS > 1 ? $clog2(PORTS) : 1,
// Propagate tdest signal
parameter DEST_ENABLE = 0,
// tdest signal width
parameter DEST_WIDTH = 8,
// Propagate tuser signal
parameter USER_ENABLE = 1,
// tuser signal width
parameter USER_WIDTH = 1,
// number of RAM pipeline registers
parameter RAM_PIPELINE = 1
)
(
input wire clk,
input wire rst,
/*
* AXI Stream inputs
*/
input wire [PORTS*S_DATA_WIDTH-1:0] s_axis_tdata,
input wire [PORTS*S_KEEP_WIDTH-1:0] s_axis_tkeep,
input wire [PORTS-1:0] s_axis_tvalid,
output wire [PORTS-1:0] s_axis_tready,
input wire [PORTS-1:0] s_axis_tlast,
input wire [PORTS*S_ID_WIDTH-1:0] s_axis_tid,
input wire [PORTS*DEST_WIDTH-1:0] s_axis_tdest,
input wire [PORTS*USER_WIDTH-1:0] s_axis_tuser,
/*
* AXI Stream output
*/
output wire [M_DATA_WIDTH-1:0] m_axis_tdata,
output wire [M_KEEP_WIDTH-1:0] m_axis_tkeep,
output wire m_axis_tvalid,
input wire m_axis_tready,
output wire m_axis_tlast,
output wire [M_ID_WIDTH-1:0] m_axis_tid,
output wire [DEST_WIDTH-1:0] m_axis_tdest,
output wire [USER_WIDTH-1:0] m_axis_tuser,
/*
* Status
*/
output wire [FIFO_DEPTH_WIDTH*PORTS-1:0] status_depth,
output wire [FIFO_DEPTH_WIDTH*PORTS-1:0] status_depth_commit,
output wire [PORTS-1:0] status_overflow,
output wire [PORTS-1:0] status_bad_frame,
output wire [PORTS-1:0] status_good_frame
);
wire [PORTS*M_DATA_WIDTH-1:0] axis_fifo_tdata;
wire [PORTS*M_KEEP_WIDTH-1:0] axis_fifo_tkeep;
wire [PORTS-1:0] axis_fifo_tvalid;
wire [PORTS-1:0] axis_fifo_tready;
wire [PORTS-1:0] axis_fifo_tlast;
wire [PORTS*S_ID_WIDTH-1:0] axis_fifo_tid;
wire [PORTS*DEST_WIDTH-1:0] axis_fifo_tdest;
wire [PORTS*USER_WIDTH-1:0] axis_fifo_tuser;
generate
genvar n;
for (n = 0; n < PORTS; n = n + 1) begin : fifo
axis_fifo_adapter #(
.DEPTH(FIFO_DEPTH),
.S_DATA_WIDTH(S_DATA_WIDTH),
.S_KEEP_ENABLE(S_KEEP_ENABLE),
.S_KEEP_WIDTH(S_KEEP_WIDTH),
.M_DATA_WIDTH(M_DATA_WIDTH),
.M_KEEP_ENABLE(M_KEEP_ENABLE),
.M_KEEP_WIDTH(M_KEEP_WIDTH),
.ID_ENABLE(ID_ENABLE),
.ID_WIDTH(S_ID_WIDTH),
.DEST_ENABLE(DEST_ENABLE),
.DEST_WIDTH(DEST_WIDTH),
.USER_ENABLE(USER_ENABLE),
.USER_WIDTH(USER_WIDTH),
.RAM_PIPELINE(RAM_PIPELINE),
.FRAME_FIFO(1),
.USER_BAD_FRAME_VALUE(1'b1),
.USER_BAD_FRAME_MASK(1'b1),
.DROP_OVERSIZE_FRAME(1),
.DROP_BAD_FRAME(USER_ENABLE),
.DROP_WHEN_FULL(0),
.MARK_WHEN_FULL(0),
.PAUSE_ENABLE(0),
.FRAME_PAUSE(1)
)
fifo_inst (
.clk(clk),
.rst(rst),
// AXI input
.s_axis_tdata(s_axis_tdata[n*S_DATA_WIDTH +: S_DATA_WIDTH]),
.s_axis_tkeep(s_axis_tkeep[n*S_KEEP_WIDTH +: S_KEEP_WIDTH]),
.s_axis_tvalid(s_axis_tvalid[n +: 1]),
.s_axis_tready(s_axis_tready[n +: 1]),
.s_axis_tlast(s_axis_tlast[n +: 1]),
.s_axis_tid(s_axis_tid[n*S_ID_WIDTH +: S_ID_WIDTH]),
.s_axis_tdest(s_axis_tdest[n*DEST_WIDTH +: DEST_WIDTH]),
.s_axis_tuser(s_axis_tuser[n*USER_WIDTH +: USER_WIDTH]),
// AXI output
.m_axis_tdata(axis_fifo_tdata[n*M_DATA_WIDTH +: M_DATA_WIDTH]),
.m_axis_tkeep(axis_fifo_tkeep[n*M_KEEP_WIDTH +: M_KEEP_WIDTH]),
.m_axis_tvalid(axis_fifo_tvalid[n +: 1]),
.m_axis_tready(axis_fifo_tready[n +: 1]),
.m_axis_tlast(axis_fifo_tlast[n +: 1]),
.m_axis_tid(axis_fifo_tid[n*S_ID_WIDTH +: S_ID_WIDTH]),
.m_axis_tdest(axis_fifo_tdest[n*DEST_WIDTH +: DEST_WIDTH]),
.m_axis_tuser(axis_fifo_tuser[n*USER_WIDTH +: USER_WIDTH]),
// Pause
.pause_req(1'b0),
.pause_ack(),
// Status
.status_depth(status_depth[n*FIFO_DEPTH_WIDTH +: FIFO_DEPTH_WIDTH]),
.status_depth_commit(status_depth_commit[n*FIFO_DEPTH_WIDTH +: FIFO_DEPTH_WIDTH]),
.status_overflow(status_overflow[n]),
.status_bad_frame(status_bad_frame[n]),
.status_good_frame(status_good_frame[n])
);
end
if (PORTS > 1) begin : mux
axis_arb_mux #(
.S_COUNT(PORTS),
.DATA_WIDTH(M_DATA_WIDTH),
.KEEP_ENABLE(M_KEEP_ENABLE),
.KEEP_WIDTH(M_KEEP_WIDTH),
.ID_ENABLE(ID_ENABLE),
.S_ID_WIDTH(S_ID_WIDTH),
.M_ID_WIDTH(M_ID_WIDTH),
.DEST_ENABLE(DEST_ENABLE),
.DEST_WIDTH(DEST_WIDTH),
.USER_ENABLE(USER_ENABLE),
.USER_WIDTH(USER_WIDTH),
.LAST_ENABLE(1'b1),
.UPDATE_TID(1),
.ARB_TYPE_ROUND_ROBIN(1'b1),
.ARB_LSB_HIGH_PRIORITY(1'b1)
)
mux_inst (
.clk(clk),
.rst(rst),
// AXI Stream inputs
.s_axis_tdata(axis_fifo_tdata),
.s_axis_tkeep(axis_fifo_tkeep),
.s_axis_tvalid(axis_fifo_tvalid),
.s_axis_tready(axis_fifo_tready),
.s_axis_tlast(axis_fifo_tlast),
.s_axis_tid(axis_fifo_tid),
.s_axis_tdest(axis_fifo_tdest),
.s_axis_tuser(axis_fifo_tuser),
// AXI Stream output
.m_axis_tdata(m_axis_tdata),
.m_axis_tkeep(m_axis_tkeep),
.m_axis_tvalid(m_axis_tvalid),
.m_axis_tready(m_axis_tready),
.m_axis_tlast(m_axis_tlast),
.m_axis_tid(m_axis_tid),
.m_axis_tdest(m_axis_tdest),
.m_axis_tuser(m_axis_tuser)
);
end else begin
assign m_axis_tdata = axis_fifo_tdata;
assign m_axis_tkeep = axis_fifo_tkeep;
assign m_axis_tvalid = axis_fifo_tvalid;
assign axis_fifo_tready = m_axis_tready;
assign m_axis_tlast = axis_fifo_tlast;
assign m_axis_tid = axis_fifo_tid;
assign m_axis_tdest = axis_fifo_tdest;
assign m_axis_tuser = axis_fifo_tuser;
end
endgenerate
endmodule
`resetall