Jump to content

how to unpack payload?

Recommended Posts

Hello all,

I am stuck at one place. I want to unpack my payload bytes which are actually produced by dynamic array. Some uvm geeks suggested me to use another parameter,length, in order to unpack the size of the payload but the specifications doesnt allow me to do that. Please find below the transaction class code. And some part of monitor class run phase. 


Transaction class:-

class transaction extends uvm_sequence_item;


rand bit [7:0] sync;

rand bit [7:0] sof;

rand bit [15:0] header;

rand bit [7:0] payload[];

rand bit [15:0] crc;

rand bit [7:0] eof;
//rand bit [7:0] length; // dont want to use this kind of parameter bcoz the specifications doesnt support it.


constraint data_size_c { payload.size inside { [1 : 4]};};
//constraint length_c { length== payload.size }; // dont want to use this kind of parameter bcoz the specifications doesnt support it.


function new(string name = "");


endfunction : new


function [15:0] cal_crc;

int j;

bit [7:0]data;

bit [15:0] n;

bit [7:0] N[];

reg [15:0] newcrc;


n = header;

N = new [this.payload.size + 2]; // 2 more for header

N = { >> {n, payload} };

`uvm_info ("TXHP", $sformatf("header + payload: %h", N), UVM_MEDIUM);


for ( j = 0; j < N.size ; j++)


bit [15:0] crc;

reg [7:0] d;

reg [15:0] c;


d = N[j]; // data[j];

c = crc;


newcrc[0] = d[4] ^ d[0] ^ c[8] ^ c[12];

newcrc[1] = d[5] ^ d[1] ^ c[9] ^ c[13];

newcrc[2] = d[6] ^ d[2] ^ c[10] ^ c[14];

newcrc[3] = d[7] ^ d[3] ^ c[11] ^ c[15];

newcrc[4] = d[4] ^ c[12];

newcrc[5] = d[5] ^ d[4] ^ d[0] ^ c[8] ^ c[12] ^ c[13];

newcrc[6] = d[6] ^ d[5] ^ d[1] ^ c[9] ^ c[13] ^ c[14];

newcrc[7] = d[7] ^ d[6] ^ d[2] ^ c[10] ^ c[14] ^ c[15];

newcrc[8] = d[7] ^ d[3] ^ c[0] ^ c[11] ^ c[15];

newcrc[9] = d[4] ^ c[1] ^ c[12];

newcrc[10] = d[5] ^ c[2] ^ c[13];

newcrc[11] = d[6] ^ c[3] ^ c[14];

newcrc[12] = d[7] ^ d[4] ^ d[0] ^ c[4] ^ c[8] ^ c[12] ^ c[15];

newcrc[13] = d[5] ^ d[1] ^ c[5] ^ c[9] ^ c[13];

newcrc[14] = d[6] ^ d[2] ^ c[6] ^ c[10] ^ c[14];

newcrc[15] = d[7] ^ d[3] ^ c[7] ^ c[11] ^ c[15];


$display("The value of CRC result newcrc = %h ",newcrc);

// return newcrc; //result;


return newcrc; //result;

endfunction : cal_crc


function void post_randomize();

crc = cal_crc();

uvm_report_info(get_full_name(),"Appending crc into the packet ",UVM_LOW);

endfunction : post_randomize



uvm_default_packer.use_metadata = 1;

//int i;

`uvm_field_int(sync, UVM_ALL_ON|UVM_NOPACK)

`uvm_field_int(sof, UVM_ALL_ON|UVM_NOPACK)

`uvm_field_int(header, UVM_ALL_ON|UVM_NOPACK)

`uvm_field_array_int(payload, UVM_ALL_ON|UVM_NOPACK)

`uvm_field_int(crc, UVM_ALL_ON|UVM_NOPACK)

