|HOME |ABOUT |ARTICLES |ACK |FEEDBACK |TOC |LINKS |BLOG |JOBS |


Tutorials



PHASE 4 PACKET




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 required methods like packing(), unpacking(), compare() and display() methods.

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.


typedef enum { GOOD_FCS, BAD_FCS } fcs_kind_t;


2) Declare the length type as enumerated data type. Name members as GOOD_LENGTH and BAD_LENGTH.


typedef enum { GOOD_LENGTH, BAD_LENGTH } length_kind_t;


3) Declare the length type and fcs type variables as rand.


rand fcs_kind_t fcs_kind;
rand length_kind_t length_kind;


4) 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.


rand bit [7:0] length;
rand bit [7:0] da;
rand bit [7:0] sa;
rand byte data[];//Payload using Dynamic array,size is generated on the fly
rand byte fcs;


5) Constraint the DA field to be any one of the configured address.


constraint address_c { da inside {`P0,`P1,`P2,`P3} ; }


6) Constrain the payload dynamic array size to between 1 to 255.


constraint payload_size_c { data.size inside { [1 : 255]};}


7) Constrain the payload length to the length field based on the length type.


constraint length_kind_c {
(length_kind == GOOD_LENGTH) -> length == data.size;
(length_kind == BAD_LENGTH) -> length == data.size + 2 ; }



Use solve before to direct the randomization to generate first the payload dynamic array size and then randomize length field.


constraint solve_size_length { solve data.size before length; }


8) Constrain the FCS field initial value based on the fcs kind field.


constraint fcs_kind_c {
(fcs_kind == GOOD_FCS) -> fcs == 8'b0;
(fcs_kind == BAD_FCS) -> fcs == 8'b1; }


9) Define the FCS method.


function byte 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



10) Define display methods:
Display method displays the current value of the packet fields to standard output.


virtual function void display();
$display("\n---------------------- PACKET KIND ------------------------- ");
$display(" fcs_kind : %s ",fcs_kind.name() );
$display(" length_kind : %s ",length_kind.name() );
$display("-------- PACKET ---------- ");
$display(" 0 : %h ",da);
$display(" 1 : %h ",sa);
$display(" 2 : %h ",length);
foreach(data[i])
$write("%3d : %0h ",i + 3,data[i]);
$display("\n %2d : %h ",data.size() + 3 , cal_fcs);
$display("----------------------------------------------------------- \n");
endfunction : display



11) Define 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.


virtual function int unsigned byte_pack(ref logic [7:0] bytes[]);
bytes = new[data.size + 4];
bytes[0] = da;
bytes[1] = sa;
bytes[2] = length;
foreach(data[i])
bytes[3 + i] = data[i];
bytes[data.size() + 3] = cal_fcs;
byte_pack = bytes.size;
endfunction : byte_pack


12) Define unpack method:


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.


virtual function void byte_unpack(const ref logic [7:0] bytes[]);
this.da = bytes[0];
this.sa = bytes[1];
this.length = bytes[2];
this.fcs = bytes[bytes.size - 1];
this.data = new[bytes.size - 4];
foreach(data[i])
data[i] = bytes[i + 3];
this.fcs = 0;
if(bytes[bytes.size - 1] != cal_fcs)
this.fcs = 1;
endfunction : byte_unpack


14) Define a compare method.
Compares the current value of the object instance with the current value of the specified object instance.
If the value is different, FALSE is returned.


virtual function bit compare(packet pkt);
compare = 1;
if(pkt == null)
begin
$display(" ** ERROR ** : pkt : received a null object ");
compare = 0;
end
else
begin
if(pkt.da !== this.da)
begin
$display(" ** ERROR **: pkt : Da field did not match");
compare = 0;
end
if(pkt.sa !== this.sa)
begin
$display(" ** ERROR **: pkt : Sa field did not match");
compare = 0;
end

if(pkt.length !== this.length)
begin
$display(" ** ERROR **: pkt : Length field did not match");
compare = 0;
end
foreach(this.data[i])
if(pkt.data[i] !== this.data[i])
begin
$display(" ** ERROR **: pkt : Data[%0d] field did not match",i);
compare = 0;
end

