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