`uvm_field_int(eof, UVM_ALL_ON|UVM_NOPACK)



function void do_pack(uvm_packer packer);

int i;


// uvm_default_packer.use_metadata = 1;








endfunction : do_pack


function void do_unpack(uvm_packer packer);

int i;

super.do_unpack(packer); //super.do_pack(packer);

//uvm_default_packer.use_metadata = 1;

sync = packer.unpack_field_int($bits(sync));

sof = packer.unpack_field_int($bits(sof));

header = packer.unpack_field_int($bits(header));

payload.delete(); // added later by me

payload = new [payload.size]; //added later


payload[i] = packer.unpack_field_int(8);

crc = packer.unpack_field_int($bits(crc));

eof = packer.unpack_field_int($bits(eof));

endfunction : do_unpack


endclass: transaction



Monitor (run phase part):-

task run_phase(uvm_phase phase);

transaction pkt;



bit [7:0] bq[$],bytes[];


repeat(3)@(dut_vi.clock); //keep repeat(3) at 3 or 4 only in order to match the first byte.


foreach(dut_vi.data[j]) // this works

// for ( int j = 0; j < pkt.size ; j++)


$display("san- Display of the packet contents %h",dut_vi.data);    

@(dut_vi.clock); //added later


$display("san1- Display of the packet contents %p",bq);

@(dut_vi.clock); //keep this uncommented


$display("san3- Display of the packet contents %h",bq.size());    

bytes = new[bq.size()] (bq); //(bq)



uvm_report_info(get_full_name(),"Received packet from the DUT into the Monitor...",UVM_LOW);

// pkt = transaction::type_id::create("pkt");

pkt = new("pkt1");

uvm_default_packer.use_metadata = 1;


void'(pkt.unpack_bytes(bytes)); // void'(tx.unpack_bytes(bytes)); //gives some sync values with unpack_bytes. and no values with pack_bytes.

//The unpack methods extract property values from an array of bits,bytes or ints.





uvm_report_info(get_full_name(),"Sending received packet from monitor to the Scoreboard ...",UVM_LOW);




endtask: run_phase




Please help me out here as this is urgent and important. I m stuck at here since some time now.

Any help is appreciated.



Share this post

Link to post
Share on other sites



    If you want to unpack the payload elements which is of the form dynamic array, use the following logic;

        assume the data is of the type dynamic array whose size is equal to payload size;

         data = new[payload.size()];



hope it helps.



Share this post

Link to post
Share on other sites

Hello Mahee,

Thanks for your reply. I tried to work on your suggestion but its not working. Its not unpacking the payload size in the received packet in monitor. Can you please give some more elaboration on its use, especially in pack and unpack function in my transaction class? Also In order to use data,  will I have to declare it as another parameter in the packet structure? 

I appreciate your help. Thanks in advance.

Share this post

Link to post
Share on other sites

Can some body please help me to solve the above issue? I want to unpack dynamic array payload[] without using any external parameter for its size in do_pack(packer) function. Its very urgent. any help is appreciated.



Share this post

Link to post
Share on other sites

In do_unpack, you can return the total packet size by querying the packer, then calculate the payload size by subtracting the known sizes of the other fields:


virtual function void do_unpack(uvm_packer packer);
    int unsigned packet_size_in_bytes;
    packet_size_in_bytes = packer.get_packed_size() / $bits(byte);
    payload_size_in_bytes =
        packet_size_in_bytes -
        ( ($bits(sync) + $bits(sof) + $bits(header) + $bits(crc) + $bits(eof)) / $bits(byte) );
    // -- Allocate the payload array.
    // -- Unpack everything here.
endfunction : do_unpack


Does this help any?  Is this more or less what you are looking for?

Share this post

Link to post
Share on other sites

The critical point that you must remember is that it is not possible to automatically unpack a stream of bits/bytes into a dynamic array since the unpack operation does not know how big the dynamic array should be (assigning to a dynamic array overwrites the existing contents and can therefore change its size). In your case, and using the example above, you would need something like this in your do_unpack function


virtual function void do_unpack(uvm_packer packer);
  ...  //unpack preceeding bytes
  payload = new [payload_size_in_bytes];
  foreach (payload[i]) `uvm_unpack_int(payload[i])
 ...  //unpack remaining fields





Share this post

Link to post
Share on other sites

You are using the `uvm_field macros with UVM_NOPACK flag, choosing to implement do_pack/do_unpack manually. Why? I suggest you either


1 - remove the UVM_NOPACK flags from the `uvm_field macros and remove the do_pack/do_unpack methods. 


2 - keep the do_pack/do_unpack implementations, but use the `uvm_pack_* and `uvm_unpack_* helper macros to do the job instead. For example, use the `uvm_pack_array and `uvm_unpack_array macros to handle packing/unpacking your dynamic array. See the Reference documentation (HTML or PDF) for more information on these macros.


Whichever you choose, just be sure that the packer's use_metadata bit is set, else the array size will not be packed along with the data. As the prior poster stated, the unpack operation needs to know the size of the array in addition to the data.

Share this post

Link to post
Share on other sites

Hi Adam,


