OpenCores
URL https://opencores.org/ocsvn/1000base-x/1000base-x/trunk

Subversion Repositories 1000base-x

[/] [1000base-x/] [trunk/] [testbench/] [rtl/] [verilog/] [ethernet_threads.v] - Blame information for rev 4

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 4 dwp
/////////////////////////////////////////////////////////////////////
2
////                                                              ////
3
////  File name "ethernet_threads.v"                              ////
4
////                                                              ////
5
////  This file is part of the :                                  ////
6
////                                                              ////
7
//// "1000BASE-X IEEE 802.3-2008 Clause 36 - PCS project"         ////
8
////                                                              ////
9
////  http://opencores.org/project,1000base-x                     ////
10
////                                                              ////
11
////  Author(s):                                                  ////
12
////      - D.W.Pegler Cambridge Broadband Networks Ltd           ////
13
////                                                              ////
14
////      { peglerd@gmail.com, dwp@cambridgebroadand.com }        ////
15
////                                                              ////
16
//////////////////////////////////////////////////////////////////////
17
////                                                              ////
18
//// Copyright (C) 2009 AUTHORS. All rights reserved.             ////
19
////                                                              ////
20
//// This source file may be used and distributed without         ////
21
//// restriction provided that this copyright statement is not    ////
22
//// removed from the file and that any derivative work contains  ////
23
//// the original copyright notice and the associated disclaimer. ////
24
////                                                              ////
25
//// This source file is free software; you can redistribute it   ////
26
//// and/or modify it under the terms of the GNU Lesser General   ////
27
//// Public License as published by the Free Software Foundation; ////
28
//// either version 2.1 of the License, or (at your option) any   ////
29
//// later version.                                               ////
30
////                                                              ////
31
//// This source is distributed in the hope that it will be       ////
32
//// useful, but WITHOUT ANY WARRANTY; without even the implied   ////
33
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      ////
34
//// PURPOSE.  See the GNU Lesser General Public License for more ////
35
//// details.                                                     ////
36
////                                                              ////
37
//// You should have received a copy of the GNU Lesser General    ////
38
//// Public License along with this source; if not, download it   ////
39
//// from http://www.opencores.org/lgpl.shtml                     ////
40
////                                                              ////
41
//////////////////////////////////////////////////////////////////////
42
////                                                              ////
43
////                                                              ////
44
//////////////////////////////////////////////////////////////////////
45
 
46
`include "timescale_tb.v"
47
 
48
`include "ge_1000baseX_constants.v"
49
 
50
package ethernet_threads;
51
 
52
  import tb_utils::hexformat;
53
 
54
  import packet::Packet;
55
  import packet::PacketMailBox;
56
 
57
  import ethernet_frame::EthernetFrame;
58
  import ethernet_frame::FrameMailBox;
59
  import ethernet_frame::ethernet_address_t;
60
 
61
`define VALID 1'b1
62
`define INVALID 1'b0
63
 
64
  virtual class TxThread;
65
    virtual task run(PacketMailBox mbx);
66
    endtask
67
 
68
    virtual task pass_to_checker(Packet p, PacketMailBox mbx);
69
      mbx.put(p);
70
    endtask
71
  endclass
72
 
73
 
74
   virtual class RxThread;
75
     virtual task run(ref int errors, PacketMailBox mbx);
76
     endtask
77
   endclass
78
 
79
   function [15:0] reorder(input [15:0] x);
80
      reorder = {x[7:0], x[15:8]};
81
 
82
   endfunction // byte_swap
83
 
84
 
85
   //******************************************************************************
86
   // 8B/10B random
87
   //******************************************************************************
88
 
89
   function automatic void random(int seed=-1, output int value);
90
 
91
      if (seed >= 0) begin int tmp = $urandom(seed); end
92
 
93
      value = $urandom() & 'hff;
94
 
95
   endfunction // random
96
 
97
  //******************************************************************************
98
  // Ethernet frame sending thread...
99
  //******************************************************************************
100
  class GmiiTxThread extends TxThread;
101
    virtual gmii_tx_if   tx;
