aboutsummaryrefslogtreecommitdiffstats
path: root/fpga/usrp3
diff options
context:
space:
mode:
Diffstat (limited to 'fpga/usrp3')
-rw-r--r--fpga/usrp3/lib/rfnoc/blocks/rfnoc_block_null_src_sink/Makefile3
-rw-r--r--fpga/usrp3/lib/rfnoc/blocks/rfnoc_block_null_src_sink/noc_shell_null_src_sink.v34
-rw-r--r--fpga/usrp3/lib/rfnoc/blocks/rfnoc_block_null_src_sink/rfnoc_block_null_src_sink.v55
-rw-r--r--fpga/usrp3/lib/rfnoc/blocks/rfnoc_block_null_src_sink/rfnoc_block_null_src_sink_all_tb.sv26
-rw-r--r--fpga/usrp3/lib/rfnoc/blocks/rfnoc_block_null_src_sink/rfnoc_block_null_src_sink_tb.sv87
-rw-r--r--fpga/usrp3/lib/rfnoc/core/chdr_stream_output.v4
-rw-r--r--fpga/usrp3/lib/rfnoc/core/chdr_to_axis_ctrl.v87
-rw-r--r--fpga/usrp3/lib/rfnoc/crossbar/crossbar_tb/chdr_crossbar_nxn_tb/Makefile3
-rw-r--r--fpga/usrp3/lib/rfnoc/crossbar/crossbar_tb/chdr_crossbar_nxn_tb/chdr_crossbar_nxn_all_tb.sv26
-rw-r--r--fpga/usrp3/lib/rfnoc/crossbar/crossbar_tb/chdr_crossbar_nxn_tb/chdr_crossbar_nxn_tb.sv11
-rw-r--r--fpga/usrp3/lib/rfnoc/crossbar/crossbar_tb/chdr_traffic_sink_sim.sv2
-rw-r--r--fpga/usrp3/lib/rfnoc/crossbar/crossbar_tb/chdr_traffic_source_sim.sv2
-rw-r--r--fpga/usrp3/lib/rfnoc/crossbar/crossbar_tb/crossbar_tb.sv32
-rw-r--r--fpga/usrp3/lib/rfnoc/sim/chdr_stream_endpoint_tb/Makefile3
-rw-r--r--fpga/usrp3/lib/rfnoc/sim/chdr_stream_endpoint_tb/chdr_stream_endpoint_all_tb.sv26
-rw-r--r--fpga/usrp3/lib/rfnoc/sim/chdr_stream_endpoint_tb/chdr_stream_endpoint_tb.sv177
-rw-r--r--fpga/usrp3/sim/rfnoc/PkgChdrBfm.sv344
-rw-r--r--fpga/usrp3/sim/rfnoc/PkgRfnocItemUtils.sv2
-rw-r--r--fpga/usrp3/sim/rfnoc/PkgTestExec.sv33
19 files changed, 568 insertions, 389 deletions
diff --git a/fpga/usrp3/lib/rfnoc/blocks/rfnoc_block_null_src_sink/Makefile b/fpga/usrp3/lib/rfnoc/blocks/rfnoc_block_null_src_sink/Makefile
index 30ce14aec..4d2e33633 100644
--- a/fpga/usrp3/lib/rfnoc/blocks/rfnoc_block_null_src_sink/Makefile
+++ b/fpga/usrp3/lib/rfnoc/blocks/rfnoc_block_null_src_sink/Makefile
@@ -29,10 +29,11 @@ $(RFNOC_OOT_SRCS) \
#-------------------------------------------------
# Testbench Specific
#-------------------------------------------------
-SIM_TOP = rfnoc_block_null_src_sink_tb
+SIM_TOP = rfnoc_block_null_src_sink_all_tb
SIM_SRCS = \
$(abspath rfnoc_block_null_src_sink_tb.sv) \
+$(abspath rfnoc_block_null_src_sink_all_tb.sv) \
# MODELSIM_USER_DO = $(abspath wave.do)
diff --git a/fpga/usrp3/lib/rfnoc/blocks/rfnoc_block_null_src_sink/noc_shell_null_src_sink.v b/fpga/usrp3/lib/rfnoc/blocks/rfnoc_block_null_src_sink/noc_shell_null_src_sink.v
index cef213920..3676ffbd3 100644
--- a/fpga/usrp3/lib/rfnoc/blocks/rfnoc_block_null_src_sink/noc_shell_null_src_sink.v
+++ b/fpga/usrp3/lib/rfnoc/blocks/rfnoc_block_null_src_sink/noc_shell_null_src_sink.v
@@ -23,6 +23,8 @@
module noc_shell_null_src_sink #(
parameter [9:0] THIS_PORTID = 10'd0,
parameter CHDR_W = 64,
+ parameter ITEM_W = 32,
+ parameter NIPC = 2,
parameter [5:0] MTU = 10
) (
//---------------------
@@ -82,8 +84,8 @@ module noc_shell_null_src_sink #(
output wire axis_data_clk,
output wire axis_data_rst,
// Payload Stream to User Logic: sink
- output wire [32*2-1:0] m_sink_payload_tdata,
- output wire [2-1:0] m_sink_payload_tkeep,
+ output wire [ITEM_W*NIPC-1:0] m_sink_payload_tdata,
+ output wire [NIPC-1:0] m_sink_payload_tkeep,
output wire m_sink_payload_tlast,
output wire m_sink_payload_tvalid,
input wire m_sink_payload_tready,
@@ -94,8 +96,8 @@ module noc_shell_null_src_sink #(
output wire m_sink_context_tvalid,
input wire m_sink_context_tready,
// Payload Stream to User Logic: loop
- output wire [32*2-1:0] m_loop_payload_tdata,
- output wire [2-1:0] m_loop_payload_tkeep,
+ output wire [ITEM_W*NIPC-1:0] m_loop_payload_tdata,
+ output wire [NIPC-1:0] m_loop_payload_tkeep,
output wire m_loop_payload_tlast,
output wire m_loop_payload_tvalid,
input wire m_loop_payload_tready,
@@ -106,8 +108,8 @@ module noc_shell_null_src_sink #(
output wire m_loop_context_tvalid,
input wire m_loop_context_tready,
// Payload Stream from User Logic: source
- input wire [32*2-1:0] s_source_payload_tdata,
- input wire [1:0] s_source_payload_tkeep,
+ input wire [ITEM_W*NIPC-1:0] s_source_payload_tdata,
+ input wire [NIPC-1:0] s_source_payload_tkeep,
input wire s_source_payload_tlast,
input wire s_source_payload_tvalid,
output wire s_source_payload_tready,
@@ -118,8 +120,8 @@ module noc_shell_null_src_sink #(
input wire s_source_context_tvalid,
output wire s_source_context_tready,
// Payload Stream from User Logic: loop
- input wire [32*2-1:0] s_loop_payload_tdata,
- input wire [1:0] s_loop_payload_tkeep,
+ input wire [ITEM_W*NIPC-1:0] s_loop_payload_tdata,
+ input wire [NIPC-1:0] s_loop_payload_tkeep,
input wire s_loop_payload_tlast,
input wire s_loop_payload_tvalid,
output wire s_loop_payload_tready,
@@ -233,8 +235,8 @@ module noc_shell_null_src_sink #(
chdr_to_axis_pyld_ctxt #(
.CHDR_W (CHDR_W),
- .ITEM_W (32),
- .NIPC (2),
+ .ITEM_W (ITEM_W),
+ .NIPC (NIPC),
.SYNC_CLKS (1),
.CONTEXT_FIFO_SIZE ($clog2(2)),
.PAYLOAD_FIFO_SIZE ($clog2(2)),
@@ -266,8 +268,8 @@ module noc_shell_null_src_sink #(
chdr_to_axis_pyld_ctxt #(
.CHDR_W (CHDR_W),
- .ITEM_W (32),
- .NIPC (2),
+ .ITEM_W (ITEM_W),
+ .NIPC (NIPC),
.SYNC_CLKS (1),
.CONTEXT_FIFO_SIZE ($clog2(2)),
.PAYLOAD_FIFO_SIZE ($clog2(2)),
@@ -303,8 +305,8 @@ module noc_shell_null_src_sink #(
axis_pyld_ctxt_to_chdr #(
.CHDR_W (CHDR_W),
- .ITEM_W (32),
- .NIPC (2),
+ .ITEM_W (ITEM_W),
+ .NIPC (NIPC),
.SYNC_CLKS (1),
.CONTEXT_FIFO_SIZE ($clog2(2)),
.PAYLOAD_FIFO_SIZE ($clog2(2)),
@@ -338,8 +340,8 @@ module noc_shell_null_src_sink #(
axis_pyld_ctxt_to_chdr #(
.CHDR_W (CHDR_W),
- .ITEM_W (32),
- .NIPC (2),
+ .ITEM_W (ITEM_W),
+ .NIPC (NIPC),
.SYNC_CLKS (1),
.CONTEXT_FIFO_SIZE ($clog2(2)),
.PAYLOAD_FIFO_SIZE ($clog2(2)),
diff --git a/fpga/usrp3/lib/rfnoc/blocks/rfnoc_block_null_src_sink/rfnoc_block_null_src_sink.v b/fpga/usrp3/lib/rfnoc/blocks/rfnoc_block_null_src_sink/rfnoc_block_null_src_sink.v
index 53c764627..9e1cdb117 100644
--- a/fpga/usrp3/lib/rfnoc/blocks/rfnoc_block_null_src_sink/rfnoc_block_null_src_sink.v
+++ b/fpga/usrp3/lib/rfnoc/blocks/rfnoc_block_null_src_sink/rfnoc_block_null_src_sink.v
@@ -4,30 +4,46 @@
// SPDX-License-Identifier: LGPL-3.0-or-later
//
// Module: rfnoc_block_null_src_sink
+//
// Description:
//
+// This block can source, sink, or loopback data. Each port is used for a
+// specific purpose. The RFNoC CHDR ports are mapped is as follows:
+//
+// Input Port 0 : Sink
+// Input Port 1 : Loopback in
+// Output Port 0 : Source
+// Output Port 1 : Loopback out
+//
// Parameters:
+// THIS_PORTID : Control crossbar port to which this block is connected
+// CHDR_W : AXIS-CHDR data bus width
+// MTU : Maximum transmission unit (i.e., maximum packet size in
+// CHDR words is 2**MTU).
+// ITEM_W : Item width
+// NIPC : Items per Clock
//
// Signals:
module rfnoc_block_null_src_sink #(
parameter [9:0] THIS_PORTID = 10'd0,
parameter CHDR_W = 64,
- parameter NIPC = 2,
- parameter [5:0] MTU = 10
+ parameter [5:0] MTU = 10,
+ parameter ITEM_W = 32,
+ parameter NIPC = CHDR_W/ITEM_W
)(
// RFNoC Framework Clocks and Resets
input wire rfnoc_chdr_clk,
input wire rfnoc_ctrl_clk,
- // RFNoC Backend Interface
+ // RFNoC Backend Interface
input wire [511:0] rfnoc_core_config,
output wire [511:0] rfnoc_core_status,
- // 2 CHDR Input Ports (from framework)
+ // 2 CHDR Input Ports (from framework)
input wire [(CHDR_W*2)-1:0] s_rfnoc_chdr_tdata,
input wire [1:0] s_rfnoc_chdr_tlast,
input wire [1:0] s_rfnoc_chdr_tvalid,
output wire [1:0] s_rfnoc_chdr_tready,
- // 2 CHDR Output Ports (to framework)
+ // 2 CHDR Output Ports (to framework)
output wire [(CHDR_W*2)-1:0] m_rfnoc_chdr_tdata,
output wire [1:0] m_rfnoc_chdr_tlast,
output wire [1:0] m_rfnoc_chdr_tvalid,
@@ -72,22 +88,24 @@ module rfnoc_block_null_src_sink #(
reg ctrlport_resp_ack;
reg [31:0] ctrlport_resp_data;
- wire [(32*NIPC)-1:0] src_pyld_tdata , loop_pyld_tdata ;
- wire [NIPC-1:0] src_pyld_tkeep , loop_pyld_tkeep ;
- wire src_pyld_tlast , snk_pyld_tlast , loop_pyld_tlast ;
- wire src_pyld_tvalid, snk_pyld_tvalid, loop_pyld_tvalid;
- wire src_pyld_tready, snk_pyld_tready, loop_pyld_tready;
+ wire [(ITEM_W*NIPC)-1:0] src_pyld_tdata , loop_pyld_tdata ;
+ wire [NIPC-1:0] src_pyld_tkeep , loop_pyld_tkeep ;
+ wire src_pyld_tlast , snk_pyld_tlast , loop_pyld_tlast ;
+ wire src_pyld_tvalid, snk_pyld_tvalid, loop_pyld_tvalid;
+ wire src_pyld_tready, snk_pyld_tready, loop_pyld_tready;
- wire [CHDR_W-1:0] src_ctxt_tdata , loop_ctxt_tdata ;
- wire [3:0] src_ctxt_tuser , loop_ctxt_tuser ;
- wire src_ctxt_tlast , loop_ctxt_tlast ;
- wire src_ctxt_tvalid, loop_ctxt_tvalid;
- wire src_ctxt_tready, snk_ctxt_tready, loop_ctxt_tready;
+ wire [CHDR_W-1:0] src_ctxt_tdata , loop_ctxt_tdata ;
+ wire [3:0] src_ctxt_tuser , loop_ctxt_tuser ;
+ wire src_ctxt_tlast , loop_ctxt_tlast ;
+ wire src_ctxt_tvalid, loop_ctxt_tvalid;
+ wire src_ctxt_tready, snk_ctxt_tready, loop_ctxt_tready;
// NoC Shell
// ---------------------------
noc_shell_null_src_sink #(
.THIS_PORTID (THIS_PORTID),
+ .NIPC (NIPC),
+ .ITEM_W (ITEM_W),
.CHDR_W (CHDR_W),
.MTU (MTU)
) noc_shell_null_src_sink_i (
@@ -257,18 +275,17 @@ module rfnoc_block_null_src_sink #(
end
end
- assign src_pyld_tdata = {NIPC{{~src_line_cnt[15:0], src_line_cnt[15:0]}}};
+ assign src_pyld_tdata = {NIPC{{~src_line_cnt[ITEM_W/2-1:0], src_line_cnt[ITEM_W/2-1:0]}}};
assign src_pyld_tkeep = {NIPC{1'b1}};
assign src_pyld_tlast = (lines_left == 12'd0);
assign src_pyld_tvalid = (state == ST_PYLD);
assign src_ctxt_tdata = chdr_build_header(
6'd0, 1'b0, 1'b0, CHDR_PKT_TYPE_DATA, CHDR_NO_MDATA, src_pkt_cnt[15:0], reg_src_bpp, 16'd0);
- assign src_ctxt_tuser = CONTEXT_FIELD_HDR;
+ assign src_ctxt_tuser = CHDR_W > 64 ? CONTEXT_FIELD_HDR_TS : CONTEXT_FIELD_HDR;
assign src_ctxt_tlast = 1'b1;
assign src_ctxt_tvalid = (state == ST_HDR && reg_src_en);
-
// Register Interface
// ---------------------------
always @(posedge rfnoc_chdr_clk) begin
@@ -294,7 +311,7 @@ module rfnoc_block_null_src_sink #(
if (ctrlport_req_rd) begin
case(ctrlport_req_addr)
REG_CTRL_STATUS:
- ctrlport_resp_data <= {NIPC[7:0], 8'd32, state, 12'h0, reg_src_en, reg_clear_cnts};
+ ctrlport_resp_data <= {NIPC[7:0],ITEM_W[7:0], state, 12'h0, reg_src_en, reg_clear_cnts};
REG_SRC_LINES_PER_PKT:
ctrlport_resp_data <= {20'h0, reg_src_lpp};
REG_SRC_BYTES_PER_PKT:
diff --git a/fpga/usrp3/lib/rfnoc/blocks/rfnoc_block_null_src_sink/rfnoc_block_null_src_sink_all_tb.sv b/fpga/usrp3/lib/rfnoc/blocks/rfnoc_block_null_src_sink/rfnoc_block_null_src_sink_all_tb.sv
new file mode 100644
index 000000000..ed5745a44
--- /dev/null
+++ b/fpga/usrp3/lib/rfnoc/blocks/rfnoc_block_null_src_sink/rfnoc_block_null_src_sink_all_tb.sv
@@ -0,0 +1,26 @@
+//
+// Copyright 2020 Ettus Research, a National Instruments Brand
+//
+// SPDX-License-Identifier: LGPL-3.0-or-later
+//
+// Module: chdr_stream_endpoint_all_tb
+//
+// Description: Testbench for chdr_stream_endpoint that runs multiple widths
+//
+
+module rfnoc_block_null_src_sink_all_tb#(
+ /* no PARAM */
+)(
+ /* no IO */
+);
+
+ rfnoc_block_null_src_sink_tb #(.TEST_NAME("64B"),.CHDR_W(64)) CHDR64 ();
+ rfnoc_block_null_src_sink_tb #(.TEST_NAME("512B"),.CHDR_W(512)) CHDR512 ();
+
+ // Wait for all done
+ bit clk,rst;
+ sim_clock_gen #(100.0) clk_gen (clk, rst);
+ always_ff@(posedge clk)
+ if (CHDR64.test.done && CHDR512.test.done) $finish(1);
+
+endmodule
diff --git a/fpga/usrp3/lib/rfnoc/blocks/rfnoc_block_null_src_sink/rfnoc_block_null_src_sink_tb.sv b/fpga/usrp3/lib/rfnoc/blocks/rfnoc_block_null_src_sink/rfnoc_block_null_src_sink_tb.sv
index 192a8143b..2ef2e31ea 100644
--- a/fpga/usrp3/lib/rfnoc/blocks/rfnoc_block_null_src_sink/rfnoc_block_null_src_sink_tb.sv
+++ b/fpga/usrp3/lib/rfnoc/blocks/rfnoc_block_null_src_sink/rfnoc_block_null_src_sink_tb.sv
@@ -1,5 +1,5 @@
//
-// Copyright 2019 Ettus Research, A National Instruments Company
+// Copyright 2020 Ettus Research, A National Instruments Brand
//
// SPDX-License-Identifier: LGPL-3.0-or-later
//
@@ -9,9 +9,15 @@
`default_nettype none
-module rfnoc_block_null_src_sink_tb;
+module rfnoc_block_null_src_sink_tb #(
+ parameter TEST_NAME = "rfnoc_block_null_src_sink_tb",
+ parameter CHDR_W = 64
+)(
+ /* no IO */
+);
// Include macros and time declarations for use with PkgTestExec
+ `define TEST_EXEC_OBJ test
`include "test_exec.svh"
import PkgTestExec::*;
@@ -23,10 +29,10 @@ module rfnoc_block_null_src_sink_tb;
localparam NOC_ID = 32'h0000_0001;
localparam [9:0] THIS_PORTID = 10'h17;
localparam [15:0] THIS_EPID = 16'hDEAD;
- localparam int CHDR_W = 64;
- localparam int ITEM_W = 32;
+ localparam int ITEM_W = 32;
+ localparam int NIPC = CHDR_W/ITEM_W; // Expected Data generation only works for full words
localparam int SPP = 201;
- localparam int LPP = ((SPP+1)/2);
+ localparam int LPP = SPP % NIPC == 0 ? SPP/NIPC : SPP/NIPC+1;
localparam int NUM_PKTS = 50;
localparam int PORT_SRCSNK = 0;
@@ -49,6 +55,8 @@ module rfnoc_block_null_src_sink_tb;
AxiStreamIf #(CHDR_W) s0_chdr (rfnoc_chdr_clk); // Optional data iface
AxiStreamIf #(CHDR_W) s1_chdr (rfnoc_chdr_clk); // Optional data iface
+ TestExec test = new();
+
typedef ChdrData #(CHDR_W, ITEM_W)::chdr_word_t chdr_word_t;
// Bus functional model for a software block controller
@@ -58,29 +66,30 @@ module rfnoc_block_null_src_sink_tb;
rfnoc_block_null_src_sink #(
.THIS_PORTID (THIS_PORTID),
.CHDR_W (CHDR_W),
- .NIPC (2),
+ .ITEM_W (ITEM_W),
+ .NIPC (NIPC),
.MTU (10)
) dut (
.rfnoc_chdr_clk (backend.chdr_clk),
.rfnoc_ctrl_clk (backend.ctrl_clk),
- .rfnoc_core_config (backend.slave.cfg),
- .rfnoc_core_status (backend.slave.sts),
- .s_rfnoc_chdr_tdata ({m1_chdr.slave.tdata , m0_chdr.slave.tdata }),
- .s_rfnoc_chdr_tlast ({m1_chdr.slave.tlast , m0_chdr.slave.tlast }),
- .s_rfnoc_chdr_tvalid({m1_chdr.slave.tvalid , m0_chdr.slave.tvalid }),
- .s_rfnoc_chdr_tready({m1_chdr.slave.tready , m0_chdr.slave.tready }),
- .m_rfnoc_chdr_tdata ({s1_chdr.master.tdata , s0_chdr.master.tdata }),
- .m_rfnoc_chdr_tlast ({s1_chdr.master.tlast , s0_chdr.master.tlast }),
- .m_rfnoc_chdr_tvalid({s1_chdr.master.tvalid, s0_chdr.master.tvalid}),
- .m_rfnoc_chdr_tready({s1_chdr.master.tready, s0_chdr.master.tready}),
- .s_rfnoc_ctrl_tdata (m_ctrl.slave.tdata ),
- .s_rfnoc_ctrl_tlast (m_ctrl.slave.tlast ),
- .s_rfnoc_ctrl_tvalid(m_ctrl.slave.tvalid ),
- .s_rfnoc_ctrl_tready(m_ctrl.slave.tready ),
- .m_rfnoc_ctrl_tdata (s_ctrl.master.tdata ),
- .m_rfnoc_ctrl_tlast (s_ctrl.master.tlast ),
- .m_rfnoc_ctrl_tvalid(s_ctrl.master.tvalid),
- .m_rfnoc_ctrl_tready(s_ctrl.master.tready)
+ .rfnoc_core_config (backend.cfg),
+ .rfnoc_core_status (backend.sts),
+ .s_rfnoc_chdr_tdata ({m1_chdr.tdata , m0_chdr.tdata }),
+ .s_rfnoc_chdr_tlast ({m1_chdr.tlast , m0_chdr.tlast }),
+ .s_rfnoc_chdr_tvalid({m1_chdr.tvalid , m0_chdr.tvalid }),
+ .s_rfnoc_chdr_tready({m1_chdr.tready , m0_chdr.tready }),
+ .m_rfnoc_chdr_tdata ({s1_chdr.tdata , s0_chdr.tdata }),
+ .m_rfnoc_chdr_tlast ({s1_chdr.tlast , s0_chdr.tlast }),
+ .m_rfnoc_chdr_tvalid({s1_chdr.tvalid, s0_chdr.tvalid}),
+ .m_rfnoc_chdr_tready({s1_chdr.tready, s0_chdr.tready}),
+ .s_rfnoc_ctrl_tdata (m_ctrl.tdata ),
+ .s_rfnoc_ctrl_tlast (m_ctrl.tlast ),
+ .s_rfnoc_ctrl_tvalid(m_ctrl.tvalid ),
+ .s_rfnoc_ctrl_tready(m_ctrl.tready ),
+ .m_rfnoc_ctrl_tdata (s_ctrl.tdata ),
+ .m_rfnoc_ctrl_tlast (s_ctrl.tlast ),
+ .m_rfnoc_ctrl_tvalid(s_ctrl.tvalid),
+ .m_rfnoc_ctrl_tready(s_ctrl.tready)
);
// ----------------------------------------
@@ -95,7 +104,7 @@ module rfnoc_block_null_src_sink_tb;
// Initialize
// ----------------------------------------
- test.start_tb("rfnoc_block_null_src_sink_tb");
+ test.start_tb({TEST_NAME,"rfnoc_block_null_src_sink_tb"});
// Start the stream endpoint BFM
blk_ctrl = new(backend, m_ctrl, s_ctrl);
@@ -107,7 +116,7 @@ module rfnoc_block_null_src_sink_tb;
// Startup block (Software initialization)
// ----------------------------------------
- test.start_test("Flush block then reset it");
+ test.start_test({TEST_NAME,"Flush block then reset it"});
begin
test.start_timeout(timeout, 10us, "Waiting for flush_and_reset");
#100; //Wait for GSR to deassert
@@ -118,7 +127,7 @@ module rfnoc_block_null_src_sink_tb;
// Run Tests
// ----------------------------------------
- test.start_test("Read Block Info");
+ test.start_test({TEST_NAME,"Read Block Info"});
begin
test.start_timeout(timeout, 1us, "Waiting for block info response");
// Get static block info and validate it
@@ -130,19 +139,20 @@ module rfnoc_block_null_src_sink_tb;
// Read status register and validate it
blk_ctrl.reg_read(dut.REG_CTRL_STATUS, rvalue);
- `ASSERT_ERROR(rvalue[31:24] == 2, "Incorrect NIPC Value");
+ `ASSERT_ERROR(rvalue[31:24] == NIPC, "Incorrect NIPC Value");
`ASSERT_ERROR(rvalue[23:16] == ITEM_W, "Incorrect ITEM_W Value");
test.end_timeout(timeout);
end
test.end_test();
- test.start_test("Stream Data Through Loopback Port");
+ test.start_test({TEST_NAME,"Stream Data Through Loopback Port m1->s1"});
begin
// Send and receive packets
repeat (NUM_PKTS) begin
chdr_word_t rx_data[$];
int rx_bytes;
- automatic ItemDataBuff #(logic[ITEM_W-1:0]) tx_dbuff = new, rx_dbuff = new;
+ automatic ItemDataBuff #(logic[ITEM_W-1:0],CHDR_W) tx_dbuff = new;
+ automatic ItemDataBuff #(logic[ITEM_W-1:0],CHDR_W) rx_dbuff = new;
for (int i = 0; i < SPP; i++)
tx_dbuff.put($urandom());
test.start_timeout(timeout, 5us, "Waiting for pkt to loop back");
@@ -173,16 +183,16 @@ module rfnoc_block_null_src_sink_tb;
end
test.end_test();
- test.start_test("Stream Data To Sink Port");
+ test.start_test({TEST_NAME,"Stream Data To Sink Port m0"});
begin
// Send packets
repeat (NUM_PKTS) begin
chdr_word_t rx_data[$];
int rx_bytes;
- automatic ItemDataBuff #(logic[ITEM_W-1:0]) tx_dbuff = new;
+ automatic ItemDataBuff #(logic[ITEM_W-1:0],CHDR_W) tx_dbuff = new;
for (int i = 0; i < SPP; i++)
tx_dbuff.put($urandom());
- test.start_timeout(timeout, 5us, "Waiting for pkt to loop back");
+ test.start_timeout(timeout, 5us, "Waiting to send packet");
blk_ctrl.send(PORT_SRCSNK, tx_dbuff.to_chdr_payload(), tx_dbuff.get_bytes());
test.end_timeout(timeout);
end
@@ -208,11 +218,12 @@ module rfnoc_block_null_src_sink_tb;
end
test.end_test();
- test.start_test("Stream Data From Source Port");
+ test.start_test({TEST_NAME,"Stream Data From Source Port s0"});
begin
// Turn on the source for some time then stop it
blk_ctrl.reg_write(dut.REG_SRC_LINES_PER_PKT, LPP-1);
- blk_ctrl.reg_write(dut.REG_SRC_BYTES_PER_PKT, (LPP+1)*8);
+ // A line is generated as NIPC Items
+ blk_ctrl.reg_write(dut.REG_SRC_BYTES_PER_PKT, (LPP+1)*ITEM_W/8*NIPC);
blk_ctrl.reg_write(dut.REG_CTRL_STATUS, 2'b10);
repeat ((NUM_PKTS / 10) * LPP) @(posedge rfnoc_chdr_clk);
blk_ctrl.reg_write(dut.REG_CTRL_STATUS, 2'b00);
@@ -228,7 +239,7 @@ module rfnoc_block_null_src_sink_tb;
test.start_timeout(timeout, 5us, "Waiting for pkt to arrive");
exp_data.delete();
for (int i = p*LPP; i < (p+1)*LPP; i++)
- exp_data.push_back({~i[15:0], i[15:0], ~i[15:0], i[15:0]});
+ exp_data.push_back({NIPC{{~i[ITEM_W/2-1:0], i[ITEM_W/2-1:0]}}});
blk_ctrl.recv(PORT_SRCSNK, rx_data, rx_bytes);
`ASSERT_ERROR(blk_ctrl.compare_data(exp_data, rx_data), "Data mismatch");
test.end_timeout(timeout);
@@ -236,7 +247,7 @@ module rfnoc_block_null_src_sink_tb;
end
test.end_test();
- test.start_test("Clear Counts");
+ test.start_test({TEST_NAME,"Clear Counts"});
begin
test.start_timeout(timeout, 1us, "Waiting for clear and readbacks");
// Clear
@@ -266,7 +277,7 @@ module rfnoc_block_null_src_sink_tb;
// Finish Up
// ----------------------------------------
// Display final statistics and results
- test.end_tb();
+ test.end_tb(.finish(0));
end
endmodule
diff --git a/fpga/usrp3/lib/rfnoc/core/chdr_stream_output.v b/fpga/usrp3/lib/rfnoc/core/chdr_stream_output.v
index 271c7fccc..c21649d44 100644
--- a/fpga/usrp3/lib/rfnoc/core/chdr_stream_output.v
+++ b/fpga/usrp3/lib/rfnoc/core/chdr_stream_output.v
@@ -411,7 +411,7 @@ module chdr_stream_output #(
if (CHDR_W < 128)
state <= ST_STRC_W1;
else
- state <= ST_STRC_WAIT;
+ state <= fc_resync_req ? ST_PASS_DATA : ST_STRC_WAIT;
end
// ST_STRC_W1
@@ -527,7 +527,7 @@ module chdr_stream_output #(
assign msg_o_tready = msg_o_tvalid && (state == ST_PASS_DATA || state == ST_STRC_WAIT);
// Acknowledge a flow control resync command
- assign fc_resync_ack = fc_resync_req && (state == ST_STRC_W1) &&
+ assign fc_resync_ack = fc_resync_req && (state == ST_STRC_W1 || state == ST_STRC_W0) &&
chdr_out_tvalid && chdr_out_tready && chdr_out_tlast;
// ---------------------------------------------------
diff --git a/fpga/usrp3/lib/rfnoc/core/chdr_to_axis_ctrl.v b/fpga/usrp3/lib/rfnoc/core/chdr_to_axis_ctrl.v
index 1f9dba2eb..130915de2 100644
--- a/fpga/usrp3/lib/rfnoc/core/chdr_to_axis_ctrl.v
+++ b/fpga/usrp3/lib/rfnoc/core/chdr_to_axis_ctrl.v
@@ -116,7 +116,7 @@ module chdr_to_axis_ctrl #(
ST_CHDR_HDR: begin
ch2ct_nmdata <= chdr_get_num_mdata(ch2ct_tdata[63:0]) - 5'd1;
if (!ch2ct_tlast)
- ch2ct_state <= (chdr_get_num_mdata(ch2ct_tdata[63:0]) == 5'd0) ?
+ ch2ct_state <= (chdr_get_num_mdata(ch2ct_tdata[63:0]) == 5'd0) ?
ST_CTRL_HDR : ST_CHDR_MDATA;
else
ch2ct_state <= ST_CHDR_HDR; // Premature termination
@@ -152,7 +152,7 @@ module chdr_to_axis_ctrl #(
);
// Create the first two lines of the Ctrl word (wide)
- // using data from CHDR packet
+ // using data from CHDR packet
wire [CHDR_W-1:0] ch2ct_new_ctrl_hdr;
assign ch2ct_new_ctrl_hdr[63:0] = {
axis_ctrl_build_hdr_hi(
@@ -172,7 +172,7 @@ module chdr_to_axis_ctrl #(
assign ch2ct_new_ctrl_hdr[CHDR_W-1:64] = ch2ct_tdata[CHDR_W-1:64];
end endgenerate
- wire [CHDR_W-1:0] ch2ct_wctrl_tdata =
+ wire [CHDR_W-1:0] ch2ct_wctrl_tdata =
(ch2ct_state == ST_CTRL_HDR) ? ch2ct_new_ctrl_hdr : ch2ct_tdata;
axis_width_conv #(
@@ -205,7 +205,7 @@ module chdr_to_axis_ctrl #(
// - Use the Ctrl RemDstPort as the CHDR DstPort (forward the master's request)
// - Use the this_epid as CHDR SrcEPID (return path for the CHDR packet)
// - Use the Ctrl SrcPort as the CHDR SrcPort (return path to the master)
- // - Ignore the Ctrl DstPort because the packet has already been routed
+ // - Ignore the Ctrl DstPort because the packet has already been routed
wire [CHDR_W-1:0] ct2ch_wctrl_tdata;
wire ct2ch_wctrl_tlast, ct2ch_wctrl_tvalid, ct2ch_wctrl_tready;
@@ -238,8 +238,7 @@ module chdr_to_axis_ctrl #(
end else if (ct2ch_tvalid && ct2ch_tready) begin
case (ct2ch_state)
ST_CHDR_HDR: begin
- if (!ct2ch_tlast)
- ct2ch_state <= ST_CTRL_HDR;
+ ct2ch_state <= ST_CTRL_HDR;
end
ST_CTRL_HDR: begin
if (ct2ch_tlast)
@@ -264,56 +263,60 @@ module chdr_to_axis_ctrl #(
// Hold the first line to generate info for the outgoing CHDR header
assign ct2ch_wctrl_tready = (ct2ch_state == ST_CTRL_HDR || ct2ch_state == ST_CTRL_BODY) ? ct2ch_tready : 1'b0;
- wire [7:0] ct2ch_32bit_lines = 8'd3 + // Header + OpWord
- (axis_ctrl_get_has_time(ct2ch_wctrl_tdata[31:0]) ? 8'd2 : 8'd0) + // Timestamp
- ({4'h0, axis_ctrl_get_num_data(ct2ch_wctrl_tdata[31:0])}); // Data words
+ wire [7:0] ct2ch_num_data = {4'h0, axis_ctrl_get_num_data(ct2ch_wctrl_tdata[31:0])};
+ wire [7:0] ct2ch_timestamp = axis_ctrl_get_has_time(ct2ch_wctrl_tdata[31:0]) ? 8'd2 : 8'd0;
+ wire [7:0] ct2ch_32bit_lines = CHDR_W/32 + // CHDR header
+ 8'd3 + // CTL Header + OpWord
+ ct2ch_timestamp + // Timestamp
+ ct2ch_num_data; // Data words
- wire [15:0] ct2ch_chdr_lines = 16'd1 + // CHDR header
- ct2ch_32bit_lines[7:$clog2(CHDR_W/32)] + // Convert 32-bit lines to CHDR_W
- (|ct2ch_32bit_lines[$clog2(CHDR_W/32)-1:0]); // Residue
+ reg [CHDR_W-1:0] ct2ch_sm_tdata,ct2ch_chdr_hdr;
+ reg [63:0] ct2ch_ctrl_hdr;
- reg [63:0] ct2ch_chdr_tdata;
+ always @(*) begin
+ ct2ch_chdr_hdr = 0;
+ ct2ch_chdr_hdr = chdr_build_header(
+ 6'd0, /* VC */
+ 1'b0, 1'b0, /* eob, eov */
+ CHDR_PKT_TYPE_CTRL,
+ CHDR_NO_MDATA,
+ ct2ch_seqnum,
+ (ct2ch_32bit_lines << $clog2(32/8)), /* length in bytes */
+ axis_ctrl_get_rem_dst_epid(ct2ch_wctrl_tdata[63:32]));
+ ct2ch_ctrl_hdr = {
+ axis_ctrl_build_hdr_hi(
+ 10'd0, /* Unused in CHDR Control payload */
+ this_epid /* This is the SrcEPID */
+ ),
+ axis_ctrl_build_hdr_lo(
+ axis_ctrl_get_is_ack (ct2ch_wctrl_tdata[31:0]),
+ axis_ctrl_get_has_time(ct2ch_wctrl_tdata[31:0]),
+ axis_ctrl_get_seq_num (ct2ch_wctrl_tdata[31:0]),
+ axis_ctrl_get_num_data(ct2ch_wctrl_tdata[31:0]),
+ axis_ctrl_get_src_port(ct2ch_wctrl_tdata[31:0]),
+ axis_ctrl_get_rem_dst_port(ct2ch_wctrl_tdata[63:32])
+ )
+ };
+ end
always @(*) begin
case (ct2ch_state)
ST_CHDR_HDR: begin
- ct2ch_chdr_tdata = chdr_build_header(
- 6'd0, /* VC */
- 1'b0, 1'b0, /* eob, eov */
- CHDR_PKT_TYPE_CTRL,
- CHDR_NO_MDATA,
- ct2ch_seqnum,
- (ct2ch_chdr_lines << $clog2(CHDR_W/8)), /* length in bytes */
- axis_ctrl_get_rem_dst_epid(ct2ch_wctrl_tdata[63:32])
- );
+ // regardless of width CHDR is always a full word
+ ct2ch_sm_tdata = ct2ch_chdr_hdr;
end
ST_CTRL_HDR: begin
- ct2ch_chdr_tdata = {
- axis_ctrl_build_hdr_hi(
- 10'd0, /* Unused in CHDR Control payload */
- this_epid /* This is the SrcEPID */
- ),
- axis_ctrl_build_hdr_lo(
- axis_ctrl_get_is_ack (ct2ch_wctrl_tdata[31:0]),
- axis_ctrl_get_has_time(ct2ch_wctrl_tdata[31:0]),
- axis_ctrl_get_seq_num (ct2ch_wctrl_tdata[31:0]),
- axis_ctrl_get_num_data(ct2ch_wctrl_tdata[31:0]),
- axis_ctrl_get_src_port(ct2ch_wctrl_tdata[31:0]),
- axis_ctrl_get_rem_dst_port(ct2ch_wctrl_tdata[63:32])
- )
- };
+ ct2ch_sm_tdata = ct2ch_wctrl_tdata;
+ ct2ch_sm_tdata[63:0] = ct2ch_ctrl_hdr;
end
default: begin
- ct2ch_chdr_tdata = ct2ch_wctrl_tdata[63:0];
+ ct2ch_sm_tdata = ct2ch_wctrl_tdata;
end
endcase
end
// Output signals
- assign ct2ch_tdata[63:0] = ct2ch_chdr_tdata;
- assign ct2ch_tlast = ct2ch_wctrl_tlast;
+ assign ct2ch_tdata = ct2ch_sm_tdata;
+ assign ct2ch_tlast = ct2ch_wctrl_tlast && (ct2ch_state != ST_CHDR_HDR);
assign ct2ch_tvalid = ct2ch_wctrl_tvalid;
- generate if (CHDR_W > 64) begin
- assign ct2ch_tdata[CHDR_W-1:64] = ct2ch_wctrl_tdata[CHDR_W-1:64];
- end endgenerate
endmodule // chdr_to_axis_ctrl
diff --git a/fpga/usrp3/lib/rfnoc/crossbar/crossbar_tb/chdr_crossbar_nxn_tb/Makefile b/fpga/usrp3/lib/rfnoc/crossbar/crossbar_tb/chdr_crossbar_nxn_tb/Makefile
index 399515640..cbeacc387 100644
--- a/fpga/usrp3/lib/rfnoc/crossbar/crossbar_tb/chdr_crossbar_nxn_tb/Makefile
+++ b/fpga/usrp3/lib/rfnoc/crossbar/crossbar_tb/chdr_crossbar_nxn_tb/Makefile
@@ -34,9 +34,10 @@ $(RFNOC_CORE_SRCS) \
# Testbench Specific
#-------------------------------------------------
# Define only one toplevel module
-SIM_TOP = chdr_crossbar_nxn_tb
+SIM_TOP = chdr_crossbar_nxn_all_tb
SIM_SRCS = \
+$(abspath chdr_crossbar_nxn_all_tb.sv) \
$(abspath chdr_crossbar_nxn_tb.sv) \
$(abspath ../crossbar_tb.sv) \
$(abspath ../chdr_traffic_source_sim.sv) \
diff --git a/fpga/usrp3/lib/rfnoc/crossbar/crossbar_tb/chdr_crossbar_nxn_tb/chdr_crossbar_nxn_all_tb.sv b/fpga/usrp3/lib/rfnoc/crossbar/crossbar_tb/chdr_crossbar_nxn_tb/chdr_crossbar_nxn_all_tb.sv
new file mode 100644
index 000000000..9dbaa2568
--- /dev/null
+++ b/fpga/usrp3/lib/rfnoc/crossbar/crossbar_tb/chdr_crossbar_nxn_tb/chdr_crossbar_nxn_all_tb.sv
@@ -0,0 +1,26 @@
+//
+// Copyright 2020 Ettus Research, a National Instruments Brand
+//
+// SPDX-License-Identifier: LGPL-3.0-or-later
+//
+// Module: chdr_crossbar_nxn
+//
+// Description: Testbench for chdr_crossbar_nxn that runs multiple widths
+//
+
+module chdr_crossbar_nxn_all_tb#(
+ /* no PARAM */
+)(
+ /* no IO */
+);
+
+ chdr_crossbar_nxn_tb #(.TEST_NAME("64B"),.CHDR_W(64)) CHDR64 ();
+ chdr_crossbar_nxn_tb #(.TEST_NAME("512B"),.CHDR_W(512)) CHDR512 ();
+
+ // Wait for all done
+ bit clk,rst;
+ sim_clock_gen #(100.0) clk_gen (clk, rst);
+ always_ff@(posedge clk)
+ if (CHDR64.impl.done && CHDR512.impl.done) $finish(1);
+
+endmodule
diff --git a/fpga/usrp3/lib/rfnoc/crossbar/crossbar_tb/chdr_crossbar_nxn_tb/chdr_crossbar_nxn_tb.sv b/fpga/usrp3/lib/rfnoc/crossbar/crossbar_tb/chdr_crossbar_nxn_tb/chdr_crossbar_nxn_tb.sv
index 1c5cace63..f5217c66f 100644
--- a/fpga/usrp3/lib/rfnoc/crossbar/crossbar_tb/chdr_crossbar_nxn_tb/chdr_crossbar_nxn_tb.sv
+++ b/fpga/usrp3/lib/rfnoc/crossbar/crossbar_tb/chdr_crossbar_nxn_tb/chdr_crossbar_nxn_tb.sv
@@ -6,12 +6,17 @@
`timescale 1ns/1ps
-module chdr_crossbar_nxn_tb();
+module chdr_crossbar_nxn_tb#(
+ parameter TEST_NAME = "chdr_crossbar_nxn_tb",
+ parameter CHDR_W = 64
+)(
+ /* no IO */
+);
crossbar_tb #(
- .TEST_NAME ("chdr_crossbar_nxn_tb"),
+ .TEST_NAME (TEST_NAME ),
.ROUTER_IMPL ("chdr_crossbar_nxn" ), // Router implementation
.ROUTER_PORTS (10 ), // Number of ports
- .ROUTER_DWIDTH (64 ), // Router datapath width
+ .ROUTER_DWIDTH (CHDR_W ), // Router datapath width
.MTU_LOG2 (7 ), // log2 of max packet size for router
.NUM_MASTERS (10 ), // Number of data generators in test
.TEST_MAX_PACKETS (100 ), // How many packets to stream per test case?
diff --git a/fpga/usrp3/lib/rfnoc/crossbar/crossbar_tb/chdr_traffic_sink_sim.sv b/fpga/usrp3/lib/rfnoc/crossbar/crossbar_tb/chdr_traffic_sink_sim.sv
index a9fe3ba27..c6af03582 100644
--- a/fpga/usrp3/lib/rfnoc/crossbar/crossbar_tb/chdr_traffic_sink_sim.sv
+++ b/fpga/usrp3/lib/rfnoc/crossbar/crossbar_tb/chdr_traffic_sink_sim.sv
@@ -88,7 +88,7 @@ module chdr_traffic_sink_sim #(
s_chdr.reset();
while (1) begin
// A session begins on the posedge of start_stb
- while (~start_stb) @(posedge clk);
+ while (start_stb !== 1) @(posedge clk);
session = session + 1;
$sformat(filename, "%s/pkts_node%05d_inj%03d_lpp%05d_traffic%c_sess%04d.csv",
FILE_PATH, NODE_ID, injection_rate, lines_per_pkt, traffic_patt, session);
diff --git a/fpga/usrp3/lib/rfnoc/crossbar/crossbar_tb/chdr_traffic_source_sim.sv b/fpga/usrp3/lib/rfnoc/crossbar/crossbar_tb/chdr_traffic_source_sim.sv
index e6cb7c5d9..8f8e2665d 100644
--- a/fpga/usrp3/lib/rfnoc/crossbar/crossbar_tb/chdr_traffic_source_sim.sv
+++ b/fpga/usrp3/lib/rfnoc/crossbar/crossbar_tb/chdr_traffic_source_sim.sv
@@ -107,7 +107,7 @@ module chdr_traffic_source_sim #(
m_chdr.reset();
while (1) begin
// A generation session begins on the posedge of start_stb
- while (~start_stb) @(posedge clk);
+ while (start_stb !== 1) @(posedge clk);
curr_pkt_num = 'd0;
m_chdr.reset();
num_samps_xferd = 'd0;
diff --git a/fpga/usrp3/lib/rfnoc/crossbar/crossbar_tb/crossbar_tb.sv b/fpga/usrp3/lib/rfnoc/crossbar/crossbar_tb/crossbar_tb.sv
index fc9d53fe7..33b09dfd5 100644
--- a/fpga/usrp3/lib/rfnoc/crossbar/crossbar_tb/crossbar_tb.sv
+++ b/fpga/usrp3/lib/rfnoc/crossbar/crossbar_tb/crossbar_tb.sv
@@ -58,12 +58,18 @@ module crossbar_tb #(
//----------------------------------------------------
// Instantiate traffic generators, checkers, buses
//----------------------------------------------------
- localparam FILE_PATH = {`WORKING_DIR, "/data/", ROUTER_IMPL};
+ `ifndef WORKING_DIR
+ // For XSim
+ localparam FILE_PATH = {`WORKING_DIR, "/data/", ROUTER_IMPL};
+ `else
+ // For ModelSim
+ localparam FILE_PATH = {"./work", "/data/", ROUTER_IMPL};
+ `endif
// Data buses
axis_t #(.DWIDTH(ROUTER_DWIDTH), .NUM_STREAMS(ROUTER_PORTS)) src2rtr_axis (.clk(clk));
axis_t #(.DWIDTH(ROUTER_DWIDTH), .NUM_STREAMS(ROUTER_PORTS)) rtr2snk_axis (.clk(clk));
-
+
// Control buses
settings_bus_master #(.SR_AWIDTH(16), .SR_DWIDTH(32)) rtr_sb (.clk(clk));
wire rtr_sb_ack;
@@ -75,6 +81,7 @@ module crossbar_tb #(
logic [31:0] set_num_pkts_to_send;
logic snk_start_stb = 0;
logic src_start_stb = 0;
+ bit done = 0;
wire [63:0] session_duration [0:ROUTER_PORTS-1];
wire [ROUTER_PORTS-1:0] src_active;
@@ -99,7 +106,7 @@ module crossbar_tb #(
.MTU (MTU_LOG2),
.NODE_ID (i),
.NUM_NODES (ROUTER_PORTS)
- ) traffic_src (
+ ) traffic_src (
.clk (clk),
.rst (rst),
.current_time (timestamp),
@@ -117,14 +124,14 @@ module crossbar_tb #(
.xfer_count (src_xfer_count[i]),
.pkt_count (src_pkt_count[i])
);
-
+
chdr_traffic_sink_sim #(
.WIDTH (ROUTER_DWIDTH),
.MTU (MTU_LOG2),
.NODE_ID (i),
.NUM_NODES (ROUTER_PORTS),
.FILE_PATH (TEST_GEN_LL_FILES==1 ? FILE_PATH : "")
- ) traffic_sink (
+ ) traffic_sink (
.clk (clk),
.rst (rst),
.current_time (timestamp),
@@ -152,8 +159,8 @@ module crossbar_tb #(
axi_fifo #(
.WIDTH(ROUTER_DWIDTH+1), .SIZE(0)
) fifo_i (
- .clk (clk),
- .reset (rst),
+ .clk (clk),
+ .reset (rst),
.clear (1'b0),
.i_tdata ({src2rtr_axis.tlast[i], src2rtr_axis.tdata[((i+1)*ROUTER_DWIDTH)-1:i*ROUTER_DWIDTH]}),
.i_tvalid (src2rtr_axis.tvalid[i]),
@@ -178,7 +185,7 @@ module crossbar_tb #(
.reset (rst),
.clear (1'b0),
.local_addr (8'd0),
- // Inputs
+ // Inputs
.i_tdata (src2rtr_axis.tdata),
.i_tlast (src2rtr_axis.tlast),
.i_tvalid (src2rtr_axis.tvalid),
@@ -210,7 +217,7 @@ module crossbar_tb #(
.NPORTS_MGMT (0),
.EXT_RTCFG_PORT (1)
) router_dut_i (
- // General
+ // General
.clk (clk),
.reset (rst),
// Inputs
@@ -242,12 +249,12 @@ module crossbar_tb #(
// General
.clk (clk),
.reset (rst),
- // Inputs
+ // Inputs
.s_axis_tdata (src2rtr_axis.tdata),
.s_axis_tlast (src2rtr_axis.tlast),
.s_axis_tvalid (src2rtr_axis.tvalid),
.s_axis_tready (src2rtr_axis.tready),
- // Output
+ // Output
.m_axis_tdata (rtr2snk_axis.tdata),
.m_axis_tlast (rtr2snk_axis.tlast),
.m_axis_tvalid (rtr2snk_axis.tvalid),
@@ -313,7 +320,7 @@ module crossbar_tb #(
@(posedge clk);
if (deadlock_re) $display("WARNING: Deadlock detected");
if (deadlock_fe) $display("Recovered from deadlock");
- end
+ end
// Wait for sink blocks to finish consuming
$display("All packets transmitted. Waiting to flush...");
while (|snk_active) @(posedge clk);
@@ -423,6 +430,7 @@ module crossbar_tb #(
`TEST_CASE_DONE(1)
`TEST_BENCH_DONE
+ done = 1;
end // initial begin
endmodule
diff --git a/fpga/usrp3/lib/rfnoc/sim/chdr_stream_endpoint_tb/Makefile b/fpga/usrp3/lib/rfnoc/sim/chdr_stream_endpoint_tb/Makefile
index b2773db02..d7152134d 100644
--- a/fpga/usrp3/lib/rfnoc/sim/chdr_stream_endpoint_tb/Makefile
+++ b/fpga/usrp3/lib/rfnoc/sim/chdr_stream_endpoint_tb/Makefile
@@ -29,11 +29,12 @@ $(RFNOC_XBAR_SRCS) \
#-------------------------------------------------
# Testbench Specific
#-------------------------------------------------
-SIM_TOP = chdr_stream_endpoint_tb
+SIM_TOP = chdr_stream_endpoint_all_tb
SIM_SRCS = \
$(abspath lossy_xport_model.v) \
$(abspath chdr_stream_endpoint_tb.sv) \
+$(abspath chdr_stream_endpoint_all_tb.sv) \
#-------------------------------------------------
# Bottom-of-Makefile
diff --git a/fpga/usrp3/lib/rfnoc/sim/chdr_stream_endpoint_tb/chdr_stream_endpoint_all_tb.sv b/fpga/usrp3/lib/rfnoc/sim/chdr_stream_endpoint_tb/chdr_stream_endpoint_all_tb.sv
new file mode 100644
index 000000000..c382be654
--- /dev/null
+++ b/fpga/usrp3/lib/rfnoc/sim/chdr_stream_endpoint_tb/chdr_stream_endpoint_all_tb.sv
@@ -0,0 +1,26 @@
+//
+// Copyright 2020 Ettus Research, a National Instruments Brand
+//
+// SPDX-License-Identifier: LGPL-3.0-or-later
+//
+// Module: chdr_stream_endpoint_all_tb
+//
+// Description: Testbench for chdr_stream_endpoint that runs multiple widths
+//
+
+module chdr_stream_endpoint_all_tb#(
+ /* no PARAM */
+)(
+ /* no IO */
+);
+
+ chdr_stream_endpoint_tb #(.TEST_NAME("64B"),.CHDR_W(64)) CHDR64 ();
+ chdr_stream_endpoint_tb #(.TEST_NAME("512B"),.CHDR_W(512)) CHDR512 ();
+
+ // Wait for all done
+ bit clk,rst;
+ sim_clock_gen #(100.0) clk_gen (clk, rst);
+ always_ff@(posedge clk)
+ if (CHDR64.test.done && CHDR512.test.done) $finish(1);
+
+endmodule
diff --git a/fpga/usrp3/lib/rfnoc/sim/chdr_stream_endpoint_tb/chdr_stream_endpoint_tb.sv b/fpga/usrp3/lib/rfnoc/sim/chdr_stream_endpoint_tb/chdr_stream_endpoint_tb.sv
index 34bf10707..daa7bf522 100644
--- a/fpga/usrp3/lib/rfnoc/sim/chdr_stream_endpoint_tb/chdr_stream_endpoint_tb.sv
+++ b/fpga/usrp3/lib/rfnoc/sim/chdr_stream_endpoint_tb/chdr_stream_endpoint_tb.sv
@@ -1,5 +1,5 @@
//
-// Copyright 2019 Ettus Research, A National Instruments Company
+// Copyright 2020 Ettus Research, A National Instruments Brand
//
// SPDX-License-Identifier: LGPL-3.0-or-later
//
@@ -8,14 +8,18 @@
`default_nettype none
-
-module chdr_stream_endpoint_tb;
-
+module chdr_stream_endpoint_tb#(
+ parameter TEST_NAME = "chdr_stream_endpoint_tb",
+ parameter CHDR_W = 64
+)(
+ /* no IO */
+);
// ----------------------------------------
// Global settings
// ----------------------------------------
-
+
// Include macros and time declarations for use with PkgTestExec
+ `define TEST_EXEC_OBJ test
`include "test_exec.svh"
import PkgTestExec::*;
@@ -34,7 +38,6 @@ module chdr_stream_endpoint_tb;
localparam int FAST_STALL_PROB = 0;
localparam int SLOW_STALL_PROB = 35;
- localparam int CHDR_W = 64;
localparam int MTU = 7;
localparam [15:0] PROTOVER = {8'd1, 8'd0};
localparam [15:0] DEV_ID = 16'hBEEF;
@@ -108,14 +111,14 @@ module chdr_stream_endpoint_tb;
.m_axis_chdr_tlast (a2c_chdr_tlast ),
.m_axis_chdr_tvalid (a2c_chdr_tvalid ),
.m_axis_chdr_tready (a2c_chdr_tready ),
- .s_axis_data_tdata ({m_a1_data.slave.tdata , m_a0_data.slave.tdata }),
- .s_axis_data_tlast ({m_a1_data.slave.tlast , m_a0_data.slave.tlast }),
- .s_axis_data_tvalid ({m_a1_data.slave.tvalid , m_a0_data.slave.tvalid }),
- .s_axis_data_tready ({m_a1_data.slave.tready , m_a0_data.slave.tready }),
- .m_axis_data_tdata ({s_a1_data.master.tdata , s_a0_data.master.tdata }),
- .m_axis_data_tlast ({s_a1_data.master.tlast , s_a0_data.master.tlast }),
- .m_axis_data_tvalid ({s_a1_data.master.tvalid, s_a0_data.master.tvalid}),
- .m_axis_data_tready ({s_a1_data.master.tready, s_a0_data.master.tready}),
+ .s_axis_data_tdata ({m_a1_data.tdata , m_a0_data.tdata }),
+ .s_axis_data_tlast ({m_a1_data.tlast , m_a0_data.tlast }),
+ .s_axis_data_tvalid ({m_a1_data.tvalid , m_a0_data.tvalid }),
+ .s_axis_data_tready ({m_a1_data.tready , m_a0_data.tready }),
+ .m_axis_data_tdata ({s_a1_data.tdata , s_a0_data.tdata }),
+ .m_axis_data_tlast ({s_a1_data.tlast , s_a0_data.tlast }),
+ .m_axis_data_tvalid ({s_a1_data.tvalid, s_a0_data.tvalid}),
+ .m_axis_data_tready ({s_a1_data.tready, s_a0_data.tready}),
.s_axis_ctrl_tdata (a_ctrl_out_tdata ),
.s_axis_ctrl_tlast (a_ctrl_loop_tlast ),
.s_axis_ctrl_tvalid (a_ctrl_loop_tvalid ),
@@ -157,14 +160,14 @@ module chdr_stream_endpoint_tb;
.m_axis_chdr_tlast (b2c_chdr_tlast ),
.m_axis_chdr_tvalid (b2c_chdr_tvalid ),
.m_axis_chdr_tready (b2c_chdr_tready ),
- .s_axis_data_tdata ({m_b1_data.slave.tdata , m_b0_data.slave.tdata }),
- .s_axis_data_tlast ({m_b1_data.slave.tlast , m_b0_data.slave.tlast }),
- .s_axis_data_tvalid ({m_b1_data.slave.tvalid , m_b0_data.slave.tvalid }),
- .s_axis_data_tready ({m_b1_data.slave.tready , m_b0_data.slave.tready }),
- .m_axis_data_tdata ({s_b1_data.master.tdata , s_b0_data.master.tdata }),
- .m_axis_data_tlast ({s_b1_data.master.tlast , s_b0_data.master.tlast }),
- .m_axis_data_tvalid ({s_b1_data.master.tvalid, s_b0_data.master.tvalid}),
- .m_axis_data_tready ({s_b1_data.master.tready, s_b0_data.master.tready}),
+ .s_axis_data_tdata ({m_b1_data.tdata , m_b0_data.tdata }),
+ .s_axis_data_tlast ({m_b1_data.tlast , m_b0_data.tlast }),
+ .s_axis_data_tvalid ({m_b1_data.tvalid , m_b0_data.tvalid }),
+ .s_axis_data_tready ({m_b1_data.tready , m_b0_data.tready }),
+ .m_axis_data_tdata ({s_b1_data.tdata , s_b0_data.tdata }),
+ .m_axis_data_tlast ({s_b1_data.tlast , s_b0_data.tlast }),
+ .m_axis_data_tvalid ({s_b1_data.tvalid, s_b0_data.tvalid}),
+ .m_axis_data_tready ({s_b1_data.tready, s_b0_data.tready}),
.s_axis_ctrl_tdata (b_ctrl_out_tdata ),
.s_axis_ctrl_tlast (b_ctrl_loop_tlast ),
.s_axis_ctrl_tvalid (b_ctrl_loop_tvalid ),
@@ -194,14 +197,14 @@ module chdr_stream_endpoint_tb;
.clk (rfnoc_chdr_clk),
.reset (rfnoc_chdr_rst),
.device_id (DEV_ID),
- .s_axis_tdata ({b2c_chdr_tdata, a2c_chdr_tdata, m_tb_chdr.slave.tdata }),
- .s_axis_tlast ({b2c_chdr_tlast, a2c_chdr_tlast, m_tb_chdr.slave.tlast }),
- .s_axis_tvalid ({b2c_chdr_tvalid, a2c_chdr_tvalid, m_tb_chdr.slave.tvalid }),
- .s_axis_tready ({b2c_chdr_tready, a2c_chdr_tready, m_tb_chdr.slave.tready }),
- .m_axis_tdata ({c2bx_chdr_tdata, c2ax_chdr_tdata, s_tb_chdr.master.tdata }),
- .m_axis_tlast ({c2bx_chdr_tlast, c2ax_chdr_tlast, s_tb_chdr.master.tlast }),
- .m_axis_tvalid ({c2bx_chdr_tvalid, c2ax_chdr_tvalid, s_tb_chdr.master.tvalid}),
- .m_axis_tready ({c2bx_chdr_tready, c2ax_chdr_tready, s_tb_chdr.master.tready}),
+ .s_axis_tdata ({b2c_chdr_tdata, a2c_chdr_tdata, m_tb_chdr.tdata }),
+ .s_axis_tlast ({b2c_chdr_tlast, a2c_chdr_tlast, m_tb_chdr.tlast }),
+ .s_axis_tvalid ({b2c_chdr_tvalid, a2c_chdr_tvalid, m_tb_chdr.tvalid }),
+ .s_axis_tready ({b2c_chdr_tready, a2c_chdr_tready, m_tb_chdr.tready }),
+ .m_axis_tdata ({c2bx_chdr_tdata, c2ax_chdr_tdata, s_tb_chdr.tdata }),
+ .m_axis_tlast ({c2bx_chdr_tlast, c2ax_chdr_tlast, s_tb_chdr.tlast }),
+ .m_axis_tvalid ({c2bx_chdr_tvalid, c2ax_chdr_tvalid, s_tb_chdr.tvalid}),
+ .m_axis_tready ({c2bx_chdr_tready, c2ax_chdr_tready, s_tb_chdr.tready}),
.ext_rtcfg_stb ('0),
.ext_rtcfg_addr ('0),
.ext_rtcfg_data ('0),
@@ -264,14 +267,15 @@ module chdr_stream_endpoint_tb;
end
end
// Respond with an ACK and the source and destination ports swapped
- assign a_ctrl_out_tdata =
+ assign a_ctrl_out_tdata =
a_first ? {1'b1, a_ctrl_in_tdata[30:20], a_ctrl_in_tdata[9:0], a_ctrl_in_tdata[19:10]} : a_ctrl_in_tdata;
- assign b_ctrl_out_tdata =
+ assign b_ctrl_out_tdata =
b_first ? {1'b1, b_ctrl_in_tdata[30:20], b_ctrl_in_tdata[9:0], b_ctrl_in_tdata[19:10]} : b_ctrl_in_tdata;
// ----------------------------------------
// Test Utilities
// ----------------------------------------
+ TestExec test = new();
integer cached_mgmt_seqnum = 0;
integer cached_ctrl_seqnum = 0;
integer cached_data_seqnum = 0;
@@ -320,7 +324,7 @@ module chdr_stream_endpoint_tb;
op_payload:{32'h0, sep_a.REG_OSTRM_DATA_ERR_CNT}, op_code:MGMT_OP_CFG_RD_REQ, ops_pending:8'd2};
tx_mgmt_pl.ops[3] = '{ // Hop 2: Read status
op_payload:{32'h0, sep_a.REG_OSTRM_ROUTE_ERR_CNT}, op_code:MGMT_OP_CFG_RD_REQ, ops_pending:8'd1};
- tx_mgmt_pl.ops[4] = '{ // Hop 2: Stream Endpoint: Return
+ tx_mgmt_pl.ops[4] = '{ // Hop 2: Stream Endpoint: Return
op_payload:48'h0, op_code:MGMT_OP_RETURN, ops_pending:8'd0};
tx_mgmt_pl.ops[5] = '{ // Hop 3: Nop for return
op_payload:48'h0, op_code:MGMT_OP_NOP, ops_pending:8'd0};
@@ -357,7 +361,7 @@ module chdr_stream_endpoint_tb;
automatic ctrl_op_word_t ctrl_op;
automatic ctrl_word_t ctrl_data[$];
automatic chdr_word_t ctrl_ts;
-
+
ctrl_data.delete();
for (int i = 0; i < $urandom_range(15,1); i++)
ctrl_data[i] = $urandom();
@@ -406,6 +410,7 @@ module chdr_stream_endpoint_tb;
if (VERBOSE) begin $write("ExpRx"); exp_chdr.print(); end
// Validate contents
+ exp_chdr.disable_comparing_beyond_length = 1;
`ASSERT_ERROR(exp_chdr.equal(rx_chdr),
"Received CHDR control packet was incorrect");
end
@@ -527,12 +532,12 @@ module chdr_stream_endpoint_tb;
// Shared Variables
// ----------------------------------------
- timeout_t timeout;
- string tc_label;
- bit stop_responder = 0;
- logic [31:0] seq_err_count;
- logic [31:0] route_err_count;
- logic [31:0] data_err_count;
+ timeout_t timeout;
+ string tc_label;
+ automatic bit stop_responder = 0;
+ logic [31:0] seq_err_count;
+ logic [31:0] route_err_count;
+ logic [31:0] data_err_count;
a_signal_data_err = 0;
b_signal_data_err = 0;
@@ -543,9 +548,10 @@ module chdr_stream_endpoint_tb;
b_rterr_prob = 0;
b_lossy_input = 0;
+
// Initialize
// ----------------------------------------
- test.start_tb("chdr_stream_endpoint_tb");
+ test.start_tb({TEST_NAME,"chdr_stream_endpoint_tb"});
// Start the BFMs
a0_data_bfm.run();
@@ -562,7 +568,7 @@ module chdr_stream_endpoint_tb;
rfnoc_ctrl_clk_gen.reset();
rfnoc_chdr_clk_gen.reset();
- test.start_test("Wait for reset");
+ test.start_test({TEST_NAME,"Wait for reset"});
test.start_timeout(timeout, 1us, "Waiting for reset");
while (rfnoc_ctrl_rst) @(posedge rfnoc_ctrl_clk);
while (rfnoc_chdr_rst) @(posedge rfnoc_chdr_clk);
@@ -572,7 +578,7 @@ module chdr_stream_endpoint_tb;
// Discover Topology
// ----------------------------------------
- test.start_test("Discover Topology");
+ test.start_test({TEST_NAME,"Discover Topology"});
begin
automatic chdr_header_t tx_mgmt_hdr, rx_mgmt_hdr;
automatic chdr_mgmt_t tx_mgmt_pl, rx_mgmt_pl;
@@ -587,9 +593,9 @@ module chdr_stream_endpoint_tb;
// Send a node info request to the crossbar
tx_mgmt_pl.header.num_hops = 2;
tx_mgmt_pl.ops.delete();
- tx_mgmt_pl.ops[0] = '{ // Hop 1: Send node info
+ tx_mgmt_pl.ops[0] = '{ // Hop 1: Send node info
op_payload:48'h0, op_code:MGMT_OP_INFO_REQ, ops_pending:8'd1};
- tx_mgmt_pl.ops[1] = '{ // Hop 1: Return
+ tx_mgmt_pl.ops[1] = '{ // Hop 1: Return
op_payload:48'h0, op_code:MGMT_OP_RETURN, ops_pending:8'd0};
tx_mgmt_pl.ops[2] = '{ // Hop 2: Nop for return
op_payload:48'h0, op_code:MGMT_OP_NOP, ops_pending:8'd0};
@@ -605,7 +611,7 @@ module chdr_stream_endpoint_tb;
`ASSERT_ERROR(rx_mgmt_pl.ops[1] == exp_mgmt_op,
"Discover XB: Mgmt response ops were incorrect");
- // *Status* We just discovered a crossbar with 3 ports!
+ // *Status* We just discovered a crossbar with 3 ports!
// Configure the crossbar routing table with our (TB) address
// then send node info request on the other two ports
@@ -613,11 +619,11 @@ module chdr_stream_endpoint_tb;
tx_mgmt_pl.ops.delete();
tx_mgmt_pl.ops[0] = '{ // Hop 1: Crossbar: Config router to return packet to dest
op_payload:{22'h0, PORT_TB, EPID_TB}, op_code:MGMT_OP_CFG_WR_REQ, ops_pending:8'd1};
- tx_mgmt_pl.ops[1] = '{ // Hop 1: Crossbar: Config router
+ tx_mgmt_pl.ops[1] = '{ // Hop 1: Crossbar: Config router
op_payload:{38'h0, PORT_A}, op_code:MGMT_OP_SEL_DEST, ops_pending:8'd0};
- tx_mgmt_pl.ops[2] = '{ // Hop 2: Stream Endpoint: Send node info
+ tx_mgmt_pl.ops[2] = '{ // Hop 2: Stream Endpoint: Send node info
op_payload:48'h0, op_code:MGMT_OP_INFO_REQ, ops_pending:8'd1};
- tx_mgmt_pl.ops[3] = '{ // Hop 2: Return
+ tx_mgmt_pl.ops[3] = '{ // Hop 2: Return
op_payload:48'h0, op_code:MGMT_OP_RETURN, ops_pending:8'd0};
tx_mgmt_pl.ops[4] = '{ // Hop 3: TB: Nop for return
op_payload:48'h0, op_code:MGMT_OP_NOP, ops_pending:8'd0};
@@ -638,11 +644,11 @@ module chdr_stream_endpoint_tb;
// Send node info request on the last port
tx_mgmt_pl.header.num_hops = 3;
tx_mgmt_pl.ops.delete();
- tx_mgmt_pl.ops[0] = '{ // Hop 1: Crossbar: Config router
+ tx_mgmt_pl.ops[0] = '{ // Hop 1: Crossbar: Config router
op_payload:{38'h0, PORT_B}, op_code:MGMT_OP_SEL_DEST, ops_pending:8'd0};
- tx_mgmt_pl.ops[1] = '{ // Hop 2: Stream Endpoint: Send node info
+ tx_mgmt_pl.ops[1] = '{ // Hop 2: Stream Endpoint: Send node info
op_payload:48'h0, op_code:MGMT_OP_INFO_REQ, ops_pending:8'd1};
- tx_mgmt_pl.ops[2] = '{ // Hop 2: Return
+ tx_mgmt_pl.ops[2] = '{ // Hop 2: Return
op_payload:48'h0, op_code:MGMT_OP_RETURN, ops_pending:8'd0};
tx_mgmt_pl.ops[3] = '{ // Hop 3: TB: Nop for return
op_payload:48'h0, op_code:MGMT_OP_NOP, ops_pending:8'd0};
@@ -664,7 +670,7 @@ module chdr_stream_endpoint_tb;
// Configure Routes to Stream Endpoints A and B
// ----------------------------------------
- test.start_test("Configure Routes");
+ test.start_test({TEST_NAME,"Configure Routes"});
begin
automatic chdr_header_t tx_mgmt_hdr, rx_mgmt_hdr;
automatic chdr_mgmt_t tx_mgmt_pl, rx_mgmt_pl;
@@ -680,9 +686,9 @@ module chdr_stream_endpoint_tb;
tx_mgmt_pl.ops[0] = '{ // Hop 1: Crossbar: Config path to EP A
op_payload:{22'h0, PORT_A, EPID_A}, op_code:MGMT_OP_CFG_WR_REQ, ops_pending:8'd2};
- tx_mgmt_pl.ops[1] = '{ // Hop 1: Crossbar: Config path to EP B
+ tx_mgmt_pl.ops[1] = '{ // Hop 1: Crossbar: Config path to EP B
op_payload:{22'h0, PORT_B, EPID_B}, op_code:MGMT_OP_CFG_WR_REQ, ops_pending:8'd1};
- tx_mgmt_pl.ops[2] = '{ // Hop 1: Request node info to make the packet come back
+ tx_mgmt_pl.ops[2] = '{ // Hop 1: Request node info to make the packet come back
op_payload:48'h0, op_code:MGMT_OP_RETURN, ops_pending:8'd0};
tx_mgmt_pl.ops[3] = '{ // Hop 2: Nop for return
op_payload:48'h0, op_code:MGMT_OP_NOP, ops_pending:8'd0};
@@ -701,13 +707,13 @@ module chdr_stream_endpoint_tb;
// Configure Stream Endpoints
// ----------------------------------------
- test.start_test("Configure Stream Endpoints");
+ test.start_test({TEST_NAME,"Configure Stream Endpoints"});
begin
automatic chdr_header_t tx_mgmt_hdr, rx_mgmt_hdr;
automatic chdr_mgmt_t tx_mgmt_pl, rx_mgmt_pl;
automatic chdr_mgmt_op_t exp_mgmt_op;
- logic [15:0] epids[2] = {EPID_A, EPID_B};
+ automatic logic [15:0] epids[2] = {EPID_A, EPID_B};
foreach (epids[i]) begin
// Generic management header
tx_mgmt_pl.header = '{
@@ -727,13 +733,13 @@ module chdr_stream_endpoint_tb;
op_payload:{32'h0, sep_a.REG_EPID_SELF}, op_code:MGMT_OP_CFG_RD_REQ, ops_pending:8'd2};
tx_mgmt_pl.ops[4] = '{ // Hop 2: Read EPID
op_payload:{32'h0, sep_a.REG_OSTRM_CTRL_STATUS}, op_code:MGMT_OP_CFG_RD_REQ, ops_pending:8'd1};
- tx_mgmt_pl.ops[5] = '{ // Hop 2: Stream Endpoint: Return
+ tx_mgmt_pl.ops[5] = '{ // Hop 2: Stream Endpoint: Return
op_payload:48'h0, op_code:MGMT_OP_RETURN, ops_pending:8'd0};
tx_mgmt_pl.ops[6] = '{ // Hop 3: Nop for return
op_payload:48'h0, op_code:MGMT_OP_NOP, ops_pending:8'd0};
tx_mgmt_hdr = '{
pkt_type:CHDR_MANAGEMENT, seq_num:cached_mgmt_seqnum++, dst_epid:epids[i], default:'0};
-
+
// Send the packet and check the response
send_recv_mgmt_packet(tx_mgmt_hdr, tx_mgmt_pl, rx_mgmt_hdr, rx_mgmt_pl);
`ASSERT_ERROR(rx_mgmt_pl.header.num_hops == 1,
@@ -752,13 +758,13 @@ module chdr_stream_endpoint_tb;
// Setup a stream between Endpoint A and B
// ----------------------------------------
- test.start_test("Setup bidirectional stream between endpoints A and B");
+ test.start_test({TEST_NAME,"Setup bidirectional stream between endpoints A and B"});
begin
automatic chdr_header_t tx_mgmt_hdr, rx_mgmt_hdr;
automatic chdr_mgmt_t tx_mgmt_pl, rx_mgmt_pl;
automatic chdr_mgmt_op_t exp_mgmt_op;
- logic [15:0] epids[2] = {EPID_A, EPID_B};
+ automatic logic [15:0] epids[2] = {EPID_A, EPID_B};
foreach (epids[i]) begin
// Generic management header
tx_mgmt_pl.header = '{
@@ -784,7 +790,7 @@ module chdr_stream_endpoint_tb;
op_payload:{32'h44, sep_a.REG_ISTRM_CTRL_STATUS}, op_code:MGMT_OP_CFG_WR_REQ, ops_pending:8'd2}; // Swap 32-bit words, endianness
tx_mgmt_pl.ops[7] = '{ // Hop 2: Configure lossy and start config
op_payload:{32'h47, sep_a.REG_OSTRM_CTRL_STATUS}, op_code:MGMT_OP_CFG_WR_REQ, ops_pending:8'd1}; // Swap 32-bit words, endianness, lossy and reset
- tx_mgmt_pl.ops[8] = '{ // Hop 2: Stream Endpoint: Return
+ tx_mgmt_pl.ops[8] = '{ // Hop 2: Stream Endpoint: Return
op_payload:48'h0, op_code:MGMT_OP_RETURN, ops_pending:8'd0};
tx_mgmt_pl.ops[9] = '{ // Hop 3: Nop for return
op_payload:48'h0, op_code:MGMT_OP_NOP, ops_pending:8'd0};
@@ -818,7 +824,7 @@ module chdr_stream_endpoint_tb;
op_payload:{32'h0, sep_a.REG_OSTRM_DATA_ERR_CNT}, op_code:MGMT_OP_CFG_RD_REQ, ops_pending:8'd2};
tx_mgmt_pl.ops[7] = '{ // Hop 2: Read status
op_payload:{32'h0, sep_a.REG_OSTRM_ROUTE_ERR_CNT}, op_code:MGMT_OP_CFG_RD_REQ, ops_pending:8'd1};
- tx_mgmt_pl.ops[8] = '{ // Hop 2: Stream Endpoint: Return
+ tx_mgmt_pl.ops[8] = '{ // Hop 2: Stream Endpoint: Return
op_payload:48'h0, op_code:MGMT_OP_RETURN, ops_pending:8'd0};
tx_mgmt_pl.ops[9] = '{ // Hop 3: Nop for return
op_payload:48'h0, op_code:MGMT_OP_NOP, ops_pending:8'd0};
@@ -859,7 +865,7 @@ module chdr_stream_endpoint_tb;
cached_ctrl_seqnum = 0;
for (int cfg = 0; cfg < 2; cfg++) begin
$sformat(tc_label, "Control Xact to A (%s)", (cfg?"Slow":"Fast"));
- test.start_test(tc_label);
+ test.start_test({TEST_NAME,tc_label});
begin
tb_chdr_bfm.set_master_stall_prob(cfg?SLOW_STALL_PROB:FAST_STALL_PROB);
tb_chdr_bfm.set_slave_stall_prob(cfg?SLOW_STALL_PROB:FAST_STALL_PROB);
@@ -874,7 +880,7 @@ module chdr_stream_endpoint_tb;
cached_ctrl_seqnum = 0;
for (int cfg = 0; cfg < 2; cfg++) begin
$sformat(tc_label, "Control Xact to B (%s)", (cfg?"Slow":"Fast"));
- test.start_test(tc_label);
+ test.start_test({TEST_NAME,tc_label});
begin
tb_chdr_bfm.set_master_stall_prob(cfg?SLOW_STALL_PROB:FAST_STALL_PROB);
tb_chdr_bfm.set_slave_stall_prob(cfg?SLOW_STALL_PROB:FAST_STALL_PROB);
@@ -892,7 +898,7 @@ module chdr_stream_endpoint_tb;
automatic logic slv_cfg = cfg[1];
$sformat(tc_label, "Stream Data from A to B (%s Mst, %s Slv)",
(mst_cfg?"Slow":"Fast"), (slv_cfg?"Slow":"Fast"));
- test.start_test(tc_label);
+ test.start_test({TEST_NAME,tc_label});
begin
set_unidir_stall_prob(EPID_A, EPID_B,
mst_cfg?SLOW_STALL_PROB:FAST_STALL_PROB,
@@ -911,7 +917,7 @@ module chdr_stream_endpoint_tb;
automatic logic slv_cfg = cfg[1];
$sformat(tc_label, "Stream Data from B to A (%s Mst, %s Slv)",
(mst_cfg?"Slow":"Fast"), (slv_cfg?"Slow":"Fast"));
- test.start_test(tc_label);
+ test.start_test({TEST_NAME,tc_label});
begin
set_unidir_stall_prob(EPID_B, EPID_A,
mst_cfg?SLOW_STALL_PROB:FAST_STALL_PROB,
@@ -929,7 +935,7 @@ module chdr_stream_endpoint_tb;
automatic logic slv_cfg = cfg[1];
$sformat(tc_label, "Stream Data between A <=> B simultaneously (%s Mst, %s Slv)",
(mst_cfg?"Slow":"Fast"), (slv_cfg?"Slow":"Fast"));
- test.start_test(tc_label);
+ test.start_test({TEST_NAME,tc_label});
begin
set_bidir_stall_prob(
mst_cfg?SLOW_STALL_PROB:FAST_STALL_PROB,
@@ -950,7 +956,7 @@ module chdr_stream_endpoint_tb;
automatic logic slv_cfg = cfg[1];
$sformat(tc_label, "Stream Data and Control between A <=> B (%s Mst, %s Slv)",
(mst_cfg?"Slow":"Fast"), (slv_cfg?"Slow":"Fast"));
- test.start_test(tc_label);
+ test.start_test({TEST_NAME,tc_label});
begin
tb_chdr_bfm.set_master_stall_prob(mst_cfg?SLOW_STALL_PROB:FAST_STALL_PROB);
tb_chdr_bfm.set_slave_stall_prob(slv_cfg?SLOW_STALL_PROB:FAST_STALL_PROB);
@@ -976,9 +982,9 @@ module chdr_stream_endpoint_tb;
// Check zero sequence errors after streaming
// ----------------------------------------
- test.start_test("Check zero sequence errors after streaming");
+ test.start_test({TEST_NAME,"Check zero sequence errors after streaming"});
begin
- logic [15:0] epids[2] = {EPID_A, EPID_B};
+ automatic logic [15:0] epids[2] = {EPID_A, EPID_B};
foreach (epids[i]) begin
mgmt_read_err_counts(epids[i], seq_err_count, route_err_count, data_err_count);
`ASSERT_ERROR(seq_err_count == 32'd0, "Check NoErrs: Incorrect seq error count");
@@ -988,9 +994,13 @@ module chdr_stream_endpoint_tb;
end
test.end_test();
+
// Force sequence error
+ // Note: Occasional StreamCommand to resynch occur, which
+ // can cause the count to be greater than just the number data packets
+ // that are sent, so the comparisons are to > instead of ==
// ----------------------------------------
- test.start_test("Force sequence error");
+ test.start_test({TEST_NAME,"Force sequence error"});
begin
// First sequence error
send_recv_data_packets(EPID_A, EPID_B, 1, cached_data_seqnum++, 1);
@@ -999,7 +1009,7 @@ module chdr_stream_endpoint_tb;
b_seqerr_prob = 0;
repeat (100) @(posedge rfnoc_chdr_clk); // Wait for sequence error to reach the upstream port
mgmt_read_err_counts(EPID_A, seq_err_count, route_err_count, data_err_count);
- `ASSERT_ERROR(seq_err_count == 32'd1, "Force SeqErr: Incorrect seq error count");
+ `ASSERT_ERROR(seq_err_count > 32'd0, "Force SeqErr: Incorrect seq error count");
`ASSERT_ERROR(route_err_count == 32'd0, "Force SeqErr: Incorrect route error count");
`ASSERT_ERROR(data_err_count == 32'd0, "Force SeqErr: Incorrect data error count");
@@ -1010,7 +1020,7 @@ module chdr_stream_endpoint_tb;
b_seqerr_prob = 0;
repeat (100) @(posedge rfnoc_chdr_clk); // Wait for sequence error to reach the upstream port
mgmt_read_err_counts(EPID_A, seq_err_count, route_err_count, data_err_count);
- `ASSERT_ERROR(seq_err_count > 32'd1, "Force SeqErr: Incorrect seq error count");
+ `ASSERT_ERROR(seq_err_count > 32'd2, "Force SeqErr: Incorrect seq error count");
`ASSERT_ERROR(route_err_count == 32'd0, "Force SeqErr: Incorrect route error count");
`ASSERT_ERROR(data_err_count == 32'd0, "Force SeqErr: Incorrect data error count");
end
@@ -1018,7 +1028,7 @@ module chdr_stream_endpoint_tb;
// Force routing error
// ----------------------------------------
- test.start_test("Force routing error");
+ test.start_test({TEST_NAME,"Force routing error"});
begin
logic [31:0] old_route_err_count;
// First sequence error
@@ -1048,13 +1058,13 @@ module chdr_stream_endpoint_tb;
// Setup a stream between Endpoint A and B
// ----------------------------------------
- test.start_test("Reconfigure flow control (reset state)");
+ test.start_test({TEST_NAME,"Reconfigure flow control (reset state)"});
begin
automatic chdr_header_t tx_mgmt_hdr, rx_mgmt_hdr;
automatic chdr_mgmt_t tx_mgmt_pl, rx_mgmt_pl;
automatic chdr_mgmt_op_t exp_mgmt_op;
- logic [15:0] epids[2] = {EPID_A, EPID_B};
+ automatic logic [15:0] epids[2] = {EPID_A, EPID_B};
foreach (epids[i]) begin
// Generic management header
tx_mgmt_pl.header = '{
@@ -1070,7 +1080,7 @@ module chdr_stream_endpoint_tb;
op_payload:{32'd0, sep_a.REG_ISTRM_CTRL_STATUS}, op_code:MGMT_OP_CFG_WR_REQ, ops_pending:8'd2};
tx_mgmt_pl.ops[2] = '{ // Hop 2: Configure lossy and start config
op_payload:{32'd3, sep_a.REG_OSTRM_CTRL_STATUS}, op_code:MGMT_OP_CFG_WR_REQ, ops_pending:8'd1};
- tx_mgmt_pl.ops[3] = '{ // Hop 2: Stream Endpoint: Return
+ tx_mgmt_pl.ops[3] = '{ // Hop 2: Stream Endpoint: Return
op_payload:48'h0, op_code:MGMT_OP_RETURN, ops_pending:8'd0};
tx_mgmt_pl.ops[4] = '{ // Hop 3: Nop for return
op_payload:48'h0, op_code:MGMT_OP_NOP, ops_pending:8'd0};
@@ -1092,7 +1102,7 @@ module chdr_stream_endpoint_tb;
op_payload:48'h0, op_code:MGMT_OP_NOP, ops_pending:8'd0};
tx_mgmt_pl.ops[1] = '{ // Hop 2: Read status
op_payload:{32'h0, sep_a.REG_OSTRM_CTRL_STATUS}, op_code:MGMT_OP_CFG_RD_REQ, ops_pending:8'd1};
- tx_mgmt_pl.ops[2] = '{ // Hop 2: Stream Endpoint: Return
+ tx_mgmt_pl.ops[2] = '{ // Hop 2: Stream Endpoint: Return
op_payload:48'h0, op_code:MGMT_OP_RETURN, ops_pending:8'd0};
tx_mgmt_pl.ops[3] = '{ // Hop 3: Nop for return
op_payload:48'h0, op_code:MGMT_OP_NOP, ops_pending:8'd0};
@@ -1112,9 +1122,9 @@ module chdr_stream_endpoint_tb;
// Check zero errors after reinit
// ----------------------------------------
- test.start_test("Check zero errors after reinit");
+ test.start_test({TEST_NAME,"Check zero errors after reinit"});
begin
- logic [15:0] epids[2] = {EPID_A, EPID_B};
+ automatic logic [15:0] epids[2] = {EPID_A, EPID_B};
foreach (epids[i]) begin
mgmt_read_err_counts(epids[i], seq_err_count, route_err_count, data_err_count);
`ASSERT_ERROR(seq_err_count == 32'd0, "Check NoErrs: Incorrect seq error count");
@@ -1126,7 +1136,7 @@ module chdr_stream_endpoint_tb;
// Stream data between A <=> B simultaneously
// ----------------------------------------
- test.start_test("Stream Data between A <=> B with a lossy link");
+ test.start_test({TEST_NAME,"Stream Data between A <=> B with a lossy link"});
begin
cached_data_seqnum = 0;
set_bidir_stall_prob(FAST_STALL_PROB, SLOW_STALL_PROB);
@@ -1145,7 +1155,8 @@ module chdr_stream_endpoint_tb;
// Finish Up
// ----------------------------------------
// Display final statistics and results
- test.end_tb();
+ test.end_tb(.finish(0));
end
endmodule
+`default_nettype wire \ No newline at end of file
diff --git a/fpga/usrp3/sim/rfnoc/PkgChdrBfm.sv b/fpga/usrp3/sim/rfnoc/PkgChdrBfm.sv
index 96bfbd3a7..08b61712f 100644
--- a/fpga/usrp3/sim/rfnoc/PkgChdrBfm.sv
+++ b/fpga/usrp3/sim/rfnoc/PkgChdrBfm.sv
@@ -1,16 +1,15 @@
//
-// Copyright 2019 Ettus Research, A National Instruments Company
+// Copyright 2020 Ettus Research, A National Instruments Brand
//
// SPDX-License-Identifier: LGPL-3.0-or-later
//
// Module: PkgChdrBfm
//
-// Description: Package for a bi-directional CHDR bus functional model (BFM),
+// Description: Package for a bi-directional CHDR bus functional model (BFM),
// which consists primarily of the ChdrPacket and ChdrBfm classes.
//
-
package PkgChdrBfm;
import PkgChdrUtils::*;
@@ -21,10 +20,13 @@ package PkgChdrBfm;
// CHDR Packet Class
//---------------------------------------------------------------------------
- class ChdrPacket #(int CHDR_W = 64);
+ class ChdrPacket #(parameter int CHDR_W = 64,
+ parameter int USER_WIDTH = 1);
- typedef ChdrPacket #(CHDR_W) ChdrPacket_t;
+ typedef ChdrPacket #(CHDR_W,USER_WIDTH) ChdrPacket_t;
+ typedef AxiStreamPacket #(CHDR_W, USER_WIDTH) AxisPacket_t;
typedef ChdrData #(CHDR_W)::chdr_word_t chdr_word_t;
+ typedef AxisPacket_t::data_t data_t;
const int BYTES_PER_CHDR_W = CHDR_W / 8;
@@ -33,6 +35,8 @@ package PkgChdrBfm;
chdr_word_t metadata[$];
chdr_word_t data[$];
+ bit disable_comparing_beyond_length = 1;
+
extern function ChdrPacket_t copy();
extern function bit equal(ChdrPacket_t packet);
extern function string sprint(bit pretty = 1);
@@ -44,22 +48,22 @@ package PkgChdrBfm;
input chdr_word_t metadata[$] = {},
input chdr_timestamp_t timestamp = 0,
input int data_byte_length = -1);
- extern function void read_raw (output chdr_header_t header,
+ extern function void read_raw (output chdr_header_t header,
output chdr_word_t data[$],
output chdr_word_t metadata[$],
output chdr_timestamp_t timestamp,
output int data_byte_length);
- extern function void write_stream_status(ref chdr_header_t header,
+ extern function void write_stream_status(ref chdr_header_t header,
ref chdr_str_status_t status);
- extern function void read_stream_status (output chdr_header_t header,
+ extern function void read_stream_status (output chdr_header_t header,
output chdr_str_status_t status);
- extern function void write_stream_cmd (ref chdr_header_t header,
+ extern function void write_stream_cmd (ref chdr_header_t header,
ref chdr_str_command_t command);
- extern function void read_stream_cmd (output chdr_header_t header,
+ extern function void read_stream_cmd (output chdr_header_t header,
output chdr_str_command_t command);
- extern function void write_mgmt (ref chdr_header_t header,
+ extern function void write_mgmt (ref chdr_header_t header,
ref chdr_mgmt_t mgmt);
- extern function void read_mgmt (output chdr_header_t header,
+ extern function void read_mgmt (output chdr_header_t header,
output chdr_mgmt_t mgmt);
extern function void write_ctrl (ref chdr_header_t header,
ref chdr_ctrl_header_t ctrl_header,
@@ -72,17 +76,22 @@ package PkgChdrBfm;
output ctrl_word_t ctrl_data[$],
output chdr_timestamp_t ctrl_timestamp);
-
// Helper methods
extern function int header_bytes();
extern function int mdata_bytes();
extern function int data_bytes();
- extern function void update_lengths();
+ extern function void update_lengths(int payload_bytes = 0);
extern function string sprint_raw();
extern function string sprint_pretty();
- extern function bit chdr_word_queues_equal(ref chdr_word_t a[$], ref chdr_word_t b[$]);
+ extern function bit chdr_word_queues_equal(ref chdr_word_t a[$],
+ ref chdr_word_t b[$],
+ input int data_byte_length = -1);
+
+ // AXI-Stream/CHDR Conversion Functions
+ extern function void axis_to_chdr (AxisPacket_t axis_packet);
+ extern function AxisPacket_t chdr_to_axis ();
endclass : ChdrPacket;
@@ -123,12 +132,6 @@ package PkgChdrBfm;
extern function bit try_get_chdr(output ChdrPacket_t chdr_packet);
extern task peek_chdr(output ChdrPacket_t chdr_packet);
extern function bit try_peek_chdr(output ChdrPacket_t chdr_packet);
-
-
- // AXI-Stream/CHDR Conversion Functions
- extern function ChdrPacket_t axis_to_chdr (AxisPacket_t axis_packet);
- extern function AxisPacket_t chdr_to_axis (ChdrPacket_t chdr_packet);
-
endclass : ChdrBfm
@@ -151,8 +154,17 @@ package PkgChdrBfm;
// Return true if this packet equals that of the argument
function bit ChdrPacket::equal(ChdrPacket_t packet);
+ int payload_length;
+ payload_length = header.length;
+ payload_length -= BYTES_PER_CHDR_W; // subtract header bytes
+ if (CHDR_W == 64) begin // subtract TS bytes if not in header word
+ if (header.pkt_type == CHDR_DATA_WITH_TS) begin
+ payload_length -= BYTES_PER_CHDR_W;
+ end
+ end
+ payload_length -= packet.metadata.size() * BYTES_PER_CHDR_W; // subtract metadata length
if (header != packet.header) return 0;
- if (!chdr_word_queues_equal(data, packet.data)) return 0;
+ if (!chdr_word_queues_equal(data, packet.data,payload_length)) return 0;
if (!chdr_word_queues_equal(metadata, packet.metadata)) return 0;
if (header.pkt_type == CHDR_DATA_WITH_TS && timestamp !== packet.timestamp) return 0;
return 1;
@@ -176,6 +188,7 @@ package PkgChdrBfm;
return str;
endfunction : sprint_raw
+
// Format the contents of the packet into a string (dissect contents)
function string ChdrPacket::sprint_pretty();
string str;
@@ -236,6 +249,7 @@ package PkgChdrBfm;
return str;
endfunction : sprint_pretty
+
function string ChdrPacket::sprint(bit pretty = 1);
if (pretty)
return sprint_pretty();
@@ -243,6 +257,7 @@ package PkgChdrBfm;
return sprint_raw();
endfunction: sprint
+
// Print the contents of the packet
function void ChdrPacket::print(bit pretty = 1);
$display(sprint(pretty));
@@ -284,7 +299,7 @@ package PkgChdrBfm;
// Read the contents of this packet
function void ChdrPacket::read_raw (
- output chdr_header_t header,
+ output chdr_header_t header,
output chdr_word_t data[$],
output chdr_word_t metadata[$],
output chdr_timestamp_t timestamp,
@@ -315,7 +330,7 @@ package PkgChdrBfm;
// Read this packet as a status packet
function void ChdrPacket::read_stream_status (
- output chdr_header_t header,
+ output chdr_header_t header,
output chdr_str_status_t status
);
// Make sure it's a stream status packet
@@ -383,7 +398,7 @@ package PkgChdrBfm;
// Insert the header
data.push_back( mgmt.header );
-
+
// Insert the ops
foreach (mgmt.ops[i]) begin
data.push_back( mgmt.ops[i] );
@@ -433,6 +448,7 @@ package PkgChdrBfm;
input chdr_timestamp_t ctrl_timestamp = 0
);
bit partial_word;
+ int byte_count = 0;
ctrl_word_t mandatory_data;
ChdrData #(CHDR_W, 64)::item_queue_t data64;
@@ -442,10 +458,12 @@ package PkgChdrBfm;
// Insert word 0 of control payload
data64.push_back(ctrl_header);
+ byte_count+=8;
// Insert word 1 of control payload, if timestamp is used
if (ctrl_header.has_time) begin
data64.push_back(ctrl_timestamp);
+ byte_count+=8;
end
// Make sure the amount of data passed matches the header
@@ -457,6 +475,7 @@ package PkgChdrBfm;
// and first word of control data.
mandatory_data = (ctrl_header.num_data > 0) ? ctrl_data[0] : '0;
data64.push_back({mandatory_data, ctrl_op_word[31:0]});
+ byte_count+=8;
// We have a half CHDR word if num_data is even
partial_word = (ctrl_header.num_data[0] == '0);
@@ -465,15 +484,17 @@ package PkgChdrBfm;
if (i == ctrl_data.size()-1) begin
// num_data must be even in this case, so last word is half filled
data64.push_back({ 32'b0, ctrl_data[i] });
+ byte_count+=4;
end else begin
data64.push_back({ ctrl_data[i+1], ctrl_data[i] });
+ byte_count+=8;
end
end
// Convert from 64-bit words to CHDR_W-bit words
data = ChdrData #(CHDR_W, 64)::item_to_chdr(data64);
- update_lengths();
+ update_lengths(.payload_bytes(byte_count));
endfunction : write_ctrl
@@ -530,7 +551,6 @@ package PkgChdrBfm;
while (dptr < data32.size()) begin
ctrl_data.push_back(data32[dptr++]);
end
-
endfunction : read_ctrl
@@ -557,21 +577,30 @@ package PkgChdrBfm;
endfunction : data_bytes;
- // Update the length and num_mdata header fields of the packet based on the
+ // Update the length and num_mdata header fields of the packet based on the
// size of the metadata queue and the data queue.
- function void ChdrPacket::update_lengths();
+ function void ChdrPacket::update_lengths(int payload_bytes = 0);
int num_bytes;
int num_mdata;
+ int my_payload_bytes;
// Calculate NumMData based on the size of metadata queue
num_mdata = metadata.size();
assert(num_mdata < 2**$bits(chdr_num_mdata_t)) else
$fatal(1, "ChdrPacket::update_lengths(): Calculated NumMData exceeds maximum size");
+ if (payload_bytes == 0) begin
+ // Calculate if optional argument not provided
+ my_payload_bytes = data.size() * BYTES_PER_CHDR_W;
+ end else begin
+ // Use optional argument if provided
+ my_payload_bytes = payload_bytes;
+ end
+
// Calculate the Length field
num_bytes = header_bytes() + // Header
num_mdata * BYTES_PER_CHDR_W + // Metadata
- data.size() * BYTES_PER_CHDR_W; // Payload
+ my_payload_bytes; // Payload
assert(num_bytes < 2**$bits(chdr_length_t)) else
$fatal(1, "ChdrPacket::update_lengths(): Calculated Length exceeds maximum size");
@@ -581,100 +610,37 @@ package PkgChdrBfm;
endfunction : update_lengths
- // Returns 1 if the queues have the same contents, otherwise returns 0. This
- // function is equivalent to (a == b), but this doesn't work correctly yet in
- // Vivado 2018.3.
- function automatic bit ChdrPacket::chdr_word_queues_equal(ref chdr_word_t a[$], ref chdr_word_t b[$]);
+ // Returns 1 if the queues have the same contents, up to the
+ // data_byte_length, if present.
+ function automatic bit ChdrPacket::chdr_word_queues_equal(
+ ref chdr_word_t a[$],
+ ref chdr_word_t b[$],
+ input int data_byte_length = -1
+ );
chdr_word_t x, y;
+ int bytes_remaining = data_byte_length;
if (a.size() != b.size()) return 0;
foreach (a[i]) begin
x = a[i];
y = b[i];
- if (x !== y) return 0;
+ if(data_byte_length > 0 && // only if optional argument is valid
+ disable_comparing_beyond_length && // only if optional feature is enabled
+ bytes_remaining < BYTES_PER_CHDR_W) begin // only compare bytes on last word
+ for (int b = 0; b < bytes_remaining*8; b += 8) begin
+ if (x[b+:8] !== y[b+:8]) return 0;
+ end
+ end else begin
+ if (x !== y) return 0;
+ end
+ bytes_remaining -= BYTES_PER_CHDR_W;
end
return 1;
endfunction : chdr_word_queues_equal
-
- //---------------------------------------------------------------------------
- // CHDR BFM Class Methods
- //---------------------------------------------------------------------------
-
-
- // Class constructor. This must be given an interface for the master
- // connection and an interface for the slave connection.
- function ChdrBfm::new (
- virtual AxiStreamIf #(CHDR_W, USER_WIDTH).master master,
- virtual AxiStreamIf #(CHDR_W, USER_WIDTH).slave slave
- );
- super.new(master, slave);
- assert(CHDR_W % 64 == 0) else begin
- $fatal(1, "ChdrBfm::new: CHDR bus width must be a multiple of 64 bits");
- end
- endfunction : new
-
-
- // Queue the provided packet for transmission
- task ChdrBfm::put_chdr (ChdrPacket_t chdr_packet);
- AxisPacket_t axis_packet;
-
- axis_packet = chdr_to_axis(chdr_packet);
- super.put(axis_packet);
- endtask : put_chdr
-
-
- // Attempt to queue the provided packet for transmission. Return 1 if
- // successful, return 0 if the queue is full.
- function bit ChdrBfm::try_put_chdr (ChdrPacket_t chdr_packet);
- AxisPacket_t axis_packet;
- bit status;
-
- axis_packet = chdr_to_axis(chdr_packet);
- return super.try_put(axis_packet);
- endfunction : try_put_chdr
-
-
- // Get the next packet when it becomes available (wait if necessary)
- task ChdrBfm::get_chdr (output ChdrPacket_t chdr_packet);
- AxisPacket_t axis_packet;
- super.get(axis_packet);
- chdr_packet = axis_to_chdr(axis_packet);
- endtask : get_chdr
-
-
- // Get the next packet if there's one available and return 1. Return 0 if
- // there's no packet available.
- function bit ChdrBfm::try_get_chdr (output ChdrPacket_t chdr_packet);
- AxisPacket_t axis_packet;
- if (!super.try_get(axis_packet)) return 0;
- chdr_packet = axis_to_chdr(axis_packet);
- return 1;
- endfunction : try_get_chdr
-
-
- // Get the next packet when it becomes available (wait if necessary), but
- // don't remove it from the receive queue.
- task ChdrBfm::peek_chdr (output ChdrPacket_t chdr_packet);
- AxisPacket_t axis_packet;
- super.peek(axis_packet);
- chdr_packet = axis_to_chdr(axis_packet);
- endtask : peek_chdr
-
-
- // Get the next packet if there's one available and return 1, but don't
- // remove it from the receive queue. Return 0 if there's no packet available.
- function bit ChdrBfm::try_peek_chdr (output ChdrPacket_t chdr_packet);
- AxisPacket_t axis_packet;
- if (!super.try_get(axis_packet)) return 0;
- chdr_packet = axis_to_chdr(axis_packet);
- return 1;
- endfunction : try_peek_chdr
-
-
- // Convert the data payload of an AXI Stream packet data structure to a CHDR
+ // Convert the data payload of an AXI Stream packet data structure to a CHDR
// packet data structure.
- function ChdrBfm::ChdrPacket_t ChdrBfm::axis_to_chdr (AxisPacket_t axis_packet);
+ function void ChdrPacket::axis_to_chdr (AxisPacket_t axis_packet);
enum int { ST_HEADER, ST_TIMESTAMP, ST_METADATA, ST_PAYLOAD } rx_state;
data_t word;
int num_rx_mdata;
@@ -685,17 +651,17 @@ package PkgChdrBfm;
for(int i = 0; i < axis_packet.data.size(); i++) begin
word = axis_packet.data[i];
-
+
case (rx_state)
ST_HEADER : begin
num_rx_bytes += BYTES_PER_CHDR_W;
- chdr_packet.header = word[63:0];
+ header = word[63:0];
- // Depending on the size of the word, we could have just the header
+ // Depending on the size of the word, we could have just the header
// or both the header and the timestamp in this word.
- if (chdr_packet.header.pkt_type == CHDR_DATA_WITH_TS) begin
+ if (header.pkt_type == CHDR_DATA_WITH_TS) begin
if (CHDR_W >= 128) begin
- chdr_packet.timestamp = word[127:64];
+ timestamp = word[127:64];
rx_state = ST_METADATA;
end else begin
rx_state = ST_TIMESTAMP;
@@ -705,104 +671,178 @@ package PkgChdrBfm;
end
// Check if there's no metadata, in which case we can skip it
- if (rx_state == ST_METADATA && chdr_packet.header.num_mdata == 0) begin
+ if (rx_state == ST_METADATA && header.num_mdata == 0) begin
rx_state = ST_PAYLOAD;
end
end
ST_TIMESTAMP : begin
num_rx_bytes += BYTES_PER_CHDR_W;
- chdr_packet.timestamp = word;
- rx_state = (chdr_packet.header.num_mdata > 0) ? ST_METADATA : ST_PAYLOAD;
+ timestamp = word;
+ rx_state = (header.num_mdata > 0) ? ST_METADATA : ST_PAYLOAD;
end
ST_METADATA : begin
- chdr_packet.metadata.push_back(word);
+ metadata.push_back(word);
num_rx_mdata++;
num_rx_bytes += BYTES_PER_CHDR_W;
- if (num_rx_mdata == chdr_packet.header.num_mdata) rx_state = ST_PAYLOAD;
+ if (num_rx_mdata == header.num_mdata) rx_state = ST_PAYLOAD;
end
ST_PAYLOAD : begin
- chdr_packet.data.push_back(word);
+ data.push_back(word);
num_rx_bytes += BYTES_PER_CHDR_W;
end
endcase
end
assert (rx_state == ST_PAYLOAD) else begin
- $error("ChdrBfm::axis_to_chdr: Malformed CHDR packet");
+ $error("ChdrPacket::axis_to_chdr: Malformed CHDR packet");
end
// Check length field, noting that the last word may be partially filled
- assert (chdr_packet.header.length >= num_rx_bytes-(BYTES_PER_CHDR_W-1) &&
- chdr_packet.header.length <= num_rx_bytes) else begin
- $error("ChdrBfm::axis_to_chdr: Incorrect CHDR length");
+ assert (header.length >= num_rx_bytes-(BYTES_PER_CHDR_W-1) &&
+ header.length <= num_rx_bytes) else begin
+ $error("ChdrPacket::axis_to_chdr: Incorrect CHDR length");
end
-
- return chdr_packet;
-
endfunction : axis_to_chdr
- // Convert a CHDR packet data structure to a an AXI-Stream packet data
+ // Convert a CHDR packet data structure to a an AXI-Stream packet data
// structure.
- function ChdrBfm::AxisPacket_t ChdrBfm::chdr_to_axis (ChdrPacket_t chdr_packet);
+ function ChdrPacket::AxisPacket_t ChdrPacket::chdr_to_axis ();
int num_words, expected_words;
data_t bus_word = 0;
AxisPacket_t axis_packet = new();
// Check that we have the right number of metadata words
- assert (chdr_packet.metadata.size() == chdr_packet.header.num_mdata) else begin
- $error("ChdrBfm::chdr_to_axis: Packet metadata size doesn't match header NumMData field");
+ assert (metadata.size() == header.num_mdata) else begin
+ $error("ChdrPacket::chdr_to_axis: Packet metadata size doesn't match header NumMData field");
end
// Calculate the number of words needed to represent this packet
- num_words = chdr_packet.data.size() + chdr_packet.metadata.size();
- if (chdr_packet.header.pkt_type == CHDR_DATA_WITH_TS && CHDR_W == 64) begin
+ num_words = data.size() + metadata.size();
+ if (header.pkt_type == CHDR_DATA_WITH_TS && CHDR_W == 64) begin
// Add two words, one for header and one for timestamp
num_words += 2;
end else begin
// Add one word only for header (which may or may not include a timestamp)
num_words += 1;
end
-
+
// Calculate the number of words represented by the Length field
- expected_words = chdr_packet.header.length / BYTES_PER_CHDR_W;
- if (chdr_packet.header.length % BYTES_PER_CHDR_W != 0) expected_words++;
+ expected_words = header.length / BYTES_PER_CHDR_W;
+ if (header.length % BYTES_PER_CHDR_W != 0) expected_words++;
// Make sure length field matches actual packet length
assert (num_words == expected_words) else begin
- $error("ChdrBfm::chdr_to_axis: Packet size doesn't match header Length field");
+ $error("ChdrPacket::chdr_to_axis: Packet size doesn't match header Length field");
end
// Insert header
- bus_word[63:0] = chdr_packet.header;
+ bus_word[63:0] = header;
if (CHDR_W == 64) begin
axis_packet.data.push_back(bus_word);
- if (chdr_packet.header.pkt_type == CHDR_DATA_WITH_TS) begin
+ if (header.pkt_type == CHDR_DATA_WITH_TS) begin
// Insert timestamp
- axis_packet.data.push_back(chdr_packet.timestamp);
+ axis_packet.data.push_back(timestamp);
end
end else begin
- // Copy the timestamp word from the header, regardless of whether or not
+ // Copy the timestamp word from the header, regardless of whether or not
// this packet uses the timestamp field.
- bus_word[127:64] = chdr_packet.timestamp;
+ bus_word[127:64] = timestamp;
axis_packet.data.push_back(bus_word);
end
// Insert metadata
- foreach (chdr_packet.metadata[i]) begin
- bus_word = chdr_packet.metadata[i];
+ foreach (metadata[i]) begin
+ bus_word = metadata[i];
axis_packet.data.push_back(bus_word);
end
// Insert payload
- foreach (chdr_packet.data[i]) begin
- bus_word = chdr_packet.data[i];
+ foreach (data[i]) begin
+ bus_word = data[i];
axis_packet.data.push_back(bus_word);
end
return axis_packet;
-
endfunction : chdr_to_axis
-
+
+
+
+ //---------------------------------------------------------------------------
+ // CHDR BFM Class Methods
+ //---------------------------------------------------------------------------
+
+ // Class constructor. This must be given an interface for the master
+ // connection and an interface for the slave connection.
+ function ChdrBfm::new (
+ virtual AxiStreamIf #(CHDR_W, USER_WIDTH).master master,
+ virtual AxiStreamIf #(CHDR_W, USER_WIDTH).slave slave
+ );
+ super.new(master, slave);
+ assert(CHDR_W % 64 == 0) else begin
+ $fatal(1, "ChdrBfm::new: CHDR bus width must be a multiple of 64 bits");
+ end
+ endfunction : new
+
+
+ // Queue the provided packet for transmission
+ task ChdrBfm::put_chdr (ChdrPacket_t chdr_packet);
+ AxisPacket_t axis_packet;
+
+ axis_packet = chdr_packet.chdr_to_axis();
+ super.put(axis_packet);
+ endtask : put_chdr
+
+
+ // Attempt to queue the provided packet for transmission. Return 1 if
+ // successful, return 0 if the queue is full.
+ function bit ChdrBfm::try_put_chdr (ChdrPacket_t chdr_packet);
+ AxisPacket_t axis_packet;
+ bit status;
+
+ axis_packet = chdr_packet.chdr_to_axis();
+ return super.try_put(axis_packet);
+ endfunction : try_put_chdr
+
+
+ // Get the next packet when it becomes available (wait if necessary)
+ task ChdrBfm::get_chdr (output ChdrPacket_t chdr_packet);
+ AxisPacket_t axis_packet;
+ super.get(axis_packet);
+ chdr_packet = new();
+ chdr_packet.axis_to_chdr(axis_packet);
+ endtask : get_chdr
+
+
+ // Get the next packet if there's one available and return 1. Return 0 if
+ // there's no packet available.
+ function bit ChdrBfm::try_get_chdr (output ChdrPacket_t chdr_packet);
+ AxisPacket_t axis_packet;
+ if (!super.try_get(axis_packet)) return 0;
+ chdr_packet = new();
+ chdr_packet.axis_to_chdr(axis_packet);
+ return 1;
+ endfunction : try_get_chdr
+
+
+ // Get the next packet when it becomes available (wait if necessary), but
+ // don't remove it from the receive queue.
+ task ChdrBfm::peek_chdr (output ChdrPacket_t chdr_packet);
+ AxisPacket_t axis_packet;
+ super.peek(axis_packet);
+ chdr_packet = new();
+ chdr_packet.axis_to_chdr(axis_packet);
+ endtask : peek_chdr
+
+
+ // Get the next packet if there's one available and return 1, but don't
+ // remove it from the receive queue. Return 0 if there's no packet available.
+ function bit ChdrBfm::try_peek_chdr (output ChdrPacket_t chdr_packet);
+ AxisPacket_t axis_packet;
+ if (!super.try_get(axis_packet)) return 0;
+ chdr_packet = new();
+ chdr_packet.axis_to_chdr(axis_packet);
+ return 1;
+ endfunction : try_peek_chdr
endpackage : PkgChdrBfm
diff --git a/fpga/usrp3/sim/rfnoc/PkgRfnocItemUtils.sv b/fpga/usrp3/sim/rfnoc/PkgRfnocItemUtils.sv
index f827d2363..64d39e63f 100644
--- a/fpga/usrp3/sim/rfnoc/PkgRfnocItemUtils.sv
+++ b/fpga/usrp3/sim/rfnoc/PkgRfnocItemUtils.sv
@@ -134,7 +134,7 @@ package PkgRfnocItemUtils;
// Check if the contents of two buffers is equal
function bit equal(
- ItemDataBuff #(item_t) rhs
+ ItemDataBuff #(item_t,CHDR_W) rhs
);
if (this.size() != rhs.size()) return 0;
for (int i = 0; i < this.size(); i++) begin
diff --git a/fpga/usrp3/sim/rfnoc/PkgTestExec.sv b/fpga/usrp3/sim/rfnoc/PkgTestExec.sv
index ba4455912..4138fca86 100644
--- a/fpga/usrp3/sim/rfnoc/PkgTestExec.sv
+++ b/fpga/usrp3/sim/rfnoc/PkgTestExec.sv
@@ -5,7 +5,7 @@
//
// Module: PkgTestExec
//
-// Description: This package provides infrastructure for tracking the state of
+// Description: This package provides infrastructure for tracking the state of
// testbench execution and the results of each test.
//
@@ -29,6 +29,7 @@ package PkgTestExec;
int num_assertions; // Number of assertions checked for the current test
time start_time, end_time; // Start and end time of the testbench
bit stop_on_error = 1; // Configuration option to stop when an error occurs
+ bit done = 0; // Flag that sets when tb is finished
bit test_status[$]; // Pass/fail status of each test
timeout_t tb_timeout; // Handle to timeout for the overall testbench
@@ -54,7 +55,7 @@ package PkgTestExec;
// Get the sempahore, to prevent multiple overlapping instances of the
// same testbench.
test_sem.get();
-
+ done = 0;
$display("========================================================");
$display("TESTBENCH STARTED: %s", tb_name);
$display("========================================================");
@@ -65,8 +66,8 @@ package PkgTestExec;
num_finished = 0;
num_passed = 0;
start_timeout(
- tb_timeout,
- time_limit,
+ tb_timeout,
+ time_limit,
$sformatf("Testbench \"%s\" time limit exceeded", tb_name),
SEV_FATAL
);
@@ -75,7 +76,7 @@ package PkgTestExec;
// Call end_tb() at the end of a testbench to report final statistics and,
// optionally, end simulation.
- //
+ //
// finish: Set to 1 (default) to cause $finish() to be called at the
// end of simulation, cuasing the simulator to close.
//
@@ -83,7 +84,6 @@ package PkgTestExec;
assert (num_started == num_finished) else begin
$fatal(1, "Testbench ended before test completed");
end
-
end_time = $time;
$display("========================================================");
$display("TESTBENCH FINISHED: %s", tb_name);
@@ -98,6 +98,7 @@ package PkgTestExec;
end_timeout(tb_timeout);
+ done = 1;
if (finish) $finish();
// Release the semaphore to allow new instances of the testbench to run
@@ -118,8 +119,8 @@ package PkgTestExec;
// Create a timeout for this test
if (time_limit > 0) begin
start_timeout(
- test_timeout,
- time_limit,
+ test_timeout,
+ time_limit,
$sformatf("Test \"%s\" time limit exceeded", test_name),
SEV_FATAL
);
@@ -133,7 +134,7 @@ package PkgTestExec;
endtask : start_test
- // Call end_test() at the end of each test.
+ // Call end_test() at the end of each test.
//
// test_result: Optional value to indicate the overall pass/fail result
// of the test. Use non-zero for pass, 0 for fail.
@@ -149,7 +150,7 @@ package PkgTestExec;
passed = test_status[num_started-1] && test_result;
num_finished++;
- $display("[TEST CASE %3d] (t = %t) DONE... %s",
+ $display("[TEST CASE %3d] (t = %t) DONE... %s",
num_started, $time, passed ? "Passed" : "FAILED");
if (passed) num_passed++;
@@ -163,7 +164,7 @@ package PkgTestExec;
//
// expr: The expression value to be asserted
// message: String to report if the assertion fails
- //
+ //
function void assert_error(int expr, string message = "");
num_assertions++;
assert (expr) else begin
@@ -178,7 +179,7 @@ package PkgTestExec;
//
// expr: The expression value to be asserted
// message: String to report if the assertion fails
- //
+ //
function void assert_fatal(int expr, string message = "");
num_assertions++;
assert (expr) else begin
@@ -192,7 +193,7 @@ package PkgTestExec;
//
// expr: The expression value to be asserted
// message: String to report if the assertion fails
- //
+ //
function void assert_warning(int expr, string message = "");
num_assertions++;
assert (expr) else begin
@@ -209,7 +210,7 @@ package PkgTestExec;
// severity: Indicates the type of severity task that should be used if
// the assertion fails ($info, $warning, $error, $fatal).
// Default value is SEV_ERROR.
- //
+ //
function void assert_sev(
int expr,
string message = "",
@@ -249,8 +250,8 @@ package PkgTestExec;
// used if the timeout expires. Default is SEV_ERROR.
//
task start_timeout(
- output timeout_t handle,
- input realtime timeout_delay,
+ output timeout_t handle,
+ input realtime timeout_delay,
input string message = "Timeout",
input severity_t severity = SEV_ERROR
);