Yeah, I agree with that assessment. I don't know what the problem is,
either. For reference, though, here's the relevant parts of a
two-input-one-output RFNoC block I did. This works for me.

Note that NUM_PORTS can be anything you want. I'm currently using
NUM_PORTS=2. NUM_CHANNELS is 4, since I'm putting two streams into each
sc16 input.

  // RFNoC Shell
  wire [31:0]             set_data[0:NUM_PORTS-1];
  wire [7:0]              set_addr[0:NUM_PORTS-1];
  wire [NUM_PORTS-1:0] set_stb;
  reg [63:0] rb_data[0:NUM_PORTS-1];
  wire [7:0] rb_addr[0:NUM_PORTS-1];

  wire [63:0]   cmdout_tdata, ackin_tdata;
  wire          cmdout_tlast, cmdout_tvalid, cmdout_tready, ackin_tlast,
ackin_tvalid, ackin_tready;

  wire [NUM_PORTS-1:0] clear_tx_seqnum;

  wire [63:0] str_sink_tdata;
  wire str_sink_tlast, str_sink_tvalid, str_sink_tready;

  wire [63:0] str_src_tdata[0:NUM_PORTS-1];
  wire [NUM_PORTS-1:0] str_src_tlast, str_src_tvalid, str_src_tready;

  wire [15:0] src_sid[0:NUM_PORTS-1];
  wire [15:0] resp_in_dst_sid;
  wire [15:0] resp_out_dst_sid[0:NUM_PORTS-1];

  // Set next destination in chain
  wire [15:0] next_dst[0:NUM_PORTS-1];

  // AXI Wrapper
  // input (sink) data
  wire [31:0]  in_tdata;
  wire [127:0] in_tuser;
  wire in_tlast, in_tvalid, in_tready;

  // predistorter output data (four of these)
  wire [15:0]  out_tdata[0:NUM_CHANNELS-1];
  wire [NUM_CHANNELS-1:0] out_tlast, out_tvalid, out_tready;

  wire [127:0] out_tuser[0:NUM_PORTS-1]; //only two of these

//----------------------------------------------------------------------------
  // Instantiations