102
    ethernet_address_t   dst_addr;
103
    ethernet_address_t   src_addr;
104
    int                  length;
105
    int                  num_frames;
106
    int                  spacing;
107
 
108
    // Do nothing constructor.
109
    function new(); endfunction
110
 
111
    // Use a static function for construction so we can use :: notation.
112
    static function GmiiTxThread NEW(
113
      virtual gmii_tx_if  tx,
114
      ethernet_address_t  dst_addr,
115
      ethernet_address_t  src_addr,
116
      int                 length,
117
      int                 num_frames,
118
      int                 spacing
119
    );
120
      GmiiTxThread x = new();
121
      x.tx           = tx;
122
      x.dst_addr     = dst_addr;
123
      x.src_addr     = src_addr;
124
      x.length       = length;
125
      x.num_frames   = num_frames;
126
      x.spacing      = spacing;
127
      return x;
128
    endfunction
129
 
130
    virtual task run(PacketMailBox mbx);
131
      EthernetFrame frame;
132
 
133
      for(int i=0; i<num_frames; i++)
134
        begin
135
          int len = length<0 ? i-length : length;
136
 
137
          $display("\nSending Ethernet frame: %0d, length: %0d", i, len);
138
 
139
          frame = new(dst_addr, src_addr, .length(len));
140
 
141
          //$display("Transmit: %s", frame.repr_verbose(20,20));
142
            $display("Transmit: %s", frame.dump());
143
 
