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 134 135 136 137 138 139 140 141 142 143 144
|
//
// Copyright 2013, 2014 Ettus Research LLC
// Copyright 2018 Ettus Research, a National Instruments Company
//
// SPDX-License-Identifier: LGPL-3.0-or-later
//
module chdr_8s_to_16s #
(
parameter BASE=0
)
(
input clk,
input rst,
// axi4 stream slave interface
input [63:0] i_tdata,
input i_tlast,
input i_tvalid,
output i_tready,
// axi4 stream master interface
output reg [63:0] o_tdata,
output o_tlast,
output o_tvalid,
input o_tready,
// settings bus slave interface
input set_stb,
input [7:0] set_addr,
input [31:0] set_data,
output [31:0] debug
);
// split up the input for lazyness reasons
wire [7:0] fixed0 = i_tdata[63:56];
wire [7:0] fixed1 = i_tdata[55:48];
wire [7:0] fixed2 = i_tdata[47:40];
wire [7:0] fixed3 = i_tdata[39:32];
wire [7:0] fixed4 = i_tdata[31:24];
wire [7:0] fixed5 = i_tdata[23:16];
wire [7:0] fixed6 = i_tdata[15:8];
wire [7:0] fixed7 = i_tdata[7:0];
// Parse CHDR info
wire chdr_has_time = i_tdata[61];
// CHDR has either 8 bytes of header or 16 if VITA time is included.
wire [15:0] chdr_header_bytes = chdr_has_time ? 16 : 8;
// Calculate size of samples input in bytes by taking CHDR size field
// and subtracting header length.
wire [15:0] sample_byte_count_in = i_tdata[47:32] - chdr_header_bytes;
// Calculate size of samples by taking input size
// and multiplying by two
wire [15:0] sample_byte_count_out = sample_byte_count_in << 1;
// Calculate size of output CHDR packet by adding back header size to new
// payload size.
wire [15:0] output_chdr_pkt_size = sample_byte_count_out + chdr_header_bytes;
// Make routing (SID) available via settings bus
wire set_sid;
wire [15:0] new_sid_dst;
setting_reg #
(
.my_addr(BASE),
.width(17)
)
new_destination
(
.clk(clk),
.rst(rst),
.strobe(set_stb),
.addr(set_addr),
.in(set_data),
.out({set_sid, new_sid_dst[15:0]}),
.changed()
);
wire handshake_ok = i_tvalid & o_tready;
//state declarations
localparam HEADER = 2'd0;
localparam TIME = 2'd1;
localparam ODD = 2'd2;
localparam EVEN = 2'd3;
reg [1:0] state;
reg end_on_odd;
always @(posedge clk) begin
if (rst) begin
state <= HEADER;
end_on_odd <= 1'b0;
end
else case(state)
HEADER:
// if we get a premature end of burst,
// we just stick around for the next header
if (handshake_ok & !i_tlast) begin
state <= (i_tdata[61])? TIME : ODD;
end_on_odd <= (i_tdata[34:32] > 0) && (i_tdata[34:32] < 5);
end
TIME:
// if we get a premature i_tlast we bail out, else proceed
if (handshake_ok)
state <= (i_tlast)? HEADER: ODD;
ODD:
if (handshake_ok)
state <= (i_tlast & end_on_odd) ? HEADER : EVEN;
EVEN:
if (handshake_ok)
state <= (i_tlast) ? HEADER: ODD;
default:
state <= HEADER;
endcase
end
always @(*)
case(state)
HEADER:
o_tdata = {i_tdata[63:48], output_chdr_pkt_size,
set_sid ? {i_tdata[15:0], new_sid_dst[15:0]} : i_tdata[31:0]};
TIME:
o_tdata = i_tdata;
ODD:
o_tdata = {fixed0, 8'h0, fixed1, 8'h0, fixed2, 8'h0, fixed3, 8'h0};
EVEN:
o_tdata = {fixed4, 8'h0, fixed5, 8'h0, fixed6, 8'h0, fixed7, 8'h0};
default:
o_tdata = i_tdata;
endcase
assign o_tvalid = i_tvalid;
assign i_tready = o_tready && ((state != ODD) || (i_tlast & end_on_odd));
assign o_tlast = i_tlast && ((state == EVEN) || ((state == ODD) & end_on_odd));
endmodule
|