diff options
Diffstat (limited to 'fpga/usrp3')
| -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 +    //---------------------------------------------------------------------------  | 
