<Previous
Page Next>
Associative Arrays
Example:
This
example shows the following System Verilog features:
* Classes
*
Associative arrays of class instances
This
example shows how handles to class objects work. The example has an
associative array of class objects with the index to the array being a
string.
When a
new class instance is assigned to the array, what is really stored in the
array is a handle to the class object (a pointer in C terms). Executing
the run.do script will run two simulation. The first simulation will run
without calling the "new" class method between each array assignment.
In this
run you will notice that the value of each element in the array is the
same even though three different values have been assigned. This is
correct behavior as all three elements of the array hold the same handle
to the class instance. The values you get, are the current values in the
class.The second run actually calls the "new" class method between each
assignment to the array. By doing this, you create new handles. Each
element in the array is a different handle and represents the values in
the class instance at that specific time. Notice the results of this run.
They are the three different values that were assigned.
module top;
class nam_dat;
string name;
int data;
endclass:nam_dat
class men_reg;
// associative array
of nam_dat with string index
nam_dat
reg_fields[string];
task add_field (input
nam_dat field);
reg_fields[field.name] = field;
endtask:add_field
endclass:men_reg
nam_dat field;
men_reg foo = new;
string s;
initial begin
// Create the First
field
field = new;
field.name =
"Verilog";
field.data = 99;
//Assign field to
dynamic array foo
foo.add_field(field);
`ifdef FIELD
field = new;
`endif
// Create the Second
Field
field.name = "Systemverilog";
field.data = 199;
foo.add_field(field);
`ifdef FIELD
field = new;
`endif
// Create the Third
Field
field.name = "VHDL";
foo.add_field(field);
if (
foo.reg_fields.first( s ) )
do
$display( "%s
: %d\n", s, foo.reg_fields[ s ] );
while (foo.reg_fields.next(s)
);
end
endmodule |
Dynamic Arrays Example:
This
example shows the following SystemVerilog features:
* Classes
* Dynamic
arrays of class instances
This
example demonstrates how to model a parameterized dynamic 2-dimensional
array of classes. The package "DynPkg" contains declarations for several
classes. The first class called "CELL" has several random variables and a
constraint on those variables. The next class declaration "ROW" creates a
dynamic array of the first class "CELL". The third class "FRAME" creates a
dynamic array of the class "ROW". The "FRAME" class also includes a
parameterized constructor function for sizing the overall dimensions of
the array. The important thing to note about calls to "new" in FRAME's
"new" function is that some are for initializing the dynamic arrays and
others are for constructing the class instances. The first "new" method:
R_Array = new[DEPTH];
creates a
dynamic array of size "DEPTH" with each element of "R_Array" being an
object handle to a class instance of "ROW". However at this point each of
these handles is set to NULL.Since the elements of the dynamic arrays are
"classes" they must be constructed with "new" individually. The first
"for" loop is used to iterate through each element in the "R_Array". The
first "new" method inside that "for" loop constructs each instance of the
"ROW" class. The second "new" method is called with "WIDTH" and created a
dynamic array of "CELL" class instances call "C_Array".
As with
the "R_Array", each handle to the class instance needs to be constructed.
Another "for" loop is used to iterate through each element of "C_Array"
and call the "new" method. Finally, in the module "top", an instance of
"FRAME" is created and the constructor is passed the arguments (3,3) thus
creating a 3x3 dynamic array of the class "CELL". The initial block in the
top level module then simply calls the built-in randomize function and
prints out these random values.
package DynPkg;
class CELL;
rand bit [3:0] A, B, C;
constraint C1 {
A inside{[0:7]}; // Constrain A & B to avoid
B inside{[0:7]}; // overflow on C
C == B + A ;
}
endclass
class ROW;
rand CELL C_Array[]; // dynamic array of CELL
endclass
class FRAME;
rand ROW R_Array[]; // dynamic array of ROW
function new (int DEPTH, int WIDTH) ;
R_Array = new[DEPTH]; // initialize ROW array
for(int i = 0; i < DEPTH; i++)
begin
R_Array[i] = new; // construct each ROW inst
R_Array[i].C_Array = new[WIDTH]; // initialize CELL
array
for(int j = 0; j < WIDTH; j++)
R_Array[i].C_Array[j] = new; // construct each
CELL inst
end
endfunction
endclass
endpackage |
SystemVerilog Dynamic Array of Classes Example - Top level
module top;
import DynPkg::*;
FRAME FR;
int result;
initial
begin
// create an instance of dynamic 3x3 array & randomize
FR = new(3,3);
result = FR.randomize();
// print header
$display(" A B C");
$display("---------------------------");
// print out values of array
for(int i = 0; i < 3; i++)
begin
for(int j = 0; j < 3; j++)
$display("CELL[%0d][%0d] = %b %b %b",i, j,
FR.R_Array[i].C_Array[j].A, FR.R_Array[i].C_Array[j].B,
FR.R_Array[i].C_Array[j].C);
$display("");
end
end
endmodule
|
Simple SystemVerilog Queue Example -
Parameterized 2-state FIFO
This
example shows the following SystemVerilog features:
* Queues
* Queue
methods
The
example is a simple FIFO that is modeled with a SystemVerilog queue. The
width and depth of the FIFO are controlled using parameters. Pushing and
popping data in and out of the FIFO as well as checking the number of
elements in the FIFO is done using queue methods.
The queue
is also modeled using SystemVerilog 2-state int and bit types. Where bus
contention and net resolution are not a concern, 2-state types can improve
performance.
In
verification environment, the queues can used for
scoreboarding purpose.
`timescale 1ns / 1ns
module FIFO #(parameter int DEPTH = 31, parameter int WIDTH = 8) (
input bit [WIDTH-1:0] DATA,
input bit CLK, RSTb, WENb, RENb,
output bit FULL, EMPTY,
output bit [WIDTH-1:0] Q);
bit [WIDTH-1:0] mem [$:DEPTH];
// FIFO write
always @(posedge CLK, negedge RSTb)
if (RSTb == 0)
mem = '{};
else if (WENb == 0 && mem.size() < DEPTH)
mem.push_back(DATA);
// FIFO read
always @(posedge CLK)
if (RENb == 0 && mem.size() > 0)
Q <= mem.pop_front();
// FIFO control flags
assign EMPTY = (mem.size() == 0) ? 1 : 0;
assign FULL = (mem.size() == DEPTH) ? 1 : 0;
endmodule |
|