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] [39;0m**
**[32;1m[INFO] [X300] [39;0mX300 initialization sequence...**
**[32;1m[INFO] [X300] [39;0mDetermining maximum frame size... **
**[32;1m[INFO] [X300] [39;0mMaximum frame size: 8000 bytes.**
**[32;1m[INFO] [X300] [39;0mSetup basic communication...**
**[32;1m[INFO] [X300] [39;0mLoading values from EEPROM...**
**[32;1m[INFO] [X300] [39;0mSetup RF frontend clocking...**
**[32;1m[INFO] [X300] [39;0mRadio 1x clock:120**
**[32;1m[INFO] [X300] [39;0mDetecting internal GPSDO.... **
**[32;1m[INFO] [GPS] [39;0mNo GPSDO found**
**[32;1m[INFO] [RFNOC] [39;0m[DMA FIFO] Running BIST for FIFO 0... **
**[32;1m[INFO] [RFNOC] [39;0mpass (Throughput: 1302.6MB/s)**
**[32;1m[INFO] [RFNOC] [39;0m[DMA FIFO] Running BIST for FIFO 1... **
**[32;1m[INFO] [RFNOC] [39;0mpass (Throughput: 1296.1MB/s)**
**[32;1m[INFO] [RFNOC RADIO] [39;0mRegister loopback test passed**
**[32;1m[INFO] [RFNOC RADIO] [39;0mRegister loopback test passed**
**[32;1m[INFO] [RFNOC RADIO] [39;0mRegister loopback test passed**
**[32;1m[INFO] [RFNOC RADIO] [39;0mRegister loopback test passed**
**[33;1m[WARNING] [RFNOC] [39;0m[0/SplitStream_0] defines 2 input
buffer sizes, but 1 input ports**
**[32;1m[INFO] [CORES] [39;0mPerforming timer loopback test... **
**[32;1m[INFO] [CORES] [39;0mTimer loopback test passed**
**[32;1m[INFO] [CORES] [39;0mPerforming timer loopback test... **
**[32;1m[INFO] [CORES] [39;0mTimer 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