144
          tx.queue_frame(EthernetFrame'(frame));
145
          pass_to_checker(frame, mbx);
146
          # spacing;
147
       end
148
 
149
      mbx.put(null);
150
    endtask
151
  endclass
152
 
153
 
154
  //******************************************************************************
155
  // Ethernet frame checking thread...
156
  //******************************************************************************
157
  class GmiiRxThread extends RxThread;
158
    virtual gmii_rx_if  rx;
159
    ethernet_address_t  dst_addr;
160
    time                timeout_first;
161
    time                timeout_rest;
162
    int                 dut_will_pad;
163
 
164
    // Do nothing constructor.
165
    function new(); endfunction
166
 
167
    // Use a static function for construction so we can use :: notation.
168
    static function GmiiRxThread NEW(
169
      input virtual gmii_rx_if   rx,
170
      input ethernet_address_t   dst_addr,
171
      input time                 timeout_first,
172
      input time                 timeout_rest,
173
      input int                  dut_will_pad=1
174
    );
175
      GmiiRxThread x = new();
176
      x.rx      = rx;
177
      x.dst_addr            = dst_addr;
178
      x.timeout_first = timeout_first;
179
      x.timeout_rest  = timeout_rest;
180
      x.dut_will_pad  = dut_will_pad;
181
      return x;
182
    endfunction
183
 
184
    virtual task run(ref int errors, PacketMailBox mbx);
185
      string         mod_name = string'(rx.whoami());
186
      FrameMailBox   rx_mbx = new();
187
      Packet         p;
188
      EthernetFrame  expected_frames[$];
189
      int            finished = 0;
190
      EthernetFrame  frame;
191
      time           end_time;
192
      time           timeout = timeout_first;
193
      int            matched;
194
      int            frames_matched = 0;
195
 
196
      rx.register_mailbox(ethernet_address_t'(dst_addr), FrameMailBox'(rx_mbx));
197
 
198
      while(1)
199
        begin
200
          // Fetch the next cell to be matched from the FIFO...
201
          if(!finished)
202
            begin
203
              mbx.get(p);
204
              if(p==null)
205
                finished = 1;
206
              else begin
207
                EthernetFrame expected = EthernetFrame'(p);
208
 
209
                // If the DUT pads frames up to the minimum Ethernet frame size then
210
                // we must pad the expected frame also!
211
                if(dut_will_pad)
212
                  expected.pad_up();
213
 
214
                expected_frames.push_back(expected);
215
                end
216
            end
217
 
218
          if(expected_frames.size()==0)
219
            break;
220
 
221
          // Wait for a frame to be received
222
          end_time = $time + timeout;
223
          timeout = timeout_rest;
224
          while((rx_mbx.try_get(frame)==0) && ($time<end_time))
225
            #100ns;
226
 
227
          if(frame==null)
228
            begin
229
              $display("%s: %0t: Error, frame timed out for address %s.", mod_name, $time, ethernet_frame::fmt_addr(dst_addr));
230
              errors += 1;
231
 
232
              // A timeout probably means the link is broken, so don't waste too much time waiting...
233
              if(finished)
234
                begin
235
                  void'(expected_frames.pop_back());
236
                  timeout_rest = timeout_rest / 2;
237
                end
238
            end
239
          else
240
            begin
241
              // Search the list of expected cells for one matching the received frames
242
              matched = 0;
243
              for(int i=0; i<expected_frames.size(); i++)
244
                if(frame.raw==expected_frames[i].raw)
245
                  begin
246
                    if(i==0) begin
247
                       $display("%s: -> Frame matched O.K %03d", mod_name, frames_matched++);
248
                    end
249
                    else
250
                      $display("%s: -> Frame did not match the next expected frame but did match frame number %0d.", mod_name, i);
251
                    expected_frames.delete(i);
252
                    matched = 1;
253
                    break;
254
                  end
255
 
256
              if(!matched)
257
                begin
258
                   $display("%s: %0t: -> Unexpected frame received.", mod_name, $time);
259
                   $display("  Rec: %s", frame.repr_verbose(25,10));
260
                   $display("  Exp: %s", expected_frames[0].repr_verbose(25,10));
261
                  errors += 1;
262
                end
263
            end
264
        end
265
 
266
      rx.unregister_mailbox(ethernet_address_t'(dst_addr));
267
 
268
      $display("%s: GmiiRxThread for %s has completed.", mod_name, ethernet_frame::fmt_addr(dst_addr));
269
    endtask
270
  endclass
271
 
272
 
273
  //******************************************************************************
274
  // Ignore frames from the specified address.
275
  //******************************************************************************
276
  task EtherIgnoreThread(
277
    virtual gmii_rx_intf rx,
278
    ethernet_address_t      dst_addr
279
  );
280
    FrameMailBox rx_mbx = new();
281
    EthernetFrame   frame;
282
 
283
    rx.register_mailbox(ethernet_address_t'(dst_addr), FrameMailBox'(rx_mbx));
284
 
285
    while(1)
286
      rx_mbx.get(frame);
287
  endtask
288
 
289
 
290
  //******************************************************************************
291
  // This structure specifies a traffic stream to be sent between two points.
292
  //******************************************************************************
293
  typedef struct {
294
    TxThread tx; RxThread rxi;
295
  } EthernetFlowEntry;
296
 
297
  //******************************************************************************
298
  // Traffic send/check task.
299
  //******************************************************************************
300
  class EthernetFlow;
301
 
302
    EthernetFlowEntry flow_table[$];
303
 
304
    function void create(TxThread s, RxThread c);
305
      EthernetFlowEntry f = '{s, c};
306
      flow_table.push_back(f);
307
    endfunction
308
 
309
    function void clear();
310
      flow_table = {};
311
    endfunction
312
 
313
    task start(ref int errors);
314
       EthernetFlowEntry f;
315
       int       local_errors = 0;
316
 
317
      $display("%m: Starting traffic flow.");
318
 
319
      // Launch all the send/receive threads...
320
      for(int i=0; i<flow_table.size(); i++)
321
        begin
322
          f = flow_table[i];
323
 
324
          fork
325
            PacketMailBox mbx = new();
326
 
327
            f.tx.run(mbx);
328
 
329
            if(f.rxi)
330
              f.rxi.run(local_errors, mbx);
331
          join_none
332
 
333
          #0; // Wait for the forked threads to start before changing their parameters!!!
334
        end
335
 
336
      wait fork;
337
 
338
      errors += local_errors;
339
 
340
      $display("%m: %0tns: All threads completed.", $time);
341
 
342
    endtask
343
  endclass
344
 
345
endpackage
346
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.