diff options
Diffstat (limited to 'fpga')
-rw-r--r-- | fpga/usrp3/lib/rfnoc/core/axis_data_to_chdr.v | 175 |
1 files changed, 117 insertions, 58 deletions
diff --git a/fpga/usrp3/lib/rfnoc/core/axis_data_to_chdr.v b/fpga/usrp3/lib/rfnoc/core/axis_data_to_chdr.v index 6a5b3ce05..2ff5a1ee7 100644 --- a/fpga/usrp3/lib/rfnoc/core/axis_data_to_chdr.v +++ b/fpga/usrp3/lib/rfnoc/core/axis_data_to_chdr.v @@ -11,27 +11,42 @@ // with sideband information for packet flags and timestamp). A CHDR packet // will be generated for each data packet that is input. // -// The sideband information (e.g., timestamp, flags) must be input coincident -// with the AXI-Stream data input and will be sampled coincident with the -// last word of data in the packet (i.e., when tlast is asserted). +// The sideband information (e.g., timestamp, flags) must be input with the +// AXI-Stream data input and will be sampled coincident with either the first +// word or the last word of data in the packet (i.e., when tlast is +// asserted), depending on the SIDEBAND_AT_END parameter setting. +// +// If sideband information is sampled at the beginning of a packet then +// tlength must be provided. +// +// If sideband information is sampled at the end of the packet then tlength +// will be ignored, and the entire packet will be buffered before the CHDR +// output can begin. Also, in this mode, the payload FIFO size will be +// coerced to be at least as big as the MTU. This mode is intended for cases +// when the sideband information is not known until the end of the packet +// (e.g., the length). // // This module also performs an optional clock crossing and data width // conversion from a user requested width for the payload bus to CHDR_W. // // Parameters: // -// CHDR_W : Width of the input CHDR bus in bits -// ITEM_W : Width of the output item bus in bits -// NIPC : The number of output items delivered per cycle -// SYNC_CLKS : Are the CHDR and data clocks synchronous to each other? -// MTU : Log2 of the maximum packet size in CHDR words -// INFO_FIFO_SIZE : Log2 of the info FIFO size. This determines the number of -// packets that can be simultaneously buffered in the -// payload FIFO. -// PYLD_FIFO_SIZE : Log2 of the payload FIFO size. The actual FIFO size will -// be the maximum of 2**MTU or 2**PYLD_FIFO_SIZE, since the -// FIFO must be at least one MTU so that we can calculate -// the packet length in the header. +// CHDR_W : Width of the input CHDR bus in bits +// ITEM_W : Width of the output item bus in bits +// NIPC : The number of output items delivered per cycle +// SYNC_CLKS : Are the CHDR and data clocks synchronous to each other? +// MTU : Log2 of the maximum packet size in CHDR words +// INFO_FIFO_SIZE : Log2 of the info FIFO size. This determines the number +// of packets that can be simultaneously buffered in the +// payload FIFO. +// PYLD_FIFO_SIZE : Log2 of the payload FIFO size. The actual FIFO size will +// be the maximum of 2**MTU or 2**PYLD_FIFO_SIZE, since the +// FIFO must be at least one MTU so that we can calculate +// the packet length in the header. +// SIDEBAND_AT_END : If 0 then the sideband information is sampled coincident +// with the first word of the input packet. If 1, then the +// sideband information is sampled with the last word of the +// input packet (the word in which tlast is asserted). // // Signals: // @@ -41,13 +56,14 @@ // module axis_data_to_chdr #( - parameter CHDR_W = 256, - parameter ITEM_W = 32, - parameter NIPC = 2, - parameter SYNC_CLKS = 0, - parameter MTU = 10, - parameter INFO_FIFO_SIZE = 5, - parameter PYLD_FIFO_SIZE = MTU + parameter CHDR_W = 256, + parameter ITEM_W = 32, + parameter NIPC = 2, + parameter SYNC_CLKS = 0, + parameter MTU = 10, + parameter INFO_FIFO_SIZE = 5, + parameter PYLD_FIFO_SIZE = MTU, + parameter SIDEBAND_AT_END = 1 )( // Clock, reset and settings input wire axis_chdr_clk, @@ -68,6 +84,7 @@ module axis_data_to_chdr #( // Payload sideband info input wire [63:0] s_axis_ttimestamp, input wire s_axis_thas_time, + input wire [15:0] s_axis_tlength, input wire s_axis_teov, input wire s_axis_teob, // Flush signals @@ -77,11 +94,11 @@ module axis_data_to_chdr #( output wire flush_done ); - // Make sure the payload FIFO is large enough to store an entire packet's - // worth of payload data. This will ensure that we can buffer the entire - // packet to calculate its length. - localparam PAYLOAD_FIFO_SIZE = PYLD_FIFO_SIZE > MTU ? - PYLD_FIFO_SIZE : MTU; + // If we are sampling the sideband information at the end of the packet then + // the payload FIFO must be large enough to store an entire packet's worth of + // payload data. We coerce the size here if needed. + localparam PAYLOAD_FIFO_SIZE = + (!SIDEBAND_AT_END || PYLD_FIFO_SIZE > MTU) ? PYLD_FIFO_SIZE : MTU; // --------------------------------------------------- @@ -93,12 +110,24 @@ module axis_data_to_chdr #( //--------------------------------------------------------------------------- - // Timestamp and Flags Capture + // Start of Packet Register //--------------------------------------------------------------------------- - // - // The timestamp and flags that we use for each packet is that of the last - // data word. Here, we capture this information at the end of the packet. - // + + // The sop register will indicate if the next word on s_axis_t* is the first + // word of a packet. + reg start_of_packet = 1'b1; + + always @(posedge axis_data_clk) begin + if (axis_data_rst) begin + start_of_packet <= 1'b1; + end else if (s_axis_tvalid && s_axis_tready) begin + start_of_packet <= s_axis_tlast; + end + end + + + //--------------------------------------------------------------------------- + // Timestamp and Flags Capture //--------------------------------------------------------------------------- reg [63:0] packet_timestamp; @@ -107,7 +136,10 @@ module axis_data_to_chdr #( reg packet_eob; always @(posedge axis_data_clk) begin - if (s_axis_tvalid & s_axis_tready & s_axis_tlast) begin + if (s_axis_tvalid && s_axis_tready && + (( SIDEBAND_AT_END && s_axis_tlast) || + (!SIDEBAND_AT_END && start_of_packet)) + ) begin packet_timestamp <= s_axis_ttimestamp; packet_has_time <= s_axis_thas_time; packet_eov <= s_axis_teov; @@ -121,43 +153,70 @@ module axis_data_to_chdr #( //--------------------------------------------------------------------------- // // Here We track the state of the incoming packet to determine the payload - // length. + // length, if needed. // //--------------------------------------------------------------------------- - localparam HDR_LEN = CHDR_W/8; // Length of CHDR header word in bytes - - reg [15:0] packet_length; - reg [15:0] length_count = HDR_LEN; reg in_pkt_info_tvalid = 0; wire in_pkt_info_tready; + reg [15:0] packet_length; - always @(posedge axis_data_clk) begin : pkt_length_counter - if (axis_data_rst) begin - length_count <= HDR_LEN; - in_pkt_info_tvalid <= 1'b0; - end else begin : pkt_length_counter_main - // Calculate the length of this word in bytes, taking tkeep into account - integer i; - integer num_bytes; - num_bytes = 0; - for (i = 0; i < NIPC; i = i + 1) begin - num_bytes = num_bytes + (s_axis_tkeep[i]*(ITEM_W/8)); + localparam HDR_LEN = CHDR_W/8; // Length of CHDR header word in bytes + + generate + if (!SIDEBAND_AT_END) begin : gen_sample_sop + //------------------------------- + // Sample at Start of Packet + //------------------------------- + + always @(posedge axis_data_clk) begin + if (axis_data_rst) begin + in_pkt_info_tvalid <= 1'b0; + end else begin + in_pkt_info_tvalid <= 1'b0; + if (s_axis_tvalid && s_axis_tready && start_of_packet) begin + packet_length <= s_axis_tlength + HDR_LEN; + in_pkt_info_tvalid <= 1'b1; + end + end end - // Update the packet length if the word is accepted - in_pkt_info_tvalid <= 1'b0; - if (s_axis_tvalid && s_axis_tready) begin - if (s_axis_tlast) begin + end else begin : gen_sample_eop + //------------------------------- + // Sample at End of Packet + //------------------------------- + + reg [15:0] length_count = HDR_LEN; + + always @(posedge axis_data_clk) begin : pkt_length_counter + if (axis_data_rst) begin length_count <= HDR_LEN; - packet_length <= length_count + num_bytes; - in_pkt_info_tvalid <= 1'b1; - end else begin - length_count <= length_count + num_bytes; + in_pkt_info_tvalid <= 1'b0; + end else begin : pkt_length_counter_main + // Calculate the length of this word in bytes, taking tkeep into account + integer i; + integer num_bytes; + num_bytes = 0; + for (i = 0; i < NIPC; i = i + 1) begin + num_bytes = num_bytes + (s_axis_tkeep[i]*(ITEM_W/8)); + end + + // Update the packet length if the word is accepted + in_pkt_info_tvalid <= 1'b0; + if (s_axis_tvalid && s_axis_tready) begin + if (s_axis_tlast) begin + length_count <= HDR_LEN; + packet_length <= length_count + num_bytes; + in_pkt_info_tvalid <= 1'b1; + end else begin + length_count <= length_count + num_bytes; + end + end end end end - end + endgenerate + //--------------------------------------------------------------------------- |