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

Subversion Repositories 1000base-x

[/] [1000base-x/] [trunk/] [testbench/] [rtl/] [verilog/] [ethernet_frame.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_frame.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
package ethernet_frame;
47
 
48
   import tb_utils::hexpretty;
49
   import tb_utils::hexformat;
50
 
51
   typedef int crc_t[4];
52
   typedef int proto_t[2];
53
   typedef int payload_t[];
54
   typedef int ethernet_address_t[6];
55
 
56
   localparam ethernet_address_t ETH_A_TB        = '{'haa, 'hbb, 'hcc, 'hdd, 'hee, 'hff};
57
   localparam ethernet_address_t ETH_A_BCAST     = '{'hff, 'hff, 'hff, 'hff, 'hff, 'hff};
58
   localparam ethernet_address_t ETH_A_NULL      = '{'h00, 'h00, 'h00, 'h00, 'h00, 'h00};
59
 
60
   localparam ethernet_address_t ether_broadcast = ETH_A_BCAST;
61
   localparam ethernet_address_t ether_null      = ETH_A_NULL;
62
   localparam ethernet_address_t def_dst_addr    = ETH_A_TB;
63
   localparam ethernet_address_t def_src_addr    = ETH_A_TB;
64
 
65
   localparam proto_t ETH_P_IP                   = '{'h08, 'h00};
66
 
67
   localparam proto_t def_proto                  = ETH_P_IP;
68
 
69
   localparam int ethernet_preamble      = 'h5;
70
   localparam int ethernet_preamble_len  = 15;
71
   localparam int ethernet_sfd           = 'hd;
72
   localparam int ethernet_min_payload   = 46;
73
   localparam int ethernet_max_payload   = 2100;
74
   localparam int ethernet_crc_poly      = 32'h04c11db7;
75
   localparam int ethernet_overhead      = (6+6+2+4); // Excludes preamble, SFD
76
 
77
   // Parameters for 100BaseTx Ethernet:
78
   localparam int ethernet_slot_time        = 512;  // bit times
79
   localparam int ethernet_inter_frame_gap  = 96;   // bits
80
   localparam int ethernet_attempt_limit    = 16;
81
   localparam int ethernet_back_off_limit   = 10;
82
   localparam int ethernet_jam_size         = 32;   // bits
83
   localparam int ethernet_min_frame_size   = ethernet_min_payload + ethernet_overhead; // = 64;
84
   localparam int ethernet_clk_rate         = 25e6;
85
 
86
   typedef enum   { ETH10, ETH100, ETH1000 } EthernetSpeed;
87
 
88
   int            nothing[] = new[0];
89
 
90
   //////////////////////////////////////////////////////////////////////////////
91
   //
92
   //////////////////////////////////////////////////////////////////////////////
93
 
94
class CRC32;
95
 
96
   static function reg [7:0] byte_swap(reg [7:0] x);
97
      return {x[0], x[1], x[2], x[3], x[4], x[5], x[6], x[7]};
98
   endfunction
99
 
100
   static function reg [31:0] word_swap(reg [31:0] x);
101
      return {byte_swap(x[7:0]), byte_swap(x[15:8]), byte_swap(x[23:16]), byte_swap(x[31:24])};
102
   endfunction
103
 
104
   static function reg[31:0] pack_swap(reg [31:0] x);
105
      return  { x[7:0], x[15:8], x[23:16], x[31:24]};
106
   endfunction // pack_swap
107
 
108
   static int     crc32_table[256];
109
   static int     crc32_table_ready = 0;
110
   int            accum = 32'hffffffff;
111
 
112
   static function automatic void populate_crc_table();
113
      $display("Populating crc32 table...");
114
      for(int i=0; i<256; i++)
115
        begin
116
           int c = i<<24;
117
           for(int j=0; j<8; j++)
118
             begin
119
                if(c & 32'h80000000)
120
                  c = (c << 1) ^ ethernet_crc_poly;
121
                else
122
                  c = (c << 1);
123
             end
124
           crc32_table[byte_swap(i)] = word_swap(c);
125
        end
126
      crc32_table_ready = 1;
127
   endfunction
128
 
129
   function void reset();
130
      accum = 32'hffffffff;
131
      if(!crc32_table_ready) populate_crc_table();
132
   endfunction
133
 
134
   function new();
135
      reset();
136
   endfunction
137
 
138
   function void push(int x);
139
      accum = (accum[31:8] ^ crc32_table[accum[7:0] ^ x[7:0]]) & 32'hffffffff;
140
   endfunction
141
 
142
   function int eval();
143
      return ~accum;
144
   endfunction
145
 
146
   static function int block(int buffer[], int start, int finish);
147
      CRC32 x = new();
148
      x.reset();
149
      for(int i=start; i<finish; i++) x.push(buffer[i]);
150
      return x.eval();
151
   endfunction
152
 
153
endclass // CRC32
154
 
155
   //////////////////////////////////////////////////////////////////////////////
156
   //
157
   //////////////////////////////////////////////////////////////////////////////
158
 
159
   function automatic string fmt_addr(ethernet_address_t addr);
160
 
161
      $sformat(fmt_addr, "%02X.%02X.%02X.%02X.%02X.%02X",
162
               addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
163
 
164
   endfunction
165
 
166
   function void random_payload(int size, output int rv[], input int randomize, int seed=-1);
167
 
168
      int tmp;
169
 
170
      if (seed >= 0) tmp = $urandom(seed);
171
 
172
      rv = new[size];
173
 
174
      for(int i=0; i<size; i++)
175
        rv[i] = (randomize) ? ($urandom() & 'hff) : ((1+i) & 'hff);
176
 
177
   endfunction
178
 
179
   //----------------------------------------------------------------------------
180
 
181
  class EthernetFrame extends packet::Packet;
182
    int raw[];
183
    int badcrc;
184
    time delay = 0;
185
    int epd_sequence = 0;
186
 
187
    function new(
188
      int da[]      = def_dst_addr,
189
      int sa[]      = def_src_addr,
190
      int proto[]   = def_proto,
191
      int payload[] = nothing,
192
      int seed      = -1,
193
      int randomize = 1,
194
      int length    = 100,
195
      int badcrc    = 0,
196
      int initraw[] = nothing
197
    );
198
       set_badcrc(badcrc, 0);
199
 
200
      if(initraw.size()!=0)
201
        raw = new[initraw.size()](initraw);
202
      else
203
        begin
204
          if(payload.size()==0) random_payload(length, payload, randomize, seed);
205
          set_payload(payload);
206
          set_da(da, 0);
207
          set_sa(sa, 0);
208
          set_proto(proto, 1);
209
        end
210
    endfunction
211
 
212
    function int len();
213
      return raw.size();
214
    endfunction
215
 
216
    function int payload_len();
217
      return raw.size() - ethernet_overhead;
218
    endfunction
219
 
220
    function string repr_verbose(int n_start=4, int n_end=4);
221
      string s;
222
      $sformat(s, "<Frame,da=%s,sa=%s,len=%s,pay=%s,crc=%s>",
223
        fmt_addr(get_da()),
224
        fmt_addr(get_sa()),
225
        hexpretty(get_proto()),
226
        hexpretty(get_payload(), n_start, n_end),
227
        hexpretty(get_crc())
228
      );
229
      return s;
230
   endfunction // repr
231
 
232
 
233
   function string dump();
234
      string s;
235
      $sformat(s, "<len=%0d,da=%s,sa=%s,type=%s,pay=%s,crc=%s>",
236
        len(),
237
        fmt_addr(get_da()),
238
        fmt_addr(get_sa()),
239
        hexpretty(get_proto()),
240
        hexformat(get_payload(), "0x%02x", ","),
241
        hexpretty(get_crc())
242
      );
243
      return s;
244
    endfunction
245
 
246
 
247
    function void resize(int n);
248
      raw = new[n](raw);
249
    endfunction
250
 
251
 
252
     function void cut(int pos, int n);
253
        for(int i=pos; i<(raw.size-n); i++)
254
          raw[i] = raw[i+n];
255
 
256
        resize(raw.size - n);
257
     endfunction; // extract  
258
 
259
    function void set_da(ethernet_address_t da, int update=1);
260
      raw[0:5] = da;
261
      if(update)
262
        update_crc();
263
    endfunction
264
 
265
    function ethernet_address_t get_da();
266
      return raw[0:5];
267
    endfunction
268
 
269
    function void set_sa(ethernet_address_t sa, int update=1);
270
      raw[6:11] = sa;
271
      if(update)
272
        update_crc();
273
    endfunction
274
 
275
    function ethernet_address_t get_sa();
276
      return raw[6:11];
277
    endfunction
278
 
279
    function void set_proto(proto_t x, int update=1);
280
      raw[12:13] = x;
281
      if(update)
282
        update_crc();
283
    endfunction
284
 
285
    function proto_t get_proto();
286
      return raw[12:13];
287
    endfunction
288
 
289
    function void set_badcrc(int b, int update=1);
290
      badcrc = b;
291
      if(update)
292
        update_crc();
293
    endfunction
294
 
295
     function void set_payload(int p[]);
296
       int   n = p.size();
297
       resize(n+ethernet_overhead);
298
       for(int i=0; i<n; i++)
299
         raw[14+i] = p[i];
300
    endfunction
301
 
302
    function void pad_up();
303
      int n = raw.size();
304
      if(n < ethernet_min_frame_size)
305
        begin
306
           $display("Inserting %0d bytes of padding.", ethernet_min_frame_size-n);
307
           resize(ethernet_min_frame_size);
308
           for(int i=n-4; i<ethernet_min_frame_size-4; i++)
309
             raw[i] = 0;
310
           update_crc();
311
        end
312
    endfunction
313
 
314
     function void align();
315
        int n = raw.size();
316
        if(n[0])
317
          begin
318
             $display("Increasing size of frame from %0d bytes to %0d bytes.", n, n+1);
319
             resize(n+1);
320
             raw[n-4] = 0;
321
             update_crc();
322
          end
323
     endfunction
324
 
325
    // Seems we can't avoid the copy in here...
326
    function payload_t get_payload();
327
      int n = raw.size()-ethernet_overhead;
328
      get_payload = new[n];
329
      for(int i=0; i<n; i++)
330
        get_payload[i] = raw[14+i];
331
    endfunction
332
 
333
    function crc_t calc_crc();
334
      int crc = CRC32::block(raw, 0, raw.size()-4);
335
      calc_crc[0] = crc[7:0];
336
      calc_crc[1] = crc[15:8];
337
      calc_crc[2] = crc[23:16];
338
      calc_crc[3] = crc[31:24];
339
    endfunction
340
 
341
    function crc_t get_crc();
342
      return raw[raw.size()-4+:4];
343
    endfunction
344
 
345
    function int check_crc();
346
      int expected_crc[4] = calc_crc();
347
      int extracted_crc[4] = get_crc();
348
      return expected_crc==extracted_crc;
349
    endfunction
350
 
351
    // Update length and CRC fields.
352
    function void update_crc();
353
      if(raw.size()>=4)
354
        begin
355
          int fcs[4];
356
          int n;
357
          fcs = calc_crc();
358
           n = raw.size();
359
          for(int i=0; i<4; i++)
360
            raw[n-4+i] = fcs[i] ^ (badcrc ? 'ha5 : 0);
361
        end
362
    endfunction
363
 
364
  endclass
365
 
366
  // Specialize a mailbox for passing Ethernet frames.
367
  typedef mailbox #(EthernetFrame) FrameMailBox;
368
 
369
endpackage
370
 

powered by: WebSVN 2.1.0

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