diff --git a/sim/eth_packet.svh b/sim/eth_packet.svh
new file mode 100644
index 0000000000000000000000000000000000000000..577bd5d73c63283abff16e50d63ab9978d62f5f4
--- /dev/null
+++ b/sim/eth_packet.svh
@@ -0,0 +1,304 @@
+`ifndef __ETH_PACKET_SVH
+`define __ETH_PACKET_SVH
+
+`include "simdrv_defs.svh"
+
+typedef byte mac_addr_t[6];
+typedef bit[11:0] vid_t;
+typedef bit[2:0] pcp_t;
+
+typedef enum
+  {
+   NONE = 0,
+   TX_FID,
+   RX_TIMESTAMP
+   } oob_type_t;
+
+typedef struct {
+   bit [27:0] ts_r;
+   bit [3:0] ts_f;
+   bit [5:0] port_id;
+   bit [15:0] frame_id;
+} wr_timestamp_t;
+
+class EthPacket;
+
+   static const mac_addr_t dummy_mac  = '{0,0,0,0,0,0}   ;
+
+   static  int _zero             = 0;
+   
+   const int CMP_OOB                  = 1;
+   const int CMP_STATUS               = 2;
+   
+   byte payload[];
+   int size;
+
+   mac_addr_t src, dst;
+   oob_type_t oob_type;
+   
+   bit is_q;
+   bit is_hp;  
+   bit has_smac;
+   bit has_crc;
+   bit error;
+
+   bit [15:0] ethertype;
+   
+   vid_t vid;
+   pcp_t pcp;
+   
+   oob_type_t oob;
+   wr_timestamp_t ts;
+   
+
+   task set_size(int size);
+      payload  = new[size](payload);
+   endtask
+   
+   function new(int size = _zero);
+      size      = 0;
+      src       = dummy_mac;
+      dst       = dummy_mac;
+      is_q      = 0;
+      is_hp     = 0;
+      has_crc   = 0;
+      oob_type  = NONE;
+      payload  = new[size](payload);
+      
+   endfunction // new
+
+   task deserialize(byte data[]);
+      int i, hsize;
+
+      
+      for(i=0; i<6;i++)
+        begin
+           dst[i]     = data[i];
+           src[i]     = data [i+6];
+        end
+
+      has_crc         = 0;
+      if(data[12] == 'h81 && data[13] == 'h00)
+        begin
+           is_q       = 1;
+           hsize      = 18;
+           ethertype  = {data[14], data[15]};
+           vid        = ((int'(data[16]) << 8) | data[17]) & 12'hfff;
+           pcp        = data[16] >> 5;
+        end else begin
+           is_q       = 0;
+           hsize      = 14;
+           ethertype  = {data[12], data[13]};
+        end
+
+      payload         = new[data.size() - hsize](payload);
+
+      for(i=0;i<data.size() - hsize;i++)
+        payload[i]    = data[hsize + i];
+
+      error           = 0;
+   endtask
+  
+   task automatic serialize(ref byte data[]); 
+      int i, hsize;
+
+      hsize              = is_q ? 18 : 14;
+      data               = new[payload.size() + hsize](data);
+      
+      for(i=0; i<6;i++)
+        begin
+           data[i]       = dst[i];
+           data[i + 6]   = src[i];
+        end
+
+      
+      if(is_q)
+        begin
+           data [12]     = 8'h81;
+           data [13]     = 8'h00;
+           data [14]     = ethertype[15:8];
+           data [15]     = ethertype[7:0];
+           data [16]     = {pcp, 1'b0, vid[11:8]};
+           data [17]     = vid[7:0];
+        end else begin
+           data[12]      = ethertype [15:8];
+           data[13]      = ethertype [7:0];
+        end
+      
+      for (i=0; i<payload.size(); i++)
+        data[i + hsize]  = payload[i];
+   endtask // serialize
+
+   function bit equal(ref EthPacket b, int flags = _zero);
+      
+      if(src != b.src || dst != b.dst || ethertype != b.ethertype)
+        return 0;
+
+      if(is_q ^ b.is_q)
+        return 0;
+
+      if(is_q && (vid != b.vid || pcp != b.pcp))
+        return 0;
+
+      if(payload != b.payload)
+        return 0;
+
+      if(flags & CMP_STATUS)
+        if(error ^ b.error)
+          return 0;
+
+      return 1;
+   endfunction // equal
+   
+
+   task copy(ref EthPacket b);
+
+      endtask // copy
+
+   task hexdump(byte buffer []);
+      string str;
+      int size           ;
+      int i;
+      int offset         = 0;
+      const int per_row  = 16;
+
+      size               = buffer.size();
+
+      
+      while(size > 0)
+        begin
+           int n;
+           n       = (size > per_row ? per_row : size);
+           $sformat(str,"+%03x: ", offset);
+           for(i=0;i<n;i++) $sformat(str,"%s%s%02x", str, (i==(per_row/2)?"-":" "), buffer[offset + i]);
+           $display(str);
+
+           offset  = offset + n;
+           size    = size - n;
+      end
+      
+      
+   endtask // hexdump
+   
+   
+   task dump(int full = _zero);
+      string str, tmp;
+      int t;
+      
+      if(is_q)
+        $sformat(str, "802.1q [VID %5d/PCP %d] ", vid, pcp);
+      else
+        str  = "802.1                    ";
+
+      $sformat(str, "%s DST [%02x:%02x:%02x:%02x:%02x:%02x] SRC: [%02x:%02x:%02x:%02x:%02x:%02x] Type = 0x%04x size = %d F:(%s%s)", str, dst[0],dst[1],dst[2],dst[3],dst[4],dst[5], src[0],src[1],src[2],src[3],src[4], src[5], ethertype, (is_q ? 18 : 14) + payload.size(), 
+is_hp ? "H" : " ", has_crc ? "C" : " ");
+      $display(str);
+
+      hexdump(payload);
+      
+       
+   endtask // dump
+   
+      
+endclass // EthPacket
+
+
+class EthPacketGenerator;
+
+   protected EthPacket template;
+   protected int min_size, max_size;
+   protected int seed;
+   
+   static const int SMAC            = (1<<0);
+   static const int      DMAC       = (1<<1);
+   static const int      ETHERTYPE  = (1<<2);
+   static const int      VID        = (1<<3);
+   static const int      PCP        = (1<<4);
+   static const int      PAYLOAD    = (1<<5);
+   static const int TX_OOB             = (1<<6);
+   static const int      ALL        = SMAC | DMAC | VID | ETHERTYPE | PCP | PAYLOAD ;
+   
+
+   protected int r_flags;
+   protected int m_current_frame_id;
+   
+
+   function new();
+      r_flags             =ALL;
+      min_size            = 64;
+      max_size            = 128;
+      m_current_frame_id  = 0;
+      template            = new;
+   endfunction // new
+   
+   task set_randomization(int flags);
+      r_flags  = flags;
+   endtask // randomize
+
+
+   typedef byte dyn_array[];
+   
+   
+   protected function dyn_array random_bvec(int size);
+      byte v[];
+      int i;
+      $display("RandomBVEC %d", size);
+      
+      v       = new[size](v);
+      for(i=0;i<size;i++)
+        v[i]  = $dist_uniform(seed, 0, 256);
+   
+      return v;
+      
+   endfunction // random_bvec
+   
+   
+   function automatic EthPacket gen();
+      EthPacket pkt;
+
+      pkt                                = new;
+      
+      
+      if (r_flags & SMAC) pkt.src        = random_bvec(6); else pkt.src = template.src;
+      if (r_flags & DMAC) pkt.dst        = random_bvec(6); else pkt.dst =  template.dst;
+
+      pkt.ethertype                      = (r_flags & ETHERTYPE ? $dist_uniform(seed, 0, 1<<16) : template.ethertype);
+      pkt.is_q                           = template.is_q;
+      pkt.vid                            = template.vid;
+      pkt.pcp                            = template.pcp;
+
+      $display("Size min %d max %d", min_size, max_size);
+
+      if(r_flags & PAYLOAD) pkt.payload  = random_bvec($dist_uniform(seed, min_size, max_size));
+      else pkt.payload                   = template.payload;
+
+      if(r_flags & TX_OOB)
+        begin
+           pkt.ts.frame_id               = m_current_frame_id++;
+           pkt.oob_type                = TX_FID;
+        end
+      
+      return pkt;
+      
+      
+   endfunction
+   
+   task set_template(EthPacket pkt);
+      template  = pkt;
+   endtask // set_template
+                
+   task set_size(int smin, int smax);
+      min_size  = smin;
+      max_size  = smax;
+   endtask // set_size
+
+   
+
+endclass // EthPacketGenerator
+
+
+
+  
+
+`endif
+  
\ No newline at end of file