FIFO verification with "n" unique elements

I have a synchronous FIFO. The depth of the FIFO is 32. Everytime the FIFO has 7 or any “n” unique elements inside it, “unique” signal goes HIGH. How do I test the “unique” signal going high in SystemVerilog or UVM? How would my scoreboard look like?

Appreciate any thoughts/ideas.

In reply to Verif Engg:

I have a synchronous FIFO. The depth of the FIFO is 32. Every time the FIFO has 7 or any “n” unique elements inside it, “unique” signal goes HIGH. How do I test the “unique” signal going high in SystemVerilog or UVM? How would my scoreboard look like?
Appreciate any thoughts/ideas.

  • I am a bit puzzled by the hardware algorithm you used to test the number of unique entries.
  • For a testbench, you have the luxury of using associative arrays with interesting methods such as “exists” “num” and “size”
  • In the model below, I did use the exists and num.
  • I tailored the stimulus vectors to avoid pops on empty queue.

The model(with some lines from 1800’2012 on associative array and queues is at
http://systemverilog.us/vf/unique_entry.sv


// Also see my reply (below) as this model is not complete. 
import uvm_pkg::*; `include "uvm_macros.svh" 
module top; 
	bit clk, pop, push;  
	int data=8; 
	int aa[int]; // associative array
	int q1[$];  // queue, emulating the fifo
	int num_unique=0; 
	always @(posedge clk)  begin 
		automatic int temp_pop; 
		if(push && !pop)  
			if(!aa.exists(data)) begin // is unique
				aa[data]=1;  // flag data into associative array 
				num_unique <=  num_unique+1'b1; // incremnet number of uniques 
				q1.push_front(data); // maintain the queue
			end
		if(pop && !push && q1.size != 0) begin 
			temp_pop=q1.pop_back(); // maintain the queue
			num_unique <= num_unique - 1'b1; // decrement uniques 
			aa.delete(temp_pop); // delete the associative array entry 
		end 
		a_unique: assert(aa.num <= 7); 
	end 
	
	initial forever #10 clk=!clk;  
 
	initial begin 
		repeat(5) push <= 1'b1; 
		repeat(200) begin 
			@(posedge clk);   #2; 
			if (!randomize(push, pop, data)  with 
					{ push dist {1'b1:=1, 1'b0:=2};
					  pop  dist {1'b1:=1, 1'b0:=8};
					  data dist {[1:99]:=1, [0:0]:=3};
					}) `uvm_error("MYERR", "This is a randomize error")
		end 
		$stop; 
	end 
endmodule   

Modifying the data stream with the following constraint
data dist {[1:9]:=1, [0:0]:=3};
causes less unique possibilities.

Ben Cohen
http://www.systemverilog.us/ ben@systemverilog.us
For training, consulting, services: contact Home - My cvcblr


In reply to ben@SystemVerilog.us:

Thanks much Ben. I struggled with on how would I test the “unique” signal. Your example and waves really helped. Sincerely appreciate your time!

In reply to Verif Engg:
Glad the model helped.
Obviously, you need to tune the model to your needs. Specifically, you need to main a count of the unique entries. Thus, on a push, aa[data]+= 1’b1 (or aa[data]= 1’1b1 + aa[data] for any entry if it exists, and decrement on a pop of that data, and delete if the count is zero.
What I am trying to say is that your queue of 32 deep could contain values like:
1, 2, 3, 3, 3, 3,3 2, 3, …
So that on the 1st “3” exit, you need to account for the other 3’s. Thus, when “3” is popped, that does not necessarily mean that “3” is flushed; there could be a “3” still in the queue. My model did not account for that.
In any case, the associative array and the methods are of great help here.
Ben

In reply to ben@SystemVerilog.us:
This is an updated model
http://systemverilog.us/vf/unique_entry.sv


I corrected the push/pop, the maintenance of number of unique entries in the associative array, and the assertion itself.


// I have a synchronous FIFO. The depth of the FIFO is 32. 
// Everytime the FIFO has 7 or any "n" unique elements inside it, 
// "unique" signal goes HIGH. How do I test the "unique" signal going high 
// in SystemVerilog or UVM? How would my scoreboard look like?
import uvm_pkg::*; `include "uvm_macros.svh" 
module top; 
	bit clk, pop, push;  
	int data=8, q1_size, q_num, just_popped; 
	int aa[int]; // associative array
	int q1[$];  // queue, emulating the fifo
	int num_unique=0; 
	always @(posedge clk)  begin 
		automatic int temp_pop; 
		if(push) begin : push1  // if(push && !pop) begin : push_no_pop  
			if(!aa.exists(data)) begin : is_unique
				aa[data]=1;  // flag data into associative array 
				num_unique <=  num_unique+1'b1; // incremnet number of uniques 
				q1.push_front(data); // maintain the queue
			end  : is_unique
		    else  begin : is_not_unique // but is in the queue
			   aa[data]+=1'b1;  // keep track of count 
			   // num_unique <=  num_unique+1'b1; // incremnet number of uniques 
			   q1.push_front(data); // maintain the queue			
		    end  : is_not_unique 
		end : push1
		if(pop && q1.size != 0) begin : pop_q  // if(pop && !push && q1.size != 0) 
			temp_pop=q1.pop_back(); // maintain the queue
			aa[temp_pop]-=1'b1;  // keep track of count
			just_popped <= temp_pop;
			if(aa[temp_pop]==0) begin : flushed 
			  num_unique <= num_unique - 1'b1; // decrement uniques 
			  aa.delete(temp_pop); // delete the associative array entry 		   
			end  : flushed 
		end : pop_q
		a_unique: assert(num_unique <= 7); 
	end 
	
	always_comb begin 
		q1_size=q1.size; // for debug 
		q_num=aa.num;
	end
	
	initial forever #10 clk=!clk;  
 
	initial begin 
		repeat(5) push <= 1'b1; 
		repeat(200) begin 
			@(posedge clk);   #2; 
			if (!randomize(push, pop, data)  with 
					{ push dist {1'b1:=1, 1'b0:=2};
					  pop  dist {1'b1:=1, 1'b0:=8};
					  data dist {[1:12]:=1, [0:0]:=3};
					}) `uvm_error("MYERR", "This is a randomize error")
		end 
		$stop; 
	end 
endmodule   

Ben Cohen
http://www.systemverilog.us/ ben@systemverilog.us
For training, consulting, services: contact http://cvcblr.com/home


In reply to ben@SystemVerilog.us:
My co-author Srini (http://cvcblr.com/home ), a very knowledgeable trainer/consultant pointed out that instead of me maintaining the number of unique entries, I could have used the array method unique


From 1800'2012: 
unique() returns all elements with unique values or whose expression evaluates to a unique value. The queue returned contains one and only one entry for each of the values found in the array. The ordering of the returned elements is unrelated to the ordering of the original array.
  int IA[int], qi[$];
  string SA[10], qs[$];
  // Find all unique string elements
  qs = SA.unique;
  // Find all unique strings in lowercase
  qs = SA.unique( s ) with ( s.tolower );
//****** for the model, the new things are
                int  aa_uniques_size; 
		int aa_uniques[$]; // for use with the unique method
// .... in the always
		aa_uniques=q1.unique; 
		aa_uniques_size = aa_uniques.size; 		
		a2_unique: assert(aa_uniques.size <=7);  

 

I added this feature to my model. The new model is at
http://SystemVerilog.us/fv/unique_entry.sv
Waveforms is at


// I have a synchronous FIFO. The depth of the FIFO is 32. 
// Everytime the FIFO has 7 or any "n" unique elements inside it, 
// "unique" signal goes HIGH. How do I test the "unique" signal going high 
// in SystemVerilog or UVM? How would my scoreboard look like?

import uvm_pkg::*; `include "uvm_macros.svh" 
module top; 
	bit clk, pop, push;  
	int data=8, q1_size, aa_num, just_popped, aa_uniques_size; 
	int aa[int]; // associative array
	int q1[$];  // queue, emulating the fifo
	int num_unique=0; 
	int aa_uniques[$]; // for use with the unique method
	// NEW solution 
	/* unique() returns all elements with unique values or whose expression evaluates to a unique value.
The queue returned contains one and only one entry for each of the values found in the array. The
ordering of the returned elements is unrelated to the ordering of the original array
int IA[int], qi[$];
string SA[10], qs[$];
// Find all unique string elements
qs = SA.unique;
// Find all unique strings in lowercase
qs = SA.unique( s ) with ( s.tolower );
*/
	always @(posedge clk)  begin 
		automatic int temp_pop; 
		if(push) begin : push1  // if(push && !pop) begin : push_no_pop  
			if(!aa.exists(data)) begin : is_unique
				aa[data]=1;  // flag data into associative array 
				num_unique =  num_unique+1'b1; // incremnet number of uniques 
				q1.push_front(data); // maintain the queue
			end  : is_unique
		    else  begin : is_not_unique // but is in the queue
			   aa[data]+=1'b1;  // keep track of count 
			   // num_unique <=  num_unique+1'b1; // incremnet number of uniques 
			   q1.push_front(data); // maintain the queue			
		    end  : is_not_unique 
		end : push1
		if(pop && q1.size != 0) begin : pop_q  // if(pop && !push && q1.size != 0) 
			temp_pop=q1.pop_back(); // maintain the queue
			aa[temp_pop]-=1'b1;  // keep track of count
			just_popped <= temp_pop;
			if(aa[temp_pop]==0) begin : flushed 
			  num_unique = num_unique - 1'b1; // decrement uniques 
			  aa.delete(temp_pop); // delete the associative array entry 		   
			end  : flushed 
		end : pop_q
		a_unique: assert(num_unique <= 7); 
		// aa_uniques.delete; // clear the temp associative array 
		aa_uniques=q1.unique; 
		
		// debug
		q1_size=q1.size; // for debug 
		aa_num=aa.num; // number of unique entries
		aa_uniques_size = aa_uniques.size; 		
		a2_unique: assert(aa_uniques.size <=7);  
	end 
	
	initial forever #10 clk=!clk;  
 
	initial begin 
		repeat(5) push <= 1'b1; 
		repeat(200) begin 
			@(posedge clk);   #2; 
			if (!randomize(push, pop, data)  with 
					{ push dist {1'b1:=1, 1'b0:=2};
					  pop  dist {1'b1:=1, 1'b0:=8};
					  data dist {[1:12]:=1, [0:0]:=3};
					}) `uvm_error("MYERR", "This is a randomize error")
		end 
		$stop; 
	end 
endmodule  
 

Ben Cohen
http://www.systemverilog.us/ ben@systemverilog.us
For training, consulting, services: contact http://cvcblr.com/home


In reply to ben@SystemVerilog.us:

Neat! Thanks much folks!