Setting the use_metadata bit in the packer will add an extra 32 bits to the payload. I gather from the original question that the driver is using the UVM packer to generate the payload that is being sent to the DUT. This must reflect what the DUT is actually expecting to see.  Adding extra bytes just to enable the monitor to automatically unpack it would not be acceptable here! That is why I suggested using a for loop with `uvm_unpack_int once the dynamic array size was known.




Share this post

Link to post
Share on other sites

Hello Swanil ,


I am samrat patel from ahmedabad .my email id is : samrat150590@gmail.com 


curently i am also working on a project of ethenet packets using uvm .

Here I have pasted a code which i have done in transaction class.

It may b helpful for you.



//ethernet transaction class declaration 
class eth_transaction extends uvm_sequence_item;
//ethernet packet field ranomization 
  rand bit [55:0] preamble;
  rand bit [7:0] sfd;
  rand bit [47:0] dst_addr;
  rand bit [47:0] src_addr;
  rand bit [15:0] data_len; // this length can accomodate MAXIMUM length of 1500
  rand bit [7:0] payload [];
  rand bit [31:0] crc;    
  rand int unsigned transmit_delay;//transmit delay between transfers
  constraint c_delay {transmit_delay==10;}//constraint on transmit delay-constraint as per need
//constraint on specific field
constraint preamble_con{
constraint sfd_con{
                   sfd== 8'hab;
constraint data_len_con{
                        data_len inside {[46:1500]};
                        solve data_len before payload;
constraint payload_con{
//macro registraton
function new(string name = "eth_transaction");
//display method  
function void display(string strng);
  $display("\n@time=%0g\tpacket displaying from %s",$time,strng);
  $display("|| preamble     || sfd  || dst_addr   || src_addr   ||   data_Len ||   payload_Len ||  crc   ||");
  $display("||%h||  %h  ||%h||%h||    %4d    ||     %6d    ||%h||",preamble,
//pack all bits of ethernet packet field
function void do_pack(uvm_packer packer);
  super.do_pack(packer); // pack super's properties
endfunction : do_pack
//unpack all bits of ethernet packet field
function void do_unpack(uvm_packer packer);
  super.do_unpack(packer); // unpack super's properties
  preamble = packer.unpack_field_int($bits(preamble));
  sfd = packer.unpack_field_int($bits(sfd));
  dst_addr = packer.unpack_field_int($bits(dst_addr));
  src_addr = packer.unpack_field_int($bits(src_addr));
  data_len = packer.unpack_field_int($bits(data_len));
  payload = new[data_len];
  payload = packer.unpack_field_int(8);
  crc = packer.unpack_field_int($bits(crc));
endfunction : do_unpack
//do_compare method -to compare specific field
function bit do_compare(uvm_object rhs,uvm_comparer comparer);
    eth_transaction rhs_;
    bit status=1;
    status &= (preamble == rhs_.preamble);
    status &= (sfd == rhs_.sfd);
    status &= (dst_addr == rhs_.dst_addr);
    status &= (src_addr == rhs_.src_addr);
    status &= (data_len == rhs_.data_len);
    status &= (payload == rhs_.payload);
    status &= (crc == rhs_.crc);
    return status;
endclass: eth_transaction

Share this post

Link to post
Share on other sites

Hello ,


LIke your 16 bit crc implemetation .Similarly I want to implement standard 32 bit crc logic in my project so can you elaborate your crc implemetation logic that how did you do xor operation between data and crc?


can any one help me for this?




Share this post

Link to post
Share on other sites

hello samrat patel


i hope this logic helps


// File Name   : serial_crc.v
// Author      : Milin Parekh
module serial_crc_ccitt (
clk     ,
reset   ,
data_in ,
//-----------Input Ports---------------
input clk     ;
input reset   ;
  input [15:0] data_in ;
//-----------Output Ports---------------
output [15:0] crc_out;
//------------Internal Variables--------
reg   [15:0] lfsr;
reg   crc_sreg ;                       //for internal application of storing the value of first x-oring bit  
//-------------Code Start-----------------
assign crc_out = lfsr;                 // the whole data array of checksum bit
// Logic to CRC Calculation  in accordance with the control signals and clock
always @ (posedge clk)
if (reset) begin
  lfsr <= 16'hFFFF;
  else begin
    // a loop to run it till the whole data byte is in to the checksum
    for(int i=0; i<16 ; i++)
    crc_sreg <= data_in ^ lfsr;
    lfsr[15] <= crc_sreg;
    lfsr[14]  <=lfsr[15];
    lfsr[13]  <= lfsr[14];
    lfsr[12]  <= lfsr[13];
    lfsr[11]  <= lfsr[12];
    lfsr[10]  <= (lfsr[11] ^ crc_sreg );
    lfsr[9]  <= lfsr[10] ;
    lfsr[8]  <= lfsr[9];
    lfsr[7]  <= lfsr[8];
    lfsr[6]  <= lfsr[7];
    lfsr[5]  <= lfsr[6];
    lfsr[4] <= lfsr[5];
    lfsr[3] <= (lfsr[4] ^ crc_sreg );
    lfsr[2] <= lfsr[3] ;
    lfsr[1] <= lfsr[2];
    lfsr[0] <= lfsr[1];



this is for a 16 bit crc value generator and there is always a crc polynomial  based on that you work your shifting and xor'ing operation and based on that only your main code logic is written

my polynomial is of x^16+x^12+x^5+x^0




Share this post

Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

  • Create New...