1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127
|
//
// Copyright 2018 Ettus Research, A National Instruments Company
//
// SPDX-License-Identifier: LGPL-3.0-or-later
//
// Module: chdr_ingress_buff
// Description:
// Ingress buffer module that does the following:
// - Stores and gates an incoming packet
// - Looks up destination in routing table and attaches a tdest for the packet
module chdr_xb_ingress_buff #(
parameter WIDTH = 64,
parameter SIZE = 5,
parameter XB_NPORTS = 8,
parameter SID_OFFSET = 0,
parameter SID_WIDTH = 16
) (
input wire clk,
input wire reset,
// CHDR input port
input wire [WIDTH-1:0] s_axis_chdr_tdata,
input wire s_axis_chdr_tlast,
input wire s_axis_chdr_tvalid,
output wire s_axis_chdr_tready,
// CHDR output port (with a tdest and tkeep)
output wire [WIDTH-1:0] m_axis_chdr_tdata,
output wire [$clog2(XB_NPORTS)-1:0] m_axis_chdr_tdest,
output wire m_axis_chdr_tkeep,
output wire m_axis_chdr_tlast,
output wire m_axis_chdr_tvalid,
input wire m_axis_chdr_tready,
// Find port going to routing table
output wire [SID_WIDTH-1:0] m_axis_find_tdata,
output wire m_axis_find_tvalid,
input wire m_axis_find_tready,
// Result port from routing table
input wire [$clog2(XB_NPORTS)-1:0] s_axis_result_tdata,
input wire s_axis_result_tkeep,
input wire s_axis_result_tvalid,
output wire s_axis_result_tready
);
//----------------------------------------------------
// Payload packet state tracker
//----------------------------------------------------
localparam [0:0] ST_HEAD = 1'd0;
localparam [0:0] ST_BODY = 1'd1;
reg [0:0] in_state = ST_HEAD, out_state = ST_HEAD;
always @(posedge clk) begin
if (reset) begin
in_state <= ST_HEAD;
end else if (s_axis_chdr_tvalid & s_axis_chdr_tready) begin
if (in_state == ST_HEAD) begin
in_state <= ST_BODY;
end else begin
in_state <= s_axis_chdr_tlast ? ST_HEAD : ST_BODY;
end
end
end
always @(posedge clk) begin
if (reset) begin
out_state <= ST_HEAD;
end else if (m_axis_chdr_tvalid & m_axis_chdr_tready) begin
if (out_state == ST_HEAD) begin
out_state <= ST_BODY;
end else begin
out_state <= m_axis_chdr_tlast ? ST_HEAD : ST_BODY;
end
end
end
//----------------------------------------------------
// Packet buffer and destination FIFO
//----------------------------------------------------
wire pkt_gate_i_tready, pkt_gate_o_tvalid, find_fifo_i_tready;
axi_packet_gate #(.WIDTH(WIDTH), .SIZE(SIZE)) pkt_gate_i (
.clk (clk),
.reset (reset),
.clear (1'b0),
.i_tdata (s_axis_chdr_tdata),
.i_tlast (s_axis_chdr_tlast),
.i_tvalid (s_axis_chdr_tvalid & s_axis_chdr_tready), //NOTE: Violates AXIS but OK since FIFO downstream
.i_tready (pkt_gate_i_tready),
.i_terror (1'b0),
.o_tdata (m_axis_chdr_tdata),
.o_tlast (m_axis_chdr_tlast),
.o_tvalid (pkt_gate_o_tvalid),
.o_tready (m_axis_chdr_tready)
);
axi_fifo #(.WIDTH(SID_WIDTH), .SIZE(1)) find_fifo_i (
.clk (clk),
.reset (reset),
.clear (1'b0),
.i_tdata (s_axis_chdr_tdata[SID_OFFSET+:SID_WIDTH]),
.i_tvalid ((in_state == ST_HEAD) & s_axis_chdr_tvalid & s_axis_chdr_tready), //NOTE: Violates AXIS but OK since FIFO downstream
.i_tready (find_fifo_i_tready),
.o_tdata (m_axis_find_tdata),
.o_tvalid (m_axis_find_tvalid),
.o_tready (m_axis_find_tready),
.space (),
.occupied ()
);
assign s_axis_chdr_tready = pkt_gate_i_tready & (in_state == ST_HEAD ? find_fifo_i_tready : 1'b1);
wire dst_fifo_o_tvalid;
axi_fifo #(.WIDTH($clog2(XB_NPORTS)+1), .SIZE(1)) res_fifo_i (
.clk (clk),
.reset (reset),
.clear (1'b0),
.i_tdata ({s_axis_result_tkeep, s_axis_result_tdata}),
.i_tvalid (s_axis_result_tvalid),
.i_tready (s_axis_result_tready),
.o_tdata ({m_axis_chdr_tkeep, m_axis_chdr_tdest}),
.o_tvalid (dst_fifo_o_tvalid),
.o_tready (m_axis_chdr_tready & m_axis_chdr_tvalid & (out_state == ST_HEAD)),
.space (),
.occupied ()
);
assign m_axis_chdr_tvalid = pkt_gate_o_tvalid & (out_state == ST_HEAD ? dst_fifo_o_tvalid : 1'b1);
endmodule
|