System Verilog : Queues

Last modified 2014-06-26

Sini

In your system verilog code, if extraction and insertion order of array elements are important, `queue` would be the best option. A queue is a variable-size, ordered collection of homogeneous elements. It is declared using the same syntax as unpacked arrays, but specifying $ as the array size. It is analogous to a one-dimensional unpacked array that grows and shrinks automatically. So like arrays, queues can be manipulated using concatenation, slicing, indexing and quality operators.

Each element in a queue is identified by an ordinal number that represents its position within the queue. In this 0 represents the first and $ represents the last. Insertion and deletion of elements from random locations using an index are also possible with queues.

Bounded queues Queue size can be limited by giving the last index (upper bound) as follows

int queueA[$:99]; // A queue whose maximum size is 100 integers

These are called bounded queues.It will not have an element whose index is higher than the queue's declared upper bound. Operators on bounded queue can be applied exactly the same way as unbounded queues, except that, result should fall in the upper bound limit.

module queuecheck;

//Declaration
int qint\[$\];              //queue of integer
logic \[31:0\] qlogic \[$\];  // queue of 32 bit logic
integer qinteger\[$:9\];    // queue of integers with max 10 elements
int i;

initial begin

 //Adding and updating elements using unpacked array concatenation
 qint = {500,1000,1500,2000};
 qlogic = {1,0,0,0,0,0,1,1,1,1,0};
 qinteger = {10,20,40,50};

 $display("qint: %0d : %0d : %0d: %0d",qint\[0\],qint\[1\],qint\[2\],qint\[3\]);
 
 //Read first item from the queue
 i = qint\[0\];
 $display("qint -First item: %0d",i);
 
 //Read last item from the queue
 i = qint\[$\];
 $display("qint -Last item : %0d",i);
 
 //Delete last item from the array
 qint = qint\[0:$-1\];
 $display("qint -Deleted last item: %0d : %0d : %0d : %0d",qint\[0\],qint\[1\],qint\[2\],qint\[3\]);
 
 //Write first item in the queue
 qint\[0\] = 250;
 $display("qint -Inserted first item: %0d",qint\[0\]);
 
 //Write last item in the queue
 qint\[$\] = 2500;
 $display("qint -Inserted last item: %0d",qint\[$\]);
 
 //Delete entire array
 qint = {};
 $display("qint -After deletion %0d",qint.size);

 //size of qinteger
 $display("qinteger -size %0d",qinteger.size);
 
 
 //qinteger = {10,20,30,40,50,60,70,80,90,100,0}; //Warning: Unpacked array concatenation contains too many queue elements.
						 //Warning: SystemVerilog queue overflow beyond 10 items, tail entry lost

 $display("qinteger -Before insertion: %0d : %0d : %0d : %0d :%0d",qinteger\[0\],qinteger\[1\],qinteger\[2\],qinteger\[3\],qinteger\[4\]);
 
 //Insertion using concatenation
 qinteger = {qinteger\[0:1\], 30, qinteger\[2:$\] }; 
 $display("qinteger -After insertion: %0d : %0d : %0d : %0d :%0d",qinteger\[0\],qinteger\[1\],qinteger\[2\],qinteger\[3\],qinteger\[4\]);
 
 qinteger = {10,20,30,40,50,60,70,80,90,100};
 $display("qinteger -new size %0d",qinteger.size);
 
 //Read second element from qlogic
 $display("qlogic %0b",qlogic\[1\]);

end
endmodule

ncsim> run
qint: 500 : 1000 : 1500: 2000
qint -First item: 500
qint -Last item : 2000
qint -Deleted last item: 500 : 1000 : 1500 : 0
qint -Inserted first item: 250
qint -Inserted last item: 2500
qint -After deletion 0
qinteger -size 4
qinteger -Before insertion: 10 : 20 : 40 : 50 :x
qinteger -After insertion: 10 : 20 : 30 : 40 :50
qinteger -new size 10
qlogic 0
ncsim: *W,RNQUIE: Simulation is complete.

There are some built in methods available in queue to do insertion, deletion, pushing, popping etc, without using the above methods.

Queue Methods

size() : The size() method returns the number of items in the queue. If the queue is empty, it returns 0.

module queuecheck1;

//Declaration
int qint\[$\];              //queue of integer
logic \[31:0\] qlogic \[$\];  // queue of 32 bit logic
integer qinteger\[$:9\];    // queue of integers with max 10 elements

initial begin

 qint = {500,1000,1500,2000};
 qlogic = {1,0,0,0,0,0,1,1,1,1,0};
 qinteger = {10,20,40,50};

 for ( int j = 0; j < qint.size; j++ ) $display( "qint : %0d",qint\[j\] ); 
 for ( int j = 0; j < qinteger.size; j++ ) $display( "qinteger : %0d",qinteger\[j\] ); 
 
 $display("size of queues qint size : %0d, qinteger size : %0d, qlogic size : %0d",qint.size,qinteger.size,qlogic.size);

end
endmodule

