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 128 129 130 131 132 133
|
//
// Copyright 2013 Ettus Research LLC
// Copyright 2018 Ettus Research, a National Instruments Company
//
// SPDX-License-Identifier: LGPL-3.0-or-later
//
// Quantize cvita packets to a configurable quantum value. o_tlast and
// i_tready will be held off until the entire quantized packet is xferred.
// If quantum is changed, it is the responsibility of the client to clear
// this module. error is asserted if a packet is larger than the quantum
// error can be reset by asserting reset or clear.
`default_nettype none
module cvita_chunker # (
parameter PAD_VALUE = 64'hFFFFFFFF_FFFFFFFF,
HOLD_ERROR = 1'b1 // If high, hold error until reset, else pulse
) (
input wire clk,
input wire reset,
input wire clear,
input wire [15:0] frame_size,
input wire [63:0] i_tdata,
input wire i_tlast,
input wire i_tvalid,
output reg i_tready,
output wire [63:0] o_tdata,
output wire o_tlast,
output reg o_tvalid,
input wire o_tready,
output wire error
);
localparam ST_HEADER = 2'd0;
localparam ST_DATA = 2'd1;
localparam ST_PADDING = 2'd2;
localparam ST_ERROR = 2'd3;
reg [1:0] state;
reg [15:0] frame_rem;
wire [15:0] cvita_len_ceil = i_tdata[47:32] + 16'd7;
wire [15:0] axi_len = {3'b000, cvita_len_ceil[15:3]};
always @(posedge clk) begin
if (reset | clear) begin
state <= ST_HEADER;
frame_rem <= 16'd0;
end else if ((state == ST_ERROR) & i_tlast & i_tvalid & !HOLD_ERROR) begin
state <= ST_HEADER;
frame_rem <= 16'd0;
end else if (o_tready) begin
case (state)
ST_HEADER: begin
if (i_tvalid) begin
if ((axi_len > frame_size) | (axi_len == 16'd0))
state <= ST_ERROR;
else if (i_tlast)
state <= ST_PADDING;
else
state <= ST_DATA;
frame_rem <= frame_size - 16'd1;
end
end
ST_DATA: begin
if (i_tvalid) begin
if (i_tlast) begin
state <= o_tlast ? ST_HEADER : ST_PADDING;
frame_rem <= o_tlast ? 16'd0 : (frame_rem - 16'd1);
end else begin
state <= ST_DATA;
frame_rem <= frame_rem - 16'd1;
end
end
end
ST_PADDING: begin
if (o_tlast) begin
state <= ST_HEADER;
frame_rem <= 16'd0;
end else begin
state <= ST_PADDING;
frame_rem <= frame_rem - 16'd1;
end
end
endcase
end
end
always @(*) begin
case (state)
ST_HEADER: begin
i_tready = o_tready;
o_tvalid = (axi_len <= frame_size) & (axi_len > 16'd0) & i_tvalid;
end
ST_DATA: begin
i_tready = o_tready;
o_tvalid = i_tvalid;
end
ST_PADDING: begin
i_tready = 1'b0;
o_tvalid = 1'b1;
end
ST_ERROR: begin
i_tready = 1'b1;
o_tvalid = 1'b0;
end
default: begin
i_tready = 1'b0;
o_tvalid = 1'b0;
end
endcase
end
assign o_tlast = (frame_rem != 16'd0) ? (frame_rem == 16'd1) : (axi_len == 16'd1);
assign o_tdata = (state == ST_PADDING) ? PAD_VALUE : i_tdata;
assign error = (state == ST_ERROR);
endmodule // cvita_chunker
`default_nettype wire
|