swapnilm Posted April 2, 2013 Report Share Posted April 2, 2013 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 = ""); super.new(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++) begin 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; end 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_object_utils_begin(transaction) 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) `uvm_object_utils_end function void do_pack(uvm_packer packer); int i; super.do_pack(packer); // uvm_default_packer.use_metadata = 1; packer.pack_field_int(sync,$bits(sync)); packer.pack_field_int(sof,$bits(sof)); packer.pack_field_int(header,$bits(header)); foreach(payload[i]) packer.pack_field_int(payload[i],8); packer.pack_field_int(crc,$bits(crc)); packer.pack_field_int(eof,$bits(eof)); 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 foreach(payload[i]) 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; forever begin 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++) begin $display("san- Display of the packet contents %h",dut_vi.data); @(dut_vi.clock); //added later bq.push_back(dut_vi.data); $display("san1- Display of the packet contents %p",bq); @(dut_vi.clock); //keep this uncommented end $display("san3- Display of the packet contents %h",bq.size()); bytes = new[bq.size()] (bq); //(bq) @(dut_vi.clock); 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. pkt.print(); @(dut_vi.clock); Montr2Agnt_port.write(pkt); uvm_report_info(get_full_name(),"Sending received packet from monitor to the Scoreboard ...",UVM_LOW); end 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. Thanks Quote Link to comment Share on other sites More sharing options...
swapnilm Posted April 3, 2013 Author Report Share Posted April 3, 2013 Can any UVM geek please help me out with this error/querry. I would appreciate it. Thanks Quote Link to comment Share on other sites More sharing options...
omahesh Posted April 3, 2013 Report Share Posted April 3, 2013 hi, 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()]; foreach(payload) data=payload; hope it helps. mahee. Quote Link to comment Share on other sites More sharing options...
swapnilm Posted April 4, 2013 Author Report Share Posted April 4, 2013 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. Quote Link to comment Share on other sites More sharing options...
swapnilm Posted April 5, 2013 Author Report Share Posted April 5, 2013 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. Thanks Quote Link to comment Share on other sites More sharing options...
mea1201 Posted April 5, 2013 Report Share Posted April 5, 2013 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; super.do_unpack(packer); 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? Quote Link to comment Share on other sites More sharing options...
David Long Posted April 5, 2013 Report Share Posted April 5, 2013 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 endfunction Regards, Dave Quote Link to comment Share on other sites More sharing options...
swapnilm Posted April 6, 2013 Author Report Share Posted April 6, 2013 Thanks to both Mea1201 and Dave, as I am new to uvm, your suggestions really helped me. I totally appreciate it, Thanks again. Quote Link to comment Share on other sites More sharing options...
adam Posted April 17, 2013 Report Share Posted April 17, 2013 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. Quote Link to comment Share on other sites More sharing options...
David Long Posted April 17, 2013 Report Share Posted April 17, 2013 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. Regards, Dave Quote Link to comment Share on other sites More sharing options...
samrat patel Posted April 27, 2013 Report Share Posted April 27, 2013 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{ preamble=={7{8'haa}}; } constraint sfd_con{ sfd== 8'hab; } constraint data_len_con{ data_len inside {[46:1500]}; solve data_len before payload; } constraint payload_con{ payload.size==data_len; } //macro registraton `uvm_object_utils_begin(eth_transaction) `uvm_field_int(preamble,UVM_ALL_ON|UVM_NOPACK) `uvm_field_int(sfd,UVM_ALL_ON|UVM_NOPACK) `uvm_field_int(dst_addr,UVM_ALL_ON|UVM_NOPACK) `uvm_field_int(src_addr,UVM_ALL_ON|UVM_NOPACK) `uvm_field_int(data_len,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(transmit_delay,UVM_DEFAULT|UVM_NOCOMPARE|UVM_NOPACK) `uvm_object_utils_end //constructor function new(string name = "eth_transaction"); super.new(name); endfunction //display method function void display(string strng); $display("\n@time=%0g\tpacket displaying from %s",$time,strng); $display("||==============||======||============||============||============||===============||========||"); $display("|| preamble || sfd || dst_addr || src_addr || data_Len || payload_Len || crc ||"); $display("||--------------||------||------------||------------||------------||---------------||--------||"); $display("||%h|| %h ||%h||%h|| %4d || %6d ||%h||",preamble, sfd, dst_addr, src_addr, data_len, payload.size, crc); $display("||==============||======||============||============||============||===============||========||"); $display("\n"); endfunction //pack all bits of ethernet packet field function void do_pack(uvm_packer packer); super.do_pack(packer); // pack super's properties packer.pack_field_int(preamble,$bits(preamble)); packer.pack_field_int(sfd,$bits(sfd)); packer.pack_field_int(dst_addr,$bits(dst_addr)); packer.pack_field_int(src_addr,$bits(src_addr)); packer.pack_field_int(data_len,$bits(data_len)); foreach(payload) packer.pack_field_int(payload,8); packer.pack_field_int(crc,$bits(crc)); 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.delete(); payload = new[data_len]; foreach(payload) 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; $cast(rhs_,rhs); 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; endfunction endclass: eth_transaction Quote Link to comment Share on other sites More sharing options...
samrat patel Posted April 27, 2013 Report Share Posted April 27, 2013 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? Regards, Samrat Quote Link to comment Share on other sites More sharing options...
milin parekh Posted November 14, 2019 Report Share Posted November 14, 2019 hello samrat patel i hope this logic helps //----------------------------------------------------- // File Name : serial_crc.v // Author : Milin Parekh //---------------------------------------------------- module serial_crc_ccitt ( clk , reset , data_in , crc_out ); //-----------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; end else begin // a loop to run it till the whole data byte is in to the checksum for(int i=0; i<16 ; i++) begin 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]; end end endmodule 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 Quote Link to comment Share on other sites More sharing options...
Recommended Posts
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.