In this Phase , We will define a packet and then test it whether it is generating as expected.
Packet is modeled using class. Packet class should be able to generate all possible packet types randomly. Packet class should also implement allocate(), psdisplay(), copy(), compare(), byte_pack() and byte_unpack() of vmm_data methods.
Using vmm macros, we will create atomic generator and channel for Packet.
We will write the packet class in Packet.sv file. Packet class variables and constraints have been derived from stimulus generation plan.
Revisit Stimulus Generation Plan
1) Packet DA: Generate packet DA with the configured address.
2) Payload length: generate payload length ranging from 2 to 255.
3) Correct or Incorrect Length field.
4) Generate good and bad FCS.
1) Declare FCS types as enumerated data types. Name members as GOOD_FCS and BAD_FCS.
typedefenum { GOOD_FCS, BAD_FCS } fcs_kind_t;
2) Declare the length type as enumerated data type. Name members as GOOD_LENGTH and BAD_LENGTH.
6) Declare the packet field as rand. All fields are bit data types. All fields are 8 bit packet array. Declare the payload as dynamic array.
randbit [7:0] length;
randbit [7:0] da;
randbit [7:0] sa;
randbit [7:0] data[];//Payload using Dynamic array,size is generated on the fly
randbyte fcs;
7) Constraint the DA field to be any one of the configured address.
constraint address_c { da inside {`P0,`P1,`P2,`P3} ; }
8) Constrain the payload dynamic array size to between 1 to 255.
virtualfunctionbyte cal_fcs;
integer i;
byte result ;
result = 0;
result = result ^ da;
result = result ^ sa;
result = result ^ length;
for (i = 0;i< data.size;i++)
result = result ^ data[i];
result = fcs ^ result;
return result;
endfunction : cal_fcs
14) Define copy() method. copy() method copies the current values of the object instance.
virtualfunction vmm_data copy(vmm_data to = null);
Packet cpy;
// Copying to a new instance?
if (to == null)
cpy = new;
else
// Copying to an existing instance. Correct type?
if (!$cast(cpy, to))
begin `vmm_fatal(this.log, "Attempting to copy to a non packet instance");
copy = null;
return copy;
end
15) Define Compare() method. Compares the current value of the object instance with the specified object instance.
If the value is different, FALSE is returned.
compare = 1; // Assume success by default.
diff = "No differences found";
if (!$cast(cmp, to))
begin `vmm_fatal(this.log, "Attempting to compare to a non packet instance");
compare = 0;
diff = "Cannot compare non packets";
return compare;
end
// data types are the same, do comparison:
if (this.da != cmp.da)
begin diff = $psprintf("Different DA values: %b != %b", this.da, cmp.da);
compare = 0;
return compare;
end
if (this.sa != cmp.sa)
begin diff = $psprintf("Different SA values: %b != %b", this.sa, cmp.sa);
compare = 0;
return compare;
end if (this.length != cmp.length)
begin diff = $psprintf("Different LEN values: %b != %b", this.length, cmp.length);
compare = 0;
return compare;
end
foreach(data[i])
if (this.data[i] != cmp.data[i])
begin diff = $psprintf("Different data[%0d] values: 0x%h != 0x%h",i, this.data[i], cmp.data[i]);
compare = 0;
return compare;
end if (this.fcs != cmp.fcs)
begin diff = $psprintf("Different FCS values: %b != %b", this.fcs, cmp.fcs);
compare = 0;
return compare;
end endfunction:compare
16)Define byte_pack() method().
Packing is commonly used to convert the high level data to low level data that can be applied to DUT. In packet class various fields are generated. Required fields are concatenated to form a stream of bytes which can be driven conveniently to DUT interface by the driver.
The unpack() method does exactly the opposite of pack method. Unpacking is commonly used to convert a data stream coming from DUT to high level data packet object.
randbit [7:0] length;
randbit [7:0] da;
randbit [7:0] sa;
randbit [7:0] data[];//Payload using Dynamic array,size is generated on the fly
randbyte fcs;
constraint address_c { da inside {`P0,`P1,`P2,`P3} ; }
///// method to calculate the fcs /////
virtualfunctionbyte cal_fcs;
integer i;
byte result ;
result = 0;
result = result ^ da;
result = result ^ sa;
result = result ^ length;
for (i = 0;i< data.size;i++)
result = result ^ data[i];
result = fcs ^ result;
return result;
endfunction : cal_fcs
virtualfunction vmm_data copy(vmm_data to = null);
Packet cpy;
// Copying to a new instance?
if (to == null)
cpy = new;
else
// Copying to an existing instance. Correct type?
if (!$cast(cpy, to))
begin `vmm_fatal(this.log, "Attempting to copy to a non packet instance");
copy = null;
return copy;
end
compare = 1; // Assume success by default.
diff = "No differences found";
if (!$cast(cmp, to))
begin `vmm_fatal(this.log, "Attempting to compare to a non packet instance");
compare = 0;
diff = "Cannot compare non packets";
return compare;
end
// data types are the same, do comparison:
if (this.da != cmp.da)
begin diff = $psprintf("Different DA values: %b != %b", this.da, cmp.da);
compare = 0;
return compare;
end
if (this.sa != cmp.sa)
begin diff = $psprintf("Different SA values: %b != %b", this.sa, cmp.sa);
compare = 0;
return compare;
end if (this.length != cmp.length)
begin diff = $psprintf("Different LEN values: %b != %b", this.length, cmp.length);
compare = 0;
return compare;
end
foreach(data[i])
if (this.data[i] != cmp.data[i])
begin diff = $psprintf("Different data[%0d] values: 0x%h != 0x%h",i, this.data[i], cmp.data[i]);
compare = 0;
return compare;
end if (this.fcs != cmp.fcs)
begin diff = $psprintf("Different FCS values: %b != %b", this.fcs, cmp.fcs);
compare = 0;
return compare;
end endfunction:compare
/////////////////////////////////////////////////////////
//// Create vmm_channel and vmm_atomic_gen for packet////
/////////////////////////////////////////////////////////
`vmm_channel(Packet)
`vmm_atomic_gen(Packet, "Packet Gen")
Now we will write a small program to test our packet implantation. This program block is not used to verify the DUT.
Write a simple program block and do the instance of packet class. Randomize the packet and call the display method to analyze the generation. Then pack the packet in to bytes and then unpack bytes and then call compare method to check all the methods.
Program Block Source Code
program test;
packet pkt1 = new();
packet pkt2 = new();
logic [7:0] bytes[];
initial repeat(10)
if(pkt1.randomize)
begin $display(" Randomization Successes full.");
pkt1.display();
void'(pkt1.byte_pack(bytes));
pkt2 = new();
pkt2.byte_unpack(bytes);
if(pkt2.compare(pkt1))
$display(" Packing, Unpacking and compare worked");
else $display(" *** Something went wrong in Packing or Unpacking or compare ***");
end else $display(" *** Randomization Failed ***");