1// 2// Copyright 2020 Ettus Research, A National Instruments Company 3// 4// SPDX-License-Identifier: LGPL-3.0-or-later 5// 6// Module: rfnoc_block_fosphor_tb 7// 8// Description: Testbench for the fosphor RFNoC block. 9// 10 11`default_nettype none 12 13 14module rfnoc_block_fosphor_tb; 15 16 `include "test_exec.svh" 17 18 import PkgTestExec::*; 19 import PkgChdrUtils::*; 20 import PkgRfnocBlockCtrlBfm::*; 21 import PkgRfnocItemUtils::*; 22 23 `include "rfnoc_block_fosphor_regs.vh" 24 25 //--------------------------------------------------------------------------- 26 // Testbench Configuration 27 //--------------------------------------------------------------------------- 28 29 localparam [ 9:0] THIS_PORTID = 10'h123; 30 localparam [31:0] NOC_ID = 32'h666F0000; 31 localparam int CHDR_W = 64; 32 localparam int ITEM_W = 32; 33 localparam int NUM_PORTS_I = 1; 34 localparam int NUM_PORTS_O = 2; 35 localparam int MTU = 10; 36 localparam int SPP = 128; 37 localparam int PKT_SIZE_BYTES = SPP * (ITEM_W/8); 38 localparam int STALL_PROB = 60; // Default BFM stall probability 39 localparam real CHDR_CLK_PER = 5.0; // 200 MHz 40 localparam real CTRL_CLK_PER = 25.0; // 40 MHz 41 localparam real CE_CLK_PER = 5.0; // 200 MHz 42 43 localparam int HIST_PKT_PER_BURST = 66; // Always 64 hist + 1 max + 1 avg 44 localparam int HIST_PORT = 0; 45 localparam int WF_PORT = 1; 46 47 //--------------------------------------------------------------------------- 48 // Clocks and Resets 49 //--------------------------------------------------------------------------- 50 51 bit rfnoc_chdr_clk; 52 bit rfnoc_ctrl_clk; 53 bit ce_clk; 54 55 sim_clock_gen #(CHDR_CLK_PER) rfnoc_chdr_clk_gen (.clk(rfnoc_chdr_clk), .rst()); 56 sim_clock_gen #(CTRL_CLK_PER) rfnoc_ctrl_clk_gen (.clk(rfnoc_ctrl_clk), .rst()); 57 sim_clock_gen #(CE_CLK_PER) ce_clk_gen (.clk(ce_clk), .rst()); 58 59 //--------------------------------------------------------------------------- 60 // Bus Functional Models 61 //--------------------------------------------------------------------------- 62 63 // Backend Interface 64 RfnocBackendIf backend (rfnoc_chdr_clk, rfnoc_ctrl_clk); 65 66 // AXIS-Ctrl Interface 67 AxiStreamIf #(32) m_ctrl (rfnoc_ctrl_clk, 1'b0); 68 AxiStreamIf #(32) s_ctrl (rfnoc_ctrl_clk, 1'b0); 69 70 // AXIS-CHDR Interfaces 71 AxiStreamIf #(CHDR_W) m_chdr [NUM_PORTS_I] (rfnoc_chdr_clk, 1'b0); 72 AxiStreamIf #(CHDR_W) s_chdr [NUM_PORTS_O] (rfnoc_chdr_clk, 1'b0); 73 74 // Block Controller BFM 75 RfnocBlockCtrlBfm #(CHDR_W, ITEM_W) blk_ctrl = new(backend, m_ctrl, s_ctrl); 76 77 // CHDR word and item/sample data types 78 typedef ChdrData #(CHDR_W, ITEM_W)::chdr_word_t chdr_word_t; 79 typedef ChdrData #(CHDR_W, ITEM_W)::item_t item_t; 80 81 // Connect block controller to BFMs 82 for (genvar i = 0; i < NUM_PORTS_I; i++) begin : gen_bfm_input_connections 83 initial begin 84 blk_ctrl.connect_master_data_port(i, m_chdr[i], PKT_SIZE_BYTES); 85 blk_ctrl.set_master_stall_prob(i, STALL_PROB); 86 end 87 end 88 for (genvar i = 0; i < NUM_PORTS_O; i++) begin : gen_bfm_output_connections 89 initial begin 90 blk_ctrl.connect_slave_data_port(i, s_chdr[i]); 91 blk_ctrl.set_slave_stall_prob(i, STALL_PROB); 92 end 93 end 94 95 //--------------------------------------------------------------------------- 96 // Device Under Test (DUT) 97 //--------------------------------------------------------------------------- 98 99 // DUT Slave (Input) Port Signals 100 logic [CHDR_W*NUM_PORTS_I-1:0] s_rfnoc_chdr_tdata; 101 logic [ NUM_PORTS_I-1:0] s_rfnoc_chdr_tlast; 102 logic [ NUM_PORTS_I-1:0] s_rfnoc_chdr_tvalid; 103 logic [ NUM_PORTS_I-1:0] s_rfnoc_chdr_tready; 104 105 // DUT Master (Output) Port Signals 106 logic [CHDR_W*NUM_PORTS_O-1:0] m_rfnoc_chdr_tdata; 107 logic [ NUM_PORTS_O-1:0] m_rfnoc_chdr_tlast; 108 logic [ NUM_PORTS_O-1:0] m_rfnoc_chdr_tvalid; 109 logic [ NUM_PORTS_O-1:0] m_rfnoc_chdr_tready; 110 111 // Map the array of BFMs to a flat vector for the DUT connections 112 for (genvar i = 0; i < NUM_PORTS_I; i++) begin : gen_dut_input_connections 113 // Connect BFM master to DUT slave port 114 assign s_rfnoc_chdr_tdata[CHDR_W*i+:CHDR_W] = m_chdr[i].tdata; 115 assign s_rfnoc_chdr_tlast[i] = m_chdr[i].tlast; 116 assign s_rfnoc_chdr_tvalid[i] = m_chdr[i].tvalid; 117 assign m_chdr[i].tready = s_rfnoc_chdr_tready[i]; 118 end 119 for (genvar i = 0; i < NUM_PORTS_O; i++) begin : gen_dut_output_connections 120 // Connect BFM slave to DUT master port 121 assign s_chdr[i].tdata = m_rfnoc_chdr_tdata[CHDR_W*i+:CHDR_W]; 122 assign s_chdr[i].tlast = m_rfnoc_chdr_tlast[i]; 123 assign s_chdr[i].tvalid = m_rfnoc_chdr_tvalid[i]; 124 assign m_rfnoc_chdr_tready[i] = s_chdr[i].tready; 125 end 126 127 rfnoc_block_fosphor #( 128 .THIS_PORTID (THIS_PORTID), 129 .CHDR_W (CHDR_W), 130 .MTU (MTU) 131 ) dut ( 132 .rfnoc_chdr_clk (rfnoc_chdr_clk), 133 .rfnoc_ctrl_clk (rfnoc_ctrl_clk), 134 .ce_clk (ce_clk), 135 .rfnoc_core_config (backend.cfg), 136 .rfnoc_core_status (backend.sts), 137 .s_rfnoc_chdr_tdata (s_rfnoc_chdr_tdata), 138 .s_rfnoc_chdr_tlast (s_rfnoc_chdr_tlast), 139 .s_rfnoc_chdr_tvalid (s_rfnoc_chdr_tvalid), 140 .s_rfnoc_chdr_tready (s_rfnoc_chdr_tready), 141 .m_rfnoc_chdr_tdata (m_rfnoc_chdr_tdata), 142 .m_rfnoc_chdr_tlast (m_rfnoc_chdr_tlast), 143 .m_rfnoc_chdr_tvalid (m_rfnoc_chdr_tvalid), 144 .m_rfnoc_chdr_tready (m_rfnoc_chdr_tready), 145 .s_rfnoc_ctrl_tdata (m_ctrl.tdata), 146 .s_rfnoc_ctrl_tlast (m_ctrl.tlast), 147 .s_rfnoc_ctrl_tvalid (m_ctrl.tvalid), 148 .s_rfnoc_ctrl_tready (m_ctrl.tready), 149 .m_rfnoc_ctrl_tdata (s_ctrl.tdata), 150 .m_rfnoc_ctrl_tlast (s_ctrl.tlast), 151 .m_rfnoc_ctrl_tvalid (s_ctrl.tvalid), 152 .m_rfnoc_ctrl_tready (s_ctrl.tready) 153 ); 154 155 156 //--------------------------------------------------------------------------- 157 // Helper Functions 158 //--------------------------------------------------------------------------- 159 160 typedef enum bit { WF_MAX_HOLD, WF_AVERAGE } wf_mode_t; 161 typedef enum bit [1:0] { WF_1_1, WF_1_8, WF_1_64, WF_1_256 } wf_div_t; 162 163 // Data structure to hold the Fosphor configuration state 164 typedef struct packed { 165 bit en_wf; 166 bit en_hist; 167 bit en_noise; 168 bit en_dither; 169 bit [11:0] hist_decim; 170 bit [15:0] offset; 171 bit [15:0] scale; 172 bit [15:0] trise; 173 bit [15:0] tdecay; 174 bit [15:0] alpha; 175 bit [15:0] epsilon; 176 wf_mode_t wf_mode; 177 wf_div_t wf_div; 178 bit [ 7:0] wf_decim; 179 } fosphor_config_t; 180 181 // Default configuration copied from GNURadio 182 const fosphor_config_t DEFAULT_CONFG = '{ 183 en_wf : 1, 184 en_hist : 1, 185 en_noise : 0, 186 en_dither : 0, 187 hist_decim : 2, 188 offset : 0, 189 scale : 256, 190 trise : 4096, 191 tdecay : 16384, 192 alpha : 65280, 193 epsilon : 2, 194 wf_mode : WF_MAX_HOLD, 195 wf_div : WF_1_8, 196 wf_decim : 2 197 }; 198 199 200 // Rand#(WIDTH)::rand_logic() returns a WIDTH-bit random number. We avoid 201 // std::randomize() due to license requirements and limited tool support. 202 class Rand #(WIDTH = 32); 203 204 static function logic [WIDTH-1:0] rand_bits(); 205 bit [WIDTH-1:0] result; 206 int num_rand32 = (WIDTH + 31) / 32; 207 for (int i = 0; i < num_rand32; i++) begin 208 result = {result, $urandom()}; 209 end 210 return result; 211 endfunction : rand_bits 212 213 endclass : Rand 214 215 216 // Set all Fosphor registers based off the cfg data structure 217 task automatic set_registers(fosphor_config_t cfg); 218 blk_ctrl.reg_write(REG_ENABLE, (int'(cfg.en_wf) << 1) | 219 (int'(cfg.en_hist) << 0)); 220 blk_ctrl.reg_write(REG_RANDOM, (int'(cfg.en_noise) << 1) | 221 (int'(cfg.en_dither) << 0)); 222 blk_ctrl.reg_write(REG_HIST_DECIM, cfg.hist_decim); 223 blk_ctrl.reg_write(REG_OFFSET, cfg.offset); 224 blk_ctrl.reg_write(REG_SCALE, cfg.scale); 225 blk_ctrl.reg_write(REG_TRISE, cfg.trise); 226 blk_ctrl.reg_write(REG_TDECAY, cfg.tdecay); 227 blk_ctrl.reg_write(REG_ALPHA, cfg.alpha); 228 blk_ctrl.reg_write(REG_EPSILON, cfg.epsilon); 229 blk_ctrl.reg_write(REG_WF_CTRL, (int'(cfg.wf_mode) << 7) | int'(cfg.wf_div)); 230 blk_ctrl.reg_write(REG_WF_DECIM, cfg.wf_decim); 231 endtask : set_registers; 232 233 234 // Verify that all the Fosphor registers match the cfg data structure 235 task automatic verify_registers(fosphor_config_t cfg); 236 bit [31:0] value; 237 238 blk_ctrl.reg_read(REG_ENABLE, value); 239 `ASSERT_ERROR(value[1] == cfg.en_wf, "REG_ENABLE[1] didn't have expected value"); 240 `ASSERT_ERROR(value[0] == cfg.en_hist, "REG_ENABLE[0] didn't have expected value"); 241 242 blk_ctrl.reg_read(REG_CLEAR, value); 243 `ASSERT_ERROR(value == 0, "REG_CLEAR didn't have expected value"); 244 245 blk_ctrl.reg_read(REG_RANDOM, value); 246 `ASSERT_ERROR(value[1] == cfg.en_noise, "REG_RANDOM[1] didn't have expected value"); 247 `ASSERT_ERROR(value[0] == cfg.en_dither, "REG_RANDOM[0] didn't have expected value"); 248 249 blk_ctrl.reg_read(REG_HIST_DECIM, value); 250 `ASSERT_ERROR(value == cfg.hist_decim, "REG_HIST_DECIM didn't have expected value"); 251 252 blk_ctrl.reg_read(REG_OFFSET, value); 253 `ASSERT_ERROR(value == cfg.offset, "REG_OFFSET didn't have expected value"); 254 255 blk_ctrl.reg_read(REG_SCALE, value); 256 `ASSERT_ERROR(value == cfg.scale, "REG_SCALE didn't have expected value"); 257 258 blk_ctrl.reg_read(REG_TRISE, value); 259 `ASSERT_ERROR(value == cfg.trise, "REG_TRISE didn't have expected value"); 260 261 blk_ctrl.reg_read(REG_TDECAY, value); 262 `ASSERT_ERROR(value == cfg.tdecay, "REG_TDECAY didn't have expected value"); 263 264 blk_ctrl.reg_read(REG_ALPHA, value); 265 `ASSERT_ERROR(value == cfg.alpha, "REG_ALPHA didn't have expected value"); 266 267 blk_ctrl.reg_read(REG_EPSILON, value); 268 `ASSERT_ERROR(value == cfg.epsilon, "REG_EPSILON didn't have expected value"); 269 270 blk_ctrl.reg_read(REG_WF_CTRL, value); 271 `ASSERT_ERROR(value[7] == cfg.wf_mode, "REG_WF_CTRL didn't have expected value"); 272 `ASSERT_ERROR(value[1:0] == cfg.wf_div, "REG_WF_CTRL didn't have expected value"); 273 274 blk_ctrl.reg_read(REG_WF_DECIM, value); 275 `ASSERT_ERROR(value == cfg.wf_decim, "REG_WF_DECIM didn't have expected value"); 276 endtask : verify_registers; 277 278 279 // Generate a random Fosphor configuration to test 280 task automatic randomize_cfg(output fosphor_config_t cfg, output int spp); 281 // Chase a random SPP size, but make it a power of 2 (like the FFT) up to 282 // the define SPP value. 283 spp = 2**$urandom_range(4, $clog2(SPP)); 284 285 // Start by randomizing the entire fosphor configuration, but then 286 cfg = Rand #($bits(cfg))::rand_bits(); 287 288 // Keep decimation relatively small to decrease simulation time 289 cfg.hist_decim = $urandom_range(0, 8); 290 291 // Make sure wf_mode and wf_div are valid values 292 cfg.wf_mode = wf_mode_t'($urandom_range(cfg.wf_mode.num()-1)); 293 cfg.wf_div = wf_div_t'($urandom_range(cfg.wf_div.num()-1)); 294 endtask : randomize_cfg 295 296 297 // Test the passed Fosphor configuration. This updates the registers, inputs 298 // num_packets of data (spp-samples each) and verifies the output. 299 task automatic test_config(fosphor_config_t cfg, int num_packets, int spp); 300 item_t fft_items[$]; 301 302 $display("Testing . . ."); 303 $display(" packets: %0d", num_packets); 304 $display(" spp: %0d", spp); 305 $display(" en_wf %0d", cfg.en_wf); 306 $display(" en_hist %0d", cfg.en_hist); 307 $display(" hist_decim: %0d", cfg.hist_decim); 308 $display(" wf_decim: %0d", cfg.wf_decim); 309 310 // Clear any existing data 311 blk_ctrl.reg_write(REG_CLEAR, 1); 312 313 // Configure all the core's registers 314 set_registers(cfg); 315 316 // Generate packets to send 317 fft_items = {}; 318 for (int i = 0; i < spp; i++) begin 319 fft_items.push_back({ 320 shortint'(i), 321 shortint'(0) 322 }); 323 end 324 325 // Send the packets 326 for (int i = 0; i < num_packets; i++) begin 327 blk_ctrl.send_items(0, fft_items); 328 end 329 330 fork 331 begin : fork_waterfall 332 item_t recv_items[$]; 333 int exp_num_packets; 334 335 if (cfg.en_wf) begin 336 // Calculate expected number of packets 337 exp_num_packets = num_packets / (cfg.wf_decim + 2); 338 end else begin 339 exp_num_packets = 0; 340 end 341 342 $display("Expecting %0d waterfall packets of length %0d bytes", 343 exp_num_packets, spp); 344 345 if (exp_num_packets > 0) begin 346 for (int i = 0; i < exp_num_packets; i++) begin 347 string err_string; 348 blk_ctrl.recv_items(WF_PORT, recv_items); 349 350 // We expect one byte output per sample input 351 $sformat( 352 err_string, 353 "Waterfall packet of %0d bytes didn't match expected length of %0d bytes", 354 recv_items.size()*4, spp 355 ); 356 `ASSERT_ERROR(recv_items.size()*4 == spp, err_string); 357 end 358 $display("All waterfall packets received!"); 359 end 360 end 361 362 begin : fork_histogram 363 item_t recv_items[$]; 364 chdr_word_t mdata[$]; 365 int exp_num_packets; 366 packet_info_t pkt_info; 367 368 if(cfg.en_hist) begin 369 // Calculate expected number of packets 370 exp_num_packets = num_packets / (cfg.hist_decim + 2); 371 // Round it down to a multiple of HIST_PKT_PER_BURST, since it always 372 // outputs HIST_PKT_PER_BURST packets at a time. 373 exp_num_packets = (exp_num_packets / HIST_PKT_PER_BURST) * HIST_PKT_PER_BURST; 374 end else begin 375 exp_num_packets = 0; 376 end 377 378 $display("Expecting %0d histogram packets of length %0d bytes", 379 exp_num_packets, spp); 380 381 if (exp_num_packets > 0) begin 382 for (int i = 0; i < exp_num_packets; i++) begin 383 string err_string; 384 blk_ctrl.recv_items_adv(HIST_PORT, recv_items, mdata, pkt_info); 385 //$display("Recvd hist pkt %0d", i); 386 387 // We expect one byte output per sample input 388 $sformat( 389 err_string, 390 "Histogram packet of %0d bytes didn't match expected length of %0d bytes", 391 recv_items.size()*4, spp 392 ); 393 `ASSERT_ERROR(recv_items.size()*4 == spp, err_string); 394 395 // Check that the last packet of each burst has EOB set 396 if ((i+1) % HIST_PKT_PER_BURST == 0) begin 397 `ASSERT_ERROR(pkt_info.eob == 1, "EOB was not set on last packet of histogram"); 398 end else begin 399 `ASSERT_ERROR(pkt_info.eob == 0, "EOB was set on middle packet histogram"); 400 end 401 end 402 $display("All histogram packets received!"); 403 end 404 end 405 join 406 407 // Wait until all input packets were accepted before moving on, since we 408 // don't want any output from these packets to be confused with the next 409 // test. 410 blk_ctrl.wait_complete(0); 411 #(CE_CLK_PER * SPP * 2); 412 413 // The current Fosphor core doesn't cleanly handle transitions between 414 // settings, so we reset the core before each test. 415 blk_ctrl.reg_write(REG_CLEAR, 2); 416 417 endtask : test_config 418 419 420 //--------------------------------------------------------------------------- 421 // Test Sequences 422 //--------------------------------------------------------------------------- 423 424 // Test that all the registers read/write as expected 425 task automatic test_registers(); 426 fosphor_config_t cfg; 427 428 // All registers reset to 0 429 test.start_test("Test Registers (reset values)", 50us); 430 cfg = '0; 431 verify_registers(cfg); 432 test.end_test(); 433 434 test.start_test("Test Registers (max values)", 50us); 435 cfg = '{ 436 en_wf : 'h1, 437 en_hist : 'h1, 438 en_noise : 'h1, 439 en_dither : 'h1, 440 hist_decim : 'hFFF, 441 offset : 'hFFFF, 442 scale : 'hFFFF, 443 trise : 'hFFFF, 444 tdecay : 'hFFFF, 445 alpha : 'hFFFF, 446 epsilon : 'hFFFF, 447 wf_mode : wf_mode_t'('h1), 448 wf_div : wf_div_t'('h3), 449 wf_decim : 'hFF 450 }; 451 set_registers(cfg); 452 verify_registers(cfg); 453 test.end_test(); 454 455 test.start_test("Test Registers (default values)", 50us); 456 cfg = DEFAULT_CONFG; 457 set_registers(cfg); 458 verify_registers(cfg); 459 test.end_test(); 460 endtask : test_registers; 461 462 463 // Test waterfall decimation settings 464 task automatic test_wf_decimation(); 465 const int spp = 16; 466 const int num_wf = 4; 467 fosphor_config_t cfg; 468 int num_packets; 469 470 test.start_test("Test waterfall decimation", 1ms); 471 cfg = DEFAULT_CONFG; 472 cfg.en_hist = 0; 473 for (int wf_decim = 0; wf_decim < 5; wf_decim++) begin 474 cfg.wf_decim = wf_decim; 475 // Input enough packets to get num_wf packets out 476 num_packets = (wf_decim+2) * (num_wf+1) - 1; 477 test_config(cfg, num_packets, spp); 478 end 479 test.end_test(); 480 endtask : test_wf_decimation 481 482 483 // Test histogram decimation settings 484 task automatic test_hist_decimation(); 485 const int spp = 16; 486 const int num_hist = HIST_PKT_PER_BURST * 4; 487 fosphor_config_t cfg; 488 int num_packets; 489 490 test.start_test("Test histogram decimation", 1ms); 491 cfg = DEFAULT_CONFG; 492 cfg.en_wf = 0; 493 for (int hist_decim = 0; hist_decim < 5; hist_decim++) begin 494 cfg.hist_decim = hist_decim; 495 // Input enough packets to get num_hist packets out 496 num_packets = (hist_decim+2) * (num_hist+HIST_PKT_PER_BURST/2); 497 test_config(cfg, num_packets, spp); 498 end 499 test.end_test(); 500 endtask : test_hist_decimation 501 502 503 // Choose num_iter random configurations and test each one 504 task automatic test_rand_config(int num_iter); 505 int num_packets, num_packets_wf, num_packets_hist; 506 int spp; 507 fosphor_config_t cfg; 508 const int num_wf = 2; // Get 2 waterfall packets 509 const int num_hist = HIST_PKT_PER_BURST * 2; // Get 2 histogram bursts 510 511 test.start_test("Test random configurations", num_iter * 10ms); 512 for(int i = 0; i < num_iter; i++) begin 513 string str; 514 $display("<<<<<<<< RANDOM ITERATION %0d >>>>>>>>", i); 515 //test.current_test = $sformatf("%0d", i); 516 517 // Choose a random configuration 518 randomize_cfg(cfg, spp); 519 520 // Only allow the output of waterfall or histogram at one time. Because 521 // they operate independently and their outputs overlap, we only check 522 // one at a time. This way we can end testing cleanly between output 523 // packets without cutting off either the waterfall or histogram output. 524 if (($urandom() & 1) == 0) begin 525 cfg.en_wf = 1; 526 cfg.en_hist = 0; 527 num_packets = (cfg.wf_decim+2) * (num_wf+1) - 1; 528 end else begin 529 cfg.en_wf = 0; 530 cfg.en_hist = 1; 531 num_packets = (cfg.hist_decim+2) * (num_hist+HIST_PKT_PER_BURST/2); 532 end 533 test_config(cfg, num_packets, spp); 534 end 535 test.end_test(); 536 endtask : test_rand_config 537 538 539 //--------------------------------------------------------------------------- 540 // Main Test Process 541 //--------------------------------------------------------------------------- 542 543 initial begin : tb_main 544 545 // Initialize the test exec object for this testbench 546 test.start_tb("rfnoc_block_fosphor_tb"); 547 548 // Start the BFMs running 549 blk_ctrl.run(); 550 551 //-------------------------------- 552 // Reset 553 //-------------------------------- 554 555 test.start_test("Flush block then reset it", 10us); 556 blk_ctrl.flush_and_reset(); 557 test.end_test(); 558 559 //-------------------------------- 560 // Verify Block Info 561 //-------------------------------- 562 563 test.start_test("Verify Block Info", 2us); 564 `ASSERT_ERROR(blk_ctrl.get_noc_id() == NOC_ID, "Incorrect NOC_ID Value"); 565 `ASSERT_ERROR(blk_ctrl.get_num_data_i() == NUM_PORTS_I, "Incorrect NUM_DATA_I Value"); 566 `ASSERT_ERROR(blk_ctrl.get_num_data_o() == NUM_PORTS_O, "Incorrect NUM_DATA_O Value"); 567 `ASSERT_ERROR(blk_ctrl.get_mtu() == MTU, "Incorrect MTU Value"); 568 test.end_test(); 569 570 //-------------------------------- 571 // Test Sequences 572 //-------------------------------- 573 574 test_registers(); 575 test_wf_decimation(); 576 test_hist_decimation(); 577 test_rand_config(16); 578 579 //-------------------------------- 580 // Finish Up 581 //-------------------------------- 582 583 // Display final statistics and results 584 test.end_tb(); 585 end : tb_main 586 587endmodule : rfnoc_block_fosphor_tb 588 589 590`default_nettype wire 591