ncsim> run
qint : 500
qint : 1000
qint : 1500
qint : 2000
qinteger : 10
qinteger : 20
qinteger : 40
qinteger : 50
size of queues qint size : 4, qinteger size : 4, qlogic size : 11
ncsim: *W,RNQUIE: Simulation is complete.

insert(): The insert() method inserts the given item at the specified index position.

function void insert (int index, qtype item); inserts an item at the index location insert()

If the index argument has any bits with unknown (x/z) value, or is negative, or is greater than the current size of the queue, then the method call shall have no effect on the queue and may cause a warning to be issued.

module queueinsertcheck;

integer qinteger\[$\];  

initial begin

 qinteger = {10,20,40,50};

 $display("qinteger -Before insertion: %0d : %0d : %0d : %0d :%0d",qinteger\[0\],qinteger\[1\],qinteger\[2\],qinteger\[3\],qinteger\[4\]);
 
 qinteger.insert(2,30); 
 $display("qinteger -After insertion: %0d : %0d : %0d : %0d :%0d",qinteger\[0\],qinteger\[1\],qinteger\[2\],qinteger\[3\],qinteger\[4\]);

end
endmodule

ncsim> run
qinteger -Before insertion: 10 : 20 : 40 : 50 :x
qinteger -After insertion: 10 : 20 : 30 : 40 :50
ncsim: *W,RNQUIE: Simulation is complete.

delete(): The delete() method deletes the item at the specified index. Index is optional. If index is not specified, entire elements in the queue will get deleted leaving the queue empty. If the index argument has any bits with unknown (x/z) value, or is negative, or is greater than or equal to the current size of the queue, then the method call shall have no effect on the queue and may cause a warning to be issued.

module queuedeletecheck;

integer qinteger\[$\];   

initial begin

 qinteger = {10,20,30,40,50};
 $display("qinteger -Before deletion: %0d : %0d : %0d : %0d :%0d",qinteger\[0\],qinteger\[1\],qinteger\[2\],qinteger\[3\],qinteger\[4\]);
 
 qinteger.delete(2); 
 $display("qinteger -After deletion of one element: %0d : %0d : %0d : %0d :%0d",qinteger\[0\],qinteger\[1\],qinteger\[2\],qinteger\[3\],qinteger\[4\]);

 qinteger.delete(); 
 $display("qinteger -After deletion: %0d : %0d : %0d : %0d :%0d",qinteger\[0\],qinteger\[1\],qinteger\[2\],qinteger\[3\],qinteger\[4\]);

end
endmodule

ncsim> run
qinteger -Before deletion: 10 : 20 : 30 : 40 :50
qinteger -After deletion of one element: 10 : 20 : 40 : 50 :x
qinteger -After deletion: x : x : x : x :x
ncsim: *W,RNQUIE: Simulation is complete.

popfront(): The popfront() method removes and returns the first element of the queue.

popback(): The popback() method removes and returns the last element of the queue.

pushfront(): The pushfront() method inserts the given element at the front of the queue.

pushback(): The pushback() method inserts the given element at the end of the queue.

module queuepushpopcheck;

integer qinteger\[$\];   
integer i;

initial begin

 qinteger = {10,20,30,40,50,60};
 $display("qinteger: %0d : %0d : %0d : %0d :%0d\\n",qinteger\[0\],qinteger\[1\],qinteger\[2\],qinteger\[3\],qinteger\[4\]);
 
 i = qinteger.popfront(); 
 $display("popfront return: %0d",i);
 $display("qinteger : After popfront: %0d : %0d : %0d : %0d :%0d \\n",qinteger\[0\],qinteger\[1\],qinteger\[2\],qinteger\[3\],qinteger\[4\]);

 i = qinteger.popback(); 
 $display("popback return: %0d",i);
 $display("qinteger : After popback: %0d : %0d : %0d : %0d :%0d\\n",qinteger\[0\],qinteger\[1\],qinteger\[2\],qinteger\[3\],qinteger\[4\]);

 qinteger.pushfront(70); 
 $display("qinteger : After pushfront: %0d : %0d : %0d : %0d :%0d\\n",qinteger\[0\],qinteger\[1\],qinteger\[2\],qinteger\[3\],qinteger\[4\]);

 qinteger.pushback(80); 
 $display("qinteger : After pushback: %0d : %0d : %0d : %0d :%0d :%0d\\n",qinteger\[0\],qinteger\[1\],qinteger\[2\],qinteger\[3\],qinteger\[4\],qinteger\[5\]);
end
endmodule

ncsim> run
qinteger: 10 : 20 : 30 : 40 :50

popfront return: 10
qinteger : After popfront: 20 : 30 : 40 : 50 :60

popback return: 60
qinteger : After popback: 20 : 30 : 40 : 50 :x

qinteger : After pushfront: 70 : 20 : 30 : 40 :50

qinteger : After pushback: 70 : 20 : 30 : 40 :50 :80

ncsim: *W,RNQUIE: Simulation is complete.