//----------------------------------------------------------------------------

  // RFNoC Shell
  noc_shell #(
    .NOC_ID(NOC_ID),
    .STR_SINK_FIFOSIZE(STR_SINK_FIFOSIZE[7:0]),
    .INPUT_PORTS(1),
    .OUTPUT_PORTS(NUM_PORTS))
  noc_shell (
    .bus_clk(bus_clk),
    .bus_rst(bus_rst),
    .i_tdata(i_tdata),
    .i_tlast(i_tlast),
    .i_tvalid(i_tvalid),
    .i_tready(i_tready),
    .o_tdata(o_tdata),
    .o_tlast(o_tlast),
    .o_tvalid(o_tvalid),
    .o_tready(o_tready),
    // Compute Engine Clock Domain
    .clk(ce_clk),
    .reset(ce_rst),
    // Control Sink
    .set_data({set_data[1], set_data[0]}),
    .set_addr({set_addr[1], set_addr[0]}),
    .set_stb({set_stb[1], set_stb[0]}),
    .rb_data({rb_data[1], rb_data[0]}),
    .rb_stb({NUM_PORTS{1'b1}}),
    .rb_addr({rb_addr[1], rb_addr[0]}),
    // Control Source (unused)
    .cmdout_tdata(cmdout_tdata),
    .cmdout_tlast(cmdout_tlast),
    .cmdout_tvalid(cmdout_tvalid),
    .cmdout_tready(cmdout_tready),
    .ackin_tdata(ackin_tdata),
    .ackin_tlast(ackin_tlast),
    .ackin_tvalid(ackin_tvalid),
    .ackin_tready(ackin_tready),
    .resp_in_dst_sid({resp_in_dst_sid[1], resp_in_dst_sid[0]}),
    .resp_out_dst_sid({resp_out_dst_sid[1], resp_out_dst_sid[0]}),
    // Stream Sink
    .str_sink_tdata(str_sink_tdata),
    .str_sink_tlast(str_sink_tlast),
    .str_sink_tvalid(str_sink_tvalid),
    .str_sink_tready(str_sink_tready),
    // Stream Sources //TODO ideally should be parameterized for
NUM_CHANNELS
    .str_src_tdata({str_src_tdata[1], str_src_tdata[0]}),
    .str_src_tlast(str_src_tlast),
    .str_src_tvalid(str_src_tvalid),
    .str_src_tready(str_src_tready),
    .src_sid({src_sid[1], src_sid[0]}),
    .next_dst_sid({next_dst[1], next_dst[0]}),
    .clear_tx_seqnum(clear_tx_seqnum),
    .debug(debug));

  assign ackin_tready = 1'b1;

<......snip.......>

  wire [31:0] mux_tdata[0:NUM_PORTS-1];
  wire [NUM_PORTS-1:0] mux_tlast, mux_tvalid, mux_tready;

   axi_wrapper #(
      .SIMPLE_MODE(0) /* Handle header internally */)
   axi_wrapper_inst (
      .clk(ce_clk), .reset(ce_rst),
      .clear_tx_seqnum(clear_tx_seqnum[0]),
      .next_dst(next_dst[0]),
      .set_stb(), .set_addr(), .set_data(),
      .i_tdata(str_sink_tdata), .i_tlast(str_sink_tlast),
.i_tvalid(str_sink_tvalid), .i_tready(str_sink_tready),
      .o_tdata(str_src_tdata[0]), .o_tlast(str_src_tlast[0]),
.o_tvalid(str_src_tvalid[0]), .o_tready(str_src_tready[0]),
      .m_axis_data_tdata(in_tdata),
      .m_axis_data_tlast(in_tlast),
      .m_axis_data_tvalid(in_tvalid),
      .m_axis_data_tready(in_tready),
      .m_axis_data_tuser(in_tuser),
      .s_axis_data_tdata(mux_tdata[0]),
      .s_axis_data_tlast(mux_tlast[0]),
      .s_axis_data_tvalid(mux_tvalid[0]),
      .s_axis_data_tready(mux_tready[0]),
      .s_axis_data_tuser(out_tuser[0]),
      .m_axis_config_tdata(),
      .m_axis_config_tlast(),
      .m_axis_config_tvalid(),
      .m_axis_config_tready(),
      .m_axis_pkt_len_tdata(),
      .m_axis_pkt_len_tvalid(),
      .m_axis_pkt_len_tready());

  genvar u;
  generate
    for (u = 1; u < NUM_PORTS; u = u + 1) begin
      axi_wrapper #(
         .SIMPLE_MODE(0) /* Handle header internally */)
      axi_wrapper_inst (
         .clk(ce_clk), .reset(ce_rst),
         .clear_tx_seqnum(clear_tx_seqnum[u]),
         .next_dst(next_dst[u]),
         .set_stb(), .set_addr(), .set_data(),
         .i_tdata(), .i_tlast(), .i_tvalid(), .i_tready(),
         .o_tdata(str_src_tdata[u]), .o_tlast(str_src_tlast[u]),
.o_tvalid(str_src_tvalid[u]), .o_tready(str_src_tready[u]),
         .m_axis_data_tdata(),
         .m_axis_data_tlast(),
         .m_axis_data_tvalid(),
         .m_axis_data_tready(),
         .m_axis_data_tuser(),
         .s_axis_data_tdata(mux_tdata[u]),
         .s_axis_data_tlast(mux_tlast[u]),
         .s_axis_data_tvalid(mux_tvalid[u]),
         .s_axis_data_tready(mux_tready[u]),
         .s_axis_data_tuser(out_tuser[u]),
         .m_axis_config_tdata(),
         .m_axis_config_tlast(),
         .m_axis_config_tvalid(),
         .m_axis_config_tready(),
         .m_axis_pkt_len_tdata(),
         .m_axis_pkt_len_tvalid(),
         .m_axis_pkt_len_tready());
   end
  endgenerate

  genvar s;
  generate
    for (s = 0; s < NUM_PORTS; s = s + 1) begin
      // Handle headers
      cvita_hdr_modify cvita_hdr_modify_inst (
         .header_in(in_tuser),
         .header_out(out_tuser[s]),
         .use_pkt_type(1'b0),  .pkt_type(),
         .use_has_time(1'b0),  .has_time(),
         .use_eob(1'b0),       .eob(),
         .use_seqnum(1'b0),    .seqnum(),
         .use_length(1'b0),    .length(),
         .use_src_sid(1'b1),   .src_sid(src_sid[s]),
         .use_dst_sid(1'b1),   .dst_sid(next_dst[s]),
         .use_vita_time(1'b0), .vita_time());
    end
  endgenerate

<.....snip.......>


Nick


On Tue, Sep 26, 2017 at 8:24 AM Dario Pennisi <da...@iptronix.com> wrote:

> Hi Nick,
>
> Sure. The block is a demodulator so basically it inputs samples and
> outputs packet bytes in bursts so of course we have rate change.
>
> The relevant code is below:
>
>
>
>   cvita_hdr_decoder cvita_hdr_decoder0 (
>
>   .header(m_axis0_data_tuser),
>
>   .pkt_type(), .eob(),    .has_time(),
>
>   .seqnum(),   .length(), .payload_length(),
>
>   .src_sid(),  .dst_sid(),
>
>   .vita_time(vita_time_in[0])
>
>   );
>
>   cvita_hdr_decoder cvita_hdr_decoder1 (
>
>   .header(m_axis01_data_tuser),
>
>   .pkt_type(), .eob(),    .has_time(),
>
>   .seqnum(),   .length(), .payload_length(),
>
>   .src_sid(),  .dst_sid(),
>
>   .vita_time(vita_time_in[1])
>
>   );
>
>
>
>   cvita_hdr_encoder cvita_hdr_encoder (
>
>     .pkt_type(2'd0), .eob(1'b1), .has_time(1'b1),
>
>     .seqnum(0), .payload_length(0), .dst_sid(next_dst_sid[0]),
> .src_sid(src_sid[0]),
>
>     .vita_time(vita_time_out),
>
>     .header(s_axis0_data_tuser));
>
>
>
> Basically I extract the time from incoming packets and then use that to
> feed timestamp to the processing logic which outputs its timestamp in
>  vita_time_out.
>
> Since I am outputting bursts I am setting eob and has time and since I
> don’t know packet length in advance I set length to 0.
>
> src_sid and dst_sid are set equal to those decoded by noc shell for the
> first channel.
>
>
>
> The one thing I don’t understand here is what has this to do with the fact
> that one input channel is not streaming…
>
> As I mentioned in this condition my first input channel is streaming data
> and processing logic connected to it is working perfectly and outputting
> decoded data which I can receive correctly on the host. The problem is that
> data is not being streamed to the second input channel (or at least if it
> is then it’s not being demultiplexed by noc shell). I can’t see any logic
> that makes cvita hdr, which is sent to the output, dependent on what’s on
> the input….
>
>
>
> Dario Pennisi
>
>
>
> *From:* Nick Foster [mailto:bistrom...@gmail.com]
> *Sent:* Tuesday, September 26, 2017 5:16 PM
> *To:* Dario Pennisi <da...@iptronix.com>; usrp-users@lists.ettus.com
>
>
> *Subject:* Re: [USRP-users] rfnoc block with two inputs
>
>
>
> Dario,
>
>
>
> Glad simulation appears to be working.
>
>
>
> Since you aren't using simple mode in the AXI wrapper (I assume because
> you're rate-changing inside the block, or some such) can you post the
> section of your code which handles the VITA headers?
>
>
>
> Nick
>
>
>
> On Tue, Sep 26, 2017 at 5:15 AM Dario Pennisi <da...@iptronix.com> wrote:
>
> Hi,
>
> I managed to get a good simulation for the two inputs. I did it by
> modifying default test bench this way:
>
>    - localparam NUM_STREAMS    = 2;  // Number of test bench streams
>    - modified RFNOC_CONNECT to two RFNOC_CONNECT_BLOCK_PORT calls each
>    with a different port. Port 0 of TB connected to port 0 of DUT and port 1
>    of TB connected to port 1 of DUT
>    - modified data streaming part with two calls to tb_streamer.send each
>    with a different channel
>
>
>
> this way I can see data being pumped in on both ports, at least in
> simulation. IP does what it should so at this point I tend to think there
> is no issue on the FPGA side.
>
>
>
> Since I am connecting to two radio blocks and since internal bus is 166
> MHz/64 bit I modified the device3 arguments to "master_clock_rate=120e6",
> this way I would have 120MSPS at 32 bit x 2 muxed on the input bus of the
> IP. This should leave enough room for overhead.
>
>
>
> Now. In these conditions I still don’t see data coming from the second
> channel so am thinking that the issue must be on the software side.
>
>
>
> Any help would be greatly appreciated.
>
> Thanks,
>
>
>
> Dario Pennisi
>
> *From:* Dario Pennisi
> *Sent:* Tuesday, September 26, 2017 12:00 PM
>
>
> *To:* usrp-users@lists.ettus.com; Nick Foster <bistrom...@gmail.com>
>
> *Subject:* RE: [USRP-users] rfnoc block with two inputs
>
>
>
> Hi,
>
> I moved forward a bit but didn’t really come up to a solution.
>
> In my block I doublechecked the signals which are replicated for each
> input and made sure they are connected at top level. This turned out to be
> apparently useless because I only have one output so src_sid and dst_sid
> for the second input channel are basically not going anywhere as there is
> no second output.
>
> Is it at all possible to have 2 inputs and 1 output or there is a strict
> need to have the same number of inputs and outputs?
>
> On the host side which are the points I can tap into to check what’s going
> on?
>
>
>
> I also would be interested in trying simulation but didn’t find any
> example of simulation with 2 inputs.
>
> Thanks,
>
>
>
> Dario Pennisi
>
> *From:* Dario Pennisi
> *Sent:* Monday, September 25, 2017 11:11 PM
> *To:* usrp-users@lists.ettus.com; Nick Foster <bistrom...@gmail.com>
> *Subject:* Re: [USRP-users] rfnoc block with two inputs
>
>
>
> Hi Nick,
>
> Thank you for your feedback. I didn't notice src and data Sid are per
> input however looking at code I don't think this is the problem. My
> understanding is that src Sid is used to form cvita packet going out of the
> block. In simple mode axis wrapper doesn't seem to use while it is used by
> cvita encoder used for tuser. In my case I have 2 inputs and 1 output. I am
> using Sid form channel 0 to create cvita header for the output.
>
> Since I don't have a second output it seems to me src and day Sid for 2nd
> input are not used anyway...
>
> For the rest there doesn't seem to be any other connection.
>
> Am I missing something?
>
> Btw is there any example of a block with 2 in and 1 out? I found only
> addsub which has 2 out and is not even using axis wrapper...
>
> Thanks
>
> Dario Pennisi
>
>
>
>
>
>
>
> On Mon, Sep 25, 2017 at 9:28 PM +0200, "Nick Foster" <bistrom...@gmail.com>
> wrote:
>
> Couple of problems just offhand.
>
>
>
> * src_sid is a one-per-input signal. See noc_shell.v for details.
>
> * Settings buses and readback buses are one-per (max(input, output)).
> Again, see noc_shell.v. I don't think this is a problem for you, though.
>
>
>
> You should be getting errors in simulation (or warnings in synthesis)
> right now. Look very carefully through these warnings to see which signals
> are undriven. My guess is src_sid is undriven on the top 16 bits and so you
> can't set src_sid correctly for input 1.
>
>
>
> Nick
>
>
>
> On Mon, Sep 25, 2017 at 12:00 PM Dario Pennisi <da...@iptronix.com> wrote:
>
> Hi,
>
> It’s quite complex and long… posting the initial part with shell and
> wrappers
>
>
>
> module noc_block_demod #(
>
>   parameter NOC_ID = 64'h1408E12980FDE75E,
>
>   parameter MAX_PACKET_SIZE = 64)
>
> (
>
>   input bus_clk, input bus_rst,
>
>   input ce_clk, input ce_rst,
>
>   input  [63:0] i_tdata, input  i_tlast, input  i_tvalid, output i_tready,
>
>   output [63:0] o_tdata, output o_tlast, output o_tvalid, input  o_tready,
>
>   output [63:0] debug
>
> );
>
>
>
>   ////////////////////////////////////////////////////////////
>
>   //
>
>   // RFNoC Shell
>
>   //
>
>   ////////////////////////////////////////////////////////////
>
>   wire [31:0] set_data;
>
>   wire [7:0]  set_addr;
>
>   wire        set_stb;
>
>   reg         rb_stb;
>
>   reg  [63:0] rb_data;
>
>   wire [7:0]  rb_addr;
>
>
>
>   wire [63:0] cmdout_tdata, ackin_tdata;
>
>   wire        cmdout_tlast, cmdout_tvalid, cmdout_tready, ackin_tlast,
> ackin_tvalid, ackin_tready;
>
>
>
>   wire [2*64-1:0] str_sink_tdata;
>
>   wire [1:0]       str_sink_tlast, str_sink_tvalid, str_sink_tready;
>
>
>
>   wire [63:0] str_src_tdata;
>
>   wire        str_src_tlast, str_src_tvalid, str_src_tready;
>
>
>
>   wire [15:0] src_sid;
>
>   wire [15:0] next_dst_sid, resp_out_dst_sid;
>
>   wire [15:0] resp_in_dst_sid;
>
>
>
>   wire        clear_tx_seqnum;
>
>
>
>   noc_shell #(
>
>     .NOC_ID(NOC_ID),
>
>     .INPUT_PORTS(2)
>
>     )
>
>   noc_shell (
>
>     .bus_clk(bus_clk), .bus_rst(bus_rst),
>
>     .i_tdata(i_tdata), .i_tlast(i_tlast), .i_tvalid(i_tvalid),
> .i_tready(i_tready),
>
>     .o_tdata(o_tdata), .o_tlast(o_tlast), .o_tvalid(o_tvalid),
> .o_tready(o_tready),
>
>     // Computer Engine Clock Domain
>
>     .clk(ce_clk), .reset(ce_rst),
>
>     // Control Sink
>
>     .set_data(set_data), .set_addr(set_addr), .set_stb(set_stb),
>
>     .rb_stb(rb_stb), .rb_data(rb_data), .rb_addr(rb_addr),
>
>     // Control Source
>
>     .cmdout_tdata(cmdout_tdata), .cmdout_tlast(cmdout_tlast),
> .cmdout_tvalid(cmdout_tvalid), .cmdout_tready(cmdout_tready),
>
>     .ackin_tdata(ackin_tdata), .ackin_tlast(ackin_tlast),
> .ackin_tvalid(ackin_tvalid), .ackin_tready(ackin_tready),
>
>     // Stream Sink
>
>     .str_sink_tdata(str_sink_tdata), .str_sink_tlast(str_sink_tlast),
> .str_sink_tvalid(str_sink_tvalid), .str_sink_tready(str_sink_tready),
>
>     // Stream Source
>
>     .str_src_tdata(str_src_tdata), .str_src_tlast(str_src_tlast),
> .str_src_tvalid(str_src_tvalid), .str_src_tready(str_src_tready),
>
>     // Stream IDs set by host
>
>     .src_sid(src_sid),                   // SID of this block
>
>     .next_dst_sid(next_dst_sid),         // Next destination SID
>
>     .resp_in_dst_sid(resp_in_dst_sid),   // Response destination SID for
> input stream responses / errors
>
>     .resp_out_dst_sid(resp_out_dst_sid), // Response destination SID for
> output stream responses / errors
>
>     // Misc
>
>     .vita_time('d0), .clear_tx_seqnum(clear_tx_seqnum),
>
>     .debug(debug));
>
>
>
>   ////////////////////////////////////////////////////////////
>
>   //
>
>   // AXI Wrapper
>
>   // Convert RFNoC Shell interface into AXI stream interface
>
>   //
>
>   ////////////////////////////////////////////////////////////
>
>   wire [31:0]  m_axis0_data_tdata;
>
>   wire         m_axis0_data_tlast;
>
>   wire         m_axis0_data_tvalid;
>
>   wire         m_axis0_data_tready;
>
>   wire [127:0] m_axis0_data_tuser;
>
>
>
>   wire [31:0]  m_axis1_data_tdata;
>
>   wire         m_axis1_data_tlast;
>
>   wire         m_axis1_data_tvalid;
>
>   wire         m_axis1_data_tready;
>
>   wire [127:0] m_axis1_data_tuser;
>
>
>
>   wire [31:0]  s_axis0_data_tdata;
>
>   wire         s_axis0_data_tlast;
>
>   wire         s_axis0_data_tvalid;
>
>   wire         s_axis0_data_tready;
>
>   wire [127:0] s_axis0_data_tuser;
>
>
>
>   wire [31:0]  s_axis1_data_tdata;
>
>   wire         s_axis1_data_tlast;
>
>   wire         s_axis1_data_tvalid;
>
>   wire         s_axis1_data_tready;
>
>   wire [127:0] s_axis1_data_tuser;
>
>   wire [63:0]  vita_time_in;
>
>   wire [63:0]  vita_time_out;
>
> //  reg  [11:0]  seq_num;
>
>
>
>   axi_wrapper #(
>
>     .SIMPLE_MODE(0))
>
>   axi_wrapper0 (
>
>     .clk(ce_clk), .reset(ce_rst),
>
>     .clear_tx_seqnum(clear_tx_seqnum),
>
>     .next_dst(next_dst_sid),
>
>     .set_stb(set_stb), .set_addr(set_addr), .set_data(set_data),
>
>     .i_tdata(str_sink_tdata[63:0]), .i_tlast(str_sink_tlast[0]),
> .i_tvalid(str_sink_tvalid[0]), .i_tready(str_sink_tready[0]),
>
>     .o_tdata(str_src_tdata), .o_tlast(str_src_tlast),
> .o_tvalid(str_src_tvalid), .o_tready(str_src_tready),
>
>     .m_axis_data_tdata(m_axis0_data_tdata),
>
>     .m_axis_data_tlast(m_axis0_data_tlast),
>
>     .m_axis_data_tvalid(m_axis0_data_tvalid),
>
>     .m_axis_data_tready(m_axis0_data_tready),
>
>     .m_axis_data_tuser(m_axis0_data_tuser),
>
>     .s_axis_data_tdata(s_axis0_data_tdata),
>
>     .s_axis_data_tlast(s_axis0_data_tlast),
>
>     .s_axis_data_tvalid(s_axis0_data_tvalid),
>
>     .s_axis_data_tready(s_axis0_data_tready),
>
>     .s_axis_data_tuser(s_axis0_data_tuser),
>
>     .m_axis_config_tdata(),
>
>     .m_axis_config_tlast(),
>
>     .m_axis_config_tvalid(),
>
>     .m_axis_config_tready(),
>
>     .m_axis_pkt_len_tdata(),
>
>     .m_axis_pkt_len_tvalid(),
>
>     .m_axis_pkt_len_tready());
>
>
>
>   axi_wrapper #(
>
>     .SIMPLE_MODE(0))
>
>   axi_wrapper1 (
>
>     .clk(ce_clk), .reset(ce_rst),
>
>     .clear_tx_seqnum(clear_tx_seqnum),
>
>     .next_dst(next_dst_sid),
>
>     .set_stb(set_stb), .set_addr(set_addr), .set_data(set_data),
>
>     .i_tdata(str_sink_tdata[127:64]), .i_tlast(str_sink_tlast[1]),
> .i_tvalid(str_sink_tvalid[1]), .i_tready(str_sink_tready[1]),
>
> //    .o_tdata(str_src_tdata), .o_tlast(str_src_tlast),
> .o_tvalid(str_src_tvalid), .o_tready(str_src_tready),
>
>     .m_axis_data_tdata(m_axis1_data_tdata),
>
>     .m_axis_data_tlast(m_axis1_data_tlast),
>
>     .m_axis_data_tvalid(m_axis1_data_tvalid),
>
>     .m_axis_data_tready(m_axis1_data_tready),
>
>     .m_axis_data_tuser(),
>
>     .s_axis_data_tdata(),
>
>     .s_axis_data_tlast(),
>
>     .s_axis_data_tvalid(),
>
>     .s_axis_data_tready(),
>
>     .s_axis_data_tuser(),
>
>     .m_axis_config_tdata(),
>
>     .m_axis_config_tlast(),
>
>     .m_axis_config_tvalid(),
>
>     .m_axis_config_tready(),
>
>     .m_axis_pkt_len_tdata(),
>
>     .m_axis_pkt_len_tvalid(),
>
>     .m_axis_pkt_len_tready());
>
> …
>
>
>
> As I mentioned I checked with ILA and ready is high for str_sink_tready so
> input is ready to accept data but I never see the valid go high.
>
> Thanks,
>
>
>
> Dario Pennisi
>
>
>
>
_______________________________________________
USRP-users mailing list
USRP-users@lists.ettus.com
http://lists.ettus.com/mailman/listinfo/usrp-users_lists.ettus.com

Reply via email to