if(pkt.fcs !== this.fcs)
begin
$display(" ** ERROR **: pkt : fcs field did not match %h %h",pkt.fcs ,this.fcs);
compare = 0;
end
end
endfunction : compare

Packet Class Source Code


`ifndef GUARD_PACKET
`define GUARD_PACKET

//Define the enumerated types for packet types
typedef enum { GOOD_FCS, BAD_FCS } fcs_kind_t;
typedef enum { GOOD_LENGTH, BAD_LENGTH } length_kind_t;

class packet;
rand fcs_kind_t fcs_kind;
rand length_kind_t length_kind;

rand bit [7:0] length;
rand bit [7:0] da;
rand bit [7:0] sa;
rand byte data[];//Payload using Dynamic array,size is generated on the fly
rand byte fcs;

constraint address_c { da inside {`P0,`P1,`P2,`P3} ; }

constraint payload_size_c { data.size inside { [1 : 255]};}

constraint length_kind_c {
(length_kind == GOOD_LENGTH) -> length == data.size;
(length_kind == BAD_LENGTH) -> length == data.size + 2 ; }

constraint solve_size_length { solve data.size before length; }

constraint fcs_kind_c {
(fcs_kind == GOOD_FCS) -> fcs == 8'b0;
(fcs_kind == BAD_FCS) -> fcs == 8'b1; }

///// method to calculate the fcs /////
function byte 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

///// method to print the packet fields ////
virtual function void display();
$display("\n---------------------- PACKET KIND ------------------------- ");
$display(" fcs_kind : %s ",fcs_kind.name() );
$display(" length_kind : %s ",length_kind.name() );
$display("-------- PACKET ---------- ");
$display(" 0 : %h ",da);
$display(" 1 : %h ",sa);
$display(" 2 : %h ",length);
foreach(data[i])
$write("%3d : %0h ",i + 3,data[i]);
$display("\n %2d : %h ",data.size() + 3 , cal_fcs);
$display("----------------------------------------------------------- \n");
endfunction : display

///// method to pack the packet into bytes/////
virtual function int unsigned byte_pack(ref logic [7:0] bytes[]);
bytes = new[data.size + 4];
bytes[0] = da;
bytes[1] = sa;
bytes[2] = length;
foreach(data[i])
bytes[3 + i] = data[i];
bytes[data.size() + 3] = cal_fcs;
byte_pack = bytes.size;
endfunction : byte_pack

////method to unpack the bytes in to packet /////
virtual function void byte_unpack(const ref logic [7:0] bytes[]);
this.da = bytes[0];
this.sa = bytes[1];
this.length = bytes[2];
this.fcs = bytes[bytes.size - 1];
this.data = new[bytes.size - 4];
foreach(data[i])
data[i] = bytes[i + 3];
this.fcs = 0;
if(bytes[bytes.size - 1] != cal_fcs)
this.fcs = 1;
endfunction : byte_unpack

//// method to compare the packets /////
virtual function bit compare(packet pkt);
compare = 1;
if(pkt == null)
begin
$display(" ** ERROR ** : pkt : received a null object ");
compare = 0;
end
else
begin
if(pkt.da !== this.da)
begin
$display(" ** ERROR **: pkt : Da field did not match");
compare = 0;
end
if(pkt.sa !== this.sa)
begin
$display(" ** ERROR **: pkt : Sa field did not match");
compare = 0;
end

if(pkt.length !== this.length)
begin
$display(" ** ERROR **: pkt : Length field did not match");
compare = 0;
end
foreach(this.data[i])
if(pkt.data[i] !== this.data[i])
begin
$display(" ** ERROR **: pkt : Data[%0d] field did not match",i);
compare = 0;
end

if(pkt.fcs !== this.fcs)
begin
$display(" ** ERROR **: pkt : fcs field did not match %h %h",pkt.fcs ,this.fcs);
compare = 0;
end
end
endfunction : compare

endclass




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 ***");

endprogram

(S)Download the packet class with program block.


switch_4.tar
Browse the code in switch_4.tar


(S)Run the simulation
vcs -sverilog -f filelist -R -ntb_opts dtm

(S)Log file report:

Randomization Sucessesfull.

---------------------- PACKET KIND -------------------------
fcs_kind : BAD_FCS
length_kind : GOOD_LENGTH
-------- PACKET ----------
0 : 00
1 : f7
2 : be
3 : a6 4 : 1b 5 : b5 6 : fa 7 : 4e 8 : 15 9 : 7d 10 : 72 11 : 96 12 : 31 13 : c4 14 : aa 15 : c4 16 : cf 17 : 4f 18 : f4 19 : 17 20 : 88 21 : f1 22 : 2c 23 : ce 24 : 5 25 : cb 26 : 8c 27 : 1a 28 : 37 29 : 60 30 : 5f 31 : 7a 32 : a2 33 : f0 34 : c9 35 : dc 36 : 41 37 : 3f 38 : 12 39 : f4 40 : df 41 : c5 42 : d7 43 : 94 44 : 88 45 : 1 46 : 31 47 : 29 48 : d6 49 : f4 50 : d9 51 : 4f 52 : 0 53 : dd 54 : d2 55 : a6 56 : 59 57 : 43 58 : 45 59 : f2 60 : a2 61 : a1 62 : fd 63 : ea 64 : c1 65 : 20 66 : c7 67 : 20 68 : e1 69 : 97 70 : c6 71 : cf 72 : cd 73 : 17 74 : 99 75 : 49 76 : b8 77 : 1c 78 : df 79 : e6 80 : 1a 81 : ce 82 : 8c 83 : ec 84 : b6 85 : bb 86 : a5 87 : 17 88 : cb 89 : 32 90 : e1 91 : 83 92 : 96 93 : e 94 : ee 95 : 57 96 : 33 97 : cd 98 : 62 99 : 88 100 : 7b 101 : e6 102 : 41 103 : ad 104 : 26 105 : ee 106 : 9c 107 : 95 108 : a7 109 : b8 110 : 83 111 : f 112 : ca 113 : ec 114 : b5 115 : 8d 116 : d8 117 : 2f 118 : 6f 119 : ea 120 : 4c 121 : 35 122 : 41 123 : f2 124 : 4e 125 : 89 126 : d8 127 : 78 128 : f1 129 : d 130 : d6 131 : d5 132 : 8 133 : c 134 : de 135 : a9 136 : 1d 137 : a0 138 : ae 139 : 99 140 : f5 141 : 53 142 : d8 143 : 7a 144 : 4c 145 : d4 146 : b8 147 : 54 148 : b7 149 : c3 150 : c9 151 : 7b 152 : a3 153 : 71 154 : 2b 155 : b4 156 : 50 157 : 54 158 : 22 159 : 95 160 : df 161 : 17 162 : c9 163 : 41 164 : 80 165 : 2b 166 : f0 167 : ba 168 : 4a 169 : a9 170 : 7f 171 : 13 172 : 1e 173 : 12 174 : a8 175 : 2 176 : 3 177 : 3d 178 : 71 179 : e6 180 : 96 181 : 89 182 : c6 183 : 46 184 : d6 185 : 1b 186 : 5f 187 : 20 188 : a0 189 : a3 190 : 49 191 : 79 192 : 9
193 : 53
-----------------------------------------------------------

Packing,Unpacking and compare worked
Randomization Sucessesfull.

..............
..............
..............

Index
Introduction
Specification
Verification Plan
Phase 1 Top
Phase 2 Environment
Phase 3 Reset
Phase 4 Packet
Phase 5 Driver
Phase 6 Receiver
Phase 7 Scoreboard
Phase 8 Coverage
Phase 9 Testcase

Report a Bug or Comment on This section - Your input is what keeps Testbench.in improving with time!





<< PREVIOUS PAGE

TOP

NEXT PAGE >>

copyright 2007-2017 :: all rights reserved www.testbench.in::Disclaimer