Hi,

I am trying to do a Rx / Tx loopback test and I am stuck for days with it.

For the sake of simplicity I altered the gain example [1] with the approach 3 from [2] (find my noc_block_gain.v and the test bench attached).

I connect the blocks like this (UHD):

*rx_graph->connect(m_radio_ctrl->get_block_id(),0, split_ctrl->get_block_id(),0,1024); rx_graph->connect(split_ctrl->get_block_id(),0, fifo_ctrl->get_block_id(),0,***1024*); rx_graph->connect(split_ctrl->get_block_id(),1, gain_ctrl->get_block_id(),0,***1024*); rx_graph->connect(gain_ctrl->get_block_id(),0, dma_fifo_ctrl->get_block_id(),0,***1024*);
rx_graph->connect(dma_fifo_ctrl->get_block_id(),0,m_radio_ctrl->get_block_id(),1,***1024*);*

Which is some how wrong, because I get following error when running the programm:*
*

*[32;1m[INFO] [UHDlinux; GNU C++ version 5.4.0 20160609; Boost_105800; UHD_4.0.0.rfnoc-devel-369-g1908672f] **
**[INFO] [X300] X300 initialization sequence...**
**[INFO] [X300] Determining maximum frame size... **
**[32;1m[INFO] [X300] Maximum frame size: 8000 bytes.**
**[32;1m[INFO] [X300] Setup basic communication...**
**[32;1m[INFO] [X300] Loading values from EEPROM...**
**[32;1m[INFO] [X300] Setup RF frontend clocking...**
**[32;1m[INFO] [X300] Radio 1x clock:120**
**[32;1m[INFO] [X300] Detecting internal GPSDO.... **
**[32;1m[INFO] [GPS] No GPSDO found**
**[32;1m[INFO] [RFNOC] [DMA FIFO] Running BIST for FIFO 0... **
**[32;1m[INFO] [RFNOC] pass (Throughput: 1302.6MB/s)**
**[32;1m[INFO] [RFNOC] [DMA FIFO] Running BIST for FIFO 1... **
**[32;1m[INFO] [RFNOC] pass (Throughput: 1296.1MB/s)**
**[32;1m[INFO] [RFNOC RADIO] Register loopback test passed**
**[32;1m[INFO] [RFNOC RADIO] Register loopback test passed**
**[32;1m[INFO] [RFNOC RADIO] Register loopback test passed**
**[32;1m[INFO] [RFNOC RADIO] Register loopback test passed**
**[33;1m[WARNING] [RFNOC] [0/SplitStream_0] defines 2 input buffer sizes, but 1 input ports**
**[32;1m[INFO] [CORES] Performing timer loopback test... **
**[32;1m[INFO] [CORES] Timer loopback test passed**
**[32;1m[INFO] [CORES] Performing timer loopback test... **
**[32;1m[INFO] [CORES] Timer loopback test passed**
**
**____________________________________**
**
**Radio0 Params:**
**Device Address:**
**    spp: 1024**
**
**____________________________________**
**
**SplitStream Params:**
**Empty Device Address**
**____________________________________**
**
**FIFO Params:**
**Empty Device Address**
**____________________________________**
**
**DmaFIFO Params:**
**Device Address:**
**    base_addr: 0**
**    depth: 65536**
**
**____________________________________**
**
**gain Params:**
**Device Address:**
**    gain: 10**
**    delaytime: 3600**
**
**____________________________________**
**Setting RX Freq: 2450.000000 MHz...**
**Actual RX Freq: 2450.000000 MHz...**
**
**Actual TX Freq: 2450.000000 MHz...**
**
**Actual RX Gain: 0.000000 dB...**
**
**Actual TX Gain: 0.000000 dB...**
**
**Connecting blocks...**
**terminate called after throwing an instance of 'uhd::runtime_error'**
** what(): RuntimeError: Input FIFO for block 0/Radio_0 is too small (0 kiB) for packets of size 1 kiB**
**coming from block 0/DmaFIFO_0.**
*

Is there anyone who did a Rx/Tx loop with a similar flow graph as shown in grc_block.png?

What am I doing wrong?

Best regards,

Daniel


[1] https://kb.ettus.com/Getting_Started_with_RFNoC_Development

[2] https://corvid.io/2017/04/22/stupid-rfnoc-tricks-loopback/

--

M.Sc. Daniel Rauschen

Communication Systems

Fraunhofer Institute for Communication, Information Processing and Ergonomics 
FKIE

Fraunhoferstr. 20 | 53343 Wachtberg | Germany

Phone +49 (0)228 9435-404

mailto:daniel.rausc...@fkie.fraunhofer.de

http://www.fkie.fraunhofer.de

/* 
 * Copyright 2017 <+YOU OR YOUR COMPANY+>.
 * 
 * This is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3, or (at your option)
 * any later version.
 * 
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this software; see the file COPYING.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street,
 * Boston, MA 02110-1301, USA.
 */

`timescale 1ns/1ps
`define NS_PER_TICK 1
`define NUM_TEST_CASES 5

`include "sim_exec_report.vh"
`include "sim_clks_rsts.vh"
`include "sim_rfnoc_lib.svh"

module noc_block_gain_tb();
  `TEST_BENCH_INIT("noc_block_gain",`NUM_TEST_CASES,`NS_PER_TICK);
  localparam BUS_CLK_PERIOD = $ceil(1e9/166.67e6);
  localparam CE_CLK_PERIOD  = $ceil(1e9/200e6);
  localparam NUM_CE         = 1;  // Number of Computation Engines / User RFNoC blocks to simulate
  localparam NUM_STREAMS    = 1;  // Number of test bench streams
  `RFNOC_SIM_INIT(NUM_CE, NUM_STREAMS, BUS_CLK_PERIOD, CE_CLK_PERIOD);
  `RFNOC_ADD_BLOCK(noc_block_gain, 0);

  localparam SPP = 16; // Samples per packet
  localparam GAIN = 10;
  localparam DELAYTIME = 3;
  localparam MAX_ITER = 3;

  /********************************************************
  ** Verification
  ********************************************************/
  initial begin : tb_main
    string s;
    logic [31:0] random_word;
    logic [63:0] readback;
    cvita_payload_t recv_payload;
    cvita_payload_t send_payload;
    cvita_metadata_t rx_md;
    cvita_metadata_t tx_md;

    /********************************************************
    ** Test 1 -- Reset
    ********************************************************/
    `TEST_CASE_START("Wait for Reset");
    while (bus_rst) @(posedge bus_clk);
    while (ce_rst) @(posedge ce_clk);
    `TEST_CASE_DONE(~bus_rst & ~ce_rst);

    /********************************************************
    ** Test 2 -- Check for correct NoC IDs
    ********************************************************/
    `TEST_CASE_START("Check NoC ID");
    // Read NOC IDs
    tb_streamer.read_reg(sid_noc_block_gain, RB_NOC_ID, readback);
    $display("Read gain NOC ID: %16x", readback);
    `ASSERT_ERROR(readback == noc_block_gain.NOC_ID, "Incorrect NOC ID");
    `TEST_CASE_DONE(1);

    /********************************************************
    ** Test 3 -- Connect RFNoC blocks
    ********************************************************/
    `TEST_CASE_START("Connect RFNoC blocks");
    `RFNOC_CONNECT(noc_block_tb,noc_block_gain,SC16,SPP);
    `RFNOC_CONNECT(noc_block_gain,noc_block_tb,SC16,SPP);
    `TEST_CASE_DONE(1);

    /********************************************************
    ** Test 4 -- Write / readback user registers
    ********************************************************/
    `TEST_CASE_START("Write / readback user registers");    
    tb_streamer.write_user_reg(sid_noc_block_gain, noc_block_gain.SR_GAIN, GAIN);
    tb_streamer.read_user_reg(sid_noc_block_gain, 0, readback);
    $sformat(s, "User register 0 incorrect readback! Expected: %0d, Actual %0d", readback[15:0], GAIN);
    `ASSERT_ERROR(readback[15:0] == GAIN, s);    
    tb_streamer.write_user_reg(sid_noc_block_gain, noc_block_gain.SR_DELAYTIME, DELAYTIME);
    tb_streamer.read_user_reg(sid_noc_block_gain, 1, readback);
    $sformat(s, "User register 1 incorrect readback! Expected: %0d, Actual %0d", readback[31:0], DELAYTIME);
    `ASSERT_ERROR(readback[31:0] == DELAYTIME, s);
    `TEST_CASE_DONE(1);

    /********************************************************
    ** Test 5 -- Test sequence
    ********************************************************/
    // gain's user code is a loopback, so we should receive
    // back exactly what we send
    `TEST_CASE_START("Test sequence");
    // ************************************************************************************************************
    for (int j = 0; j < MAX_ITER; j++) begin 
    
        $display("_________________________________ | Iteration#: %0d",j+1); 
    
        send_payload.delete();
        
        for (int i = 0; i < SPP / 2; i++) begin        
           
            $display("[Sim] Samples: i1: %0d | q1: %0d | i2: %0d | q2: %0d", i + SPP * j,i + 1 + SPP * j,i + 2 + SPP * j,i + 3 + SPP * j);            
            
            send_payload.push_back({16'(i + SPP * j),16'(i + 1 + SPP * j),16'(i + 2 + SPP * j),16'(i + 3 + SPP * j)});
            
        end       
        
        if(j == MAX_ITER - 1)begin
            tx_md.eob = 1;
            tx_md.has_time = 1;
            tx_md.timestamp = j * SPP + DELAYTIME;
        end else begin
            tx_md.eob = 0;
            tx_md.has_time = 1;
            tx_md.timestamp = j * SPP + DELAYTIME;
        end
        
        tb_streamer.send(send_payload,tx_md);
        
        $display("_________________________________"); 
        
        tb_streamer.recv(recv_payload,rx_md);
        
        for (int i = 0; i < SPP / 2; i++) begin        
            reg [64:0] iq12 = recv_payload[i];
            $display("[Sim] Samples processed: i1: %0d | q1: %0d | i2: %0d | q2: %0d | ts: %0d",iq12[63:48], iq12[47:32], iq12[31:16], iq12[15:0],rx_md.timestamp);                
        end
        
        recv_payload.delete();     
    end

    `TEST_CASE_DONE(1);
    `TEST_BENCH_DONE;

  end
endmodule
//
/* 
* Copyright 2017 <+YOU OR YOUR COMPANY+>.
* 
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
* 
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
* 
* You should have received a copy of the GNU General Public License
* along with this software; see the file COPYING.  If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/

//
module noc_block_gain #(
parameter NOC_ID = 64'hEAFBCBF4447FF362,
parameter STR_SINK_FIFOSIZE = 11)
(
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  [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 [63:0] str_sink_tdata, str_src_tdata;
wire        str_sink_tlast, str_sink_tvalid, str_sink_tready, 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),
    .STR_SINK_FIFOSIZE(STR_SINK_FIFOSIZE))
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(1'b1), .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_axis_data_tdata;
wire [127:0] m_axis_data_tuser;
//wire [127:0] m_axis_data_tuser_mod;
wire         m_axis_data_tlast;
wire         m_axis_data_tvalid;
wire         m_axis_data_tready;

wire [31:0]  s_axis_data_tdata;
wire [127:0] s_axis_data_tuser;
wire         s_axis_data_tlast;
wire         s_axis_data_tvalid;
wire         s_axis_data_tready;

axi_wrapper #(
    .SIMPLE_MODE(1))
axi_wrapper (
    .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), .i_tlast(str_sink_tlast), .i_tvalid(str_sink_tvalid), .i_tready(str_sink_tready),
    .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_axis_data_tdata),
    .m_axis_data_tlast(m_axis_data_tlast),
    .m_axis_data_tvalid(m_axis_data_tvalid),
    .m_axis_data_tready(m_axis_data_tready),
    .m_axis_data_tuser(m_axis_data_tuser),
    .s_axis_data_tdata(s_axis_data_tdata),
    .s_axis_data_tlast(s_axis_data_tlast),
    .s_axis_data_tvalid(s_axis_data_tvalid),
    .s_axis_data_tready(s_axis_data_tready),
    .s_axis_data_tuser(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());

////////////////////////////////////////////////////////////
//
// User code
//
////////////////////////////////////////////////////////////
// NoC Shell registers 0 - 127,
// User register address space starts at 128
localparam SR_USER_REG_BASE = 128;

// Control Source Unused
assign cmdout_tdata  = 64'd0;
assign cmdout_tlast  = 1'b0;
assign cmdout_tvalid = 1'b0;
assign ackin_tready  = 1'b1;

// Settings registers
//
// - The settings register bus is a simple strobed interface.
// - Transactions include both a write and a readback.
// - The write occurs when set_stb is asserted.
//   The settings register with the address matching set_addr will
//   be loaded with the data on set_data.
// - Readback occurs when rb_stb is asserted. The read back strobe
//   must assert at least one clock cycle after set_stb asserts /
//   rb_stb is ignored if asserted on the same clock cycle of set_stb.
//   Example valid and invalid timing:
//              __    __    __    __
//   clk     __|  |__|  |__|  |__|  |__
//               _____
//   set_stb ___|     |________________
//                     _____
//   rb_stb  _________|     |__________     (Valid)
//                           _____
//   rb_stb  _______________|     |____     (Valid)
//           __________________________
//   rb_stb                                 (Valid if readback data is a constant)
//               _____
//   rb_stb  ___|     |________________     (Invalid / ignored, same cycle as set_stb)
//
    wire [31:0] delaytime;
    wire [63:0] future_vita_time = m_axis_data_tuser[63:0] + delaytime;
    
    cvita_hdr_modify cvita_hdr_modify_data (
    .header_in(m_axis_data_tuser),
    .header_out(s_axis_data_tuser),
    .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'b0), .src_sid(),
    .use_dst_sid(1'b0), .dst_sid(),
    .use_vita_time(1'b1), .vita_time(future_vita_time));
 
    localparam [7:0] SR_GAIN = SR_USER_REG_BASE;
    localparam [7:0] SR_DELAYTIME = SR_USER_REG_BASE + 8'd1;

    wire [15:0] gain;
    setting_reg #(.my_addr(SR_GAIN), .awidth(8), .width(16))
    sr_gain (.clk(ce_clk), .rst(ce_rst),.strobe(set_stb), .addr(set_addr), .in(set_data), .out(gain), .changed());
    

    setting_reg #(.my_addr(SR_DELAYTIME), .awidth(8), .width(32))
    sr_delaytime (.clk(ce_clk), .rst(ce_rst),.strobe(set_stb), .addr(set_addr), .in(set_data), .out(delaytime), .changed());
    
    always @(posedge ce_clk) begin
    case(rb_addr)
        8'd0 : rb_data <= {48'd0, gain};
        8'd1 : rb_data <= {32'd0, delaytime};
        default : rb_data <= 64'h0BADC0DE0BADC0DE;
    endcase
    end
    
    wire [31:0] pipe_in_tdata;
    wire pipe_in_tvalid, pipe_in_tlast;
    wire pipe_in_tready;

    wire [31:0] pipe_out_tdata;
    wire pipe_out_tvalid, pipe_out_tlast;
    wire pipe_out_tready;

    // Adding FIFO to ensure Pipeline
    axi_fifo_flop #(.WIDTH(32+1))
    pipeline0_axi_fifo_flop (
    .clk(ce_clk),
    .reset(ce_rst),
    .clear(clear_tx_seqnum),
    .i_tdata({m_axis_data_tlast,m_axis_data_tdata}),
    .i_tvalid(m_axis_data_tvalid),
    .i_tready(m_axis_data_tready),
    .o_tdata({pipe_in_tlast,pipe_in_tdata}),
    .o_tvalid(pipe_in_tvalid),
    .o_tready(pipe_in_tready));  

    wire [15:0] i = pipe_in_tdata[31:16];
    wire [15:0] q = pipe_in_tdata[15:0];

    wire [31:0] i_mult_gain = i * gain;
    wire [31:0] q_mult_gain = q * gain;

    wire [31:0] mult_gain = {i_mult_gain[15:0], q_mult_gain[15:0]};
    axi_fifo_flop #(.WIDTH(32+1))
    pipeline1_axi_fifo_flop (
    .clk(ce_clk),
    .reset(ce_rst),
    .clear(clear_tx_seqnum),
    .i_tdata({pipe_in_tlast,mult_gain}),
    .i_tvalid(pipe_in_tvalid),
    .i_tready(pipe_in_tready),
    .o_tdata({pipe_out_tlast,pipe_out_tdata}),
    .o_tvalid(pipe_out_tvalid),
    .o_tready(pipe_out_tready));

    /* Output Signals */
    assign pipe_out_tready = s_axis_data_tready;
    assign s_axis_data_tvalid = pipe_out_tvalid;
    assign s_axis_data_tlast  = pipe_out_tlast;
    assign s_axis_data_tdata  = pipe_out_tdata;
    //assign s_axis_data_tuser = m_axis_data_tuser_mod;


endmodule
_______________________________________________
USRP-users mailing list
USRP-users@lists.ettus.com
http://lists.ettus.com/mailman/listinfo/usrp-users_lists.ettus.com

Reply via email to