1// 2// Copyright 2020 Ettus Research, a National Instruments Brand 3// 4// SPDX-License-Identifier: LGPL-3.0-or-later 5// 6// Module: eth_ifc_tb 7// 8// Description: Testbench for eth_interface 9// 10 11module eth_ifc_tb #( 12 parameter TEST_NAME = "eth_ifc_tb", 13 parameter SV_ETH_IFC =1, 14 parameter ENET_W =64, 15 parameter CPU_W =64, 16 parameter CHDR_W =64 17)( 18 /* no IO */ 19); 20 // Include macros and time declarations for use with PkgTestExec 21 `define TEST_EXEC_OBJ test 22 `include "test_exec.svh" 23 import PkgAxiStreamBfm::*; 24 import PkgTestExec::*; 25 import PkgChdrUtils::*; 26 import PkgChdrBfm::*; 27 import PkgEthernet::*; 28 29 //--------------------------------------------------------------------------- 30 // Local Parameters 31 //--------------------------------------------------------------------------- 32 localparam ENET_USER_W = $clog2(ENET_W/8)+1; 33 localparam CPU_USER_W = $clog2(CPU_W/8)+1; 34 localparam CHDR_USER_W = $clog2(CHDR_W/8)+1; 35 localparam REG_AWIDTH = 14; 36 localparam [15:0] PROTOVER = {8'd1, 8'd0}; 37 localparam MTU = 10; 38 localparam NODE_INST = 0; 39 localparam RT_TBL_SIZE = 6; 40 localparam REG_BASE_ETH_SWITCH = 14'h1000; 41 localparam BASE = REG_BASE_ETH_SWITCH; 42 localparam DROP_MIN_PACKET = 0; 43 localparam SYNC = (ENET_W==512) ? 0:1; 44 localparam ETH_PERIOD = (ENET_W==512) ? 3.1:5.0; 45 // can set PREAMBLE_BYTES to 0 or 6 if SV_ETH_IFC, but otherwise 46 // it's hardcoded to 6. (0 is normal for 100G)(6 is normal for old Xge) 47 localparam PREAMBLE_BYTES = SV_ETH_IFC ? 0 : 6; 48 // Include for register offsets 49 `include "../eth_regs.vh" 50 // allows the DUT to push full words and tb does not check tuser/tkeep of packets it's transmitting 51 localparam IGNORE_EXTRA_DATA = 0; 52 53 //--------------------------------------------------------------------------- 54 // Clocks 55 //--------------------------------------------------------------------------- 56 57 bit clk; 58 bit reset; 59 60 sim_clock_gen #(.PERIOD(5.0), .AUTOSTART(1)) 61 clk_gen (.clk(clk), .rst(reset)); 62 sim_clock_gen #(.PERIOD(ETH_PERIOD), .AUTOSTART(1)) 63 eth_clk_gen (.clk(eth_clk), .rst(eth_reset)); 64 65 //--------------------------------------------------------------------------- 66 // Bus Functional Models 67 //--------------------------------------------------------------------------- 68 TestExec test = new(); 69 70 localparam MAX_PACKET_BYTES = 2**16; 71 AxiStreamIf #(.DATA_WIDTH(ENET_W),.USER_WIDTH(ENET_USER_W), 72 .MAX_PACKET_BYTES(MAX_PACKET_BYTES)) 73 eth_tx (eth_clk, eth_reset); 74 AxiStreamIf #(.DATA_WIDTH(ENET_W),.USER_WIDTH(ENET_USER_W), 75 .MAX_PACKET_BYTES(MAX_PACKET_BYTES)) 76 eth_rx (eth_clk, eth_reset); 77 78 AxiStreamIf #(.DATA_WIDTH(CHDR_W),.USER_WIDTH(CHDR_USER_W),.TKEEP(0),.TUSER(0)) 79 v2e (clk, reset); 80 AxiStreamIf #(.DATA_WIDTH(CHDR_W),.USER_WIDTH(CHDR_USER_W),.TKEEP(0),.TUSER(0)) 81 e2v (clk, reset); 82 83 AxiStreamIf #(.DATA_WIDTH(CPU_W),.USER_WIDTH(CPU_USER_W),.TKEEP(0)) 84 c2e (clk, reset); 85 AxiStreamIf #(.DATA_WIDTH(CPU_W),.USER_WIDTH(CPU_USER_W),.TKEEP(0)) 86 e2c (clk, reset); 87 88 // Bus functional model for a axi_stream controller 89 AxiStreamBfm #(.DATA_WIDTH(ENET_W),.USER_WIDTH(ENET_USER_W), 90 .MAX_PACKET_BYTES(MAX_PACKET_BYTES)) eth = 91 new(.master(eth_rx), .slave(eth_tx)); 92 AxiStreamBfm #(.DATA_WIDTH(CHDR_W),.USER_WIDTH(CHDR_USER_W),.TKEEP(0),.TUSER(0)) v = 93 new(.master(v2e), .slave(e2v)); 94 AxiStreamBfm #(.DATA_WIDTH(CPU_W),.USER_WIDTH(CPU_USER_W),.TKEEP(0)) cpu = 95 new(.master(c2e), .slave(e2c)); 96 97 //---------------------------------------------------- 98 // Instantiate DUT 99 //---------------------------------------------------- 100 101 reg reg_wr_req = 1'b0; 102 reg [REG_AWIDTH-1:0] reg_wr_addr = 0; 103 reg [31:0] reg_wr_data = 32'd0; 104 105 reg reg_rd_req = 1'b0; 106 reg [REG_AWIDTH-1:0] reg_rd_addr = 0; 107 reg reg_rd_resp; 108 reg [31:0] reg_rd_data; 109 110 reg [3:0] eth_tx_tuser = 4'd0; 111 reg [3:0] eth_rx_tuser = 4'd0; 112 reg [3:0] e2c_tuser = 4'd0; 113 reg [3:0] c2e_tuser = 4'd0; 114 115 reg [15:0] device_id =16'd0; 116 117 reg [47:0] my_mac; 118 reg [31:0] my_ip; 119 reg [15:0] my_udp_chdr_port; 120 121 122 if (SV_ETH_IFC) begin : gen_new_dut 123 124 eth_ipv4_interface #( 125 .PREAMBLE_BYTES(PREAMBLE_BYTES), 126 .CPU_FIFO_SIZE(MTU), 127 .CHDR_FIFO_SIZE(MTU), 128 .PROTOVER(PROTOVER), 129 .NODE_INST(NODE_INST), 130 .REG_AWIDTH(REG_AWIDTH), 131 .RT_TBL_SIZE(RT_TBL_SIZE), 132 .BASE(BASE),.SYNC(SYNC), 133 .ENET_W(ENET_W),.CPU_W(CPU_W),.CHDR_W(CHDR_W) 134 ) eth_interface ( 135 .bus_clk(clk),.bus_rst(reset),.* 136 ); 137 end else begin : gen_old_dut 138 logic [63:0] eth_tx_tdata; 139 logic [3:0] eth_tx_tuser; 140 logic eth_tx_tlast; 141 logic eth_tx_tvalid; 142 logic eth_tx_tready; 143 144 logic [63:0] eth_rx_tdata; 145 logic [3:0] eth_rx_tuser; 146 logic eth_rx_tlast; 147 logic eth_rx_tvalid; 148 logic eth_rx_tready; 149 150 logic [63:0] e2v_tdata; 151 logic e2v_tlast; 152 logic e2v_tvalid; 153 logic e2v_tready; 154 155 logic [63:0] v2e_tdata; 156 logic v2e_tlast; 157 logic v2e_tvalid; 158 logic v2e_tready; 159 160 logic [63:0] e2c_tdata; 161 logic [3:0] e2c_tuser; 162 logic e2c_tlast; 163 logic e2c_tvalid; 164 logic e2c_tready; 165 166 logic [63:0] c2e_tdata; 167 logic [3:0] c2e_tuser; 168 logic c2e_tlast; 169 logic c2e_tvalid; 170 logic c2e_tready; 171 172 always_comb begin 173 eth_tx.tdata = eth_tx_tdata; 174 eth_tx.tuser = eth_tx_tuser; 175 eth_tx.tkeep = eth_tx.trailing2keep(eth_tx_tuser); 176 eth_tx.tlast = eth_tx_tlast; 177 eth_tx.tvalid = eth_tx_tvalid; 178 eth_tx_tready = eth_tx.tready; 179 180 eth_rx_tdata = eth_rx.tdata; 181 eth_rx_tuser = eth_rx.tuser; 182 eth_rx_tlast = eth_rx.tlast; 183 eth_rx_tvalid = eth_rx.tvalid; 184 eth_rx.tready = eth_rx_tready; 185 186 e2v.tdata = e2v_tdata; 187 e2v.tlast = e2v_tlast; 188 e2v.tvalid = e2v_tvalid; 189 e2v_tready = e2v.tready; 190 191 v2e_tdata = v2e.tdata; 192 v2e_tlast = v2e.tlast; 193 v2e_tvalid = v2e.tvalid; 194 v2e.tready = v2e_tready; 195 196 e2c.tdata = e2c_tdata; 197 e2c.tuser = e2c_tuser; 198 e2c.tlast = e2c_tlast; 199 e2c.tvalid = e2c_tvalid; 200 e2c_tready = e2c.tready; 201 202 c2e_tdata = c2e.tdata; 203 c2e_tuser = c2e.tuser; 204 c2e_tlast = c2e.tlast; 205 c2e_tvalid = c2e.tvalid; 206 c2e.tready = c2e_tready; 207 end 208 209 eth_interface #( 210 .PROTOVER(PROTOVER), .NODE_INST(NODE_INST), .MTU(MTU), 211 .REG_AWIDTH(REG_AWIDTH), .RT_TBL_SIZE(RT_TBL_SIZE), 212 .BASE(BASE) 213 ) eth_interface ( 214 .*, 215 .my_udp_port (my_udp_chdr_port) 216 ); 217 end 218 219 task automatic reg_wr ( 220 // Register port: Write port (domain: clk) 221 input int addr, 222 input int data); 223 begin 224 @(posedge clk); 225 reg_wr_req = 1'b1; 226 reg_wr_addr = addr; 227 reg_wr_data = data; 228 @(posedge clk); 229 reg_wr_req = 1'b0; 230 end 231 endtask 232 233 task automatic reg_rd_check ( 234 // Register port: Write port (domain: clk) 235 input int addr, 236 input int data); 237 begin 238 @(posedge clk); 239 reg_rd_req = 1'b1; // drive at posedge 240 reg_rd_addr = addr; 241 @(negedge clk); // check at negedge 242 if (SV_ETH_IFC) begin 243 assert(reg_rd_resp==1'b0) else $error("resp set early"); 244 end else begin 245 // The original doesn't initialize reg_rd_resp so it comes back as X on first read 246 assert(reg_rd_resp==1'b0 || $isunknown(reg_rd_resp)) else $error("resp set early"); 247 end 248 @(posedge clk); 249 reg_rd_req = 1'b0; 250 @(negedge clk); 251 assert(data==reg_rd_data) else $error("read data didn't match"); 252 assert(reg_rd_resp==1'b1) else $error("resp didn't pulse"); 253 @(posedge clk); 254 @(negedge clk); 255 assert(reg_rd_resp==1'b0) else $error("resp set late"); 256 end 257 endtask 258 259 260 //--------------------------------------------------------------------------- 261 // Reset 262 //--------------------------------------------------------------------------- 263 264 task test_reset(); 265 wait(!reset); 266 repeat (10) @(posedge clk); 267 test.end_test(); 268 endtask : test_reset 269 270 //--------------------------------------------------------------------------- 271 // Test Registers 272 //--------------------------------------------------------------------------- 273 274 task test_registers(); 275 test.start_test({TEST_NAME,"Test/Setup Registers"}, 10us); 276 // DEF_DEST_MAC/IP/UDP are defined in the 277 // sim_ethernet_lib.svh, as the destination 278 // addresses. Using the defaults means 279 // if I don't change the dest address on 280 // a packet it will go to the CHDR 281 reg_wr(REG_MAC_LSB,DEF_DEST_MAC_ADDR[31:0]); 282 reg_wr(REG_MAC_MSB,DEF_DEST_MAC_ADDR[47:32]); 283 reg_wr(REG_IP,DEF_DEST_IP_ADDR); 284 reg_wr(REG_UDP,DEF_DEST_UDP_PORT); 285 286 repeat (3) @(posedge clk); 287 288 `ASSERT_ERROR(my_mac==DEF_DEST_MAC_ADDR, "my mac mismatched!"); 289 `ASSERT_ERROR(my_ip==DEF_DEST_IP_ADDR, "my ip mismatched!"); 290 `ASSERT_ERROR(my_udp_chdr_port==DEF_DEST_UDP_PORT,"my udp mismatched!"); 291 292 reg_wr(REG_BRIDGE_ENABLE,1); 293 reg_wr(REG_BRIDGE_MAC_LSB,DEF_BRIDGE_MAC_ADDR[31:0]); 294 reg_wr(REG_BRIDGE_MAC_MSB,DEF_BRIDGE_MAC_ADDR[47:32]); 295 reg_wr(REG_BRIDGE_IP,DEF_BRIDGE_IP_ADDR); 296 reg_wr(REG_BRIDGE_UDP,DEF_BRIDGE_UDP_PORT); 297 298 repeat (3) @(posedge clk); 299 `ASSERT_ERROR(my_mac==DEF_BRIDGE_MAC_ADDR, "my mac mismatched!"); 300 `ASSERT_ERROR(my_ip==DEF_BRIDGE_IP_ADDR, "my ip mismatched!"); 301 `ASSERT_ERROR(my_udp_chdr_port==DEF_BRIDGE_UDP_PORT,"my udp mismatched!"); 302 303 reg_wr(REG_BRIDGE_ENABLE,0); 304 305 // Readback the values 306 reg_rd_check(REG_MAC_LSB,DEF_DEST_MAC_ADDR[31:0]); 307 reg_rd_check(REG_MAC_MSB,DEF_DEST_MAC_ADDR[47:32]); 308 reg_rd_check(REG_IP,DEF_DEST_IP_ADDR); 309 reg_rd_check(REG_UDP,DEF_DEST_UDP_PORT); 310 reg_rd_check(REG_BRIDGE_ENABLE,0); 311 reg_rd_check(REG_BRIDGE_MAC_LSB,DEF_BRIDGE_MAC_ADDR[31:0]); 312 reg_rd_check(REG_BRIDGE_MAC_MSB,DEF_BRIDGE_MAC_ADDR[47:32]); 313 reg_rd_check(REG_BRIDGE_IP,DEF_BRIDGE_IP_ADDR); 314 reg_rd_check(REG_BRIDGE_UDP,DEF_BRIDGE_UDP_PORT); 315 if (SV_ETH_IFC) begin 316 reg_rd_check(REG_CHDR_DROPPED,0); 317 reg_rd_check(REG_CPU_DROPPED,0); 318 end 319 test.end_test(); 320 endtask : test_registers 321 322 //--------------------------------------------------------------------------- 323 // Ethernet to CPU test 324 //--------------------------------------------------------------------------- 325 typedef ChdrData #(CHDR_W)::chdr_word_t chdr_word_t; 326 typedef chdr_word_t word_queue_t[$]; 327 328 typedef XportStreamPacket #(ENET_W) EthXportPacket_t; 329 typedef AxiStreamPacket #(ENET_W,ENET_USER_W) EthAxisPacket_t; 330 331 typedef XportStreamPacket #(CPU_W) CpuXportPacket_t; 332 typedef AxiStreamPacket #(CPU_W,CPU_USER_W) CpuAxisPacket_t; 333 334 typedef XportStreamPacket #(CHDR_W) ChdrXportPacket_t; 335 typedef AxiStreamPacket #(CHDR_W,CHDR_USER_W) ChdrAxisPacket_t; 336 typedef ChdrPacket #(CHDR_W,CHDR_USER_W) ChdrPacket_t; 337 338 task automatic test_ethcpu(int num_samples[$], int ERROR_PROB=2, int EXPECT_DROPS=0); 339 TestExec test_e2c = new(); 340 automatic EthXportPacket_t send[$]; 341 automatic CpuXportPacket_t expected[$]; 342 automatic int sample_sum = 0; 343 344 test_e2c.start_test({TEST_NAME,"Ethernet to CPU"}, 60us); 345 // This path is 346 // eth_rx -> s_mac(eth_adapter) -> s_mac(eth_dispatch) -> 347 //// in_reg(AXI_FIFO)(SIZE=1) 348 // (eth_dispatch) in -> STATMACHINE (Dispatch) + cpu -> 349 //// out_reg_cpu(AXI_FIFO)(SIZE=1) 350 // (eth_dispatch) o_cpu -> 351 //// cpu_out_gate(AXI_GATE)(SIZE=11) 352 // (eth_dispatch) m_cpu -> (eth_adapter) e2c_chdr -> e2c_fifo 353 //// cpu_fifo(AXI_FIFO)(SIZE=CPU_FIFO_SIZE) 354 // (eth_adapater) m_cpu -> e2c 355 356 foreach (num_samples[i]) begin 357 automatic eth_hdr_t eth_hdr; 358 automatic ipv4_hdr_t ipv4_hdr; 359 automatic udp_hdr_t udp_hdr; 360 automatic raw_pkt_t pay,udp_raw; 361 automatic int preamble; 362 363 if (PREAMBLE_BYTES == 6) preamble = NORMAL_PREAMBLE; 364 else if (PREAMBLE_BYTES == 0) preamble = NO_PREAMBLE; 365 else $fatal("Invalid PREAMBLE_BYTES"); 366 367 expected[i] = new; 368 send[i] = new; 369 370 udp_hdr.dest_port = 0; //change dest port from default so it goes to cpu 371 get_ramp_raw_pkt(.num_samps(num_samples[i]),.ramp_start((sample_sum)%256), 372 .ramp_inc(1),.pkt(pay),.SWIDTH(8)); 373 sample_sum += num_samples[i]; 374 udp_raw = build_udp_pkt(eth_hdr,ipv4_hdr,udp_hdr,pay, 375 .preamble(preamble)); 376 send[i].push_bytes(udp_raw); 377 send[i].tkeep_to_tuser(.ERROR_PROB(ERROR_PROB)); 378 379 // rebuild the expected packet for comparison without the preamble 380 udp_raw = build_udp_pkt(eth_hdr,ipv4_hdr,udp_hdr,pay, 381 .preamble(NO_PREAMBLE)); 382 expected[i].push_bytes(udp_raw); 383 expected[i].tkeep_to_tuser(); 384 385 end 386 387 // iterate in descending order so deleting doesn't shift down 388 // the packets in future loop iterations. 389 for (int i= num_samples.size()-1 ; i >= 0; i--) begin 390 // original only checks for errors in last word. 391 if (!SV_ETH_IFC && send[i].has_error()) send[i].set_error(); 392 // If a packet has an error it shouldn't make it through 393 if (send[i].has_error()) expected.delete(i); // MAC ERROR 394 else if (DROP_MIN_PACKET) begin 395 if (send[i].byte_length()-PREAMBLE_BYTES < 64) begin 396 // short packet rejection feature broken in original 397 if (SV_ETH_IFC) expected.delete(i); // TOO SHORT 398 end 399 end 400 401 end 402 403 fork 404 begin // tx_thread 405 foreach(send[i])begin 406 #1 eth.put(send[i]); 407 end 408 end 409 begin //rx_thread 410 if (EXPECT_DROPS > 0) begin 411 automatic int pkt_num = 0; 412 automatic int drop_count = 0; 413 while (expected.size() > 0) begin 414 automatic CpuAxisPacket_t actual_a; 415 automatic CpuXportPacket_t actual = new(); 416 cpu.get(actual_a); 417 actual.import_axis(actual_a); 418 actual.tuser_to_tkeep(); 419 while (expected.size > 0 && actual.compare_no_user(expected[0],.PRINT_LVL(0))) begin 420 void'(expected.pop_front()); 421 ++drop_count; 422 ++pkt_num; 423 $display("Droped packet %d",pkt_num); 424 `ASSERT_ERROR(drop_count < EXPECT_DROPS,"Exceeded anticipated number of dropped packets e2c"); 425 end 426 if (expected.size() > 0) begin 427 ++pkt_num; 428 $display("Rcvd packet %d",pkt_num); 429 void'(expected.pop_front()); 430 end 431 end 432 if (SV_ETH_IFC) begin 433 $display("Verify drop count is %d",drop_count); 434 reg_rd_check(REG_CPU_DROPPED,drop_count); 435 end 436 end else begin 437 foreach(expected[i]) begin 438 automatic CpuAxisPacket_t actual_a; 439 automatic CpuXportPacket_t actual = new(); 440 cpu.get(actual_a); 441 actual.import_axis(actual_a); 442 actual.tuser_to_tkeep(); 443 `ASSERT_ERROR(!actual.compare_w_sof(expected[i]),"failed to send packet to e2c"); 444 end 445 end 446 end 447 join 448 449 test_e2c.end_test(); 450 endtask : test_ethcpu 451 452 task automatic wait_for_udp_packets(int udp_dest_port); 453 automatic EthAxisPacket_t actual_a; 454 automatic raw_pkt_t rcv_raw,rcv_pay; 455 automatic udp_hdr_t rcv_udp; 456 automatic eth_hdr_t rcv_eth; 457 automatic ipv4_hdr_t rcv_ip; 458 automatic int try_count = 0; 459 460 do begin 461 ++try_count; 462 // check if packet is for our port 463 #100; 464 eth.peek(actual_a); 465 rcv_raw = actual_a.dump_bytes(); 466 repeat(PREAMBLE_BYTES) rcv_raw.delete(0); // strip preamble 467 decode_udp_pkt(rcv_raw,rcv_eth,rcv_ip,rcv_udp,rcv_pay); 468 `ASSERT_ERROR(try_count != 100,"unclaimed packet on c2e"); 469 end while (rcv_udp.dest_port != udp_dest_port); 470 471 endtask : wait_for_udp_packets 472 473 474 task automatic test_cpueth(int num_samples[$]); 475 TestExec test_c2e = new(); 476 automatic CpuXportPacket_t send[$]; 477 automatic EthXportPacket_t expected[$]; 478 automatic int sample_sum = 0; 479 480 test_c2e.start_test({TEST_NAME,"CPU to Ethernet"}, 60us); 481 // This path is 482 // c2e -> (eth_adapter) s_cpu -> 483 //// (ARM_DEFRAMER)(IF ARM) 484 // (eth_adapater) c2e -> 485 //// (ETH_MUX)(SIZE=2) 486 // (eth_adapater) m_mac -> eth_tx 487 488 foreach (num_samples[i]) begin 489 automatic eth_hdr_t eth_hdr; 490 automatic ipv4_hdr_t ipv4_hdr; 491 automatic udp_hdr_t udp_hdr; 492 automatic raw_pkt_t pay,udp_raw; 493 automatic int preamble; 494 495 expected[i] = new; 496 send[i] = new; 497 498 if (PREAMBLE_BYTES == 6) preamble = ZERO_PREAMBLE; 499 else if (PREAMBLE_BYTES == 0) preamble = NO_PREAMBLE; 500 else $fatal("Invalid PREAMBLE_BYTES"); 501 502 get_ramp_raw_pkt(.num_samps(num_samples[i]),.ramp_start((sample_sum)%256), 503 .ramp_inc(1),.pkt(pay),.SWIDTH(8)); 504 sample_sum += num_samples[i]; 505 udp_raw = build_udp_pkt(eth_hdr,ipv4_hdr,udp_hdr,pay, 506 .preamble(NO_PREAMBLE)); 507 send[i].push_bytes(udp_raw); 508 send[i].tkeep_to_tuser(); 509 510 // rebuild the expected packet for comparison with a zero preamble 511 udp_raw = build_udp_pkt(eth_hdr,ipv4_hdr,udp_hdr,pay, 512 .preamble(preamble)); 513 if (SV_ETH_IFC) begin 514 while (udp_raw.size < 64) begin 515 udp_raw.push_back(0); 516 end 517 end; 518 expected[i].push_bytes(udp_raw); 519 expected[i].tkeep_to_tuser(); 520 end 521 522 fork 523 begin // tx_thread 524 foreach(send[i])begin 525 cpu.put(send[i]); 526 end 527 end 528 begin //rx_thread 529 foreach(expected[i]) begin 530 automatic EthAxisPacket_t actual_a; 531 automatic EthXportPacket_t actual = new(); 532 automatic raw_pkt_t rcv_raw,rcv_pay; 533 automatic udp_hdr_t rcv_udp; 534 automatic eth_hdr_t rcv_eth; 535 automatic ipv4_hdr_t rcv_ip; 536 automatic int try_count = 0; 537 538 wait_for_udp_packets(DEF_DEST_UDP_PORT); 539 eth.get(actual_a); 540 actual.import_axis(actual_a); 541 if (!SV_ETH_IFC) begin 542 actual.tuser_to_tkeep(); 543 end 544 `ASSERT_ERROR(!actual.compare_w_pad(expected[i],!SV_ETH_IFC),"failed to send packet to c2e"); 545 end 546 end 547 join 548 test_c2e.end_test(); 549 550 endtask : test_cpueth 551 //--------------------------------------------------------------------------- 552 // Ethernet to CHDR test 553 //--------------------------------------------------------------------------- 554 555 function automatic word_queue_t bytes_to_words(raw_pkt_t pay); 556 automatic ChdrXportPacket_t axis_pkt = new(); 557 558 axis_pkt.push_bytes(pay); 559 return axis_pkt.data; 560 561 endfunction : bytes_to_words; 562 563 function automatic raw_pkt_t flatten_chdr(ChdrPacket_t chdr_pkt); 564 automatic ChdrAxisPacket_t axis_chdr; 565 automatic ChdrXportPacket_t xport_chdr = new(); 566 axis_chdr = chdr_pkt.chdr_to_axis(); 567 foreach (axis_chdr.data[i]) begin 568 axis_chdr.keep[i] = '1; 569 axis_chdr.user[i] = '0; 570 end 571 xport_chdr.import_axis(axis_chdr); 572 return xport_chdr.dump_bytes(); 573 endfunction : flatten_chdr 574 575 function automatic ChdrPacket_t unflatten_chdr(raw_pkt_t chdr_raw); 576 automatic ChdrXportPacket_t xport_chdr = new(); 577 automatic ChdrPacket_t chdr_pkt = new(); 578 xport_chdr.push_bytes(chdr_raw); 579 foreach (xport_chdr.data[i]) begin 580 xport_chdr.keep[i] = '1; 581 xport_chdr.user[i] = '0; 582 end 583 chdr_pkt.axis_to_chdr(xport_chdr); 584 return chdr_pkt; 585 endfunction : unflatten_chdr 586 587 task automatic test_ethchdr(int num_samples[$], int ERROR_PROB=2, int EXPECT_DROPS=0); 588 TestExec test_e2v = new(); 589 automatic EthXportPacket_t send[$]; 590 automatic ChdrXportPacket_t expected[$]; 591 automatic int sample_sum = 0; 592 593 test_e2v.start_test({TEST_NAME,"Ethernet to CHDR"}, 60us); 594 // This path is 595 // eth_rx -> s_mac(eth_adapter) -> s_mac(eth_dispatch) -> 596 //// in_reg(AXI_FIFO)(SIZE=1) 597 // (eth_dispatch) in -> STATMACHINE (Dispatch) + chdr -> 598 //// chdr_user_fifo(AXI_FIFO)(SIZE=8) (capture eth header) 599 //// chdr_out_gate(AXI_GATE)(SIZE=11) 600 // (eth_dispatch) o_chdr -> 601 //// chdr_trim(CHDR_TRIM_PAYLOAD) 602 // (eth_dispatch) m_chdr -> (eth_adapater) e2x_chdr -> (xport_adapter_gen) s_axis_xport 603 //// xport_in_swap (AXIS_DATA_SWAP) 604 // (xport_adapter_gen) i_xport -> 605 //// mgmt_ep(CHDR_MGMT_PKT_HANDLER) 606 // (xport_adapter_gen) x2d -> 607 //// rtn_demux(AXI_SWITCH) x2x(loopback) or m_axis_rfnoc 608 // (xport_adapter_gen) m_axis_rfnoc -> (eth_adapter) e2x_fifo 609 //// chdr_fifo(AXI_FIFO)(SIZE=MTU) 610 // (eth_adapater) m_chdr -> e2v 611 612 foreach (num_samples[i]) begin 613 automatic eth_hdr_t eth_hdr; 614 automatic ipv4_hdr_t ipv4_hdr; 615 automatic udp_hdr_t udp_hdr; 616 automatic raw_pkt_t pay,udp_raw,chdr_raw; 617 618 automatic ChdrPacket_t chdr_pkt = new(); 619 automatic chdr_header_t chdr_hdr; 620 automatic chdr_word_t chdr_ts; 621 automatic chdr_word_t chdr_mdata[$]; 622 automatic chdr_word_t chdr_data[$]; 623 automatic int preamble; 624 625 expected[i] = new; 626 send[i] = new; 627 628 if (PREAMBLE_BYTES == 6) preamble = NORMAL_PREAMBLE; 629 else if (PREAMBLE_BYTES == 0) preamble = NO_PREAMBLE; 630 else $fatal("Invalid PREAMBLE_BYTES"); 631 632 // build a payload 633 get_ramp_raw_pkt(.num_samps(num_samples[i]),.ramp_start((sample_sum)%256), 634 .ramp_inc(1),.pkt(pay),.SWIDTH(8)); 635 sample_sum += num_samples[i]; 636 // Fill data in the chdr packet 637 chdr_hdr = '{ 638 vc : 0, 639 dst_epid : 0, 640 seq_num : 0, 641 pkt_type : CHDR_DATA_NO_TS, 642 num_mdata : 0, 643 default : 0 644 }; 645 chdr_ts = 0; // no timestamp 646 chdr_mdata.delete(); // not adding meta data 647 chdr_data = bytes_to_words(pay); 648 649 chdr_pkt.write_raw(chdr_hdr, chdr_data, chdr_mdata, chdr_ts); 650 chdr_raw = flatten_chdr(chdr_pkt); 651 652 //build a udp packet 653 udp_raw = build_udp_pkt(eth_hdr,ipv4_hdr,udp_hdr,chdr_raw, 654 .preamble(preamble)); 655 send[i].push_bytes(udp_raw); 656 send[i].tkeep_to_tuser(.ERROR_PROB(ERROR_PROB)); 657 658 // expect just the chdr packet (UDP stripped) 659 expected[i].push_bytes(chdr_raw); 660 expected[i].tkeep_to_tuser(); 661 662 end 663 664 // iterate in descending order so deleting doesn't shift down 665 // the packets in future loop iterations. 666 for (int i= num_samples.size()-1 ; i >= 0; i--) begin 667 // original only checks for errors in last word. 668 if (!SV_ETH_IFC && send[i].has_error()) send[i].set_error(); 669 // If a packet has an error it shouldn't make it through 670 if (send[i].has_error()) expected.delete(i);//MAC ERROR 671 else if (DROP_MIN_PACKET) begin 672 if (send[i].byte_length()-PREAMBLE_BYTES < 64) begin 673 // short packet rejection feature broken in original 674 if (SV_ETH_IFC) expected.delete(i); // TOO SHORT 675 end 676 end 677 end 678 679 fork 680 begin // tx_thread 681 foreach(send[i])begin 682 #1 eth.put(send[i]); 683 end 684 end 685 begin //rx_thread 686 if (EXPECT_DROPS > 0) begin 687 automatic int pkt_num = 0; 688 automatic int drop_count = 0; 689 while (expected.size() > 0) begin 690 automatic ChdrAxisPacket_t actual_a; 691 automatic ChdrXportPacket_t actual = new(); 692 v.get(actual_a); 693 actual.import_axis(actual_a); 694 actual.tuser_to_tkeep(); 695 while (expected.size > 0 && actual.compare_no_user(expected[0],.PRINT_LVL(0))) begin 696 void'(expected.pop_front()); 697 ++drop_count; 698 ++pkt_num; 699 $display("Droped packet %d",pkt_num); 700 `ASSERT_ERROR(drop_count < EXPECT_DROPS,"Exceeded anticipated number of dropped packets e2v"); 701 end 702 if (expected.size() > 0) begin 703 ++pkt_num; 704 $display("Rcvd packet %d",pkt_num); 705 void'(expected.pop_front()); 706 end 707 end 708 if (SV_ETH_IFC) begin 709 $display("Verify drop count is %d",drop_count); 710 reg_rd_check(REG_CHDR_DROPPED,drop_count); 711 end 712 end else begin 713 foreach(expected[i]) begin 714 automatic ChdrAxisPacket_t actual_a; 715 automatic ChdrXportPacket_t actual = new(); 716 v.get(actual_a); 717 actual.import_axis(actual_a); 718 actual.tuser_to_tkeep(); 719 `ASSERT_ERROR(!actual.compare_no_user(expected[i]),"failed to send packet e2v"); 720 end 721 end 722 end 723 join 724 test_e2v.end_test(); 725 726 endtask : test_ethchdr; 727 728 task automatic test_chdreth(int num_samples[$]); 729 TestExec test_v2e = new(); 730 automatic ChdrXportPacket_t send[$]; 731 automatic EthXportPacket_t expected[$]; 732 automatic int sample_sum = 0; 733 734 test_v2e.start_test({TEST_NAME,"CHDR to Ethernet"}, 60us); 735 // This path is 736 // v2e -> s_chdr(eth_adapter) -> s_axis_rfnoc (xport_adapter_gen) -> 737 //// axi_demux_mgmt_filter (AXI_DEMUX) (IF ALLOW_DISC) (discards discovery packets) 738 // (xport_adapter_gen) f2m -> 739 //// rtn_mux(AXI_MUX) between x2x and f2m 740 // (xport_adapter_gen) m2x -> 741 //// data_fifo/lookup_fifo (AXI_FIFO_SHORT) 742 //// LOOKUP LOGIC (lookup_fifo,data_fifo,results) 743 // (xport_adapter_gen) o_xport -> 744 //// xport_out_swap (AXIS_DATA_SWAP) 745 // (xport_adapter_gen) m_axis_xport -> (eth_adapater) x2e_chdr -> 746 //// ENET_HDR_LOGIC (frame_state) 747 // (eth_adapater) frame -> (eth_adapater) x2e_framed 748 //// (ETH_MUX)(SIZE=2) 749 // (eth_adapater) m_mac -> eth_tx 750 751 foreach (num_samples[i]) begin 752 automatic eth_hdr_t eth_hdr; 753 automatic ipv4_hdr_t ipv4_hdr; 754 automatic udp_hdr_t udp_hdr; 755 automatic raw_pkt_t pay,udp_raw,chdr_raw; 756 757 automatic ChdrPacket_t chdr_pkt = new(); 758 automatic chdr_header_t chdr_hdr; 759 automatic chdr_word_t chdr_ts; 760 automatic chdr_word_t chdr_mdata[$]; 761 automatic chdr_word_t chdr_data[$]; 762 automatic int preamble; 763 764 expected[i] = new; 765 send[i] = new; 766 767 if (PREAMBLE_BYTES == 6) preamble = ZERO_PREAMBLE; 768 else if (PREAMBLE_BYTES == 0) preamble = NO_PREAMBLE; 769 else $fatal("Invalid PREAMBLE_BYTES"); 770 771 // build a payload 772 get_ramp_raw_pkt(.num_samps(num_samples[i]),.ramp_start((sample_sum)%256), 773 .ramp_inc(1),.pkt(pay),.SWIDTH(8)); 774 sample_sum += num_samples[i]; 775 776 // Fill data in the chdr packet 777 chdr_hdr = '{ 778 vc : 0, 779 dst_epid : 0, 780 seq_num : 0, 781 pkt_type : CHDR_DATA_NO_TS, 782 num_mdata : 0, 783 default : 0 784 }; 785 chdr_ts = 0; // no timestamp 786 chdr_mdata.delete(); // not adding meta data 787 chdr_data = bytes_to_words(pay); 788 789 chdr_pkt.write_raw(chdr_hdr, chdr_data, chdr_mdata, chdr_ts); 790 chdr_raw = flatten_chdr(chdr_pkt); 791 792 // send the raw chedar packet 793 send[i].push_bytes(chdr_raw); 794 send[i].tkeep_to_tuser(); 795 796 //build a udp packet 797 // modify as the EthInterface does 798 udp_hdr.src_port = DEF_DEST_UDP_PORT; 799 udp_hdr.dest_port = 0; // Extract from router lookup results (Default) 800 udp_hdr.checksum = 0; // Checksum not calculated at this point 801 ipv4_hdr.src_ip = DEF_DEST_IP_ADDR; 802 ipv4_hdr.dest_ip = 0; // Extract from router lookup results (Default) 803 ipv4_hdr.dscp = 0; // hardcoded 804 ipv4_hdr.dont_frag = 1; // hardcoded 805 ipv4_hdr.identification = 0; // hardcoded 806 ipv4_hdr.time_to_live = 8'h10; //hardcoded 807 eth_hdr.src_mac = DEF_DEST_MAC_ADDR; 808 eth_hdr.dest_mac = 0; // Extract from router lookup results (Default) 809 810 udp_raw = build_udp_pkt(eth_hdr,ipv4_hdr,udp_hdr,chdr_raw, 811 .preamble(preamble)); 812 813 // expect udp wrapped chdr 814 expected[i].push_bytes(udp_raw); 815 if (IGNORE_EXTRA_DATA) begin 816 expected[i].clear_user(); // expect all full words! 817 expected[i].tuser_to_tkeep(); 818 end else begin 819 expected[i].tkeep_to_tuser(); 820 end 821 end 822 823 fork 824 begin // tx_thread 825 foreach(send[i])begin 826 v.put(send[i]); 827 end 828 end 829 begin //rx_thread 830 foreach(expected[i]) begin 831 automatic EthAxisPacket_t actual_a; 832 automatic EthXportPacket_t actual = new(); 833 automatic eth_hdr_t eth_hdr; 834 automatic ipv4_hdr_t ipv4_hdr; 835 automatic udp_hdr_t udp_hdr; 836 automatic raw_pkt_t chdr_raw,actual_raw; 837 automatic ChdrPacket_t chdr_pkt; 838 automatic integer chdr_len; 839 localparam UDP_LEN = 8/*udp*/+20/*ipv4*/+14/*eth-no vlan*/; 840 841 wait_for_udp_packets(.udp_dest_port(0)); 842 eth.get(actual_a); 843 actual.import_axis(actual_a); 844 actual_raw = actual.dump_bytes(); 845 repeat(PREAMBLE_BYTES) void'(actual_raw.pop_front()); 846 decode_udp_pkt(actual_raw,eth_hdr,ipv4_hdr,udp_hdr,chdr_raw); 847 chdr_pkt = unflatten_chdr(chdr_raw); 848 // fills remainder of packet with zeros 849 if (IGNORE_EXTRA_DATA) begin 850 for (int w=chdr_pkt.header.length+UDP_LEN;w <actual_raw.size();w++) begin 851 actual_raw[w] = '0; 852 end 853 repeat(PREAMBLE_BYTES) actual_raw.push_front(0); 854 actual.empty(); 855 actual.push_bytes(actual_raw); 856 end 857 `ASSERT_ERROR(!actual.compare_w_error(expected[i]),"failed to send packet v2e"); 858 end 859 end 860 join 861 test_v2e.end_test(); 862 863 endtask : test_chdreth 864 865 integer cached_mgmt_seqnum = 0; 866 867 `include "../../core/rfnoc_chdr_utils.vh" 868 `include "../../core/rfnoc_chdr_internal_utils.vh" 869 `include "../../xport/rfnoc_xport_types.vh" 870 task automatic test_chdr_endpoint(); 871 TestExec test_e2v = new(); 872 automatic EthXportPacket_t send[$]; 873 automatic EthXportPacket_t expected[$]; 874 automatic int sample_sum = 0; 875 876 automatic eth_hdr_t eth_hdr; 877 automatic ipv4_hdr_t ipv4_hdr; 878 automatic udp_hdr_t udp_hdr; 879 automatic raw_pkt_t pay,udp_raw,chdr_raw; 880 881 automatic ChdrPacket_t chdr_pkt = new(); 882 automatic chdr_header_t chdr_hdr; 883 automatic chdr_mgmt_t mgmt_pl; 884 automatic chdr_mgmt_op_t exp_mgmt_op; 885 886 automatic chdr_word_t chdr_ts; 887 automatic chdr_word_t chdr_mdata[$]; 888 automatic chdr_word_t chdr_data[$]; 889 automatic logic [47:0] node_info; 890 automatic int preamble; 891 localparam NODE_INST=0; 892 893 test_e2v.start_test({TEST_NAME,"ChdrEndpoint"}, 60us); 894 895 896 expected[0] = new; 897 send[0] = new; 898 899 if (PREAMBLE_BYTES == 6) preamble = NORMAL_PREAMBLE; 900 else if (PREAMBLE_BYTES == 0) preamble = NO_PREAMBLE; 901 else $fatal("Invalid PREAMBLE_BYTES"); 902 903 // Generic management header 904 mgmt_pl.header = '{ 905 default:'0, prot_ver:PROTOVER, chdr_width:translate_chdr_w(CHDR_W), src_epid:1 906 }; 907 // Send a node info request to the crossbar 908 mgmt_pl.header.num_hops = 2; 909 mgmt_pl.ops.delete(); 910 mgmt_pl.ops[0] = '{ // Hop 1: Send node info 911 op_payload:48'h0, op_code:MGMT_OP_INFO_REQ, ops_pending:8'd1}; 912 mgmt_pl.ops[1] = '{ // Hop 1: Return 913 op_payload:48'h0, op_code:MGMT_OP_RETURN, ops_pending:8'd0}; 914 mgmt_pl.ops[2] = '{ // Hop 2: Nop for return 915 op_payload:48'h0, op_code:MGMT_OP_NOP, ops_pending:8'd0}; 916 chdr_hdr = '{ 917 pkt_type:CHDR_MANAGEMENT, seq_num:cached_mgmt_seqnum, dst_epid:16'h0, default:'0}; 918 chdr_pkt.write_mgmt(chdr_hdr, mgmt_pl); 919 chdr_raw = flatten_chdr(chdr_pkt); 920 921 //build a udp packet 922 udp_raw = build_udp_pkt(eth_hdr,ipv4_hdr,udp_hdr,chdr_raw, 923 .preamble(preamble)); 924 send[0].push_bytes(udp_raw); 925 send[0].tkeep_to_tuser(); 926 927 // build expected response 928 // Generic management header 929 if (PREAMBLE_BYTES == 6) preamble = ZERO_PREAMBLE; 930 else if (PREAMBLE_BYTES == 0) preamble = NO_PREAMBLE; 931 else $fatal("Invalid PREAMBLE_BYTES"); 932 933 mgmt_pl.header = '{ 934 default:'0, prot_ver:PROTOVER, chdr_width:translate_chdr_w(CHDR_W), src_epid:0 935 }; 936 // Send a node info request to the crossbar 937 mgmt_pl.header.num_hops = 1; 938 mgmt_pl.ops.delete(); 939 mgmt_pl.ops[0] = '{ // Hop 2: Nop for return 940 op_payload:48'h0, op_code:MGMT_OP_NOP, ops_pending:8'd1}; 941 942 node_info = chdr_mgmt_build_node_info({ 10'h0, NODE_SUBTYPE_XPORT_IPV4_CHDR64}, 943 NODE_INST, NODE_TYPE_TRANSPORT, device_id); 944 mgmt_pl.ops[1] = '{op_payload:node_info, 945 op_code:MGMT_OP_INFO_RESP, ops_pending:8'd0}; 946 947 chdr_hdr = '{ 948 pkt_type:CHDR_MANAGEMENT, seq_num:cached_mgmt_seqnum++, dst_epid:16'h1, default:'0}; 949 chdr_pkt.write_mgmt(chdr_hdr, mgmt_pl); 950 chdr_raw = flatten_chdr(chdr_pkt); 951 952 // build a udp packet 953 // modify as the EthInterface does 954 udp_hdr.src_port = DEF_DEST_UDP_PORT; 955 udp_hdr.dest_port = DEF_SRC_UDP_PORT; // Extract from router lookup results (Default) 956 udp_hdr.checksum = 0; // Checksum not calculated at this point 957 ipv4_hdr.src_ip = DEF_DEST_IP_ADDR; 958 ipv4_hdr.dest_ip = DEF_SRC_IP_ADDR; // Extract from router lookup results (Default) 959 ipv4_hdr.dscp = 0; // hardcoded 960 ipv4_hdr.dont_frag = 1; // hardcoded 961 ipv4_hdr.identification = 0; // hardcoded 962 ipv4_hdr.time_to_live = 8'h10; //hardcoded 963 eth_hdr.src_mac = DEF_DEST_MAC_ADDR; 964 eth_hdr.dest_mac = DEF_SRC_MAC_ADDR; // Extract from router lookup results (Default) 965 966 udp_raw = build_udp_pkt(eth_hdr,ipv4_hdr,udp_hdr,chdr_raw, 967 .preamble(preamble)); 968 969 expected[0].push_bytes(udp_raw); 970 if (IGNORE_EXTRA_DATA) begin 971 expected[0].clear_user(); // expect all full words! 972 expected[0].tuser_to_tkeep(); 973 end else begin 974 expected[0].tkeep_to_tuser(); 975 end 976 977 fork 978 begin // tx_thread 979 foreach(send[i])begin 980 #1 eth.put(send[i]); 981 end 982 end 983 begin //rx_thread 984 foreach(expected[i]) begin 985 automatic EthAxisPacket_t actual_a; 986 automatic EthXportPacket_t actual = new(); 987 automatic eth_hdr_t eth_hdr; 988 automatic ipv4_hdr_t ipv4_hdr; 989 automatic udp_hdr_t udp_hdr; 990 automatic raw_pkt_t chdr_raw,actual_raw; 991 automatic ChdrPacket_t chdr_pkt; 992 automatic integer chdr_len; 993 localparam UDP_LEN = 8/*udp*/+20/*ipv4*/+14/*eth-no vlan*/; 994 995 eth.get(actual_a); 996 actual.import_axis(actual_a); 997 actual_raw = actual.dump_bytes(); 998 repeat(PREAMBLE_BYTES) void'(actual_raw.pop_front()); 999 decode_udp_pkt(actual_raw,eth_hdr,ipv4_hdr,udp_hdr,chdr_raw); 1000 chdr_pkt = unflatten_chdr(chdr_raw); 1001 // fills remainder of packet with zeros 1002 if (IGNORE_EXTRA_DATA) begin 1003 for (int w=chdr_pkt.header.length+UDP_LEN;w <actual_raw.size();w++) begin 1004 actual_raw[w] = '0; 1005 end 1006 repeat(PREAMBLE_BYTES) actual_raw.push_front(0); 1007 actual.empty(); 1008 actual.push_bytes(actual_raw); 1009 end 1010 `ASSERT_ERROR(!actual.compare_no_user(expected[i]),"failed to get node info"); 1011 end 1012 end 1013 join 1014 test_e2v.end_test(); 1015 1016 endtask : test_chdr_endpoint 1017 //---------------------------------------------------- 1018 // Main test loop 1019 //---------------------------------------------------- 1020 initial begin : tb_main 1021 automatic int num_samples[$]; 1022 automatic int cpu_num_samples[$]; 1023 automatic int expected_drops; 1024 localparam QUICK = 0; 1025 test.start_test({TEST_NAME,"Wait for Reset"}, 10us); 1026 clk_gen.reset(); 1027 eth_clk_gen.reset(); 1028 1029 eth.run(); 1030 cpu.run(); 1031 v.run(); 1032 1033 1034 test_reset(); 1035 test_registers(); 1036 1037 test_chdr_endpoint(); 1038 1039 // Check what happens if the input bandwidth exceeds 1040 // the devices ability to consume packets 1041 // This can happen in matched bandwidth cases 1042 // if there is hold off from upstream 1043 // Dropped packets exceed the drop count cause an error 1044 // The actual droped count is compared versus the real count 1045 test.start_test({TEST_NAME,"::Input overrun"}, 200us); 1046 1047 eth.set_master_stall_prob(0); 1048 eth.set_slave_stall_prob(0); 1049 cpu.set_master_stall_prob(0); 1050 cpu.set_slave_stall_prob(0); 1051 v.set_master_stall_prob(0); 1052 v.set_slave_stall_prob(0); 1053 1054 num_samples = {7936,7936,7936,7936,7936,320, 1055 7936,7936,7936,7936,7936,320}; 1056 1057 // The actual number of expected drops depends on the 1058 // bus width difference between ENET_W and CHDR/CPU_W 1059 1060 // in this SIM unlimited etherent bandwidth is coming in at over 300 MHZ 1061 // and output runs at 200 MHZ. This causes excess BW on transmitter even when matched. 1062 expected_drops = 9; 1063 1064 test_ethchdr(num_samples,.EXPECT_DROPS(expected_drops),.ERROR_PROB(0)); 1065 test_ethcpu(num_samples,.EXPECT_DROPS(expected_drops),.ERROR_PROB(0)); 1066 test.end_test(); 1067 1068 eth.set_master_stall_prob(38); 1069 eth.set_slave_stall_prob(38); 1070 cpu.set_master_stall_prob(38); 1071 cpu.set_slave_stall_prob(38); 1072 v.set_master_stall_prob(38); 1073 v.set_slave_stall_prob(38); 1074 1075 num_samples = {1,2,3,4,5,6,7,8, 1076 ENET_W/8-1,ENET_W/8,ENET_W/8+1, 1077 2*ENET_W/8-1,2*ENET_W/8,2*ENET_W/8+1, 1078 CPU_W/8-1,CPU_W/8,CPU_W/8+1, 1079 2*CPU_W/8-1,2*CPU_W/8,2*CPU_W/8+1, 1080 CHDR_W/8-1,CHDR_W/8,CHDR_W/8+1, 1081 2*CHDR_W/8-1,2*CHDR_W/8,2*CHDR_W/8+1 1082 }; 1083 // add some extra samples for CPU packets to try to get above the min 1084 //packet size of 64. (just the headers makes up 42 bytes) 1085 //this way we still have some short packets to drop, but not as many. 1086 foreach (num_samples[i]) cpu_num_samples[i] = num_samples[i]+20; 1087 test.start_test({TEST_NAME,"::PacketW Combos NO Errors"}, 10us); 1088 fork // run in parallel 1089 // ethrx 1090 test_ethcpu(cpu_num_samples,.ERROR_PROB(0)); 1091 test_ethchdr(num_samples,.ERROR_PROB(0)); 1092 // ethtx 1093 test_chdreth(num_samples); 1094 test_cpueth(num_samples); 1095 join 1096 test.end_test(); 1097 1098 if (!QUICK) begin 1099 1100 test.start_test({TEST_NAME,"::PacketW Combos Errors"}, 10us); 1101 fork // run in parallel 1102 // ethrx 1103 test_ethcpu(cpu_num_samples,.ERROR_PROB(2)); 1104 test_ethchdr(num_samples,.ERROR_PROB(2)); 1105 // ethtx 1106 test_chdreth(num_samples); 1107 test_cpueth(num_samples); 1108 join 1109 test.end_test(); 1110 1111 num_samples = {16,32,64,128,256,512,1024,1500,1522,9000}; 1112 test.start_test({TEST_NAME,"::Pwr2 NoErrors"}, 60us); 1113 fork // run in parallel 1114 // ethrx 1115 test_ethcpu(cpu_num_samples,.ERROR_PROB(0)); 1116 test_ethchdr(num_samples,.ERROR_PROB(0)); 1117 // ethtx 1118 test_chdreth(num_samples); 1119 test_cpueth(num_samples); 1120 join 1121 test.end_test(); 1122 end 1123 1124 eth.set_master_stall_prob(0); 1125 eth.set_slave_stall_prob(0); 1126 cpu.set_master_stall_prob(0); 1127 cpu.set_slave_stall_prob(0); 1128 v.set_master_stall_prob(0); 1129 v.set_slave_stall_prob(0); 1130 1131 num_samples = {1,2,3,4,5,6,7,8, 1132 ENET_W/8-1,ENET_W/8,ENET_W/8+1, 1133 2*ENET_W/8-1,2*ENET_W/8,2*ENET_W/8+1, 1134 CPU_W/8-1,CPU_W/8,CPU_W/8+1, 1135 2*CPU_W/8-1,2*CPU_W/8,2*CPU_W/8+1, 1136 CHDR_W/8-1,CHDR_W/8,CHDR_W/8+1, 1137 2*CHDR_W/8-1,2*CHDR_W/8,2*CHDR_W/8+1 1138 }; 1139 test.start_test({TEST_NAME,"::Pktw NoStall+Error"}, 10us); 1140 fork // run in parallel 1141 // ethrx 1142 test_ethcpu(cpu_num_samples,.ERROR_PROB(2)); 1143 test_ethchdr(num_samples,.ERROR_PROB(2)); 1144 // ethtx 1145 test_chdreth(num_samples); 1146 test_cpueth(num_samples); 1147 join 1148 test.end_test(); 1149 1150 // repeat with back to back cpu/chdr packets 1151 test.start_test({TEST_NAME,"::Serial Pktw NoStall+Error"}, 10us); 1152 fork // run in parallel 1153 // ethrx 1154 begin 1155 test_ethcpu(cpu_num_samples,.ERROR_PROB(2)); 1156 test_ethchdr(num_samples,.ERROR_PROB(2)); 1157 end 1158 // ethtx 1159 begin 1160 test_chdreth(num_samples); 1161 test_cpueth(num_samples); 1162 end 1163 join 1164 test.end_test(); 1165 1166 // End the TB, but don't $finish, since we don't want to kill other 1167 // instances of this testbench that may be running. 1168 test.end_tb(0); 1169 1170 // Kill the clocks to end this instance of the testbench 1171 clk_gen.kill(); 1172 eth_clk_gen.kill(); 1173 end // initial begin 1174 1175endmodule 1176